mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-26 18:09:04 +00:00
WIP moving positions to new system
This commit is contained in:
parent
7737123d0f
commit
d3cb9bdd4a
@ -4,9 +4,11 @@ You probably don't care about this section - skip to the next one.
|
|||||||
|
|
||||||
For app cleanup:
|
For app cleanup:
|
||||||
|
|
||||||
|
* have python tool check max packet size before sending to device
|
||||||
* require a recent python api to talk to these new device loads
|
* require a recent python api to talk to these new device loads
|
||||||
* on android for received positions handle either old or new positions
|
* on android for received positions handle either old or new positions
|
||||||
* on android side send old or new positions as needed
|
* on android side send old or new positions as needed
|
||||||
|
* fix position sending to use new plugin
|
||||||
* move positions into regular data packets (use new app framework)
|
* move positions into regular data packets (use new app framework)
|
||||||
* move user info into regular data packets (use new app framework)
|
* move user info into regular data packets (use new app framework)
|
||||||
* test that positions, text messages and user info still work
|
* test that positions, text messages and user info still work
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
*/
|
*/
|
||||||
class MeshPlugin
|
class MeshPlugin
|
||||||
{
|
{
|
||||||
const char *name;
|
|
||||||
|
|
||||||
static std::vector<MeshPlugin *> *plugins;
|
static std::vector<MeshPlugin *> *plugins;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -31,6 +29,8 @@ class MeshPlugin
|
|||||||
static void callPlugins(const MeshPacket &mp);
|
static void callPlugins(const MeshPacket &mp);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
const char *name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize your plugin. This setup function is called once after all hardware and mesh protocol layers have
|
* Initialize your plugin. This setup function is called once after all hardware and mesh protocol layers have
|
||||||
* been initialized
|
* been initialized
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
#include "plugins/PositionPlugin.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone.
|
receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone.
|
||||||
@ -254,7 +255,7 @@ void MeshService::sendToMesh(MeshPacket *p)
|
|||||||
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
|
// 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
|
// 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.
|
// devices can get time.
|
||||||
if (p->which_payload == MeshPacket_decoded_tag && p->decoded.which_payload == SubPacket_position_tag) {
|
if (p->which_payload == MeshPacket_decoded_tag && p->decoded.which_payload == SubPacket_position_tag && p->decoded.position.time) {
|
||||||
if (getRTCQuality() < RTCQualityGPS) {
|
if (getRTCQuality() < RTCQualityGPS) {
|
||||||
DEBUG_MSG("Stripping time %u from position send\n", p->decoded.position.time);
|
DEBUG_MSG("Stripping time %u from position send\n", p->decoded.position.time);
|
||||||
p->decoded.position.time = 0;
|
p->decoded.position.time = 0;
|
||||||
@ -273,27 +274,12 @@ void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
|
|||||||
|
|
||||||
DEBUG_MSG("Sending network ping to 0x%x, with position=%d, wantReplies=%d\n", dest, node->has_position, wantReplies);
|
DEBUG_MSG("Sending network ping to 0x%x, with position=%d, wantReplies=%d\n", dest, node->has_position, wantReplies);
|
||||||
if (node->has_position)
|
if (node->has_position)
|
||||||
sendOurPosition(dest, wantReplies);
|
positionPlugin.sendOurPosition(dest, wantReplies);
|
||||||
else
|
else
|
||||||
sendOurOwner(dest, wantReplies);
|
sendOurOwner(dest, wantReplies);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshService::sendOurPosition(NodeNum dest, bool wantReplies)
|
|
||||||
{
|
|
||||||
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
|
||||||
assert(node);
|
|
||||||
assert(node->has_position);
|
|
||||||
|
|
||||||
// Update our local node info with our position (even if we don't decide to update anyone else)
|
|
||||||
MeshPacket *p = router->allocForSending();
|
|
||||||
p->to = dest;
|
|
||||||
p->decoded.which_payload = SubPacket_position_tag;
|
|
||||||
p->decoded.position = node->position;
|
|
||||||
p->decoded.want_response = wantReplies;
|
|
||||||
p->decoded.position.time =
|
|
||||||
getValidTime(RTCQualityGPS); // This nodedb timestamp might be stale, so update it if our clock is valid.
|
|
||||||
sendToMesh(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
int MeshService::onGPSChanged(const meshtastic::GPSStatus *unused)
|
int MeshService::onGPSChanged(const meshtastic::GPSStatus *unused)
|
||||||
{
|
{
|
||||||
|
@ -78,15 +78,13 @@ class MeshService
|
|||||||
/// Send our owner info to a particular node
|
/// Send our owner info to a particular node
|
||||||
void sendOurOwner(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
|
void sendOurOwner(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
|
||||||
|
|
||||||
private:
|
|
||||||
/// Broadcasts our last known position
|
|
||||||
void sendOurPosition(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
|
|
||||||
|
|
||||||
/// Send a packet into the mesh - note p must have been allocated from packetPool. We will return it to that pool after
|
/// Send a packet into the mesh - note p must have been allocated from packetPool. We will return it to that pool after
|
||||||
/// sending. This is the ONLY function you should use for sending messages into the mesh, because it also updates the nodedb
|
/// sending. This is the ONLY function you should use for sending messages into the mesh, because it also updates the nodedb
|
||||||
/// cache
|
/// cache
|
||||||
void sendToMesh(MeshPacket *p);
|
void sendToMesh(MeshPacket *p);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
/// Called when our gps position has changed - updates nodedb and sends Location message out into the mesh
|
/// Called when our gps position has changed - updates nodedb and sends Location message out into the mesh
|
||||||
/// returns 0 to allow futher processing
|
/// returns 0 to allow futher processing
|
||||||
int onGPSChanged(const meshtastic::GPSStatus *arg);
|
int onGPSChanged(const meshtastic::GPSStatus *arg);
|
||||||
|
@ -405,6 +405,19 @@ size_t NodeDB::getNumOnlineNodes()
|
|||||||
|
|
||||||
#include "MeshPlugin.h"
|
#include "MeshPlugin.h"
|
||||||
|
|
||||||
|
/** Update position info for this node based on received position data
|
||||||
|
*/
|
||||||
|
void NodeDB::updatePosition(uint32_t nodeId, const Position &p) {
|
||||||
|
|
||||||
|
NodeInfo *info = getOrCreateNode(nodeId);
|
||||||
|
|
||||||
|
// we always trust our local timestamps more
|
||||||
|
info->position = p;
|
||||||
|
info->has_position = true;
|
||||||
|
updateGUIforNode = info;
|
||||||
|
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||||
|
}
|
||||||
|
|
||||||
/// given a subpacket sniffed from the network, update our DB state
|
/// given a subpacket sniffed from the network, update our DB state
|
||||||
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
||||||
void NodeDB::updateFrom(const MeshPacket &mp)
|
void NodeDB::updateFrom(const MeshPacket &mp)
|
||||||
@ -424,13 +437,9 @@ void NodeDB::updateFrom(const MeshPacket &mp)
|
|||||||
|
|
||||||
switch (p.which_payload) {
|
switch (p.which_payload) {
|
||||||
case SubPacket_position_tag: {
|
case SubPacket_position_tag: {
|
||||||
// we always trust our local timestamps more
|
// handle a legacy position packet
|
||||||
info->position = p.position;
|
DEBUG_MSG("WARNING: Processing a (deprecated) position packet from %d\n", mp.from);
|
||||||
if (mp.rx_time)
|
updatePosition(mp.from, p.position);
|
||||||
info->position.time = mp.rx_time;
|
|
||||||
info->has_position = true;
|
|
||||||
updateGUIforNode = info;
|
|
||||||
notifyObservers(true); // Force an update whether or not our node counts have changed
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,10 @@ class NodeDB
|
|||||||
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
||||||
void updateFrom(const MeshPacket &p);
|
void updateFrom(const MeshPacket &p);
|
||||||
|
|
||||||
|
/** Update position info for this node based on received position data
|
||||||
|
*/
|
||||||
|
void updatePosition(uint32_t nodeId, const Position &p);
|
||||||
|
|
||||||
/// @return our node number
|
/// @return our node number
|
||||||
NodeNum getNodeNum() { return myNodeInfo.my_node_num; }
|
NodeNum getNodeNum() { return myNodeInfo.my_node_num; }
|
||||||
|
|
||||||
|
3
src/mesh/ProtobufPlugin.cpp
Normal file
3
src/mesh/ProtobufPlugin.cpp
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#include "ProtobufPlugin.h"
|
||||||
|
|
||||||
|
|
72
src/mesh/ProtobufPlugin.h
Normal file
72
src/mesh/ProtobufPlugin.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#include "MeshPlugin.h"
|
||||||
|
#include "Router.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A base class for mesh plugins that assume that they are sending/receiving one particular protobuf based
|
||||||
|
* payload. Using one particular app ID.
|
||||||
|
*
|
||||||
|
* If you are using protobufs to encode your packets (recommended) you can use this as a baseclass for your plugin
|
||||||
|
* and avoid a bunch of boilerplate code.
|
||||||
|
*/
|
||||||
|
template <class T> class ProtobufPlugin : private MeshPlugin
|
||||||
|
{
|
||||||
|
const pb_msgdesc_t *fields;
|
||||||
|
PortNum ourPortNum;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Constructor
|
||||||
|
* name is for debugging output
|
||||||
|
*/
|
||||||
|
ProtobufPlugin(const char *_name, PortNum _ourPortNum, const pb_msgdesc_t *_fields)
|
||||||
|
: MeshPlugin(_name), fields(_fields), ourPortNum(_ourPortNum)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* @return true if you want to receive the specified portnum
|
||||||
|
*/
|
||||||
|
virtual bool wantPortnum(PortNum p) { return p == ourPortNum; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a received message, the data field in the message is already decoded and is provided
|
||||||
|
*/
|
||||||
|
virtual bool handleReceivedProtobuf(const MeshPacket &mp, const T &decoded) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a mesh packet which has been preinited with a particular protobuf data payload and port number.
|
||||||
|
* You can then send this packet (after customizing any of the payload fields you might need) with
|
||||||
|
* service.sendToMesh()
|
||||||
|
*/
|
||||||
|
MeshPacket *allocForSending(const T &payload)
|
||||||
|
{
|
||||||
|
// Update our local node info with our position (even if we don't decide to update anyone else)
|
||||||
|
MeshPacket *p = router->allocForSending();
|
||||||
|
p->decoded.which_payload = SubPacket_data_tag;
|
||||||
|
p->decoded.data.portnum = ourPortNum;
|
||||||
|
|
||||||
|
p->decoded.data.payload.size =
|
||||||
|
pb_encode_to_bytes(p->decoded.data.payload.bytes, sizeof(p->decoded.data.payload.bytes), fields, &payload);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** 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 bool handleReceived(const MeshPacket &mp)
|
||||||
|
{
|
||||||
|
// FIXME - we currently update position data in the DB only if the message was a broadcast or destined to us
|
||||||
|
// it would be better to update even if the message was destined to others.
|
||||||
|
|
||||||
|
auto &p = mp.decoded.data;
|
||||||
|
DEBUG_MSG("Received %s from=0x%0x, id=%d, msg=%.*s\n", name, mp.from, mp.id, p.payload.size, p.payload.bytes);
|
||||||
|
|
||||||
|
T scratch;
|
||||||
|
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch))
|
||||||
|
handleReceivedProtobuf(mp, scratch);
|
||||||
|
|
||||||
|
return false; // Let others look at this message also if they want
|
||||||
|
}
|
||||||
|
};
|
@ -1,13 +1,35 @@
|
|||||||
#include "configuration.h"
|
|
||||||
#include "PositionPlugin.h"
|
#include "PositionPlugin.h"
|
||||||
|
#include "MeshService.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
|
#include "RTC.h"
|
||||||
|
#include "Router.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
PositionPlugin positionPlugin;
|
PositionPlugin positionPlugin;
|
||||||
|
|
||||||
bool PositionPlugin::handleReceived(const MeshPacket &mp)
|
bool PositionPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Position &p)
|
||||||
{
|
{
|
||||||
auto &p = mp.decoded.data;
|
// FIXME - we currently update position data in the DB only if the message was a broadcast or destined to us
|
||||||
DEBUG_MSG("Received position from=0x%0x, id=%d, msg=%.*s\n", mp.from, mp.id, p.payload.size, p.payload.bytes);
|
// it would be better to update even if the message was destined to others.
|
||||||
|
|
||||||
|
nodeDB.updatePosition(mp.from, p);
|
||||||
|
|
||||||
return false; // Let others look at this message also if they want
|
return false; // Let others look at this message also if they want
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PositionPlugin::sendOurPosition(NodeNum dest, bool wantReplies)
|
||||||
|
{
|
||||||
|
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
||||||
|
assert(node);
|
||||||
|
assert(node->has_position);
|
||||||
|
|
||||||
|
// Update our local node info with our position (even if we don't decide to update anyone else)
|
||||||
|
auto position = node->position;
|
||||||
|
position.time = getValidTime(RTCQualityGPS); // This nodedb timestamp might be stale, so update it if our clock is valid.
|
||||||
|
|
||||||
|
MeshPacket *p = allocForSending(position);
|
||||||
|
p->to = dest;
|
||||||
|
p->decoded.want_response = wantReplies;
|
||||||
|
|
||||||
|
service.sendToMesh(p);
|
||||||
|
}
|
||||||
|
28
src/plugins/PositionPlugin.h
Normal file
28
src/plugins/PositionPlugin.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "ProtobufPlugin.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Position plugin for sending/receiving positions into the mesh
|
||||||
|
*/
|
||||||
|
class PositionPlugin : public ProtobufPlugin<Position>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Constructor
|
||||||
|
* name is for debugging output
|
||||||
|
*/
|
||||||
|
PositionPlugin() : ProtobufPlugin("position", PortNum_POSITION_APP, Position_fields) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send our position into the mesh
|
||||||
|
*/
|
||||||
|
void sendOurPosition(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 bool handleReceivedProtobuf(const MeshPacket &mp, const Position &p);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern PositionPlugin positionPlugin;
|
Loading…
Reference in New Issue
Block a user