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:
Ken Van Hoeylandt
2025-03-30 01:14:22 +01:00
committed by GitHub
parent 81ece6f2e7
commit d0ca3b16f8
47 changed files with 1266 additions and 277 deletions
@@ -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();
}
@@ -0,0 +1,69 @@
#pragma once
#include "Tactility/Mutex.h"
#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 {
class GpsService final : public Service {
private:
struct GpsDeviceRecord {
std::shared_ptr<hal::gps::GpsDevice> device = nullptr;
hal::gps::GpsDevice::GgaSubscriptionId satelliteSubscriptionId = -1;
hal::gps::GpsDevice::RmcSubscriptionId rmcSubscriptionId = -1;
};
minmea_sentence_rmc rmcRecord;
TickType_t rmcTime = 0;
Mutex mutex = Mutex(Mutex::Type::Recursive);
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);
static bool stopGpsDevice(GpsDeviceRecord& deviceRecord);
GpsDeviceRecord* _Nullable findGpsRecord(const std::shared_ptr<hal::gps::GpsDevice>& record);
void onGgaSentence(hal::Device::Id deviceId, const minmea_sentence_gga& gga);
void onRmcSentence(hal::Device::Id deviceId, const minmea_sentence_rmc& rmc);
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;
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();
State getState() const;
bool hasCoordinates() const;
bool getCoordinates(minmea_sentence_rmc& rmc) const;
/** @return GPS service pubsub that broadcasts State* objects */
std::shared_ptr<PubSub> getStatePubsub() const { return statePubSub; }
};
std::shared_ptr<GpsService> findGpsService();
} // tt::service::gps