diff --git a/lib/comms/comms.cpp b/lib/comms/comms.cpp index b68bcde..48dfae6 100644 --- a/lib/comms/comms.cpp +++ b/lib/comms/comms.cpp @@ -262,6 +262,7 @@ bool ReadlineComms::send(Message &m) Serial.println(name + ": the message is: " + p); break; case MessageType::SCAN_RESULT: + case MessageType::SCAN_MAX_RESULT: p = _scan_result_str(m.payload.dump); break; case MessageType::CONFIG_TASK: @@ -420,7 +421,7 @@ String _wrap_str(String v) Message::~Message() { - if (type == SCAN_RESULT) + if (type == SCAN_RESULT || type == SCAN_MAX_RESULT) { if (payload.dump.sz > 0) { diff --git a/lib/comms/comms.h b/lib/comms/comms.h index ff11325..3573ebd 100644 --- a/lib/comms/comms.h +++ b/lib/comms/comms.h @@ -13,11 +13,18 @@ #define SERIAL0 Serial0 #endif +#ifndef SCAN_MAX_RESULT_KHZ_SCALE +// kHz scale: round frequency, so it fits into 2 bytes +// 2500000 / 40 = 62500, scale 40 fits 2.5GHz into two bytes +#define SCAN_MAX_RESULT_KHZ_SCALE 40 +#endif + enum MessageType { WRAP = 0, SCAN, SCAN_RESULT, + SCAN_MAX_RESULT, CONFIG_TASK, _MAX_MESSAGE_TYPE = CONFIG_TASK }; diff --git a/lib/comms/radio_comms.cpp b/lib/comms/radio_comms.cpp index 0cce77b..49b5296 100644 --- a/lib/comms/radio_comms.cpp +++ b/lib/comms/radio_comms.cpp @@ -62,9 +62,9 @@ uint8_t *_serialize_scan_result(Message &m, size_t &p, uint8_t *msg) // first cut: dump the RSSI as-is // optimize the message size later + p = _write(msg, max_msg, p, (uint8_t *)&dump_sz, 2); p = _write(msg, max_msg, p, (uint8_t *)&m.payload.dump.freqs_khz[0], 4); p = _write(msg, max_msg, p, (uint8_t *)&m.payload.dump.freqs_khz[dump_sz - 1], 4); - p = _write(msg, max_msg, p, (uint8_t *)&dump_sz, 2); size_t rem = max_msg - p; if (rem > dump_sz) @@ -104,6 +104,44 @@ uint8_t *_serialize_scan_result(Message &m, size_t &p, uint8_t *msg) return msg; } +uint8_t *_serialize_scan_max_result(Message &m, size_t &p, uint8_t *msg) +{ + if (m.type != SCAN_MAX_RESULT) + { + return NULL; + } + + size_t dump_sz = m.payload.dump.sz; + size_t max_msg = p; + p = _write(msg, max_msg, 0, (uint8_t)m.type); + p = _write(msg, max_msg, p, (uint8_t *)&dump_sz, 2); + + int16_t b = SCAN_MAX_RESULT_KHZ_SCALE; // scale to fit khz into 2 bytes + p = _write(msg, max_msg, p, (uint8_t)b); + + for (int i = 0; i < dump_sz; i++) + { + b = m.payload.dump.freqs_khz[i] / SCAN_MAX_RESULT_KHZ_SCALE; + p = _write(msg, max_msg, p, (uint8_t *)&b, 2); + b = m.payload.dump.rssis[i]; + if (b >= 0) + { + b = 255; + } + else + { + b += 255; + if (b < 0) + { + b = 0; + } + } + p = _write(msg, max_msg, p, (uint8_t)b); + } + + return msg; +} + uint8_t *_serialize_config_task(Message &m, size_t &p, uint8_t *msg) { if (m.type != CONFIG_TASK) @@ -152,6 +190,10 @@ int16_t RadioComms::send(Message &m) { msg = _serialize_scan_result(m, p, msg_buf); } + else if (m.type == MessageType::SCAN_MAX_RESULT) + { + msg = _serialize_scan_max_result(m, p, msg_buf); + } else if (m.type == MessageType::CONFIG_TASK) { msg = _serialize_config_task(m, p, msg_buf); @@ -195,9 +237,9 @@ Message *_deserialize_scan_result(size_t len, size_t &p, uint8_t *packet) uint32_t s, e; size_t dump_sz = 0; + p = _read(packet, len, p, (uint8_t *)&dump_sz, 2); p = _read(packet, len, p, (uint8_t *)&s, 4); p = _read(packet, len, p, (uint8_t *)&e, 4); - p = _read(packet, len, p, (uint8_t *)&dump_sz, 2); size_t rem = len - p; message->payload.dump.sz = dump_sz; @@ -231,6 +273,36 @@ Message *_deserialize_scan_result(size_t len, size_t &p, uint8_t *packet) return message; } +Message *_deserialize_scan_max_result(size_t len, size_t &p, uint8_t *packet) +{ + Message *message = new Message(); + message->type = SCAN_MAX_RESULT; + + uint32_t b = 0; + size_t dump_sz = 0; + p = _read(packet, len, p, (uint8_t *)&dump_sz, 2); + uint32_t *freqs = new uint32_t[dump_sz]; + int16_t *rssis = new int16_t[dump_sz]; + message->payload.dump.sz = dump_sz; + message->payload.dump.freqs_khz = freqs; + message->payload.dump.rssis = rssis; + + uint32_t scale = 0; + p = _read(packet, len, p, (uint8_t *)&scale); + + for (int i = 0; i < dump_sz; i++) + { + p = _read(packet, len, p, (uint8_t *)&b, 2); + freqs[i] = scale * b; + + b = 0; + p = _read(packet, len, p, (uint8_t *)&b); + rssis[i] = ((int16_t)b) - 255; + } + + return message; +} + Message *_deserialize_config_task(size_t len, size_t &p, uint8_t *packet) { Message *message = new Message(); @@ -346,6 +418,10 @@ Message *RadioComms::receive(uint16_t timeout_ms) { message = _deserialize_scan_result(len, p, packet); } + else if (b == SCAN_MAX_RESULT) + { + message = _deserialize_scan_max_result(len, p, packet); + } else if (b == CONFIG_TASK) { message = _deserialize_config_task(len, p, packet); diff --git a/lib/config/config.h b/lib/config/config.h index 8c9fc59..7eaaca0 100644 --- a/lib/config/config.h +++ b/lib/config/config.h @@ -20,6 +20,22 @@ struct ScanRange uint64_t step_khz; }; +struct ScanPage +{ + uint64_t start_mhz; + uint64_t end_mhz; + size_t page_sz; + ScanRange *scan_ranges; + + ~ScanPage() + { + if (page_sz > 0) + { + delete[] scan_ranges; + } + } +}; + struct LoRaConfig { float freq; diff --git a/lib/scan/scan.h b/lib/scan/scan.h index 6b8c28c..5bf8800 100644 --- a/lib/scan/scan.h +++ b/lib/scan/scan.h @@ -34,22 +34,6 @@ constexpr float LO_RSSI_THRESHOLD = HI_RSSI_THRESHOLD - 66; #define SAMPLES_RSSI 20 #endif -struct ScanPage -{ - uint64_t start_mhz; - uint64_t end_mhz; - size_t page_sz; - ScanRange *scan_ranges; - - ~ScanPage() - { - if (page_sz > 0) - { - delete[] scan_ranges; - } - } -}; - struct Scan { uint64_t epoch; diff --git a/src/main.cpp b/src/main.cpp index f8d3225..d0d6de0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -909,7 +909,7 @@ void configureDetection() CONF_FREQ_BEGIN = config.scan_ranges[0].start_khz / 1000; CONF_FREQ_END = config.scan_ranges[0].end_khz / 1000; - for (int i = 0; i < config.scan_ranges_sz; i++) + for (int i = 1; i < config.scan_ranges_sz; i++) { CONF_FREQ_BEGIN = min(CONF_FREQ_BEGIN, config.scan_ranges[i].start_khz / 1000); CONF_FREQ_END = max(CONF_FREQ_END, config.scan_ranges[i].end_khz / 1000); @@ -1419,6 +1419,7 @@ void routeMessage(RoutedMessage &m) } if (m.message->type == MessageType::SCAN_RESULT || + m.message->type == MessageType::SCAN_MAX_RESULT || m.message->type == MessageType::CONFIG_TASK && (m.message->payload.config.task_type == ConfigTaskType::GETSET_SUCCESS || m.message->payload.config.task_type == ConfigTaskType::SET_FAIL)) @@ -1477,6 +1478,12 @@ void sendMessage(RoutedMessage &m) success = config.updateConfig(*msg->payload.config.key, *msg->payload.config.value); delete msg->payload.config.value; + + if (success && + msg->payload.config.key->equalsIgnoreCase("detection_strategy")) + { + configureDetection(); // redo the pages and scan ranges + } } if (success) @@ -1771,7 +1778,8 @@ void doScan() float (*g)(void *); samples = CONF_SAMPLES; - if (config.detection_strategy.equalsIgnoreCase("RSSI")) + if (config.detection_strategy.equalsIgnoreCase("RSSI") || + config.detection_strategy.equalsIgnoreCase("RSSI_MAX")) g = &getRSSI; else if (config.detection_strategy.equalsIgnoreCase("CAD")) { @@ -2117,8 +2125,52 @@ void reportScan() Message m; m.type = SCAN_RESULT; - m.payload.dump = frequency_scan_result.dump; - loraSendMessage(m); + m.payload.dump.sz = 0; - m.payload.dump.sz = 0; // dump is shared, so should not delete underlying arrays + if (config.detection_strategy.equalsIgnoreCase("RSSI")) + { + size_t sz = frequency_scan_result.dump.sz; + m.payload.dump.sz = sz; + m.payload.dump.freqs_khz = new uint32_t[sz]; + m.payload.dump.rssis = new int16_t[sz]; + + memcpy(m.payload.dump.freqs_khz, frequency_scan_result.dump.freqs_khz, + sizeof(uint32_t) * sz); + memcpy(m.payload.dump.rssis, frequency_scan_result.dump.rssis, + sizeof(int16_t) * sz); + } + else if (config.detection_strategy.equalsIgnoreCase("RSSI_MAX")) + { + m.type = SCAN_MAX_RESULT; + + size_t sz = config.scan_ranges_sz; + m.payload.dump.sz = sz; + m.payload.dump.freqs_khz = new uint32_t[sz]; + m.payload.dump.rssis = new int16_t[sz]; + + for (int i = 0; i < sz; i++) + { + int16_t rssi = -999; + for (int j = 0; j < frequency_scan_result.dump.sz; j++) + { + uint32_t f = frequency_scan_result.dump.freqs_khz[j]; + + if (config.scan_ranges[i].start_khz > f || + config.scan_ranges[i].end_khz < f) + continue; + + rssi = max(rssi, frequency_scan_result.dump.rssis[j]); + } + + m.payload.dump.freqs_khz[i] = + (config.scan_ranges[i].start_khz + config.scan_ranges[i].end_khz) / 2; + m.payload.dump.rssis[i] = rssi; + } + } + else + { + return; + } + + loraSendMessage(m); }