Skip to content

Commit

Permalink
Adding support for integration testing
Browse files Browse the repository at this point in the history
Reg Marr committed Jan 23, 2025
1 parent 4335e71 commit 72303c0
Showing 7 changed files with 148 additions and 45 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ ENV PATH="/home/user/.local/bin:${PATH}"
# Install Python packages
RUN pip install setuptools setuptools_scm wheel pip fprime-tools --upgrade && \
pip install -r $FSW_WDIR/fprime/requirements.txt && \
pip install -e $FSW_WDIR/fprime-gds && \
# pip install -e $FSW_WDIR/fprime-gds && \
pip install pytest debugpy pyinfra asyncio asyncssh gitpython python-dotenv --upgrade

FROM fprime_src AS stars_base
50 changes: 23 additions & 27 deletions FlightComputer/CCSDSTester/CCSDSConfig.cpp
Original file line number Diff line number Diff line change
@@ -6,31 +6,26 @@

namespace FlightComputer {

// std::array<std::array<U8, MessageSize>, MessageNum> ChannelMsgs = {{
// {'B', 'O', 'N', 'J', 'O', 'U', 'R'}, // Channel 0: "BONJOUR"
// {'S', 'A', 'L', 'U', 'T', 0, 0}, // Channel 1: "SALUT" (padded with 0s)
// {0xF0, 0x9F, 0x8D, 0x81, 0, 0, 0} // Channel 2: Oh Canada (padded with 0s)
// }};

static constexpr std::array<TMSpaceDataLink::VirtualChannelParams_t, MessageNum> VCParams = {
{{
0, // virtualChannelId = 0,
MessageSize, // VCA_SDULength = 7 (channelMessages max size),
0, // VC_FSHLength = 0,
false, // isVC_OCFPresent = false,
},
{
1, // virtualChannelId = 1,
MessageSize, // VCA_SDULength = 7 (channelMessages max size),
0, // VC_FSHLength = 0,
false, // isVC_OCFPresent = false,
},
{
2, // virtualChannelId = 2,
MessageSize, // VCA_SDULength = 7 (channelMessages max size),
0, // VC_FSHLength = 0,
false, // isVC_OCFPresent = false,
}}};
static constexpr std::array<TMSpaceDataLink::VirtualChannelParams_t, MessageNum>
VCParams = {
{{
0, // virtualChannelId = 0,
MessageSize, // VCA_SDULength = 7 (channelMessages max size),
0, // VC_FSHLength = 0,
false, // isVC_OCFPresent = false,
},
{
1, // virtualChannelId = 1,
MessageSize, // VCA_SDULength = 7 (channelMessages max size),
0, // VC_FSHLength = 0,
false, // isVC_OCFPresent = false,
},
{
2, // virtualChannelId = 2,
MessageSize, // VCA_SDULength = 7 (channelMessages max size),
0, // VC_FSHLength = 0,
false, // isVC_OCFPresent = false,
}}};

static constexpr TMSpaceDataLink::MasterChannelParams_t MasterChannelParams = {
.spaceCraftId = CCSDS_SCID,
@@ -43,7 +38,8 @@ static constexpr TMSpaceDataLink::MasterChannelParams_t MasterChannelParams = {

TMSpaceDataLink::ProtocolEntity createProtocolEntity() {

// NOTE this must be defined on the stack as a consequence of using the non-trivial type Fw::String
// NOTE this must be defined on the stack as a consequence of using the
// non-trivial type Fw::String
// TODO consider removing that constraint
const TMSpaceDataLink::PhysicalChannelParams_t PhysicalChannelParams = {
.channelName = "Loopback Channel",
@@ -62,4 +58,4 @@ TMSpaceDataLink::ProtocolEntity createProtocolEntity() {
return TMSpaceDataLink::ProtocolEntity(ManagedParams);
}

}
} // namespace FlightComputer
85 changes: 80 additions & 5 deletions FlightComputer/CCSDSTester/CCSDSTester.cpp
Original file line number Diff line number Diff line change
@@ -7,21 +7,27 @@
#include "FlightComputer/CCSDSTester/CCSDSTester.hpp"
#include "Drv/ByteStreamDriverModel/RecvStatusEnumAc.hpp"
#include "Drv/ByteStreamDriverModel/SendStatusEnumAc.hpp"
#include "FlightComputer/CCSDSTester/CCSDSTester_MsgSummarySerializableAc.hpp"
#include "FlightComputer/CCSDSTester/CCSDSTester_MsgWindowArrayAc.hpp"
#include "FlightComputer/CCSDSTester/FppConstantsAc.hpp"
#include "FpConfig.h"
#include "FpConfig.hpp"
#include "Fw/Buffer/Buffer.hpp"
#include "Fw/Com/ComBuffer.hpp"
#include "Fw/Com/ComPacket.hpp"
#include "Fw/Logger/Logger.hpp"
#include "Fw/Time/Time.hpp"
#include "Fw/Types/Assert.hpp"
#include "Fw/Types/Serializable.hpp"
#include "Fw/Types/String.hpp"
#include "Svc/FrameAccumulator/FrameDetector/CCSDSFrameDetector.hpp"
#include "Svc/FramingProtocol/CCSDSProtocols/TMSpaceDataLink/Channels.hpp"
#include "Svc/FramingProtocol/CCSDSProtocols/TMSpaceDataLink/ManagedParameters.hpp"
#include "Svc/FramingProtocol/CCSDSProtocols/TMSpaceDataLink/ProtocolInterface.hpp"
#include "Svc/FramingProtocol/CCSDSProtocols/TMSpaceDataLink/TransferFrame.hpp"
#include "Utils/Types/CircularBuffer.hpp"
#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdio>
#include <iomanip> // for std::hex and std::setfill
@@ -203,6 +209,7 @@ void CCSDSTester::run_handler(
const NATIVE_INT_TYPE portNum,
NATIVE_UINT_TYPE context
) {
this->tlmWrite_pipelineStats(this->m_pipelineStats);
// If we haven't enabled running the pipeline then return
if (!this->m_ShouldRunPipeline) {
return;
@@ -211,6 +218,63 @@ void CCSDSTester::run_handler(
runPipeline();
}

void CCSDSTester::updatePipelineStats(
std::array<CCSDSTester_MsgSummary, CCSDSTester_MSG_WINDOW_SIZE>& rawMsgWindow)
{
CCSDSTester_MsgWindow currentMsgWindow = this->m_pipelineStats.getmsgWindow();
F64 totalBytes = 0;

// Process the message window
for (NATIVE_UINT_TYPE idx = 0; idx < CCSDSTester_MSG_WINDOW_SIZE; idx++) {
CCSDSTester_MsgSummary& msgSummary = rawMsgWindow.at(idx);
U64 lastSendTime;

// Get appropriate last send time
if (idx == 0) {
// For first message, use last message from previous window
if (currentMsgWindow[CCSDSTester_MSG_WINDOW_SIZE - 1].getsendTimeUs() != 0) {
lastSendTime = currentMsgWindow[CCSDSTester_MSG_WINDOW_SIZE - 1].getsendTimeUs();
} else {
// If no previous message, use current message time
lastSendTime = msgSummary.getsendTimeUs();
}
} else {
lastSendTime = rawMsgWindow.at(idx - 1).getsendTimeUs();
}

FwSizeType currentMsgSize = msgSummary.getmsgSize();

// Calculate instantaneous baud rate (bits per second)
U64 timeDiffUs = msgSummary.getsendTimeUs() - lastSendTime;
if (timeDiffUs > 0) {
F64 baudRate = (currentMsgSize * 8.0) / (static_cast<F64>(timeDiffUs) / 1000000.0);
this->m_baudRateWindow.at(idx) = baudRate;
}

// Update message window
currentMsgWindow[idx] = msgSummary;
totalBytes += currentMsgSize;
}

// Calculate average baud rate over the window
U64 windowTimeUs = rawMsgWindow.back().getsendTimeUs() - rawMsgWindow.front().getsendTimeUs();
F64 windowAvgBaudRate = 0.0;
if (windowTimeUs > 0) {
// Convert to bits per second
windowAvgBaudRate = (totalBytes * 8.0) / (static_cast<F64>(windowTimeUs) / 1000000.0);
}

// Update pipeline stats
this->m_pipelineStats.set(
this->m_pipelineStats.gettotalBytesSent() + totalBytes,
windowAvgBaudRate,
currentMsgWindow
);

this->tlmWrite_pipelineStats(this->m_pipelineStats);
Fw::Logger::log("Updated pipeline\n");
}

void CCSDSTester::sendLoopbackMsg(loopbackMsgHeader_t &header) {
std::array<Fw::ComBuffer, MessageNum> comBuffers;
std::array<Fw::Buffer, MessageNum> plainBuffers;
@@ -221,24 +285,35 @@ void CCSDSTester::sendLoopbackMsg(loopbackMsgHeader_t &header) {
Fw::ComPacket::ComPacketType::FW_PACKET_PACKETIZED_TLM,
};

std::array<CCSDSTester_MsgSummary, CCSDSTester_MSG_WINDOW_SIZE> rawWindow;
CCSDSTester_MsgWindow msgWindow;

for (int i = 0; i < MessageNum; i++) {
std::string msg(ChannelMsgs.at(i).begin(), ChannelMsgs.at(i).end());
std::string msgJson(createJsonMessage(header, msg));
std::array<U8, MessageSize> msgJsonArr;
std::copy(msgJson.begin(), msgJson.end(), msgJsonArr.data());

// plainBuffers.at(i).set(0, plainBuffers.at(i).getSize());

plainBuffers.at(i) = createSerializedBuffer(packetTypeVals.at(i), msgJsonArr, comBuffers.at(i));
Fw::Time time(this->getTime());
this->tlmWrite_sendTimeUs(time.getUSeconds());

// m_pipelineStats.set(plainBuffers.at(i).getSize(),
// m_pipelineStats.gettotalBytesSent()+plainBuffers.at(i).getSize(),
// time.getUSeconds(), wh);
// (std::string(msgJson.data(), CCSDSTester_MSG_WINDOW_SIZE));
CCSDSTester_MsgSummary msgSummary(time.getUSeconds(), header.cmdSeq, header.opCode,
MessageSize,
Fw::String(msgJson.data()));
rawWindow.at(i) = msgSummary;
routeMessage(plainBuffers.at(i), i);
}

updatePipelineStats(rawWindow);

std::nullptr_t null_arg = nullptr;
// Transfer data after all messages have been sent
this->m_protocolEntity.m_physicalChannel.m_subChannels.at(0).transfer(null_arg);

// // Generate and handle responses
// runPipeline();
}

void CCSDSTester::RUN_PIPELINE_cmdHandler(const FwOpcodeType opCode, const U32 cmdSeq) {
23 changes: 22 additions & 1 deletion FlightComputer/CCSDSTester/CCSDSTester.fpp
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@ module FlightComputer {

@ Loopback CCSDS Testing component
active component CCSDSTester {

###############################################################################
# Standard AC Ports: Required for Channels, Events, Commands, and Parameters #
###############################################################################
@@ -102,6 +101,28 @@ module FlightComputer {
str1: string size 50
)
constant MSG_PEEK_SIZE = 55
constant MSG_WINDOW_SIZE = 3
struct MsgSummary {
sendTimeUs: U64
cmdSeq: U32
opCode: U32
msgSize: U32
msgPeek: string size MSG_PEEK_SIZE
}
array MsgWindow = [MSG_WINDOW_SIZE] MsgSummary
struct PipelineStats {
totalBytesSent: U32
avgBaudRate: F64
msgWindow: MsgWindow
}
telemetry sendTimeUs: U64
telemetry pipelineStats: PipelineStats
# telemetry pipelineStats: PipelineStats update on change
}
}
9 changes: 9 additions & 0 deletions FlightComputer/CCSDSTester/CCSDSTester.hpp
Original file line number Diff line number Diff line change
@@ -10,12 +10,16 @@
#include "Drv/ByteStreamDriverModel/SendStatusEnumAc.hpp"
#include "Drv/Ip/IpSocket.hpp"
#include "FlightComputer/CCSDSTester/CCSDSTesterComponentAc.hpp"
#include "FlightComputer/CCSDSTester/CCSDSTester_PipelineStatsSerializableAc.hpp"
#include "FlightComputer/CCSDSTester/FppConstantsAc.hpp"
#include "FpConfig.h"
#include "Fw/Cmd/CmdString.hpp"
#include "Fw/Logger/Logger.hpp"
#include "Fw/Types/String.hpp"
#include "Svc/FramingProtocol/CCSDSProtocols/TMSpaceDataLink/ManagedParameters.hpp"
#include "Svc/FramingProtocol/CCSDSProtocols/TMSpaceDataLink/ProtocolInterface.hpp"
#include "CCSDSConfig.hpp"
#include <array>

namespace FlightComputer {

@@ -40,8 +44,12 @@ class CCSDSTester : public CCSDSTesterComponentBase {
bool m_IsConnected = false;

bool m_ShouldRunPipeline = false;
static constexpr FwSizeType BAUD_RATE_WINDOW_SIZE = MessageNum * 3;
std::array<FwSizeType, BAUD_RATE_WINDOW_SIZE> m_baudRateWindow;
Fw::ComBuffer m_pipelineBuffer;

CCSDSTester_PipelineStats m_pipelineStats;

void bufferSendIn_handler(const NATIVE_INT_TYPE portNum,
Fw::Buffer &fwBuffer);
Fw::Buffer createSerializedBuffer(const FwPacketDescriptorType packetType,
@@ -52,6 +60,7 @@ class CCSDSTester : public CCSDSTesterComponentBase {
void runPipeline();

// Handler functions
void updatePipelineStats(std::array<CCSDSTester_MsgSummary, CCSDSTester_MSG_WINDOW_SIZE> &rawWindow);
void seqCmdBuff_handler(NATIVE_INT_TYPE portNum, Fw::ComBuffer &data,
U32 context);
void comStatusIn_handler(FwIndexType portNum, //!< The port number
2 changes: 1 addition & 1 deletion FlightComputer/Top/topology.fpp
Original file line number Diff line number Diff line change
@@ -108,6 +108,7 @@ module FlightComputer {
rateGroup1Comp.RateGroupMemberOut[1] -> blockDrv.Sched
rateGroup1Comp.RateGroupMemberOut[2] -> commsBufferManager.schedIn
rateGroup1Comp.RateGroupMemberOut[3] -> flightSequencer.run
rateGroup3Comp.RateGroupMemberOut[4] -> ccsdsNode.run

# Rate group 2 (1/2Hz)
rateGroupDriverComp.CycleOut[Ports_RateGroups.rateGroup2] -> rateGroup2Comp.CycleIn
@@ -118,7 +119,6 @@ module FlightComputer {
rateGroupDriverComp.CycleOut[Ports_RateGroups.rateGroup3] -> rateGroup3Comp.CycleIn
rateGroup3Comp.RateGroupMemberOut[0] -> systemResources.run
rateGroup3Comp.RateGroupMemberOut[1] -> fileDownlink.Run
rateGroup3Comp.RateGroupMemberOut[2] -> ccsdsNode.run
}

# NOTE this is not really used atm and is here more to match closer to the Ref
22 changes: 12 additions & 10 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -12,14 +12,15 @@ services:
image: $FSW_IMG
command: "fprime-gds -n --ip-port=$UPLINK_TARGET_PORT --tts-port=$DOWNLINK_TARGET_PORT --dictionary ./dict/FlightComputerTopologyAppDictionary.xml"
working_dir: ${DEPLOYMENT_ROOT}/build-artifacts/Linux/FlightComputer/
ports:
- $GDB_PORT:5555
- $DOWNLINK_TARGET_PORT:50050
- $GDS_WEB_GUI_PORT:5000
- $UPLINK_TARGET_PORT:50000
volumes:
- ${SCRIPT_DIR}:${FSW_WDIR}
network_mode: host # uses the host's network stack
# not needed when using network_mode "host"
# ports:
# - $GDB_PORT:5555
# - $DOWNLINK_TARGET_PORT:50050
# - $GDS_WEB_GUI_PORT:5000
# - $UPLINK_TARGET_PORT:50000
network_mode: host
healthcheck:
test: ["CMD-SHELL", "pgrep fprime-gds"]
interval: 2s
@@ -48,11 +49,12 @@ services:
- PATH=/home/user/STARS/autocoder:/home/user/.local/bin:${PATH} # TODO should check is necessary
volumes:
- ${SCRIPT_DIR}:${FSW_WDIR}
ports:
- "${GDB_PORT}:${GDB_PORT}"
- $DOWNLINK_TARGET_PORT:50050
- $GDS_WEB_GUI_PORT:5000
network_mode: host # uses the host's network stack
# Not needed when using host network
# ports:
# - "${GDB_PORT}:${GDB_PORT}"
# - $DOWNLINK_TARGET_PORT:50050
# - $GDS_WEB_GUI_PORT:5000
security_opt:
- seccomp:unconfined
cap_add:

0 comments on commit 72303c0

Please sign in to comment.