* Companion: new CMD_GET_CHANNEL, CMD_SET_CHANNEL

This commit is contained in:
Scott Powell 2025-03-11 14:50:40 +11:00
parent f9b2428dcd
commit 8c68dbb6e9
4 changed files with 92 additions and 25 deletions

View file

@ -161,6 +161,8 @@ static uint32_t _atoi(const char* sp) {
#define CMD_HAS_CONNECTION 28
#define CMD_LOGOUT 29 // 'Disconnect'
#define CMD_GET_CONTACT_BY_KEY 30
#define CMD_GET_CHANNEL 31
#define CMD_SET_CHANNEL 32
#define RESP_CODE_OK 0
#define RESP_CODE_ERR 1
@ -178,6 +180,7 @@ static uint32_t _atoi(const char* sp) {
#define RESP_CODE_DEVICE_INFO 13 // a reply to CMD_DEVICE_QEURY
#define RESP_CODE_PRIVATE_KEY 14 // a reply to CMD_EXPORT_PRIVATE_KEY
#define RESP_CODE_DISABLED 15
#define RESP_CODE_CHANNEL_INFO 16 // a reply to CMD_GET_CHANNEL
// these are _pushed_ to client app at any time
#define PUSH_CODE_ADVERT 0x80
@ -216,7 +219,6 @@ class MyMesh : public BaseChatMesh {
uint32_t expected_ack_crc; // TODO: keep table of expected ACKs
uint32_t pending_login;
uint32_t pending_status;
mesh::GroupChannel* _public;
BaseSerialInterface* _serial;
unsigned long last_msg_sent;
ContactsIterator _iter;
@ -536,7 +538,7 @@ protected:
void onChannelMessageRecv(const mesh::GroupChannel& channel, int in_path_len, uint32_t timestamp, const char *text) override {
int i = 0;
out_frame[i++] = RESP_CODE_CHANNEL_MSG_RECV;
out_frame[i++] = 0; // FUTURE: channel_idx (will just be 'public' for now)
out_frame[i++] = findChannelIdx(channel);
out_frame[i++] = in_path_len < 0 ? 0xFF : in_path_len;
out_frame[i++] = TXT_TYPE_PLAIN;
memcpy(&out_frame[i], &timestamp, 4); i += 4;
@ -713,7 +715,7 @@ public:
_fs->mkdir("/bl");
loadContacts();
_public = addChannel(PUBLIC_GROUP_PSK); // pre-configure Andy's public channel
addChannel(PUBLIC_GROUP_PSK); // pre-configure Andy's public channel
_phy->setFrequency(_prefs.freq);
_phy->setSpreadingFactor(_prefs.sf);
@ -844,12 +846,14 @@ public:
} else if (cmd_frame[0] == CMD_SEND_CHANNEL_TXT_MSG) { // send GroupChannel msg
int i = 1;
uint8_t txt_type = cmd_frame[i++]; // should be TXT_TYPE_PLAIN
uint8_t channel_idx = cmd_frame[i++]; // reserved future
uint8_t channel_idx = cmd_frame[i++];
uint32_t msg_timestamp;
memcpy(&msg_timestamp, &cmd_frame[i], 4); i += 4;
const char *text = (char *) &cmd_frame[i];
if (txt_type == TXT_TYPE_PLAIN && sendGroupMessage(msg_timestamp, *_public, _prefs.node_name, text, len - i)) { // hard-coded to 'public' channel for now
mesh::GroupChannel channel;
bool success = getChannel(channel_idx, channel);
if (success && txt_type == TXT_TYPE_PLAIN && sendGroupMessage(msg_timestamp, channel, _prefs.node_name, text, len - i)) {
writeOKFrame();
} else {
writeErrFrame();
@ -1161,6 +1165,29 @@ public:
uint8_t* pub_key = &cmd_frame[1];
stopConnection(pub_key);
writeOKFrame();
} else if (cmd_frame[0] == CMD_GET_CHANNEL && len >= 2) {
uint8_t channel_idx = cmd_frame[1];
mesh::GroupChannel channel;
if (getChannel(channel_idx, channel)) {
out_frame[0] = RESP_CODE_CHANNEL_INFO;
out_frame[1] = channel_idx;
memcpy(&out_frame[2], channel.secret, 16); // NOTE: only 128-bit supported
_serial->writeFrame(out_frame, 2 + 16);
} else {
writeErrFrame();
}
} else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 3+32) {
writeErrFrame(); // not supported (yet)
} else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 3+16) {
uint8_t channel_idx = cmd_frame[1];
mesh::GroupChannel channel;
memset(channel.secret, 0, sizeof(channel.secret));
memcpy(channel.secret, &cmd_frame[2], 16); // NOTE: only 128-bit supported
if (setChannel(channel_idx, channel)) {
writeOKFrame();
} else {
writeErrFrame();
}
} else {
writeErrFrame();
MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]);

View file

@ -78,7 +78,7 @@ extends = Heltec_lora32_v2
build_flags =
${Heltec_lora32_v2.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v2.build_src_filter}
@ -93,7 +93,7 @@ extends = Heltec_lora32_v2
build_flags =
${Heltec_lora32_v2.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
; -D ENABLE_PRIVATE_KEY_IMPORT=1
@ -180,7 +180,7 @@ extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
-D DISPLAY_CLASS=SSD1306Display
; -D ENABLE_PRIVATE_KEY_IMPORT=1
; -D ENABLE_PRIVATE_KEY_EXPORT=1
@ -198,7 +198,7 @@ extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
-D DISPLAY_CLASS=SSD1306Display
-D BLE_PIN_CODE=0 ; dynamic, random PIN
-D BLE_DEBUG_LOGGING=1
@ -219,7 +219,7 @@ extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
-D DISPLAY_CLASS=SSD1306Display
-D WIFI_DEBUG_LOGGING=1
-D WIFI_SSID='"myssid"'
@ -268,7 +268,7 @@ extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
; -D ENABLE_PRIVATE_KEY_IMPORT=1
@ -375,7 +375,7 @@ extends = Xiao_S3_WIO
build_flags =
${Xiao_S3_WIO.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Xiao_S3_WIO.build_src_filter}
@ -389,7 +389,7 @@ extends = Xiao_S3_WIO
build_flags =
${Xiao_S3_WIO.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
; -D ENABLE_PRIVATE_KEY_IMPORT=1
@ -454,7 +454,7 @@ extends = LilyGo_TLora_V2_1_1_6
build_flags =
${LilyGo_TLora_V2_1_1_6.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter}
@ -469,7 +469,7 @@ extends = LilyGo_TLora_V2_1_1_6
build_flags =
${LilyGo_TLora_V2_1_1_6.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
; -D ENABLE_PRIVATE_KEY_IMPORT=1
; -D ENABLE_PRIVATE_KEY_EXPORT=1
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
@ -486,7 +486,7 @@ extends = LilyGo_TLora_V2_1_1_6
build_flags =
${LilyGo_TLora_V2_1_1_6.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
; -D ENABLE_PRIVATE_KEY_IMPORT=1
@ -572,7 +572,7 @@ extends = LilyGo_T3S3_sx1262
build_flags =
${LilyGo_T3S3_sx1262.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
; -D ENABLE_PRIVATE_KEY_IMPORT=1
; -D ENABLE_PRIVATE_KEY_EXPORT=1
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
@ -588,7 +588,7 @@ extends = LilyGo_T3S3_sx1262
build_flags =
${LilyGo_T3S3_sx1262.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
; -D ENABLE_PRIVATE_KEY_IMPORT=1
@ -728,7 +728,7 @@ extends = rak4631
build_flags =
${rak4631.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
; -D ENABLE_PRIVATE_KEY_IMPORT=1
; -D ENABLE_PRIVATE_KEY_EXPORT=1
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
@ -744,7 +744,7 @@ extends = rak4631
build_flags =
${rak4631.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
; -D ENABLE_PRIVATE_KEY_IMPORT=1
@ -796,7 +796,7 @@ upload_protocol = nrfutil
extends = t1000-e
build_flags = ${t1000-e.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
-D MESH_PACKET_LOGGING=1
@ -870,7 +870,7 @@ extends = Heltec_t114
build_flags =
${Heltec_t114.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
; -D ENABLE_PRIVATE_KEY_IMPORT=1
@ -943,7 +943,7 @@ extends = LilyGo_Techo
build_flags =
${LilyGo_Techo.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
; -D ENABLE_PRIVATE_KEY_IMPORT=1

View file

@ -203,7 +203,7 @@ void BaseChatMesh::onAckRecv(mesh::Packet* packet, uint32_t ack_crc) {
#ifdef MAX_GROUP_CHANNELS
int BaseChatMesh::searchChannelsByHash(const uint8_t* hash, mesh::GroupChannel dest[], int max_matches) {
int n = 0;
for (int i = 0; i < num_channels && n < max_matches; i++) {
for (int i = 0; i < MAX_GROUP_CHANNELS && n < max_matches; i++) {
if (channels[i].hash[0] == hash[0]) {
dest[n++] = channels[i];
}
@ -602,10 +602,46 @@ mesh::GroupChannel* BaseChatMesh::addChannel(const char* psk_base64) {
}
return NULL;
}
bool BaseChatMesh::getChannel(int idx, mesh::GroupChannel& dest) {
if (idx >= 0 && idx < MAX_GROUP_CHANNELS) {
dest = channels[idx];
return true;
}
return false;
}
bool BaseChatMesh::setChannel(int idx, const mesh::GroupChannel& src) {
static uint8_t zeroes[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
if (idx >= 0 && idx < MAX_GROUP_CHANNELS) {
channels[idx] = src;
if (memcmp(&src.secret[16], zeroes, 16) == 0) {
mesh::Utils::sha256(channels[idx].hash, sizeof(channels[idx].hash), src.secret, 16); // 128-bit key
} else {
mesh::Utils::sha256(channels[idx].hash, sizeof(channels[idx].hash), src.secret, 32); // 256-bit key
}
return true;
}
return false;
}
int BaseChatMesh::findChannelIdx(const mesh::GroupChannel& ch) {
for (int i = 0; i < MAX_GROUP_CHANNELS; i++) {
if (memcmp(ch.secret, channels[i].secret, sizeof(ch.secret)) == 0) return i;
}
return -1; // not found
}
#else
mesh::GroupChannel* BaseChatMesh::addChannel(const char* psk_base64) {
return NULL; // not supported
}
bool BaseChatMesh::getChannel(int idx, mesh::GroupChannel& dest) {
return false;
}
bool BaseChatMesh::setChannel(int idx, const mesh::GroupChannel& src) {
return false;
}
int BaseChatMesh::findChannelIdx(const mesh::GroupChannel& ch) {
return -1; // not found
}
#endif
ContactsIterator BaseChatMesh::startContactsIterator() {

View file

@ -75,7 +75,7 @@ class BaseChatMesh : public mesh::Mesh {
unsigned long txt_send_timeout;
#ifdef MAX_GROUP_CHANNELS
mesh::GroupChannel channels[MAX_GROUP_CHANNELS];
int num_channels;
int num_channels; // only for addChannel()
#endif
mesh::Packet* _pendingLoopback;
uint8_t temp_buf[MAX_TRANS_UNIT];
@ -89,6 +89,7 @@ protected:
{
num_contacts = 0;
#ifdef MAX_GROUP_CHANNELS
memset(channels, 0, sizeof(channels));
num_channels = 0;
#endif
txt_send_timeout = 0;
@ -152,6 +153,9 @@ public:
int getNumContacts() const { return num_contacts; }
ContactsIterator startContactsIterator();
mesh::GroupChannel* addChannel(const char* psk_base64);
bool getChannel(int idx, mesh::GroupChannel& dest);
bool setChannel(int idx, const mesh::GroupChannel& src);
int findChannelIdx(const mesh::GroupChannel& ch);
void loop();
};