Compare commits
10 Commits
master
...
mueller/dh
Author | SHA1 | Date | |
---|---|---|---|
5ff28ff562 | |||
fcdb90ff0a | |||
8d1777fa0c | |||
e10e71cee9 | |||
d675a789a2 | |||
6b8c83be29 | |||
093052604a | |||
192255df1c | |||
bdd79d060d | |||
3a47062f2a |
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
|
||||
# [unreleased]
|
||||
|
||||
# [v6.0.0]
|
||||
|
||||
## Changes
|
||||
|
||||
- Removed `HasReturnvaluesIF` class in favor of `returnvalue` namespace with `OK` and `FAILED`
|
||||
|
@ -16,6 +18,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
|
||||
## Added
|
||||
|
||||
- DHB TM handler `handleDeviceTM` renamed to `handleDeviceTm` and now takes
|
||||
`util::DataWrapper` as the data input argument. This allows more flexibility in the possible
|
||||
types of telemetry.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/669
|
||||
- Add `util::DataWrapper` class inside the `util` module. This is a tagged union which allows
|
||||
to specify raw data either as a classic C-style raw pointer and size or as a `SerializeIF`
|
||||
pointer.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/668
|
||||
- Add new `UnsignedByteField` class
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
|
||||
|
||||
|
|
|
@ -1257,30 +1257,40 @@ ReturnValue_t DeviceHandlerBase::letChildHandleMessage(CommandMessage* message)
|
|||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::handleDeviceTM(SerializeIF* dataSet, DeviceCommandId_t replyId,
|
||||
void DeviceHandlerBase::handleDeviceTm(util::DataWrapper dataWrapper, DeviceCommandId_t replyId,
|
||||
bool forceDirectTm) {
|
||||
if (dataSet == nullptr) {
|
||||
if (dataWrapper.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId);
|
||||
auto iter = deviceReplyMap.find(replyId);
|
||||
if (iter == deviceReplyMap.end()) {
|
||||
triggerEvent(DEVICE_UNKNOWN_REPLY, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Regular replies to a command */
|
||||
auto reportData = [&](MessageQueueId_t queueId) {
|
||||
if (dataWrapper.type == util::DataTypes::SERIALIZABLE) {
|
||||
return actionHelper.reportData(queueId, replyId, dataWrapper.dataUnion.serializable);
|
||||
} else if (dataWrapper.type == util::DataTypes::RAW) {
|
||||
return actionHelper.reportData(queueId, replyId, dataWrapper.dataUnion.raw.data,
|
||||
dataWrapper.dataUnion.raw.len);
|
||||
}
|
||||
return returnvalue::FAILED;
|
||||
};
|
||||
|
||||
// Regular replies to a command
|
||||
if (iter->second.command != deviceCommandMap.end()) {
|
||||
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
|
||||
|
||||
// This may fail, but we'll ignore the fault.
|
||||
if (queueId != NO_COMMANDER) {
|
||||
/* This may fail, but we'll ignore the fault. */
|
||||
actionHelper.reportData(queueId, replyId, dataSet);
|
||||
reportData(queueId);
|
||||
}
|
||||
|
||||
/* This check should make sure we get any TM but don't get anything doubled. */
|
||||
// This check should make sure we get any TM but don't get anything doubled.
|
||||
if (wiretappingMode == TM && (requestedRawTraffic != queueId)) {
|
||||
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataSet);
|
||||
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataWrapper);
|
||||
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
|
||||
}
|
||||
|
||||
|
@ -1289,22 +1299,16 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* dataSet, DeviceCommandId_t r
|
|||
// hiding of sender needed so the service will handle it as
|
||||
// unexpected Data, no matter what state (progress or completed)
|
||||
// it is in
|
||||
actionHelper.reportData(defaultRawReceiver, replyId, dataSet, true);
|
||||
reportData(defaultRawReceiver);
|
||||
}
|
||||
}
|
||||
/* Unrequested or aperiodic replies */
|
||||
// Unrequested or aperiodic replies
|
||||
else {
|
||||
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataSet);
|
||||
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataWrapper);
|
||||
if (wiretappingMode == TM) {
|
||||
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
|
||||
}
|
||||
if (forceDirectTm and defaultRawReceiver != MessageQueueIF::NO_QUEUE) {
|
||||
// sid_t setSid = sid_t(this->getObjectId(), replyId);
|
||||
// LocalPoolDataSetBase* dataset = getDataSetHandle(setSid);
|
||||
// if(dataset != nullptr) {
|
||||
// poolManager.generateHousekeepingPacket(setSid, dataset, true);
|
||||
// }
|
||||
|
||||
// hiding of sender needed so the service will handle it as
|
||||
// unexpected Data, no matter what state (progress or completed)
|
||||
// it is in
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/tasks/PeriodicTaskIF.h"
|
||||
#include "fsfw/util/dataWrapper.h"
|
||||
|
||||
namespace Factory {
|
||||
void setStaticFrameworkObjectIds();
|
||||
|
@ -1052,9 +1053,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
|
||||
bool isAwaitingReply();
|
||||
|
||||
void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t replyId, bool forceDirectTm = false);
|
||||
// void handleDeviceTM(uint8_t* data, size_t dataSize, DeviceCommandId_t replyId,
|
||||
// bool forceDirectTm);
|
||||
void handleDeviceTm(util::DataWrapper dataWrapper, DeviceCommandId_t replyId,
|
||||
bool forceDirectTm = false);
|
||||
|
||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode);
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
#include "fsfw/serialize/SerializeAdapter.h"
|
||||
|
||||
DeviceTmReportingWrapper::DeviceTmReportingWrapper(object_id_t objectId, ActionId_t actionId,
|
||||
SerializeIF* data)
|
||||
: objectId(objectId), actionId(actionId), data(data) {}
|
||||
util::DataWrapper data)
|
||||
: objectId(objectId), actionId(actionId), dataWrapper(data) {}
|
||||
|
||||
DeviceTmReportingWrapper::~DeviceTmReportingWrapper() {}
|
||||
DeviceTmReportingWrapper::~DeviceTmReportingWrapper() = default;
|
||||
|
||||
ReturnValue_t DeviceTmReportingWrapper::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
|
@ -19,22 +19,27 @@ ReturnValue_t DeviceTmReportingWrapper::serialize(uint8_t** buffer, size_t* size
|
|||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return data->serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (dataWrapper.isNull()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (dataWrapper.type == util::DataTypes::SERIALIZABLE) {
|
||||
return dataWrapper.dataUnion.serializable->serialize(buffer, size, maxSize, streamEndianness);
|
||||
} else if (dataWrapper.type == util::DataTypes::RAW) {
|
||||
if (*size + dataWrapper.dataUnion.raw.len > maxSize) {
|
||||
return SerializeIF::BUFFER_TOO_SHORT;
|
||||
}
|
||||
std::memcpy(*buffer, dataWrapper.dataUnion.raw.data, dataWrapper.dataUnion.raw.len);
|
||||
*buffer += dataWrapper.dataUnion.raw.len;
|
||||
*size += dataWrapper.dataUnion.raw.len;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
size_t DeviceTmReportingWrapper::getSerializedSize() const {
|
||||
return sizeof(objectId) + sizeof(ActionId_t) + data->getSerializedSize();
|
||||
return sizeof(objectId) + sizeof(ActionId_t) + dataWrapper.getLength();
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceTmReportingWrapper::deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) {
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&objectId, buffer, size, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = SerializeAdapter::deSerialize(&actionId, buffer, size, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return data->deSerialize(buffer, size, streamEndianness);
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
|
|
@ -1,27 +1,29 @@
|
|||
#ifndef FSFW_DEVICEHANDLERS_DEVICETMREPORTINGWRAPPER_H_
|
||||
#define FSFW_DEVICEHANDLERS_DEVICETMREPORTINGWRAPPER_H_
|
||||
|
||||
#include "../action/HasActionsIF.h"
|
||||
#include "../objectmanager/SystemObjectIF.h"
|
||||
#include "../serialize/SerializeIF.h"
|
||||
#include "fsfw/action/HasActionsIF.h"
|
||||
#include "fsfw/objectmanager/SystemObjectIF.h"
|
||||
#include "fsfw/serialize/SerializeIF.h"
|
||||
#include "fsfw/util/dataWrapper.h"
|
||||
|
||||
class DeviceTmReportingWrapper : public SerializeIF {
|
||||
public:
|
||||
DeviceTmReportingWrapper(object_id_t objectId, ActionId_t actionId, SerializeIF* data);
|
||||
virtual ~DeviceTmReportingWrapper();
|
||||
DeviceTmReportingWrapper(object_id_t objectId, ActionId_t actionId, util::DataWrapper data);
|
||||
~DeviceTmReportingWrapper() override;
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
|
||||
virtual size_t getSerializedSize() const override;
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
[[nodiscard]] size_t getSerializedSize() const override;
|
||||
|
||||
private:
|
||||
object_id_t objectId;
|
||||
ActionId_t actionId;
|
||||
SerializeIF* data;
|
||||
util::DataWrapper dataWrapper;
|
||||
|
||||
// Deserialization forbidden
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
};
|
||||
|
||||
#endif /* FSFW_DEVICEHANDLERS_DEVICETMREPORTINGWRAPPER_H_ */
|
||||
|
|
|
@ -9,7 +9,10 @@
|
|||
|
||||
namespace util {
|
||||
|
||||
using BufPair = std::pair<const uint8_t*, size_t>;
|
||||
|
||||
struct RawData {
|
||||
RawData() = default;
|
||||
const uint8_t* data = nullptr;
|
||||
size_t len = 0;
|
||||
};
|
||||
|
@ -17,14 +20,28 @@ struct RawData {
|
|||
enum DataTypes { NONE, RAW, SERIALIZABLE };
|
||||
|
||||
union DataUnion {
|
||||
RawData raw;
|
||||
SerializeIF* serializable = nullptr;
|
||||
RawData raw{};
|
||||
SerializeIF* serializable;
|
||||
};
|
||||
|
||||
struct DataWrapper {
|
||||
|
||||
DataWrapper() = default;
|
||||
|
||||
DataWrapper(const uint8_t* data, size_t size): type(DataTypes::RAW) {
|
||||
setRawData({data, size});
|
||||
}
|
||||
|
||||
explicit DataWrapper(BufPair raw): type(DataTypes::RAW) {
|
||||
setRawData(raw);
|
||||
}
|
||||
|
||||
explicit DataWrapper(SerializeIF& serializable): type(DataTypes::SERIALIZABLE) {
|
||||
setSerializable(serializable);
|
||||
}
|
||||
|
||||
DataTypes type = DataTypes::NONE;
|
||||
DataUnion dataUnion;
|
||||
using BufPairT = std::pair<const uint8_t*, size_t>;
|
||||
|
||||
[[nodiscard]] size_t getLength() const {
|
||||
if (type == DataTypes::RAW) {
|
||||
|
@ -42,7 +59,7 @@ struct DataWrapper {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
void setRawData(BufPairT bufPair) {
|
||||
void setRawData(BufPair bufPair) {
|
||||
type = DataTypes::RAW;
|
||||
dataUnion.raw.data = bufPair.first;
|
||||
dataUnion.raw.len = bufPair.second;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testUnsignedByteField.cpp
|
||||
testDataWrapper.cpp
|
||||
)
|
||||
|
|
59
unittests/util/testDataWrapper.cpp
Normal file
59
unittests/util/testDataWrapper.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/util/dataWrapper.h"
|
||||
#include "mocks/SimpleSerializable.h"
|
||||
|
||||
TEST_CASE("Data Wrapper", "[util]") {
|
||||
util::DataWrapper wrapper;
|
||||
SECTION("State") {
|
||||
REQUIRE(wrapper.isNull());
|
||||
REQUIRE(wrapper.type == util::DataTypes::NONE);
|
||||
}
|
||||
|
||||
SECTION("Set Raw Data") {
|
||||
util::DataWrapper* instance = &wrapper;
|
||||
bool deleteInst = false;
|
||||
REQUIRE(wrapper.isNull());
|
||||
std::array<uint8_t, 4> data = {1, 2, 3, 4};
|
||||
SECTION("Setter") {
|
||||
wrapper.setRawData({data.data(), data.size()});
|
||||
}
|
||||
SECTION("Direct Construction Pair") {
|
||||
instance = new util::DataWrapper(util::BufPair(data.data(), data.size()));
|
||||
deleteInst = true;
|
||||
}
|
||||
SECTION("Direct Construction Single Args") {
|
||||
instance = new util::DataWrapper(data.data(), data.size());
|
||||
deleteInst = true;
|
||||
}
|
||||
REQUIRE(not instance->isNull());
|
||||
REQUIRE(instance->type == util::DataTypes::RAW);
|
||||
REQUIRE(instance->dataUnion.raw.data == data.data());
|
||||
REQUIRE(instance->dataUnion.raw.len == data.size());
|
||||
if(deleteInst) {
|
||||
delete instance;
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Simple Serializable") {
|
||||
util::DataWrapper* instance = &wrapper;
|
||||
bool deleteInst = false;
|
||||
REQUIRE(instance->isNull());
|
||||
SimpleSerializable serializable;
|
||||
SECTION("Setter") {
|
||||
wrapper.setSerializable(serializable);
|
||||
}
|
||||
SECTION("Direct Construction") {
|
||||
instance = new util::DataWrapper(serializable);
|
||||
deleteInst = true;
|
||||
}
|
||||
|
||||
REQUIRE(not instance->isNull());
|
||||
REQUIRE(instance->type == util::DataTypes::SERIALIZABLE);
|
||||
REQUIRE(instance->dataUnion.serializable == &serializable);
|
||||
if(deleteInst) {
|
||||
delete instance;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "fsfw/util/UnsignedByteField.h"
|
||||
|
||||
TEST_CASE("Unsigned Byte Field", "[unsigned-byte-field]") {
|
||||
TEST_CASE("Unsigned Byte Field", "[util]") {
|
||||
auto testByteField = UnsignedByteField<uint32_t>(10);
|
||||
auto u32ByteField = U32ByteField(10);
|
||||
auto u16ByteField = U16ByteField(5);
|
||||
|
|
Loading…
Reference in New Issue
Block a user