Read and parse multimon-ng output for pager messages.
(self, proc: subprocess.Popen)
| 2258 | return {'status': 'error', 'message': str(e)} |
| 2259 | |
| 2260 | def _pager_output_reader(self, proc: subprocess.Popen): |
| 2261 | """Read and parse multimon-ng output for pager messages.""" |
| 2262 | mode = 'pager' |
| 2263 | stop_event = self.stop_events.get(mode) |
| 2264 | |
| 2265 | try: |
| 2266 | for line in iter(proc.stdout.readline, b''): |
| 2267 | if stop_event and stop_event.is_set(): |
| 2268 | break |
| 2269 | |
| 2270 | line = line.decode('utf-8', errors='replace').strip() |
| 2271 | if not line: |
| 2272 | continue |
| 2273 | |
| 2274 | parsed = self._parse_pager_message(line) |
| 2275 | if parsed: |
| 2276 | parsed['received_at'] = datetime.now(timezone.utc).isoformat() |
| 2277 | |
| 2278 | gps_pos = gps_manager.position |
| 2279 | if gps_pos: |
| 2280 | parsed['agent_gps'] = gps_pos |
| 2281 | |
| 2282 | snapshots = self.data_snapshots.get(mode, []) |
| 2283 | snapshots.append(parsed) |
| 2284 | if len(snapshots) > 200: |
| 2285 | snapshots = snapshots[-200:] |
| 2286 | self.data_snapshots[mode] = snapshots |
| 2287 | |
| 2288 | logger.debug(f"Pager: {parsed.get('protocol')} addr={parsed.get('address')}") |
| 2289 | |
| 2290 | except (OSError, ValueError) as e: |
| 2291 | # Bad file descriptor or closed file - process was terminated |
| 2292 | logger.debug(f"Pager reader stopped: {e}") |
| 2293 | except Exception as e: |
| 2294 | logger.error(f"Pager reader error: {e}") |
| 2295 | finally: |
| 2296 | with contextlib.suppress(Exception): |
| 2297 | proc.wait(timeout=1) |
| 2298 | if 'pager_rtl' in self.processes: |
| 2299 | try: |
| 2300 | rtl_proc = self.processes['pager_rtl'] |
| 2301 | if rtl_proc.poll() is None: |
| 2302 | rtl_proc.terminate() |
| 2303 | del self.processes['pager_rtl'] |
| 2304 | except Exception: |
| 2305 | pass |
| 2306 | logger.info("Pager reader stopped") |
| 2307 | |
| 2308 | def _parse_pager_message(self, line: str) -> dict | None: |
| 2309 | """Parse multimon-ng output line for POCSAG/FLEX using Intercept's parser.""" |