Radio: Add state PubSub, generalize PubSub
This commit is contained in:
parent
f57868b3fd
commit
4625f56c6e
49
Tactility/Include/Tactility/hal/radio/PubSub.h
Normal file
49
Tactility/Include/Tactility/hal/radio/PubSub.h
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace tt::hal::radio {
|
||||
|
||||
// Proposed PubSub class, can be moved elsewhere
|
||||
template<class... Ts>
|
||||
class PubSub
|
||||
{
|
||||
public:
|
||||
typedef int SubscriptionId;
|
||||
using Notifier = std::function<void(Ts...)>;
|
||||
|
||||
protected:
|
||||
struct Subscription {
|
||||
SubscriptionId id;
|
||||
std::shared_ptr<Notifier> notifier;
|
||||
};
|
||||
|
||||
SubscriptionId lastSubscriptionId = 0;
|
||||
std::vector<Subscription> subscriptions;
|
||||
|
||||
public:
|
||||
|
||||
PubSub() {}
|
||||
virtual ~PubSub() = default;
|
||||
|
||||
SubscriptionId subscribe(Notifier onPublish) {
|
||||
subscriptions.push_back({
|
||||
.id = ++lastSubscriptionId,
|
||||
.notifier = std::make_shared<Notifier>(onPublish)
|
||||
});
|
||||
return lastSubscriptionId;
|
||||
}
|
||||
|
||||
void unsubscribe(SubscriptionId subscriptionId) {
|
||||
std::erase_if(subscriptions, [subscriptionId](auto& subscription) { return subscription.id == subscriptionId; });
|
||||
}
|
||||
|
||||
void publish(Ts... pargs) {
|
||||
for (auto& subscription : subscriptions) {
|
||||
(*subscription.notifier)(pargs...);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Device.h"
|
||||
#include "PubSub.h"
|
||||
#include "Unit.h"
|
||||
|
||||
#include <Tactility/Mutex.h>
|
||||
@ -52,10 +53,6 @@ public:
|
||||
Success
|
||||
};
|
||||
|
||||
typedef int RxSubscriptionId;
|
||||
typedef int TxId;
|
||||
|
||||
|
||||
enum class State {
|
||||
PendingOn,
|
||||
On,
|
||||
@ -72,6 +69,15 @@ public:
|
||||
Error
|
||||
};
|
||||
|
||||
typedef int TxId;
|
||||
|
||||
using StatePubSub = PubSub<Device::Id, State>;
|
||||
using RxPubSub = PubSub<Device::Id, const RxPacket&>;
|
||||
using StateSubscriptionId = StatePubSub::SubscriptionId;
|
||||
using RxSubscriptionId = RxPubSub::SubscriptionId;
|
||||
|
||||
using StateCallback = StatePubSub::Notifier;
|
||||
using RxCallback = RxPubSub::Notifier;
|
||||
using TxStateCallback = std::function<void(TxId id, TransmissionState state)>;
|
||||
|
||||
protected:
|
||||
@ -82,18 +88,13 @@ protected:
|
||||
};
|
||||
|
||||
private:
|
||||
struct RxSubscription {
|
||||
RxSubscriptionId id;
|
||||
std::shared_ptr<std::function<void(Device::Id id, const RxPacket&)>> onData;
|
||||
};
|
||||
|
||||
State state;
|
||||
Modulation modulation;
|
||||
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
||||
std::vector<RxSubscription> rxSubscriptions;
|
||||
StatePubSub statePubSub;
|
||||
RxPubSub rxPubSub;
|
||||
std::deque<TxItem> txQueue;
|
||||
TxId lastTxId = 0;
|
||||
RxSubscriptionId lastRxSubscriptionId = 0;
|
||||
|
||||
protected:
|
||||
const Mutex &getMutex() const { return mutex; }
|
||||
@ -150,20 +151,28 @@ public:
|
||||
return txId;
|
||||
}
|
||||
|
||||
RxSubscriptionId subscribeRx(const std::function<void(Device::Id id, const RxPacket&)>& onData) {
|
||||
StateSubscriptionId subscribeStateChange(StateCallback onChange) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
rxSubscriptions.push_back({
|
||||
.id = ++lastRxSubscriptionId,
|
||||
.onData = std::make_shared<std::function<void(Device::Id, const RxPacket&)>>(onData)
|
||||
});
|
||||
return lastRxSubscriptionId;
|
||||
return statePubSub.subscribe(onChange);
|
||||
}
|
||||
|
||||
void unsubscribeStateChange(StateSubscriptionId subscriptionId) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
return rxPubSub.unsubscribe(subscriptionId);
|
||||
}
|
||||
|
||||
RxSubscriptionId subscribeRx(const RxCallback& onData) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
return rxPubSub.subscribe(onData);
|
||||
}
|
||||
|
||||
void unsubscribeRx(RxSubscriptionId subscriptionId) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
std::erase_if(rxSubscriptions, [subscriptionId](auto& subscription) { return subscription.id == subscriptionId; });
|
||||
return rxPubSub.unsubscribe(subscriptionId);
|
||||
}
|
||||
|
||||
State getState() const;
|
||||
|
||||
@ -39,14 +39,17 @@ RadioDevice::State RadioDevice::getState() const {
|
||||
void RadioDevice::setState(State newState) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
if (state != newState) {
|
||||
statePubSub.publish(getId(), newState);
|
||||
}
|
||||
|
||||
state = newState;
|
||||
}
|
||||
|
||||
void RadioDevice::publishRx(const RxPacket& packet) {
|
||||
mutex.lock();
|
||||
for (auto& subscription : rxSubscriptions) {
|
||||
(*subscription.onData)(getId(), packet);
|
||||
}
|
||||
rxPubSub.publish(getId(), packet);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
@ -52,6 +52,7 @@ enum RadioTxState {
|
||||
};
|
||||
|
||||
typedef int32_t RadioRxSubscriptionId;
|
||||
typedef int32_t RadioStateSubscriptionId;
|
||||
typedef int32_t RadioTxId;
|
||||
|
||||
struct RadioRxPacket {
|
||||
@ -67,6 +68,7 @@ struct RadioTxPacket {
|
||||
uint32_t address;
|
||||
};
|
||||
|
||||
typedef void (*RadioStateCallback)(DeviceId id, RadioState state);
|
||||
typedef void (*RadioTxStateCallback)(RadioTxId id, RadioTxState state);
|
||||
typedef void (*RadioOnReceiveCallback)(DeviceId id, const RadioRxPacket* packet);
|
||||
|
||||
@ -203,6 +205,14 @@ RadioTxId tt_hal_radio_transmit(RadioHandle handle, RadioTxPacket packet, RadioT
|
||||
*/
|
||||
RadioRxSubscriptionId tt_hal_radio_subscribe_receive(RadioHandle handle, RadioOnReceiveCallback callback);
|
||||
|
||||
/**
|
||||
* Subscribe for any state change of the radio driver object.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @param[in] callback function to call when the state of the radio changes
|
||||
* @return the identifier for the subscription
|
||||
*/
|
||||
RadioStateSubscriptionId tt_hal_radio_subscribe_state(RadioHandle handle, RadioStateCallback callback);
|
||||
|
||||
/**
|
||||
* Unsubscribe for any received packet that the radio driver object receives.
|
||||
* @param[in] handle the radio driver handle
|
||||
|
||||
@ -129,6 +129,15 @@ extern "C" {
|
||||
});
|
||||
}
|
||||
|
||||
RadioStateSubscriptionId tt_hal_radio_subscribe_state(RadioHandle handle, RadioStateCallback callback) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return wrapper->device->subscribeStateChange([callback](tt::hal::Device::Id id, tt::hal::radio::RadioDevice::State state) {
|
||||
if (callback) {
|
||||
callback(id, fromCpp(state));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RadioRxSubscriptionId tt_hal_radio_subscribe_receive(RadioHandle handle, RadioOnReceiveCallback callback) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return wrapper->device->subscribeRx([callback](tt::hal::Device::Id id, const tt::hal::radio::RxPacket& ttPacket) {
|
||||
|
||||
@ -282,6 +282,7 @@ const esp_elfsym elf_symbols[] {
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_start),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_stop),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_transmit),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_subscribe_state),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_subscribe_receive),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_unsubscribe_receive),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_touch_driver_get_touched_points),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user