mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-19 09:12:45 +00:00
begin cleaning up mesh library layer so that it could be split someday
This commit is contained in:
238
src/mesh/PhoneAPI.cpp
Normal file
238
src/mesh/PhoneAPI.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
#include "PhoneAPI.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include <assert.h>
|
||||
|
||||
PhoneAPI::PhoneAPI()
|
||||
{
|
||||
// Make sure that we never let our packets grow too large for one BLE packet
|
||||
assert(FromRadio_size <= 512);
|
||||
assert(ToRadio_size <= 512);
|
||||
}
|
||||
|
||||
void PhoneAPI::init()
|
||||
{
|
||||
observe(&service.fromNumChanged);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a ToRadio protobuf
|
||||
*/
|
||||
void PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
|
||||
{
|
||||
if (pb_decode_from_bytes(buf, bufLength, ToRadio_fields, &toRadioScratch)) {
|
||||
switch (toRadioScratch.which_variant) {
|
||||
case ToRadio_packet_tag: {
|
||||
// If our phone is sending a position, see if we can use it to set our RTC
|
||||
MeshPacket &p = toRadioScratch.variant.packet;
|
||||
service.handleToRadio(p);
|
||||
break;
|
||||
}
|
||||
case ToRadio_want_config_id_tag:
|
||||
config_nonce = toRadioScratch.variant.want_config_id;
|
||||
DEBUG_MSG("Client wants config, nonce=%u\n", config_nonce);
|
||||
state = STATE_SEND_MY_INFO;
|
||||
|
||||
DEBUG_MSG("Reset nodeinfo read pointer\n");
|
||||
nodeInfoForPhone = NULL; // Don't keep returning old nodeinfos
|
||||
nodeDB.resetReadPointer(); // FIXME, this read pointer should be moved out of nodeDB and into this class - because
|
||||
// this will break once we have multiple instances of PhoneAPI running independently
|
||||
break;
|
||||
|
||||
case ToRadio_set_owner_tag:
|
||||
DEBUG_MSG("Client is setting owner\n");
|
||||
handleSetOwner(toRadioScratch.variant.set_owner);
|
||||
break;
|
||||
|
||||
case ToRadio_set_radio_tag:
|
||||
DEBUG_MSG("Client is setting radio\n");
|
||||
handleSetRadio(toRadioScratch.variant.set_radio);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_MSG("Error: unexpected ToRadio variant\n");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
DEBUG_MSG("Error: ignoring malformed toradio\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next packet we want to send to the phone, or NULL if no such packet is available.
|
||||
*
|
||||
* We assume buf is at least FromRadio_size bytes long.
|
||||
*
|
||||
* Our sending states progress in the following sequence (the client app ASSUMES THIS SEQUENCE, DO NOT CHANGE IT):
|
||||
* STATE_SEND_MY_INFO, // send our my info record
|
||||
STATE_SEND_RADIO,
|
||||
STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client
|
||||
STATE_SEND_COMPLETE_ID,
|
||||
STATE_SEND_PACKETS // send packets or debug strings
|
||||
*/
|
||||
size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||
{
|
||||
if (!available())
|
||||
return false;
|
||||
|
||||
// In case we send a FromRadio packet
|
||||
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
|
||||
|
||||
// Advance states as needed
|
||||
switch (state) {
|
||||
case STATE_SEND_NOTHING:
|
||||
break;
|
||||
|
||||
case STATE_SEND_MY_INFO:
|
||||
fromRadioScratch.which_variant = FromRadio_my_info_tag;
|
||||
fromRadioScratch.variant.my_info = myNodeInfo;
|
||||
state = STATE_SEND_RADIO;
|
||||
break;
|
||||
|
||||
case STATE_SEND_RADIO:
|
||||
fromRadioScratch.which_variant = FromRadio_radio_tag;
|
||||
fromRadioScratch.variant.radio = radioConfig;
|
||||
state = STATE_SEND_NODEINFO;
|
||||
break;
|
||||
|
||||
case STATE_SEND_NODEINFO: {
|
||||
const NodeInfo *info = nodeInfoForPhone;
|
||||
nodeInfoForPhone = NULL; // We just consumed a nodeinfo, will need a new one next time
|
||||
|
||||
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);
|
||||
fromRadioScratch.which_variant = FromRadio_node_info_tag;
|
||||
fromRadioScratch.variant.node_info = *info;
|
||||
// Stay in current state until done sending nodeinfos
|
||||
} else {
|
||||
DEBUG_MSG("Done sending nodeinfos\n");
|
||||
state = STATE_SEND_COMPLETE_ID;
|
||||
// Go ahead and send that ID right now
|
||||
return getFromRadio(buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case STATE_SEND_COMPLETE_ID:
|
||||
fromRadioScratch.which_variant = FromRadio_config_complete_id_tag;
|
||||
fromRadioScratch.variant.config_complete_id = config_nonce;
|
||||
config_nonce = 0;
|
||||
state = STATE_SEND_PACKETS;
|
||||
break;
|
||||
|
||||
case STATE_LEGACY: // Treat as the same as send packets
|
||||
case STATE_SEND_PACKETS:
|
||||
// Do we have a message from the mesh?
|
||||
if (packetForPhone) {
|
||||
// Encapsulate as a FromRadio packet
|
||||
fromRadioScratch.which_variant = FromRadio_packet_tag;
|
||||
fromRadioScratch.variant.packet = *packetForPhone;
|
||||
|
||||
service.releaseToPool(packetForPhone); // we just copied the bytes, so don't need this buffer anymore
|
||||
packetForPhone = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0); // unexpected state - FIXME, make an error code and reboot
|
||||
}
|
||||
|
||||
// Do we have a message from the mesh?
|
||||
if (fromRadioScratch.which_variant != 0) {
|
||||
// Encapsulate as a FromRadio packet
|
||||
DEBUG_MSG("encoding toPhone packet to phone variant=%d", fromRadioScratch.which_variant);
|
||||
size_t numbytes = pb_encode_to_bytes(buf, FromRadio_size, FromRadio_fields, &fromRadioScratch);
|
||||
DEBUG_MSG(", %d bytes\n", numbytes);
|
||||
return numbytes;
|
||||
}
|
||||
|
||||
DEBUG_MSG("no FromRadio packet available\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if we have data available to send to the phone
|
||||
*/
|
||||
bool PhoneAPI::available()
|
||||
{
|
||||
switch (state) {
|
||||
case STATE_SEND_NOTHING:
|
||||
return false;
|
||||
|
||||
case STATE_SEND_MY_INFO:
|
||||
return true;
|
||||
|
||||
case STATE_SEND_NODEINFO:
|
||||
if (!nodeInfoForPhone)
|
||||
nodeInfoForPhone = nodeDB.readNextInfo();
|
||||
return true; // Always say we have something, because we might need to advance our state machine
|
||||
|
||||
case STATE_SEND_RADIO:
|
||||
return true;
|
||||
|
||||
case STATE_SEND_COMPLETE_ID:
|
||||
return true;
|
||||
|
||||
case STATE_LEGACY: // Treat as the same as send packets
|
||||
case STATE_SEND_PACKETS:
|
||||
// Try to pull a new packet from the service (if we haven't already)
|
||||
if (!packetForPhone)
|
||||
packetForPhone = service.getForPhone();
|
||||
return !!packetForPhone;
|
||||
|
||||
default:
|
||||
assert(0); // unexpected state - FIXME, make an error code and reboot
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// The following routines are only public for now - until the rev1 bluetooth API is removed
|
||||
//
|
||||
|
||||
void PhoneAPI::handleSetOwner(const User &o)
|
||||
{
|
||||
int changed = 0;
|
||||
|
||||
if (*o.long_name) {
|
||||
changed |= strcmp(owner.long_name, o.long_name);
|
||||
strcpy(owner.long_name, o.long_name);
|
||||
}
|
||||
if (*o.short_name) {
|
||||
changed |= strcmp(owner.short_name, o.short_name);
|
||||
strcpy(owner.short_name, o.short_name);
|
||||
}
|
||||
if (*o.id) {
|
||||
changed |= strcmp(owner.id, o.id);
|
||||
strcpy(owner.id, o.id);
|
||||
}
|
||||
|
||||
if (changed) // If nothing really changed, don't broadcast on the network or write to flash
|
||||
service.reloadOwner();
|
||||
}
|
||||
|
||||
void PhoneAPI::handleSetRadio(const RadioConfig &r)
|
||||
{
|
||||
radioConfig = r;
|
||||
|
||||
service.reloadConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a packet that the phone wants us to send. It is our responsibility to free the packet to the pool
|
||||
*/
|
||||
void PhoneAPI::handleToRadioPacket(MeshPacket *p) {}
|
||||
|
||||
/// If the mesh service tells us fromNum has changed, tell the phone
|
||||
int PhoneAPI::onNotify(uint32_t newValue)
|
||||
{
|
||||
if (state == STATE_SEND_PACKETS || state == STATE_LEGACY) {
|
||||
DEBUG_MSG("Telling client we have new packets %u\n", newValue);
|
||||
onNowHasData(newValue);
|
||||
} else
|
||||
DEBUG_MSG("(Client not yet interested in packets)\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user