mirror of
https://github.com/meshtastic/firmware.git
synced 2025-05-02 03:56:47 +00:00
commit
c0fbfccf43
2
proto
2
proto
@ -1 +1 @@
|
|||||||
Subproject commit b1aed06442025624841b2288fac273d9bc41c438
|
Subproject commit 0cadaed3953f66cf1edc99d0fa53e4fd5ebf56d6
|
@ -9,6 +9,7 @@ enum class Cmd {
|
|||||||
SET_OFF,
|
SET_OFF,
|
||||||
ON_PRESS,
|
ON_PRESS,
|
||||||
START_BLUETOOTH_PIN_SCREEN,
|
START_BLUETOOTH_PIN_SCREEN,
|
||||||
|
START_FIRMWARE_UPDATE_SCREEN,
|
||||||
STOP_BLUETOOTH_PIN_SCREEN,
|
STOP_BLUETOOTH_PIN_SCREEN,
|
||||||
STOP_BOOT_SCREEN,
|
STOP_BOOT_SCREEN,
|
||||||
PRINT,
|
PRINT,
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "nimble/BluetoothUtil.h"
|
#include "nimble/BluetoothUtil.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
|
#include "../graphics/Screen.h"
|
||||||
|
#include "../main.h"
|
||||||
|
|
||||||
#include <CRC32.h>
|
#include <CRC32.h>
|
||||||
#include <Update.h>
|
#include <Update.h>
|
||||||
@ -47,8 +49,9 @@ int update_size_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_
|
|||||||
// void stopMeshBluetoothService();
|
// void stopMeshBluetoothService();
|
||||||
// stopMeshBluetoothService();
|
// stopMeshBluetoothService();
|
||||||
|
|
||||||
|
screen->startFirmwareUpdateScreen();
|
||||||
if (RadioLibInterface::instance)
|
if (RadioLibInterface::instance)
|
||||||
RadioLibInterface::instance->sleep(); // FIXME, nasty hack - the RF95 ISR/SPI code on ESP32 can fail while we are
|
RadioLibInterface::instance->disable(); // FIXME, nasty hack - the RF95 ISR/SPI code on ESP32 can fail while we are
|
||||||
// writing flash - shut the radio off during updates
|
// writing flash - shut the radio off during updates
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,20 @@ static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state,
|
|||||||
display->drawString(64 + x, 48 + y, buf);
|
display->drawString(64 + x, 48 + y, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
display->drawString(64 + x, y, "Updating");
|
||||||
|
|
||||||
|
display->setFont(FONT_SMALL);
|
||||||
|
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait...");
|
||||||
|
|
||||||
|
//display->setFont(FONT_LARGE);
|
||||||
|
//display->drawString(64 + x, 26 + y, btPIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Draw the last text message we received
|
/// Draw the last text message we received
|
||||||
static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
@ -798,6 +812,9 @@ int32_t Screen::runOnce()
|
|||||||
case Cmd::START_BLUETOOTH_PIN_SCREEN:
|
case Cmd::START_BLUETOOTH_PIN_SCREEN:
|
||||||
handleStartBluetoothPinScreen(cmd.bluetooth_pin);
|
handleStartBluetoothPinScreen(cmd.bluetooth_pin);
|
||||||
break;
|
break;
|
||||||
|
case Cmd::START_FIRMWARE_UPDATE_SCREEN:
|
||||||
|
handleStartFirmwareUpdateScreen();
|
||||||
|
break;
|
||||||
case Cmd::STOP_BLUETOOTH_PIN_SCREEN:
|
case Cmd::STOP_BLUETOOTH_PIN_SCREEN:
|
||||||
case Cmd::STOP_BOOT_SCREEN:
|
case Cmd::STOP_BOOT_SCREEN:
|
||||||
setFrames();
|
setFrames();
|
||||||
@ -928,6 +945,18 @@ void Screen::handleStartBluetoothPinScreen(uint32_t pin)
|
|||||||
setFastFramerate();
|
setFastFramerate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Screen::handleStartFirmwareUpdateScreen()
|
||||||
|
{
|
||||||
|
DEBUG_MSG("showing firmware screen\n");
|
||||||
|
showingNormalScreen = false;
|
||||||
|
|
||||||
|
static FrameCallback btFrames[] = {drawFrameFirmware};
|
||||||
|
|
||||||
|
ui.disableAllIndicators();
|
||||||
|
ui.setFrames(btFrames, 1);
|
||||||
|
setFastFramerate();
|
||||||
|
}
|
||||||
|
|
||||||
void Screen::blink()
|
void Screen::blink()
|
||||||
{
|
{
|
||||||
setFastFramerate();
|
setFastFramerate();
|
||||||
|
@ -128,6 +128,14 @@ class Screen : public concurrency::OSThread
|
|||||||
enqueueCmd(cmd);
|
enqueueCmd(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void startFirmwareUpdateScreen()
|
||||||
|
{
|
||||||
|
ScreenCmd cmd;
|
||||||
|
cmd.cmd = Cmd::START_FIRMWARE_UPDATE_SCREEN;
|
||||||
|
enqueueCmd(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Stops showing the bluetooth PIN screen.
|
/// Stops showing the bluetooth PIN screen.
|
||||||
void stopBluetoothPinScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BLUETOOTH_PIN_SCREEN}); }
|
void stopBluetoothPinScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BLUETOOTH_PIN_SCREEN}); }
|
||||||
|
|
||||||
@ -233,6 +241,7 @@ class Screen : public concurrency::OSThread
|
|||||||
void handleOnPress();
|
void handleOnPress();
|
||||||
void handleStartBluetoothPinScreen(uint32_t pin);
|
void handleStartBluetoothPinScreen(uint32_t pin);
|
||||||
void handlePrint(const char *text);
|
void handlePrint(const char *text);
|
||||||
|
void handleStartFirmwareUpdateScreen();
|
||||||
|
|
||||||
/// Rebuilds our list of frames (screens) to default ones.
|
/// Rebuilds our list of frames (screens) to default ones.
|
||||||
void setFrames();
|
void setFrames();
|
||||||
|
@ -51,22 +51,7 @@ MeshService service;
|
|||||||
|
|
||||||
#include "Router.h"
|
#include "Router.h"
|
||||||
|
|
||||||
static int32_t sendOwnerCb()
|
|
||||||
{
|
|
||||||
static uint32_t currentGeneration;
|
|
||||||
|
|
||||||
// If we changed channels, ask everyone else for their latest info
|
|
||||||
bool requestReplies = currentGeneration != radioGeneration;
|
|
||||||
currentGeneration = radioGeneration;
|
|
||||||
|
|
||||||
DEBUG_MSG("Sending our nodeinfo to mesh (wantReplies=%d)\n", requestReplies);
|
|
||||||
assert(nodeInfoPlugin);
|
|
||||||
nodeInfoPlugin->sendOurNodeInfo(NODENUM_BROADCAST, requestReplies); // Send our info (don't request replies)
|
|
||||||
|
|
||||||
return getPref_send_owner_interval() * getPref_position_broadcast_secs() * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
static concurrency::Periodic *sendOwnerPeriod;
|
|
||||||
|
|
||||||
MeshService::MeshService() : toPhoneQueue(MAX_RX_TOPHONE)
|
MeshService::MeshService() : toPhoneQueue(MAX_RX_TOPHONE)
|
||||||
{
|
{
|
||||||
@ -75,9 +60,6 @@ MeshService::MeshService() : toPhoneQueue(MAX_RX_TOPHONE)
|
|||||||
|
|
||||||
void MeshService::init()
|
void MeshService::init()
|
||||||
{
|
{
|
||||||
sendOwnerPeriod = new concurrency::Periodic("SendOwner", sendOwnerCb);
|
|
||||||
sendOwnerPeriod->setIntervalFromNow(30 * 1000); // Send our initial owner announcement 30 seconds after we start (to give network time to setup)
|
|
||||||
|
|
||||||
// moved much earlier in boot (called from setup())
|
// moved much earlier in boot (called from setup())
|
||||||
// nodeDB.init();
|
// nodeDB.init();
|
||||||
|
|
||||||
@ -178,18 +160,6 @@ void MeshService::sendToMesh(MeshPacket *p)
|
|||||||
{
|
{
|
||||||
nodeDB.updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...)
|
nodeDB.updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...)
|
||||||
|
|
||||||
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
|
|
||||||
// nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless
|
|
||||||
// devices can get time.
|
|
||||||
if (p->which_payloadVariant == MeshPacket_decoded_tag && p->decoded.which_payloadVariant == SubPacket_position_tag &&
|
|
||||||
p->decoded.position.time) {
|
|
||||||
if (getRTCQuality() < RTCQualityGPS) {
|
|
||||||
DEBUG_MSG("Stripping time %u from position send\n", p->decoded.position.time);
|
|
||||||
p->decoded.position.time = 0;
|
|
||||||
} else
|
|
||||||
DEBUG_MSG("Providing time to mesh %u\n", p->decoded.position.time);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it
|
// Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it
|
||||||
router->sendLocal(p);
|
router->sendLocal(p);
|
||||||
}
|
}
|
||||||
@ -221,7 +191,7 @@ NodeInfo *MeshService::refreshMyNodeInfo() {
|
|||||||
Position &position = node->position;
|
Position &position = node->position;
|
||||||
|
|
||||||
// Update our local node info with our position (even if we don't decide to update anyone else)
|
// Update our local node info with our position (even if we don't decide to update anyone else)
|
||||||
position.time = getValidTime(RTCQualityGPS); // This nodedb timestamp might be stale, so update it if our clock is valid.
|
position.time = getValidTime(RTCQualityFromNet); // This nodedb timestamp might be stale, so update it if our clock is kinda valid
|
||||||
|
|
||||||
position.battery_level = powerStatus->getBatteryChargePercent();
|
position.battery_level = powerStatus->getBatteryChargePercent();
|
||||||
updateBatteryLevel(position.battery_level);
|
updateBatteryLevel(position.battery_level);
|
||||||
@ -244,7 +214,7 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *unused)
|
|||||||
else {
|
else {
|
||||||
// The GPS has lost lock, if we are fixed position we should just keep using
|
// The GPS has lost lock, if we are fixed position we should just keep using
|
||||||
// the old position
|
// the old position
|
||||||
if(!radioConfig.preferences.fixed_position) {
|
if(radioConfig.preferences.fixed_position) {
|
||||||
DEBUG_MSG("WARNING: Using fixed position\n");
|
DEBUG_MSG("WARNING: Using fixed position\n");
|
||||||
} else {
|
} else {
|
||||||
// throw away old position
|
// throw away old position
|
||||||
@ -254,27 +224,10 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *unused)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_MSG("got gps notify time=%u, lat=%d, bat=%d\n", pos.latitude_i, pos.time, pos.battery_level);
|
DEBUG_MSG("got gps notify time=%u, lat=%d, bat=%d\n", pos.time, pos.latitude_i, pos.battery_level);
|
||||||
|
|
||||||
// Update our current position in the local DB
|
// Update our current position in the local DB
|
||||||
nodeDB.updatePosition(nodeDB.getNodeNum(), pos);
|
nodeDB.updatePosition(nodeDB.getNodeNum(), pos);
|
||||||
|
|
||||||
// We limit our GPS broadcasts to a max rate
|
|
||||||
static uint32_t lastGpsSend;
|
|
||||||
uint32_t now = millis();
|
|
||||||
if (lastGpsSend == 0 || now - lastGpsSend > getPref_position_broadcast_secs() * 1000) {
|
|
||||||
lastGpsSend = now;
|
|
||||||
|
|
||||||
static uint32_t currentGeneration;
|
|
||||||
|
|
||||||
// If we changed channels, ask everyone else for their latest info
|
|
||||||
bool requestReplies = currentGeneration != radioGeneration;
|
|
||||||
currentGeneration = radioGeneration;
|
|
||||||
|
|
||||||
DEBUG_MSG("Sending position to mesh (wantReplies=%d)\n", requestReplies);
|
|
||||||
assert(positionPlugin);
|
|
||||||
positionPlugin->sendOurPosition(NODENUM_BROADCAST, requestReplies);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ typedef uint32_t PacketId; // A packet sequence number
|
|||||||
#define ERRNO_OK 0
|
#define ERRNO_OK 0
|
||||||
#define ERRNO_NO_INTERFACES 33
|
#define ERRNO_NO_INTERFACES 33
|
||||||
#define ERRNO_UNKNOWN 32 // pick something that doesn't conflict with RH_ROUTER_ERROR_UNABLE_TO_DELIVER
|
#define ERRNO_UNKNOWN 32 // pick something that doesn't conflict with RH_ROUTER_ERROR_UNABLE_TO_DELIVER
|
||||||
|
#define ERRNO_DISABLED 34 // the itnerface is disabled
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the max number of hops a message can pass through, used as the default max for hop_limit in MeshPacket.
|
* the max number of hops a message can pass through, used as the default max for hop_limit in MeshPacket.
|
||||||
|
@ -54,6 +54,8 @@ class RadioInterface
|
|||||||
uint32_t shortPacketMsec;
|
uint32_t shortPacketMsec;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool disabled = false;
|
||||||
|
|
||||||
float bw = 125;
|
float bw = 125;
|
||||||
uint8_t sf = 9;
|
uint8_t sf = 9;
|
||||||
uint8_t cr = 7;
|
uint8_t cr = 7;
|
||||||
@ -98,6 +100,9 @@ class RadioInterface
|
|||||||
/// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep.
|
/// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep.
|
||||||
virtual bool sleep() { return true; }
|
virtual bool sleep() { return true; }
|
||||||
|
|
||||||
|
/// Disable this interface (while disabled, no packets can be sent or received)
|
||||||
|
void disable() { disabled = true; sleep(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a packet (possibly by enquing in a private fifo). This routine will
|
* Send a packet (possibly by enquing in a private fifo). This routine will
|
||||||
* later free() the packet to pool. This routine is not allowed to stall.
|
* later free() the packet to pool. This routine is not allowed to stall.
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
#include "MeshTypes.h"
|
#include "MeshTypes.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "SPILock.h"
|
#include "SPILock.h"
|
||||||
#include "mesh-pb-constants.h"
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "mesh-pb-constants.h"
|
||||||
#include <configuration.h>
|
#include <configuration.h>
|
||||||
#include <pb_decode.h>
|
#include <pb_decode.h>
|
||||||
#include <pb_encode.h>
|
#include <pb_encode.h>
|
||||||
@ -68,13 +68,12 @@ bool RadioLibInterface::canSendImmediately()
|
|||||||
bool busyTx = sendingPacket != NULL;
|
bool busyTx = sendingPacket != NULL;
|
||||||
bool busyRx = isReceiving && isActivelyReceiving();
|
bool busyRx = isReceiving && isActivelyReceiving();
|
||||||
|
|
||||||
|
|
||||||
if (busyTx || busyRx) {
|
if (busyTx || busyRx) {
|
||||||
if (busyTx)
|
if (busyTx)
|
||||||
DEBUG_MSG("Can not send yet, busyTx\n");
|
DEBUG_MSG("Can not send yet, busyTx\n");
|
||||||
// If we've been trying to send the same packet more than one minute and we haven't gotten a
|
// If we've been trying to send the same packet more than one minute and we haven't gotten a
|
||||||
// TX IRQ from the radio, the radio is probably broken.
|
// TX IRQ from the radio, the radio is probably broken.
|
||||||
if (busyTx && (millis() - lastTxStart > 60000)){
|
if (busyTx && (millis() - lastTxStart > 60000)) {
|
||||||
DEBUG_MSG("Hardware Failure! busyTx for more than 60s\n");
|
DEBUG_MSG("Hardware Failure! busyTx for more than 60s\n");
|
||||||
recordCriticalError(CriticalErrorCode_TransmitFailed);
|
recordCriticalError(CriticalErrorCode_TransmitFailed);
|
||||||
#ifndef NO_ESP32
|
#ifndef NO_ESP32
|
||||||
@ -94,6 +93,11 @@ bool RadioLibInterface::canSendImmediately()
|
|||||||
/// bluetooth comms code. If the txmit queue is empty it might return an error
|
/// bluetooth comms code. If the txmit queue is empty it might return an error
|
||||||
ErrorCode RadioLibInterface::send(MeshPacket *p)
|
ErrorCode RadioLibInterface::send(MeshPacket *p)
|
||||||
{
|
{
|
||||||
|
if (disabled) {
|
||||||
|
packetPool.release(p);
|
||||||
|
return ERRNO_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
// Sometimes when testing it is useful to be able to never turn on the xmitter
|
// Sometimes when testing it is useful to be able to never turn on the xmitter
|
||||||
#ifndef LORA_DISABLE_SENDING
|
#ifndef LORA_DISABLE_SENDING
|
||||||
printPacket("enqueuing for send", p);
|
printPacket("enqueuing for send", p);
|
||||||
@ -110,7 +114,7 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
|||||||
// Count the packet toward our TX airtime utilization.
|
// Count the packet toward our TX airtime utilization.
|
||||||
// We only count it if it can be added to the TX queue.
|
// We only count it if it can be added to the TX queue.
|
||||||
airTime->logAirtime(TX_LOG, xmitMsec);
|
airTime->logAirtime(TX_LOG, xmitMsec);
|
||||||
//airTime.logAirtime(TX_LOG, xmitMsec);
|
// airTime.logAirtime(TX_LOG, xmitMsec);
|
||||||
|
|
||||||
// We want all sending/receiving to be done by our daemon thread, We use a delay here because this packet might have been sent
|
// We want all sending/receiving to be done by our daemon thread, We use a delay here because this packet might have been sent
|
||||||
// in response to a packet we just received. So we want to make sure the other side has had a chance to reconfigure its radio
|
// in response to a packet we just received. So we want to make sure the other side has had a chance to reconfigure its radio
|
||||||
@ -119,7 +123,7 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
|||||||
return res;
|
return res;
|
||||||
#else
|
#else
|
||||||
packetPool.release(p);
|
packetPool.release(p);
|
||||||
return ERRNO_UNKNOWN;
|
return ERRNO_DISABLED;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,17 +137,17 @@ bool RadioLibInterface::canSleep()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */
|
/** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */
|
||||||
bool RadioLibInterface::cancelSending(NodeNum from, PacketId id) {
|
bool RadioLibInterface::cancelSending(NodeNum from, PacketId id)
|
||||||
|
{
|
||||||
auto p = txQueue.remove(from, id);
|
auto p = txQueue.remove(from, id);
|
||||||
if(p)
|
if (p)
|
||||||
packetPool.release(p); // free the packet we just removed
|
packetPool.release(p); // free the packet we just removed
|
||||||
|
|
||||||
bool result = (p != NULL);
|
bool result = (p != NULL);
|
||||||
DEBUG_MSG("cancelSending id=0x%x, removed=%d", id, result);
|
DEBUG_MSG("cancelSending id=0x%x, removed=%d\n", id, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** radio helper thread callback.
|
/** radio helper thread callback.
|
||||||
|
|
||||||
We never immediately transmit after any operation (either rx or tx). Instead we should start receiving and
|
We never immediately transmit after any operation (either rx or tx). Instead we should start receiving and
|
||||||
@ -242,7 +246,7 @@ void RadioLibInterface::handleReceiveInterrupt()
|
|||||||
|
|
||||||
xmitMsec = getPacketTime(length);
|
xmitMsec = getPacketTime(length);
|
||||||
airTime->logAirtime(RX_ALL_LOG, xmitMsec);
|
airTime->logAirtime(RX_ALL_LOG, xmitMsec);
|
||||||
//airTime.logAirtime(RX_ALL_LOG, xmitMsec);
|
// airTime.logAirtime(RX_ALL_LOG, xmitMsec);
|
||||||
|
|
||||||
int state = iface->readData(radiobuf, length);
|
int state = iface->readData(radiobuf, length);
|
||||||
if (state != ERR_NONE) {
|
if (state != ERR_NONE) {
|
||||||
@ -277,7 +281,7 @@ void RadioLibInterface::handleReceiveInterrupt()
|
|||||||
addReceiveMetadata(mp);
|
addReceiveMetadata(mp);
|
||||||
|
|
||||||
mp->which_payloadVariant = MeshPacket_encrypted_tag; // Mark that the payload is still encrypted at this point
|
mp->which_payloadVariant = MeshPacket_encrypted_tag; // Mark that the payload is still encrypted at this point
|
||||||
assert(((uint32_t) payloadLen) <= sizeof(mp->encrypted.bytes));
|
assert(((uint32_t)payloadLen) <= sizeof(mp->encrypted.bytes));
|
||||||
memcpy(mp->encrypted.bytes, payload, payloadLen);
|
memcpy(mp->encrypted.bytes, payload, payloadLen);
|
||||||
mp->encrypted.size = payloadLen;
|
mp->encrypted.size = payloadLen;
|
||||||
|
|
||||||
@ -285,7 +289,7 @@ void RadioLibInterface::handleReceiveInterrupt()
|
|||||||
|
|
||||||
xmitMsec = getPacketTime(mp);
|
xmitMsec = getPacketTime(mp);
|
||||||
airTime->logAirtime(RX_LOG, xmitMsec);
|
airTime->logAirtime(RX_LOG, xmitMsec);
|
||||||
//airTime.logAirtime(RX_LOG, xmitMsec);
|
// airTime.logAirtime(RX_LOG, xmitMsec);
|
||||||
|
|
||||||
deliverToReceiver(mp);
|
deliverToReceiver(mp);
|
||||||
}
|
}
|
||||||
@ -295,16 +299,21 @@ void RadioLibInterface::handleReceiveInterrupt()
|
|||||||
/** start an immediate transmit */
|
/** start an immediate transmit */
|
||||||
void RadioLibInterface::startSend(MeshPacket *txp)
|
void RadioLibInterface::startSend(MeshPacket *txp)
|
||||||
{
|
{
|
||||||
printPacket("Starting low level send", txp);
|
printPacket("Starting low level send", txp);
|
||||||
setStandby(); // Cancel any already in process receives
|
if (disabled) {
|
||||||
|
DEBUG_MSG("startSend is dropping tx packet because we are disabled\n");
|
||||||
|
packetPool.release(txp);
|
||||||
|
} else {
|
||||||
|
setStandby(); // Cancel any already in process receives
|
||||||
|
|
||||||
configHardwareForSend(); // must be after setStandby
|
configHardwareForSend(); // must be after setStandby
|
||||||
|
|
||||||
size_t numbytes = beginSending(txp);
|
size_t numbytes = beginSending(txp);
|
||||||
|
|
||||||
int res = iface->startTransmit(radiobuf, numbytes);
|
int res = iface->startTransmit(radiobuf, numbytes);
|
||||||
assert(res == ERR_NONE);
|
assert(res == ERR_NONE);
|
||||||
|
|
||||||
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
|
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
|
||||||
enableInterrupt(isrTxLevel0);
|
enableInterrupt(isrTxLevel0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ bool NodeInfoPlugin::handleReceivedProtobuf(const MeshPacket &mp, const User &p)
|
|||||||
void NodeInfoPlugin::sendOurNodeInfo(NodeNum dest, bool wantReplies)
|
void NodeInfoPlugin::sendOurNodeInfo(NodeNum dest, bool wantReplies)
|
||||||
{
|
{
|
||||||
// cancel any not yet sent (now stale) position packets
|
// cancel any not yet sent (now stale) position packets
|
||||||
if(prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
|
if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
|
||||||
service.cancelSending(prevPacketId);
|
service.cancelSending(prevPacketId);
|
||||||
|
|
||||||
MeshPacket *p = allocReply();
|
MeshPacket *p = allocReply();
|
||||||
@ -48,3 +48,26 @@ MeshPacket *NodeInfoPlugin::allocReply()
|
|||||||
DEBUG_MSG("sending owner %s/%s/%s\n", u.id, u.long_name, u.short_name);
|
DEBUG_MSG("sending owner %s/%s/%s\n", u.id, u.long_name, u.short_name);
|
||||||
return allocDataProtobuf(u);
|
return allocDataProtobuf(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeInfoPlugin::NodeInfoPlugin()
|
||||||
|
: ProtobufPlugin("nodeinfo", PortNum_NODEINFO_APP, User_fields), concurrency::OSThread("NodeInfoPlugin")
|
||||||
|
{
|
||||||
|
setIntervalFromNow(30 *
|
||||||
|
1000); // Send our initial owner announcement 30 seconds after we start (to give network time to setup)
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t NodeInfoPlugin::runOnce()
|
||||||
|
{
|
||||||
|
static uint32_t currentGeneration;
|
||||||
|
|
||||||
|
// If we changed channels, ask everyone else for their latest info
|
||||||
|
bool requestReplies = currentGeneration != radioGeneration;
|
||||||
|
currentGeneration = radioGeneration;
|
||||||
|
|
||||||
|
DEBUG_MSG("Sending our nodeinfo to mesh (wantReplies=%d)\n", requestReplies);
|
||||||
|
assert(nodeInfoPlugin);
|
||||||
|
nodeInfoPlugin->sendOurNodeInfo(NODENUM_BROADCAST, requestReplies); // Send our info (don't request replies)
|
||||||
|
|
||||||
|
return getPref_position_broadcast_secs() * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -4,17 +4,18 @@
|
|||||||
/**
|
/**
|
||||||
* NodeInfo plugin for sending/receiving NodeInfos into the mesh
|
* NodeInfo plugin for sending/receiving NodeInfos into the mesh
|
||||||
*/
|
*/
|
||||||
class NodeInfoPlugin : public ProtobufPlugin<User>
|
class NodeInfoPlugin : public ProtobufPlugin<User>, private concurrency::OSThread
|
||||||
{
|
{
|
||||||
/// The id of the last packet we sent, to allow us to cancel it if we make something fresher
|
/// The id of the last packet we sent, to allow us to cancel it if we make something fresher
|
||||||
PacketId prevPacketId = 0;
|
PacketId prevPacketId = 0;
|
||||||
|
|
||||||
|
uint32_t currentGeneration = 0;
|
||||||
public:
|
public:
|
||||||
/** Constructor
|
/** Constructor
|
||||||
* name is for debugging output
|
* name is for debugging output
|
||||||
*/
|
*/
|
||||||
NodeInfoPlugin() : ProtobufPlugin("nodeinfo", PortNum_NODEINFO_APP, User_fields) {}
|
NodeInfoPlugin();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send our NodeInfo into the mesh
|
* Send our NodeInfo into the mesh
|
||||||
*/
|
*/
|
||||||
@ -30,6 +31,9 @@ class NodeInfoPlugin : public ProtobufPlugin<User>
|
|||||||
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked
|
/** 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. */
|
* so that subclasses can (optionally) send a response back to the original sender. */
|
||||||
virtual MeshPacket *allocReply();
|
virtual MeshPacket *allocReply();
|
||||||
|
|
||||||
|
/** Does our periodic broadcast */
|
||||||
|
virtual int32_t runOnce();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NodeInfoPlugin *nodeInfoPlugin;
|
extern NodeInfoPlugin *nodeInfoPlugin;
|
@ -7,6 +7,14 @@
|
|||||||
|
|
||||||
PositionPlugin *positionPlugin;
|
PositionPlugin *positionPlugin;
|
||||||
|
|
||||||
|
PositionPlugin::PositionPlugin()
|
||||||
|
: ProtobufPlugin("position", PortNum_POSITION_APP, Position_fields), concurrency::OSThread("PositionPlugin")
|
||||||
|
{
|
||||||
|
setIntervalFromNow(60 *
|
||||||
|
1000); // Send our initial position 60 seconds after we start (to give GPS time to setup)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool PositionPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Position &p)
|
bool PositionPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Position &p)
|
||||||
{
|
{
|
||||||
// FIXME - we currently update position data in the DB only if the message was a broadcast or destined to us
|
// FIXME - we currently update position data in the DB only if the message was a broadcast or destined to us
|
||||||
@ -31,14 +39,25 @@ MeshPacket *PositionPlugin::allocReply()
|
|||||||
{
|
{
|
||||||
NodeInfo *node = service.refreshMyNodeInfo(); // should guarantee there is now a position
|
NodeInfo *node = service.refreshMyNodeInfo(); // should guarantee there is now a position
|
||||||
assert(node->has_position);
|
assert(node->has_position);
|
||||||
|
|
||||||
return allocDataProtobuf(node->position);
|
Position p = node->position;
|
||||||
|
|
||||||
|
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
|
||||||
|
// nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless
|
||||||
|
// devices can get time.
|
||||||
|
if (getRTCQuality() < RTCQualityGPS) {
|
||||||
|
DEBUG_MSG("Stripping time %u from position send\n", p.time);
|
||||||
|
p.time = 0;
|
||||||
|
} else
|
||||||
|
DEBUG_MSG("Providing time to mesh %u\n", p.time);
|
||||||
|
|
||||||
|
return allocDataProtobuf(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PositionPlugin::sendOurPosition(NodeNum dest, bool wantReplies)
|
void PositionPlugin::sendOurPosition(NodeNum dest, bool wantReplies)
|
||||||
{
|
{
|
||||||
// cancel any not yet sent (now stale) position packets
|
// cancel any not yet sent (now stale) position packets
|
||||||
if(prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
|
if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
|
||||||
service.cancelSending(prevPacketId);
|
service.cancelSending(prevPacketId);
|
||||||
|
|
||||||
MeshPacket *p = allocReply();
|
MeshPacket *p = allocReply();
|
||||||
@ -50,3 +69,21 @@ void PositionPlugin::sendOurPosition(NodeNum dest, bool wantReplies)
|
|||||||
service.sendToMesh(p);
|
service.sendToMesh(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t PositionPlugin::runOnce()
|
||||||
|
{
|
||||||
|
|
||||||
|
// We limit our GPS broadcasts to a max rate
|
||||||
|
uint32_t now = millis();
|
||||||
|
if (lastGpsSend == 0 || now - lastGpsSend >= getPref_position_broadcast_secs() * 1000) {
|
||||||
|
lastGpsSend = now;
|
||||||
|
|
||||||
|
// If we changed channels, ask everyone else for their latest info
|
||||||
|
bool requestReplies = currentGeneration != radioGeneration;
|
||||||
|
currentGeneration = radioGeneration;
|
||||||
|
|
||||||
|
DEBUG_MSG("Sending position to mesh (wantReplies=%d)\n", requestReplies);
|
||||||
|
sendOurPosition(NODENUM_BROADCAST, requestReplies);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 5000; // to save power only wake for our callback occasionally
|
||||||
|
}
|
@ -1,20 +1,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "ProtobufPlugin.h"
|
#include "ProtobufPlugin.h"
|
||||||
|
#include "concurrency/OSThread.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Position plugin for sending/receiving positions into the mesh
|
* Position plugin for sending/receiving positions into the mesh
|
||||||
*/
|
*/
|
||||||
class PositionPlugin : public ProtobufPlugin<Position>
|
class PositionPlugin : public ProtobufPlugin<Position>, private concurrency::OSThread
|
||||||
{
|
{
|
||||||
/// The id of the last packet we sent, to allow us to cancel it if we make something fresher
|
/// The id of the last packet we sent, to allow us to cancel it if we make something fresher
|
||||||
PacketId prevPacketId = 0;
|
PacketId prevPacketId = 0;
|
||||||
|
|
||||||
|
/// We limit our GPS broadcasts to a max rate
|
||||||
|
uint32_t lastGpsSend = 0;
|
||||||
|
|
||||||
|
/// We force a rebroadcast if the radio settings change
|
||||||
|
uint32_t currentGeneration = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Constructor
|
/** Constructor
|
||||||
* name is for debugging output
|
* name is for debugging output
|
||||||
*/
|
*/
|
||||||
PositionPlugin() : ProtobufPlugin("position", PortNum_POSITION_APP, Position_fields) {}
|
PositionPlugin();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send our position into the mesh
|
* Send our position into the mesh
|
||||||
*/
|
*/
|
||||||
@ -31,6 +38,9 @@ class PositionPlugin : public ProtobufPlugin<Position>
|
|||||||
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked
|
/** 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. */
|
* so that subclasses can (optionally) send a response back to the original sender. */
|
||||||
virtual MeshPacket *allocReply();
|
virtual MeshPacket *allocReply();
|
||||||
|
|
||||||
|
/** Does our periodic broadcast */
|
||||||
|
virtual int32_t runOnce();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern PositionPlugin *positionPlugin;
|
extern PositionPlugin *positionPlugin;
|
@ -1,4 +1,4 @@
|
|||||||
[VERSION]
|
[VERSION]
|
||||||
major = 1
|
major = 1
|
||||||
minor = 1
|
minor = 1
|
||||||
build = 46
|
build = 47
|
||||||
|
Loading…
Reference in New Issue
Block a user