GPS refactored (#262)
- Refactored GPS service and HAL: GPS is no longer part of the HAL configuration. You can now add configure new GPS devices from the GPS settings app. - T-Deck adds a boot hook to check if a GPS configuration exists and adds it when the config is empty. - Implemented the concept of ObjectFile to read/write arrays of a raw data type (e.g. struct) to disk. - Implemented more file utils (e.g. to create all directories of a path)
This commit is contained in:
committed by
GitHub
parent
81ece6f2e7
commit
d0ca3b16f8
@@ -53,9 +53,6 @@ struct Configuration {
|
||||
|
||||
/** A list of UART interface configurations */
|
||||
const std::vector<uart::Configuration> uart = {};
|
||||
|
||||
/** A list of GPS device configurations */
|
||||
const std::vector<gps::GpsDevice::Configuration> gps = {};
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace tt::hal::gps {
|
||||
|
||||
enum class GpsModel {
|
||||
Unknown = 0,
|
||||
AG3335,
|
||||
AG3352,
|
||||
ATGM336H, // Casic (might work with AT6558, Neoway N58 LTE Cat.1, Neoway G2, Neoway G7A)
|
||||
LS20031,
|
||||
MTK,
|
||||
MTK_L76B,
|
||||
MTK_PA1616S,
|
||||
UBLOX6,
|
||||
UBLOX7,
|
||||
UBLOX8,
|
||||
UBLOX9,
|
||||
UBLOX10,
|
||||
UC6580,
|
||||
};
|
||||
|
||||
const char* toString(GpsModel model);
|
||||
|
||||
std::vector<std::string> getModels();
|
||||
|
||||
struct GpsConfiguration {
|
||||
char uartName[32]; // e.g. "Internal" or "/dev/ttyUSB0"
|
||||
uint32_t baudRate;
|
||||
GpsModel model; // Choosing "Unknown" will result in a probe
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Device.h"
|
||||
#include "GpsConfiguration.h"
|
||||
#include "Satellites.h"
|
||||
|
||||
#include <Tactility/Mutex.h>
|
||||
@@ -18,25 +19,6 @@ enum class GpsResponse {
|
||||
Ok,
|
||||
};
|
||||
|
||||
enum class GpsModel {
|
||||
Unknown = 0,
|
||||
AG3335,
|
||||
AG3352,
|
||||
ATGM336H, // Casic (might work with AT6558, Neoway N58 LTE Cat.1, Neoway G2, Neoway G7A)
|
||||
LS20031,
|
||||
MTK,
|
||||
MTK_L76B,
|
||||
MTK_PA1616S,
|
||||
UBLOX6,
|
||||
UBLOX7,
|
||||
UBLOX8,
|
||||
UBLOX9,
|
||||
UBLOX10,
|
||||
UC6580,
|
||||
};
|
||||
|
||||
const char* toString(GpsModel model);
|
||||
|
||||
class GpsDevice : public Device {
|
||||
|
||||
public:
|
||||
@@ -44,13 +26,6 @@ public:
|
||||
typedef int GgaSubscriptionId;
|
||||
typedef int RmcSubscriptionId;
|
||||
|
||||
struct Configuration {
|
||||
std::string name;
|
||||
std::string uartName; // e.g. "Internal" or "/dev/ttyUSB0"
|
||||
uint32_t baudRate;
|
||||
GpsModel model;
|
||||
};
|
||||
|
||||
enum class State {
|
||||
PendingOn,
|
||||
On,
|
||||
@@ -71,7 +46,7 @@ private:
|
||||
std::shared_ptr<std::function<void(Device::Id id, const minmea_sentence_rmc&)>> onData;
|
||||
};
|
||||
|
||||
const Configuration configuration;
|
||||
const GpsConfiguration configuration;
|
||||
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
||||
std::unique_ptr<Thread> _Nullable thread;
|
||||
bool threadInterrupted = false;
|
||||
@@ -91,13 +66,20 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
explicit GpsDevice(Configuration configuration) : configuration(std::move(configuration)) {}
|
||||
explicit GpsDevice(GpsConfiguration configuration) : configuration(std::move(configuration)) {}
|
||||
|
||||
~GpsDevice() override = default;
|
||||
|
||||
Type getType() const override { return Type::Gps; }
|
||||
|
||||
std::string getName() const override { return configuration.name; }
|
||||
std::string getName() const override {
|
||||
if (model != GpsModel::Unknown) {
|
||||
return toString(model);
|
||||
} else {
|
||||
return "Unknown GPS";
|
||||
}
|
||||
}
|
||||
|
||||
std::string getDescription() const override { return ""; }
|
||||
|
||||
bool start();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
namespace tt::kernel {
|
||||
|
||||
@@ -26,10 +27,12 @@ enum class SystemEvent {
|
||||
/** Value 0 mean "no subscription" */
|
||||
typedef uint32_t SystemEventSubscription;
|
||||
|
||||
typedef void (*OnSystemEvent)(SystemEvent event);
|
||||
typedef std::function<void(SystemEvent)> OnSystemEvent;
|
||||
|
||||
void systemEventPublish(SystemEvent event);
|
||||
|
||||
SystemEventSubscription systemEventAddListener(SystemEvent event, OnSystemEvent handler);
|
||||
|
||||
void systemEventRemoveListener(SystemEventSubscription subscription);
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Tactility/hal/gps/GpsDevice.h"
|
||||
#include "GpsState.h"
|
||||
|
||||
#include <Tactility/PubSub.h>
|
||||
|
||||
namespace tt::service::gps {
|
||||
|
||||
/** Register a hardware device to the GPS service. */
|
||||
void addGpsDevice(const std::shared_ptr<hal::gps::GpsDevice>& device);
|
||||
|
||||
/** Deregister a hardware device to the GPS service. */
|
||||
void removeGpsDevice(const std::shared_ptr<hal::gps::GpsDevice>& device);
|
||||
|
||||
/** @return true when GPS is set to receive updates from at least 1 device */
|
||||
bool startReceiving();
|
||||
|
||||
/** Turn GPS receiving off */
|
||||
void stopReceiving();
|
||||
|
||||
bool hasCoordinates();
|
||||
|
||||
bool getCoordinates(minmea_sentence_rmc& rmc);
|
||||
|
||||
State getState();
|
||||
|
||||
/** @return GPS service pubsub that broadcasts State* objects */
|
||||
std::shared_ptr<PubSub> getStatePubsub();
|
||||
|
||||
}
|
||||
+13
-3
@@ -4,6 +4,7 @@
|
||||
#include "Tactility/PubSub.h"
|
||||
#include "Tactility/hal/gps/GpsDevice.h"
|
||||
#include "Tactility/service/Service.h"
|
||||
#include "Tactility/service/ServiceContext.h"
|
||||
#include "Tactility/service/gps/GpsState.h"
|
||||
|
||||
namespace tt::service::gps {
|
||||
@@ -25,6 +26,7 @@ private:
|
||||
Mutex stateMutex;
|
||||
std::vector<GpsDeviceRecord> deviceRecords;
|
||||
std::shared_ptr<PubSub> statePubSub = std::make_shared<PubSub>();
|
||||
std::unique_ptr<Paths> paths;
|
||||
State state = State::Off;
|
||||
|
||||
bool startGpsDevice(GpsDeviceRecord& deviceRecord);
|
||||
@@ -37,13 +39,19 @@ private:
|
||||
|
||||
void setState(State newState);
|
||||
|
||||
void addGpsDevice(const std::shared_ptr<hal::gps::GpsDevice>& device);
|
||||
void removeGpsDevice(const std::shared_ptr<hal::gps::GpsDevice>& device);
|
||||
|
||||
bool getConfigurationFilePath(std::string& output) const;
|
||||
|
||||
public:
|
||||
|
||||
void onStart(tt::service::ServiceContext &serviceContext) final;
|
||||
void onStop(tt::service::ServiceContext &serviceContext) final;
|
||||
|
||||
void addGpsDevice(const std::shared_ptr<hal::gps::GpsDevice>& device);
|
||||
void removeGpsDevice(const std::shared_ptr<hal::gps::GpsDevice>& device);
|
||||
bool addGpsConfiguration(hal::gps::GpsConfiguration configuration);
|
||||
bool removeGpsConfiguration(hal::gps::GpsConfiguration configuration);
|
||||
bool getGpsConfigurations(std::vector<hal::gps::GpsConfiguration>& configurations) const;
|
||||
|
||||
bool startReceiving();
|
||||
void stopReceiving();
|
||||
@@ -56,4 +64,6 @@ public:
|
||||
std::shared_ptr<PubSub> getStatePubsub() const { return statePubSub; }
|
||||
};
|
||||
|
||||
} // tt::hal::gps
|
||||
std::shared_ptr<GpsService> findGpsService();
|
||||
|
||||
} // tt::service::gps
|
||||
@@ -6,13 +6,6 @@ namespace tt::hal::uart { class Uart; }
|
||||
|
||||
namespace tt::hal::gps {
|
||||
|
||||
/**
|
||||
* Called by main HAL init to ready the internal state of the GPS HAL.
|
||||
* @param[in] configurations HAL configuration for a board
|
||||
* @return true on success
|
||||
*/
|
||||
bool init(const std::vector<GpsDevice::Configuration>& configurations);
|
||||
|
||||
/**
|
||||
* Init sequence on UART for a specific GPS model.
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,8 @@ constexpr uint8_t _message_PMREQ[] = {
|
||||
0x02, 0x00, 0x00, 0x00 // Bitfield, set backup = 1
|
||||
};
|
||||
|
||||
// Used for sleep mode
|
||||
// See https://github.com/meshtastic/firmware/blob/af8b64e84ee60175d7a0e43c6c3458e3a3558708/src/gps/GPS.cpp#L939
|
||||
constexpr uint8_t _message_PMREQ_10[] = {
|
||||
0x00, // version (0 for this version)
|
||||
0x00, 0x00, 0x00, // Reserved 1
|
||||
|
||||
@@ -29,8 +29,6 @@ void init(const Configuration& configuration) {
|
||||
tt_check(uart::init(configuration.uart), "UART init failed");
|
||||
kernel::systemEventPublish(kernel::SystemEvent::BootInitUartEnd);
|
||||
|
||||
tt_check(gps::init(configuration.gps), "GPS init failed");
|
||||
|
||||
if (configuration.initBoot != nullptr) {
|
||||
TT_LOG_I(TAG, "Init power");
|
||||
tt_check(configuration.initBoot(), "Init power failed");
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "Tactility/hal/gps/GpsConfiguration.h"
|
||||
#include "Tactility/service/gps/GpsService.h"
|
||||
|
||||
#include <Tactility/TactilityCore.h>
|
||||
#include <Tactility/file/ObjectFile.h>
|
||||
|
||||
namespace tt::hal::gps {
|
||||
|
||||
const char* toString(GpsModel model) {
|
||||
using enum GpsModel;
|
||||
switch (model) {
|
||||
case AG3335:
|
||||
return TT_STRINGIFY(AG3335);
|
||||
case AG3352:
|
||||
return TT_STRINGIFY(AG3352);
|
||||
case ATGM336H:
|
||||
return TT_STRINGIFY(ATGM336H);
|
||||
case LS20031:
|
||||
return TT_STRINGIFY(LS20031);
|
||||
case MTK:
|
||||
return TT_STRINGIFY(MTK);
|
||||
case MTK_L76B:
|
||||
return TT_STRINGIFY(MTK_L76B);
|
||||
case MTK_PA1616S:
|
||||
return TT_STRINGIFY(MTK_PA1616S);
|
||||
case UBLOX6:
|
||||
return TT_STRINGIFY(UBLOX6);
|
||||
case UBLOX7:
|
||||
return TT_STRINGIFY(UBLOX7);
|
||||
case UBLOX8:
|
||||
return TT_STRINGIFY(UBLOX8);
|
||||
case UBLOX9:
|
||||
return TT_STRINGIFY(UBLOX9);
|
||||
case UBLOX10:
|
||||
return TT_STRINGIFY(UBLOX10);
|
||||
case UC6580:
|
||||
return TT_STRINGIFY(UC6580);
|
||||
default:
|
||||
return TT_STRINGIFY(Unknown);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> getModels() {
|
||||
std::vector<std::string> result;
|
||||
for (GpsModel model = GpsModel::Unknown; model <= GpsModel::UC6580; ++(int&)model) {
|
||||
result.push_back(toString(model));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,44 +5,10 @@
|
||||
#include <cstring>
|
||||
#include <minmea.h>
|
||||
|
||||
#define TAG "gps"
|
||||
#define GPS_UART_BUFFER_SIZE 256
|
||||
|
||||
namespace tt::hal::gps {
|
||||
|
||||
const char* toString(GpsModel model) {
|
||||
using enum GpsModel;
|
||||
switch (model) {
|
||||
case AG3335:
|
||||
return TT_STRINGIFY(AG3335);
|
||||
case AG3352:
|
||||
return TT_STRINGIFY(AG3352);
|
||||
case ATGM336H:
|
||||
return TT_STRINGIFY(ATGM336H);
|
||||
case LS20031:
|
||||
return TT_STRINGIFY(LS20031);
|
||||
case MTK:
|
||||
return TT_STRINGIFY(MTK);
|
||||
case MTK_L76B:
|
||||
return TT_STRINGIFY(MTK_L76B);
|
||||
case MTK_PA1616S:
|
||||
return TT_STRINGIFY(MTK_PA1616S);
|
||||
case UBLOX6:
|
||||
return TT_STRINGIFY(UBLOX6);
|
||||
case UBLOX7:
|
||||
return TT_STRINGIFY(UBLOX7);
|
||||
case UBLOX8:
|
||||
return TT_STRINGIFY(UBLOX8);
|
||||
case UBLOX9:
|
||||
return TT_STRINGIFY(UBLOX9);
|
||||
case UBLOX10:
|
||||
return TT_STRINGIFY(UBLOX10);
|
||||
case UC6580:
|
||||
return TT_STRINGIFY(UC6580);
|
||||
default:
|
||||
return TT_STRINGIFY(Unknown);
|
||||
}
|
||||
}
|
||||
constexpr uint32_t GPS_UART_BUFFER_SIZE = 256;
|
||||
constexpr const char* TAG = "GpsDevice";
|
||||
|
||||
int32_t GpsDevice::threadMainStatic(void* parameter) {
|
||||
auto* gps_device = (GpsDevice*)parameter;
|
||||
@@ -54,17 +20,17 @@ int32_t GpsDevice::threadMain() {
|
||||
|
||||
auto uart = uart::open(configuration.uartName);
|
||||
if (uart == nullptr) {
|
||||
TT_LOG_E(TAG, "Failed to open UART %s", configuration.uartName.c_str());
|
||||
TT_LOG_E(TAG, "Failed to open UART %s", configuration.uartName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!uart->start()) {
|
||||
TT_LOG_E(TAG, "Failed to start UART %s", configuration.uartName.c_str());
|
||||
TT_LOG_E(TAG, "Failed to start UART %s", configuration.uartName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!uart->setBaudRate((int)configuration.baudRate)) {
|
||||
TT_LOG_E(TAG, "Failed to set baud rate to %lu for UART %s", configuration.baudRate, configuration.uartName.c_str());
|
||||
TT_LOG_E(TAG, "Failed to set baud rate to %lu for UART %s", configuration.baudRate, configuration.uartName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -77,7 +43,6 @@ int32_t GpsDevice::threadMain() {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
mutex.lock();
|
||||
this->model = model;
|
||||
mutex.unlock();
|
||||
@@ -101,7 +66,7 @@ int32_t GpsDevice::threadMain() {
|
||||
|
||||
if (bytes_read > 0U) {
|
||||
|
||||
TT_LOG_D(TAG, "%s", buffer);
|
||||
TT_LOG_I(TAG, "[%ul] %s", bytes_read, buffer);
|
||||
|
||||
switch (minmea_sentence_id((char*)buffer, false)) {
|
||||
case MINMEA_SENTENCE_RMC:
|
||||
@@ -137,7 +102,7 @@ int32_t GpsDevice::threadMain() {
|
||||
}
|
||||
|
||||
if (uart->isStarted() && !uart->stop()) {
|
||||
TT_LOG_W(TAG, "Failed to stop UART %s", configuration.uartName.c_str());
|
||||
TT_LOG_W(TAG, "Failed to stop UART %s", configuration.uartName);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "Tactility/hal/gps/Cas.h"
|
||||
#include "Tactility/hal/gps/GpsDevice.h"
|
||||
#include "Tactility/hal/gps/Ublox.h"
|
||||
#include "Tactility/service/Service.h"
|
||||
#include <cstring>
|
||||
|
||||
#define TAG "gps"
|
||||
@@ -133,17 +132,6 @@ GpsResponse getACKCas(uart::Uart& uart, uint8_t class_id, uint8_t msg_id, uint32
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
/** Initialize the HAL with the provided configuration */
|
||||
bool init(const std::vector<GpsDevice::Configuration>& configurations) {
|
||||
for (auto& configuration : configurations) {
|
||||
auto device = std::make_shared<GpsDevice>(configuration);
|
||||
hal::registerDevice(std::move(device));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool init(uart::Uart& uart, GpsModel type) {
|
||||
switch (type) {
|
||||
case GpsModel::Unknown:
|
||||
|
||||
@@ -69,7 +69,7 @@ void systemEventPublish(SystemEvent event) {
|
||||
}
|
||||
}
|
||||
|
||||
SystemEventSubscription systemEventAddListener(SystemEvent event, OnSystemEvent handler) {
|
||||
SystemEventSubscription systemEventAddListener(SystemEvent event, std::function<void(SystemEvent)> handler) {
|
||||
if (mutex.lock(portMAX_DELAY)) {
|
||||
auto id = ++subscriptionCounter;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Tactility/Partitions.h"
|
||||
|
||||
#define LVGL_PATH_PREFIX std::string("A:/")
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#define PARTITION_PREFIX std::string("/")
|
||||
#else
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
#include "Tactility/PubSub.h"
|
||||
#include "Tactility/service/ServiceManifest.h"
|
||||
#include "Tactility/service/ServiceRegistry.h"
|
||||
#include "Tactility/service/gps/GpsService.h"
|
||||
|
||||
using tt::hal::gps::GpsDevice;
|
||||
|
||||
namespace tt::service::gps {
|
||||
|
||||
extern ServiceManifest manifest;
|
||||
|
||||
static std::shared_ptr<GpsService> findGpsService() {
|
||||
auto service = findServiceById(manifest.id);
|
||||
assert(service != nullptr);
|
||||
return std::static_pointer_cast<GpsService>(service);
|
||||
}
|
||||
|
||||
void addGpsDevice(const std::shared_ptr<GpsDevice>& device) {
|
||||
return findGpsService()->addGpsDevice(device);
|
||||
}
|
||||
|
||||
void removeGpsDevice(const std::shared_ptr<GpsDevice>& device) {
|
||||
return findGpsService()->removeGpsDevice(device);
|
||||
}
|
||||
|
||||
bool startReceiving() {
|
||||
return findGpsService()->startReceiving();
|
||||
}
|
||||
|
||||
void stopReceiving() {
|
||||
findGpsService()->stopReceiving();
|
||||
}
|
||||
|
||||
bool hasCoordinates() {
|
||||
return findGpsService()->hasCoordinates();
|
||||
}
|
||||
|
||||
bool getCoordinates(minmea_sentence_rmc& rmc) {
|
||||
return findGpsService()->getCoordinates(rmc);
|
||||
}
|
||||
|
||||
State getState() {
|
||||
return findGpsService()->getState();
|
||||
}
|
||||
|
||||
std::shared_ptr<PubSub> getStatePubsub() {
|
||||
return findGpsService()->getStatePubsub();
|
||||
}
|
||||
|
||||
} // namespace tt::service::gps
|
||||
@@ -0,0 +1,108 @@
|
||||
#include "Tactility/service/gps/GpsService.h"
|
||||
|
||||
#include <Tactility/file/ObjectFile.h>
|
||||
#include <cstring>
|
||||
|
||||
using tt::hal::gps::GpsDevice;
|
||||
|
||||
namespace tt::service::gps {
|
||||
|
||||
constexpr const char* TAG = "GpsService";
|
||||
|
||||
bool GpsService::getConfigurationFilePath(std::string& output) const {
|
||||
if (paths == nullptr) {
|
||||
TT_LOG_E(TAG, "Can't add configuration: service not started");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file::findOrCreateDirectory(paths->getDataDirectory(), 0777)) {
|
||||
TT_LOG_E(TAG, "Failed to find or create path %s", paths->getDataDirectory().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
output = paths->getDataPath("config.bin");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GpsService::getGpsConfigurations(std::vector<hal::gps::GpsConfiguration>& configurations) const {
|
||||
std::string path;
|
||||
if (!getConfigurationFilePath(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto reader = file::ObjectFileReader(path, sizeof(hal::gps::GpsConfiguration));
|
||||
if (!reader.open()) {
|
||||
TT_LOG_E(TAG, "Failed to open configuration file");
|
||||
return false;
|
||||
}
|
||||
|
||||
hal::gps::GpsConfiguration configuration;
|
||||
while (reader.hasNext()) {
|
||||
if (!reader.readNext(&configuration)) {
|
||||
TT_LOG_E(TAG, "Failed to read configuration");
|
||||
reader.close();
|
||||
return false;
|
||||
} else {
|
||||
configurations.push_back(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GpsService::addGpsConfiguration(hal::gps::GpsConfiguration configuration) {
|
||||
std::string path;
|
||||
if (!getConfigurationFilePath(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto appender = file::ObjectFileWriter(path, sizeof(hal::gps::GpsConfiguration), 1, true);
|
||||
if (!appender.open()) {
|
||||
TT_LOG_E(TAG, "Failed to open/create configuration file");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!appender.write(&configuration)) {
|
||||
TT_LOG_E(TAG, "Failed to add configuration");
|
||||
appender.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
appender.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GpsService::removeGpsConfiguration(hal::gps::GpsConfiguration configuration) {
|
||||
std::string path;
|
||||
if (!getConfigurationFilePath(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<hal::gps::GpsConfiguration> configurations;
|
||||
if (!getGpsConfigurations(configurations)) {
|
||||
TT_LOG_E(TAG, "Failed to get gps configurations");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto count = std::erase_if(configurations, [&configuration](auto& item) {
|
||||
return strcmp(item.uartName, configuration.uartName) == 0 &&
|
||||
item.baudRate == configuration.baudRate &&
|
||||
item.model == configuration.model;
|
||||
});
|
||||
|
||||
auto writer = file::ObjectFileWriter(path, sizeof(hal::gps::GpsConfiguration), 1, false);
|
||||
if (!writer.open()) {
|
||||
TT_LOG_E(TAG, "Failed to open configuration file");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& configuration : configurations) {
|
||||
writer.write(&configuration);
|
||||
}
|
||||
|
||||
writer.close();
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
} // namespace tt::service::gps
|
||||
@@ -1,12 +1,17 @@
|
||||
#include "Tactility/service/gps/GpsService.h"
|
||||
#include "Tactility/service/ServiceManifest.h"
|
||||
#include "Tactility/service/ServiceRegistry.h"
|
||||
|
||||
#define TAG "gps_service"
|
||||
#include <Tactility/Log.h>
|
||||
#include <Tactility/file/File.h>
|
||||
|
||||
using tt::hal::gps::GpsDevice;
|
||||
|
||||
namespace tt::service::gps {
|
||||
|
||||
constexpr const char* TAG = "GpsService";
|
||||
extern const ServiceManifest manifest;
|
||||
|
||||
constexpr inline bool hasTimeElapsed(TickType_t now, TickType_t timeInThePast, TickType_t expireTimeInTicks) {
|
||||
return (TickType_t)(now - timeInThePast) >= expireTimeInTicks;
|
||||
}
|
||||
@@ -15,7 +20,7 @@ GpsService::GpsDeviceRecord* _Nullable GpsService::findGpsRecord(const std::shar
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
auto result = std::views::filter(deviceRecords, [&device](auto& record){
|
||||
auto result = std::views::filter(deviceRecords, [&device](auto& record) {
|
||||
return record.device.get() == device.get();
|
||||
});
|
||||
if (!result.empty()) {
|
||||
@@ -29,7 +34,7 @@ void GpsService::addGpsDevice(const std::shared_ptr<GpsDevice>& device) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
GpsDeviceRecord record = { .device = device };
|
||||
GpsDeviceRecord record = {.device = device};
|
||||
|
||||
if (getState() == State::On) { // Ignore during OnPending due to risk of data corruptiohn
|
||||
startGpsDevice(record);
|
||||
@@ -48,25 +53,19 @@ void GpsService::removeGpsDevice(const std::shared_ptr<GpsDevice>& device) {
|
||||
stopGpsDevice(*record);
|
||||
}
|
||||
|
||||
std::erase_if(deviceRecords, [&device](auto& reference){
|
||||
std::erase_if(deviceRecords, [&device](auto& reference) {
|
||||
return reference.device.get() == device.get();
|
||||
});
|
||||
}
|
||||
|
||||
void GpsService::onStart(tt::service::ServiceContext &serviceContext) {
|
||||
void GpsService::onStart(tt::service::ServiceContext& serviceContext) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
deviceRecords.clear();
|
||||
|
||||
auto devices = hal::findDevices<GpsDevice>(hal::Device::Type::Gps);
|
||||
for (auto& device : devices) {
|
||||
TT_LOG_I(TAG, "[device %lu] added", device->getId());
|
||||
addGpsDevice(device);
|
||||
}
|
||||
paths = serviceContext.getPaths();
|
||||
}
|
||||
|
||||
void GpsService::onStop(tt::service::ServiceContext &serviceContext) {
|
||||
void GpsService::onStop(tt::service::ServiceContext& serviceContext) {
|
||||
if (getState() == State::On) {
|
||||
stopReceiving();
|
||||
}
|
||||
@@ -126,14 +125,39 @@ bool GpsService::stopGpsDevice(GpsDeviceRecord& record) {
|
||||
bool GpsService::startReceiving() {
|
||||
TT_LOG_I(TAG, "Start receiving");
|
||||
|
||||
if (getState() != State::Off) {
|
||||
TT_LOG_E(TAG, "Already receiving");
|
||||
return false;
|
||||
}
|
||||
|
||||
setState(State::OnPending);
|
||||
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
deviceRecords.clear();
|
||||
|
||||
std::vector<hal::gps::GpsConfiguration> configurations;
|
||||
if (!getGpsConfigurations(configurations)) {
|
||||
TT_LOG_E(TAG, "Failed to get GPS configurations");
|
||||
setState(State::Off);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (configurations.empty()) {
|
||||
TT_LOG_E(TAG, "No GPS configurations");
|
||||
setState(State::Off);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& configuration: configurations) {
|
||||
auto device = std::make_shared<GpsDevice>(configuration);
|
||||
addGpsDevice(device);
|
||||
}
|
||||
|
||||
bool started_one_or_more = false;
|
||||
|
||||
for (auto& record : deviceRecords) {
|
||||
for (auto& record: deviceRecords) {
|
||||
started_one_or_more |= startGpsDevice(record);
|
||||
}
|
||||
|
||||
@@ -156,7 +180,7 @@ void GpsService::stopReceiving() {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
for (auto& record : deviceRecords) {
|
||||
for (auto& record: deviceRecords) {
|
||||
stopGpsDevice(record);
|
||||
}
|
||||
|
||||
@@ -202,9 +226,15 @@ bool GpsService::getCoordinates(minmea_sentence_rmc& rmc) const {
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<GpsService> findGpsService() {
|
||||
auto service = findServiceById(manifest.id);
|
||||
assert(service != nullptr);
|
||||
return std::static_pointer_cast<GpsService>(service);
|
||||
}
|
||||
|
||||
extern const ServiceManifest manifest = {
|
||||
.id = "Gps",
|
||||
.createService = create<GpsService>
|
||||
};
|
||||
|
||||
} // tt::hal::gps
|
||||
} // namespace tt::service::gps
|
||||
|
||||
Reference in New Issue
Block a user