LiveData: Initial implementation

Add support for live data subscription via Device::subscribeLiveData() and
Device::unsubscribeLiveData(). The live data API can be used to subscribe to
individual "signals", a full list of which can be found in LiveDataValueType.
This commit is contained in:
Kyle Johannes
2023-08-22 16:20:48 -04:00
committed by Kyle Schwarz
parent 018f1fac8e
commit 8d704b1bbb
20 changed files with 894 additions and 1 deletions
+12 -1
View File
@@ -35,7 +35,7 @@ enum class Command : uint8_t {
ExtendedData = 0xF2, // Previously known as RED_CMD_EXTENDED_DATA
FlexRayControl = 0xF3,
CoreMiniPreload = 0xF4, // Previously known as RED_CMD_COREMINI_PRELOAD
PHYControlRegisters = 0xEF
PHYControlRegisters = 0xEF,
};
enum class ExtendedCommand : uint16_t {
@@ -53,6 +53,7 @@ enum class ExtendedCommand : uint16_t {
Reboot = 0x001C,
SetUploadedFlag = 0x0027,
GenericBinaryInfo = 0x0030,
LiveData = 0x0035,
};
enum class ExtendedResponse : int32_t {
@@ -68,6 +69,16 @@ enum class ExtendedDataSubCommand : uint32_t {
GenericBinaryRead = 13,
};
#pragma pack(push,1)
struct ExtendedCommandHeader {
uint8_t netid; // should be Main51
uint16_t fullLength;
uint8_t command; // should be Command::Extended
uint16_t extendedCommand;
uint16_t payloadLength;
};
#pragma pack(pop)
}
#endif // __cplusplus
+146
View File
@@ -0,0 +1,146 @@
#ifndef __LIVEDATA_H__
#define __LIVEDATA_H__
#ifdef __cplusplus
#include <cstdint>
#include <vector>
#include <memory>
#include "icsneo/communication/command.h"
#include "icsneo/api/eventmanager.h"
namespace icsneo {
typedef uint32_t LiveDataHandle;
static constexpr size_t MAX_LIVE_DATA_ENTRIES = 20;
enum class LiveDataCommand : uint32_t {
STATUS = 0,
SUBSCRIBE,
UNSUBSCRIBE,
RESPONSE,
CLEAR_ALL,
};
enum class LiveDataStatus : uint32_t {
SUCCESS = 0,
ERR_UNKNOWN_COMMAND,
ERR_HANDLE,
ERR_DUPLICATE,
ERR_FULL
};
enum LiveDataObjectType : uint16_t {
MISC = 8,
SNA = UINT16_MAX,
};
enum class LiveDataValueType : uint32_t {
GPS_LATITUDE = 2,
GPS_LONGITUDE,
GPS_ALTITUDE,
GPS_SPEED,
GPS_VALID,
GPS_ENABLE = 62,
GPS_ACCURACY = 120,
GPS_BEARING = 121,
GPS_TIME = 122,
GPS_TIME_VALID = 123,
};
inline std::ostream& operator<<(std::ostream& os, const LiveDataCommand cmd) {
switch (cmd) {
case LiveDataCommand::STATUS: return os << "Status";
case LiveDataCommand::SUBSCRIBE: return os << "Subscribe";
case LiveDataCommand::UNSUBSCRIBE: return os << "Unsubscribe";
case LiveDataCommand::RESPONSE: return os << "Response";
}
return os;
}
inline std::ostream& operator<<(std::ostream& os, const LiveDataStatus cmd) {
switch (cmd) {
case LiveDataStatus::SUCCESS: return os << "Success";
case LiveDataStatus::ERR_UNKNOWN_COMMAND: return os << "Error: Unknown Command";
case LiveDataStatus::ERR_HANDLE: return os << "Error: Handle";
case LiveDataStatus::ERR_DUPLICATE: return os << "Error: Duplicate";
case LiveDataStatus::ERR_FULL: return os << "Error: Argument limit reached";
}
return os;
}
inline std::ostream& operator<<(std::ostream& os, const LiveDataValueType cmd) {
switch (cmd) {
case LiveDataValueType::GPS_LATITUDE: return os << "GPS Latitude";
case LiveDataValueType::GPS_LONGITUDE: return os << "GPS Longitude";
case LiveDataValueType::GPS_ALTITUDE: return os << "GPS Altitude";
case LiveDataValueType::GPS_SPEED: return os << "GPS Speed";
case LiveDataValueType::GPS_VALID: return os << "GPS Valid";
case LiveDataValueType::GPS_ENABLE: return os << "GPS Enabled";
case LiveDataValueType::GPS_ACCURACY: return os << "GPS Accuracy";
case LiveDataValueType::GPS_BEARING: return os << "GPS Bearing";
case LiveDataValueType::GPS_TIME: return os << "GPS Time";
case LiveDataValueType::GPS_TIME_VALID: return os << "GPS Time Valid";
}
return os;
}
#pragma pack(push,2)
struct LiveDataHeader {
uint32_t version; // See LiveDataVersion
uint32_t cmd;
uint32_t handle;
};
struct LiveDataArgument {
LiveDataObjectType objectType;
uint32_t objectIndex;
uint32_t signalIndex;
LiveDataValueType valueType;
};
struct LiveDataValueHeader {
uint16_t length; // Number of bytes to follow header
uint8_t reserved[2];
};
typedef struct
{
LiveDataValueHeader header;
int64_t value;
} LiveDataValue;
struct LiveDataValueResponse : public LiveDataHeader {
uint32_t numArgs;
LiveDataValue values[1];
};
struct LiveDataStatusResponse : public LiveDataHeader {
LiveDataCommand requestedCommand;
LiveDataStatus status;
};
struct LiveDataSubscribe : public LiveDataHeader {
uint32_t numArgs;
uint32_t freqMs;
uint32_t expireMs;
LiveDataArgument args[1];
};
struct ExtResponseHeader {
ExtendedCommand command;
uint16_t length;
};
#pragma pack(pop)
namespace LiveDataUtil
{
LiveDataHandle getNewHandle();
double liveDataValueToDouble(const LiveDataValue& val);
static constexpr uint32_t LiveDataVersion = 1;
} // namespace LiveDataUtil
} // namespace icsneo
#endif // _cplusplus
#endif // __LIVEDATA_H__
@@ -0,0 +1,44 @@
#ifndef __EXTENDEDLIVEDATAMESSAGE_H_
#define __EXTENDEDLIVEDATAMESSAGE_H_
#ifdef __cplusplus
#include <chrono>
#include "icsneo/communication/message/message.h"
#include "icsneo/communication/command.h"
#include "icsneo/communication/livedata.h"
namespace icsneo {
class LiveDataMessage : public RawMessage {
public:
LiveDataMessage() : RawMessage(Message::Type::LiveData, Network::NetID::ExtendedCommand) {}
LiveDataHandle handle;
LiveDataCommand cmd;
};
class LiveDataCommandMessage : public LiveDataMessage {
public:
LiveDataCommandMessage() {}
std::chrono::milliseconds updatePeriod;
std::chrono::milliseconds expirationTime;
std::vector<std::shared_ptr<LiveDataArgument>> args;
void appendSignalArg(LiveDataValueType valueType);
};
class LiveDataValueMessage : public LiveDataMessage {
public:
LiveDataValueMessage() {}
uint32_t numArgs;
std::vector<std::shared_ptr<LiveDataValue>> values;
};
class LiveDataStatusMessage : public LiveDataMessage {
public:
LiveDataStatusMessage() {}
LiveDataCommand requestedCommand;
LiveDataStatus status;
};
} // namespace icsneo
#endif // __cplusplus
#endif // __EXTENDEDLIVEDATAMESSAGE_H_
@@ -37,6 +37,7 @@ public:
ComponentVersions = 0x800c,
SupportedFeatures = 0x800d,
GenericBinaryStatus = 0x800e,
LiveData = 0x800f,
};
Message(Type t) : type(t) {}
@@ -0,0 +1,27 @@
#ifndef __LIVEDATAPACKET_H__
#define __LIVEDATAPACKET_H__
#ifdef __cplusplus
#include <cstdint>
#include <memory>
#include <vector>
#include "icsneo/api/eventmanager.h"
#include "icsneo/communication/message/message.h"
#include "icsneo/communication/message/livedatamessage.h"
#include "icsneo/communication/livedata.h"
namespace icsneo {
class LiveDataMessage;
struct HardwareLiveDataPacket {
static std::shared_ptr<Message> DecodeToMessage(const std::vector<uint8_t>& bytes, const device_eventhandler_t& report);
static bool EncodeFromMessage(LiveDataMessage& message, std::vector<uint8_t>& bytes, const device_eventhandler_t& report);
};
}
#endif // __cplusplus
#endif // __LIVEDATAPACKET_H__