A lot of new features and tweaks #12
27
container/DynamicFIFO.h
Normal file
27
container/DynamicFIFO.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef FRAMEWORK_CONTAINER_DYNAMICFIFO_H_
|
||||||
|
#define FRAMEWORK_CONTAINER_DYNAMICFIFO_H_
|
||||||
|
|
||||||
|
#include <framework/container/FIFOBase.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Simple First-In-First-Out data structure. The maximum size
|
||||||
|
* can be set in the constructor.
|
||||||
|
* @details
|
||||||
|
* The maximum capacity can be determined at run-time, so this container
|
||||||
|
* performs dynamic memory allocation!
|
||||||
|
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
||||||
|
* @tparam T Entry Type
|
||||||
|
* @tparam capacity Maximum capacity
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
class DynamicFIFO: public FIFOBase<T> {
|
||||||
|
public:
|
||||||
|
DynamicFIFO(size_t maxCapacity): FIFOBase<T>(values.data(), maxCapacity),
|
||||||
|
values(maxCapacity) {};
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<T> values;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ */
|
@ -1,31 +1,26 @@
|
|||||||
#ifndef FRAMEWORK_CONTAINER_FIFO_H_
|
#ifndef FRAMEWORK_CONTAINER_FIFO_H_
|
||||||
#define FRAMEWORK_CONTAINER_FIFO_H_
|
#define FRAMEWORK_CONTAINER_FIFO_H_
|
||||||
|
|
||||||
|
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||||
#include <framework/container/FIFOBase.h>
|
#include <framework/container/FIFOBase.h>
|
||||||
#include <vector>
|
#include <array>
|
||||||
|
|
||||||
namespace fsfw {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Simple First-In-First-Out data structure. The maximum size
|
* @brief Simple First-In-First-Out data structure with size fixed at
|
||||||
* can be set in the constructor.
|
* compile time
|
||||||
* @details
|
* @details
|
||||||
* The maximum capacity can be determined at run-time, so this container
|
* Performs no dynamic memory allocation.
|
||||||
* performs dynamic memory allocation!
|
|
||||||
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
||||||
* @tparam T Entry Type
|
* @tparam T Entry Type
|
||||||
* @tparam capacity Maximum capacity
|
* @tparam capacity Maximum capacity
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T, size_t capacity>
|
||||||
class FIFO: public FIFOBase<T> {
|
class FIFO: public FIFOBase<T> {
|
||||||
public:
|
public:
|
||||||
FIFO(size_t maxCapacity): FIFOBase<T>(values.data(), maxCapacity),
|
FIFO(): FIFOBase<T>(values.data(), capacity) {};
|
||||||
values(maxCapacity) {};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<T> values;
|
std::array<T, capacity> values;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */
|
||||||
|
|
||||||
#endif /* FRAMEWORK_CONTAINER_FIFO_H_ */
|
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
namespace fsfw {
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class FIFOBase {
|
class FIFOBase {
|
||||||
public:
|
public:
|
||||||
@ -60,6 +58,4 @@ private:
|
|||||||
|
|
||||||
#include <framework/container/FIFOBase.tpp>
|
#include <framework/container/FIFOBase.tpp>
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */
|
#endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */
|
||||||
|
@ -17,7 +17,7 @@ SimpleRingBuffer::~SimpleRingBuffer() {
|
|||||||
|
|
||||||
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
|
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
|
||||||
uint32_t amount) {
|
uint32_t amount) {
|
||||||
if (availableWriteSpace() >= amount || overwriteOld) {
|
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||||
uint32_t amountTillWrap = writeTillWrap();
|
uint32_t amountTillWrap = writeTillWrap();
|
||||||
if (amountTillWrap >= amount) {
|
if (amountTillWrap >= amount) {
|
||||||
memcpy(&buffer[write], data, amount);
|
memcpy(&buffer[write], data, amount);
|
||||||
@ -43,7 +43,7 @@ ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, uint32_t amount,
|
|||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trueAmount != NULL) {
|
if (trueAmount != nullptr) {
|
||||||
*trueAmount = amount;
|
*trueAmount = amount;
|
||||||
}
|
}
|
||||||
if (amountTillWrap >= amount) {
|
if (amountTillWrap >= amount) {
|
||||||
@ -65,7 +65,7 @@ ReturnValue_t SimpleRingBuffer::deleteData(uint32_t amount,
|
|||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trueAmount != NULL) {
|
if (trueAmount != nullptr) {
|
||||||
*trueAmount = amount;
|
*trueAmount = amount;
|
||||||
}
|
}
|
||||||
incrementRead(amount, READ_PTR);
|
incrementRead(amount, READ_PTR);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
|
#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
|
||||||
|
|
||||||
#include <framework/container/RingBufferBase.h>
|
#include <framework/container/RingBufferBase.h>
|
||||||
#include <stddef.h>
|
#include <cstddef>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Circular buffer implementation, useful for buffering
|
* @brief Circular buffer implementation, useful for buffering
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
#ifndef FRAMEWORK_CONTAINER_STATICFIFO_H_
|
|
||||||
#define FRAMEWORK_CONTAINER_STATICFIFO_H_
|
|
||||||
|
|
||||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
|
||||||
#include <framework/container/FIFOBase.h>
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
namespace fsfw {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Simple First-In-First-Out data structure with size fixed at
|
|
||||||
* compile time
|
|
||||||
* @details
|
|
||||||
* Performs no dynamic memory allocation.
|
|
||||||
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
|
||||||
* @tparam T Entry Type
|
|
||||||
* @tparam capacity Maximum capacity
|
|
||||||
*/
|
|
||||||
template<typename T, size_t capacity>
|
|
||||||
class StaticFIFO: public FIFOBase<T> {
|
|
||||||
public:
|
|
||||||
StaticFIFO(): FIFOBase<T>(values.data(), capacity) {};
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::array<T, capacity> values;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */
|
|
@ -58,4 +58,4 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/*.cpp)
|
|||||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp)
|
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp)
|
||||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp)
|
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp)
|
||||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp)
|
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp)
|
||||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/test/*.cpp)
|
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/pus/*.cpp)
|
@ -1,95 +1,124 @@
|
|||||||
#include <framework/globalfunctions/DleEncoder.h>
|
#include <framework/globalfunctions/DleEncoder.h>
|
||||||
|
|
||||||
DleEncoder::DleEncoder() {
|
DleEncoder::DleEncoder() {}
|
||||||
}
|
|
||||||
|
|
||||||
DleEncoder::~DleEncoder() {
|
DleEncoder::~DleEncoder() {}
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream,
|
|
||||||
uint32_t sourceStreamLen, uint32_t *readLen, uint8_t *destStream,
|
|
||||||
uint32_t maxDestStreamlen, uint32_t *decodedLen) {
|
|
||||||
uint32_t encodedIndex = 0, decodedIndex = 0;
|
|
||||||
uint8_t nextByte;
|
|
||||||
if (*sourceStream != STX) {
|
|
||||||
return RETURN_FAILED;
|
|
||||||
}
|
|
||||||
++encodedIndex;
|
|
||||||
while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen)
|
|
||||||
&& (sourceStream[encodedIndex] != ETX)
|
|
||||||
&& (sourceStream[encodedIndex] != STX)) {
|
|
||||||
if (sourceStream[encodedIndex] == DLE) {
|
|
||||||
nextByte = sourceStream[encodedIndex + 1];
|
|
||||||
if (nextByte == 0x10) {
|
|
||||||
destStream[decodedIndex] = nextByte;
|
|
||||||
} else {
|
|
||||||
if ((nextByte == 0x42) || (nextByte == 0x43)
|
|
||||||
|| (nextByte == 0x4D)) {
|
|
||||||
destStream[decodedIndex] = nextByte - 0x40;
|
|
||||||
} else {
|
|
||||||
return RETURN_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++encodedIndex;
|
|
||||||
} else {
|
|
||||||
destStream[decodedIndex] = sourceStream[encodedIndex];
|
|
||||||
}
|
|
||||||
++encodedIndex;
|
|
||||||
++decodedIndex;
|
|
||||||
}
|
|
||||||
if (sourceStream[encodedIndex] != ETX) {
|
|
||||||
return RETURN_FAILED;
|
|
||||||
} else {
|
|
||||||
*readLen = ++encodedIndex;
|
|
||||||
*decodedLen = decodedIndex;
|
|
||||||
return RETURN_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream,
|
ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream,
|
||||||
uint32_t sourceLen, uint8_t* destStream, uint32_t maxDestLen,
|
size_t sourceLen, uint8_t* destStream, size_t maxDestLen,
|
||||||
uint32_t* encodedLen, bool addStxEtx) {
|
size_t* encodedLen, bool addStxEtx) {
|
||||||
if (maxDestLen < 2) {
|
if (maxDestLen < 2) {
|
||||||
return RETURN_FAILED;
|
return STREAM_TOO_SHORT;
|
||||||
}
|
}
|
||||||
uint32_t encodedIndex = 0, sourceIndex = 0;
|
size_t encodedIndex = 0, sourceIndex = 0;
|
||||||
uint8_t nextByte;
|
uint8_t nextByte;
|
||||||
if (addStxEtx) {
|
if (addStxEtx) {
|
||||||
destStream[0] = STX;
|
destStream[0] = STX;
|
||||||
++encodedIndex;
|
++encodedIndex;
|
||||||
}
|
}
|
||||||
while ((encodedIndex < maxDestLen) && (sourceIndex < sourceLen)) {
|
|
||||||
|
while (encodedIndex < maxDestLen and sourceIndex < sourceLen)
|
||||||
|
{
|
||||||
nextByte = sourceStream[sourceIndex];
|
nextByte = sourceStream[sourceIndex];
|
||||||
if ((nextByte == STX) || (nextByte == ETX) || (nextByte == 0x0D)) {
|
// STX, ETX and CR characters in the stream need to be escaped with DLE
|
||||||
|
if (nextByte == STX or nextByte == ETX or nextByte == CARRIAGE_RETURN) {
|
||||||
if (encodedIndex + 1 >= maxDestLen) {
|
if (encodedIndex + 1 >= maxDestLen) {
|
||||||
return RETURN_FAILED;
|
return STREAM_TOO_SHORT;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
destStream[encodedIndex] = DLE;
|
destStream[encodedIndex] = DLE;
|
||||||
++encodedIndex;
|
++encodedIndex;
|
||||||
|
/* Escaped byte will be actual byte + 0x40. This prevents
|
||||||
|
* STX, ETX, and carriage return characters from appearing
|
||||||
|
* in the encoded data stream at all, so when polling an
|
||||||
|
* encoded stream, the transmission can be stopped at ETX.
|
||||||
|
* 0x40 was chosen at random with special requirements:
|
||||||
|
* - Prevent going from one control char to another
|
||||||
|
* - Prevent overflow for common characters */
|
||||||
destStream[encodedIndex] = nextByte + 0x40;
|
destStream[encodedIndex] = nextByte + 0x40;
|
||||||
}
|
}
|
||||||
} else if (nextByte == DLE) {
|
}
|
||||||
|
// DLE characters are simply escaped with DLE.
|
||||||
|
else if (nextByte == DLE) {
|
||||||
if (encodedIndex + 1 >= maxDestLen) {
|
if (encodedIndex + 1 >= maxDestLen) {
|
||||||
return RETURN_FAILED;
|
return STREAM_TOO_SHORT;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
destStream[encodedIndex] = DLE;
|
destStream[encodedIndex] = DLE;
|
||||||
++encodedIndex;
|
++encodedIndex;
|
||||||
destStream[encodedIndex] = DLE;
|
destStream[encodedIndex] = DLE;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
destStream[encodedIndex] = nextByte;
|
destStream[encodedIndex] = nextByte;
|
||||||
}
|
}
|
||||||
++encodedIndex;
|
++encodedIndex;
|
||||||
++sourceIndex;
|
++sourceIndex;
|
||||||
}
|
}
|
||||||
if ((sourceIndex == sourceLen) && (encodedIndex < maxDestLen)) {
|
|
||||||
|
if (sourceIndex == sourceLen and encodedIndex < maxDestLen) {
|
||||||
if (addStxEtx) {
|
if (addStxEtx) {
|
||||||
destStream[encodedIndex] = ETX;
|
destStream[encodedIndex] = ETX;
|
||||||
++encodedIndex;
|
++encodedIndex;
|
||||||
}
|
}
|
||||||
*encodedLen = encodedIndex;
|
*encodedLen = encodedIndex;
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
} else {
|
}
|
||||||
return RETURN_FAILED;
|
else {
|
||||||
|
return STREAM_TOO_SHORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream,
|
||||||
|
size_t sourceStreamLen, size_t *readLen, uint8_t *destStream,
|
||||||
|
size_t maxDestStreamlen, size_t *decodedLen) {
|
||||||
|
size_t encodedIndex = 0, decodedIndex = 0;
|
||||||
|
uint8_t nextByte;
|
||||||
|
if (*sourceStream != STX) {
|
||||||
|
return DECODING_ERROR;
|
||||||
|
}
|
||||||
|
++encodedIndex;
|
||||||
|
|
||||||
|
while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen)
|
||||||
|
&& (sourceStream[encodedIndex] != ETX)
|
||||||
|
&& (sourceStream[encodedIndex] != STX))
|
||||||
|
{
|
||||||
|
if (sourceStream[encodedIndex] == DLE) {
|
||||||
|
nextByte = sourceStream[encodedIndex + 1];
|
||||||
|
// The next byte is a DLE character that was escaped by another
|
||||||
|
// DLE character, so we can write it to the destination stream.
|
||||||
|
if (nextByte == DLE) {
|
||||||
|
destStream[decodedIndex] = nextByte;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* The next byte is a STX, DTX or 0x0D character which
|
||||||
|
* was escaped by a DLE character. The actual byte was
|
||||||
|
* also encoded by adding + 0x40 to preven having control chars,
|
||||||
|
* in the stream at all, so we convert it back. */
|
||||||
|
if (nextByte == 0x42 or nextByte == 0x43 or nextByte == 0x4D) {
|
||||||
|
destStream[decodedIndex] = nextByte - 0x40;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return DECODING_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++encodedIndex;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
destStream[decodedIndex] = sourceStream[encodedIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
++encodedIndex;
|
||||||
|
++decodedIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceStream[encodedIndex] != ETX) {
|
||||||
|
return DECODING_ERROR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*readLen = ++encodedIndex;
|
||||||
|
*decodedLen = decodedIndex;
|
||||||
|
return RETURN_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,25 +1,79 @@
|
|||||||
#ifndef DLEENCODER_H_
|
#ifndef FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_
|
||||||
#define DLEENCODER_H_
|
#define FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_
|
||||||
|
|
||||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This DLE Encoder (Data Link Encoder) can be used to encode and
|
||||||
|
* decode arbitrary data with ASCII control characters
|
||||||
|
* @details
|
||||||
|
* List of control codes:
|
||||||
|
* https://en.wikipedia.org/wiki/C0_and_C1_control_codes
|
||||||
|
*
|
||||||
|
* This encoder can be used to achieve a basic transport layer when using
|
||||||
|
* char based transmission systems.
|
||||||
|
* The passed source strean is converted into a encoded stream by adding
|
||||||
|
* a STX marker at the start of the stream and an ETX marker at the end of
|
||||||
|
* the stream. Any STX, ETX, DLE and CR occurences in the source stream are
|
||||||
|
* escaped by a DLE character. The encoder also replaces escaped control chars
|
||||||
|
* by another char, so STX, ETX and CR should not appear anywhere in the actual
|
||||||
|
* encoded data stream.
|
||||||
|
*
|
||||||
|
* When using a strictly char based reception of packets enoded with DLE,
|
||||||
|
* STX can be used to notify a reader that actual data will start to arrive
|
||||||
|
* while ETX can be used to notify the reader that the data has ended.
|
||||||
|
*/
|
||||||
class DleEncoder: public HasReturnvaluesIF {
|
class DleEncoder: public HasReturnvaluesIF {
|
||||||
private:
|
private:
|
||||||
DleEncoder();
|
DleEncoder();
|
||||||
virtual ~DleEncoder();
|
virtual ~DleEncoder();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const uint8_t STX = 0x02;
|
static constexpr uint8_t INTERFACE_ID = CLASS_ID::DLE_ENCODER;
|
||||||
static const uint8_t ETX = 0x03;
|
static constexpr ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(0x01);
|
||||||
static const uint8_t DLE = 0x10;
|
static constexpr ReturnValue_t DECODING_ERROR = MAKE_RETURN_CODE(0x02);
|
||||||
|
|
||||||
static ReturnValue_t decode(const uint8_t *sourceStream,
|
//! Start Of Text character. First character is encoded stream
|
||||||
uint32_t sourceStreamLen, uint32_t *readLen, uint8_t *destStream,
|
static constexpr uint8_t STX = 0x02;
|
||||||
uint32_t maxDestStreamlen, uint32_t *decodedLen);
|
//! End Of Text character. Last character in encoded stream
|
||||||
|
static constexpr uint8_t ETX = 0x03;
|
||||||
|
//! Data Link Escape character. Used to escape STX, ETX and DLE occurences
|
||||||
|
//! in the source stream.
|
||||||
|
static constexpr uint8_t DLE = 0x10;
|
||||||
|
static constexpr uint8_t CARRIAGE_RETURN = 0x0D;
|
||||||
|
|
||||||
static ReturnValue_t encode(const uint8_t *sourceStream, uint32_t sourceLen,
|
/**
|
||||||
uint8_t *destStream, uint32_t maxDestLen, uint32_t *encodedLen,
|
* Encodes the give data stream by preceding it with the STX marker
|
||||||
|
* and ending it with an ETX marker. STX, ETX and DLE characters inside
|
||||||
|
* the stream are escaped by DLE characters and also replaced by adding
|
||||||
|
* 0x40 (which is reverted in the decoing process).
|
||||||
|
* @param sourceStream
|
||||||
|
* @param sourceLen
|
||||||
|
* @param destStream
|
||||||
|
* @param maxDestLen
|
||||||
|
* @param encodedLen
|
||||||
|
* @param addStxEtx
|
||||||
|
* Adding STX and ETX can be omitted, if they are added manually.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static ReturnValue_t encode(const uint8_t *sourceStream, size_t sourceLen,
|
||||||
|
uint8_t *destStream, size_t maxDestLen, size_t *encodedLen,
|
||||||
bool addStxEtx = true);
|
bool addStxEtx = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an encoded stream back.
|
||||||
|
* @param sourceStream
|
||||||
|
* @param sourceStreamLen
|
||||||
|
* @param readLen
|
||||||
|
* @param destStream
|
||||||
|
* @param maxDestStreamlen
|
||||||
|
* @param decodedLen
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static ReturnValue_t decode(const uint8_t *sourceStream,
|
||||||
|
size_t sourceStreamLen, size_t *readLen, uint8_t *destStream,
|
||||||
|
size_t maxDestStreamlen, size_t *decodedLen);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DLEENCODER_H_ */
|
#endif /* FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ */
|
||||||
|
@ -18,18 +18,14 @@ public:
|
|||||||
static const MessageQueueId_t NO_QUEUE = MessageQueueMessageIF::NO_QUEUE; //!< Ugly hack.
|
static const MessageQueueId_t NO_QUEUE = MessageQueueMessageIF::NO_QUEUE; //!< Ugly hack.
|
||||||
|
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF;
|
||||||
/**
|
//! No new messages on the queue
|
||||||
* No new messages on the queue
|
|
||||||
*/
|
|
||||||
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1);
|
||||||
/**
|
//! No space left for more messages
|
||||||
* No space left for more messages
|
|
||||||
*/
|
|
||||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(2);
|
static const ReturnValue_t FULL = MAKE_RETURN_CODE(2);
|
||||||
/**
|
//! Returned if a reply method was called without partner
|
||||||
* Returned if a reply method was called without partner
|
|
||||||
*/
|
|
||||||
static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3);
|
static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3);
|
||||||
|
//! Returned if the target destination is invalid.
|
||||||
|
static constexpr ReturnValue_t DESTINVATION_INVALID = MAKE_RETURN_CODE(4);
|
||||||
|
|
||||||
virtual ~MessageQueueIF() {}
|
virtual ~MessageQueueIF() {}
|
||||||
/**
|
/**
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
namespace objects {
|
namespace objects {
|
||||||
enum framework_objects {
|
enum framework_objects {
|
||||||
|
// Default verification reporter.
|
||||||
|
PUS_SERVICE_1 = 0x53000000,
|
||||||
|
|
||||||
//Generic IDs for IPC, modes, health, events
|
//Generic IDs for IPC, modes, health, events
|
||||||
HEALTH_TABLE = 0x53010000,
|
HEALTH_TABLE = 0x53010000,
|
||||||
// MODE_STORE = 0x53010100,
|
// MODE_STORE = 0x53010100,
|
||||||
@ -12,6 +15,7 @@ enum framework_objects {
|
|||||||
//IDs for PUS Packet Communication
|
//IDs for PUS Packet Communication
|
||||||
TC_STORE = 0x534f0100,
|
TC_STORE = 0x534f0100,
|
||||||
TM_STORE = 0x534f0200,
|
TM_STORE = 0x534f0200,
|
||||||
|
|
||||||
NO_OBJECT = 0xFFFFFFFF
|
NO_OBJECT = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
sif::error << "Component " << std::hex << componentId <<
|
sif::error << "Component " << std::hex << componentId <<
|
||||||
" not found, not adding it to pst" << std::endl;
|
" not found, not adding it to pst" << std::dec << std::endl;
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,8 +156,8 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
|||||||
|
|
||||||
if(message->getMaximumMessageSize() < maxMessageSize) {
|
if(message->getMaximumMessageSize() < maxMessageSize) {
|
||||||
sif::error << "MessageQueue::receiveMessage: Message size "
|
sif::error << "MessageQueue::receiveMessage: Message size "
|
||||||
<< message->getMaximumMessageSize() <<
|
<< message->getMaximumMessageSize()
|
||||||
" too small to receive data!" << std::endl;
|
<< " too small to receive data!" << std::endl;
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,13 +330,16 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
|||||||
//MQ_NONBLOCK flag was set in its attributes, and the
|
//MQ_NONBLOCK flag was set in its attributes, and the
|
||||||
//specified queue is full.
|
//specified queue is full.
|
||||||
return MessageQueueIF::FULL;
|
return MessageQueueIF::FULL;
|
||||||
case EBADF:
|
case EBADF: {
|
||||||
//mq_des doesn't represent a valid message queue descriptor,
|
//mq_des doesn't represent a valid message queue descriptor,
|
||||||
//or mq_des wasn't opened for writing.
|
//or mq_des wasn't opened for writing.
|
||||||
sif::error << "MessageQueue::sendMessage: Configuration error "
|
sif::error << "MessageQueue::sendMessage: Configuration error, MQ"
|
||||||
<< strerror(errno) << " in mq_send mqSendTo: " << sendTo
|
<< " destination invalid." << std::endl;
|
||||||
<< " sent from " << sentFrom << std::endl;
|
sif::error << strerror(errno) << " in "
|
||||||
/*NO BREAK*/
|
<<"mq_send to: " << sendTo << " sent from "
|
||||||
|
<< sentFrom << std::endl;
|
||||||
|
return DESTINVATION_INVALID;
|
||||||
|
}
|
||||||
case EINTR:
|
case EINTR:
|
||||||
//The call was interrupted by a signal.
|
//The call was interrupted by a signal.
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
|
@ -68,12 +68,12 @@ void PeriodicPosixTask::taskFunctionality(void) {
|
|||||||
char name[20] = {0};
|
char name[20] = {0};
|
||||||
int status = pthread_getname_np(pthread_self(),name,sizeof(name));
|
int status = pthread_getname_np(pthread_self(),name,sizeof(name));
|
||||||
if(status == 0){
|
if(status == 0){
|
||||||
sif::error << "PeriodicPosixTask " << name << ": Deadline "
|
//sif::error << "PeriodicPosixTask " << name << ": Deadline "
|
||||||
"missed." << std::endl;
|
// "missed." << std::endl;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sif::error << "PeriodicPosixTask X: Deadline missed. " <<
|
//sif::error << "PeriodicPosixTask X: Deadline missed. " <<
|
||||||
status << std::endl;
|
// status << std::endl;
|
||||||
}
|
}
|
||||||
if (this->deadlineMissedFunc != nullptr) {
|
if (this->deadlineMissedFunc != nullptr) {
|
||||||
this->deadlineMissedFunc();
|
this->deadlineMissedFunc();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <framework/osal/linux/TcUnixUdpPollingTask.h>
|
#include <framework/osal/linux/TcUnixUdpPollingTask.h>
|
||||||
|
#include <framework/globalfunctions/arrayprinter.h>
|
||||||
|
|
||||||
TcSocketPollingTask::TcSocketPollingTask(object_id_t objectId,
|
TcUnixUdpPollingTask::TcUnixUdpPollingTask(object_id_t objectId,
|
||||||
object_id_t tmtcUnixUdpBridge, size_t frameSize,
|
object_id_t tmtcUnixUdpBridge, size_t frameSize,
|
||||||
double timeoutSeconds): SystemObject(objectId),
|
double timeoutSeconds): SystemObject(objectId),
|
||||||
tmtcBridgeId(tmtcUnixUdpBridge) {
|
tmtcBridgeId(tmtcUnixUdpBridge) {
|
||||||
@ -23,23 +24,12 @@ TcSocketPollingTask::TcSocketPollingTask(object_id_t objectId,
|
|||||||
else {
|
else {
|
||||||
receptionTimeout = timevalOperations::toTimeval(timeoutSeconds);
|
receptionTimeout = timevalOperations::toTimeval(timeoutSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set receive timeout.
|
|
||||||
int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO,
|
|
||||||
&receptionTimeout, sizeof(receptionTimeout));
|
|
||||||
if(result == -1) {
|
|
||||||
sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting receive"
|
|
||||||
"timeout failed with " << strerror(errno) << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TcSocketPollingTask::~TcSocketPollingTask() {
|
TcUnixUdpPollingTask::~TcUnixUdpPollingTask() {}
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t TcSocketPollingTask::performOperation(uint8_t opCode) {
|
ReturnValue_t TcUnixUdpPollingTask::performOperation(uint8_t opCode) {
|
||||||
// Poll for new data permanently. The call will block until the specified
|
// Poll for new UDP datagrams in permanent loop.
|
||||||
// length of bytes has been received or a timeout occured.
|
|
||||||
while(1) {
|
while(1) {
|
||||||
//! Sender Address is cached here.
|
//! Sender Address is cached here.
|
||||||
struct sockaddr_in senderAddress;
|
struct sockaddr_in senderAddress;
|
||||||
@ -49,20 +39,57 @@ ReturnValue_t TcSocketPollingTask::performOperation(uint8_t opCode) {
|
|||||||
reinterpret_cast<sockaddr*>(&senderAddress), &senderSockLen);
|
reinterpret_cast<sockaddr*>(&senderAddress), &senderSockLen);
|
||||||
if(bytesReceived < 0) {
|
if(bytesReceived < 0) {
|
||||||
// handle error
|
// handle error
|
||||||
sif::error << "TcSocketPollingTask::performOperation: recvfrom "
|
sif::error << "TcSocketPollingTask::performOperation: Reception"
|
||||||
"failed with " << strerror(errno) << std::endl;
|
"error." << std::endl;
|
||||||
|
handleReadError();
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sif::debug << "TcSocketPollingTask::performOperation: " << bytesReceived
|
// sif::debug << "TcSocketPollingTask::performOperation: " << bytesReceived
|
||||||
<< " bytes received" << std::endl;
|
// << " bytes received" << std::endl;
|
||||||
|
|
||||||
ReturnValue_t result = handleSuccessfullTcRead();
|
ReturnValue_t result = handleSuccessfullTcRead(bytesReceived);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_FAILED) {
|
||||||
|
|
||||||
|
}
|
||||||
|
tmtcBridge->registerCommConnect();
|
||||||
tmtcBridge->checkAndSetClientAddress(senderAddress);
|
tmtcBridge->checkAndSetClientAddress(senderAddress);
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TcSocketPollingTask::initialize() {
|
|
||||||
|
ReturnValue_t TcUnixUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) {
|
||||||
|
store_address_t storeId;
|
||||||
|
ReturnValue_t result = tcStore->addData(&storeId,
|
||||||
|
receptionBuffer.data(), bytesRead);
|
||||||
|
// arrayprinter::print(receptionBuffer.data(), bytesRead);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
sif::error << "TcSerialPollingTask::transferPusToSoftwareBus: Data "
|
||||||
|
"storage failed" << std::endl;
|
||||||
|
sif::error << "Packet size: " << bytesRead << std::endl;
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
TmTcMessage message(storeId);
|
||||||
|
|
||||||
|
result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
sif::error << "Serial Polling: Sending message to queue failed"
|
||||||
|
<< std::endl;
|
||||||
|
tcStore->deleteData(storeId);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t TcUnixUdpPollingTask::initialize() {
|
||||||
|
tcStore = objectManager->get<StorageManagerIF>(objects::TC_STORE);
|
||||||
|
if (tcStore == nullptr) {
|
||||||
|
sif::error << "TcSerialPollingTask::initialize: TC Store uninitialized!"
|
||||||
|
<< std::endl;
|
||||||
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
tmtcBridge = objectManager->get<TmTcUnixUdpBridge>(tmtcBridgeId);
|
tmtcBridge = objectManager->get<TmTcUnixUdpBridge>(tmtcBridgeId);
|
||||||
if(tmtcBridge == nullptr) {
|
if(tmtcBridge == nullptr) {
|
||||||
sif::error << "TcSocketPollingTask::TcSocketPollingTask: Invalid"
|
sif::error << "TcSocketPollingTask::TcSocketPollingTask: Invalid"
|
||||||
@ -71,9 +98,40 @@ ReturnValue_t TcSocketPollingTask::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
serverUdpSocket = tmtcBridge->serverSocket;
|
serverUdpSocket = tmtcBridge->serverSocket;
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TcSocketPollingTask::handleSuccessfullTcRead() {
|
ReturnValue_t TcUnixUdpPollingTask::initializeAfterTaskCreation() {
|
||||||
|
// Initialize the destination after task creation. This ensures
|
||||||
|
// that the destination will be set in the TMTC bridge.
|
||||||
|
targetTcDestination = tmtcBridge->getRequestQueue();
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TcUnixUdpPollingTask::setTimeout(double timeoutSeconds) {
|
||||||
|
timeval tval;
|
||||||
|
tval = timevalOperations::toTimeval(timeoutSeconds);
|
||||||
|
int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO,
|
||||||
|
&tval, sizeof(receptionTimeout));
|
||||||
|
if(result == -1) {
|
||||||
|
sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting "
|
||||||
|
"receive timeout failed with " << strerror(errno) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcUnixUdpPollingTask::handleReadError() {
|
||||||
|
switch(errno) {
|
||||||
|
case(EAGAIN): {
|
||||||
|
// todo: When working in timeout mode, this will occur more often
|
||||||
|
// and is not an error.
|
||||||
|
sif::error << "TcUnixUdpPollingTask::handleReadError: Timeout."
|
||||||
|
<< std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
sif::error << "TcUnixUdpPollingTask::handleReadError: "
|
||||||
|
<< strerror(errno) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#ifndef FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_
|
#ifndef FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_
|
||||||
#define FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_
|
#define FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_
|
||||||
|
|
||||||
#include <framework/objectmanager/SystemObject.h>
|
#include <framework/objectmanager/SystemObject.h>
|
||||||
#include <framework/osal/linux/TmTcUnixUdpBridge.h>
|
#include <framework/osal/linux/TmTcUnixUdpBridge.h>
|
||||||
#include <framework/tasks/ExecutableObjectIF.h>
|
#include <framework/tasks/ExecutableObjectIF.h>
|
||||||
@ -16,7 +17,7 @@
|
|||||||
* This class caches the IP address of the sender. It is assumed there
|
* This class caches the IP address of the sender. It is assumed there
|
||||||
* is only one sender for now.
|
* is only one sender for now.
|
||||||
*/
|
*/
|
||||||
class TcSocketPollingTask: public SystemObject,
|
class TcUnixUdpPollingTask: public SystemObject,
|
||||||
public ExecutableObjectIF {
|
public ExecutableObjectIF {
|
||||||
friend class TmTcUnixUdpBridge;
|
friend class TmTcUnixUdpBridge;
|
||||||
public:
|
public:
|
||||||
@ -24,17 +25,29 @@ public:
|
|||||||
//! 0.5 default milliseconds timeout for now.
|
//! 0.5 default milliseconds timeout for now.
|
||||||
static constexpr timeval DEFAULT_TIMEOUT = {.tv_sec = 0, .tv_usec = 500};
|
static constexpr timeval DEFAULT_TIMEOUT = {.tv_sec = 0, .tv_usec = 500};
|
||||||
|
|
||||||
TcSocketPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge,
|
TcUnixUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge,
|
||||||
size_t frameSize = 0, double timeoutSeconds = -1);
|
size_t frameSize = 0, double timeoutSeconds = -1);
|
||||||
virtual~ TcSocketPollingTask();
|
virtual~ TcUnixUdpPollingTask();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn on optional timeout for UDP polling. In the default mode,
|
||||||
|
* the receive function will block until a packet is received.
|
||||||
|
* @param timeoutSeconds
|
||||||
|
*/
|
||||||
|
void setTimeout(double timeoutSeconds);
|
||||||
|
|
||||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
virtual ReturnValue_t initialize() override;
|
virtual ReturnValue_t initialize() override;
|
||||||
|
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
StorageManagerIF* tcStore = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! TMTC bridge is cached.
|
//! TMTC bridge is cached.
|
||||||
object_id_t tmtcBridgeId = objects::NO_OBJECT;
|
object_id_t tmtcBridgeId = objects::NO_OBJECT;
|
||||||
TmTcUnixUdpBridge* tmtcBridge = nullptr;
|
TmTcUnixUdpBridge* tmtcBridge = nullptr;
|
||||||
|
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;
|
||||||
//! Reception flags: https://linux.die.net/man/2/recvfrom.
|
//! Reception flags: https://linux.die.net/man/2/recvfrom.
|
||||||
int receptionFlags = 0;
|
int receptionFlags = 0;
|
||||||
|
|
||||||
@ -47,8 +60,8 @@ private:
|
|||||||
size_t frameSize = 0;
|
size_t frameSize = 0;
|
||||||
timeval receptionTimeout;
|
timeval receptionTimeout;
|
||||||
|
|
||||||
ReturnValue_t handleSuccessfullTcRead();
|
ReturnValue_t handleSuccessfullTcRead(size_t bytesRead);
|
||||||
|
void handleReadError();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ */
|
#endif /* FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ */
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
#include <framework/osal/linux/TmTcUnixUdpBridge.h>
|
#include <framework/osal/linux/TmTcUnixUdpBridge.h>
|
||||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <framework/ipc/MutexHelper.h>
|
#include <framework/ipc/MutexHelper.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId,
|
TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId,
|
||||||
object_id_t ccsdsPacketDistributor, uint16_t serverPort,
|
object_id_t tcDestination, object_id_t tmStoreId, object_id_t tcStoreId,
|
||||||
uint16_t clientPort):
|
uint16_t serverPort, uint16_t clientPort):
|
||||||
TmTcBridge(objectId, ccsdsPacketDistributor) {
|
TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
|
|
||||||
uint16_t setServerPort = DEFAULT_UDP_SERVER_PORT;
|
uint16_t setServerPort = DEFAULT_UDP_SERVER_PORT;
|
||||||
@ -20,31 +22,37 @@ TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html
|
// Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html
|
||||||
serverSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
//clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if(socket < 0) {
|
if(socket < 0) {
|
||||||
sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open"
|
sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open"
|
||||||
" UDP socket!" << std::endl;
|
" UDP socket!" << std::endl;
|
||||||
// check errno here.
|
|
||||||
handleSocketError();
|
handleSocketError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
serverAddress.sin_family = AF_INET;
|
serverAddress.sin_family = AF_INET;
|
||||||
|
|
||||||
// Accept packets from any interface.
|
// Accept packets from any interface.
|
||||||
|
//serverAddress.sin_addr.s_addr = inet_addr("127.73.73.0");
|
||||||
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
serverAddress.sin_port = htons(setServerPort);
|
serverAddress.sin_port = htons(setServerPort);
|
||||||
|
serverAddressLen = sizeof(serverAddress);
|
||||||
setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &serverSocketOptions,
|
setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &serverSocketOptions,
|
||||||
sizeof(serverSocketOptions));
|
sizeof(serverSocketOptions));
|
||||||
|
|
||||||
serverSocketLen = sizeof(serverAddress);
|
clientAddress.sin_family = AF_INET;
|
||||||
|
clientAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
clientAddress.sin_port = htons(setClientPort);
|
||||||
|
clientAddressLen = sizeof(clientAddress);
|
||||||
|
|
||||||
int result = bind(serverSocket,
|
int result = bind(serverSocket,
|
||||||
reinterpret_cast<struct sockaddr*>(&serverAddress),
|
reinterpret_cast<struct sockaddr*>(&serverAddress),
|
||||||
serverSocketLen);
|
serverAddressLen);
|
||||||
if(result == -1) {
|
if(result == -1) {
|
||||||
sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not bind "
|
sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not bind "
|
||||||
"local port " << setServerPort << " to server socket!"
|
"local port " << setServerPort << " to server socket!"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
// check errno here.
|
|
||||||
handleBindError();
|
handleBindError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -55,14 +63,41 @@ TmTcUnixUdpBridge::~TmTcUnixUdpBridge() {
|
|||||||
|
|
||||||
ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
ssize_t result = send(serverSocket, data, dataLen, flags);
|
|
||||||
if(result < 0) {
|
clientAddress.sin_addr.s_addr = htons(INADDR_ANY);
|
||||||
//handle error
|
//clientAddress.sin_addr.s_addr = inet_addr("127.73.73.1");
|
||||||
sif::error << "TmTcUnixUdpBridge::sendTm: Send operation failed "
|
clientAddressLen = sizeof(serverAddress);
|
||||||
"with error " << strerror(errno) << std::endl;
|
|
||||||
|
// char ipAddress [15];
|
||||||
|
// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET,
|
||||||
|
// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
|
||||||
|
|
||||||
|
ssize_t bytesSent = sendto(serverSocket, data, dataLen, flags,
|
||||||
|
reinterpret_cast<sockaddr*>(&clientAddress), clientAddressLen);
|
||||||
|
if(bytesSent < 0) {
|
||||||
|
sif::error << "TmTcUnixUdpBridge::sendTm: Send operation failed."
|
||||||
|
<< std::endl;
|
||||||
|
handleSendError();
|
||||||
|
}
|
||||||
|
// sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were"
|
||||||
|
// " sent." << std::endl;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) {
|
||||||
|
MutexHelper lock(mutex, 10);
|
||||||
|
|
||||||
|
// char ipAddress [15];
|
||||||
|
// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET,
|
||||||
|
// &newAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
|
||||||
|
// sif::debug << "IP Address Old: " << inet_ntop(AF_INET,
|
||||||
|
// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
|
||||||
|
|
||||||
|
// Set new IP address if it has changed.
|
||||||
|
if(clientAddress.sin_addr.s_addr != newAddress.sin_addr.s_addr) {
|
||||||
|
clientAddress.sin_addr.s_addr = newAddress.sin_addr.s_addr;
|
||||||
|
clientAddressLen = sizeof(clientAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TmTcUnixUdpBridge::handleSocketError() {
|
void TmTcUnixUdpBridge::handleSocketError() {
|
||||||
@ -77,39 +112,29 @@ void TmTcUnixUdpBridge::handleSocketError() {
|
|||||||
case(ENOBUFS):
|
case(ENOBUFS):
|
||||||
case(ENOMEM):
|
case(ENOMEM):
|
||||||
case(EPROTONOSUPPORT):
|
case(EPROTONOSUPPORT):
|
||||||
sif::error << "TmTcUnixBridge::TmTcUnixBridge: Socket creation failed"
|
sif::error << "TmTcUnixBridge::handleSocketError: Socket creation failed"
|
||||||
<< " with " << strerror(errno) << std::endl;
|
<< " with " << strerror(errno) << std::endl;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sif::error << "TmTcUnixBridge::TmTcUnixBridge: Unknown error"
|
sif::error << "TmTcUnixBridge::handleSocketError: Unknown error"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TmTcUnixUdpBridge::setTimeout(float timeoutSeconds) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) {
|
|
||||||
MutexHelper lock(mutex, 10);
|
|
||||||
// Set new IP address if it has changed.
|
|
||||||
if(clientAddress.sin_addr.s_addr != newAddress.sin_addr.s_addr) {
|
|
||||||
clientAddress.sin_addr.s_addr = newAddress.sin_addr.s_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TmTcUnixUdpBridge::handleBindError() {
|
void TmTcUnixUdpBridge::handleBindError() {
|
||||||
// See: https://man7.org/linux/man-pages/man2/bind.2.html
|
// See: https://man7.org/linux/man-pages/man2/bind.2.html
|
||||||
switch(errno) {
|
switch(errno) {
|
||||||
case(EACCES):
|
case(EACCES): {
|
||||||
/*
|
/*
|
||||||
Ephermeral ports can be shown with following command:
|
Ephermeral ports can be shown with following command:
|
||||||
sysctl -A | grep ip_local_port_range
|
sysctl -A | grep ip_local_port_range
|
||||||
*/
|
*/
|
||||||
sif::error << "TmTcUnixBridge::TmTcUnixBridge: Port access issue."
|
sif::error << "TmTcUnixBridge::handleBindError: Port access issue."
|
||||||
"Ports 1-1024 are reserved on UNIX systems and require root "
|
"Ports 1-1024 are reserved on UNIX systems and require root "
|
||||||
"rights while ephermeral ports should not be used as well."
|
"rights while ephermeral ports should not be used as well."
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case(EADDRINUSE):
|
case(EADDRINUSE):
|
||||||
case(EBADF):
|
case(EBADF):
|
||||||
@ -122,19 +147,22 @@ void TmTcUnixUdpBridge::handleBindError() {
|
|||||||
case(ENOENT):
|
case(ENOENT):
|
||||||
case(ENOMEM):
|
case(ENOMEM):
|
||||||
case(ENOTDIR):
|
case(ENOTDIR):
|
||||||
case(EROFS):
|
case(EROFS): {
|
||||||
sif::error << "TmTcUnixBridge::TmTcUnixBridge: Socket creation failed"
|
sif::error << "TmTcUnixBridge::handleBindError: Socket creation failed"
|
||||||
<< " with " << strerror(errno) << std::endl;
|
<< " with " << strerror(errno) << std::endl;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
sif::error << "TmTcUnixBridge::TmTcUnixBridge: Unknown error"
|
sif::error << "TmTcUnixBridge::handleBindError: Unknown error"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TmTcUnixUdpBridge::handleSendError() {
|
||||||
ReturnValue_t TmTcUnixUdpBridge::receiveTc(uint8_t **recvBuffer, size_t *size) {
|
switch(errno) {
|
||||||
// TC reception handled by separate polling task because it is blocking.
|
default:
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
sif::error << "Error: " << strerror(errno) << std::endl;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,39 +1,40 @@
|
|||||||
#ifndef FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_
|
#ifndef FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_
|
||||||
#define FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_
|
#define FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_
|
||||||
|
|
||||||
|
#include <framework/tmtcservices/AcceptsTelecommandsIF.h>
|
||||||
#include <framework/tmtcservices/TmTcBridge.h>
|
#include <framework/tmtcservices/TmTcBridge.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/udp.h>
|
#include <netinet/udp.h>
|
||||||
|
|
||||||
class TmTcUnixUdpBridge: public TmTcBridge {
|
class TmTcUnixUdpBridge: public TmTcBridge {
|
||||||
friend class TcSocketPollingTask;
|
friend class TcUnixUdpPollingTask;
|
||||||
public:
|
public:
|
||||||
// The ports chosen here should not be used by any other process.
|
// The ports chosen here should not be used by any other process.
|
||||||
// List of used ports on Linux: /etc/services
|
// List of used ports on Linux: /etc/services
|
||||||
static constexpr uint16_t DEFAULT_UDP_SERVER_PORT = 7301;
|
static constexpr uint16_t DEFAULT_UDP_SERVER_PORT = 7301;
|
||||||
static constexpr uint16_t DEFAULT_UDP_CLIENT_PORT = 7302;
|
static constexpr uint16_t DEFAULT_UDP_CLIENT_PORT = 7302;
|
||||||
|
|
||||||
TmTcUnixUdpBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor,
|
TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
|
object_id_t tmStoreId, object_id_t tcStoreId,
|
||||||
uint16_t serverPort = 0xFFFF,uint16_t clientPort = 0xFFFF);
|
uint16_t serverPort = 0xFFFF,uint16_t clientPort = 0xFFFF);
|
||||||
virtual~ TmTcUnixUdpBridge();
|
virtual~ TmTcUnixUdpBridge();
|
||||||
|
|
||||||
void setTimeout(float timeoutSeconds);
|
|
||||||
void checkAndSetClientAddress(sockaddr_in clientAddress);
|
void checkAndSetClientAddress(sockaddr_in clientAddress);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ReturnValue_t receiveTc(uint8_t ** recvBuffer,
|
|
||||||
size_t * size) override;
|
|
||||||
virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override;
|
virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int serverSocket = 0;
|
int serverSocket = 0;
|
||||||
|
|
||||||
const int serverSocketOptions = 0;
|
const int serverSocketOptions = 0;
|
||||||
|
|
||||||
struct sockaddr_in clientAddress;
|
struct sockaddr_in clientAddress;
|
||||||
socklen_t clientSocketLen = 0;
|
socklen_t clientAddressLen = 0;
|
||||||
|
|
||||||
struct sockaddr_in serverAddress;
|
struct sockaddr_in serverAddress;
|
||||||
socklen_t serverSocketLen = 0;
|
socklen_t serverAddressLen = 0;
|
||||||
|
|
||||||
//! Access to the client address is mutex protected as it is set
|
//! Access to the client address is mutex protected as it is set
|
||||||
//! by another task.
|
//! by another task.
|
||||||
@ -41,8 +42,7 @@ private:
|
|||||||
|
|
||||||
void handleSocketError();
|
void handleSocketError();
|
||||||
void handleBindError();
|
void handleBindError();
|
||||||
|
void handleSendError();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ */
|
#endif /* FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ */
|
||||||
|
100
pus/Service1TelecommandVerification.cpp
Normal file
100
pus/Service1TelecommandVerification.cpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#include <framework/pus/Service1TelecommandVerification.h>
|
||||||
|
#include <framework/pus/servicepackets/Service1Packets.h>
|
||||||
|
|
||||||
|
#include <framework/ipc/QueueFactory.h>
|
||||||
|
#include <framework/tmtcservices/PusVerificationReport.h>
|
||||||
|
#include <framework/tmtcpacket/pus/TmPacketStored.h>
|
||||||
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
#include <framework/tmtcservices/AcceptsTelemetryIF.h>
|
||||||
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
|
||||||
|
|
||||||
|
Service1TelecommandVerification::Service1TelecommandVerification(
|
||||||
|
object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
||||||
|
object_id_t targetDestination):
|
||||||
|
SystemObject(objectId), apid(apid), serviceId(serviceId),
|
||||||
|
targetDestination(targetDestination) {
|
||||||
|
tmQueue = QueueFactory::instance()->createMessageQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
Service1TelecommandVerification::~Service1TelecommandVerification() {}
|
||||||
|
|
||||||
|
MessageQueueId_t Service1TelecommandVerification::getVerificationQueue(){
|
||||||
|
return tmQueue->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service1TelecommandVerification::performOperation(
|
||||||
|
uint8_t operationCode){
|
||||||
|
PusVerificationMessage message;
|
||||||
|
ReturnValue_t status = tmQueue->receiveMessage(&message);
|
||||||
|
while(status == HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
status = sendVerificationReport(&message);
|
||||||
|
if(status != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
status = tmQueue->receiveMessage(&message);
|
||||||
|
}
|
||||||
|
if (status == MessageQueueIF::EMPTY) {
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service1TelecommandVerification::sendVerificationReport(
|
||||||
|
PusVerificationMessage* message) {
|
||||||
|
ReturnValue_t result;
|
||||||
|
if(message->getReportId() % 2 == 0) {
|
||||||
|
result = generateFailureReport(message);
|
||||||
|
} else {
|
||||||
|
result = generateSuccessReport(message);
|
||||||
|
}
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||||
|
sif::error << "Service1TelecommandVerification::initialize: "
|
||||||
|
"Sending verification packet failed !" << std::endl;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service1TelecommandVerification::generateFailureReport(
|
||||||
|
PusVerificationMessage *message) {
|
||||||
|
FailureReport report(
|
||||||
|
message->getReportId(), message->getTcPacketId(),
|
||||||
|
message->getTcSequenceControl(), message->getStep(),
|
||||||
|
message->getErrorCode(), message->getParameter1(),
|
||||||
|
message->getParameter2());
|
||||||
|
TmPacketStored tmPacket(apid, serviceId, message->getReportId(),
|
||||||
|
packetSubCounter++, &report);
|
||||||
|
ReturnValue_t result = tmPacket.sendPacket(tmQueue->getDefaultDestination(),
|
||||||
|
tmQueue->getId());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service1TelecommandVerification::generateSuccessReport(
|
||||||
|
PusVerificationMessage *message) {
|
||||||
|
SuccessReport report(message->getReportId(),message->getTcPacketId(),
|
||||||
|
message->getTcSequenceControl(),message->getStep());
|
||||||
|
TmPacketStored tmPacket(apid, serviceId, message->getReportId(),
|
||||||
|
packetSubCounter++, &report);
|
||||||
|
ReturnValue_t result = tmPacket.sendPacket(tmQueue->getDefaultDestination(),
|
||||||
|
tmQueue->getId());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service1TelecommandVerification::initialize() {
|
||||||
|
// Get target object for TC verification messages
|
||||||
|
AcceptsTelemetryIF* funnel = objectManager->
|
||||||
|
get<AcceptsTelemetryIF>(targetDestination);
|
||||||
|
if(funnel == nullptr){
|
||||||
|
sif::error << "Service1TelecommandVerification::initialize: Specified"
|
||||||
|
" TM funnel invalid. Make sure it is set up and implements"
|
||||||
|
" AcceptsTelemetryIF." << std::endl;
|
||||||
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
|
}
|
||||||
|
tmQueue->setDefaultDestination(funnel->getReportReceptionQueue());
|
||||||
|
return SystemObject::initialize();
|
||||||
|
}
|
94
pus/Service1TelecommandVerification.h
Normal file
94
pus/Service1TelecommandVerification.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#ifndef MISSION_PUS_SERVICE1TELECOMMANDVERIFICATION_H_
|
||||||
|
#define MISSION_PUS_SERVICE1TELECOMMANDVERIFICATION_H_
|
||||||
|
|
||||||
|
#include <framework/objectmanager/SystemObject.h>
|
||||||
|
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||||
|
#include <framework/tasks/ExecutableObjectIF.h>
|
||||||
|
#include <framework/tmtcservices/AcceptsVerifyMessageIF.h>
|
||||||
|
#include <framework/tmtcservices/PusVerificationReport.h>
|
||||||
|
#include <framework/ipc/MessageQueueIF.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Verify TC acceptance, start, progress and execution.
|
||||||
|
*
|
||||||
|
* Full Documentation: ECSS-E70-41A p.51
|
||||||
|
*
|
||||||
|
* The telecommand verification service provides the capability for
|
||||||
|
* explicit verification of each distinct stage of execution of a telecommand
|
||||||
|
* packet, from on-board acceptance through to completion of execution.
|
||||||
|
*
|
||||||
|
* Minimum capabilities of this service:
|
||||||
|
*
|
||||||
|
* - TM[1,1]: Telecommand Acceptance Report - Success.
|
||||||
|
* - TM[1,2]: Telecommand Acceptance Report - Failure.
|
||||||
|
*
|
||||||
|
* Additional capabilities of this service:
|
||||||
|
*
|
||||||
|
* - TM[1,3]: Telecommand Execution Started Report - Success (Req. 4).
|
||||||
|
* - TM[1,4]: Telecommand Execution Started Report - Failure (Req. 3).
|
||||||
|
* - TM[1,5]: Telecommand Execution Progress Report - Success (Req. 6).
|
||||||
|
* - TM[1,6]: Telecommand Execution Progress Report - Failure (Req. 5).
|
||||||
|
* - TM[1,7]: Telecommand Execution Completed Report - Success (Req. 8).
|
||||||
|
* - TM[1,8]: Telecommand Execution Completed Report - Failure (Req. 7).
|
||||||
|
*
|
||||||
|
* This Service is not inherited from PUSServiceBase unlike other PUS Services
|
||||||
|
* because all services implementing PUSServiceBase use this service to
|
||||||
|
* generate verification reports.
|
||||||
|
* @ingroup pus_services
|
||||||
|
*/
|
||||||
|
class Service1TelecommandVerification: public AcceptsVerifyMessageIF,
|
||||||
|
public SystemObject,
|
||||||
|
public ExecutableObjectIF,
|
||||||
|
public HasReturnvaluesIF {
|
||||||
|
public:
|
||||||
|
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_1;
|
||||||
|
|
||||||
|
Service1TelecommandVerification(object_id_t objectId,
|
||||||
|
uint16_t apid, uint8_t serviceId, object_id_t targetDestination);
|
||||||
|
virtual ~Service1TelecommandVerification();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return ID of Verification Queue
|
||||||
|
*/
|
||||||
|
virtual MessageQueueId_t getVerificationQueue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the service periodically as specified in init_mission().
|
||||||
|
* Triggers the handlePacket function to send TC verification messages
|
||||||
|
* @param operationCode
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the destination for TC verification messages and initializes
|
||||||
|
* Service 1 as a system object
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ReturnValue_t initialize() override;
|
||||||
|
private:
|
||||||
|
uint16_t apid = 0;
|
||||||
|
uint8_t serviceId = 0;
|
||||||
|
|
||||||
|
object_id_t targetDestination = objects::NO_OBJECT;
|
||||||
|
|
||||||
|
ReturnValue_t sendVerificationReport(PusVerificationMessage* message);
|
||||||
|
ReturnValue_t generateFailureReport(PusVerificationMessage* message);
|
||||||
|
ReturnValue_t generateSuccessReport(PusVerificationMessage* message);
|
||||||
|
|
||||||
|
uint16_t packetSubCounter = 0;
|
||||||
|
|
||||||
|
MessageQueueIF* tmQueue = nullptr;
|
||||||
|
|
||||||
|
enum class Subservice: uint8_t {
|
||||||
|
VERIFY_ACCEPTANCE_SUCCESS = 1, //!< [EXPORT] : [TM]
|
||||||
|
VERIFY_ACCEPTANCE_FAILED = 2, //!< [EXPORT] : [TM]
|
||||||
|
VERIFY_START_SUCCESS = 3, //!< [EXPORT] : [TM]
|
||||||
|
VERIFY_START_FAILED = 4, //!< [EXPORT] : [TM]
|
||||||
|
VERIFY_STEP_SUCCESS = 5, //!< [EXPORT] : [TM]
|
||||||
|
VERIFY_STEP_FAILED = 6 //!< [EXPORT] : [TM]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MISSION_PUS_SERVICE1TELECOMMANDVERIFICATION_H_ */
|
167
pus/Service2DeviceAccess.cpp
Normal file
167
pus/Service2DeviceAccess.cpp
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
#include <framework/pus/Service2DeviceAccess.h>
|
||||||
|
#include <framework/pus/servicepackets/Service2Packets.h>
|
||||||
|
|
||||||
|
#include <framework/devicehandlers/DeviceHandlerIF.h>
|
||||||
|
#include <framework/storagemanager/StorageManagerIF.h>
|
||||||
|
#include <framework/devicehandlers/DeviceHandlerMessage.h>
|
||||||
|
#include <framework/serialize/EndianConverter.h>
|
||||||
|
#include <framework/action/ActionMessage.h>
|
||||||
|
#include <framework/serialize/SerializeAdapter.h>
|
||||||
|
#include <framework/serialize/SerialLinkedListAdapter.h>
|
||||||
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
|
||||||
|
Service2DeviceAccess::Service2DeviceAccess(object_id_t objectId,
|
||||||
|
uint16_t apid, uint8_t serviceId, uint8_t numberOfParallelCommands,
|
||||||
|
uint16_t commandTimeoutSeconds):
|
||||||
|
CommandingServiceBase(objectId, apid, serviceId,
|
||||||
|
numberOfParallelCommands, commandTimeoutSeconds) {}
|
||||||
|
|
||||||
|
Service2DeviceAccess::~Service2DeviceAccess() {}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::isValidSubservice(uint8_t subservice) {
|
||||||
|
switch(static_cast<Subservice>(subservice)){
|
||||||
|
case Subservice::RAW_COMMANDING:
|
||||||
|
case Subservice::TOGGLE_WIRETAPPING:
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
default:
|
||||||
|
sif::error << "Invalid Subservice" << std::endl;
|
||||||
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::getMessageQueueAndObject(
|
||||||
|
uint8_t subservice, const uint8_t* tcData, size_t tcDataLen,
|
||||||
|
MessageQueueId_t* id, object_id_t* objectId) {
|
||||||
|
if(tcDataLen < sizeof(object_id_t)) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
SerializeAdapter::deSerialize(objectId, &tcData,
|
||||||
|
&tcDataLen, SerializeIF::Endianness::BIG);
|
||||||
|
|
||||||
|
ReturnValue_t result = checkInterfaceAndAcquireMessageQueue(id,objectId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::checkInterfaceAndAcquireMessageQueue(
|
||||||
|
MessageQueueId_t * messageQueueToSet, object_id_t *objectId) {
|
||||||
|
DeviceHandlerIF* possibleTarget =
|
||||||
|
objectManager->get<DeviceHandlerIF>(*objectId);
|
||||||
|
if(possibleTarget == nullptr) {
|
||||||
|
return CommandingServiceBase::INVALID_OBJECT;
|
||||||
|
}
|
||||||
|
*messageQueueToSet = possibleTarget->getCommandQueue();
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::prepareCommand(CommandMessage* message,
|
||||||
|
uint8_t subservice, const uint8_t* tcData, size_t tcDataLen,
|
||||||
|
uint32_t* state, object_id_t objectId) {
|
||||||
|
switch(static_cast<Subservice>(subservice)){
|
||||||
|
case Subservice::RAW_COMMANDING: {
|
||||||
|
return prepareRawCommand(dynamic_cast<CommandMessage*>(message),
|
||||||
|
tcData, tcDataLen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Subservice::TOGGLE_WIRETAPPING: {
|
||||||
|
return prepareWiretappingCommand(dynamic_cast<CommandMessage*>(message),
|
||||||
|
tcData, tcDataLen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::prepareRawCommand(
|
||||||
|
CommandMessage* messageToSet, const uint8_t *tcData,size_t tcDataLen) {
|
||||||
|
RawCommand RawCommand(tcData,tcDataLen);
|
||||||
|
// store command into the Inter Process Communication Store
|
||||||
|
store_address_t storeAddress;
|
||||||
|
ReturnValue_t result = IPCStore->addData(&storeAddress,
|
||||||
|
RawCommand.getCommand(), RawCommand.getCommandSize());
|
||||||
|
DeviceHandlerMessage::setDeviceHandlerRawCommandMessage(messageToSet,
|
||||||
|
storeAddress);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::prepareWiretappingCommand(
|
||||||
|
CommandMessage *messageToSet, const uint8_t *tcData,
|
||||||
|
size_t tcDataLen) {
|
||||||
|
if(tcDataLen != WiretappingToggle::WIRETAPPING_COMMAND_SIZE) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
WiretappingToggle command;
|
||||||
|
ReturnValue_t result = command.deSerialize(&tcData, &tcDataLen,
|
||||||
|
SerializeIF::Endianness::BIG);
|
||||||
|
DeviceHandlerMessage::setDeviceHandlerWiretappingMessage(messageToSet,
|
||||||
|
command.getWiretappingMode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service2DeviceAccess::handleReply(const CommandMessage* reply,
|
||||||
|
Command_t previousCommand, uint32_t* state,
|
||||||
|
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||||
|
bool* isStep) {
|
||||||
|
switch(reply->getCommand()) {
|
||||||
|
case CommandMessage::REPLY_COMMAND_OK:
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
case CommandMessage::REPLY_REJECTED:
|
||||||
|
return reply->getReplyRejectedReason();
|
||||||
|
default:
|
||||||
|
return CommandingServiceBase::INVALID_REPLY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All device handlers set service 2 as default raw receiver for wiretapping
|
||||||
|
// so we have to handle those unrequested messages.
|
||||||
|
void Service2DeviceAccess::handleUnrequestedReply(CommandMessage* reply) {
|
||||||
|
switch(reply->getCommand()) {
|
||||||
|
case DeviceHandlerMessage::REPLY_RAW_COMMAND:
|
||||||
|
sendWiretappingTm(reply,
|
||||||
|
static_cast<uint8_t>(Subservice::WIRETAPPING_RAW_TC));
|
||||||
|
break;
|
||||||
|
case DeviceHandlerMessage::REPLY_RAW_REPLY:
|
||||||
|
sendWiretappingTm(reply,
|
||||||
|
static_cast<uint8_t>(Subservice::RAW_REPLY));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sif::error << "Unknown message in Service2DeviceAccess::"
|
||||||
|
"handleUnrequestedReply with command ID " <<
|
||||||
|
reply->getCommand() << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//Must be reached by all cases to clear message
|
||||||
|
reply->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Service2DeviceAccess::sendWiretappingTm(CommandMessage *reply,
|
||||||
|
uint8_t subservice) {
|
||||||
|
// Raw Wiretapping
|
||||||
|
// Get Address of Data from Message
|
||||||
|
store_address_t storeAddress = DeviceHandlerMessage::getStoreAddress(reply);
|
||||||
|
const uint8_t* data = nullptr;
|
||||||
|
size_t size = 0;
|
||||||
|
ReturnValue_t result = IPCStore->getData(storeAddress, &data, &size);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||||
|
sif::error << "Service2DeviceAccess::sendWiretappingTm: Data Lost in "
|
||||||
|
"handleUnrequestedReply with failure ID "<< result
|
||||||
|
<< std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init our dummy packet and correct endianness of object ID before
|
||||||
|
// sending it back.
|
||||||
|
WiretappingPacket TmPacket(DeviceHandlerMessage::getDeviceObjectId(reply),
|
||||||
|
data);
|
||||||
|
TmPacket.objectId = EndianConverter::convertBigEndian(TmPacket.objectId);
|
||||||
|
sendTmPacket(subservice, TmPacket.data,size, reinterpret_cast<uint8_t*>(
|
||||||
|
&TmPacket.objectId), sizeof(TmPacket.objectId));
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t Service2DeviceAccess::getDeviceQueue() {
|
||||||
|
return commandQueue->getId();
|
||||||
|
}
|
||||||
|
|
92
pus/Service2DeviceAccess.h
Normal file
92
pus/Service2DeviceAccess.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#ifndef FRAMEWORK_PUS_SERVICE2DEVICEACCESS_H_
|
||||||
|
#define FRAMEWORK_PUS_SERVICE2DEVICEACCESS_H_
|
||||||
|
|
||||||
|
#include <framework/objectmanager/SystemObjectIF.h>
|
||||||
|
#include <framework/devicehandlers/AcceptsDeviceResponsesIF.h>
|
||||||
|
#include <framework/tmtcservices/CommandingServiceBase.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Raw Commanding and Wiretapping of devices.
|
||||||
|
* @details
|
||||||
|
* Full Documentation: ECSS-E-ST-70-41C or ECSS-E-70-41A
|
||||||
|
* Dissertation Baetz p. 115, 116, 165-167.
|
||||||
|
*
|
||||||
|
* This service provides the capability to communicate with devices in their
|
||||||
|
* native protocols with raw commands through the DeviceHandlerIF.
|
||||||
|
*
|
||||||
|
* This is a gateway service. It relays device commands to the software bus.
|
||||||
|
* This service is very closely tied to the CommandingServiceBase
|
||||||
|
* template class.
|
||||||
|
*
|
||||||
|
* There are 4 adaption points for component implementation through the
|
||||||
|
* CommandingServiceBase.
|
||||||
|
*
|
||||||
|
* This service employs custom subservices exclusively. This includes a
|
||||||
|
* wiretapping subservice to monitor all traffic between target devices and
|
||||||
|
* this service.
|
||||||
|
*
|
||||||
|
* - TC[2,128]: Raw Commanding
|
||||||
|
* - TC[2,129]: Toggle Wiretapping
|
||||||
|
* - TM[2,130]: Wiretapping Packet TM
|
||||||
|
* - TM[2,131]: Wiretapping Packet TC
|
||||||
|
* @ingroup pus_services
|
||||||
|
*/
|
||||||
|
class Service2DeviceAccess : public CommandingServiceBase,
|
||||||
|
public AcceptsDeviceResponsesIF
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Service2DeviceAccess(object_id_t objectId, uint16_t apid,
|
||||||
|
uint8_t serviceId, uint8_t numberOfParallelCommands = 4,
|
||||||
|
uint16_t commandTimeoutSeconds = 60);
|
||||||
|
virtual ~Service2DeviceAccess();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//! CommandingServiceBase (CSB) abstract functions. See CSB documentation.
|
||||||
|
ReturnValue_t isValidSubservice(uint8_t subservice) override;
|
||||||
|
ReturnValue_t getMessageQueueAndObject(uint8_t subservice,
|
||||||
|
const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id,
|
||||||
|
object_id_t *objectId) override;
|
||||||
|
ReturnValue_t prepareCommand(CommandMessage* message, uint8_t subservice,
|
||||||
|
const uint8_t *tcData, size_t tcDataLen, uint32_t *state,
|
||||||
|
object_id_t objectId) override;
|
||||||
|
ReturnValue_t handleReply(const CommandMessage* reply,
|
||||||
|
Command_t previousCommand, uint32_t *state,
|
||||||
|
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||||
|
bool *isStep) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generates TM packets containing either the TC wiretapping
|
||||||
|
* packets or the TM wiretapping packets.
|
||||||
|
* Note that for service 2, all telemetry will be treated as an
|
||||||
|
* unrequested reply regardless of wiretapping mode.
|
||||||
|
* @param reply
|
||||||
|
*/
|
||||||
|
void handleUnrequestedReply(CommandMessage* reply) override;
|
||||||
|
|
||||||
|
MessageQueueId_t getDeviceQueue() override;
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Generates TM packets for Wiretapping Service
|
||||||
|
* @param reply
|
||||||
|
* @param subservice
|
||||||
|
*/
|
||||||
|
void sendWiretappingTm(CommandMessage* reply,uint8_t subservice);
|
||||||
|
|
||||||
|
ReturnValue_t checkInterfaceAndAcquireMessageQueue(
|
||||||
|
MessageQueueId_t* messageQueueToSet, object_id_t* objectId);
|
||||||
|
|
||||||
|
ReturnValue_t prepareRawCommand(CommandMessage* messageToSet,
|
||||||
|
const uint8_t* tcData, size_t tcDataLen);
|
||||||
|
ReturnValue_t prepareWiretappingCommand(CommandMessage* messageToSet,
|
||||||
|
const uint8_t* tcData, size_t tcDataLen);
|
||||||
|
|
||||||
|
enum class Subservice {
|
||||||
|
RAW_COMMANDING = 128, //!< [EXPORT] : [COMMAND] Command in device native protocol
|
||||||
|
TOGGLE_WIRETAPPING = 129, //!< [EXPORT] : [COMMAND] Toggle wiretapping of raw communication
|
||||||
|
RAW_REPLY = 130, //!< [EXPORT] : [REPLY] Includes wiretapping TM and normal TM raw replies from device
|
||||||
|
WIRETAPPING_RAW_TC = 131 //!< [EXPORT] : [REPLY] Wiretapping packets of commands built by device handler
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* MISSION_PUS_DEVICE2DEVICECOMMANDING_H_ */
|
92
pus/Service5EventReporting.cpp
Normal file
92
pus/Service5EventReporting.cpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#include <framework/pus/Service5EventReporting.h>
|
||||||
|
#include <framework/pus/servicepackets/Service5Packets.h>
|
||||||
|
|
||||||
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
#include <framework/events/EventManagerIF.h>
|
||||||
|
#include <framework/ipc/QueueFactory.h>
|
||||||
|
#include <framework/tmtcpacket/pus/TmPacketStored.h>
|
||||||
|
|
||||||
|
|
||||||
|
Service5EventReporting::Service5EventReporting(object_id_t objectId,
|
||||||
|
uint16_t apid, uint8_t serviceId, size_t maxNumberReportsPerCycle):
|
||||||
|
PusServiceBase(objectId, apid, serviceId),
|
||||||
|
maxNumberReportsPerCycle(maxNumberReportsPerCycle) {
|
||||||
|
eventQueue = QueueFactory::instance()->createMessageQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
Service5EventReporting::~Service5EventReporting(){}
|
||||||
|
|
||||||
|
ReturnValue_t Service5EventReporting::performService() {
|
||||||
|
EventMessage message;
|
||||||
|
ReturnValue_t status = RETURN_OK;
|
||||||
|
for(uint8_t counter = 0;
|
||||||
|
counter < maxNumberReportsPerCycle;
|
||||||
|
counter++)
|
||||||
|
{
|
||||||
|
// Receive messages even if reporting is disabled for now.
|
||||||
|
status = eventQueue->receiveMessage(&message);
|
||||||
|
if(status == MessageQueueIF::EMPTY) {
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(enableEventReport) {
|
||||||
|
status = generateEventReport(message);
|
||||||
|
if(status != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sif::debug << "Service5EventReporting::generateEventReport:"
|
||||||
|
" Too many events" << std::endl;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service5EventReporting::generateEventReport(
|
||||||
|
EventMessage message)
|
||||||
|
{
|
||||||
|
EventReport report(message.getEventId(),message.getReporter(),
|
||||||
|
message.getParameter1(),message.getParameter2());
|
||||||
|
TmPacketStored tmPacket(PusServiceBase::apid, PusServiceBase::serviceId,
|
||||||
|
message.getSeverity(), packetSubCounter++, &report);
|
||||||
|
ReturnValue_t result = tmPacket.sendPacket(
|
||||||
|
requestQueue->getDefaultDestination(),requestQueue->getId());
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
sif::debug << "Service5EventReporting::generateEventReport:"
|
||||||
|
" Could not send TM packet" << std::endl;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service5EventReporting::handleRequest(uint8_t subservice) {
|
||||||
|
switch(subservice)
|
||||||
|
{
|
||||||
|
case Subservice::ENABLE: {
|
||||||
|
enableEventReport = true;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
case Subservice::DISABLE: {
|
||||||
|
enableEventReport = false;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// In addition to the default PUSServiceBase initialization, this service needs
|
||||||
|
// to be registered to the event manager to listen for events.
|
||||||
|
ReturnValue_t Service5EventReporting::initialize() {
|
||||||
|
EventManagerIF* manager = objectManager->get<EventManagerIF>(
|
||||||
|
objects::EVENT_MANAGER);
|
||||||
|
if (manager == NULL) {
|
||||||
|
return RETURN_FAILED;
|
||||||
|
}
|
||||||
|
// register Service 5 as listener for events
|
||||||
|
ReturnValue_t result = manager->registerListener(eventQueue->getId(),true);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return PusServiceBase::initialize();
|
||||||
|
}
|
86
pus/Service5EventReporting.h
Normal file
86
pus/Service5EventReporting.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#ifndef FRAMEWORK_PUS_SERVICE5EVENTREPORTING_H_
|
||||||
|
#define FRAMEWORK_PUS_SERVICE5EVENTREPORTING_H_
|
||||||
|
|
||||||
|
#include <framework/tmtcservices/PusServiceBase.h>
|
||||||
|
#include <framework/events/EventMessage.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Report on-board events like information or errors
|
||||||
|
* @details
|
||||||
|
* Full Documentation: ECSS-E70-41A p.79
|
||||||
|
* Implements the PusServiceBase template class.
|
||||||
|
* Documentation: Dissertation Baetz p.135,136
|
||||||
|
*
|
||||||
|
* This service provides for the reporting to the service user of information of
|
||||||
|
* operational significance.
|
||||||
|
* 1. reporting of failures or anomalies detected on-board;
|
||||||
|
* 2. reporting of autonomous on-board actions;
|
||||||
|
* 3. reporting of normal progress of operations and activities, e.g.
|
||||||
|
* detection of events which are not anomalous (such as payload events),
|
||||||
|
* reaching of predefined steps in an operation. Some reports can combine
|
||||||
|
* more than one of these events.
|
||||||
|
*
|
||||||
|
* Minimum capabilities of this service:
|
||||||
|
*
|
||||||
|
* - TM[5,1]: Normal/Progress Report
|
||||||
|
* - TM[5,2]: Error/Anomaly Report - Low Severity
|
||||||
|
* - TM[5,3]: Error/Anomaly Report - Medium Severity
|
||||||
|
* - TM[5,4]: Error/Anomaly Report - High Severity
|
||||||
|
*
|
||||||
|
* Events can be translated by using translator files located in
|
||||||
|
* /config/objects/ and /config/events/. Description to events can be added by
|
||||||
|
* adding a comment behind the event definition with [//!<] as leading string
|
||||||
|
*
|
||||||
|
* Additional capabilities of this service:
|
||||||
|
*
|
||||||
|
* - TC[5,5]: Enable Event Report Generation (Req. 6)
|
||||||
|
* - TC[5,6]: Disable Event Report Generation (Req. 5)
|
||||||
|
* @author R. Mueller
|
||||||
|
* @ingroup pus_services
|
||||||
|
*/
|
||||||
|
class Service5EventReporting: public PusServiceBase {
|
||||||
|
public:
|
||||||
|
|
||||||
|
Service5EventReporting(object_id_t objectId, uint16_t apid,
|
||||||
|
uint8_t serviceId, size_t maxNumberReportsPerCycle = 10);
|
||||||
|
virtual ~Service5EventReporting();
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Check for events and generate event reports if required.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ReturnValue_t performService() override;
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Turn event generation on or off.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ReturnValue_t handleRequest(uint8_t subservice) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default PusServiceBase initialize has been overridden but is still
|
||||||
|
* executed. Registers this service as a listener for events at the
|
||||||
|
* EventManager.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
|
enum Subservice: uint8_t {
|
||||||
|
NORMAL_REPORT = 1, //!< [EXPORT] : [REPLY] Generate normal report
|
||||||
|
ERROR_LOW_SEVERITY = 2, //!< [EXPORT] : [REPLY] Generate error report with low severity
|
||||||
|
ERROR_MED_SEVERITY = 3, //!< [EXPORT] : [REPLY] Generate error report with medium severity
|
||||||
|
ERROR_HIGH_SEVERITY = 4, //!< [EXPORT] : [REPLY] Generate error report with high severity
|
||||||
|
ENABLE = 5, //!< [EXPORT] : [COMMAND] Enable report generation
|
||||||
|
DISABLE = 6 //!< [EXPORT] : [COMMAND] Disable report generation
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t packetSubCounter = 0;
|
||||||
|
MessageQueueIF* eventQueue = nullptr;
|
||||||
|
bool enableEventReport = true;
|
||||||
|
const uint8_t maxNumberReportsPerCycle;
|
||||||
|
|
||||||
|
ReturnValue_t generateEventReport(EventMessage message);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MISSION_PUS_SERVICE5EVENTREPORTING_H_ */
|
129
pus/Service8FunctionManagement.cpp
Normal file
129
pus/Service8FunctionManagement.cpp
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#include <framework/pus/Service8FunctionManagement.h>
|
||||||
|
#include <framework/pus/servicepackets/Service8Packets.h>
|
||||||
|
|
||||||
|
#include <framework/action/ActionMessage.h>
|
||||||
|
#include <framework/objectmanager/SystemObjectIF.h>
|
||||||
|
#include <framework/action/HasActionsIF.h>
|
||||||
|
#include <framework/devicehandlers/DeviceHandlerIF.h>
|
||||||
|
#include <framework/serialize/SerializeAdapter.h>
|
||||||
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
|
||||||
|
Service8FunctionManagement::Service8FunctionManagement(object_id_t object_id,
|
||||||
|
uint16_t apid, uint8_t serviceId, uint8_t numParallelCommands,
|
||||||
|
uint16_t commandTimeoutSeconds):
|
||||||
|
CommandingServiceBase(object_id, apid, serviceId, numParallelCommands,
|
||||||
|
commandTimeoutSeconds) {}
|
||||||
|
|
||||||
|
Service8FunctionManagement::~Service8FunctionManagement() {}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service8FunctionManagement::isValidSubservice(
|
||||||
|
uint8_t subservice) {
|
||||||
|
switch(static_cast<Subservice>(subservice)) {
|
||||||
|
case Subservice::DIRECT_COMMANDING:
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
default:
|
||||||
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service8FunctionManagement::getMessageQueueAndObject(
|
||||||
|
uint8_t subservice, const uint8_t* tcData, size_t tcDataLen,
|
||||||
|
MessageQueueId_t* id, object_id_t* objectId) {
|
||||||
|
if(tcDataLen < sizeof(object_id_t)) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
SerializeAdapter::deSerialize(objectId, &tcData,
|
||||||
|
&tcDataLen, SerializeIF::Endianness::BIG);
|
||||||
|
|
||||||
|
return checkInterfaceAndAcquireMessageQueue(id,objectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service8FunctionManagement::checkInterfaceAndAcquireMessageQueue(
|
||||||
|
MessageQueueId_t* messageQueueToSet, object_id_t* objectId) {
|
||||||
|
// check HasActionIF property of target
|
||||||
|
HasActionsIF* possibleTarget = objectManager->get<HasActionsIF>(*objectId);
|
||||||
|
if(possibleTarget == nullptr){
|
||||||
|
return CommandingServiceBase::INVALID_OBJECT;
|
||||||
|
}
|
||||||
|
*messageQueueToSet = possibleTarget->getCommandQueue();
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service8FunctionManagement::prepareCommand(
|
||||||
|
CommandMessage* message, uint8_t subservice, const uint8_t* tcData,
|
||||||
|
size_t tcDataLen, uint32_t* state, object_id_t objectId) {
|
||||||
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
if(subservice == static_cast<uint8_t>(Subservice::DIRECT_COMMANDING)) {
|
||||||
|
result = prepareDirectCommand(dynamic_cast<CommandMessage*>(message),
|
||||||
|
tcData, tcDataLen);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service8FunctionManagement::prepareDirectCommand(
|
||||||
|
CommandMessage *message, const uint8_t *tcData, size_t tcDataLen) {
|
||||||
|
// Create direct command instance by extracting data from Telecommand
|
||||||
|
DirectCommand command(tcData,tcDataLen);
|
||||||
|
|
||||||
|
// store additional parameters into the IPC Store
|
||||||
|
store_address_t parameterAddress;
|
||||||
|
ReturnValue_t result = IPCStore->addData(¶meterAddress,
|
||||||
|
command.getParameters(),command.getParametersSize());
|
||||||
|
|
||||||
|
// setCommand expects a Command Message, an Action ID and a store adress
|
||||||
|
// pointing to additional parameters
|
||||||
|
ActionMessage::setCommand(message,command.getActionId(),parameterAddress);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service8FunctionManagement::handleReply(
|
||||||
|
const CommandMessage* reply, Command_t previousCommand,
|
||||||
|
uint32_t* state, CommandMessage* optionalNextCommand,
|
||||||
|
object_id_t objectId, bool* isStep) {
|
||||||
|
Command_t replyId = reply->getCommand();
|
||||||
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
ActionId_t actionId = ActionMessage::getActionId(reply);
|
||||||
|
ReturnValue_t returnCode = ActionMessage::getReturnCode(reply);
|
||||||
|
|
||||||
|
switch(replyId) {
|
||||||
|
case ActionMessage::COMPLETION_SUCCESS: {
|
||||||
|
DirectReply completionReply(objectId, actionId,returnCode);
|
||||||
|
result = CommandingServiceBase::EXECUTION_COMPLETE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActionMessage::STEP_SUCCESS: {
|
||||||
|
*isStep = true;
|
||||||
|
result = HasReturnvaluesIF::RETURN_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActionMessage::DATA_REPLY: {
|
||||||
|
store_address_t storeId = ActionMessage::getStoreId(reply);
|
||||||
|
size_t size = 0;
|
||||||
|
const uint8_t * buffer = nullptr;
|
||||||
|
result = IPCStore->getData(storeId, &buffer, &size);
|
||||||
|
if(result != RETURN_OK) {
|
||||||
|
sif::error << "Service 8: Could not retrieve data for data reply";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
DataReply dataReply(objectId,actionId,buffer,size);
|
||||||
|
sendTmPacket(static_cast<uint8_t>(
|
||||||
|
Subservice::DIRECT_COMMANDING_DATA_REPLY), &dataReply);
|
||||||
|
result = IPCStore ->deleteData(storeId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActionMessage::STEP_FAILED:
|
||||||
|
*isStep = true;
|
||||||
|
/*No break, falls through*/
|
||||||
|
case ActionMessage::COMPLETION_FAILED:
|
||||||
|
result = ActionMessage::getReturnCode(reply);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = INVALID_REPLY;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
64
pus/Service8FunctionManagement.h
Normal file
64
pus/Service8FunctionManagement.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef FRAMEWORK_PUS_SERVICE8FUNCTIONMANAGEMENT_H_
|
||||||
|
#define FRAMEWORK_PUS_SERVICE8FUNCTIONMANAGEMENT_H_
|
||||||
|
|
||||||
|
#include <framework/tmtcservices/CommandingServiceBase.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Functional commanding.
|
||||||
|
* Full Documentation: ECSS-E-ST-70-41C p.64, p. 451
|
||||||
|
* Dissertation Baetz p. 115, 116, 165-167
|
||||||
|
*
|
||||||
|
* This service provides the capability to perform functions of an
|
||||||
|
* application process and provides high-level commanding as opposed to the
|
||||||
|
* Raw Access provided by Service 2. Examples for these functions can include
|
||||||
|
* control and operation of payload or the AOCS subsystem.
|
||||||
|
* This service will be the primary means to control the spacecraft as it is
|
||||||
|
* considered safer than the Raw Access provided
|
||||||
|
* by Service 2 and is generally sufficient for most tasks.
|
||||||
|
*
|
||||||
|
* This is a gateway service. It relays device commands using the software bus.
|
||||||
|
* This service is very closely tied to the Commanding Service Base template
|
||||||
|
* class. There is constant interaction between this Service Base und a
|
||||||
|
* subclass like this service.
|
||||||
|
*
|
||||||
|
* Service Capability:
|
||||||
|
* - TC[8,128]: Direct Commanding
|
||||||
|
* - TM[8,130]: Direct Commanding Data Reply
|
||||||
|
*
|
||||||
|
* @ingroup pus_services
|
||||||
|
*/
|
||||||
|
class Service8FunctionManagement : public CommandingServiceBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Service8FunctionManagement(object_id_t objectId, uint16_t apid,
|
||||||
|
uint8_t serviceId, uint8_t numParallelCommands = 4,
|
||||||
|
uint16_t commandTimeoutSeconds = 60);
|
||||||
|
virtual ~Service8FunctionManagement();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* CSB abstract functions implementation . See CSB documentation. */
|
||||||
|
ReturnValue_t isValidSubservice(uint8_t subservice) override;
|
||||||
|
ReturnValue_t getMessageQueueAndObject(uint8_t subservice,
|
||||||
|
const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id,
|
||||||
|
object_id_t *objectId) override;
|
||||||
|
ReturnValue_t prepareCommand(CommandMessage* message,
|
||||||
|
uint8_t subservice, const uint8_t *tcData, size_t tcDataLen,
|
||||||
|
uint32_t *state, object_id_t objectId) override;
|
||||||
|
ReturnValue_t handleReply(const CommandMessage* reply,
|
||||||
|
Command_t previousCommand, uint32_t *state,
|
||||||
|
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||||
|
bool *isStep) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class Subservice {
|
||||||
|
DIRECT_COMMANDING = 128, //!< [EXPORT] : [COMMAND] Functional commanding
|
||||||
|
DIRECT_COMMANDING_DATA_REPLY = 130, //!< [EXPORT] : [REPLY] Data reply
|
||||||
|
};
|
||||||
|
|
||||||
|
ReturnValue_t checkInterfaceAndAcquireMessageQueue(
|
||||||
|
MessageQueueId_t* messageQueueToSet, object_id_t* objectId);
|
||||||
|
ReturnValue_t prepareDirectCommand(CommandMessage* message,
|
||||||
|
const uint8_t* tcData, size_t tcDataLen);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FRAMEWORK_PUS_SERVICE8FUNCTIONMANAGEMENT_H_ */
|
166
pus/servicepackets/Service1Packets.h
Normal file
166
pus/servicepackets/Service1Packets.h
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/**
|
||||||
|
* @defgroup spacepackets PUS Packet Definitions
|
||||||
|
* This group contains all implemented TM or TM packages that are sent to
|
||||||
|
* or sent by the OBC.They are exported later to display
|
||||||
|
* packet structures in Mission Information Base (MIB).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MISSION_PUS_SERVICEPACKETS_SERVICE1PACKETS_H_
|
||||||
|
#define MISSION_PUS_SERVICEPACKETS_SERVICE1PACKETS_H_
|
||||||
|
|
||||||
|
#include <framework/serialize/SerializeAdapter.h>
|
||||||
|
#include <framework/tmtcservices/VerificationCodes.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief FailureReport class to serialize a failure report
|
||||||
|
* @brief Subservice 1, 3, 5, 7
|
||||||
|
* @ingroup spacepackets
|
||||||
|
*/
|
||||||
|
class FailureReport: public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 3, 5, 7
|
||||||
|
public:
|
||||||
|
FailureReport(uint8_t failureSubtype_, uint16_t packetId_,
|
||||||
|
uint16_t packetSequenceControl_, uint8_t stepNumber_,
|
||||||
|
ReturnValue_t errorCode_, uint32_t errorParameter1_,
|
||||||
|
uint32_t errorParameter2_) :
|
||||||
|
packetId(packetId_), packetSequenceControl(packetSequenceControl_),
|
||||||
|
stepNumber(stepNumber_), errorCode(errorCode_),
|
||||||
|
errorParameter1(errorParameter1_), errorParameter2(errorParameter2_),
|
||||||
|
failureSubtype(failureSubtype_) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called by the FSFW when calling the tm packet send
|
||||||
|
* function and supplying the SerializeIF* as parameter
|
||||||
|
* @param buffer Object content is serialized into the buffer
|
||||||
|
* @param size
|
||||||
|
* @param max_size
|
||||||
|
* @param bigEndian
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||||
|
size_t maxSize, SerializeIF::Endianness streamEndianness
|
||||||
|
) const override {
|
||||||
|
ReturnValue_t result = SerializeAdapter::serialize(&packetId, buffer,
|
||||||
|
size, maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = SerializeAdapter::serialize(&packetSequenceControl, buffer,
|
||||||
|
size, maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (failureSubtype == TC_VERIFY::PROGRESS_FAILURE) {
|
||||||
|
result = SerializeAdapter::serialize(&stepNumber, buffer, size,
|
||||||
|
maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = SerializeAdapter::serialize(&errorCode, buffer, size,
|
||||||
|
maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = SerializeAdapter::serialize(&errorParameter1, buffer, size,
|
||||||
|
maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = SerializeAdapter::serialize(&errorParameter2, buffer, size,
|
||||||
|
maxSize, streamEndianness);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual size_t getSerializedSize() const {
|
||||||
|
size_t size = 0;
|
||||||
|
size += SerializeAdapter::getSerializedSize(&packetId);
|
||||||
|
size += sizeof(packetSequenceControl);
|
||||||
|
if(failureSubtype==TC_VERIFY::PROGRESS_FAILURE){
|
||||||
|
size += SerializeAdapter::getSerializedSize(&stepNumber);
|
||||||
|
}
|
||||||
|
size += SerializeAdapter::getSerializedSize(&errorCode);
|
||||||
|
size += SerializeAdapter::getSerializedSize(&errorParameter1);
|
||||||
|
size += SerializeAdapter::getSerializedSize(&errorParameter2);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialization is not allowed for a report.
|
||||||
|
* @param buffer
|
||||||
|
* @param size
|
||||||
|
* @param bigEndian
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
|
SerializeIF::Endianness streamEndianness) override {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
uint16_t packetId; //!< [EXPORT] : [COMMENT] Packet ID of respective Telecommand
|
||||||
|
uint16_t packetSequenceControl; //!< [EXPORT] : [COMMENT] Packet SSC of respective Telecommand
|
||||||
|
uint8_t stepNumber; //!< [EXPORT] : [OPTIONAL][SUBSERVICE] 6
|
||||||
|
ReturnValue_t errorCode; //!< [EXPORT] : [COMMENT] Error code which can be looked up in generated error code file
|
||||||
|
uint32_t errorParameter1;
|
||||||
|
uint32_t errorParameter2;
|
||||||
|
const uint8_t failureSubtype; //!< [EXPORT] : [IGNORE]
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Subservices 2, 4, 6, 8
|
||||||
|
* @ingroup spacepackets
|
||||||
|
*/
|
||||||
|
class SuccessReport: public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 2, 4, 6, 8
|
||||||
|
public:
|
||||||
|
SuccessReport(uint8_t subtype_, uint16_t packetId_,
|
||||||
|
uint16_t packetSequenceControl_,uint8_t stepNumber_) :
|
||||||
|
packetId(packetId_), packetSequenceControl(packetSequenceControl_),
|
||||||
|
stepNumber(stepNumber_), subtype(subtype_) {}
|
||||||
|
|
||||||
|
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||||
|
size_t maxSize, SerializeIF::Endianness streamEndianness
|
||||||
|
) const override {
|
||||||
|
ReturnValue_t result = SerializeAdapter::serialize(&packetId, buffer,
|
||||||
|
size, maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = SerializeAdapter::serialize(&packetSequenceControl, buffer,
|
||||||
|
size, maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (subtype == TC_VERIFY::PROGRESS_SUCCESS) {
|
||||||
|
result = SerializeAdapter::serialize(&stepNumber, buffer, size,
|
||||||
|
maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t getSerializedSize() const override {
|
||||||
|
size_t size = 0;
|
||||||
|
size += SerializeAdapter::getSerializedSize(&packetId);
|
||||||
|
size += sizeof(packetSequenceControl);
|
||||||
|
if(subtype == TC_VERIFY::PROGRESS_SUCCESS){
|
||||||
|
size += SerializeAdapter::getSerializedSize(&stepNumber);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
|
SerializeIF::Endianness streamEndianness) override {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
uint16_t packetId; //!< [EXPORT] : [COMMENT] Packet ID of respective Telecommand
|
||||||
|
uint16_t packetSequenceControl; //!< [EXPORT] : [COMMENT] Packet SSC of respective Telecommand
|
||||||
|
uint8_t stepNumber; //!< [EXPORT] : [OPTIONAL][SUBSERVICE] 6
|
||||||
|
const uint8_t subtype; //!< [EXPORT] : [IGNORE]
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MISSION_PUS_SERVICEPACKETS_SERVICE1PACKETS_H_ */
|
76
pus/servicepackets/Service2Packets.h
Normal file
76
pus/servicepackets/Service2Packets.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_
|
||||||
|
#define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_
|
||||||
|
|
||||||
|
#include <framework/action/ActionMessage.h>
|
||||||
|
#include <framework/objectmanager/SystemObjectIF.h>
|
||||||
|
#include <framework/serialize/SerialLinkedListAdapter.h>
|
||||||
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Subservice 128
|
||||||
|
* @ingroup spacepackets
|
||||||
|
*/
|
||||||
|
class RawCommand { //!< [EXPORT] : [SUBSERVICE] 128
|
||||||
|
public:
|
||||||
|
RawCommand(const uint8_t* buffer, size_t size) {
|
||||||
|
// Deserialize Adapter to get correct endianness
|
||||||
|
SerializeAdapter::deSerialize(&objectId, &buffer, &size,
|
||||||
|
SerializeIF::Endianness::BIG);
|
||||||
|
commandBuffer = buffer;
|
||||||
|
// size is decremented by AutoSerializeAdapter,
|
||||||
|
// remaining size is data size
|
||||||
|
dataSize = size;
|
||||||
|
}
|
||||||
|
object_id_t getObjectId() const {
|
||||||
|
return objectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* getCommand() {
|
||||||
|
return commandBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getCommandSize() const {
|
||||||
|
return dataSize;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
object_id_t objectId = 0;
|
||||||
|
const uint8_t* commandBuffer = nullptr; //!< [EXPORT] : [MAXSIZE] 256 Bytes
|
||||||
|
size_t dataSize = 0; //!< [EXPORT] : [IGNORE]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Subservice 129: Command packet to set wiretapping mode
|
||||||
|
* @ingroup spacepackets
|
||||||
|
*/
|
||||||
|
class WiretappingToggle: public SerialLinkedListAdapter<SerializeIF>{ //!< [EXPORT] : [SUBSERVICE] 129
|
||||||
|
public:
|
||||||
|
static const size_t WIRETAPPING_COMMAND_SIZE = 5;
|
||||||
|
WiretappingToggle(){
|
||||||
|
setStart(&objectId);
|
||||||
|
objectId.setNext(&wiretappingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getWiretappingMode() const {
|
||||||
|
return wiretappingMode.entry;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
SerializeElement<object_id_t> objectId;
|
||||||
|
SerializeElement<uint8_t> wiretappingMode; //!< [EXPORT] : [INPUT] Mode 0: OFF, Mode 1: RAW
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Subservices 130 and 131: TM packets
|
||||||
|
* @ingroup spacepackets
|
||||||
|
*/
|
||||||
|
class WiretappingPacket { //!< [EXPORT] : [SUBSERVICE] 130, 131
|
||||||
|
public:
|
||||||
|
object_id_t objectId; //!< [EXPORT] : [COMMENT] Object ID of source object
|
||||||
|
const uint8_t* data; //!< [EXPORT] : [MAXSIZE] Raw Command Max. Size
|
||||||
|
WiretappingPacket(object_id_t objectId, const uint8_t* buffer):
|
||||||
|
objectId(objectId), data(buffer) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FRAMEWORK_PUS_SERVICEPACKETS_SERVICE2PACKETS_H_ */
|
76
pus/servicepackets/Service5Packets.h
Normal file
76
pus/servicepackets/Service5Packets.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#ifndef MISSION_PUS_SERVICEPACKETS_SERVICE5PACKETS_H_
|
||||||
|
#define MISSION_PUS_SERVICEPACKETS_SERVICE5PACKETS_H_
|
||||||
|
|
||||||
|
#include <framework/serialize/SerializeAdapter.h>
|
||||||
|
#include <framework/tmtcservices/VerificationCodes.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Subservice 1, 2, 3, 4
|
||||||
|
* Structure of Event Report.
|
||||||
|
* It consists of:
|
||||||
|
* 1. Report ID(RID). This is the Event ID in the FSFW
|
||||||
|
* 2. Object ID of the reporter (e.g. subsystem)
|
||||||
|
* 2. Parameter 1
|
||||||
|
* 3. Parameter 2
|
||||||
|
*
|
||||||
|
* @ingroup spacepackets
|
||||||
|
*/
|
||||||
|
class EventReport: public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 1, 2, 3, 4
|
||||||
|
public:
|
||||||
|
|
||||||
|
EventReport(EventId_t reportId_, object_id_t objectId_, uint32_t parameter1_,
|
||||||
|
uint32_t parameter2_):
|
||||||
|
reportId(reportId_),objectId(objectId_), parameter1(parameter1_),
|
||||||
|
parameter2(parameter2_) {}
|
||||||
|
|
||||||
|
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||||
|
size_t maxSize,
|
||||||
|
SerializeIF::Endianness streamEndianness) const override
|
||||||
|
{
|
||||||
|
ReturnValue_t result = SerializeAdapter::serialize(&reportId, buffer,
|
||||||
|
size, maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = SerializeAdapter::serialize(&objectId, buffer, size,
|
||||||
|
maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = SerializeAdapter::serialize(¶meter1, buffer, size,
|
||||||
|
maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = SerializeAdapter::serialize(¶meter2, buffer, size,
|
||||||
|
maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t getSerializedSize() const override {
|
||||||
|
uint32_t size = 0;
|
||||||
|
size += SerializeAdapter::getSerializedSize(&reportId);
|
||||||
|
size += SerializeAdapter::getSerializedSize(&objectId);
|
||||||
|
size += SerializeAdapter::getSerializedSize(¶meter1);
|
||||||
|
size += SerializeAdapter::getSerializedSize(¶meter2);
|
||||||
|
return size;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
|
SerializeIF::Endianness streamEndianness) override {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
EventId_t reportId;
|
||||||
|
object_id_t objectId;
|
||||||
|
uint32_t parameter1;
|
||||||
|
uint32_t parameter2;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* MISSION_PUS_SERVICEPACKETS_SERVICE5PACKETS_H_ */
|
136
pus/servicepackets/Service8Packets.h
Normal file
136
pus/servicepackets/Service8Packets.h
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/**
|
||||||
|
* \file Service8Packets.h
|
||||||
|
*
|
||||||
|
* \brief Structure of a Direct Command.
|
||||||
|
* Normal reply (subservice 130) consists of
|
||||||
|
* 1. Target object ID
|
||||||
|
* 2. Action ID (taget device has specified functions with action IDs)
|
||||||
|
* 3. Return Code
|
||||||
|
* 4. Optional step number for step replies
|
||||||
|
*
|
||||||
|
* Data reply (subservice 132) consists of
|
||||||
|
* 1. Target Object ID
|
||||||
|
* 2. Action ID
|
||||||
|
* 3. Data
|
||||||
|
*
|
||||||
|
* \date 01.07.2019
|
||||||
|
* \author R. Mueller
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_
|
||||||
|
#define FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_
|
||||||
|
|
||||||
|
#include <framework/action/ActionMessage.h>
|
||||||
|
#include <framework/objectmanager/SystemObjectIF.h>
|
||||||
|
#include <framework/serialize/SerialBufferAdapter.h>
|
||||||
|
#include <framework/serialize/SerializeElement.h>
|
||||||
|
#include <framework/serialize/SerialLinkedListAdapter.h>
|
||||||
|
#include <framework/serialize/SerialFixedArrayListAdapter.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Subservice 128
|
||||||
|
* \ingroup spacepackets
|
||||||
|
*/
|
||||||
|
class DirectCommand: public SerialLinkedListAdapter<SerializeIF> { //!< [EXPORT] : [SUBSERVICE] 128
|
||||||
|
public:
|
||||||
|
//typedef uint16_t typeOfMaxData;
|
||||||
|
//static const typeOfMaxData MAX_DATA = 256;
|
||||||
|
DirectCommand(const uint8_t* dataBuffer_, uint32_t size_) {
|
||||||
|
size_t size = sizeof(objectId);
|
||||||
|
SerializeAdapter::deSerialize(&objectId,&dataBuffer_,&size,
|
||||||
|
SerializeIF::Endianness::BIG);
|
||||||
|
size = sizeof(actionId);
|
||||||
|
SerializeAdapter::deSerialize(&actionId,&dataBuffer_,&size,
|
||||||
|
SerializeIF::Endianness::BIG);
|
||||||
|
parameterBuffer = dataBuffer_;
|
||||||
|
parametersSize = size_ - sizeof(objectId) - sizeof(actionId);
|
||||||
|
}
|
||||||
|
ActionId_t getActionId() const {
|
||||||
|
return actionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
object_id_t getObjectId() const {
|
||||||
|
return objectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* getParameters() {
|
||||||
|
return parameterBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getParametersSize() const {
|
||||||
|
return parametersSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DirectCommand(const DirectCommand &command);
|
||||||
|
object_id_t objectId;
|
||||||
|
ActionId_t actionId;
|
||||||
|
uint32_t parametersSize; //!< [EXPORT] : [IGNORE]
|
||||||
|
const uint8_t * parameterBuffer; //!< [EXPORT] : [MAXSIZE] 65535 Bytes
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Subservice 130
|
||||||
|
* \ingroup spacepackets
|
||||||
|
*/
|
||||||
|
class DataReply: public SerialLinkedListAdapter<SerializeIF> { //!< [EXPORT] : [SUBSERVICE] 130
|
||||||
|
public:
|
||||||
|
typedef uint16_t typeOfMaxDataSize;
|
||||||
|
static const uint16_t MAX_DATA_LENGTH = sizeof(typeOfMaxDataSize);
|
||||||
|
DataReply(object_id_t objectId_, ActionId_t actionId_,
|
||||||
|
const uint8_t * replyDataBuffer_ = NULL, uint16_t replyDataSize_ = 0):
|
||||||
|
objectId(objectId_), actionId(actionId_), replyData(replyDataBuffer_,replyDataSize_){
|
||||||
|
setLinks();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DataReply(const DataReply &reply);
|
||||||
|
void setLinks() {
|
||||||
|
setStart(&objectId);
|
||||||
|
objectId.setNext(&actionId);
|
||||||
|
actionId.setNext(&replyData);
|
||||||
|
}
|
||||||
|
SerializeElement<object_id_t> objectId;
|
||||||
|
SerializeElement<ActionId_t> actionId;
|
||||||
|
SerializeElement<SerialBufferAdapter<uint16_t>> replyData;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Subservice 132
|
||||||
|
* \ingroup spacepackets
|
||||||
|
*/
|
||||||
|
class DirectReply: public SerialLinkedListAdapter<SerializeIF> { //!< [EXPORT] : [SUBSERVICE] 132
|
||||||
|
public:
|
||||||
|
typedef uint16_t typeOfMaxDataSize;
|
||||||
|
static const uint16_t MAX_DATA_LENGTH = sizeof(typeOfMaxDataSize);
|
||||||
|
|
||||||
|
DirectReply(object_id_t objectId_, ActionId_t actionId_, ReturnValue_t returnCode_,
|
||||||
|
bool isStep_ = false, uint8_t step_ = 0):
|
||||||
|
isStep(isStep_), objectId(objectId_), actionId(actionId_),
|
||||||
|
returnCode(returnCode_),step(step_) {
|
||||||
|
setLinks();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
|
||||||
|
void setLinks() {
|
||||||
|
setStart(&objectId);
|
||||||
|
objectId.setNext(&actionId);
|
||||||
|
actionId.setNext(&returnCode);
|
||||||
|
if(isStep) {
|
||||||
|
returnCode.setNext(&step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool isDataReply; //!< [EXPORT] : [IGNORE]
|
||||||
|
bool isStep; //!< [EXPORT] : [IGNORE]
|
||||||
|
SerializeElement<object_id_t> objectId; //!< [EXPORT] : [IGNORE]
|
||||||
|
SerializeElement<ActionId_t> actionId; //!< [EXPORT] : [IGNORE]
|
||||||
|
SerializeElement<ReturnValue_t> returnCode; //!< [EXPORT] : [IGNORE]
|
||||||
|
SerializeElement<uint8_t> step; //!< [EXPORT] : [OPTIONAL] [IGNORE]
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FRAMEWORK_PUS_SERVICEPACKETS_SERVICE8PACKETS_H_ */
|
@ -64,7 +64,8 @@ enum {
|
|||||||
LOCAL_POOL_OWNER_IF, //LPIF 58
|
LOCAL_POOL_OWNER_IF, //LPIF 58
|
||||||
POOL_VARIABLE_IF, //PVA 59
|
POOL_VARIABLE_IF, //PVA 59
|
||||||
HOUSEKEEPING_MANAGER, //HKM 60
|
HOUSEKEEPING_MANAGER, //HKM 60
|
||||||
PUS_PARSER, //PUSP 61
|
DLE_ENCODER, //DLEE 61
|
||||||
|
PUS_PARSER, //PUSP 62
|
||||||
FW_CLASS_ID_COUNT //is actually count + 1 !
|
FW_CLASS_ID_COUNT //is actually count + 1 !
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -2,30 +2,37 @@
|
|||||||
#include <framework/tcdistribution/CCSDSDistributor.h>
|
#include <framework/tcdistribution/CCSDSDistributor.h>
|
||||||
#include <framework/tmtcpacket/SpacePacketBase.h>
|
#include <framework/tmtcpacket/SpacePacketBase.h>
|
||||||
|
|
||||||
CCSDSDistributor::CCSDSDistributor( uint16_t setDefaultApid, object_id_t setObjectId ) :
|
CCSDSDistributor::CCSDSDistributor(uint16_t setDefaultApid,
|
||||||
TcDistributor( setObjectId ), default_apid( setDefaultApid ), tcStore(NULL) {
|
object_id_t setObjectId):
|
||||||
|
TcDistributor(setObjectId), defaultApid( setDefaultApid ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CCSDSDistributor::~CCSDSDistributor() {
|
CCSDSDistributor::~CCSDSDistributor() {}
|
||||||
|
|
||||||
}
|
TcDistributor::TcMqMapIter CCSDSDistributor::selectDestination() {
|
||||||
|
// sif::debug << "CCSDSDistributor::selectDestination received: " <<
|
||||||
iterator_t CCSDSDistributor::selectDestination() {
|
// this->currentMessage.getStorageId().pool_index << ", " <<
|
||||||
// debug << "CCSDSDistributor::selectDestination received: " << this->currentMessage.getStorageId().pool_index << ", " << this->currentMessage.getStorageId().packet_index << std::endl;
|
// this->currentMessage.getStorageId().packet_index << std::endl;
|
||||||
const uint8_t* p_packet = NULL;
|
const uint8_t* packet = nullptr;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
//TODO check returncode?
|
ReturnValue_t result = this->tcStore->getData(currentMessage.getStorageId(),
|
||||||
this->tcStore->getData( this->currentMessage.getStorageId(), &p_packet, &size );
|
&packet, &size );
|
||||||
SpacePacketBase current_packet( p_packet );
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
// info << "CCSDSDistributor::selectDestination has packet with APID " << std::hex << current_packet.getAPID() << std::dec << std::endl;
|
sif::error << "CCSDSDistributor::selectDestination: Getting data from"
|
||||||
iterator_t position = this->queueMap.find( current_packet.getAPID() );
|
"store failed!" << std::endl;
|
||||||
|
}
|
||||||
|
SpacePacketBase currentPacket(packet);
|
||||||
|
|
||||||
|
// sif:: info << "CCSDSDistributor::selectDestination has packet with APID "
|
||||||
|
// << std::hex << currentPacket.getAPID() << std::dec << std::endl;
|
||||||
|
TcMqMapIter position = this->queueMap.find(currentPacket.getAPID());
|
||||||
if ( position != this->queueMap.end() ) {
|
if ( position != this->queueMap.end() ) {
|
||||||
return position;
|
return position;
|
||||||
} else {
|
} else {
|
||||||
//The APID was not found. Forward packet to main SW-APID anyway to create acceptance failure report.
|
//The APID was not found. Forward packet to main SW-APID anyway to
|
||||||
return this->queueMap.find( this->default_apid );
|
// create acceptance failure report.
|
||||||
|
return this->queueMap.find( this->defaultApid );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t CCSDSDistributor::getRequestQueue() {
|
MessageQueueId_t CCSDSDistributor::getRequestQueue() {
|
||||||
|
@ -1,58 +1,69 @@
|
|||||||
#ifndef CCSDSDISTRIBUTOR_H_
|
#ifndef FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_
|
||||||
#define CCSDSDISTRIBUTOR_H_
|
#define FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_
|
||||||
|
|
||||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||||
#include <framework/storagemanager/StorageManagerIF.h>
|
#include <framework/storagemanager/StorageManagerIF.h>
|
||||||
#include <framework/tcdistribution/CCSDSDistributorIF.h>
|
#include <framework/tcdistribution/CCSDSDistributorIF.h>
|
||||||
#include <framework/tcdistribution/TcDistributor.h>
|
#include <framework/tcdistribution/TcDistributor.h>
|
||||||
#include <framework/tmtcservices/AcceptsTelecommandsIF.h>
|
#include <framework/tmtcservices/AcceptsTelecommandsIF.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instantiation of the CCSDSDistributorIF.
|
* @brief An instantiation of the CCSDSDistributorIF.
|
||||||
* It receives Space Packets, and selects a destination depending on the APID of the telecommands.
|
* @details
|
||||||
|
* It receives Space Packets, and selects a destination depending on the
|
||||||
|
* APID of the telecommands.
|
||||||
* The Secondary Header (with Service/Subservice) is ignored.
|
* The Secondary Header (with Service/Subservice) is ignored.
|
||||||
* \ingroup tc_distribution
|
* @ingroup tc_distribution
|
||||||
*/
|
*/
|
||||||
class CCSDSDistributor : public TcDistributor, public CCSDSDistributorIF, public AcceptsTelecommandsIF {
|
class CCSDSDistributor : public TcDistributor,
|
||||||
protected:
|
public CCSDSDistributorIF,
|
||||||
/**
|
public AcceptsTelecommandsIF {
|
||||||
* This implementation checks if an Application with fitting APID has registered and forwards the
|
|
||||||
* packet to the according message queue.
|
|
||||||
* If the packet is not found, it returns the queue to \c default_apid, where a Acceptance Failure
|
|
||||||
* message should be generated.
|
|
||||||
* @return Iterator to map entry of found APID or iterator to default APID.
|
|
||||||
*/
|
|
||||||
iterator_t selectDestination();
|
|
||||||
/**
|
|
||||||
* The default APID, where packets with unknown APID are sent to.
|
|
||||||
*/
|
|
||||||
uint16_t default_apid;
|
|
||||||
/**
|
|
||||||
* A reference to the TC storage must be maintained, as this class handles pure Space Packets and there
|
|
||||||
* exists no SpacePacketStored class.
|
|
||||||
*/
|
|
||||||
StorageManagerIF* tcStore;
|
|
||||||
/**
|
|
||||||
* The callback here handles the generation of acceptance success/failure messages.
|
|
||||||
*/
|
|
||||||
ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus );
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* The constructor sets the default APID and calls the TcDistributor ctor with a certain object id.
|
* @brief The constructor sets the default APID and calls the
|
||||||
* \c tcStore is set in the \c initialize method.
|
* TcDistributor ctor with a certain object id.
|
||||||
* @param set_default_apid The default APID, where packets with unknown destination are sent to.
|
* @details
|
||||||
|
* @c tcStore is set in the @c initialize method.
|
||||||
|
* @param setDefaultApid The default APID, where packets with unknown
|
||||||
|
* destination are sent to.
|
||||||
*/
|
*/
|
||||||
CCSDSDistributor(uint16_t setDefaultApid, object_id_t setObjectId);
|
CCSDSDistributor(uint16_t setDefaultApid, object_id_t setObjectId);
|
||||||
/**
|
/**
|
||||||
* The destructor is empty.
|
* The destructor is empty.
|
||||||
*/
|
*/
|
||||||
~CCSDSDistributor();
|
virtual ~CCSDSDistributor();
|
||||||
MessageQueueId_t getRequestQueue();
|
|
||||||
ReturnValue_t registerApplication( uint16_t apid, MessageQueueId_t id );
|
MessageQueueId_t getRequestQueue() override;
|
||||||
ReturnValue_t registerApplication( AcceptsTelecommandsIF* application );
|
ReturnValue_t registerApplication( uint16_t apid,
|
||||||
|
MessageQueueId_t id) override;
|
||||||
|
ReturnValue_t registerApplication(
|
||||||
|
AcceptsTelecommandsIF* application) override;
|
||||||
uint16_t getIdentifier();
|
uint16_t getIdentifier();
|
||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* This implementation checks if an application with fitting APID has
|
||||||
|
* registered and forwards the packet to the according message queue.
|
||||||
|
* If the packet is not found, it returns the queue to @c defaultApid,
|
||||||
|
* where a Acceptance Failure message should be generated.
|
||||||
|
* @return Iterator to map entry of found APID or iterator to default APID.
|
||||||
|
*/
|
||||||
|
TcMqMapIter selectDestination() override;
|
||||||
|
/**
|
||||||
|
* The default APID, where packets with unknown APID are sent to.
|
||||||
|
*/
|
||||||
|
uint16_t defaultApid;
|
||||||
|
/**
|
||||||
|
* A reference to the TC storage must be maintained, as this class handles
|
||||||
|
* pure Space Packets and there exists no SpacePacketStored class.
|
||||||
|
*/
|
||||||
|
StorageManagerIF* tcStore = nullptr;
|
||||||
|
/**
|
||||||
|
* The callback here handles the generation of acceptance
|
||||||
|
* success/failure messages.
|
||||||
|
*/
|
||||||
|
ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif /* FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_ */
|
||||||
|
|
||||||
#endif /* CCSDSDISTRIBUTOR_H_ */
|
|
||||||
|
@ -12,13 +12,13 @@ PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId,
|
|||||||
|
|
||||||
PUSDistributor::~PUSDistributor() {}
|
PUSDistributor::~PUSDistributor() {}
|
||||||
|
|
||||||
iterator_t PUSDistributor::selectDestination() {
|
TcDistributor::TcMqMapIter PUSDistributor::selectDestination() {
|
||||||
// debug << "PUSDistributor::handlePacket received: " << this->current_packet_id.store_index << ", " << this->current_packet_id.packet_index << std::endl;
|
TcMqMapIter queueMapIt = this->queueMap.end();
|
||||||
iterator_t queueMapIt = this->queueMap.end();
|
|
||||||
this->currentPacket.setStoreAddress(this->currentMessage.getStorageId());
|
this->currentPacket.setStoreAddress(this->currentMessage.getStorageId());
|
||||||
if (currentPacket.getWholeData() != NULL) {
|
if (currentPacket.getWholeData() != NULL) {
|
||||||
tcStatus = checker.checkPacket(¤tPacket);
|
tcStatus = checker.checkPacket(¤tPacket);
|
||||||
// info << "PUSDistributor::handlePacket: packetCheck returned with " << (int)tc_status << std::endl;
|
// sif::debug << "PUSDistributor::handlePacket: packetCheck returned with "
|
||||||
|
// << (int)tcStatus << std::endl;
|
||||||
uint32_t queue_id = currentPacket.getService();
|
uint32_t queue_id = currentPacket.getService();
|
||||||
queueMapIt = this->queueMap.find(queue_id);
|
queueMapIt = this->queueMap.find(queue_id);
|
||||||
} else {
|
} else {
|
||||||
@ -29,8 +29,8 @@ iterator_t PUSDistributor::selectDestination() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tcStatus != RETURN_OK) {
|
if (tcStatus != RETURN_OK) {
|
||||||
sif::debug << "PUSDistributor::handlePacket: error with " << (int) tcStatus
|
sif::debug << "PUSDistributor::handlePacket: Error with " << tcStatus
|
||||||
<< ", 0x"<< std::hex << (int) tcStatus << std::endl;
|
<< ", 0x"<< std::hex << tcStatus << std::dec << std::endl;
|
||||||
return this->queueMap.end();
|
return this->queueMap.end();
|
||||||
} else {
|
} else {
|
||||||
return queueMapIt;
|
return queueMapIt;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef PUSDISTRIBUTOR_H_
|
#ifndef FRAMEWORK_TCDISTRIBUTION_PUSDISTRIBUTOR_H_
|
||||||
#define PUSDISTRIBUTOR_H_
|
#define FRAMEWORK_TCDISTRIBUTION_PUSDISTRIBUTOR_H_
|
||||||
|
|
||||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||||
#include <framework/tcdistribution/PUSDistributorIF.h>
|
#include <framework/tcdistribution/PUSDistributorIF.h>
|
||||||
@ -9,37 +9,42 @@
|
|||||||
#include <framework/tmtcservices/VerificationReporter.h>
|
#include <framework/tmtcservices/VerificationReporter.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class accepts PUS Telecommands and forwards them to Application services.
|
* This class accepts PUS Telecommands and forwards them to Application
|
||||||
* In addition, the class performs a formal packet check and sends acceptance success
|
* services. In addition, the class performs a formal packet check and
|
||||||
* or failure messages.
|
* sends acceptance success or failure messages.
|
||||||
* \ingroup tc_distribution
|
* @ingroup tc_distribution
|
||||||
*/
|
*/
|
||||||
class PUSDistributor: public TcDistributor,
|
class PUSDistributor: public TcDistributor,
|
||||||
public PUSDistributorIF,
|
public PUSDistributorIF,
|
||||||
public AcceptsTelecommandsIF {
|
public AcceptsTelecommandsIF {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* The ctor passes \c set_apid to the checker class and calls the TcDistribution ctor with a certain object id.
|
* The ctor passes @c set_apid to the checker class and calls the
|
||||||
|
* TcDistribution ctor with a certain object id.
|
||||||
* @param setApid The APID of this receiving Application.
|
* @param setApid The APID of this receiving Application.
|
||||||
* @param setObjectId Object ID of the distributor itself
|
* @param setObjectId Object ID of the distributor itself
|
||||||
* @param setPacketSource Object ID of the source of TC packets. Must implement CCSDSDistributorIF.
|
* @param setPacketSource Object ID of the source of TC packets.
|
||||||
|
* Must implement CCSDSDistributorIF.
|
||||||
*/
|
*/
|
||||||
PUSDistributor(uint16_t setApid, object_id_t setObjectId, object_id_t setPacketSource);
|
PUSDistributor(uint16_t setApid, object_id_t setObjectId,
|
||||||
|
object_id_t setPacketSource);
|
||||||
/**
|
/**
|
||||||
* The destructor is empty.
|
* The destructor is empty.
|
||||||
*/
|
*/
|
||||||
virtual ~PUSDistributor();
|
virtual ~PUSDistributor();
|
||||||
ReturnValue_t registerService(AcceptsTelecommandsIF* service);
|
ReturnValue_t registerService(AcceptsTelecommandsIF* service) override;
|
||||||
MessageQueueId_t getRequestQueue();
|
MessageQueueId_t getRequestQueue() override;
|
||||||
uint16_t getIdentifier();
|
ReturnValue_t initialize() override;
|
||||||
ReturnValue_t initialize();
|
uint16_t getIdentifier() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* This attribute contains the class, that performs a formal packet check.
|
* This attribute contains the class, that performs a formal packet check.
|
||||||
*/
|
*/
|
||||||
TcPacketCheck checker;
|
TcPacketCheck checker;
|
||||||
/**
|
/**
|
||||||
* With this class, verification messages are sent to the TC Verification service.
|
* With this class, verification messages are sent to the
|
||||||
|
* TC Verification service.
|
||||||
*/
|
*/
|
||||||
VerificationReporter verifyChannel;
|
VerificationReporter verifyChannel;
|
||||||
/**
|
/**
|
||||||
@ -47,21 +52,26 @@ protected:
|
|||||||
*/
|
*/
|
||||||
TcPacketStored currentPacket;
|
TcPacketStored currentPacket;
|
||||||
/**
|
/**
|
||||||
* With this variable, the current check status is stored to generate acceptance messages later.
|
* With this variable, the current check status is stored to generate
|
||||||
|
* acceptance messages later.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t tcStatus;
|
ReturnValue_t tcStatus;
|
||||||
|
|
||||||
const object_id_t packetSource;
|
const object_id_t packetSource;
|
||||||
/**
|
/**
|
||||||
* This method reads the packet service, checks if such a service is registered and forwards the packet to the destination.
|
* This method reads the packet service, checks if such a service is
|
||||||
* It also initiates the formal packet check and sending of verification messages.
|
* registered and forwards the packet to the destination.
|
||||||
* @return Iterator to map entry of found service id or iterator to \c map.end().
|
* It also initiates the formal packet check and sending of verification
|
||||||
|
* messages.
|
||||||
|
* @return Iterator to map entry of found service id
|
||||||
|
* or iterator to @c map.end().
|
||||||
*/
|
*/
|
||||||
iterator_t selectDestination();
|
TcMqMapIter selectDestination() override;
|
||||||
/**
|
/**
|
||||||
* The callback here handles the generation of acceptance success/failure messages.
|
* The callback here handles the generation of acceptance
|
||||||
|
* success/failure messages.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus);
|
ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PUSDISTRIBUTOR_H_ */
|
#endif /* FRAMEWORK_TCDISTRIBUTION_PUSDISTRIBUTOR_H_ */
|
||||||
|
@ -15,7 +15,6 @@ TcDistributor::~TcDistributor() {
|
|||||||
|
|
||||||
ReturnValue_t TcDistributor::performOperation(uint8_t opCode) {
|
ReturnValue_t TcDistributor::performOperation(uint8_t opCode) {
|
||||||
ReturnValue_t status = RETURN_OK;
|
ReturnValue_t status = RETURN_OK;
|
||||||
// debug << "TcDistributor: performing Operation." << std::endl;
|
|
||||||
for (status = tcQueue->receiveMessage(¤tMessage); status == RETURN_OK;
|
for (status = tcQueue->receiveMessage(¤tMessage); status == RETURN_OK;
|
||||||
status = tcQueue->receiveMessage(¤tMessage)) {
|
status = tcQueue->receiveMessage(¤tMessage)) {
|
||||||
status = handlePacket();
|
status = handlePacket();
|
||||||
@ -29,7 +28,7 @@ ReturnValue_t TcDistributor::performOperation(uint8_t opCode) {
|
|||||||
|
|
||||||
ReturnValue_t TcDistributor::handlePacket() {
|
ReturnValue_t TcDistributor::handlePacket() {
|
||||||
|
|
||||||
iterator_t queueMapIt = this->selectDestination();
|
TcMqMapIter queueMapIt = this->selectDestination();
|
||||||
ReturnValue_t returnValue = RETURN_FAILED;
|
ReturnValue_t returnValue = RETURN_FAILED;
|
||||||
if (queueMapIt != this->queueMap.end()) {
|
if (queueMapIt != this->queueMap.end()) {
|
||||||
returnValue = this->tcQueue->sendMessage(queueMapIt->second,
|
returnValue = this->tcQueue->sendMessage(queueMapIt->second,
|
||||||
@ -41,7 +40,7 @@ ReturnValue_t TcDistributor::handlePacket() {
|
|||||||
void TcDistributor::print() {
|
void TcDistributor::print() {
|
||||||
sif::debug << "Distributor content is: " << std::endl << "ID\t| message queue id"
|
sif::debug << "Distributor content is: " << std::endl << "ID\t| message queue id"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
for (iterator_t it = this->queueMap.begin(); it != this->queueMap.end();
|
for (TcMqMapIter it = this->queueMap.begin(); it != this->queueMap.end();
|
||||||
it++) {
|
it++) {
|
||||||
sif::debug << it->first << "\t| 0x" << std::hex << it->second << std::dec
|
sif::debug << it->first << "\t| 0x" << std::hex << it->second << std::dec
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#ifndef TCDISTRIBUTOR_H_
|
#ifndef FRAMEWORK_TMTCSERVICES_TCDISTRIBUTOR_H_
|
||||||
#define TCDISTRIBUTOR_H_
|
#define FRAMEWORK_TMTCSERVICES_TCDISTRIBUTOR_H_
|
||||||
|
|
||||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||||
#include <framework/objectmanager/SystemObject.h>
|
#include <framework/objectmanager/SystemObject.h>
|
||||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||||
@ -9,16 +10,12 @@
|
|||||||
#include <framework/ipc/MessageQueueIF.h>
|
#include <framework/ipc/MessageQueueIF.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \defgroup tc_distribution Telecommand Distribution
|
* @defgroup tc_distribution Telecommand Distribution
|
||||||
* All classes associated with Routing and Distribution of Telecommands belong to this group.
|
* All classes associated with Routing and Distribution of Telecommands
|
||||||
|
* belong to this group.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* This typedef simplifies writing down the \c map iterator.
|
|
||||||
*/
|
|
||||||
typedef std::map<uint32_t, MessageQueueId_t>::iterator iterator_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the base class to implement distributors for Space Packets.
|
* This is the base class to implement distributors for Space Packets.
|
||||||
@ -28,59 +25,15 @@ typedef std::map<uint32_t, MessageQueueId_t>::iterator iterator_t;
|
|||||||
* message queue ids to some identifier. The process of unpacking the
|
* message queue ids to some identifier. The process of unpacking the
|
||||||
* destination information from the packet is handled by the child class
|
* destination information from the packet is handled by the child class
|
||||||
* implementations.
|
* implementations.
|
||||||
* \ingroup tc_distribution
|
* @ingroup tc_distribution
|
||||||
*/
|
*/
|
||||||
class TcDistributor : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF {
|
class TcDistributor : public SystemObject,
|
||||||
private:
|
public ExecutableObjectIF,
|
||||||
/**
|
public HasReturnvaluesIF {
|
||||||
* This constant sets the maximum number of packets distributed per call.
|
|
||||||
*/
|
|
||||||
static const uint8_t DISTRIBUTER_MAX_PACKETS = 128;
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* This is the receiving queue for incoming Telecommands.
|
|
||||||
* The child classes must make its queue id public.
|
|
||||||
*/
|
|
||||||
MessageQueueIF* tcQueue;
|
|
||||||
/**
|
|
||||||
* The last received incoming packet information is stored in this
|
|
||||||
* member.
|
|
||||||
* As different child classes unpack the incoming packet differently
|
|
||||||
* (i.e. as a CCSDS Space Packet or as a PUS Telecommand Packet), it
|
|
||||||
* is not tried to unpack the packet information within this class.
|
|
||||||
*/
|
|
||||||
TmTcMessage currentMessage;
|
|
||||||
/**
|
|
||||||
* The map that links certain packet information to a destination.
|
|
||||||
* The packet information may be the APID of the packet or the service
|
|
||||||
* identifier. Filling of the map is under control of the different child
|
|
||||||
* classes.
|
|
||||||
*/
|
|
||||||
std::map<uint32_t, MessageQueueId_t> queueMap;
|
|
||||||
/**
|
|
||||||
* This method shall unpack the routing information from the incoming
|
|
||||||
* packet and select the map entry which represents the packet's target.
|
|
||||||
* @return An iterator to the map element to forward to or queuMap.end().
|
|
||||||
*/
|
|
||||||
virtual iterator_t selectDestination() = 0;
|
|
||||||
/**
|
|
||||||
* The handlePacket method calls the child class's selectDestination method
|
|
||||||
* and forwards the packet to its destination, if found.
|
|
||||||
* @return The message queue return value or \c RETURN_FAILED, in case no
|
|
||||||
* destination was found.
|
|
||||||
*/
|
|
||||||
ReturnValue_t handlePacket();
|
|
||||||
/**
|
|
||||||
* This method gives the child class a chance to perform some kind of operation
|
|
||||||
* after the parent tried to forward the message.
|
|
||||||
* A typically application would be sending success/failure messages.
|
|
||||||
* The default implementation just returns \c RETURN_OK.
|
|
||||||
* @param queueStatus The status of the message queue after an attempt to send the TC.
|
|
||||||
* @return - \c RETURN_OK on success
|
|
||||||
* - \c RETURN_FAILED on failure
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus );
|
|
||||||
public:
|
public:
|
||||||
|
using TcMessageQueueMap = std::map<uint32_t, MessageQueueId_t>;
|
||||||
|
using TcMqMapIter = std::map<uint32_t, MessageQueueId_t>::iterator;
|
||||||
|
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::PACKET_DISTRIBUTION;
|
static const uint8_t INTERFACE_ID = CLASS_ID::PACKET_DISTRIBUTION;
|
||||||
static const ReturnValue_t PACKET_LOST = MAKE_RETURN_CODE( 1 );
|
static const ReturnValue_t PACKET_LOST = MAKE_RETURN_CODE( 1 );
|
||||||
static const ReturnValue_t DESTINATION_NOT_FOUND = MAKE_RETURN_CODE( 2 );
|
static const ReturnValue_t DESTINATION_NOT_FOUND = MAKE_RETURN_CODE( 2 );
|
||||||
@ -110,6 +63,57 @@ public:
|
|||||||
* queueMap.
|
* queueMap.
|
||||||
*/
|
*/
|
||||||
void print();
|
void print();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* This is the receiving queue for incoming Telecommands.
|
||||||
|
* The child classes must make its queue id public.
|
||||||
|
*/
|
||||||
|
MessageQueueIF* tcQueue;
|
||||||
|
/**
|
||||||
|
* The last received incoming packet information is stored in this
|
||||||
|
* member.
|
||||||
|
* As different child classes unpack the incoming packet differently
|
||||||
|
* (i.e. as a CCSDS Space Packet or as a PUS Telecommand Packet), it
|
||||||
|
* is not tried to unpack the packet information within this class.
|
||||||
|
*/
|
||||||
|
TmTcMessage currentMessage;
|
||||||
|
/**
|
||||||
|
* The map that links certain packet information to a destination.
|
||||||
|
* The packet information may be the APID of the packet or the service
|
||||||
|
* identifier. Filling of the map is under control of the different child
|
||||||
|
* classes.
|
||||||
|
*/
|
||||||
|
TcMessageQueueMap queueMap;
|
||||||
|
/**
|
||||||
|
* This method shall unpack the routing information from the incoming
|
||||||
|
* packet and select the map entry which represents the packet's target.
|
||||||
|
* @return An iterator to the map element to forward to or queuMap.end().
|
||||||
|
*/
|
||||||
|
virtual TcMqMapIter selectDestination() = 0;
|
||||||
|
/**
|
||||||
|
* The handlePacket method calls the child class's selectDestination method
|
||||||
|
* and forwards the packet to its destination, if found.
|
||||||
|
* @return The message queue return value or \c RETURN_FAILED, in case no
|
||||||
|
* destination was found.
|
||||||
|
*/
|
||||||
|
ReturnValue_t handlePacket();
|
||||||
|
/**
|
||||||
|
* This method gives the child class a chance to perform some kind of operation
|
||||||
|
* after the parent tried to forward the message.
|
||||||
|
* A typically application would be sending success/failure messages.
|
||||||
|
* The default implementation just returns \c RETURN_OK.
|
||||||
|
* @param queueStatus The status of the message queue after an attempt to send the TC.
|
||||||
|
* @return - \c RETURN_OK on success
|
||||||
|
* - \c RETURN_FAILED on failure
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus );
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* This constant sets the maximum number of packets distributed per call.
|
||||||
|
*/
|
||||||
|
static const uint8_t DISTRIBUTER_MAX_PACKETS = 128;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef ACCEPTSTELECOMMANDSIF_H_
|
#ifndef FRAMEWORK_TMTCSERVICES_ACCEPTSTELECOMMANDSIF_H_
|
||||||
#define ACCEPTSTELECOMMANDSIF_H_
|
#define FRAMEWORK_TMTCSERVICES_ACCEPTSTELECOMMANDSIF_H_
|
||||||
|
|
||||||
#include <framework/ipc/MessageQueueSenderIF.h>
|
#include <framework/ipc/MessageQueueSenderIF.h>
|
||||||
|
|
||||||
@ -26,9 +26,9 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Getter for the service id.
|
* @brief Getter for the service id.
|
||||||
* @details Any receiving service (at least any PUS service) shall have a
|
* @details Any receiving service (at least any PUS service) shall have a
|
||||||
* service id. If the receiver can handle Telecommands, but for
|
* service ID. If the receiver can handle Telecommands, but for
|
||||||
* some reason has no service id, it shall return 0.
|
* some reason has no service id, it shall return 0.
|
||||||
* @return The service id or 0.
|
* @return The service ID or 0.
|
||||||
*/
|
*/
|
||||||
virtual uint16_t getIdentifier() = 0;
|
virtual uint16_t getIdentifier() = 0;
|
||||||
/**
|
/**
|
||||||
@ -40,4 +40,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* ACCEPTSTELECOMMANDSIF_H_ */
|
#endif /* FRAMEWORK_TMTCSERVICES_ACCEPTSTELECOMMANDSIF_H_ */
|
||||||
|
@ -8,18 +8,28 @@
|
|||||||
#include <framework/tmtcpacket/pus/TcPacketStored.h>
|
#include <framework/tmtcpacket/pus/TcPacketStored.h>
|
||||||
#include <framework/tmtcpacket/pus/TmPacketStored.h>
|
#include <framework/tmtcpacket/pus/TmPacketStored.h>
|
||||||
|
|
||||||
|
object_id_t CommandingServiceBase::packetSource = objects::NO_OBJECT;
|
||||||
|
object_id_t CommandingServiceBase::packetDestination = objects::NO_OBJECT;
|
||||||
|
|
||||||
CommandingServiceBase::CommandingServiceBase(object_id_t setObjectId,
|
CommandingServiceBase::CommandingServiceBase(object_id_t setObjectId,
|
||||||
uint16_t apid, uint8_t service, uint8_t numberOfParallelCommands,
|
uint16_t apid, uint8_t service, uint8_t numberOfParallelCommands,
|
||||||
uint16_t commandTimeoutSeconds, object_id_t setPacketSource,
|
uint16_t commandTimeoutSeconds, size_t queueDepth) :
|
||||||
object_id_t setPacketDestination, size_t queueDepth) :
|
|
||||||
SystemObject(setObjectId), apid(apid), service(service),
|
SystemObject(setObjectId), apid(apid), service(service),
|
||||||
timeoutSeconds(commandTimeoutSeconds),
|
timeoutSeconds(commandTimeoutSeconds),
|
||||||
commandMap(numberOfParallelCommands), packetSource(setPacketSource),
|
commandMap(numberOfParallelCommands) {
|
||||||
packetDestination(setPacketDestination) {
|
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
|
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
|
||||||
requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
|
requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandingServiceBase::setPacketSource(object_id_t packetSource) {
|
||||||
|
this->packetSource = packetSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandingServiceBase::setPacketDestination(
|
||||||
|
object_id_t packetDestination) {
|
||||||
|
this->packetDestination = packetDestination;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CommandingServiceBase::~CommandingServiceBase() {
|
CommandingServiceBase::~CommandingServiceBase() {
|
||||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||||
|
@ -10,11 +10,15 @@
|
|||||||
#include <framework/tmtcservices/VerificationReporter.h>
|
#include <framework/tmtcservices/VerificationReporter.h>
|
||||||
#include <framework/ipc/CommandMessage.h>
|
#include <framework/ipc/CommandMessage.h>
|
||||||
#include <framework/container/FixedMap.h>
|
#include <framework/container/FixedMap.h>
|
||||||
#include <framework/container/StaticFIFO.h>
|
#include <framework/container/FIFO.h>
|
||||||
#include <framework/serialize/SerializeIF.h>
|
#include <framework/serialize/SerializeIF.h>
|
||||||
|
|
||||||
class TcPacketStored;
|
class TcPacketStored;
|
||||||
|
|
||||||
|
namespace Factory{
|
||||||
|
void setStaticFrameworkObjectIds();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class is the basis for all PUS Services, which have to
|
* @brief This class is the basis for all PUS Services, which have to
|
||||||
* relay Telecommands to software bus.
|
* relay Telecommands to software bus.
|
||||||
@ -33,6 +37,7 @@ class CommandingServiceBase: public SystemObject,
|
|||||||
public AcceptsTelecommandsIF,
|
public AcceptsTelecommandsIF,
|
||||||
public ExecutableObjectIF,
|
public ExecutableObjectIF,
|
||||||
public HasReturnvaluesIF {
|
public HasReturnvaluesIF {
|
||||||
|
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_SERVICE_BASE;
|
static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_SERVICE_BASE;
|
||||||
static const ReturnValue_t EXECUTION_COMPLETE = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t EXECUTION_COMPLETE = MAKE_RETURN_CODE(1);
|
||||||
@ -57,10 +62,24 @@ public:
|
|||||||
*/
|
*/
|
||||||
CommandingServiceBase(object_id_t setObjectId, uint16_t apid,
|
CommandingServiceBase(object_id_t setObjectId, uint16_t apid,
|
||||||
uint8_t service, uint8_t numberOfParallelCommands,
|
uint8_t service, uint8_t numberOfParallelCommands,
|
||||||
uint16_t commandTimeoutSeconds, object_id_t setPacketSource,
|
uint16_t commandTimeoutSeconds, size_t queueDepth = 20);
|
||||||
object_id_t setPacketDestination, size_t queueDepth = 20);
|
|
||||||
virtual ~CommandingServiceBase();
|
virtual ~CommandingServiceBase();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This setter can be used to set the packet source individually instead
|
||||||
|
* of using the default static framework ID set in the factory.
|
||||||
|
* This should be called at object initialization and not during run-time!
|
||||||
|
* @param packetSource
|
||||||
|
*/
|
||||||
|
void setPacketSource(object_id_t packetSource);
|
||||||
|
/**
|
||||||
|
* This setter can be used to set the packet destination individually
|
||||||
|
* instead of using the default static framework ID set in the factory.
|
||||||
|
* This should be called at object initialization and not during run-time!
|
||||||
|
* @param packetDestination
|
||||||
|
*/
|
||||||
|
void setPacketDestination(object_id_t packetDestination);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* This is the periodically called function.
|
* This is the periodically called function.
|
||||||
* Handle request queue for external commands.
|
* Handle request queue for external commands.
|
||||||
@ -199,7 +218,7 @@ protected:
|
|||||||
uint32_t state;
|
uint32_t state;
|
||||||
Command_t command;
|
Command_t command;
|
||||||
object_id_t objectId;
|
object_id_t objectId;
|
||||||
fsfw::StaticFIFO<store_address_t, 3> fifo;
|
FIFO<store_address_t, 3> fifo;
|
||||||
};
|
};
|
||||||
|
|
||||||
using CommandMapIter = FixedMap<MessageQueueId_t,
|
using CommandMapIter = FixedMap<MessageQueueId_t,
|
||||||
@ -229,9 +248,8 @@ protected:
|
|||||||
uint32_t failureParameter1 = 0;
|
uint32_t failureParameter1 = 0;
|
||||||
uint32_t failureParameter2 = 0;
|
uint32_t failureParameter2 = 0;
|
||||||
|
|
||||||
object_id_t packetSource;
|
static object_id_t packetSource;
|
||||||
|
static object_id_t packetDestination;
|
||||||
object_id_t packetDestination;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to the task which executes this component,
|
* Pointer to the task which executes this component,
|
||||||
|
@ -64,7 +64,7 @@ ReturnValue_t PusParser::readMultiplePackets(const uint8_t *frame,
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsfw::FIFO<PusParser::indexSizePair>* PusParser::fifo(){
|
DynamicFIFO<PusParser::indexSizePair>* PusParser::fifo(){
|
||||||
return &indexSizePairFIFO;
|
return &indexSizePairFIFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
#ifndef FRAMEWORK_TMTCSERVICES_PUSPARSER_H_
|
#ifndef FRAMEWORK_TMTCSERVICES_PUSPARSER_H_
|
||||||
#define FRAMEWORK_TMTCSERVICES_PUSPARSER_H_
|
#define FRAMEWORK_TMTCSERVICES_PUSPARSER_H_
|
||||||
|
|
||||||
#include <framework/container/FIFO.h>
|
#include <framework/container/DynamicFIFO.h>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@ -55,7 +54,7 @@ public:
|
|||||||
* by the parsePusPackets() function.
|
* by the parsePusPackets() function.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fsfw::FIFO<indexSizePair>* fifo();
|
DynamicFIFO<indexSizePair>* fifo();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the next index and packet size pair from the FIFO.
|
* Retrieve the next index and packet size pair from the FIFO.
|
||||||
@ -69,7 +68,7 @@ private:
|
|||||||
//! A FIFO is used to store information about multiple PUS packets
|
//! A FIFO is used to store information about multiple PUS packets
|
||||||
//! inside the receive buffer. The maximum number of entries is defined
|
//! inside the receive buffer. The maximum number of entries is defined
|
||||||
//! by the first constructor argument.
|
//! by the first constructor argument.
|
||||||
fsfw::FIFO<indexSizePair> indexSizePairFIFO;
|
DynamicFIFO<indexSizePair> indexSizePairFIFO;
|
||||||
|
|
||||||
bool storeSplitPackets = false;
|
bool storeSplitPackets = false;
|
||||||
|
|
||||||
|
@ -41,9 +41,14 @@ void PusServiceBase::handleRequestQueue() {
|
|||||||
ReturnValue_t result = RETURN_FAILED;
|
ReturnValue_t result = RETURN_FAILED;
|
||||||
for (uint8_t count = 0; count < PUS_SERVICE_MAX_RECEPTION; count++) {
|
for (uint8_t count = 0; count < PUS_SERVICE_MAX_RECEPTION; count++) {
|
||||||
ReturnValue_t status = this->requestQueue->receiveMessage(&message);
|
ReturnValue_t status = this->requestQueue->receiveMessage(&message);
|
||||||
// debug << "PusServiceBase::performOperation: Receiving from MQ ID: "
|
// if(status != MessageQueueIF::EMPTY) {
|
||||||
// << std::hex << this->requestQueue.getId()
|
// sif::debug << "PusServiceBase::performOperation: Receiving from "
|
||||||
// << std::dec << " returned: " << status << std::endl;
|
// << "MQ ID: " << std::hex << "0x" << std::setw(8)
|
||||||
|
// << std::setfill('0') << this->requestQueue->getId()
|
||||||
|
// << std::dec << " returned: " << status << std::setfill(' ')
|
||||||
|
// << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
if (status == RETURN_OK) {
|
if (status == RETURN_OK) {
|
||||||
this->currentPacket.setStoreAddress(message.getStorageId());
|
this->currentPacket.setStoreAddress(message.getStorageId());
|
||||||
//info << "Service " << (uint16_t) this->serviceId <<
|
//info << "Service " << (uint16_t) this->serviceId <<
|
||||||
@ -74,9 +79,8 @@ void PusServiceBase::handleRequestQueue() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sif::error << "PusServiceBase::performOperation: Service "
|
sif::error << "PusServiceBase::performOperation: Service "
|
||||||
<< (uint16_t) this->serviceId
|
<< this->serviceId << ": Error receiving packet. Code: "
|
||||||
<< ": Error receiving packet. Code: " << std::hex << status
|
<< std::hex << status << std::dec << std::endl;
|
||||||
<< std::dec << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,19 +102,17 @@ ReturnValue_t PusServiceBase::initialize() {
|
|||||||
packetDestination);
|
packetDestination);
|
||||||
PUSDistributorIF* distributor = objectManager->get<PUSDistributorIF>(
|
PUSDistributorIF* distributor = objectManager->get<PUSDistributorIF>(
|
||||||
packetSource);
|
packetSource);
|
||||||
if ((destService != nullptr) && (distributor != nullptr)) {
|
if (destService == nullptr or distributor == nullptr) {
|
||||||
|
sif::error << "PusServiceBase::PusServiceBase: Service "
|
||||||
|
<< this->serviceId << ": Configuration error. Make sure "
|
||||||
|
<< "packetSource and packetDestination are defined correctly"
|
||||||
|
<< std::endl;
|
||||||
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
|
}
|
||||||
this->requestQueue->setDefaultDestination(
|
this->requestQueue->setDefaultDestination(
|
||||||
destService->getReportReceptionQueue());
|
destService->getReportReceptionQueue());
|
||||||
distributor->registerService(this);
|
distributor->registerService(this);
|
||||||
return RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
|
||||||
else {
|
|
||||||
sif::error << "PusServiceBase::PusServiceBase: Service "
|
|
||||||
<< (uint32_t) this->serviceId << ": Configuration error."
|
|
||||||
<< " Make sure packetSource and packetDestination are defined "
|
|
||||||
"correctly" << std::endl;
|
|
||||||
return RETURN_FAILED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PusServiceBase::initializeAfterTaskCreation() {
|
ReturnValue_t PusServiceBase::initializeAfterTaskCreation() {
|
||||||
|
@ -5,11 +5,13 @@
|
|||||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
#include <framework/globalfunctions/arrayprinter.h>
|
#include <framework/globalfunctions/arrayprinter.h>
|
||||||
|
|
||||||
TmTcBridge::TmTcBridge(object_id_t objectId,
|
TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
object_id_t ccsdsPacketDistributor): SystemObject(objectId),
|
object_id_t tmStoreId, object_id_t tcStoreId):
|
||||||
ccsdsPacketDistributor(ccsdsPacketDistributor)
|
SystemObject(objectId),tmStoreId(tmStoreId), tcStoreId(tcStoreId),
|
||||||
|
tcDestination(tcDestination)
|
||||||
|
|
||||||
{
|
{
|
||||||
TmTcReceptionQueue = QueueFactory::instance()->
|
tmTcReceptionQueue = QueueFactory::instance()->
|
||||||
createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH);
|
createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,20 +44,27 @@ ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TmTcBridge::initialize() {
|
ReturnValue_t TmTcBridge::initialize() {
|
||||||
tcStore = objectManager->get<StorageManagerIF>(objects::TC_STORE);
|
tcStore = objectManager->get<StorageManagerIF>(tcStoreId);
|
||||||
if (tcStore == NULL) {
|
if (tcStore == nullptr) {
|
||||||
return RETURN_FAILED;
|
sif::error << "TmTcBridge::initialize: TC store invalid. Make sure"
|
||||||
|
"it is created and set up properly." << std::endl;
|
||||||
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
}
|
}
|
||||||
tmStore = objectManager->get<StorageManagerIF>(objects::TM_STORE);
|
tmStore = objectManager->get<StorageManagerIF>(tmStoreId);
|
||||||
if (tmStore == NULL) {
|
if (tmStore == nullptr) {
|
||||||
return RETURN_FAILED;
|
sif::error << "TmTcBridge::initialize: TM store invalid. Make sure"
|
||||||
|
"it is created and set up properly." << std::endl;
|
||||||
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
}
|
}
|
||||||
AcceptsTelecommandsIF* tcDistributor =
|
AcceptsTelecommandsIF* tcDistributor =
|
||||||
objectManager->get<AcceptsTelecommandsIF>(ccsdsPacketDistributor);
|
objectManager->get<AcceptsTelecommandsIF>(tcDestination);
|
||||||
if (tcDistributor == NULL) {
|
if (tcDistributor == nullptr) {
|
||||||
return RETURN_FAILED;
|
sif::error << "TmTcBridge::initialize: TC Distributor invalid"
|
||||||
|
<< std::endl;
|
||||||
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
}
|
}
|
||||||
TmTcReceptionQueue->setDefaultDestination(tcDistributor->getRequestQueue());
|
|
||||||
|
tmTcReceptionQueue->setDefaultDestination(tcDistributor->getRequestQueue());
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,10 +82,7 @@ ReturnValue_t TmTcBridge::performOperation(uint8_t operationCode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TmTcBridge::handleTc() {
|
ReturnValue_t TmTcBridge::handleTc() {
|
||||||
uint8_t * recvBuffer = nullptr;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
size_t recvLen = 0;
|
|
||||||
ReturnValue_t result = receiveTc(&recvBuffer, &recvLen);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TmTcBridge::handleTm() {
|
ReturnValue_t TmTcBridge::handleTm() {
|
||||||
@ -97,8 +103,8 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
|
|||||||
TmTcMessage message;
|
TmTcMessage message;
|
||||||
const uint8_t* data = nullptr;
|
const uint8_t* data = nullptr;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
for (ReturnValue_t result = TmTcReceptionQueue->receiveMessage(&message);
|
for (ReturnValue_t result = tmTcReceptionQueue->receiveMessage(&message);
|
||||||
result == RETURN_OK; result = TmTcReceptionQueue->receiveMessage(&message))
|
result == RETURN_OK; result = tmTcReceptionQueue->receiveMessage(&message))
|
||||||
{
|
{
|
||||||
if(communicationLinkUp == false) {
|
if(communicationLinkUp == false) {
|
||||||
result = storeDownlinkData(&message);
|
result = storeDownlinkData(&message);
|
||||||
@ -183,10 +189,20 @@ void TmTcBridge::registerCommDisconnect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t TmTcBridge::getReportReceptionQueue(uint8_t virtualChannel) {
|
MessageQueueId_t TmTcBridge::getReportReceptionQueue(uint8_t virtualChannel) {
|
||||||
return TmTcReceptionQueue->getId();
|
return tmTcReceptionQueue->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TmTcBridge::printData(uint8_t * data, size_t dataLen) {
|
void TmTcBridge::printData(uint8_t * data, size_t dataLen) {
|
||||||
arrayprinter::print(data, dataLen);
|
arrayprinter::print(data, dataLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t TmTcBridge::getIdentifier() {
|
||||||
|
// This is no PUS service, so we just return 0
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t TmTcBridge::getRequestQueue() {
|
||||||
|
// Default implementation: Relay TC messages to TC distributor directly.
|
||||||
|
return tmTcReceptionQueue->getDefaultDestination();
|
||||||
|
}
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
#ifndef FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_
|
#ifndef FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_
|
||||||
#define FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_
|
#define FRAMEWORK_TMTCSERVICES_TMTCBRIDGE_H_
|
||||||
|
|
||||||
|
#include <framework/objectmanager/SystemObject.h>
|
||||||
#include <framework/tmtcservices/AcceptsTelemetryIF.h>
|
#include <framework/tmtcservices/AcceptsTelemetryIF.h>
|
||||||
#include <framework/tasks/ExecutableObjectIF.h>
|
#include <framework/tasks/ExecutableObjectIF.h>
|
||||||
#include <framework/ipc/MessageQueueIF.h>
|
#include <framework/ipc/MessageQueueIF.h>
|
||||||
#include <framework/storagemanager/StorageManagerIF.h>
|
#include <framework/storagemanager/StorageManagerIF.h>
|
||||||
#include <framework/objectmanager/SystemObject.h>
|
#include <framework/tmtcservices/AcceptsTelecommandsIF.h>
|
||||||
|
|
||||||
|
#include <framework/container/FIFO.h>
|
||||||
#include <framework/tmtcservices/TmTcMessage.h>
|
#include <framework/tmtcservices/TmTcMessage.h>
|
||||||
#include <framework/container/StaticFIFO.h>
|
|
||||||
|
|
||||||
class TmTcBridge : public AcceptsTelemetryIF,
|
class TmTcBridge : public AcceptsTelemetryIF,
|
||||||
|
public AcceptsTelecommandsIF,
|
||||||
public ExecutableObjectIF,
|
public ExecutableObjectIF,
|
||||||
public HasReturnvaluesIF,
|
public HasReturnvaluesIF,
|
||||||
public SystemObject {
|
public SystemObject {
|
||||||
@ -22,7 +24,8 @@ public:
|
|||||||
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
|
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
|
||||||
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
|
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
|
||||||
|
|
||||||
TmTcBridge(object_id_t objectId, object_id_t ccsdsPacketDistributor);
|
TmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
|
object_id_t tmStoreId, object_id_t tcStoreId);
|
||||||
virtual ~TmTcBridge();
|
virtual ~TmTcBridge();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,45 +60,41 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||||
|
|
||||||
/**
|
|
||||||
* Return TMTC Reception Queue
|
/** AcceptsTelemetryIF override */
|
||||||
* @param virtualChannel
|
virtual MessageQueueId_t getReportReceptionQueue(
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
MessageQueueId_t getReportReceptionQueue(
|
|
||||||
uint8_t virtualChannel = 0) override;
|
uint8_t virtualChannel = 0) override;
|
||||||
|
|
||||||
|
/** AcceptsTelecommandsIF override */
|
||||||
|
virtual uint16_t getIdentifier() override;
|
||||||
|
virtual MessageQueueId_t getRequestQueue() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
//! Cached for initialize function.
|
||||||
|
object_id_t tmStoreId = objects::NO_OBJECT;
|
||||||
|
object_id_t tcStoreId = objects::NO_OBJECT;
|
||||||
|
object_id_t tcDestination = objects::NO_OBJECT;
|
||||||
|
|
||||||
//! Used to send and receive TMTC messages.
|
//! Used to send and receive TMTC messages.
|
||||||
//! TmTcMessage is used to transport messages between tasks.
|
//! TmTcMessage is used to transport messages between tasks.
|
||||||
MessageQueueIF* TmTcReceptionQueue = nullptr;
|
MessageQueueIF* tmTcReceptionQueue = nullptr;
|
||||||
StorageManagerIF* tcStore = nullptr;
|
|
||||||
StorageManagerIF* tmStore = nullptr;
|
StorageManagerIF* tmStore = nullptr;
|
||||||
object_id_t ccsdsPacketDistributor = 0;
|
StorageManagerIF* tcStore = nullptr;
|
||||||
//! Used to specify whether communication link is up
|
|
||||||
bool communicationLinkUp = false;
|
//! Used to specify whether communication link is up by default.
|
||||||
|
bool communicationLinkUp = true;
|
||||||
bool tmStored = false;
|
bool tmStored = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handle TC reception
|
* @brief Handle TC reception
|
||||||
* @details
|
* @details
|
||||||
* Default implementation provided, but is empty.
|
* Default implementation provided, but is empty.
|
||||||
* Child handler should override this in most cases orsend TC to the
|
* In most cases, TC reception will be handled in a separate task anyway.
|
||||||
* TC distributor directly with the address of the reception queue by
|
|
||||||
* calling getReportRecptionQueue()
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t handleTc();
|
virtual ReturnValue_t handleTc();
|
||||||
|
|
||||||
/**
|
|
||||||
* Implemented by child class. Perform receiving of Telecommand,
|
|
||||||
* for example by implementing specific drivers or wrappers,
|
|
||||||
* e.g. UART Communication or an ethernet stack
|
|
||||||
* @param recvBuffer [out] Received data
|
|
||||||
* @param size [out] Size of received data
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t receiveTc(uint8_t ** recvBuffer, size_t * size) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle Telemetry. Default implementation provided.
|
* Handle Telemetry. Default implementation provided.
|
||||||
* Calls sendTm()
|
* Calls sendTm()
|
||||||
@ -143,7 +142,7 @@ protected:
|
|||||||
* This fifo can be used to store downlink data
|
* This fifo can be used to store downlink data
|
||||||
* which can not be sent at the moment.
|
* which can not be sent at the moment.
|
||||||
*/
|
*/
|
||||||
fsfw::StaticFIFO<store_address_t, LIMIT_DOWNLINK_PACKETS_STORED> tmFifo;
|
FIFO<store_address_t, LIMIT_DOWNLINK_PACKETS_STORED> tmFifo;
|
||||||
uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
|
uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
|
||||||
uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
|
uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
|
||||||
};
|
};
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
|
||||||
#include <framework/tmtcservices/AcceptsVerifyMessageIF.h>
|
|
||||||
#include <framework/tmtcservices/PusVerificationReport.h>
|
|
||||||
#include <framework/tmtcservices/VerificationReporter.h>
|
#include <framework/tmtcservices/VerificationReporter.h>
|
||||||
|
|
||||||
object_id_t VerificationReporter::messageReceiver = 0;
|
#include <framework/ipc/MessageQueueIF.h>
|
||||||
|
#include <framework/tmtcservices/AcceptsVerifyMessageIF.h>
|
||||||
|
#include <framework/tmtcservices/PusVerificationReport.h>
|
||||||
|
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
#include <framework/objectmanager/frameworkObjects.h>
|
||||||
|
|
||||||
|
object_id_t VerificationReporter::messageReceiver = objects::PUS_SERVICE_1;
|
||||||
|
|
||||||
VerificationReporter::VerificationReporter() :
|
VerificationReporter::VerificationReporter() :
|
||||||
acknowledgeQueue() {
|
acknowledgeQueue(MessageQueueIF::NO_QUEUE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
VerificationReporter::~VerificationReporter() {
|
VerificationReporter::~VerificationReporter() {}
|
||||||
//Default, empty
|
|
||||||
}
|
|
||||||
|
|
||||||
void VerificationReporter::sendSuccessReport(uint8_t set_report_id,
|
void VerificationReporter::sendSuccessReport(uint8_t set_report_id,
|
||||||
TcPacketBase* current_packet, uint8_t set_step) {
|
TcPacketBase* current_packet, uint8_t set_step) {
|
||||||
if (this->acknowledgeQueue == 0) {
|
if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) {
|
||||||
this->initialize();
|
this->initialize();
|
||||||
}
|
}
|
||||||
PusVerificationMessage message(set_report_id,
|
PusVerificationMessage message(set_report_id,
|
||||||
@ -26,14 +27,15 @@ void VerificationReporter::sendSuccessReport(uint8_t set_report_id,
|
|||||||
&message);
|
&message);
|
||||||
if (status != HasReturnvaluesIF::RETURN_OK) {
|
if (status != HasReturnvaluesIF::RETURN_OK) {
|
||||||
sif::error << "VerificationReporter::sendSuccessReport: Error writing "
|
sif::error << "VerificationReporter::sendSuccessReport: Error writing "
|
||||||
"to queue. Code: " << std::hex << (uint16_t) status << std::endl;
|
<< "to queue. Code: " << std::hex << status << std::dec
|
||||||
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerificationReporter::sendSuccessReport(uint8_t set_report_id,
|
void VerificationReporter::sendSuccessReport(uint8_t set_report_id,
|
||||||
uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl,
|
uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl,
|
||||||
uint8_t set_step) {
|
uint8_t set_step) {
|
||||||
if (this->acknowledgeQueue == 0) {
|
if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) {
|
||||||
this->initialize();
|
this->initialize();
|
||||||
}
|
}
|
||||||
PusVerificationMessage message(set_report_id, ackFlags, tcPacketId,
|
PusVerificationMessage message(set_report_id, ackFlags, tcPacketId,
|
||||||
@ -42,14 +44,15 @@ void VerificationReporter::sendSuccessReport(uint8_t set_report_id,
|
|||||||
&message);
|
&message);
|
||||||
if (status != HasReturnvaluesIF::RETURN_OK) {
|
if (status != HasReturnvaluesIF::RETURN_OK) {
|
||||||
sif::error << "VerificationReporter::sendSuccessReport: Error writing "
|
sif::error << "VerificationReporter::sendSuccessReport: Error writing "
|
||||||
"to queue. Code: " << std::hex << (uint16_t) status << std::endl;
|
<< "to queue. Code: " << std::hex << status << std::dec
|
||||||
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerificationReporter::sendFailureReport(uint8_t report_id,
|
void VerificationReporter::sendFailureReport(uint8_t report_id,
|
||||||
TcPacketBase* current_packet, ReturnValue_t error_code, uint8_t step,
|
TcPacketBase* current_packet, ReturnValue_t error_code, uint8_t step,
|
||||||
uint32_t parameter1, uint32_t parameter2) {
|
uint32_t parameter1, uint32_t parameter2) {
|
||||||
if (this->acknowledgeQueue == 0) {
|
if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) {
|
||||||
this->initialize();
|
this->initialize();
|
||||||
}
|
}
|
||||||
PusVerificationMessage message(report_id,
|
PusVerificationMessage message(report_id,
|
||||||
@ -60,9 +63,9 @@ void VerificationReporter::sendFailureReport(uint8_t report_id,
|
|||||||
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue,
|
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue,
|
||||||
&message);
|
&message);
|
||||||
if (status != HasReturnvaluesIF::RETURN_OK) {
|
if (status != HasReturnvaluesIF::RETURN_OK) {
|
||||||
sif::error
|
sif::error << "VerificationReporter::sendFailureReport Error writing "
|
||||||
<< "VerificationReporter::sendFailureReport Error writing to queue. Code: "
|
<< "to queue. Code: " << std::hex << status << std::dec
|
||||||
<< (uint16_t) status << std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +73,7 @@ void VerificationReporter::sendFailureReport(uint8_t report_id,
|
|||||||
uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl,
|
uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl,
|
||||||
ReturnValue_t error_code, uint8_t step, uint32_t parameter1,
|
ReturnValue_t error_code, uint8_t step, uint32_t parameter1,
|
||||||
uint32_t parameter2) {
|
uint32_t parameter2) {
|
||||||
if (this->acknowledgeQueue == 0) {
|
if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) {
|
||||||
this->initialize();
|
this->initialize();
|
||||||
}
|
}
|
||||||
PusVerificationMessage message(report_id, ackFlags, tcPacketId,
|
PusVerificationMessage message(report_id, ackFlags, tcPacketId,
|
||||||
@ -78,20 +81,25 @@ void VerificationReporter::sendFailureReport(uint8_t report_id,
|
|||||||
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue,
|
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue,
|
||||||
&message);
|
&message);
|
||||||
if (status != HasReturnvaluesIF::RETURN_OK) {
|
if (status != HasReturnvaluesIF::RETURN_OK) {
|
||||||
sif::error
|
sif::error << "VerificationReporter::sendFailureReport Error writing "
|
||||||
<< "VerificationReporter::sendFailureReport Error writing to queue. Code: "
|
<< "to queue. Code: " << std::hex << status << std::dec
|
||||||
<< (uint16_t) status << std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerificationReporter::initialize() {
|
void VerificationReporter::initialize() {
|
||||||
|
if(messageReceiver == objects::NO_OBJECT) {
|
||||||
|
sif::warning << "VerificationReporter::initialize: Verification message"
|
||||||
|
" receiver object ID not set yet in Factory!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
AcceptsVerifyMessageIF* temp = objectManager->get<AcceptsVerifyMessageIF>(
|
AcceptsVerifyMessageIF* temp = objectManager->get<AcceptsVerifyMessageIF>(
|
||||||
messageReceiver);
|
messageReceiver);
|
||||||
if (temp != NULL) {
|
if (temp == nullptr) {
|
||||||
|
sif::error << "VerificationReporter::initialize: Message "
|
||||||
|
<< "receiver invalid. Make sure it is set up properly and "
|
||||||
|
<<"implementsAcceptsVerifyMessageIF" << std::endl;
|
||||||
|
|
||||||
|
}
|
||||||
this->acknowledgeQueue = temp->getVerificationQueue();
|
this->acknowledgeQueue = temp->getVerificationQueue();
|
||||||
} else {
|
|
||||||
sif::error
|
|
||||||
<< "VerificationReporter::VerificationReporter: Configuration error."
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef VERIFICATIONREPORTER_H_
|
#ifndef FRAMEWORK_TMTCSERVICES_VERIFICATIONREPORTER_H_
|
||||||
#define VERIFICATIONREPORTER_H_
|
#define FRAMEWORK_TMTCSERVICES_VERIFICATIONREPORTER_H_
|
||||||
|
|
||||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||||
#include <framework/tmtcservices/PusVerificationReport.h>
|
#include <framework/tmtcservices/PusVerificationReport.h>
|
||||||
@ -8,24 +8,43 @@ namespace Factory{
|
|||||||
void setStaticFrameworkObjectIds();
|
void setStaticFrameworkObjectIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This helper object is used to forward verification messages
|
||||||
|
* which are generated by the Flight Software Framework.
|
||||||
|
* @details
|
||||||
|
* The messages can be relayed to an arbitrary object, for example a dedicated
|
||||||
|
* Verification Reporter. The destination is set by setting the static framework
|
||||||
|
* Id VerificationReporter::messageReceiver. The default verification reporter
|
||||||
|
* will be the PUS service 1, which sends verification messages according
|
||||||
|
* to the PUS standard.
|
||||||
|
*
|
||||||
|
*/
|
||||||
class VerificationReporter {
|
class VerificationReporter {
|
||||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||||
public:
|
public:
|
||||||
VerificationReporter();
|
VerificationReporter();
|
||||||
virtual ~VerificationReporter();
|
virtual ~VerificationReporter();
|
||||||
void sendSuccessReport( uint8_t set_report_id, TcPacketBase* current_packet, uint8_t set_step = 0 );
|
|
||||||
void sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, uint8_t set_step = 0);
|
void sendSuccessReport( uint8_t set_report_id, TcPacketBase* current_packet,
|
||||||
void sendFailureReport( uint8_t report_id, TcPacketBase* current_packet, ReturnValue_t error_code = 0,
|
uint8_t set_step = 0 );
|
||||||
uint8_t step = 0, uint32_t parameter1 = 0, uint32_t parameter2 = 0 );
|
void sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags,
|
||||||
|
uint16_t tcPacketId, uint16_t tcSequenceControl,
|
||||||
|
uint8_t set_step = 0);
|
||||||
|
|
||||||
|
void sendFailureReport( uint8_t report_id, TcPacketBase* current_packet,
|
||||||
|
ReturnValue_t error_code = 0,
|
||||||
|
uint8_t step = 0, uint32_t parameter1 = 0,
|
||||||
|
uint32_t parameter2 = 0 );
|
||||||
void sendFailureReport(uint8_t report_id,
|
void sendFailureReport(uint8_t report_id,
|
||||||
uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t error_code = 0, uint8_t step = 0,
|
uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl,
|
||||||
|
ReturnValue_t error_code = 0, uint8_t step = 0,
|
||||||
uint32_t parameter1 = 0, uint32_t parameter2 = 0);
|
uint32_t parameter1 = 0, uint32_t parameter2 = 0);
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static object_id_t messageReceiver;
|
static object_id_t messageReceiver;
|
||||||
MessageQueueId_t acknowledgeQueue;
|
MessageQueueId_t acknowledgeQueue;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* VERIFICATIONREPORTER_H_ */
|
#endif /* FRAMEWORK_TMTCSERVICES_VERIFICATIONREPORTER_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user