Compare commits

..

6 Commits

Author SHA1 Message Date
Kevin Hester
9d21e58b0b 1.2.46 2021-10-15 10:10:12 -07:00
Kevin Hester
576acdc117 update protobufs 2021-10-15 10:10:12 -07:00
Kevin Hester
538e22c7cd fix build for my hacked up nrf52 devboard (must use SD140) 2021-10-15 10:10:12 -07:00
Kevin Hester
d81f19c7c3 regen protos 2021-10-12 08:41:36 -07:00
Kevin Hester
252d847779 bl602 notes 2021-10-12 08:41:36 -07:00
Kevin Hester
3da6607a18 todo update 2021-10-12 08:41:36 -07:00
50 changed files with 408 additions and 796 deletions

View File

@@ -2,10 +2,4 @@
[![Open in Visual Studio Code](https://open.vscode.dev/badges/open-in-vscode.svg)](https://open.vscode.dev/meshtastic/Meshtastic-device) [![Open in Visual Studio Code](https://open.vscode.dev/badges/open-in-vscode.svg)](https://open.vscode.dev/meshtastic/Meshtastic-device)
## This repository contains the device firmware used in the [Meshtastic](https://meshtastic.org) project. ## This repository contains the device firmware used in the [Meshtastic](https://meshtastic.org) project.
Update Instructions
[For ESP32 devices click here](https://meshtastic.org/docs/getting-started/flashing-esp32)
[For nRF52 devices click here](https://meshtastic.org/docs/getting-started/flashing-nrf52)
For developer information and specific building instructions, please see the [developer doccumentation](https://meshtastic.org/docs/developers) For developer information and specific building instructions, please see the [developer doccumentation](https://meshtastic.org/docs/developers)

Binary file not shown.

View File

@@ -1 +0,0 @@
cd proto && ..\nanopb-0.4.4\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\proto *.proto

View File

@@ -111,8 +111,6 @@ lib_deps =
https://github.com/meshtastic/esp32_https_server.git https://github.com/meshtastic/esp32_https_server.git
adafruit/DHT sensor library@^1.4.1 adafruit/DHT sensor library@^1.4.1
adafruit/Adafruit Unified Sensor@^1.1.4 adafruit/Adafruit Unified Sensor@^1.1.4
paulstoffregen/OneWire@^2.3.5
robtillaart/DS18B20@^0.1.11
# Hmm - this doesn't work yet # Hmm - this doesn't work yet
# board_build.ldscript = linker/esp32.extram.bss.ld # board_build.ldscript = linker/esp32.extram.bss.ld
lib_ignore = segger_rtt lib_ignore = segger_rtt

View File

@@ -19,39 +19,28 @@ class GPSStatus : public Status
bool hasLock = false; // default to false, until we complete our first read bool hasLock = false; // default to false, until we complete our first read
bool isConnected = false; // Do we have a GPS we are talking to bool isConnected = false; // Do we have a GPS we are talking to
int32_t latitude = 0, longitude = 0; // as an int mult by 1e-7 to get value as double
Position p = Position_init_default; int32_t altitude = 0;
uint32_t dop = 0; // Diminution of position; PDOP where possible (UBlox), HDOP otherwise (TinyGPS) in 10^2 units (needs
// scaling before use)
uint32_t heading = 0;
uint32_t numSatellites = 0;
public: public:
GPSStatus() { statusType = STATUS_TYPE_GPS; } GPSStatus() { statusType = STATUS_TYPE_GPS; }
// proposed for deprecation
GPSStatus(bool hasLock, bool isConnected, int32_t latitude, int32_t longitude, int32_t altitude, uint32_t dop, GPSStatus(bool hasLock, bool isConnected, int32_t latitude, int32_t longitude, int32_t altitude, uint32_t dop,
uint32_t heading, uint32_t numSatellites) uint32_t heading, uint32_t numSatellites)
: Status() : Status()
{ {
this->hasLock = hasLock; this->hasLock = hasLock;
this->isConnected = isConnected; this->isConnected = isConnected;
this->latitude = latitude;
this->p.latitude_i = latitude; this->longitude = longitude;
this->p.longitude_i = longitude; this->altitude = altitude;
this->p.altitude = altitude; this->dop = dop;
this->p.PDOP = dop; this->heading = heading;
this->p.ground_track = heading; this->numSatellites = numSatellites;
this->p.sats_in_view = numSatellites;
} }
// preferred method
GPSStatus(bool hasLock, bool isConnected, Position pos)
: Status()
{
this->hasLock = hasLock;
this->isConnected = isConnected;
// all-in-one struct copy
this->p = pos;
}
GPSStatus(const GPSStatus &); GPSStatus(const GPSStatus &);
GPSStatus &operator=(const GPSStatus &); GPSStatus &operator=(const GPSStatus &);
@@ -67,7 +56,7 @@ class GPSStatus : public Status
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
return node->position.latitude_i; return node->position.latitude_i;
} else { } else {
return p.latitude_i; return latitude;
} }
} }
@@ -77,7 +66,7 @@ class GPSStatus : public Status
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
return node->position.longitude_i; return node->position.longitude_i;
} else { } else {
return p.longitude_i; return longitude;
} }
} }
@@ -87,59 +76,44 @@ class GPSStatus : public Status
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
return node->position.altitude; return node->position.altitude;
} else { } else {
return p.altitude; return altitude;
} }
} }
uint32_t getDOP() const { return p.PDOP; }
uint32_t getHeading() const { return p.ground_track; } uint32_t getDOP() const { return dop; }
uint32_t getNumSatellites() const { return p.sats_in_view; } uint32_t getHeading() const { return heading; }
uint32_t getNumSatellites() const { return numSatellites; }
bool matches(const GPSStatus *newStatus) const bool matches(const GPSStatus *newStatus) const
{ {
#if GPS_EXTRAVERBOSE return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected || newStatus->latitude != latitude ||
DEBUG_MSG("GPSStatus.match() new pos@%x to old pos@%x\n", newStatus->longitude != longitude || newStatus->altitude != altitude || newStatus->dop != dop ||
newStatus->p.pos_timestamp, p.pos_timestamp); newStatus->heading != heading || newStatus->numSatellites != numSatellites);
#endif
return (newStatus->hasLock != hasLock ||
newStatus->isConnected != isConnected ||
newStatus->p.latitude_i != p.latitude_i ||
newStatus->p.longitude_i != p.longitude_i ||
newStatus->p.altitude != p.altitude ||
newStatus->p.altitude_hae != p.altitude_hae ||
newStatus->p.PDOP != p.PDOP ||
newStatus->p.ground_track != p.ground_track ||
newStatus->p.sats_in_view != p.sats_in_view);
} }
int updateStatus(const GPSStatus *newStatus) int updateStatus(const GPSStatus *newStatus)
{ {
// Only update the status if values have actually changed // Only update the status if values have actually changed
bool isDirty = matches(newStatus); bool isDirty;
{
if (isDirty && p.pos_timestamp && isDirty = matches(newStatus);
(newStatus->p.pos_timestamp == p.pos_timestamp)) { initialized = true;
// We can NEVER be in two locations at the same time! (also PR #886) hasLock = newStatus->hasLock;
DEBUG_MSG("BUG!! positional timestamp unchanged from prev solution\n"); isConnected = newStatus->isConnected;
latitude = newStatus->latitude;
longitude = newStatus->longitude;
altitude = newStatus->altitude;
dop = newStatus->dop;
heading = newStatus->heading;
numSatellites = newStatus->numSatellites;
} }
initialized = true;
hasLock = newStatus->hasLock;
isConnected = newStatus->isConnected;
p = newStatus->p;
if (isDirty) { if (isDirty) {
if (hasLock) { if (hasLock)
// In debug logs, identify position by @timestamp:stage (stage 3 = notify) DEBUG_MSG("New GPS pos lat=%f, lon=%f, alt=%d, pdop=%f, heading=%f, sats=%d\n", latitude * 1e-7, longitude * 1e-7,
DEBUG_MSG("New GPS pos@%x:3 lat=%f, lon=%f, alt=%d, pdop=%.2f, track=%.2f, sats=%d\n", altitude, dop * 1e-2, heading * 1e-5, numSatellites);
p.pos_timestamp, else
p.latitude_i * 1e-7, p.longitude_i * 1e-7,
p.altitude, p.PDOP * 1e-2, p.ground_track * 1e-5,
p.sats_in_view);
} else
DEBUG_MSG("No GPS lock\n"); DEBUG_MSG("No GPS lock\n");
onNewStatus.notifyObservers(this); onNewStatus.notifyObservers(this);
} }

View File

@@ -11,11 +11,6 @@
/// Should we behave as if we have AC power now? /// Should we behave as if we have AC power now?
static bool isPowered() static bool isPowered()
{ {
// Completely circumvents the battery / power sensing logic and assumes constant power source
if (radioConfig.preferences.is_always_powered) {
return true;
}
bool isRouter = radioConfig.preferences.is_router; bool isRouter = radioConfig.preferences.is_router;
// If we are not a router and we already have AC power go to POWER state after init, otherwise go to ON // If we are not a router and we already have AC power go to POWER state after init, otherwise go to ON

View File

@@ -256,7 +256,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// supported modules list // supported modules list
#define USE_SX1262 #define USE_SX1262
#define USE_SX1268 #define USE_SX1268
#define USE_LLCC68
// common pinouts for SX126X modules // common pinouts for SX126X modules
#define SX126X_CS 18 // NSS for SX126X #define SX126X_CS 18 // NSS for SX126X

View File

@@ -202,13 +202,11 @@ void GPS::publishUpdate()
if (shouldPublish) { if (shouldPublish) {
shouldPublish = false; shouldPublish = false;
// In debug logs, identify position by @timestamp:stage (stage 2 = publish) DEBUG_MSG("publishing GPS lock=%d\n", hasLock());
DEBUG_MSG("publishing pos@%x:2, hasVal=%d, GPSlock=%d\n",
p.pos_timestamp, hasValidLocation, hasLock());
// Notify any status instances that are observing us // Notify any status instances that are observing us
const meshtastic::GPSStatus status = const meshtastic::GPSStatus status =
meshtastic::GPSStatus(hasValidLocation, isConnected(), p); meshtastic::GPSStatus(hasLock(), isConnected(), latitude, longitude, altitude, dop, heading, numSatellites);
newStatus.notifyObservers(&status); newStatus.notifyObservers(&status);
} }
} }
@@ -246,7 +244,6 @@ int32_t GPS::runOnce()
bool gotLoc = lookForLocation(); bool gotLoc = lookForLocation();
if (gotLoc && !hasValidLocation) { // declare that we have location ASAP if (gotLoc && !hasValidLocation) { // declare that we have location ASAP
DEBUG_MSG("hasValidLocation RISING EDGE\n");
hasValidLocation = true; hasValidLocation = true;
shouldPublish = true; shouldPublish = true;
} }
@@ -263,10 +260,6 @@ int32_t GPS::runOnce()
if (tooLong) { if (tooLong) {
// we didn't get a location during this ack window, therefore declare loss of lock // we didn't get a location during this ack window, therefore declare loss of lock
if (hasValidLocation) {
DEBUG_MSG("hasValidLocation FALLING EDGE (last read: %d)\n", gotLoc);
}
p = Position_init_default;
hasValidLocation = false; hasValidLocation = false;
} }

View File

@@ -17,10 +17,6 @@ class GPS : private concurrency::OSThread
private: private:
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastWhileActiveMsec = 0; uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastWhileActiveMsec = 0;
/**
* hasValidLocation - indicates that the position variables contain a complete
* GPS location, valid and fresh (< gps_update_interval + gps_attempt_time)
*/
bool hasValidLocation = false; // default to false, until we complete our first read bool hasValidLocation = false; // default to false, until we complete our first read
bool isAwake = false; // true if we want a location right now bool isAwake = false; // true if we want a location right now
@@ -43,7 +39,14 @@ class GPS : private concurrency::OSThread
/** If !0 we will attempt to connect to the GPS over I2C */ /** If !0 we will attempt to connect to the GPS over I2C */
static uint8_t i2cAddress; static uint8_t i2cAddress;
Position p = Position_init_default; int32_t latitude = 0, longitude = 0; // as an int mult by 1e-7 to get value as double
int32_t altitude = 0;
uint32_t dop = 0; // Diminution of position; PDOP where possible (UBlox), HDOP otherwise (TinyGPS) in 10^2 units (needs
// scaling before use)
uint32_t heading = 0; // Heading of motion, in degrees * 10^-5
int32_t geoidal_height = 0; // geoidal separation, in meters!
time_t pos_timestamp = 0; // positional timestamp from GPS solution
GPS() : concurrency::OSThread("GPS") {} GPS() : concurrency::OSThread("GPS") {}

View File

@@ -14,7 +14,7 @@
// Helper functions // Helper functions
// Raises a number to an exponent, handling negative exponents. // Raises a number to an exponent, handling negative exponents.
static inline double pow_neg(double base, double exponent) { static double pow_neg(double base, double exponent) {
if (exponent == 0) { if (exponent == 0) {
return 1; return 1;
} else if (exponent > 0) { } else if (exponent > 0) {

View File

@@ -95,17 +95,6 @@ bool NMEAGPS::lookForLocation()
if (! hasLock()) if (! hasLock())
return false; return false;
#ifdef GPS_EXTRAVERBOSE
DEBUG_MSG("AGE: LOC=%d FIX=%d DATE=%d TIME=%d\n",
reader.location.age(),
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
gsafixtype.age(),
#else
0,
#endif
reader.date.age(), reader.time.age());
#endif // GPS_EXTRAVERBOSE
// check if a complete GPS solution set is available for reading // check if a complete GPS solution set is available for reading
// tinyGPSDatum::age() also includes isValid() test // tinyGPSDatum::age() also includes isValid() test
// FIXME // FIXME
@@ -116,7 +105,7 @@ bool NMEAGPS::lookForLocation()
(reader.time.age() < GPS_SOL_EXPIRY_MS) && (reader.time.age() < GPS_SOL_EXPIRY_MS) &&
(reader.date.age() < GPS_SOL_EXPIRY_MS))) (reader.date.age() < GPS_SOL_EXPIRY_MS)))
{ {
DEBUG_MSG("SOME data is TOO OLD\n"); // DEBUG_MSG("SOME data is TOO OLD\n");
return false; return false;
} }
@@ -124,7 +113,7 @@ bool NMEAGPS::lookForLocation()
if (! reader.location.isUpdated()) if (! reader.location.isUpdated())
return false; return false;
// We know the solution is fresh and valid, so just read the data // Start reading the data
auto loc = reader.location.value(); auto loc = reader.location.value();
// Some GPSes (Air530) seem to send a zero longitude when the current fix is bogus // Some GPSes (Air530) seem to send a zero longitude when the current fix is bogus
@@ -134,34 +123,27 @@ bool NMEAGPS::lookForLocation()
return false; return false;
} }
p.location_source = Position_LocSource_LOCSRC_GPS_INTERNAL;
// Dilution of precision (an accuracy metric) is reported in 10^2 units, so we need to scale down when we use it // Dilution of precision (an accuracy metric) is reported in 10^2 units, so we need to scale down when we use it
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS #ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
p.HDOP = reader.hdop.value(); dop = TinyGPSPlus::parseDecimal(gsapdop.value());
p.PDOP = TinyGPSPlus::parseDecimal(gsapdop.value());
DEBUG_MSG("PDOP=%d, HDOP=%d\n", dop, reader.hdop.value());
#else #else
// FIXME! naive PDOP emulation (assumes VDOP==HDOP) // FIXME! naive PDOP emulation (assumes VDOP==HDOP)
// correct formula is PDOP = SQRT(HDOP^2 + VDOP^2) // correct formula is PDOP = SQRT(HDOP^2 + VDOP^2)
p.HDOP = reader.hdop.value(); dop = 1.41 * reader.hdop.value();
p.PDOP = 1.41 * reader.hdop.value();
#endif #endif
// Discard incomplete or erroneous readings // Discard incomplete or erroneous readings
if (reader.hdop.value() == 0) if (dop == 0)
return false; return false;
p.latitude_i = toDegInt(loc.lat); latitude = toDegInt(loc.lat);
p.longitude_i = toDegInt(loc.lng); longitude = toDegInt(loc.lng);
p.alt_geoid_sep = reader.geoidHeight.meters(); geoidal_height = reader.geoidHeight.meters();
p.altitude_hae = reader.altitude.meters() + p.alt_geoid_sep; #ifdef GPS_ALTITUDE_HAE
p.altitude = reader.altitude.meters(); altitude = reader.altitude.meters() + geoidal_height;
#else
p.fix_quality = fixQual; altitude = reader.altitude.meters();
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
p.fix_type = fixType;
#endif #endif
// positional timestamp // positional timestamp
@@ -173,16 +155,16 @@ bool NMEAGPS::lookForLocation()
t.tm_mon = reader.date.month() - 1; t.tm_mon = reader.date.month() - 1;
t.tm_year = reader.date.year() - 1900; t.tm_year = reader.date.year() - 1900;
t.tm_isdst = false; t.tm_isdst = false;
p.pos_timestamp = mktime(&t); pos_timestamp = mktime(&t);
// Nice to have, if available // Nice to have, if available
if (reader.satellites.isUpdated()) { if (reader.satellites.isUpdated()) {
p.sats_in_view = reader.satellites.value(); setNumSatellites(reader.satellites.value());
} }
if (reader.course.isUpdated() && reader.course.isValid()) { if (reader.course.isUpdated() && reader.course.isValid()) {
if (reader.course.value() < 36000) { // sanity check if (reader.course.value() < 36000) { // sanity check
p.ground_track = reader.course.value() * 1e3; // Scale the heading (in degrees * 10^-2) to match the expected degrees * 10^-5 heading = reader.course.value() * 1e3; // Scale the heading (in degrees * 10^-2) to match the expected degrees * 10^-5
} else { } else {
DEBUG_MSG("BOGUS course.value() REJECTED: %d\n", DEBUG_MSG("BOGUS course.value() REJECTED: %d\n",
reader.course.value()); reader.course.value());

View File

@@ -10,8 +10,6 @@
#define PDOP_INVALID 9999 #define PDOP_INVALID 9999
// #define UBX_MODE_NMEA
extern RadioConfig radioConfig; extern RadioConfig radioConfig;
UBloxGPS::UBloxGPS() {} UBloxGPS::UBloxGPS() {}
@@ -50,22 +48,12 @@ bool UBloxGPS::setupGPS()
delay(500); delay(500);
if (isConnected()) { if (isConnected()) {
#ifdef UBX_MODE_NMEA
DEBUG_MSG("Connected to UBLOX GPS, downgrading to NMEA mode\n");
DEBUG_MSG("- GPS errors below are related and safe to ignore\n");
#else
DEBUG_MSG("Connected to UBLOX GPS successfully\n"); DEBUG_MSG("Connected to UBLOX GPS successfully\n");
#endif
if (!setUBXMode()) if (!setUBXMode())
RECORD_CRITICALERROR(CriticalErrorCode_UBloxInitFailed); // Don't halt the boot if saving the config fails, but do report the bug RECORD_CRITICALERROR(CriticalErrorCode_UBloxInitFailed); // Don't halt the boot if saving the config fails, but do report the bug
#ifdef UBX_MODE_NMEA
return false;
#else
return true; return true;
#endif
} else { } else {
return false; return false;
} }
@@ -73,17 +61,6 @@ bool UBloxGPS::setupGPS()
bool UBloxGPS::setUBXMode() bool UBloxGPS::setUBXMode()
{ {
#ifdef UBX_MODE_NMEA
if (_serial_gps) {
ublox.setUART1Output(COM_TYPE_NMEA, 1000);
}
if (i2cAddress) {
ublox.setI2COutput(COM_TYPE_NMEA, 1000);
}
return false; // pretend initialization failed to force NMEA mode
#endif
if (_serial_gps) { if (_serial_gps) {
if (!ublox.setUART1Output(COM_TYPE_UBX, 1000)) // Use native API if (!ublox.setUART1Output(COM_TYPE_UBX, 1000)) // Use native API
return false; return false;
@@ -142,6 +119,7 @@ bool UBloxGPS::factoryReset()
void UBloxGPS::whileActive() void UBloxGPS::whileActive()
{ {
ublox.flushPVT(); // reset ALL freshness flags first ublox.flushPVT(); // reset ALL freshness flags first
ublox.getT(maxWait()); // ask for new time data - hopefully ready when we come back ublox.getT(maxWait()); // ask for new time data - hopefully ready when we come back
// Ask for a new position fix - hopefully it will have results ready by next time // Ask for a new position fix - hopefully it will have results ready by next time
@@ -192,29 +170,25 @@ bool UBloxGPS::lookForLocation()
{ {
bool foundLocation = false; bool foundLocation = false;
// check if a complete GPS solution set is available for reading // catch fixType changes here, instead of whileActive()
// (some of these, like lat/lon are redundant and can be removed) if (ublox.moduleQueried.fixType) {
if ( ! (ublox.moduleQueried.fixType && fixType = ublox.getFixType();
ublox.moduleQueried.latitude &&
ublox.moduleQueried.longitude &&
ublox.moduleQueried.altitude &&
ublox.moduleQueried.pDOP &&
ublox.moduleQueried.SIV &&
ublox.moduleQueried.gpsDay))
{
// Not ready? No problem! We'll try again later.
return false;
} }
fixType = ublox.getFixType();
#ifdef UBLOX_EXTRAVERBOSE
DEBUG_MSG("FixType=%d\n", fixType);
#endif
// check if GPS has an acceptable lock // check if GPS has an acceptable lock
if (! hasLock()) { if (! hasLock()) {
ublox.flushPVT(); // reset ALL freshness flags return false;
}
// check if a complete GPS solution set is available for reading
// (some of these, like lat/lon are redundant and can be removed)
if ( ! (ublox.moduleQueried.latitude &&
ublox.moduleQueried.longitude &&
ublox.moduleQueried.altitude &&
ublox.moduleQueried.pDOP &&
ublox.moduleQueried.gpsiTOW))
{
// Not ready? No problem! We'll try again later.
return false; return false;
} }
@@ -225,10 +199,6 @@ bool UBloxGPS::lookForLocation()
int32_t tmp_lon = ublox.getLongitude(0); int32_t tmp_lon = ublox.getLongitude(0);
int32_t tmp_alt_msl = ublox.getAltitudeMSL(0); int32_t tmp_alt_msl = ublox.getAltitudeMSL(0);
int32_t tmp_alt_hae = ublox.getAltitude(0); int32_t tmp_alt_hae = ublox.getAltitude(0);
int32_t max_dop = PDOP_INVALID;
if (radioConfig.preferences.gps_max_dop)
max_dop = radioConfig.preferences.gps_max_dop * 100; // scaling
// Note: heading is only currently implmented in the ublox for the 8m chipset - therefore // Note: heading is only currently implmented in the ublox for the 8m chipset - therefore
// don't read it here - it will generate an ignored getPVT command on the 6ms // don't read it here - it will generate an ignored getPVT command on the 6ms
// heading = ublox.getHeading(0); // heading = ublox.getHeading(0);
@@ -245,55 +215,41 @@ bool UBloxGPS::lookForLocation()
time_t tmp_ts = mktime(&t); time_t tmp_ts = mktime(&t);
// FIXME - can opportunistically attempt to set RTC from GPS timestamp? // SIV number is nice-to-have if it's available
if (ublox.moduleQueried.SIV) {
uint16_t gSIV = ublox.getSIV(0);
setNumSatellites(gSIV);
}
// bogus lat lon is reported as 0 or 0 (can be bogus just for one) // bogus lat lon is reported as 0 or 0 (can be bogus just for one)
// Also: apparently when the GPS is initially reporting lock it can output a bogus latitude > 90 deg! // Also: apparently when the GPS is initially reporting lock it can output a bogus latitude > 90 deg!
// FIXME - NULL ISLAND is a real location on Earth! // FIXME - NULL ISLAND is a real location on Earth!
foundLocation = (tmp_lat != 0) && (tmp_lon != 0) && foundLocation = (tmp_lat != 0) && (tmp_lon != 0) &&
(tmp_lat <= 900000000) && (tmp_lat >= -900000000) && (tmp_lat <= 900000000) && (tmp_lat >= -900000000) &&
(tmp_dop < max_dop); (tmp_dop < PDOP_INVALID);
// only if entire dataset is valid, update globals from temp vars // only if entire dataset is valid, update globals from temp vars
if (foundLocation) { if (foundLocation) {
p.location_source = Position_LocSource_LOCSRC_GPS_INTERNAL; longitude = tmp_lon;
p.longitude_i = tmp_lon; latitude = tmp_lat;
p.latitude_i = tmp_lat; #ifdef GPS_ALTITUDE_HAE
if (fixType > 2) { altitude = tmp_alt_hae / 1000;
// if fix is 2d, ignore altitude data #else
p.altitude = tmp_alt_msl / 1000; altitude = tmp_alt_msl / 1000;
p.altitude_hae = tmp_alt_hae / 1000;
p.alt_geoid_sep = (tmp_alt_hae - tmp_alt_msl) / 1000;
} else {
#ifdef GPS_EXTRAVERBOSE
DEBUG_MSG("no altitude data (fixType=%d)\n", fixType);
#endif #endif
// clean up old values in case it's a 3d-2d fix transition geoidal_height = (tmp_alt_hae - tmp_alt_msl) / 1000;
p.altitude = p.altitude_hae = p.alt_geoid_sep = 0; pos_timestamp = tmp_ts;
} dop = tmp_dop;
p.pos_timestamp = tmp_ts;
p.PDOP = tmp_dop;
p.fix_type = fixType;
p.sats_in_view = ublox.getSIV(0);
// In debug logs, identify position by @timestamp:stage (stage 1 = birth)
DEBUG_MSG("lookForLocation() new pos@%x:1\n", tmp_ts);
} else { } else {
// INVALID solution - should never happen DEBUG_MSG("Invalid location discarded\n");
DEBUG_MSG("Invalid location lat/lon/hae/dop %d/%d/%d/%d - discarded\n",
tmp_lat, tmp_lon, tmp_alt_hae, tmp_dop);
} }
ublox.flushPVT(); // reset ALL freshness flags at the end
return foundLocation; return foundLocation;
} }
bool UBloxGPS::hasLock() bool UBloxGPS::hasLock()
{ {
if (radioConfig.preferences.gps_accept_2d) return (fixType >= 3 && fixType <= 4);
return (fixType >= 2 && fixType <= 4);
else
return (fixType >= 3 && fixType <= 4);
} }
bool UBloxGPS::whileIdle() bool UBloxGPS::whileIdle()

View File

@@ -226,13 +226,6 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta
display->drawString(0 + x, FONT_HEIGHT_MEDIUM + y, "For help, please post on\nmeshtastic.discourse.group"); display->drawString(0 + x, FONT_HEIGHT_MEDIUM + y, "For help, please post on\nmeshtastic.discourse.group");
} }
// Ignore messages orginating from phone (from the current node 0x0) unless range test or store and forward plugin are enabled
static bool shouldDrawMessage(const MeshPacket *packet) {
return packet->from != 0 &&
!radioConfig.preferences.range_test_plugin_enabled &&
!radioConfig.preferences.store_forward_plugin_enabled;
}
/// Draw the last text message we received /// Draw the last text message we received
static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
@@ -932,8 +925,8 @@ void Screen::setFrames()
if (myNodeInfo.error_code) if (myNodeInfo.error_code)
normalFrames[numframes++] = drawCriticalFaultFrame; normalFrames[numframes++] = drawCriticalFaultFrame;
// If we have a text message - show it next, unless it's a phone message and we aren't using any special plugins // If we have a text message - show it next
if (devicestate.has_rx_text_message && shouldDrawMessage(&devicestate.rx_text_message)) if (devicestate.has_rx_text_message)
normalFrames[numframes++] = drawTextMessageFrame; normalFrames[numframes++] = drawTextMessageFrame;
// then all the nodes // then all the nodes
@@ -1364,7 +1357,8 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
return 0; return 0;
} }
int Screen::handleTextMessage(const MeshPacket *packet) { int Screen::handleTextMessage(const MeshPacket *arg)
{
if (showingNormalScreen) { if (showingNormalScreen) {
setFrames(); // Regen the list of screens (will show new text message) setFrames(); // Regen the list of screens (will show new text message)
} }

View File

@@ -40,7 +40,6 @@
#include "RF95Interface.h" #include "RF95Interface.h"
#include "SX1262Interface.h" #include "SX1262Interface.h"
#include "SX1268Interface.h" #include "SX1268Interface.h"
#include "LLCC68Interface.h"
#ifdef NRF52_SERIES #ifdef NRF52_SERIES
#include "variant.h" #include "variant.h"
@@ -540,19 +539,6 @@ void setup()
} }
#endif #endif
#if defined(USE_LLCC68)
if (!rIf) {
rIf = new LLCC68Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
if (!rIf->init()) {
DEBUG_MSG("Warning: Failed to find LLCC68 radio\n");
delete rIf;
rIf = NULL;
} else {
DEBUG_MSG("LLCC68 Radio init succeeded, using LLCC68 radio\n");
}
}
#endif
#ifdef USE_SIM_RADIO #ifdef USE_SIM_RADIO
if (!rIf) { if (!rIf) {
rIf = new SimRadio; rIf = new SimRadio;

View File

@@ -3,5 +3,4 @@
// We need this declaration for proper linking in derived classes // We need this declaration for proper linking in derived classes
template class SX126xInterface<SX1262>; template class SX126xInterface<SX1262>;
template class SX126xInterface<SX1268>; template class SX126xInterface<SX1268>;
template class SX126xInterface<LLCC68>;

View File

@@ -1,9 +0,0 @@
#include "configuration.h"
#include "LLCC68Interface.h"
#include "error.h"
LLCC68Interface::LLCC68Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi)
: SX126xInterface(cs, irq, rst, busy, spi)
{
}

View File

@@ -1,17 +0,0 @@
#pragma once
#include "SX126xInterface.h"
/**
* Our adapter for LLCC68 radios
* https://www.semtech.com/products/wireless-rf/lora-core/llcc68
* ⚠️⚠️⚠️
* Be aware that LLCC68 does not support Spreading Factor 12 (SF12) and will not work on the default "Long Slow" channel.
* You must change the channel if you get `Critical Error #3` with this module.
* ⚠️⚠️⚠️
*/
class LLCC68Interface : public SX126xInterface<LLCC68>
{
public:
LLCC68Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
};

View File

@@ -112,11 +112,7 @@ bool MeshService::reloadConfig()
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh /// The owner User record just got updated, update our node DB and broadcast the info into the mesh
void MeshService::reloadOwner() void MeshService::reloadOwner()
{ {
// DEBUG_MSG("reloadOwner()\n");
// update our local data directly
nodeDB.updateUser(nodeDB.getNodeNum(), owner);
assert(nodeInfoPlugin); assert(nodeInfoPlugin);
// update everyone else
if (nodeInfoPlugin) if (nodeInfoPlugin)
nodeInfoPlugin->sendOurNodeInfo(); nodeInfoPlugin->sendOurNodeInfo();
nodeDB.saveToDisk(); nodeDB.saveToDisk();
@@ -144,7 +140,7 @@ void MeshService::handleToRadio(MeshPacket &p)
// Send the packet into the mesh // Send the packet into the mesh
sendToMesh(packetPool.allocCopy(p), RX_SRC_USER); sendToMesh(packetPool.allocCopy(p));
bool loopback = false; // if true send any packet the phone sends back itself (for testing) bool loopback = false; // if true send any packet the phone sends back itself (for testing)
if (loopback) { if (loopback) {
@@ -161,12 +157,12 @@ bool MeshService::cancelSending(PacketId id)
return router->cancelSending(nodeDB.getNodeNum(), id); return router->cancelSending(nodeDB.getNodeNum(), id);
} }
void MeshService::sendToMesh(MeshPacket *p, RxSource src) void MeshService::sendToMesh(MeshPacket *p)
{ {
nodeDB.updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...) nodeDB.updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...)
// Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it // Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it
router->sendLocal(p, src); router->sendLocal(p);
} }
void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies) void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
@@ -213,39 +209,34 @@ NodeInfo *MeshService::refreshMyNodeInfo()
return node; return node;
} }
int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus) int MeshService::onGPSChanged(const meshtastic::GPSStatus *unused)
{ {
// Update our local node info with our position (even if we don't decide to update anyone else) // Update our local node info with our position (even if we don't decide to update anyone else)
NodeInfo *node = refreshMyNodeInfo(); NodeInfo *node = refreshMyNodeInfo();
Position pos = Position_init_default; Position pos = node->position;
if (newStatus->getHasLock()) { if (gps->hasLock()) {
// load data from GPS object, will add timestamp + battery further down if (gps->altitude != 0)
pos = gps->p; pos.altitude = gps->altitude;
pos.latitude_i = gps->latitude;
pos.longitude_i = gps->longitude;
} else { } else {
// The GPS has lost lock, if we are fixed position we should just keep using // The GPS has lost lock, if we are fixed position we should just keep using
// the old position // the old position
#if GPS_EXTRAVERBOSE
DEBUG_MSG("onGPSchanged() - lost validLocation\n");
#endif
if (radioConfig.preferences.fixed_position) { if (radioConfig.preferences.fixed_position) {
DEBUG_MSG("WARNING: Using fixed position\n"); DEBUG_MSG("WARNING: Using fixed position\n");
pos = node->position; } else {
// throw away old position
pos.latitude_i = 0;
pos.longitude_i = 0;
pos.altitude = 0;
} }
} }
// Finally add a fresh timestamp and battery level reading DEBUG_MSG("got gps notify time=%u, lat=%d, bat=%d\n", pos.time, pos.latitude_i, pos.battery_level);
// I KNOW this is redundant with refreshMyNodeInfo() above, but these are
// inexpensive nonblocking calls and can be refactored in due course
pos.time = getValidTime(RTCQualityGPS);
pos.battery_level = powerStatus->getBatteryChargePercent();
// In debug logs, identify position by @timestamp:stage (stage 4 = nodeDB)
DEBUG_MSG("onGPSChanged() pos@%x:4, time=%u, lat=%d, bat=%d\n",
pos.pos_timestamp, pos.time, pos.latitude_i, pos.battery_level);
// Update our current position in the local DB // Update our current position in the local DB
nodeDB.updatePosition(nodeDB.getNodeNum(), pos, RX_SRC_LOCAL); nodeDB.updatePosition(nodeDB.getNodeNum(), pos);
return 0; return 0;
} }

View File

@@ -75,7 +75,7 @@ class MeshService
/// Send a packet into the mesh - note p must have been allocated from packetPool. We will return it to that pool after /// Send a packet into the mesh - note p must have been allocated from packetPool. We will return it to that pool after
/// sending. This is the ONLY function you should use for sending messages into the mesh, because it also updates the nodedb /// sending. This is the ONLY function you should use for sending messages into the mesh, because it also updates the nodedb
/// cache /// cache
void sendToMesh(MeshPacket *p, RxSource src = RX_SRC_LOCAL); void sendToMesh(MeshPacket *p);
/** Attempt to cancel a previously sent packet from this _local_ node. Returns true if a packet was found we could cancel */ /** Attempt to cancel a previously sent packet from this _local_ node. Returns true if a packet was found we could cancel */
bool cancelSending(PacketId id); bool cancelSending(PacketId id);

View File

@@ -20,8 +20,7 @@ typedef uint32_t PacketId; // A packet sequence number
*/ */
enum RxSource { enum RxSource {
RX_SRC_LOCAL, // message was generated locally RX_SRC_LOCAL, // message was generated locally
RX_SRC_RADIO, // message was received from radio mesh RX_SRC_RADIO // message was received from radio mesh
RX_SRC_USER // message was received from end-user device
}; };
/** /**

View File

@@ -125,11 +125,6 @@ void NodeDB::installDefaultRadioConfig()
memset(&radioConfig, 0, sizeof(radioConfig)); memset(&radioConfig, 0, sizeof(radioConfig));
radioConfig.has_preferences = true; radioConfig.has_preferences = true;
resetRadioConfig(); resetRadioConfig();
// for backward compat, default position flags are BAT+ALT+MSL (0x23 = 35)
radioConfig.preferences.position_flags = (PositionFlags_POS_BATTERY |
PositionFlags_POS_ALTITUDE | PositionFlags_POS_ALT_MSL);
} }
void NodeDB::installDefaultChannels() void NodeDB::installDefaultChannels()
@@ -447,42 +442,25 @@ size_t NodeDB::getNumOnlineNodes()
/** Update position info for this node based on received position data /** Update position info for this node based on received position data
*/ */
void NodeDB::updatePosition(uint32_t nodeId, const Position &p, RxSource src) void NodeDB::updatePosition(uint32_t nodeId, const Position &p)
{ {
NodeInfo *info = getOrCreateNode(nodeId); NodeInfo *info = getOrCreateNode(nodeId);
if (src == RX_SRC_LOCAL) { DEBUG_MSG("DB update position node=0x%x time=%u, latI=%d, lonI=%d\n", nodeId, p.time, p.latitude_i, p.longitude_i);
// Local packet, fully authoritative
DEBUG_MSG("updatePosition LOCAL pos@%x:5, time=%u, latI=%d, lonI=%d\n",
p.pos_timestamp, p.time, p.latitude_i, p.longitude_i);
info->position = p;
} else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.pos_timestamp && // Be careful to only update fields that have been set by the sender
!p.location_source) { // A lot of position reports don't have time populated. In that case, be careful to not blow away the time we
// FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO // recorded based on the packet rxTime
// (stop-gap fix for issue #900) if (p.time)
DEBUG_MSG("updatePosition SPECIAL time setting time=%u\n", p.time);
info->position.time = p.time; info->position.time = p.time;
if (p.battery_level)
} else { info->position.battery_level = p.battery_level;
// Be careful to only update fields that have been set by the REMOTE sender if (p.latitude_i || p.longitude_i) {
// A lot of position reports don't have time populated. In that case, be careful to not blow away the time we info->position.latitude_i = p.latitude_i;
// recorded based on the packet rxTime info->position.longitude_i = p.longitude_i;
//
// FIXME perhaps handle RX_SRC_USER separately?
DEBUG_MSG("updatePosition REMOTE node=0x%x time=%u, latI=%d, lonI=%d\n",
nodeId, p.time, p.latitude_i, p.longitude_i);
// First, back up fields that we want to protect from overwrite
uint32_t tmp_time = info->position.time;
// Next, update atomically
info->position = p;
// Last, restore any fields that may have been overwritten
if (! info->position.time)
info->position.time = tmp_time;
} }
if (p.altitude)
info->position.altitude = p.altitude;
info->has_position = true; info->has_position = true;
updateGUIforNode = info; updateGUIforNode = info;
notifyObservers(true); // Force an update whether or not our node counts have changed notifyObservers(true); // Force an update whether or not our node counts have changed

View File

@@ -59,7 +59,7 @@ class NodeDB
/** Update position info for this node based on received position data /** Update position info for this node based on received position data
*/ */
void updatePosition(uint32_t nodeId, const Position &p, RxSource src = RX_SRC_RADIO); void updatePosition(uint32_t nodeId, const Position &p);
/** Update user info for this node based on received user data /** Update user info for this node based on received user data
*/ */

View File

@@ -307,8 +307,6 @@ void RadioInterface::applyModemConfig()
if (bw == 31) // This parameter is not an integer if (bw == 31) // This parameter is not an integer
bw = 31.25; bw = 31.25;
if (bw == 62) // Fix for 62.5Khz bandwidth
bw = 62.5;
} }
power = channelSettings.tx_power; power = channelSettings.tx_power;

View File

@@ -145,7 +145,7 @@ void Router::setReceivedMessage()
runASAP = true; runASAP = true;
} }
ErrorCode Router::sendLocal(MeshPacket *p, RxSource src) ErrorCode Router::sendLocal(MeshPacket *p)
{ {
// No need to deliver externally if the destination is the local node // No need to deliver externally if the destination is the local node
if (p->to == nodeDB.getNodeNum()) { if (p->to == nodeDB.getNodeNum()) {
@@ -161,7 +161,7 @@ ErrorCode Router::sendLocal(MeshPacket *p, RxSource src)
// If we are sending a broadcast, we also treat it as if we just received it ourself // If we are sending a broadcast, we also treat it as if we just received it ourself
// this allows local apps (and PCs) to see broadcasts sourced locally // this allows local apps (and PCs) to see broadcasts sourced locally
if (p->to == NODENUM_BROADCAST) { if (p->to == NODENUM_BROADCAST) {
handleReceived(p, src); handleReceived(p, RX_SRC_LOCAL);
} }
return send(p); return send(p);
@@ -334,11 +334,9 @@ void Router::handleReceived(MeshPacket *p, RxSource src)
if (decoded) { if (decoded) {
// parsing was successful, queue for our recipient // parsing was successful, queue for our recipient
if (src == RX_SRC_LOCAL) if (src == RX_SRC_LOCAL)
printPacket("handleReceived(LOCAL)", p); printPacket("handleReceived(local)", p);
else if (src == RX_SRC_USER)
printPacket("handleReceived(USER)", p);
else else
printPacket("handleReceived(REMOTE)", p); printPacket("handleReceived(remote)", p);
} else { } else {
printPacket("packet decoding failed (no PSK?)", p); printPacket("packet decoding failed (no PSK?)", p);
} }

View File

@@ -45,7 +45,7 @@ class Router : protected concurrency::OSThread
* *
* NOTE: This method will free the provided packet (even if we return an error code) * NOTE: This method will free the provided packet (even if we return an error code)
*/ */
ErrorCode sendLocal(MeshPacket *p, RxSource src = RX_SRC_RADIO); ErrorCode sendLocal(MeshPacket *p);
/** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */ /** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */
bool cancelSending(NodeNum from, PacketId id); bool cancelSending(NodeNum from, PacketId id);

View File

@@ -79,7 +79,7 @@ extern const pb_msgdesc_t AdminMessage_msg;
#define AdminMessage_fields &AdminMessage_msg #define AdminMessage_fields &AdminMessage_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define AdminMessage_size 420 #define AdminMessage_size 407
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@@ -125,7 +125,7 @@ extern const pb_msgdesc_t ChannelFile_msg;
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define LegacyRadioConfig_size 4 #define LegacyRadioConfig_size 4
#define LegacyRadioConfig_LegacyPreferences_size 2 #define LegacyRadioConfig_LegacyPreferences_size 2
#define DeviceState_size 9000 #define DeviceState_size 10054
#define ChannelFile_size 832 #define ChannelFile_size 832
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -51,4 +51,3 @@ PB_BIND(ToRadio_PeerInfo, ToRadio_PeerInfo, AUTO)

View File

@@ -33,24 +33,6 @@ typedef enum _HardwareModel {
HardwareModel_DIY_V1 = 39 HardwareModel_DIY_V1 = 39
} HardwareModel; } HardwareModel;
typedef enum _Team {
Team_CLEAR = 0,
Team_CYAN = 1,
Team_WHITE = 2,
Team_YELLOW = 3,
Team_ORANGE = 4,
Team_MAGENTA = 5,
Team_RED = 6,
Team_MAROON = 7,
Team_PURPLE = 8,
Team_DARK_BLUE = 9,
Team_BLUE = 10,
Team_TEAL = 11,
Team_GREEN = 12,
Team_DARK_GREEN = 13,
Team_BROWN = 14
} Team;
typedef enum _Constants { typedef enum _Constants {
Constants_Unused = 0, Constants_Unused = 0,
Constants_DATA_PAYLOAD_LEN = 237 Constants_DATA_PAYLOAD_LEN = 237
@@ -176,6 +158,11 @@ typedef struct _Position {
uint32_t fix_type; uint32_t fix_type;
uint32_t sats_in_view; uint32_t sats_in_view;
uint32_t sensor_id; uint32_t sensor_id;
uint32_t heading;
int32_t roll;
int32_t pitch;
uint32_t air_speed;
uint32_t ground_distance_cm;
uint32_t pos_next_update; uint32_t pos_next_update;
uint32_t pos_seq_number; uint32_t pos_seq_number;
} Position; } Position;
@@ -197,7 +184,6 @@ typedef struct _User {
pb_byte_t macaddr[6]; pb_byte_t macaddr[6];
HardwareModel hw_model; HardwareModel hw_model;
bool is_licensed; bool is_licensed;
Team team;
} User; } User;
typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t; typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t;
@@ -267,10 +253,6 @@ typedef struct _ToRadio {
#define _HardwareModel_MAX HardwareModel_DIY_V1 #define _HardwareModel_MAX HardwareModel_DIY_V1
#define _HardwareModel_ARRAYSIZE ((HardwareModel)(HardwareModel_DIY_V1+1)) #define _HardwareModel_ARRAYSIZE ((HardwareModel)(HardwareModel_DIY_V1+1))
#define _Team_MIN Team_CLEAR
#define _Team_MAX Team_BROWN
#define _Team_ARRAYSIZE ((Team)(Team_BROWN+1))
#define _Constants_MIN Constants_Unused #define _Constants_MIN Constants_Unused
#define _Constants_MAX Constants_DATA_PAYLOAD_LEN #define _Constants_MAX Constants_DATA_PAYLOAD_LEN
#define _Constants_ARRAYSIZE ((Constants)(Constants_DATA_PAYLOAD_LEN+1)) #define _Constants_ARRAYSIZE ((Constants)(Constants_DATA_PAYLOAD_LEN+1))
@@ -305,8 +287,8 @@ extern "C" {
#endif #endif
/* Initializer values for message structs */ /* Initializer values for message structs */
#define Position_init_default {0, 0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define Position_init_default {0, 0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define User_init_default {"", "", "", {0}, _HardwareModel_MIN, 0, _Team_MIN} #define User_init_default {"", "", "", {0}, _HardwareModel_MIN, 0}
#define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}} #define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}}
#define Routing_init_default {0, {RouteDiscovery_init_default}} #define Routing_init_default {0, {RouteDiscovery_init_default}}
#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0} #define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0}
@@ -317,8 +299,8 @@ extern "C" {
#define FromRadio_init_default {0, 0, {MyNodeInfo_init_default}} #define FromRadio_init_default {0, 0, {MyNodeInfo_init_default}}
#define ToRadio_init_default {0, {MeshPacket_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}}
#define ToRadio_PeerInfo_init_default {0, 0} #define ToRadio_PeerInfo_init_default {0, 0}
#define Position_init_zero {0, 0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define Position_init_zero {0, 0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0, _Team_MIN} #define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0}
#define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}} #define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
#define Routing_init_zero {0, {RouteDiscovery_init_zero}} #define Routing_init_zero {0, {RouteDiscovery_init_zero}}
#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0} #define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0}
@@ -375,6 +357,11 @@ extern "C" {
#define Position_fix_type_tag 23 #define Position_fix_type_tag 23
#define Position_sats_in_view_tag 24 #define Position_sats_in_view_tag 24
#define Position_sensor_id_tag 25 #define Position_sensor_id_tag 25
#define Position_heading_tag 30
#define Position_roll_tag 31
#define Position_pitch_tag 32
#define Position_air_speed_tag 33
#define Position_ground_distance_cm_tag 34
#define Position_pos_next_update_tag 40 #define Position_pos_next_update_tag 40
#define Position_pos_seq_number_tag 41 #define Position_pos_seq_number_tag 41
#define RouteDiscovery_route_tag 2 #define RouteDiscovery_route_tag 2
@@ -386,7 +373,6 @@ extern "C" {
#define User_macaddr_tag 4 #define User_macaddr_tag 4
#define User_hw_model_tag 6 #define User_hw_model_tag 6
#define User_is_licensed_tag 7 #define User_is_licensed_tag 7
#define User_team_tag 8
#define MeshPacket_from_tag 1 #define MeshPacket_from_tag 1
#define MeshPacket_to_tag 2 #define MeshPacket_to_tag 2
#define MeshPacket_channel_tag 3 #define MeshPacket_channel_tag 3
@@ -442,6 +428,11 @@ X(a, STATIC, SINGULAR, UINT32, fix_quality, 22) \
X(a, STATIC, SINGULAR, UINT32, fix_type, 23) \ X(a, STATIC, SINGULAR, UINT32, fix_type, 23) \
X(a, STATIC, SINGULAR, UINT32, sats_in_view, 24) \ X(a, STATIC, SINGULAR, UINT32, sats_in_view, 24) \
X(a, STATIC, SINGULAR, UINT32, sensor_id, 25) \ X(a, STATIC, SINGULAR, UINT32, sensor_id, 25) \
X(a, STATIC, SINGULAR, UINT32, heading, 30) \
X(a, STATIC, SINGULAR, SINT32, roll, 31) \
X(a, STATIC, SINGULAR, SINT32, pitch, 32) \
X(a, STATIC, SINGULAR, UINT32, air_speed, 33) \
X(a, STATIC, SINGULAR, UINT32, ground_distance_cm, 34) \
X(a, STATIC, SINGULAR, UINT32, pos_next_update, 40) \ X(a, STATIC, SINGULAR, UINT32, pos_next_update, 40) \
X(a, STATIC, SINGULAR, UINT32, pos_seq_number, 41) X(a, STATIC, SINGULAR, UINT32, pos_seq_number, 41)
#define Position_CALLBACK NULL #define Position_CALLBACK NULL
@@ -453,8 +444,7 @@ X(a, STATIC, SINGULAR, STRING, long_name, 2) \
X(a, STATIC, SINGULAR, STRING, short_name, 3) \ X(a, STATIC, SINGULAR, STRING, short_name, 3) \
X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4) \ X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4) \
X(a, STATIC, SINGULAR, UENUM, hw_model, 6) \ X(a, STATIC, SINGULAR, UENUM, hw_model, 6) \
X(a, STATIC, SINGULAR, BOOL, is_licensed, 7) \ X(a, STATIC, SINGULAR, BOOL, is_licensed, 7)
X(a, STATIC, SINGULAR, UENUM, team, 8)
#define User_CALLBACK NULL #define User_CALLBACK NULL
#define User_DEFAULT NULL #define User_DEFAULT NULL
@@ -594,13 +584,13 @@ extern const pb_msgdesc_t ToRadio_PeerInfo_msg;
#define ToRadio_PeerInfo_fields &ToRadio_PeerInfo_msg #define ToRadio_PeerInfo_fields &ToRadio_PeerInfo_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define Position_size 153 #define Position_size 188
#define User_size 78 #define User_size 76
#define RouteDiscovery_size 40 #define RouteDiscovery_size 40
#define Routing_size 42 #define Routing_size 42
#define Data_size 260 #define Data_size 260
#define MeshPacket_size 309 #define MeshPacket_size 309
#define NodeInfo_size 252 #define NodeInfo_size 285
#define MyNodeInfo_size 101 #define MyNodeInfo_size 101
#define LogRecord_size 81 #define LogRecord_size 81
#define FromRadio_size 318 #define FromRadio_size 318

View File

@@ -80,8 +80,7 @@ typedef enum _PositionFlags {
} PositionFlags; } PositionFlags;
typedef enum _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType { typedef enum _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType {
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11 = 0, RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11 = 0
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20 = 1
} RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType; } RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType;
/* Struct definitions */ /* Struct definitions */
@@ -113,8 +112,6 @@ typedef struct _RadioConfig_UserPreferences {
char mqtt_server[32]; char mqtt_server[32];
bool mqtt_disabled; bool mqtt_disabled;
GpsCoordinateFormat gps_format; GpsCoordinateFormat gps_format;
bool gps_accept_2d;
uint32_t gps_max_dop;
bool factory_reset; bool factory_reset;
bool debug_log_enabled; bool debug_log_enabled;
pb_size_t ignore_incoming_count; pb_size_t ignore_incoming_count;
@@ -145,7 +142,6 @@ typedef struct _RadioConfig_UserPreferences {
uint32_t environmental_measurement_plugin_sensor_pin; uint32_t environmental_measurement_plugin_sensor_pin;
bool store_forward_plugin_enabled; bool store_forward_plugin_enabled;
uint32_t position_flags; uint32_t position_flags;
bool is_always_powered;
} RadioConfig_UserPreferences; } RadioConfig_UserPreferences;
typedef struct _RadioConfig { typedef struct _RadioConfig {
@@ -180,8 +176,8 @@ typedef struct _RadioConfig {
#define _PositionFlags_ARRAYSIZE ((PositionFlags)(PositionFlags_POS_TIMESTAMP+1)) #define _PositionFlags_ARRAYSIZE ((PositionFlags)(PositionFlags_POS_TIMESTAMP+1))
#define _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11 #define _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11
#define _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MAX RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20 #define _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MAX RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11
#define _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_ARRAYSIZE ((RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType)(RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20+1)) #define _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_ARRAYSIZE ((RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType)(RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11+1))
#ifdef __cplusplus #ifdef __cplusplus
@@ -190,9 +186,9 @@ extern "C" {
/* Initializer values for message structs */ /* Initializer values for message structs */
#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default}
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0, 0} #define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0}
#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero}
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0, 0} #define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0}
/* Field tags (for use in manual encoding/decoding) */ /* Field tags (for use in manual encoding/decoding) */
#define RadioConfig_UserPreferences_position_broadcast_secs_tag 1 #define RadioConfig_UserPreferences_position_broadcast_secs_tag 1
@@ -222,8 +218,6 @@ extern "C" {
#define RadioConfig_UserPreferences_mqtt_server_tag 42 #define RadioConfig_UserPreferences_mqtt_server_tag 42
#define RadioConfig_UserPreferences_mqtt_disabled_tag 43 #define RadioConfig_UserPreferences_mqtt_disabled_tag 43
#define RadioConfig_UserPreferences_gps_format_tag 44 #define RadioConfig_UserPreferences_gps_format_tag 44
#define RadioConfig_UserPreferences_gps_accept_2d_tag 45
#define RadioConfig_UserPreferences_gps_max_dop_tag 46
#define RadioConfig_UserPreferences_factory_reset_tag 100 #define RadioConfig_UserPreferences_factory_reset_tag 100
#define RadioConfig_UserPreferences_debug_log_enabled_tag 101 #define RadioConfig_UserPreferences_debug_log_enabled_tag 101
#define RadioConfig_UserPreferences_ignore_incoming_tag 103 #define RadioConfig_UserPreferences_ignore_incoming_tag 103
@@ -253,7 +247,6 @@ extern "C" {
#define RadioConfig_UserPreferences_environmental_measurement_plugin_sensor_pin_tag 147 #define RadioConfig_UserPreferences_environmental_measurement_plugin_sensor_pin_tag 147
#define RadioConfig_UserPreferences_store_forward_plugin_enabled_tag 148 #define RadioConfig_UserPreferences_store_forward_plugin_enabled_tag 148
#define RadioConfig_UserPreferences_position_flags_tag 150 #define RadioConfig_UserPreferences_position_flags_tag 150
#define RadioConfig_UserPreferences_is_always_powered_tag 151
#define RadioConfig_preferences_tag 1 #define RadioConfig_preferences_tag 1
/* Struct field encoding specification for nanopb */ /* Struct field encoding specification for nanopb */
@@ -291,8 +284,6 @@ X(a, STATIC, SINGULAR, FLOAT, frequency_offset, 41) \
X(a, STATIC, SINGULAR, STRING, mqtt_server, 42) \ X(a, STATIC, SINGULAR, STRING, mqtt_server, 42) \
X(a, STATIC, SINGULAR, BOOL, mqtt_disabled, 43) \ X(a, STATIC, SINGULAR, BOOL, mqtt_disabled, 43) \
X(a, STATIC, SINGULAR, UENUM, gps_format, 44) \ X(a, STATIC, SINGULAR, UENUM, gps_format, 44) \
X(a, STATIC, SINGULAR, BOOL, gps_accept_2d, 45) \
X(a, STATIC, SINGULAR, UINT32, gps_max_dop, 46) \
X(a, STATIC, SINGULAR, BOOL, factory_reset, 100) \ X(a, STATIC, SINGULAR, BOOL, factory_reset, 100) \
X(a, STATIC, SINGULAR, BOOL, debug_log_enabled, 101) \ X(a, STATIC, SINGULAR, BOOL, debug_log_enabled, 101) \
X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) \ X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) \
@@ -321,8 +312,7 @@ X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_display_fare
X(a, STATIC, SINGULAR, UENUM, environmental_measurement_plugin_sensor_type, 146) \ X(a, STATIC, SINGULAR, UENUM, environmental_measurement_plugin_sensor_type, 146) \
X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_sensor_pin, 147) \ X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_sensor_pin, 147) \
X(a, STATIC, SINGULAR, BOOL, store_forward_plugin_enabled, 148) \ X(a, STATIC, SINGULAR, BOOL, store_forward_plugin_enabled, 148) \
X(a, STATIC, SINGULAR, UINT32, position_flags, 150) \ X(a, STATIC, SINGULAR, UINT32, position_flags, 150)
X(a, STATIC, SINGULAR, BOOL, is_always_powered, 151)
#define RadioConfig_UserPreferences_CALLBACK NULL #define RadioConfig_UserPreferences_CALLBACK NULL
#define RadioConfig_UserPreferences_DEFAULT NULL #define RadioConfig_UserPreferences_DEFAULT NULL
@@ -334,8 +324,8 @@ extern const pb_msgdesc_t RadioConfig_UserPreferences_msg;
#define RadioConfig_UserPreferences_fields &RadioConfig_UserPreferences_msg #define RadioConfig_UserPreferences_fields &RadioConfig_UserPreferences_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define RadioConfig_size 417 #define RadioConfig_size 404
#define RadioConfig_UserPreferences_size 414 #define RadioConfig_UserPreferences_size 401
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@@ -137,15 +137,10 @@ void AdminPlugin::handleSetOwner(const User &o)
strcpy(owner.id, o.id); strcpy(owner.id, o.id);
} }
if (owner.is_licensed != o.is_licensed) { if (owner.is_licensed != o.is_licensed) {
changed = 1; changed = true;
owner.is_licensed = o.is_licensed; owner.is_licensed = o.is_licensed;
} }
if ((!changed || o.team) && (owner.team != o.team)) {
changed = 1;
owner.team = o.team;
}
if (changed) // If nothing really changed, don't broadcast on the network or write to flash if (changed) // If nothing really changed, don't broadcast on the network or write to flash
service.reloadOwner(); service.reloadOwner();
} }

View File

@@ -5,11 +5,12 @@
#include "plugins/RemoteHardwarePlugin.h" #include "plugins/RemoteHardwarePlugin.h"
#include "plugins/ReplyPlugin.h" #include "plugins/ReplyPlugin.h"
#include "plugins/TextMessagePlugin.h" #include "plugins/TextMessagePlugin.h"
#include "plugins/SerialPlugin.h"
#include "plugins/TextMessagePlugin.h" #include "plugins/TextMessagePlugin.h"
#include "plugins/RoutingPlugin.h" #include "plugins/RoutingPlugin.h"
#include "plugins/AdminPlugin.h" #include "plugins/AdminPlugin.h"
#ifndef NO_ESP32 #ifndef NO_ESP32
#include "plugins/esp32/SerialPlugin.h" #include "plugins/SerialPlugin.h"
#include "plugins/esp32/EnvironmentalMeasurementPlugin.h" #include "plugins/esp32/EnvironmentalMeasurementPlugin.h"
#include "plugins/esp32/RangeTestPlugin.h" #include "plugins/esp32/RangeTestPlugin.h"
#include "plugins/esp32/StoreForwardPlugin.h" #include "plugins/esp32/StoreForwardPlugin.h"

View File

@@ -18,36 +18,6 @@ bool PositionPlugin::handleReceivedProtobuf(const MeshPacket &mp, Position *pptr
{ {
auto p = *pptr; auto p = *pptr;
// If inbound message is a replay (or spoof!) of our own messages, we shouldn't process
// (why use second-hand sources for our own data?)
// FIXME this can in fact happen with packets sent from EUD (src=RX_SRC_USER)
// to set fixed location, EUD-GPS location or just the time (see also issue #900)
if (nodeDB.getNodeNum() == getFrom(&mp)) {
DEBUG_MSG("Incoming update from MYSELF\n");
// DEBUG_MSG("Ignored an incoming update from MYSELF\n");
// return false;
}
// Log packet size and list of fields
DEBUG_MSG("POSITION node=%08x l=%d %s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
getFrom(&mp),
mp.decoded.payload.size,
p.latitude_i ? "LAT ":"",
p.longitude_i ? "LON ":"",
p.altitude ? "MSL ":"",
p.altitude_hae ? "HAE ":"",
p.alt_geoid_sep ? "GEO ":"",
p.PDOP ? "PDOP ":"",
p.HDOP ? "HDOP ":"",
p.VDOP ? "VDOP ":"",
p.sats_in_view ? "SIV ":"",
p.fix_quality ? "FXQ ":"",
p.fix_type ? "FXT ":"",
p.pos_timestamp ? "PTS ":"",
p.time ? "TIME ":"",
p.battery_level ? "BAT ":"");
if (p.time) { if (p.time) {
struct timeval tv; struct timeval tv;
uint32_t secs = p.time; uint32_t secs = p.time;
@@ -68,44 +38,7 @@ MeshPacket *PositionPlugin::allocReply()
NodeInfo *node = service.refreshMyNodeInfo(); // should guarantee there is now a position NodeInfo *node = service.refreshMyNodeInfo(); // should guarantee there is now a position
assert(node->has_position); assert(node->has_position);
// configuration of POSITION packet Position p = node->position;
// consider making this a function argument?
uint32_t pos_flags = radioConfig.preferences.position_flags;
// Populate a Position struct with ONLY the requested fields
Position p = Position_init_default; // Start with an empty structure
// lat/lon are unconditionally included - IF AVAILABLE!
p.latitude_i = node->position.latitude_i;
p.longitude_i = node->position.longitude_i;
p.time = node->position.time;
if (pos_flags & PositionFlags_POS_BATTERY)
p.battery_level = node->position.battery_level;
if (pos_flags & PositionFlags_POS_ALTITUDE) {
if (pos_flags & PositionFlags_POS_ALT_MSL)
p.altitude = node->position.altitude;
else
p.altitude_hae = node->position.altitude_hae;
if (pos_flags & PositionFlags_POS_GEO_SEP)
p.alt_geoid_sep = node->position.alt_geoid_sep;
}
if (pos_flags & PositionFlags_POS_DOP) {
if (pos_flags & PositionFlags_POS_HVDOP) {
p.HDOP = node->position.HDOP;
p.VDOP = node->position.VDOP;
} else
p.PDOP = node->position.PDOP;
}
if (pos_flags & PositionFlags_POS_SATINVIEW)
p.sats_in_view = node->position.sats_in_view;
if (pos_flags & PositionFlags_POS_TIMESTAMP)
p.pos_timestamp = node->position.pos_timestamp;
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other // 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 // nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless
@@ -136,20 +69,17 @@ void PositionPlugin::sendOurPosition(NodeNum dest, bool wantReplies)
int32_t PositionPlugin::runOnce() int32_t PositionPlugin::runOnce()
{ {
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
// We limit our GPS broadcasts to a max rate // We limit our GPS broadcasts to a max rate
uint32_t now = millis(); uint32_t now = millis();
if (lastGpsSend == 0 || now - lastGpsSend >= getPref_position_broadcast_secs() * 1000) { if (lastGpsSend == 0 || now - lastGpsSend >= getPref_position_broadcast_secs() * 1000) {
lastGpsSend = now; lastGpsSend = now;
// If we changed channels, ask everyone else for their latest info // If we changed channels, ask everyone else for their latest info
bool requestReplies = currentGeneration != radioGeneration; bool requestReplies = currentGeneration != radioGeneration;
currentGeneration = radioGeneration; currentGeneration = radioGeneration;
DEBUG_MSG("Sending pos@%x:6 to mesh (wantReplies=%d)\n", DEBUG_MSG("Sending position to mesh (wantReplies=%d)\n", requestReplies);
node->position.pos_timestamp, requestReplies);
sendOurPosition(NODENUM_BROADCAST, requestReplies); sendOurPosition(NODENUM_BROADCAST, requestReplies);
} }

View File

@@ -50,4 +50,4 @@ class SerialPluginRadio : public SinglePortPlugin
virtual ProcessMessage handleReceived(const MeshPacket &mp); virtual ProcessMessage handleReceived(const MeshPacket &mp);
}; };
extern SerialPluginRadio *serialPluginRadio; extern SerialPluginRadio *serialPluginRadio;

View File

@@ -1,23 +1,20 @@
#include "EnvironmentalMeasurementPlugin.h" #include "EnvironmentalMeasurementPlugin.h"
#include "../mesh/generated/environmental_measurement.pb.h"
#include "MeshService.h" #include "MeshService.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "RTC.h" #include "RTC.h"
#include "Router.h" #include "Router.h"
#include "configuration.h" #include "configuration.h"
#include "main.h" #include "main.h"
#include "../mesh/generated/environmental_measurement.pb.h"
#include <DHT.h> #include <DHT.h>
#include <DS18B20.h>
#include <OLEDDisplay.h> #include <OLEDDisplay.h>
#include <OLEDDisplayUi.h> #include <OLEDDisplayUi.h>
#include <OneWire.h>
#define DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000 #define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000 // Some sensors (the DHT11) have a minimum required duration between read attempts
#define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
#define DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10 #define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true #define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
#ifdef HAS_EINK #ifdef HAS_EINK
// The screen is bigger so use bigger fonts // The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16 #define FONT_SMALL ArialMT_Plain_16
@@ -34,136 +31,123 @@
#define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL) #define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL)
#define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM) #define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM)
int32_t EnvironmentalMeasurementPlugin::runOnce()
{ int32_t EnvironmentalMeasurementPlugin::runOnce() {
#ifndef NO_ESP32 // this only works on ESP32 devices #ifndef NO_ESP32 // this only works on ESP32 devices
/* /*
Uncomment the preferences below if you want to use the plugin Uncomment the preferences below if you want to use the plugin
without having to configure it from the PythonAPI or WebUI. without having to configure it from the PythonAPI or WebUI.
*/ */
/*radioConfig.preferences.environmental_measurement_plugin_measurement_enabled = 1; /*radioConfig.preferences.environmental_measurement_plugin_measurement_enabled = 1;
radioConfig.preferences.environmental_measurement_plugin_screen_enabled = 1; radioConfig.preferences.environmental_measurement_plugin_screen_enabled = 1;
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold = 5; radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold = 5;
radioConfig.preferences.environmental_measurement_plugin_update_interval = 600; radioConfig.preferences.environmental_measurement_plugin_update_interval = 30;
radioConfig.preferences.environmental_measurement_plugin_recovery_interval = 60; radioConfig.preferences.environmental_measurement_plugin_recovery_interval = 60;
radioConfig.preferences.environmental_measurement_plugin_display_farenheit = false; radioConfig.preferences.environmental_measurement_plugin_display_farenheit = true;
radioConfig.preferences.environmental_measurement_plugin_sensor_pin = 13; radioConfig.preferences.environmental_measurement_plugin_sensor_pin = 13;
radioConfig.preferences.environmental_measurement_plugin_sensor_type = radioConfig.preferences.environmental_measurement_plugin_sensor_type = RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType::RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11;*/
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType::
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20;
*/
if (!(radioConfig.preferences.environmental_measurement_plugin_measurement_enabled || if (! (radioConfig.preferences.environmental_measurement_plugin_measurement_enabled || radioConfig.preferences.environmental_measurement_plugin_screen_enabled)){
radioConfig.preferences.environmental_measurement_plugin_screen_enabled)) {
// If this plugin is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it // If this plugin is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it
return (INT32_MAX); return (INT32_MAX);
} }
if (firstTime) { if (firstTime) {
// This is the first time the OSThread library has called this function, so do some setup // This is the first time the OSThread library has called this function, so do some setup
firstTime = 0; firstTime = 0;
if (radioConfig.preferences.environmental_measurement_plugin_measurement_enabled) { if (radioConfig.preferences.environmental_measurement_plugin_measurement_enabled)
{
DEBUG_MSG("EnvironmentalMeasurement: Initializing\n"); DEBUG_MSG("EnvironmentalMeasurement: Initializing\n");
// it's possible to have this plugin enabled, only for displaying values on the screen. // it's possible to have this plugin enabled, only for displaying values on the screen.
// therefore, we should only enable the sensor loop if measurement is also enabled // therefore, we should only enable the sensor loop if measurement is also enabled
switch (radioConfig.preferences.environmental_measurement_plugin_sensor_type) { switch(radioConfig.preferences.environmental_measurement_plugin_sensor_type) {
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11: case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11:
dht = new DHT(radioConfig.preferences.environmental_measurement_plugin_sensor_pin, DHT11); dht = new DHT(radioConfig.preferences.environmental_measurement_plugin_sensor_pin,DHT11);
this->dht->begin(); this->dht->begin();
this->dht->read(); this->dht->read();
DEBUG_MSG("EnvironmentalMeasurement: Opened DHT11 on pin: %d\n", DEBUG_MSG("EnvironmentalMeasurement: Opened DHT11 on pin: %d\n",radioConfig.preferences.environmental_measurement_plugin_sensor_pin);
radioConfig.preferences.environmental_measurement_plugin_sensor_pin);
return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20:
oneWire = new OneWire(radioConfig.preferences.environmental_measurement_plugin_sensor_pin);
ds18b20 = new DS18B20(oneWire);
this->ds18b20->begin();
this->ds18b20->setResolution(12);
this->ds18b20->requestTemperatures();
DEBUG_MSG("EnvironmentalMeasurement: Opened DS18B20 on pin: %d\n",
radioConfig.preferences.environmental_measurement_plugin_sensor_pin);
return (DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
default:
DEBUG_MSG("EnvironmentalMeasurement: Invalid sensor type selected; Disabling plugin");
return (INT32_MAX);
break; break;
default:
DEBUG_MSG("EnvironmentalMeasurement: Invalid sensor type selected; Disabling plugin");
return (INT32_MAX);
break;
} }
// begin reading measurements from the sensor
// DHT have a max read-rate of 1HZ, so we should wait at least 1 second
// after initializing the sensor before we try to read from it.
// returning the interval here means that the next time OSThread
// calls our plugin, we'll run the other branch of this if statement
// and actually do a "sendOurEnvironmentalMeasurement()"
return(DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
} }
return (INT32_MAX); return (INT32_MAX);
} else { }
if (!radioConfig.preferences.environmental_measurement_plugin_measurement_enabled) { else {
if (!radioConfig.preferences.environmental_measurement_plugin_measurement_enabled)
{
// if we somehow got to a second run of this plugin with measurement disabled, then just wait forever // if we somehow got to a second run of this plugin with measurement disabled, then just wait forever
// I can't imagine we'd ever get here though. // I can't imagine we'd ever get here though.
return (INT32_MAX); return (INT32_MAX);
} }
// this is not the first time OSThread library has called this function // this is not the first time OSThread library has called this function
// so just do what we intend to do on the interval // so just do what we intend to do on the interval
if (sensor_read_error_count > radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold) { if(sensor_read_error_count > radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold)
if (radioConfig.preferences.environmental_measurement_plugin_recovery_interval > 0) { {
DEBUG_MSG("EnvironmentalMeasurement: TEMPORARILY DISABLED; The " if (radioConfig.preferences.environmental_measurement_plugin_recovery_interval > 0 ) {
"environmental_measurement_plugin_read_error_count_threshold has been exceed: %d. Will retry reads in " DEBUG_MSG(
"%d seconds\n", "EnvironmentalMeasurement: TEMPORARILY DISABLED; The environmental_measurement_plugin_read_error_count_threshold has been exceed: %d. Will retry reads in %d seconds\n",
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold, radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold,
radioConfig.preferences.environmental_measurement_plugin_recovery_interval); radioConfig.preferences.environmental_measurement_plugin_recovery_interval);
sensor_read_error_count = 0; sensor_read_error_count = 0;
return (radioConfig.preferences.environmental_measurement_plugin_recovery_interval * 1000); return(radioConfig.preferences.environmental_measurement_plugin_recovery_interval*1000);
} }
DEBUG_MSG("EnvironmentalMeasurement: DISABLED; The environmental_measurement_plugin_read_error_count_threshold has " DEBUG_MSG(
"been exceed: %d. Reads will not be retried until after device reset\n", "EnvironmentalMeasurement: DISABLED; The environmental_measurement_plugin_read_error_count_threshold has been exceed: %d. Reads will not be retried until after device reset\n",
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold); radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold);
return (INT32_MAX); return(INT32_MAX);
} else if (sensor_read_error_count > 0) {
DEBUG_MSG("EnvironmentalMeasurement: There have been %d sensor read failures. Will retry %d more times\n",
sensor_read_error_count, sensor_read_error_count, sensor_read_error_count,
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold -
sensor_read_error_count);
} }
if (!sendOurEnvironmentalMeasurement()) { else if (sensor_read_error_count > 0){
// if we failed to read the sensor, then try again DEBUG_MSG("EnvironmentalMeasurement: There have been %d sensor read failures. Will retry %d more times\n",
sensor_read_error_count,
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold-sensor_read_error_count);
}
if (!sendOurEnvironmentalMeasurement() ){
// if we failed to read the sensor, then try again
// as soon as we can according to the maximum polling frequency // as soon as we can according to the maximum polling frequency
// return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS); return(DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
switch (radioConfig.preferences.environmental_measurement_plugin_sensor_type) {
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11:
return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20:
return (DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
default:
return (DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
}
} }
} }
// The return of runOnce is an int32 representing the desired number of // The return of runOnce is an int32 representing the desired number of
// miliseconds until the function should be called again by the // miliseconds until the function should be called again by the
// OSThread library. Multiply the preference value by 1000 to convert seconds to miliseconds // OSThread library. Multiply the preference value by 1000 to convert seconds to miliseconds
return (radioConfig.preferences.environmental_measurement_plugin_update_interval * 1000); return(radioConfig.preferences.environmental_measurement_plugin_update_interval * 1000);
#endif #endif
} }
bool EnvironmentalMeasurementPlugin::wantUIFrame() bool EnvironmentalMeasurementPlugin::wantUIFrame() {
{
return radioConfig.preferences.environmental_measurement_plugin_screen_enabled; return radioConfig.preferences.environmental_measurement_plugin_screen_enabled;
} }
String GetSenderName(const MeshPacket &mp) String GetSenderName(const MeshPacket &mp) {
{
String sender; String sender;
auto node = nodeDB.getNode(getFrom(&mp)); auto node = nodeDB.getNode(getFrom(&mp));
if (node) { if (node){
sender = node->user.short_name; sender = node->user.short_name;
} else { }
else {
sender = "UNK"; sender = "UNK";
} }
return sender; return sender;
} }
uint32_t GetTimeSinceMeshPacket(const MeshPacket *mp) uint32_t GetTimeSinceMeshPacket(const MeshPacket *mp) {
{
uint32_t now = getTime(); uint32_t now = getTime();
uint32_t last_seen = mp->rx_time; uint32_t last_seen = mp->rx_time;
@@ -172,13 +156,15 @@ uint32_t GetTimeSinceMeshPacket(const MeshPacket *mp)
delta = 0; delta = 0;
return delta; return delta;
} }
float EnvironmentalMeasurementPlugin::CelsiusToFarenheit(float c)
{ float EnvironmentalMeasurementPlugin::CelsiusToFarenheit(float c) {
return (c * 9) / 5 + 32; return (c*9)/5 + 32;
} }
void EnvironmentalMeasurementPlugin::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) void EnvironmentalMeasurementPlugin::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
@@ -187,16 +173,21 @@ void EnvironmentalMeasurementPlugin::drawFrame(OLEDDisplay *display, OLEDDisplay
if (lastMeasurementPacket == nullptr) { if (lastMeasurementPacket == nullptr) {
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
display->drawString(x, y += fontHeight(FONT_MEDIUM), "No measurement"); display->drawString(x, y += fontHeight(FONT_MEDIUM), "No measurement");
//DEBUG_MSG("EnvironmentalMeasurement: No previous measurement; not drawing frame\n");
return; return;
} }
EnvironmentalMeasurement lastMeasurement; EnvironmentalMeasurement lastMeasurement;
uint32_t agoSecs = GetTimeSinceMeshPacket(lastMeasurementPacket); uint32_t agoSecs = GetTimeSinceMeshPacket(lastMeasurementPacket);
String lastSender = GetSenderName(*lastMeasurementPacket); String lastSender = GetSenderName(*lastMeasurementPacket);
auto &p = lastMeasurementPacket->decoded; auto &p = lastMeasurementPacket->decoded;
if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, EnvironmentalMeasurement_fields, &lastMeasurement)) { if (!pb_decode_from_bytes(p.payload.bytes,
p.payload.size,
EnvironmentalMeasurement_fields,
&lastMeasurement)) {
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
display->drawString(x, y += fontHeight(FONT_MEDIUM), "Measurement Error"); display->drawString(x, y += fontHeight(FONT_MEDIUM), "Measurement Error");
DEBUG_MSG("EnvironmentalMeasurement: unable to decode last packet"); DEBUG_MSG("EnvironmentalMeasurement: unable to decode last packet");
@@ -204,23 +195,20 @@ void EnvironmentalMeasurementPlugin::drawFrame(OLEDDisplay *display, OLEDDisplay
} }
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
String last_temp = String(lastMeasurement.temperature, 0) + "°C"; String last_temp = String(lastMeasurement.temperature,0) +"°C";
if (radioConfig.preferences.environmental_measurement_plugin_display_farenheit) { if (radioConfig.preferences.environmental_measurement_plugin_display_farenheit){
last_temp = String(CelsiusToFarenheit(lastMeasurement.temperature), 0) + "°F"; last_temp = String(CelsiusToFarenheit(lastMeasurement.temperature),0) +"°F";;
;
} }
display->drawString(x, y += fontHeight(FONT_MEDIUM), display->drawString(x, y += fontHeight(FONT_MEDIUM), lastSender+": "+last_temp +"/"+ String(lastMeasurement.relative_humidity,0) + "%("+String(agoSecs)+"s)");
lastSender + ": " + last_temp + "/" + String(lastMeasurement.relative_humidity, 0) + "%(" +
String(agoSecs) + "s)");
} }
bool EnvironmentalMeasurementPlugin::handleReceivedProtobuf(const MeshPacket &mp, EnvironmentalMeasurement *p) bool EnvironmentalMeasurementPlugin::handleReceivedProtobuf(const MeshPacket &mp, EnvironmentalMeasurement *p)
{ {
if (!(radioConfig.preferences.environmental_measurement_plugin_measurement_enabled || if (!(radioConfig.preferences.environmental_measurement_plugin_measurement_enabled || radioConfig.preferences.environmental_measurement_plugin_screen_enabled)){
radioConfig.preferences.environmental_measurement_plugin_screen_enabled)) { // If this plugin is not enabled in any capacity, don't handle the packet, and allow other plugins to consume
// If this plugin is not enabled in any capacity, don't handle the packet, and allow other plugins to consume return false;
return false;
} }
String sender = GetSenderName(mp); String sender = GetSenderName(mp);
@@ -242,32 +230,13 @@ bool EnvironmentalMeasurementPlugin::sendOurEnvironmentalMeasurement(NodeNum des
DEBUG_MSG("-----------------------------------------\n"); DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("EnvironmentalMeasurement: Read data\n"); DEBUG_MSG("EnvironmentalMeasurement: Read data\n");
if (!this->dht->read(true)){
switch (radioConfig.preferences.environmental_measurement_plugin_sensor_type) { sensor_read_error_count++;
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11: DEBUG_MSG("EnvironmentalMeasurement: FAILED TO READ DATA\n");
if (!this->dht->read(true)) {
sensor_read_error_count++;
DEBUG_MSG("EnvironmentalMeasurement: FAILED TO READ DATA\n");
return false;
}
m.relative_humidity = this->dht->readHumidity();
m.temperature = this->dht->readTemperature();
break;
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20:
if (this->ds18b20->isConversionComplete()) {
m.temperature = this->ds18b20->getTempC();
m.relative_humidity = 0; // This sensor is temperature only
this->ds18b20->requestTemperatures();
break;
} else {
sensor_read_error_count++;
DEBUG_MSG("EnvironmentalMeasurement: FAILED TO READ DATA\n");
return false;
}
default:
DEBUG_MSG("EnvironmentalMeasurement: Invalid sensor type selected; Disabling plugin");
return false; return false;
} }
m.relative_humidity = this->dht->readHumidity();
m.temperature = this->dht->readTemperature();
DEBUG_MSG("EnvironmentalMeasurement->relative_humidity: %f\n", m.relative_humidity); DEBUG_MSG("EnvironmentalMeasurement->relative_humidity: %f\n", m.relative_humidity);
DEBUG_MSG("EnvironmentalMeasurement->temperature: %f\n", m.temperature); DEBUG_MSG("EnvironmentalMeasurement->temperature: %f\n", m.temperature);
@@ -281,3 +250,4 @@ bool EnvironmentalMeasurementPlugin::sendOurEnvironmentalMeasurement(NodeNum des
service.sendToMesh(p); service.sendToMesh(p);
return true; return true;
} }

View File

@@ -1,20 +1,15 @@
#pragma once #pragma once
#include "../mesh/generated/environmental_measurement.pb.h"
#include "ProtobufPlugin.h" #include "ProtobufPlugin.h"
#include <DHT.h> #include "../mesh/generated/environmental_measurement.pb.h"
#include <DS18B20.h>
#include <OLEDDisplay.h> #include <OLEDDisplay.h>
#include <OLEDDisplayUi.h> #include <OLEDDisplayUi.h>
#include <OneWire.h> #include <DHT.h>
class EnvironmentalMeasurementPlugin : private concurrency::OSThread, public ProtobufPlugin<EnvironmentalMeasurement> class EnvironmentalMeasurementPlugin : private concurrency::OSThread, public ProtobufPlugin<EnvironmentalMeasurement>
{ {
public: public:
EnvironmentalMeasurementPlugin() EnvironmentalMeasurementPlugin(): concurrency::OSThread("EnvironmentalMeasurementPlugin"), ProtobufPlugin("EnvironmentalMeasurement", PortNum_ENVIRONMENTAL_MEASUREMENT_APP, &EnvironmentalMeasurement_msg) {
: concurrency::OSThread("EnvironmentalMeasurementPlugin"), lastMeasurementPacket = nullptr;
ProtobufPlugin("EnvironmentalMeasurement", PortNum_ENVIRONMENTAL_MEASUREMENT_APP, &EnvironmentalMeasurement_msg)
{
lastMeasurementPacket = nullptr;
} }
virtual bool wantUIFrame(); virtual bool wantUIFrame();
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
@@ -29,13 +24,11 @@ class EnvironmentalMeasurementPlugin : private concurrency::OSThread, public Pro
* Send our EnvironmentalMeasurement into the mesh * Send our EnvironmentalMeasurement into the mesh
*/ */
bool sendOurEnvironmentalMeasurement(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false); bool sendOurEnvironmentalMeasurement(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
private: private:
float CelsiusToFarenheit(float c); float CelsiusToFarenheit(float c);
bool firstTime = 1; bool firstTime = 1;
DHT *dht; DHT* dht;
OneWire *oneWire;
DS18B20 *ds18b20;
const MeshPacket *lastMeasurementPacket; const MeshPacket *lastMeasurementPacket;
uint32_t sensor_read_error_count = 0; uint32_t sensor_read_error_count = 0;
}; };

View File

@@ -237,7 +237,7 @@ bool RangeTestPluginRadio::appendFile(const MeshPacket &mp)
// Print the CSV header // Print the CSV header
if (fileToWrite.println( if (fileToWrite.println(
"time,from,sender name,sender lat,sender long,rx lat,rx long,rx elevation,rx snr,distance,payload")) { "time,from,sender name,sender lat,sender long,rx lat,rx long,rx snr,rx elevation,distance,payload")) {
DEBUG_MSG("File was written\n"); DEBUG_MSG("File was written\n");
} else { } else {
DEBUG_MSG("File write failed\n"); DEBUG_MSG("File write failed\n");

View File

@@ -8,8 +8,10 @@
#include "plugins/PluginDev.h" #include "plugins/PluginDev.h"
#include <Arduino.h> #include <Arduino.h>
#include <map> #include <map>
#include <iterator>
#define STOREFORWARD_MAX_PACKETS 0
#define STOREFORWARD_SEND_HISTORY_PERIOD 10 * 60
#define STOREFORWARD_SEND_HISTORY_MAX 0
StoreForwardPlugin *storeForwardPlugin; StoreForwardPlugin *storeForwardPlugin;
@@ -21,31 +23,22 @@ int32_t StoreForwardPlugin::runOnce()
if (radioConfig.preferences.store_forward_plugin_enabled) { if (radioConfig.preferences.store_forward_plugin_enabled) {
if (radioConfig.preferences.is_router) { if (radioConfig.preferences.is_router) {
// Maybe some cleanup functions?
if (this->busy) { this->historyReport();
// Send out the message queue. return (60 * 1000);
//DEBUG_MSG("--- --- --- In busy loop 1 %d\n", this->packetHistoryTXQueue_index);
storeForwardPlugin->sendPayload(this->busyTo, this->packetHistoryTXQueue_index);
if (this->packetHistoryTXQueue_index == packetHistoryTXQueue_size) {
strcpy(this->routerMessage, "** S&F - Done");
storeForwardPlugin->sendMessage(this->busyTo, this->routerMessage);
//DEBUG_MSG("--- --- --- In busy loop - Done \n");
this->packetHistoryTXQueue_index = 0;
this->busy = false;
} else {
this->packetHistoryTXQueue_index++;
}
}
// TODO: Dynamicly adjust the time this returns in the loop based on the size of the packets being actually transmitted.
return (this->packetTimeMax);
} else { } else {
DEBUG_MSG("Store & Forward Plugin - Disabled (is_router = false)\n"); /*
* If the plugin is turned on and is_router is not enabled, then we'll send a heartbeat every
* few minutes.
*
* This behavior is expected to change. It's only here until we come up with something better.
*/
return (INT32_MAX); DEBUG_MSG("Store & Forward Plugin - Sending heartbeat\n");
storeForwardPlugin->sendPayload();
return (4 * 60 * 1000);
} }
} else { } else {
@@ -58,9 +51,6 @@ int32_t StoreForwardPlugin::runOnce()
return (INT32_MAX); return (INT32_MAX);
} }
/*
Create our data structure in the PSRAM.
*/
void StoreForwardPlugin::populatePSRAM() void StoreForwardPlugin::populatePSRAM()
{ {
/* /*
@@ -68,8 +58,6 @@ void StoreForwardPlugin::populatePSRAM()
https://learn.upesy.com/en/programmation/psram.html#psram-tab https://learn.upesy.com/en/programmation/psram.html#psram-tab
*/ */
uint32_t store_forward_plugin_replay_max_records = 250;
DEBUG_MSG("Before PSRAM initilization:\n"); DEBUG_MSG("Before PSRAM initilization:\n");
DEBUG_MSG(" Total heap: %d\n", ESP.getHeapSize()); DEBUG_MSG(" Total heap: %d\n", ESP.getHeapSize());
@@ -77,13 +65,12 @@ void StoreForwardPlugin::populatePSRAM()
DEBUG_MSG(" Total PSRAM: %d\n", ESP.getPsramSize()); DEBUG_MSG(" Total PSRAM: %d\n", ESP.getPsramSize());
DEBUG_MSG(" Free PSRAM: %d\n", ESP.getFreePsram()); DEBUG_MSG(" Free PSRAM: %d\n", ESP.getFreePsram());
// Use a maximum of 2/3 the available PSRAM unless otherwise specified. // Use a maximum of half the available PSRAM unless otherwise specified.
uint32_t numberOfPackets = uint32_t numberOfPackets =
(radioConfig.preferences.store_forward_plugin_records ? radioConfig.preferences.store_forward_plugin_records STOREFORWARD_MAX_PACKETS ? STOREFORWARD_MAX_PACKETS : ((ESP.getPsramSize() / 2) / sizeof(PacketHistoryStruct));
: (((ESP.getFreePsram() / 3) * 2) / sizeof(PacketHistoryStruct)));
// this->packetHistory = (PacketHistoryStruct *)ps_calloc(numberOfPackets, sizeof(PacketHistoryStruct));
this->packetHistory = static_cast<PacketHistoryStruct *>(ps_calloc(numberOfPackets, sizeof(PacketHistoryStruct))); this->packetHistory = static_cast<PacketHistoryStruct *>(ps_calloc(numberOfPackets, sizeof(PacketHistoryStruct)));
this->packetHistoryTXQueue = static_cast<PacketHistoryStruct *>(ps_calloc(store_forward_plugin_replay_max_records, sizeof(PacketHistoryStruct)));
DEBUG_MSG("After PSRAM initilization:\n"); DEBUG_MSG("After PSRAM initilization:\n");
DEBUG_MSG(" Total heap: %d\n", ESP.getHeapSize()); DEBUG_MSG(" Total heap: %d\n", ESP.getHeapSize());
@@ -91,13 +78,34 @@ void StoreForwardPlugin::populatePSRAM()
DEBUG_MSG(" Total PSRAM: %d\n", ESP.getPsramSize()); DEBUG_MSG(" Total PSRAM: %d\n", ESP.getPsramSize());
DEBUG_MSG(" Free PSRAM: %d\n", ESP.getFreePsram()); DEBUG_MSG(" Free PSRAM: %d\n", ESP.getFreePsram());
DEBUG_MSG("Store and Forward Stats:\n"); DEBUG_MSG("Store and Forward Stats:\n");
DEBUG_MSG(" numberOfPackets for packetHistory - %u\n", numberOfPackets); DEBUG_MSG(" numberOfPackets - %u\n", numberOfPackets);
}
// We saw a node.
void StoreForwardPlugin::sawNode(uint32_t whoWeSaw, uint32_t sawSecAgo)
{
if (radioConfig.preferences.is_router) {
// If node has been away for more than 10 minutes, send the node the last 10 minutes of
// messages
if (sawSecAgo > STOREFORWARD_SEND_HISTORY_PERIOD) {
// Node has been away for a while.
storeForwardPlugin->historySend(STOREFORWARD_SEND_HISTORY_PERIOD, whoWeSaw);
}
}
} }
void StoreForwardPlugin::historyReport() void StoreForwardPlugin::historyReport()
{ {
DEBUG_MSG("Iterating through the message history...\n"); DEBUG_MSG("Iterating through the message history...\n");
DEBUG_MSG("Message history contains %u records\n", this->packetHistoryCurrent); DEBUG_MSG("Message history contains %u records\n", this->packetHistoryCurrent);
uint32_t startTimer = millis();
for (int i = 0; i < this->packetHistoryCurrent; i++) {
if (this->packetHistory[i].time) {
// DEBUG_MSG("... time-%u to-0x%08x\n", this->packetHistory[i].time, this->packetHistory[i].to & 0xffffffff);
}
}
DEBUG_MSG("StoreForwardPlugin::historyReport runtime - %u ms\n", millis() - startTimer);
} }
/* /*
@@ -105,80 +113,31 @@ void StoreForwardPlugin::historyReport()
*/ */
void StoreForwardPlugin::historySend(uint32_t msAgo, uint32_t to) void StoreForwardPlugin::historySend(uint32_t msAgo, uint32_t to)
{ {
// Send "Welcome back"
uint32_t packetsSent = 0; this->sendPayloadWelcome(to, false);
uint32_t queueSize = storeForwardPlugin->historyQueueCreate(msAgo, to);
if (queueSize) {
snprintf(this->routerMessage, 80, "** S&F - Sending %d message(s)", queueSize);
storeForwardPlugin->sendMessage(to, this->routerMessage);
this->busy = true; // runOnce() will pickup the next steps once busy = true.
this->busyTo = to;
} else {
strcpy(this->routerMessage, "** S&F - No history to send");
storeForwardPlugin->sendMessage(to, this->routerMessage);
}
}
uint32_t StoreForwardPlugin::historyQueueCreate(uint32_t msAgo, uint32_t to) {
//uint32_t packetHistoryTXQueueIndex = 0;
this->packetHistoryTXQueue_size = 0;
for (int i = 0; i < this->packetHistoryCurrent; i++) { for (int i = 0; i < this->packetHistoryCurrent; i++) {
/* if (this->packetHistory[i].time) {
DEBUG_MSG("SF historyQueueCreate\n"); // DEBUG_MSG("... time-%u to-0x%08x\n", this->packetHistory[i].time, this->packetHistory[i].to & 0xffffffff);
DEBUG_MSG("SF historyQueueCreate - time %d\n", this->packetHistory[i].time);
DEBUG_MSG("SF historyQueueCreate - millis %d\n", millis());
DEBUG_MSG("SF historyQueueCreate - math %d\n", (millis() - msAgo));
*/
if (this->packetHistory[i].time && (this->packetHistory[i].time < (millis() - msAgo))) {
DEBUG_MSG("SF historyQueueCreate - Time matches - ok\n");
/*
Copy the messages that were received by the router in the last msAgo
to the packetHistoryTXQueue structure.
TODO: The condition (this->packetHistory[i].to & 0xffffffff) == to) is not tested since
I don't have an easy way to target a specific user. Will need to do this soon.
*/
if ((this->packetHistory[i].to & 0xffffffff) == 0xffffffff
||
((this->packetHistory[i].to & 0xffffffff) == to)
) {
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].time = this->packetHistory[i].time;
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].to = this->packetHistory[i].to;
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].from = this->packetHistory[i].from;
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].payload_size = this->packetHistory[i].payload_size;
memcpy(this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].payload, this->packetHistory[i].payload, Constants_DATA_PAYLOAD_LEN);
this->packetHistoryTXQueue_size++;
DEBUG_MSG("PacketHistoryStruct time=%d\n", this->packetHistory[i].time);
DEBUG_MSG("PacketHistoryStruct msg=%.*s\n", this->packetHistory[i].payload);
//DEBUG_MSG("PacketHistoryStruct msg=%.*s\n", this->packetHistoryTXQueue[packetHistoryTXQueueIndex].payload);
}
} }
} }
return this->packetHistoryTXQueue_size;
} }
void StoreForwardPlugin::historyAdd(const MeshPacket &mp) void StoreForwardPlugin::historyAdd(const MeshPacket *mp)
{ {
auto &p = mp.decoded; auto &p = mp;
static uint8_t bytes[MAX_RHPACKETLEN];
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded);
assert(numbytes <= MAX_RHPACKETLEN);
DEBUG_MSG("MP numbytes %u\n", numbytes);
// destination, source, bytes
// memcpy(p->encrypted.bytes, bytes, numbytes);
memcpy(this->packetHistory[this->packetHistoryCurrent].bytes, bytes, MAX_RHPACKETLEN);
this->packetHistory[this->packetHistoryCurrent].time = millis(); this->packetHistory[this->packetHistoryCurrent].time = millis();
this->packetHistory[this->packetHistoryCurrent].to = mp.to; this->packetHistory[this->packetHistoryCurrent].to = mp->to;
this->packetHistory[this->packetHistoryCurrent].from = mp.from;
this->packetHistory[this->packetHistoryCurrent].payload_size = p.payload.size;
memcpy(this->packetHistory[this->packetHistoryCurrent].payload, p.payload.bytes, Constants_DATA_PAYLOAD_LEN);
this->packetHistoryCurrent++; this->packetHistoryCurrent++;
} }
@@ -188,39 +147,46 @@ MeshPacket *StoreForwardPlugin::allocReply()
return reply; return reply;
} }
void StoreForwardPlugin::sendPayload(NodeNum dest, uint32_t packetHistory_index) void StoreForwardPlugin::sendPayload(NodeNum dest, bool wantReplies)
{ {
DEBUG_MSG("Sending S&F Payload\n"); DEBUG_MSG("Sending S&F Payload\n");
MeshPacket *p = allocReply(); MeshPacket *p = allocReply();
p->to = dest; p->to = dest;
p->from = this->packetHistoryTXQueue[packetHistory_index].from; p->decoded.want_response = wantReplies;
// Let's assume that if the router received the S&F request that the client is in range. p->want_ack = true;
// TODO: Make this configurable.
p->want_ack = false;
p->decoded.payload.size = static char heartbeatString[20];
this->packetHistoryTXQueue[packetHistory_index].payload_size; // You must specify how many bytes are in the reply snprintf(heartbeatString, sizeof(heartbeatString), "1");
memcpy(p->decoded.payload.bytes, this->packetHistoryTXQueue[packetHistory_index].payload,
this->packetHistoryTXQueue[packetHistory_index].payload_size); p->decoded.payload.size = strlen(heartbeatString); // You must specify how many bytes are in the reply
memcpy(p->decoded.payload.bytes, "1", 1);
service.sendToMesh(p); service.sendToMesh(p);
} }
void StoreForwardPlugin::sendMessage(NodeNum dest, char *str) void StoreForwardPlugin::sendPayloadWelcome(NodeNum dest, bool wantReplies)
{ {
DEBUG_MSG("*********************************\n");
DEBUG_MSG("*********************************\n");
DEBUG_MSG("*********************************\n");
DEBUG_MSG("Sending S&F Welcome Message\n");
DEBUG_MSG("*********************************\n");
DEBUG_MSG("*********************************\n");
DEBUG_MSG("*********************************\n");
MeshPacket *p = allocReply(); MeshPacket *p = allocReply();
p->to = dest; p->to = dest;
p->decoded.want_response = wantReplies;
// Let's assume that if the router received the S&F request that the client is in range. p->want_ack = true;
// TODO: Make this configurable.
p->want_ack = false;
p->decoded.payload.size = strlen(str); // You must specify how many bytes are in the reply p->decoded.portnum = PortNum_TEXT_MESSAGE_APP;
memcpy(p->decoded.payload.bytes, str, strlen(str));
static char heartbeatString[80];
snprintf(heartbeatString, sizeof(heartbeatString), "Welcome back to the mesh. We have not seen you in x minutes!");
p->decoded.payload.size = strlen(heartbeatString); // You must specify how many bytes are in the reply
memcpy(p->decoded.payload.bytes, heartbeatString, p->decoded.payload.size);
service.sendToMesh(p); service.sendToMesh(p);
} }
@@ -230,33 +196,15 @@ ProcessMessage StoreForwardPlugin::handleReceived(const MeshPacket &mp)
#ifndef NO_ESP32 #ifndef NO_ESP32
if (radioConfig.preferences.store_forward_plugin_enabled) { if (radioConfig.preferences.store_forward_plugin_enabled) {
DEBUG_MSG("--- S&F Received something\n");
auto &p = mp.decoded;
// The router node should not be sending messages as a client.
if (getFrom(&mp) != nodeDB.getNodeNum()) { if (getFrom(&mp) != nodeDB.getNodeNum()) {
printPacket("----- PACKET FROM RADIO -----", &mp);
// uint32_t sawTime = storeForwardPlugin->sawNode(getFrom(&mp) & 0xffffffff);
// DEBUG_MSG("We last saw this node (%u), %u sec ago\n", mp.from & 0xffffffff, (millis() - sawTime) / 1000);
DEBUG_MSG(" -------------- ");
if (mp.decoded.portnum == PortNum_TEXT_MESSAGE_APP) { if (mp.decoded.portnum == PortNum_TEXT_MESSAGE_APP) {
DEBUG_MSG("Packet came from - PortNum_TEXT_MESSAGE_APP\n"); DEBUG_MSG("Packet came from - PortNum_TEXT_MESSAGE_APP\n");
if ((p.payload.bytes[0] == 'S') && (p.payload.bytes[1] == 'F') && (p.payload.bytes[2] == 0x00)) { storeForwardPlugin->historyAdd(&mp);
DEBUG_MSG("--- --- --- Request to send\n");
// Send the last 60 minutes of messages.
if (this->busy) {
strcpy(this->routerMessage, "** S&F - Busy. Try again shortly.");
storeForwardPlugin->sendMessage(getFrom(&mp), this->routerMessage);
} else {
storeForwardPlugin->historySend(1000 * 60, getFrom(&mp));
}
} else if ((p.payload.bytes[0] == 'S') && (p.payload.bytes[1] == 'F') && (p.payload.bytes[2] == 'm') && (p.payload.bytes[3] == 0x00)) {
strcpy(this->routerMessage, "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456");
storeForwardPlugin->sendMessage(getFrom(&mp), this->routerMessage);
} else {
storeForwardPlugin->historyAdd(mp);
}
} else { } else {
DEBUG_MSG("Packet came from an unknown port %u\n", mp.decoded.portnum); DEBUG_MSG("Packet came from an unknown port %u\n", mp.decoded.portnum);
@@ -273,22 +221,21 @@ ProcessMessage StoreForwardPlugin::handleReceived(const MeshPacket &mp)
} }
StoreForwardPlugin::StoreForwardPlugin() StoreForwardPlugin::StoreForwardPlugin()
: SinglePortPlugin("StoreForwardPlugin", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("StoreForwardPlugin") : SinglePortPlugin("StoreForwardPlugin", PortNum_STORE_FORWARD_APP), concurrency::OSThread("StoreForwardPlugin")
{ {
#ifndef NO_ESP32 #ifndef NO_ESP32
isPromiscuous = true; // Brown chicken brown cow isPromiscuous = true; // Brown chicken brown cow
if (StoreForward_Dev) { /*
/* Uncomment the preferences below if you want to use the plugin
Uncomment the preferences below if you want to use the plugin without having to configure it from the PythonAPI or WebUI.
without having to configure it from the PythonAPI or WebUI. */
*/
// radioConfig.preferences.store_forward_plugin_enabled = 1; if (StoreForward_Dev) {
// radioConfig.preferences.is_router = 1; radioConfig.preferences.store_forward_plugin_enabled = 1;
// radioConfig.preferences.is_always_powered = 1; radioConfig.preferences.is_router = 1;
} }
if (radioConfig.preferences.store_forward_plugin_enabled) { if (radioConfig.preferences.store_forward_plugin_enabled) {
@@ -301,17 +248,7 @@ StoreForwardPlugin::StoreForwardPlugin()
// Do the startup here // Do the startup here
// Popupate PSRAM with our data structures.
this->populatePSRAM(); this->populatePSRAM();
// Calculate the packet time.
// this->packetTimeMax = RadioLibInterface::instance->getPacketTime(Constants_DATA_PAYLOAD_LEN);
//RadioLibInterface::instance->getPacketTime(Constants_DATA_PAYLOAD_LEN);
//RadioLibInterface::instance->getPacketTime(Constants_DATA_PAYLOAD_LEN);
//RadioInterface::getPacketTime(500)l
this->packetTimeMax = 2000;
} else { } else {
DEBUG_MSG("Device has less than 1M of PSRAM free. Aborting startup.\n"); DEBUG_MSG("Device has less than 1M of PSRAM free. Aborting startup.\n");
DEBUG_MSG("Store & Forward Plugin - Aborting Startup.\n"); DEBUG_MSG("Store & Forward Plugin - Aborting Startup.\n");
@@ -328,4 +265,4 @@ StoreForwardPlugin::StoreForwardPlugin()
} }
} }
#endif #endif
} }

View File

@@ -9,31 +9,19 @@
struct PacketHistoryStruct { struct PacketHistoryStruct {
uint32_t time; uint32_t time;
uint32_t to; uint32_t to;
uint32_t from;
bool ack; bool ack;
uint8_t payload[Constants_DATA_PAYLOAD_LEN]; uint8_t bytes[MAX_RHPACKETLEN];
pb_size_t payload_size;
}; };
class StoreForwardPlugin : public SinglePortPlugin, private concurrency::OSThread class StoreForwardPlugin : public SinglePortPlugin, private concurrency::OSThread
{ {
//bool firstTime = 1; bool firstTime = 1;
bool busy = 0;
uint32_t busyTo;
char routerMessage[80];
uint32_t receivedRecord[50][2] = {{0}}; uint32_t receivedRecord[50][2] = {{0}};
PacketHistoryStruct *packetHistory; PacketHistoryStruct *packetHistory;
uint32_t packetHistoryCurrent = 0; uint32_t packetHistoryCurrent = 0;
PacketHistoryStruct *packetHistoryTXQueue;
uint32_t packetHistoryTXQueue_size;
uint32_t packetHistoryTXQueue_index = 0;
uint32_t packetTimeMax = 0;
public: public:
StoreForwardPlugin(); StoreForwardPlugin();
@@ -41,32 +29,54 @@ class StoreForwardPlugin : public SinglePortPlugin, private concurrency::OSThrea
Update our local reference of when we last saw that node. Update our local reference of when we last saw that node.
@return 0 if we have never seen that node before otherwise return the last time we saw the node. @return 0 if we have never seen that node before otherwise return the last time we saw the node.
*/ */
void historyAdd(const MeshPacket &mp); void sawNode(uint32_t whoWeSaw, uint32_t sawSecAgo);
void historyAdd(const MeshPacket *mp);
void historyReport(); void historyReport();
void historySend(uint32_t msAgo, uint32_t to); void historySend(uint32_t msAgo, uint32_t to);
void populatePSRAM();
uint32_t historyQueueCreate(uint32_t msAgo, uint32_t to);
/** /**
* Send our payload into the mesh * Send our payload into the mesh
*/ */
void sendPayload(NodeNum dest = NODENUM_BROADCAST, uint32_t packetHistory_index = 0); void sendPayload(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
void sendMessage(NodeNum dest, char *str); void sendPayloadWelcome(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
virtual MeshPacket *allocReply(); virtual MeshPacket *allocReply();
virtual bool wantPortnum(PortNum p) { return true; }; virtual bool wantPortnum(PortNum p) { return true; };
private: private:
void populatePSRAM(); // Nothing here
protected: protected:
virtual int32_t runOnce(); virtual int32_t runOnce();
/** Called to handle a particular incoming message /** Called to handle a particular incoming message
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for @return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for it
it
*/ */
virtual ProcessMessage handleReceived(const MeshPacket &mp); virtual ProcessMessage handleReceived(const MeshPacket &mp);
}; };
extern StoreForwardPlugin *storeForwardPlugin; extern StoreForwardPlugin *storeForwardPlugin;
/*
* Radio interface for StoreForwardPlugin
*
*/
/*
class StoreForwardPluginRadio : public SinglePortPlugin
{
// uint32_t lastRxID;
public:
StoreForwardPluginRadio() : SinglePortPlugin("StoreForwardPluginRadio", PortNum_STORE_FORWARD_APP) {}
// StoreForwardPluginRadio() : SinglePortPlugin("StoreForwardPluginRadio", PortNum_TEXT_MESSAGE_APP) {}
void sendPayloadHeartbeat(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
protected:
virtual MeshPacket *allocReply2();
};
extern StoreForwardPluginRadio *storeForwardPluginRadio;
*/

View File

@@ -151,7 +151,6 @@ static const uint8_t SCK = PIN_SPI_SCK;
*/ */
// RAK4630 LoRa module // RAK4630 LoRa module
#define USE_SX1262
#define SX126X_CS (42) #define SX126X_CS (42)
#define SX126X_DIO1 (47) #define SX126X_DIO1 (47)
#define SX126X_BUSY (46) #define SX126X_BUSY (46)

View File

@@ -178,7 +178,6 @@ External serial flash WP25R1635FZUIL0
* Lora radio * Lora radio
*/ */
#define USE_SX1262
#define SX126X_CS (0 + 24) // FIXME - we really should define LORA_CS instead #define SX126X_CS (0 + 24) // FIXME - we really should define LORA_CS instead
#define SX126X_DIO1 (0 + 20) #define SX126X_DIO1 (0 + 20)
// Note DIO2 is attached internally to the module to an analog switch for TX/RX switching // Note DIO2 is attached internally to the module to an analog switch for TX/RX switching

View File

@@ -57,7 +57,6 @@
#define WIRE_INTERFACES_COUNT 0 #define WIRE_INTERFACES_COUNT 0
// GPIOs the SX1262 is connected // GPIOs the SX1262 is connected
#define USE_SX1262
#define SX126X_CS 1 // aka SPI_NSS #define SX126X_CS 1 // aka SPI_NSS
#define SX126X_DIO1 (4) #define SX126X_DIO1 (4)
#define SX126X_BUSY (5) #define SX126X_BUSY (5)

View File

@@ -116,9 +116,6 @@ static const uint8_t SCK = PIN_SPI_SCK;
// I2C device addresses // I2C device addresses
#define I2C_ADDR_BQ27441 0x55 // Battery gauge #define I2C_ADDR_BQ27441 0x55 // Battery gauge
// SX1262 declaration
#define USE_SX1262
// CUSTOM GPIOs the SX1262 // CUSTOM GPIOs the SX1262
#define SX126X_CS (32) #define SX126X_CS (32)

View File

@@ -136,9 +136,6 @@ static const uint8_t SCK = PIN_SPI_SCK;
// I2C device addresses // I2C device addresses
#define I2C_ADDR_BQ27441 0x55 // Battery gauge #define I2C_ADDR_BQ27441 0x55 // Battery gauge
// SX1262 declaration
#define USE_SX1262
// CUSTOM GPIOs the SX1262 // CUSTOM GPIOs the SX1262
#define SX126X_CS (32) #define SX126X_CS (32)

View File

@@ -140,7 +140,6 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define EXTERNAL_FLASH_USE_QSPI #define EXTERNAL_FLASH_USE_QSPI
// CUSTOM GPIOs the SX1262MB2CAS shield when installed on the NRF52840-DK development board // CUSTOM GPIOs the SX1262MB2CAS shield when installed on the NRF52840-DK development board
#define USE_SX1262
#define SX126X_CS (32 + 8) // P1.08 #define SX126X_CS (32 + 8) // P1.08
#define SX126X_DIO1 (32 + 6) // P1.06 #define SX126X_DIO1 (32 + 6) // P1.06
#define SX126X_BUSY (32 + 4) // P1.04 #define SX126X_BUSY (32 + 4) // P1.04

View File

@@ -129,7 +129,6 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define PIN_WIRE_SCL (32) #define PIN_WIRE_SCL (32)
// CUSTOM GPIOs the SX1262 // CUSTOM GPIOs the SX1262
#define USE_SX1262
#define SX126X_CS (10) #define SX126X_CS (10)
#define SX126X_DIO1 (20) #define SX126X_DIO1 (20)
#define SX1262_DIO2 (26) #define SX1262_DIO2 (26)

View File

@@ -152,7 +152,6 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define PIN_WIRE_SCL (32) #define PIN_WIRE_SCL (32)
// CUSTOM GPIOs the SX1262 // CUSTOM GPIOs the SX1262
#define USE_SX1262
#define SX126X_CS (0 + 10) // FIXME - we really should define LORA_CS instead #define SX126X_CS (0 + 10) // FIXME - we really should define LORA_CS instead
#define SX126X_DIO1 (0 + 20) #define SX126X_DIO1 (0 + 20)
#define SX1262_DIO2 (0 + 26) #define SX1262_DIO2 (0 + 26)

View File

@@ -180,7 +180,6 @@ External serial flash WP25R1635FZUIL0
* Lora radio * Lora radio
*/ */
#define USE_SX1262
#define SX126X_CS (0 + 24) // FIXME - we really should define LORA_CS instead #define SX126X_CS (0 + 24) // FIXME - we really should define LORA_CS instead
#define SX126X_DIO1 (0 + 20) #define SX126X_DIO1 (0 + 20)
// Note DIO2 is attached internally to the module to an analog switch for TX/RX switching // Note DIO2 is attached internally to the module to an analog switch for TX/RX switching

View File

@@ -1,4 +1,4 @@
[VERSION] [VERSION]
major = 1 major = 1
minor = 2 minor = 2
build = 47 build = 46