mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-17 23:37:44 +00:00
Merge branch 'master' into apollo
This commit is contained in:
@@ -154,9 +154,16 @@ static void adcEnable()
|
||||
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
|
||||
#ifdef ADC_USE_PULLUP
|
||||
pinMode(ADC_CTRL, INPUT_PULLUP);
|
||||
#else
|
||||
#ifdef HELTEC_V3
|
||||
pinMode(ADC_CTRL, INPUT);
|
||||
uint8_t adc_ctl_enable_value = !(digitalRead(ADC_CTRL));
|
||||
pinMode(ADC_CTRL, OUTPUT);
|
||||
digitalWrite(ADC_CTRL, adc_ctl_enable_value);
|
||||
#else
|
||||
pinMode(ADC_CTRL, OUTPUT);
|
||||
digitalWrite(ADC_CTRL, ADC_CTRL_ENABLED);
|
||||
#endif
|
||||
#endif
|
||||
delay(10);
|
||||
#endif
|
||||
@@ -167,10 +174,14 @@ static void adcDisable()
|
||||
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
|
||||
#ifdef ADC_USE_PULLUP
|
||||
pinMode(ADC_CTRL, INPUT_PULLDOWN);
|
||||
#else
|
||||
#ifdef HELTEC_V3
|
||||
pinMode(ADC_CTRL, ANALOG);
|
||||
#else
|
||||
digitalWrite(ADC_CTRL, !ADC_CTRL_ENABLED);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -207,6 +207,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef GPS_BAUDRATE
|
||||
#define GPS_BAUDRATE 9600
|
||||
#define GPS_BAUDRATE_FIXED 0
|
||||
#else
|
||||
#define GPS_BAUDRATE_FIXED 1
|
||||
#endif
|
||||
|
||||
/* Step #2: follow with defines common to the architecture;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#include "PortduinoGlue.h"
|
||||
#include "meshUtils.h"
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#endif
|
||||
|
||||
@@ -412,30 +413,42 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup the GPS based on the model detected.
|
||||
* We detect the GPS by cycling through a set of baud rates, first common then rare.
|
||||
* For each baud rate, we run GPS::Probe to send commands and match the responses
|
||||
* to known GPS responses.
|
||||
* @retval Whether setup reached the end of its potential to configure the GPS.
|
||||
*/
|
||||
bool GPS::setup()
|
||||
{
|
||||
|
||||
if (!didSerialInit) {
|
||||
int msglen = 0;
|
||||
if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
|
||||
// if GPS_BAUDRATE is specified in variant (i.e. not 9600), skip to the specified rate.
|
||||
if (speedSelect == 0 && GPS_BAUDRATE != serialSpeeds[speedSelect]) {
|
||||
speedSelect = std::find(serialSpeeds, std::end(serialSpeeds), GPS_BAUDRATE) - serialSpeeds;
|
||||
if (probeTries < 2) {
|
||||
LOG_DEBUG("Probing for GPS at %d", serialSpeeds[speedSelect]);
|
||||
gnssModel = probe(serialSpeeds[speedSelect]);
|
||||
if (gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
if (++speedSelect == sizeof(serialSpeeds) / sizeof(int)) {
|
||||
speedSelect = 0;
|
||||
++probeTries;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG("Probing for GPS at %d", serialSpeeds[speedSelect]);
|
||||
gnssModel = probe(serialSpeeds[speedSelect]);
|
||||
if (gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
if (++speedSelect == sizeof(serialSpeeds) / sizeof(int)) {
|
||||
speedSelect = 0;
|
||||
if (--probeTries == 0) {
|
||||
LOG_WARN("Giving up on GPS probe and setting to 9600.");
|
||||
// Rare Serial Speeds
|
||||
if (probeTries == 2) {
|
||||
LOG_DEBUG("Probing for GPS at %d", rareSerialSpeeds[speedSelect]);
|
||||
gnssModel = probe(rareSerialSpeeds[speedSelect]);
|
||||
if (gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
if (++speedSelect == sizeof(rareSerialSpeeds) / sizeof(int)) {
|
||||
LOG_WARN("Giving up on GPS probe and setting to %d", GPS_BAUDRATE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
} else {
|
||||
gnssModel = GNSS_MODEL_UNKNOWN;
|
||||
}
|
||||
@@ -475,6 +488,18 @@ bool GPS::setup()
|
||||
// Switch to Fitness Mode, for running and walking purpose with low speed (<5 m/s)
|
||||
_serial_gps->write("$PMTK886,1*29\r\n");
|
||||
delay(250);
|
||||
} else if (gnssModel == GNSS_MODEL_MTK_PA1616S) {
|
||||
// PA1616S is used in some GPS breakout boards from Adafruit
|
||||
// PA1616S does not have GLONASS capability. PA1616D does, but is not implemented here.
|
||||
_serial_gps->write("$PMTK353,1,0,0,0,0*2A\r\n");
|
||||
// Above command will reset the GPS and takes longer before it will accept new commands
|
||||
delay(1000);
|
||||
// Only ask for RMC and GGA (GNRMC and GNGGA)
|
||||
_serial_gps->write("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n");
|
||||
delay(250);
|
||||
// Enable SBAS / WAAS
|
||||
_serial_gps->write("$PMTK301,2*2E\r\n");
|
||||
delay(250);
|
||||
} else if (gnssModel == GNSS_MODEL_ATGM336H) {
|
||||
// Set the intial configuration of the device - these _should_ work for most AT6558 devices
|
||||
msglen = makeCASPacket(0x06, 0x07, sizeof(_message_CAS_CFG_NAVX_CONF), _message_CAS_CFG_NAVX_CONF);
|
||||
@@ -662,7 +687,8 @@ bool GPS::setup()
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_SBAS_BBR, "disable SBAS M10 GPS BBR", 300);
|
||||
delay(750); // will cause a receiver restart so wait a bit
|
||||
|
||||
// Done with initialization, Now enable wanted NMEA messages in BBR layer so they will survive a periodic sleep.
|
||||
// Done with initialization, Now enable wanted NMEA messages in BBR layer so they will survive a periodic
|
||||
// sleep.
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ENABLE_NMEA_BBR, "enable messages for M10 GPS BBR", 300);
|
||||
delay(750);
|
||||
// Next enable wanted NMEA messages in RAM layer
|
||||
@@ -924,10 +950,10 @@ void GPS::down()
|
||||
#endif
|
||||
|
||||
if (softsleepSupported) {
|
||||
// How long does gps_update_interval need to be, for GPS_HARDSLEEP to become more efficient than GPS_SOFTSLEEP?
|
||||
// Heuristic equation. A compromise manually fitted to power observations from U-blox NEO-6M and M10050
|
||||
// https://www.desmos.com/calculator/6gvjghoumr
|
||||
// This is not particularly accurate, but probably an impromevement over a single, fixed threshold
|
||||
// How long does gps_update_interval need to be, for GPS_HARDSLEEP to become more efficient than
|
||||
// GPS_SOFTSLEEP? Heuristic equation. A compromise manually fitted to power observations from U-blox NEO-6M
|
||||
// and M10050 https://www.desmos.com/calculator/6gvjghoumr This is not particularly accurate, but probably an
|
||||
// improvement over a single, fixed threshold
|
||||
uint32_t hardsleepThreshold = (2750 * pow(predictedSearchDuration / 1000, 1.22));
|
||||
LOG_DEBUG("gps_update_interval >= %us needed to justify hardsleep", hardsleepThreshold / 1000);
|
||||
|
||||
@@ -1143,6 +1169,7 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
delay(20);
|
||||
|
||||
PROBE_SIMPLE("L76B", "$PMTK605*31", "Quectel-L76B", GNSS_MODEL_MTK_L76B, 500);
|
||||
PROBE_SIMPLE("PA1616S", "$PMTK605*31", "1616S", GNSS_MODEL_MTK_PA1616S, 500);
|
||||
|
||||
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
|
||||
UBXChecksum(cfg_rate, sizeof(cfg_rate));
|
||||
@@ -1279,10 +1306,12 @@ GPS *GPS::createGps()
|
||||
|
||||
if (!GPS_EN_ACTIVE) { // Need to invert the pin before hardware
|
||||
new GpioNotTransformer(
|
||||
virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
|
||||
virtPin,
|
||||
p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
|
||||
} else {
|
||||
new GpioUnaryTransformer(
|
||||
virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
|
||||
virtPin,
|
||||
p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1390,8 +1419,8 @@ bool GPS::factoryReset()
|
||||
_serial_gps->write("$PMTK104*37\r\n");
|
||||
// No PMTK_ACK for this command.
|
||||
delay(100);
|
||||
// send the UBLOX Factory Reset Command regardless of detect state, something is very wrong, just assume it's UBLOX.
|
||||
// Factory Reset
|
||||
// send the UBLOX Factory Reset Command regardless of detect state, something is very wrong, just assume it's
|
||||
// UBLOX. Factory Reset
|
||||
byte _message_reset[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFB, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x17, 0x2B, 0x7E};
|
||||
_serial_gps->write(_message_reset, sizeof(_message_reset));
|
||||
@@ -1430,8 +1459,8 @@ bool GPS::lookForTime()
|
||||
auto d = reader.date;
|
||||
if (ti.isValid() && d.isValid()) { // Note: we don't check for updated, because we'll only be called if needed
|
||||
/* Convert to unix time
|
||||
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970
|
||||
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
|
||||
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1,
|
||||
1970 (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
|
||||
*/
|
||||
struct tm t;
|
||||
t.tm_sec = ti.second() + round(ti.age() / 1000);
|
||||
@@ -1664,7 +1693,9 @@ bool GPS::whileActive()
|
||||
}
|
||||
}
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG(debugmsg.c_str());
|
||||
if (debugmsg != "") {
|
||||
LOG_DEBUG(debugmsg.c_str());
|
||||
}
|
||||
#endif
|
||||
return isValid;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ typedef enum {
|
||||
GNSS_MODEL_UC6580,
|
||||
GNSS_MODEL_UNKNOWN,
|
||||
GNSS_MODEL_MTK_L76B,
|
||||
GNSS_MODEL_MTK_PA1616S,
|
||||
GNSS_MODEL_AG3335,
|
||||
GNSS_MODEL_AG3352
|
||||
} GnssModel_t;
|
||||
@@ -75,13 +76,21 @@ class GPS : private concurrency::OSThread
|
||||
uint8_t fixType = 0; // fix type from GPGSA
|
||||
#endif
|
||||
private:
|
||||
const int serialSpeeds[6] = {9600, 115200, 38400, 4800, 57600, 9600};
|
||||
#if GPS_BAUDRATE_FIXED
|
||||
// if GPS_BAUDRATE is specified in variant, only try that.
|
||||
const int serialSpeeds[1] = {GPS_BAUDRATE};
|
||||
const int rareSerialSpeeds[1] = {GPS_BAUDRATE};
|
||||
#else
|
||||
const int serialSpeeds[3] = {9600, 115200, 38400};
|
||||
const int rareSerialSpeeds[3] = {4800, 57600, GPS_BAUDRATE};
|
||||
#endif
|
||||
|
||||
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0;
|
||||
uint32_t rx_gpio = 0;
|
||||
uint32_t tx_gpio = 0;
|
||||
|
||||
int speedSelect = 0;
|
||||
int probeTries = 2;
|
||||
int probeTries = 0;
|
||||
|
||||
/**
|
||||
* hasValidLocation - indicates that the position variables contain a complete
|
||||
|
||||
@@ -70,9 +70,9 @@ bool GPSUpdateScheduling::isUpdateDue()
|
||||
// Have we been searching for a GPS position for too long?
|
||||
bool GPSUpdateScheduling::searchedTooLong()
|
||||
{
|
||||
uint32_t maxSearchMs =
|
||||
Default::getConfiguredOrDefaultMs(config.position.position_broadcast_secs, default_broadcast_interval_secs);
|
||||
|
||||
uint32_t minimumOrConfiguredSecs =
|
||||
Default::getConfiguredOrMinimumValue(config.position.position_broadcast_secs, default_broadcast_interval_secs);
|
||||
uint32_t maxSearchMs = Default::getConfiguredOrDefaultMs(minimumOrConfiguredSecs, default_broadcast_interval_secs);
|
||||
// If broadcast interval set to max, no such thing as "too long"
|
||||
if (maxSearchMs == UINT32_MAX)
|
||||
return false;
|
||||
@@ -115,4 +115,4 @@ void GPSUpdateScheduling::updateLockTimePrediction()
|
||||
uint32_t GPSUpdateScheduling::predictedSearchDurationMs()
|
||||
{
|
||||
return GPSUpdateScheduling::predictedMsToGetLock;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ int32_t ScanAndSelectInput::runOnce()
|
||||
// If: "no messages added" alert screen currently shown
|
||||
if (alertingNoMessage) {
|
||||
// Dismiss the alert screen several seconds after it appears
|
||||
if (now > alertingSinceMs + durationAlertMs) {
|
||||
if (!Throttle::isWithinTimespanMs(alertingSinceMs, durationAlertMs)) {
|
||||
alertingNoMessage = false;
|
||||
screen->endAlert();
|
||||
}
|
||||
@@ -74,9 +74,9 @@ int32_t ScanAndSelectInput::runOnce()
|
||||
|
||||
// Existing press
|
||||
else {
|
||||
// Duration enough for long press
|
||||
// Longer than shortpress window
|
||||
// Long press not yet fired (prevent repeat firing while held)
|
||||
if (!longPressFired && Throttle::isWithinTimespanMs(downSinceMs, durationLongMs)) {
|
||||
if (!longPressFired && !Throttle::isWithinTimespanMs(downSinceMs, durationLongMs)) {
|
||||
longPressFired = true;
|
||||
longPress();
|
||||
}
|
||||
@@ -91,7 +91,9 @@ int32_t ScanAndSelectInput::runOnce()
|
||||
// Button newly released
|
||||
// Long press event didn't already fire
|
||||
if (held && !longPressFired) {
|
||||
// Duration enough for short press
|
||||
// Duration within shortpress window
|
||||
// - longer than durationShortPress (debounce)
|
||||
// - shorter than durationLongPress
|
||||
if (!Throttle::isWithinTimespanMs(downSinceMs, durationShortMs)) {
|
||||
shortPress();
|
||||
}
|
||||
|
||||
12
src/main.cpp
12
src/main.cpp
@@ -267,14 +267,19 @@ void setup()
|
||||
#ifdef DEBUG_PORT
|
||||
consoleInit(); // Set serial baud rate and init our mesh console
|
||||
#endif
|
||||
|
||||
#ifdef UNPHONE
|
||||
unphone.printStore();
|
||||
#endif
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
struct timeval tv;
|
||||
tv.tv_sec = time(NULL);
|
||||
tv.tv_usec = 0;
|
||||
perhapsSetRTC(RTCQualityNTP, &tv);
|
||||
#endif
|
||||
powerMonInit();
|
||||
|
||||
powerMonInit();
|
||||
serialSinceMsec = millis();
|
||||
|
||||
LOG_INFO("\n\n//\\ E S H T /\\ S T / C\n");
|
||||
@@ -643,6 +648,8 @@ void setup()
|
||||
rp2040Setup();
|
||||
#endif
|
||||
|
||||
initSPI(); // needed here before reading from littleFS
|
||||
|
||||
// We do this as early as possible because this loads preferences from flash
|
||||
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
|
||||
nodeDB = new NodeDB;
|
||||
@@ -706,7 +713,6 @@ void setup()
|
||||
#endif
|
||||
|
||||
// Init our SPI controller (must be before screen and lora)
|
||||
initSPI();
|
||||
#ifdef ARCH_RP2040
|
||||
#ifdef HW_SPI1_DEVICE
|
||||
SPI1.setSCK(LORA_SCK);
|
||||
@@ -1190,4 +1196,4 @@ void loop()
|
||||
mainDelay.delay(delayMsec);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#if HAS_WIFI
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
#include "SPILock.h"
|
||||
#include "modules/StoreForwardModule.h"
|
||||
#include <Preferences.h>
|
||||
#include <esp_efuse.h>
|
||||
@@ -136,11 +137,12 @@ NodeDB::NodeDB()
|
||||
memcpy(myNodeInfo.device_id.bytes, &device_id_start, sizeof(device_id_start));
|
||||
memcpy(myNodeInfo.device_id.bytes + sizeof(device_id_start), &device_id_end, sizeof(device_id_end));
|
||||
myNodeInfo.device_id.size = 16;
|
||||
hasUniqueId = true;
|
||||
// Uncomment below to print the device id
|
||||
// hasUniqueId = true;
|
||||
#else
|
||||
// FIXME - implement for other platforms
|
||||
#endif
|
||||
// Uncomment below to print the device id
|
||||
|
||||
// if (hasUniqueId) {
|
||||
// std::string deviceIdHex;
|
||||
// for (size_t i = 0; i < myNodeInfo.device_id.size; ++i) {
|
||||
@@ -173,21 +175,23 @@ NodeDB::NodeDB()
|
||||
}
|
||||
|
||||
#if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN || MESHTASTIC_EXCLUDE_PKI)
|
||||
bool keygenSuccess = false;
|
||||
if (config.security.private_key.size == 32) {
|
||||
if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) {
|
||||
if (!owner.is_licensed) {
|
||||
bool keygenSuccess = false;
|
||||
if (config.security.private_key.size == 32) {
|
||||
if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) {
|
||||
keygenSuccess = true;
|
||||
}
|
||||
} else {
|
||||
LOG_INFO("Generating new PKI keys");
|
||||
crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes);
|
||||
keygenSuccess = true;
|
||||
}
|
||||
} else {
|
||||
LOG_INFO("Generating new PKI keys");
|
||||
crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes);
|
||||
keygenSuccess = true;
|
||||
}
|
||||
if (keygenSuccess) {
|
||||
config.security.public_key.size = 32;
|
||||
config.security.private_key.size = 32;
|
||||
owner.public_key.size = 32;
|
||||
memcpy(owner.public_key.bytes, config.security.public_key.bytes, 32);
|
||||
if (keygenSuccess) {
|
||||
config.security.public_key.size = 32;
|
||||
config.security.private_key.size = 32;
|
||||
owner.public_key.size = 32;
|
||||
memcpy(owner.public_key.bytes, config.security.public_key.bytes, 32);
|
||||
}
|
||||
}
|
||||
#elif !(MESHTASTIC_EXCLUDE_PKI)
|
||||
// Calculate Curve25519 public and private keys
|
||||
@@ -556,8 +560,10 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role)
|
||||
if (role == meshtastic_Config_DeviceConfig_Role_ROUTER) {
|
||||
initConfigIntervals();
|
||||
initModuleConfigIntervals();
|
||||
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY;
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||
config.display.screen_on_secs = 1;
|
||||
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY;
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_SENSOR) {
|
||||
moduleConfig.telemetry.environment_measurement_enabled = true;
|
||||
moduleConfig.telemetry.environment_update_interval = 300;
|
||||
@@ -870,6 +876,9 @@ void NodeDB::loadFromDisk()
|
||||
bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_t *fields, const void *dest_struct,
|
||||
bool fullAtomic)
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
concurrency::LockGuard g(spiLock);
|
||||
#endif
|
||||
bool okay = false;
|
||||
#ifdef FSCom
|
||||
auto f = SafeFile(filename, fullAtomic);
|
||||
@@ -1270,4 +1279,4 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co
|
||||
LOG_ERROR("A critical failure occurred, portduino is exiting...");
|
||||
exit(2);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -271,7 +271,7 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
|
||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ||
|
||||
config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||
delay = random(0, 2 * CWsize) * slotTimeMsec;
|
||||
LOG_DEBUG("rx_snr found in packet. As a router, setting tx delay:%d", delay);
|
||||
LOG_DEBUG("rx_snr found in packet. Router: setting tx delay:%d", delay);
|
||||
} else {
|
||||
// offset the maximum delay for routers: (2 * CWmax * slotTimeMsec)
|
||||
delay = (2 * CWmax * slotTimeMsec) + random(0, pow(2, CWsize)) * slotTimeMsec;
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
#include "PortduinoGlue.h"
|
||||
#include "meshUtils.h"
|
||||
#endif
|
||||
void LockingArduinoHal::spiBeginTransaction()
|
||||
{
|
||||
spiLock->lock();
|
||||
@@ -20,9 +24,9 @@ void LockingArduinoHal::spiBeginTransaction()
|
||||
|
||||
void LockingArduinoHal::spiEndTransaction()
|
||||
{
|
||||
spiLock->unlock();
|
||||
|
||||
ArduinoHal::spiEndTransaction();
|
||||
|
||||
spiLock->unlock();
|
||||
}
|
||||
#if ARCH_PORTDUINO
|
||||
void LockingArduinoHal::spiTransfer(uint8_t *out, size_t len, uint8_t *in)
|
||||
@@ -278,11 +282,14 @@ void RadioLibInterface::onNotify(uint32_t notification)
|
||||
// Send any outgoing packets we have ready
|
||||
meshtastic_MeshPacket *txp = txQueue.dequeue();
|
||||
assert(txp);
|
||||
bool isLoraTx = txp->to != NODENUM_BROADCAST_NO_LORA;
|
||||
startSend(txp);
|
||||
|
||||
// Packet has been sent, count it toward our TX airtime utilization.
|
||||
uint32_t xmitMsec = getPacketTime(txp);
|
||||
airTime->logAirtime(TX_LOG, xmitMsec);
|
||||
if (isLoraTx) {
|
||||
// Packet has been sent, count it toward our TX airtime utilization.
|
||||
uint32_t xmitMsec = getPacketTime(txp);
|
||||
airTime->logAirtime(TX_LOG, xmitMsec);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -390,6 +397,11 @@ void RadioLibInterface::handleReceiveInterrupt()
|
||||
#endif
|
||||
|
||||
int state = iface->readData((uint8_t *)&radioBuffer, length);
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[logoutputlevel] == level_trace) {
|
||||
printBytes("Raw incoming packet: ", (uint8_t *)&radioBuffer, length);
|
||||
}
|
||||
#endif
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
LOG_ERROR("ignoring received packet due to error=%d", state);
|
||||
rxBad++;
|
||||
|
||||
@@ -81,14 +81,17 @@ int32_t Router::runOnce()
|
||||
*/
|
||||
void Router::enqueueReceivedMessage(meshtastic_MeshPacket *p)
|
||||
{
|
||||
if (fromRadioQueue.enqueue(p, 0)) { // NOWAIT - fixme, if queue is full, delete older messages
|
||||
|
||||
// Nasty hack because our threading is primitive. interfaces shouldn't need to know about routers FIXME
|
||||
setReceivedMessage();
|
||||
} else {
|
||||
printPacket("BUG! fromRadioQueue is full! Discarding!", p);
|
||||
packetPool.release(p);
|
||||
// Try enqueue until successful
|
||||
while (!fromRadioQueue.enqueue(p, 0)) {
|
||||
meshtastic_MeshPacket *old_p;
|
||||
old_p = fromRadioQueue.dequeuePtr(0); // Dequeue and discard the oldest packet
|
||||
if (old_p) {
|
||||
printPacket("fromRadioQ full, drop oldest!", old_p);
|
||||
packetPool.release(old_p);
|
||||
}
|
||||
}
|
||||
// Nasty hack because our threading is primitive. interfaces shouldn't need to know about routers FIXME
|
||||
setReceivedMessage();
|
||||
}
|
||||
|
||||
/// Generate a unique packet id
|
||||
@@ -591,19 +594,20 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
||||
skipHandle = true;
|
||||
}
|
||||
|
||||
bool shouldIgnoreNonstandardPorts =
|
||||
config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY;
|
||||
#if USERPREFS_EVENT_MODE
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
|
||||
(p->decoded.portnum == meshtastic_PortNum_ATAK_FORWARDER || p->decoded.portnum == meshtastic_PortNum_ATAK_PLUGIN ||
|
||||
p->decoded.portnum == meshtastic_PortNum_PAXCOUNTER_APP || p->decoded.portnum == meshtastic_PortNum_IP_TUNNEL_APP ||
|
||||
p->decoded.portnum == meshtastic_PortNum_AUDIO_APP || p->decoded.portnum == meshtastic_PortNum_PRIVATE_APP ||
|
||||
p->decoded.portnum == meshtastic_PortNum_DETECTION_SENSOR_APP ||
|
||||
p->decoded.portnum == meshtastic_PortNum_RANGE_TEST_APP ||
|
||||
p->decoded.portnum == meshtastic_PortNum_REMOTE_HARDWARE_APP)) {
|
||||
LOG_DEBUG("Ignoring packet on blacklisted portnum during event");
|
||||
shouldIgnoreNonstandardPorts = true;
|
||||
#endif
|
||||
if (shouldIgnoreNonstandardPorts && p->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
|
||||
IS_ONE_OF(p->decoded.portnum, meshtastic_PortNum_ATAK_FORWARDER, meshtastic_PortNum_ATAK_PLUGIN,
|
||||
meshtastic_PortNum_PAXCOUNTER_APP, meshtastic_PortNum_IP_TUNNEL_APP, meshtastic_PortNum_AUDIO_APP,
|
||||
meshtastic_PortNum_PRIVATE_APP, meshtastic_PortNum_DETECTION_SENSOR_APP, meshtastic_PortNum_RANGE_TEST_APP,
|
||||
meshtastic_PortNum_REMOTE_HARDWARE_APP)) {
|
||||
LOG_DEBUG("Ignoring packet on blacklisted portnum for CORE_PORTNUMS_ONLY");
|
||||
cancelSending(p->from, p->id);
|
||||
skipHandle = true;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
printPacket("packet decoding failed or skipped (no PSK?)", p);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#ifndef PB_MESHTASTIC_MESHTASTIC_CONFIG_PB_H_INCLUDED
|
||||
#define PB_MESHTASTIC_MESHTASTIC_CONFIG_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "meshtastic/device_ui.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
@@ -576,6 +577,7 @@ typedef struct _meshtastic_Config {
|
||||
meshtastic_Config_BluetoothConfig bluetooth;
|
||||
meshtastic_Config_SecurityConfig security;
|
||||
meshtastic_Config_SessionkeyConfig sessionkey;
|
||||
meshtastic_DeviceUIConfig device_ui;
|
||||
} payload_variant;
|
||||
} meshtastic_Config;
|
||||
|
||||
@@ -779,6 +781,7 @@ extern "C" {
|
||||
#define meshtastic_Config_bluetooth_tag 7
|
||||
#define meshtastic_Config_security_tag 8
|
||||
#define meshtastic_Config_sessionkey_tag 9
|
||||
#define meshtastic_Config_device_ui_tag 10
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_Config_FIELDLIST(X, a) \
|
||||
@@ -790,7 +793,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,display,payload_variant.disp
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,lora,payload_variant.lora), 6) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,bluetooth,payload_variant.bluetooth), 7) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,security,payload_variant.security), 8) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,sessionkey,payload_variant.sessionkey), 9)
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,sessionkey,payload_variant.sessionkey), 9) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,device_ui,payload_variant.device_ui), 10)
|
||||
#define meshtastic_Config_CALLBACK NULL
|
||||
#define meshtastic_Config_DEFAULT NULL
|
||||
#define meshtastic_Config_payload_variant_device_MSGTYPE meshtastic_Config_DeviceConfig
|
||||
@@ -802,6 +806,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,sessionkey,payload_variant.s
|
||||
#define meshtastic_Config_payload_variant_bluetooth_MSGTYPE meshtastic_Config_BluetoothConfig
|
||||
#define meshtastic_Config_payload_variant_security_MSGTYPE meshtastic_Config_SecurityConfig
|
||||
#define meshtastic_Config_payload_variant_sessionkey_MSGTYPE meshtastic_Config_SessionkeyConfig
|
||||
#define meshtastic_Config_payload_variant_device_ui_MSGTYPE meshtastic_DeviceUIConfig
|
||||
|
||||
#define meshtastic_Config_DeviceConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, role, 1) \
|
||||
|
||||
@@ -40,7 +40,19 @@ typedef enum _meshtastic_Language {
|
||||
/* Polish */
|
||||
meshtastic_Language_POLISH = 8,
|
||||
/* Turkish */
|
||||
meshtastic_Language_TURKISH = 9
|
||||
meshtastic_Language_TURKISH = 9,
|
||||
/* Serbian */
|
||||
meshtastic_Language_SERBIAN = 10,
|
||||
/* Russian */
|
||||
meshtastic_Language_RUSSIAN = 11,
|
||||
/* Dutch */
|
||||
meshtastic_Language_DUTCH = 12,
|
||||
/* Greek */
|
||||
meshtastic_Language_GREEK = 13,
|
||||
/* Simplified Chinese (experimental) */
|
||||
meshtastic_Language_SIMPLIFIED_CHINESE = 30,
|
||||
/* Traditional Chinese (experimental) */
|
||||
meshtastic_Language_TRADITIONAL_CHINESE = 31
|
||||
} meshtastic_Language;
|
||||
|
||||
/* Struct definitions */
|
||||
@@ -73,16 +85,22 @@ typedef struct _meshtastic_NodeHighlight {
|
||||
} meshtastic_NodeHighlight;
|
||||
|
||||
typedef struct _meshtastic_DeviceUIConfig {
|
||||
/* A version integer used to invalidate saved files when we make incompatible changes. */
|
||||
uint32_t version;
|
||||
/* TFT display brightness 1..255 */
|
||||
uint8_t screen_brightness;
|
||||
/* Screen timeout 0..900 */
|
||||
uint16_t screen_timeout;
|
||||
/* Screen lock enabled */
|
||||
/* Screen/Settings lock enabled */
|
||||
bool screen_lock;
|
||||
bool settings_lock;
|
||||
uint32_t pin_code;
|
||||
/* Color theme */
|
||||
meshtastic_Theme theme;
|
||||
/* Audible message alert enabled */
|
||||
/* Audible message, banner and ring tone */
|
||||
bool alert_enabled;
|
||||
bool banner_enabled;
|
||||
uint8_t ring_tone_id;
|
||||
/* Localization */
|
||||
meshtastic_Language language;
|
||||
/* Node list filter */
|
||||
@@ -104,8 +122,8 @@ extern "C" {
|
||||
#define _meshtastic_Theme_ARRAYSIZE ((meshtastic_Theme)(meshtastic_Theme_RED+1))
|
||||
|
||||
#define _meshtastic_Language_MIN meshtastic_Language_ENGLISH
|
||||
#define _meshtastic_Language_MAX meshtastic_Language_TURKISH
|
||||
#define _meshtastic_Language_ARRAYSIZE ((meshtastic_Language)(meshtastic_Language_TURKISH+1))
|
||||
#define _meshtastic_Language_MAX meshtastic_Language_TRADITIONAL_CHINESE
|
||||
#define _meshtastic_Language_ARRAYSIZE ((meshtastic_Language)(meshtastic_Language_TRADITIONAL_CHINESE+1))
|
||||
|
||||
#define meshtastic_DeviceUIConfig_theme_ENUMTYPE meshtastic_Theme
|
||||
#define meshtastic_DeviceUIConfig_language_ENUMTYPE meshtastic_Language
|
||||
@@ -114,10 +132,10 @@ extern "C" {
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, _meshtastic_Theme_MIN, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default}
|
||||
#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default}
|
||||
#define meshtastic_NodeFilter_init_default {0, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_NodeHighlight_init_default {0, 0, 0, 0, ""}
|
||||
#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, _meshtastic_Theme_MIN, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero}
|
||||
#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero}
|
||||
#define meshtastic_NodeFilter_init_zero {0, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_NodeHighlight_init_zero {0, 0, 0, 0, ""}
|
||||
|
||||
@@ -133,25 +151,35 @@ extern "C" {
|
||||
#define meshtastic_NodeHighlight_telemetry_switch_tag 3
|
||||
#define meshtastic_NodeHighlight_iaq_switch_tag 4
|
||||
#define meshtastic_NodeHighlight_node_name_tag 5
|
||||
#define meshtastic_DeviceUIConfig_screen_brightness_tag 1
|
||||
#define meshtastic_DeviceUIConfig_screen_timeout_tag 2
|
||||
#define meshtastic_DeviceUIConfig_screen_lock_tag 3
|
||||
#define meshtastic_DeviceUIConfig_theme_tag 4
|
||||
#define meshtastic_DeviceUIConfig_alert_enabled_tag 5
|
||||
#define meshtastic_DeviceUIConfig_language_tag 6
|
||||
#define meshtastic_DeviceUIConfig_node_filter_tag 7
|
||||
#define meshtastic_DeviceUIConfig_node_highlight_tag 8
|
||||
#define meshtastic_DeviceUIConfig_version_tag 1
|
||||
#define meshtastic_DeviceUIConfig_screen_brightness_tag 2
|
||||
#define meshtastic_DeviceUIConfig_screen_timeout_tag 3
|
||||
#define meshtastic_DeviceUIConfig_screen_lock_tag 4
|
||||
#define meshtastic_DeviceUIConfig_settings_lock_tag 5
|
||||
#define meshtastic_DeviceUIConfig_pin_code_tag 6
|
||||
#define meshtastic_DeviceUIConfig_theme_tag 7
|
||||
#define meshtastic_DeviceUIConfig_alert_enabled_tag 8
|
||||
#define meshtastic_DeviceUIConfig_banner_enabled_tag 9
|
||||
#define meshtastic_DeviceUIConfig_ring_tone_id_tag 10
|
||||
#define meshtastic_DeviceUIConfig_language_tag 11
|
||||
#define meshtastic_DeviceUIConfig_node_filter_tag 12
|
||||
#define meshtastic_DeviceUIConfig_node_highlight_tag 13
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_DeviceUIConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, screen_brightness, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, screen_timeout, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, screen_lock, 3) \
|
||||
X(a, STATIC, SINGULAR, UENUM, theme, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, alert_enabled, 5) \
|
||||
X(a, STATIC, SINGULAR, UENUM, language, 6) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, node_filter, 7) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, node_highlight, 8)
|
||||
X(a, STATIC, SINGULAR, UINT32, version, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, screen_brightness, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, screen_timeout, 3) \
|
||||
X(a, STATIC, SINGULAR, BOOL, screen_lock, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, settings_lock, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, pin_code, 6) \
|
||||
X(a, STATIC, SINGULAR, UENUM, theme, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, alert_enabled, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, banner_enabled, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ring_tone_id, 10) \
|
||||
X(a, STATIC, SINGULAR, UENUM, language, 11) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, node_filter, 12) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, node_highlight, 13)
|
||||
#define meshtastic_DeviceUIConfig_CALLBACK NULL
|
||||
#define meshtastic_DeviceUIConfig_DEFAULT NULL
|
||||
#define meshtastic_DeviceUIConfig_node_filter_MSGTYPE meshtastic_NodeFilter
|
||||
@@ -187,7 +215,7 @@ extern const pb_msgdesc_t meshtastic_NodeHighlight_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_DEVICE_UI_PB_H_MAX_SIZE meshtastic_DeviceUIConfig_size
|
||||
#define meshtastic_DeviceUIConfig_size 80
|
||||
#define meshtastic_DeviceUIConfig_size 99
|
||||
#define meshtastic_NodeFilter_size 36
|
||||
#define meshtastic_NodeHighlight_size 25
|
||||
|
||||
|
||||
@@ -408,7 +408,7 @@ typedef enum _meshtastic_LogRecord_Level {
|
||||
} meshtastic_LogRecord_Level;
|
||||
|
||||
/* Struct definitions */
|
||||
/* a gps position */
|
||||
/* A GPS Position */
|
||||
typedef struct _meshtastic_Position {
|
||||
/* The new preferred location encoding, multiply by 1e-7 to get degrees
|
||||
in floating point */
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "FSCommon.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include <Arduino.h>
|
||||
#include <assert.h>
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
|
||||
@@ -14,8 +13,6 @@ size_t pb_encode_to_bytes(uint8_t *destbuf, size_t destbufsize, const pb_msgdesc
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(destbuf, destbufsize);
|
||||
if (!pb_encode(&stream, fields, src_struct)) {
|
||||
LOG_ERROR("Panic: can't encode protobuf reason='%s'", PB_GET_ERROR(&stream));
|
||||
assert(
|
||||
0); // If this assert fails it probably means you made a field too large for the max limits specified in mesh.options
|
||||
return 0;
|
||||
} else {
|
||||
return stream.bytes_written;
|
||||
@@ -71,4 +68,4 @@ bool is_in_helper(uint32_t n, const uint32_t *array, pb_size_t count)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,15 +61,13 @@ char *strnstr(const char *s, const char *find, size_t slen)
|
||||
void printBytes(const char *label, const uint8_t *p, size_t numbytes)
|
||||
{
|
||||
int labelSize = strlen(label);
|
||||
if (labelSize < 100 && numbytes < 64) {
|
||||
char *messageBuffer = new char[labelSize + (numbytes * 3) + 2];
|
||||
strncpy(messageBuffer, label, labelSize);
|
||||
for (size_t i = 0; i < numbytes; i++)
|
||||
snprintf(messageBuffer + labelSize + i * 3, 4, " %02x", p[i]);
|
||||
strcpy(messageBuffer + labelSize + numbytes * 3, "\n");
|
||||
LOG_DEBUG(messageBuffer);
|
||||
delete[] messageBuffer;
|
||||
}
|
||||
char *messageBuffer = new char[labelSize + (numbytes * 3) + 2];
|
||||
strncpy(messageBuffer, label, labelSize);
|
||||
for (size_t i = 0; i < numbytes; i++)
|
||||
snprintf(messageBuffer + labelSize + i * 3, 4, " %02x", p[i]);
|
||||
strcpy(messageBuffer + labelSize + numbytes * 3, "\n");
|
||||
LOG_DEBUG(messageBuffer);
|
||||
delete[] messageBuffer;
|
||||
}
|
||||
|
||||
bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes)
|
||||
|
||||
@@ -900,7 +900,7 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
|
||||
#ifdef ARCH_PORTDUINO
|
||||
conn.wifi.status.is_connected = true;
|
||||
#else
|
||||
conn.wifi.status.is_connected = WiFi.status() != WL_CONNECTED;
|
||||
conn.wifi.status.is_connected = WiFi.status() == WL_CONNECTED;
|
||||
#endif
|
||||
strncpy(conn.wifi.ssid, config.network.wifi_ssid, 33);
|
||||
if (conn.wifi.status.is_connected) {
|
||||
@@ -932,10 +932,14 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
|
||||
conn.has_bluetooth = true;
|
||||
conn.bluetooth.pin = config.bluetooth.fixed_pin;
|
||||
#ifdef ARCH_ESP32
|
||||
conn.bluetooth.is_connected = nimbleBluetooth->isConnected();
|
||||
conn.bluetooth.rssi = nimbleBluetooth->getRssi();
|
||||
if (config.bluetooth.enabled && nimbleBluetooth) {
|
||||
conn.bluetooth.is_connected = nimbleBluetooth->isConnected();
|
||||
conn.bluetooth.rssi = nimbleBluetooth->getRssi();
|
||||
}
|
||||
#elif defined(ARCH_NRF52)
|
||||
conn.bluetooth.is_connected = nrf52Bluetooth->isConnected();
|
||||
if (config.bluetooth.enabled && nrf52Bluetooth) {
|
||||
conn.bluetooth.is_connected = nrf52Bluetooth->isConnected();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
conn.has_serial = true; // No serial-less devices
|
||||
|
||||
@@ -93,7 +93,7 @@ int32_t ExternalNotificationModule::runOnce()
|
||||
nagCycleCutoff = UINT32_MAX;
|
||||
LOG_INFO("Turning off external notification: ");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
setExternalOff(i);
|
||||
setExternalState(i, false);
|
||||
externalTurnedOn[i] = 0;
|
||||
LOG_INFO("%d ", i);
|
||||
}
|
||||
@@ -114,17 +114,17 @@ int32_t ExternalNotificationModule::runOnce()
|
||||
if (externalTurnedOn[0] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms
|
||||
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) <
|
||||
millis()) {
|
||||
getExternal(0) ? setExternalOff(0) : setExternalOn(0);
|
||||
setExternalState(0, !getExternal(0));
|
||||
}
|
||||
if (externalTurnedOn[1] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms
|
||||
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) <
|
||||
millis()) {
|
||||
getExternal(1) ? setExternalOff(1) : setExternalOn(1);
|
||||
setExternalState(0, !getExternal(1));
|
||||
}
|
||||
if (externalTurnedOn[2] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms
|
||||
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) <
|
||||
millis()) {
|
||||
getExternal(2) ? setExternalOff(2) : setExternalOn(2);
|
||||
setExternalState(0, !getExternal(2));
|
||||
}
|
||||
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
|
||||
red = (colorState & 4) ? brightnessValues[brightnessIndex] : 0; // Red enabled on colorState = 4,5,6,7
|
||||
@@ -184,7 +184,7 @@ int32_t ExternalNotificationModule::runOnce()
|
||||
}
|
||||
#endif
|
||||
// now let the PWM buzzer play
|
||||
if (moduleConfig.external_notification.use_pwm) {
|
||||
if (moduleConfig.external_notification.use_pwm && config.device.buzzer_gpio) {
|
||||
if (rtttl::isPlaying()) {
|
||||
rtttl::play();
|
||||
} else if (isNagging && (nagCycleCutoff >= millis())) {
|
||||
@@ -203,86 +203,42 @@ bool ExternalNotificationModule::wantPacket(const meshtastic_MeshPacket *p)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the external notification on for the specified index.
|
||||
* Sets the external notification for the specified index.
|
||||
*
|
||||
* @param index The index of the external notification to turn on.
|
||||
* @param index The index of the external notification to change state.
|
||||
* @param on Whether we are turning things on (true) or off (false).
|
||||
*/
|
||||
void ExternalNotificationModule::setExternalOn(uint8_t index)
|
||||
void ExternalNotificationModule::setExternalState(uint8_t index, bool on)
|
||||
{
|
||||
externalCurrentState[index] = 1;
|
||||
externalCurrentState[index] = on;
|
||||
externalTurnedOn[index] = millis();
|
||||
|
||||
switch (index) {
|
||||
case 1:
|
||||
#ifdef UNPHONE
|
||||
unphone.vibe(true); // the unPhone's vibration motor is on a i2c GPIO expander
|
||||
unphone.vibe(on); // the unPhone's vibration motor is on a i2c GPIO expander
|
||||
#endif
|
||||
if (moduleConfig.external_notification.output_vibra)
|
||||
digitalWrite(moduleConfig.external_notification.output_vibra, true);
|
||||
digitalWrite(moduleConfig.external_notification.output_vibra, on);
|
||||
break;
|
||||
case 2:
|
||||
if (moduleConfig.external_notification.output_buzzer)
|
||||
digitalWrite(moduleConfig.external_notification.output_buzzer, true);
|
||||
digitalWrite(moduleConfig.external_notification.output_buzzer, on);
|
||||
break;
|
||||
default:
|
||||
if (output > 0)
|
||||
digitalWrite(output, (moduleConfig.external_notification.active ? true : false));
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAS_NCP5623
|
||||
if (rgb_found.type == ScanI2C::NCP5623) {
|
||||
rgb.setColor(red, green, blue);
|
||||
}
|
||||
#endif
|
||||
#ifdef RGBLED_CA
|
||||
analogWrite(RGBLED_RED, 255 - red); // CA type needs reverse logic
|
||||
analogWrite(RGBLED_GREEN, 255 - green);
|
||||
analogWrite(RGBLED_BLUE, 255 - blue);
|
||||
#elif defined(RGBLED_RED)
|
||||
analogWrite(RGBLED_RED, red);
|
||||
analogWrite(RGBLED_GREEN, green);
|
||||
analogWrite(RGBLED_BLUE, blue);
|
||||
#endif
|
||||
#ifdef HAS_NEOPIXEL
|
||||
pixels.fill(pixels.Color(red, green, blue), 0, NEOPIXEL_COUNT);
|
||||
pixels.show();
|
||||
#endif
|
||||
#ifdef UNPHONE
|
||||
unphone.rgb(red, green, blue);
|
||||
#endif
|
||||
#ifdef T_WATCH_S3
|
||||
drv.go();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ExternalNotificationModule::setExternalOff(uint8_t index)
|
||||
{
|
||||
externalCurrentState[index] = 0;
|
||||
externalTurnedOn[index] = millis();
|
||||
|
||||
switch (index) {
|
||||
case 1:
|
||||
#ifdef UNPHONE
|
||||
unphone.vibe(false); // the unPhone's vibration motor is on a i2c GPIO expander
|
||||
#endif
|
||||
if (moduleConfig.external_notification.output_vibra)
|
||||
digitalWrite(moduleConfig.external_notification.output_vibra, false);
|
||||
break;
|
||||
case 2:
|
||||
if (moduleConfig.external_notification.output_buzzer)
|
||||
digitalWrite(moduleConfig.external_notification.output_buzzer, false);
|
||||
break;
|
||||
default:
|
||||
if (output > 0)
|
||||
digitalWrite(output, (moduleConfig.external_notification.active ? false : true));
|
||||
digitalWrite(output, (moduleConfig.external_notification.active ? on : !on));
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
|
||||
red = 0;
|
||||
green = 0;
|
||||
blue = 0;
|
||||
if (!on) {
|
||||
red = 0;
|
||||
green = 0;
|
||||
blue = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_NCP5623
|
||||
if (rgb_found.type == ScanI2C::NCP5623) {
|
||||
rgb.setColor(red, green, blue);
|
||||
@@ -304,10 +260,12 @@ void ExternalNotificationModule::setExternalOff(uint8_t index)
|
||||
#ifdef UNPHONE
|
||||
unphone.rgb(red, green, blue);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
drv.stop();
|
||||
if (on) {
|
||||
drv.go();
|
||||
} else {
|
||||
drv.stop();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -379,19 +337,19 @@ ExternalNotificationModule::ExternalNotificationModule()
|
||||
LOG_INFO("Using Pin %i in digital mode", output);
|
||||
pinMode(output, OUTPUT);
|
||||
}
|
||||
setExternalOff(0);
|
||||
setExternalState(0, false);
|
||||
externalTurnedOn[0] = 0;
|
||||
if (moduleConfig.external_notification.output_vibra) {
|
||||
LOG_INFO("Using Pin %i for vibra motor", moduleConfig.external_notification.output_vibra);
|
||||
pinMode(moduleConfig.external_notification.output_vibra, OUTPUT);
|
||||
setExternalOff(1);
|
||||
setExternalState(1, false);
|
||||
externalTurnedOn[1] = 0;
|
||||
}
|
||||
if (moduleConfig.external_notification.output_buzzer) {
|
||||
if (!moduleConfig.external_notification.use_pwm) {
|
||||
LOG_INFO("Using Pin %i for buzzer", moduleConfig.external_notification.output_buzzer);
|
||||
pinMode(moduleConfig.external_notification.output_buzzer, OUTPUT);
|
||||
setExternalOff(2);
|
||||
setExternalState(2, false);
|
||||
externalTurnedOn[2] = 0;
|
||||
} else {
|
||||
config.device.buzzer_gpio = config.device.buzzer_gpio ? config.device.buzzer_gpio : PIN_BUZZER;
|
||||
@@ -449,7 +407,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
||||
if (containsBell) {
|
||||
LOG_INFO("externalNotificationModule - Notification Bell");
|
||||
isNagging = true;
|
||||
setExternalOn(0);
|
||||
setExternalState(0, true);
|
||||
if (moduleConfig.external_notification.nag_timeout) {
|
||||
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
|
||||
} else {
|
||||
@@ -462,7 +420,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
||||
if (containsBell) {
|
||||
LOG_INFO("externalNotificationModule - Notification Bell (Vibra)");
|
||||
isNagging = true;
|
||||
setExternalOn(1);
|
||||
setExternalState(1, true);
|
||||
if (moduleConfig.external_notification.nag_timeout) {
|
||||
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
|
||||
} else {
|
||||
@@ -476,7 +434,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
||||
LOG_INFO("externalNotificationModule - Notification Bell (Buzzer)");
|
||||
isNagging = true;
|
||||
if (!moduleConfig.external_notification.use_pwm) {
|
||||
setExternalOn(2);
|
||||
setExternalState(2, true);
|
||||
} else {
|
||||
#ifdef HAS_I2S
|
||||
audioThread->beginRttl(rtttlConfig.ringtone, strlen_P(rtttlConfig.ringtone));
|
||||
@@ -495,7 +453,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
||||
if (moduleConfig.external_notification.alert_message) {
|
||||
LOG_INFO("externalNotificationModule - Notification Module");
|
||||
isNagging = true;
|
||||
setExternalOn(0);
|
||||
setExternalState(0, true);
|
||||
if (moduleConfig.external_notification.nag_timeout) {
|
||||
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
|
||||
} else {
|
||||
@@ -506,7 +464,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
||||
if (moduleConfig.external_notification.alert_message_vibra) {
|
||||
LOG_INFO("externalNotificationModule - Notification Module (Vibra)");
|
||||
isNagging = true;
|
||||
setExternalOn(1);
|
||||
setExternalState(1, true);
|
||||
if (moduleConfig.external_notification.nag_timeout) {
|
||||
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
|
||||
} else {
|
||||
@@ -518,7 +476,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
||||
LOG_INFO("externalNotificationModule - Notification Module (Buzzer)");
|
||||
isNagging = true;
|
||||
if (!moduleConfig.external_notification.use_pwm && !moduleConfig.external_notification.use_i2s_as_buzzer) {
|
||||
setExternalOn(2);
|
||||
setExternalState(2, true);
|
||||
} else {
|
||||
#ifdef HAS_I2S
|
||||
if (moduleConfig.external_notification.use_i2s_as_buzzer) {
|
||||
|
||||
@@ -32,10 +32,9 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency:
|
||||
public:
|
||||
ExternalNotificationModule();
|
||||
|
||||
uint32_t nagCycleCutoff = UINT32_MAX;
|
||||
uint32_t nagCycleCutoff = 1;
|
||||
|
||||
void setExternalOn(uint8_t index = 0);
|
||||
void setExternalOff(uint8_t index = 0);
|
||||
void setExternalState(uint8_t index = 0, bool on = false);
|
||||
bool getExternal(uint8_t index = 0);
|
||||
|
||||
void setMute(bool mute) { isMuted = mute; }
|
||||
|
||||
@@ -121,9 +121,7 @@ Will be used for broadcast.
|
||||
*/
|
||||
int32_t NeighborInfoModule::runOnce()
|
||||
{
|
||||
if (airTime->isTxAllowedChannelUtil(true) && airTime->isTxAllowedAirUtil()) {
|
||||
sendNeighborInfo(NODENUM_BROADCAST_NO_LORA, false);
|
||||
}
|
||||
sendNeighborInfo(NODENUM_BROADCAST_NO_LORA, false);
|
||||
return Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_neighbor_info_broadcast_secs);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,12 @@ meshtastic_MeshPacket *NodeInfoModule::allocReply()
|
||||
ignoreRequest = false; // Don't ignore requests anymore
|
||||
meshtastic_User &u = owner;
|
||||
|
||||
// Strip the public key if the user is licensed
|
||||
if (u.is_licensed && u.public_key.size > 0) {
|
||||
u.public_key.bytes[0] = 0;
|
||||
u.public_key.size = 0;
|
||||
}
|
||||
|
||||
LOG_INFO("sending owner %s/%s/%s", u.id, u.long_name, u.short_name);
|
||||
lastSentToMesh = millis();
|
||||
return allocDataProtobuf(u);
|
||||
|
||||
@@ -315,7 +315,7 @@ ProcessMessage SerialModuleRadio::handleReceived(const meshtastic_MeshPacket &mp
|
||||
// LOG_DEBUG("Received text msg self=0x%0x, from=0x%0x, to=0x%0x, id=%d, msg=%.*s",
|
||||
// nodeDB->getNodeNum(), mp.from, mp.to, mp.id, p.payload.size, p.payload.bytes);
|
||||
|
||||
if (!isFromUs(&mp)) {
|
||||
if (isFromUs(&mp)) {
|
||||
|
||||
/*
|
||||
* If moduleConfig.serial.echo is true, then echo the packets that are sent out
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "QMA6100PSensor.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && HAS_QMA6100P
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_QMA6100P)
|
||||
|
||||
// Flag when an interrupt has been detected
|
||||
volatile static bool QMA6100P_IRQ = false;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "MotionSensor.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && HAS_QMA6100P
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_QMA6100P)
|
||||
|
||||
#include <QMA6100P.h>
|
||||
|
||||
|
||||
@@ -51,7 +51,11 @@ void updateBatteryLevel(uint8_t level) {}
|
||||
|
||||
void getMacAddr(uint8_t *dmac)
|
||||
{
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32C6) && defined(CONFIG_SOC_IEEE802154_SUPPORTED)
|
||||
assert(esp_base_mac_addr_get(dmac) == ESP_OK);
|
||||
#else
|
||||
assert(esp_efuse_mac_get_default(dmac) == ESP_OK);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAS_32768HZ
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "PortduinoGlue.h"
|
||||
#include "linux/gpio/LinuxGPIOPin.h"
|
||||
#include "yaml-cpp/yaml.h"
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <unistd.h>
|
||||
@@ -100,33 +101,22 @@ void portduinoSetup()
|
||||
settingsStrings[displayspidev] = "";
|
||||
settingsMap[spiSpeed] = 2000000;
|
||||
settingsMap[ascii_logs] = !isatty(1);
|
||||
settingsMap[displayPanel] = no_screen;
|
||||
settingsMap[touchscreenModule] = no_touchscreen;
|
||||
|
||||
YAML::Node yamlConfig;
|
||||
|
||||
if (configPath != nullptr) {
|
||||
std::cout << "Using " << configPath << " as config file" << std::endl;
|
||||
try {
|
||||
yamlConfig = YAML::LoadFile(configPath);
|
||||
} catch (YAML::Exception &e) {
|
||||
std::cout << "Could not open " << configPath << " because of error: " << e.what() << std::endl;
|
||||
if (loadConfig(configPath)) {
|
||||
std::cout << "Using " << configPath << " as config file" << std::endl;
|
||||
} else {
|
||||
std::cout << "Unable to use " << configPath << " as config file" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (access("config.yaml", R_OK) == 0) {
|
||||
} else if (access("config.yaml", R_OK) == 0 && loadConfig("config.yaml")) {
|
||||
std::cout << "Using local config.yaml as config file" << std::endl;
|
||||
try {
|
||||
yamlConfig = YAML::LoadFile("config.yaml");
|
||||
} catch (YAML::Exception &e) {
|
||||
std::cout << "*** Exception " << e.what() << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0) {
|
||||
} else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0 && loadConfig("/etc/meshtasticd/config.yaml")) {
|
||||
std::cout << "Using /etc/meshtasticd/config.yaml as config file" << std::endl;
|
||||
try {
|
||||
yamlConfig = YAML::LoadFile("/etc/meshtasticd/config.yaml");
|
||||
} catch (YAML::Exception &e) {
|
||||
std::cout << "*** Exception " << e.what() << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
std::cout << "No 'config.yaml' found, running simulated." << std::endl;
|
||||
settingsMap[maxnodes] = 200; // Default to 200 nodes
|
||||
@@ -136,170 +126,21 @@ void portduinoSetup()
|
||||
return;
|
||||
}
|
||||
|
||||
if (settingsStrings[config_directory] != "") {
|
||||
std::string filetype = ".yaml";
|
||||
for (const std::filesystem::directory_entry &entry :
|
||||
std::filesystem::directory_iterator{settingsStrings[config_directory]}) {
|
||||
if (ends_with(entry.path().string(), ".yaml")) {
|
||||
std::cout << "Also using " << entry << " as additional config file" << std::endl;
|
||||
loadConfig(entry.path().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rather important to set this, if not running simulated.
|
||||
randomSeed(time(NULL));
|
||||
|
||||
try {
|
||||
if (yamlConfig["Logging"]) {
|
||||
if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "trace") {
|
||||
settingsMap[logoutputlevel] = level_trace;
|
||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "debug") {
|
||||
settingsMap[logoutputlevel] = level_debug;
|
||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "info") {
|
||||
settingsMap[logoutputlevel] = level_info;
|
||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "warn") {
|
||||
settingsMap[logoutputlevel] = level_warn;
|
||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "error") {
|
||||
settingsMap[logoutputlevel] = level_error;
|
||||
}
|
||||
settingsStrings[traceFilename] = yamlConfig["Logging"]["TraceFile"].as<std::string>("");
|
||||
if (yamlConfig["Logging"]["AsciiLogs"]) {
|
||||
// Default is !isatty(1) but can be set explicitly in config.yaml
|
||||
settingsMap[ascii_logs] = yamlConfig["Logging"]["AsciiLogs"].as<bool>();
|
||||
}
|
||||
}
|
||||
if (yamlConfig["Lora"]) {
|
||||
settingsMap[use_sx1262] = false;
|
||||
settingsMap[use_rf95] = false;
|
||||
settingsMap[use_sx1280] = false;
|
||||
settingsMap[use_sx1268] = false;
|
||||
|
||||
if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1262") {
|
||||
settingsMap[use_sx1262] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "RF95") {
|
||||
settingsMap[use_rf95] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1280") {
|
||||
settingsMap[use_sx1280] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1268") {
|
||||
settingsMap[use_sx1268] = true;
|
||||
}
|
||||
settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as<bool>(false);
|
||||
settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<bool>(false);
|
||||
settingsMap[cs] = yamlConfig["Lora"]["CS"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[irq] = yamlConfig["Lora"]["IRQ"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[busy] = yamlConfig["Lora"]["Busy"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[reset] = yamlConfig["Lora"]["Reset"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[txen] = yamlConfig["Lora"]["TXen"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[rxen] = yamlConfig["Lora"]["RXen"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[sx126x_ant_sw] = yamlConfig["Lora"]["SX126X_ANT_SW"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(0);
|
||||
settingsMap[ch341Quirk] = yamlConfig["Lora"]["ch341_quirk"].as<bool>(false);
|
||||
settingsMap[spiSpeed] = yamlConfig["Lora"]["spiSpeed"].as<int>(2000000);
|
||||
gpioChipName += std::to_string(settingsMap[gpiochip]);
|
||||
|
||||
settingsStrings[spidev] = "/dev/" + yamlConfig["Lora"]["spidev"].as<std::string>("spidev0.0");
|
||||
if (settingsStrings[spidev].length() == 14) {
|
||||
int x = settingsStrings[spidev].at(11) - '0';
|
||||
int y = settingsStrings[spidev].at(13) - '0';
|
||||
if (x >= 0 && x < 10 && y >= 0 && y < 10) {
|
||||
settingsMap[spidev] = x + y << 4;
|
||||
settingsMap[displayspidev] = settingsMap[spidev];
|
||||
settingsMap[touchscreenspidev] = settingsMap[spidev];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlConfig["GPIO"]) {
|
||||
settingsMap[user] = yamlConfig["GPIO"]["User"].as<int>(RADIOLIB_NC);
|
||||
}
|
||||
if (yamlConfig["GPS"]) {
|
||||
std::string serialPath = yamlConfig["GPS"]["SerialPath"].as<std::string>("");
|
||||
if (serialPath != "") {
|
||||
Serial1.setPath(serialPath);
|
||||
settingsMap[has_gps] = 1;
|
||||
}
|
||||
}
|
||||
if (yamlConfig["I2C"]) {
|
||||
settingsStrings[i2cdev] = yamlConfig["I2C"]["I2CDevice"].as<std::string>("");
|
||||
}
|
||||
settingsMap[displayPanel] = no_screen;
|
||||
if (yamlConfig["Display"]) {
|
||||
if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7789")
|
||||
settingsMap[displayPanel] = st7789;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735")
|
||||
settingsMap[displayPanel] = st7735;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735S")
|
||||
settingsMap[displayPanel] = st7735s;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7796")
|
||||
settingsMap[displayPanel] = st7796;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9341")
|
||||
settingsMap[displayPanel] = ili9341;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9342")
|
||||
settingsMap[displayPanel] = ili9342;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9488")
|
||||
settingsMap[displayPanel] = ili9488;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "HX8357D")
|
||||
settingsMap[displayPanel] = hx8357d;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "X11")
|
||||
settingsMap[displayPanel] = x11;
|
||||
settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as<int>(0);
|
||||
settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as<int>(0);
|
||||
settingsMap[displayDC] = yamlConfig["Display"]["DC"].as<int>(-1);
|
||||
settingsMap[displayCS] = yamlConfig["Display"]["CS"].as<int>(-1);
|
||||
settingsMap[displayRGBOrder] = yamlConfig["Display"]["RGBOrder"].as<bool>(false);
|
||||
settingsMap[displayBacklight] = yamlConfig["Display"]["Backlight"].as<int>(-1);
|
||||
settingsMap[displayBacklightInvert] = yamlConfig["Display"]["BacklightInvert"].as<bool>(false);
|
||||
settingsMap[displayBacklightPWMChannel] = yamlConfig["Display"]["BacklightPWMChannel"].as<int>(-1);
|
||||
settingsMap[displayReset] = yamlConfig["Display"]["Reset"].as<int>(-1);
|
||||
settingsMap[displayOffsetX] = yamlConfig["Display"]["OffsetX"].as<int>(0);
|
||||
settingsMap[displayOffsetY] = yamlConfig["Display"]["OffsetY"].as<int>(0);
|
||||
settingsMap[displayRotate] = yamlConfig["Display"]["Rotate"].as<bool>(false);
|
||||
settingsMap[displayOffsetRotate] = yamlConfig["Display"]["OffsetRotate"].as<int>(1);
|
||||
settingsMap[displayInvert] = yamlConfig["Display"]["Invert"].as<bool>(false);
|
||||
settingsMap[displayBusFrequency] = yamlConfig["Display"]["BusFrequency"].as<int>(40000000);
|
||||
if (yamlConfig["Display"]["spidev"]) {
|
||||
settingsStrings[displayspidev] = "/dev/" + yamlConfig["Display"]["spidev"].as<std::string>("spidev0.1");
|
||||
if (settingsStrings[displayspidev].length() == 14) {
|
||||
int x = settingsStrings[displayspidev].at(11) - '0';
|
||||
int y = settingsStrings[displayspidev].at(13) - '0';
|
||||
if (x >= 0 && x < 10 && y >= 0 && y < 10) {
|
||||
settingsMap[displayspidev] = x + y << 4;
|
||||
settingsMap[touchscreenspidev] = settingsMap[displayspidev];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
settingsMap[touchscreenModule] = no_touchscreen;
|
||||
if (yamlConfig["Touchscreen"]) {
|
||||
if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "XPT2046")
|
||||
settingsMap[touchscreenModule] = xpt2046;
|
||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "STMPE610")
|
||||
settingsMap[touchscreenModule] = stmpe610;
|
||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "GT911")
|
||||
settingsMap[touchscreenModule] = gt911;
|
||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "FT5x06")
|
||||
settingsMap[touchscreenModule] = ft5x06;
|
||||
settingsMap[touchscreenCS] = yamlConfig["Touchscreen"]["CS"].as<int>(-1);
|
||||
settingsMap[touchscreenIRQ] = yamlConfig["Touchscreen"]["IRQ"].as<int>(-1);
|
||||
settingsMap[touchscreenBusFrequency] = yamlConfig["Touchscreen"]["BusFrequency"].as<int>(1000000);
|
||||
settingsMap[touchscreenRotate] = yamlConfig["Touchscreen"]["Rotate"].as<int>(-1);
|
||||
settingsMap[touchscreenI2CAddr] = yamlConfig["Touchscreen"]["I2CAddr"].as<int>(-1);
|
||||
if (yamlConfig["Touchscreen"]["spidev"]) {
|
||||
settingsStrings[touchscreenspidev] = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as<std::string>("");
|
||||
if (settingsStrings[touchscreenspidev].length() == 14) {
|
||||
int x = settingsStrings[touchscreenspidev].at(11) - '0';
|
||||
int y = settingsStrings[touchscreenspidev].at(13) - '0';
|
||||
if (x >= 0 && x < 10 && y >= 0 && y < 10) {
|
||||
settingsMap[touchscreenspidev] = x + y << 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlConfig["Input"]) {
|
||||
settingsStrings[keyboardDevice] = (yamlConfig["Input"]["KeyboardDevice"]).as<std::string>("");
|
||||
}
|
||||
|
||||
if (yamlConfig["Webserver"]) {
|
||||
settingsMap[webserverport] = (yamlConfig["Webserver"]["Port"]).as<int>(-1);
|
||||
settingsStrings[webserverrootpath] = (yamlConfig["Webserver"]["RootPath"]).as<std::string>("");
|
||||
}
|
||||
|
||||
settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as<int>(200);
|
||||
settingsMap[maxtophone] = (yamlConfig["General"]["MaxMessageQueue"]).as<int>(100);
|
||||
|
||||
} catch (YAML::Exception &e) {
|
||||
std::cout << "*** Exception " << e.what() << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
gpioChipName += std::to_string(settingsMap[gpiochip]);
|
||||
|
||||
for (configNames i : GPIO_lines) {
|
||||
if (settingsMap.count(i) && settingsMap[i] > max_GPIO)
|
||||
@@ -402,4 +243,178 @@ int initGPIOPin(int pinNum, const std::string gpioChipName)
|
||||
#else
|
||||
return ERRNO_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool loadConfig(const char *configPath)
|
||||
{
|
||||
YAML::Node yamlConfig;
|
||||
try {
|
||||
yamlConfig = YAML::LoadFile(configPath);
|
||||
if (yamlConfig["Logging"]) {
|
||||
if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "trace") {
|
||||
settingsMap[logoutputlevel] = level_trace;
|
||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "debug") {
|
||||
settingsMap[logoutputlevel] = level_debug;
|
||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "info") {
|
||||
settingsMap[logoutputlevel] = level_info;
|
||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "warn") {
|
||||
settingsMap[logoutputlevel] = level_warn;
|
||||
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "error") {
|
||||
settingsMap[logoutputlevel] = level_error;
|
||||
}
|
||||
settingsStrings[traceFilename] = yamlConfig["Logging"]["TraceFile"].as<std::string>("");
|
||||
if (yamlConfig["Logging"]["AsciiLogs"]) {
|
||||
// Default is !isatty(1) but can be set explicitly in config.yaml
|
||||
settingsMap[ascii_logs] = yamlConfig["Logging"]["AsciiLogs"].as<bool>();
|
||||
}
|
||||
}
|
||||
if (yamlConfig["Lora"]) {
|
||||
settingsMap[use_sx1262] = false;
|
||||
settingsMap[use_rf95] = false;
|
||||
settingsMap[use_sx1280] = false;
|
||||
settingsMap[use_sx1268] = false;
|
||||
|
||||
if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1262") {
|
||||
settingsMap[use_sx1262] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "RF95") {
|
||||
settingsMap[use_rf95] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1280") {
|
||||
settingsMap[use_sx1280] = true;
|
||||
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1268") {
|
||||
settingsMap[use_sx1268] = true;
|
||||
}
|
||||
settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as<bool>(false);
|
||||
settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<bool>(false);
|
||||
settingsMap[cs] = yamlConfig["Lora"]["CS"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[irq] = yamlConfig["Lora"]["IRQ"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[busy] = yamlConfig["Lora"]["Busy"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[reset] = yamlConfig["Lora"]["Reset"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[txen] = yamlConfig["Lora"]["TXen"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[rxen] = yamlConfig["Lora"]["RXen"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[sx126x_ant_sw] = yamlConfig["Lora"]["SX126X_ANT_SW"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(0);
|
||||
settingsMap[ch341Quirk] = yamlConfig["Lora"]["ch341_quirk"].as<bool>(false);
|
||||
settingsMap[spiSpeed] = yamlConfig["Lora"]["spiSpeed"].as<int>(2000000);
|
||||
|
||||
settingsStrings[spidev] = "/dev/" + yamlConfig["Lora"]["spidev"].as<std::string>("spidev0.0");
|
||||
if (settingsStrings[spidev].length() == 14) {
|
||||
int x = settingsStrings[spidev].at(11) - '0';
|
||||
int y = settingsStrings[spidev].at(13) - '0';
|
||||
if (x >= 0 && x < 10 && y >= 0 && y < 10) {
|
||||
settingsMap[spidev] = x + y << 4;
|
||||
settingsMap[displayspidev] = settingsMap[spidev];
|
||||
settingsMap[touchscreenspidev] = settingsMap[spidev];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlConfig["GPIO"]) {
|
||||
settingsMap[user] = yamlConfig["GPIO"]["User"].as<int>(RADIOLIB_NC);
|
||||
}
|
||||
if (yamlConfig["GPS"]) {
|
||||
std::string serialPath = yamlConfig["GPS"]["SerialPath"].as<std::string>("");
|
||||
if (serialPath != "") {
|
||||
Serial1.setPath(serialPath);
|
||||
settingsMap[has_gps] = 1;
|
||||
}
|
||||
}
|
||||
if (yamlConfig["I2C"]) {
|
||||
settingsStrings[i2cdev] = yamlConfig["I2C"]["I2CDevice"].as<std::string>("");
|
||||
}
|
||||
if (yamlConfig["Display"]) {
|
||||
if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7789")
|
||||
settingsMap[displayPanel] = st7789;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735")
|
||||
settingsMap[displayPanel] = st7735;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735S")
|
||||
settingsMap[displayPanel] = st7735s;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7796")
|
||||
settingsMap[displayPanel] = st7796;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9341")
|
||||
settingsMap[displayPanel] = ili9341;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9342")
|
||||
settingsMap[displayPanel] = ili9342;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9488")
|
||||
settingsMap[displayPanel] = ili9488;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "HX8357D")
|
||||
settingsMap[displayPanel] = hx8357d;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "X11")
|
||||
settingsMap[displayPanel] = x11;
|
||||
settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as<int>(0);
|
||||
settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as<int>(0);
|
||||
settingsMap[displayDC] = yamlConfig["Display"]["DC"].as<int>(-1);
|
||||
settingsMap[displayCS] = yamlConfig["Display"]["CS"].as<int>(-1);
|
||||
settingsMap[displayRGBOrder] = yamlConfig["Display"]["RGBOrder"].as<bool>(false);
|
||||
settingsMap[displayBacklight] = yamlConfig["Display"]["Backlight"].as<int>(-1);
|
||||
settingsMap[displayBacklightInvert] = yamlConfig["Display"]["BacklightInvert"].as<bool>(false);
|
||||
settingsMap[displayBacklightPWMChannel] = yamlConfig["Display"]["BacklightPWMChannel"].as<int>(-1);
|
||||
settingsMap[displayReset] = yamlConfig["Display"]["Reset"].as<int>(-1);
|
||||
settingsMap[displayOffsetX] = yamlConfig["Display"]["OffsetX"].as<int>(0);
|
||||
settingsMap[displayOffsetY] = yamlConfig["Display"]["OffsetY"].as<int>(0);
|
||||
settingsMap[displayRotate] = yamlConfig["Display"]["Rotate"].as<bool>(false);
|
||||
settingsMap[displayOffsetRotate] = yamlConfig["Display"]["OffsetRotate"].as<int>(1);
|
||||
settingsMap[displayInvert] = yamlConfig["Display"]["Invert"].as<bool>(false);
|
||||
settingsMap[displayBusFrequency] = yamlConfig["Display"]["BusFrequency"].as<int>(40000000);
|
||||
if (yamlConfig["Display"]["spidev"]) {
|
||||
settingsStrings[displayspidev] = "/dev/" + yamlConfig["Display"]["spidev"].as<std::string>("spidev0.1");
|
||||
if (settingsStrings[displayspidev].length() == 14) {
|
||||
int x = settingsStrings[displayspidev].at(11) - '0';
|
||||
int y = settingsStrings[displayspidev].at(13) - '0';
|
||||
if (x >= 0 && x < 10 && y >= 0 && y < 10) {
|
||||
settingsMap[displayspidev] = x + y << 4;
|
||||
settingsMap[touchscreenspidev] = settingsMap[displayspidev];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlConfig["Touchscreen"]) {
|
||||
if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "XPT2046")
|
||||
settingsMap[touchscreenModule] = xpt2046;
|
||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "STMPE610")
|
||||
settingsMap[touchscreenModule] = stmpe610;
|
||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "GT911")
|
||||
settingsMap[touchscreenModule] = gt911;
|
||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "FT5x06")
|
||||
settingsMap[touchscreenModule] = ft5x06;
|
||||
settingsMap[touchscreenCS] = yamlConfig["Touchscreen"]["CS"].as<int>(-1);
|
||||
settingsMap[touchscreenIRQ] = yamlConfig["Touchscreen"]["IRQ"].as<int>(-1);
|
||||
settingsMap[touchscreenBusFrequency] = yamlConfig["Touchscreen"]["BusFrequency"].as<int>(1000000);
|
||||
settingsMap[touchscreenRotate] = yamlConfig["Touchscreen"]["Rotate"].as<int>(-1);
|
||||
settingsMap[touchscreenI2CAddr] = yamlConfig["Touchscreen"]["I2CAddr"].as<int>(-1);
|
||||
if (yamlConfig["Touchscreen"]["spidev"]) {
|
||||
settingsStrings[touchscreenspidev] = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as<std::string>("");
|
||||
if (settingsStrings[touchscreenspidev].length() == 14) {
|
||||
int x = settingsStrings[touchscreenspidev].at(11) - '0';
|
||||
int y = settingsStrings[touchscreenspidev].at(13) - '0';
|
||||
if (x >= 0 && x < 10 && y >= 0 && y < 10) {
|
||||
settingsMap[touchscreenspidev] = x + y << 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yamlConfig["Input"]) {
|
||||
settingsStrings[keyboardDevice] = (yamlConfig["Input"]["KeyboardDevice"]).as<std::string>("");
|
||||
}
|
||||
|
||||
if (yamlConfig["Webserver"]) {
|
||||
settingsMap[webserverport] = (yamlConfig["Webserver"]["Port"]).as<int>(-1);
|
||||
settingsStrings[webserverrootpath] = (yamlConfig["Webserver"]["RootPath"]).as<std::string>("");
|
||||
}
|
||||
|
||||
if (yamlConfig["General"]) {
|
||||
settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as<int>(200);
|
||||
settingsMap[maxtophone] = (yamlConfig["General"]["MaxMessageQueue"]).as<int>(100);
|
||||
settingsStrings[config_directory] = (yamlConfig["General"]["ConfigDirectory"]).as<std::string>("");
|
||||
}
|
||||
|
||||
} catch (YAML::Exception &e) {
|
||||
std::cout << "*** Exception " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/874134/find-out-if-string-ends-with-another-string-in-c
|
||||
static bool ends_with(std::string_view str, std::string_view suffix)
|
||||
{
|
||||
return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
|
||||
}
|
||||
@@ -55,7 +55,8 @@ enum configNames {
|
||||
webserverrootpath,
|
||||
maxtophone,
|
||||
maxnodes,
|
||||
ascii_logs
|
||||
ascii_logs,
|
||||
config_directory
|
||||
};
|
||||
enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9488, hx8357d };
|
||||
enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 };
|
||||
@@ -64,4 +65,6 @@ enum { level_error, level_warn, level_info, level_debug, level_trace };
|
||||
extern std::map<configNames, int> settingsMap;
|
||||
extern std::map<configNames, std::string> settingsStrings;
|
||||
extern std::ofstream traceFile;
|
||||
int initGPIOPin(int pinNum, std::string gpioChipname);
|
||||
int initGPIOPin(int pinNum, std::string gpioChipname);
|
||||
bool loadConfig(const char *configPath);
|
||||
static bool ends_with(std::string_view str, std::string_view suffix);
|
||||
Reference in New Issue
Block a user