mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-29 11:01:15 +00:00
Add TAK Tracker role behavior (#3233)
* Proto * Standalone TAK Tracker * Add log * Make TAK_Tracker behave like Tracker
This commit is contained in:
parent
1bacd8641d
commit
998013aff3
@ -246,6 +246,7 @@ void PowerFSM_setup()
|
|||||||
{
|
{
|
||||||
bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
|
bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
|
||||||
bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
|
bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
|
||||||
|
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER ||
|
||||||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR;
|
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR;
|
||||||
bool hasPower = isPowered();
|
bool hasPower = isPowered();
|
||||||
|
|
||||||
|
@ -325,6 +325,17 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role)
|
|||||||
(meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_SPEED |
|
(meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_SPEED |
|
||||||
meshtastic_Config_PositionConfig_PositionFlags_HEADING | meshtastic_Config_PositionConfig_PositionFlags_DOP);
|
meshtastic_Config_PositionConfig_PositionFlags_HEADING | meshtastic_Config_PositionConfig_PositionFlags_DOP);
|
||||||
moduleConfig.telemetry.device_update_interval = ONE_DAY;
|
moduleConfig.telemetry.device_update_interval = ONE_DAY;
|
||||||
|
} else if (role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) {
|
||||||
|
config.device.node_info_broadcast_secs = ONE_DAY;
|
||||||
|
config.position.position_broadcast_smart_enabled = true;
|
||||||
|
config.position.position_broadcast_secs = 3 * 60; // Every 3 minutes
|
||||||
|
config.position.broadcast_smart_minimum_distance = 20;
|
||||||
|
config.position.broadcast_smart_minimum_interval_secs = 15;
|
||||||
|
// Remove Altitude MSL from flags since CoTs use HAE (height above ellipsoid)
|
||||||
|
config.position.position_flags =
|
||||||
|
(meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_SPEED |
|
||||||
|
meshtastic_Config_PositionConfig_PositionFlags_HEADING | meshtastic_Config_PositionConfig_PositionFlags_DOP);
|
||||||
|
moduleConfig.telemetry.device_update_interval = ONE_DAY;
|
||||||
} else if (role == meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) {
|
} else if (role == meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) {
|
||||||
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY;
|
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY;
|
||||||
config.device.node_info_broadcast_secs = UINT32_MAX;
|
config.device.node_info_broadcast_secs = UINT32_MAX;
|
||||||
|
@ -8,9 +8,15 @@
|
|||||||
#include "airtime.h"
|
#include "airtime.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "gps/GeoCoord.h"
|
#include "gps/GeoCoord.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "meshtastic/atak.pb.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "mesh/compression/unishox2.h"
|
||||||
|
}
|
||||||
|
|
||||||
PositionModule *positionModule;
|
PositionModule *positionModule;
|
||||||
|
|
||||||
PositionModule::PositionModule()
|
PositionModule::PositionModule()
|
||||||
@ -18,11 +24,14 @@ PositionModule::PositionModule()
|
|||||||
concurrency::OSThread("PositionModule")
|
concurrency::OSThread("PositionModule")
|
||||||
{
|
{
|
||||||
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
|
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
|
||||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)
|
if (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER &&
|
||||||
|
config.device.role != meshtastic_Config_DeviceConfig_Role_TAK_TRACKER)
|
||||||
setIntervalFromNow(60 * 1000);
|
setIntervalFromNow(60 * 1000);
|
||||||
|
|
||||||
// Power saving trackers should clear their position on startup to avoid waking up and sending a stale position
|
// Power saving trackers should clear their position on startup to avoid waking up and sending a stale position
|
||||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER && config.power.is_power_saving) {
|
if ((config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
|
||||||
|
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) &&
|
||||||
|
config.power.is_power_saving) {
|
||||||
clearPosition();
|
clearPosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,9 +166,47 @@ meshtastic_MeshPacket *PositionModule::allocReply()
|
|||||||
|
|
||||||
LOG_INFO("Position reply: time=%i, latI=%i, lonI=-%i\n", p.time, p.latitude_i, p.longitude_i);
|
LOG_INFO("Position reply: time=%i, latI=%i, lonI=-%i\n", p.time, p.latitude_i, p.longitude_i);
|
||||||
|
|
||||||
|
// TAK Tracker devices should send their position in a TAK packet over the ATAK port
|
||||||
|
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER)
|
||||||
|
return allocAtakPli();
|
||||||
|
|
||||||
return allocDataProtobuf(p);
|
return allocDataProtobuf(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meshtastic_MeshPacket *PositionModule::allocAtakPli()
|
||||||
|
{
|
||||||
|
LOG_INFO("Sending TAK PLI packet\n");
|
||||||
|
meshtastic_MeshPacket *mp = allocDataPacket();
|
||||||
|
mp->decoded.portnum = meshtastic_PortNum_ATAK_PLUGIN;
|
||||||
|
|
||||||
|
meshtastic_TAKPacket takPacket = {.is_compressed = true,
|
||||||
|
.has_contact = true,
|
||||||
|
.contact = {0},
|
||||||
|
.has_group = true,
|
||||||
|
.group = {meshtastic_MemberRole_TeamMember, meshtastic_Team_Cyan},
|
||||||
|
.has_status = true,
|
||||||
|
.status =
|
||||||
|
{
|
||||||
|
.battery = powerStatus->getBatteryChargePercent(),
|
||||||
|
},
|
||||||
|
.which_payload_variant = meshtastic_TAKPacket_pli_tag,
|
||||||
|
{.pli = {
|
||||||
|
.latitude_i = localPosition.latitude_i,
|
||||||
|
.longitude_i = localPosition.longitude_i,
|
||||||
|
.altitude = localPosition.altitude_hae > 0 ? localPosition.altitude_hae : 0,
|
||||||
|
.speed = localPosition.ground_speed,
|
||||||
|
.course = static_cast<uint16_t>(localPosition.ground_track),
|
||||||
|
}}};
|
||||||
|
|
||||||
|
auto length = unishox2_compress_simple(owner.long_name, strlen(owner.long_name), takPacket.contact.device_callsign);
|
||||||
|
LOG_DEBUG("Uncompressed device_callsign '%s' - %d bytes\n", owner.long_name, strlen(owner.long_name));
|
||||||
|
LOG_DEBUG("Compressed device_callsign '%s' - %d bytes\n", takPacket.contact.device_callsign, length);
|
||||||
|
length = unishox2_compress_simple(owner.long_name, strlen(owner.long_name), takPacket.contact.callsign);
|
||||||
|
mp->decoded.payload.size =
|
||||||
|
pb_encode_to_bytes(mp->decoded.payload.bytes, sizeof(mp->decoded.payload.bytes), &meshtastic_TAKPacket_msg, &takPacket);
|
||||||
|
return mp;
|
||||||
|
}
|
||||||
|
|
||||||
void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t channel)
|
void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t channel)
|
||||||
{
|
{
|
||||||
// cancel any not yet sent (now stale) position packets
|
// cancel any not yet sent (now stale) position packets
|
||||||
@ -174,7 +221,8 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
|
|||||||
|
|
||||||
p->to = dest;
|
p->to = dest;
|
||||||
p->decoded.want_response = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ? false : wantReplies;
|
p->decoded.want_response = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ? false : wantReplies;
|
||||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER)
|
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
|
||||||
|
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER)
|
||||||
p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
|
p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
|
||||||
else
|
else
|
||||||
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
|
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
|
||||||
@ -185,7 +233,9 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
|
|||||||
|
|
||||||
service.sendToMesh(p, RX_SRC_LOCAL, true);
|
service.sendToMesh(p, RX_SRC_LOCAL, true);
|
||||||
|
|
||||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER && config.power.is_power_saving) {
|
if ((config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
|
||||||
|
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) &&
|
||||||
|
config.power.is_power_saving) {
|
||||||
LOG_DEBUG("Starting next execution in 5 seconds and then going to sleep.\n");
|
LOG_DEBUG("Starting next execution in 5 seconds and then going to sleep.\n");
|
||||||
sleepOnNextExecution = true;
|
sleepOnNextExecution = true;
|
||||||
setIntervalFromNow(5000);
|
setIntervalFromNow(5000);
|
||||||
@ -212,7 +262,8 @@ int32_t PositionModule::runOnce()
|
|||||||
uint32_t intervalMs = getConfiguredOrDefaultMs(config.position.position_broadcast_secs, default_broadcast_interval_secs);
|
uint32_t intervalMs = getConfiguredOrDefaultMs(config.position.position_broadcast_secs, default_broadcast_interval_secs);
|
||||||
uint32_t msSinceLastSend = now - lastGpsSend;
|
uint32_t msSinceLastSend = now - lastGpsSend;
|
||||||
// Only send packets if the channel util. is less than 25% utilized or we're a tracker with less than 40% utilized.
|
// Only send packets if the channel util. is less than 25% utilized or we're a tracker with less than 40% utilized.
|
||||||
if (!airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)) {
|
if (!airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER &&
|
||||||
|
config.device.role != meshtastic_Config_DeviceConfig_Role_TAK_TRACKER)) {
|
||||||
return RUNONCE_INTERVAL;
|
return RUNONCE_INTERVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
struct SmartPosition getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition);
|
struct SmartPosition getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition);
|
||||||
|
meshtastic_MeshPacket *allocAtakPli();
|
||||||
|
|
||||||
/** Only used in power saving trackers for now */
|
/** Only used in power saving trackers for now */
|
||||||
void clearPosition();
|
void clearPosition();
|
||||||
|
@ -185,6 +185,7 @@ void cpuDeepSleep(uint32_t msecToWake)
|
|||||||
// Don't enter this if we're sleeping portMAX_DELAY, since that's a shutdown event
|
// Don't enter this if we're sleeping portMAX_DELAY, since that's a shutdown event
|
||||||
if (msecToWake != portMAX_DELAY &&
|
if (msecToWake != portMAX_DELAY &&
|
||||||
(config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
|
(config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
|
||||||
|
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER ||
|
||||||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR) &&
|
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR) &&
|
||||||
config.power.is_power_saving == true) {
|
config.power.is_power_saving == true) {
|
||||||
sd_power_mode_set(NRF_POWER_MODE_LOWPWR);
|
sd_power_mode_set(NRF_POWER_MODE_LOWPWR);
|
||||||
|
Loading…
Reference in New Issue
Block a user