working on tm
This commit is contained in:
parent
ad4adc7cba
commit
de93bff561
@ -30,6 +30,7 @@ add_subdirectory(tasks)
|
||||
add_subdirectory(tcdistribution)
|
||||
#add_subdirectory(thermal)
|
||||
add_subdirectory(timemanager)
|
||||
add_subdirectory(tmtc)
|
||||
add_subdirectory(tmtcpacket)
|
||||
add_subdirectory(tmtcservices)
|
||||
add_subdirectory(filesystem)
|
||||
|
@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
#include <fsfw/introspection/Enum.h>
|
||||
#include <fsfw/ipc/MutexIF.h>
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
#include <fsfw/storagemanager/storeAddress.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <vector>
|
||||
@ -10,6 +11,32 @@
|
||||
#include "DatasetEntryIF.h"
|
||||
#include "HasDatapoolIF.h"
|
||||
|
||||
/**
|
||||
* This class has a dual use
|
||||
*
|
||||
* 1) It is used as an IPC method:
|
||||
* It implements a shared memory which can be written and read by different parties
|
||||
*
|
||||
* 2) It is used to define data that is to be downlinked, either periodically or
|
||||
* triggered by an (abstract, not in the sense of fsfw/events) event occuring, ie
|
||||
* data was received from an external source and should be shared with ground.
|
||||
*
|
||||
* Generating a downlinked report is coupled to commiting, as without a commit there is no
|
||||
* change in information to be reported.
|
||||
*
|
||||
* Nominally, the decision to report is done by the set itself, depending on its settings.
|
||||
* If a report is to be forced regardless of these settings, the commitAndReport() functions
|
||||
* are provided which will always generate a report.
|
||||
*
|
||||
* Periodic reports are not tied to a specific tc and are reported as "unrequested". When forcing
|
||||
* a report, optionally a tc can be provided which (logically) triggered the report.
|
||||
*
|
||||
* And, as life is complicated, there is a third set of commits: commitAndReportIfRequested(). Same
|
||||
* as before, but this time, a report is only generated, if the store_address_t is valid. These are
|
||||
* used if at the place where the commit is called, it is not known if there is a request (cf DHB
|
||||
* interpretDeviceReply)
|
||||
*/
|
||||
|
||||
class Dataset {
|
||||
protected:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
@ -31,11 +58,59 @@ class Dataset {
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
*
|
||||
* calls setValit(valid) before committing
|
||||
* calls setValid(valid) before committing
|
||||
*
|
||||
*/
|
||||
void commit(bool valid);
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
* Force sending of TM packet
|
||||
*
|
||||
*/
|
||||
void commitAndReport();
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
* Force sending of TM packet
|
||||
*
|
||||
* calls setValid(valid) before committing
|
||||
*
|
||||
*/
|
||||
void commitAndReport(bool valid);
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
* Force sending of TM packet, in reference to tc
|
||||
*
|
||||
*/
|
||||
void commitAndReport(store_address_t tc);
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
* Force sending of TM packet, in reference to tc
|
||||
*
|
||||
* calls setValid(valid) before committing
|
||||
*
|
||||
*/
|
||||
void commitAndReport(bool valid, store_address_t tc);
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
* Force sending of TM packet, in reference to tc
|
||||
*
|
||||
*/
|
||||
void commitAndReportIfRequested(store_address_t tc);
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
* Force sending of TM packet, in reference to tc
|
||||
*
|
||||
* calls setValid(valid) before committing
|
||||
*
|
||||
*/
|
||||
void commitAndReportIfRequested(bool valid, store_address_t tc);
|
||||
|
||||
/**
|
||||
* set all contained variables to #valid
|
||||
*
|
||||
@ -71,7 +146,6 @@ class Dataset {
|
||||
*/
|
||||
virtual const std::vector<DatasetEntryIF*>* getVariables() const;
|
||||
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
// operator[]
|
||||
|
29
src/fsfw/tmtc/AcceptsTelemetryIF.h
Normal file
29
src/fsfw/tmtc/AcceptsTelemetryIF.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef FSFW_TMTCSERVICES_ACCEPTSTELEMETRYIF_H_
|
||||
#define FSFW_TMTCSERVICES_ACCEPTSTELEMETRYIF_H_
|
||||
|
||||
#include "fsfw/ipc/MessageQueueSenderIF.h"
|
||||
/**
|
||||
* @brief This interface is implemented by classes that are sinks for
|
||||
* Telemetry.
|
||||
* @details Any object receiving telemetry shall implement this interface
|
||||
*
|
||||
*/
|
||||
class AcceptsTelemetryIF {
|
||||
public:
|
||||
/**
|
||||
* @brief The virtual destructor as it is mandatory for C++ interfaces.
|
||||
*/
|
||||
virtual ~AcceptsTelemetryIF() = default;
|
||||
|
||||
// [[nodiscard]] virtual const char* getName() const = 0;
|
||||
// /**
|
||||
// * @brief This method returns the message queue id of the telemetry
|
||||
// * receiving message queue.
|
||||
// * @return The telemetry reception message queue id.
|
||||
// */
|
||||
// [[nodiscard]] virtual MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const = 0;
|
||||
|
||||
[[nodiscard]] virtual MessageQueueId_t getReportReceptionQueue() const = 0;
|
||||
};
|
||||
|
||||
#endif /* FSFW_TMTCSERVICES_ACCEPTSTELEMETRYIF_H_ */
|
5
src/fsfw/tmtc/CMakeLists.txt
Normal file
5
src/fsfw/tmtc/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE
|
||||
FsfwProtocolHeader.cpp
|
||||
TmManager.cpp
|
||||
UdpTmTcBridge.cpp)
|
51
src/fsfw/tmtc/FsfwProtocolHeader.cpp
Normal file
51
src/fsfw/tmtc/FsfwProtocolHeader.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "FsfwProtocolHeader.h"
|
||||
|
||||
#include <fsfw/serialize/SerializeAdapter.h>
|
||||
|
||||
FsfwProtocolHeader::FsfwProtocolHeader() {}
|
||||
|
||||
FsfwProtocolHeader::FsfwProtocolHeader(object_id_t objectId, uint8_t interface, uint8_t function)
|
||||
: objectId(objectId), interface(interface), function(function) {}
|
||||
|
||||
FsfwProtocolHeader::~FsfwProtocolHeader() {}
|
||||
|
||||
ReturnValue_t FsfwProtocolHeader::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t result =
|
||||
SerializeAdapter::serialize(&objectId, buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = SerializeAdapter::serialize(&interface, buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return SerializeAdapter::serialize(&function, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
|
||||
size_t FsfwProtocolHeader::getSerializedSize() const {
|
||||
return HEADER_SIZE;
|
||||
}
|
||||
|
||||
ReturnValue_t FsfwProtocolHeader::deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) {
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&objectId, buffer, size, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = SerializeAdapter::deSerialize(&interface, buffer, size, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = SerializeAdapter::deSerialize(&function, buffer, size, streamEndianness);
|
||||
return result;
|
||||
}
|
||||
|
||||
object_id_t FsfwProtocolHeader::getObjectId() const { return objectId; }
|
||||
|
||||
uint8_t FsfwProtocolHeader::getInterface() const { return interface; }
|
||||
|
||||
uint8_t FsfwProtocolHeader::getFunction() const { return function; }
|
30
src/fsfw/tmtc/FsfwProtocolHeader.h
Normal file
30
src/fsfw/tmtc/FsfwProtocolHeader.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/serialize/SerializeIF.h>
|
||||
|
||||
class FsfwProtocolHeader : public SerializeIF {
|
||||
public:
|
||||
static const size_t HEADER_SIZE = 6;
|
||||
|
||||
FsfwProtocolHeader();
|
||||
FsfwProtocolHeader(object_id_t objectID, uint8_t interface, uint8_t function);
|
||||
~FsfwProtocolHeader() override;
|
||||
|
||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
|
||||
size_t getSerializedSize() const override;
|
||||
|
||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
object_id_t getObjectId() const;
|
||||
uint8_t getInterface() const;
|
||||
uint8_t getFunction() const;
|
||||
|
||||
private:
|
||||
object_id_t objectId;
|
||||
uint8_t interface;
|
||||
uint8_t function;
|
||||
};
|
5
src/fsfw/tmtc/FsfwProtocols.h
Normal file
5
src/fsfw/tmtc/FsfwProtocols.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum neither_type : uint8_t { IP4, IP6, IP4_ENCAPSULATED, SPACEPACKET };
|
64
src/fsfw/tmtc/TmManager.cpp
Normal file
64
src/fsfw/tmtc/TmManager.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "TmManager.h"
|
||||
|
||||
#include <fsfw/objectmanager/ObjectManager.h>
|
||||
|
||||
ReturnValue_t TmManager::initialize() {
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
IPCStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (IPCStore == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t TmManager::getProtocolInformation(store_address_t tc,
|
||||
protocolInformation* information) const {
|
||||
const uint8_t* tcData;
|
||||
size_t tcDataSize;
|
||||
ReturnValue_t result = IPCStore->getData(tc, &tcData, &tcDataSize);
|
||||
if (result != returnvalue::OK) {
|
||||
return getDefaultProtocolInformation(information);
|
||||
}
|
||||
|
||||
neither_type tcProtocol = neither_type(*tcData);
|
||||
|
||||
if (not protocolMap.contains(tcProtocol)) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
auto protocolIter = protocolMap.find(tcProtocol);
|
||||
|
||||
information->reportingQueue = protocolIter->second.queue;
|
||||
information->offset = protocolIter->second.offset;
|
||||
information->protocol = tcProtocol;
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t TmManager::registerNetworkProtocolInterface(AcceptsTelemetryIF* object,
|
||||
neither_type protocol, size_t offset) {
|
||||
if (protocolMap.contains(protocol)) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
protocolMap.emplace(protocol, ProtocolInformation({object->getReportReceptionQueue(), offset}));
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t TmManager::getDefaultProtocolInformation(protocolInformation* information) const {
|
||||
if (protocolMap.empty()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
auto protocolIter = protocolMap.begin();
|
||||
|
||||
information->reportingQueue = protocolIter->second.queue;
|
||||
information->offset = protocolIter->second.offset;
|
||||
information->protocol = protocolIter->first;
|
||||
return returnvalue::OK;
|
||||
}
|
56
src/fsfw/tmtc/TmManager.h
Normal file
56
src/fsfw/tmtc/TmManager.h
Normal file
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/storagemanager/StorageManagerIF.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "AcceptsTelemetryIF.h"
|
||||
#include "FsfwProtocols.h"
|
||||
|
||||
// TODO handle VCs and backpressure
|
||||
|
||||
class TmManager : public SystemObject {
|
||||
public:
|
||||
struct protocolInformation {
|
||||
neither_type protocol;
|
||||
size_t offset;
|
||||
MessageQueueId_t reportingQueue;
|
||||
};
|
||||
|
||||
|
||||
TmManager(object_id_t setObjectId);
|
||||
|
||||
virtual ~TmManager() = default;
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
/**
|
||||
* returns the offset which the application data should start at, using the same network layer as
|
||||
* the tc, as well as the protocol type which should be the first byte of the tm
|
||||
*
|
||||
*/
|
||||
ReturnValue_t getProtocolInformation(store_address_t tc, protocolInformation *information) const;
|
||||
|
||||
/**
|
||||
* If tm is unrequested, get Default path
|
||||
*/
|
||||
ReturnValue_t getDefaultProtocolInformation(protocolInformation *information) const;
|
||||
|
||||
/**
|
||||
* Offset is where application data should start in a preset zero-copy packet. If no fixed value,
|
||||
* report 0 and allocate and copy yourself
|
||||
*/
|
||||
ReturnValue_t registerNetworkProtocolInterface(AcceptsTelemetryIF *object, neither_type protocol,
|
||||
size_t offset);
|
||||
|
||||
protected:
|
||||
struct ProtocolInformation {
|
||||
MessageQueueId_t queue;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
StorageManagerIF *IPCStore;
|
||||
|
||||
std::map<neither_type, ProtocolInformation> protocolMap;
|
||||
};
|
142
src/fsfw/tmtc/UdpTmTcBridge.cpp
Normal file
142
src/fsfw/tmtc/UdpTmTcBridge.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
#include "UdpTmTcBridge.h"
|
||||
|
||||
#include "FsfwProtocolHeader.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fsfw/action.h>
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <fsfw/objectmanager.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h> // POSIX.1-2001 does not require the inclusion of <sys/types.h>, and this header file is not required on Linux. However, some historical (BSD) implementations required this header file, and portable applications are probably wise to include it.
|
||||
|
||||
UdpTmTcBridgeNew::UdpTmTcBridgeNew(object_id_t objectId, object_id_t tmStoreId,
|
||||
object_id_t tcStoreId)
|
||||
: SystemObject(objectId) {
|
||||
messageQueue =
|
||||
QueueFactory::instance()->createMessageQueue(50, MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
}
|
||||
|
||||
UdpTmTcBridgeNew::~UdpTmTcBridgeNew() {}
|
||||
|
||||
ReturnValue_t UdpTmTcBridgeNew::initialize() {
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
IPCStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (IPCStore == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
int retval;
|
||||
|
||||
serverSocket = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
|
||||
if (serverSocket == -1) {
|
||||
// TODO resolve errno
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "UdpTmTcBridge::initialize: Socket initialization failed!" << std::endl;
|
||||
#endif
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
sockaddr_in serverAddr;
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(6667);
|
||||
|
||||
retval = inet_aton("10.13.90.2", &serverAddr.sin_addr);
|
||||
if (retval == 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "UdpTmTcBridge::initialize: Invalid IP!" << std::endl;
|
||||
#endif
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
retval = bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
|
||||
if (retval == -1) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "UdpTmTcBridge::initialize: bind failed with " << errno << std::endl;
|
||||
#endif
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t UdpTmTcBridgeNew::performOperation(uint8_t operationCode) {
|
||||
ssize_t peekLen = recv(serverSocket, NULL, 0, MSG_PEEK | MSG_TRUNC);
|
||||
|
||||
if (peekLen <= 0) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
if (peekLen < FsfwProtocolHeader::HEADER_SIZE) {
|
||||
recv(serverSocket, NULL, 0, MSG_TRUNC);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
store_address_t storageId;
|
||||
uint8_t *bufferPointer;
|
||||
ReturnValue_t result = IPCStore->getFreeElement(&storageId, peekLen, &bufferPointer);
|
||||
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
sockaddr_storage sender;
|
||||
socklen_t senderlen = sizeof(sender);
|
||||
|
||||
ssize_t receivedLen =
|
||||
recvfrom(serverSocket, bufferPointer, peekLen, 0, (struct sockaddr *)&sender, &senderlen);
|
||||
|
||||
if (receivedLen == -1) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
if (receivedLen != peekLen) {
|
||||
// should not happen, if it does throw away
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t bufferLen = receivedLen;
|
||||
const uint8_t *constBufferPointer = bufferPointer;
|
||||
|
||||
FsfwProtocolHeader header;
|
||||
|
||||
result = header.deSerialize(&constBufferPointer, &bufferLen,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
sif::debug << "Received msg for 0x" << std::hex << header.getObjectId() << std::dec << " interface "
|
||||
<< (int) header.getInterface() << std::endl;
|
||||
|
||||
CommandMessage message;
|
||||
|
||||
switch (header.getInterface()) {
|
||||
case HasActionsIF::INTERFACE_ID: {
|
||||
HasActionsIF *object = ObjectManager::instance()->get<HasActionsIF>(header.getObjectId());
|
||||
if (object == nullptr) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ActionMessage::setCommand(&message, header.HEADER_SIZE, storageId);
|
||||
result = messageQueue->sendMessage(object->getCommandQueue(), &message);
|
||||
// sif::debug << "UdpTmTcBridge::performOperation: sent " << (int)storageId.raw << std::endl;
|
||||
} break;
|
||||
default:
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
// sif::debug << "UdpTmTcBridge::performOperation: illegal interface"
|
||||
// << (int) header.getInterface() << std::endl;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
25
src/fsfw/tmtc/UdpTmTcBridge.h
Normal file
25
src/fsfw/tmtc/UdpTmTcBridge.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/storagemanager/StorageManagerIF.h>
|
||||
#include <fsfw/ipc/MessageQueueIF.h>
|
||||
|
||||
|
||||
class UdpTmTcBridgeNew : public SystemObject, public ExecutableObjectIF {
|
||||
public:
|
||||
|
||||
static const size_t MINIMAL_LENGTH = 4 + 2; // ObjectId, interface, function
|
||||
UdpTmTcBridgeNew(object_id_t objectId,
|
||||
object_id_t tmStoreId, object_id_t tcStoreId);
|
||||
virtual ~UdpTmTcBridgeNew();
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
ReturnValue_t performOperation(uint8_t operationCode) override;
|
||||
|
||||
private:
|
||||
MessageQueueIF* messageQueue;
|
||||
int serverSocket;
|
||||
StorageManagerIF* IPCStore;
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user