Compare commits

...

36 Commits

Author SHA1 Message Date
Ben Meadors
b0d05522c0 Make telemetry packets minimum priority (#1810) 2022-10-16 15:59:59 -05:00
Ben Meadors
fc57a9daa4 Send environment telemetry every minute (#1808) 2022-10-16 11:36:38 -05:00
Thomas Göttgens
d8f44d7b1b Merge pull request #1807 from meshtastic/nmea-serial
Add NMEA output mode to serial module
2022-10-16 17:15:24 +02:00
Ben Meadors
efe2e90a03 Merge branch 'master' into nmea-serial 2022-10-16 09:59:30 -05:00
Ben Meadors
45f9dee89a Telemetry phone api guard (#1805)
* Delay start of telemetry modules

* Don't send unless our toPhoneQueue is empty

* Get wrecked, checks!
2022-10-16 09:58:58 -05:00
Thomas Göttgens
cc73d2c2f2 Sigh... 2022-10-16 16:51:17 +02:00
Thomas Göttgens
b1f789dddd fix cppcheck 2022-10-16 16:45:32 +02:00
Thomas Göttgens
d3e9dbf6a9 Add NMEA output mode (my own position, and other devices as waypoints) to serial module 2022-10-16 16:37:38 +02:00
Thomas Göttgens
44529620ad Merge pull request #1806 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-16 16:25:34 +02:00
caveman99
7a9673dc37 [create-pull-request] automated change 2022-10-16 14:24:27 +00:00
Thomas Göttgens
27bcf67c0c add routine to output waypoint data 2022-10-16 12:28:49 +02:00
Ben Meadors
7fde56b8ac Make telemetry logging more concise (#1804)
* Make telemetry logging more concise

* Whoops
2022-10-15 18:48:34 -05:00
Ben Meadors
6b614a2d6a Added LPS22HB (RAK-1902) sensor support (#1802) 2022-10-15 14:55:57 -05:00
Ben Meadors
1e1509fbf5 Use pio registry (#1801) 2022-10-15 12:34:52 -05:00
Ben Meadors
a3e67f8e4b SHTC3 Sensor (RAK-1901) support (#1800) 2022-10-15 09:11:05 -05:00
Ben Meadors
028b25cfe8 Change RTCQuality acceptance criteria (#1797)
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-10-14 19:12:55 -05:00
Ben Meadors
2555e082d6 Add nrf52 to serial module registration (#1799)
* Add nrf52 to serial module registration

* Update Modules.cpp

* Update Modules.cpp

* Update Modules.cpp
2022-10-14 11:38:56 -05:00
Thomas Göttgens
f8fa721c72 Merge pull request #1798 from meshtastic/i2cscan
Scan for I2C devices twice on all CPU's
2022-10-14 15:33:46 +02:00
Thomas Göttgens
a7e0127793 scan i2c twice for all devices, not just tbeam 2022-10-13 23:46:25 +02:00
Thomas Göttgens
603f60d86a Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-13 19:13:09 +02:00
Thomas Göttgens
6febf6b17c Merge pull request #1796 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-13 17:58:41 +02:00
thebentern
53aaf766dd [create-pull-request] automated change 2022-10-13 14:54:05 +00:00
Thomas Göttgens
4fa8d02b08 update FromRadio UUID for nRF52 devices (#1795) 2022-10-13 09:32:54 -05:00
Thomas Göttgens
efa423c8ad update FromRadio UUID for nRF52 devices 2022-10-13 16:20:27 +02:00
Thomas Göttgens
43fb0d80f1 Merge pull request #1794 from meshtastic/canned-spice
Display looks better that way...
2022-10-13 15:56:13 +02:00
Thomas Göttgens
b25ace14e5 Update CannedMessageModule.h 2022-10-13 15:44:27 +02:00
Thomas Göttgens
8734751bc4 make screen timeout work again 2022-10-13 15:31:57 +02:00
Thomas Göttgens
5559a1edb0 Display looks better that way... 2022-10-13 15:22:57 +02:00
Thomas Göttgens
bf503354f3 Merge pull request #1792 from meshtastic/atecca
Support for ATECCA608B Cryptographic Coprocessor
2022-10-13 14:34:44 +02:00
Thomas Göttgens
7b10441a28 update raspberry pi framework some more... 2022-10-13 14:21:48 +02:00
Thomas Göttgens
994e396c00 update Raspberry Pico Framework 2022-10-13 13:57:17 +02:00
Thomas Göttgens
6e22ee9061 make nRF52 happy 2022-10-13 13:31:19 +02:00
Thomas Göttgens
b5fb0f60b0 don't compile on Portduino 2022-10-13 13:01:24 +02:00
Thomas Göttgens
a7fe69ed6b Support for ATECCA608B Cryptographic Coprocessor 2022-10-13 12:55:28 +02:00
Thomas Göttgens
7f05298172 Merge pull request #1790 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-13 08:45:13 +02:00
thebentern
92a2505056 [create-pull-request] automated change 2022-10-12 23:42:47 +00:00
33 changed files with 494 additions and 93 deletions

View File

@@ -1,6 +1,6 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#5ce1a228e7cae453f366deb8962252b9b7356bbc
extends = arduino_base
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m

View File

@@ -65,6 +65,7 @@ lib_deps =
${env.lib_deps}
; Portduino is using meshtastic fork for now
jgromes/RadioLib@5.4.1
https://github.com/caveman99/SparkFun_ATECCX08a_Arduino_Library.git#008e7f9d40bad66b2f7a0074aaac05b7c424339d
build_flags = ${env.build_flags} -Os
-DRADIOLIB_SPI_PARANOID=0
@@ -89,4 +90,5 @@ lib_deps =
adafruit/Adafruit MCP9808 Library@^2.0.0
adafruit/Adafruit INA260 Library@^1.5.0
adafruit/Adafruit INA219@^1.2.0
adafruit/Adafruit SHTC3 Library@^1.0.0
adafruit/Adafruit LPS2X@^2.0.4

View File

@@ -7,7 +7,7 @@ const uint8_t MESH_SERVICE_UUID_16[16u] = {0xfd, 0xea, 0x73, 0xe2, 0xca, 0x5d, 0
0x1f, 0x46, 0xa8, 0x15, 0x18, 0xb2, 0xa1, 0x6b};
const uint8_t TORADIO_UUID_16[16u] = {0xe7, 0x01, 0x44, 0x12, 0x66, 0x78, 0xdd, 0xa1,
0xad, 0x4d, 0x9e, 0x12, 0xd2, 0x76, 0x5c, 0xf7};
const uint8_t FROMRADIO_UUID_16[16u] = {0xd5, 0x54, 0xe4, 0xc5, 0x25, 0xc5, 0x31, 0xa5,
0x55, 0x4a, 0x02, 0xee, 0xc2, 0xbc, 0xa2, 0x8b};
const uint8_t FROMRADIO_UUID_16[16u] = {0x02, 0x00, 0x12, 0xac, 0x42, 0x02, 0x78, 0xb8,
0xed, 0x11, 0x93, 0x49, 0x9e, 0xe6, 0x55, 0x2c};
const uint8_t FROMNUM_UUID_16[16u] = {0x53, 0x44, 0xe3, 0x47, 0x75, 0xaa, 0x70, 0xa6,
0x66, 0x4f, 0x00, 0xa8, 0x8c, 0xa1, 0x9d, 0xed};

View File

@@ -110,6 +110,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define INA_ADDR_ALTERNATE 0x41
#define QMC6310_ADDR 0x1C
#define QMI8658_ADDR 0x6B
#define SHTC3_ADDR 0x70
#define LPS22HB_ADDR 0x5C
#define LPS22HB_ADDR_ALT 0x5D
// -----------------------------------------------------------------------------
// Security
// -----------------------------------------------------------------------------
#define ATECC608B_ADDR 0x35
// -----------------------------------------------------------------------------
// GPS
// -----------------------------------------------------------------------------

View File

@@ -9,6 +9,41 @@
#endif
#if HAS_WIRE
void printATECCInfo()
{
#ifndef ARCH_PORTDUINO
atecc.readConfigZone(false);
DEBUG_MSG("ATECC608B Serial Number: ");
for (int i = 0 ; i < 9 ; i++) {
DEBUG_MSG("%02x",atecc.serialNumber[i]);
}
DEBUG_MSG(", Rev Number: ");
for (int i = 0 ; i < 4 ; i++) {
DEBUG_MSG("%02x",atecc.revisionNumber[i]);
}
DEBUG_MSG("\n");
DEBUG_MSG("ATECC608B Config %s",atecc.configLockStatus ? "Locked" : "Unlocked");
DEBUG_MSG(", Data %s",atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
DEBUG_MSG(", Slot 0 %s\n",atecc.slot0LockStatus ? "Locked" : "Unlocked");
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
if (atecc.generatePublicKey() == false) {
DEBUG_MSG("ATECC608B Error generating public key\n");
} else {
DEBUG_MSG("ATECC608B Public Key: ");
for (int i = 0 ; i < 64 ; i++) {
DEBUG_MSG("%02x",atecc.publicKey64Bytes[i]);
}
DEBUG_MSG("\n");
}
}
#endif
}
uint16_t getRegisterValue(uint8_t address, uint8_t reg, uint8_t length) {
uint16_t value = 0x00;
Wire.beginTransmission(address);
@@ -79,6 +114,17 @@ void scanI2Cdevice(void)
DEBUG_MSG("unknown display found\n");
}
}
#ifndef ARCH_PORTDUINO
if (addr == ATECC608B_ADDR){
keystore_found = addr;
if (atecc.begin(keystore_found) == true) {
DEBUG_MSG("ATECC608B initialized\n");
} else {
DEBUG_MSG("ATECC608B initialization failed\n");
}
printATECCInfo();
}
#endif
#ifdef RV3028_RTC
if (addr == RV3028_RTC){
rtc_found = addr;
@@ -145,14 +191,22 @@ void scanI2Cdevice(void)
nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = addr;
DEBUG_MSG("MCP9808 sensor found at address 0x%x\n", (uint8_t)addr);
}
if(addr == QMC6310_ADDR){
if (addr == QMC6310_ADDR) {
DEBUG_MSG("QMC6310 3-Axis magnetic sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_QMC6310] = addr;
}
if(addr == QMI8658_ADDR){
if (addr == QMI8658_ADDR) {
DEBUG_MSG("QMI8658 6-Axis inertial measurement sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658] = addr;
}
if (addr == SHTC3_ADDR) {
DEBUG_MSG("SHTC3 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_SHTC3] = addr;
}
if (addr == LPS22HB_ADDR || addr == LPS22HB_ADDR_ALT) {
DEBUG_MSG("LPS22HB sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_LPS22] = addr;
}
} else if (err == 4) {
DEBUG_MSG("Unknow error at address 0x%x\n", addr);
}

76
src/gps/NMEAWPL.cpp Normal file
View File

@@ -0,0 +1,76 @@
#include "NMEAWPL.h"
/* -------------------------------------------
* 1 2 3 4 5 6
* | | | | | |
* $--WPL,llll.ll,a,yyyyy.yy,a,c--c*hh<CR><LF>
*
* Field Number:
* 1 Latitude
* 2 N or S (North or South)
* 3 Longitude
* 4 E or W (East or West)
* 5 Waypoint name
* 6 Checksum
* -------------------------------------------
*/
uint printWPL(char *buf, const Position &pos, const char *name)
{
uint len = sprintf(buf, "$GNWPL,%07.2f,%c,%08.2f,%c,%s", pos.latitude_i * 1e-5, pos.latitude_i < 0 ? 'S' : 'N', pos.longitude_i * 1e-5, pos.longitude_i < 0 ? 'W' : 'E', name);
uint chk = 0;
for (uint i = 1; i < len; i++) {
chk ^= buf[i];
}
len += sprintf(buf + len, "*%02X\r\n", chk);
return len;
}
/* -------------------------------------------
* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
* | | | | | | | | | | | | | | |
* $--GGA,hhmmss.ss,ddmm.mm,a,ddmm.mm,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh<CR><LF>
*
* Field Number:
* 1 UTC of this position report, hh is hours, mm is minutes, ss.ss is seconds.
* 2 Latitude
* 3 N or S (North or South)
* 4 Longitude
* 5 E or W (East or West)
* 6 GPS Quality Indicator (non null)
* 7 Number of satellites in use, 00 - 12
* 8 Horizontal Dilution of precision (meters)
* 9 Antenna Altitude above/below mean-sea-level (geoid) (in meters)
* 10 Units of antenna altitude, meters
* 11 Geoidal separation, the difference between the WGS-84 earth ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below ellipsoid
* 12 Units of geoidal separation, meters
* 13 Age of differential GPS data, time in seconds since last SC104 type 1 or 9 update, null field when DGPS is not used
* 14 Differential reference station ID, 0000-1023
* 15 Checksum
* -------------------------------------------
*/
uint printGGA(char *buf, const Position &pos)
{
uint len = sprintf(buf, "$GNGGA,%06u.%03u,%07.2f,%c,%08.2f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d",
pos.time / 1000,
pos.time % 1000,
pos.latitude_i * 1e-5, pos.latitude_i < 0 ? 'S' : 'N',
pos.longitude_i * 1e-5, pos.longitude_i < 0 ? 'W' : 'E',
pos.fix_type,
pos.sats_in_view,
pos.HDOP,
pos.altitude,
'M',
pos.altitude_geoidal_separation,
'M',
0,
0);
uint chk = 0;
for (uint i = 1; i < len; i++) {
chk ^= buf[i];
}
len += sprintf(buf + len, "*%02X\r\n", chk);
return len;
}

7
src/gps/NMEAWPL.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include <Arduino.h>
#include "main.h"
uint printWPL(char *buf, const Position &pos, const char *name);
uint printGGA(char *buf, const Position &pos);

View File

@@ -16,7 +16,7 @@ enum RTCQuality {
RTCQualityFromNet = 2,
/// Our time is based on NTP
RTCQualityNTP= 3,
RTCQualityNTP = 3,
/// Our time is based on our own GPS
RTCQualityGPS = 4

View File

@@ -80,6 +80,12 @@ uint8_t kb_model;
// The I2C address of the RTC Module (if found)
uint8_t rtc_found;
// Keystore Chips
uint8_t keystore_found;
#ifndef ARCH_PORTDUINO
ATECCX08A atecc;
#endif
bool eink_found = true;
uint32_t serialSinceMsec;
@@ -275,12 +281,10 @@ void setup()
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
/*
* Repeat the scanning for I2C devices after power initialization.
* Repeat the scanning for I2C devices after power initialization or look for 'latecomers'.
* Boards with an PMU need to be powered on to correctly scan to the device address, such as t-beam-s3-core
*/
if ((HW_VENDOR == HardwareModel_LILYGO_TBEAM_S3_CORE) || (HW_VENDOR == HardwareModel_TBEAM)) {
scanI2Cdevice();
}
scanI2Cdevice();
// Init our SPI controller (must be before screen and lora)
initSPI();

View File

@@ -6,18 +6,26 @@
#include "PowerStatus.h"
#include "graphics/Screen.h"
#include "mesh/generated/telemetry.pb.h"
#ifndef ARCH_PORTDUINO
#include <SparkFun_ATECCX08a_Arduino_Library.h>
#endif
extern uint8_t screen_found;
extern uint8_t screen_model;
extern uint8_t cardkb_found;
extern uint8_t kb_model;
extern uint8_t rtc_found;
extern uint8_t keystore_found;
extern bool eink_found;
extern bool pmu_found;
extern bool isCharging;
extern bool isUSBPowered;
#ifndef ARCH_PORTDUINO
extern ATECCX08A atecc;
#endif
extern uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658+1];
extern int TCPPort; // set by Portduino

View File

@@ -283,3 +283,8 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
return 0;
}
bool MeshService::isToPhoneQueueEmpty()
{
return toPhoneQueue.isEmpty();
}

View File

@@ -89,6 +89,8 @@ class MeshService
/// Send a packet to the phone
void sendToPhone(MeshPacket *p);
bool isToPhoneQueueEmpty();
private:
/// Called when our gps position has changed - updates nodedb and sends Location message out into the mesh
/// returns 0 to allow futher processing

View File

@@ -33,7 +33,8 @@ typedef enum _ModuleConfig_SerialConfig_Serial_Mode {
ModuleConfig_SerialConfig_Serial_Mode_DEFAULT = 0,
ModuleConfig_SerialConfig_Serial_Mode_SIMPLE = 1,
ModuleConfig_SerialConfig_Serial_Mode_PROTO = 2,
ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG = 3
ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG = 3,
ModuleConfig_SerialConfig_Serial_Mode_NMEA = 4
} ModuleConfig_SerialConfig_Serial_Mode;
typedef enum _ModuleConfig_CannedMessageConfig_InputEventChar {
@@ -140,8 +141,8 @@ typedef struct _ModuleConfig {
#define _ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Baud)(ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1))
#define _ModuleConfig_SerialConfig_Serial_Mode_MIN ModuleConfig_SerialConfig_Serial_Mode_DEFAULT
#define _ModuleConfig_SerialConfig_Serial_Mode_MAX ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG
#define _ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Mode)(ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG+1))
#define _ModuleConfig_SerialConfig_Serial_Mode_MAX ModuleConfig_SerialConfig_Serial_Mode_NMEA
#define _ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Mode)(ModuleConfig_SerialConfig_Serial_Mode_NMEA+1))
#define _ModuleConfig_CannedMessageConfig_InputEventChar_MIN ModuleConfig_CannedMessageConfig_InputEventChar_NONE
#define _ModuleConfig_CannedMessageConfig_InputEventChar_MAX ModuleConfig_CannedMessageConfig_InputEventChar_BACK

View File

@@ -225,7 +225,7 @@ int32_t CannedMessageModule::runOnce()
this->cursor = 0;
this->destSelect = false;
this->notifyObservers(&e);
} else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) && (millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS) {
} else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) && ((millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS)) {
// Reset module
DEBUG_MSG("Reset due to lack of activity.\n");
e.frameChanged = true;
@@ -430,6 +430,8 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
{
displayedNodeNum = 0; // Not currently showing a node pane
char buffer[50];
if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM);
@@ -445,7 +447,6 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
}
char buffer[50];
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
// used chars right aligned
sprintf(buffer, "%d left", Constants_DATA_PAYLOAD_LEN - this->freetext.length());
@@ -456,11 +457,13 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
if (this->messagesCount > 0) {
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_SMALL);
display->drawString(0 + x, 0 + y, cannedMessageModule->getPrevMessage());
display->setFont(FONT_MEDIUM);
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getCurrentMessage());
display->setFont(FONT_SMALL);
display->drawString(0 + x, 0 + y + FONT_HEIGHT_MEDIUM, cannedMessageModule->getNextMessage());
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getPrevMessage());
display->fillRect(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, cannedMessageModule->getCurrentMessage());
display->setColor(WHITE);
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 3, cannedMessageModule->getNextMessage());
}
}
}

View File

@@ -87,4 +87,4 @@ class CannedMessageModule :
};
extern CannedMessageModule *cannedMessageModule;
#endif
#endif

View File

@@ -60,13 +60,15 @@ void setupModules()
new DeviceTelemetryModule();
new EnvironmentTelemetryModule();
#endif
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO)
new SerialModule();
#endif
#ifdef ARCH_ESP32
// Only run on an esp32 based device.
/*
Maintained by MC Hamster (Jm Casler) jm@casler.org
*/
new SerialModule();
new ExternalNotificationModule();
storeForwardModule = new StoreForwardModule();

View File

@@ -108,7 +108,7 @@ MeshPacket *PositionModule::allocReply()
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
// nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless
// devices can get time.
if (getRTCQuality() < RTCQualityGPS) {
if (getRTCQuality() < RTCQualityDevice) {
DEBUG_MSG("Stripping time %u from position send\n", p.time);
p.time = 0;
} else

View File

@@ -2,6 +2,7 @@
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "NMEAWPL.h"
#include "Router.h"
#include "configuration.h"
#include <Arduino.h>
@@ -40,7 +41,7 @@
KNOWN PROBLEMS
* Until the module is initilized by the startup sequence, the TX pin is in a floating
state. Device connected to that pin may see this as "noise".
* Will not work on NRF and the Linux device targets.
* Will not work on T-Echo and the Linux device targets.
*/
@@ -62,16 +63,19 @@ char serialStringChar[Constants_DATA_PAYLOAD_LEN];
SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio")
{
// restrict to the admin channel for rx
boundChannel = Channels::serialChannel;
switch (moduleConfig.serial.mode)
{
case ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG:
ourPortNum = PortNum_TEXT_MESSAGE_APP;
break;
case ModuleConfig_SerialConfig_Serial_Mode_NMEA:
ourPortNum = PortNum_POSITION_APP;
break;
default:
ourPortNum = PortNum_SERIAL_APP;
// restrict to the serial channel for rx
boundChannel = Channels::serialChannel;
break;
}
}
@@ -175,15 +179,25 @@ int32_t SerialModule::runOnce()
firstTime = 0;
} else {
String serialString;
while (Serial2.available()) {
serialString = Serial2.readString();
serialString.toCharArray(serialStringChar, Constants_DATA_PAYLOAD_LEN);
// in NMEA mode send out GGA every 2 seconds, Don't read from Port
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
if (millis() - lastNmeaTime > 2000) {
lastNmeaTime = millis();
printGGA(outbuf, nodeDB.getNode(myNodeInfo.my_node_num)->position);
Serial2.printf("%s", outbuf);
}
} else {
String serialString;
serialModuleRadio->sendPayload();
while (Serial2.available()) {
serialString = Serial2.readString();
serialString.toCharArray(serialStringChar, Constants_DATA_PAYLOAD_LEN);
DEBUG_MSG("Received: %s\n", serialStringChar);
serialModuleRadio->sendPayload();
DEBUG_MSG("Received: %s\n", serialStringChar);
}
}
}
@@ -191,7 +205,7 @@ int32_t SerialModule::runOnce()
} else {
DEBUG_MSG("Serial Module Disabled\n");
return (INT32_MAX);
return INT32_MAX;
}
#else
return INT32_MAX;
@@ -255,6 +269,19 @@ ProcessMessage SerialModuleRadio::handleReceived(const MeshPacket &mp)
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_PROTO) {
// TODO this needs to be implemented
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
// Decode the Payload some more
Position scratch;
Position *decoded = NULL;
if (mp.which_payload_variant == MeshPacket_decoded_tag && mp.decoded.portnum == ourPortNum) {
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, Position_fields, &scratch)) {
decoded = &scratch;
}
// send position packet as WPL to the serial port
printWPL(outbuf, *decoded, nodeDB.getNode(getFrom(&mp))->user.long_name);
Serial2.printf("%s", outbuf);
}
}
}

View File

@@ -11,6 +11,8 @@
class SerialModule : private concurrency::OSThread
{
bool firstTime = 1;
unsigned long lastNmeaTime = millis();
char outbuf[90] = "";
public:
SerialModule();
@@ -28,6 +30,7 @@ extern SerialModule *serialModule;
class SerialModuleRadio : public MeshModule
{
uint32_t lastRxID = 0;
char outbuf[90] = "";
public:
SerialModuleRadio();

View File

@@ -9,17 +9,20 @@
#include "main.h"
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
#include "MeshService.h"
int32_t DeviceTelemetryModule::runOnce()
{
#ifndef ARCH_PORTDUINO
uint32_t now = millis();
if ((lastSentToMesh == 0 || (now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval))
&& airTime->channelUtilizationPercent() < max_channel_util_percent) {
if ((lastSentToMesh == 0 ||
(now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval)) &&
airTime->channelUtilizationPercent() < max_channel_util_percent) {
sendTelemetry();
lastSentToMesh = now;
} else {
} else if (service.isToPhoneQueueEmpty()) {
// Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true);
}
return sendToPhoneIntervalMs;
@@ -30,14 +33,13 @@ bool DeviceTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Telemet
{
if (t->which_variant == Telemetry_device_metrics_tag) {
const char *sender = getSenderShortName(mp);
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("Device Telemetry: Received data from %s\n", sender);
DEBUG_MSG("Telemetry->time: %i\n", t->time);
DEBUG_MSG("Telemetry->air_util_tx: %f\n", t->variant.device_metrics.air_util_tx);
DEBUG_MSG("Telemetry->battery_level: %i\n", t->variant.device_metrics.battery_level);
DEBUG_MSG("Telemetry->channel_utilization: %f\n", t->variant.device_metrics.channel_utilization);
DEBUG_MSG("Telemetry->voltage: %f\n", t->variant.device_metrics.voltage);
DEBUG_MSG("(Received from %s): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f\n",
sender,
t->variant.device_metrics.air_util_tx,
t->variant.device_metrics.channel_utilization,
t->variant.device_metrics.battery_level,
t->variant.device_metrics.voltage);
lastMeasurementPacket = packetPool.allocCopy(mp);
@@ -58,26 +60,24 @@ bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
t.variant.device_metrics.channel_utilization = myNodeInfo.channel_utilization;
t.variant.device_metrics.voltage = powerStatus->getBatteryVoltageMv() / 1000.0;
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("Device Telemetry: Read data\n");
DEBUG_MSG("Telemetry->time: %i\n", t.time);
DEBUG_MSG("Telemetry->air_util_tx: %f\n", t.variant.device_metrics.air_util_tx);
DEBUG_MSG("Telemetry->battery_level: %i\n", t.variant.device_metrics.battery_level);
DEBUG_MSG("Telemetry->channel_utilization: %f\n", t.variant.device_metrics.channel_utilization);
DEBUG_MSG("Telemetry->voltage: %f\n", t.variant.device_metrics.voltage);
DEBUG_MSG("(Sending): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f\n",
t.variant.device_metrics.air_util_tx,
t.variant.device_metrics.channel_utilization,
t.variant.device_metrics.battery_level,
t.variant.device_metrics.voltage);
MeshPacket *p = allocDataProtobuf(t);
p->to = dest;
p->decoded.want_response = false;
p->priority = MeshPacket_Priority_MIN;
lastMeasurementPacket = packetPool.allocCopy(*p);
nodeDB.updateTelemetry(nodeDB.getNodeNum(), t, RX_SRC_LOCAL);
if (phoneOnly) {
DEBUG_MSG("Device Telemetry: Sending packet to phone\n");
DEBUG_MSG("Sending packet to phone\n");
service.sendToPhone(p);
} else {
DEBUG_MSG("Device Telemetry: Sending packet to mesh\n");
DEBUG_MSG("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true);
}
return true;

View File

@@ -11,7 +11,8 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu
DeviceTelemetryModule()
: concurrency::OSThread("DeviceTelemetryModule"), ProtobufModule("DeviceTelemetry", PortNum_TELEMETRY_APP, &Telemetry_msg)
{
lastMeasurementPacket = nullptr;
lastMeasurementPacket = nullptr;
setIntervalFromNow(10 * 1000);
}
virtual bool wantUIFrame() { return false; }

View File

@@ -9,6 +9,7 @@
#include "main.h"
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
#include "MeshService.h"
// Sensors
#include "Sensor/BMP280Sensor.h"
@@ -17,6 +18,8 @@
#include "Sensor/MCP9808Sensor.h"
#include "Sensor/INA260Sensor.h"
#include "Sensor/INA219Sensor.h"
#include "Sensor/SHTC3Sensor.h"
#include "Sensor/LPS22HBSensor.h"
BMP280Sensor bmp280Sensor;
BME280Sensor bme280Sensor;
@@ -24,6 +27,8 @@ BME680Sensor bme680Sensor;
MCP9808Sensor mcp9808Sensor;
INA260Sensor ina260Sensor;
INA219Sensor ina219Sensor;
SHTC3Sensor shtc3Sensor;
LPS22HBSensor lps22hbSensor;
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
@@ -83,21 +88,31 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = ina260Sensor.runOnce();
if (ina219Sensor.hasSensor())
result = ina219Sensor.runOnce();
if (shtc3Sensor.hasSensor())
result = shtc3Sensor.runOnce();
if (lps22hbSensor.hasSensor()) {
result = lps22hbSensor.runOnce();
}
}
return result;
} else {
// if we somehow got to a second run of this module with measurement disabled, then just wait forever
if (!moduleConfig.telemetry.environment_measurement_enabled)
return result;
// this is not the first time OSThread library has called this function
// so just do what we intend to do on the interval
if (!sendOurTelemetry()) {
// if we failed to read the sensor, then try again
// as soon as we can according to the maximum polling frequency
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
uint32_t now = millis();
if ((lastSentToMesh == 0 ||
(now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval)) &&
airTime->channelUtilizationPercent() < max_channel_util_percent) {
sendTelemetry();
lastSentToMesh = now;
} else if (service.isToPhoneQueueEmpty()) {
// Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true);
}
}
return getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval);
return sendToPhoneIntervalMs;
#endif
}
@@ -143,7 +158,7 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, Telemetry_fields, &lastMeasurement)) {
display->setFont(FONT_SMALL);
display->drawString(x, y += fontHeight(FONT_MEDIUM), "Measurement Error");
DEBUG_MSG("Environment Telemetry: unable to decode last packet");
DEBUG_MSG("Unable to decode last packet");
return;
}
@@ -168,15 +183,14 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Te
if (t->which_variant == Telemetry_environment_metrics_tag) {
const char *sender = getSenderShortName(mp);
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("Environment Telemetry: Received data from %s\n", sender);
DEBUG_MSG("Telemetry->time: %i\n", t->time);
DEBUG_MSG("Telemetry->barometric_pressure: %f\n", t->variant.environment_metrics.barometric_pressure);
DEBUG_MSG("Telemetry->current: %f\n", t->variant.environment_metrics.current);
DEBUG_MSG("Telemetry->gas_resistance: %f\n", t->variant.environment_metrics.gas_resistance);
DEBUG_MSG("Telemetry->relative_humidity: %f\n", t->variant.environment_metrics.relative_humidity);
DEBUG_MSG("Telemetry->temperature: %f\n", t->variant.environment_metrics.temperature);
DEBUG_MSG("Telemetry->voltage: %f\n", t->variant.environment_metrics.voltage);
DEBUG_MSG("(Received from %s): barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f, voltage=%f\n",
sender,
t->variant.environment_metrics.barometric_pressure,
t->variant.environment_metrics.current,
t->variant.environment_metrics.gas_resistance,
t->variant.environment_metrics.relative_humidity,
t->variant.environment_metrics.temperature,
t->variant.environment_metrics.voltage);
lastMeasurementPacket = packetPool.allocCopy(mp);
}
@@ -184,7 +198,7 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Te
return false; // Let others look at this message also if they want
}
bool EnvironmentTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies)
bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
{
Telemetry m;
m.time = getTime();
@@ -197,9 +211,10 @@ bool EnvironmentTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies
m.variant.environment_metrics.temperature = 0;
m.variant.environment_metrics.voltage = 0;
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("Environment Telemetry: Read data\n");
if (lps22hbSensor.hasSensor())
lps22hbSensor.getMetrics(&m);
if (shtc3Sensor.hasSensor())
shtc3Sensor.getMetrics(&m);
if (bmp280Sensor.hasSensor())
bmp280Sensor.getMetrics(&m);
if (bme280Sensor.hasSensor())
@@ -213,22 +228,28 @@ bool EnvironmentTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies
if (ina260Sensor.hasSensor())
ina260Sensor.getMetrics(&m);
DEBUG_MSG("Telemetry->time: %i\n", m.time);
DEBUG_MSG("Telemetry->barometric_pressure: %f\n", m.variant.environment_metrics.barometric_pressure);
DEBUG_MSG("Telemetry->current: %f\n", m.variant.environment_metrics.current);
DEBUG_MSG("Telemetry->gas_resistance: %f\n", m.variant.environment_metrics.gas_resistance);
DEBUG_MSG("Telemetry->relative_humidity: %f\n", m.variant.environment_metrics.relative_humidity);
DEBUG_MSG("Telemetry->temperature: %f\n", m.variant.environment_metrics.temperature);
DEBUG_MSG("Telemetry->voltage: %f\n", m.variant.environment_metrics.voltage);
DEBUG_MSG("(Sending): barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f, voltage=%f\n",
m.variant.environment_metrics.barometric_pressure,
m.variant.environment_metrics.current,
m.variant.environment_metrics.gas_resistance,
m.variant.environment_metrics.relative_humidity,
m.variant.environment_metrics.temperature,
m.variant.environment_metrics.voltage);
sensor_read_error_count = 0;
MeshPacket *p = allocDataProtobuf(m);
p->to = dest;
p->decoded.want_response = wantReplies;
p->decoded.want_response = false;
p->priority = MeshPacket_Priority_MIN;
lastMeasurementPacket = packetPool.allocCopy(*p);
DEBUG_MSG("Environment Telemetry: Sending packet to mesh");
service.sendToMesh(p, RX_SRC_LOCAL, true);
if (phoneOnly) {
DEBUG_MSG("Sending packet to phone\n");
service.sendToPhone(p);
} else {
DEBUG_MSG("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true);
}
return true;
}

View File

@@ -12,7 +12,8 @@ class EnvironmentTelemetryModule : private concurrency::OSThread, public Protobu
: concurrency::OSThread("EnvironmentTelemetryModule"),
ProtobufModule("EnvironmentTelemetry", PortNum_TELEMETRY_APP, &Telemetry_msg)
{
lastMeasurementPacket = nullptr;
lastMeasurementPacket = nullptr;
setIntervalFromNow(10 * 1000);
}
virtual bool wantUIFrame() override;
#if !HAS_SCREEN
@@ -30,11 +31,13 @@ class EnvironmentTelemetryModule : private concurrency::OSThread, public Protobu
/**
* Send our Telemetry into the mesh
*/
bool sendOurTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
bool sendTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
private:
float CelsiusToFahrenheit(float c);
bool firstTime = 1;
const MeshPacket *lastMeasurementPacket;
uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute
uint32_t lastSentToMesh = 0;
uint32_t sensor_read_error_count = 0;
};

View File

@@ -0,0 +1,36 @@
#include "../mesh/generated/telemetry.pb.h"
#include "configuration.h"
#include "TelemetrySensor.h"
#include "LPS22HBSensor.h"
#include <Adafruit_LPS2X.h>
#include <Adafruit_Sensor.h>
LPS22HBSensor::LPS22HBSensor() :
TelemetrySensor(TelemetrySensorType_LPS22, "LPS22HB")
{
}
int32_t LPS22HBSensor::runOnce() {
DEBUG_MSG("Init sensor: %s\n", sensorName);
if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
status = lps22hb.begin_I2C(nodeTelemetrySensorsMap[sensorType]);
return initI2CSensor();
}
void LPS22HBSensor::setup()
{
lps22hb.setDataRate(LPS22_RATE_10_HZ);
}
bool LPS22HBSensor::getMetrics(Telemetry *measurement) {
sensors_event_t temp;
sensors_event_t pressure;
lps22hb.getEvent(&pressure, &temp);
measurement->variant.environment_metrics.temperature = temp.temperature;
measurement->variant.environment_metrics.barometric_pressure = pressure.pressure;
return true;
}

View File

@@ -0,0 +1,17 @@
#include "../mesh/generated/telemetry.pb.h"
#include "TelemetrySensor.h"
#include <Adafruit_LPS2X.h>
#include <Adafruit_Sensor.h>
class LPS22HBSensor : virtual public TelemetrySensor {
private:
Adafruit_LPS22 lps22hb;
protected:
virtual void setup() override;
public:
LPS22HBSensor();
virtual int32_t runOnce() override;
virtual bool getMetrics(Telemetry *measurement) override;
};

View File

@@ -0,0 +1,34 @@
#include "../mesh/generated/telemetry.pb.h"
#include "configuration.h"
#include "TelemetrySensor.h"
#include "SHTC3Sensor.h"
#include <Adafruit_SHTC3.h>
SHTC3Sensor::SHTC3Sensor() :
TelemetrySensor(TelemetrySensorType_SHTC3, "SHTC3")
{
}
int32_t SHTC3Sensor::runOnce() {
DEBUG_MSG("Init sensor: %s\n", sensorName);
if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
status = shtc3.begin();
return initI2CSensor();
}
void SHTC3Sensor::setup()
{
// Set up oversampling and filter initialization
}
bool SHTC3Sensor::getMetrics(Telemetry *measurement) {
sensors_event_t humidity, temp;
shtc3.getEvent(&humidity, &temp);
measurement->variant.environment_metrics.temperature = temp.temperature;
measurement->variant.environment_metrics.relative_humidity = humidity.relative_humidity;
return true;
}

View File

@@ -0,0 +1,16 @@
#include "../mesh/generated/telemetry.pb.h"
#include "TelemetrySensor.h"
#include <Adafruit_SHTC3.h>
class SHTC3Sensor : virtual public TelemetrySensor {
private:
Adafruit_SHTC3 shtc3 = Adafruit_SHTC3();
protected:
virtual void setup() override;
public:
SHTC3Sensor();
virtual int32_t runOnce() override;
virtual bool getMetrics(Telemetry *measurement) override;
};

View File

@@ -1,12 +1,12 @@
[env:pico]
extends = rp2040_base
board = pico
board = rpipico
upload_protocol = picotool
# add our variants files to the include and src paths
build_flags = ${rp2040_base.build_flags}
-DPRIVATE_HW
-Ivariants/pico
-Ivariants/rpipico
-DARDUINO_AVR_NANO_EVERY
-DDEBUG_RP2040_WIRE
-DDEBUG_RP2040_SPI

View File

@@ -0,0 +1,17 @@
[env:picow]
extends = rp2040_base
board = rpipicow
upload_protocol = picotool
# add our variants files to the include and src paths
build_flags = ${rp2040_base.build_flags}
-DPRIVATE_HW
-Ivariants/rpipicow
-DARDUINO_AVR_NANO_EVERY
-DDEBUG_RP2040_WIRE
-DDEBUG_RP2040_SPI
-DDEBUG_RP2040_CORE
-DDEBUG_RP2040_PORT=Serial
-DUSE_TINYUSB
lib_deps =
${rp2040_base.lib_deps}

View File

@@ -0,0 +1,52 @@
// #define RADIOLIB_CUSTOM_ARDUINO 1
// #define RADIOLIB_TONE_UNSUPPORTED 1
// #define RADIOLIB_SOFTWARE_SERIAL_UNSUPPORTED 1
#define ARDUINO_ARCH_AVR
#define CBC 0
#define CTR 1
#define ECB 0
#define NO_GPS 1
#define USE_SH1106 1
#undef GPS_SERIAL_NUM
// #define I2C_SDA 6
// #define I2C_SCL 7
#define BUTTON_PIN 17
#define EXT_NOTIFY_OUT 4
#define BATTERY_PIN 26
// ratio of voltage divider = 3.0 (R17=200k, R18=100k)
#define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic
#define USE_RF95
#define USE_SX1262
#undef RF95_SCK
#undef RF95_MISO
#undef RF95_MOSI
#undef RF95_NSS
#define RF95_SCK 10
#define RF95_MISO 12
#define RF95_MOSI 11
#define RF95_NSS 3
#define LORA_DIO0 RADIOLIB_NC
#define LORA_RESET 15
#define LORA_DIO1 20
#define LORA_DIO2 2
#define LORA_DIO3 RADIOLIB_NC
#ifdef USE_SX1262
#define SX126X_CS RF95_NSS
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22
#endif
#include <Adafruit_TinyUSB.h>

View File

@@ -1,4 +1,4 @@
[VERSION]
major = 1
minor = 3
build = 43
build = 45