Merge branch 'dev'
This commit is contained in:
79 files changed
+813
-784
No files matched your search
@@ -1,11 +1,12 @@
|
||||
# Packet Structure
|
||||
|
||||
| Field | Size (bytes) | Description |
|
||||
|----------|----------------------------------|-----------------------------------------------------------|
|
||||
| header | 1 | Contains routing type, payload type, and payload version. |
|
||||
| path_len | 1 | Length of the path field in bytes. |
|
||||
| path | up to 64 (`MAX_PATH_SIZE`) | Stores the routing path if applicable. |
|
||||
| payload | up to 184 (`MAX_PACKET_PAYLOAD`) | The actual data being transmitted. |
|
||||
| Field | Size (bytes) | Description |
|
||||
|-----------------|----------------------------------|-----------------------------------------------------------|
|
||||
| header | 1 | Contains routing type, payload type, and payload version. |
|
||||
| transport_codes | 4 (optional) | 2x 16-bit transport codes (if ROUTE_TYPE_TRANSPORT_*) |
|
||||
| path_len | 1 | Length of the path field in bytes. |
|
||||
| path | up to 64 (`MAX_PATH_SIZE`) | Stores the routing path if applicable. |
|
||||
| payload | up to 184 (`MAX_PACKET_PAYLOAD`) | The actual data being transmitted. |
|
||||
|
||||
Note: see the [payloads doc](./payloads.md) for more information about the content of payload.
|
||||
|
||||
@@ -42,6 +43,7 @@ bit 0 means the lowest bit (1s place)
|
||||
| `0x07` | `PAYLOAD_TYPE_ANON_REQ` | Anonymous request. |
|
||||
| `0x08` | `PAYLOAD_TYPE_PATH` | Returned path. |
|
||||
| `0x09` | `PAYLOAD_TYPE_TRACE` | trace a path, collecting SNI for each hop. |
|
||||
| `0x0A` | `PAYLOAD_TYPE_MULTIPART` | packet is part of a sequence of packets. |
|
||||
| `0x0F` | `PAYLOAD_TYPE_RAW_CUSTOM` | Custom packet (raw bytes, custom encryption). |
|
||||
|
||||
## Payload Version Values
|
||||
|
||||
+26
-24
@@ -10,13 +10,16 @@ Inside of each [meshcore packet](./packet_structure.md) is a payload, identified
|
||||
* Anonymous request.
|
||||
* Group text message (unverified).
|
||||
* Group datagram (unverified).
|
||||
* Multi-part packet
|
||||
* Custom packet (raw bytes, custom encryption).
|
||||
|
||||
This document defines the structure of each of these payload types
|
||||
This document defines the structure of each of these payload types.
|
||||
|
||||
NOTE: all 16 and 32-bit integer fields are Little Endian.
|
||||
|
||||
## Important concepts:
|
||||
|
||||
* Node/channel hash: the first byte of the node or channel's public key
|
||||
* Node hash: the first byte of the node's public key
|
||||
|
||||
# Node advertisement
|
||||
This kind of payload notifies receivers that a node exists, and gives information about the node
|
||||
@@ -33,10 +36,10 @@ Appdata
|
||||
| Field | Size (bytes) | Description |
|
||||
|---------------|-----------------|-------------------------------------------------------|
|
||||
| flags | 1 | specifies which of the fields are present, see below |
|
||||
| latitude | 4 | decimal latitude multiplied by 1000000, integer |
|
||||
| longitude | 4 | decimal longitude multiplied by 1000000, integer |
|
||||
| feature 1 | 2 | reserved for future use |
|
||||
| feature 2 | 2 | reserved for future use |
|
||||
| latitude | 4 (optional) | decimal latitude multiplied by 1000000, integer |
|
||||
| longitude | 4 (optional) | decimal longitude multiplied by 1000000, integer |
|
||||
| feature 1 | 2 (optional) | reserved for future use |
|
||||
| feature 2 | 2 (optional) | reserved for future use |
|
||||
| name | rest of appdata | name of the node |
|
||||
|
||||
Appdata Flags
|
||||
@@ -46,6 +49,7 @@ Appdata Flags
|
||||
| `0x01` | is chat node | advert is for a chat node |
|
||||
| `0x02` | is repeater | advert is for a repeater |
|
||||
| `0x03` | is room server | advert is for a room server |
|
||||
| `0x04` | is sensor | advert is for a sensor server |
|
||||
| `0x10` | has location | appdata contains lat/long information |
|
||||
| `0x20` | has feature 1 | Reserved for future use. |
|
||||
| `0x40` | has feature 2 | Reserved for future use. |
|
||||
@@ -92,13 +96,15 @@ Returned path messages provide a description of the route a packet took from the
|
||||
|
||||
Request type
|
||||
|
||||
| Value | Name | Description |
|
||||
|--------|--------------------|---------------------------------------|
|
||||
| `0x01` | get status | get status of repeater or room server |
|
||||
| `0x02` | keepalive | TODO |
|
||||
| `0x03` | get telemetry data | TODO |
|
||||
| Value | Name | Description |
|
||||
|--------|----------------------|---------------------------------------|
|
||||
| `0x01` | get stats | get stats of repeater or room server |
|
||||
| `0x02` | keepalive | (deprecated) |
|
||||
| `0x03` | get telemetry data | TODO |
|
||||
| `0x04` | get min,max,avg data | sensor nodes - get min, max, average for given time span |
|
||||
| `0x05` | get access list | get node's approved access list |
|
||||
|
||||
### Get status
|
||||
### Get stats
|
||||
|
||||
Gets information about the node, possibly including the following:
|
||||
|
||||
@@ -121,10 +127,6 @@ Gets information about the node, possibly including the following:
|
||||
* Number posted (?)
|
||||
* Number of post pushes (?)
|
||||
|
||||
### Keepalive
|
||||
|
||||
No-op request.
|
||||
|
||||
### Get telemetry data
|
||||
|
||||
Request data about sensors on the node, including battery level.
|
||||
@@ -138,11 +140,11 @@ Request data about sensors on the node, including battery level.
|
||||
|
||||
## Plain text message
|
||||
|
||||
| Field | Size (bytes) | Description |
|
||||
|--------------|-----------------|--------------------------------------------------------------|
|
||||
| timestamp | 4 | send time (unix timestamp) |
|
||||
| flags + TODO | 1 | first six bits are flags (see below), last two bits are TODO |
|
||||
| message | rest of payload | the message content, see next table |
|
||||
| Field | Size (bytes) | Description |
|
||||
|-----------------|-----------------|--------------------------------------------------------------|
|
||||
| timestamp | 4 | send time (unix timestamp) |
|
||||
| flags + attempt | 1 | upper six bits are flags (see below), lower two bits are attempt number (0..3) |
|
||||
| message | rest of payload | the message content, see next table |
|
||||
|
||||
Flags
|
||||
|
||||
@@ -150,7 +152,7 @@ Flags
|
||||
|--------|---------------------------|------------------------------------------------------------|
|
||||
| `0x00` | plain text message | the plain text of the message |
|
||||
| `0x01` | CLI command | the command text of the message |
|
||||
| `0x02` | signed plain text message | two bytes of sender prefix, followed by plain text message |
|
||||
| `0x02` | signed plain text message | first four bytes is sender pubkey prefix, followed by plain text message |
|
||||
|
||||
# Anonymous request
|
||||
|
||||
@@ -166,14 +168,14 @@ Plaintext message
|
||||
| Field | Size (bytes) | Description |
|
||||
|----------------|-----------------|-------------------------------------------------------------------------------|
|
||||
| timestamp | 4 | send time (unix timestamp) |
|
||||
| sync timestamp | 4 | for room server, otherwise absent: sender's "sync messages SINCE x" timestamp |
|
||||
| sync timestamp | 4 | NOTE: room server only! - sender's "sync messages SINCE x" timestamp |
|
||||
| password | rest of message | password for repeater/room |
|
||||
|
||||
# Group text message / datagram
|
||||
|
||||
| Field | Size (bytes) | Description |
|
||||
|--------------|-----------------|--------------------------------------------|
|
||||
| channel hash | 1 | the first byte of the channel's public key |
|
||||
| channel hash | 1 | first byte of SHA256 of channel's shared key |
|
||||
| cipher MAC | 2 | MAC for encrypted data in next field |
|
||||
| ciphertext | rest of payload | encrypted message, see below for details |
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
|
||||
file.read((uint8_t *)&_prefs.freq, sizeof(_prefs.freq)); // 56
|
||||
file.read((uint8_t *)&_prefs.sf, sizeof(_prefs.sf)); // 60
|
||||
file.read((uint8_t *)&_prefs.cr, sizeof(_prefs.cr)); // 61
|
||||
file.read((uint8_t *)&_prefs.reserved1, sizeof(_prefs.reserved1)); // 62
|
||||
file.read(pad, 1); // 62
|
||||
file.read((uint8_t *)&_prefs.manual_add_contacts, sizeof(_prefs.manual_add_contacts)); // 63
|
||||
file.read((uint8_t *)&_prefs.bw, sizeof(_prefs.bw)); // 64
|
||||
file.read((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68
|
||||
@@ -163,7 +163,8 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
|
||||
file.read((uint8_t *)&_prefs.telemetry_mode_env, sizeof(_prefs.telemetry_mode_env)); // 71
|
||||
file.read((uint8_t *)&_prefs.rx_delay_base, sizeof(_prefs.rx_delay_base)); // 72
|
||||
file.read((uint8_t *)&_prefs.advert_loc_policy, sizeof(_prefs.advert_loc_policy)); // 76
|
||||
file.read(pad, 3); // 77
|
||||
file.read((uint8_t *)&_prefs.multi_acks, sizeof(_prefs.multi_acks)); // 77
|
||||
file.read(pad, 2); // 78
|
||||
file.read((uint8_t *)&_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80
|
||||
|
||||
file.close();
|
||||
@@ -184,7 +185,7 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
|
||||
file.write((uint8_t *)&_prefs.freq, sizeof(_prefs.freq)); // 56
|
||||
file.write((uint8_t *)&_prefs.sf, sizeof(_prefs.sf)); // 60
|
||||
file.write((uint8_t *)&_prefs.cr, sizeof(_prefs.cr)); // 61
|
||||
file.write((uint8_t *)&_prefs.reserved1, sizeof(_prefs.reserved1)); // 62
|
||||
file.write(pad, 1); // 62
|
||||
file.write((uint8_t *)&_prefs.manual_add_contacts, sizeof(_prefs.manual_add_contacts)); // 63
|
||||
file.write((uint8_t *)&_prefs.bw, sizeof(_prefs.bw)); // 64
|
||||
file.write((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68
|
||||
@@ -193,7 +194,8 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
|
||||
file.write((uint8_t *)&_prefs.telemetry_mode_env, sizeof(_prefs.telemetry_mode_env)); // 71
|
||||
file.write((uint8_t *)&_prefs.rx_delay_base, sizeof(_prefs.rx_delay_base)); // 72
|
||||
file.write((uint8_t *)&_prefs.advert_loc_policy, sizeof(_prefs.advert_loc_policy)); // 76
|
||||
file.write(pad, 3); // 77
|
||||
file.write((uint8_t *)&_prefs.multi_acks, sizeof(_prefs.multi_acks)); // 77
|
||||
file.write(pad, 2); // 78
|
||||
file.write((uint8_t *)&_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80
|
||||
|
||||
file.close();
|
||||
|
||||
@@ -210,6 +210,10 @@ int MyMesh::calcRxDelay(float score, uint32_t air_time) const {
|
||||
return (int)((pow(_prefs.rx_delay_base, 0.85f - score) - 1.0) * air_time);
|
||||
}
|
||||
|
||||
uint8_t MyMesh::getExtraAckTransmitCount() const {
|
||||
return _prefs.multi_acks;
|
||||
}
|
||||
|
||||
void MyMesh::logRxRaw(float snr, float rssi, const uint8_t raw[], int len) {
|
||||
if (_serial->isConnected() && len + 3 <= MAX_FRAME_SIZE) {
|
||||
int i = 0;
|
||||
@@ -719,7 +723,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
i += 4;
|
||||
memcpy(&out_frame[i], &lon, 4);
|
||||
i += 4;
|
||||
out_frame[i++] = 0; // reserved
|
||||
out_frame[i++] = _prefs.multi_acks; // new v7+
|
||||
out_frame[i++] = _prefs.advert_loc_policy;
|
||||
out_frame[i++] = (_prefs.telemetry_mode_env << 4) | (_prefs.telemetry_mode_loc << 2) |
|
||||
(_prefs.telemetry_mode_base); // v5+
|
||||
@@ -1050,6 +1054,9 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
|
||||
if (len >= 4) {
|
||||
_prefs.advert_loc_policy = cmd_frame[3];
|
||||
if (len >= 5) {
|
||||
_prefs.multi_acks = cmd_frame[4];
|
||||
}
|
||||
}
|
||||
}
|
||||
savePrefs();
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
#define FIRMWARE_VER_CODE 7
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "15 Jul 2025"
|
||||
#define FIRMWARE_BUILD_DATE "24 Jul 2025"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.7.3"
|
||||
#define FIRMWARE_VERSION "v1.7.4"
|
||||
#endif
|
||||
|
||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||
@@ -97,6 +97,7 @@ protected:
|
||||
float getAirtimeBudgetFactor() const override;
|
||||
int getInterferenceThreshold() const override;
|
||||
int calcRxDelay(float score, uint32_t air_time) const override;
|
||||
uint8_t getExtraAckTransmitCount() const override;
|
||||
|
||||
void logRxRaw(float snr, float rssi, const uint8_t raw[], int len) override;
|
||||
bool isAutoAddEnabled() const override;
|
||||
|
||||
@@ -14,7 +14,7 @@ struct NodePrefs { // persisted to file
|
||||
float freq;
|
||||
uint8_t sf;
|
||||
uint8_t cr;
|
||||
uint8_t reserved1;
|
||||
uint8_t multi_acks;
|
||||
uint8_t manual_add_contacts;
|
||||
float bw;
|
||||
uint8_t tx_power_dbm;
|
||||
|
||||
@@ -408,8 +408,12 @@ void UITask::handleButtonQuadruplePress() {
|
||||
if (strcmp(_sensors->getSettingName(i), "gps") == 0) {
|
||||
if (strcmp(_sensors->getSettingValue(i), "1") == 0) {
|
||||
_sensors->setSettingValue("gps", "0");
|
||||
soundBuzzer(UIEventType::ack);
|
||||
sprintf(_alert, "GPS: Disabled");
|
||||
} else {
|
||||
_sensors->setSettingValue("gps", "1");
|
||||
soundBuzzer(UIEventType::ack);
|
||||
sprintf(_alert, "GPS: Enabled");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
/* ------------------------------ Config -------------------------------- */
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "15 Jul 2025"
|
||||
#define FIRMWARE_BUILD_DATE "24 Jul 2025"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.7.3"
|
||||
#define FIRMWARE_VERSION "v1.7.4"
|
||||
#endif
|
||||
|
||||
#ifndef LORA_FREQ
|
||||
@@ -120,7 +120,7 @@ struct NeighbourInfo {
|
||||
int8_t snr; // multiplied by 4, user should divide to get float value
|
||||
};
|
||||
|
||||
#define CLI_REPLY_DELAY_MILLIS 1000
|
||||
#define CLI_REPLY_DELAY_MILLIS 600
|
||||
|
||||
class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
|
||||
FILESYSTEM* _fs;
|
||||
@@ -134,6 +134,11 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
|
||||
NeighbourInfo neighbours[MAX_NEIGHBOURS];
|
||||
#endif
|
||||
CayenneLPP telemetry;
|
||||
unsigned long set_radio_at, revert_radio_at;
|
||||
float pending_freq;
|
||||
float pending_bw;
|
||||
uint8_t pending_sf;
|
||||
uint8_t pending_cr;
|
||||
|
||||
ClientInfo* putClient(const mesh::Identity& id) {
|
||||
uint32_t min_time = 0xFFFFFFFF;
|
||||
@@ -339,6 +344,9 @@ protected:
|
||||
int getAGCResetInterval() const override {
|
||||
return ((int)_prefs.agc_reset_interval) * 4000; // milliseconds
|
||||
}
|
||||
uint8_t getExtraAckTransmitCount() const override {
|
||||
return _prefs.multi_acks;
|
||||
}
|
||||
|
||||
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override {
|
||||
if (packet->getPayloadType() == PAYLOAD_TYPE_ANON_REQ) { // received an initial request by a possible admin client (unknown at this stage)
|
||||
@@ -555,6 +563,7 @@ public:
|
||||
{
|
||||
memset(known_clients, 0, sizeof(known_clients));
|
||||
next_local_advert = next_flood_advert = 0;
|
||||
set_radio_at = revert_radio_at = 0;
|
||||
_logging = false;
|
||||
|
||||
#if MAX_NEIGHBOURS
|
||||
@@ -606,6 +615,16 @@ public:
|
||||
_cli.savePrefs(_fs);
|
||||
}
|
||||
|
||||
void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) override {
|
||||
set_radio_at = futureMillis(2000); // give CLI reply some time to be sent back, before applying temp radio params
|
||||
pending_freq = freq;
|
||||
pending_bw = bw;
|
||||
pending_sf = sf;
|
||||
pending_cr = cr;
|
||||
|
||||
revert_radio_at = futureMillis(2000 + timeout_mins*60*1000); // schedule when to revert radio params
|
||||
}
|
||||
|
||||
bool formatFileSystem() override {
|
||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||
return InternalFS.format();
|
||||
@@ -731,6 +750,19 @@ public:
|
||||
|
||||
updateAdvertTimer(); // schedule next local advert
|
||||
}
|
||||
|
||||
if (set_radio_at && millisHasNowPassed(set_radio_at)) { // apply pending (temporary) radio params
|
||||
set_radio_at = 0; // clear timer
|
||||
radio_set_params(pending_freq, pending_bw, pending_sf, pending_cr);
|
||||
MESH_DEBUG_PRINTLN("Temp radio params");
|
||||
}
|
||||
|
||||
if (revert_radio_at && millisHasNowPassed(revert_radio_at)) { // revert radio params to orig
|
||||
revert_radio_at = 0; // clear timer
|
||||
radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
|
||||
MESH_DEBUG_PRINTLN("Radio params restored");
|
||||
}
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
ui_task.loop();
|
||||
#endif
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
/* ------------------------------ Config -------------------------------- */
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "15 Jul 2025"
|
||||
#define FIRMWARE_BUILD_DATE "24 Jul 2025"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.7.3"
|
||||
#define FIRMWARE_VERSION "v1.7.4"
|
||||
#endif
|
||||
|
||||
#ifndef LORA_FREQ
|
||||
@@ -165,6 +165,11 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
|
||||
int next_post_idx;
|
||||
PostInfo posts[MAX_UNSYNCED_POSTS]; // cyclic queue
|
||||
CayenneLPP telemetry;
|
||||
unsigned long set_radio_at, revert_radio_at;
|
||||
float pending_freq;
|
||||
float pending_bw;
|
||||
uint8_t pending_sf;
|
||||
uint8_t pending_cr;
|
||||
|
||||
ClientInfo* putClient(const mesh::Identity& id) {
|
||||
for (int i = 0; i < num_clients; i++) {
|
||||
@@ -424,6 +429,9 @@ protected:
|
||||
int getAGCResetInterval() const override {
|
||||
return ((int)_prefs.agc_reset_interval) * 4000; // milliseconds
|
||||
}
|
||||
uint8_t getExtraAckTransmitCount() const override {
|
||||
return _prefs.multi_acks;
|
||||
}
|
||||
|
||||
bool allowPacketForward(const mesh::Packet* packet) override {
|
||||
if (_prefs.disable_fwd) return false;
|
||||
@@ -578,15 +586,22 @@ protected:
|
||||
|
||||
uint32_t delay_millis;
|
||||
if (send_ack) {
|
||||
mesh::Packet* ack = createAck(ack_hash);
|
||||
if (ack) {
|
||||
if (client->out_path_len < 0) {
|
||||
sendFlood(ack, TXT_ACK_DELAY);
|
||||
} else {
|
||||
sendDirect(ack, client->out_path, client->out_path_len, TXT_ACK_DELAY);
|
||||
if (client->out_path_len < 0) {
|
||||
mesh::Packet* ack = createAck(ack_hash);
|
||||
if (ack) sendFlood(ack, TXT_ACK_DELAY);
|
||||
delay_millis = TXT_ACK_DELAY + REPLY_DELAY_MILLIS;
|
||||
} else {
|
||||
uint32_t d = TXT_ACK_DELAY;
|
||||
if (getExtraAckTransmitCount() > 0) {
|
||||
mesh::Packet* a1 = createMultiAck(ack_hash, 1);
|
||||
if (a1) sendDirect(a1, client->out_path, client->out_path_len, d);
|
||||
d += 300;
|
||||
}
|
||||
|
||||
mesh::Packet* a2 = createAck(ack_hash);
|
||||
if (a2) sendDirect(a2, client->out_path, client->out_path_len, d);
|
||||
delay_millis = d + REPLY_DELAY_MILLIS;
|
||||
}
|
||||
delay_millis = TXT_ACK_DELAY + REPLY_DELAY_MILLIS;
|
||||
} else {
|
||||
delay_millis = 0;
|
||||
}
|
||||
@@ -711,6 +726,7 @@ public:
|
||||
{
|
||||
next_local_advert = next_flood_advert = 0;
|
||||
_logging = false;
|
||||
set_radio_at = revert_radio_at = 0;
|
||||
|
||||
// defaults
|
||||
memset(&_prefs, 0, sizeof(_prefs));
|
||||
@@ -768,6 +784,16 @@ public:
|
||||
_cli.savePrefs(_fs);
|
||||
}
|
||||
|
||||
void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) override {
|
||||
set_radio_at = futureMillis(2000); // give CLI reply some time to be sent back, before applying temp radio params
|
||||
pending_freq = freq;
|
||||
pending_bw = bw;
|
||||
pending_sf = sf;
|
||||
pending_cr = cr;
|
||||
|
||||
revert_radio_at = futureMillis(2000 + timeout_mins*60*1000); // schedule when to revert radio params
|
||||
}
|
||||
|
||||
bool formatFileSystem() override {
|
||||
#if defined(NRF52_PLATFORM)
|
||||
return InternalFS.format();
|
||||
@@ -912,6 +938,18 @@ public:
|
||||
updateAdvertTimer(); // schedule next local advert
|
||||
}
|
||||
|
||||
if (set_radio_at && millisHasNowPassed(set_radio_at)) { // apply pending (temporary) radio params
|
||||
set_radio_at = 0; // clear timer
|
||||
radio_set_params(pending_freq, pending_bw, pending_sf, pending_cr);
|
||||
MESH_DEBUG_PRINTLN("Temp radio params");
|
||||
}
|
||||
|
||||
if (revert_radio_at && millisHasNowPassed(revert_radio_at)) { // revert radio params to orig
|
||||
revert_radio_at = 0; // clear timer
|
||||
radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
|
||||
MESH_DEBUG_PRINTLN("Radio params restored");
|
||||
}
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
ui_task.loop();
|
||||
#endif
|
||||
|
||||
@@ -243,7 +243,7 @@ static uint8_t putFloat(uint8_t * dest, float value, uint8_t size, uint32_t mult
|
||||
uint8_t SensorMesh::handleRequest(uint8_t perms, uint32_t sender_timestamp, uint8_t req_type, uint8_t* payload, size_t payload_len) {
|
||||
memcpy(reply_data, &sender_timestamp, 4); // reflect sender_timestamp back in response packet (kind of like a 'tag')
|
||||
|
||||
if (req_type == REQ_TYPE_GET_TELEMETRY_DATA && (perms & PERM_GET_TELEMETRY) != 0) {
|
||||
if (req_type == REQ_TYPE_GET_TELEMETRY_DATA) { // allow all
|
||||
telemetry.reset();
|
||||
telemetry.addVoltage(TELEM_CHANNEL_SELF, (float)board.getBattMilliVolts() / 1000.0f);
|
||||
// query other sensors -- target specific
|
||||
@@ -254,7 +254,7 @@ uint8_t SensorMesh::handleRequest(uint8_t perms, uint32_t sender_timestamp, uint
|
||||
memcpy(&reply_data[4], telemetry.getBuffer(), tlen);
|
||||
return 4 + tlen; // reply_len
|
||||
}
|
||||
if (req_type == REQ_TYPE_GET_AVG_MIN_MAX && (perms & PERM_GET_OTHER_STATS) != 0) {
|
||||
if (req_type == REQ_TYPE_GET_AVG_MIN_MAX && (perms & PERM_ACL_ROLE_MASK) >= PERM_ACL_READ_ONLY) {
|
||||
uint32_t start_secs_ago, end_secs_ago;
|
||||
memcpy(&start_secs_ago, &payload[0], 4);
|
||||
memcpy(&end_secs_ago, &payload[4], 4);
|
||||
@@ -288,13 +288,14 @@ uint8_t SensorMesh::handleRequest(uint8_t perms, uint32_t sender_timestamp, uint
|
||||
}
|
||||
return ofs;
|
||||
}
|
||||
if (req_type == REQ_TYPE_GET_ACCESS_LIST && (perms & PERM_ACL_ROLE_MASK) == PERM_ACL_LEVEL3) {
|
||||
if (req_type == REQ_TYPE_GET_ACCESS_LIST && (perms & PERM_ACL_ROLE_MASK) == PERM_ACL_ADMIN) {
|
||||
uint8_t res1 = payload[0]; // reserved for future (extra query params)
|
||||
uint8_t res2 = payload[1];
|
||||
if (res1 == 0 && res2 == 0) {
|
||||
uint8_t ofs = 4;
|
||||
for (int i = 0; i < num_contacts && ofs + 7 <= sizeof(reply_data) - 4; i++) {
|
||||
auto c = &contacts[i];
|
||||
if (c->permissions == 0) continue; // skip deleted entries
|
||||
memcpy(&reply_data[ofs], c->id.pub_key, 6); ofs += 6; // just 6-byte pub_key prefix
|
||||
reply_data[ofs++] = c->permissions;
|
||||
}
|
||||
@@ -315,7 +316,14 @@ mesh::Packet* SensorMesh::createSelfAdvert() {
|
||||
return createAdvert(self_id, app_data, app_data_len);
|
||||
}
|
||||
|
||||
ContactInfo* SensorMesh::putContact(const mesh::Identity& id) {
|
||||
ContactInfo* SensorMesh::getContact(const uint8_t* pubkey, int key_len) {
|
||||
for (int i = 0; i < num_contacts; i++) {
|
||||
if (memcmp(pubkey, contacts[i].id.pub_key, key_len) == 0) return &contacts[i]; // already known
|
||||
}
|
||||
return NULL; // not found
|
||||
}
|
||||
|
||||
ContactInfo* SensorMesh::putContact(const mesh::Identity& id, uint8_t init_perms) {
|
||||
uint32_t min_time = 0xFFFFFFFF;
|
||||
ContactInfo* oldest = &contacts[MAX_CONTACTS - 1];
|
||||
for (int i = 0; i < num_contacts; i++) {
|
||||
@@ -333,22 +341,35 @@ ContactInfo* SensorMesh::putContact(const mesh::Identity& id) {
|
||||
c = oldest; // evict least active contact
|
||||
}
|
||||
memset(c, 0, sizeof(*c));
|
||||
c->permissions = init_perms;
|
||||
c->id = id;
|
||||
c->out_path_len = -1; // initially out_path is unknown
|
||||
return c;
|
||||
}
|
||||
|
||||
void SensorMesh::applyContactPermissions(const uint8_t* pubkey, uint8_t perms) {
|
||||
mesh::Identity id(pubkey);
|
||||
auto c = putContact(id);
|
||||
|
||||
bool SensorMesh::applyContactPermissions(const uint8_t* pubkey, int key_len, uint8_t perms) {
|
||||
ContactInfo* c;
|
||||
if ((perms & PERM_ACL_ROLE_MASK) == PERM_ACL_GUEST) { // guest role is not persisted in contacts
|
||||
memset(c, 0, sizeof(*c));
|
||||
c = getContact(pubkey, key_len);
|
||||
if (c == NULL) return false; // partial pubkey not found
|
||||
|
||||
num_contacts--; // delete from contacts[]
|
||||
int i = c - contacts;
|
||||
while (i < num_contacts) {
|
||||
contacts[i] = contacts[i + 1];
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
if (key_len < PUB_KEY_SIZE) return false; // need complete pubkey when adding/modifying
|
||||
|
||||
mesh::Identity id(pubkey);
|
||||
c = putContact(id, 0);
|
||||
|
||||
c->permissions = perms; // update their permissions
|
||||
self_id.calcSharedSecret(c->shared_secret, pubkey);
|
||||
}
|
||||
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); // trigger saveContacts()
|
||||
return true;
|
||||
}
|
||||
|
||||
void SensorMesh::sendAlert(ContactInfo* c, Trigger* t) {
|
||||
@@ -434,32 +455,43 @@ int SensorMesh::getAGCResetInterval() const {
|
||||
}
|
||||
|
||||
uint8_t SensorMesh::handleLoginReq(const mesh::Identity& sender, const uint8_t* secret, uint32_t sender_timestamp, const uint8_t* data) {
|
||||
if (strcmp((char *) data, _prefs.password) != 0) { // check for valid password
|
||||
#if MESH_DEBUG
|
||||
MESH_DEBUG_PRINTLN("Invalid password: %s", &data[4]);
|
||||
#endif
|
||||
return 0;
|
||||
ContactInfo* client;
|
||||
if (data[0] == 0) { // blank password, just check if sender is in ACL
|
||||
client = getContact(sender.pub_key, PUB_KEY_SIZE);
|
||||
if (client == NULL) {
|
||||
#if MESH_DEBUG
|
||||
MESH_DEBUG_PRINTLN("Login, sender not in ACL");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (strcmp((char *) data, _prefs.password) != 0) { // check for valid admin password
|
||||
#if MESH_DEBUG
|
||||
MESH_DEBUG_PRINTLN("Invalid password: %s", &data[4]);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
client = putContact(sender, PERM_RECV_ALERTS_HI | PERM_RECV_ALERTS_LO); // add to contacts (if not already known)
|
||||
if (sender_timestamp <= client->last_timestamp) {
|
||||
MESH_DEBUG_PRINTLN("Possible login replay attack!");
|
||||
return 0; // FATAL: client table is full -OR- replay attack
|
||||
}
|
||||
|
||||
MESH_DEBUG_PRINTLN("Login success!");
|
||||
client->last_timestamp = sender_timestamp;
|
||||
client->last_activity = getRTCClock()->getCurrentTime();
|
||||
client->permissions |= PERM_ACL_ADMIN;
|
||||
memcpy(client->shared_secret, secret, PUB_KEY_SIZE);
|
||||
|
||||
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
|
||||
}
|
||||
|
||||
auto client = putContact(sender); // add to contacts (if not already known)
|
||||
if (sender_timestamp <= client->last_timestamp) {
|
||||
MESH_DEBUG_PRINTLN("Possible login replay attack!");
|
||||
return 0; // FATAL: client table is full -OR- replay attack
|
||||
}
|
||||
|
||||
MESH_DEBUG_PRINTLN("Login success!");
|
||||
client->last_timestamp = sender_timestamp;
|
||||
client->last_activity = getRTCClock()->getCurrentTime();
|
||||
client->permissions = PERM_ACL_LEVEL3 | PERM_RECV_ALERTS_HI | PERM_RECV_ALERTS_LO; // initially opt-in to receive alerts (can opt out)
|
||||
memcpy(client->shared_secret, secret, PUB_KEY_SIZE);
|
||||
|
||||
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
|
||||
|
||||
uint32_t now = getRTCClock()->getCurrentTimeUnique();
|
||||
memcpy(reply_data, &now, 4); // response packets always prefixed with timestamp
|
||||
reply_data[4] = RESP_SERVER_LOGIN_OK;
|
||||
reply_data[5] = 0; // NEW: recommended keep-alive interval (secs / 16)
|
||||
reply_data[6] = 1; // 1 = is admin
|
||||
reply_data[6] = client->isAdmin() ? 1 : 0;
|
||||
reply_data[7] = client->permissions;
|
||||
getRNG()->random(&reply_data[8], 4); // random blob to help packet-hash uniqueness
|
||||
|
||||
@@ -484,16 +516,20 @@ void SensorMesh::handleCommand(uint32_t sender_timestamp, char* command, char* r
|
||||
if (memcmp(command, "setperm ", 8) == 0) { // format: setperm {pubkey-hex} {permissions-int8}
|
||||
char* hex = &command[8];
|
||||
char* sp = strchr(hex, ' '); // look for separator char
|
||||
if (sp == NULL || sp - hex != PUB_KEY_SIZE*2) {
|
||||
strcpy(reply, "Err - bad pubkey len");
|
||||
if (sp == NULL) {
|
||||
strcpy(reply, "Err - bad params");
|
||||
} else {
|
||||
*sp++ = 0; // replace space with null terminator
|
||||
|
||||
uint8_t pubkey[PUB_KEY_SIZE];
|
||||
if (mesh::Utils::fromHex(pubkey, PUB_KEY_SIZE, hex)) {
|
||||
int hex_len = min(sp - hex, PUB_KEY_SIZE*2);
|
||||
if (mesh::Utils::fromHex(pubkey, hex_len / 2, hex)) {
|
||||
uint8_t perms = atoi(sp);
|
||||
applyContactPermissions(pubkey, perms);
|
||||
strcpy(reply, "OK");
|
||||
if (applyContactPermissions(pubkey, hex_len / 2, perms)) {
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Err - invalid params");
|
||||
}
|
||||
} else {
|
||||
strcpy(reply, "Err - bad pubkey");
|
||||
}
|
||||
@@ -502,6 +538,7 @@ void SensorMesh::handleCommand(uint32_t sender_timestamp, char* command, char* r
|
||||
Serial.println("ACL:");
|
||||
for (int i = 0; i < num_contacts; i++) {
|
||||
auto c = &contacts[i];
|
||||
if (c->permissions == 0) continue; // skip deleted entries
|
||||
|
||||
Serial.printf("%02X ", c->permissions);
|
||||
mesh::Utils::printHex(Serial, c->id.pub_key, PUB_KEY_SIZE);
|
||||
@@ -569,7 +606,7 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i
|
||||
memcpy(×tamp, data, 4);
|
||||
|
||||
if (timestamp > from.last_timestamp) { // prevent replay attacks
|
||||
uint8_t reply_len = handleRequest(from.isAdmin() ? 0xFFFF : from.permissions, timestamp, data[4], &data[5], len - 5);
|
||||
uint8_t reply_len = handleRequest(from.isAdmin() ? 0xFF : from.permissions, timestamp, data[4], &data[5], len - 5);
|
||||
if (reply_len == 0) return; // invalid command
|
||||
|
||||
from.last_timestamp = timestamp;
|
||||
@@ -685,6 +722,7 @@ SensorMesh::SensorMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::Millise
|
||||
dirty_contacts_expiry = 0;
|
||||
last_read_time = 0;
|
||||
num_alert_tasks = 0;
|
||||
set_radio_at = revert_radio_at = 0;
|
||||
|
||||
// defaults
|
||||
memset(&_prefs, 0, sizeof(_prefs));
|
||||
@@ -735,6 +773,16 @@ bool SensorMesh::formatFileSystem() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void SensorMesh::applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) {
|
||||
set_radio_at = futureMillis(2000); // give CLI reply some time to be sent back, before applying temp radio params
|
||||
pending_freq = freq;
|
||||
pending_bw = bw;
|
||||
pending_sf = sf;
|
||||
pending_cr = cr;
|
||||
|
||||
revert_radio_at = futureMillis(2000 + timeout_mins*60*1000); // schedule when to revert radio params
|
||||
}
|
||||
|
||||
void SensorMesh::sendSelfAdvertisement(int delay_millis) {
|
||||
mesh::Packet* pkt = createSelfAdvert();
|
||||
if (pkt) {
|
||||
@@ -810,6 +858,18 @@ void SensorMesh::loop() {
|
||||
updateAdvertTimer(); // schedule next local advert
|
||||
}
|
||||
|
||||
if (set_radio_at && millisHasNowPassed(set_radio_at)) { // apply pending (temporary) radio params
|
||||
set_radio_at = 0; // clear timer
|
||||
radio_set_params(pending_freq, pending_bw, pending_sf, pending_cr);
|
||||
MESH_DEBUG_PRINTLN("Temp radio params");
|
||||
}
|
||||
|
||||
if (revert_radio_at && millisHasNowPassed(revert_radio_at)) { // revert radio params to orig
|
||||
revert_radio_at = 0; // clear timer
|
||||
radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
|
||||
MESH_DEBUG_PRINTLN("Radio params restored");
|
||||
}
|
||||
|
||||
uint32_t curr = getRTCClock()->getCurrentTime();
|
||||
if (curr >= last_read_time + SENSOR_READ_INTERVAL_SECS) {
|
||||
telemetry.reset();
|
||||
|
||||
@@ -25,14 +25,14 @@
|
||||
|
||||
#define PERM_ACL_ROLE_MASK 3 // lower 2 bits
|
||||
#define PERM_ACL_GUEST 0
|
||||
#define PERM_ACL_LEVEL1 1
|
||||
#define PERM_ACL_LEVEL2 2
|
||||
#define PERM_ACL_LEVEL3 3 // admin
|
||||
#define PERM_ACL_READ_ONLY 1
|
||||
#define PERM_ACL_READ_WRITE 2
|
||||
#define PERM_ACL_ADMIN 3
|
||||
|
||||
#define PERM_GET_TELEMETRY (1 << 2)
|
||||
#define PERM_GET_OTHER_STATS (1 << 3)
|
||||
#define PERM_RESERVED1 (1 << 4)
|
||||
#define PERM_RESERVED2 (1 << 5)
|
||||
#define PERM_RESERVED1 (1 << 2)
|
||||
#define PERM_RESERVED2 (1 << 3)
|
||||
#define PERM_RESERVED3 (1 << 4)
|
||||
#define PERM_RESERVED4 (1 << 5)
|
||||
#define PERM_RECV_ALERTS_LO (1 << 6) // low priority alerts
|
||||
#define PERM_RECV_ALERTS_HI (1 << 7) // high priority alerts
|
||||
|
||||
@@ -45,15 +45,15 @@ struct ContactInfo {
|
||||
uint32_t last_timestamp; // by THEIR clock (transient)
|
||||
uint32_t last_activity; // by OUR clock (transient)
|
||||
|
||||
bool isAdmin() const { return (permissions & PERM_ACL_ROLE_MASK) == PERM_ACL_LEVEL3; }
|
||||
bool isAdmin() const { return (permissions & PERM_ACL_ROLE_MASK) == PERM_ACL_ADMIN; }
|
||||
};
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "2 Jul 2025"
|
||||
#define FIRMWARE_BUILD_DATE "24 Jul 2025"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.7.2"
|
||||
#define FIRMWARE_VERSION "v1.7.4"
|
||||
#endif
|
||||
|
||||
#define FIRMWARE_ROLE "sensor"
|
||||
@@ -90,6 +90,7 @@ public:
|
||||
}
|
||||
const uint8_t* getSelfIdPubKey() override { return self_id.pub_key; }
|
||||
void clearStats() override { }
|
||||
void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) override;
|
||||
|
||||
float getTelemValue(uint8_t channel, uint8_t type);
|
||||
|
||||
@@ -154,14 +155,20 @@ private:
|
||||
int matching_peer_indexes[MAX_SEARCH_RESULTS];
|
||||
int num_alert_tasks;
|
||||
Trigger* alert_tasks[MAX_CONCURRENT_ALERTS];
|
||||
unsigned long set_radio_at, revert_radio_at;
|
||||
float pending_freq;
|
||||
float pending_bw;
|
||||
uint8_t pending_sf;
|
||||
uint8_t pending_cr;
|
||||
|
||||
void loadContacts();
|
||||
void saveContacts();
|
||||
uint8_t handleLoginReq(const mesh::Identity& sender, const uint8_t* secret, uint32_t sender_timestamp, const uint8_t* data);
|
||||
uint8_t handleRequest(uint8_t perms, uint32_t sender_timestamp, uint8_t req_type, uint8_t* payload, size_t payload_len);
|
||||
mesh::Packet* createSelfAdvert();
|
||||
ContactInfo* putContact(const mesh::Identity& id);
|
||||
void applyContactPermissions(const uint8_t* pubkey, uint8_t perms);
|
||||
ContactInfo* getContact(const uint8_t* pubkey, int key_len);
|
||||
ContactInfo* putContact(const mesh::Identity& id, uint8_t init_perms);
|
||||
bool applyContactPermissions(const uint8_t* pubkey, int key_len, uint8_t perms);
|
||||
|
||||
void sendAlert(ContactInfo* c, Trigger* t);
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ build_flags = -w -DNDEBUG -DRADIOLIB_STATIC_ONLY=1 -DRADIOLIB_GODMODE=1
|
||||
build_src_filter =
|
||||
+<*.cpp>
|
||||
+<helpers/*.cpp>
|
||||
+<helpers/radiolib/*.cpp>
|
||||
|
||||
; ----------------- ESP32 ---------------------
|
||||
|
||||
|
||||
+120
-14
@@ -22,6 +22,9 @@ uint32_t Mesh::getRetransmitDelay(const mesh::Packet* packet) {
|
||||
uint32_t Mesh::getDirectRetransmitDelay(const Packet* packet) {
|
||||
return 0; // by default, no delay
|
||||
}
|
||||
uint8_t Mesh::getExtraAckTransmitCount() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t Mesh::getCADFailRetryDelay() const {
|
||||
return _rng->nextInt(1, 4)*120;
|
||||
@@ -67,22 +70,22 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
|
||||
|
||||
if (pkt->isRouteDirect() && pkt->path_len >= PATH_HASH_SIZE) {
|
||||
if (self_id.isHashMatch(pkt->path) && allowPacketForward(pkt)) {
|
||||
if (_tables->hasSeen(pkt)) return ACTION_RELEASE; // don't retransmit!
|
||||
|
||||
// remove our hash from 'path', then re-broadcast
|
||||
pkt->path_len -= PATH_HASH_SIZE;
|
||||
#if 0
|
||||
memcpy(pkt->path, &pkt->path[PATH_HASH_SIZE], pkt->path_len);
|
||||
#elif PATH_HASH_SIZE == 1
|
||||
for (int k = 0; k < pkt->path_len; k++) { // shuffle bytes by 1
|
||||
pkt->path[k] = pkt->path[k + 1];
|
||||
if (pkt->getPayloadType() == PAYLOAD_TYPE_MULTIPART) {
|
||||
return forwardMultipartDirect(pkt);
|
||||
} else if (pkt->getPayloadType() == PAYLOAD_TYPE_ACK) {
|
||||
if (!_tables->hasSeen(pkt)) { // don't retransmit!
|
||||
removeSelfFromPath(pkt);
|
||||
routeDirectRecvAcks(pkt, 0);
|
||||
}
|
||||
return ACTION_RELEASE;
|
||||
}
|
||||
#else
|
||||
#error "need path remove impl"
|
||||
#endif
|
||||
|
||||
uint32_t d = getDirectRetransmitDelay(pkt);
|
||||
return ACTION_RETRANSMIT_DELAYED(0, d); // Routed traffic is HIGHEST priority
|
||||
if (!_tables->hasSeen(pkt)) {
|
||||
removeSelfFromPath(pkt);
|
||||
|
||||
uint32_t d = getDirectRetransmitDelay(pkt);
|
||||
return ACTION_RETRANSMIT_DELAYED(0, d); // Routed traffic is HIGHEST priority
|
||||
}
|
||||
}
|
||||
return ACTION_RELEASE; // this node is NOT the next hop (OR this packet has already been forwarded), so discard.
|
||||
}
|
||||
@@ -261,6 +264,32 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PAYLOAD_TYPE_MULTIPART:
|
||||
if (pkt->payload_len > 2) {
|
||||
uint8_t remaining = pkt->payload[0] >> 4; // num of packets in this multipart sequence still to be sent
|
||||
uint8_t type = pkt->payload[0] & 0x0F;
|
||||
|
||||
if (type == PAYLOAD_TYPE_ACK && pkt->payload_len >= 5) { // a multipart ACK
|
||||
Packet tmp;
|
||||
tmp.header = pkt->header;
|
||||
tmp.path_len = pkt->path_len;
|
||||
memcpy(tmp.path, pkt->path, pkt->path_len);
|
||||
tmp.payload_len = pkt->payload_len - 1;
|
||||
memcpy(tmp.payload, &pkt->payload[1], tmp.payload_len);
|
||||
|
||||
if (!_tables->hasSeen(&tmp)) {
|
||||
uint32_t ack_crc;
|
||||
memcpy(&ack_crc, tmp.payload, 4);
|
||||
|
||||
onAckRecv(&tmp, ack_crc);
|
||||
//action = routeRecvPacket(&tmp); // NOTE: currently not needed, as multipart ACKs not sent Flood
|
||||
}
|
||||
} else {
|
||||
// FUTURE: other multipart types??
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): unknown payload type, header: %d", getLogDateTime(), (int) pkt->header);
|
||||
// Don't flood route unknown packet types! action = routeRecvPacket(pkt);
|
||||
@@ -269,6 +298,20 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
|
||||
return action;
|
||||
}
|
||||
|
||||
void Mesh::removeSelfFromPath(Packet* pkt) {
|
||||
// remove our hash from 'path'
|
||||
pkt->path_len -= PATH_HASH_SIZE;
|
||||
#if 0
|
||||
memcpy(pkt->path, &pkt->path[PATH_HASH_SIZE], pkt->path_len);
|
||||
#elif PATH_HASH_SIZE == 1
|
||||
for (int k = 0; k < pkt->path_len; k++) { // shuffle bytes by 1
|
||||
pkt->path[k] = pkt->path[k + 1];
|
||||
}
|
||||
#else
|
||||
#error "need path remove impl"
|
||||
#endif
|
||||
}
|
||||
|
||||
DispatcherAction Mesh::routeRecvPacket(Packet* packet) {
|
||||
if (packet->isRouteFlood() && !packet->isMarkedDoNotRetransmit()
|
||||
&& packet->path_len + PATH_HASH_SIZE <= MAX_PATH_SIZE && allowPacketForward(packet)) {
|
||||
@@ -282,6 +325,54 @@ DispatcherAction Mesh::routeRecvPacket(Packet* packet) {
|
||||
return ACTION_RELEASE;
|
||||
}
|
||||
|
||||
DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) {
|
||||
uint8_t remaining = pkt->payload[0] >> 4; // num of packets in this multipart sequence still to be sent
|
||||
uint8_t type = pkt->payload[0] & 0x0F;
|
||||
|
||||
if (type == PAYLOAD_TYPE_ACK && pkt->payload_len >= 5) { // a multipart ACK
|
||||
Packet tmp;
|
||||
tmp.header = pkt->header;
|
||||
tmp.path_len = pkt->path_len;
|
||||
memcpy(tmp.path, pkt->path, pkt->path_len);
|
||||
tmp.payload_len = pkt->payload_len - 1;
|
||||
memcpy(tmp.payload, &pkt->payload[1], tmp.payload_len);
|
||||
|
||||
if (!_tables->hasSeen(&tmp)) { // don't retransmit!
|
||||
removeSelfFromPath(&tmp);
|
||||
routeDirectRecvAcks(&tmp, ((uint32_t)remaining + 1) * 300); // expect multipart ACKs 300ms apart (x2)
|
||||
}
|
||||
}
|
||||
return ACTION_RELEASE;
|
||||
}
|
||||
|
||||
void Mesh::routeDirectRecvAcks(Packet* packet, uint32_t delay_millis) {
|
||||
if (!packet->isMarkedDoNotRetransmit()) {
|
||||
uint32_t crc;
|
||||
memcpy(&crc, packet->payload, 4);
|
||||
|
||||
uint8_t extra = getExtraAckTransmitCount();
|
||||
while (extra > 0) {
|
||||
delay_millis += getDirectRetransmitDelay(packet) + 300;
|
||||
auto a1 = createMultiAck(crc, extra);
|
||||
if (a1) {
|
||||
memcpy(a1->path, packet->path, a1->path_len = packet->path_len);
|
||||
a1->header &= ~PH_ROUTE_MASK;
|
||||
a1->header |= ROUTE_TYPE_DIRECT;
|
||||
sendPacket(a1, 0, delay_millis);
|
||||
}
|
||||
extra--;
|
||||
}
|
||||
|
||||
auto a2 = createAck(crc);
|
||||
if (a2) {
|
||||
memcpy(a2->path, packet->path, a2->path_len = packet->path_len);
|
||||
a2->header &= ~PH_ROUTE_MASK;
|
||||
a2->header |= ROUTE_TYPE_DIRECT;
|
||||
sendPacket(a2, 0, delay_millis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Packet* Mesh::createAdvert(const LocalIdentity& id, const uint8_t* app_data, size_t app_data_len) {
|
||||
if (app_data_len > MAX_ADVERT_DATA_SIZE) return NULL;
|
||||
|
||||
@@ -449,6 +540,21 @@ Packet* Mesh::createAck(uint32_t ack_crc) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
Packet* Mesh::createMultiAck(uint32_t ack_crc, uint8_t remaining) {
|
||||
Packet* packet = obtainNewPacket();
|
||||
if (packet == NULL) {
|
||||
MESH_DEBUG_PRINTLN("%s Mesh::createMultiAck(): error, packet pool empty", getLogDateTime());
|
||||
return NULL;
|
||||
}
|
||||
packet->header = (PAYLOAD_TYPE_MULTIPART << PH_TYPE_SHIFT); // ROUTE_TYPE_* set later
|
||||
|
||||
packet->payload[0] = (remaining << 4) | PAYLOAD_TYPE_ACK;
|
||||
memcpy(&packet->payload[1], &ack_crc, 4);
|
||||
packet->payload_len = 5;
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
Packet* Mesh::createRawData(const uint8_t* data, size_t len) {
|
||||
if (len > sizeof(Packet::payload)) return NULL; // invalid arg
|
||||
|
||||
|
||||
+11
@@ -28,6 +28,11 @@ class Mesh : public Dispatcher {
|
||||
RNG* _rng;
|
||||
MeshTables* _tables;
|
||||
|
||||
void removeSelfFromPath(Packet* packet);
|
||||
void routeDirectRecvAcks(Packet* packet, uint32_t delay_millis);
|
||||
//void routeRecvAcks(Packet* packet, uint32_t delay_millis);
|
||||
DispatcherAction forwardMultipartDirect(Packet* pkt);
|
||||
|
||||
protected:
|
||||
DispatcherAction onRecvPacket(Packet* pkt) override;
|
||||
|
||||
@@ -54,6 +59,11 @@ protected:
|
||||
*/
|
||||
virtual uint32_t getDirectRetransmitDelay(const Packet* packet);
|
||||
|
||||
/**
|
||||
* \returns number of extra (Direct) ACK transmissions wanted.
|
||||
*/
|
||||
virtual uint8_t getExtraAckTransmitCount() const;
|
||||
|
||||
/**
|
||||
* \brief Perform search of local DB of peers/contacts.
|
||||
* \returns Number of peers with matching hash
|
||||
@@ -165,6 +175,7 @@ public:
|
||||
Packet* createAnonDatagram(uint8_t type, const LocalIdentity& sender, const Identity& dest, const uint8_t* secret, const uint8_t* data, size_t data_len);
|
||||
Packet* createGroupDatagram(uint8_t type, const GroupChannel& channel, const uint8_t* data, size_t data_len);
|
||||
Packet* createAck(uint32_t ack_crc);
|
||||
Packet* createMultiAck(uint32_t ack_crc, uint8_t remaining);
|
||||
Packet* createPathReturn(const uint8_t* dest_hash, const uint8_t* secret, const uint8_t* path, uint8_t path_len, uint8_t extra_type, const uint8_t*extra, size_t extra_len);
|
||||
Packet* createPathReturn(const Identity& dest, const uint8_t* secret, const uint8_t* path, uint8_t path_len, uint8_t extra_type, const uint8_t*extra, size_t extra_len);
|
||||
Packet* createRawData(const uint8_t* data, size_t len);
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace mesh {
|
||||
#define PAYLOAD_TYPE_ANON_REQ 0x07 // generic request (prefixed with dest_hash, ephemeral pub_key, MAC) (enc data: ...)
|
||||
#define PAYLOAD_TYPE_PATH 0x08 // returned path (prefixed with dest/src hashes, MAC) (enc data: path, extra)
|
||||
#define PAYLOAD_TYPE_TRACE 0x09 // trace a path, collecting SNI for each hop
|
||||
#define PAYLOAD_TYPE_MULTIPART 0x0A // packet is one of a set of packets
|
||||
//...
|
||||
#define PAYLOAD_TYPE_RAW_CUSTOM 0x0F // custom packet as raw bytes, for applications with custom encryption, payloads, etc
|
||||
|
||||
|
||||
@@ -31,6 +31,23 @@ mesh::Packet* BaseChatMesh::createSelfAdvert(const char* name, double lat, doubl
|
||||
return createAdvert(self_id, app_data, app_data_len);
|
||||
}
|
||||
|
||||
void BaseChatMesh::sendAckTo(const ContactInfo& dest, uint32_t ack_hash) {
|
||||
if (dest.out_path_len < 0) {
|
||||
mesh::Packet* ack = createAck(ack_hash);
|
||||
if (ack) sendFlood(ack, TXT_ACK_DELAY);
|
||||
} else {
|
||||
uint32_t d = TXT_ACK_DELAY;
|
||||
if (getExtraAckTransmitCount() > 0) {
|
||||
mesh::Packet* a1 = createMultiAck(ack_hash, 1);
|
||||
if (a1) sendDirect(a1, dest.out_path, dest.out_path_len, d);
|
||||
d += 300;
|
||||
}
|
||||
|
||||
mesh::Packet* a2 = createAck(ack_hash);
|
||||
if (a2) sendDirect(a2, dest.out_path, dest.out_path_len, d);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseChatMesh::onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id, uint32_t timestamp, const uint8_t* app_data, size_t app_data_len) {
|
||||
AdvertDataParser parser(app_data, app_data_len);
|
||||
if (!(parser.isValid() && parser.hasName())) {
|
||||
@@ -152,14 +169,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
|
||||
PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4);
|
||||
if (path) sendFlood(path, TXT_ACK_DELAY);
|
||||
} else {
|
||||
mesh::Packet* ack = createAck(ack_hash);
|
||||
if (ack) {
|
||||
if (from.out_path_len < 0) {
|
||||
sendFlood(ack, TXT_ACK_DELAY);
|
||||
} else {
|
||||
sendDirect(ack, from.out_path, from.out_path_len, TXT_ACK_DELAY);
|
||||
}
|
||||
}
|
||||
sendAckTo(from, ack_hash);
|
||||
}
|
||||
} else if (flags == TXT_TYPE_CLI_DATA) {
|
||||
onCommandDataRecv(from, packet, timestamp, (const char *) &data[5]); // let UI know
|
||||
@@ -185,14 +195,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
|
||||
PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4);
|
||||
if (path) sendFlood(path, TXT_ACK_DELAY);
|
||||
} else {
|
||||
mesh::Packet* ack = createAck(ack_hash);
|
||||
if (ack) {
|
||||
if (from.out_path_len < 0) {
|
||||
sendFlood(ack, TXT_ACK_DELAY);
|
||||
} else {
|
||||
sendDirect(ack, from.out_path, from.out_path_len, TXT_ACK_DELAY);
|
||||
}
|
||||
}
|
||||
sendAckTo(from, ack_hash);
|
||||
}
|
||||
} else {
|
||||
MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported message type: %u", (uint32_t) flags);
|
||||
|
||||
@@ -72,6 +72,7 @@ class BaseChatMesh : public mesh::Mesh {
|
||||
ConnectionInfo connections[MAX_CONNECTIONS];
|
||||
|
||||
mesh::Packet* composeMsgPacket(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char *text, uint32_t& expected_ack);
|
||||
void sendAckTo(const ContactInfo& dest, uint32_t ack_hash);
|
||||
|
||||
protected:
|
||||
BaseChatMesh(mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::PacketManager& mgr, mesh::MeshTables& tables)
|
||||
|
||||
@@ -51,7 +51,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
file.read((uint8_t *) &_prefs->sf, sizeof(_prefs->sf)); // 112
|
||||
file.read((uint8_t *) &_prefs->cr, sizeof(_prefs->cr)); // 113
|
||||
file.read((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114
|
||||
file.read((uint8_t *) &_prefs->reserved2, sizeof(_prefs->reserved2)); // 115
|
||||
file.read((uint8_t *) &_prefs->multi_acks, sizeof(_prefs->multi_acks)); // 115
|
||||
file.read((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116
|
||||
file.read((uint8_t *) &_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120
|
||||
file.read(pad, 3); // 121
|
||||
@@ -69,6 +69,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
_prefs->sf = constrain(_prefs->sf, 7, 12);
|
||||
_prefs->cr = constrain(_prefs->cr, 5, 8);
|
||||
_prefs->tx_power_dbm = constrain(_prefs->tx_power_dbm, 1, 30);
|
||||
_prefs->multi_acks = constrain(_prefs->multi_acks, 0, 1);
|
||||
|
||||
file.close();
|
||||
}
|
||||
@@ -106,7 +107,7 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
|
||||
file.write((uint8_t *) &_prefs->sf, sizeof(_prefs->sf)); // 112
|
||||
file.write((uint8_t *) &_prefs->cr, sizeof(_prefs->cr)); // 113
|
||||
file.write((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114
|
||||
file.write((uint8_t *) &_prefs->reserved2, sizeof(_prefs->reserved2)); // 115
|
||||
file.write((uint8_t *) &_prefs->multi_acks, sizeof(_prefs->multi_acks)); // 115
|
||||
file.write((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116
|
||||
file.write((uint8_t *) &_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120
|
||||
file.write(pad, 3); // 121
|
||||
@@ -131,7 +132,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
||||
if (memcmp(command, "reboot", 6) == 0) {
|
||||
_board->reboot(); // doesn't return
|
||||
} else if (memcmp(command, "advert", 6) == 0) {
|
||||
_callbacks->sendSelfAdvertisement(400);
|
||||
_callbacks->sendSelfAdvertisement(1500); // longer delay, give CLI response time to be sent first
|
||||
strcpy(reply, "OK - Advert sent");
|
||||
} else if (memcmp(command, "clock sync", 10) == 0) {
|
||||
uint32_t curr = getRTCClock()->getCurrentTime();
|
||||
@@ -164,6 +165,21 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
||||
}
|
||||
} else if (memcmp(command, "neighbors", 9) == 0) {
|
||||
_callbacks->formatNeighborsReply(reply);
|
||||
} else if (memcmp(command, "tempradio ", 10) == 0) {
|
||||
strcpy(tmp, &command[10]);
|
||||
const char *parts[5];
|
||||
int num = mesh::Utils::parseTextParts(tmp, parts, 5);
|
||||
float freq = num > 0 ? atof(parts[0]) : 0.0f;
|
||||
float bw = num > 1 ? atof(parts[1]) : 0.0f;
|
||||
uint8_t sf = num > 2 ? atoi(parts[2]) : 0;
|
||||
uint8_t cr = num > 3 ? atoi(parts[3]) : 0;
|
||||
int temp_timeout_mins = num > 4 ? atoi(parts[4]) : 0;
|
||||
if (freq >= 300.0f && freq <= 2500.0f && sf >= 7 && sf <= 12 && cr >= 5 && cr <= 8 && bw >= 7.0f && bw <= 500.0f && temp_timeout_mins > 0) {
|
||||
_callbacks->applyTempRadioParams(freq, bw, sf, cr, temp_timeout_mins);
|
||||
sprintf(reply, "OK - temp params for %d mins", temp_timeout_mins);
|
||||
} else {
|
||||
strcpy(reply, "Error, invalid params");
|
||||
}
|
||||
} else if (memcmp(command, "password ", 9) == 0) {
|
||||
// change admin password
|
||||
StrHelper::strncpy(_prefs->password, &command[9], sizeof(_prefs->password));
|
||||
@@ -180,6 +196,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
||||
sprintf(reply, "> %d", (uint32_t) _prefs->interference_threshold);
|
||||
} else if (memcmp(config, "agc.reset.interval", 18) == 0) {
|
||||
sprintf(reply, "> %d", ((uint32_t) _prefs->agc_reset_interval) * 4);
|
||||
} else if (memcmp(config, "multi.acks", 10) == 0) {
|
||||
sprintf(reply, "> %d", (uint32_t) _prefs->multi_acks);
|
||||
} else if (memcmp(config, "allow.read.only", 15) == 0) {
|
||||
sprintf(reply, "> %s", _prefs->allow_read_only ? "on" : "off");
|
||||
} else if (memcmp(config, "flood.advert.interval", 21) == 0) {
|
||||
@@ -235,6 +253,10 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
||||
_prefs->agc_reset_interval = atoi(&config[19]) / 4;
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else if (memcmp(config, "multi.acks ", 11) == 0) {
|
||||
_prefs->multi_acks = atoi(&config[11]);
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else if (memcmp(config, "allow.read.only ", 16) == 0) {
|
||||
_prefs->allow_read_only = memcmp(&config[16], "on", 2) == 0;
|
||||
savePrefs();
|
||||
|
||||
@@ -21,7 +21,7 @@ struct NodePrefs { // persisted to file
|
||||
uint8_t sf;
|
||||
uint8_t cr;
|
||||
uint8_t allow_read_only;
|
||||
uint8_t reserved2;
|
||||
uint8_t multi_acks;
|
||||
float bw;
|
||||
uint8_t flood_max;
|
||||
uint8_t interference_threshold;
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
virtual void formatNeighborsReply(char *reply) = 0;
|
||||
virtual const uint8_t* getSelfIdPubKey() = 0;
|
||||
virtual void clearStats() = 0;
|
||||
virtual void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) = 0;
|
||||
};
|
||||
|
||||
class CommonCLI {
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -96,8 +96,9 @@ bool RadioLibWrapper::isInRecvMode() const {
|
||||
}
|
||||
|
||||
int RadioLibWrapper::recvRaw(uint8_t* bytes, int sz) {
|
||||
int len = 0;
|
||||
if (state & STATE_INT_READY) {
|
||||
int len = _radio->getPacketLength();
|
||||
len = _radio->getPacketLength();
|
||||
if (len > 0) {
|
||||
if (len > sz) { len = sz; }
|
||||
int err = _radio->readData(bytes, len);
|
||||
@@ -110,7 +111,6 @@ int RadioLibWrapper::recvRaw(uint8_t* bytes, int sz) {
|
||||
}
|
||||
}
|
||||
state = STATE_IDLE; // need another startReceive()
|
||||
return len;
|
||||
}
|
||||
|
||||
if (state != STATE_RX) {
|
||||
@@ -121,7 +121,7 @@ int RadioLibWrapper::recvRaw(uint8_t* bytes, int sz) {
|
||||
MESH_DEBUG_PRINTLN("RadioLibWrapper: error: startReceive(%d)", err);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
uint32_t RadioLibWrapper::getEstAirtimeFor(int len_bytes) {
|
||||
File renamed without changes.
@@ -1,5 +1,11 @@
|
||||
#include "EnvironmentSensorManager.h"
|
||||
|
||||
#if ENV_PIN_SDA && ENV_PIN_SCL
|
||||
#define TELEM_WIRE &Wire1 // Use Wire1 as the I2C bus for Environment Sensors
|
||||
#else
|
||||
#define TELEM_WIRE &Wire // Use default I2C bus for Environment Sensors
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_AHTX0
|
||||
#define TELEM_AHTX_ADDRESS 0x38 // AHT10, AHT20 temperature and humidity sensor I2C address
|
||||
#include <Adafruit_AHTX0.h>
|
||||
@@ -47,13 +53,43 @@ static Adafruit_INA3221 INA3221;
|
||||
static Adafruit_INA219 INA219(TELEM_INA219_ADDRESS);
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_MLX90614
|
||||
#define TELEM_MLX90614_ADDRESS 0x5A // MLX90614 IR temperature sensor I2C address
|
||||
#include <Adafruit_MLX90614.h>
|
||||
static Adafruit_MLX90614 MLX90614;
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_VL53L0X
|
||||
#define TELEM_VL53L0X_ADDRESS 0x29 // VL53L0X time-of-flight distance sensor I2C address
|
||||
#include <Adafruit_VL53L0X.h>
|
||||
static Adafruit_VL53L0X VL53L0X;
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_GPS && RAK_BOARD
|
||||
static uint32_t gpsResetPin = 0;
|
||||
static bool i2cGPSFlag = false;
|
||||
static bool serialGPSFlag = false;
|
||||
#define TELEM_RAK12500_ADDRESS 0x42 //RAK12500 Ublox GPS via i2c
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h>
|
||||
static SFE_UBLOX_GNSS ublox_GNSS;
|
||||
#endif
|
||||
|
||||
bool EnvironmentSensorManager::begin() {
|
||||
#if ENV_INCLUDE_GPS
|
||||
#if RAK_BOARD
|
||||
rakGPSInit(); //probe base board/sockets for GPS
|
||||
#else
|
||||
initBasicGPS();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENV_PIN_SDA && ENV_PIN_SCL
|
||||
Wire1.begin(ENV_PIN_SDA, ENV_PIN_SCL, 100000);
|
||||
MESH_DEBUG_PRINTLN("Second I2C initialized on pins SDA: %d SCL: %d", ENV_PIN_SDA, ENV_PIN_SCL);
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_AHTX0
|
||||
if (AHTX0.begin(&Wire, 0, TELEM_AHTX_ADDRESS)) {
|
||||
if (AHTX0.begin(TELEM_WIRE, 0, TELEM_AHTX_ADDRESS)) {
|
||||
MESH_DEBUG_PRINTLN("Found AHT10/AHT20 at address: %02X", TELEM_AHTX_ADDRESS);
|
||||
AHTX0_initialized = true;
|
||||
} else {
|
||||
@@ -63,7 +99,7 @@ bool EnvironmentSensorManager::begin() {
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BME280
|
||||
if (BME280.begin(TELEM_BME280_ADDRESS, &Wire)) {
|
||||
if (BME280.begin(TELEM_BME280_ADDRESS, TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found BME280 at address: %02X", TELEM_BME280_ADDRESS);
|
||||
MESH_DEBUG_PRINTLN("BME sensor ID: %02X", BME280.sensorID());
|
||||
BME280_initialized = true;
|
||||
@@ -105,7 +141,7 @@ bool EnvironmentSensorManager::begin() {
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA3221
|
||||
if (INA3221.begin(TELEM_INA3221_ADDRESS, &Wire)) {
|
||||
if (INA3221.begin(TELEM_INA3221_ADDRESS, TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found INA3221 at address: %02X", TELEM_INA3221_ADDRESS);
|
||||
MESH_DEBUG_PRINTLN("%04X %04X", INA3221.getDieID(), INA3221.getManufacturerID());
|
||||
|
||||
@@ -120,7 +156,7 @@ bool EnvironmentSensorManager::begin() {
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA219
|
||||
if (INA219.begin(&Wire)) {
|
||||
if (INA219.begin(TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found INA219 at address: %02X", TELEM_INA219_ADDRESS);
|
||||
INA219_initialized = true;
|
||||
} else {
|
||||
@@ -129,6 +165,26 @@ bool EnvironmentSensorManager::begin() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_MLX90614
|
||||
if (MLX90614.begin(TELEM_MLX90614_ADDRESS, TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found MLX90614 at address: %02X", TELEM_MLX90614_ADDRESS);
|
||||
MLX90614_initialized = true;
|
||||
} else {
|
||||
MLX90614_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("MLX90614 was not found at I2C address %02X", TELEM_MLX90614_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_VL53L0X
|
||||
if (VL53L0X.begin(TELEM_VL53L0X_ADDRESS, false, TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found VL53L0X at address: %02X", TELEM_VL53L0X_ADDRESS);
|
||||
VL53L0X_initialized = true;
|
||||
} else {
|
||||
VL53L0X_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("VL53L0X was not found at I2C address %02X", TELEM_VL53L0X_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -162,7 +218,7 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen
|
||||
#if ENV_INCLUDE_BMP280
|
||||
if (BMP280_initialized) {
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, BMP280.readTemperature());
|
||||
telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, BMP280.readPressure());
|
||||
telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, BMP280.readPressure()/100);
|
||||
telemetry.addAltitude(TELEM_CHANNEL_SELF, BME280.readAltitude(TELEM_BME280_SEALEVELPRESSURE_HPA));
|
||||
}
|
||||
#endif
|
||||
@@ -209,6 +265,25 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_MLX90614
|
||||
if (MLX90614_initialized) {
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, MLX90614.readObjectTempC());
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF + 1, MLX90614.readAmbientTempC());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_VL53L0X
|
||||
if (VL53L0X_initialized) {
|
||||
VL53L0X_RangingMeasurementData_t measure;
|
||||
VL53L0X.rangingTest(&measure, false); // pass in 'true' to get debug data
|
||||
if (measure.RangeStatus != 4) { // phase failures
|
||||
telemetry.addDistance(TELEM_CHANNEL_SELF, measure.RangeMilliMeter / 1000.0f); // convert mm to m
|
||||
} else {
|
||||
telemetry.addDistance(TELEM_CHANNEL_SELF, 0.0f); // no valid measurement
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -296,8 +371,85 @@ void EnvironmentSensorManager::initBasicGPS() {
|
||||
gps_active = false; //Set GPS visibility off until setting is changed
|
||||
}
|
||||
|
||||
#ifdef RAK_BOARD
|
||||
void EnvironmentSensorManager::rakGPSInit(){
|
||||
|
||||
Serial1.setPins(PIN_GPS_TX, PIN_GPS_RX);
|
||||
|
||||
#ifdef GPS_BAUD_RATE
|
||||
Serial1.begin(GPS_BAUD_RATE);
|
||||
#else
|
||||
Serial1.begin(9600);
|
||||
#endif
|
||||
|
||||
//search for the correct IO standby pin depending on socket used
|
||||
if(gpsIsAwake(WB_IO2)){
|
||||
// MESH_DEBUG_PRINTLN("RAK base board is RAK19007/10");
|
||||
// MESH_DEBUG_PRINTLN("GPS is installed on Socket A");
|
||||
}
|
||||
else if(gpsIsAwake(WB_IO4)){
|
||||
// MESH_DEBUG_PRINTLN("RAK base board is RAK19003/9");
|
||||
// MESH_DEBUG_PRINTLN("GPS is installed on Socket C");
|
||||
}
|
||||
else if(gpsIsAwake(WB_IO5)){
|
||||
// MESH_DEBUG_PRINTLN("RAK base board is RAK19001/11");
|
||||
// MESH_DEBUG_PRINTLN("GPS is installed on Socket F");
|
||||
}
|
||||
else{
|
||||
MESH_DEBUG_PRINTLN("No GPS found");
|
||||
gps_active = false;
|
||||
gps_detected = false;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef FORCE_GPS_ALIVE // for use with repeaters, until GPS toggle is implimented
|
||||
//Now that GPS is found and set up, set to sleep for initial state
|
||||
stop_gps();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool EnvironmentSensorManager::gpsIsAwake(uint8_t ioPin){
|
||||
|
||||
//set initial waking state
|
||||
pinMode(ioPin,OUTPUT);
|
||||
digitalWrite(ioPin,LOW);
|
||||
delay(500);
|
||||
digitalWrite(ioPin,HIGH);
|
||||
delay(500);
|
||||
|
||||
//Try to init RAK12500 on I2C
|
||||
if (ublox_GNSS.begin(Wire) == true){
|
||||
MESH_DEBUG_PRINTLN("RAK12500 GPS init correctly with pin %i",ioPin);
|
||||
ublox_GNSS.setI2COutput(COM_TYPE_NMEA);
|
||||
ublox_GNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT);
|
||||
gpsResetPin = ioPin;
|
||||
i2cGPSFlag = true;
|
||||
gps_active = true;
|
||||
gps_detected = true;
|
||||
return true;
|
||||
}
|
||||
else if(Serial1){
|
||||
MESH_DEBUG_PRINTLN("Serial GPS init correctly and is turned on");
|
||||
if(PIN_GPS_EN){
|
||||
gpsResetPin = PIN_GPS_EN;
|
||||
}
|
||||
serialGPSFlag = true;
|
||||
gps_active = true;
|
||||
gps_detected = true;
|
||||
return true;
|
||||
}
|
||||
MESH_DEBUG_PRINTLN("GPS did not init with this IO pin... try the next");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void EnvironmentSensorManager::start_gps() {
|
||||
gps_active = true;
|
||||
#ifdef RAK_BOARD
|
||||
pinMode(gpsResetPin, OUTPUT);
|
||||
digitalWrite(gpsResetPin, HIGH);
|
||||
return;
|
||||
#endif
|
||||
#ifdef PIN_GPS_EN
|
||||
pinMode(PIN_GPS_EN, OUTPUT);
|
||||
digitalWrite(PIN_GPS_EN, HIGH);
|
||||
@@ -309,6 +461,11 @@ void EnvironmentSensorManager::start_gps() {
|
||||
|
||||
void EnvironmentSensorManager::stop_gps() {
|
||||
gps_active = false;
|
||||
#ifdef RAK_BOARD
|
||||
pinMode(gpsResetPin, OUTPUT);
|
||||
digitalWrite(gpsResetPin, LOW);
|
||||
return;
|
||||
#endif
|
||||
#ifdef PIN_GPS_EN
|
||||
pinMode(PIN_GPS_EN, OUTPUT);
|
||||
digitalWrite(PIN_GPS_EN, LOW);
|
||||
@@ -324,12 +481,29 @@ void EnvironmentSensorManager::loop() {
|
||||
_location->loop();
|
||||
|
||||
if (millis() > next_gps_update) {
|
||||
if (gps_active && _location->isValid()) {
|
||||
if(gps_active){
|
||||
#ifndef RAK_BOARD
|
||||
if (_location->isValid()) {
|
||||
node_lat = ((double)_location->getLatitude())/1000000.;
|
||||
node_lon = ((double)_location->getLongitude())/1000000.;
|
||||
MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon);
|
||||
}
|
||||
#else
|
||||
if(i2cGPSFlag){
|
||||
node_lat = ((double)ublox_GNSS.getLatitude())/10000000.;
|
||||
node_lon = ((double)ublox_GNSS.getLongitude())/10000000.;
|
||||
MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon);
|
||||
}
|
||||
else if (serialGPSFlag && _location->isValid()) {
|
||||
node_lat = ((double)_location->getLatitude())/1000000.;
|
||||
node_lon = ((double)_location->getLongitude())/1000000.;
|
||||
MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon);
|
||||
}
|
||||
//else
|
||||
//MESH_DEBUG_PRINTLN("No valid GPS data");
|
||||
#endif
|
||||
}
|
||||
next_gps_update = millis() + 1000;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -15,6 +15,8 @@ protected:
|
||||
bool INA219_initialized = false;
|
||||
bool SHTC3_initialized = false;
|
||||
bool LPS22HB_initialized = false;
|
||||
bool MLX90614_initialized = false;
|
||||
bool VL53L0X_initialized = false;
|
||||
|
||||
bool gps_detected = false;
|
||||
bool gps_active = false;
|
||||
@@ -24,6 +26,10 @@ protected:
|
||||
void start_gps();
|
||||
void stop_gps();
|
||||
void initBasicGPS();
|
||||
#ifdef RAK_BOARD
|
||||
void rakGPSInit();
|
||||
bool gpsIsAwake(uint8_t ioPin);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/ESP32Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/CustomSX1268Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1268Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
|
||||
|
||||
@@ -10,43 +10,10 @@ ESP32RTCClock fallback_clock;
|
||||
AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
||||
SensorManager sensors;
|
||||
|
||||
#ifndef LORA_CR
|
||||
#define LORA_CR 5
|
||||
#endif
|
||||
|
||||
bool radio_init() {
|
||||
fallback_clock.begin();
|
||||
rtc_clock.begin(Wire);
|
||||
|
||||
#ifdef SX126X_DIO3_TCXO_VOLTAGE
|
||||
float tcxo = SX126X_DIO3_TCXO_VOLTAGE;
|
||||
#else
|
||||
float tcxo = 1.6f;
|
||||
#endif
|
||||
|
||||
#if defined(P_LORA_SCLK)
|
||||
SPI.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
|
||||
#endif
|
||||
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo);
|
||||
if (status != RADIOLIB_ERR_NONE) {
|
||||
Serial.print("ERROR: radio init failed: ");
|
||||
Serial.println(status);
|
||||
return false; // fail
|
||||
}
|
||||
|
||||
radio.setCRC(1);
|
||||
|
||||
#ifdef SX126X_CURRENT_LIMIT
|
||||
radio.setCurrentLimit(SX126X_CURRENT_LIMIT);
|
||||
#endif
|
||||
#ifdef SX126X_DIO2_AS_RF_SWITCH
|
||||
radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH);
|
||||
#endif
|
||||
#ifdef SX126X_RX_BOOSTED_GAIN
|
||||
radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN);
|
||||
#endif
|
||||
|
||||
return true; // success
|
||||
rtc_clock.begin(Wire);
|
||||
return radio.std_init(&SPI);
|
||||
}
|
||||
|
||||
uint32_t radio_get_rng_seed() {
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include "HT-CT62Board.h"
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/HeltecV3Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/HeltecV2Board.h>
|
||||
#include <helpers/CustomSX1276Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1276Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
|
||||
@@ -147,6 +147,30 @@ lib_deps =
|
||||
${Heltec_lora32_v3.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:Heltec_v3_sensor]
|
||||
extends = Heltec_lora32_v3
|
||||
build_flags =
|
||||
${Heltec_lora32_v3.build_flags}
|
||||
-D ADVERT_NAME='"Heltec v3 Sensor"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D ENV_PIN_SDA=33
|
||||
-D ENV_PIN_SCL=34
|
||||
-D ENV_INCLUDE_MLX90614=1
|
||||
-D ENV_INCLUDE_VL53L0X=1
|
||||
-D DISPLAY_CLASS=SSD1306Display
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<../examples/simple_sensor>
|
||||
lib_deps =
|
||||
${Heltec_lora32_v3.lib_deps}
|
||||
${esp32_ota.lib_deps}
|
||||
adafruit/Adafruit MLX90614 Library @ ^2.1.5
|
||||
adafruit/Adafruit_VL53L0X @ ^1.2.4
|
||||
|
||||
[env:Heltec_WSL3_repeater]
|
||||
extends = Heltec_lora32_v3
|
||||
build_flags =
|
||||
@@ -214,4 +238,3 @@ build_src_filter = ${Heltec_lora32_v3.build_src_filter}
|
||||
lib_deps =
|
||||
${Heltec_lora32_v3.lib_deps}
|
||||
${esp32_ota.lib_deps}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/HeltecV3Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/HeltecV3Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/ESP32Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/ESP32Board.h>
|
||||
#include <helpers/CustomSX1276Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1276Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/esp32/TBeamBoard.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
//#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/esp32/TBeamBoard.h>
|
||||
#include <helpers/CustomSX1276Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1276Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/esp32/TBeamBoard.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/ESP32Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/LilyGoTLoraBoard.h>
|
||||
#include <helpers/CustomSX1276Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1276Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/MeshadventurerBoard.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/CustomSX1268Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1268Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <MinewsemiME25LS01Board.h>
|
||||
#include <helpers/CustomLR1110Wrapper.h>
|
||||
#include <helpers/radiolib/CustomLR1110Wrapper.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include "nano-g2.h"
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
@@ -12,8 +12,7 @@
|
||||
#endif
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
|
||||
class NanoG2UltraSensorManager : public SensorManager
|
||||
{
|
||||
class NanoG2UltraSensorManager : public SensorManager {
|
||||
bool gps_active = false;
|
||||
LocationProvider *_location;
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/rp2040/PicoWBoard.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <PromicroBoard.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/CustomLLCC68Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
#include <helpers/ui/SSD1306Display.h>
|
||||
@@ -27,4 +26,3 @@ uint32_t radio_get_rng_seed();
|
||||
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
|
||||
void radio_set_tx_power(uint8_t dbm);
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
|
||||
@@ -21,6 +21,14 @@ build_flags = ${rak3x72.build_flags}
|
||||
build_src_filter = ${rak3x72.build_src_filter}
|
||||
+<../examples/simple_repeater/main.cpp>
|
||||
|
||||
[env:rak3x72-sensor]
|
||||
extends = rak3x72
|
||||
build_flags = ${rak3x72.build_flags}
|
||||
-D ADVERT_NAME='"RAK3x72 Sensor"'
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
build_src_filter = ${rak3x72.build_src_filter}
|
||||
+<../examples/simple_sensor>
|
||||
|
||||
[env:rak3x72_companion_radio_usb]
|
||||
extends = rak3x72
|
||||
build_flags = ${rak3x72.build_flags}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/stm32/STM32Board.h>
|
||||
#include <helpers/CustomSTM32WLxWrapper.h>
|
||||
#include <helpers/radiolib/CustomSTM32WLxWrapper.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
uint32_t raw = 0;
|
||||
for (int i=0; i<8;i++) {
|
||||
raw += analogRead(PIN_VBAT_READ);
|
||||
}
|
||||
}
|
||||
return ((double)raw) * ADC_MULTIPLIER / 8 / 4096;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -13,14 +13,11 @@
|
||||
#define P_LORA_MOSI 44
|
||||
#define SX126X_POWER_EN 37
|
||||
|
||||
#define P_GPS_SDA 13 //GPS SDA pin (output option)
|
||||
#define P_GPS_SCL 14 //GPS SCL pin (output option)
|
||||
#define P_GPS_TX 16 //GPS TX pin
|
||||
#define P_GPS_RX 15 //GPS RX pin
|
||||
#define P_GPS_STANDBY_A 34 //GPS Reset/Standby pin (IO2 for socket A)
|
||||
#define P_GPS_STANDBY_C 4 //GPS Reset/Standby pin (IO4 for socket C)
|
||||
#define P_GPS_STANDBY_F 9 //GPS Reset/Standby pin (IO5 for socket F)
|
||||
#define P_GPS_1PPS 17 //GPS PPS pin
|
||||
//#define PIN_GPS_SDA 13 //GPS SDA pin (output option)
|
||||
//#define PIN_GPS_SCL 14 //GPS SCL pin (output option)
|
||||
//#define PIN_GPS_TX 16 //GPS TX pin
|
||||
//#define PIN_GPS_RX 15 //GPS RX pin
|
||||
#define PIN_GPS_1PPS 17 //GPS PPS pin
|
||||
#define GPS_BAUD_RATE 9600
|
||||
#define GPS_ADDRESS 0x42 //i2c address for GPS
|
||||
|
||||
|
||||
@@ -6,20 +6,41 @@ board_check = true
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
-I variants/rak4631
|
||||
-D RAK_4631
|
||||
-D RAK_BOARD
|
||||
-D PIN_BOARD_SCL=14
|
||||
-D PIN_BOARD_SDA=13
|
||||
-D PIN_GPS_TX=16
|
||||
-D PIN_GPS_RX=15
|
||||
-D PIN_GPS_EN=-1
|
||||
-D PIN_OLED_RESET=-1
|
||||
-D RADIO_CLASS=CustomSX1262
|
||||
-D WRAPPER_CLASS=CustomSX1262Wrapper
|
||||
-D LORA_TX_POWER=22
|
||||
-D SX126X_CURRENT_LIMIT=140
|
||||
-D SX126X_RX_BOOSTED_GAIN=1
|
||||
-D ENV_INCLUDE_GPS=1
|
||||
-D ENV_INCLUDE_AHTX0=1
|
||||
-D ENV_INCLUDE_BME280=1
|
||||
-D ENV_INCLUDE_BMP280=1
|
||||
-D ENV_INCLUDE_SHTC3=1
|
||||
-D ENV_INCLUDE_LPS22HB=1
|
||||
-D ENV_INCLUDE_INA3221=1
|
||||
-D ENV_INCLUDE_INA219=1
|
||||
build_src_filter = ${nrf52_base.build_src_filter}
|
||||
+<../variants/rak4631>
|
||||
+<helpers/sensors>
|
||||
lib_deps =
|
||||
${nrf52_base.lib_deps}
|
||||
adafruit/Adafruit SSD1306 @ ^2.5.13
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
arduino-libraries/Arduino_LPS22HB@^1.0.2
|
||||
adafruit/Adafruit INA3221 Library @ ^1.0.1
|
||||
adafruit/Adafruit INA219 @ ^1.2.3
|
||||
adafruit/Adafruit AHTX0 @ ^2.0.5
|
||||
adafruit/Adafruit BME280 Library @ ^2.3.0
|
||||
adafruit/Adafruit BMP280 Library @ ^2.6.8
|
||||
adafruit/Adafruit SHTC3 Library @ ^1.0.1
|
||||
sparkfun/SparkFun u-blox GNSS Arduino Library@^2.2.27
|
||||
|
||||
[env:RAK_4631_Repeater]
|
||||
extends = rak4631
|
||||
@@ -37,30 +58,6 @@ build_src_filter = ${rak4631.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<../examples/simple_repeater>
|
||||
|
||||
[env:RAK_4631_GPS_Repeater]
|
||||
extends = rak4631
|
||||
build_flags =
|
||||
${rak4631.build_flags}
|
||||
-D DISPLAY_CLASS=SSD1306Display
|
||||
-D ADVERT_NAME='"RAK4631 GPS Repeater"'
|
||||
-D ADVERT_LAT=0.0
|
||||
-D ADVERT_LON=0.0
|
||||
-D ADMIN_PASSWORD='"password"'
|
||||
-D MAX_NEIGHBOURS=8
|
||||
-D FORCE_GPS_ALIVE=1
|
||||
-D ENV_INCLUDE_GPS=1
|
||||
-D ENV_INCLUDE_BME680=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${rak4631.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<../examples/simple_repeater>
|
||||
lib_deps =
|
||||
${rak4631.lib_deps}
|
||||
sparkfun/SparkFun u-blox GNSS Arduino Library @ ^2.2.27
|
||||
https://github.com/boschsensortec/Bosch-BSEC2-Library
|
||||
https://github.com/boschsensortec/Bosch-BME68x-Library
|
||||
|
||||
[env:RAK_4631_room_server]
|
||||
extends = rak4631
|
||||
build_flags =
|
||||
@@ -117,33 +114,6 @@ lib_deps =
|
||||
${rak4631.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:RAK_4631_GPS_companion_radio_ble]
|
||||
extends = rak4631
|
||||
build_flags =
|
||||
${rak4631.build_flags}
|
||||
-D PIN_USER_BTN=9
|
||||
-D PIN_USER_BTN_ANA=31
|
||||
-D DISPLAY_CLASS=SSD1306Display
|
||||
-D MAX_CONTACTS=100
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D BLE_DEBUG_LOGGING=1
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
-D ENV_INCLUDE_GPS=1
|
||||
-D ENV_INCLUDE_BME680=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${rak4631.build_src_filter}
|
||||
+<helpers/ui/SSD1306Display.cpp>
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<../examples/companion_radio>
|
||||
lib_deps =
|
||||
${rak4631.lib_deps}
|
||||
sparkfun/SparkFun u-blox GNSS Arduino Library @ ^2.2.27
|
||||
https://github.com/boschsensortec/Bosch-BSEC2-Library
|
||||
https://github.com/boschsensortec/Bosch-BME68x-Library
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:RAK_4631_terminal_chat]
|
||||
extends = rak4631
|
||||
build_flags =
|
||||
|
||||
+8
-392
@@ -1,10 +1,13 @@
|
||||
#include <Arduino.h>
|
||||
#include "target.h"
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/sensors/MicroNMEALocationProvider.h>
|
||||
|
||||
RAK4631Board board;
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
DISPLAY_CLASS display;
|
||||
#endif
|
||||
|
||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
|
||||
|
||||
WRAPPER_CLASS radio_driver(radio, board);
|
||||
@@ -13,80 +16,11 @@ VolatileRTCClock fallback_clock;
|
||||
AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
||||
|
||||
#if ENV_INCLUDE_GPS
|
||||
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Wire);
|
||||
RAK4631SensorManager sensors = RAK4631SensorManager(nmea);
|
||||
#include <helpers/sensors/MicroNMEALocationProvider.h>
|
||||
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
|
||||
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
|
||||
#else
|
||||
RAK4631SensorManager sensors;
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BME680
|
||||
#ifndef TELEM_BME680_ADDRESS
|
||||
#define TELEM_BME680_ADDRESS 0x76 // BME680 environmental sensor I2C address
|
||||
#endif
|
||||
#include <bsec2.h>
|
||||
static Bsec2 BME680;
|
||||
static float rawPressure = 0;
|
||||
static float rawTemperature = 0;
|
||||
static float compTemperature = 0;
|
||||
static float rawHumidity = 0;
|
||||
static float compHumidity = 0;
|
||||
static float readIAQ = 0;
|
||||
static float readStaticIAQ = 0;
|
||||
static float readCO2 = 0;
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
DISPLAY_CLASS display;
|
||||
#endif
|
||||
|
||||
#ifdef MESH_DEBUG
|
||||
uint32_t deviceOnline = 0x00;
|
||||
static void scanDevices(TwoWire *w)
|
||||
{
|
||||
uint8_t err, addr;
|
||||
int nDevices = 0;
|
||||
uint32_t start = 0;
|
||||
|
||||
Serial.println("Scanning I2C for Devices");
|
||||
for (addr = 1; addr < 127; addr++) {
|
||||
start = millis();
|
||||
w->beginTransmission(addr); delay(2);
|
||||
err = w->endTransmission();
|
||||
if (err == 0) {
|
||||
nDevices++;
|
||||
switch (addr) {
|
||||
case 0x42:
|
||||
Serial.println("\tFound RAK12500 GPS Sensor");
|
||||
deviceOnline |= RAK12500_ONLINE;
|
||||
break;
|
||||
case 0x76:
|
||||
Serial.println("\tFound RAK1906 Environment Sensor");
|
||||
deviceOnline |= BME680_ONLINE;
|
||||
break;
|
||||
default:
|
||||
Serial.print("\tI2C device found at address 0x");
|
||||
if (addr < 16) {
|
||||
Serial.print("0");
|
||||
}
|
||||
Serial.print(addr, HEX);
|
||||
Serial.println(" !");
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (err == 4) {
|
||||
Serial.print("Unknow error at address 0x");
|
||||
if (addr < 16) {
|
||||
Serial.print("0");
|
||||
}
|
||||
Serial.println(addr, HEX);
|
||||
}
|
||||
}
|
||||
if (nDevices == 0)
|
||||
Serial.println("No I2C devices found\n");
|
||||
|
||||
Serial.println("Scan for devices is complete.");
|
||||
Serial.println("\n");
|
||||
}
|
||||
EnvironmentSensorManager sensors;
|
||||
#endif
|
||||
|
||||
bool radio_init() {
|
||||
@@ -109,324 +43,6 @@ void radio_set_tx_power(uint8_t dbm) {
|
||||
radio.setOutputPower(dbm);
|
||||
}
|
||||
|
||||
#if ENV_INCLUDE_GPS
|
||||
void RAK4631SensorManager::start_gps()
|
||||
{
|
||||
//function currently not used
|
||||
gps_active = true;
|
||||
pinMode(disStandbyPin, OUTPUT);
|
||||
digitalWrite(disStandbyPin, 1);
|
||||
MESH_DEBUG_PRINTLN("GPS should be on now");
|
||||
}
|
||||
|
||||
void RAK4631SensorManager::stop_gps()
|
||||
{
|
||||
//function currently not used
|
||||
gps_active = false;
|
||||
pinMode(disStandbyPin, OUTPUT);
|
||||
digitalWrite(disStandbyPin, 0);
|
||||
MESH_DEBUG_PRINTLN("GPS should be off now");
|
||||
}
|
||||
|
||||
void RAK4631SensorManager::sleep_gps() {
|
||||
gps_active = false;
|
||||
ublox_GNSS.powerSaveMode();
|
||||
MESH_DEBUG_PRINTLN("GPS should be sleeping now");
|
||||
}
|
||||
|
||||
void RAK4631SensorManager::wake_gps() {
|
||||
gps_active = true;
|
||||
ublox_GNSS.powerSaveMode(false);
|
||||
MESH_DEBUG_PRINTLN("GPS should be waking now");
|
||||
}
|
||||
|
||||
bool RAK4631SensorManager::gpsIsAwake(uint32_t ioPin){
|
||||
|
||||
int pinInitialState = 0;
|
||||
|
||||
//set initial waking state
|
||||
pinMode(ioPin,OUTPUT);
|
||||
digitalWrite(ioPin,0);
|
||||
delay(1000);
|
||||
digitalWrite(ioPin,1);
|
||||
delay(1000);
|
||||
|
||||
if (ublox_GNSS.begin(Wire) == true){
|
||||
MESH_DEBUG_PRINTLN("GPS init correctly and GPS is turned on");
|
||||
ublox_GNSS.setI2COutput(COM_TYPE_NMEA);
|
||||
ublox_GNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT);
|
||||
disStandbyPin = ioPin;
|
||||
gps_active = true;
|
||||
gps_detected = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
MESH_DEBUG_PRINTLN("GPS failed to init on this IO pin... try the next");
|
||||
//digitalWrite(ioPin,pinInitialState); //reset the IO pin to initial state
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BME680
|
||||
static void checkBMEStatus(Bsec2 bsec) {
|
||||
if (bsec.status < BSEC_OK)
|
||||
{
|
||||
MESH_DEBUG_PRINTLN("BSEC error code : %f", float(bsec.status));
|
||||
}
|
||||
else if (bsec.status > BSEC_OK)
|
||||
{
|
||||
MESH_DEBUG_PRINTLN("BSEC warning code : %f", float(bsec.status));
|
||||
}
|
||||
|
||||
if (bsec.sensor.status < BME68X_OK)
|
||||
{
|
||||
MESH_DEBUG_PRINTLN("BME68X error code : %f", bsec.sensor.status);
|
||||
}
|
||||
else if (bsec.sensor.status > BME68X_OK)
|
||||
{
|
||||
MESH_DEBUG_PRINTLN("BME68X warning code : %f", bsec.sensor.status);
|
||||
}
|
||||
}
|
||||
|
||||
static void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec) {
|
||||
if (!outputs.nOutputs) {
|
||||
MESH_DEBUG_PRINTLN("No new data to report out");
|
||||
return;
|
||||
}
|
||||
|
||||
MESH_DEBUG_PRINTLN("BSEC outputs:\n\tTime stamp = %f", (int) (outputs.output[0].time_stamp / INT64_C(1000000)));
|
||||
for (uint8_t i = 0; i < outputs.nOutputs; i++) {
|
||||
const bsecData output = outputs.output[i];
|
||||
switch (output.sensor_id)
|
||||
{
|
||||
case BSEC_OUTPUT_IAQ:
|
||||
readIAQ = output.signal;
|
||||
MESH_DEBUG_PRINTLN("\tIAQ = %f", output.signal);
|
||||
MESH_DEBUG_PRINTLN("\tIAQ accuracy = %f", output.accuracy);
|
||||
break;
|
||||
case BSEC_OUTPUT_RAW_TEMPERATURE:
|
||||
rawTemperature = output.signal;
|
||||
MESH_DEBUG_PRINTLN("\tTemperature = %f", output.signal);
|
||||
break;
|
||||
case BSEC_OUTPUT_RAW_PRESSURE:
|
||||
rawPressure = output.signal;
|
||||
MESH_DEBUG_PRINTLN("\tPressure = %f", output.signal);
|
||||
break;
|
||||
case BSEC_OUTPUT_RAW_HUMIDITY:
|
||||
rawHumidity = output.signal;
|
||||
MESH_DEBUG_PRINTLN("\tHumidity = %f", output.signal);
|
||||
break;
|
||||
case BSEC_OUTPUT_RAW_GAS:
|
||||
MESH_DEBUG_PRINTLN("\tGas resistance = %f", output.signal);
|
||||
break;
|
||||
case BSEC_OUTPUT_STABILIZATION_STATUS:
|
||||
MESH_DEBUG_PRINTLN("\tStabilization status = %f", output.signal);
|
||||
break;
|
||||
case BSEC_OUTPUT_RUN_IN_STATUS:
|
||||
MESH_DEBUG_PRINTLN("\tRun in status = %f", output.signal);
|
||||
break;
|
||||
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
|
||||
compTemperature = output.signal;
|
||||
MESH_DEBUG_PRINTLN("\tCompensated temperature = %f", output.signal);
|
||||
break;
|
||||
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
|
||||
compHumidity = output.signal;
|
||||
MESH_DEBUG_PRINTLN("\tCompensated humidity = %f", output.signal);
|
||||
break;
|
||||
case BSEC_OUTPUT_STATIC_IAQ:
|
||||
readStaticIAQ = output.signal;
|
||||
MESH_DEBUG_PRINTLN("\tStatic IAQ = %f", output.signal);
|
||||
break;
|
||||
case BSEC_OUTPUT_CO2_EQUIVALENT:
|
||||
readCO2 = output.signal;
|
||||
MESH_DEBUG_PRINTLN("\tCO2 Equivalent = %f", output.signal);
|
||||
break;
|
||||
case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
|
||||
MESH_DEBUG_PRINTLN("\tbVOC equivalent = %f", output.signal);
|
||||
break;
|
||||
case BSEC_OUTPUT_GAS_PERCENTAGE:
|
||||
MESH_DEBUG_PRINTLN("\tGas percentage = %f", output.signal);
|
||||
break;
|
||||
case BSEC_OUTPUT_COMPENSATED_GAS:
|
||||
MESH_DEBUG_PRINTLN("\tCompensated gas = %f", output.signal);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool RAK4631SensorManager::begin() {
|
||||
|
||||
#ifdef MESH_DEBUG
|
||||
scanDevices(&Wire);
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_GPS
|
||||
//search for the correct IO standby pin depending on socket used
|
||||
if(gpsIsAwake(P_GPS_STANDBY_A)){
|
||||
MESH_DEBUG_PRINTLN("GPS is on socket A");
|
||||
}
|
||||
else if(gpsIsAwake(P_GPS_STANDBY_C)){
|
||||
MESH_DEBUG_PRINTLN("GPS is on socket C");
|
||||
}
|
||||
else if(gpsIsAwake(P_GPS_STANDBY_F)){
|
||||
MESH_DEBUG_PRINTLN("GPS is on socket F");
|
||||
}
|
||||
else{
|
||||
MESH_DEBUG_PRINTLN("Error: No GPS found on sockets A, C or F");
|
||||
gps_active = false;
|
||||
gps_detected = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef FORCE_GPS_ALIVE
|
||||
//Now that GPS is found and set up, set to sleep for initial state
|
||||
stop_gps();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BME680
|
||||
|
||||
bsecSensor sensorList[5] = {
|
||||
BSEC_OUTPUT_IAQ,
|
||||
// BSEC_OUTPUT_RAW_TEMPERATURE,
|
||||
BSEC_OUTPUT_RAW_PRESSURE,
|
||||
// BSEC_OUTPUT_RAW_HUMIDITY,
|
||||
// BSEC_OUTPUT_RAW_GAS,
|
||||
// BSEC_OUTPUT_STABILIZATION_STATUS,
|
||||
// BSEC_OUTPUT_RUN_IN_STATUS,
|
||||
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
|
||||
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
|
||||
BSEC_OUTPUT_STATIC_IAQ,
|
||||
// BSEC_OUTPUT_CO2_EQUIVALENT,
|
||||
// BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
|
||||
// BSEC_OUTPUT_GAS_PERCENTAGE,
|
||||
// BSEC_OUTPUT_COMPENSATED_GAS
|
||||
};
|
||||
|
||||
if(!BME680.begin(TELEM_BME680_ADDRESS, Wire)){
|
||||
checkBMEStatus(BME680);
|
||||
bme680_present = false;
|
||||
bme680_active = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
MESH_DEBUG_PRINTLN("Found BME680 at address: %02X", TELEM_BME680_ADDRESS);
|
||||
bme680_present = true;
|
||||
bme680_active = true;
|
||||
|
||||
if (SAMPLING_RATE == BSEC_SAMPLE_RATE_ULP)
|
||||
{
|
||||
BME680.setTemperatureOffset(BSEC_SAMPLE_RATE_ULP);
|
||||
}
|
||||
else if (SAMPLING_RATE == BSEC_SAMPLE_RATE_LP)
|
||||
{
|
||||
BME680.setTemperatureOffset(TEMP_OFFSET_LP);
|
||||
}
|
||||
|
||||
if (!BME680.updateSubscription(sensorList, ARRAY_LEN(sensorList), SAMPLING_RATE))
|
||||
{
|
||||
checkBMEStatus(BME680);
|
||||
}
|
||||
|
||||
BME680.attachCallback(newDataCallback);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RAK4631SensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) {
|
||||
#ifdef ENV_INCLUDE_GPS
|
||||
if (requester_permissions & TELEM_PERM_LOCATION && gps_active) { // does requester have permission?
|
||||
telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (requester_permissions & TELEM_PERM_ENVIRONMENT) {
|
||||
|
||||
#if ENV_INCLUDE_BME680
|
||||
if (bme680_active) {
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, compTemperature);
|
||||
telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, compHumidity);
|
||||
telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, rawPressure);
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF+1, readIAQ);
|
||||
telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF+1, readStaticIAQ);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RAK4631SensorManager::loop() {
|
||||
static long next_update = 0;
|
||||
|
||||
#ifdef ENV_INCLUDE_GPS
|
||||
_nmea->loop();
|
||||
#endif
|
||||
|
||||
if (millis() > next_update) {
|
||||
|
||||
#ifdef ENV_INCLUDE_GPS
|
||||
if(gps_active){
|
||||
node_lat = (double)ublox_GNSS.getLatitude()/10000000.;
|
||||
node_lon = (double)ublox_GNSS.getLongitude()/10000000.;
|
||||
node_altitude = (double)ublox_GNSS.getAltitude()/1000.;
|
||||
MESH_DEBUG_PRINT("lat %f lon %f alt %f\r\n", node_lat, node_lon, node_altitude);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENV_INCLUDE_BME680
|
||||
if(bme680_active){
|
||||
if (!BME680.run()){
|
||||
checkBMEStatus(BME680);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
next_update = millis() + 1000;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int RAK4631SensorManager::getNumSettings() const {
|
||||
#if ENV_INCLUDE_GPS
|
||||
return gps_detected ? 1 : 0; // only show GPS setting if GPS is detected
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* RAK4631SensorManager::getSettingName(int i) const {
|
||||
#if ENV_INCLUDE_GPS
|
||||
return (gps_detected && i == 0) ? "gps" : NULL;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* RAK4631SensorManager::getSettingValue(int i) const {
|
||||
#if ENV_INCLUDE_GPS
|
||||
if (gps_detected && i == 0) {
|
||||
return gps_active ? "1" : "0";
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool RAK4631SensorManager::setSettingValue(const char* name, const char* value) {
|
||||
#if ENV_INCLUDE_GPS
|
||||
if (gps_detected && strcmp(name, "gps") == 0) {
|
||||
if (strcmp(value, "0") == 0) {
|
||||
stop_gps();
|
||||
} else {
|
||||
start_gps();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false; // not supported
|
||||
}
|
||||
|
||||
mesh::LocalIdentity radio_new_identity() {
|
||||
RadioNoiseListener rng(radio);
|
||||
return mesh::LocalIdentity(&rng); // create new random identity
|
||||
|
||||
@@ -2,84 +2,21 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <RAK4631Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#if ENV_INCLUDE_GPS
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h>
|
||||
#endif
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
#include <helpers/ui/SSD1306Display.h>
|
||||
extern DISPLAY_CLASS display;
|
||||
#endif
|
||||
|
||||
#define _BV(x) (1 << x)
|
||||
|
||||
class RAK4631SensorManager: public SensorManager {
|
||||
#if ENV_INCLUDE_GPS
|
||||
bool gps_active = false;
|
||||
bool gps_detected = false;
|
||||
LocationProvider * _nmea;
|
||||
SFE_UBLOX_GNSS ublox_GNSS;
|
||||
uint32_t disStandbyPin = 0;
|
||||
|
||||
void start_gps();
|
||||
void stop_gps();
|
||||
void sleep_gps();
|
||||
void wake_gps();
|
||||
bool gpsIsAwake(uint32_t ioPin);
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BME680
|
||||
bool bme680_active = false;
|
||||
bool bme680_present = false;
|
||||
#define SAMPLING_RATE BSEC_SAMPLE_RATE_ULP
|
||||
#endif
|
||||
|
||||
public:
|
||||
#if ENV_INCLUDE_GPS
|
||||
RAK4631SensorManager(LocationProvider &nmea): _nmea(&nmea) { }
|
||||
#else
|
||||
RAK4631SensorManager() { }
|
||||
#endif
|
||||
|
||||
void loop() override;
|
||||
bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override;
|
||||
int getNumSettings() const override;
|
||||
const char* getSettingName(int i) const override;
|
||||
const char* getSettingValue(int i) const override;
|
||||
bool setSettingValue(const char* name, const char* value) override;
|
||||
bool begin() override;
|
||||
};
|
||||
|
||||
extern RAK4631Board board;
|
||||
extern WRAPPER_CLASS radio_driver;
|
||||
extern AutoDiscoverRTCClock rtc_clock;
|
||||
extern RAK4631SensorManager sensors;
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
extern DISPLAY_CLASS display;
|
||||
#endif
|
||||
|
||||
enum {
|
||||
POWERMANAGE_ONLINE = _BV(0),
|
||||
DISPLAY_ONLINE = _BV(1),
|
||||
RADIO_ONLINE = _BV(2),
|
||||
GPS_ONLINE = _BV(3),
|
||||
PSRAM_ONLINE = _BV(4),
|
||||
SDCARD_ONLINE = _BV(5),
|
||||
AXDL345_ONLINE = _BV(6),
|
||||
BME280_ONLINE = _BV(7),
|
||||
BMP280_ONLINE = _BV(8),
|
||||
BME680_ONLINE = _BV(9),
|
||||
QMC6310_ONLINE = _BV(10),
|
||||
QMI8658_ONLINE = _BV(11),
|
||||
PCF8563_ONLINE = _BV(12),
|
||||
OSC32768_ONLINE = _BV(13),
|
||||
RAK12500_ONLINE = _BV(14),
|
||||
};
|
||||
extern EnvironmentSensorManager sensors;
|
||||
|
||||
bool radio_init();
|
||||
uint32_t radio_get_rng_seed();
|
||||
|
||||
@@ -32,13 +32,11 @@ build_flags = ${nrf52_base.build_flags}
|
||||
build_src_filter = ${nrf52_base.build_src_filter}
|
||||
+<helpers/*.cpp>
|
||||
+<helpers/sensors>
|
||||
+<helpers/nrf52/SenseCapSolarBoard.cpp>
|
||||
+<../variants/SenseCap_Solar>
|
||||
+<../variants/sensecap_solar>
|
||||
debug_tool = jlink
|
||||
upload_protocol = nrfutil
|
||||
lib_deps =
|
||||
${nrf52_base.lib_deps}
|
||||
rweather/Crypto @ ^0.4.0
|
||||
adafruit/Adafruit INA3221 Library @ ^1.0.1
|
||||
adafruit/Adafruit INA219 @ ^1.2.3
|
||||
adafruit/Adafruit AHTX0 @ ^2.0.5
|
||||
@@ -72,4 +70,37 @@ build_flags =
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${SenseCap_Solar.build_src_filter}
|
||||
+<../examples/simple_room_server/main.cpp>
|
||||
+<../examples/simple_room_server/main.cpp>
|
||||
|
||||
[env:SenseCap_Solar_companion_radio_ble]
|
||||
extends = SenseCap_Solar
|
||||
build_flags =
|
||||
${SenseCap_Solar.build_flags}
|
||||
-D MAX_CONTACTS=100
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
-D BLE_PIN_CODE=123456
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
; -D BLE_DEBUG_LOGGING=1
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${SenseCap_Solar.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<../examples/companion_radio>
|
||||
lib_deps =
|
||||
${SenseCap_Solar.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:SenseCap_Solar_companion_radio_usb]
|
||||
extends = SenseCap_Solar
|
||||
build_flags =
|
||||
${SenseCap_Solar.build_flags}
|
||||
-D MAX_CONTACTS=100
|
||||
-D MAX_GROUP_CHANNELS=8
|
||||
; -D MESH_PACKET_LOGGING=1
|
||||
; -D MESH_DEBUG=1
|
||||
build_src_filter = ${SenseCap_Solar.build_src_filter}
|
||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
||||
+<../examples/companion_radio>
|
||||
lib_deps =
|
||||
${SenseCap_Solar.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <SenseCapSolarBoard.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/StationG2Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include "T1000eBoard.h"
|
||||
#include <helpers/CustomLR1110Wrapper.h>
|
||||
#include <helpers/radiolib/CustomLR1110Wrapper.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/nrf52/T114Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/nrf52/TechoBoard.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/XiaoC3Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/CustomSX1268Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1268Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/nrf52/ThinkNodeM1Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/sensors/LocationProvider.h>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/rp2040/WaveshareBoard.h>
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/stm32/STM32Board.h>
|
||||
#include <helpers/CustomSTM32WLxWrapper.h>
|
||||
#include <helpers/radiolib/CustomSTM32WLxWrapper.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
|
||||
// Just returns ADC value for now to test adc
|
||||
uint16_t getBattMilliVolts() override {
|
||||
uint32_t raw = analogRead(PIN_A3);
|
||||
uint32_t raw = analogRead(PIN_A3);
|
||||
return raw;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/stm32/STM32Board.h>
|
||||
#include <helpers/CustomSTM32WLxWrapper.h>
|
||||
#include <helpers/radiolib/CustomSTM32WLxWrapper.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
@@ -37,14 +37,14 @@ public:
|
||||
uint32_t raw = 0;
|
||||
for (int i=0; i<8;i++) {
|
||||
raw += analogRead(PIN_A3);
|
||||
}
|
||||
}
|
||||
return ((double)raw) * 1.73 * 5 * 1000 / 8 / 4096;
|
||||
}
|
||||
};
|
||||
|
||||
class WIOE5SensorManager : public SensorManager {
|
||||
BME280I2C bme;
|
||||
bool has_bme = false;
|
||||
bool has_bme = false;
|
||||
|
||||
public:
|
||||
WIOE5SensorManager() {}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <WioTrackerL1Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#define PIN_BUTTON3 (26) // Joystick Down
|
||||
#define PIN_BUTTON4 (27) // Joystick Left
|
||||
#define PIN_BUTTON5 (28) // Joystick Right
|
||||
#define PIN_BUTTON6 (28) // Joystick Press
|
||||
#define PIN_BUTTON6 (29) // Joystick Press
|
||||
#define PIN_USER_BTN PIN_BUTTON1
|
||||
#define JOYSTICK_UP PIN_BUTTON2
|
||||
#define JOYSTICK_DOWN PIN_BUTTON3
|
||||
@@ -70,6 +70,8 @@
|
||||
#define P_LORA_NSS (4)
|
||||
#define SX126X_RXEN (5)
|
||||
#define SX126X_TXEN RADIOLIB_NC
|
||||
#define SX126X_DIO2_AS_RF_SWITCH true
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE (1.8f)
|
||||
|
||||
// Wire Interfaces
|
||||
#define WIRE_INTERFACES_COUNT (2)
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/XiaoC3Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/CustomSX1268Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1268Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/ESP32Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <XiaoNrf52Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#include <helpers/rp2040/XiaoRP2040Board.h>
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#define RADIOLIB_STATIC_ONLY 1
|
||||
#include <RadioLib.h>
|
||||
#include <helpers/RadioLibWrappers.h>
|
||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
||||
#include <helpers/ESP32Board.h>
|
||||
#include <helpers/CustomSX1262Wrapper.h>
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
#include <helpers/AutoDiscoverRTCClock.h>
|
||||
#include <helpers/SensorManager.h>
|
||||
#ifdef DISPLAY_CLASS
|
||||
|
||||
Reference in New Issue
Block a user