Skip to main content

meshcore_rs/
reader.rs

1//! Message reader for parsing incoming MeshCore packets
2
3use std::collections::HashMap;
4use std::sync::Arc;
5use std::time::{Duration, Instant};
6use tokio::sync::RwLock;
7
8use crate::events::*;
9use crate::packets::{BinaryReqType, ControlType, PacketType};
10use crate::parsing::*;
11use crate::{Result, CHANNEL_INFO_LEN, CHANNEL_NAME_LEN, CHANNEL_SECRET_LEN};
12
13/// Tracks a pending binary request
14#[derive(Debug, Clone)]
15#[allow(dead_code)]
16struct BinaryRequest {
17    /// Request type
18    request_type: BinaryReqType,
19    /// Public key prefix for matching
20    pubkey_prefix: Vec<u8>,
21    /// Expiration time
22    expires_at: Instant,
23    /// Context data
24    context: HashMap<String, String>,
25    /// Whether this is an anonymous request
26    is_anon: bool,
27}
28
29/// Message reader that parses packets and emits events
30pub struct MessageReader {
31    /// Event dispatcher
32    dispatcher: Arc<EventDispatcher>,
33    /// Pending binary requests
34    pending_requests: Arc<RwLock<HashMap<String, BinaryRequest>>>,
35    /// Contacts being built during the multi-packet contact list
36    pending_contacts: Arc<RwLock<Vec<Contact>>>,
37    /// Current contact list last_modification_timestamp value
38    contacts_last_modification_timestamp: Arc<RwLock<u32>>,
39}
40
41impl MessageReader {
42    /// Create a new message reader
43    pub fn new(dispatcher: Arc<EventDispatcher>) -> Self {
44        Self {
45            dispatcher,
46            pending_requests: Arc::new(RwLock::new(HashMap::new())),
47            pending_contacts: Arc::new(RwLock::new(Vec::new())),
48            contacts_last_modification_timestamp: Arc::new(RwLock::new(0)),
49        }
50    }
51
52    /// Register a binary request for response matching
53    pub async fn register_binary_request(
54        &self,
55        tag: &[u8],
56        request_type: BinaryReqType,
57        pubkey_prefix: Vec<u8>,
58        timeout: Duration,
59        context: HashMap<String, String>,
60        is_anon: bool,
61    ) {
62        let tag_hex = hex_encode(tag);
63        let request = BinaryRequest {
64            request_type,
65            pubkey_prefix,
66            expires_at: Instant::now() + timeout,
67            context,
68            is_anon,
69        };
70
71        self.pending_requests.write().await.insert(tag_hex, request);
72    }
73
74    /// Clean up expired requests
75    async fn cleanup_expired(&self) {
76        let now = Instant::now();
77        self.pending_requests
78            .write()
79            .await
80            .retain(|_, req| req.expires_at > now);
81    }
82
83    /// Handle received data
84    pub async fn handle_rx(&self, data: Vec<u8>) -> Result<()> {
85        if data.is_empty() {
86            return Ok(());
87        }
88
89        // Clean up expired requests periodically
90        self.cleanup_expired().await;
91
92        let packet_type = PacketType::from(data[0]);
93        let payload = if data.len() > 1 { &data[1..] } else { &[] };
94
95        match packet_type {
96            PacketType::Ok => {
97                self.dispatcher.emit(MeshCoreEvent::ok()).await;
98            }
99
100            PacketType::Error => {
101                let msg = if !payload.is_empty() {
102                    String::from_utf8_lossy(payload).to_string()
103                } else {
104                    "Unknown error".to_string()
105                };
106                self.dispatcher.emit(MeshCoreEvent::error(msg)).await;
107            }
108
109            PacketType::ContactStart => {
110                // Clear pending contacts
111                self.pending_contacts.write().await.clear();
112            }
113
114            PacketType::Contact | PacketType::PushCodeNewAdvert => {
115                if let Ok(contact) = parse_contact(payload) {
116                    if packet_type == PacketType::PushCodeNewAdvert {
117                        // Emit as a new contact event
118                        let event = MeshCoreEvent::new(
119                            EventType::NewContact,
120                            EventPayload::Contact(contact),
121                        );
122                        self.dispatcher.emit(event).await;
123                    } else {
124                        // Add to pending contacts
125                        self.pending_contacts.write().await.push(contact);
126                    }
127                }
128            }
129
130            PacketType::ContactEnd => {
131                // Get last_modification_timestamp if present
132                let last_modification_timestamp = if payload.len() >= 4 {
133                    read_u32_le(payload, 0).unwrap_or(0)
134                } else {
135                    0
136                };
137                *self.contacts_last_modification_timestamp.write().await =
138                    last_modification_timestamp;
139
140                // Emit contacts event
141                let contacts = std::mem::take(&mut *self.pending_contacts.write().await);
142                let event =
143                    MeshCoreEvent::new(EventType::Contacts, EventPayload::Contacts(contacts))
144                        .with_attribute("lastmod", last_modification_timestamp.to_string());
145                self.dispatcher.emit(event).await;
146            }
147
148            PacketType::SelfInfo => {
149                if let Ok(info) = parse_self_info(payload) {
150                    let event =
151                        MeshCoreEvent::new(EventType::SelfInfo, EventPayload::SelfInfo(info));
152                    self.dispatcher.emit(event).await;
153                }
154            }
155
156            PacketType::DeviceInfo => {
157                let device_info = parse_device_info(payload);
158                let event = MeshCoreEvent::new(
159                    EventType::DeviceInfo,
160                    EventPayload::DeviceInfo(device_info),
161                );
162                self.dispatcher.emit(event).await;
163            }
164
165            PacketType::Battery => {
166                if payload.len() >= 2 {
167                    let battery_mv = read_u16_le(payload, 0).unwrap_or(0);
168                    // Storage info is optional and uses u32 fields
169                    let (used_kb, total_kb) = if payload.len() >= 10 {
170                        (
171                            Some(read_u32_le(payload, 2).unwrap_or(0)),
172                            Some(read_u32_le(payload, 6).unwrap_or(0)),
173                        )
174                    } else {
175                        (None, None)
176                    };
177                    let event = MeshCoreEvent::new(
178                        EventType::Battery,
179                        EventPayload::Battery(BatteryInfo {
180                            battery_mv,
181                            used_kb,
182                            total_kb,
183                        }),
184                    );
185                    self.dispatcher.emit(event).await;
186                }
187            }
188
189            PacketType::CurrentTime => {
190                if payload.len() >= 4 {
191                    let time = read_u32_le(payload, 0).unwrap_or(0);
192                    let event =
193                        MeshCoreEvent::new(EventType::CurrentTime, EventPayload::Time(time));
194                    self.dispatcher.emit(event).await;
195                }
196            }
197
198            PacketType::MsgSent => {
199                if payload.len() >= 9 {
200                    let message_type = payload[0];
201                    let expected_ack: [u8; 4] = read_bytes(payload, 1).unwrap_or([0; 4]);
202                    let suggested_timeout = read_u32_le(payload, 5).unwrap_or(5000);
203
204                    let event = MeshCoreEvent::new(
205                        EventType::MsgSent,
206                        EventPayload::MsgSent(MsgSentInfo {
207                            message_type,
208                            expected_ack,
209                            suggested_timeout,
210                        }),
211                    )
212                    .with_attribute("tag", hex_encode(&expected_ack));
213                    self.dispatcher.emit(event).await;
214                }
215            }
216
217            PacketType::ContactMsgRecv => {
218                if let Ok(msg) = parse_contact_msg(payload) {
219                    let event = MeshCoreEvent::new(
220                        EventType::ContactMsgRecv,
221                        EventPayload::ContactMessage(msg),
222                    );
223                    self.dispatcher.emit(event).await;
224                }
225            }
226
227            PacketType::ContactMsgRecvV3 => {
228                if let Ok(msg) = parse_contact_msg_v3(payload) {
229                    let event = MeshCoreEvent::new(
230                        EventType::ContactMsgRecv,
231                        EventPayload::ContactMessage(msg),
232                    );
233                    self.dispatcher.emit(event).await;
234                }
235            }
236
237            PacketType::ChannelMsgRecv => {
238                if let Ok(msg) = parse_channel_msg(payload) {
239                    let event = MeshCoreEvent::new(
240                        EventType::ChannelMsgRecv,
241                        EventPayload::ChannelMessage(msg),
242                    );
243                    self.dispatcher.emit(event).await;
244                }
245            }
246
247            PacketType::ChannelMsgRecvV3 => {
248                if let Ok(msg) = parse_channel_msg_v3(payload) {
249                    let event = MeshCoreEvent::new(
250                        EventType::ChannelMsgRecv,
251                        EventPayload::ChannelMessage(msg),
252                    );
253                    self.dispatcher.emit(event).await;
254                }
255            }
256
257            PacketType::NoMoreMsgs => {
258                let event = MeshCoreEvent::new(EventType::NoMoreMessages, EventPayload::None);
259                self.dispatcher.emit(event).await;
260            }
261
262            PacketType::ContactUri => {
263                let uri = String::from_utf8_lossy(payload).to_string();
264                let event = MeshCoreEvent::new(EventType::ContactUri, EventPayload::String(uri));
265                self.dispatcher.emit(event).await;
266            }
267
268            PacketType::PrivateKey => {
269                if payload.len() >= 64 {
270                    let key: [u8; 64] = read_bytes(payload, 0).unwrap_or([0; 64]);
271                    let event =
272                        MeshCoreEvent::new(EventType::PrivateKey, EventPayload::PrivateKey(key));
273                    self.dispatcher.emit(event).await;
274                }
275            }
276
277            PacketType::Disabled => {
278                let msg = String::from_utf8_lossy(payload).to_string();
279                let event = MeshCoreEvent::new(EventType::Disabled, EventPayload::String(msg));
280                self.dispatcher.emit(event).await;
281            }
282
283            PacketType::ChannelInfo => {
284                // Firmware always sends CHANNEL_INFO_LEN bytes: 1 (idx) + name + secret
285                if payload.len() >= CHANNEL_INFO_LEN {
286                    let channel_idx = payload[0];
287                    let name = read_string(payload, 1, CHANNEL_NAME_LEN);
288                    let secret: [u8; CHANNEL_SECRET_LEN] =
289                        read_bytes(payload, 1 + CHANNEL_NAME_LEN)
290                            .unwrap_or([0; CHANNEL_SECRET_LEN]);
291
292                    let event = MeshCoreEvent::new(
293                        EventType::ChannelInfo,
294                        EventPayload::ChannelInfo(ChannelInfoData {
295                            channel_idx,
296                            name,
297                            secret,
298                        }),
299                    );
300                    self.dispatcher.emit(event).await;
301                }
302            }
303
304            PacketType::SignStart => {
305                if payload.len() >= 4 {
306                    let max_length = read_u32_le(payload, 0).unwrap_or(0);
307                    let event = MeshCoreEvent::new(
308                        EventType::SignStart,
309                        EventPayload::SignStart { max_length },
310                    );
311                    self.dispatcher.emit(event).await;
312                }
313            }
314
315            PacketType::Signature => {
316                let event = MeshCoreEvent::new(
317                    EventType::Signature,
318                    EventPayload::Signature(payload.to_vec()),
319                );
320                self.dispatcher.emit(event).await;
321            }
322
323            PacketType::CustomVars => {
324                // Parse key-value pairs
325                let mut vars = HashMap::new();
326                let text = String::from_utf8_lossy(payload);
327                for line in text.lines() {
328                    if let Some((key, value)) = line.split_once('=') {
329                        vars.insert(key.to_string(), value.to_string());
330                    }
331                }
332                let event =
333                    MeshCoreEvent::new(EventType::CustomVars, EventPayload::CustomVars(vars));
334                self.dispatcher.emit(event).await;
335            }
336
337            PacketType::Stats => {
338                // Stats have a category byte followed by data
339                if !payload.is_empty() {
340                    let category = match payload[0] {
341                        0 => StatsCategory::Core,
342                        1 => StatsCategory::Radio,
343                        2 => StatsCategory::Packets,
344                        _ => StatsCategory::Core,
345                    };
346                    let event_type = match category {
347                        StatsCategory::Core => EventType::StatsCore,
348                        StatsCategory::Radio => EventType::StatsRadio,
349                        StatsCategory::Packets => EventType::StatsPackets,
350                    };
351                    let event = MeshCoreEvent::new(
352                        event_type,
353                        EventPayload::Stats(StatsData {
354                            category,
355                            raw: payload[1..].to_vec(),
356                        }),
357                    );
358                    self.dispatcher.emit(event).await;
359                }
360            }
361
362            PacketType::AutoaddConfig => {
363                let flags = if !payload.is_empty() { payload[0] } else { 0 };
364                let event = MeshCoreEvent::new(
365                    EventType::AutoAddConfig,
366                    EventPayload::AutoAddConfig { flags },
367                );
368                self.dispatcher.emit(event).await;
369            }
370
371            PacketType::Advertisement => {
372                if payload.len() >= 14 {
373                    let prefix: [u8; 6] = read_bytes(payload, 0).unwrap_or([0; 6]);
374                    let name = read_string(payload, 6, 32);
375                    let lat = if payload.len() >= 42 {
376                        read_i32_le(payload, 38).unwrap_or(0)
377                    } else {
378                        0
379                    };
380                    let lon = if payload.len() >= 46 {
381                        read_i32_le(payload, 42).unwrap_or(0)
382                    } else {
383                        0
384                    };
385
386                    let event = MeshCoreEvent::new(
387                        EventType::Advertisement,
388                        EventPayload::Advertisement(AdvertisementData {
389                            prefix,
390                            name,
391                            lat,
392                            lon,
393                        }),
394                    );
395                    self.dispatcher.emit(event).await;
396                }
397            }
398
399            PacketType::PathUpdate => {
400                if payload.len() >= 7 {
401                    let prefix: [u8; 6] = read_bytes(payload, 0).unwrap_or([0; 6]);
402                    let path_len = payload[6] as i8;
403                    let path = if payload.len() > 7 {
404                        payload[7..].to_vec()
405                    } else {
406                        Vec::new()
407                    };
408
409                    let event = MeshCoreEvent::new(
410                        EventType::PathUpdate,
411                        EventPayload::PathUpdate(PathUpdateData {
412                            prefix,
413                            path_len,
414                            path,
415                        }),
416                    );
417                    self.dispatcher.emit(event).await;
418                }
419            }
420
421            PacketType::Ack => {
422                if payload.len() >= 4 {
423                    let tag: [u8; 4] = read_bytes(payload, 0).unwrap_or([0; 4]);
424                    let event = MeshCoreEvent::new(EventType::Ack, EventPayload::Ack { tag })
425                        .with_attribute("tag", hex_encode(&tag));
426                    self.dispatcher.emit(event).await;
427                }
428            }
429
430            PacketType::MessagesWaiting => {
431                let event = MeshCoreEvent::new(EventType::MessagesWaiting, EventPayload::None);
432                self.dispatcher.emit(event).await;
433            }
434
435            PacketType::LoginSuccess => {
436                let event = MeshCoreEvent::new(EventType::LoginSuccess, EventPayload::None);
437                self.dispatcher.emit(event).await;
438            }
439
440            PacketType::LoginFailed => {
441                let event = MeshCoreEvent::new(EventType::LoginFailed, EventPayload::None);
442                self.dispatcher.emit(event).await;
443            }
444
445            PacketType::StatusResponse => {
446                if payload.len() >= 58 {
447                    // The first 6 bytes are the sender prefix
448                    let sender_prefix: [u8; 6] = read_bytes(payload, 0).unwrap_or([0; 6]);
449                    if let Ok(status) = parse_status(&payload[6..], sender_prefix) {
450                        let tag_hex = hex_encode(&sender_prefix);
451                        let event = MeshCoreEvent::new(
452                            EventType::StatusResponse,
453                            EventPayload::Status(status),
454                        )
455                        .with_attribute("prefix", tag_hex);
456                        self.dispatcher.emit(event).await;
457                    }
458                }
459            }
460
461            PacketType::TelemetryResponse => {
462                // The first bytes are tag, the rest is LPP data
463                if payload.len() >= 4 {
464                    let tag: [u8; 4] = read_bytes(payload, 0).unwrap_or([0; 4]);
465                    let telemetry = payload[4..].to_vec();
466                    let event = MeshCoreEvent::new(
467                        EventType::TelemetryResponse,
468                        EventPayload::Telemetry(telemetry),
469                    )
470                    .with_attribute("tag", hex_encode(&tag));
471                    self.dispatcher.emit(event).await;
472                }
473            }
474
475            PacketType::BinaryResponse => {
476                if payload.len() >= 4 {
477                    let tag: [u8; 4] = read_bytes(payload, 0).unwrap_or([0; 4]);
478                    let data = payload[4..].to_vec();
479
480                    // Check if we have a pending request for this tag
481                    let tag_hex = hex_encode(&tag);
482                    let request = self.pending_requests.write().await.remove(&tag_hex);
483
484                    if let Some(req) = request {
485                        // Emit typed event based on the request type
486                        let event = match req.request_type {
487                            BinaryReqType::Status => {
488                                if let Ok(status) = parse_status(&data, [0; 6]) {
489                                    MeshCoreEvent::new(
490                                        EventType::StatusResponse,
491                                        EventPayload::Status(status),
492                                    )
493                                } else {
494                                    MeshCoreEvent::new(
495                                        EventType::BinaryResponse,
496                                        EventPayload::BinaryResponse { tag, data },
497                                    )
498                                }
499                            }
500                            BinaryReqType::Telemetry => MeshCoreEvent::new(
501                                EventType::TelemetryResponse,
502                                EventPayload::Telemetry(data),
503                            ),
504                            BinaryReqType::Mma => {
505                                let entries = parse_mma(&data);
506                                MeshCoreEvent::new(
507                                    EventType::MmaResponse,
508                                    EventPayload::Mma(entries),
509                                )
510                            }
511                            BinaryReqType::Acl => {
512                                let entries = parse_acl(&data);
513                                MeshCoreEvent::new(
514                                    EventType::AclResponse,
515                                    EventPayload::Acl(entries),
516                                )
517                            }
518                            BinaryReqType::Neighbours => {
519                                // Default to 6-byte pubkey prefix
520                                if let Ok(neighbours) = parse_neighbours(&data, 6) {
521                                    MeshCoreEvent::new(
522                                        EventType::NeighboursResponse,
523                                        EventPayload::Neighbours(neighbours),
524                                    )
525                                } else {
526                                    MeshCoreEvent::new(
527                                        EventType::BinaryResponse,
528                                        EventPayload::BinaryResponse { tag, data },
529                                    )
530                                }
531                            }
532                            BinaryReqType::KeepAlive => MeshCoreEvent::new(
533                                EventType::BinaryResponse,
534                                EventPayload::BinaryResponse { tag, data },
535                            ),
536                        }
537                        .with_attribute("tag", tag_hex);
538
539                        self.dispatcher.emit(event).await;
540                    } else {
541                        // No matching request, emit generic binary response
542                        let event = MeshCoreEvent::new(
543                            EventType::BinaryResponse,
544                            EventPayload::BinaryResponse { tag, data },
545                        )
546                        .with_attribute("tag", tag_hex);
547                        self.dispatcher.emit(event).await;
548                    }
549                }
550            }
551
552            PacketType::ControlData => {
553                if !payload.is_empty() {
554                    let control_type = ControlType::from(payload[0]);
555                    match control_type {
556                        ControlType::NodeDiscoverResp => {
557                            // Parse discover response
558                            let mut entries = Vec::new();
559                            let mut offset = 1;
560                            while offset + 38 <= payload.len() {
561                                let pubkey = payload[offset..offset + 32].to_vec();
562                                let name = read_string(payload, offset + 32, 32);
563                                entries.push(DiscoverEntry { pubkey, name });
564                                offset += 64;
565                            }
566                            let event = MeshCoreEvent::new(
567                                EventType::DiscoverResponse,
568                                EventPayload::DiscoverResponse(entries),
569                            );
570                            self.dispatcher.emit(event).await;
571                        }
572                        _ => {
573                            let event = MeshCoreEvent::new(
574                                EventType::ControlData,
575                                EventPayload::Bytes(payload.to_vec()),
576                            );
577                            self.dispatcher.emit(event).await;
578                        }
579                    }
580                }
581            }
582
583            PacketType::TraceData => {
584                // Parse trace hops
585                let mut hops = Vec::new();
586                let mut offset = 0;
587                while offset + 7 <= payload.len() {
588                    let prefix: [u8; 6] = read_bytes(payload, offset).unwrap_or([0; 6]);
589                    let snr_raw = payload[offset + 6] as i8;
590                    let snr = snr_raw as f32 / 4.0;
591                    hops.push(TraceHop { prefix, snr });
592                    offset += 7;
593                }
594                let event = MeshCoreEvent::new(
595                    EventType::TraceData,
596                    EventPayload::TraceData(TraceInfo { hops }),
597                );
598                self.dispatcher.emit(event).await;
599            }
600
601            PacketType::AdvertResponse => {
602                if payload.len() >= 42 {
603                    let tag: [u8; 4] = read_bytes(payload, 0).unwrap_or([0; 4]);
604                    let pubkey: [u8; 32] = read_bytes(payload, 4).unwrap_or([0; 32]);
605                    let adv_type = payload[36];
606                    let node_name = read_string(payload, 37, 32);
607                    let timestamp = read_u32_le(payload, 69).unwrap_or(0);
608                    let flags = if payload.len() > 73 { payload[73] } else { 0 };
609
610                    let (lat, lon, node_desc) = if payload.len() >= 82 {
611                        let lat = Some(read_i32_le(payload, 74).unwrap_or(0));
612                        let lon = Some(read_i32_le(payload, 78).unwrap_or(0));
613                        let desc = if payload.len() > 82 {
614                            Some(read_string(payload, 82, 32))
615                        } else {
616                            None
617                        };
618                        (lat, lon, desc)
619                    } else {
620                        (None, None, None)
621                    };
622
623                    let event = MeshCoreEvent::new(
624                        EventType::AdvertResponse,
625                        EventPayload::AdvertResponse(AdvertResponseData {
626                            tag,
627                            pubkey,
628                            adv_type,
629                            node_name,
630                            timestamp,
631                            flags,
632                            lat,
633                            lon,
634                            node_desc,
635                        }),
636                    )
637                    .with_attribute("tag", hex_encode(&tag));
638                    self.dispatcher.emit(event).await;
639                }
640            }
641            PacketType::BinaryReq => {}
642            PacketType::FactoryReset => {}
643            PacketType::PathDiscovery => {}
644            PacketType::SetFloodScope => {}
645            PacketType::SendControlData => {}
646            PacketType::RawData => {}
647            PacketType::LogData => {
648                // LOG_DATA format:
649                // Byte 0: SNR (signed byte, divide by 4.0)
650                // Byte 1: RSSI (signed byte)
651                // Bytes 2+: Raw RF payload
652                if payload.len() >= 2 {
653                    let snr_byte = payload[0] as i8;
654                    let snr = snr_byte as f32 / 4.0;
655
656                    let rssi = payload[1] as i8 as i16;
657
658                    let rf_payload = if payload.len() > 2 {
659                        payload[2..].to_vec()
660                    } else {
661                        Vec::new()
662                    };
663
664                    let log_data = LogData {
665                        snr,
666                        rssi,
667                        payload: rf_payload,
668                    };
669                    let event =
670                        MeshCoreEvent::new(EventType::LogData, EventPayload::LogData(log_data));
671                    self.dispatcher.emit(event).await;
672                }
673            }
674            PacketType::PathDiscoveryResponse => {}
675            _ => {
676                // Unknown packet type - emit raw data
677                tracing::debug!("Unknown packet type: {:?}", packet_type);
678                let event = MeshCoreEvent::new(EventType::Unknown, EventPayload::Bytes(data));
679                self.dispatcher.emit(event).await;
680            }
681        }
682
683        Ok(())
684    }
685}
686
687#[cfg(test)]
688mod tests {
689    use super::*;
690    use std::time::Duration;
691
692    fn create_reader() -> (MessageReader, Arc<EventDispatcher>) {
693        let dispatcher = Arc::new(EventDispatcher::new());
694        let reader = MessageReader::new(dispatcher.clone());
695        (reader, dispatcher)
696    }
697
698    #[tokio::test]
699    async fn test_handle_rx_empty() {
700        let (reader, _dispatcher) = create_reader();
701        let result = reader.handle_rx(vec![]).await;
702        assert!(result.is_ok());
703    }
704
705    #[tokio::test]
706    async fn test_handle_rx_ok() {
707        let (reader, dispatcher) = create_reader();
708        let mut receiver = dispatcher.receiver();
709
710        reader.handle_rx(vec![PacketType::Ok as u8]).await.unwrap();
711
712        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
713            .await
714            .unwrap()
715            .unwrap();
716
717        assert_eq!(event.event_type, EventType::Ok);
718    }
719
720    #[tokio::test]
721    async fn test_handle_rx_error_with_message() {
722        let (reader, dispatcher) = create_reader();
723        let mut receiver = dispatcher.receiver();
724
725        let mut data = vec![PacketType::Error as u8];
726        data.extend_from_slice(b"Test error");
727
728        reader.handle_rx(data).await.unwrap();
729
730        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
731            .await
732            .unwrap()
733            .unwrap();
734
735        assert_eq!(event.event_type, EventType::Error);
736        match event.payload {
737            EventPayload::String(s) => assert_eq!(s, "Test error"),
738            _ => panic!("Expected String payload"),
739        }
740    }
741
742    #[tokio::test]
743    async fn test_handle_rx_error_empty() {
744        let (reader, dispatcher) = create_reader();
745        let mut receiver = dispatcher.receiver();
746
747        reader
748            .handle_rx(vec![PacketType::Error as u8])
749            .await
750            .unwrap();
751
752        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
753            .await
754            .unwrap()
755            .unwrap();
756
757        assert_eq!(event.event_type, EventType::Error);
758        match event.payload {
759            EventPayload::String(s) => assert_eq!(s, "Unknown error"),
760            _ => panic!("Expected String payload"),
761        }
762    }
763
764    #[tokio::test]
765    async fn test_handle_rx_contact_start() {
766        let (reader, _dispatcher) = create_reader();
767
768        // Add some fake contacts
769        reader.pending_contacts.write().await.push(Contact {
770            public_key: [0u8; 32],
771            contact_type: 1,
772            flags: 0,
773            path_len: 0,
774            out_path: vec![],
775            adv_name: "Old".to_string(),
776            last_advert: 0,
777            adv_lat: 0,
778            adv_lon: 0,
779            last_modification_timestamp: 0,
780        });
781
782        reader
783            .handle_rx(vec![PacketType::ContactStart as u8])
784            .await
785            .unwrap();
786
787        // Verify pending contacts were cleared
788        assert!(reader.pending_contacts.read().await.is_empty());
789    }
790
791    #[tokio::test]
792    async fn test_handle_rx_battery() {
793        let (reader, dispatcher) = create_reader();
794        let mut receiver = dispatcher.receiver();
795
796        // Test with just battery voltage (no storage info)
797        let mut data = vec![PacketType::Battery as u8];
798        data.extend_from_slice(&4200u16.to_le_bytes()); // battery_mv (4.2V)
799
800        reader.handle_rx(data).await.unwrap();
801
802        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
803            .await
804            .unwrap()
805            .unwrap();
806
807        assert_eq!(event.event_type, EventType::Battery);
808        match event.payload {
809            EventPayload::Battery(info) => {
810                assert_eq!(info.battery_mv, 4200);
811                assert!(info.used_kb.is_none());
812                assert!(info.total_kb.is_none());
813                assert!((info.voltage() - 4.2).abs() < 0.001);
814            }
815            _ => panic!("Expected Battery payload"),
816        }
817    }
818
819    #[tokio::test]
820    async fn test_handle_rx_battery_with_storage() {
821        let (reader, dispatcher) = create_reader();
822        let mut receiver = dispatcher.receiver();
823
824        // Test with battery voltage and storage info
825        let mut data = vec![PacketType::Battery as u8];
826        data.extend_from_slice(&3700u16.to_le_bytes()); // battery_mv (3.7V)
827        data.extend_from_slice(&512u32.to_le_bytes()); // used_kb
828        data.extend_from_slice(&4096u32.to_le_bytes()); // total_kb
829
830        reader.handle_rx(data).await.unwrap();
831
832        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
833            .await
834            .unwrap()
835            .unwrap();
836
837        assert_eq!(event.event_type, EventType::Battery);
838        match event.payload {
839            EventPayload::Battery(info) => {
840                assert_eq!(info.battery_mv, 3700);
841                assert_eq!(info.used_kb, Some(512));
842                assert_eq!(info.total_kb, Some(4096));
843                assert!((info.voltage() - 3.7).abs() < 0.001);
844            }
845            _ => panic!("Expected Battery payload"),
846        }
847    }
848
849    #[tokio::test]
850    async fn test_handle_rx_current_time() {
851        let (reader, dispatcher) = create_reader();
852        let mut receiver = dispatcher.receiver();
853
854        let mut data = vec![PacketType::CurrentTime as u8];
855        data.extend_from_slice(&1234567890u32.to_le_bytes());
856
857        reader.handle_rx(data).await.unwrap();
858
859        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
860            .await
861            .unwrap()
862            .unwrap();
863
864        assert_eq!(event.event_type, EventType::CurrentTime);
865        match event.payload {
866            EventPayload::Time(t) => assert_eq!(t, 1234567890),
867            _ => panic!("Expected Time payload"),
868        }
869    }
870
871    #[tokio::test]
872    async fn test_handle_rx_no_more_msgs() {
873        let (reader, dispatcher) = create_reader();
874        let mut receiver = dispatcher.receiver();
875
876        reader
877            .handle_rx(vec![PacketType::NoMoreMsgs as u8])
878            .await
879            .unwrap();
880
881        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
882            .await
883            .unwrap()
884            .unwrap();
885
886        assert_eq!(event.event_type, EventType::NoMoreMessages);
887    }
888
889    #[tokio::test]
890    async fn test_handle_rx_contact_uri() {
891        let (reader, dispatcher) = create_reader();
892        let mut receiver = dispatcher.receiver();
893
894        let mut data = vec![PacketType::ContactUri as u8];
895        data.extend_from_slice(b"mod.rs://contact/abc123");
896
897        reader.handle_rx(data).await.unwrap();
898
899        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
900            .await
901            .unwrap()
902            .unwrap();
903
904        assert_eq!(event.event_type, EventType::ContactUri);
905        match event.payload {
906            EventPayload::String(s) => assert_eq!(s, "mod.rs://contact/abc123"),
907            _ => panic!("Expected String payload"),
908        }
909    }
910
911    #[tokio::test]
912    async fn test_handle_rx_private_key() {
913        let (reader, dispatcher) = create_reader();
914        let mut receiver = dispatcher.receiver();
915
916        let mut data = vec![PacketType::PrivateKey as u8];
917        let key = [0xAA; 64];
918        data.extend_from_slice(&key);
919
920        reader.handle_rx(data).await.unwrap();
921
922        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
923            .await
924            .unwrap()
925            .unwrap();
926
927        assert_eq!(event.event_type, EventType::PrivateKey);
928        match event.payload {
929            EventPayload::PrivateKey(k) => assert_eq!(k, [0xAA; 64]),
930            _ => panic!("Expected PrivateKey payload"),
931        }
932    }
933
934    #[tokio::test]
935    async fn test_handle_rx_disabled() {
936        let (reader, dispatcher) = create_reader();
937        let mut receiver = dispatcher.receiver();
938
939        let mut data = vec![PacketType::Disabled as u8];
940        data.extend_from_slice(b"Feature disabled");
941
942        reader.handle_rx(data).await.unwrap();
943
944        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
945            .await
946            .unwrap()
947            .unwrap();
948
949        assert_eq!(event.event_type, EventType::Disabled);
950        match event.payload {
951            EventPayload::String(s) => assert_eq!(s, "Feature disabled"),
952            _ => panic!("Expected String payload"),
953        }
954    }
955
956    #[tokio::test]
957    async fn test_handle_rx_sign_start() {
958        let (reader, dispatcher) = create_reader();
959        let mut receiver = dispatcher.receiver();
960
961        let mut data = vec![PacketType::SignStart as u8];
962        data.extend_from_slice(&1024u32.to_le_bytes());
963
964        reader.handle_rx(data).await.unwrap();
965
966        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
967            .await
968            .unwrap()
969            .unwrap();
970
971        assert_eq!(event.event_type, EventType::SignStart);
972        match event.payload {
973            EventPayload::SignStart { max_length } => assert_eq!(max_length, 1024),
974            _ => panic!("Expected SignStart payload"),
975        }
976    }
977
978    #[tokio::test]
979    async fn test_handle_rx_signature() {
980        let (reader, dispatcher) = create_reader();
981        let mut receiver = dispatcher.receiver();
982
983        let mut data = vec![PacketType::Signature as u8];
984        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]);
985
986        reader.handle_rx(data).await.unwrap();
987
988        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
989            .await
990            .unwrap()
991            .unwrap();
992
993        assert_eq!(event.event_type, EventType::Signature);
994        match event.payload {
995            EventPayload::Signature(sig) => assert_eq!(sig, vec![0x01, 0x02, 0x03, 0x04]),
996            _ => panic!("Expected Signature payload"),
997        }
998    }
999
1000    #[tokio::test]
1001    async fn test_handle_rx_custom_vars() {
1002        let (reader, dispatcher) = create_reader();
1003        let mut receiver = dispatcher.receiver();
1004
1005        let mut data = vec![PacketType::CustomVars as u8];
1006        data.extend_from_slice(b"key1=value1\nkey2=value2");
1007
1008        reader.handle_rx(data).await.unwrap();
1009
1010        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1011            .await
1012            .unwrap()
1013            .unwrap();
1014
1015        assert_eq!(event.event_type, EventType::CustomVars);
1016        match event.payload {
1017            EventPayload::CustomVars(vars) => {
1018                assert_eq!(vars.get("key1"), Some(&"value1".to_string()));
1019                assert_eq!(vars.get("key2"), Some(&"value2".to_string()));
1020            }
1021            _ => panic!("Expected CustomVars payload"),
1022        }
1023    }
1024
1025    #[tokio::test]
1026    async fn test_handle_rx_msg_sent() {
1027        let (reader, dispatcher) = create_reader();
1028        let mut receiver = dispatcher.receiver();
1029
1030        let mut data = vec![PacketType::MsgSent as u8];
1031        data.push(1); // message_type
1032        data.extend_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD]); // expected_ack
1033        data.extend_from_slice(&5000u32.to_le_bytes()); // suggested_timeout
1034
1035        reader.handle_rx(data).await.unwrap();
1036
1037        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1038            .await
1039            .unwrap()
1040            .unwrap();
1041
1042        assert_eq!(event.event_type, EventType::MsgSent);
1043        match event.payload {
1044            EventPayload::MsgSent(info) => {
1045                assert_eq!(info.message_type, 1);
1046                assert_eq!(info.expected_ack, [0xAA, 0xBB, 0xCC, 0xDD]);
1047                assert_eq!(info.suggested_timeout, 5000);
1048            }
1049            _ => panic!("Expected MsgSent payload"),
1050        }
1051        assert_eq!(event.attributes.get("tag"), Some(&"aabbccdd".to_string()));
1052    }
1053
1054    #[tokio::test]
1055    async fn test_handle_rx_ack() {
1056        let (reader, dispatcher) = create_reader();
1057        let mut receiver = dispatcher.receiver();
1058
1059        let mut data = vec![PacketType::Ack as u8];
1060        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]);
1061
1062        reader.handle_rx(data).await.unwrap();
1063
1064        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1065            .await
1066            .unwrap()
1067            .unwrap();
1068
1069        assert_eq!(event.event_type, EventType::Ack);
1070        match event.payload {
1071            EventPayload::Ack { tag } => assert_eq!(tag, [0x01, 0x02, 0x03, 0x04]),
1072            _ => panic!("Expected Ack payload"),
1073        }
1074    }
1075
1076    #[tokio::test]
1077    async fn test_handle_rx_messages_waiting() {
1078        let (reader, dispatcher) = create_reader();
1079        let mut receiver = dispatcher.receiver();
1080
1081        reader
1082            .handle_rx(vec![PacketType::MessagesWaiting as u8])
1083            .await
1084            .unwrap();
1085
1086        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1087            .await
1088            .unwrap()
1089            .unwrap();
1090
1091        assert_eq!(event.event_type, EventType::MessagesWaiting);
1092    }
1093
1094    #[tokio::test]
1095    async fn test_handle_rx_login_success() {
1096        let (reader, dispatcher) = create_reader();
1097        let mut receiver = dispatcher.receiver();
1098
1099        reader
1100            .handle_rx(vec![PacketType::LoginSuccess as u8])
1101            .await
1102            .unwrap();
1103
1104        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1105            .await
1106            .unwrap()
1107            .unwrap();
1108
1109        assert_eq!(event.event_type, EventType::LoginSuccess);
1110    }
1111
1112    #[tokio::test]
1113    async fn test_handle_rx_login_failed() {
1114        let (reader, dispatcher) = create_reader();
1115        let mut receiver = dispatcher.receiver();
1116
1117        reader
1118            .handle_rx(vec![PacketType::LoginFailed as u8])
1119            .await
1120            .unwrap();
1121
1122        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1123            .await
1124            .unwrap()
1125            .unwrap();
1126
1127        assert_eq!(event.event_type, EventType::LoginFailed);
1128    }
1129
1130    #[tokio::test]
1131    async fn test_handle_rx_stats_core() {
1132        let (reader, dispatcher) = create_reader();
1133        let mut receiver = dispatcher.receiver();
1134
1135        let mut data = vec![PacketType::Stats as u8];
1136        data.push(0); // StatsCategory::Core
1137        data.extend_from_slice(&[0x01, 0x02, 0x03]);
1138
1139        reader.handle_rx(data).await.unwrap();
1140
1141        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1142            .await
1143            .unwrap()
1144            .unwrap();
1145
1146        assert_eq!(event.event_type, EventType::StatsCore);
1147        match event.payload {
1148            EventPayload::Stats(stats) => {
1149                assert_eq!(stats.category, StatsCategory::Core);
1150                assert_eq!(stats.raw, vec![0x01, 0x02, 0x03]);
1151            }
1152            _ => panic!("Expected Stats payload"),
1153        }
1154    }
1155
1156    #[tokio::test]
1157    async fn test_handle_rx_stats_radio() {
1158        let (reader, dispatcher) = create_reader();
1159        let mut receiver = dispatcher.receiver();
1160
1161        let mut data = vec![PacketType::Stats as u8];
1162        data.push(1); // StatsCategory::Radio
1163        data.extend_from_slice(&[0x04, 0x05]);
1164
1165        reader.handle_rx(data).await.unwrap();
1166
1167        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1168            .await
1169            .unwrap()
1170            .unwrap();
1171
1172        assert_eq!(event.event_type, EventType::StatsRadio);
1173    }
1174
1175    #[tokio::test]
1176    async fn test_handle_rx_stats_packets() {
1177        let (reader, dispatcher) = create_reader();
1178        let mut receiver = dispatcher.receiver();
1179
1180        let mut data = vec![PacketType::Stats as u8];
1181        data.push(2); // StatsCategory::Packets
1182        data.extend_from_slice(&[0x06, 0x07]);
1183
1184        reader.handle_rx(data).await.unwrap();
1185
1186        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1187            .await
1188            .unwrap()
1189            .unwrap();
1190
1191        assert_eq!(event.event_type, EventType::StatsPackets);
1192    }
1193
1194    #[tokio::test]
1195    async fn test_handle_rx_autoadd_config() {
1196        let (reader, dispatcher) = create_reader();
1197        let mut receiver = dispatcher.receiver();
1198
1199        let data = vec![PacketType::AutoaddConfig as u8, 0x03];
1200
1201        reader.handle_rx(data).await.unwrap();
1202
1203        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1204            .await
1205            .unwrap()
1206            .unwrap();
1207
1208        assert_eq!(event.event_type, EventType::AutoAddConfig);
1209        match event.payload {
1210            EventPayload::AutoAddConfig { flags } => assert_eq!(flags, 0x03),
1211            _ => panic!("Expected AutoAddConfig payload"),
1212        }
1213    }
1214
1215    #[tokio::test]
1216    async fn test_handle_rx_device_info_minimal() {
1217        let (reader, dispatcher) = create_reader();
1218        let mut receiver = dispatcher.receiver();
1219
1220        // Minimal device info: just fw_version_code
1221        let mut data = vec![PacketType::DeviceInfo as u8];
1222        data.push(0x02); // fw_version_code = 2 (pre-v3)
1223
1224        reader.handle_rx(data).await.unwrap();
1225
1226        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1227            .await
1228            .unwrap()
1229            .unwrap();
1230
1231        assert_eq!(event.event_type, EventType::DeviceInfo);
1232        match event.payload {
1233            EventPayload::DeviceInfo(info) => {
1234                assert_eq!(info.fw_version_code, 0x02);
1235                assert!(info.max_contacts.is_none());
1236                assert!(info.model.is_none());
1237            }
1238            _ => panic!("Expected DeviceInfo payload"),
1239        }
1240    }
1241
1242    #[tokio::test]
1243    async fn test_handle_rx_device_info_full() {
1244        let (reader, dispatcher) = create_reader();
1245        let mut receiver = dispatcher.receiver();
1246
1247        let mut data = vec![PacketType::DeviceInfo as u8];
1248        // Build a full v3+ device info payload
1249        data.push(9); // fw_version_code (v9+)
1250        data.push(50); // max_contacts / 2 = 50, so max_contacts = 100
1251        data.push(8); // max_channels
1252        data.extend_from_slice(&1234u32.to_le_bytes()); // ble_pin
1253
1254        // fw_build (12 bytes)
1255        let mut fw_build = [0u8; 12];
1256        fw_build[..11].copy_from_slice(b"Feb 15 2025");
1257        data.extend_from_slice(&fw_build);
1258
1259        // model (40 bytes)
1260        let mut model = [0u8; 40];
1261        model[..10].copy_from_slice(b"T-Deck Pro");
1262        data.extend_from_slice(&model);
1263
1264        // version (20 bytes)
1265        let mut version = [0u8; 20];
1266        version[..5].copy_from_slice(b"1.2.3");
1267        data.extend_from_slice(&version);
1268
1269        // repeat (1 byte)
1270        data.push(1); // repeat enabled
1271
1272        reader.handle_rx(data).await.unwrap();
1273
1274        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1275            .await
1276            .unwrap()
1277            .unwrap();
1278
1279        assert_eq!(event.event_type, EventType::DeviceInfo);
1280        match event.payload {
1281            EventPayload::DeviceInfo(info) => {
1282                assert_eq!(info.fw_version_code, 9);
1283                assert_eq!(info.max_contacts, Some(100));
1284                assert_eq!(info.max_channels, Some(8));
1285                assert_eq!(info.ble_pin, Some(1234));
1286                assert_eq!(info.fw_build.as_deref(), Some("Feb 15 2025"));
1287                assert_eq!(info.model.as_deref(), Some("T-Deck Pro"));
1288                assert_eq!(info.version.as_deref(), Some("1.2.3"));
1289                assert_eq!(info.repeat, Some(true));
1290            }
1291            _ => panic!("Expected DeviceInfo payload"),
1292        }
1293    }
1294
1295    #[tokio::test]
1296    async fn test_handle_rx_path_update() {
1297        let (reader, dispatcher) = create_reader();
1298        let mut receiver = dispatcher.receiver();
1299
1300        let mut data = vec![PacketType::PathUpdate as u8];
1301        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]); // prefix
1302        data.push(3); // path_len
1303        data.extend_from_slice(&[0x0A, 0x0B, 0x0C]); // path
1304
1305        reader.handle_rx(data).await.unwrap();
1306
1307        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1308            .await
1309            .unwrap()
1310            .unwrap();
1311
1312        assert_eq!(event.event_type, EventType::PathUpdate);
1313        match event.payload {
1314            EventPayload::PathUpdate(update) => {
1315                assert_eq!(update.prefix, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
1316                assert_eq!(update.path_len, 3);
1317                assert_eq!(update.path, vec![0x0A, 0x0B, 0x0C]);
1318            }
1319            _ => panic!("Expected PathUpdate payload"),
1320        }
1321    }
1322
1323    #[tokio::test]
1324    async fn test_handle_rx_telemetry_response() {
1325        let (reader, dispatcher) = create_reader();
1326        let mut receiver = dispatcher.receiver();
1327
1328        let mut data = vec![PacketType::TelemetryResponse as u8];
1329        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]); // tag
1330        data.extend_from_slice(&[0xAA, 0xBB, 0xCC]); // telemetry data
1331
1332        reader.handle_rx(data).await.unwrap();
1333
1334        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1335            .await
1336            .unwrap()
1337            .unwrap();
1338
1339        assert_eq!(event.event_type, EventType::TelemetryResponse);
1340        match event.payload {
1341            EventPayload::Telemetry(data) => assert_eq!(data, vec![0xAA, 0xBB, 0xCC]),
1342            _ => panic!("Expected Telemetry payload"),
1343        }
1344    }
1345
1346    #[tokio::test]
1347    async fn test_handle_rx_trace_data() {
1348        let (reader, dispatcher) = create_reader();
1349        let mut receiver = dispatcher.receiver();
1350
1351        let mut data = vec![PacketType::TraceData as u8];
1352        // Hop 1: 6 bytes prefix + 1 byte snr
1353        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
1354        data.push(40); // snr = 10.0
1355                       // Hop 2
1356        data.extend_from_slice(&[0x11, 0x12, 0x13, 0x14, 0x15, 0x16]);
1357        data.push(20); // snr = 5.0
1358
1359        reader.handle_rx(data).await.unwrap();
1360
1361        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1362            .await
1363            .unwrap()
1364            .unwrap();
1365
1366        assert_eq!(event.event_type, EventType::TraceData);
1367        match event.payload {
1368            EventPayload::TraceData(info) => {
1369                assert_eq!(info.hops.len(), 2);
1370                assert_eq!(info.hops[0].snr, 10.0);
1371                assert_eq!(info.hops[1].snr, 5.0);
1372            }
1373            _ => panic!("Expected TraceData payload"),
1374        }
1375    }
1376
1377    #[tokio::test]
1378    async fn test_handle_rx_unknown() {
1379        let (reader, dispatcher) = create_reader();
1380        let mut receiver = dispatcher.receiver();
1381
1382        let data = vec![0xFE, 0x01, 0x02, 0x03];
1383
1384        reader.handle_rx(data.clone()).await.unwrap();
1385
1386        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1387            .await
1388            .unwrap()
1389            .unwrap();
1390
1391        assert_eq!(event.event_type, EventType::Unknown);
1392        match event.payload {
1393            EventPayload::Bytes(d) => assert_eq!(d, data),
1394            _ => panic!("Expected Bytes payload"),
1395        }
1396    }
1397
1398    #[tokio::test]
1399    async fn test_register_binary_request() {
1400        let (reader, _dispatcher) = create_reader();
1401
1402        reader
1403            .register_binary_request(
1404                &[0x01, 0x02, 0x03, 0x04],
1405                BinaryReqType::Status,
1406                vec![0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF],
1407                Duration::from_secs(30),
1408                HashMap::new(),
1409                false,
1410            )
1411            .await;
1412
1413        let requests = reader.pending_requests.read().await;
1414        assert!(requests.contains_key("01020304"));
1415    }
1416
1417    #[tokio::test]
1418    async fn test_cleanup_expired() {
1419        let (reader, _dispatcher) = create_reader();
1420
1421        // Register a request with immediate expiration
1422        reader
1423            .register_binary_request(
1424                &[0x01, 0x02, 0x03, 0x04],
1425                BinaryReqType::Status,
1426                vec![],
1427                Duration::from_millis(1),
1428                HashMap::new(),
1429                false,
1430            )
1431            .await;
1432
1433        // Wait for expiration
1434        tokio::time::sleep(Duration::from_millis(10)).await;
1435
1436        // Trigger cleanup
1437        reader.cleanup_expired().await;
1438
1439        let requests = reader.pending_requests.read().await;
1440        assert!(requests.is_empty());
1441    }
1442
1443    #[tokio::test]
1444    async fn test_handle_rx_binary_response_with_pending_request() {
1445        let (reader, dispatcher) = create_reader();
1446        let mut receiver = dispatcher.receiver();
1447
1448        // Register a pending request
1449        reader
1450            .register_binary_request(
1451                &[0x01, 0x02, 0x03, 0x04],
1452                BinaryReqType::Telemetry,
1453                vec![],
1454                Duration::from_secs(30),
1455                HashMap::new(),
1456                false,
1457            )
1458            .await;
1459
1460        let mut data = vec![PacketType::BinaryResponse as u8];
1461        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]); // matching tag
1462        data.extend_from_slice(&[0xAA, 0xBB, 0xCC]); // telemetry data
1463
1464        reader.handle_rx(data).await.unwrap();
1465
1466        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1467            .await
1468            .unwrap()
1469            .unwrap();
1470
1471        // Should emit TelemetryResponse due to the pending request type
1472        assert_eq!(event.event_type, EventType::TelemetryResponse);
1473    }
1474
1475    #[tokio::test]
1476    async fn test_handle_rx_binary_response_no_pending() {
1477        let (reader, dispatcher) = create_reader();
1478        let mut receiver = dispatcher.receiver();
1479
1480        let mut data = vec![PacketType::BinaryResponse as u8];
1481        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]); // tag
1482        data.extend_from_slice(&[0xAA, 0xBB, 0xCC]); // data
1483
1484        reader.handle_rx(data).await.unwrap();
1485
1486        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1487            .await
1488            .unwrap()
1489            .unwrap();
1490
1491        // Should emit generic BinaryResponse
1492        assert_eq!(event.event_type, EventType::BinaryResponse);
1493    }
1494
1495    #[tokio::test]
1496    async fn test_handle_rx_channel_info() {
1497        let (reader, dispatcher) = create_reader();
1498        let mut receiver = dispatcher.receiver();
1499
1500        let mut data = vec![PacketType::ChannelInfo as u8];
1501        data.push(1); // channel_idx
1502        let mut name = [0u8; CHANNEL_NAME_LEN];
1503        name[..7].copy_from_slice(b"General");
1504        data.extend_from_slice(&name);
1505        data.extend_from_slice(&[0xAA; CHANNEL_SECRET_LEN]); // secret
1506
1507        reader.handle_rx(data).await.unwrap();
1508
1509        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1510            .await
1511            .unwrap()
1512            .unwrap();
1513
1514        assert_eq!(event.event_type, EventType::ChannelInfo);
1515        match event.payload {
1516            EventPayload::ChannelInfo(info) => {
1517                assert_eq!(info.channel_idx, 1);
1518                assert_eq!(info.name, "General");
1519                assert_eq!(info.secret, [0xAA; CHANNEL_SECRET_LEN]);
1520            }
1521            _ => panic!("Expected ChannelInfo payload"),
1522        }
1523    }
1524
1525    #[tokio::test]
1526    async fn test_handle_rx_channel_info_zero_secret() {
1527        let (reader, dispatcher) = create_reader();
1528        let mut receiver = dispatcher.receiver();
1529
1530        let mut data = vec![PacketType::ChannelInfo as u8];
1531        data.push(2); // channel_idx
1532        let mut name = [0u8; CHANNEL_NAME_LEN];
1533        name[..4].copy_from_slice(b"Test");
1534        data.extend_from_slice(&name);
1535        data.extend_from_slice(&[0u8; CHANNEL_SECRET_LEN]); // zero secret
1536
1537        reader.handle_rx(data).await.unwrap();
1538
1539        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1540            .await
1541            .unwrap()
1542            .unwrap();
1543
1544        assert_eq!(event.event_type, EventType::ChannelInfo);
1545        match event.payload {
1546            EventPayload::ChannelInfo(info) => {
1547                assert_eq!(info.channel_idx, 2);
1548                assert_eq!(info.name, "Test");
1549                assert_eq!(info.secret, [0; CHANNEL_SECRET_LEN]);
1550            }
1551            _ => panic!("Expected ChannelInfo payload"),
1552        }
1553    }
1554
1555    #[tokio::test]
1556    async fn test_handle_rx_channel_info_too_short() {
1557        let (reader, dispatcher) = create_reader();
1558        let mut receiver = dispatcher.receiver();
1559
1560        // Payload shorter than CHANNEL_INFO_LEN (49 bytes) should not emit event
1561        let mut data = vec![PacketType::ChannelInfo as u8];
1562        data.push(1); // channel_idx
1563        let name = [0u8; CHANNEL_NAME_LEN];
1564        data.extend_from_slice(&name);
1565        // Missing secret - only 33 bytes total, need 49
1566
1567        reader.handle_rx(data).await.unwrap();
1568
1569        // Should timeout because no event is emitted for short payload
1570        let result = tokio::time::timeout(Duration::from_millis(50), receiver.recv()).await;
1571        assert!(result.is_err(), "Should not emit event for short payload");
1572    }
1573
1574    #[tokio::test]
1575    async fn test_handle_rx_channel_info_max_name_length() {
1576        let (reader, dispatcher) = create_reader();
1577        let mut receiver = dispatcher.receiver();
1578
1579        let mut data = vec![PacketType::ChannelInfo as u8];
1580        data.push(3); // channel_idx
1581                      // Fill name with 31 chars + null terminator
1582        let mut name = [0u8; CHANNEL_NAME_LEN];
1583        let long_name = b"This is a very long channel nam"; // 31 chars
1584        name[..31].copy_from_slice(long_name);
1585        data.extend_from_slice(&name);
1586        data.extend_from_slice(&[0xBB; CHANNEL_SECRET_LEN]);
1587
1588        reader.handle_rx(data).await.unwrap();
1589
1590        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1591            .await
1592            .unwrap()
1593            .unwrap();
1594
1595        assert_eq!(event.event_type, EventType::ChannelInfo);
1596        match event.payload {
1597            EventPayload::ChannelInfo(info) => {
1598                assert_eq!(info.channel_idx, 3);
1599                assert_eq!(info.name, "This is a very long channel nam");
1600                assert_eq!(info.name.len(), 31);
1601                assert_eq!(info.secret, [0xBB; CHANNEL_SECRET_LEN]);
1602            }
1603            _ => panic!("Expected ChannelInfo payload"),
1604        }
1605    }
1606
1607    #[tokio::test]
1608    async fn test_handle_rx_advertisement() {
1609        let (reader, dispatcher) = create_reader();
1610        let mut receiver = dispatcher.receiver();
1611
1612        let mut data = vec![PacketType::Advertisement as u8];
1613        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]); // prefix
1614                                                                       // name (32 bytes padded)
1615        let mut name_bytes = [0u8; 32];
1616        name_bytes[..5].copy_from_slice(b"Node1");
1617        data.extend_from_slice(&name_bytes);
1618        // lat at offset 38
1619        data.extend_from_slice(&37774900i32.to_le_bytes());
1620        // lon at offset 42
1621        data.extend_from_slice(&(-122419400i32).to_le_bytes());
1622
1623        reader.handle_rx(data).await.unwrap();
1624
1625        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1626            .await
1627            .unwrap()
1628            .unwrap();
1629
1630        assert_eq!(event.event_type, EventType::Advertisement);
1631        match event.payload {
1632            EventPayload::Advertisement(adv) => {
1633                assert_eq!(adv.prefix, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
1634                assert_eq!(adv.name, "Node1");
1635                assert_eq!(adv.lat, 37774900);
1636                assert_eq!(adv.lon, -122419400);
1637            }
1638            _ => panic!("Expected Advertisement payload"),
1639        }
1640    }
1641
1642    #[tokio::test]
1643    async fn test_handle_rx_advertisement_minimal() {
1644        let (reader, dispatcher) = create_reader();
1645        let mut receiver = dispatcher.receiver();
1646
1647        let mut data = vec![PacketType::Advertisement as u8];
1648        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]); // prefix
1649                                                                       // Just 8 bytes for name (minimal)
1650        data.extend_from_slice(b"ShortNam");
1651
1652        reader.handle_rx(data).await.unwrap();
1653
1654        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1655            .await
1656            .unwrap()
1657            .unwrap();
1658
1659        assert_eq!(event.event_type, EventType::Advertisement);
1660        match event.payload {
1661            EventPayload::Advertisement(adv) => {
1662                assert_eq!(adv.lat, 0); // default when not present
1663                assert_eq!(adv.lon, 0);
1664            }
1665            _ => panic!("Expected Advertisement payload"),
1666        }
1667    }
1668
1669    #[tokio::test]
1670    async fn test_handle_rx_self_info() {
1671        let (reader, dispatcher) = create_reader();
1672        let mut receiver = dispatcher.receiver();
1673
1674        let mut data = vec![PacketType::SelfInfo as u8];
1675        // Create a minimal valid self_info buffer (52+ bytes)
1676        let mut payload = vec![0u8; 60];
1677        payload[0] = 1; // adv_type
1678        payload[1] = 20; // tx_power
1679        payload[2] = 30; // max_tx_power
1680        payload[35..39].copy_from_slice(&37774900i32.to_le_bytes()); // adv_lat
1681        payload[39..43].copy_from_slice(&(-122419400i32).to_le_bytes()); // adv_lon
1682        payload[47..51].copy_from_slice(&915000000u32.to_le_bytes()); // radio_freq
1683        payload[51..55].copy_from_slice(&125000u32.to_le_bytes()); // radio_bw
1684        payload[55] = 7; // sf
1685        payload[56] = 5; // cr
1686        payload[57..60].copy_from_slice(b"Dev");
1687        data.extend_from_slice(&payload);
1688
1689        reader.handle_rx(data).await.unwrap();
1690
1691        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1692            .await
1693            .unwrap()
1694            .unwrap();
1695
1696        assert_eq!(event.event_type, EventType::SelfInfo);
1697        match event.payload {
1698            EventPayload::SelfInfo(info) => {
1699                assert_eq!(info.tx_power, 20);
1700                assert_eq!(info.radio_freq, 915000000);
1701            }
1702            _ => panic!("Expected SelfInfo payload"),
1703        }
1704    }
1705
1706    #[tokio::test]
1707    async fn test_handle_rx_contact_msg_recv() {
1708        let (reader, dispatcher) = create_reader();
1709        let mut receiver = dispatcher.receiver();
1710
1711        let mut data = vec![PacketType::ContactMsgRecv as u8];
1712        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]); // sender_prefix
1713        data.push(2); // path_len
1714        data.push(1); // txt_type
1715        data.extend_from_slice(&1234567890u32.to_le_bytes()); // sender_timestamp
1716        data.extend_from_slice(b"Hello!"); // text
1717
1718        reader.handle_rx(data).await.unwrap();
1719
1720        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1721            .await
1722            .unwrap()
1723            .unwrap();
1724
1725        assert_eq!(event.event_type, EventType::ContactMsgRecv);
1726        match event.payload {
1727            EventPayload::ContactMessage(msg) => {
1728                assert_eq!(msg.text, "Hello!");
1729                assert_eq!(msg.path_len, 2);
1730            }
1731            _ => panic!("Expected ContactMessage payload"),
1732        }
1733    }
1734
1735    #[tokio::test]
1736    async fn test_handle_rx_contact_msg_recv_v3() {
1737        let (reader, dispatcher) = create_reader();
1738        let mut receiver = dispatcher.receiver();
1739
1740        let mut data = vec![PacketType::ContactMsgRecvV3 as u8];
1741        data.push(40); // snr_raw = 40 means SNR = 10.0
1742        data.extend_from_slice(&[0x00, 0x00]); // reserved
1743        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]); // sender_prefix
1744        data.push(3); // path_len
1745        data.push(1); // txt_type
1746        data.extend_from_slice(&1234567890u32.to_le_bytes()); // sender_timestamp
1747        data.extend_from_slice(b"V3 msg!"); // text
1748
1749        reader.handle_rx(data).await.unwrap();
1750
1751        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1752            .await
1753            .unwrap()
1754            .unwrap();
1755
1756        assert_eq!(event.event_type, EventType::ContactMsgRecv);
1757        match event.payload {
1758            EventPayload::ContactMessage(msg) => {
1759                assert_eq!(msg.text, "V3 msg!");
1760                assert_eq!(msg.snr, Some(10.0));
1761            }
1762            _ => panic!("Expected ContactMessage payload"),
1763        }
1764    }
1765
1766    #[tokio::test]
1767    async fn test_handle_rx_channel_msg_recv() {
1768        let (reader, dispatcher) = create_reader();
1769        let mut receiver = dispatcher.receiver();
1770
1771        let mut data = vec![PacketType::ChannelMsgRecv as u8];
1772        data.push(5); // channel_idx
1773        data.push(1); // path_len
1774        data.push(0); // txt_type
1775        data.extend_from_slice(&1234567890u32.to_le_bytes()); // sender_timestamp
1776        data.extend_from_slice(b"Channel msg"); // text
1777
1778        reader.handle_rx(data).await.unwrap();
1779
1780        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1781            .await
1782            .unwrap()
1783            .unwrap();
1784
1785        assert_eq!(event.event_type, EventType::ChannelMsgRecv);
1786        match event.payload {
1787            EventPayload::ChannelMessage(msg) => {
1788                assert_eq!(msg.channel_idx, 5);
1789                assert_eq!(msg.text, "Channel msg");
1790            }
1791            _ => panic!("Expected ChannelMessage payload"),
1792        }
1793    }
1794
1795    #[tokio::test]
1796    async fn test_handle_rx_status_response() {
1797        let (reader, dispatcher) = create_reader();
1798        let mut receiver = dispatcher.receiver();
1799
1800        let mut data = vec![PacketType::StatusResponse as u8];
1801        // sender_prefix (6 bytes)
1802        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
1803        // status data (52 bytes)
1804        let mut status_data = vec![0u8; 52];
1805        status_data[0..2].copy_from_slice(&4200u16.to_le_bytes()); // battery_mv (4.2V)
1806        status_data[2..4].copy_from_slice(&5u16.to_le_bytes()); // tx_queue_len
1807        status_data[20..24].copy_from_slice(&86400u32.to_le_bytes()); // uptime
1808        data.extend_from_slice(&status_data);
1809
1810        reader.handle_rx(data).await.unwrap();
1811
1812        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1813            .await
1814            .unwrap()
1815            .unwrap();
1816
1817        assert_eq!(event.event_type, EventType::StatusResponse);
1818        match event.payload {
1819            EventPayload::Status(status) => {
1820                assert_eq!(status.battery_mv, 4200);
1821                assert_eq!(status.uptime, 86400);
1822            }
1823            _ => panic!("Expected Status payload"),
1824        }
1825    }
1826
1827    #[tokio::test]
1828    async fn test_handle_rx_new_contact() {
1829        let (reader, dispatcher) = create_reader();
1830        let mut receiver = dispatcher.receiver();
1831
1832        let mut data = vec![PacketType::PushCodeNewAdvert as u8];
1833        // Create a minimal valid contact buffer (145+ bytes)
1834        let mut contact_data = vec![0u8; 149];
1835        contact_data[0..6].copy_from_slice(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
1836        contact_data[32] = 1; // contact_type
1837        contact_data[99..104].copy_from_slice(b"New\0\0");
1838        data.extend_from_slice(&contact_data);
1839
1840        reader.handle_rx(data).await.unwrap();
1841
1842        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1843            .await
1844            .unwrap()
1845            .unwrap();
1846
1847        assert_eq!(event.event_type, EventType::NewContact);
1848        match event.payload {
1849            EventPayload::Contact(contact) => {
1850                assert_eq!(contact.adv_name, "New");
1851            }
1852            _ => panic!("Expected Contact payload"),
1853        }
1854    }
1855
1856    #[tokio::test]
1857    async fn test_handle_rx_contact_list_flow() {
1858        let (reader, dispatcher) = create_reader();
1859        let mut receiver = dispatcher.receiver();
1860
1861        // Start the contact list
1862        reader
1863            .handle_rx(vec![PacketType::ContactStart as u8])
1864            .await
1865            .unwrap();
1866
1867        // Add a contact
1868        let mut contact_data = vec![PacketType::Contact as u8];
1869        let mut contact = vec![0u8; 149];
1870        contact[0..6].copy_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
1871        contact[32] = 1;
1872        contact[99..105].copy_from_slice(b"Test1\0");
1873        contact_data.extend_from_slice(&contact);
1874        reader.handle_rx(contact_data).await.unwrap();
1875
1876        // End contact list
1877        let mut end_data = vec![PacketType::ContactEnd as u8];
1878        end_data.extend_from_slice(&999u32.to_le_bytes());
1879        reader.handle_rx(end_data).await.unwrap();
1880
1881        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1882            .await
1883            .unwrap()
1884            .unwrap();
1885
1886        assert_eq!(event.event_type, EventType::Contacts);
1887        match event.payload {
1888            EventPayload::Contacts(contacts) => {
1889                assert_eq!(contacts.len(), 1);
1890                assert_eq!(contacts[0].adv_name, "Test1");
1891            }
1892            _ => panic!("Expected Contacts payload"),
1893        }
1894    }
1895
1896    #[tokio::test]
1897    async fn test_handle_rx_binary_response_acl() {
1898        let (reader, dispatcher) = create_reader();
1899        let mut receiver = dispatcher.receiver();
1900
1901        // Register a pending ACL request
1902        reader
1903            .register_binary_request(
1904                &[0x01, 0x02, 0x03, 0x04],
1905                BinaryReqType::Acl,
1906                vec![],
1907                Duration::from_secs(30),
1908                HashMap::new(),
1909                false,
1910            )
1911            .await;
1912
1913        let mut data = vec![PacketType::BinaryResponse as u8];
1914        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]); // matching tag
1915                                                           // ACL entry data (7 bytes per entry)
1916        data.extend_from_slice(&[0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x01]);
1917
1918        reader.handle_rx(data).await.unwrap();
1919
1920        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1921            .await
1922            .unwrap()
1923            .unwrap();
1924
1925        assert_eq!(event.event_type, EventType::AclResponse);
1926        match event.payload {
1927            EventPayload::Acl(entries) => {
1928                assert_eq!(entries.len(), 1);
1929                assert_eq!(entries[0].permissions, 0x01);
1930            }
1931            _ => panic!("Expected Acl payload"),
1932        }
1933    }
1934
1935    #[tokio::test]
1936    async fn test_handle_rx_binary_response_mma() {
1937        let (reader, dispatcher) = create_reader();
1938        let mut receiver = dispatcher.receiver();
1939
1940        // Register a pending MMA request
1941        reader
1942            .register_binary_request(
1943                &[0x01, 0x02, 0x03, 0x04],
1944                BinaryReqType::Mma,
1945                vec![],
1946                Duration::from_secs(30),
1947                HashMap::new(),
1948                false,
1949            )
1950            .await;
1951
1952        let mut data = vec![PacketType::BinaryResponse as u8];
1953        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]); // matching tag
1954                                                           // MMA entry (14 bytes)
1955        data.push(1); // channel
1956        data.push(2); // entry_type
1957        data.extend_from_slice(&100i32.to_le_bytes()); // min
1958        data.extend_from_slice(&200i32.to_le_bytes()); // max
1959        data.extend_from_slice(&150i32.to_le_bytes()); // avg
1960
1961        reader.handle_rx(data).await.unwrap();
1962
1963        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
1964            .await
1965            .unwrap()
1966            .unwrap();
1967
1968        assert_eq!(event.event_type, EventType::MmaResponse);
1969    }
1970
1971    #[tokio::test]
1972    async fn test_handle_rx_binary_response_neighbours() {
1973        let (reader, dispatcher) = create_reader();
1974        let mut receiver = dispatcher.receiver();
1975
1976        // Register a pending Neighbours request
1977        reader
1978            .register_binary_request(
1979                &[0x01, 0x02, 0x03, 0x04],
1980                BinaryReqType::Neighbours,
1981                vec![],
1982                Duration::from_secs(30),
1983                HashMap::new(),
1984                false,
1985            )
1986            .await;
1987
1988        let mut data = vec![PacketType::BinaryResponse as u8];
1989        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]); // matching tag
1990                                                           // Neighbours data
1991        data.extend_from_slice(&1u16.to_le_bytes()); // total
1992        data.extend_from_slice(&1u16.to_le_bytes()); // count
1993                                                     // Entry: pubkey (6) + secs_ago (4) + snr (1)
1994        data.extend_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
1995        data.extend_from_slice(&300i32.to_le_bytes());
1996        data.push(40); // snr
1997
1998        reader.handle_rx(data).await.unwrap();
1999
2000        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
2001            .await
2002            .unwrap()
2003            .unwrap();
2004
2005        assert_eq!(event.event_type, EventType::NeighboursResponse);
2006    }
2007
2008    #[tokio::test]
2009    async fn test_handle_rx_binary_response_status() {
2010        let (reader, dispatcher) = create_reader();
2011        let mut receiver = dispatcher.receiver();
2012
2013        // Register a pending Status request
2014        reader
2015            .register_binary_request(
2016                &[0x01, 0x02, 0x03, 0x04],
2017                BinaryReqType::Status,
2018                vec![],
2019                Duration::from_secs(30),
2020                HashMap::new(),
2021                false,
2022            )
2023            .await;
2024
2025        let mut data = vec![PacketType::BinaryResponse as u8];
2026        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]); // matching tag
2027                                                           // Status data (52 bytes)
2028        let mut status_data = vec![0u8; 52];
2029        status_data[0..2].copy_from_slice(&100u16.to_le_bytes());
2030        data.extend_from_slice(&status_data);
2031
2032        reader.handle_rx(data).await.unwrap();
2033
2034        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
2035            .await
2036            .unwrap()
2037            .unwrap();
2038
2039        assert_eq!(event.event_type, EventType::StatusResponse);
2040    }
2041
2042    #[tokio::test]
2043    async fn test_handle_rx_binary_response_keepalive() {
2044        let (reader, dispatcher) = create_reader();
2045        let mut receiver = dispatcher.receiver();
2046
2047        // Register a pending KeepAlive request
2048        reader
2049            .register_binary_request(
2050                &[0x01, 0x02, 0x03, 0x04],
2051                BinaryReqType::KeepAlive,
2052                vec![],
2053                Duration::from_secs(30),
2054                HashMap::new(),
2055                false,
2056            )
2057            .await;
2058
2059        let mut data = vec![PacketType::BinaryResponse as u8];
2060        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]); // matching tag
2061        data.extend_from_slice(&[0xAA, 0xBB]);
2062
2063        reader.handle_rx(data).await.unwrap();
2064
2065        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
2066            .await
2067            .unwrap()
2068            .unwrap();
2069
2070        assert_eq!(event.event_type, EventType::BinaryResponse);
2071    }
2072
2073    #[tokio::test]
2074    async fn test_handle_rx_control_data_discover_resp() {
2075        let (reader, dispatcher) = create_reader();
2076        let mut receiver = dispatcher.receiver();
2077
2078        let mut data = vec![PacketType::ControlData as u8];
2079        data.push(ControlType::NodeDiscoverResp as u8);
2080        // Entry: 32 bytes pubkey + 32 byte name
2081        let mut entry = vec![0u8; 64];
2082        entry[0..6].copy_from_slice(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
2083        entry[32..37].copy_from_slice(b"Node1");
2084        data.extend_from_slice(&entry);
2085
2086        reader.handle_rx(data).await.unwrap();
2087
2088        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
2089            .await
2090            .unwrap()
2091            .unwrap();
2092
2093        assert_eq!(event.event_type, EventType::DiscoverResponse);
2094        match event.payload {
2095            EventPayload::DiscoverResponse(entries) => {
2096                assert_eq!(entries.len(), 1);
2097                assert_eq!(entries[0].name, "Node1");
2098            }
2099            _ => panic!("Expected DiscoverResponse payload"),
2100        }
2101    }
2102
2103    #[tokio::test]
2104    async fn test_handle_rx_control_data_other() {
2105        let (reader, dispatcher) = create_reader();
2106        let mut receiver = dispatcher.receiver();
2107
2108        let mut data = vec![PacketType::ControlData as u8];
2109        data.push(ControlType::NodeDiscoverReq as u8); // Not a response
2110        data.extend_from_slice(&[0x01, 0x02, 0x03]);
2111
2112        reader.handle_rx(data).await.unwrap();
2113
2114        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
2115            .await
2116            .unwrap()
2117            .unwrap();
2118
2119        assert_eq!(event.event_type, EventType::ControlData);
2120        match event.payload {
2121            EventPayload::Bytes(d) => {
2122                assert_eq!(d[0], ControlType::NodeDiscoverReq as u8);
2123            }
2124            _ => panic!("Expected Bytes payload"),
2125        }
2126    }
2127
2128    #[tokio::test]
2129    async fn test_handle_rx_advert_response() {
2130        let (reader, dispatcher) = create_reader();
2131        let mut receiver = dispatcher.receiver();
2132
2133        let mut data = vec![PacketType::AdvertResponse as u8];
2134        // tag (4) + pubkey (32) + adv_type (1) + node_name (32) + timestamp (4) + flags (1) = 74 bytes min
2135        data.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]); // tag
2136        data.extend_from_slice(&[0xAA; 32]); // pubkey
2137        data.push(1); // adv_type
2138        let mut name = [0u8; 32];
2139        name[..5].copy_from_slice(b"Node1");
2140        data.extend_from_slice(&name); // node_name (32 bytes)
2141        data.extend_from_slice(&1234567890u32.to_le_bytes()); // timestamp
2142        data.push(0x01); // flags
2143                         // lat/lon
2144        data.extend_from_slice(&37774900i32.to_le_bytes());
2145        data.extend_from_slice(&(-122419400i32).to_le_bytes());
2146
2147        reader.handle_rx(data).await.unwrap();
2148
2149        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
2150            .await
2151            .unwrap()
2152            .unwrap();
2153
2154        assert_eq!(event.event_type, EventType::AdvertResponse);
2155        match event.payload {
2156            EventPayload::AdvertResponse(resp) => {
2157                assert_eq!(resp.tag, [0x01, 0x02, 0x03, 0x04]);
2158                assert_eq!(resp.adv_type, 1);
2159                assert_eq!(resp.node_name, "Node1");
2160                assert_eq!(resp.lat, Some(37774900));
2161            }
2162            _ => panic!("Expected AdvertResponse payload"),
2163        }
2164    }
2165
2166    #[tokio::test]
2167    async fn test_handle_rx_contact_end_with_timestamp() {
2168        let (reader, dispatcher) = create_reader();
2169        let mut receiver = dispatcher.receiver();
2170
2171        // Add a pending contact first
2172        reader.pending_contacts.write().await.push(Contact {
2173            public_key: [0u8; 32],
2174            contact_type: 1,
2175            flags: 0,
2176            path_len: 0,
2177            out_path: vec![],
2178            adv_name: "Test".to_string(),
2179            last_advert: 0,
2180            adv_lat: 0,
2181            adv_lon: 0,
2182            last_modification_timestamp: 0,
2183        });
2184
2185        let mut data = vec![PacketType::ContactEnd as u8];
2186        data.extend_from_slice(&1234567890u32.to_le_bytes());
2187
2188        reader.handle_rx(data).await.unwrap();
2189
2190        let event = tokio::time::timeout(Duration::from_millis(100), receiver.recv())
2191            .await
2192            .unwrap()
2193            .unwrap();
2194
2195        assert_eq!(event.event_type, EventType::Contacts);
2196        assert_eq!(
2197            event.attributes.get("lastmod"),
2198            Some(&"1234567890".to_string())
2199        );
2200        match event.payload {
2201            EventPayload::Contacts(contacts) => assert_eq!(contacts.len(), 1),
2202            _ => panic!("Expected Contacts payload"),
2203        }
2204    }
2205}