Merge pull request #2100 from meshtastic/develop

Update Raspi branch
This commit is contained in:
Thomas Göttgens
2023-01-04 21:11:47 +01:00
committed by GitHub
27 changed files with 307 additions and 128 deletions

View File

@@ -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()
{

View File

@@ -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

View File

@@ -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();

View File

@@ -52,10 +52,15 @@ FIXME in the initial proof of concept we just skip the entire want/deny flow and
MeshService service;
static MemoryDynamic<QueueStatus> staticQueueStatusPool;
Allocator<QueueStatus> &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);

View File

@@ -14,6 +14,8 @@
#include "../platform/portduino/SimRadio.h"
#endif
extern Allocator<QueueStatus> &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<MeshPacket> toPhoneQueue;
// keep list of QueueStatus packets to be send to the phone
PointerQueue<QueueStatus> 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;

View File

@@ -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;
}

View File

@@ -42,6 +42,9 @@ class PhoneAPI : public Observer<uint32_t> // 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<uint32_t> // FIXME, we shouldn't be inheriting
private:
void releasePhonePacket();
void releaseQueueStatusPhonePacket();
/// begin a new connection
void handleStartConfig();

View File

@@ -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; }

View File

@@ -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();

View File

@@ -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 */

View File

@@ -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

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -36,6 +36,9 @@ PB_BIND(MyNodeInfo, MyNodeInfo, AUTO)
PB_BIND(LogRecord, LogRecord, AUTO)
PB_BIND(QueueStatus, QueueStatus, AUTO)
PB_BIND(FromRadio, FromRadio, 2)

View File

@@ -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

View File

@@ -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;

View File

@@ -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,

View File

@@ -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
}

View File

@@ -5,6 +5,18 @@
#include "configuration.h"
#ifndef ARCH_PORTDUINO
#include <NonBlockingRtttl.h>
#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 <Arduino.h>
#include <functional>
@@ -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;
};

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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;