2020-02-02 20:45:32 +00:00
# include <Arduino.h>
# include <assert.h>
2020-04-15 03:22:27 +00:00
# include <string>
2020-02-02 20:45:32 +00:00
2020-03-19 02:15:51 +00:00
# include "GPS.h"
2020-04-10 19:18:48 +00:00
//#include "MeshBluetoothService.h"
2020-07-10 02:57:55 +00:00
# include "../concurrency/Periodic.h"
# include "BluetoothCommon.h" // needed for updateBatteryLevel, FIXME, eventually when we pull mesh out into a lib we shouldn't be whacking bluetooth from here
2020-03-19 02:15:51 +00:00
# include "MeshService.h"
2020-02-03 17:13:19 +00:00
# include "NodeDB.h"
2020-03-03 21:31:44 +00:00
# include "PowerFSM.h"
2020-10-07 23:28:57 +00:00
# include "RTC.h"
2020-03-19 02:15:51 +00:00
# include "main.h"
# include "mesh-pb-constants.h"
Report battery level to other nodes in mesh (and apps).
Also today I'll turn back on the the standard "has a battery" BLE
device profile, so the locally connected radio should show up in the
phone's bluetooth popup of battery levels (similar to how a BLE
headphone battery level appears)
cc @lgoix - using code from @professr
```
meshtastic --info
Connected to radio...
my_node_num: 2883444536
has_gps: true
num_channels: 13
region: "unset"
hw_model: "tbeam"
firmware_version: "unset"
packet_id_bits: 32
current_packet_id: 91018534
node_num_bits: 32
message_timeout_msec: 300000
min_app_version: 172
preferences {
position_broadcast_secs: 900
send_owner_interval: 4
wait_bluetooth_secs: 120
screen_on_secs: 300
phone_timeout_secs: 900
phone_sds_timeout_sec: 7200
mesh_sds_timeout_secs: 7200
sds_secs: 31536000
ls_secs: 3600
}
channel_settings {
tx_power: 23
modem_config: Bw125Cr48Sf4096
psk: "\324\361\273: )\007Y\360\274\377\253\317Ni\277"
name: "Default"
}
Nodes in mesh:
{'num': 2883444536, 'user': {'id': '!2462abdddf38', 'longName': 'Unknown df38', 'shortName': '?38', 'macaddr': 'JGKr3d84'}, 'position': {'altitude': 96, 'batteryLevel': 100, 'latitudeI': 375210641, 'longitudeI': -1223090398, 'time': 1592843564, 'latitude': 37.5210641, 'longitude': -122.3090398}}
```
2020-06-22 16:36:19 +00:00
# include "power.h"
2020-12-03 08:48:44 +00:00
# include "plugins/PositionPlugin.h"
2020-02-02 20:45:32 +00:00
/*
receivedPacketQueue - this is a queue of messages we ' ve received from the mesh , which we are keeping to deliver to the phone .
2020-03-19 02:15:51 +00:00
It is implemented with a FreeRTos queue ( wrapped with a little RTQueue class ) of pointers to MeshPacket protobufs ( which were
alloced with new ) . After a packet ptr is removed from the queue and processed it should be deleted . ( eventually we should move
sent packets into a ' sentToPhone ' queue of packets we can delete just as soon as we are sure the phone has acked those packets -
when the phone writes to FromNum )
2020-02-02 20:45:32 +00:00
2020-03-19 02:15:51 +00:00
mesh - an instance of Mesh class . Which manages the interface to the mesh radio library , reception of packets from other nodes ,
arbitrating to select a node number and keeping the current nodedb .
2020-02-02 20:45:32 +00:00
*/
2020-02-08 20:42:54 +00:00
/* Broadcast when a newly powered mesh node wants to find a node num it can use
The algoritm is as follows :
2020-03-19 02:15:51 +00:00
* when a node starts up , it broadcasts their user and the normal flow is for all other nodes to reply with their User as well ( so
the new node can build its node db )
* If a node ever receives a User ( not just the first broadcast ) message where the sender node number equals our node number , that
indicates a collision has occurred and the following steps should happen :
2020-02-08 20:42:54 +00:00
2020-03-19 02:15:51 +00:00
If the receiving node ( that was already in the mesh ) ' s macaddr is LOWER than the new User who just tried to sign in : it gets to
keep its nodenum . We send a broadcast message of OUR User ( we use a broadcast so that the other node can receive our message ,
considering we have the same id - it also serves to let observers correct their nodedb ) - this case is rare so it should be okay .
2020-02-08 20:42:54 +00:00
2020-03-19 02:15:51 +00:00
If any node receives a User where the macaddr is GTE than their local macaddr , they have been vetoed and should pick a new random
nodenum ( filtering against whatever it knows about the nodedb ) and rebroadcast their User .
2020-02-08 20:42:54 +00:00
FIXME in the initial proof of concept we just skip the entire want / deny flow and just hand pick node numbers at first .
*/
2020-02-02 20:45:32 +00:00
2020-02-08 20:42:54 +00:00
MeshService service ;
2020-02-08 18:00:15 +00:00
2020-04-17 16:48:54 +00:00
# include "Router.h"
2020-02-03 17:13:19 +00:00
2020-10-10 01:57:57 +00:00
static int32_t sendOwnerCb ( )
2020-04-25 17:59:40 +00:00
{
service . sendOurOwner ( ) ;
2020-10-06 01:43:00 +00:00
return getPref_send_owner_interval ( ) * getPref_position_broadcast_secs ( ) * 1000 ;
2020-04-25 17:59:40 +00:00
}
2020-10-10 01:57:57 +00:00
static concurrency : : Periodic * sendOwnerPeriod ;
2020-04-25 17:59:40 +00:00
2020-04-17 16:48:54 +00:00
MeshService : : MeshService ( ) : toPhoneQueue ( MAX_RX_TOPHONE )
2020-02-02 20:45:32 +00:00
{
2020-02-03 17:13:19 +00:00
// assert(MAX_RX_TOPHONE == 32); // FIXME, delete this, just checking my clever macro
2020-02-02 20:45:32 +00:00
}
void MeshService : : init ( )
{
2020-10-10 01:57:57 +00:00
sendOwnerPeriod = new concurrency : : Periodic ( " SendOwner " , sendOwnerCb ) ;
2020-02-04 17:00:17 +00:00
nodeDB . init ( ) ;
2020-02-06 16:49:33 +00:00
2020-09-06 21:45:43 +00:00
if ( gps )
gpsObserver . observe ( & gps - > newStatus ) ;
2020-10-10 01:57:57 +00:00
packetReceivedObserver . observe ( & router - > notifyPacketReceived ) ;
2020-02-06 18:58:19 +00:00
}
2020-03-25 20:09:12 +00:00
void MeshService : : sendOurOwner ( NodeNum dest , bool wantReplies )
2020-02-06 18:58:19 +00:00
{
2020-10-10 01:57:57 +00:00
MeshPacket * p = router - > allocForSending ( ) ;
2020-02-06 18:58:19 +00:00
p - > to = dest ;
2020-05-10 00:51:20 +00:00
p - > decoded . want_response = wantReplies ;
2020-05-12 20:35:22 +00:00
p - > decoded . which_payload = SubPacket_user_tag ;
2020-05-10 00:51:20 +00:00
User & u = p - > decoded . user ;
2020-02-06 18:58:19 +00:00
u = owner ;
2020-02-07 17:36:15 +00:00
DEBUG_MSG ( " sending owner %s/%s/%s \n " , u . id , u . long_name , u . short_name ) ;
2020-02-06 18:58:19 +00:00
sendToMesh ( p ) ;
2020-02-02 20:45:32 +00:00
}
2020-02-13 03:58:44 +00:00
/// handle a user packet that just arrived on the radio, return NULL if we should not process this packet at all
2020-04-17 16:48:54 +00:00
const MeshPacket * MeshService : : handleFromRadioUser ( const MeshPacket * mp )
2020-02-13 03:58:44 +00:00
{
bool wasBroadcast = mp - > to = = NODENUM_BROADCAST ;
2020-06-06 20:16:36 +00:00
// Disable this collision testing if we use 32 bit nodenums
2020-11-28 01:56:21 +00:00
// (We do this always now, because we don't use 8 bit nodenums since 0.6 ish)
bool isCollision = false ; // (sizeof(NodeNum) == 1) && (mp->from == myNodeInfo.my_node_num);
2020-02-13 03:58:44 +00:00
2020-03-19 02:15:51 +00:00
if ( isCollision ) {
2020-06-06 20:16:36 +00:00
// we win if we have a lower macaddr
bool weWin = memcmp ( & owner . macaddr , & mp - > decoded . user . macaddr , sizeof ( owner . macaddr ) ) < 0 ;
2020-03-19 02:15:51 +00:00
if ( weWin ) {
2020-02-13 03:58:44 +00:00
DEBUG_MSG ( " NOTE! Received a nodenum collision and we are vetoing \n " ) ;
mp = NULL ;
sendOurOwner ( ) ; // send our owner as a _broadcast_ because that other guy is mistakenly using our nodenum
2020-03-19 02:15:51 +00:00
} else {
2020-02-13 03:58:44 +00:00
// we lost, we need to try for a new nodenum!
DEBUG_MSG ( " NOTE! Received a nodenum collision we lost, so picking a new nodenum \n " ) ;
2020-03-19 02:15:51 +00:00
nodeDB . updateFrom (
* mp ) ; // update the DB early - before trying to repick (so we don't select the same node number again)
2020-02-13 03:58:44 +00:00
nodeDB . pickNewNodeNum ( ) ;
sendOurOwner ( ) ; // broadcast our new attempt at a node number
}
2020-03-19 02:15:51 +00:00
} else if ( wasBroadcast ) {
// If we haven't yet abandoned the packet and it was a broadcast, reply (just to them) with our User record so they can
// build their DB
2020-02-13 03:58:44 +00:00
// Someone just sent us a User, reply with our Owner
DEBUG_MSG ( " Received broadcast Owner from 0x%x, replying with our owner \n " , mp - > from ) ;
sendOurOwner ( mp - > from ) ;
2020-05-10 00:51:20 +00:00
String lcd = String ( " Joined: " ) + mp - > decoded . user . long_name + " \n " ;
2020-10-10 01:57:57 +00:00
screen - > print ( lcd . c_str ( ) ) ;
2020-02-13 03:58:44 +00:00
}
return mp ;
}
2020-04-17 16:48:54 +00:00
void MeshService : : handleIncomingPosition ( const MeshPacket * mp )
2020-02-26 17:00:53 +00:00
{
2020-05-12 20:35:22 +00:00
if ( mp - > which_payload = = MeshPacket_decoded_tag & & mp - > decoded . which_payload = = SubPacket_position_tag ) {
2020-05-10 00:51:20 +00:00
DEBUG_MSG ( " handled incoming position time=%u \n " , mp - > decoded . position . time ) ;
2020-02-26 17:00:53 +00:00
2020-05-10 00:51:20 +00:00
if ( mp - > decoded . position . time ) {
2020-02-26 17:00:53 +00:00
struct timeval tv ;
2020-05-10 00:51:20 +00:00
uint32_t secs = mp - > decoded . position . time ;
2020-02-26 17:00:53 +00:00
tv . tv_sec = secs ;
tv . tv_usec = 0 ;
2020-10-07 23:46:20 +00:00
perhapsSetRTC ( RTCQualityFromNet , & tv ) ;
2020-02-26 17:00:53 +00:00
}
2020-03-25 20:35:49 +00:00
} else {
DEBUG_MSG ( " Ignoring incoming packet - not a position \n " ) ;
2020-02-26 17:00:53 +00:00
}
}
2020-04-17 16:48:54 +00:00
int MeshService : : handleFromRadio ( const MeshPacket * mp )
2020-02-18 01:47:01 +00:00
{
2020-03-03 21:31:44 +00:00
powerFSM . trigger ( EVENT_RECEIVED_PACKET ) ; // Possibly keep the node from sleeping
2020-10-09 02:01:13 +00:00
// If it is a position packet, perhaps set our clock - this must be before nodeDB.updateFrom
2020-10-07 23:46:20 +00:00
handleIncomingPosition ( mp ) ;
2020-02-26 17:00:53 +00:00
2020-05-12 20:35:22 +00:00
if ( mp - > which_payload = = MeshPacket_decoded_tag & & mp - > decoded . which_payload = = SubPacket_user_tag ) {
2020-02-18 01:47:01 +00:00
mp = handleFromRadioUser ( mp ) ;
}
// If we veto a received User packet, we don't put it into the DB or forward it to the phone (to prevent confusing it)
2020-03-19 02:15:51 +00:00
if ( mp ) {
2020-06-14 22:30:42 +00:00
printPacket ( " Forwarding to phone " , mp ) ;
2020-02-18 01:47:01 +00:00
nodeDB . updateFrom ( * mp ) ; // update our DB state based off sniffing every RX packet from the radio
fromNum + + ;
2020-03-19 02:15:51 +00:00
if ( toPhoneQueue . numFree ( ) = = 0 ) {
2020-02-18 01:47:01 +00:00
DEBUG_MSG ( " NOTE: tophone queue is full, discarding oldest \n " ) ;
MeshPacket * d = toPhoneQueue . dequeuePtr ( 0 ) ;
if ( d )
releaseToPool ( d ) ;
}
2020-04-17 16:48:54 +00:00
MeshPacket * copied = packetPool . allocCopy ( * mp ) ;
assert ( toPhoneQueue . enqueue ( copied , 0 ) ) ; // FIXME, instead of failing for full queue, delete the oldest mssages
2020-02-20 02:51:17 +00:00
2020-05-10 00:51:20 +00:00
if ( mp - > decoded . want_response )
2020-02-20 02:51:17 +00:00
sendNetworkPing ( mp - > from ) ;
2020-04-05 20:58:38 +00:00
} else {
DEBUG_MSG ( " Not delivering vetoed User message \n " ) ;
}
2020-02-13 03:58:44 +00:00
2020-04-17 16:48:54 +00:00
return 0 ;
2020-02-02 20:45:32 +00:00
}
2020-02-08 17:39:26 +00:00
/// Do idle processing (mostly processing messages which have been queued from the radio)
void MeshService : : loop ( )
{
2020-04-17 16:48:54 +00:00
if ( oldFromNum ! = fromNum ) { // We don't want to generate extra notifies for multiple new packets
fromNumChanged . notifyObservers ( fromNum ) ;
2020-04-17 20:05:16 +00:00
oldFromNum = fromNum ;
2020-04-17 16:48:54 +00:00
}
2020-02-08 17:39:26 +00:00
}
2020-02-11 19:56:48 +00:00
/// The radioConfig object just changed, call this to force the hw to change to the new settings
2020-09-19 18:19:42 +00:00
bool MeshService : : reloadConfig ( )
2020-02-11 19:56:48 +00:00
{
// If we can successfully set this radio to these settings, save them to disk
2020-10-29 05:26:36 +00:00
// This will also update the region as needed
2020-09-19 18:19:42 +00:00
bool didReset = nodeDB . resetRadioConfig ( ) ; // Don't let the phone send us fatally bad settings
2020-10-29 05:26:36 +00:00
2020-04-14 18:40:49 +00:00
configChanged . notifyObservers ( NULL ) ;
2020-02-11 19:56:48 +00:00
nodeDB . saveToDisk ( ) ;
2020-09-19 18:19:42 +00:00
return didReset ;
2020-02-11 19:56:48 +00:00
}
2020-09-16 16:08:35 +00:00
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh
void MeshService : : reloadOwner ( )
{
sendOurOwner ( ) ;
nodeDB . saveToDisk ( ) ;
}
2020-04-22 21:55:36 +00:00
/**
* Given a ToRadio buffer parse it and properly handle it ( setup radio , owner or send packet into the mesh )
2020-04-25 17:59:40 +00:00
* Called by PhoneAPI . handleToRadio . Note : p is a scratch buffer , this function is allowed to write to it but it can not keep a
* reference
2020-04-22 21:55:36 +00:00
*/
void MeshService : : handleToRadio ( MeshPacket & p )
2020-02-02 20:45:32 +00:00
{
2020-04-22 21:55:36 +00:00
handleIncomingPosition ( & p ) ; // If it is a position packet, perhaps set our clock
2020-02-02 20:45:32 +00:00
2020-04-22 21:55:36 +00:00
if ( p . from = = 0 ) // If the phone didn't set a sending node ID, use ours
p . from = nodeDB . getNodeNum ( ) ;
2020-02-19 18:53:09 +00:00
2020-04-22 21:55:36 +00:00
if ( p . id = = 0 )
p . id = generatePacketId ( ) ; // If the phone didn't supply one, then pick one
2020-04-17 18:52:20 +00:00
2020-10-09 02:01:13 +00:00
p . rx_time = getValidTime ( RTCQualityFromNet ) ; // Record the time the packet arrived from the phone
2020-10-09 06:16:51 +00:00
// (so we update our nodedb for the local node)
2020-04-17 19:41:01 +00:00
2020-04-22 21:55:36 +00:00
// Send the packet into the mesh
2020-02-19 18:53:09 +00:00
2020-04-22 21:55:36 +00:00
sendToMesh ( packetPool . allocCopy ( p ) ) ;
2020-04-17 18:52:20 +00:00
2020-04-22 21:55:36 +00:00
bool loopback = false ; // if true send any packet the phone sends back itself (for testing)
if ( loopback ) {
// no need to copy anymore because handle from radio assumes it should _not_ delete
// packetPool.allocCopy(r.variant.packet);
handleFromRadio ( & p ) ;
// handleFromRadio will tell the phone a new packet arrived
2020-03-15 23:27:15 +00:00
}
2020-02-02 20:45:32 +00:00
}
2020-02-06 16:49:33 +00:00
void MeshService : : sendToMesh ( MeshPacket * p )
2020-02-02 20:45:32 +00:00
{
2020-02-17 00:03:16 +00:00
nodeDB . updateFrom ( * p ) ; // update our local DB for this packet (because phone might have sent position packets etc...)
2020-02-19 04:17:11 +00:00
2020-03-19 02:15:51 +00:00
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
2020-10-10 01:20:38 +00:00
// nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless
2020-03-19 02:15:51 +00:00
// devices can get time.
2020-12-03 08:48:44 +00:00
if ( p - > which_payload = = MeshPacket_decoded_tag & & p - > decoded . which_payload = = SubPacket_position_tag & & p - > decoded . position . time ) {
2020-10-10 01:20:38 +00:00
if ( getRTCQuality ( ) < RTCQualityGPS ) {
2020-05-10 00:51:20 +00:00
DEBUG_MSG ( " Stripping time %u from position send \n " , p - > decoded . position . time ) ;
p - > decoded . position . time = 0 ;
2020-03-25 20:09:12 +00:00
} else
2020-05-10 00:51:20 +00:00
DEBUG_MSG ( " Providing time to mesh %u \n " , p - > decoded . position . time ) ;
2020-02-26 17:00:53 +00:00
}
2020-02-19 23:29:18 +00:00
2020-05-19 18:56:17 +00:00
// Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it
2020-10-10 01:57:57 +00:00
router - > sendLocal ( p ) ;
2020-02-06 16:49:33 +00:00
}
2020-02-02 20:45:32 +00:00
2020-03-25 20:09:12 +00:00
void MeshService : : sendNetworkPing ( NodeNum dest , bool wantReplies )
2020-02-12 22:07:06 +00:00
{
NodeInfo * node = nodeDB . getNode ( nodeDB . getNodeNum ( ) ) ;
assert ( node ) ;
2020-03-25 20:09:12 +00:00
DEBUG_MSG ( " Sending network ping to 0x%x, with position=%d, wantReplies=%d \n " , dest , node - > has_position , wantReplies ) ;
2020-02-12 22:07:06 +00:00
if ( node - > has_position )
2020-12-03 08:48:44 +00:00
positionPlugin . sendOurPosition ( dest , wantReplies ) ;
2020-02-12 22:07:06 +00:00
else
2020-03-25 20:09:12 +00:00
sendOurOwner ( dest , wantReplies ) ;
2020-02-12 22:07:06 +00:00
}
2020-08-12 22:51:57 +00:00
int MeshService : : onGPSChanged ( const meshtastic : : GPSStatus * unused )
2020-02-06 18:58:19 +00:00
{
2020-02-12 22:07:06 +00:00
// Update our local node info with our position (even if we don't decide to update anyone else)
2020-10-10 01:57:57 +00:00
MeshPacket * p = router - > allocForSending ( ) ;
2020-05-12 20:35:22 +00:00
p - > decoded . which_payload = SubPacket_position_tag ;
2020-03-18 21:51:54 +00:00
2020-05-10 00:51:20 +00:00
Position & pos = p - > decoded . position ;
2020-09-16 16:18:44 +00:00
if ( gps - > hasLock ( ) ) {
2020-05-04 18:15:05 +00:00
if ( gps - > altitude ! = 0 )
pos . altitude = gps - > altitude ;
pos . latitude_i = gps - > latitude ;
pos . longitude_i = gps - > longitude ;
2020-03-19 01:34:22 +00:00
}
2020-02-06 16:49:33 +00:00
2020-10-09 02:01:13 +00:00
pos . time = getValidTime ( RTCQualityGPS ) ;
Report battery level to other nodes in mesh (and apps).
Also today I'll turn back on the the standard "has a battery" BLE
device profile, so the locally connected radio should show up in the
phone's bluetooth popup of battery levels (similar to how a BLE
headphone battery level appears)
cc @lgoix - using code from @professr
```
meshtastic --info
Connected to radio...
my_node_num: 2883444536
has_gps: true
num_channels: 13
region: "unset"
hw_model: "tbeam"
firmware_version: "unset"
packet_id_bits: 32
current_packet_id: 91018534
node_num_bits: 32
message_timeout_msec: 300000
min_app_version: 172
preferences {
position_broadcast_secs: 900
send_owner_interval: 4
wait_bluetooth_secs: 120
screen_on_secs: 300
phone_timeout_secs: 900
phone_sds_timeout_sec: 7200
mesh_sds_timeout_secs: 7200
sds_secs: 31536000
ls_secs: 3600
}
channel_settings {
tx_power: 23
modem_config: Bw125Cr48Sf4096
psk: "\324\361\273: )\007Y\360\274\377\253\317Ni\277"
name: "Default"
}
Nodes in mesh:
{'num': 2883444536, 'user': {'id': '!2462abdddf38', 'longName': 'Unknown df38', 'shortName': '?38', 'macaddr': 'JGKr3d84'}, 'position': {'altitude': 96, 'batteryLevel': 100, 'latitudeI': 375210641, 'longitudeI': -1223090398, 'time': 1592843564, 'latitude': 37.5210641, 'longitude': -122.3090398}}
```
2020-06-22 16:36:19 +00:00
// Include our current battery voltage in our position announcement
2020-06-29 01:17:52 +00:00
pos . battery_level = powerStatus - > getBatteryChargePercent ( ) ;
2020-06-22 17:04:26 +00:00
updateBatteryLevel ( pos . battery_level ) ;
Report battery level to other nodes in mesh (and apps).
Also today I'll turn back on the the standard "has a battery" BLE
device profile, so the locally connected radio should show up in the
phone's bluetooth popup of battery levels (similar to how a BLE
headphone battery level appears)
cc @lgoix - using code from @professr
```
meshtastic --info
Connected to radio...
my_node_num: 2883444536
has_gps: true
num_channels: 13
region: "unset"
hw_model: "tbeam"
firmware_version: "unset"
packet_id_bits: 32
current_packet_id: 91018534
node_num_bits: 32
message_timeout_msec: 300000
min_app_version: 172
preferences {
position_broadcast_secs: 900
send_owner_interval: 4
wait_bluetooth_secs: 120
screen_on_secs: 300
phone_timeout_secs: 900
phone_sds_timeout_sec: 7200
mesh_sds_timeout_secs: 7200
sds_secs: 31536000
ls_secs: 3600
}
channel_settings {
tx_power: 23
modem_config: Bw125Cr48Sf4096
psk: "\324\361\273: )\007Y\360\274\377\253\317Ni\277"
name: "Default"
}
Nodes in mesh:
{'num': 2883444536, 'user': {'id': '!2462abdddf38', 'longName': 'Unknown df38', 'shortName': '?38', 'macaddr': 'JGKr3d84'}, 'position': {'altitude': 96, 'batteryLevel': 100, 'latitudeI': 375210641, 'longitudeI': -1223090398, 'time': 1592843564, 'latitude': 37.5210641, 'longitude': -122.3090398}}
```
2020-06-22 16:36:19 +00:00
2020-08-12 22:51:57 +00:00
// DEBUG_MSG("got gps notify time=%u, lat=%d, bat=%d\n", pos.latitude_i, pos.time, pos.battery_level);
2020-02-12 22:07:06 +00:00
// We limit our GPS broadcasts to a max rate
static uint32_t lastGpsSend ;
2020-09-05 19:34:48 +00:00
uint32_t now = millis ( ) ;
2020-10-06 01:43:00 +00:00
if ( lastGpsSend = = 0 | | now - lastGpsSend > getPref_position_broadcast_secs ( ) * 1000 ) {
2020-02-12 22:07:06 +00:00
lastGpsSend = now ;
DEBUG_MSG ( " Sending position to mesh \n " ) ;
sendToMesh ( p ) ;
2020-03-19 02:15:51 +00:00
} else {
2020-02-12 22:07:06 +00:00
// We don't need to send this packet to anyone else, but it still serves as a nice uniform way to update our local state
nodeDB . updateFrom ( * p ) ;
releaseToPool ( p ) ;
}
2020-04-10 19:40:44 +00:00
return 0 ;
2020-02-02 20:45:32 +00:00
}