diff --git a/README.md b/README.md index 5bae2f345..d450b88d3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Meshtastic Firmware ![GitHub release downloads](https://img.shields.io/github/downloads/meshtastic/firmware/total) -[![CI](https://img.shields.io/github/workflow/status/meshtastic/firmware/CI?label=actions&logo=github&color=yellow)](https://github.com/meshtastic/firmware/actions/workflows/main_matrix.yml) +[![CI](https://img.shields.io/github/actions/workflow/status/meshtastic/firmware/main_matrix.yml?branch=master&label=actions&logo=github&color=yellow)](https://github.com/meshtastic/firmware/actions/workflows/ci.yml) [![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/firmware)](https://cla-assistant.io/meshtastic/firmware) [![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg?label=Fiscal%20Contributors&color=deeppink)](https://opencollective.com/meshtastic/) [![Vercel](https://img.shields.io/static/v1?label=Powered%20by&message=Vercel&style=flat&logo=vercel&color=000000)](https://vercel.com?utm_source=meshtastic&utm_campaign=oss) diff --git a/protobufs b/protobufs index e406029f6..3b0d871ca 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit e406029f68d8a554f43fd1f250baca6b3c1a9a33 +Subproject commit 3b0d871ca1e0f8a2ed823f0696e2d7cf31ed2ebd diff --git a/src/SerialConsole.cpp b/src/SerialConsole.cpp index 0b6b9ee24..b66eae455 100644 --- a/src/SerialConsole.cpp +++ b/src/SerialConsole.cpp @@ -20,9 +20,7 @@ void consolePrintf(const char *format, ...) va_start(arg, format); console->vprintf(format, arg); va_end(arg); -#ifdef ARCH_ESP32 console->flush(); -#endif } SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), concurrency::OSThread("SerialConsole") @@ -51,6 +49,10 @@ int32_t SerialConsole::runOnce() return runOncePart(); } +void SerialConsole::flush() { + Port.flush(); +} + // For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages bool SerialConsole::checkIsConnected() { diff --git a/src/SerialConsole.h b/src/SerialConsole.h index d1f2abac8..f5e2077ba 100644 --- a/src/SerialConsole.h +++ b/src/SerialConsole.h @@ -26,6 +26,8 @@ class SerialConsole : public StreamAPI, public RedirectablePrint, private concur virtual int32_t runOnce() override; + void flush(); + protected: /// Check the current underlying physical link to see if the client is currently connected diff --git a/src/mesh/MeshPacketQueue.h b/src/mesh/MeshPacketQueue.h index 8c93b452e..ee6c6954a 100644 --- a/src/mesh/MeshPacketQueue.h +++ b/src/mesh/MeshPacketQueue.h @@ -26,6 +26,12 @@ class MeshPacketQueue /** return true if the queue is empty */ bool empty(); + /** return amount of free packets in Queue */ + size_t getFree() { return maxLen - queue.size(); } + + /** return total size of the Queue */ + size_t getMaxLen() { return maxLen; } + MeshPacket *dequeue(); MeshPacket *getFront(); diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index c300104a4..208b1b9ea 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -52,10 +52,15 @@ FIXME in the initial proof of concept we just skip the entire want/deny flow and MeshService service; +static MemoryDynamic staticQueueStatusPool; + +Allocator &queueStatusPool = staticQueueStatusPool; + #include "Router.h" -MeshService::MeshService() : toPhoneQueue(MAX_RX_TOPHONE) +MeshService::MeshService() : toPhoneQueue(MAX_RX_TOPHONE), toPhoneQueueStatusQueue(MAX_RX_TOPHONE) { + lastQueueStatus = { 0, 0, 16, 0 }; // assert(MAX_RX_TOPHONE == 32); // FIXME, delete this, just checking my clever macro } @@ -83,6 +88,11 @@ int MeshService::handleFromRadio(const MeshPacket *mp) /// Do idle processing (mostly processing messages which have been queued from the radio) void MeshService::loop() { + if (lastQueueStatus.free == 0) { // check if there is now free space in TX queue + QueueStatus qs = router->getQueueStatus(); + if (qs.free != lastQueueStatus.free) + (void)sendQueueStatusToPhone(qs, 0, 0); + } if (oldFromNum != fromNum) { // We don't want to generate extra notifies for multiple new packets fromNumChanged.notifyObservers(fromNum); oldFromNum = fromNum; @@ -179,12 +189,43 @@ bool MeshService::cancelSending(PacketId id) return router->cancelSending(nodeDB.getNodeNum(), id); } +ErrorCode MeshService::sendQueueStatusToPhone(const QueueStatus &qs, ErrorCode res, uint32_t mesh_packet_id) +{ + QueueStatus *copied = queueStatusPool.allocCopy(qs); + + copied->res = res; + copied->mesh_packet_id = mesh_packet_id; + + if (toPhoneQueueStatusQueue.numFree() == 0) { + LOG_DEBUG("NOTE: tophone queue status queue is full, discarding oldest\n"); + QueueStatus *d = toPhoneQueueStatusQueue.dequeuePtr(0); + if (d) + releaseQueueStatusToPool(d); + } + + lastQueueStatus = *copied; + + res = toPhoneQueueStatusQueue.enqueue(copied, 0); + fromNum++; + + return res ? ERRNO_OK : ERRNO_UNKNOWN; +} + void MeshService::sendToMesh(MeshPacket *p, RxSource src, bool ccToPhone) { + uint32_t mesh_packet_id = p->id; nodeDB.updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...) // Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it - router->sendLocal(p, src); + ErrorCode res = router->sendLocal(p, src); + + /* NOTE(pboldin): Prepare and send QueueStatus message to the phone as a + * high-priority message. */ + QueueStatus qs = router->getQueueStatus(); + ErrorCode r = sendQueueStatusToPhone(qs, res, mesh_packet_id); + if (r != ERRNO_OK) { + LOG_DEBUG("Can't send status to phone"); + } if (ccToPhone) { sendToPhone(p); diff --git a/src/mesh/MeshService.h b/src/mesh/MeshService.h index c3b3c95d9..31b63bd3f 100644 --- a/src/mesh/MeshService.h +++ b/src/mesh/MeshService.h @@ -14,6 +14,8 @@ #include "../platform/portduino/SimRadio.h" #endif +extern Allocator &queueStatusPool; + /** * Top level app for this service. keeps the mesh, the radio config and the queue of received packets. * @@ -29,6 +31,12 @@ class MeshService /// FIXME - save this to flash on deep sleep PointerQueue toPhoneQueue; + // keep list of QueueStatus packets to be send to the phone + PointerQueue toPhoneQueueStatusQueue; + + // This holds the last QueueStatus send + QueueStatus lastQueueStatus; + /// The current nonce for the newest packet which has been queued for the phone uint32_t fromNum = 0; @@ -56,6 +64,12 @@ class MeshService /// Allows the bluetooth handler to free packets after they have been sent void releaseToPool(MeshPacket *p) { packetPool.release(p); } + /// Return the next QueueStatus packet destined to the phone. + QueueStatus *getQueueStatusForPhone() { return toPhoneQueueStatusQueue.dequeuePtr(0); } + + // Release QueueStatus packet to pool + void releaseQueueStatusToPool(QueueStatus *p) { queueStatusPool.release(p); } + /** * Given a ToRadio buffer parse it and properly handle it (setup radio, owner or send packet into the mesh) * Called by PhoneAPI.handleToRadio. Note: p is a scratch buffer, this function is allowed to write to it but it can not keep @@ -100,6 +114,8 @@ class MeshService /// needs to keep the packet around it makes a copy int handleFromRadio(const MeshPacket *p); friend class RoutingModule; + + ErrorCode sendQueueStatusToPhone(const QueueStatus &qs, ErrorCode res, uint32_t mesh_packet_id); }; extern MeshService service; diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 897ddfe8a..c1d56b7ec 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -50,6 +50,7 @@ void PhoneAPI::close() unobserve(&service.fromNumChanged); releasePhonePacket(); // Don't leak phone packets on shutdown + releaseQueueStatusPhonePacket(); onConnectionChanged(false); } @@ -282,14 +283,19 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) case STATE_SEND_PACKETS: // Do we have a message from the mesh? LOG_INFO("getFromRadio=STATE_SEND_PACKETS\n"); - if (packetForPhone) { + if (queueStatusPacketForPhone) { + + fromRadioScratch.which_payload_variant = FromRadio_queueStatus_tag; + fromRadioScratch.queueStatus = *queueStatusPacketForPhone; + releaseQueueStatusPhonePacket(); + } else if (packetForPhone) { printPacket("phone downloaded packet", packetForPhone); // Encapsulate as a FromRadio packet fromRadioScratch.which_payload_variant = FromRadio_packet_tag; fromRadioScratch.packet = *packetForPhone; + releasePhonePacket(); } - releasePhonePacket(); break; default: @@ -322,6 +328,14 @@ void PhoneAPI::releasePhonePacket() } } +void PhoneAPI::releaseQueueStatusPhonePacket() +{ + if (queueStatusPacketForPhone) { + service.releaseQueueStatusToPool(queueStatusPacketForPhone); + queueStatusPacketForPhone = NULL; + } +} + /** * Return true if we have data available to send to the phone */ @@ -342,9 +356,15 @@ bool PhoneAPI::available() return true; // Always say we have something, because we might need to advance our state machine case STATE_SEND_PACKETS: { + if (!queueStatusPacketForPhone) + queueStatusPacketForPhone = service.getQueueStatusForPhone(); + bool hasPacket = !!queueStatusPacketForPhone; + if (hasPacket) + return true; + if (!packetForPhone) packetForPhone = service.getForPhone(); - bool hasPacket = !!packetForPhone; + hasPacket = !!packetForPhone; // LOG_DEBUG("available hasPacket=%d\n", hasPacket); return hasPacket; } diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h index cbac5f688..2f2695807 100644 --- a/src/mesh/PhoneAPI.h +++ b/src/mesh/PhoneAPI.h @@ -42,6 +42,9 @@ class PhoneAPI : public Observer // FIXME, we shouldn't be inheriting /// downloads it MeshPacket *packetForPhone = NULL; + // Keep QueueStatus packet just as packetForPhone + QueueStatus *queueStatusPacketForPhone = NULL; + /// We temporarily keep the nodeInfo here between the call to available and getFromRadio const NodeInfo *nodeInfoForPhone = NULL; @@ -115,6 +118,8 @@ class PhoneAPI : public Observer // FIXME, we shouldn't be inheriting private: void releasePhonePacket(); + void releaseQueueStatusPhonePacket(); + /// begin a new connection void handleStartConfig(); diff --git a/src/mesh/RadioInterface.h b/src/mesh/RadioInterface.h index f50c0ae77..59c63add2 100644 --- a/src/mesh/RadioInterface.h +++ b/src/mesh/RadioInterface.h @@ -115,6 +115,13 @@ class RadioInterface */ virtual ErrorCode send(MeshPacket *p) = 0; + /** Return TX queue status */ + virtual QueueStatus getQueueStatus() { + QueueStatus qs; + qs.res = qs.mesh_packet_id = qs.free = qs.maxlen = 0; + return qs; + } + /** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */ virtual bool cancelSending(NodeNum from, PacketId id) { return false; } diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 53eaeca60..81a4d803e 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -158,6 +158,17 @@ ErrorCode RadioLibInterface::send(MeshPacket *p) #endif } +QueueStatus RadioLibInterface::getQueueStatus() +{ + QueueStatus qs; + + qs.res = qs.mesh_packet_id = 0; + qs.free = txQueue.getFree(); + qs.maxlen = txQueue.getMaxLen(); + + return qs; +} + bool RadioLibInterface::canSleep() { bool res = txQueue.empty(); diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index 16495c2f4..628ea863f 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -153,6 +153,8 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified */ virtual void startSend(MeshPacket *txp); + QueueStatus getQueueStatus(); + protected: /** Do any hardware setup needed on entry into send configuration for the radio. Subclasses can customize */ diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 0a8497463..0f34010ec 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -148,6 +148,11 @@ void Router::setReceivedMessage() runASAP = true; } +QueueStatus Router::getQueueStatus() +{ + return iface->getQueueStatus(); +} + ErrorCode Router::sendLocal(MeshPacket *p, RxSource src) { // No need to deliver externally if the destination is the local node diff --git a/src/mesh/Router.h b/src/mesh/Router.h index f7748bb2b..5a9cc0702 100644 --- a/src/mesh/Router.h +++ b/src/mesh/Router.h @@ -55,6 +55,9 @@ class Router : protected concurrency::OSThread */ MeshPacket *allocForSending(); + /** Return Underlying interface's TX queue status */ + QueueStatus getQueueStatus(); + /** * @return our local nodenum */ NodeNum getNodeNum(); diff --git a/src/mesh/compression/unishox2.c b/src/mesh/compression/unishox2.c index e1f32ae05..2d6c60d75 100644 --- a/src/mesh/compression/unishox2.c +++ b/src/mesh/compression/unishox2.c @@ -33,14 +33,14 @@ #include "unishox2.h" -/// byte is unsigned char -typedef unsigned char byte; +/// uint8_t is unsigned char +typedef unsigned char uint8_t; /// possible horizontal sets and states enum {USX_ALPHA = 0, USX_SYM, USX_NUM, USX_DICT, USX_DELTA, USX_NUM_TEMP}; -/// This 2D array has the characters for the sets USX_ALPHA, USX_SYM and USX_NUM. Where a character cannot fit into a byte, 0 is used and handled in code. -byte usx_sets[][28] = {{ 0, ' ', 'e', 't', 'a', 'o', 'i', 'n', +/// This 2D array has the characters for the sets USX_ALPHA, USX_SYM and USX_NUM. Where a character cannot fit into a uint8_t, 0 is used and handled in code. +uint8_t usx_sets[][28] = {{ 0, ' ', 'e', 't', 'a', 'o', 'i', 'n', 's', 'r', 'l', 'c', 'd', 'h', 'u', 'p', 'm', 'b', 'g', 'w', 'f', 'y', 'v', 'k', 'q', 'j', 'x', 'z'}, {'"', '{', '}', '_', '<', '>', ':', '\n', @@ -53,22 +53,22 @@ byte usx_sets[][28] = {{ 0, ' ', 'e', 't', 'a', 'o', 'i', 'n', /// Stores position of letter in usx_sets. /// First 3 bits - position in usx_hcodes /// Next 5 bits - position in usx_vcodes -byte usx_code_94[94]; +uint8_t usx_code_94[94]; /// Vertical codes starting from the MSB -byte usx_vcodes[] = { 0x00, 0x40, 0x60, 0x80, 0x90, 0xA0, 0xB0, +uint8_t usx_vcodes[] = { 0x00, 0x40, 0x60, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xD8, 0xE0, 0xE4, 0xE8, 0xEC, 0xEE, 0xF0, 0xF2, 0xF4, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF }; /// Length of each veritical code -byte usx_vcode_lens[] = { 2, 3, 3, 4, 4, 4, 4, +uint8_t usx_vcode_lens[] = { 2, 3, 3, 4, 4, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }; /// Vertical Codes and Set number for frequent sequences in sets USX_SYM and USX_NUM. First 3 bits indicate set (USX_SYM/USX_NUM) and rest are vcode positions -byte usx_freq_codes[] = {(1 << 5) + 25, (1 << 5) + 26, (1 << 5) + 27, (2 << 5) + 23, (2 << 5) + 24, (2 << 5) + 25}; +uint8_t usx_freq_codes[] = {(1 << 5) + 25, (1 << 5) + 26, (1 << 5) + 27, (2 << 5) + 23, (2 << 5) + 24, (2 << 5) + 25}; /// Not used const int UTF8_MASK[] = {0xE0, 0xF0, 0xF8}; @@ -117,7 +117,7 @@ const int UTF8_PREFIX[] = {0xC0, 0xE0, 0xF0}; #define USX_OFFSET_94 33 /// global to indicate whether initialization is complete or not -byte is_inited = 0; +uint8_t is_inited = 0; /// Fills the usx_code_94 94 letter array based on sets of characters at usx_sets \n /// For each element in usx_code_94, first 3 msb bits is set (USX_ALPHA / USX_SYM / USX_NUM) \n @@ -128,7 +128,7 @@ void init_coder() { memset(usx_code_94, '\0', sizeof(usx_code_94)); for (int i = 0; i < 3; i++) { for (int j = 0; j < 28; j++) { - byte c = usx_sets[i][j]; + uint8_t c = usx_sets[i][j]; if (c > 32) { usx_code_94[c - USX_OFFSET_94] = (i << 5) + j; if (c >= 'a' && c <= 'z') @@ -145,7 +145,7 @@ unsigned int usx_mask[] = {0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF}; /// Appends specified number of bits to the output (out) \n /// If maximum limit (olen) is reached, -1 is returned \n /// Otherwise clen bits in code are appended to out starting with MSB -int append_bits(char *out, int olen, int ol, byte code, int clen) { +int append_bits(char *out, int olen, int ol, uint8_t code, int clen) { //printf("%d,%x,%d,%d\n", ol, code, clen, state); @@ -154,8 +154,8 @@ int append_bits(char *out, int olen, int ol, byte code, int clen) { int oidx; unsigned char a_byte; - byte cur_bit = ol % 8; - byte blen = clen; + uint8_t cur_bit = ol % 8; + uint8_t blen = clen; a_byte = code & usx_mask[blen - 1]; a_byte >>= cur_bit; if (blen + cur_bit > 8) @@ -181,7 +181,7 @@ int append_bits(char *out, int olen, int ol, byte code, int clen) { } while (0) /// Appends switch code to out depending on the state (USX_DELTA or other) -int append_switch_code(char *out, int olen, int ol, byte state) { +int append_switch_code(char *out, int olen, int ol, uint8_t state) { if (state == USX_DELTA) { SAFE_APPEND_BITS(ol = append_bits(out, olen, ol, UNI_STATE_SPL_CODE, UNI_STATE_SPL_CODE_LEN)); SAFE_APPEND_BITS(ol = append_bits(out, olen, ol, UNI_STATE_SW_CODE, UNI_STATE_SW_CODE_LEN)); @@ -191,9 +191,9 @@ int append_switch_code(char *out, int olen, int ol, byte state) { } /// Appends given horizontal and veritical code bits to out -int append_code(char *out, int olen, int ol, byte code, byte *state, const byte usx_hcodes[], const byte usx_hcode_lens[]) { - byte hcode = code >> 5; - byte vcode = code & 0x1F; +int append_code(char *out, int olen, int ol, uint8_t code, uint8_t *state, const uint8_t usx_hcodes[], const uint8_t usx_hcode_lens[]) { + uint8_t hcode = code >> 5; + uint8_t vcode = code & 0x1F; if (!usx_hcode_lens[hcode] && hcode != USX_ALPHA) return ol; switch (hcode) { @@ -221,11 +221,11 @@ int append_code(char *out, int olen, int ol, byte code, byte *state, const byte } /// Length of bits used to represent count for each level -const byte count_bit_lens[5] = {2, 4, 7, 11, 16}; +const uint8_t count_bit_lens[5] = {2, 4, 7, 11, 16}; /// Cumulative counts represented at each level const int32_t count_adder[5] = {4, 20, 148, 2196, 67732}; /// Codes used to specify the level that the count belongs to -const byte count_codes[] = {0x01, 0x82, 0xC3, 0xE4, 0xF4}; +const uint8_t count_codes[] = {0x01, 0x82, 0xC3, 0xE4, 0xF4}; /// Encodes given count to out int encodeCount(char *out, int olen, int ol, int count) { // First five bits are code and Last three bits of codes represent length @@ -245,15 +245,15 @@ int encodeCount(char *out, int olen, int ol, int count) { } /// Length of bits used to represent delta code for each level -const byte uni_bit_len[5] = {6, 12, 14, 16, 21}; +const uint8_t uni_bit_len[5] = {6, 12, 14, 16, 21}; /// Cumulative delta codes represented at each level const int32_t uni_adder[5] = {0, 64, 4160, 20544, 86080}; /// Encodes the unicode code point given by code to out. prev_code is used to calculate the delta int encodeUnicode(char *out, int olen, int ol, int32_t code, int32_t prev_code) { // First five bits are code and Last three bits of codes represent length - //const byte codes[8] = {0x00, 0x42, 0x83, 0xA3, 0xC3, 0xE4, 0xF5, 0xFD}; - const byte codes[6] = {0x01, 0x82, 0xC3, 0xE4, 0xF5, 0xFD}; + //const uint8_t codes[8] = {0x00, 0x42, 0x83, 0xA3, 0xC3, 0xE4, 0xF5, 0xFD}; + const uint8_t codes[6] = {0x01, 0x82, 0xC3, 0xE4, 0xF5, 0xFD}; int32_t till = 0; int32_t diff = code - prev_code; if (diff < 0) @@ -331,7 +331,7 @@ int32_t readUTF8(const char *in, int len, int l, int *utf8len) { /// This is also used for Unicode strings \n /// This is a crude implementation that is not optimized. Assuming only short strings \n /// are encoded, this is not much of an issue. -int matchOccurance(const char *in, int len, int l, char *out, int olen, int *ol, byte *state, const byte usx_hcodes[], const byte usx_hcode_lens[]) { +int matchOccurance(const char *in, int len, int l, char *out, int olen, int *ol, uint8_t *state, const uint8_t usx_hcodes[], const uint8_t usx_hcode_lens[]) { int j, k; int longest_dist = 0; int longest_len = 0; @@ -372,7 +372,7 @@ int matchOccurance(const char *in, int len, int l, char *out, int olen, int *ol, /// This is also used for Unicode strings \n /// This is a crude implementation that is not optimized. Assuming only short strings \n /// are encoded, this is not much of an issue. -int matchLine(const char *in, int len, int l, char *out, int olen, int *ol, struct us_lnk_lst *prev_lines, byte *state, const byte usx_hcodes[], const byte usx_hcode_lens[]) { +int matchLine(const char *in, int len, int l, char *out, int olen, int *ol, struct us_lnk_lst *prev_lines, uint8_t *state, const uint8_t usx_hcodes[], const uint8_t usx_hcode_lens[]) { int last_ol = *ol; int last_len = 0; int last_dist = 0; @@ -431,7 +431,7 @@ int matchLine(const char *in, int len, int l, char *out, int olen, int *ol, stru /// Returns 4 bit code assuming ch falls between '0' to '9', \n /// 'A' to 'F' or 'a' to 'f' -byte getBaseCode(char ch) { +uint8_t getBaseCode(char ch) { if (ch >= '0' && ch <= '9') return (ch - '0') << 4; else if (ch >= 'A' && ch <= 'F') @@ -458,7 +458,7 @@ char getNibbleType(char ch) { } /// Starts coding of nibble sets -int append_nibble_escape(char *out, int olen, int ol, byte state, const byte usx_hcodes[], const byte usx_hcode_lens[]) { +int append_nibble_escape(char *out, int olen, int ol, uint8_t state, const uint8_t usx_hcodes[], const uint8_t usx_hcode_lens[]) { SAFE_APPEND_BITS(ol = append_switch_code(out, olen, ol, state)); SAFE_APPEND_BITS(ol = append_bits(out, olen, ol, usx_hcodes[USX_NUM], usx_hcode_lens[USX_NUM])); SAFE_APPEND_BITS(ol = append_bits(out, olen, ol, 0, 2)); @@ -471,7 +471,7 @@ long min_of(long c, long i) { } /// Appends the terminator code depending on the state, preset and whether full terminator needs to be encoded to out or not \n -int append_final_bits(char *const out, const int olen, int ol, const byte state, const byte is_all_upper, const byte usx_hcodes[], const byte usx_hcode_lens[]) { +int append_final_bits(char *const out, const int olen, int ol, const uint8_t state, const uint8_t is_all_upper, const uint8_t usx_hcodes[], const uint8_t usx_hcode_lens[]) { if (usx_hcode_lens[USX_ALPHA]) { if (USX_NUM != state) { // for num state, append TERM_CODE directly @@ -486,7 +486,7 @@ int append_final_bits(char *const out, const int olen, int ol, const byte state, SAFE_APPEND_BITS(ol = append_bits(out, olen, ol, TERM_BYTE_PRESET_1, is_all_upper ? TERM_BYTE_PRESET_1_LEN_UPPER : TERM_BYTE_PRESET_1_LEN_LOWER)); } - // fill byte with the last bit + // fill uint8_t with the last bit SAFE_APPEND_BITS(ol = append_bits(out, olen, ol, (ol == 0 || out[(ol-1)/8] << ((ol-1)&7) >= 0) ? 0 : 0xFF, (8 - ol % 8) & 7)); return ol; @@ -500,21 +500,21 @@ int append_final_bits(char *const out, const int olen, int ol, const byte state, } while (0) // Main API function. See unishox2.h for documentation -int unishox2_compress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(char *out, int olen), const byte usx_hcodes[], const byte usx_hcode_lens[], const char *usx_freq_seq[], const char *usx_templates[], struct us_lnk_lst *prev_lines) { +int unishox2_compress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(char *out, int olen), const uint8_t usx_hcodes[], const uint8_t usx_hcode_lens[], const char *usx_freq_seq[], const char *usx_templates[], struct us_lnk_lst *prev_lines) { - byte state; + uint8_t state; int l, ll, ol; char c_in, c_next; int prev_uni; - byte is_upper, is_all_upper; + uint8_t is_upper, is_all_upper; #if (UNISHOX_API_OUT_AND_LEN(0,1)) == 0 const int olen = INT_MAX - 1; const int rawolen = olen; - const byte need_full_term_codes = 0; + const uint8_t need_full_term_codes = 0; #else const int rawolen = olen; - byte need_full_term_codes = 0; + uint8_t need_full_term_codes = 0; if (olen < 0) { need_full_term_codes = 1; olen *= -1; @@ -735,9 +735,9 @@ int unishox2_compress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(cha } } if (state == USX_DELTA && (c_in == ' ' || c_in == '.' || c_in == ',')) { - byte spl_code = (c_in == ',' ? 0xC0 : (c_in == '.' ? 0xE0 : (c_in == ' ' ? 0 : 0xFF))); + uint8_t spl_code = (c_in == ',' ? 0xC0 : (c_in == '.' ? 0xE0 : (c_in == ' ' ? 0 : 0xFF))); if (spl_code != 0xFF) { - byte spl_code_len = (c_in == ',' ? 3 : (c_in == '.' ? 4 : (c_in == ' ' ? 1 : 4))); + uint8_t spl_code_len = (c_in == ',' ? 3 : (c_in == '.' ? 4 : (c_in == ' ' ? 1 : 4))); SAFE_APPEND_BITS2(rawolen, ol = append_bits(out, olen, ol, UNI_STATE_SPL_CODE, UNI_STATE_SPL_CODE_LEN)); SAFE_APPEND_BITS2(rawolen, ol = append_bits(out, olen, ol, spl_code, spl_code_len)); continue; @@ -833,7 +833,7 @@ int unishox2_compress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(cha } // Main API function. See unishox2.h for documentation -int unishox2_compress(const char *in, int len, UNISHOX_API_OUT_AND_LEN(char *out, int olen), const byte usx_hcodes[], const byte usx_hcode_lens[], const char *usx_freq_seq[], const char *usx_templates[]) { +int unishox2_compress(const char *in, int len, UNISHOX_API_OUT_AND_LEN(char *out, int olen), const uint8_t usx_hcodes[], const uint8_t usx_hcode_lens[], const char *usx_freq_seq[], const char *usx_templates[]) { return unishox2_compress_lines(in, len, UNISHOX_API_OUT_AND_LEN(out, olen), usx_hcodes, usx_hcode_lens, usx_freq_seq, usx_templates, NULL); } @@ -852,10 +852,10 @@ int read8bitCode(const char *in, int len, int bit_no) { int bit_pos = bit_no & 0x07; int char_pos = bit_no >> 3; len >>= 3; - byte code = (((byte)in[char_pos]) << bit_pos); + uint8_t code = (((uint8_t)in[char_pos]) << bit_pos); char_pos++; if (char_pos < len) { - code |= ((byte)in[char_pos]) >> (8 - bit_pos); + code |= ((uint8_t)in[char_pos]) >> (8 - bit_pos); } else code |= (0xFF >> (8 - bit_pos)); return code; @@ -864,17 +864,17 @@ int read8bitCode(const char *in, int len, int bit_no) { /// The list of veritical codes is split into 5 sections. Used by readVCodeIdx() #define SECTION_COUNT 5 /// Used by readVCodeIdx() for finding the section under which the code read using read8bitCode() falls -byte usx_vsections[] = {0x7F, 0xBF, 0xDF, 0xEF, 0xFF}; +uint8_t usx_vsections[] = {0x7F, 0xBF, 0xDF, 0xEF, 0xFF}; /// Used by readVCodeIdx() for finding the section vertical position offset -byte usx_vsection_pos[] = {0, 4, 8, 12, 20}; +uint8_t usx_vsection_pos[] = {0, 4, 8, 12, 20}; /// Used by readVCodeIdx() for masking the code read by read8bitCode() -byte usx_vsection_mask[] = {0x7F, 0x3F, 0x1F, 0x0F, 0x0F}; +uint8_t usx_vsection_mask[] = {0x7F, 0x3F, 0x1F, 0x0F, 0x0F}; /// Used by readVCodeIdx() for shifting the code read by read8bitCode() to obtain the vpos -byte usx_vsection_shift[] = {5, 4, 3, 1, 0}; +uint8_t usx_vsection_shift[] = {5, 4, 3, 1, 0}; /// Vertical decoder lookup table - 3 bits code len, 5 bytes vertical pos /// code len is one less as 8 cannot be accommodated in 3 bits -byte usx_vcode_lookup[36] = { +uint8_t usx_vcode_lookup[36] = { (1 << 5) + 0, (1 << 5) + 0, (2 << 5) + 1, (2 << 5) + 2, // Section 1 (3 << 5) + 3, (3 << 5) + 4, (3 << 5) + 5, (3 << 5) + 6, // Section 2 (3 << 5) + 7, (3 << 5) + 7, (4 << 5) + 8, (4 << 5) + 9, // Section 3 @@ -887,19 +887,19 @@ byte usx_vcode_lookup[36] = { }; /// Decodes the vertical code from the given bitstream at in \n -/// This is designed to use less memory using a 36 byte buffer \n -/// compared to using a 256 byte buffer to decode the next 8 bits read by read8bitCode() \n +/// This is designed to use less memory using a 36 uint8_t buffer \n +/// compared to using a 256 uint8_t buffer to decode the next 8 bits read by read8bitCode() \n /// by splitting the list of vertical codes. \n /// Decoder is designed for using less memory, not speed. \n /// Returns the veritical code index or 99 if match could not be found. \n /// Also updates bit_no_p with how many ever bits used by the vertical code. int readVCodeIdx(const char *in, int len, int *bit_no_p) { if (*bit_no_p < len) { - byte code = read8bitCode(in, len, *bit_no_p); + uint8_t code = read8bitCode(in, len, *bit_no_p); int i = 0; do { if (code <= usx_vsections[i]) { - byte vcode = usx_vcode_lookup[usx_vsection_pos[i] + ((code & usx_vsection_mask[i]) >> usx_vsection_shift[i])]; + uint8_t vcode = usx_vcode_lookup[usx_vsection_pos[i] + ((code & usx_vsection_mask[i]) >> usx_vsection_shift[i])]; (*bit_no_p) += ((vcode >> 5) + 1); if (*bit_no_p > len) return 99; @@ -912,16 +912,16 @@ int readVCodeIdx(const char *in, int len, int *bit_no_p) { /// Mask for retrieving each code to be decoded according to its length \n /// Same as usx_mask so redundant -byte len_masks[] = {0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF}; +uint8_t len_masks[] = {0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF}; /// Decodes the horizontal code from the given bitstream at in \n /// depending on the hcodes defined using usx_hcodes and usx_hcode_lens \n /// Returns the horizontal code index or 99 if match could not be found. \n /// Also updates bit_no_p with how many ever bits used by the horizontal code. -int readHCodeIdx(const char *in, int len, int *bit_no_p, const byte usx_hcodes[], const byte usx_hcode_lens[]) { +int readHCodeIdx(const char *in, int len, int *bit_no_p, const uint8_t usx_hcodes[], const uint8_t usx_hcode_lens[]) { if (!usx_hcode_lens[USX_ALPHA]) return USX_ALPHA; if (*bit_no_p < len) { - byte code = read8bitCode(in, len, *bit_no_p); + uint8_t code = read8bitCode(in, len, *bit_no_p); for (int code_pos = 0; code_pos < 5; code_pos++) { if (usx_hcode_lens[code_pos] && (code & len_masks[usx_hcode_lens[code_pos] - 1]) == usx_hcodes[code_pos]) { *bit_no_p += usx_hcode_lens[code_pos]; @@ -1083,12 +1083,12 @@ char getHexChar(int32_t nibble, int hex_type) { } // Main API function. See unishox2.h for documentation -int unishox2_decompress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(char *out, int olen), const byte usx_hcodes[], const byte usx_hcode_lens[], const char *usx_freq_seq[], const char *usx_templates[], struct us_lnk_lst *prev_lines) { +int unishox2_decompress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(char *out, int olen), const uint8_t usx_hcodes[], const uint8_t usx_hcode_lens[], const char *usx_freq_seq[], const char *usx_templates[], struct us_lnk_lst *prev_lines) { int dstate; int bit_no; int h, v; - byte is_all_upper; + uint8_t is_all_upper; #if (UNISHOX_API_OUT_AND_LEN(0,1)) == 0 const int olen = INT_MAX - 1; #endif @@ -1155,7 +1155,7 @@ int unishox2_decompress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(c } else h = dstate; char c = 0; - byte is_upper = is_all_upper; + uint8_t is_upper = is_all_upper; v = readVCodeIdx(in, len, &bit_no); if (v == 99 || h == 99) { bit_no = orig_bit_no; @@ -1357,7 +1357,7 @@ int unishox2_decompress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(c } // Main API function. See unishox2.h for documentation -int unishox2_decompress(const char *in, int len, UNISHOX_API_OUT_AND_LEN(char *out, int olen), const byte usx_hcodes[], const byte usx_hcode_lens[], const char *usx_freq_seq[], const char *usx_templates[]) { +int unishox2_decompress(const char *in, int len, UNISHOX_API_OUT_AND_LEN(char *out, int olen), const uint8_t usx_hcodes[], const uint8_t usx_hcode_lens[], const char *usx_freq_seq[], const char *usx_templates[]) { return unishox2_decompress_lines(in, len, UNISHOX_API_OUT_AND_LEN(out, olen), usx_hcodes, usx_hcode_lens, usx_freq_seq, usx_templates, NULL); } diff --git a/src/mesh/eth/ethClient.cpp b/src/mesh/eth/ethClient.cpp index 588913781..29f55ebee 100644 --- a/src/mesh/eth/ethClient.cpp +++ b/src/mesh/eth/ethClient.cpp @@ -95,10 +95,10 @@ bool initEthernet() getMacAddr(mac); // FIXME use the BLE MAC for now... - if (config.network.eth_mode == Config_NetworkConfig_EthMode_DHCP) { + if (config.network.address_mode == Config_NetworkConfig_AddressMode_DHCP) { LOG_INFO("starting Ethernet DHCP\n"); status = Ethernet.begin(mac); - } else if (config.network.eth_mode == Config_NetworkConfig_EthMode_STATIC) { + } else if (config.network.address_mode == Config_NetworkConfig_AddressMode_STATIC) { LOG_INFO("starting Ethernet Static\n"); Ethernet.begin(mac, config.network.ipv4_config.ip, config.network.ipv4_config.dns, config.network.ipv4_config.subnet); } else { diff --git a/src/mesh/generated/config.pb.h b/src/mesh/generated/config.pb.h index a5f7694cb..38e53d0c8 100644 --- a/src/mesh/generated/config.pb.h +++ b/src/mesh/generated/config.pb.h @@ -60,12 +60,12 @@ typedef enum _Config_PositionConfig_PositionFlags { Config_PositionConfig_PositionFlags_SPEED = 512 } Config_PositionConfig_PositionFlags; -typedef enum _Config_NetworkConfig_EthMode { +typedef enum _Config_NetworkConfig_AddressMode { /* obtain ip address via DHCP */ - Config_NetworkConfig_EthMode_DHCP = 0, + Config_NetworkConfig_AddressMode_DHCP = 0, /* use static ip address */ - Config_NetworkConfig_EthMode_STATIC = 1 -} Config_NetworkConfig_EthMode; + Config_NetworkConfig_AddressMode_STATIC = 1 +} Config_NetworkConfig_AddressMode; /* How the GPS coordinates are displayed on the OLED screen. */ typedef enum _Config_DisplayConfig_GpsCoordinateFormat { @@ -292,7 +292,7 @@ typedef struct _Config_NetworkConfig { /* Enable Ethernet */ bool eth_enabled; /* acquire an address via DHCP or assign static */ - Config_NetworkConfig_EthMode eth_mode; + Config_NetworkConfig_AddressMode address_mode; /* struct to keep static address */ bool has_ipv4_config; Config_NetworkConfig_IpV4Config ipv4_config; @@ -416,9 +416,9 @@ extern "C" { #define _Config_PositionConfig_PositionFlags_MAX Config_PositionConfig_PositionFlags_SPEED #define _Config_PositionConfig_PositionFlags_ARRAYSIZE ((Config_PositionConfig_PositionFlags)(Config_PositionConfig_PositionFlags_SPEED+1)) -#define _Config_NetworkConfig_EthMode_MIN Config_NetworkConfig_EthMode_DHCP -#define _Config_NetworkConfig_EthMode_MAX Config_NetworkConfig_EthMode_STATIC -#define _Config_NetworkConfig_EthMode_ARRAYSIZE ((Config_NetworkConfig_EthMode)(Config_NetworkConfig_EthMode_STATIC+1)) +#define _Config_NetworkConfig_AddressMode_MIN Config_NetworkConfig_AddressMode_DHCP +#define _Config_NetworkConfig_AddressMode_MAX Config_NetworkConfig_AddressMode_STATIC +#define _Config_NetworkConfig_AddressMode_ARRAYSIZE ((Config_NetworkConfig_AddressMode)(Config_NetworkConfig_AddressMode_STATIC+1)) #define _Config_DisplayConfig_GpsCoordinateFormat_MIN Config_DisplayConfig_GpsCoordinateFormat_DEC #define _Config_DisplayConfig_GpsCoordinateFormat_MAX Config_DisplayConfig_GpsCoordinateFormat_OSGR @@ -453,7 +453,7 @@ extern "C" { -#define Config_NetworkConfig_eth_mode_ENUMTYPE Config_NetworkConfig_EthMode +#define Config_NetworkConfig_address_mode_ENUMTYPE Config_NetworkConfig_AddressMode #define Config_DisplayConfig_gps_format_ENUMTYPE Config_DisplayConfig_GpsCoordinateFormat @@ -472,7 +472,7 @@ extern "C" { #define Config_DeviceConfig_init_default {_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0} #define Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0} #define Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0} -#define Config_NetworkConfig_init_default {0, "", "", "", 0, _Config_NetworkConfig_EthMode_MIN, false, Config_NetworkConfig_IpV4Config_init_default} +#define Config_NetworkConfig_init_default {0, "", "", "", 0, _Config_NetworkConfig_AddressMode_MIN, false, Config_NetworkConfig_IpV4Config_init_default} #define Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0} #define Config_DisplayConfig_init_default {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN, _Config_DisplayConfig_OledType_MIN, _Config_DisplayConfig_DisplayMode_MIN, 0} #define Config_LoRaConfig_init_default {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, {0, 0, 0}} @@ -481,7 +481,7 @@ extern "C" { #define Config_DeviceConfig_init_zero {_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0} #define Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0} #define Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0} -#define Config_NetworkConfig_init_zero {0, "", "", "", 0, _Config_NetworkConfig_EthMode_MIN, false, Config_NetworkConfig_IpV4Config_init_zero} +#define Config_NetworkConfig_init_zero {0, "", "", "", 0, _Config_NetworkConfig_AddressMode_MIN, false, Config_NetworkConfig_IpV4Config_init_zero} #define Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0} #define Config_DisplayConfig_init_zero {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN, _Config_DisplayConfig_OledType_MIN, _Config_DisplayConfig_DisplayMode_MIN, 0} #define Config_LoRaConfig_init_zero {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, {0, 0, 0}} @@ -519,7 +519,7 @@ extern "C" { #define Config_NetworkConfig_wifi_psk_tag 4 #define Config_NetworkConfig_ntp_server_tag 5 #define Config_NetworkConfig_eth_enabled_tag 6 -#define Config_NetworkConfig_eth_mode_tag 7 +#define Config_NetworkConfig_address_mode_tag 7 #define Config_NetworkConfig_ipv4_config_tag 8 #define Config_DisplayConfig_screen_on_secs_tag 1 #define Config_DisplayConfig_gps_format_tag 2 @@ -613,7 +613,7 @@ X(a, STATIC, SINGULAR, STRING, wifi_ssid, 3) \ X(a, STATIC, SINGULAR, STRING, wifi_psk, 4) \ X(a, STATIC, SINGULAR, STRING, ntp_server, 5) \ X(a, STATIC, SINGULAR, BOOL, eth_enabled, 6) \ -X(a, STATIC, SINGULAR, UENUM, eth_mode, 7) \ +X(a, STATIC, SINGULAR, UENUM, address_mode, 7) \ X(a, STATIC, OPTIONAL, MESSAGE, ipv4_config, 8) #define Config_NetworkConfig_CALLBACK NULL #define Config_NetworkConfig_DEFAULT NULL diff --git a/src/mesh/generated/mesh.pb.c b/src/mesh/generated/mesh.pb.c index bd749b6cb..29594c612 100644 --- a/src/mesh/generated/mesh.pb.c +++ b/src/mesh/generated/mesh.pb.c @@ -36,6 +36,9 @@ PB_BIND(MyNodeInfo, MyNodeInfo, AUTO) PB_BIND(LogRecord, LogRecord, AUTO) +PB_BIND(QueueStatus, QueueStatus, AUTO) + + PB_BIND(FromRadio, FromRadio, 2) diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index 31e7817a0..d1f3e5bf5 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -621,6 +621,17 @@ typedef struct _LogRecord { LogRecord_Level level; } LogRecord; +typedef struct _QueueStatus { + /* Last attempt to queue status, ErrorCode */ + int8_t res; + /* Free entries in the outgoing queue */ + uint8_t free; + /* Maximum entries in the outgoing queue */ + uint8_t maxlen; + /* What was mesh packet id that generated this response? */ + uint32_t mesh_packet_id; +} QueueStatus; + /* Packets from the radio to the phone will appear on the fromRadio characteristic. It will support READ and NOTIFY. When a new packet arrives the device will BLE notify? It will sit in that descriptor until consumed by the phone, @@ -657,6 +668,8 @@ typedef struct _FromRadio { ModuleConfig moduleConfig; /* One packet is sent for each channel */ Channel channel; + /* Queue status info */ + QueueStatus queueStatus; }; } FromRadio; @@ -755,6 +768,7 @@ extern "C" { + #define Compressed_portnum_ENUMTYPE PortNum @@ -769,6 +783,7 @@ extern "C" { #define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0, false, DeviceMetrics_init_default} #define MyNodeInfo_init_default {0, 0, 0, "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0} #define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN} +#define QueueStatus_init_default {0, 0, 0, 0} #define FromRadio_init_default {0, 0, {MeshPacket_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}} #define Compressed_init_default {_PortNum_MIN, {0, {0}}} @@ -782,6 +797,7 @@ extern "C" { #define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0, false, DeviceMetrics_init_zero} #define MyNodeInfo_init_zero {0, 0, 0, "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0} #define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN} +#define QueueStatus_init_zero {0, 0, 0, 0} #define FromRadio_init_zero {0, 0, {MeshPacket_init_zero}} #define ToRadio_init_zero {0, {MeshPacket_init_zero}} #define Compressed_init_zero {_PortNum_MIN, {0, {0}}} @@ -873,6 +889,10 @@ extern "C" { #define LogRecord_time_tag 2 #define LogRecord_source_tag 3 #define LogRecord_level_tag 4 +#define QueueStatus_res_tag 1 +#define QueueStatus_free_tag 2 +#define QueueStatus_maxlen_tag 3 +#define QueueStatus_mesh_packet_id_tag 4 #define FromRadio_id_tag 1 #define FromRadio_packet_tag 2 #define FromRadio_my_info_tag 3 @@ -883,6 +903,7 @@ extern "C" { #define FromRadio_rebooted_tag 8 #define FromRadio_moduleConfig_tag 9 #define FromRadio_channel_tag 10 +#define FromRadio_queueStatus_tag 11 #define ToRadio_packet_tag 1 #define ToRadio_want_config_id_tag 3 #define ToRadio_disconnect_tag 4 @@ -1022,6 +1043,14 @@ X(a, STATIC, SINGULAR, UENUM, level, 4) #define LogRecord_CALLBACK NULL #define LogRecord_DEFAULT NULL +#define QueueStatus_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, res, 1) \ +X(a, STATIC, SINGULAR, UINT32, free, 2) \ +X(a, STATIC, SINGULAR, UINT32, maxlen, 3) \ +X(a, STATIC, SINGULAR, UINT32, mesh_packet_id, 4) +#define QueueStatus_CALLBACK NULL +#define QueueStatus_DEFAULT NULL + #define FromRadio_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, id, 1) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,packet,packet), 2) \ @@ -1032,7 +1061,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,log_record,log_record), 6) X(a, STATIC, ONEOF, UINT32, (payload_variant,config_complete_id,config_complete_id), 7) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,rebooted,rebooted), 8) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,moduleConfig,moduleConfig), 9) \ -X(a, STATIC, ONEOF, MESSAGE, (payload_variant,channel,channel), 10) +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,channel,channel), 10) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,queueStatus,queueStatus), 11) #define FromRadio_CALLBACK NULL #define FromRadio_DEFAULT NULL #define FromRadio_payload_variant_packet_MSGTYPE MeshPacket @@ -1042,6 +1072,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,channel,channel), 10) #define FromRadio_payload_variant_log_record_MSGTYPE LogRecord #define FromRadio_payload_variant_moduleConfig_MSGTYPE ModuleConfig #define FromRadio_payload_variant_channel_MSGTYPE Channel +#define FromRadio_payload_variant_queueStatus_MSGTYPE QueueStatus #define ToRadio_FIELDLIST(X, a) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,packet,packet), 1) \ @@ -1067,6 +1098,7 @@ extern const pb_msgdesc_t MeshPacket_msg; extern const pb_msgdesc_t NodeInfo_msg; extern const pb_msgdesc_t MyNodeInfo_msg; extern const pb_msgdesc_t LogRecord_msg; +extern const pb_msgdesc_t QueueStatus_msg; extern const pb_msgdesc_t FromRadio_msg; extern const pb_msgdesc_t ToRadio_msg; extern const pb_msgdesc_t Compressed_msg; @@ -1082,6 +1114,7 @@ extern const pb_msgdesc_t Compressed_msg; #define NodeInfo_fields &NodeInfo_msg #define MyNodeInfo_fields &MyNodeInfo_msg #define LogRecord_fields &LogRecord_msg +#define QueueStatus_fields &QueueStatus_msg #define FromRadio_fields &FromRadio_msg #define ToRadio_fields &ToRadio_msg #define Compressed_fields &Compressed_msg @@ -1095,6 +1128,7 @@ extern const pb_msgdesc_t Compressed_msg; #define MyNodeInfo_size 179 #define NodeInfo_size 258 #define Position_size 137 +#define QueueStatus_size 23 #define RouteDiscovery_size 40 #define Routing_size 42 #define ToRadio_size 324 diff --git a/src/mesh/generated/telemetry.pb.h b/src/mesh/generated/telemetry.pb.h index 1b294dc1a..e5c71a2b7 100644 --- a/src/mesh/generated/telemetry.pb.h +++ b/src/mesh/generated/telemetry.pb.h @@ -71,10 +71,10 @@ typedef struct _EnvironmentMetrics { /* Types of Measurements the telemetry module is equipped to handle */ typedef struct _Telemetry { - /* This is usually not sent over the mesh (to save space), but it is sent - from the phone so that the local device can set its RTC If it is sent over - the mesh (because there are devices on the mesh without GPS), it will only - be sent by devices which has a hardware GPS clock (IE Mobile Phone). + /* This is usually not sent over the mesh (to save space), but it is sent + from the phone so that the local device can set its RTC If it is sent over + the mesh (because there are devices on the mesh without GPS), it will only + be sent by devices which has a hardware GPS clock (IE Mobile Phone). seconds since 1970 */ uint32_t time; pb_size_t which_variant; diff --git a/src/mesh/http/WiFiAPClient.cpp b/src/mesh/http/WiFiAPClient.cpp index cba09dd7c..ec34f9927 100644 --- a/src/mesh/http/WiFiAPClient.cpp +++ b/src/mesh/http/WiFiAPClient.cpp @@ -169,7 +169,7 @@ bool initWifi() WiFi.onEvent(WiFiEvent); WiFi.setAutoReconnect(false); WiFi.setSleep(false); - if (config.network.eth_mode == Config_NetworkConfig_EthMode_STATIC && config.network.ipv4_config.ip != 0) { + if (config.network.address_mode == Config_NetworkConfig_AddressMode_STATIC && config.network.ipv4_config.ip != 0) { WiFi.config(config.network.ipv4_config.ip, config.network.ipv4_config.gateway, config.network.ipv4_config.subnet, diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index b24b0bbc0..e0014f98c 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -42,26 +42,22 @@ int32_t ExternalNotificationModule::runOnce() if (!moduleConfig.external_notification.enabled) { return INT32_MAX; // we don't need this thread here... } else { -#ifndef ARCH_PORTDUINO if ((nagCycleCutoff < millis()) && !rtttl::isPlaying()) { -#else - if (nagCycleCutoff < millis()) { -#endif + // let the song finish if we reach timeout nagCycleCutoff = UINT32_MAX; LOG_INFO("Turning off external notification: "); for (int i = 0; i < 2; i++) { - if (getExternal(i)) { - setExternalOff(i); - externalTurnedOn[i] = 0; - LOG_INFO("%d ", i); - } + setExternalOff(i); + externalTurnedOn[i] = 0; + LOG_INFO("%d ", i); } LOG_INFO("\n"); + isNagging = false; return INT32_MAX; // save cycles till we're needed again } // If the output is turned on, turn it back off after the given period of time. - if (nagCycleCutoff != UINT32_MAX) { + if (isNagging) { if (externalTurnedOn[0] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms : EXT_NOTIFICATION_MODULE_OUTPUT_MS) < millis()) { @@ -80,16 +76,14 @@ int32_t ExternalNotificationModule::runOnce() } // now let the PWM buzzer play -#ifndef ARCH_PORTDUINO if (moduleConfig.external_notification.use_pwm) { if (rtttl::isPlaying()) { rtttl::play(); - } else if (nagCycleCutoff >= millis()) { + } else if (isNagging && (nagCycleCutoff >= millis())) { // start the song again if we have time left rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone); } } -#endif return 25; } } @@ -140,10 +134,9 @@ bool ExternalNotificationModule::getExternal(uint8_t index) } void ExternalNotificationModule::stopNow() { -#ifndef ARCH_PORTDUINO rtttl::stop(); -#endif nagCycleCutoff = 1; // small value + isNagging = false; setIntervalFromNow(0); } @@ -230,6 +223,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp) if (moduleConfig.external_notification.alert_bell) { if (containsBell) { LOG_INFO("externalNotificationModule - Notification Bell\n"); + isNagging = true; setExternalOn(0); if (moduleConfig.external_notification.nag_timeout) { nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000; @@ -242,6 +236,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp) if (moduleConfig.external_notification.alert_bell_vibra) { if (containsBell) { LOG_INFO("externalNotificationModule - Notification Bell (Vibra)\n"); + isNagging = true; setExternalOn(1); if (moduleConfig.external_notification.nag_timeout) { nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000; @@ -254,12 +249,11 @@ ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp) if (moduleConfig.external_notification.alert_bell_buzzer) { if (containsBell) { LOG_INFO("externalNotificationModule - Notification Bell (Buzzer)\n"); + isNagging = true; if (!moduleConfig.external_notification.use_pwm) { setExternalOn(2); } else { -#ifndef ARCH_PORTDUINO rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone); -#endif } if (moduleConfig.external_notification.nag_timeout) { nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000; @@ -271,6 +265,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp) if (moduleConfig.external_notification.alert_message) { LOG_INFO("externalNotificationModule - Notification Module\n"); + isNagging = true; setExternalOn(0); if (moduleConfig.external_notification.nag_timeout) { nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000; @@ -279,33 +274,33 @@ ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp) } } - if (!moduleConfig.external_notification.use_pwm) { - if (moduleConfig.external_notification.alert_message_vibra) { - LOG_INFO("externalNotificationModule - Notification Module (Vibra)\n"); - setExternalOn(1); - if (moduleConfig.external_notification.nag_timeout) { - nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000; - } else { - nagCycleCutoff = millis() + moduleConfig.external_notification.output_ms; - } - } - - if (moduleConfig.external_notification.alert_message_buzzer) { - LOG_INFO("externalNotificationModule - Notification Module (Buzzer)\n"); - if (!moduleConfig.external_notification.use_pwm) { - setExternalOn(2); - } else { -#ifndef ARCH_PORTDUINO - rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone); -#endif - } - if (moduleConfig.external_notification.nag_timeout) { - nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000; - } else { - nagCycleCutoff = millis() + moduleConfig.external_notification.output_ms; - } + + if (moduleConfig.external_notification.alert_message_vibra) { + LOG_INFO("externalNotificationModule - Notification Module (Vibra)\n"); + isNagging = true; + setExternalOn(1); + if (moduleConfig.external_notification.nag_timeout) { + nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000; + } else { + nagCycleCutoff = millis() + moduleConfig.external_notification.output_ms; } } + + if (moduleConfig.external_notification.alert_message_buzzer) { + LOG_INFO("externalNotificationModule - Notification Module (Buzzer)\n"); + isNagging = true; + if (!moduleConfig.external_notification.use_pwm) { + setExternalOn(2); + } else { + rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone); + } + if (moduleConfig.external_notification.nag_timeout) { + nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000; + } else { + nagCycleCutoff = millis() + moduleConfig.external_notification.output_ms; + } + } + setIntervalFromNow(0); // run once so we know if we should do something } diff --git a/src/modules/ExternalNotificationModule.h b/src/modules/ExternalNotificationModule.h index 50af360c1..097ae96b3 100644 --- a/src/modules/ExternalNotificationModule.h +++ b/src/modules/ExternalNotificationModule.h @@ -5,6 +5,18 @@ #include "configuration.h" #ifndef ARCH_PORTDUINO #include +#else +// Noop class for portduino. +class rtttl +{ + public: + explicit rtttl() {} + static bool isPlaying() { return false; } + static void play() {} + static void begin(byte a, const char * b) {}; + static void stop() {} + static bool done() { return true; } +}; #endif #include #include @@ -39,6 +51,8 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency: virtual int32_t runOnce() override; + bool isNagging = false; + virtual AdminMessageHandleResult handleAdminMessageForModule(const MeshPacket &mp, AdminMessage *request, AdminMessage *response) override; }; diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp index 96a6c0582..cd873a466 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp @@ -75,7 +75,7 @@ void setupModules() new RangeTestModule(); #elif defined(ARCH_NRF52) - new ExternalNotificationModule(); + externalNotificationModule = new ExternalNotificationModule(); #endif // NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra acks diff --git a/src/platform/portduino/SimRadio.cpp b/src/platform/portduino/SimRadio.cpp index 87800de22..a2611a464 100644 --- a/src/platform/portduino/SimRadio.cpp +++ b/src/platform/portduino/SimRadio.cpp @@ -215,6 +215,16 @@ void SimRadio::startReceive(MeshPacket *p) { handleReceiveInterrupt(p); } +QueueStatus SimRadio::getQueueStatus() +{ + QueueStatus qs; + + qs.res = qs.mesh_packet_id = 0; + qs.free = txQueue.getFree(); + qs.maxlen = txQueue.getMaxLen(); + + return qs; +} void SimRadio::handleReceiveInterrupt(MeshPacket *p) { diff --git a/src/platform/portduino/SimRadio.h b/src/platform/portduino/SimRadio.h index a71cf22f8..d2a36c81e 100644 --- a/src/platform/portduino/SimRadio.h +++ b/src/platform/portduino/SimRadio.h @@ -45,6 +45,9 @@ class SimRadio : public RadioInterface */ virtual void startReceive(MeshPacket *p); + QueueStatus getQueueStatus() override; + + protected: /// are _trying_ to receive a packet currently (note - we might just be waiting for one) bool isReceiving = false; diff --git a/version.properties b/version.properties index 5c253336e..816f7c2ac 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 0 -build = 11 +build = 12