diff --git a/custom_components/myhome/sound_source.py b/custom_components/myhome/sound_source.py index 50c1a22c..3bc6e0ce 100644 --- a/custom_components/myhome/sound_source.py +++ b/custom_components/myhome/sound_source.py @@ -292,6 +292,7 @@ async def async_set_frequency(self, megahertz: float) -> None: self._frequency_khz = kilohertz self._station = None self._attr_source = None + self._attr_media_title = None self.async_schedule_update_ha_state() async def async_play_media(self, media_type: str, media_id: str, **kwargs: Any) -> None: @@ -326,15 +327,36 @@ async def async_play_media(self, media_type: str, media_id: str, **kwargs: Any) @callback def handle_event(self, message: OWNSoundEvent) -> None: """Apply a WHO=16 event addressed to this source device.""" - dimension = getattr(message, "dimension", None) - values = [str(v) for v in (getattr(message, "dimension_value", None) or [])] + raw_dim = getattr(message, "dimension", getattr(message, "_dimension", None)) + try: + dimension = int(raw_dim) if raw_dim is not None else None + except (ValueError, TypeError): + dimension = None + + values = [ + str(v) + for v in ( + getattr(message, "dimension_value", None) + or getattr(message, "_dimension_value", None) + or getattr(message, "dimension_values", None) + or [] + ) + ] if dimension == 6 and values: self._set_frequency_from_bus(values[-1]) elif dimension == 7 and values: self._set_station_from_bus(values[-1]) elif dimension == 8 and values: - self._attr_media_title = rds_text(values) + if len(values) == 8: + self._attr_media_title = rds_text(values) + else: + LOGGER.debug( + "%s: ignoring malformed RDS frame with %d values: %s", + self.entity_id, + len(values), + values, + ) elif getattr(message, "is_on", False): self._attr_state = MediaPlayerState.ON elif getattr(message, "is_off", False): @@ -354,6 +376,7 @@ def _set_frequency_from_bus(self, raw: str) -> None: self._frequency_khz = kilohertz self._station = None self._attr_source = None + self._attr_media_title = None else: LOGGER.debug( "%s: ignoring reported frequency %s kHz, outside the FM band", diff --git a/tests/fixtures/traces/f500_tuner/README.md b/tests/fixtures/traces/f500_tuner/README.md index 260eea4c..75e0b589 100644 --- a/tests/fixtures/traces/f500_tuner/README.md +++ b/tests/fixtures/traces/f500_tuner/README.md @@ -26,3 +26,9 @@ Authentic on-wire bus frames captured by `@manfredgittmaier-afk` on a live insta - Seek down: `*16*5100*101##` -> locks to previous station (e.g. 88.8 MHz). 8. **RDS Blanking and Dynamic Text**: - After tuning, tuner sends 8 spaces `*#16*101*8*32*32*32*32*32*32*32*32##` before delivering station title. +9. **Rotating RDS and Malformed Frames (`myhome_trace_MH200N_all_2026-09-26T20-00-28.json`)**: + - Reported in [PR #427 (comment 5849429368)](https://github.com/OpenWebNet-HA/MyHOME/pull/427#issuecomment-5849429368). + - Some stations rotate RDS PS text every ~5s (e.g. `*RADIO* ` / `**OOE** `). + - Rare hardware buffer glitches occasionally produce malformed 12-code frames (e.g. `*#16*101*8*42*42*79*79*69*42*79*79*69*42*42*32##`), which must be dropped to prevent state corruption. + - Live stepping sequence across presets 1–4 confirms frequency, station preset, and RDS tracking across real `OWNSoundEvent` replies. + diff --git a/tests/fixtures/traces/f500_tuner/myhome_trace_MH200N_all_2026-09-26T20-00-28.json b/tests/fixtures/traces/f500_tuner/myhome_trace_MH200N_all_2026-09-26T20-00-28.json new file mode 100644 index 00000000..722c0eed --- /dev/null +++ b/tests/fixtures/traces/f500_tuner/myhome_trace_MH200N_all_2026-09-26T20-00-28.json @@ -0,0 +1,2464 @@ +{ + "capture": { + "kind": "trace", + "started_at": null, + "filters": { + "who": null, + "where": null, + "direction": null + }, + "window": { + "first": "2026-09-26T19:53:28.296Z", + "last": "2026-09-26T20:00:26.473Z", + "frames": 200, + "buffer_frames": 200, + "buffer_depth": 200, + "truncated": true + } + }, + "environment": { + "home_assistant_version": "2026.9.3", + "integration_version": "2.0.0b13", + "ownd_version": "2.0.0b8", + "exported_at": "2026-09-26T20:00:28.746Z" + }, + "gateway": { + "model": "MH200N", + "manufacturer": "BTicino S.p.A.", + "firmware": "1.0", + "mac_prefix": "00:03:50", + "connection_type": "tcp", + "queue_pacing": 0.15, + "is_connected": true, + "identification": { + "model": "MH200N", + "source": "ssdp", + "configured_model": "MH200N", + "ssdp_model": "MH200N", + "who13_code": null, + "who13_model": null, + "who13_model_official": null, + "who13_model_observed": null, + "who13_firmware": null, + "who13_kernel": null, + "who13_distribution": null, + "who1013_code": null, + "who1013_model": null, + "who1013_other_names": [], + "who1013_n_conf": null, + "who1013_brand": null, + "who1013_line": null, + "profile": "MH200NProfile", + "conflict": null + } + }, + "telemetry": { + "total_rx": 535, + "total_tx": 99, + "captured_in_buffer": 200, + "buffer_depth": 200, + "queue_depth": 0 + }, + "frames": [ + { + "timestamp": 1790452408.296792, + "iso_time": "2026-09-26T19:53:28.296792+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452408.307871, + "iso_time": "2026-09-26T19:53:28.307871+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452410.501283, + "iso_time": "2026-09-26T19:53:30.501283+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452410.504605, + "iso_time": "2026-09-26T19:53:30.504605+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452415.581478, + "iso_time": "2026-09-26T19:53:35.581478+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452415.584895, + "iso_time": "2026-09-26T19:53:35.584895+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452420.395959, + "iso_time": "2026-09-26T19:53:40.395959+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452420.400396, + "iso_time": "2026-09-26T19:53:40.400396+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452425.213992, + "iso_time": "2026-09-26T19:53:45.213992+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452425.218832, + "iso_time": "2026-09-26T19:53:45.218832+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452430.033871, + "iso_time": "2026-09-26T19:53:50.033871+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452430.038956, + "iso_time": "2026-09-26T19:53:50.038956+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452434.843545, + "iso_time": "2026-09-26T19:53:54.843545+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452434.848553, + "iso_time": "2026-09-26T19:53:54.848553+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452438.113853, + "iso_time": "2026-09-26T19:53:58.113853+00:00", + "direction": "rx", + "raw": "*#13**22*11*59*04*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452441.740114, + "iso_time": "2026-09-26T19:54:01.740114+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452441.74124, + "iso_time": "2026-09-26T19:54:01.741240+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452445.608079, + "iso_time": "2026-09-26T19:54:05.608079+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452445.618803, + "iso_time": "2026-09-26T19:54:05.618803+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452450.69769, + "iso_time": "2026-09-26T19:54:10.697690+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452450.708914, + "iso_time": "2026-09-26T19:54:10.708914+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452455.51546, + "iso_time": "2026-09-26T19:54:15.515460+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452455.520231, + "iso_time": "2026-09-26T19:54:15.520231+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452460.319558, + "iso_time": "2026-09-26T19:54:20.319558+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452460.330885, + "iso_time": "2026-09-26T19:54:20.330885+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452465.139585, + "iso_time": "2026-09-26T19:54:25.139585+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452465.150765, + "iso_time": "2026-09-26T19:54:25.150765+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452468.176727, + "iso_time": "2026-09-26T19:54:28.176727+00:00", + "direction": "rx", + "raw": "*#13**22*11*59*34*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452469.965951, + "iso_time": "2026-09-26T19:54:29.965951+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452469.970719, + "iso_time": "2026-09-26T19:54:29.970719+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452475.048378, + "iso_time": "2026-09-26T19:54:35.048378+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452475.053124, + "iso_time": "2026-09-26T19:54:35.053124+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452480.639768, + "iso_time": "2026-09-26T19:54:40.639768+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452480.651525, + "iso_time": "2026-09-26T19:54:40.651525+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452485.72012, + "iso_time": "2026-09-26T19:54:45.720120+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452485.730588, + "iso_time": "2026-09-26T19:54:45.730588+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452490.547157, + "iso_time": "2026-09-26T19:54:50.547157+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452490.551932, + "iso_time": "2026-09-26T19:54:50.551932+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452494.13364, + "iso_time": "2026-09-26T19:54:54.133640+00:00", + "direction": "rx", + "raw": "*#4*1*0*0201##", + "who": "4", + "what": null, + "where": "1", + "dimension": "0", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452494.263779, + "iso_time": "2026-09-26T19:54:54.263779+00:00", + "direction": "rx", + "raw": "*#4*1*14*0200*3##", + "who": "4", + "what": null, + "where": "1", + "dimension": "14", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452494.634455, + "iso_time": "2026-09-26T19:54:54.634455+00:00", + "direction": "rx", + "raw": "*#4*2*0*0217##", + "who": "4", + "what": null, + "where": "2", + "dimension": "0", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452494.82349, + "iso_time": "2026-09-26T19:54:54.823490+00:00", + "direction": "rx", + "raw": "*#4*2*14*0200*3##", + "who": "4", + "what": null, + "where": "2", + "dimension": "14", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452495.144563, + "iso_time": "2026-09-26T19:54:55.144563+00:00", + "direction": "rx", + "raw": "*#4*3*0*0217##", + "who": "4", + "what": null, + "where": "3", + "dimension": "0", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452495.323977, + "iso_time": "2026-09-26T19:54:55.323977+00:00", + "direction": "rx", + "raw": "*#4*3*14*0200*3##", + "who": "4", + "what": null, + "where": "3", + "dimension": "14", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452495.421323, + "iso_time": "2026-09-26T19:54:55.421323+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452495.429718, + "iso_time": "2026-09-26T19:54:55.429718+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452495.665623, + "iso_time": "2026-09-26T19:54:55.665623+00:00", + "direction": "rx", + "raw": "*#4*4*0*0218##", + "who": "4", + "what": null, + "where": "4", + "dimension": "0", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452495.844925, + "iso_time": "2026-09-26T19:54:55.844925+00:00", + "direction": "rx", + "raw": "*#4*4*14*0220*3##", + "who": "4", + "what": null, + "where": "4", + "dimension": "14", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452496.006035, + "iso_time": "2026-09-26T19:54:56.006035+00:00", + "direction": "rx", + "raw": "*#4*3#1*20*0##", + "who": "4", + "what": null, + "where": "3", + "dimension": "20", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452496.145583, + "iso_time": "2026-09-26T19:54:56.145583+00:00", + "direction": "rx", + "raw": "*#4*4#1*20*1##", + "who": "4", + "what": null, + "where": "4", + "dimension": "20", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452496.26359, + "iso_time": "2026-09-26T19:54:56.263590+00:00", + "direction": "rx", + "raw": "*#4*5*0*0222##", + "who": "4", + "what": null, + "where": "5", + "dimension": "0", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452496.440131, + "iso_time": "2026-09-26T19:54:56.440131+00:00", + "direction": "rx", + "raw": "*#4*5*14*0180*3##", + "who": "4", + "what": null, + "where": "5", + "dimension": "14", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452496.722813, + "iso_time": "2026-09-26T19:54:56.722813+00:00", + "direction": "rx", + "raw": "*#4*6*0*0227##", + "who": "4", + "what": null, + "where": "6", + "dimension": "0", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452496.924431, + "iso_time": "2026-09-26T19:54:56.924431+00:00", + "direction": "rx", + "raw": "*#13**#0*12*00*00*##", + "who": "13", + "what": null, + "where": "", + "dimension": "0", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452496.997211, + "iso_time": "2026-09-26T19:54:56.997211+00:00", + "direction": "rx", + "raw": "*#13**22*12*00*02*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452497.000744, + "iso_time": "2026-09-26T19:54:57.000744+00:00", + "direction": "rx", + "raw": "*#4*6*14*0180*3##", + "who": "4", + "what": null, + "where": "6", + "dimension": "14", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452497.263434, + "iso_time": "2026-09-26T19:54:57.263434+00:00", + "direction": "rx", + "raw": "*#4*7*0*0226##", + "who": "4", + "what": null, + "where": "7", + "dimension": "0", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452497.390892, + "iso_time": "2026-09-26T19:54:57.390892+00:00", + "direction": "rx", + "raw": "*#4*7*14*0180*3##", + "who": "4", + "what": null, + "where": "7", + "dimension": "14", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452500.170498, + "iso_time": "2026-09-26T19:55:00.170498+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452500.181895, + "iso_time": "2026-09-26T19:55:00.181895+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452502.654486, + "iso_time": "2026-09-26T19:55:02.654486+00:00", + "direction": "rx", + "raw": "*#4*2#1*20*0##", + "who": "4", + "what": null, + "where": "2", + "dimension": "20", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452504.45409, + "iso_time": "2026-09-26T19:55:04.454090+00:00", + "direction": "rx", + "raw": "*#4*5#1*20*0##", + "who": "4", + "what": null, + "where": "5", + "dimension": "20", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452505.080663, + "iso_time": "2026-09-26T19:55:05.080663+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452505.084326, + "iso_time": "2026-09-26T19:55:05.084326+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452507.624671, + "iso_time": "2026-09-26T19:55:07.624671+00:00", + "direction": "rx", + "raw": "*#4*7#1*20*0##", + "who": "4", + "what": null, + "where": "7", + "dimension": "20", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452507.745535, + "iso_time": "2026-09-26T19:55:07.745535+00:00", + "direction": "rx", + "raw": "*#4*6#1*20*0##", + "who": "4", + "what": null, + "where": "6", + "dimension": "20", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452510.152057, + "iso_time": "2026-09-26T19:55:10.152057+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452510.163982, + "iso_time": "2026-09-26T19:55:10.163982+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452516.677334, + "iso_time": "2026-09-26T19:55:16.677334+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452516.678419, + "iso_time": "2026-09-26T19:55:16.678419+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452516.678909, + "iso_time": "2026-09-26T19:55:16.678909+00:00", + "direction": "rx", + "raw": "*1*1000#0*24##", + "who": "1", + "what": "1000", + "where": "24", + "dimension": null, + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452516.679333, + "iso_time": "2026-09-26T19:55:16.679333+00:00", + "direction": "rx", + "raw": "*1*0*24##", + "who": "1", + "what": "0", + "where": "24", + "dimension": null, + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452516.874992, + "iso_time": "2026-09-26T19:55:16.874992+00:00", + "direction": "rx", + "raw": "*17*1*24##", + "who": "17", + "what": "1", + "where": "24", + "dimension": null, + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452516.897417, + "iso_time": "2026-09-26T19:55:16.897417+00:00", + "direction": "rx", + "raw": "*17*2*24##", + "who": "17", + "what": "2", + "where": "24", + "dimension": null, + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452520.834395, + "iso_time": "2026-09-26T19:55:20.834395+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452520.841282, + "iso_time": "2026-09-26T19:55:20.841282+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452524.514277, + "iso_time": "2026-09-26T19:55:24.514277+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452524.519528, + "iso_time": "2026-09-26T19:55:24.519528+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452527.102665, + "iso_time": "2026-09-26T19:55:27.102665+00:00", + "direction": "rx", + "raw": "*#13**22*12*00*32*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452529.585949, + "iso_time": "2026-09-26T19:55:29.585949+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452529.592423, + "iso_time": "2026-09-26T19:55:29.592423+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452534.410004, + "iso_time": "2026-09-26T19:55:34.410004+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452534.411425, + "iso_time": "2026-09-26T19:55:34.411425+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452539.235205, + "iso_time": "2026-09-26T19:55:39.235205+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452539.236996, + "iso_time": "2026-09-26T19:55:39.236996+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452544.05648, + "iso_time": "2026-09-26T19:55:44.056480+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452544.061309, + "iso_time": "2026-09-26T19:55:44.061309+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452549.039984, + "iso_time": "2026-09-26T19:55:49.039984+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452549.041313, + "iso_time": "2026-09-26T19:55:49.041313+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452554.827491, + "iso_time": "2026-09-26T19:55:54.827491+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452554.83326, + "iso_time": "2026-09-26T19:55:54.833260+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452556.168929, + "iso_time": "2026-09-26T19:55:56.168929+00:00", + "direction": "rx", + "raw": "*#13**22*12*01*02*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452559.431622, + "iso_time": "2026-09-26T19:55:59.431622+00:00", + "direction": "rx", + "raw": "*#4*1#1*20*0##", + "who": "4", + "what": null, + "where": "1", + "dimension": "20", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452559.545369, + "iso_time": "2026-09-26T19:55:59.545369+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452559.547635, + "iso_time": "2026-09-26T19:55:59.547635+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452564.715799, + "iso_time": "2026-09-26T19:56:04.715799+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452564.725352, + "iso_time": "2026-09-26T19:56:04.725352+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452569.541278, + "iso_time": "2026-09-26T19:56:09.541278+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452569.54383, + "iso_time": "2026-09-26T19:56:09.543830+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452574.365477, + "iso_time": "2026-09-26T19:56:14.365477+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452574.370047, + "iso_time": "2026-09-26T19:56:14.370047+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452579.190597, + "iso_time": "2026-09-26T19:56:19.190597+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452579.195133, + "iso_time": "2026-09-26T19:56:19.195133+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452583.989032, + "iso_time": "2026-09-26T19:56:23.989032+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452583.996416, + "iso_time": "2026-09-26T19:56:23.996416+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452586.211672, + "iso_time": "2026-09-26T19:56:26.211672+00:00", + "direction": "rx", + "raw": "*#13**22*12*01*32*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452592.570053, + "iso_time": "2026-09-26T19:56:32.570053+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452592.571219, + "iso_time": "2026-09-26T19:56:32.571219+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452594.665977, + "iso_time": "2026-09-26T19:56:34.665977+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452594.677722, + "iso_time": "2026-09-26T19:56:34.677722+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452599.746471, + "iso_time": "2026-09-26T19:56:39.746471+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452599.757753, + "iso_time": "2026-09-26T19:56:39.757753+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452604.571541, + "iso_time": "2026-09-26T19:56:44.571541+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452604.574838, + "iso_time": "2026-09-26T19:56:44.574838+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452609.436128, + "iso_time": "2026-09-26T19:56:49.436128+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452609.447142, + "iso_time": "2026-09-26T19:56:49.447142+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452614.195917, + "iso_time": "2026-09-26T19:56:54.195917+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452614.200452, + "iso_time": "2026-09-26T19:56:54.200452+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452616.262963, + "iso_time": "2026-09-26T19:56:56.262963+00:00", + "direction": "rx", + "raw": "*#13**22*12*02*02*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452619.02286, + "iso_time": "2026-09-26T19:56:59.022860+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452619.02784, + "iso_time": "2026-09-26T19:56:59.027840+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452624.19959, + "iso_time": "2026-09-26T19:57:04.199590+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452624.204504, + "iso_time": "2026-09-26T19:57:04.204504+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452630.268532, + "iso_time": "2026-09-26T19:57:10.268532+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452630.269611, + "iso_time": "2026-09-26T19:57:10.269611+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452634.873992, + "iso_time": "2026-09-26T19:57:14.873992+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452634.878841, + "iso_time": "2026-09-26T19:57:14.878841+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452639.695546, + "iso_time": "2026-09-26T19:57:19.695546+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452639.704698, + "iso_time": "2026-09-26T19:57:19.704698+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452644.499025, + "iso_time": "2026-09-26T19:57:24.499025+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452644.510386, + "iso_time": "2026-09-26T19:57:24.510386+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452646.274006, + "iso_time": "2026-09-26T19:57:26.274006+00:00", + "direction": "rx", + "raw": "*#13**22*12*02*32*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452649.324481, + "iso_time": "2026-09-26T19:57:29.324481+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452649.329756, + "iso_time": "2026-09-26T19:57:29.329756+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452654.145851, + "iso_time": "2026-09-26T19:57:34.145851+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452654.150588, + "iso_time": "2026-09-26T19:57:34.150588+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452659.225485, + "iso_time": "2026-09-26T19:57:39.225485+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452659.23049, + "iso_time": "2026-09-26T19:57:39.230490+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452663.961027, + "iso_time": "2026-09-26T19:57:43.961027+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452663.96629, + "iso_time": "2026-09-26T19:57:43.966290+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452669.899149, + "iso_time": "2026-09-26T19:57:49.899149+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452669.909745, + "iso_time": "2026-09-26T19:57:49.909745+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452674.726412, + "iso_time": "2026-09-26T19:57:54.726412+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452674.731393, + "iso_time": "2026-09-26T19:57:54.731393+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452676.317572, + "iso_time": "2026-09-26T19:57:56.317572+00:00", + "direction": "rx", + "raw": "*#13**22*12*03*02*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452679.552415, + "iso_time": "2026-09-26T19:57:59.552415+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452679.557313, + "iso_time": "2026-09-26T19:57:59.557313+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452684.448085, + "iso_time": "2026-09-26T19:58:04.448085+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452684.452277, + "iso_time": "2026-09-26T19:58:04.452277+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452690.301147, + "iso_time": "2026-09-26T19:58:10.301147+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452690.312708, + "iso_time": "2026-09-26T19:58:10.312708+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452695.261051, + "iso_time": "2026-09-26T19:58:15.261051+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452695.27308, + "iso_time": "2026-09-26T19:58:15.273080+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452699.946549, + "iso_time": "2026-09-26T19:58:19.946549+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452699.951457, + "iso_time": "2026-09-26T19:58:19.951457+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452706.964484, + "iso_time": "2026-09-26T19:58:26.964484+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*82*65*68*73*79*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452706.965583, + "iso_time": "2026-09-26T19:58:26.965583+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*82*65*68*73*79*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452706.966301, + "iso_time": "2026-09-26T19:58:26.966301+00:00", + "direction": "rx", + "raw": "*#13**22*12*03*32*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452710.709725, + "iso_time": "2026-09-26T19:58:30.709725+00:00", + "direction": "rx", + "raw": "*#16*101*8*42*42*79*79*69*42*42*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452710.714219, + "iso_time": "2026-09-26T19:58:30.714219+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*42*42*79*79*69*42*42*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452714.004923, + "iso_time": "2026-09-26T19:58:34.004923+00:00", + "direction": "tx", + "raw": "*16*6001*101##", + "who": "16", + "what": "6001", + "where": "101", + "dimension": null, + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452714.181406, + "iso_time": "2026-09-26T19:58:34.181406+00:00", + "direction": "rx", + "raw": "*#16*101*6*0*88800##", + "who": "16", + "what": null, + "where": "101", + "dimension": "6", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452714.193063, + "iso_time": "2026-09-26T19:58:34.193063+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*5*1*8880##", + "who": "22", + "what": null, + "where": "5", + "dimension": "5", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452714.204343, + "iso_time": "2026-09-26T19:58:34.204343+00:00", + "direction": "rx", + "raw": "*#16*101*7*0*1##", + "who": "16", + "what": null, + "where": "101", + "dimension": "7", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452714.234831, + "iso_time": "2026-09-26T19:58:34.234831+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*11*1*8880*1##", + "who": "22", + "what": null, + "where": "5", + "dimension": "11", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452714.240606, + "iso_time": "2026-09-26T19:58:34.240606+00:00", + "direction": "rx", + "raw": "*#22*2#1*6*1##", + "who": "22", + "what": null, + "where": "2", + "dimension": "6", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452714.388017, + "iso_time": "2026-09-26T19:58:34.388017+00:00", + "direction": "rx", + "raw": "*#16*101*8*72*73*84*82*65*68*73*79##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452714.393029, + "iso_time": "2026-09-26T19:58:34.393029+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*72*73*84*82*65*68*73*79##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452715.998618, + "iso_time": "2026-09-26T19:58:35.998618+00:00", + "direction": "rx", + "raw": "*#16*101*8*32*32*79*69*32*51*32*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452716.003488, + "iso_time": "2026-09-26T19:58:36.003488+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*32*32*79*69*32*51*32*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452736.371755, + "iso_time": "2026-09-26T19:58:56.371755+00:00", + "direction": "rx", + "raw": "*#13**22*12*04*02*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452751.398022, + "iso_time": "2026-09-26T19:59:11.398022+00:00", + "direction": "tx", + "raw": "*16*6001*101##", + "who": "16", + "what": "6001", + "where": "101", + "dimension": null, + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452751.575682, + "iso_time": "2026-09-26T19:59:11.575682+00:00", + "direction": "rx", + "raw": "*#16*101*6*0*96200##", + "who": "16", + "what": null, + "where": "101", + "dimension": "6", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452751.585695, + "iso_time": "2026-09-26T19:59:11.585695+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*5*1*9620##", + "who": "22", + "what": null, + "where": "5", + "dimension": "5", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452751.597703, + "iso_time": "2026-09-26T19:59:11.597703+00:00", + "direction": "rx", + "raw": "*#16*101*7*0*2##", + "who": "16", + "what": null, + "where": "101", + "dimension": "7", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452751.627309, + "iso_time": "2026-09-26T19:59:11.627309+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*11*1*9620*2##", + "who": "22", + "what": null, + "where": "5", + "dimension": "11", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452751.632542, + "iso_time": "2026-09-26T19:59:11.632542+00:00", + "direction": "rx", + "raw": "*#22*2#1*6*2##", + "who": "22", + "what": null, + "where": "2", + "dimension": "6", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452751.769456, + "iso_time": "2026-09-26T19:59:11.769456+00:00", + "direction": "rx", + "raw": "*#16*101*8*75*82*79*78*69*72*73*84##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452751.774344, + "iso_time": "2026-09-26T19:59:11.774344+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*75*82*79*78*69*72*73*84##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452752.886342, + "iso_time": "2026-09-26T19:59:12.886342+00:00", + "direction": "rx", + "raw": "*#16*101*8*107*114*111*110*101*104*105*116##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452752.891929, + "iso_time": "2026-09-26T19:59:12.891929+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*107*114*111*110*101*104*105*116##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452766.380977, + "iso_time": "2026-09-26T19:59:26.380977+00:00", + "direction": "rx", + "raw": "*#13**22*12*04*32*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452796.376265, + "iso_time": "2026-09-26T19:59:56.376265+00:00", + "direction": "rx", + "raw": "*#13**22*12*05*02*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452813.244809, + "iso_time": "2026-09-26T20:00:13.244809+00:00", + "direction": "tx", + "raw": "*16*6001*101##", + "who": "16", + "what": "6001", + "where": "101", + "dimension": null, + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452813.396513, + "iso_time": "2026-09-26T20:00:13.396513+00:00", + "direction": "rx", + "raw": "*#16*101*6*0*90300##", + "who": "16", + "what": null, + "where": "101", + "dimension": "6", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452813.399205, + "iso_time": "2026-09-26T20:00:13.399205+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*5*1*9030##", + "who": "22", + "what": null, + "where": "5", + "dimension": "5", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452813.424458, + "iso_time": "2026-09-26T20:00:13.424458+00:00", + "direction": "rx", + "raw": "*#16*101*7*0*3##", + "who": "16", + "what": null, + "where": "101", + "dimension": "7", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452813.439758, + "iso_time": "2026-09-26T20:00:13.439758+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*11*1*9030*3##", + "who": "22", + "what": null, + "where": "5", + "dimension": "11", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452813.453897, + "iso_time": "2026-09-26T20:00:13.453897+00:00", + "direction": "rx", + "raw": "*#22*2#1*6*3##", + "who": "22", + "what": null, + "where": "2", + "dimension": "6", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452813.587525, + "iso_time": "2026-09-26T20:00:13.587525+00:00", + "direction": "rx", + "raw": "*#16*101*8*83*78*82*84*45*65*109*122##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452813.599107, + "iso_time": "2026-09-26T20:00:13.599107+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*83*78*82*84*45*65*109*122##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452815.691629, + "iso_time": "2026-09-26T20:00:15.691629+00:00", + "direction": "tx", + "raw": "*16*6001*101##", + "who": "16", + "what": "6001", + "where": "101", + "dimension": null, + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452815.873798, + "iso_time": "2026-09-26T20:00:15.873798+00:00", + "direction": "rx", + "raw": "*#16*101*6*0*103500##", + "who": "16", + "what": null, + "where": "101", + "dimension": "6", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452815.878102, + "iso_time": "2026-09-26T20:00:15.878102+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*5*1*10350##", + "who": "22", + "what": null, + "where": "5", + "dimension": "5", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452815.889114, + "iso_time": "2026-09-26T20:00:15.889114+00:00", + "direction": "rx", + "raw": "*#16*101*7*0*4##", + "who": "16", + "what": null, + "where": "101", + "dimension": "7", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452815.919139, + "iso_time": "2026-09-26T20:00:15.919139+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*11*1*10350*4##", + "who": "22", + "what": null, + "where": "5", + "dimension": "11", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452815.924403, + "iso_time": "2026-09-26T20:00:15.924403+00:00", + "direction": "rx", + "raw": "*#22*2#1*6*4##", + "who": "22", + "what": null, + "where": "2", + "dimension": "6", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452816.046982, + "iso_time": "2026-09-26T20:00:16.046982+00:00", + "direction": "rx", + "raw": "*#16*101*8*65*78*84*69*78*78*69*32##", + "who": "16", + "what": null, + "where": "101", + "dimension": "8", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452816.058405, + "iso_time": "2026-09-26T20:00:16.058405+00:00", + "direction": "rx", + "raw": "*#22*5#2#1*10*65*78*84*69*78*78*69*32##", + "who": "22", + "what": null, + "where": "5", + "dimension": "10", + "is_ack": false, + "is_nack": false + }, + { + "timestamp": 1790452826.473558, + "iso_time": "2026-09-26T20:00:26.473558+00:00", + "direction": "rx", + "raw": "*#13**22*12*05*32*001*04*20*04*2000##", + "who": "13", + "what": null, + "where": "", + "dimension": "22", + "is_ack": false, + "is_nack": false + } + ] +} \ No newline at end of file diff --git a/tests/test_component_sound_source.py b/tests/test_component_sound_source.py index cdf3223e..9eb0fc54 100644 --- a/tests/test_component_sound_source.py +++ b/tests/test_component_sound_source.py @@ -214,6 +214,11 @@ def test_handle_event_ignores_impossible_payloads(hass, tuner): assert "station" not in tuner.extra_state_attributes assert tuner.source is None + tuner.handle_event(MagicMock( + spec=OWNSoundEvent, dimension="not-a-number", dimension_value=[], + is_on=False, is_off=False, + )) + def test_handle_event_power_state(hass, tuner): """Standby clears the title: a tuner in standby is listening to nothing.""" @@ -233,6 +238,54 @@ def test_handle_event_power_state(hass, tuner): assert tuner.media_content_type is None +def test_handle_event_real_own_sound_events(hass, tuner): + """Real OWNSoundEvents without public dimension_value are handled correctly.""" + tuner.handle_event(OWNSoundEvent("*#16*101*6*0*103500##")) + assert tuner.extra_state_attributes["frequency"] == 103.5 + + tuner.handle_event(OWNSoundEvent("*#16*101*7*0*4##")) + assert tuner.extra_state_attributes["station"] == 4 + assert tuner.source == "Station 4" + + tuner.handle_event(OWNSoundEvent("*#16*101*8*65*78*84*69*78*78*69*32##")) + assert tuner.media_title == "ANTENNE" + + +def test_handle_event_ignores_malformed_rds(hass, tuner): + """A malformed RDS report with length != 8 is ignored and does not alter title.""" + tuner.handle_event(OWNSoundEvent("*#16*101*8*42*82*65*68*73*79*42*32##")) + assert tuner.media_title == "*RADIO*" + + # 12-code glitch from live bus + tuner.handle_event(OWNSoundEvent("*#16*101*8*42*42*79*79*69*42*79*79*69*42*42*32##")) + assert tuner.media_title == "*RADIO*" + + # Valid follow-up 8-code frame updates title + tuner.handle_event(OWNSoundEvent("*#16*101*8*42*42*79*79*69*42*42*32##")) + assert tuner.media_title == "**OOE**" + + +@pytest.mark.asyncio +async def test_next_previous_station_source_follow(hass, tuner, mock_gateway): + """Entity source and station follow the reported station after next/previous.""" + await tuner.async_select_source("Station 2") + assert tuner.source == "Station 2" + assert tuner.extra_state_attributes["station"] == 2 + + await tuner.async_media_next_track() + assert str(mock_gateway.send.call_args[0][0]) == "*16*6001*101##" + + # Tuner hardware reports new frequency, station and RDS + tuner.handle_event(OWNSoundEvent("*#16*101*6*0*103500##")) + tuner.handle_event(OWNSoundEvent("*#16*101*7*0*4##")) + tuner.handle_event(OWNSoundEvent("*#16*101*8*65*78*84*69*78*78*69*32##")) + + assert tuner.extra_state_attributes["frequency"] == 103.5 + assert tuner.extra_state_attributes["station"] == 4 + assert tuner.source == "Station 4" + assert tuner.media_title == "ANTENNE" + + def test_build_sound_sources_only_for_declared_tuners(hass, mock_gateway): """Only inputs the user marked as tuners get an entity.""" entry = MagicMock() diff --git a/tests/test_sound_source_trace_replay.py b/tests/test_sound_source_trace_replay.py index 89c147d5..944e312c 100644 --- a/tests/test_sound_source_trace_replay.py +++ b/tests/test_sound_source_trace_replay.py @@ -37,6 +37,14 @@ / "myhome_trace_MH200N_f500n_tuner_seek_and_frequency.json" ) +FIXTURE_ALL_PATH = ( + Path(__file__).parent + / "fixtures" + / "traces" + / "f500_tuner" + / "myhome_trace_MH200N_all_2026-09-26T20-00-28.json" +) + @pytest.fixture def mock_gateway(): @@ -94,19 +102,10 @@ def test_f500n_authentic_trace_replay(tuner): raw = frame["raw"] who = frame.get("who") - dimension = frame.get("dimension") - values = frame.get("dimension_values", []) # The tuner entity subscribes to WHO 16 frames addressed to 101 if who == "16" and frame.get("where") == "101": - event = MagicMock(spec=OWNSoundEvent) - event.raw = raw - event.who = "16" - event.where = "101" - event.dimension = int(dimension) if dimension is not None else None - event.dimension_value = values - event.is_on = False - event.is_off = False + event = OWNSoundEvent(raw) tuner.handle_event(event) if raw == "*#16*101*6*0*96200##": @@ -201,18 +200,9 @@ async def test_f500n_seek_and_frequency_trace_replay(tuner, mock_gateway): for frame in frames: raw = frame["raw"] who = frame.get("who") - dimension = frame.get("dimension") - values = frame.get("dimension_values", []) if who == "16" and frame.get("where") == "101" and frame["direction"] == "rx": - event = MagicMock(spec=OWNSoundEvent) - event.raw = raw - event.who = "16" - event.where = "101" - event.dimension = int(dimension) if dimension is not None else None - event.dimension_value = values - event.is_on = False - event.is_off = False + event = OWNSoundEvent(raw) tuner.handle_event(event) if raw == "*#16*101*6*0*96200##": @@ -255,3 +245,61 @@ async def test_f500n_seek_and_frequency_trace_replay(tuner, mock_gateway): await tuner.async_seek_down() assert str(mock_gateway.send.call_args.args[0]) == "*16*5100*101##" + +def test_f500n_station_advance_and_rds_rotation_replay(tuner): + """Replay authentic MH200N + F500N trace covering RDS rotation, 12-code glitch, and advance. + + Contributed by @manfredgittmaier-afk on PR #427 / comment 5849429368. + """ + assert FIXTURE_ALL_PATH.is_file(), f"Missing trace fixture: {FIXTURE_ALL_PATH}" + + with open(FIXTURE_ALL_PATH, encoding="utf-8") as f: + trace_data = json.load(f) + + frames = trace_data["frames"] + + for frame in frames: + if frame.get("direction") != "rx" or frame.get("who") != "16" or frame.get("where") != "101": + continue + + raw = frame["raw"] + event = OWNSoundEvent(raw) + tuner.handle_event(event) + + if raw == "*#16*101*8*42*82*65*68*73*79*42*32##": + # Dynamic RDS title "*RADIO*" + assert tuner.media_title == "*RADIO*" + + elif raw == "*#16*101*8*42*42*79*79*69*42*42*32##": + # Dynamic RDS title alternate "**OOE**" + assert tuner.media_title == "**OOE**" + + elif raw == "*#16*101*8*42*42*79*79*69*42*79*79*69*42*42*32##": + # Malformed 12-code frame ignored; title remains previous clean title + assert tuner.media_title in ("*RADIO*", "**OOE**") + + elif raw == "*#16*101*7*0*1##": + assert tuner.extra_state_attributes["frequency"] == 88.8 + assert tuner.extra_state_attributes["station"] == 1 + assert tuner.source == "Station 1" + + elif raw == "*#16*101*7*0*2##": + assert tuner.extra_state_attributes["frequency"] == 96.2 + assert tuner.extra_state_attributes["station"] == 2 + assert tuner.source == "Station 2" + + elif raw == "*#16*101*7*0*3##": + assert tuner.extra_state_attributes["frequency"] == 90.3 + assert tuner.extra_state_attributes["station"] == 3 + assert tuner.source == "Station 3" + + elif raw == "*#16*101*7*0*4##": + assert tuner.extra_state_attributes["frequency"] == 103.5 + assert tuner.extra_state_attributes["station"] == 4 + assert tuner.source == "Station 4" + + elif raw == "*#16*101*8*65*78*84*69*78*78*69*32##": + # "ANTENNE " + assert tuner.media_title == "ANTENNE" + +