Merge branch 'meshtastic:master' into router
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,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
@@ -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
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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
@@ -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:
|
||||
/**
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user