Merge branch 'meshtastic:master' into router

This commit is contained in:
Jm Casler
2022-03-14 16:59:09 -07:00
committed by GitHub
co-authored by GitHub
78 changed files with 1080 additions and 7770 deletions
+4
View File
@@ -1,3 +1,5 @@
#ifndef USE_NEW_ESP32_BLUETOOTH
#include <Arduino.h>
#include "../concurrency/LockGuard.h"
@@ -154,3 +156,5 @@ void reinitUpdateService()
res = ble_gatts_add_svcs(gatt_update_svcs);
assert(res == 0);
}
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
+5 -1
View File
@@ -1,3 +1,5 @@
#ifndef USE_NEW_ESP32_BLUETOOTH
#pragma once
#include "nimble/NimbleDefs.h"
@@ -22,4 +24,6 @@ extern int16_t updateResultHandle;
#ifdef __cplusplus
};
#endif
#endif
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
+262
View File
@@ -0,0 +1,262 @@
#ifdef USE_NEW_ESP32_BLUETOOTH
#include "configuration.h"
#include "ESP32Bluetooth.h"
#include "BluetoothCommon.h"
#include "PowerFSM.h"
#include "sleep.h"
#include "main.h"
#include "mesh/PhoneAPI.h"
#include "mesh/mesh-pb-constants.h"
#include <NimBLEDevice.h>
//static BLEService meshBleService = BLEService(BLEUuid(MESH_SERVICE_UUID_16));
//static BLECharacteristic fromNum = BLECharacteristic(BLEUuid(FROMNUM_UUID_16));
//static BLECharacteristic fromRadio = BLECharacteristic(BLEUuid(FROMRADIO_UUID_16));
//static BLECharacteristic toRadio = BLECharacteristic(BLEUuid(TORADIO_UUID_16));
//static BLEDis bledis; // DIS (Device Information Service) helper class instance
//static BLEBas blebas; // BAS (Battery Service) helper class instance
//static BLEDfu bledfu; // DFU software update helper service
// This scratch buffer is used for various bluetooth reads/writes - but it is safe because only one bt operation can be in
// proccess at once
// static uint8_t trBytes[_max(_max(_max(_max(ToRadio_size, RadioConfig_size), User_size), MyNodeInfo_size), FromRadio_size)];
static uint8_t fromRadioBytes[FromRadio_size];
static uint8_t toRadioBytes[ToRadio_size];
static bool bleConnected;
NimBLECharacteristic *FromNumCharacteristic;
NimBLEServer *bleServer;
static bool passkeyShowing;
static uint32_t doublepressed;
/**
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
*/
void BluetoothPhoneAPI::onNowHasData(uint32_t fromRadioNum)
{
PhoneAPI::onNowHasData(fromRadioNum);
DEBUG_MSG("BLE notify fromNum\n");
//fromNum.notify32(fromRadioNum);
uint8_t val[4];
put_le32(val, fromRadioNum);
std::string fromNumByteString(&val[0], &val[0] + sizeof(val));
FromNumCharacteristic->setValue(fromNumByteString);
FromNumCharacteristic->notify();
}
/// Check the current underlying physical link to see if the client is currently connected
bool BluetoothPhoneAPI::checkIsConnected() {
if (bleServer && bleServer->getConnectedCount() > 0) {
return true;
}
return false;
}
PhoneAPI *bluetoothPhoneAPI;
class ESP32BluetoothToRadioCallback : public NimBLECharacteristicCallbacks {
virtual void onWrite(NimBLECharacteristic *pCharacteristic) {
DEBUG_MSG("To Radio onwrite\n");
auto valueString = pCharacteristic->getValue();
bluetoothPhoneAPI->handleToRadio(reinterpret_cast<const uint8_t*>(&valueString[0]), pCharacteristic->getDataLength());
}
};
class ESP32BluetoothFromRadioCallback : public NimBLECharacteristicCallbacks {
virtual void onRead(NimBLECharacteristic *pCharacteristic) {
DEBUG_MSG("From Radio onread\n");
size_t numBytes = bluetoothPhoneAPI->getFromRadio(fromRadioBytes);
std::string fromRadioByteString(fromRadioBytes, fromRadioBytes + numBytes);
pCharacteristic->setValue(fromRadioByteString);
}
};
class ESP32BluetoothServerCallback : public NimBLEServerCallbacks {
virtual uint32_t onPassKeyRequest() {
uint32_t passkey = 0;
if (doublepressed > 0 && (doublepressed + (30 * 1000)) > millis()) {
DEBUG_MSG("User has overridden passkey\n");
passkey = defaultBLEPin;
} else {
DEBUG_MSG("Using random passkey\n");
passkey = random(
100000, 999999); // This is the passkey to be entered on peer - we pick a number >100,000 to ensure 6 digits
}
DEBUG_MSG("*** Enter passkey %d on the peer side ***\n", passkey);
powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
screen->startBluetoothPinScreen(passkey);
passkeyShowing = true;
return passkey;
}
virtual void onAuthenticationComplete(ble_gap_conn_desc *desc) {
DEBUG_MSG("BLE authentication complete\n");
if (passkeyShowing) {
passkeyShowing = false;
screen->stopBluetoothPinScreen();
}
}
};
static ESP32BluetoothToRadioCallback *toRadioCallbacks;
static ESP32BluetoothFromRadioCallback *fromRadioCallbacks;
void ESP32Bluetooth::shutdown()
{
// Shutdown bluetooth for minimum power draw
DEBUG_MSG("Disable bluetooth\n");
//Bluefruit.Advertising.stop();
}
void ESP32Bluetooth::setup()
{
// Initialise the Bluefruit module
DEBUG_MSG("Initialise the ESP32 bluetooth module\n");
//Bluefruit.autoConnLed(false);
//Bluefruit.begin();
// Set the advertised device name (keep it short!)
//Bluefruit.setName(getDeviceName());
// Set the connect/disconnect callback handlers
//Bluefruit.Periph.setConnectCallback(connect_callback);
//Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
// Configure and Start the Device Information Service
DEBUG_MSG("Configuring the Device Information Service\n");
// FIXME, we should set a mfg string based on our HW_VENDOR enum
// bledis.setManufacturer(HW_VENDOR);
//bledis.setModel(optstr(HW_VERSION));
//bledis.setFirmwareRev(optstr(APP_VERSION));
//bledis.begin();
// Start the BLE Battery Service and set it to 100%
//DEBUG_MSG("Configuring the Battery Service\n");
//blebas.begin();
//blebas.write(0); // Unknown battery level for now
//bledfu.begin(); // Install the DFU helper
// Setup the Heart Rate Monitor service using
// BLEService and BLECharacteristic classes
DEBUG_MSG("Configuring the Mesh bluetooth service\n");
//setupMeshService();
// Supposedly debugging works with soft device if you disable advertising
//if (isSoftDeviceAllowed) {
// Setup the advertising packet(s)
// DEBUG_MSG("Setting up the advertising payload(s)\n");
// startAdv();
// DEBUG_MSG("Advertising\n");
//}
//NimBLEDevice::deleteAllBonds();
NimBLEDevice::init("Meshtastic_1234");
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
NimBLEDevice::setSecurityAuth(true, true, true);
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
bleServer = NimBLEDevice::createServer();
ESP32BluetoothServerCallback *serverCallbacks = new ESP32BluetoothServerCallback();
bleServer->setCallbacks(serverCallbacks);
NimBLEService *bleService = bleServer->createService(MESH_SERVICE_UUID);
//NimBLECharacteristic *pNonSecureCharacteristic = bleService->createCharacteristic("1234", NIMBLE_PROPERTY::READ );
//NimBLECharacteristic *pSecureCharacteristic = bleService->createCharacteristic("1235", NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN);
//define the characteristics that the app is looking for
NimBLECharacteristic *ToRadioCharacteristic = bleService->createCharacteristic(TORADIO_UUID, NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_AUTHEN | NIMBLE_PROPERTY::WRITE_ENC);
NimBLECharacteristic *FromRadioCharacteristic = bleService->createCharacteristic(FROMRADIO_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC);
FromNumCharacteristic = bleService->createCharacteristic(FROMNUM_UUID, NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC);
bluetoothPhoneAPI = new BluetoothPhoneAPI();
toRadioCallbacks = new ESP32BluetoothToRadioCallback();
ToRadioCharacteristic->setCallbacks(toRadioCallbacks);
fromRadioCallbacks = new ESP32BluetoothFromRadioCallback();
FromRadioCharacteristic->setCallbacks(fromRadioCallbacks);
//uint8_t val[4];
//uint32_t zero = 0;
//put_le32(val, zero);
//std::string fromNumByteString(&val[0], &val[0] + sizeof(val));
//FromNumCharacteristic->setValue(fromNumByteString);
bleService->start();
//pNonSecureCharacteristic->setValue("Hello Non Secure BLE");
//pSecureCharacteristic->setValue("Hello Secure BLE");
//FromRadioCharacteristic->setValue("FromRadioString");
//ToRadioCharacteristic->setCallbacks()
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->addServiceUUID(MESH_SERVICE_UUID);
pAdvertising->start();
}
/// Given a level between 0-100, update the BLE attribute
void updateBatteryLevel(uint8_t level)
{
//blebas.write(level);
}
void ESP32Bluetooth::clearBonds()
{
DEBUG_MSG("Clearing bluetooth bonds!\n");
//bond_print_list(BLE_GAP_ROLE_PERIPH);
//bond_print_list(BLE_GAP_ROLE_CENTRAL);
//Bluefruit.Periph.clearBonds();
//Bluefruit.Central.clearBonds();
}
void clearNVS() {
NimBLEDevice::deleteAllBonds();
ESP.restart();
}
void disablePin() {
DEBUG_MSG("User Override, disabling bluetooth pin requirement\n");
// keep track of when it was pressed, so we know it was within X seconds
// Flash the LED
setLed(true);
delay(100);
setLed(false);
delay(100);
setLed(true);
delay(100);
setLed(false);
delay(100);
setLed(true);
delay(100);
setLed(false);
doublepressed = millis();
}
#endif
+33
View File
@@ -0,0 +1,33 @@
#ifdef USE_NEW_ESP32_BLUETOOTH
#pragma once
extern uint16_t fromNumValHandle;
class BluetoothPhoneAPI : public PhoneAPI
{
protected:
/**
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
*/
virtual void onNowHasData(uint32_t fromRadioNum) override;
/// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected() override;
};
extern PhoneAPI *bluetoothPhoneAPI;
class ESP32Bluetooth
{
public:
void setup();
void shutdown();
void clearBonds();
};
void setBluetoothEnable(bool on);
void clearNVS();
void disablePin();
#endif
+3
View File
@@ -1,3 +1,4 @@
#ifndef USE_NEW_ESP32_BLUETOOTH
#include "BluetoothSoftwareUpdate.h"
// NRF52 wants these constants as byte arrays
@@ -68,3 +69,5 @@ const struct ble_gatt_svc_def gatt_update_svcs[] = {
0, /* No more services. */
},
};
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
+25 -1
View File
@@ -3,7 +3,13 @@
#include "configuration.h"
#include "esp_task_wdt.h"
#include "main.h"
#ifdef USE_NEW_ESP32_BLUETOOTH
#include "ESP32Bluetooth.h"
#else
#include "nimble/BluetoothUtil.h"
#endif
#include "sleep.h"
#include "target_specific.h"
#include "utils.h"
@@ -12,6 +18,10 @@
#include <nvs.h>
#include <nvs_flash.h>
#ifdef USE_NEW_ESP32_BLUETOOTH
ESP32Bluetooth *esp32Bluetooth;
#endif
void getMacAddr(uint8_t *dmac)
{
assert(esp_efuse_mac_get_default(dmac) == ESP_OK);
@@ -28,6 +38,19 @@ static void printBLEinfo() {
}
} */
#ifdef USE_NEW_ESP32_BLUETOOTH
void setBluetoothEnable(bool on) {
if (!esp32Bluetooth) {
esp32Bluetooth = new ESP32Bluetooth();
}
if (on) {
esp32Bluetooth->setup();
} else {
esp32Bluetooth->shutdown();
}
}
#endif
void esp32Setup()
{
@@ -92,11 +115,12 @@ uint32_t axpDebugRead()
Periodic axpDebugOutput(axpDebugRead);
#endif
/// loop code specific to ESP32 targets
void esp32Loop()
{
esp_task_wdt_reset(); // service our app level watchdog
loopBLE();
//loopBLE();
// for debug printing
// radio.radioIf.canSleep();
+4 -4
View File
@@ -69,7 +69,7 @@ uint32_t dopThresholds[5] = {2000, 1000, 500, 200, 100};
// At some point, we're going to ask all of the modules if they would like to display a screen frame
// we'll need to hold onto pointers for the modules that can draw a frame.
std::vector<MeshPlugin *> moduleFrames;
std::vector<MeshModule *> moduleFrames;
// Stores the last 4 of our hardware ID, to make finding the device for pairing easier
static char ourId[5];
@@ -194,7 +194,7 @@ static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int
// DEBUG_MSG("Screen is not in transition. Frame: %d\n\n", module_frame);
}
// DEBUG_MSG("Drawing Module Frame %d\n\n", module_frame);
MeshPlugin &pi = *moduleFrames.at(module_frame);
MeshModule &pi = *moduleFrames.at(module_frame);
pi.drawFrame(display, state, x, y);
}
@@ -828,7 +828,7 @@ void Screen::setup()
textMessageObserver.observe(textMessageModule);
// Modules can notify screen about refresh
MeshPlugin::observeUIEvents(&uiFrameEventObserver);
MeshModule::observeUIEvents(&uiFrameEventObserver);
}
void Screen::forceDisplay()
@@ -976,7 +976,7 @@ void Screen::setFrames()
DEBUG_MSG("showing standard frames\n");
showingNormalScreen = true;
moduleFrames = MeshPlugin::GetMeshModulesWithUIFrames();
moduleFrames = MeshModule::GetMeshModulesWithUIFrames();
DEBUG_MSG("Showing %d module frames\n", moduleFrames.size());
int totalFrameCount = MAX_NUM_NODES + NUM_EXTRA_FRAMES + moduleFrames.size();
DEBUG_MSG("Total frame count: %d\n", totalFrameCount);
+1 -1
View File
@@ -40,7 +40,7 @@ class Screen
#include "concurrency/OSThread.h"
#include "power.h"
#include <string>
#include "mesh/MeshPlugin.h"
#include "mesh/MeshModule.h"
// 0 to 255, though particular variants might define different defaults
#ifndef BRIGHTNESS_DEFAULT
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#include "SinglePortPlugin.h" // TODO: what header file to include?
#include "SinglePortModule.h" // TODO: what header file to include?
#include "InputBroker.h"
enum RotaryEncoderInterruptBaseStateType
+8 -2
View File
@@ -30,8 +30,14 @@
#include "mesh/http/WiFiAPClient.h"
#ifndef NO_ESP32
#include "mesh/http/WebServer.h"
#include "nimble/BluetoothUtil.h"
#include "mesh/http/WebServer.h"
#ifdef USE_NEW_ESP32_BLUETOOTH
#include "esp32/ESP32Bluetooth.h"
#else
#include "nimble/BluetoothUtil.h"
#endif
#endif
#if defined(HAS_WIFI) || defined(PORTDUINO)
@@ -1,38 +1,38 @@
#include "configuration.h"
#include "MeshPlugin.h"
#include "MeshModule.h"
#include "Channels.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "modules/RoutingModule.h"
#include <assert.h>
std::vector<MeshPlugin *> *MeshPlugin::modules;
std::vector<MeshModule *> *MeshModule::modules;
const MeshPacket *MeshPlugin::currentRequest;
const MeshPacket *MeshModule::currentRequest;
/**
* If any of the current chain of modules has already sent a reply, it will be here. This is useful to allow
* the RoutingPlugin to avoid sending redundant acks
*/
MeshPacket *MeshPlugin::currentReply;
MeshPacket *MeshModule::currentReply;
MeshPlugin::MeshPlugin(const char *_name) : name(_name)
MeshModule::MeshModule(const char *_name) : name(_name)
{
// Can't trust static initalizer order, so we check each time
if (!modules)
modules = new std::vector<MeshPlugin *>();
modules = new std::vector<MeshModule *>();
modules->push_back(this);
}
void MeshPlugin::setup() {}
void MeshModule::setup() {}
MeshPlugin::~MeshPlugin()
MeshModule::~MeshModule()
{
assert(0); // FIXME - remove from list of modules once someone needs this feature
}
MeshPacket *MeshPlugin::allocAckNak(Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex)
MeshPacket *MeshModule::allocAckNak(Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex)
{
Routing c = Routing_init_default;
@@ -57,7 +57,7 @@ MeshPacket *MeshPlugin::allocAckNak(Routing_Error err, NodeNum to, PacketId idFr
return p;
}
MeshPacket *MeshPlugin::allocErrorResponse(Routing_Error err, const MeshPacket *p)
MeshPacket *MeshModule::allocErrorResponse(Routing_Error err, const MeshPacket *p)
{
auto r = allocAckNak(err, getFrom(p), p->id, p->channel);
@@ -66,7 +66,7 @@ MeshPacket *MeshPlugin::allocErrorResponse(Routing_Error err, const MeshPacket *
return r;
}
void MeshPlugin::callPlugins(const MeshPacket &mp, RxSource src)
void MeshModule::callPlugins(const MeshPacket &mp, RxSource src)
{
// DEBUG_MSG("In call modules\n");
bool moduleFound = false;
@@ -183,7 +183,7 @@ void MeshPlugin::callPlugins(const MeshPacket &mp, RxSource src)
(src == RX_SRC_LOCAL) ? "LOCAL":"REMOTE");
}
MeshPacket *MeshPlugin::allocReply()
MeshPacket *MeshModule::allocReply()
{
auto r = myReply;
myReply = NULL; // Only use each reply once
@@ -194,7 +194,7 @@ MeshPacket *MeshPlugin::allocReply()
* so that subclasses can (optionally) send a response back to the original sender. Implementing this method
* is optional
*/
void MeshPlugin::sendResponse(const MeshPacket &req)
void MeshModule::sendResponse(const MeshPacket &req)
{
auto r = allocReply();
if (r) {
@@ -222,10 +222,10 @@ void setReplyTo(MeshPacket *p, const MeshPacket &to)
p->decoded.request_id = to.id;
}
std::vector<MeshPlugin *> MeshPlugin::GetMeshModulesWithUIFrames()
std::vector<MeshModule *> MeshModule::GetMeshModulesWithUIFrames()
{
std::vector<MeshPlugin *> modulesWithUIFrames;
std::vector<MeshModule *> modulesWithUIFrames;
if (modules) {
for (auto i = modules->begin(); i != modules->end(); ++i) {
auto &pi = **i;
@@ -238,7 +238,7 @@ std::vector<MeshPlugin *> MeshPlugin::GetMeshModulesWithUIFrames()
return modulesWithUIFrames;
}
void MeshPlugin::observeUIEvents(
void MeshModule::observeUIEvents(
Observer<const UIFrameEvent *> *observer)
{
if (modules) {
@@ -254,7 +254,7 @@ void MeshPlugin::observeUIEvents(
}
}
AdminMessageHandleResult MeshPlugin::handleAdminMessageForAllPlugins(const MeshPacket &mp, AdminMessage *request, AdminMessage *response)
AdminMessageHandleResult MeshModule::handleAdminMessageForAllPlugins(const MeshPacket &mp, AdminMessage *request, AdminMessage *response)
{
AdminMessageHandleResult handled = AdminMessageHandleResult::NOT_HANDLED;
if (modules) {
@@ -52,23 +52,23 @@ typedef struct _UIFrameEvent {
* Interally we use modules to implement the core meshtastic text messaging and gps position sharing features. You
* can use these classes as examples for how to write your own custom module. See here: (FIXME)
*/
class MeshPlugin
class MeshModule
{
static std::vector<MeshPlugin *> *modules;
static std::vector<MeshModule *> *modules;
public:
/** Constructor
* name is for debugging output
*/
MeshPlugin(const char *_name);
MeshModule(const char *_name);
virtual ~MeshPlugin();
virtual ~MeshModule();
/** For use only by MeshService
*/
static void callPlugins(const MeshPacket &mp, RxSource src = RX_SRC_RADIO);
static std::vector<MeshPlugin *> GetMeshModulesWithUIFrames();
static std::vector<MeshModule *> GetMeshModulesWithUIFrames();
static void observeUIEvents(Observer<const UIFrameEvent *> *observer);
static AdminMessageHandleResult handleAdminMessageForAllPlugins(
const MeshPacket &mp, AdminMessage *request, AdminMessage *response);
+1 -1
View File
@@ -438,7 +438,7 @@ size_t NodeDB::getNumOnlineNodes()
return numseen;
}
#include "MeshPlugin.h"
#include "MeshModule.h"
/** Update position info for this node based on received position data
*/
@@ -1,4 +1,4 @@
#include "configuration.h"
#include "ProtobufPlugin.h"
#include "ProtobufModule.h"
@@ -1,5 +1,5 @@
#pragma once
#include "SinglePortPlugin.h"
#include "SinglePortModule.h"
/**
* A base class for mesh modules that assume that they are sending/receiving one particular protobuf based
@@ -8,7 +8,7 @@
* If you are using protobufs to encode your packets (recommended) you can use this as a baseclass for your module
* and avoid a bunch of boilerplate code.
*/
template <class T> class ProtobufPlugin : protected SinglePortPlugin
template <class T> class ProtobufModule : protected SinglePortModule
{
const pb_msgdesc_t *fields;
@@ -16,8 +16,8 @@ template <class T> class ProtobufPlugin : protected SinglePortPlugin
/** Constructor
* name is for debugging output
*/
ProtobufPlugin(const char *_name, PortNum _ourPortNum, const pb_msgdesc_t *_fields)
: SinglePortPlugin(_name, _ourPortNum), fields(_fields)
ProtobufModule(const char *_name, PortNum _ourPortNum, const pb_msgdesc_t *_fields)
: SinglePortModule(_name, _ourPortNum), fields(_fields)
{
}
+2 -2
View File
@@ -1,6 +1,6 @@
#include "configuration.h"
#include "ReliableRouter.h"
#include "MeshPlugin.h"
#include "MeshModule.h"
#include "MeshTypes.h"
#include "mesh-pb-constants.h"
@@ -92,7 +92,7 @@ void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing *c)
if (p->to == ourNode) { // ignore ack/nak/want_ack packets that are not address to us (we only handle 0 hop reliability
// - not DSR routing)
if (p->want_ack) {
if (MeshPlugin::currentReply)
if (MeshModule::currentReply)
DEBUG_MSG("Someone else has replied to this message, no need for a 2nd ack\n");
else
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
+1 -1
View File
@@ -377,7 +377,7 @@ void Router::handleReceived(MeshPacket *p, RxSource src)
}
// call modules here
MeshPlugin::callPlugins(*p, src);
MeshModule::callPlugins(*p, src);
}
void Router::perhapsHandleReceived(MeshPacket *p)
@@ -1,12 +1,12 @@
#pragma once
#include "MeshPlugin.h"
#include "MeshModule.h"
#include "Router.h"
/**
* Most modules are only interested in sending/receving one particular portnum. This baseclass simplifies that common
* case.
*/
class SinglePortPlugin : public MeshPlugin
class SinglePortModule : public MeshModule
{
protected:
PortNum ourPortNum;
@@ -15,7 +15,7 @@ class SinglePortPlugin : public MeshPlugin
/** Constructor
* name is for debugging output
*/
SinglePortPlugin(const char *_name, PortNum _ourPortNum) : MeshPlugin(_name), ourPortNum(_ourPortNum) {}
SinglePortModule(const char *_name, PortNum _ourPortNum) : MeshModule(_name), ourPortNum(_ourPortNum) {}
protected:
/**
+21 -21
View File
@@ -148,12 +148,12 @@ typedef struct _RadioConfig_UserPreferences {
bool debug_log_enabled;
pb_size_t ignore_incoming_count;
uint32_t ignore_incoming[3];
bool serialmodule_enabled;
bool serialmodule_echo;
uint32_t serialmodule_rxd;
uint32_t serialmodule_txd;
uint32_t serialmodule_timeout;
uint32_t serialmodule_mode;
bool serial_module_enabled;
bool serial_module_echo;
uint32_t serial_module_rxd;
uint32_t serial_module_txd;
uint32_t serial_module_timeout;
uint32_t serial_module_mode;
bool ext_notification_module_enabled;
uint32_t ext_notification_module_output_ms;
uint32_t ext_notification_module_output;
@@ -197,7 +197,7 @@ typedef struct _RadioConfig_UserPreferences {
bool canned_message_module_send_bell;
bool mqtt_encryption_enabled;
float adc_multiplier_override;
uint32_t serialmodule_baud;
uint32_t serial_module_baud;
} RadioConfig_UserPreferences;
typedef struct _RadioConfig {
@@ -289,12 +289,12 @@ extern "C" {
#define RadioConfig_UserPreferences_factory_reset_tag 100
#define RadioConfig_UserPreferences_debug_log_enabled_tag 101
#define RadioConfig_UserPreferences_ignore_incoming_tag 103
#define RadioConfig_UserPreferences_serialmodule_enabled_tag 120
#define RadioConfig_UserPreferences_serialmodule_echo_tag 121
#define RadioConfig_UserPreferences_serialmodule_rxd_tag 122
#define RadioConfig_UserPreferences_serialmodule_txd_tag 123
#define RadioConfig_UserPreferences_serialmodule_timeout_tag 124
#define RadioConfig_UserPreferences_serialmodule_mode_tag 125
#define RadioConfig_UserPreferences_serial_module_enabled_tag 120
#define RadioConfig_UserPreferences_serial_module_echo_tag 121
#define RadioConfig_UserPreferences_serial_module_rxd_tag 122
#define RadioConfig_UserPreferences_serial_module_txd_tag 123
#define RadioConfig_UserPreferences_serial_module_timeout_tag 124
#define RadioConfig_UserPreferences_serial_module_mode_tag 125
#define RadioConfig_UserPreferences_ext_notification_module_enabled_tag 126
#define RadioConfig_UserPreferences_ext_notification_module_output_ms_tag 127
#define RadioConfig_UserPreferences_ext_notification_module_output_tag 128
@@ -338,7 +338,7 @@ extern "C" {
#define RadioConfig_UserPreferences_canned_message_module_send_bell_tag 173
#define RadioConfig_UserPreferences_mqtt_encryption_enabled_tag 174
#define RadioConfig_UserPreferences_adc_multiplier_override_tag 175
#define RadioConfig_UserPreferences_serialmodule_baud_tag 176
#define RadioConfig_UserPreferences_serial_module_baud_tag 176
#define RadioConfig_preferences_tag 1
/* Struct field encoding specification for nanopb */
@@ -383,12 +383,12 @@ X(a, STATIC, SINGULAR, UINT32, gps_max_dop, 46) \
X(a, STATIC, SINGULAR, BOOL, factory_reset, 100) \
X(a, STATIC, SINGULAR, BOOL, debug_log_enabled, 101) \
X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) \
X(a, STATIC, SINGULAR, BOOL, serialmodule_enabled, 120) \
X(a, STATIC, SINGULAR, BOOL, serialmodule_echo, 121) \
X(a, STATIC, SINGULAR, UINT32, serialmodule_rxd, 122) \
X(a, STATIC, SINGULAR, UINT32, serialmodule_txd, 123) \
X(a, STATIC, SINGULAR, UINT32, serialmodule_timeout, 124) \
X(a, STATIC, SINGULAR, UINT32, serialmodule_mode, 125) \
X(a, STATIC, SINGULAR, BOOL, serial_module_enabled, 120) \
X(a, STATIC, SINGULAR, BOOL, serial_module_echo, 121) \
X(a, STATIC, SINGULAR, UINT32, serial_module_rxd, 122) \
X(a, STATIC, SINGULAR, UINT32, serial_module_txd, 123) \
X(a, STATIC, SINGULAR, UINT32, serial_module_timeout, 124) \
X(a, STATIC, SINGULAR, UINT32, serial_module_mode, 125) \
X(a, STATIC, SINGULAR, BOOL, ext_notification_module_enabled, 126) \
X(a, STATIC, SINGULAR, UINT32, ext_notification_module_output_ms, 127) \
X(a, STATIC, SINGULAR, UINT32, ext_notification_module_output, 128) \
@@ -432,7 +432,7 @@ X(a, STATIC, SINGULAR, STRING, canned_message_module_allow_input_source, 171
X(a, STATIC, SINGULAR, BOOL, canned_message_module_send_bell, 173) \
X(a, STATIC, SINGULAR, BOOL, mqtt_encryption_enabled, 174) \
X(a, STATIC, SINGULAR, FLOAT, adc_multiplier_override, 175) \
X(a, STATIC, SINGULAR, UINT32, serialmodule_baud, 176)
X(a, STATIC, SINGULAR, UINT32, serial_module_baud, 176)
#define RadioConfig_UserPreferences_CALLBACK NULL
#define RadioConfig_UserPreferences_DEFAULT NULL
+5 -4
View File
@@ -205,11 +205,12 @@ bool initWifi(bool forceSoftAP)
if (forcedSoftAP) {
const char *softAPssid = "meshtasticAdmin";
const char *softAPpasswd = "12345678";
DEBUG_MSG("Starting (Forced) WIFI AP: ssid=%s, ok=%d\n", softAPssid, WiFi.softAP(softAPssid, softAPpasswd));
int ok = WiFi.softAP(softAPssid, softAPpasswd);
DEBUG_MSG("Starting (Forced) WIFI AP: ssid=%s, ok=%d\n", softAPssid, ok);
} else {
DEBUG_MSG("Starting WIFI AP: ssid=%s, ok=%d\n", wifiName, WiFi.softAP(wifiName, wifiPsw));
int ok = WiFi.softAP(wifiName, wifiPsw);
DEBUG_MSG("Starting WIFI AP: ssid=%s, ok=%d\n", wifiName, ok);
}
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
@@ -362,4 +363,4 @@ void handleDNSResponse()
uint8_t getWifiDisconnectReason()
{
return wifiDisconnectReason;
}
}
+19 -2
View File
@@ -61,6 +61,18 @@ void AdminModule::handleGetRadio(const MeshPacket &req)
}
}
void AdminModule::handleGetOwner(const MeshPacket &req)
{
if (req.decoded.want_response) {
// We create the reply here
AdminMessage r = AdminMessage_init_default;
r.get_owner_response = owner;
r.which_variant = AdminMessage_get_owner_response_tag;
myReply = allocDataProtobuf(r);
}
}
bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
{
// if handled == false, then let others look at this message also if they want
@@ -101,6 +113,11 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
handleGetRadio(mp);
break;
case AdminMessage_get_owner_request_tag:
DEBUG_MSG("Client is getting owner\n");
handleGetOwner(mp);
break;
case AdminMessage_reboot_seconds_tag: {
int32_t s = r->reboot_seconds;
DEBUG_MSG("Rebooting in %d seconds\n", s);
@@ -123,7 +140,7 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
default:
AdminMessage response = AdminMessage_init_default;
AdminMessageHandleResult handleResult = MeshPlugin::handleAdminMessageForAllPlugins(mp, r, &response);
AdminMessageHandleResult handleResult = MeshModule::handleAdminMessageForAllPlugins(mp, r, &response);
if (handleResult == AdminMessageHandleResult::HANDLED_WITH_RESPONSE)
{
@@ -195,7 +212,7 @@ void AdminModule::handleSetRadio(RadioConfig &r)
service.reloadConfig();
}
AdminModule::AdminModule() : ProtobufPlugin("Admin", PortNum_ADMIN_APP, AdminMessage_fields)
AdminModule::AdminModule() : ProtobufModule("Admin", PortNum_ADMIN_APP, AdminMessage_fields)
{
// restrict to the admin channel for rx
boundChannel = Channels::adminChannel;
+3 -2
View File
@@ -1,10 +1,10 @@
#pragma once
#include "ProtobufPlugin.h"
#include "ProtobufModule.h"
/**
* Routing module for router control messages
*/
class AdminModule : public ProtobufPlugin<AdminMessage>
class AdminModule : public ProtobufModule<AdminMessage>
{
public:
/** Constructor
@@ -26,6 +26,7 @@ class AdminModule : public ProtobufPlugin<AdminMessage>
void handleGetChannel(const MeshPacket &req, uint32_t channelIndex);
void handleGetRadio(const MeshPacket &req);
void handleGetOwner(const MeshPacket &req);
};
extern AdminModule *adminModule;
+1 -1
View File
@@ -23,7 +23,7 @@ extern bool loadProto(const char *filename, size_t protoSize, size_t objSize, co
extern bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, const void *dest_struct);
CannedMessageModule::CannedMessageModule()
: SinglePortPlugin("canned", PortNum_TEXT_MESSAGE_APP),
: SinglePortModule("canned", PortNum_TEXT_MESSAGE_APP),
concurrency::OSThread("CannedMessageModule")
{
if (radioConfig.preferences.canned_message_module_enabled)
+2 -2
View File
@@ -1,5 +1,5 @@
#pragma once
#include "ProtobufPlugin.h"
#include "ProtobufModule.h"
#include "input/InputBroker.h"
enum cannedMessageModuleRunState
@@ -21,7 +21,7 @@ enum cannedMessageModuleRunState
#define CANNED_MESSAGE_MODULE_MESSAGES_SIZE 800
class CannedMessageModule :
public SinglePortPlugin,
public SinglePortModule,
public Observable<const UIFrameEvent *>,
private concurrency::OSThread
{
+1 -1
View File
@@ -108,7 +108,7 @@ void ExternalNotificationModule::setExternalOff()
// --------
ExternalNotificationModule::ExternalNotificationModule()
: SinglePortPlugin("ExternalNotificationModule", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread(
: SinglePortModule("ExternalNotificationModule", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread(
"ExternalNotificationModule")
{
// restrict to the admin channel for rx
+2 -2
View File
@@ -1,6 +1,6 @@
#pragma once
#include "SinglePortPlugin.h"
#include "SinglePortModule.h"
#include "concurrency/OSThread.h"
#include "configuration.h"
#include <Arduino.h>
@@ -10,7 +10,7 @@
* Radio interface for ExternalNotificationModule
*
*/
class ExternalNotificationModule : public SinglePortPlugin, private concurrency::OSThread
class ExternalNotificationModule : public SinglePortModule, private concurrency::OSThread
{
public:
ExternalNotificationModule();
+1 -1
View File
@@ -51,7 +51,7 @@ MeshPacket *NodeInfoModule::allocReply()
}
NodeInfoModule::NodeInfoModule()
: ProtobufPlugin("nodeinfo", PortNum_NODEINFO_APP, User_fields), concurrency::OSThread("NodeInfoModule")
: ProtobufModule("nodeinfo", PortNum_NODEINFO_APP, User_fields), concurrency::OSThread("NodeInfoModule")
{
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
setIntervalFromNow(30 *
+2 -2
View File
@@ -1,10 +1,10 @@
#pragma once
#include "ProtobufPlugin.h"
#include "ProtobufModule.h"
/**
* NodeInfo module for sending/receiving NodeInfos into the mesh
*/
class NodeInfoModule : public ProtobufPlugin<User>, private concurrency::OSThread
class NodeInfoModule : public ProtobufModule<User>, private concurrency::OSThread
{
/// The id of the last packet we sent, to allow us to cancel it if we make something fresher
PacketId prevPacketId = 0;
+1 -1
View File
@@ -10,7 +10,7 @@
PositionModule *positionModule;
PositionModule::PositionModule()
: ProtobufPlugin("position", PortNum_POSITION_APP, Position_fields), concurrency::OSThread("PositionModule")
: ProtobufModule("position", PortNum_POSITION_APP, Position_fields), concurrency::OSThread("PositionModule")
{
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
setIntervalFromNow(60 * 1000); // Send our initial position 60 seconds after we start (to give GPS time to setup)
+2 -2
View File
@@ -1,11 +1,11 @@
#pragma once
#include "ProtobufPlugin.h"
#include "ProtobufModule.h"
#include "concurrency/OSThread.h"
/**
* Position module for sending/receiving positions into the mesh
*/
class PositionModule : public ProtobufPlugin<Position>, private concurrency::OSThread
class PositionModule : public ProtobufModule<Position>, private concurrency::OSThread
{
/// The id of the last packet we sent, to allow us to cancel it if we make something fresher
PacketId prevPacketId = 0;
+1 -1
View File
@@ -47,7 +47,7 @@ static uint64_t digitalReads(uint64_t mask)
}
RemoteHardwareModule::RemoteHardwareModule()
: ProtobufPlugin("remotehardware", PortNum_REMOTE_HARDWARE_APP, HardwareMessage_fields), concurrency::OSThread(
: ProtobufModule("remotehardware", PortNum_REMOTE_HARDWARE_APP, HardwareMessage_fields), concurrency::OSThread(
"remotehardware")
{
}
+2 -2
View File
@@ -1,12 +1,12 @@
#pragma once
#include "ProtobufPlugin.h"
#include "ProtobufModule.h"
#include "mesh/generated/remote_hardware.pb.h"
#include "concurrency/OSThread.h"
/**
* A module that provides easy low-level remote access to device hardware.
*/
class RemoteHardwareModule : public ProtobufPlugin<HardwareMessage>, private concurrency::OSThread
class RemoteHardwareModule : public ProtobufModule<HardwareMessage>, private concurrency::OSThread
{
/// The current set of GPIOs we've been asked to watch for changes
uint64_t watchGpios = 0;
+3 -3
View File
@@ -1,17 +1,17 @@
#pragma once
#include "SinglePortPlugin.h"
#include "SinglePortModule.h"
/**
* A simple example module that just replies with "Message received" to any message it receives.
*/
class ReplyModule : public SinglePortPlugin
class ReplyModule : public SinglePortModule
{
public:
/** Constructor
* name is for debugging output
*/
ReplyModule() : SinglePortPlugin("reply", PortNum_REPLY_APP) {}
ReplyModule() : SinglePortModule("reply", PortNum_REPLY_APP) {}
protected:
+1 -1
View File
@@ -41,7 +41,7 @@ void RoutingModule::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom, C
router->sendLocal(p); // we sometimes send directly to the local node
}
RoutingModule::RoutingModule() : ProtobufPlugin("routing", PortNum_ROUTING_APP, Routing_fields)
RoutingModule::RoutingModule() : ProtobufModule("routing", PortNum_ROUTING_APP, Routing_fields)
{
isPromiscuous = true;
}
+2 -2
View File
@@ -1,11 +1,11 @@
#pragma once
#include "ProtobufPlugin.h"
#include "ProtobufModule.h"
#include "Channels.h"
/**
* Routing module for router control messages
*/
class RoutingModule : public ProtobufPlugin<Routing>
class RoutingModule : public ProtobufModule<Routing>
{
public:
/** Constructor
+3 -3
View File
@@ -1,15 +1,15 @@
#pragma once
#include "../mesh/generated/telemetry.pb.h"
#include "ProtobufPlugin.h"
#include "ProtobufModule.h"
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
class TelemetryModule : private concurrency::OSThread, public ProtobufPlugin<Telemetry>
class TelemetryModule : private concurrency::OSThread, public ProtobufModule<Telemetry>
{
public:
TelemetryModule()
: concurrency::OSThread("TelemetryModule"),
ProtobufPlugin("Telemetry", PortNum_TELEMETRY_APP, &Telemetry_msg)
ProtobufModule("Telemetry", PortNum_TELEMETRY_APP, &Telemetry_msg)
{
lastMeasurementPacket = nullptr;
}
+3 -3
View File
@@ -1,17 +1,17 @@
#pragma once
#include "SinglePortPlugin.h"
#include "SinglePortModule.h"
#include "Observer.h"
/**
* Text message handling for meshtastic - draws on the OLED display the most recent received message
*/
class TextMessageModule : public SinglePortPlugin, public Observable<const MeshPacket *>
class TextMessageModule : public SinglePortModule, public Observable<const MeshPacket *>
{
public:
/** Constructor
* name is for debugging output
*/
TextMessageModule() : SinglePortPlugin("text", PortNum_TEXT_MESSAGE_APP) {}
TextMessageModule() : SinglePortModule("text", PortNum_TEXT_MESSAGE_APP) {}
protected:
+3 -3
View File
@@ -1,6 +1,6 @@
#pragma once
#include "SinglePortPlugin.h"
#include "SinglePortModule.h"
#include "concurrency/OSThread.h"
#include "configuration.h"
#include <Arduino.h>
@@ -23,12 +23,12 @@ extern RangeTestModule *rangeTestModule;
* Radio interface for RangeTestModule
*
*/
class RangeTestModuleRadio : public SinglePortPlugin
class RangeTestModuleRadio : public SinglePortModule
{
uint32_t lastRxID = 0;
public:
RangeTestModuleRadio() : SinglePortPlugin("RangeTestModuleRadio", PortNum_TEXT_MESSAGE_APP) {}
RangeTestModuleRadio() : SinglePortModule("RangeTestModuleRadio", PortNum_TEXT_MESSAGE_APP) {}
/**
* Send our payload into the mesh
+30 -30
View File
@@ -20,18 +20,18 @@
Basic Usage:
1) Enable the module by setting serialmodule_enabled to 1.
2) Set the pins (serialmodule_rxd / serialmodule_rxd) for your preferred RX and TX GPIO pins.
1) Enable the module by setting serial_module_enabled to 1.
2) Set the pins (serial_module_rxd / serial_module_rxd) for your preferred RX and TX GPIO pins.
On tbeam, recommend to use:
RXD 35
TXD 15
3) Set serialmodule_timeout to the amount of time to wait before we consider
3) Set serial_module_timeout to the amount of time to wait before we consider
your packet as "done".
4) (Optional) In SerialModule.h set the port to PortNum_TEXT_MESSAGE_APP if you want to
send messages to/from the general text message channel.
5) Connect to your device over the serial interface at 38400 8N1.
6) Send a packet up to 240 bytes in length. This will get relayed over the mesh network.
7) (Optional) Set serialmodule_echo to 1 and any message you send out will be echoed back
7) (Optional) Set serial_module_echo to 1 and any message you send out will be echoed back
to your device.
TODO (in this order):
@@ -48,11 +48,11 @@
#define RXD2 16
#define TXD2 17
#define SERIALMODULE_RX_BUFFER 128
#define SERIALMODULE_STRING_MAX Constants_DATA_PAYLOAD_LEN
#define SERIALMODULE_TIMEOUT 250
#define SERIALMODULE_BAUD 38400
#define SERIALMODULE_ACK 1
#define SERIAL_MODULE_RX_BUFFER 128
#define SERIAL_MODULE_STRING_MAX Constants_DATA_PAYLOAD_LEN
#define SERIAL_MODULE_TIMEOUT 250
#define SERIAL_MODULE_BAUD 38400
#define SERIAL_MODULE_ACK 1
SerialModule *serialModule;
SerialModuleRadio *serialModuleRadio;
@@ -61,7 +61,7 @@ SerialModule::SerialModule() : concurrency::OSThread("SerialModule") {}
char serialStringChar[Constants_DATA_PAYLOAD_LEN];
SerialModuleRadio::SerialModuleRadio() : SinglePortPlugin("SerialModuleRadio", PortNum_SERIAL_APP)
SerialModuleRadio::SerialModuleRadio() : SinglePortModule("SerialModuleRadio", PortNum_SERIAL_APP)
{
// restrict to the admin channel for rx
boundChannel = Channels::serialChannel;
@@ -76,36 +76,36 @@ int32_t SerialModule::runOnce()
without having to configure it from the PythonAPI or WebUI.
*/
// radioConfig.preferences.serialmodule_enabled = 1;
// radioConfig.preferences.serialmodule_rxd = 35;
// radioConfig.preferences.serialmodule_txd = 15;
// radioConfig.preferences.serialmodule_timeout = 1000;
// radioConfig.preferences.serialmodule_echo = 1;
// radioConfig.preferences.serial_module_enabled = 1;
// radioConfig.preferences.serial_module_rxd = 35;
// radioConfig.preferences.serial_module_txd = 15;
// radioConfig.preferences.serial_module_timeout = 1000;
// radioConfig.preferences.serial_module_echo = 1;
if (radioConfig.preferences.serialmodule_enabled) {
if (radioConfig.preferences.serial_module_enabled) {
if (firstTime) {
// Interface with the serial peripheral from in here.
DEBUG_MSG("Initializing serial peripheral interface\n");
if (radioConfig.preferences.serialmodule_rxd && radioConfig.preferences.serialmodule_txd) {
Serial2.begin(SERIALMODULE_BAUD, SERIAL_8N1, radioConfig.preferences.serialmodule_rxd,
radioConfig.preferences.serialmodule_txd);
if (radioConfig.preferences.serial_module_rxd && radioConfig.preferences.serial_module_txd) {
Serial2.begin(SERIAL_MODULE_BAUD, SERIAL_8N1, radioConfig.preferences.serial_module_rxd,
radioConfig.preferences.serial_module_txd);
} else {
Serial2.begin(SERIALMODULE_BAUD, SERIAL_8N1, RXD2, TXD2);
Serial2.begin(SERIAL_MODULE_BAUD, SERIAL_8N1, RXD2, TXD2);
}
if (radioConfig.preferences.serialmodule_timeout) {
if (radioConfig.preferences.serial_module_timeout) {
Serial2.setTimeout(
radioConfig.preferences.serialmodule_timeout); // Number of MS to wait to set the timeout for the string.
radioConfig.preferences.serial_module_timeout); // Number of MS to wait to set the timeout for the string.
} else {
Serial2.setTimeout(SERIALMODULE_TIMEOUT); // Number of MS to wait to set the timeout for the string.
Serial2.setTimeout(SERIAL_MODULE_TIMEOUT); // Number of MS to wait to set the timeout for the string.
}
Serial2.setRxBufferSize(SERIALMODULE_RX_BUFFER);
Serial2.setRxBufferSize(SERIAL_MODULE_RX_BUFFER);
serialModuleRadio = new SerialModuleRadio();
@@ -149,7 +149,7 @@ void SerialModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
p->to = dest;
p->decoded.want_response = wantReplies;
p->want_ack = SERIALMODULE_ACK;
p->want_ack = SERIAL_MODULE_ACK;
p->decoded.payload.size = strlen(serialStringChar); // You must specify how many bytes are in the reply
memcpy(p->decoded.payload.bytes, serialStringChar, p->decoded.payload.size);
@@ -161,7 +161,7 @@ ProcessMessage SerialModuleRadio::handleReceived(const MeshPacket &mp)
{
#ifndef NO_ESP32
if (radioConfig.preferences.serialmodule_enabled) {
if (radioConfig.preferences.serial_module_enabled) {
auto &p = mp.decoded;
// DEBUG_MSG("Received text msg self=0x%0x, from=0x%0x, to=0x%0x, id=%d, msg=%.*s\n",
@@ -170,10 +170,10 @@ ProcessMessage SerialModuleRadio::handleReceived(const MeshPacket &mp)
if (getFrom(&mp) == nodeDB.getNodeNum()) {
/*
* If radioConfig.preferences.serialmodule_echo is true, then echo the packets that are sent out back to the TX
* If radioConfig.preferences.serial_module_echo is true, then echo the packets that are sent out back to the TX
* of the serial interface.
*/
if (radioConfig.preferences.serialmodule_echo) {
if (radioConfig.preferences.serial_module_echo) {
// For some reason, we get the packet back twice when we send out of the radio.
// TODO: need to find out why.
@@ -187,12 +187,12 @@ ProcessMessage SerialModuleRadio::handleReceived(const MeshPacket &mp)
} else {
if (radioConfig.preferences.serialmodule_mode == 0 || radioConfig.preferences.serialmodule_mode == 1) {
if (radioConfig.preferences.serial_module_mode == 0 || radioConfig.preferences.serial_module_mode == 1) {
// DEBUG_MSG("* * Message came from the mesh\n");
// Serial2.println("* * Message came from the mesh");
Serial2.printf("%s", p.payload.bytes);
} else if (radioConfig.preferences.serialmodule_mode == 10) {
} else if (radioConfig.preferences.serial_module_mode == 10) {
/*
@jobionekabnoi
Add code here to handle what gets sent out to the serial interface.
+2 -2
View File
@@ -1,6 +1,6 @@
#pragma once
#include "SinglePortPlugin.h"
#include "SinglePortModule.h"
#include "concurrency/OSThread.h"
#include "configuration.h"
#include <Arduino.h>
@@ -23,7 +23,7 @@ extern SerialModule *serialModule;
* Radio interface for SerialModule
*
*/
class SerialModuleRadio : public SinglePortPlugin
class SerialModuleRadio : public SinglePortModule
{
uint32_t lastRxID = 0;
+1 -1
View File
@@ -378,7 +378,7 @@ ProcessMessage StoreForwardModule::handleReceivedProtobuf(const MeshPacket &mp,
}
StoreForwardModule::StoreForwardModule()
: SinglePortPlugin("StoreForwardModule", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("StoreForwardModule")
: SinglePortModule("StoreForwardModule", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("StoreForwardModule")
{
#ifndef NO_ESP32
+2 -2
View File
@@ -1,6 +1,6 @@
#pragma once
#include "SinglePortPlugin.h"
#include "SinglePortModule.h"
#include "concurrency/OSThread.h"
#include "mesh/generated/storeforward.pb.h"
@@ -18,7 +18,7 @@ struct PacketHistoryStruct {
pb_size_t payload_size;
};
class StoreForwardModule : public SinglePortPlugin, private concurrency::OSThread
class StoreForwardModule : public SinglePortModule, private concurrency::OSThread
{
// bool firstTime = 1;
bool busy = 0;
+170 -6
View File
@@ -1,18 +1,22 @@
#include "MQTT.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "main.h"
#include "mesh/Channels.h"
#include "mesh/Router.h"
#include "mesh/generated/mqtt.pb.h"
#include "mesh/generated/telemetry.pb.h"
#include "sleep.h"
#include <WiFi.h>
#include <assert.h>
#include <json11.hpp>
MQTT *mqtt;
String statusTopic = "msh/1/stat/";
String cryptTopic = "msh/1/c/"; // msh/1/c/CHANNELID/NODEID
String cryptTopic = "msh/1/c/"; // msh/1/c/CHANNELID/NODEID
String jsonTopic = "msh/1/json/"; // msh/1/json/CHANNELID/NODEID
void MQTT::mqttCallback(char *topic, byte *payload, unsigned int length)
{
@@ -24,7 +28,43 @@ void MQTT::onPublish(char *topic, byte *payload, unsigned int length)
// parsing ServiceEnvelope
ServiceEnvelope e = ServiceEnvelope_init_default;
if (!pb_decode_from_bytes(payload, length, ServiceEnvelope_fields, &e)) {
DEBUG_MSG("Invalid MQTT service envelope, topic %s, len %u!\n", topic, length);
// check if this is a json payload message
using namespace json11;
char payloadStr[length + 1];
memcpy(payloadStr, payload, length);
payloadStr[length] = 0; // null terminated string
std::string err;
auto json = Json::parse(payloadStr, err);
if (err.empty()) {
DEBUG_MSG("Received json payload on MQTT, parsing..\n");
// check if it is a valid envelope
if (json.object_items().count("sender") != 0 && json.object_items().count("payload") != 0) {
// this is a valid envelope
if (json["sender"].string_value().compare(owner.id) != 0) {
std::string jsonPayloadStr = json["payload"].dump();
DEBUG_MSG("Received json payload %s, length %u\n", jsonPayloadStr.c_str(), jsonPayloadStr.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);
} else {
DEBUG_MSG("Received MQTT json payload too long, dropping\n");
}
} else {
DEBUG_MSG("Ignoring downlink message we originally sent.\n");
}
} else {
DEBUG_MSG("Received json payload on MQTT but not a valid envelope\n");
}
} else {
// no json, this is an invalid payload
DEBUG_MSG("Invalid MQTT service envelope, topic %s, len %u!\n", topic, length);
}
} else {
if (strcmp(e.gateway_id, owner.id) == 0)
DEBUG_MSG("Ignoring downlink message we originally sent.\n");
@@ -72,11 +112,11 @@ void MQTT::reconnect()
const char *mqttPassword = "large4cats";
if (*radioConfig.preferences.mqtt_server) {
serverAddr = radioConfig.preferences.mqtt_server; // Override the default
mqttUsername = radioConfig.preferences.mqtt_username; //do not use the hardcoded credentials for a custom mqtt server
serverAddr = radioConfig.preferences.mqtt_server; // Override the default
mqttUsername = radioConfig.preferences.mqtt_username; // do not use the hardcoded credentials for a custom mqtt server
mqttPassword = radioConfig.preferences.mqtt_password;
} else {
//we are using the default server. Use the hardcoded credentials by default, but allow overriding
// we are using the default server. Use the hardcoded credentials by default, but allow overriding
if (*radioConfig.preferences.mqtt_username && radioConfig.preferences.mqtt_username[0] != '\0') {
mqttUsername = radioConfig.preferences.mqtt_username;
}
@@ -95,7 +135,8 @@ void MQTT::reconnect()
}
pubSub.setServer(serverAddr, serverPort);
DEBUG_MSG("Connecting to MQTT server %s, port: %d, username: %s, password: %s\n", serverAddr, serverPort, mqttUsername, mqttPassword);
DEBUG_MSG("Connecting to MQTT server %s, port: %d, username: %s, password: %s\n", serverAddr, serverPort, mqttUsername,
mqttPassword);
auto myStatus = (statusTopic + owner.id);
bool connected = pubSub.connect(owner.id, mqttUsername, mqttPassword, myStatus.c_str(), 1, true, "offline");
if (connected) {
@@ -122,6 +163,9 @@ void MQTT::sendSubscriptions()
String topic = cryptTopic + channels.getGlobalId(i) + "/#";
DEBUG_MSG("Subscribing to %s\n", topic.c_str());
pubSub.subscribe(topic.c_str(), 1); // FIXME, is QOS 1 right?
String topicDecoded = jsonTopic + channels.getGlobalId(i) + "/#";
DEBUG_MSG("Subscribing to %s\n", topicDecoded.c_str());
pubSub.subscribe(topicDecoded.c_str(), 1); // FIXME, is QOS 1 right?
}
}
}
@@ -193,5 +237,125 @@ void MQTT::onSend(const MeshPacket &mp, ChannelIndex chIndex)
DEBUG_MSG("publish %s, %u bytes\n", topic.c_str(), numBytes);
pubSub.publish(topic.c_str(), bytes, numBytes, false);
// handle json topic
using namespace json11;
auto jsonString = this->downstreamPacketToJson((MeshPacket *)&mp);
if (jsonString.length() != 0) {
String topicJson = jsonTopic + channelId + "/" + owner.id;
DEBUG_MSG("publish json message to %s, %u bytes: %s\n", topicJson.c_str(), jsonString.length(), jsonString.c_str());
pubSub.publish(topicJson.c_str(), jsonString.c_str(), false);
}
}
}
// converts a downstream packet into a json message
String MQTT::downstreamPacketToJson(MeshPacket *mp)
{
using namespace json11;
// the created jsonObj is immutable after creation, so
// we need to do the heavy lifting before assembling it.
String msgType;
Json msgPayload;
switch (mp->decoded.portnum) {
case PortNum_TEXT_MESSAGE_APP: {
msgType = "text";
// convert bytes to string
DEBUG_MSG("got text message of size %u\n", mp->decoded.payload.size);
char payloadStr[(mp->decoded.payload.size) + 1];
memcpy(payloadStr, mp->decoded.payload.bytes, mp->decoded.payload.size);
payloadStr[mp->decoded.payload.size] = 0; // null terminated string
// check if this is a JSON payload
std::string err;
auto json = Json::parse(payloadStr, err);
if (err.empty()) {
DEBUG_MSG("text message payload is of type json\n");
// if it is, then we can just use the json object
msgPayload = json;
} else {
// if it isn't, then we need to create a json object
// with the string as the value
DEBUG_MSG("text message payload is of type plaintext\n");
msgPayload = Json::object({{"text", payloadStr}});
}
break;
}
case PortNum_TELEMETRY_APP: {
msgType = "telemetry";
Telemetry scratch;
Telemetry *decoded = NULL;
if (mp->which_payloadVariant == MeshPacket_decoded_tag) {
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &Telemetry_msg,
&scratch)) {
decoded = &scratch;
msgPayload = Json::object{
{"temperature", decoded->temperature},
{"relative_humidity", decoded->relative_humidity},
{"barometric_pressure", decoded->barometric_pressure},
{"gas_resistance", decoded->gas_resistance},
{"voltage", decoded->voltage},
{"current", decoded->current},
};
} else
DEBUG_MSG("Error decoding protobuf for telemetry message!\n");
};
break;
}
case PortNum_NODEINFO_APP: {
msgType = "nodeinfo";
User scratch;
User *decoded = NULL;
if (mp->which_payloadVariant == MeshPacket_decoded_tag) {
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &User_msg, &scratch)) {
decoded = &scratch;
msgPayload = Json::object{{"id", decoded->id},
{"longname", decoded->long_name},
{"shortname", decoded->short_name},
{"hardware", decoded->hw_model}};
} else
DEBUG_MSG("Error decoding protobuf for nodeinfo message!\n");
};
break;
}
case PortNum_POSITION_APP: {
msgType = "position";
Position scratch;
Position *decoded = NULL;
if (mp->which_payloadVariant == MeshPacket_decoded_tag) {
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &Position_msg, &scratch)) {
decoded = &scratch;
msgPayload = Json::object{
{"latitude_i", decoded->latitude_i}, {"longitude_i", decoded->longitude_i}, {"altitude", decoded->altitude}};
} else {
DEBUG_MSG("Error decoding protobuf for position message!\n");
}
};
break;
}
// add more packet types here if needed
default:
break;
}
// assemble the final jsonObj
Json jsonObj = Json::object{{"id", Json((int)mp->id)},
{"timestamp", Json((int)mp->rx_time)},
{"to", Json((int)mp->to)},
{"from", Json((int)mp->from)},
{"channel", Json((int)mp->channel)},
{"type", msgType.c_str()},
{"sender", owner.id},
{"payload", msgPayload}};
// serialize and return it
std::string jsonStr = jsonObj.dump();
DEBUG_MSG("serialized json message: %s\n", jsonStr.c_str());
return jsonStr.c_str();
}
+3
View File
@@ -57,6 +57,9 @@ class MQTT : private concurrency::OSThread
/// Called when a new publish arrives from the MQTT server
void onPublish(char *topic, byte *payload, unsigned int length);
/// Called when a new publish arrives from the MQTT server
String downstreamPacketToJson(MeshPacket *mp);
/// Return 0 if sleep is okay, veto sleep if we are connected to pubsub server
// int preflightSleepCb(void *unused = NULL) { return pubSub.connected() ? 1 : 0; }
};
+23 -1
View File
@@ -1,3 +1,5 @@
#ifndef USE_NEW_ESP32_BLUETOOTH
#include "BluetoothUtil.h"
#include "BluetoothSoftwareUpdate.h"
#include "NimbleBluetoothAPI.h"
@@ -23,6 +25,8 @@ static uint32_t doublepressed;
static bool bluetoothActive;
//put the wider device into a bluetooth pairing mode, and show the pin on screen.
//called in this file only
static void startCb(uint32_t pin)
{
pinShowing = true;
@@ -30,6 +34,8 @@ static void startCb(uint32_t pin)
screen->startBluetoothPinScreen(pin);
};
//pairing has ended
//called in this file only
static void stopCb()
{
if (pinShowing) {
@@ -52,6 +58,8 @@ void updateBatteryLevel(uint8_t level)
// FIXME
}
//shutdown the bluetooth and tear down all the data structures. to prevent memory leaks
//called here only
void deinitBLE()
{
if (bluetoothActive) {
@@ -85,6 +93,7 @@ void loopBLE()
extern "C" void ble_store_config_init(void);
/// Print a macaddr - bytes are sometimes stored in reverse order
//called here only
static void print_addr(const uint8_t v[], bool isReversed = true)
{
const int macaddrlen = 6;
@@ -96,6 +105,7 @@ static void print_addr(const uint8_t v[], bool isReversed = true)
/**
* Logs information about a connection to the console.
* called here only
*/
static void print_conn_desc(struct ble_gap_conn_desc *desc)
{
@@ -260,6 +270,8 @@ static int gap_event(struct ble_gap_event *event, void *arg)
* Enables advertising with the following parameters:
* o General discoverable mode.
* o Undirected connectable mode.
*
* Called here only
*/
static void advertise(void)
{
@@ -324,12 +336,16 @@ static void advertise(void)
}
}
//callback
//doesn't do anything
static void on_reset(int reason)
{
// 19 == BLE_HS_ETIMEOUT_HCI
DEBUG_MSG("Resetting state; reason=%d\n", reason);
}
//callback
//
static void on_sync(void)
{
int rc;
@@ -356,6 +372,7 @@ static void on_sync(void)
advertise();
}
//do the bluetooth tasks
static void ble_host_task(void *param)
{
DEBUG_MSG("BLE task running\n");
@@ -366,6 +383,7 @@ static void ble_host_task(void *param)
nimble_port_freertos_deinit(); // delete the task
}
//saves the stream handles when characteristics are successfully registered
void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
{
char buf[BLE_UUID_STR_LEN];
@@ -405,6 +423,8 @@ void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
*
* If a read, the provided value will be returned over bluetooth. If a write, the value from the received packet
* will be written into the variable.
*
* used a few places
*/
int chr_readwrite32le(uint32_t *v, struct ble_gatt_access_ctxt *ctxt)
{
@@ -637,4 +657,6 @@ void updateBatteryLevel(uint8_t level)
BLEServer *serve = initBLE(, , getDeviceName(), HW_VENDOR, optstr(APP_VERSION),
optstr(HW_VERSION)); // FIXME, use a real name based on the macaddr
#endif
#endif
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
+5 -1
View File
@@ -1,3 +1,5 @@
#ifndef USE_NEW_ESP32_BLUETOOTH
#pragma once
#include <functional>
@@ -28,4 +30,6 @@ int chr_readwrite32le(uint32_t *v, struct ble_gatt_access_ctxt *ctxt);
/**
* A helper for readwrite access to an array of bytes (with no endian conversion)
*/
int chr_readwrite8(uint8_t *v, size_t vlen, struct ble_gatt_access_ctxt *ctxt);
int chr_readwrite8(uint8_t *v, size_t vlen, struct ble_gatt_access_ctxt *ctxt);
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
+4
View File
@@ -1,3 +1,5 @@
#ifndef USE_NEW_ESP32_BLUETOOTH
#include "NimbleBluetoothAPI.h"
#include "PhoneAPI.h"
#include "configuration.h"
@@ -69,3 +71,5 @@ int fromnum_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt
{
return chr_readwrite32le(&fromNum, ctxt);
}
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
+4
View File
@@ -1,3 +1,5 @@
#ifndef USE_NEW_ESP32_BLUETOOTH
#pragma once
#include "PhoneAPI.h"
@@ -17,3 +19,5 @@ protected:
};
extern PhoneAPI *bluetoothPhoneAPI;
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
+4
View File
@@ -1,3 +1,5 @@
#ifndef USE_NEW_ESP32_BLUETOOTH
#include "NimbleDefs.h"
// NRF52 wants these constants as byte arrays
@@ -44,3 +46,5 @@ const struct ble_gatt_svc_def gatt_svr_svcs[] = {
0, /* No more services. */
},
};
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
+5 -1
View File
@@ -1,3 +1,5 @@
#ifndef USE_NEW_ESP32_BLUETOOTH
#pragma once
// Keep nimble #defs from messing up the build
@@ -28,4 +30,6 @@ extern const ble_uuid128_t mesh_service_uuid, fromnum_uuid;
#ifdef __cplusplus
};
#endif
#endif
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
+2 -1
View File
@@ -289,6 +289,7 @@ void enableModemSleep()
config.max_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
config.min_freq_mhz = 20; // 10Mhz is minimum recommended
config.light_sleep_enable = false;
DEBUG_MSG("Sleep request result %x\n", esp_pm_configure(&config));
int rv = esp_pm_configure(&config);
DEBUG_MSG("Sleep request result %x\n", rv);
}
#endif