fix(mesh): add txt_type + timestamp to CMD_SEND_CHANNEL_TXT_MSG frame
MeshCore firmware frame for cmd 0x03 is `[cmd][txt_type][channel][timestamp_le32][text]`, not `[cmd][channel][text]`. Missing txt_type + timestamp caused every channel broadcast to come back with ERR_UNSUPPORTED, which broke the DM-via-channel path entirely (nothing was reaching the radio). Bring the frame into spec — verified against meshcore-dev/MeshCore docs/companion_protocol.md. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
26088462c5
commit
6641c1d183
@ -222,6 +222,10 @@ pub fn build_send_text(dest_pubkey_prefix: &[u8; 6], msg: &[u8]) -> Result<Vec<u
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// CMD_SEND_CHANNEL_TXT_MSG (0x03): Broadcast a text message on a channel.
|
/// CMD_SEND_CHANNEL_TXT_MSG (0x03): Broadcast a text message on a channel.
|
||||||
|
/// Frame layout per meshcore companion protocol:
|
||||||
|
/// `[0x03][txt_type=0][channel][timestamp_le32][text…]`
|
||||||
|
/// The txt_type and timestamp fields are mandatory — without them the
|
||||||
|
/// firmware rejects the command with ERR_UNSUPPORTED.
|
||||||
pub fn build_send_channel_text(channel: u8, msg: &[u8]) -> Result<Vec<u8>> {
|
pub fn build_send_channel_text(channel: u8, msg: &[u8]) -> Result<Vec<u8>> {
|
||||||
if msg.len() > MAX_MESSAGE_LEN {
|
if msg.len() > MAX_MESSAGE_LEN {
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
@ -230,7 +234,12 @@ pub fn build_send_channel_text(channel: u8, msg: &[u8]) -> Result<Vec<u8>> {
|
|||||||
MAX_MESSAGE_LEN
|
MAX_MESSAGE_LEN
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let mut data = vec![CMD_SEND_CHANNEL_TXT_MSG, channel];
|
let timestamp = std::time::SystemTime::now()
|
||||||
|
.duration_since(std::time::UNIX_EPOCH)
|
||||||
|
.map(|d| d.as_secs() as u32)
|
||||||
|
.unwrap_or(0);
|
||||||
|
let mut data = vec![CMD_SEND_CHANNEL_TXT_MSG, 0x00, channel];
|
||||||
|
data.extend_from_slice(×tamp.to_le_bytes());
|
||||||
data.extend_from_slice(msg);
|
data.extend_from_slice(msg);
|
||||||
Ok(encode_frame(&data))
|
Ok(encode_frame(&data))
|
||||||
}
|
}
|
||||||
@ -697,10 +706,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_send_channel_text() -> Result<()> {
|
fn test_build_send_channel_text() -> Result<()> {
|
||||||
let frame = build_send_channel_text(0, b"test")?;
|
let frame = build_send_channel_text(2, b"test")?;
|
||||||
|
// Frame: [marker][len_lo][len_hi][cmd][txt_type][channel][ts(4)][text]
|
||||||
assert_eq!(frame[3], CMD_SEND_CHANNEL_TXT_MSG);
|
assert_eq!(frame[3], CMD_SEND_CHANNEL_TXT_MSG);
|
||||||
assert_eq!(frame[4], 0); // channel 0
|
assert_eq!(frame[4], 0); // txt_type
|
||||||
assert_eq!(&frame[5..], b"test");
|
assert_eq!(frame[5], 2); // channel idx
|
||||||
|
// frame[6..10] = timestamp, non-deterministic
|
||||||
|
assert_eq!(&frame[10..], b"test");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user