mirror of
https://github.com/meshtastic/firmware.git
synced 2026-02-06 17:11:52 +00:00
Compare commits
1 Commits
zps-module
...
thinknode-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e65ce4d21c |
@@ -50,7 +50,6 @@ build_flags = -Wno-missing-field-initializers
|
|||||||
-DRADIOLIB_EXCLUDE_APRS=1
|
-DRADIOLIB_EXCLUDE_APRS=1
|
||||||
-DRADIOLIB_EXCLUDE_LORAWAN=1
|
-DRADIOLIB_EXCLUDE_LORAWAN=1
|
||||||
-DMESHTASTIC_EXCLUDE_DROPZONE=1
|
-DMESHTASTIC_EXCLUDE_DROPZONE=1
|
||||||
-DMESHTASTIC_EXCLUDE_ZPS=1
|
|
||||||
-DMESHTASTIC_EXCLUDE_REPLYBOT=1
|
-DMESHTASTIC_EXCLUDE_REPLYBOT=1
|
||||||
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
|
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
|
||||||
-DMESHTASTIC_EXCLUDE_HEALTH_TELEMETRY=1
|
-DMESHTASTIC_EXCLUDE_HEALTH_TELEMETRY=1
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ extern MemGet memGet;
|
|||||||
#define LED_STATE_ON 1
|
#define LED_STATE_ON 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// WIFI LED
|
||||||
|
#ifndef WIFI_STATE_ON
|
||||||
|
#define WIFI_STATE_ON 1
|
||||||
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// DEBUG
|
// DEBUG
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -147,7 +152,9 @@ extern "C" void logLegacy(const char *level, const char *fmt, ...);
|
|||||||
// Default Bluetooth PIN
|
// Default Bluetooth PIN
|
||||||
#define defaultBLEPin 123456
|
#define defaultBLEPin 123456
|
||||||
|
|
||||||
#if HAS_ETHERNET && !defined(USE_WS5500)
|
#if HAS_ETHERNET && defined(USE_CH390D)
|
||||||
|
#include <ESP32_CH390.h>
|
||||||
|
#elif HAS_ETHERNET && !defined(USE_WS5500)
|
||||||
#include <RAK13800_W5100S.h>
|
#include <RAK13800_W5100S.h>
|
||||||
#endif // HAS_ETHERNET
|
#endif // HAS_ETHERNET
|
||||||
|
|
||||||
|
|||||||
@@ -361,7 +361,7 @@ void setup()
|
|||||||
|
|
||||||
#ifdef WIFI_LED
|
#ifdef WIFI_LED
|
||||||
pinMode(WIFI_LED, OUTPUT);
|
pinMode(WIFI_LED, OUTPUT);
|
||||||
digitalWrite(WIFI_LED, LOW);
|
digitalWrite(WIFI_LED, HIGH ^ WIFI_STATE_ON);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BLE_LED
|
#ifdef BLE_LED
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ template class LR11x0Interface<LR1121>;
|
|||||||
template class SX126xInterface<STM32WLx>;
|
template class SX126xInterface<STM32WLx>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_ETHERNET && !defined(USE_WS5500)
|
#if HAS_ETHERNET && !defined(USE_WS5500) && !defined(USE_CH390D)
|
||||||
#include "api/ethServerAPI.h"
|
#include "api/ethServerAPI.h"
|
||||||
template class ServerAPI<EthernetClient>;
|
template class ServerAPI<EthernetClient>;
|
||||||
template class APIServerPort<ethServerAPI, EthernetServer>;
|
template class APIServerPort<ethServerAPI, EthernetServer>;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#if HAS_ETHERNET && !defined(USE_WS5500)
|
#if HAS_ETHERNET && !defined(USE_WS5500) && !defined(USE_CH390D)
|
||||||
|
|
||||||
#include "ethServerAPI.h"
|
#include "ethServerAPI.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ServerAPI.h"
|
#include "ServerAPI.h"
|
||||||
#ifndef USE_WS5500
|
#if !defined(USE_WS5500) && !defined(USE_CH390D)
|
||||||
#include <RAK13800_W5100S.h>
|
#include <RAK13800_W5100S.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -384,13 +384,13 @@ static void WiFiEvent(WiFiEvent_t event)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef WIFI_LED
|
#ifdef WIFI_LED
|
||||||
digitalWrite(WIFI_LED, HIGH);
|
digitalWrite(WIFI_LED, LOW ^ WIFI_STATE_ON);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||||
LOG_INFO("Disconnected from WiFi access point");
|
LOG_INFO("Disconnected from WiFi access point");
|
||||||
#ifdef WIFI_LED
|
#ifdef WIFI_LED
|
||||||
digitalWrite(WIFI_LED, LOW);
|
digitalWrite(WIFI_LED, HIGH ^ WIFI_STATE_ON);
|
||||||
#endif
|
#endif
|
||||||
if (!isReconnecting) {
|
if (!isReconnecting) {
|
||||||
WiFi.disconnect(false, true);
|
WiFi.disconnect(false, true);
|
||||||
@@ -442,13 +442,13 @@ static void WiFiEvent(WiFiEvent_t event)
|
|||||||
case ARDUINO_EVENT_WIFI_AP_START:
|
case ARDUINO_EVENT_WIFI_AP_START:
|
||||||
LOG_INFO("WiFi access point started");
|
LOG_INFO("WiFi access point started");
|
||||||
#ifdef WIFI_LED
|
#ifdef WIFI_LED
|
||||||
digitalWrite(WIFI_LED, HIGH);
|
digitalWrite(WIFI_LED, LOW ^ WIFI_STATE_ON);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_AP_STOP:
|
case ARDUINO_EVENT_WIFI_AP_STOP:
|
||||||
LOG_INFO("WiFi access point stopped");
|
LOG_INFO("WiFi access point stopped");
|
||||||
#ifdef WIFI_LED
|
#ifdef WIFI_LED
|
||||||
digitalWrite(WIFI_LED, LOW);
|
digitalWrite(WIFI_LED, HIGH ^ WIFI_STATE_ON);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
|
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
|
||||||
|
|||||||
@@ -1274,7 +1274,7 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_ETHERNET && !defined(USE_WS5500)
|
#if HAS_ETHERNET && !defined(USE_WS5500) && !defined(USE_CH390D)
|
||||||
conn.has_ethernet = true;
|
conn.has_ethernet = true;
|
||||||
conn.ethernet.has_status = true;
|
conn.ethernet.has_status = true;
|
||||||
if (Ethernet.linkStatus() == LinkON) {
|
if (Ethernet.linkStatus() == LinkON) {
|
||||||
|
|||||||
@@ -94,10 +94,6 @@
|
|||||||
#include "modules/StatusMessageModule.h"
|
#include "modules/StatusMessageModule.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !MESHTASTIC_EXCLUDE_ZPS
|
|
||||||
#include "modules/esp32/ZPSModule.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(HAS_HARDWARE_WATCHDOG)
|
#if defined(HAS_HARDWARE_WATCHDOG)
|
||||||
#include "watchdog/watchdogThread.h"
|
#include "watchdog/watchdogThread.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -160,9 +156,6 @@ void setupModules()
|
|||||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
#if !MESHTASTIC_EXCLUDE_STATUS
|
||||||
statusMessageModule = new StatusMessageModule();
|
statusMessageModule = new StatusMessageModule();
|
||||||
#endif
|
#endif
|
||||||
#if !MESHTASTIC_EXCLUDE_ZPS
|
|
||||||
zpsModule = new ZPSModule();
|
|
||||||
#endif
|
|
||||||
#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE
|
#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE
|
||||||
new GenericThreadModule();
|
new GenericThreadModule();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,419 +0,0 @@
|
|||||||
/*
|
|
||||||
* ZPS - Zero-GPS Positioning System for standalone Meshtastic devices
|
|
||||||
* - experimental tools for estimating own position without a GPS -
|
|
||||||
*
|
|
||||||
* Copyright 2021 all rights reserved by https://github.com/a-f-G-U-C
|
|
||||||
* Released under GPL v3 (see LICENSE file for details)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ZPSModule.h"
|
|
||||||
#include "Default.h"
|
|
||||||
#include "MeshService.h"
|
|
||||||
#include "NodeDB.h"
|
|
||||||
#include "NodeStatus.h"
|
|
||||||
#include "Router.h"
|
|
||||||
#include "configuration.h"
|
|
||||||
#include "gps/RTC.h"
|
|
||||||
#include <WiFi.h>
|
|
||||||
|
|
||||||
#if !defined(MESHTASTIC_EXCLUDE_BLUETOOTH)
|
|
||||||
|
|
||||||
#include "NimBLEDevice.h"
|
|
||||||
|
|
||||||
#define BLE_MAX_REC 15
|
|
||||||
#define BLE_NO_RESULTS -1 // Indicates a BLE scan is in progress
|
|
||||||
|
|
||||||
uint8_t bleCounter = 0; // used internally by the ble scanner
|
|
||||||
uint64_t bleResult[BLE_MAX_REC + 1];
|
|
||||||
int bleResSize = BLE_NO_RESULTS;
|
|
||||||
|
|
||||||
uint64_t scanStart = 0;
|
|
||||||
|
|
||||||
ZPSModule *zpsModule;
|
|
||||||
|
|
||||||
// Mini BLE scanner, NIMBLE based and modelled loosely after the Wifi scanner
|
|
||||||
static int ble_scan(uint32_t duration, bool passive = true, bool dedup = true);
|
|
||||||
|
|
||||||
// ZPSModule::ZPSModule()
|
|
||||||
// : ProtobufModule("ZPS", ZPS_PORTNUM, Position_fields), concurrency::OSThread("ZPSModule")
|
|
||||||
ZPSModule::ZPSModule() : SinglePortModule("ZPS", ZPS_PORTNUM), concurrency::OSThread("ZPSModule")
|
|
||||||
{
|
|
||||||
setIntervalFromNow(ZPS_STARTUP_DELAY); // Delay startup by 10 seconds, no need to race :)
|
|
||||||
|
|
||||||
wantBSS = true;
|
|
||||||
wantBLE = true;
|
|
||||||
|
|
||||||
WiFi.mode(WIFI_STA);
|
|
||||||
WiFi.disconnect();
|
|
||||||
WiFi.scanNetworks(true, true); // nonblock, showhidden
|
|
||||||
scanState = SCAN_BSS_RUN;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessMessage ZPSModule::handleReceived(const meshtastic_MeshPacket &mp)
|
|
||||||
{
|
|
||||||
meshtastic_Position pos = meshtastic_Position_init_default;
|
|
||||||
|
|
||||||
auto &pd = mp.decoded;
|
|
||||||
uint8_t nRecs = pd.payload.size >> 3;
|
|
||||||
|
|
||||||
LOG_DEBUG("handleReceived %s 0x%0x->0x%0x, id=0x%x, port=%d, len=%d, rec=%d\n", name, mp.from, mp.to, mp.id, pd.portnum,
|
|
||||||
pd.payload.size, nRecs);
|
|
||||||
if (nRecs > ZPS_DATAPKT_MAXITEMS)
|
|
||||||
nRecs = ZPS_DATAPKT_MAXITEMS;
|
|
||||||
memcpy(&netData, pd.payload.bytes, nRecs << 3);
|
|
||||||
|
|
||||||
// Currently we are unable to act as a position server, so we're
|
|
||||||
// not interested in broadcasts (this will change later)
|
|
||||||
if (mp.to != nodeDB->getNodeNum()) {
|
|
||||||
// Message is not for us, won't process
|
|
||||||
return ProcessMessage::CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ZPS_EXTRAVERBOSE
|
|
||||||
for (int i = 0; i < nRecs; i++) {
|
|
||||||
LOG_DEBUG("ZPS[%d]: %08x"
|
|
||||||
"%08x\n",
|
|
||||||
i, (uint32_t)(netData[i] >> 32), (uint32_t)netData[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((netData[0] & 0x800000000000) && (nRecs >= 2)) {
|
|
||||||
// message contains a position
|
|
||||||
pos.PDOP = (netData[0] >> 40) & 0x7f;
|
|
||||||
pos.timestamp = netData[0] & 0xffffffff;
|
|
||||||
// second int64 encodes lat and lon
|
|
||||||
pos.longitude_i = (int32_t)(netData[1] & 0xffffffff);
|
|
||||||
pos.latitude_i = (int32_t)((netData[1] >> 32) & 0xffffffff);
|
|
||||||
|
|
||||||
// FIXME should be conditional, to ensure we don't overwrite a good GPS fix!
|
|
||||||
LOG_DEBUG("ZPS lat/lon/dop/pts %d/%d/%d/%d\n", pos.latitude_i, pos.longitude_i, pos.PDOP, pos.timestamp);
|
|
||||||
|
|
||||||
// Some required fields
|
|
||||||
pos.time = getTime();
|
|
||||||
pos.location_source = meshtastic_Position_LocSource_LOC_EXTERNAL;
|
|
||||||
|
|
||||||
// don't update position if my gps fix is valid
|
|
||||||
if (nodeDB->hasValidPosition(nodeDB->getMeshNode(nodeDB->getNodeNum()))) {
|
|
||||||
LOG_DEBUG("ZPSModule::handleReceived: ignoring position update, GPS is valid\n");
|
|
||||||
return ProcessMessage::CONTINUE;
|
|
||||||
}
|
|
||||||
nodeDB->updatePosition(nodeDB->getNodeNum(), pos);
|
|
||||||
} else {
|
|
||||||
// nothing we can do - for now
|
|
||||||
return ProcessMessage::CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
|
||||||
}
|
|
||||||
|
|
||||||
meshtastic_MeshPacket *ZPSModule::allocReply()
|
|
||||||
{
|
|
||||||
meshtastic_MeshPacket *p = allocDataPacket();
|
|
||||||
p->decoded.payload.size = (netRecs + 2) << 3; // actually can be only +1 if no GPS data
|
|
||||||
|
|
||||||
LOG_DEBUG("Allocating dataPacket for %d items, %d bytes\n", netRecs, p->decoded.payload.size);
|
|
||||||
memcpy(p->decoded.payload.bytes, &netData, p->decoded.payload.size);
|
|
||||||
|
|
||||||
return (p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZPSModule::sendDataPacket(NodeNum dest, bool wantReplies)
|
|
||||||
{
|
|
||||||
// cancel any not yet sent (now stale) position packets
|
|
||||||
if (prevPacketId)
|
|
||||||
service->cancelSending(prevPacketId);
|
|
||||||
|
|
||||||
meshtastic_MeshPacket *p = allocReply();
|
|
||||||
p->to = dest;
|
|
||||||
p->decoded.portnum = meshtastic_PortNum_ZPS_APP;
|
|
||||||
p->decoded.want_response = wantReplies;
|
|
||||||
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
|
|
||||||
prevPacketId = p->id;
|
|
||||||
|
|
||||||
service->sendToMesh(p, RX_SRC_LOCAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t ZPSModule::runOnce()
|
|
||||||
{
|
|
||||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
|
||||||
assert(node);
|
|
||||||
|
|
||||||
// LOG_DEBUG("ZPSModule::runOnce() START, scanState: %d\n", (int) scanState);
|
|
||||||
|
|
||||||
int numWifi = 0;
|
|
||||||
|
|
||||||
if (scanState == SCAN_BSS_RUN) {
|
|
||||||
// check completion status of any running Wifi scan
|
|
||||||
numWifi = WiFi.scanComplete();
|
|
||||||
|
|
||||||
if (numWifi >= 0) {
|
|
||||||
// scan is complete
|
|
||||||
LOG_DEBUG("%d BSS found\n", numWifi);
|
|
||||||
LOG_DEBUG("BSS scan done in %d millis\n", millis() - scanStart);
|
|
||||||
|
|
||||||
if (wantBSS && haveBSS) {
|
|
||||||
// old data exists, overwrite it
|
|
||||||
netRecs = 0;
|
|
||||||
haveBSS = haveBLE = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < numWifi; i++) {
|
|
||||||
// pack each Wifi network record into a 64-bit int
|
|
||||||
uint64_t netBytes = encodeBSS(WiFi.BSSID(i), WiFi.channel(i), abs(WiFi.RSSI(i)));
|
|
||||||
|
|
||||||
if (wantBSS) {
|
|
||||||
// load into outbound array if needed
|
|
||||||
outBufAdd(netBytes);
|
|
||||||
haveBSS = true;
|
|
||||||
}
|
|
||||||
#ifdef ZPS_EXTRAVERBOSE
|
|
||||||
LOG_DEBUG("BSS[%02d]: %08x"
|
|
||||||
"%08x\n",
|
|
||||||
i, (uint32_t)(netBytes >> 32), (uint32_t)netBytes);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
WiFi.scanDelete();
|
|
||||||
scanState = SCAN_BSS_DONE;
|
|
||||||
|
|
||||||
#ifdef ZPS_EXTRAVERBOSE
|
|
||||||
} else if (numWifi == -1) {
|
|
||||||
// LOG_DEBUG("BSS scan in-progress\n");
|
|
||||||
} else {
|
|
||||||
LOG_DEBUG("BSS scan state=%d\n", numWifi);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((scanState == SCAN_BLE_RUN) && (bleResSize >= 0)) {
|
|
||||||
// completion status checked above (bleResSize >= 0)
|
|
||||||
LOG_DEBUG("BLE scan done in %d millis\n", millis() - scanStart);
|
|
||||||
scanState = SCAN_BLE_DONE;
|
|
||||||
|
|
||||||
if (wantBLE && haveBLE) {
|
|
||||||
// old data exists, overwrite it
|
|
||||||
netRecs = 0;
|
|
||||||
haveBSS = haveBLE = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < bleResSize; i++) {
|
|
||||||
// load data into output array if needed
|
|
||||||
if (wantBLE) {
|
|
||||||
outBufAdd(bleResult[i]);
|
|
||||||
haveBLE = true;
|
|
||||||
}
|
|
||||||
#ifdef ZPS_EXTRAVERBOSE
|
|
||||||
LOG_DEBUG("BLE[%d]: %08x"
|
|
||||||
"%08x\n",
|
|
||||||
i, (uint32_t)(bleResult[i] >> 32), (uint32_t)bleResult[i]);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the counter once we're done with the dataset
|
|
||||||
bleResSize = BLE_NO_RESULTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Are we finished assembling that packet? Then send it out
|
|
||||||
if ((wantBSS == haveBSS) && (wantBLE == haveBLE) &&
|
|
||||||
airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
|
|
||||||
airTime->isTxAllowedAirUtil() &&
|
|
||||||
(lastSend == 0 || millis() - lastSend >= Default::getConfiguredOrDefaultMsScaled(config.position.position_broadcast_secs,
|
|
||||||
default_broadcast_interval_secs,
|
|
||||||
nodeStatus->getNumOnline()))) {
|
|
||||||
|
|
||||||
haveBSS = haveBLE = false;
|
|
||||||
sendDataPacket(NODENUM_BROADCAST, false); // no replies
|
|
||||||
lastSend = millis();
|
|
||||||
netRecs = 0; // reset packet
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* State machine transitions
|
|
||||||
*
|
|
||||||
* FIXME could be managed better, for example: check if we require
|
|
||||||
* each type of scan (wantBSS/wantBLE), and if not, don't start it!
|
|
||||||
*/
|
|
||||||
if (scanState == SCAN_BLE_DONE) {
|
|
||||||
// BLE done, transition to BSS scanning
|
|
||||||
scanStart = millis();
|
|
||||||
LOG_DEBUG("BSS scan start t=%d\n", scanStart);
|
|
||||||
if (WiFi.scanNetworks(true, true) == WIFI_SCAN_RUNNING) // nonblock, showhidden
|
|
||||||
scanState = SCAN_BSS_RUN;
|
|
||||||
|
|
||||||
} else if (scanState == SCAN_BSS_DONE) {
|
|
||||||
// BSS done, transition to BLE scanning
|
|
||||||
scanStart = millis();
|
|
||||||
LOG_DEBUG("BLE scan start t=%d\n", scanStart);
|
|
||||||
if (ble_scan(ZPS_BLE_SCANTIME) == 0)
|
|
||||||
scanState = SCAN_BLE_RUN;
|
|
||||||
}
|
|
||||||
|
|
||||||
// LOG_DEBUG("ZPSModule::runOnce() DONE, scanState=%d\n", scanState);
|
|
||||||
if ((scanState == SCAN_BSS_RUN) || (scanState == SCAN_BLE_RUN)) {
|
|
||||||
return 1000; // scan in progress, re-check soon
|
|
||||||
}
|
|
||||||
|
|
||||||
return 5000;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t encodeBSS(uint8_t *bssid, uint8_t chan, uint8_t absRSSI)
|
|
||||||
{
|
|
||||||
uint64_t netBytes = absRSSI & 0xff;
|
|
||||||
netBytes <<= 8;
|
|
||||||
netBytes |= (chan & 0xff);
|
|
||||||
|
|
||||||
for (uint8_t b = 0; b < 6; b++) {
|
|
||||||
netBytes <<= 8;
|
|
||||||
netBytes |= bssid[b];
|
|
||||||
}
|
|
||||||
|
|
||||||
return netBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t encodeBLE(uint8_t *addr, uint8_t absRSSI)
|
|
||||||
{
|
|
||||||
uint64_t netBytes = absRSSI & 0xff;
|
|
||||||
netBytes <<= 8;
|
|
||||||
netBytes |= 0xff; // "channel" byte reserved in BLE records
|
|
||||||
|
|
||||||
for (uint8_t b = 0; b < 6; b++) {
|
|
||||||
netBytes <<= 8;
|
|
||||||
netBytes |= addr[5 - b] & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
return netBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event handler
|
|
||||||
*/
|
|
||||||
static int ble_gap_event(struct ble_gap_event *event, void *arg)
|
|
||||||
{
|
|
||||||
// Adverts matching certain patterns are useless for positioning purposes
|
|
||||||
// (ephemeral MAC etc), so try excluding them if possible
|
|
||||||
//
|
|
||||||
// TODO: Expand the list of reject patterns for BLE adverts.
|
|
||||||
// There are likely more than 10 patterns to test and reject, including most Apple devices and others.
|
|
||||||
//
|
|
||||||
// TODO: Implement full packet search for reject patterns (use memmem() or similar),
|
|
||||||
// not just at the beginning (currently uses memcmp()).
|
|
||||||
|
|
||||||
const uint8_t rejPat[] = {0x1e, 0xff, 0x06, 0x00, 0x01}; // one of many
|
|
||||||
|
|
||||||
struct ble_hs_adv_fields fields;
|
|
||||||
int rc;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
uint64_t netBytes = 0;
|
|
||||||
|
|
||||||
switch (event->type) {
|
|
||||||
case BLE_GAP_EVENT_DISC:
|
|
||||||
// called once for every BLE advert received
|
|
||||||
rc = ble_hs_adv_parse_fields(&fields, event->disc.data, event->disc.length_data);
|
|
||||||
if (rc != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (bleResSize != BLE_NO_RESULTS)
|
|
||||||
// as far as we know, we're not in the middle of a BLE scan!
|
|
||||||
LOG_DEBUG("Unexpected BLE_GAP_EVENT_DISC!\n");
|
|
||||||
|
|
||||||
#ifdef ZPS_EXTRAVERBOSE
|
|
||||||
// Dump the advertisement packet
|
|
||||||
DEBUG_PORT.hexDump("DEBUG", (unsigned char *)event->disc.data, event->disc.length_data);
|
|
||||||
#endif
|
|
||||||
// Reject beacons known to be unreliable (ephemeral etc)
|
|
||||||
if (memcmp(event->disc.data, rejPat, sizeof(rejPat)) == 0) {
|
|
||||||
LOG_DEBUG("(BLE item filtered by pattern)\n");
|
|
||||||
return 0; // Processing-wise, it's still a success
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// STORE THE RESULTS IN A SORTED LIST
|
|
||||||
//
|
|
||||||
|
|
||||||
// first, pack each BLE item reading into a 64-bit int
|
|
||||||
netBytes = encodeBLE(event->disc.addr.val, abs(event->disc.rssi));
|
|
||||||
|
|
||||||
// SOME DUPLICATES SURVIVE through filter_duplicates = 1, catch them here
|
|
||||||
// Duplicate filtering is now handled in the sorting loop below,
|
|
||||||
// but right now we write for clarity not optimization
|
|
||||||
for (i = 0; i < bleCounter; i++) {
|
|
||||||
if ((bleResult[i] & 0xffffffffffff) == (netBytes & 0xffffffffffff)) {
|
|
||||||
LOG_DEBUG("(BLE duplicate filtered)\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ZPS_EXTRAVERBOSE
|
|
||||||
// redundant extraverbosity, but I need it for duplicate hunting
|
|
||||||
LOG_DEBUG("BL_[%02d]: %08x"
|
|
||||||
"%08x\n",
|
|
||||||
bleCounter, (uint32_t)(netBytes >> 32), (uint32_t)netBytes);
|
|
||||||
#endif
|
|
||||||
// then insert item into a list (up to BLE_MAX_REC records), sorted by RSSI
|
|
||||||
for (i = 0; i < bleCounter; i++) {
|
|
||||||
// find first element greater than ours, that will be our insertion point
|
|
||||||
if (bleResult[i] > netBytes)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// any other records move down one position to vacate res[i]
|
|
||||||
for (int j = bleCounter; j > i; j--)
|
|
||||||
bleResult[j] = bleResult[j - 1];
|
|
||||||
// write new element at insertion point
|
|
||||||
bleResult[i] = netBytes;
|
|
||||||
|
|
||||||
// advance tail of list, but not beyond limit
|
|
||||||
if (bleCounter < BLE_MAX_REC)
|
|
||||||
bleCounter++;
|
|
||||||
|
|
||||||
return 0; // SUCCESS
|
|
||||||
|
|
||||||
case BLE_GAP_EVENT_DISC_COMPLETE:
|
|
||||||
LOG_DEBUG("EVENT_DISC_COMPLETE in %d millis\n", (millis() - scanStart));
|
|
||||||
LOG_DEBUG("%d BLE found\n", bleCounter);
|
|
||||||
bleResSize = bleCounter;
|
|
||||||
|
|
||||||
bleCounter = 0; // reset counter
|
|
||||||
return 0; // SUCCESS
|
|
||||||
|
|
||||||
default:
|
|
||||||
return 0; // SUCCESS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initiates the GAP general discovery procedure (non-blocking)
|
|
||||||
*/
|
|
||||||
static int ble_scan(uint32_t duration, bool passive, bool dedup)
|
|
||||||
{
|
|
||||||
uint8_t own_addr_type;
|
|
||||||
struct ble_gap_disc_params disc_params;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
// Figure out address type to use
|
|
||||||
rc = ble_hs_id_infer_auto(0, &own_addr_type);
|
|
||||||
if (rc != 0) {
|
|
||||||
LOG_DEBUG("error determining address type; rc=%d\n", rc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scanning parameters, these are mostly default
|
|
||||||
disc_params.itvl = 0;
|
|
||||||
disc_params.window = 0;
|
|
||||||
disc_params.filter_policy = 0;
|
|
||||||
disc_params.limited = 0;
|
|
||||||
|
|
||||||
// These two params are the more interesting ones
|
|
||||||
disc_params.filter_duplicates = dedup; // self-explanatory
|
|
||||||
disc_params.passive = passive; // passive uses less power
|
|
||||||
|
|
||||||
// Start scanning process (non-blocking) and return
|
|
||||||
rc = ble_gap_disc(own_addr_type, duration, &disc_params, ble_gap_event, NULL);
|
|
||||||
if (rc != 0) {
|
|
||||||
LOG_DEBUG("error initiating GAP discovery; rc=%d\n", rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // MESHTASTIC_EXCLUDE_BLUETOOTH
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "SinglePortModule.h"
|
|
||||||
#include "concurrency/OSThread.h"
|
|
||||||
#include "gps/RTC.h"
|
|
||||||
|
|
||||||
#define ZPS_PORTNUM meshtastic_PortNum_ZPS_APP
|
|
||||||
|
|
||||||
#define ZPS_DATAPKT_MAXITEMS 20 // max number of records to pack in an outbound packet (~10)
|
|
||||||
#define ZPS_STARTUP_DELAY 10000 // Module startup delay in millis
|
|
||||||
|
|
||||||
// Duration of a BLE scan in millis.
|
|
||||||
// We want this number to be SLIGHTLY UNDER an integer number of seconds,
|
|
||||||
// to be able to catch the result as fresh as possible on a 1-second polling loop
|
|
||||||
#define ZPS_BLE_SCANTIME 2900 // millis
|
|
||||||
|
|
||||||
enum SCANSTATE { SCAN_NONE, SCAN_BSS_RUN, SCAN_BSS_DONE, SCAN_BLE_RUN, SCAN_BLE_DONE };
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Data packing "compression" functions
|
|
||||||
* Ingest a WiFi BSSID, channel and RSSI (or BLE address and RSSI)
|
|
||||||
* and encode them into a packed uint64
|
|
||||||
*/
|
|
||||||
uint64_t encodeBSS(uint8_t *bssid, uint8_t chan, uint8_t absRSSI);
|
|
||||||
uint64_t encodeBLE(uint8_t *addr, uint8_t absRSSI);
|
|
||||||
|
|
||||||
class ZPSModule : public SinglePortModule, 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;
|
|
||||||
|
|
||||||
/// We limit our broadcasts to a max rate
|
|
||||||
uint32_t lastSend = 0;
|
|
||||||
|
|
||||||
bool wantBSS = true;
|
|
||||||
bool haveBSS = false;
|
|
||||||
|
|
||||||
bool wantBLE = true;
|
|
||||||
bool haveBLE = false;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** Constructor
|
|
||||||
* name is for debugging output
|
|
||||||
*/
|
|
||||||
ZPSModule();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send our radio environment data into the mesh
|
|
||||||
*/
|
|
||||||
void sendDataPacket(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** Called to handle a particular incoming message
|
|
||||||
@return true if you've guaranteed you've handled this message and no other handlers should be considered for it
|
|
||||||
*/
|
|
||||||
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp);
|
|
||||||
|
|
||||||
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked
|
|
||||||
* so that subclasses can (optionally) send a response back to the original sender. */
|
|
||||||
virtual meshtastic_MeshPacket *allocReply();
|
|
||||||
|
|
||||||
/** Does our periodic broadcast */
|
|
||||||
virtual int32_t runOnce();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// outbound data packet staging buffer and record counter
|
|
||||||
uint64_t netData[ZPS_DATAPKT_MAXITEMS + 2] = {0};
|
|
||||||
uint8_t netRecs = 0;
|
|
||||||
|
|
||||||
// mini state machine to alternate between BSS(Wifi) and BLE scanning
|
|
||||||
SCANSTATE scanState = SCAN_NONE;
|
|
||||||
|
|
||||||
inline void outBufAdd(uint64_t netBytes)
|
|
||||||
{
|
|
||||||
// If this is the first record, initialize the header with the current time and reset the record count.
|
|
||||||
if (!netRecs) {
|
|
||||||
netData[0] = getTime();
|
|
||||||
netData[1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// push to buffer and update counter
|
|
||||||
if (netRecs < ZPS_DATAPKT_MAXITEMS)
|
|
||||||
netData[2 + (netRecs++)] = netBytes;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
extern ZPSModule *zpsModule;
|
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
#include <WiFiClientSecure.h>
|
#include <WiFiClientSecure.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if HAS_ETHERNET && !defined(USE_WS5500)
|
#if HAS_ETHERNET && !defined(USE_WS5500) && !defined(USE_CH390D)
|
||||||
#include <EthernetClient.h>
|
#include <EthernetClient.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
26
variants/esp32s3/ELECROW-ThinkNode-G3/pins_arduino.h
Normal file
26
variants/esp32s3/ELECROW-ThinkNode-G3/pins_arduino.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef Pins_Arduino_h
|
||||||
|
#define Pins_Arduino_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define USB_VID 0x303a
|
||||||
|
#define USB_PID 0x1001
|
||||||
|
|
||||||
|
// The default Wire will be mapped to PMU and RTC
|
||||||
|
static const uint8_t SDA = 17;
|
||||||
|
static const uint8_t SCL = 18;
|
||||||
|
|
||||||
|
// Default SPI will be mapped to Radio
|
||||||
|
static const uint8_t SS = 39;
|
||||||
|
static const uint8_t MOSI = 40;
|
||||||
|
static const uint8_t MISO = 41;
|
||||||
|
static const uint8_t SCK = 42;
|
||||||
|
|
||||||
|
// #define SPI_MOSI (11)
|
||||||
|
// #define SPI_SCK (10)
|
||||||
|
// #define SPI_MISO (9)
|
||||||
|
// #define SPI_CS (12)
|
||||||
|
|
||||||
|
// #define SDCARD_CS SPI_CS
|
||||||
|
|
||||||
|
#endif /* Pins_Arduino_h */
|
||||||
22
variants/esp32s3/ELECROW-ThinkNode-G3/platformio.ini
Normal file
22
variants/esp32s3/ELECROW-ThinkNode-G3/platformio.ini
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[env:thinknode_g3]
|
||||||
|
extends = esp32s3_base
|
||||||
|
board = ESP32-S3-WROOM-1-N4
|
||||||
|
board_build.psram_type = opi
|
||||||
|
|
||||||
|
build_flags =
|
||||||
|
${esp32s3_base.build_flags}
|
||||||
|
-D ELECROW_ThinkNode_G3
|
||||||
|
-D HAS_UDP_MULTICAST=1
|
||||||
|
-D BOARD_HAS_PSRAM
|
||||||
|
-D PRIVATE_HW
|
||||||
|
# -D CONFIG_ETH_ENABLED=1
|
||||||
|
# -D CONFIG_ETH_USE_ESP32_EMAC=1
|
||||||
|
-I variants/esp32s3/ELECROW-ThinkNode-G3
|
||||||
|
-mfix-esp32-psram-cache-issue
|
||||||
|
|
||||||
|
lib_ignore =
|
||||||
|
Ethernet
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${esp32s3_base.lib_deps}
|
||||||
|
# file://../ESP32-CH390/ESP32-CH390-1.0.1.tar.gz
|
||||||
36
variants/esp32s3/ELECROW-ThinkNode-G3/variant.h
Normal file
36
variants/esp32s3/ELECROW-ThinkNode-G3/variant.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#define HAS_GPS 0
|
||||||
|
#define HAS_WIRE 0
|
||||||
|
#define I2C_NO_RESCAN
|
||||||
|
|
||||||
|
#define WIFI_LED 5
|
||||||
|
#define WIFI_STATE_ON 0
|
||||||
|
|
||||||
|
#define LED_PIN 6 // The blue LORA LED
|
||||||
|
#define LED_STATE_ON 0
|
||||||
|
#define BUTTON_PIN 4 // the external user button of the device, BOOT and RESET are not accessible without opening it up.
|
||||||
|
|
||||||
|
#define USE_SX1262
|
||||||
|
#define LORA_SCK 42
|
||||||
|
#define LORA_MISO 41
|
||||||
|
#define LORA_MOSI 40
|
||||||
|
#define LORA_CS 39
|
||||||
|
#define LORA_RESET 21
|
||||||
|
|
||||||
|
#define SX126X_CS LORA_CS
|
||||||
|
#define SX126X_DIO1 15
|
||||||
|
#define SX126X_BUSY 47
|
||||||
|
#define SX126X_RESET LORA_RESET
|
||||||
|
#define SX126X_DIO2_AS_RF_SWITCH
|
||||||
|
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||||
|
#define PIN_POWER_EN 45
|
||||||
|
|
||||||
|
// #define HAS_ETHERNET 1
|
||||||
|
// #define USE_CH390D 1 // this driver uses the same stack as the ESP32 Wifi driver
|
||||||
|
|
||||||
|
// #define ETH_MISO_PIN 47
|
||||||
|
// #define ETH_MOSI_PIN 21
|
||||||
|
// #define ETH_SCLK_PIN 48
|
||||||
|
// #define ETH_CS_PIN 45
|
||||||
|
// #define ETH_INT_PIN 14
|
||||||
|
// #define ETH_RST_PIN -1
|
||||||
|
// #define ETH_ADDR 1
|
||||||
Reference in New Issue
Block a user