mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-14 09:02:14 +00:00
Merge branch 'develop' of github.com:meshtastic/firmware into xmodem-proto
This commit is contained in:
commit
80d1a993dd
@ -8,7 +8,7 @@ build_flags =
|
||||
${arduino_base.build_flags} -Wno-unused-variable
|
||||
-Isrc/platform/nrf52
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040> -<mesh/eth/>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040> -<mesh/eth/>
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
|
||||
|
@ -12,7 +12,7 @@ build_flags =
|
||||
-D__PLAT_RP2040__
|
||||
# -D _POSIX_THREADS
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/>
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
lib_deps =
|
||||
|
@ -10,7 +10,7 @@ build_flags =
|
||||
# Arduino/PlatformIO framework-arduinoststm32 package does not presently have SUBGHZSPI support
|
||||
# -DPIN_SPI_MOSI=PINSUBGHZSPIMOSI -DPIN_SPI_MISO=PINSUBGHZSPIMISO -DPIN_SPI_SCK=PINSUBGHZSPISCK
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 3b0d871ca1e0f8a2ed823f0696e2d7cf31ed2ebd
|
||||
Subproject commit e00b5ba7d06053d820f1123351881fc4fa9270d1
|
@ -3,7 +3,6 @@
|
||||
#include "RTC.h"
|
||||
#include "NodeDB.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
// #include "wifi/WiFiServerAPI.h"
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
@ -27,10 +26,6 @@ size_t RedirectablePrint::write(uint8_t c)
|
||||
SEGGER_RTT_PutChar(SEGGER_STDOUT_CH, c);
|
||||
#endif
|
||||
|
||||
// FIXME - clean this up, the whole relationship of this class to SerialConsole to TCP/bluetooth debug log output is kinda messed up. But for now, just have this hack to
|
||||
// optionally send chars to TCP also
|
||||
//WiFiServerPort::debugOut(c);
|
||||
|
||||
if (!config.has_lora || config.device.serial_enabled)
|
||||
dest->write(c);
|
||||
|
||||
@ -108,3 +103,31 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16_t len) {
|
||||
const char alphabet[17] = "0123456789abcdef";
|
||||
log(logLevel, " +------------------------------------------------+ +----------------+\n");
|
||||
log(logLevel, " |.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .a .b .c .d .e .f | | ASCII |\n");
|
||||
for (uint16_t i = 0; i < len; i += 16) {
|
||||
if (i % 128 == 0)
|
||||
log(logLevel, " +------------------------------------------------+ +----------------+\n");
|
||||
char s[] = "| | | |\n";
|
||||
uint8_t ix = 1, iy = 52;
|
||||
for (uint8_t j = 0; j < 16; j++) {
|
||||
if (i + j < len) {
|
||||
uint8_t c = buf[i + j];
|
||||
s[ix++] = alphabet[(c >> 4) & 0x0F];
|
||||
s[ix++] = alphabet[c & 0x0F];
|
||||
ix++;
|
||||
if (c > 31 && c < 128) s[iy++] = c;
|
||||
else s[iy++] = '.';
|
||||
}
|
||||
}
|
||||
uint8_t index = i / 16;
|
||||
if (i < 256) log(logLevel, " ");
|
||||
log(logLevel, "%02x",index);
|
||||
log(logLevel, ".");
|
||||
log(logLevel, s);
|
||||
}
|
||||
log(logLevel, " +------------------------------------------------+ +----------------+\n");
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ class RedirectablePrint : public Print
|
||||
|
||||
/** like printf but va_list based */
|
||||
size_t vprintf(const char *format, va_list arg);
|
||||
|
||||
void hexDump(const char *logLevel, unsigned char *buf, uint16_t len);
|
||||
};
|
||||
|
||||
class NoopPrint : public Print
|
||||
|
@ -117,6 +117,31 @@ float AirTime::utilizationTXPercent()
|
||||
return (float(sum) / float(MS_IN_HOUR)) * 100;
|
||||
}
|
||||
|
||||
bool AirTime::isTxAllowedChannelUtil(bool polite)
|
||||
{
|
||||
uint8_t percentage = (polite ? polite_channel_util_percent : max_channel_util_percent);
|
||||
if (channelUtilizationPercent() < percentage) {
|
||||
return true;
|
||||
} else {
|
||||
LOG_WARN("Channel utilization is >%d percent. Skipping this opportunity to send.\n", percentage);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool AirTime::isTxAllowedAirUtil()
|
||||
{
|
||||
if (!config.lora.override_duty_cycle && myRegion->dutyCycle < 100) {
|
||||
if (utilizationTXPercent() < polite_tx_util_percent) {
|
||||
return true;
|
||||
} else {
|
||||
LOG_WARN("Tx air utilization is >%d percent. Skipping this opportunity to send.\n", polite_tx_util_percent);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the amount of minutes we have to be silent before we can send again
|
||||
uint8_t AirTime::getSilentMinutes(float txPercent, float dutyCycle)
|
||||
{
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
#include <functional>
|
||||
#include "MeshRadio.h"
|
||||
|
||||
/*
|
||||
TX_LOG - Time on air this device has transmitted
|
||||
@ -59,12 +60,17 @@ class AirTime : private concurrency::OSThread
|
||||
uint32_t getSecondsSinceBoot();
|
||||
uint32_t *airtimeReport(reportTypes reportType);
|
||||
uint8_t getSilentMinutes(float txPercent, float dutyCycle);
|
||||
bool isTxAllowedChannelUtil(bool polite=false);
|
||||
bool isTxAllowedAirUtil();
|
||||
|
||||
private:
|
||||
bool firstTime = true;
|
||||
uint8_t lastUtilPeriod = 0;
|
||||
uint8_t lastUtilPeriodTX = 0;
|
||||
uint32_t secSinceBoot = 0;
|
||||
uint8_t max_channel_util_percent = 40;
|
||||
uint8_t polite_channel_util_percent = 25;
|
||||
uint8_t polite_tx_util_percent = 5;
|
||||
|
||||
struct airtimeStruct {
|
||||
uint32_t periodTX[PERIODS_TO_LOG]; // AirTime transmitted
|
||||
|
@ -36,12 +36,12 @@
|
||||
#endif
|
||||
|
||||
#if HAS_WIFI
|
||||
#include "mesh/wifi/WiFiServerAPI.h"
|
||||
#include "mesh/api/WiFiServerAPI.h"
|
||||
#include "mqtt/MQTT.h"
|
||||
#endif
|
||||
|
||||
#if HAS_ETHERNET
|
||||
#include "mesh/eth/ethServerAPI.h"
|
||||
#include "mesh/api/ethServerAPI.h"
|
||||
#include "mqtt/MQTT.h"
|
||||
#endif
|
||||
|
||||
@ -239,7 +239,7 @@ void setup()
|
||||
#ifdef RAK4630
|
||||
// We need to enable 3.3V periphery in order to scan it
|
||||
pinMode(PIN_3V3_EN, OUTPUT);
|
||||
digitalWrite(PIN_3V3_EN, 1);
|
||||
digitalWrite(PIN_3V3_EN, HIGH);
|
||||
#endif
|
||||
|
||||
// Currently only the tbeam has a PMU
|
||||
|
@ -210,7 +210,7 @@ Channel &Channels::getByIndex(ChannelIndex chIndex)
|
||||
Channel &Channels::getByName(const char* chName)
|
||||
{
|
||||
for (ChannelIndex i = 0; i < getNumChannels(); i++) {
|
||||
if (strcasecmp(channelFile.channels[i].settings.name, chName) == 0) {
|
||||
if (strcasecmp(getGlobalId(i), chName) == 0) {
|
||||
return channelFile.channels[i];
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,23 @@
|
||||
#include "SX126xInterface.cpp"
|
||||
#include "SX128xInterface.h"
|
||||
#include "SX128xInterface.cpp"
|
||||
#include "api/ServerAPI.h"
|
||||
#include "api/ServerAPI.cpp"
|
||||
|
||||
// We need this declaration for proper linking in derived classes
|
||||
template class SX126xInterface<SX1262>;
|
||||
template class SX126xInterface<SX1268>;
|
||||
template class SX126xInterface<LLCC68>;
|
||||
template class SX128xInterface<SX1280>;
|
||||
|
||||
#if HAS_ETHERNET
|
||||
#include "api/ethServerAPI.h"
|
||||
template class ServerAPI<EthernetClient>;
|
||||
template class APIServerPort<ethServerAPI, EthernetServer>;
|
||||
#endif
|
||||
|
||||
#if HAS_WIFI
|
||||
#include "api/WiFiServerAPI.h"
|
||||
template class ServerAPI<WiFiClient>;
|
||||
template class APIServerPort<WiFiServerAPI, WiFiServer>;
|
||||
#endif
|
@ -280,8 +280,7 @@ NodeInfo *MeshService::refreshMyNodeInfo()
|
||||
node->last_heard =
|
||||
getValidTime(RTCQualityFromNet); // This nodedb timestamp might be stale, so update it if our clock is kinda valid
|
||||
|
||||
// For the time in the position field, only set that if we have a real GPS clock
|
||||
position.time = getValidTime(RTCQualityGPS);
|
||||
position.time = getValidTime(RTCQualityFromNet);
|
||||
|
||||
updateBatteryLevel(powerStatus->getBatteryChargePercent());
|
||||
|
||||
@ -327,4 +326,4 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
|
||||
bool MeshService::isToPhoneQueueEmpty()
|
||||
{
|
||||
return toPhoneQueue.isEmpty();
|
||||
}
|
||||
}
|
||||
|
@ -89,9 +89,6 @@ class PhoneAPI : public Observer<uint32_t> // FIXME, we shouldn't be inheriting
|
||||
|
||||
void setInitialState() { state = STATE_SEND_MY_INFO; }
|
||||
|
||||
/// emit a debugging log character, FIXME - implement
|
||||
void debugOut(char c) { }
|
||||
|
||||
protected:
|
||||
/// Our fromradio packet while it is being assembled
|
||||
FromRadio fromRadioScratch = {};
|
||||
|
@ -138,7 +138,7 @@ void Router::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom, ChannelI
|
||||
void Router::abortSendAndNak(Routing_Error err, MeshPacket *p)
|
||||
{
|
||||
LOG_ERROR("Error=%d, returning NAK and dropping packet.\n", err);
|
||||
sendAckNak(Routing_Error_NO_INTERFACE, getFrom(p), p->id, p->channel);
|
||||
sendAckNak(err, getFrom(p), p->id, p->channel);
|
||||
packetPool.release(p);
|
||||
}
|
||||
|
||||
@ -199,15 +199,19 @@ ErrorCode Router::send(MeshPacket *p)
|
||||
} // should have already been handled by sendLocal
|
||||
|
||||
// Abort sending if we are violating the duty cycle
|
||||
if (!config.lora.override_duty_cycle && myRegion->dutyCycle != 100) {
|
||||
float hourlyTxPercent = airTime->utilizationTXPercent();
|
||||
if (hourlyTxPercent > myRegion->dutyCycle) {
|
||||
uint8_t silentMinutes = airTime->getSilentMinutes(hourlyTxPercent, myRegion->dutyCycle);
|
||||
LOG_WARN("Duty cycle limit exceeded. Aborting send for now, you can send again in %d minutes.\n", silentMinutes);
|
||||
Routing_Error err = Routing_Error_DUTY_CYCLE_LIMIT;
|
||||
abortSendAndNak(err, p);
|
||||
return err;
|
||||
}
|
||||
if (!config.lora.override_duty_cycle && myRegion->dutyCycle < 100) {
|
||||
float hourlyTxPercent = airTime->utilizationTXPercent();
|
||||
if (hourlyTxPercent > myRegion->dutyCycle) {
|
||||
uint8_t silentMinutes = airTime->getSilentMinutes(hourlyTxPercent, myRegion->dutyCycle);
|
||||
LOG_WARN("Duty cycle limit exceeded. Aborting send for now, you can send again in %d minutes.\n", silentMinutes);
|
||||
Routing_Error err = Routing_Error_DUTY_CYCLE_LIMIT;
|
||||
if (getFrom(p) == nodeDB.getNodeNum()) { // only send NAK to API, not to the mesh
|
||||
abortSendAndNak(err, p);
|
||||
} else {
|
||||
packetPool.release(p);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0;
|
||||
|
@ -70,7 +70,7 @@ bool SX126xInterface<T>::init()
|
||||
#if defined(SX126X_TXEN) && (SX126X_TXEN != RADIOLIB_NC)
|
||||
// lora.begin sets Dio2 as RF switch control, which is not true if we are manually controlling RX and TX
|
||||
if (res == RADIOLIB_ERR_NONE)
|
||||
res = lora.setDio2AsRfSwitch(false);
|
||||
res = lora.setDio2AsRfSwitch(true);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
@ -18,9 +18,6 @@ class SinglePortModule : public MeshModule
|
||||
SinglePortModule(const char *_name, PortNum _ourPortNum) : MeshModule(_name), ourPortNum(_ourPortNum) {}
|
||||
|
||||
protected:
|
||||
uint32_t max_channel_util_percent = 40;
|
||||
uint32_t polite_channel_util_percent = 25;
|
||||
|
||||
/**
|
||||
* @return true if you want to receive the specified portnum
|
||||
*/
|
||||
|
67
src/mesh/api/ServerAPI.cpp
Normal file
67
src/mesh/api/ServerAPI.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include "ServerAPI.h"
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
template<typename T>
|
||||
ServerAPI<T>::ServerAPI(T &_client) : StreamAPI(&client), concurrency::OSThread("ServerAPI"), client(_client)
|
||||
{
|
||||
LOG_INFO("Incoming wifi connection\n");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ServerAPI<T>::~ServerAPI()
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ServerAPI<T>::close()
|
||||
{
|
||||
client.stop(); // drop tcp connection
|
||||
StreamAPI::close();
|
||||
}
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
template<typename T>
|
||||
bool ServerAPI<T>::checkIsConnected()
|
||||
{
|
||||
return client.connected();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int32_t ServerAPI<T>::runOnce()
|
||||
{
|
||||
if (client.connected()) {
|
||||
return StreamAPI::runOncePart();
|
||||
} else {
|
||||
LOG_INFO("Client dropped connection, suspending API service\n");
|
||||
enabled = false; // we no longer need to run
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
APIServerPort<T, U>::APIServerPort(int port) : U(port), concurrency::OSThread("ApiServer") {}
|
||||
|
||||
template<class T, class U>
|
||||
void APIServerPort<T, U>::init()
|
||||
{
|
||||
U::begin();
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
int32_t APIServerPort<T, U>::runOnce()
|
||||
{
|
||||
auto client = U::available();
|
||||
if (client) {
|
||||
// Close any previous connection (see FIXME in header file)
|
||||
if (openAPI) {
|
||||
LOG_INFO("Force closing previous TCP connection\n");
|
||||
delete openAPI;
|
||||
}
|
||||
|
||||
openAPI = new T(client);
|
||||
}
|
||||
|
||||
return 100; // only check occasionally for incoming connections
|
||||
}
|
@ -1,21 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "StreamAPI.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
/**
|
||||
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
||||
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
||||
*/
|
||||
class WiFiServerAPI : public StreamAPI, private concurrency::OSThread
|
||||
template<class T>
|
||||
class ServerAPI : public StreamAPI, private concurrency::OSThread
|
||||
{
|
||||
private:
|
||||
WiFiClient client;
|
||||
T client;
|
||||
|
||||
public:
|
||||
explicit WiFiServerAPI(WiFiClient &_client);
|
||||
explicit ServerAPI(T &_client);
|
||||
|
||||
virtual ~WiFiServerAPI();
|
||||
virtual ~ServerAPI();
|
||||
|
||||
/// override close to also shutdown the TCP link
|
||||
virtual void close();
|
||||
@ -34,25 +34,21 @@ class WiFiServerAPI : public StreamAPI, private concurrency::OSThread
|
||||
/**
|
||||
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
|
||||
*/
|
||||
class WiFiServerPort : public WiFiServer, private concurrency::OSThread
|
||||
template<class T, class U>
|
||||
class APIServerPort : public U, private concurrency::OSThread
|
||||
{
|
||||
/** The currently open port
|
||||
*
|
||||
* FIXME: We currently only allow one open TCP connection at a time, because we depend on the loop() call in this class to
|
||||
* delegate to the worker. Once coroutines are implemented we can relax this restriction.
|
||||
*/
|
||||
WiFiServerAPI *openAPI = NULL;
|
||||
T *openAPI = NULL;
|
||||
|
||||
public:
|
||||
explicit WiFiServerPort(int port);
|
||||
explicit APIServerPort(int port);
|
||||
|
||||
void init();
|
||||
|
||||
/// If an api server is running, we try to spit out debug 'serial' characters there
|
||||
static void debugOut(char c);
|
||||
|
||||
protected:
|
||||
int32_t runOnce() override;
|
||||
};
|
||||
|
||||
void initApiServer(int port=4403);
|
25
src/mesh/api/WiFiServerAPI.cpp
Normal file
25
src/mesh/api/WiFiServerAPI.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
#if HAS_WIFI
|
||||
#include "WiFiServerAPI.h"
|
||||
|
||||
static WiFiServerPort *apiPort;
|
||||
|
||||
void initApiServer(int port)
|
||||
{
|
||||
// Start API server on port 4403
|
||||
if (!apiPort) {
|
||||
apiPort = new WiFiServerPort(port);
|
||||
LOG_INFO("API server listening on TCP port %d\n", port);
|
||||
apiPort->init();
|
||||
}
|
||||
}
|
||||
|
||||
WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : ServerAPI(_client)
|
||||
{
|
||||
LOG_INFO("Incoming wifi connection\n");
|
||||
}
|
||||
|
||||
WiFiServerPort::WiFiServerPort(int port) : APIServerPort(port) {}
|
||||
#endif
|
25
src/mesh/api/WiFiServerAPI.h
Normal file
25
src/mesh/api/WiFiServerAPI.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "ServerAPI.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
/**
|
||||
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
||||
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
||||
*/
|
||||
class WiFiServerAPI : public ServerAPI<WiFiClient>
|
||||
{
|
||||
public:
|
||||
explicit WiFiServerAPI(WiFiClient &_client);
|
||||
};
|
||||
|
||||
/**
|
||||
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
|
||||
*/
|
||||
class WiFiServerPort : public APIServerPort<WiFiServerAPI, WiFiServer>
|
||||
{
|
||||
public:
|
||||
explicit WiFiServerPort(int port);
|
||||
};
|
||||
|
||||
void initApiServer(int port=4403);
|
27
src/mesh/api/ethServerAPI.cpp
Normal file
27
src/mesh/api/ethServerAPI.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
#if HAS_ETHERNET
|
||||
|
||||
#include "ethServerAPI.h"
|
||||
|
||||
static ethServerPort *apiPort;
|
||||
|
||||
void initApiServer(int port)
|
||||
{
|
||||
// Start API server on port 4403
|
||||
if (!apiPort) {
|
||||
apiPort = new ethServerPort(port);
|
||||
LOG_INFO("API server listening on TCP port %d\n", port);
|
||||
apiPort->init();
|
||||
}
|
||||
}
|
||||
|
||||
ethServerAPI::ethServerAPI(EthernetClient &_client) : ServerAPI(_client)
|
||||
{
|
||||
LOG_INFO("Incoming ethernet connection\n");
|
||||
}
|
||||
|
||||
ethServerPort::ethServerPort(int port) : APIServerPort(port) {}
|
||||
|
||||
#endif
|
25
src/mesh/api/ethServerAPI.h
Normal file
25
src/mesh/api/ethServerAPI.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "ServerAPI.h"
|
||||
#include <RAK13800_W5100S.h>
|
||||
|
||||
/**
|
||||
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
||||
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
||||
*/
|
||||
class ethServerAPI : public ServerAPI<EthernetClient>
|
||||
{
|
||||
public:
|
||||
explicit ethServerAPI(EthernetClient &_client);
|
||||
};
|
||||
|
||||
/**
|
||||
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
|
||||
*/
|
||||
class ethServerPort : public APIServerPort<ethServerAPI, EthernetServer>
|
||||
{
|
||||
public:
|
||||
explicit ethServerPort(int port);
|
||||
};
|
||||
|
||||
void initApiServer(int port=4403);
|
@ -5,7 +5,7 @@
|
||||
#include <SPI.h>
|
||||
#include <RAK13800_W5100S.h>
|
||||
#include "target_specific.h"
|
||||
#include "mesh/eth/ethServerAPI.h"
|
||||
#include "mesh/api/ethServerAPI.h"
|
||||
#include "mqtt/MQTT.h"
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
|
@ -1,82 +0,0 @@
|
||||
#include "ethServerAPI.h"
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
static ethServerPort *apiPort;
|
||||
|
||||
void initApiServer(int port)
|
||||
{
|
||||
// Start API server on port 4403
|
||||
if (!apiPort) {
|
||||
apiPort = new ethServerPort(port);
|
||||
LOG_INFO("API server listening on TCP port %d\n", port);
|
||||
apiPort->init();
|
||||
}
|
||||
}
|
||||
|
||||
ethServerAPI::ethServerAPI(EthernetClient &_client) : StreamAPI(&client), concurrency::OSThread("ethServerAPI"), client(_client)
|
||||
{
|
||||
LOG_INFO("Incoming ethernet connection\n");
|
||||
}
|
||||
|
||||
ethServerAPI::~ethServerAPI()
|
||||
{
|
||||
client.stop();
|
||||
|
||||
// FIXME - delete this if the client dropps the connection!
|
||||
}
|
||||
|
||||
/// override close to also shutdown the TCP link
|
||||
void ethServerAPI::close()
|
||||
{
|
||||
client.stop(); // drop tcp connection
|
||||
StreamAPI::close();
|
||||
}
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
bool ethServerAPI::checkIsConnected()
|
||||
{
|
||||
return client.connected();
|
||||
}
|
||||
|
||||
int32_t ethServerAPI::runOnce()
|
||||
{
|
||||
if (client.connected()) {
|
||||
return StreamAPI::runOncePart();
|
||||
} else {
|
||||
LOG_INFO("Client dropped connection, suspending API service\n");
|
||||
enabled = false; // we no longer need to run
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// If an api server is running, we try to spit out debug 'serial' characters there
|
||||
void ethServerPort::debugOut(char c)
|
||||
{
|
||||
if (apiPort && apiPort->openAPI)
|
||||
apiPort->openAPI->debugOut(c);
|
||||
}
|
||||
|
||||
|
||||
ethServerPort::ethServerPort(int port) : EthernetServer(port), concurrency::OSThread("ApiServer") {}
|
||||
|
||||
void ethServerPort::init()
|
||||
{
|
||||
begin();
|
||||
}
|
||||
|
||||
int32_t ethServerPort::runOnce()
|
||||
{
|
||||
auto client = available();
|
||||
if (client) {
|
||||
// Close any previous connection (see FIXME in header file)
|
||||
if (openAPI) {
|
||||
LOG_WARN("Force closing previous TCP connection\n");
|
||||
delete openAPI;
|
||||
}
|
||||
|
||||
openAPI = new ethServerAPI(client);
|
||||
}
|
||||
|
||||
return 100; // only check occasionally for incoming connections
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "StreamAPI.h"
|
||||
#include <RAK13800_W5100S.h>
|
||||
|
||||
/**
|
||||
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
||||
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
||||
*/
|
||||
class ethServerAPI : public StreamAPI, private concurrency::OSThread
|
||||
{
|
||||
private:
|
||||
EthernetClient client;
|
||||
|
||||
public:
|
||||
explicit ethServerAPI(EthernetClient &_client);
|
||||
|
||||
virtual ~ethServerAPI();
|
||||
|
||||
/// override close to also shutdown the TCP link
|
||||
virtual void close();
|
||||
|
||||
protected:
|
||||
/// We override this method to prevent publishing EVENT_SERIAL_CONNECTED/DISCONNECTED for wifi links (we want the board to
|
||||
/// stay in the POWERED state to prevent disabling wifi)
|
||||
virtual void onConnectionChanged(bool connected) override {}
|
||||
|
||||
virtual int32_t runOnce() override; // Check for dropped client connections
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
virtual bool checkIsConnected() override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
|
||||
*/
|
||||
class ethServerPort : public EthernetServer, private concurrency::OSThread
|
||||
{
|
||||
/** The currently open port
|
||||
*
|
||||
* FIXME: We currently only allow one open TCP connection at a time, because we depend on the loop() call in this class to
|
||||
* delegate to the worker. Once coroutines are implemented we can relax this restriction.
|
||||
*/
|
||||
ethServerAPI *openAPI = NULL;
|
||||
|
||||
public:
|
||||
explicit ethServerPort(int port);
|
||||
|
||||
void init();
|
||||
|
||||
/// If an api server is running, we try to spit out debug 'serial' characters there
|
||||
static void debugOut(char c);
|
||||
|
||||
protected:
|
||||
int32_t runOnce() override;
|
||||
};
|
||||
|
||||
void initApiServer(int port=4403);
|
@ -157,7 +157,7 @@ extern const pb_msgdesc_t LocalModuleConfig_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define LocalConfig_size 391
|
||||
#define LocalModuleConfig_size 380
|
||||
#define LocalModuleConfig_size 412
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@ -85,6 +85,8 @@ typedef enum _HardwareModel {
|
||||
HardwareModel_HELTEC_V3 = 43,
|
||||
/* New Heltec Wireless Stick Lite with ESP32-S3 CPU */
|
||||
HardwareModel_HELTEC_WSL_V3 = 44,
|
||||
/* New BETAFPV ELRS Micro TX Module 2.4G with ESP32 CPU */
|
||||
HardwareModel_BETAFPV_2400_TX = 45,
|
||||
/* Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. */
|
||||
HardwareModel_PRIVATE_HW = 255
|
||||
} HardwareModel;
|
||||
@ -440,9 +442,10 @@ typedef struct _Waypoint {
|
||||
bool locked;
|
||||
/* Name of the waypoint - max 30 chars */
|
||||
char name[30];
|
||||
/* *
|
||||
Description of the waypoint - max 100 chars */
|
||||
/* Description of the waypoint - max 100 chars */
|
||||
char description[100];
|
||||
/* Designator icon for the waypoint in the form of a unicode emoji */
|
||||
uint32_t icon;
|
||||
} Waypoint;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t;
|
||||
@ -783,7 +786,7 @@ extern "C" {
|
||||
#define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define Routing_init_default {0, {RouteDiscovery_init_default}}
|
||||
#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
|
||||
#define Waypoint_init_default {0, 0, 0, 0, 0, "", ""}
|
||||
#define Waypoint_init_default {0, 0, 0, 0, 0, "", "", 0}
|
||||
#define MeshPacket_init_default {0, 0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN}
|
||||
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0, false, DeviceMetrics_init_default}
|
||||
#define MyNodeInfo_init_default {0, 0, 0, "", _CriticalErrorCode_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}
|
||||
@ -797,7 +800,7 @@ extern "C" {
|
||||
#define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define Routing_init_zero {0, {RouteDiscovery_init_zero}}
|
||||
#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
|
||||
#define Waypoint_init_zero {0, 0, 0, 0, 0, "", ""}
|
||||
#define Waypoint_init_zero {0, 0, 0, 0, 0, "", "", 0}
|
||||
#define MeshPacket_init_zero {0, 0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN}
|
||||
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0, false, DeviceMetrics_init_zero}
|
||||
#define MyNodeInfo_init_zero {0, 0, 0, "", _CriticalErrorCode_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}
|
||||
@ -855,6 +858,7 @@ extern "C" {
|
||||
#define Waypoint_locked_tag 5
|
||||
#define Waypoint_name_tag 6
|
||||
#define Waypoint_description_tag 7
|
||||
#define Waypoint_icon_tag 8
|
||||
#define MeshPacket_from_tag 1
|
||||
#define MeshPacket_to_tag 2
|
||||
#define MeshPacket_channel_tag 3
|
||||
@ -987,7 +991,8 @@ X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, expire, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, locked, 5) \
|
||||
X(a, STATIC, SINGULAR, STRING, name, 6) \
|
||||
X(a, STATIC, SINGULAR, STRING, description, 7)
|
||||
X(a, STATIC, SINGULAR, STRING, description, 7) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, icon, 8)
|
||||
#define Waypoint_CALLBACK NULL
|
||||
#define Waypoint_DEFAULT NULL
|
||||
|
||||
@ -1144,7 +1149,7 @@ extern const pb_msgdesc_t Compressed_msg;
|
||||
#define Routing_size 42
|
||||
#define ToRadio_size 324
|
||||
#define User_size 77
|
||||
#define Waypoint_size 156
|
||||
#define Waypoint_size 161
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@ -80,7 +80,7 @@ typedef struct _ModuleConfig_MQTTConfig {
|
||||
bool enabled;
|
||||
/* The server to use for our MQTT global message gateway feature.
|
||||
If not set, the default server will be used */
|
||||
char address[32];
|
||||
char address[64];
|
||||
/* MQTT username to use (most useful for a custom MQTT server).
|
||||
If using a custom server, this will be honoured even if empty.
|
||||
If using the default server, this will only be honoured if set, otherwise the device will use the default username */
|
||||
@ -553,13 +553,13 @@ extern const pb_msgdesc_t ModuleConfig_CannedMessageConfig_msg;
|
||||
#define ModuleConfig_AudioConfig_size 19
|
||||
#define ModuleConfig_CannedMessageConfig_size 49
|
||||
#define ModuleConfig_ExternalNotificationConfig_size 40
|
||||
#define ModuleConfig_MQTTConfig_size 169
|
||||
#define ModuleConfig_MQTTConfig_size 201
|
||||
#define ModuleConfig_RangeTestConfig_size 10
|
||||
#define ModuleConfig_RemoteHardwareConfig_size 2
|
||||
#define ModuleConfig_SerialConfig_size 26
|
||||
#define ModuleConfig_StoreForwardConfig_size 22
|
||||
#define ModuleConfig_TelemetryConfig_size 18
|
||||
#define ModuleConfig_size 172
|
||||
#define ModuleConfig_size 204
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "mesh/wifi/WiFiServerAPI.h"
|
||||
#include "mesh/api/WiFiServerAPI.h"
|
||||
#include "mqtt/MQTT.h"
|
||||
#include "target_specific.h"
|
||||
#include <ESPmDNS.h>
|
||||
@ -55,11 +55,13 @@ static int32_t reconnectWiFi()
|
||||
|
||||
// Make sure we clear old connection credentials
|
||||
WiFi.disconnect(false, true);
|
||||
|
||||
LOG_INFO("Reconnecting to WiFi access point %s\n",wifiName);
|
||||
|
||||
WiFi.mode(WIFI_MODE_STA);
|
||||
WiFi.begin(wifiName, wifiPsw);
|
||||
delay(5000);
|
||||
|
||||
if (!WiFi.isConnected()) {
|
||||
WiFi.begin(wifiName, wifiPsw);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DISABLE_NTP
|
||||
@ -167,7 +169,7 @@ bool initWifi()
|
||||
WiFi.mode(WIFI_MODE_STA);
|
||||
WiFi.setHostname(ourHost);
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
WiFi.setAutoReconnect(false);
|
||||
WiFi.setAutoReconnect(true);
|
||||
WiFi.setSleep(false);
|
||||
if (config.network.address_mode == Config_NetworkConfig_AddressMode_STATIC && config.network.ipv4_config.ip != 0) {
|
||||
WiFi.config(config.network.ipv4_config.ip,
|
||||
@ -182,7 +184,8 @@ bool initWifi()
|
||||
|
||||
WiFi.onEvent(
|
||||
[](WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
LOG_WARN("WiFi lost connection. Reason: %d", info.wifi_sta_disconnected.reason);
|
||||
|
||||
LOG_WARN("WiFi lost connection. Reason: %d\n", info.wifi_sta_disconnected.reason);
|
||||
|
||||
/*
|
||||
If we are disconnected from the AP for some reason,
|
||||
|
@ -1,82 +0,0 @@
|
||||
#include "WiFiServerAPI.h"
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
static WiFiServerPort *apiPort;
|
||||
|
||||
void initApiServer(int port)
|
||||
{
|
||||
// Start API server on port 4403
|
||||
if (!apiPort) {
|
||||
apiPort = new WiFiServerPort(port);
|
||||
LOG_INFO("API server listening on TCP port %d\n", port);
|
||||
apiPort->init();
|
||||
}
|
||||
}
|
||||
|
||||
WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : StreamAPI(&client), concurrency::OSThread("WiFiServerAPI"), client(_client)
|
||||
{
|
||||
LOG_INFO("Incoming wifi connection\n");
|
||||
}
|
||||
|
||||
WiFiServerAPI::~WiFiServerAPI()
|
||||
{
|
||||
client.stop();
|
||||
|
||||
// FIXME - delete this if the client dropps the connection!
|
||||
}
|
||||
|
||||
/// override close to also shutdown the TCP link
|
||||
void WiFiServerAPI::close()
|
||||
{
|
||||
client.stop(); // drop tcp connection
|
||||
StreamAPI::close();
|
||||
}
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
bool WiFiServerAPI::checkIsConnected()
|
||||
{
|
||||
return client.connected();
|
||||
}
|
||||
|
||||
int32_t WiFiServerAPI::runOnce()
|
||||
{
|
||||
if (client.connected()) {
|
||||
return StreamAPI::runOncePart();
|
||||
} else {
|
||||
LOG_INFO("Client dropped connection, suspending API service\n");
|
||||
enabled = false; // we no longer need to run
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// If an api server is running, we try to spit out debug 'serial' characters there
|
||||
void WiFiServerPort::debugOut(char c)
|
||||
{
|
||||
if (apiPort && apiPort->openAPI)
|
||||
apiPort->openAPI->debugOut(c);
|
||||
}
|
||||
|
||||
|
||||
WiFiServerPort::WiFiServerPort(int port) : WiFiServer(port), concurrency::OSThread("ApiServer") {}
|
||||
|
||||
void WiFiServerPort::init()
|
||||
{
|
||||
begin();
|
||||
}
|
||||
|
||||
int32_t WiFiServerPort::runOnce()
|
||||
{
|
||||
auto client = available();
|
||||
if (client) {
|
||||
// Close any previous connection (see FIXME in header file)
|
||||
if (openAPI) {
|
||||
LOG_INFO("Force closing previous TCP connection\n");
|
||||
delete openAPI;
|
||||
}
|
||||
|
||||
openAPI = new WiFiServerAPI(client);
|
||||
}
|
||||
|
||||
return 100; // only check occasionally for incoming connections
|
||||
}
|
@ -65,8 +65,10 @@ int32_t NodeInfoModule::runOnce()
|
||||
bool requestReplies = currentGeneration != radioGeneration;
|
||||
currentGeneration = radioGeneration;
|
||||
|
||||
LOG_INFO("Sending our nodeinfo to mesh (wantReplies=%d)\n", requestReplies);
|
||||
sendOurNodeInfo(NODENUM_BROADCAST, requestReplies); // Send our info (don't request replies)
|
||||
if (airTime->isTxAllowedAirUtil()) {
|
||||
LOG_INFO("Sending our nodeinfo to mesh (wantReplies=%d)\n", requestReplies);
|
||||
sendOurNodeInfo(NODENUM_BROADCAST, requestReplies); // Send our info (don't request replies)
|
||||
}
|
||||
|
||||
return default_broadcast_interval_secs * 1000;
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ int32_t PositionModule::runOnce()
|
||||
if (lastGpsSend == 0 || (now - lastGpsSend) >= intervalMs) {
|
||||
|
||||
// Only send packets if the channel is less than 40% utilized.
|
||||
if (airTime->channelUtilizationPercent() < max_channel_util_percent) {
|
||||
if (airTime->isTxAllowedChannelUtil()) {
|
||||
if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) {
|
||||
lastGpsSend = now;
|
||||
|
||||
@ -158,14 +158,12 @@ int32_t PositionModule::runOnce()
|
||||
LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", node->position.timestamp, requestReplies);
|
||||
sendOurPosition(NODENUM_BROADCAST, requestReplies);
|
||||
}
|
||||
} else {
|
||||
LOG_WARN("Channel utilization is >40 percent. Skipping this opportunity to send.\n");
|
||||
}
|
||||
|
||||
} else if (config.position.position_broadcast_smart_enabled) {
|
||||
|
||||
// Only send packets if the channel is less than 25% utilized.
|
||||
if (airTime->channelUtilizationPercent() < polite_channel_util_percent) {
|
||||
if (airTime->isTxAllowedChannelUtil(true)) {
|
||||
|
||||
NodeInfo *node2 = service.refreshMyNodeInfo(); // should guarantee there is now a position
|
||||
|
||||
@ -208,8 +206,6 @@ int32_t PositionModule::runOnce()
|
||||
lastGpsSend = now;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_WARN("Channel utilization is >25 percent. Skipping this opportunity to send.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,11 +13,10 @@
|
||||
|
||||
int32_t DeviceTelemetryModule::runOnce()
|
||||
{
|
||||
#ifndef ARCH_PORTDUINO
|
||||
uint32_t now = millis();
|
||||
if ((lastSentToMesh == 0 ||
|
||||
(now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval)) &&
|
||||
airTime->channelUtilizationPercent() < max_channel_util_percent) {
|
||||
airTime->isTxAllowedChannelUtil() && airTime->isTxAllowedAirUtil()) {
|
||||
sendTelemetry();
|
||||
lastSentToMesh = now;
|
||||
} else if (service.isToPhoneQueueEmpty()) {
|
||||
@ -26,7 +25,6 @@ int32_t DeviceTelemetryModule::runOnce()
|
||||
sendTelemetry(NODENUM_BROADCAST, true);
|
||||
}
|
||||
return sendToPhoneIntervalMs;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool DeviceTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Telemetry *t)
|
||||
|
@ -107,7 +107,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
uint32_t now = millis();
|
||||
if ((lastSentToMesh == 0 ||
|
||||
(now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval)) &&
|
||||
airTime->channelUtilizationPercent() < max_channel_util_percent) {
|
||||
airTime->isTxAllowedAirUtil()) {
|
||||
sendTelemetry();
|
||||
lastSentToMesh = now;
|
||||
} else if (service.isToPhoneQueueEmpty()) {
|
||||
|
@ -73,10 +73,8 @@ int32_t RangeTestModule::runOnce()
|
||||
LOG_INFO("fixed_position() %d\n", config.position.fixed_position);
|
||||
|
||||
// Only send packets if the channel is less than 25% utilized.
|
||||
if (airTime->channelUtilizationPercent() < 25) {
|
||||
if (airTime->isTxAllowedChannelUtil(true)) {
|
||||
rangeTestModuleRadio->sendPayload();
|
||||
} else {
|
||||
LOG_WARN("RangeTest - Channel utilization is >25 percent. Skipping this opportunity to send.\n");
|
||||
}
|
||||
|
||||
return (senderHeartbeat);
|
||||
|
@ -21,7 +21,7 @@ int32_t StoreForwardModule::runOnce()
|
||||
// Send out the message queue.
|
||||
if (this->busy) {
|
||||
// Only send packets if the channel is less than 25% utilized.
|
||||
if (airTime->channelUtilizationPercent() < polite_channel_util_percent) {
|
||||
if (airTime->isTxAllowedChannelUtil(true)) {
|
||||
storeForwardModule->sendPayload(this->busyTo, this->packetHistoryTXQueue_index);
|
||||
if (this->packetHistoryTXQueue_index == packetHistoryTXQueue_size) {
|
||||
// Tell the client we're done sending
|
||||
@ -34,12 +34,10 @@ int32_t StoreForwardModule::runOnce()
|
||||
} else {
|
||||
this->packetHistoryTXQueue_index++;
|
||||
}
|
||||
} else {
|
||||
LOG_WARN("*** Channel utilization is too high. Retrying later.\n");
|
||||
}
|
||||
LOG_DEBUG("*** SF bitrate = %f bytes / sec\n", myNodeInfo.bitrate);
|
||||
|
||||
} else if ((millis() - lastHeartbeat > (heartbeatInterval * 1000)) && (airTime->channelUtilizationPercent() < polite_channel_util_percent)) {
|
||||
} else if ((millis() - lastHeartbeat > (heartbeatInterval * 1000)) && airTime->isTxAllowedChannelUtil(true)) {
|
||||
lastHeartbeat = millis();
|
||||
LOG_INFO("*** Sending heartbeat\n");
|
||||
StoreAndForward sf = StoreAndForward_init_zero;
|
||||
|
@ -43,9 +43,20 @@ void MQTT::onPublish(char *topic, byte *payload, unsigned int length)
|
||||
JSONValue *json_value = JSON::Parse(payloadStr);
|
||||
if (json_value != NULL) {
|
||||
LOG_INFO("JSON Received on MQTT, parsing..\n");
|
||||
|
||||
// check if it is a valid envelope
|
||||
JSONObject json;
|
||||
json = json_value->AsObject();
|
||||
|
||||
// parse the channel name from the topic string
|
||||
char *ptr = strtok(topic, "/");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ptr = strtok(NULL, "/");
|
||||
}
|
||||
LOG_DEBUG("Looking for Channel name: %s\n", ptr);
|
||||
Channel sendChannel = channels.getByName(ptr);
|
||||
LOG_DEBUG("Found Channel name: %s (Index %d)\n", channels.getGlobalId(sendChannel.settings.channel_num), sendChannel.settings.channel_num);
|
||||
|
||||
if ((json.find("sender") != json.end()) && (json.find("payload") != json.end()) && (json.find("type") != json.end()) && json["type"]->IsString() && (json["type"]->AsString().compare("sendtext") == 0)) {
|
||||
// this is a valid envelope
|
||||
if (json["payload"]->IsString() && json["type"]->IsString() && (json["sender"]->AsString().compare(owner.id) != 0)) {
|
||||
@ -55,13 +66,18 @@ void MQTT::onPublish(char *topic, byte *payload, unsigned int length)
|
||||
// construct protobuf data packet using TEXT_MESSAGE, send it to the mesh
|
||||
MeshPacket *p = router->allocForSending();
|
||||
p->decoded.portnum = PortNum_TEXT_MESSAGE_APP;
|
||||
if (jsonPayloadStr.length() <= sizeof(p->decoded.payload.bytes)) {
|
||||
memcpy(p->decoded.payload.bytes, jsonPayloadStr.c_str(), jsonPayloadStr.length());
|
||||
p->decoded.payload.size = jsonPayloadStr.length();
|
||||
MeshPacket *packet = packetPool.allocCopy(*p);
|
||||
service.sendToMesh(packet, RX_SRC_LOCAL);
|
||||
p->channel = sendChannel.settings.channel_num;
|
||||
if (sendChannel.settings.downlink_enabled) {
|
||||
if (jsonPayloadStr.length() <= sizeof(p->decoded.payload.bytes)) {
|
||||
memcpy(p->decoded.payload.bytes, jsonPayloadStr.c_str(), jsonPayloadStr.length());
|
||||
p->decoded.payload.size = jsonPayloadStr.length();
|
||||
MeshPacket *packet = packetPool.allocCopy(*p);
|
||||
service.sendToMesh(packet, RX_SRC_LOCAL);
|
||||
} else {
|
||||
LOG_WARN("Received MQTT json payload too long, dropping\n");
|
||||
}
|
||||
} else {
|
||||
LOG_WARN("Received MQTT json payload too long, dropping\n");
|
||||
LOG_WARN("Received MQTT json payload on channel %s, but downlink is disabled, dropping\n", sendChannel.settings.name);
|
||||
}
|
||||
} else {
|
||||
LOG_DEBUG("JSON Ignoring downlink message we originally sent.\n");
|
||||
@ -80,9 +96,13 @@ void MQTT::onPublish(char *topic, byte *payload, unsigned int length)
|
||||
// construct protobuf data packet using POSITION, send it to the mesh
|
||||
MeshPacket *p = router->allocForSending();
|
||||
p->decoded.portnum = PortNum_POSITION_APP;
|
||||
p->decoded.payload.size = pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &Position_msg, &pos); //make the Data protobuf from position
|
||||
service.sendToMesh(p, RX_SRC_LOCAL);
|
||||
|
||||
p->channel = sendChannel.settings.channel_num;
|
||||
if (sendChannel.settings.downlink_enabled) {
|
||||
p->decoded.payload.size = pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &Position_msg, &pos); //make the Data protobuf from position
|
||||
service.sendToMesh(p, RX_SRC_LOCAL);
|
||||
} else {
|
||||
LOG_WARN("Received MQTT json payload on channel %s, but downlink is disabled, dropping\n", sendChannel.settings.name);
|
||||
}
|
||||
} else {
|
||||
LOG_DEBUG("JSON Ignoring downlink message we originally sent.\n");
|
||||
}
|
||||
@ -187,14 +207,17 @@ void MQTT::reconnect()
|
||||
|
||||
sendSubscriptions();
|
||||
} else {
|
||||
LOG_ERROR("Failed to contact MQTT server (%d/10)...\n",reconnectCount);
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||
if (reconnectCount > 9) {
|
||||
LOG_ERROR("Failed to contact MQTT server (%d/5)...\n",reconnectCount + 1);
|
||||
if (reconnectCount >= 4) {
|
||||
needReconnect = true;
|
||||
wifiReconnect->setIntervalFromNow(1000);
|
||||
wifiReconnect->setIntervalFromNow(0);
|
||||
reconnectCount = 0;
|
||||
} else {
|
||||
reconnectCount++;
|
||||
}
|
||||
|
||||
#endif
|
||||
reconnectCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -264,7 +287,6 @@ int32_t MQTT::runOnce()
|
||||
|
||||
String topic = cryptTopic + env->channel_id + "/" + owner.id;
|
||||
LOG_INFO("publish %s, %u bytes from queue\n", topic.c_str(), numBytes);
|
||||
|
||||
|
||||
pubSub.publish(topic.c_str(), bytes, numBytes, false);
|
||||
|
||||
@ -279,7 +301,7 @@ int32_t MQTT::runOnce()
|
||||
}
|
||||
mqttPool.release(env);
|
||||
}
|
||||
return 20;
|
||||
return 200;
|
||||
} else {
|
||||
return 30000;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <EthernetClient.h>
|
||||
#endif
|
||||
|
||||
#define MAX_MQTT_QUEUE 32
|
||||
#define MAX_MQTT_QUEUE 16
|
||||
|
||||
/**
|
||||
* Our wrapper/singleton for sending/receiving MQTT "udp" packets. This object isolates the MQTT protocol implementation from
|
||||
|
@ -172,6 +172,9 @@ void cpuDeepSleep(uint64_t msecToWake)
|
||||
Serial1.end();
|
||||
#endif
|
||||
setBluetoothEnable(false);
|
||||
#ifdef RAK4630
|
||||
digitalWrite(PIN_3V3_EN, LOW);
|
||||
#endif
|
||||
// FIXME, use system off mode with ram retention for key state?
|
||||
// FIXME, use non-init RAM per
|
||||
// https://devzone.nordicsemi.com/f/nordic-q-a/48919/ram-retention-settings-with-softdevice-enabled
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "RadioInterface.h"
|
||||
#include "MeshPacketQueue.h"
|
||||
#include "wifi/WiFiServerAPI.h"
|
||||
#include "api/WiFiServerAPI.h"
|
||||
|
||||
#include <RadioLib.h>
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
extends = nrf52840_base
|
||||
board = wiscore_rak4631
|
||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631 -D RAK_4631
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/rak4631> +<mesh/eth/> +<mqtt/>
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/rak4631> +<mesh/eth/> +<mesh/api/> +<mqtt/>
|
||||
lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
|
@ -1,4 +1,4 @@
|
||||
[VERSION]
|
||||
major = 2
|
||||
minor = 0
|
||||
build = 12
|
||||
build = 13
|
||||
|
Loading…
Reference in New Issue
Block a user