#pragma once #include "../Device.h" #include "GpsConfiguration.h" #include "Satellites.h" #include #include #include #include namespace tt::hal::gps { enum class GpsResponse { None, NotAck, FrameErrors, Ok, }; class GpsDevice : public Device { public: typedef int GgaSubscriptionId; typedef int RmcSubscriptionId; enum class State { PendingOn, On, Error, PendingOff, Off }; private: struct GgaSubscription { GgaSubscriptionId id; std::shared_ptr> onData; }; struct RmcSubscription { RmcSubscriptionId id; std::shared_ptr> onData; }; const GpsConfiguration configuration; Mutex mutex = Mutex(Mutex::Type::Recursive); std::unique_ptr _Nullable thread; bool threadInterrupted = false; std::vector ggaSubscriptions; std::vector rmcSubscriptions; GgaSubscriptionId lastSatelliteSubscriptionId = 0; RmcSubscriptionId lastRmcSubscriptionId = 0; GpsModel model = GpsModel::Unknown; State state = State::Off; static int32_t threadMainStatic(void* parameter); int32_t threadMain(); bool isThreadInterrupted() const; void setState(State newState); public: explicit GpsDevice(GpsConfiguration configuration) : configuration(std::move(configuration)) {} ~GpsDevice() override = default; Type getType() const override { return Type::Gps; } std::string getName() const override { if (model != GpsModel::Unknown) { return toString(model); } else { return "Unknown GPS"; } } std::string getDescription() const override { return ""; } bool start(); bool stop(); GgaSubscriptionId subscribeGga(const std::function& onData) { auto lock = mutex.asScopedLock(); lock.lock(); ggaSubscriptions.push_back({ .id = ++lastSatelliteSubscriptionId, .onData = std::make_shared>(onData) }); return lastSatelliteSubscriptionId; } void unsubscribeGga(GgaSubscriptionId subscriptionId) { auto lock = mutex.asScopedLock(); lock.lock(); std::erase_if(ggaSubscriptions, [subscriptionId](auto& subscription) { return subscription.id == subscriptionId; }); } RmcSubscriptionId subscribeRmc(const std::function& onData) { auto lock = mutex.asScopedLock(); lock.lock(); rmcSubscriptions.push_back({ .id = ++lastRmcSubscriptionId, .onData = std::make_shared>(onData) }); return lastRmcSubscriptionId; } void unsubscribeRmc(GgaSubscriptionId subscriptionId) { auto lock = mutex.asScopedLock(); lock.lock(); std::erase_if(rmcSubscriptions, [subscriptionId](auto& subscription) { return subscription.id == subscriptionId; }); } GpsModel getModel() const; State getState() const; }; }