sforkowany z mirror/meshtastic-firmware
commit
e650033f2c
|
@ -1,3 +1,3 @@
|
|||
|
||||
|
||||
export VERSION=0.6.8
|
||||
export VERSION=0.7.4
|
|
@ -36,6 +36,10 @@ From lower to higher power consumption.
|
|||
onEntry: setBluetoothOn(true), screen.setOn(true)
|
||||
onExit: screen.setOn(false)
|
||||
|
||||
- serial API usage (SERIAL) - Screen is on, device doesn't sleep, bluetooth off
|
||||
onEntry: setBluetooth off, screen on
|
||||
onExit:
|
||||
|
||||
## Behavior
|
||||
|
||||
### events that increase CPU activity
|
||||
|
@ -51,9 +55,11 @@ From lower to higher power consumption.
|
|||
- While in DARK/ON: If we receive EVENT_BLUETOOTH_PAIR we transition to ON and start our screen_on_secs timeout
|
||||
- While in NB/DARK/ON: If we receive EVENT_NODEDB_UPDATED we transition to ON (so the new screen can be shown)
|
||||
- While in DARK: While the phone talks to us over BLE (EVENT_CONTACT_FROM_PHONE) reset any sleep timers and stay in DARK (needed for bluetooth sw update and nice user experience if the user is reading/replying to texts)
|
||||
- while in LS/NB/DARK: if SERIAL_CONNECTED, go to serial
|
||||
|
||||
### events that decrease cpu activity
|
||||
|
||||
- While in SERIAL: if SERIAL_DISCONNECTED, go to NB
|
||||
- While in ON: If PRESS event occurs, reset screen_on_secs timer and tell the screen to handle the pess
|
||||
- While in ON: If it has been more than screen_on_secs since a press, lower to DARK
|
||||
- While in DARK: If time since last contact by our phone exceeds phone_timeout_secs (15 minutes), we transition down into NB mode
|
||||
|
|
|
@ -104,6 +104,12 @@ static void darkEnter()
|
|||
screen.setOn(false);
|
||||
}
|
||||
|
||||
static void serialEnter()
|
||||
{
|
||||
setBluetoothEnable(false);
|
||||
screen.setOn(true);
|
||||
}
|
||||
|
||||
static void onEnter()
|
||||
{
|
||||
screen.setOn(true);
|
||||
|
@ -133,6 +139,7 @@ State stateSDS(sdsEnter, NULL, NULL, "SDS");
|
|||
State stateLS(lsEnter, lsIdle, lsExit, "LS");
|
||||
State stateNB(nbEnter, NULL, NULL, "NB");
|
||||
State stateDARK(darkEnter, NULL, NULL, "DARK");
|
||||
State stateSERIAL(serialEnter, NULL, NULL, "SERIAL");
|
||||
State stateBOOT(bootEnter, NULL, NULL, "BOOT");
|
||||
State stateON(onEnter, NULL, NULL, "ON");
|
||||
Fsm powerFSM(&stateBOOT);
|
||||
|
@ -148,7 +155,7 @@ void PowerFSM_setup()
|
|||
|
||||
powerFSM.add_transition(&stateNB, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet, resetting win wake");
|
||||
|
||||
// Handle press events
|
||||
// Handle press events - note: we ignore button presses when in API mode
|
||||
powerFSM.add_transition(&stateLS, &stateON, EVENT_PRESS, NULL, "Press");
|
||||
powerFSM.add_transition(&stateNB, &stateON, EVENT_PRESS, NULL, "Press");
|
||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "Press");
|
||||
|
@ -160,6 +167,7 @@ void PowerFSM_setup()
|
|||
powerFSM.add_transition(&stateNB, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateDARK, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateON, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateSERIAL, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
|
||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
||||
powerFSM.add_transition(&stateON, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
|
||||
|
@ -173,6 +181,13 @@ void PowerFSM_setup()
|
|||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
|
||||
powerFSM.add_transition(&stateON, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text"); // restarts the sleep timer
|
||||
|
||||
powerFSM.add_transition(&stateLS, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API");
|
||||
powerFSM.add_transition(&stateNB, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API");
|
||||
powerFSM.add_transition(&stateDARK, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API");
|
||||
powerFSM.add_transition(&stateON, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API");
|
||||
|
||||
powerFSM.add_transition(&stateSERIAL, &stateNB, EVENT_SERIAL_DISCONNECTED, NULL, "serial disconnect");
|
||||
|
||||
powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone");
|
||||
|
||||
powerFSM.add_transition(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Packet for phone");
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#define EVENT_NODEDB_UPDATED 8 // NodeDB has a big enough change that we think you should turn on the screen
|
||||
#define EVENT_CONTACT_FROM_PHONE 9 // the phone just talked to us over bluetooth
|
||||
#define EVENT_LOW_BATTERY 10 // Battery is critically low, go to sleep
|
||||
#define EVENT_SERIAL_CONNECTED 11
|
||||
#define EVENT_SERIAL_DISCONNECTED 12
|
||||
|
||||
extern Fsm powerFSM;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "SerialConsole.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
|
@ -26,12 +27,19 @@ void SerialConsole::init()
|
|||
*/
|
||||
void SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
|
||||
{
|
||||
// Note: for the time being we could _allow_ debug printing to keep going out the console
|
||||
// I _think_ this is okay because we currently only print debug msgs from loop() and we are only
|
||||
// dispatching serial protobuf msgs from loop() as well. When things are more threaded in the future this
|
||||
// will need to change.
|
||||
// setDestination(&noopPrint);
|
||||
// Turn off debug serial printing once the API is activated, because other threads could print and corrupt packets
|
||||
setDestination(&noopPrint);
|
||||
canWrite = true;
|
||||
|
||||
StreamAPI::handleToRadio(buf, len);
|
||||
}
|
||||
|
||||
/// Hookable to find out when connection changes
|
||||
void SerialConsole::onConnectionChanged(bool connected)
|
||||
{
|
||||
if (connected) { // To prevent user confusion, turn off bluetooth while using the serial port api
|
||||
powerFSM.trigger(EVENT_SERIAL_CONNECTED);
|
||||
} else {
|
||||
powerFSM.trigger(EVENT_SERIAL_DISCONNECTED);
|
||||
}
|
||||
}
|
|
@ -26,6 +26,10 @@ class SerialConsole : public StreamAPI, public RedirectablePrint
|
|||
RedirectablePrint::write('\r');
|
||||
return RedirectablePrint::write(c);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Hookable to find out when connection changes
|
||||
virtual void onConnectionChanged(bool connected);
|
||||
};
|
||||
|
||||
extern SerialConsole console;
|
||||
|
|
|
@ -30,8 +30,6 @@ class TotalSizeCharacteristic : public CallbackCharacteristic
|
|||
|
||||
void onWrite(BLECharacteristic *c)
|
||||
{
|
||||
BLEKeepAliveCallbacks::onWrite(c);
|
||||
|
||||
LockGuard g(updateLock);
|
||||
// Check if there is enough to OTA Update
|
||||
uint32_t len = getValue32(c, 0);
|
||||
|
@ -67,8 +65,6 @@ class DataCharacteristic : public CallbackCharacteristic
|
|||
|
||||
void onWrite(BLECharacteristic *c)
|
||||
{
|
||||
BLEKeepAliveCallbacks::onWrite(c);
|
||||
|
||||
LockGuard g(updateLock);
|
||||
std::string value = c->getValue();
|
||||
uint32_t len = value.length();
|
||||
|
@ -92,8 +88,6 @@ class CRC32Characteristic : public CallbackCharacteristic
|
|||
|
||||
void onWrite(BLECharacteristic *c)
|
||||
{
|
||||
BLEKeepAliveCallbacks::onWrite(c);
|
||||
|
||||
LockGuard g(updateLock);
|
||||
uint32_t expectedCRC = getValue32(c, 0);
|
||||
uint32_t actualCRC = crc.finalize();
|
||||
|
|
|
@ -1,33 +1,12 @@
|
|||
#pragma once
|
||||
#include "PowerFSM.h" // FIXME - someday I want to make this OTA thing a separate lb at at that point it can't touch this
|
||||
#include "BLECharacteristic.h"
|
||||
|
||||
/**
|
||||
* This mixin just lets the power management state machine know the phone is still talking to us
|
||||
*/
|
||||
class BLEKeepAliveCallbacks : public BLECharacteristicCallbacks
|
||||
{
|
||||
public:
|
||||
void onRead(BLECharacteristic *c)
|
||||
{
|
||||
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);
|
||||
}
|
||||
|
||||
void onWrite(BLECharacteristic *c)
|
||||
{
|
||||
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);
|
||||
}
|
||||
};
|
||||
#include "PowerFSM.h" // FIXME - someday I want to make this OTA thing a separate lb at at that point it can't touch this
|
||||
|
||||
/**
|
||||
* A characterstic with a set of overridable callbacks
|
||||
*/
|
||||
class CallbackCharacteristic : public BLECharacteristic, public BLEKeepAliveCallbacks
|
||||
class CallbackCharacteristic : public BLECharacteristic, public BLECharacteristicCallbacks
|
||||
{
|
||||
public:
|
||||
CallbackCharacteristic(const char *uuid, uint32_t btprops)
|
||||
: BLECharacteristic(uuid, btprops)
|
||||
{
|
||||
setCallbacks(this);
|
||||
}
|
||||
public:
|
||||
CallbackCharacteristic(const char *uuid, uint32_t btprops) : BLECharacteristic(uuid, btprops) { setCallbacks(this); }
|
||||
};
|
||||
|
|
|
@ -23,9 +23,6 @@ static CallbackCharacteristic *meshFromNumCharacteristic;
|
|||
|
||||
BLEService *meshService;
|
||||
|
||||
// If defined we will also support the old API
|
||||
#define SUPPORT_OLD_BLE_API
|
||||
|
||||
class BluetoothPhoneAPI : public PhoneAPI
|
||||
{
|
||||
/**
|
||||
|
@ -58,17 +55,12 @@ class ProtobufCharacteristic : public CallbackCharacteristic
|
|||
|
||||
void onRead(BLECharacteristic *c)
|
||||
{
|
||||
BLEKeepAliveCallbacks::onRead(c);
|
||||
size_t numbytes = pb_encode_to_bytes(trBytes, sizeof(trBytes), fields, my_struct);
|
||||
DEBUG_MSG("pbread from %s returns %d bytes\n", c->getUUID().toString().c_str(), numbytes);
|
||||
c->setValue(trBytes, numbytes);
|
||||
}
|
||||
|
||||
void onWrite(BLECharacteristic *c)
|
||||
{
|
||||
BLEKeepAliveCallbacks::onWrite(c);
|
||||
writeToDest(c, my_struct);
|
||||
}
|
||||
void onWrite(BLECharacteristic *c) { writeToDest(c, my_struct); }
|
||||
|
||||
protected:
|
||||
/// like onWrite, but we provide an different destination to write to, for use by subclasses that
|
||||
|
@ -83,112 +75,6 @@ class ProtobufCharacteristic : public CallbackCharacteristic
|
|||
}
|
||||
};
|
||||
|
||||
#ifdef SUPPORT_OLD_BLE_API
|
||||
class NodeInfoCharacteristic : public BLECharacteristic, public BLEKeepAliveCallbacks
|
||||
{
|
||||
public:
|
||||
NodeInfoCharacteristic()
|
||||
: BLECharacteristic("d31e02e0-c8ab-4d3f-9cc9-0b8466bdabe8",
|
||||
BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ)
|
||||
{
|
||||
setCallbacks(this);
|
||||
}
|
||||
|
||||
void onRead(BLECharacteristic *c)
|
||||
{
|
||||
BLEKeepAliveCallbacks::onRead(c);
|
||||
|
||||
const NodeInfo *info = nodeDB.readNextInfo();
|
||||
|
||||
if (info) {
|
||||
DEBUG_MSG("Sending nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", info->num, info->position.time, info->user.id,
|
||||
info->user.long_name);
|
||||
size_t numbytes = pb_encode_to_bytes(trBytes, sizeof(trBytes), NodeInfo_fields, info);
|
||||
c->setValue(trBytes, numbytes);
|
||||
} else {
|
||||
c->setValue(trBytes, 0); // Send an empty response
|
||||
DEBUG_MSG("Done sending nodeinfos\n");
|
||||
}
|
||||
}
|
||||
|
||||
void onWrite(BLECharacteristic *c)
|
||||
{
|
||||
BLEKeepAliveCallbacks::onWrite(c);
|
||||
DEBUG_MSG("Reset nodeinfo read pointer\n");
|
||||
nodeDB.resetReadPointer();
|
||||
}
|
||||
};
|
||||
|
||||
// wrap our protobuf version with something that forces the service to reload the config
|
||||
class RadioCharacteristic : public ProtobufCharacteristic
|
||||
{
|
||||
public:
|
||||
RadioCharacteristic()
|
||||
: ProtobufCharacteristic("b56786c8-839a-44a1-b98e-a1724c4a0262",
|
||||
BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ, RadioConfig_fields,
|
||||
&radioConfig)
|
||||
{
|
||||
}
|
||||
|
||||
void onRead(BLECharacteristic *c)
|
||||
{
|
||||
DEBUG_MSG("Reading radio config, sdsecs %u\n", radioConfig.preferences.sds_secs);
|
||||
ProtobufCharacteristic::onRead(c);
|
||||
}
|
||||
|
||||
void onWrite(BLECharacteristic *c)
|
||||
{
|
||||
DEBUG_MSG("Writing radio config\n");
|
||||
ProtobufCharacteristic::onWrite(c);
|
||||
bluetoothPhoneAPI->handleSetRadio(radioConfig);
|
||||
}
|
||||
};
|
||||
|
||||
// wrap our protobuf version with something that forces the service to reload the owner
|
||||
class OwnerCharacteristic : public ProtobufCharacteristic
|
||||
{
|
||||
public:
|
||||
OwnerCharacteristic()
|
||||
: ProtobufCharacteristic("6ff1d8b6-e2de-41e3-8c0b-8fa384f64eb6",
|
||||
BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ, User_fields, &owner)
|
||||
{
|
||||
}
|
||||
|
||||
void onWrite(BLECharacteristic *c)
|
||||
{
|
||||
BLEKeepAliveCallbacks::onWrite(
|
||||
c); // NOTE: We do not call the standard ProtobufCharacteristic superclass, because we want custom write behavior
|
||||
|
||||
static User o; // if the phone doesn't set ID we are careful to keep ours, we also always keep our macaddr
|
||||
if (writeToDest(c, &o)) {
|
||||
bluetoothPhoneAPI->handleSetOwner(o);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MyNodeInfoCharacteristic : public ProtobufCharacteristic
|
||||
{
|
||||
public:
|
||||
MyNodeInfoCharacteristic()
|
||||
: ProtobufCharacteristic("ea9f3f82-8dc4-4733-9452-1f6da28892a2", BLECharacteristic::PROPERTY_READ, MyNodeInfo_fields,
|
||||
&myNodeInfo)
|
||||
{
|
||||
}
|
||||
|
||||
void onRead(BLECharacteristic *c)
|
||||
{
|
||||
// update gps connection state
|
||||
myNodeInfo.has_gps = gps->isConnected;
|
||||
|
||||
ProtobufCharacteristic::onRead(c);
|
||||
|
||||
myNodeInfo.error_code = 0; // The phone just read us, so throw it away
|
||||
myNodeInfo.error_address = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
class ToRadioCharacteristic : public CallbackCharacteristic
|
||||
{
|
||||
public:
|
||||
|
@ -196,7 +82,6 @@ class ToRadioCharacteristic : public CallbackCharacteristic
|
|||
|
||||
void onWrite(BLECharacteristic *c)
|
||||
{
|
||||
BLEKeepAliveCallbacks::onWrite(c);
|
||||
DEBUG_MSG("Got on write\n");
|
||||
|
||||
bluetoothPhoneAPI->handleToRadio(c->getData(), c->getValue().length());
|
||||
|
@ -212,7 +97,6 @@ class FromRadioCharacteristic : public CallbackCharacteristic
|
|||
|
||||
void onRead(BLECharacteristic *c)
|
||||
{
|
||||
BLEKeepAliveCallbacks::onRead(c);
|
||||
size_t numBytes = bluetoothPhoneAPI->getFromRadio(trBytes);
|
||||
|
||||
// Someone is going to read our value as soon as this callback returns. So fill it with the next message in the queue
|
||||
|
@ -236,11 +120,7 @@ class FromNumCharacteristic : public CallbackCharacteristic
|
|||
// observe(&service.fromNumChanged);
|
||||
}
|
||||
|
||||
void onRead(BLECharacteristic *c)
|
||||
{
|
||||
BLEKeepAliveCallbacks::onRead(c);
|
||||
DEBUG_MSG("FIXME implement fromnum read\n");
|
||||
}
|
||||
void onRead(BLECharacteristic *c) { DEBUG_MSG("FIXME implement fromnum read\n"); }
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -263,12 +143,6 @@ BLEService *createMeshBluetoothService(BLEServer *server)
|
|||
addWithDesc(service, meshFromNumCharacteristic, "fromRadio");
|
||||
addWithDesc(service, new ToRadioCharacteristic, "toRadio");
|
||||
addWithDesc(service, new FromRadioCharacteristic, "fromNum");
|
||||
#ifdef SUPPORT_OLD_BLE_API
|
||||
addWithDesc(service, new MyNodeInfoCharacteristic, "myNode");
|
||||
addWithDesc(service, new RadioCharacteristic, "radio");
|
||||
addWithDesc(service, new OwnerCharacteristic, "owner");
|
||||
addWithDesc(service, new NodeInfoCharacteristic, "nodeinfo");
|
||||
#endif
|
||||
|
||||
meshFromNumCharacteristic->addDescriptor(addBLEDescriptor(new BLE2902())); // Needed so clients can request notification
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "PhoneAPI.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include <assert.h>
|
||||
|
||||
PhoneAPI::PhoneAPI()
|
||||
|
@ -14,11 +15,30 @@ void PhoneAPI::init()
|
|||
observe(&service.fromNumChanged);
|
||||
}
|
||||
|
||||
void PhoneAPI::checkConnectionTimeout()
|
||||
{
|
||||
if (isConnected) {
|
||||
bool newConnected = (millis() - lastContactMsec < radioConfig.preferences.phone_timeout_secs * 1000L);
|
||||
if (!newConnected) {
|
||||
isConnected = false;
|
||||
onConnectionChanged(isConnected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a ToRadio protobuf
|
||||
*/
|
||||
void PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
|
||||
{
|
||||
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE); // As long as the phone keeps talking to us, don't let the radio go to sleep
|
||||
lastContactMsec = millis();
|
||||
if (!isConnected) {
|
||||
isConnected = true;
|
||||
onConnectionChanged(isConnected);
|
||||
}
|
||||
// return (lastContactMsec != 0) &&
|
||||
|
||||
if (pb_decode_from_bytes(buf, bufLength, ToRadio_fields, &toRadioScratch)) {
|
||||
switch (toRadioScratch.which_variant) {
|
||||
case ToRadio_packet_tag: {
|
||||
|
@ -227,6 +247,9 @@ void PhoneAPI::handleToRadioPacket(MeshPacket *p) {}
|
|||
/// If the mesh service tells us fromNum has changed, tell the phone
|
||||
int PhoneAPI::onNotify(uint32_t newValue)
|
||||
{
|
||||
checkConnectionTimeout(); // a handy place to check if we've heard from the phone (since the BLE version doesn't call this
|
||||
// from idle)
|
||||
|
||||
if (state == STATE_SEND_PACKETS || state == STATE_LEGACY) {
|
||||
DEBUG_MSG("Telling client we have new packets %u\n", newValue);
|
||||
onNowHasData(newValue);
|
||||
|
|
|
@ -50,6 +50,11 @@ class PhoneAPI
|
|||
/// Use to ensure that clients don't get confused about old messages from the radio
|
||||
uint32_t config_nonce = 0;
|
||||
|
||||
/** the last msec we heard from the client on the other side of this link */
|
||||
uint32_t lastContactMsec = 0;
|
||||
|
||||
bool isConnected = false;
|
||||
|
||||
public:
|
||||
PhoneAPI();
|
||||
|
||||
|
@ -85,6 +90,12 @@ class PhoneAPI
|
|||
/// Our fromradio packet while it is being assembled
|
||||
FromRadio fromRadioScratch;
|
||||
|
||||
/// Hookable to find out when connection changes
|
||||
virtual void onConnectionChanged(bool connected) {}
|
||||
|
||||
/// If we haven't heard from the other side in a while then say not connected
|
||||
void checkConnectionTimeout();
|
||||
|
||||
/**
|
||||
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
|
||||
*/
|
||||
|
|
|
@ -9,6 +9,7 @@ void StreamAPI::loop()
|
|||
{
|
||||
writeStream();
|
||||
readStream();
|
||||
checkConnectionTimeout();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -129,6 +129,7 @@ static void waitEnterSleep()
|
|||
|
||||
if (millis() - now > 30 * 1000) { // If we wait too long just report an error and go to sleep
|
||||
recordCriticalError(ErrSleepEnterWait);
|
||||
ESP.restart(); // FIXME - for now we just restart, need to fix bug #167
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue