Upgrade to Version 0.3.0

This commit is contained in:
tuxphone 2024-05-12 20:35:38 +02:00
parent 9e9ae92849
commit 200893ee84
14 changed files with 584 additions and 417 deletions

View File

@ -1,7 +1,12 @@
# CubeCellRepeater # CubeCellRepeater
This is the code for a simple repeater node for the meshtastic project: https://github.com/meshtastic This is the code for a simple repeater node for the meshtastic project: https://github.com/meshtastic (https://www.meshtastic.org)
The Meshtastic project is in no way affiliated with or respnsible for the CubeCellRepeater project.
To be compatible with meshtastic project, portions of their code was used.
(c) Copyright Meshtastic Project (and others).
Hardware:
The actual node can be one of the LoRa CubeCell nodes by Heltec Automation: https://github.com/HelTecAutomation/ASR650x-Arduino/ The actual node can be one of the LoRa CubeCell nodes by Heltec Automation: https://github.com/HelTecAutomation/ASR650x-Arduino/
Notes: Notes:
@ -9,15 +14,69 @@ Notes:
Intended for use with the platform.io IDE. Serial output speed is 115200. Intended for use with the platform.io IDE. Serial output speed is 115200.
See the provided platformio.ini for built-in environments. Default is cubecell_board. See the provided platformio.ini for built-in environments. Default is cubecell_board.
Will repeat packets ONCE with HopLimit reduced by one. To prevent flooding the last repeated packet ID will not be repeated again. Will repeat packets ONCE with HopLimit reduced by one. To prevent flooding the last 64 repeated packets will not be repeated again.
If the HopLimit was already 0, the packet will not be repeated. If the HopLimit was already 0, the packet will not be repeated.
Keep in mind that re-sending packets will cause the initial sender to assume that the packet is "received" or at least in the mesh. Keep in mind that re-sending packets will cause the initial sender to assume that the packet is "received" or at least in the mesh.
If no other meshtastic node is in range of either the node or the repeater, the message will still be shown as received. If no other meshtastic node is in range of either the node or the repeater, the message will still be shown as received.
Will work with most packets meeting the radio settings, but the serial output is based on the assumption that the node receives meshtastic packets. Will work with most packets meeting the radio settings, but the serial output is based on the assumption that the node receives meshtastic packets.
Minimum size for none-Meshtastic packets is 14 bytes. Minimum size for none-Meshtastic packets is 16 bytes.
"#define SILENT" in main.h to stop serial output. "#define SILENT" in main.h to stop serial output.
Modifying radio settings for your own radio settings: edit the main.h The node can decode meshtastic packets meeting some requirements:
- they key is the default meshtastic key or provided by you (see main.h)
- the packets are sent over channel 0, primary channel. This should already be true for all telemetry, node info, traces and DM.
##Modifying radio settings: edit the main.h
List of meshtastic-supported regions:
/* United States */
meshtastic_Config_LoRaConfig_RegionCode_US
/* European Union 433mhz */
meshtastic_Config_LoRaConfig_RegionCode_EU_433
/* European Union 868mhz */
meshtastic_Config_LoRaConfig_RegionCode_EU_868 (default)
/* China */
meshtastic_Config_LoRaConfig_RegionCode_CN
/* Japan */
meshtastic_Config_LoRaConfig_RegionCode_JP
/* Australia / New Zealand */
meshtastic_Config_LoRaConfig_RegionCode_ANZ
/* Korea */
meshtastic_Config_LoRaConfig_RegionCode_KR
/* Taiwan */
meshtastic_Config_LoRaConfig_RegionCode_TW
/* Russia */
meshtastic_Config_LoRaConfig_RegionCode_RU
/* India */
meshtastic_Config_LoRaConfig_RegionCode_IN
/* New Zealand 865mhz */
meshtastic_Config_LoRaConfig_RegionCode_NZ_865
/* Thailand */
meshtastic_Config_LoRaConfig_RegionCode_TH
/* WLAN Band */
meshtastic_Config_LoRaConfig_RegionCode_LORA_24
/* Ukraine 433mhz */
meshtastic_Config_LoRaConfig_RegionCode_UA_433
/* Ukraine 868mhz */
meshtastic_Config_LoRaConfig_RegionCode_UA_868
/* Malaysia 433mhz */
meshtastic_Config_LoRaConfig_RegionCode_MY_433
/* Malaysia 919mhz */
meshtastic_Config_LoRaConfig_RegionCode_MY_919
/* Singapore 923mhz */
meshtastic_Config_LoRaConfig_RegionCode_SG_923
For lora modem settings you should always try the default (LongFast), it's proven to be THE setting to go for.
If you want to try other presets, here is the list:
meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST
meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW
meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST
meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW
meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST (default)
meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE
meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW
meshtastic_Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW

View File

@ -17,13 +17,32 @@ monitor_speed = 115200
build_flags = -Os build_flags = -Os
-Isrc -Isrc/mesh -Isrc/mesh/generated -Isrc -Isrc/mesh -Isrc/mesh/generated
-D PB_ENABLE_MALLOC=1 -D PB_ENABLE_MALLOC=1
-D APP_VERSION=0.01.1 -D APP_VERSION=0.3.0
-DRADIOLIB_EXCLUDE_CC1101
-DRADIOLIB_EXCLUDE_NRF24
-DRADIOLIB_EXCLUDE_RF69
-DRADIOLIB_EXCLUDE_SX1231
-DRADIOLIB_EXCLUDE_SX1233
-DRADIOLIB_EXCLUDE_SI443X
-DRADIOLIB_EXCLUDE_RFM2X
-DRADIOLIB_EXCLUDE_AFSK
-DRADIOLIB_EXCLUDE_BELL
-DRADIOLIB_EXCLUDE_HELLSCHREIBER
-DRADIOLIB_EXCLUDE_MORSE
-DRADIOLIB_EXCLUDE_RTTY
-DRADIOLIB_EXCLUDE_SSTV
-DRADIOLIB_EXCLUDE_AX25
-DRADIOLIB_EXCLUDE_DIRECT_RECEIVE
-DRADIOLIB_EXCLUDE_BELL
-DRADIOLIB_EXCLUDE_PAGER
-DRADIOLIB_EXCLUDE_FSK4
-DRADIOLIB_EXCLUDE_APRS
-DRADIOLIB_EXCLUDE_LORAWAN
lib_deps = nanopb/Nanopb lib_deps = nanopb/Nanopb
https://github.com/meshtastic/protobufs.git https://github.com/meshtastic/protobufs.git
jgromes/RadioLib jgromes/RadioLib
https://github.com/kokke/tiny-AES-c.git https://github.com/kokke/tiny-AES-c.git
check_tool = cppcheck check_tool = cppcheck
build_type = release build_type = release
@ -33,6 +52,5 @@ platform = heltec-cubecell
board = cubecell_board board = cubecell_board
platform_packages = platformio/toolchain-gccarmnoneeabi@^1.120301.0 platform_packages = platformio/toolchain-gccarmnoneeabi@^1.120301.0
build_flags = ${common.build_flags} -Isrc/platform/cubecell build_flags = ${common.build_flags} -Isrc/platform/cubecell
-D CUBECELL=1 -D CUBECELL
-D HW_VENDOR=CUBECELL -D HW_VENDOR=CUBECELL

View File

@ -1,48 +1,43 @@
#include <main.h> #include <main.h>
#include <assert.h>
typedef struct {
uint32_t to, from, id;
// The bottom three bits of flags are used to store hop_limit
uint8_t flags;
uint8_t channel;
} PacketHeader;
void setup() { void setup() {
UART_1_RxWakeDisableInt(); // no wake on UART activity msgID.clear();
memset(idList, 0, MAX_ID_LIST *4); txQueue.clear();
for (uint8_t i = 0; i<(MAX_TX_QUEUE - 1); i++) {
txQueue[i].size = 0;
}
#ifndef SILENT #ifndef SILENT
Serial.begin(115200); Serial.begin(115200);
#endif #endif
MSG("[INFO][CryptoEngine] Initializing ... "); MSG("[INF][CryptoEngine]Initializing ... ");
memcpy(psk.bytes, mypsk, sizeof(mypsk)); memcpy(psk.bytes, mypsk, sizeof(mypsk));
psk.length = sizeof(psk.bytes); psk.length = sizeof(psk.bytes);
crypto->setKey(psk); crypto->setKey(psk);
initRegion(); // create regions[] and load myRegion initRegion(); // create regions[] and load myRegion
applyModemConfig(); // apply lora settings applyModemConfig(); // apply lora settings
MSG("[INFO][SX1262] Starting to listen ... "); radio.setDio1Action(ISR_dio1Action);
MSG("[INF][SX1262]Starting to listen ...\n");
startReceive(); startReceive();
if (state == RADIOLIB_ERR_NONE) {
MSG("success!\n\n");
} else {
MSG("\n[ERROR][SX1262] startReceive() failed, code: %i\n\n ** Full Stop **", state);
while (true);
}
} }
void loop() { void loop() {
if (dio1) {
dio1 = false;
static uint16_t irqStatus = radio.getIrqStatus();
if (irqStatus & RADIOLIB_SX126X_IRQ_RX_DONE) {
PacketReceived = true;
}
if (irqStatus & RADIOLIB_SX126X_IRQ_TX_DONE) {
PacketSent = true;
}
}
if (PacketReceived) { if (PacketReceived) {
PacketReceived = false; PacketReceived = false;
const size_t length = radio.getPacketLength(); const size_t length = radio.getPacketLength();
state = radio.readData(radiobuf, length); state = radio.readData(radiobuf, length);
PacketHeader* h = (PacketHeader *)radiobuf; PacketHeader* h = (PacketHeader *)radiobuf;
//MSG("[RX]");
if (state == RADIOLIB_ERR_NONE) { if (state == RADIOLIB_ERR_NONE) {
const int32_t payloadLen = length - sizeof(PacketHeader); const int32_t payloadLen = length - sizeof(PacketHeader);
if (payloadLen < 0) { if (payloadLen < 0) {
@ -50,47 +45,17 @@ void loop() {
return; // will not repeat return; // will not repeat
} }
const uint8_t hop_limit = h->flags & PACKET_FLAGS_HOP_MASK; const uint8_t hop_limit = h->flags & PACKET_FLAGS_HOP_MASK;
/* // do not repeat if id is known or hop limit is zero
MSG(" (id=0x%08X) HopLim=%i from=0x%08X to=0x%08X WantAck=%s viaMQTT=%s", h->id, repeatPacket = msgID.add(h->id);
hop_limit, h->from, h->to, (h->flags & PACKET_FLAGS_WANT_ACK_MASK)? "YES":"NO", (h->flags & PACKET_FLAGS_VIA_MQTT_MASK)? "YES":"NO"); if (hop_limit == 0) repeatPacket = false;
MSG("\n[NEW](id=0x%08X) (HopLim %d) ", h->id, hop_limit);
MSGFLOAT(" SNR=",radio.getSNR() );
MSGFLOAT(" RSSI=", radio.getRSSI() );
*/
repeatPacket = update_idList(h->id);
if ( hop_limit == 0) repeatPacket = false; // do not repeat if id is known or hop limit is Zero
#ifndef SILENT // print packet:
const uint8_t *payload = radiobuf + sizeof(PacketHeader);
mp.from = h->from;
mp.to = h->to;
mp.id = h->id;
mp.channel = h->channel;
mp.hop_limit = h->flags & PACKET_FLAGS_HOP_MASK;
mp.want_ack = h->flags & PACKET_FLAGS_WANT_ACK_MASK;
mp.via_mqtt = h->flags & PACKET_FLAGS_VIA_MQTT_MASK;
mp.rx_snr = radio.getSNR();
mp.rx_rssi = lround(radio.getRSSI());
mp.which_payload_variant = meshtastic_MeshPacket_encrypted_tag; // Mark that the payload is still encrypted at this point
assert(((uint32_t)payloadLen) <= sizeof(mp.encrypted.bytes));
memcpy(mp.encrypted.bytes, payload, payloadLen);
mp.encrypted.size = payloadLen;
MSG("\n[NEW]");
if ( !repeatPacket ){ if ( !repeatPacket ){
MSG("(id=0x%08X) no repeat! (HopLim %d)\n", mp.id, mp.hop_limit); MSG("no repeat!\n");
} else {
perhapsDecode(&mp); // try to decode and print the result
} }
#endif //SILENT else {
h->flags -= 1; // decrease hop limit by 1
/* MSG(" repeat=%s\n", (repeatPacket)?"YES":"NO"); txQueue.add(radiobuf, length);
MSGFLOAT(" Freq Error=", radio.getFrequencyError());
MSG("\n");
*/
if ( repeatPacket ) {
h->flags -= 1; // decrease HopLim by 1
enqueueTX(radiobuf, length);
} }
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) { } else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
MSG(" [ERROR]CRC error!\n"); MSG(" [ERROR]CRC error!\n");
} else { } else {
@ -98,47 +63,68 @@ void loop() {
} }
} }
if (txQueueHasPacket) { // try to repeat packets while (txQueue.hasPackets) {
//const long wait = lround( abs( radio.getSNR() * radio.getRSSI() )); p = txQueue.pop();
long wait = 1000; // if we pop a Nullpointer (empty queue), hasPackets will be false now
radio.startChannelScan(3, 24, 10); if (txQueue.hasPackets) {
for (int i = 1; i < wait; i++) { TimerTime_t now = systime; //RtcGetTimerValue();
//try to decode the packet and print it
uint32_t wait = maxPacketTimeMsec + abs( radio.getRSSI() * radio.getSNR() ) + random(0, 3*slotTimeMsec);
MSG("[INF]wait %i ms before TX\n", wait);
while ( (now + wait) > systime ) {
// while waiting, we still are in receive mode
if (dio1) {
MSG("[INF]New packet, no TX\n");
return; // new packet arrived, return to handle it
}
delay(5);
}
// last check before actually sending the packet
radio.startChannelScan(); // RadioLib 6.5 overrides all user params
// CAD will activate dio1 at activity or timeout
MCU_deepsleep();
if (radio.getChannelScanResult() == RADIOLIB_LORA_DETECTED) { if (radio.getChannelScanResult() == RADIOLIB_LORA_DETECTED) {
clearInterrupts(); dio1 = false;
radio.setPacketReceivedAction(ISR_setReceived); startReceive();
radio.startReceive(20000); MSG("[INF]Lora activity, no TX\n");
return; // new packet arrived while waiting! return;
} }
delay(2); dio1 = false;
} if (perhapsSend(&p->buf[0], p->size) ) {
perhapsDecode(&p->buf[0], p->size);
uint8_t idx = poptxQueue(); PacketSent = true;
if (txQueue[idx].size == 0){ // mark packet as "deleted"
txQueueHasPacket = false; // empty Queue, do nothing p->size = 0;
//MSG("[INFO] TX Queue is empty\n"); } else {
} // Could not send, resume receiving
else { PacketSent = true;
perhapsSend(&txQueue[idx].buf[0], txQueue[idx].size);
txQueue[idx].size = 0;
} }
} }
if (PacketSent) { if (PacketSent) {
PacketSent = false; PacketSent = false;
radio.finishTransmit();
dio1 = false;
startReceive(); startReceive();
} }
}
#ifndef SILENT
// wait for serial output to conplete
delay(10);
#endif
delay(100); // wait for Serial
MCU_deepsleep(); MCU_deepsleep();
} }
void MCU_deepsleep(void) { void MCU_deepsleep(void) {
#ifdef CUBECELL #ifdef CUBECELL
#ifndef SILENT #ifndef SILENT
UART_1_Sleep; // aka USB, if you use UART2 for communication, add UART_2_Sleep / Wakeup UART_1_Sleep; // aka USB, if you use UART2 for communication, add UART_2_Sleep / Wakeup
#endif #endif
pinMode(P4_1, ANALOG); // SPI0 MISO, save power pinMode(P4_1, ANALOG); // SPI0 MISO, save power
CySysPmDeepSleep(); // deep sleep mode CySysPmDeepSleep();
// after sleep, set global time counter, set MISO to input, reactivate UART : // after sleep, set global time counter, set MISO to input, reactivate UART :
systime = (uint32_t)RtcGetTimerValue(); systime = (uint32_t)RtcGetTimerValue();
pinMode(P4_1, INPUT); pinMode(P4_1, INPUT);
@ -148,240 +134,144 @@ void MCU_deepsleep(void) {
#endif //CUBECELL #endif //CUBECELL
} }
void clearInterrupts(void) {
radio.clearDio1Action();
radio.finishTransmit();
}
void startReceive(){ void startReceive(){
clearInterrupts(); MSG("[RX]Start receiving ...\n");
radio.setPacketReceivedAction(ISR_setReceived); while (RADIOLIB_ERR_NONE != radio.startReceive(RADIOLIB_SX126X_RX_TIMEOUT_INF, RADIOLIB_SX126X_IRQ_RX_DEFAULT , RADIOLIB_SX126X_IRQ_RX_DONE, 0) )
state=radio.startReceive(); {
MSG("\n[ERROR][SX1262] startReceive() failed, code: %i\n", state);
delay(1000);
}
} }
bool update_idList(uint32_t id){ bool perhapsSend(uint8_t* buf, size_t size) {
for (uint8_t i=0; i < (MAX_ID_LIST - 1); i++) {
//MSG("\nstored: 0x%08X delivered: 0x%08X",idQueue[i-1], id);
if (idList[i] == id){
return false; // packet ID is known, no Queue update
}
}
// store new ID:
uint8_t idx = MAX_ID_LIST;
for (uint8_t i=0; i < (MAX_ID_LIST -1); i++){
if (idList[i] == 0) {
idx = i;
break;
}
}
if (idx == MAX_ID_LIST) {
idList[0] = id;
idList[1] = 0;
}
else {
idList[idx] = id;
if (++idx < MAX_ID_LIST) { idList[idx] = 0; }
else { idList[0] = 0; }
}
return true; // packet ID was not known, Queue was updated
}
void enqueueTX(uint8_t* buf, size_t size){
PacketHeader* h = (PacketHeader *)buf; PacketHeader* h = (PacketHeader *)buf;
uint8_t idx = MAX_TX_QUEUE; MSG("\n[TX](id=0x%08X) HopLim=%i ", h->id, (h->flags & PACKET_FLAGS_HOP_MASK));
for (uint8_t i=0; i<(MAX_TX_QUEUE -1); i++) {
if (txQueue[i].size == 0) { // search for a free slot
idx = i;
break;
}
}
if (idx == MAX_TX_QUEUE) { // no free slot, overwrite oldest packet
idx = 0;
for (uint8_t i=1; i<(MAX_TX_QUEUE -1); i++) {
if (txQueue[idx].packetTime < txQueue[i].packetTime) idx = i;
}
}
txQueue[idx].size = size;
MSG("[INF](id=0x%08X) enQueue Index=%i size=%i", h->id, idx, size);
txQueue[idx].packetTime = (uint32_t)RtcGetTimerValue();
MSG(" Time=%i\n",txQueue[idx].packetTime); //MSG("\n");
memcpy(&txQueue[idx].buf[0], buf, size);
//MSG(" Copy done!\n");
txQueueHasPacket = true;
}
uint8_t poptxQueue(void) {
uint8_t idx = MAX_TX_QUEUE;
for (uint8_t i=0 ;i < (MAX_TX_QUEUE -1); i++ ){
if (txQueue[i].size != 0) {
idx = i;
break;
}
}
if (idx == MAX_TX_QUEUE) { // empty Queue
return 0;
}
for (uint8_t i=idx; i<(MAX_TX_QUEUE -1); i++) {
if ( (txQueue[i].size != 0) && (txQueue[idx].packetTime < txQueue[i].packetTime) ) idx = i; // find oldest packet
}
//MSG("[INFO]POP index=%i\n", idx);
return idx;
}
void perhapsSend(uint8_t* buf, size_t size) {
PacketHeader* h = (PacketHeader *)buf;
//clearInterrupts();
//while ( radio.scanChannel() == RADIOLIB_LORA_DETECTED ) delay( (uint32_t)lround( abs(radio.getSNR() + radio.getRSSI() ) ) );
MSG("[TX] (id=0x%08X) HopLim=%i ... ", h->id, (h->flags & PACKET_FLAGS_HOP_MASK));
clearInterrupts();
radio.setPacketSentAction(ISR_setPacketSent);
state=radio.startTransmit(buf, size); state=radio.startTransmit(buf, size);
if (state == RADIOLIB_ERR_NONE) { if (state == RADIOLIB_ERR_NONE) {
MSG("OK\n"); MSG("starting ... ");
} }
else { else {
MSG("failed, ERR = %i - resume RX", state); MSG("failed, ERR = %i - resume RX\n", state);
PacketSent=true; // do not halt on error return false;
} }
delay(10);
MCU_deepsleep(); // wait for TX to complete, will wake on any DIO1
state = radio.getIrqStatus();
(state & RADIOLIB_SX126X_IRQ_TX_DONE) ? MSG("done!\n") : MSG("failed. Returned IRQ=%i\n", state);
dio1 = false;
return ( state & RADIOLIB_SX126X_IRQ_TX_DONE );
} }
static uint8_t bytes[MAX_RHPACKETLEN]; bool perhapsDecode(uint8_t* buf, size_t size) {
// modified code, (c) Meshtastic https://github.com/meshtastic/firmware
bool perhapsDecode(meshtastic_MeshPacket *p) PacketHeader* h = (PacketHeader *)buf;
{ const int32_t len = size - sizeof(PacketHeader);
/* concurrency::LockGuard g(cryptLock); const uint8_t *payload = radiobuf + sizeof(PacketHeader);
mp.from = h->from;
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER && mp.to = h->to;
config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING) mp.id = h->id;
return false; mp.channel = h->channel;
mp.hop_limit = h->flags & PACKET_FLAGS_HOP_MASK;
if (config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY && mp.hop_limit += 1;
!nodeDB.getMeshNode(p->from)->has_user) { mp.want_ack = h->flags & PACKET_FLAGS_WANT_ACK_MASK;
LOG_DEBUG("Node 0x%x not in NodeDB. Rebroadcast mode KNOWN_ONLY will ignore packet\n", p->from); mp.via_mqtt = h->flags & PACKET_FLAGS_VIA_MQTT_MASK;
return false; mp.rx_snr = radio.getSNR();
} mp.rx_rssi = lround(radio.getRSSI());
*/ mp.which_payload_variant = meshtastic_MeshPacket_encrypted_tag;
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) mp.encrypted.size = 0;
return true; // If packet was already decoded just return static uint8_t scratchbuf[MAX_RHPACKETLEN];
assert(len <= sizeof(scratchbuf));
// assert(p->which_payloadVariant == MeshPacket_encrypted_tag); // we have to copy into a scratch buffer, because mp.encrypted is a union with the decoded protobuf
memcpy(scratchbuf, buf + sizeof(PacketHeader), len);
// Try to find a channel that works with this hash crypto->decrypt(mp.from, mp.id, len, scratchbuf);
/* for (ChannelIndex chIndex = 0; chIndex < channels.getNumChannels(); chIndex++) { memset(&mp.decoded, 0, sizeof(mp.decoded));
// Try to use this hash/channel pair if (!pb_decode_from_bytes((const uint8_t*)scratchbuf, len, &meshtastic_Data_msg, &mp.decoded)) {
if (channels.decryptForHash(chIndex, p->channel)) { */
// Try to decrypt the packet if we can
size_t rawSize = p->encrypted.size;
assert(rawSize <= sizeof(bytes));
memcpy(bytes, p->encrypted.bytes,
rawSize); // we have to copy into a scratch buffer, because these bytes are a union with the decoded protobuf
crypto->decrypt(p->from, p->id, rawSize, bytes);
// printBytes("plaintext", bytes, p->encrypted.size);
// Take those raw bytes and convert them back into a well structured protobuf we can understand
memset(&p->decoded, 0, sizeof(p->decoded));
if (!pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &p->decoded)) {
MSG("[ERROR]Invalid protobufs in received mesh packet (bad psk?)!\n"); MSG("[ERROR]Invalid protobufs in received mesh packet (bad psk?)!\n");
} else if (p->decoded.portnum == meshtastic_PortNum_UNKNOWN_APP) { } else if (mp.decoded.portnum == meshtastic_PortNum_UNKNOWN_APP) {
MSG("[ERROR]Invalid portnum (bad psk?)!\n"); MSG("[ERROR]Invalid portnum (bad psk?)!\n");
} else { } else {
// parsing was successful mp.which_payload_variant = meshtastic_MeshPacket_decoded_tag;
p->which_payload_variant = meshtastic_MeshPacket_decoded_tag; // change type to decoded mp.channel = generateHash(0);
p->channel = generateHash(0); // change to store the index instead of the hash /*
if (mp.decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_COMPRESSED_APP) {
// Decompress if needed. jm
if (p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_COMPRESSED_APP) {
// Decompress the payload
char compressed_in[meshtastic_Constants_DATA_PAYLOAD_LEN] = {}; char compressed_in[meshtastic_Constants_DATA_PAYLOAD_LEN] = {};
char decompressed_out[meshtastic_Constants_DATA_PAYLOAD_LEN] = {}; char decompressed_out[meshtastic_Constants_DATA_PAYLOAD_LEN] = {};
int decompressed_len; int decompressed_len;
memcpy(compressed_in, mp.decoded.payload.bytes, mp.decoded.payload.size);
memcpy(compressed_in, p->decoded.payload.bytes, p->decoded.payload.size); decompressed_len = unishox2_decompress_simple(compressed_in, mp.decoded.payload.size, decompressed_out);
memcpy(mp.decoded.payload.bytes, decompressed_out, decompressed_len);
decompressed_len = unishox2_decompress_simple(compressed_in, p->decoded.payload.size, decompressed_out); mp.decoded.portnum = meshtastic_PortNum_TEXT_MESSAGE_APP;
// LOG_DEBUG("\n\n**\n\nDecompressed length - %d \n", decompressed_len);
memcpy(p->decoded.payload.bytes, decompressed_out, decompressed_len);
// Switch the port from PortNum_TEXT_MESSAGE_COMPRESSED_APP to PortNum_TEXT_MESSAGE_APP
p->decoded.portnum = meshtastic_PortNum_TEXT_MESSAGE_APP;
} }
*/
printPacket("", p); printPacket();
return true; return true;
} }
//} MSG("[ERROR]No suitable channel found for decoding, hash was 0x%x!\n", mp.channel);
//}
MSG("[ERROR]No suitable channel found for decoding, hash was 0x%x!\n", p->channel);
return false; return false;
} }
void printPacket(const char *prefix, const meshtastic_MeshPacket *p) { void printPacket(void) {
MSG("[INF](id=0x%08X) from=0x%.2X to=0x%.2X, WantAck=%s, HopLim=%d Ch=0x%X",
MSG("%s(id=0x%08X fr=0x%.2X to=0x%.2X, WantAck=%s, HopLim=%d Ch=0x%X", prefix, p->id, mp.id, mp.from, mp.to, (mp.want_ack)? "YES":"NO", mp.hop_limit, mp.channel);
p->from, p->to, (p->want_ack)? "YES":"NO", p->hop_limit, p->channel); if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { auto &s = mp.decoded;
auto &s = p->decoded;
MSG(" Portnum=%d", s.portnum); MSG(" Portnum=%d", s.portnum);
if (s.want_response) if (s.want_response) MSG(" WANTRESP");
MSG(" WANTRESP"); if (s.source != 0) MSG(" source=%08x", s.source);
if (s.source != 0) if (s.dest != 0) MSG(" dest=%08x", s.dest);
MSG(" source=%08x", s.source); if (s.request_id) MSG(" requestId=%0x", s.request_id);
if (s.dest != 0) if (mp.rx_time != 0) MSG(" rxtime=%u", mp.rx_time);
MSG(" dest=%08x", s.dest); if (mp.rx_snr != 0.0) MSGFLOAT(" rxSNR=", mp.rx_snr);
if (s.request_id) if (mp.rx_rssi != 0) MSG(" rxRSSI=%i", mp.rx_rssi);
MSG(" requestId=%0x", s.request_id); if (mp.via_mqtt != 0) MSG(" via MQTT");
if (p->rx_time != 0) if (mp.priority != 0) MSG(" priority=%d", mp.priority);
MSG(" rxtime=%u", p->rx_time); MSG("\nPayload: ");
if (p->rx_snr != 0.0) printVariants();
MSGFLOAT(" rxSNR=", p->rx_snr);
if (p->rx_rssi != 0)
MSG(" rxRSSI=%i", p->rx_rssi);
if (p->via_mqtt != 0)
MSG(" via MQTT");
if (p->priority != 0)
MSG(" priority=%d", p->priority);
MSG("\nPayload: "); printVariants(p);
} else { } else {
MSG(" encrypted!\n"); MSG(" encrypted!\n");
} }
//MSG("\n");
} }
void printVariants(const meshtastic_MeshPacket *p){ void printVariants(void){
// Make sure we have a decoded packet // Make sure we have a decoded packet
if (p->which_payload_variant != meshtastic_MeshPacket_decoded_tag) if (mp.which_payload_variant != meshtastic_MeshPacket_decoded_tag)
return; return;
auto &d = mp.decoded;
auto &mp = p->decoded;
// TEXT MESSAGE // TEXT MESSAGE
// /modules/TextMessageModule.cpp // /modules/TextMessageModule.cpp
if (mp.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP){ if (d.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP){
MSG("\"%.*s\"\n", mp.payload.size, mp.payload.bytes); MSG("TEXT ");
MSG("\"%.*s\"\n", d.payload.size, d.payload.bytes);
return;
}
// HARDWARE MESSAGE
// /modules/RemoteHardwareModule.cpp
if (d.portnum == meshtastic_PortNum_REMOTE_HARDWARE_APP){
MSG("GPIO ");
meshtastic_NodeRemoteHardwarePin pin;
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_NodeRemoteHardwarePin_msg, &pin)) {
MSG("*** Error ***\n");
return;
}
return; return;
} }
// POSITION MESSAGE // POSITION MESSAGE
// /modules/PositionModule.cpp // /modules/PositionModule.cpp
if (mp.portnum == meshtastic_PortNum_POSITION_APP){ if (d.portnum == meshtastic_PortNum_POSITION_APP){
MSG("Position "); MSG("POSITION ");
meshtastic_Position pos; meshtastic_Position pos;
if (!pb_decode_from_bytes(mp.payload.bytes, mp.payload.size, &meshtastic_Position_msg, &pos)) { if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_Position_msg, &pos)) {
MSG("*** Error ***\n"); MSG("*** Error ***\n");
return; return;
} }
// Log packet size and data fields // Log packet size and data fields
MSG("node=%08x l=%d latI=%d lonI=%d msl=%d hae=%d geo=%d pdop=%d hdop=%d vdop=%d siv=%d fxq=%d fxt=%d pts=%d " MSG("Node=%08X l=%d latI=%d lonI=%d msl=%d hae=%d geo=%d pdop=%d hdop=%d vdop=%d siv=%d fxq=%d fxt=%d pts=%d "
"time=%d\n", "time=%d\n",
p->from, mp.payload.size, pos.latitude_i, pos.longitude_i, pos.altitude, pos.altitude_hae, mp.from, d.payload.size, pos.latitude_i, pos.longitude_i, pos.altitude, pos.altitude_hae,
pos.altitude_geoidal_separation, pos.PDOP, pos.HDOP, pos.VDOP, pos.sats_in_view, pos.fix_quality, pos.fix_type, pos.timestamp, pos.altitude_geoidal_separation, pos.PDOP, pos.HDOP, pos.VDOP, pos.sats_in_view, pos.fix_quality, pos.fix_type, pos.timestamp,
pos.time); pos.time);
return; return;
@ -389,10 +279,10 @@ void printVariants(const meshtastic_MeshPacket *p){
// NODEINFO MESSAGE // NODEINFO MESSAGE
// /modules/NodeInfoModule.cpp // /modules/NodeInfoModule.cpp
if (mp.portnum == meshtastic_PortNum_NODEINFO_APP){ if (d.portnum == meshtastic_PortNum_NODEINFO_APP){
MSG("Node Info: "); MSG("NODE INFO ");
meshtastic_User user; meshtastic_User user;
if (!pb_decode_from_bytes(mp.payload.bytes, mp.payload.size, &meshtastic_User_msg, &user)) { if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_User_msg, &user)) {
MSG("*** Error ***\n"); MSG("*** Error ***\n");
return; return;
} }
@ -405,14 +295,37 @@ void printVariants(const meshtastic_MeshPacket *p){
return; return;
} }
// ROUTING MESSAGE
// /modules/RoutingModule.cpp
if (d.portnum == meshtastic_PortNum_ROUTING_APP){
MSG("ROUTING \n");
/*
meshtastic_Routing r;
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_Routing_msg, &r)) {
MSG("*** Error ***\n");
return;
}
if (r.which_variant == sizeof(meshtastic_Routing_Error) ) {
MSG("RoutingError=%i\n", r.error_reason);
} else {
MSG("RouteRequest [");
for (uint8_t i=0; i < r.route_request.route_count; i++) MSG("0x%X ", r.route_request.route[i]);
MSG("] ");
MSG("RouteReply [");
for (uint8_t i=0; i < r.route_reply.route_count; i++) MSG("0x%X ", r.route_reply.route[i]);
MSG("]\n");
}
*/
return;
}
// TELEMETRY // TELEMETRY MESSAGE
if (mp.portnum == meshtastic_PortNum_TELEMETRY_APP){ if (d.portnum == meshtastic_PortNum_TELEMETRY_APP){
MSG("Telemetry "); MSG("TELEMETRY");
meshtastic_Telemetry telemetry; meshtastic_Telemetry telemetry;
meshtastic_Telemetry *t = &telemetry; meshtastic_Telemetry *t = &telemetry;
if (!pb_decode_from_bytes(mp.payload.bytes, mp.payload.size, &meshtastic_Telemetry_msg, &telemetry)) { if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_Telemetry_msg, &telemetry)) {
MSG("*** Error ***\n"); MSG("*** Error ***\n");
return; return;
} }
@ -444,9 +357,9 @@ void printVariants(const meshtastic_MeshPacket *p){
MSGFLOAT("barometric_pressure=", t->variant.environment_metrics.barometric_pressure); MSGFLOAT("barometric_pressure=", t->variant.environment_metrics.barometric_pressure);
MSGFLOAT(", current=", t->variant.environment_metrics.current); MSGFLOAT(", current=", t->variant.environment_metrics.current);
MSGFLOAT(", gas_resistance=",t->variant.environment_metrics.gas_resistance); MSGFLOAT(", gas_resistance=",t->variant.environment_metrics.gas_resistance);
MSGFLOAT(", relative_humidity=",t->variant.environment_metrics.relative_humidity); MSGFLOAT(", rel_humidity=",t->variant.environment_metrics.relative_humidity);
MSGFLOAT(", temperature=", t->variant.environment_metrics.temperature); MSGFLOAT(", temp=", t->variant.environment_metrics.temperature);
MSGFLOAT(", voltage=", t->variant.environment_metrics.voltage); MSGFLOAT(", volt=", t->variant.environment_metrics.voltage);
MSG("\n"); MSG("\n");
return; return;
} }
@ -463,11 +376,123 @@ void printVariants(const meshtastic_MeshPacket *p){
} }
} }
// TRACEROUTE MESSAGE
// /modules/TraceRouteModule.cpp
if (d.portnum == meshtastic_PortNum_TRACEROUTE_APP){
MSG("TRACEROUTE");
meshtastic_RouteDiscovery route;
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_RouteDiscovery_msg, &route)) {
MSG("*** Error ***\n");
return;
}
MSG("(seen by %i Nodes", route.route_count);
if (route.route_count > 0) {
for (uint8_t i=0; i < route.route_count; i++) {
MSG(" %08X", route.route[i]);
}
}
MSG(")\n");
return;
}
// NEIGHBORINFO MESSAGE
// /modules/NeighborInfoModule.cpp
if (d.portnum == meshtastic_PortNum_NEIGHBORINFO_APP){
MSG("NEIGHBORINFO ");
meshtastic_NeighborInfo np;
if (!pb_decode_from_bytes(d.payload.bytes, d.payload.size, &meshtastic_NeighborInfo_msg, &np)) {
MSG("*** Error ***\n");
return;
}
MSG("(last sent by 0x%x) Number of neighbors=%d\n", np.last_sent_by_id, np.neighbors_count);
for (uint8_t i = 0; i < np.neighbors_count; i++) {
MSG("[0x%X, ", np.neighbors[i].node_id);
MSGFLOAT("snr=%.2f]\n", np.neighbors[i].snr);
}
return;
}
// ATAK PLUGIN MESSAGE
// /modules/AtakPluginModule.cpp
if (d.portnum == meshtastic_PortNum_ATAK_PLUGIN){
MSG("ATAK \n");
return;
}
// No known PortNum: // No known PortNum:
MSG("\""); MSG("\"");
for (uint32_t i=0; i < mp.payload.size; i++){ for (uint32_t i=0; i < d.payload.size; i++){
MSG("%X", mp.payload.bytes[i]); MSG("%X", d.payload.bytes[i]);
} }
MSG("\"\n"); MSG("\"\n");
return; return;
} }
// PacketQueueClass Definitions
void PacketQueueClass::add(uint8_t* buf, size_t size) {
uint8_t idx = MAX_TX_QUEUE;
for (uint8_t i=0; i<(MAX_TX_QUEUE -1); i++) {
if (Queue[i].size == 0) { // search for a free slot
idx = i;
break;
}
}
if (idx == MAX_TX_QUEUE) { // no free slot, overwrite oldest packet
for (uint8_t i=1; i<(MAX_TX_QUEUE -1); i++) {
if (Queue[idx].packetTime < Queue[i].packetTime) idx = i;
}
}
Queue[idx].size = size;
Queue[idx].packetTime = (uint32_t)RtcGetTimerValue();
MSG("enQueue Index=%i Size=%i\n", idx, Queue[idx].size);
memcpy(Queue[idx].buf, buf, size);
hasPackets = true;
}
Packet_t* PacketQueueClass::pop(void) {
uint8_t idx = MAX_TX_QUEUE;
for (uint8_t i=0 ;i < (MAX_TX_QUEUE -1); i++ ){
if (Queue[i].size != 0) { // first not empty entry
idx = i;
break;
}
}
if (idx == MAX_TX_QUEUE) { // empty Queue
hasPackets = false;
return (Packet_t*)NULL;
}
for (uint8_t i=idx; i<(MAX_TX_QUEUE -1); i++) {
if ( (Queue[i].size != 0) && (Queue[idx].packetTime < Queue[i].packetTime) ) idx = i; // find oldest packet
}
return &Queue[idx];
}
void PacketQueueClass::clear(void) {
for (uint8_t i = 0; i<(MAX_TX_QUEUE - 1); i++) {
Queue[i].size = 0; // mark as "deleted"
}
}
// idStoreClass Definitions
bool idStoreClass::add(uint32_t id) {
uint8_t idx = 0;
for (uint8_t i = MAX_ID_LIST; i > 0; i--) {
if (storage[i] == id){
return false; // packet ID is known, no update
}
if (storage[i] == 0) idx = i;
}
storage[idx] = id;
if (++idx <= MAX_ID_LIST) {
storage[idx] = 0;
} else {
storage[0] = 0;
}
return true; // new packet ID was added
}
void idStoreClass::clear(void) {
memset(this->storage, 0, sizeof(this->storage));
}

View File

@ -10,28 +10,48 @@
#define CC_MY_LORA_BW 125.0 // use these settings, if not using a modem preset #define CC_MY_LORA_BW 125.0 // use these settings, if not using a modem preset
#define CC_MY_LORA_SF 10 #define CC_MY_LORA_SF 10
#define CC_MY_LORA_CR 5 #define CC_MY_LORA_CR 5
#define CC_MY_LORA_POWER 0 // 0 = max legal power for region #define CC_MY_LORA_POWER 20 // 0 = max legal power for region
#define CC_MY_LORA_FREQ 0.0 // if you want to override frequency calculation, in MHz (e.g. 869.4) #define CC_MY_LORA_FREQ 0.0 // if you want to override frequency calculation: Freq in MHz (e.g. 869.4)
#define CC_MAX_POWER 22 // TX power setting. Maximum for CubeCell is 22, enforced by RadioLib. #define CC_MAX_POWER 22 // TX power setting. Absolute Max for CubeCell is 22, enforced by RadioLib.
#define MAX_ID_LIST 32 // number of stored packet IDs to prevent unnecesary repeating #define MAX_ID_LIST 64 // number of stored packet IDs to prevent unnecesary repeating
#define MAX_TX_QUEUE 16 // max number of packets which can be waiting for transmission #define MAX_TX_QUEUE 24 // max number of packets which can be waiting for transmission
#define MAX_RHPACKETLEN 256 #define MAX_RHPACKETLEN 256
#include <RadioLib.h>
#ifdef CUBECELL
#include "cyPm.c" // for reliable sleep we use MCU_deepSleep()
extern uint32_t systime; // CubeCell global system time count, Millis
SX1262 radio = new Module(RADIOLIB_BUILTIN_MODULE);
#endif //CUBECELL
/// 16 bytes of random PSK for our _public_ default channel that all devices power up on (AES128) /// 16 bytes of random PSK for our _public_ default channel that all devices power up on (AES128)
/// Meshtastic default key (AQ==): /// Meshtastic default key (AQ==):
static const uint8_t mypsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, static const uint8_t mypsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01}; 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01};
// No Crypto = all zero // No Crypto = all zero
#ifndef SILENT
#define MSG(...) Serial.printf(__VA_ARGS__)
#define MSGFLOAT(a,b) Serial.print(a); Serial.print(b)
#else
#define MSG(...)
#define MSGFLOAT(a,b)
#endif
// Heltec borked the Arduino.h
#ifdef __cplusplus
#undef min
#undef max
#undef abs
#include <algorithm>
using std::abs;
using std::max;
using std::min;
#endif /* __cplusplus */
#include <RadioLib.h>
#ifdef CUBECELL
#include "cyPm.c" // for reliable sleep we use MCU_deepSleep()
extern uint32_t systime; // CubeCell global system time count, Millis
SX1262 radio = new Module(RADIOLIB_BUILTIN_MODULE);
#endif
#include <assert.h> #include <assert.h>
#include <pb.h> #include <pb.h>
#include <MeshTypes.h> #include <MeshTypes.h>
@ -44,62 +64,82 @@ extern "C"
#include <mesh/compression/unishox2.h> #include <mesh/compression/unishox2.h>
} }
CryptoKey psk;
meshtastic_MeshPacket mp;
uint8_t radiobuf[MAX_RHPACKETLEN -1];
typedef struct { typedef struct {
size_t size; size_t size;
uint8_t buf[MAX_RHPACKETLEN -1]; uint8_t buf[MAX_RHPACKETLEN -1];
uint32_t packetTime; uint32_t packetTime;
} Packet_t; } Packet_t;
Packet_t txQueue[MAX_TX_QUEUE - 1]; typedef struct {
uint32_t idList[MAX_ID_LIST - 1]; uint32_t to, from;
uint32_t id;
uint8_t flags;
uint8_t channel;
uint8_t next_hop;
uint8_t relay_node;
} PacketHeader; // see Meshtastic RadioInterface.h
class PacketQueueClass {
private:
Packet_t Queue[MAX_TX_QUEUE - 1];
public:
void clear(void);
bool hasPackets = false;
void add(uint8_t* buf, size_t size);
Packet_t* pop(void);
};
PacketQueueClass txQueue;
class idStoreClass {
private:
uint32_t storage[MAX_ID_LIST];
public:
void clear(void);
// add() returns false if the message id is already known
bool add(uint32_t id);
};
idStoreClass msgID;
CryptoKey psk;
meshtastic_MeshPacket mp;
uint8_t radiobuf[MAX_RHPACKETLEN];
bool repeatPacket = false; bool repeatPacket = false;
bool txQueueHasPacket = false;
int state = RADIOLIB_ERR_NONE; int state = RADIOLIB_ERR_NONE;
Packet_t* p = NULL;
void MCU_deepsleep(void); void MCU_deepsleep(void);
void clearInterrupts(void);
void startReceive(void); void startReceive(void);
bool update_idList(uint32_t id); bool perhapsSend(uint8_t* buf, size_t size);
void enqueueTX(uint8_t* buf, size_t size); bool perhapsDecode(uint8_t* buf, size_t size);
uint8_t poptxQueue(void); void printPacket(void);
void perhapsSend(uint8_t* buf, size_t size); void printVariants(void);
void printVariants(const meshtastic_MeshPacket *p); bool PacketReceived = false;
void printPacket(const char *prefix, const meshtastic_MeshPacket *p); bool PacketSent = false;
bool perhapsDecode(meshtastic_MeshPacket *p); volatile bool dio1 = false;
// Flag and ISR for "Received packet" - events void ISR_dio1Action(void) {
volatile bool PacketReceived = false; dio1 = true;
void ISR_setReceived(void) {
PacketReceived = true;
} }
// Flag and ISR for "Packet sent" - events
volatile bool PacketSent = false;
void ISR_setPacketSent(void) {
PacketSent = true;
}
#ifndef SILENT
#define MSG(...) Serial.printf(__VA_ARGS__)
#define MSGFLOAT(a,b) Serial.print(a); Serial.print(b)
#else
#define MSG(...)
#define MSGFLOAT(a,b)
#endif
/************** /**************
* Meshtastic * * Meshtastic * https://github.com/meshtastic/firmware
**************/ **************/
/** Slottime is the minimum time to wait, consisting of:
- CAD duration (maximum of SX126x and SX127x);
- roundtrip air propagation time (assuming max. 30km between nodes);
- Tx/Rx turnaround time (maximum of SX126x and SX127x);
- MAC processing time (measured on T-beam) */
uint32_t slotTimeMsec; //= 8.5 * pow(2, sf) / bw + 0.2 + 0.4 + 7; --> calculated at applyModemConfig()
uint16_t preambleLength = 16; // 8 is default, but we use longer to increase the amount of sleep time when receiving
uint32_t preambleTimeMsec = 165; // calculated on startup, this is the default for LongFast
uint32_t maxPacketTimeMsec = 3246; // calculated on startup, this is the default for LongFast
const uint32_t PROCESSING_TIME_MSEC =
4500; // time to construct, process and construct a packet again (empirically determined)
const uint8_t CWmin = 2; // minimum CWsize
const uint8_t CWmax = 8; // maximum CWsize
#define PACKET_FLAGS_HOP_MASK 0x07 #define PACKET_FLAGS_HOP_MASK 0x07
#define PACKET_FLAGS_WANT_ACK_MASK 0x08 #define PACKET_FLAGS_WANT_ACK_MASK 0x08
#define PACKET_FLAGS_VIA_MQTT_MASK 0x10 #define PACKET_FLAGS_VIA_MQTT_MASK 0x10
@ -111,8 +151,7 @@ size_t pb_encode_to_bytes(uint8_t *destbuf, size_t destbufsize, const pb_msgdesc
pb_ostream_t stream = pb_ostream_from_buffer(destbuf, destbufsize); pb_ostream_t stream = pb_ostream_from_buffer(destbuf, destbufsize);
if (!pb_encode(&stream, fields, src_struct)) { if (!pb_encode(&stream, fields, src_struct)) {
MSG("[ERROR]Panic: can't encode protobuf reason='%s'\n", PB_GET_ERROR(&stream)); MSG("[ERROR]Panic: can't encode protobuf reason='%s'\n", PB_GET_ERROR(&stream));
assert( //assert(0); // If this assert fails it probably means you made a field too large for the max limits specified in mesh.options
0); // If this assert fails it probably means you made a field too large for the max limits specified in mesh.options
} else { } else {
return stream.bytes_written; return stream.bytes_written;
} }
@ -148,7 +187,9 @@ struct RegionInfo {
bool wideLora; bool wideLora;
const char *name; // EU433 etc const char *name; // EU433 etc
}; };
const RegionInfo *myRegion; const RegionInfo *myRegion;
const RegionInfo regions[] = { const RegionInfo regions[] = {
/* /*
https://link.springer.com/content/pdf/bbm%3A978-1-4842-4357-2%2F1.pdf https://link.springer.com/content/pdf/bbm%3A978-1-4842-4357-2%2F1.pdf
@ -269,10 +310,11 @@ const RegionInfo regions[] = {
void initRegion() void initRegion()
{ {
MSG("[INF]Init region List ...");
const RegionInfo *r = regions; const RegionInfo *r = regions;
for (; r->code != meshtastic_Config_LoRaConfig_RegionCode_UNSET && r->code != CC_MY_REGION; r++) for (; r->code != meshtastic_Config_LoRaConfig_RegionCode_UNSET && r->code != CC_MY_REGION; r++) ;
;
myRegion = r; myRegion = r;
MSG(" done!\n");
} }
/** hash a string into an integer /** hash a string into an integer
@ -330,10 +372,10 @@ int16_t generateHash(ChannelIndex channelNum)
void applyModemConfig() void applyModemConfig()
{ {
float bw=0; float bw = 0;
uint8_t sf = 0; uint8_t sf = 0;
uint8_t cr = 0; uint8_t cr = 0;
int8_t power = 0; // 0 = max legal power for region int8_t power = CC_MY_LORA_POWER; // 0 = max legal power for region
float freq = 0; float freq = 0;
if (CC_LORA_USE_PRESET) { if (CC_LORA_USE_PRESET) {
@ -426,13 +468,12 @@ void applyModemConfig()
channel_num = -1; channel_num = -1;
} }
MSG("\nRegion %s (Power Limit is %idb) ",myRegion->name, myRegion->powerLimit); MSG("[INF]Using Region %s freq %d bw %i sf %i cr %i power %i ... ",myRegion->name, lround(freq*1E6), lround(bw*1000), sf, cr, power);
MSG(" freq %d bw %i sf %i cr %i power %i ... ", lround(freq*1E6), lround(bw*1000), sf, cr, power);
// Syncword is 0x2b, see RadioLibInterface.h // Syncword is 0x2b, see RadioLibInterface.h
// preamble length is 16, see RadioInterface.h // preamble length is 16, see RadioInterface.h
int state = radio.begin(freq, bw, sf, cr, 0x2b, power, 16); state = radio.begin(freq, bw, sf, cr, 0x2b, power, 16);
if (state == RADIOLIB_ERR_NONE) { if (state == RADIOLIB_ERR_NONE) {
MSG("success!\n"); MSG("success!\n");
@ -441,4 +482,6 @@ void applyModemConfig()
while (true); while (true);
} }
// used to calculate wait time before repeating a packet
slotTimeMsec = 8.5 * pow(2, sf) / bw + 0.2 + 0.4 + 7;
} }

View File

@ -55,7 +55,7 @@ extern const pb_msgdesc_t meshtastic_ChannelSet_msg;
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_APPONLY_PB_H_MAX_SIZE meshtastic_ChannelSet_size #define MESHTASTIC_MESHTASTIC_APPONLY_PB_H_MAX_SIZE meshtastic_ChannelSet_size
#define meshtastic_ChannelSet_size 658 #define meshtastic_ChannelSet_size 674
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -34,6 +34,9 @@ typedef enum _meshtastic_Channel_Role {
typedef struct _meshtastic_ModuleSettings { typedef struct _meshtastic_ModuleSettings {
/* Bits of precision for the location sent in position packets. */ /* Bits of precision for the location sent in position packets. */
uint32_t position_precision; uint32_t position_precision;
/* Controls whether or not the phone / clients should mute the current channel
Useful for noisy public channels you don't necessarily want to disable */
bool is_client_muted;
} meshtastic_ModuleSettings; } meshtastic_ModuleSettings;
typedef PB_BYTES_ARRAY_T(32) meshtastic_ChannelSettings_psk_t; typedef PB_BYTES_ARRAY_T(32) meshtastic_ChannelSettings_psk_t;
@ -126,14 +129,15 @@ extern "C" {
/* Initializer values for message structs */ /* Initializer values for message structs */
#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_default} #define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_default}
#define meshtastic_ModuleSettings_init_default {0} #define meshtastic_ModuleSettings_init_default {0, 0}
#define meshtastic_Channel_init_default {0, false, meshtastic_ChannelSettings_init_default, _meshtastic_Channel_Role_MIN} #define meshtastic_Channel_init_default {0, false, meshtastic_ChannelSettings_init_default, _meshtastic_Channel_Role_MIN}
#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_zero} #define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_zero}
#define meshtastic_ModuleSettings_init_zero {0} #define meshtastic_ModuleSettings_init_zero {0, 0}
#define meshtastic_Channel_init_zero {0, false, meshtastic_ChannelSettings_init_zero, _meshtastic_Channel_Role_MIN} #define meshtastic_Channel_init_zero {0, false, meshtastic_ChannelSettings_init_zero, _meshtastic_Channel_Role_MIN}
/* Field tags (for use in manual encoding/decoding) */ /* Field tags (for use in manual encoding/decoding) */
#define meshtastic_ModuleSettings_position_precision_tag 1 #define meshtastic_ModuleSettings_position_precision_tag 1
#define meshtastic_ModuleSettings_is_client_muted_tag 2
#define meshtastic_ChannelSettings_channel_num_tag 1 #define meshtastic_ChannelSettings_channel_num_tag 1
#define meshtastic_ChannelSettings_psk_tag 2 #define meshtastic_ChannelSettings_psk_tag 2
#define meshtastic_ChannelSettings_name_tag 3 #define meshtastic_ChannelSettings_name_tag 3
@ -159,7 +163,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, module_settings, 7)
#define meshtastic_ChannelSettings_module_settings_MSGTYPE meshtastic_ModuleSettings #define meshtastic_ChannelSettings_module_settings_MSGTYPE meshtastic_ModuleSettings
#define meshtastic_ModuleSettings_FIELDLIST(X, a) \ #define meshtastic_ModuleSettings_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, position_precision, 1) X(a, STATIC, SINGULAR, UINT32, position_precision, 1) \
X(a, STATIC, SINGULAR, BOOL, is_client_muted, 2)
#define meshtastic_ModuleSettings_CALLBACK NULL #define meshtastic_ModuleSettings_CALLBACK NULL
#define meshtastic_ModuleSettings_DEFAULT NULL #define meshtastic_ModuleSettings_DEFAULT NULL
@ -182,9 +187,9 @@ extern const pb_msgdesc_t meshtastic_Channel_msg;
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_CHANNEL_PB_H_MAX_SIZE meshtastic_Channel_size #define MESHTASTIC_MESHTASTIC_CHANNEL_PB_H_MAX_SIZE meshtastic_Channel_size
#define meshtastic_ChannelSettings_size 70 #define meshtastic_ChannelSettings_size 72
#define meshtastic_Channel_size 85 #define meshtastic_Channel_size 87
#define meshtastic_ModuleSettings_size 6 #define meshtastic_ModuleSettings_size 8
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -283,6 +283,8 @@ typedef struct _meshtastic_Config_DeviceConfig {
bool disable_triple_click; bool disable_triple_click;
/* POSIX Timezone definition string from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv. */ /* POSIX Timezone definition string from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv. */
char tzdef[65]; char tzdef[65];
/* If true, disable the default blinking LED (LED_PIN) behavior on the device */
bool led_heartbeat_disabled;
} meshtastic_Config_DeviceConfig; } meshtastic_Config_DeviceConfig;
/* Position Config */ /* Position Config */
@ -324,35 +326,30 @@ typedef struct _meshtastic_Config_PositionConfig {
/* Power Config\ /* Power Config\
See [Power Config](/docs/settings/config/power) for additional power config details. */ See [Power Config](/docs/settings/config/power) for additional power config details. */
typedef struct _meshtastic_Config_PowerConfig { typedef struct _meshtastic_Config_PowerConfig {
/* If set, we are powered from a low-current source (i.e. solar), so even if it looks like we have power flowing in /* Description: Will sleep everything as much as possible, for the tracker and sensor role this will also include the lora radio.
we should try to minimize power consumption as much as possible. Don't use this setting if you want to use your device with the phone apps or are using a device without a user button.
YOU DO NOT NEED TO SET THIS IF YOU'VE set is_router (it is implied in that case). Technical Details: Works for ESP32 devices and NRF52 devices in the Sensor or Tracker roles */
Advanced Option */
bool is_power_saving; bool is_power_saving;
/* If non-zero, the device will fully power off this many seconds after external power is removed. */ /* Description: If non-zero, the device will fully power off this many seconds after external power is removed. */
uint32_t on_battery_shutdown_after_secs; uint32_t on_battery_shutdown_after_secs;
/* Ratio of voltage divider for battery pin eg. 3.20 (R1=100k, R2=220k) /* Ratio of voltage divider for battery pin eg. 3.20 (R1=100k, R2=220k)
Overrides the ADC_MULTIPLIER defined in variant for battery voltage calculation. Overrides the ADC_MULTIPLIER defined in variant for battery voltage calculation.
Should be set to floating point value between 2 and 4 https://meshtastic.org/docs/configuration/radio/power/#adc-multiplier-override
Fixes issues on Heltec v2 */ Should be set to floating point value between 2 and 6 */
float adc_multiplier_override; float adc_multiplier_override;
/* Wait Bluetooth Seconds /* Description: The number of seconds for to wait before turning off BLE in No Bluetooth states
The number of seconds for to wait before turning off BLE in No Bluetooth states Technical Details: ESP32 Only 0 for default of 1 minute */
0 for default of 1 minute */
uint32_t wait_bluetooth_secs; uint32_t wait_bluetooth_secs;
/* Super Deep Sleep Seconds /* Super Deep Sleep Seconds
While in Light Sleep if mesh_sds_timeout_secs is exceeded we will lower into super deep sleep While in Light Sleep if mesh_sds_timeout_secs is exceeded we will lower into super deep sleep
for this value (default 1 year) or a button press for this value (default 1 year) or a button press
0 for default of one year */ 0 for default of one year */
uint32_t sds_secs; uint32_t sds_secs;
/* Light Sleep Seconds /* Description: In light sleep the CPU is suspended, LoRa radio is on, BLE is off an GPS is on
In light sleep the CPU is suspended, LoRa radio is on, BLE is off an GPS is on Technical Details: ESP32 Only 0 for default of 300 */
ESP32 Only
0 for default of 300 */
uint32_t ls_secs; uint32_t ls_secs;
/* Minimum Wake Seconds /* Description: While in light sleep when we receive packets on the LoRa radio we will wake and handle them and stay awake in no BLE mode for this value
While in light sleep when we receive packets on the LoRa radio we will wake and handle them and stay awake in no BLE mode for this value Technical Details: ESP32 Only 0 for default of 10 seconds */
0 for default of 10 seconds */
uint32_t min_wake_secs; uint32_t min_wake_secs;
/* I2C address of INA_2XX to use for reading device battery voltage */ /* I2C address of INA_2XX to use for reading device battery voltage */
uint8_t device_battery_ina_address; uint8_t device_battery_ina_address;
@ -585,7 +582,7 @@ extern "C" {
/* Initializer values for message structs */ /* Initializer values for message structs */
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}} #define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, ""} #define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN} #define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""} #define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
@ -594,7 +591,7 @@ extern "C" {
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0} #define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0}
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0} #define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}} #define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, ""} #define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN} #define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""} #define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
@ -615,6 +612,7 @@ extern "C" {
#define meshtastic_Config_DeviceConfig_is_managed_tag 9 #define meshtastic_Config_DeviceConfig_is_managed_tag 9
#define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10 #define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10
#define meshtastic_Config_DeviceConfig_tzdef_tag 11 #define meshtastic_Config_DeviceConfig_tzdef_tag 11
#define meshtastic_Config_DeviceConfig_led_heartbeat_disabled_tag 12
#define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1 #define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1
#define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2 #define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2
#define meshtastic_Config_PositionConfig_fixed_position_tag 3 #define meshtastic_Config_PositionConfig_fixed_position_tag 3
@ -715,7 +713,8 @@ X(a, STATIC, SINGULAR, UINT32, node_info_broadcast_secs, 7) \
X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) \ X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) \
X(a, STATIC, SINGULAR, BOOL, is_managed, 9) \ X(a, STATIC, SINGULAR, BOOL, is_managed, 9) \
X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10) \ X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10) \
X(a, STATIC, SINGULAR, STRING, tzdef, 11) X(a, STATIC, SINGULAR, STRING, tzdef, 11) \
X(a, STATIC, SINGULAR, BOOL, led_heartbeat_disabled, 12)
#define meshtastic_Config_DeviceConfig_CALLBACK NULL #define meshtastic_Config_DeviceConfig_CALLBACK NULL
#define meshtastic_Config_DeviceConfig_DEFAULT NULL #define meshtastic_Config_DeviceConfig_DEFAULT NULL
@ -834,7 +833,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size #define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size
#define meshtastic_Config_BluetoothConfig_size 10 #define meshtastic_Config_BluetoothConfig_size 10
#define meshtastic_Config_DeviceConfig_size 98 #define meshtastic_Config_DeviceConfig_size 100
#define meshtastic_Config_DisplayConfig_size 28 #define meshtastic_Config_DisplayConfig_size 28
#define meshtastic_Config_LoRaConfig_size 80 #define meshtastic_Config_LoRaConfig_size 80
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20 #define meshtastic_Config_NetworkConfig_IpV4Config_size 20

View File

@ -306,9 +306,9 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg;
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
/* meshtastic_DeviceState_size depends on runtime parameters */ /* meshtastic_DeviceState_size depends on runtime parameters */
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_OEMStore_size #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_OEMStore_size
#define meshtastic_ChannelFile_size 702 #define meshtastic_ChannelFile_size 718
#define meshtastic_NodeInfoLite_size 166 #define meshtastic_NodeInfoLite_size 166
#define meshtastic_OEMStore_size 3344 #define meshtastic_OEMStore_size 3346
#define meshtastic_PositionLite_size 28 #define meshtastic_PositionLite_size 28
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -181,7 +181,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalModuleConfig_size #define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalModuleConfig_size
#define meshtastic_LocalConfig_size 535 #define meshtastic_LocalConfig_size 537
#define meshtastic_LocalModuleConfig_size 663 #define meshtastic_LocalModuleConfig_size 663
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -63,6 +63,8 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_NANO_G2_ULTRA = 18, meshtastic_HardwareModel_NANO_G2_ULTRA = 18,
/* LoRAType device: https://loratype.org/ */ /* LoRAType device: https://loratype.org/ */
meshtastic_HardwareModel_LORA_TYPE = 19, meshtastic_HardwareModel_LORA_TYPE = 19,
/* wiphone https://www.wiphone.io/ */
meshtastic_HardwareModel_WIPHONE = 20,
/* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */ /* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */
meshtastic_HardwareModel_STATION_G1 = 25, meshtastic_HardwareModel_STATION_G1 = 25,
/* RAK11310 (RP2040 + SX1262) */ /* RAK11310 (RP2040 + SX1262) */
@ -146,6 +148,14 @@ typedef enum _meshtastic_HardwareModel {
/* Teledatics TD-LORAC NRF52840 based M.2 LoRA module /* Teledatics TD-LORAC NRF52840 based M.2 LoRA module
Compatible with the TD-WRLS development board */ Compatible with the TD-WRLS development board */
meshtastic_HardwareModel_TD_LORAC = 60, meshtastic_HardwareModel_TD_LORAC = 60,
/* CDEBYTE EoRa-S3 board using their own MM modules, clone of LILYGO T3S3 */
meshtastic_HardwareModel_CDEBYTE_EORA_S3 = 61,
/* TWC_MESH_V4
Adafruit NRF52840 feather express with SX1262, SSD1306 OLED and NEO6M GPS */
meshtastic_HardwareModel_TWC_MESH_V4 = 62,
/* NRF52_PROMICRO_DIY
Promicro NRF52840 with SX1262/LLCC68, SSD1306 OLED and NEO6M GPS */
meshtastic_HardwareModel_NRF52_PROMICRO_DIY = 63,
/* ------------------------------------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */ ------------------------------------------------------------------------------------------------------------------------------------------ */

View File

@ -43,7 +43,11 @@ typedef enum _meshtastic_TelemetrySensorType {
/* INA3221 3 Channel Voltage / Current Sensor */ /* INA3221 3 Channel Voltage / Current Sensor */
meshtastic_TelemetrySensorType_INA3221 = 14, meshtastic_TelemetrySensorType_INA3221 = 14,
/* BMP085/BMP180 High accuracy temperature and pressure (older Version of BMP280) */ /* BMP085/BMP180 High accuracy temperature and pressure (older Version of BMP280) */
meshtastic_TelemetrySensorType_BMP085 = 15 meshtastic_TelemetrySensorType_BMP085 = 15,
/* RCWL-9620 Doppler Radar Distance Sensor, used for water level detection */
meshtastic_TelemetrySensorType_RCWL9620 = 16,
/* Sensirion High accuracy temperature and humidity */
meshtastic_TelemetrySensorType_SHT4X = 17
} meshtastic_TelemetrySensorType; } meshtastic_TelemetrySensorType;
/* Struct definitions */ /* Struct definitions */
@ -78,6 +82,8 @@ typedef struct _meshtastic_EnvironmentMetrics {
/* relative scale IAQ value as measured by Bosch BME680 . value 0-500. /* relative scale IAQ value as measured by Bosch BME680 . value 0-500.
Belongs to Air Quality but is not particle but VOC measurement. Other VOC values can also be put in here. */ Belongs to Air Quality but is not particle but VOC measurement. Other VOC values can also be put in here. */
uint16_t iaq; uint16_t iaq;
/* RCWL9620 Doppler Radar Distance Sensor, used for water level detection. Float value in mm. */
float distance;
} meshtastic_EnvironmentMetrics; } meshtastic_EnvironmentMetrics;
/* Power Metrics (voltage / current / etc) */ /* Power Metrics (voltage / current / etc) */
@ -148,8 +154,8 @@ extern "C" {
/* Helper constants for enums */ /* Helper constants for enums */
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_BMP085 #define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SHT4X
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_BMP085+1)) #define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SHT4X+1))
@ -159,12 +165,12 @@ extern "C" {
/* Initializer values for message structs */ /* Initializer values for message structs */
#define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0, 0} #define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0, 0}
#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0, 0} #define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_PowerMetrics_init_default {0, 0, 0, 0, 0, 0} #define meshtastic_PowerMetrics_init_default {0, 0, 0, 0, 0, 0}
#define meshtastic_AirQualityMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_AirQualityMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}}
#define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0, 0} #define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0, 0}
#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0, 0} #define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_PowerMetrics_init_zero {0, 0, 0, 0, 0, 0} #define meshtastic_PowerMetrics_init_zero {0, 0, 0, 0, 0, 0}
#define meshtastic_AirQualityMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_AirQualityMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}} #define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}}
@ -182,6 +188,7 @@ extern "C" {
#define meshtastic_EnvironmentMetrics_voltage_tag 5 #define meshtastic_EnvironmentMetrics_voltage_tag 5
#define meshtastic_EnvironmentMetrics_current_tag 6 #define meshtastic_EnvironmentMetrics_current_tag 6
#define meshtastic_EnvironmentMetrics_iaq_tag 7 #define meshtastic_EnvironmentMetrics_iaq_tag 7
#define meshtastic_EnvironmentMetrics_distance_tag 8
#define meshtastic_PowerMetrics_ch1_voltage_tag 1 #define meshtastic_PowerMetrics_ch1_voltage_tag 1
#define meshtastic_PowerMetrics_ch1_current_tag 2 #define meshtastic_PowerMetrics_ch1_current_tag 2
#define meshtastic_PowerMetrics_ch2_voltage_tag 3 #define meshtastic_PowerMetrics_ch2_voltage_tag 3
@ -223,7 +230,8 @@ X(a, STATIC, SINGULAR, FLOAT, barometric_pressure, 3) \
X(a, STATIC, SINGULAR, FLOAT, gas_resistance, 4) \ X(a, STATIC, SINGULAR, FLOAT, gas_resistance, 4) \
X(a, STATIC, SINGULAR, FLOAT, voltage, 5) \ X(a, STATIC, SINGULAR, FLOAT, voltage, 5) \
X(a, STATIC, SINGULAR, FLOAT, current, 6) \ X(a, STATIC, SINGULAR, FLOAT, current, 6) \
X(a, STATIC, SINGULAR, UINT32, iaq, 7) X(a, STATIC, SINGULAR, UINT32, iaq, 7) \
X(a, STATIC, SINGULAR, FLOAT, distance, 8)
#define meshtastic_EnvironmentMetrics_CALLBACK NULL #define meshtastic_EnvironmentMetrics_CALLBACK NULL
#define meshtastic_EnvironmentMetrics_DEFAULT NULL #define meshtastic_EnvironmentMetrics_DEFAULT NULL
@ -283,7 +291,7 @@ extern const pb_msgdesc_t meshtastic_Telemetry_msg;
#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size #define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size
#define meshtastic_AirQualityMetrics_size 72 #define meshtastic_AirQualityMetrics_size 72
#define meshtastic_DeviceMetrics_size 27 #define meshtastic_DeviceMetrics_size 27
#define meshtastic_EnvironmentMetrics_size 34 #define meshtastic_EnvironmentMetrics_size 39
#define meshtastic_PowerMetrics_size 30 #define meshtastic_PowerMetrics_size 30
#define meshtastic_Telemetry_size 79 #define meshtastic_Telemetry_size 79