mirror of
https://github.com/nasa/fprime.git
synced 2025-12-10 00:44:37 -06:00
Add DP Demo for testing DPs and fprime-dp-writer (#3951)
* Initial DpDemo component, added test for decoding DPs * Updated Dp demo to include additional types, arrays, and struct records * Added struct member array to DP demo * Remove unused tlm * Cleanup after merging devel * Add deepdiff to requirements, fix formatting, update spelling * fpp v3.0.0a16 * fprime-gds v4.0.0a10 * Add 3 array record cases to DP demo * Remove comments * Remove deepdiff * Formatting, update spelling * FPP v3.0.0a18 * Spelling --------- Co-authored-by: Thomas Boyer-Chammard <49786685+thomas-bc@users.noreply.github.com>
This commit is contained in:
parent
d460468b1b
commit
dfaf496263
1
.github/actions/spelling/expect.txt
vendored
1
.github/actions/spelling/expect.txt
vendored
@ -337,6 +337,7 @@ itr
|
||||
itrunc
|
||||
itval
|
||||
janamian
|
||||
jawest
|
||||
Jax
|
||||
jdk
|
||||
jdperez
|
||||
|
||||
@ -98,7 +98,7 @@ Single-value records with _type = T_ have the following format:
|
||||
|Field Name|Data Type|Serialized Size|Description|
|
||||
|----------|---------|---------------|-----------|
|
||||
|`Id`|`FwDpIdType`|`sizeof(FwDpIdType)`|The record ID|
|
||||
|`Data`|_T_|`sizeof(`_T_`)` if _T_ is a primitive type; otherwise _T_`::SERIALIZED_SIZE`|The serialized data|
|
||||
|`Data`|_T_|Size of the serialized data|The serialized data|
|
||||
|
||||
**Array records:**
|
||||
An array record is specified in FPP in the form `product record` _name_ `:` _type_ `array`.
|
||||
@ -110,7 +110,7 @@ Array records with _type = T_ have the following format:
|
||||
|----------|---------|---------------|-----------|
|
||||
|`Id`|`FwDpIdType`|`sizeof(FwDpIdType)`|The record ID|
|
||||
|`Size`|`FwSizeType`|`sizeof(FwSizeStoreType)`|The number _n_ of elements in the record|
|
||||
|`Data`|Array of _n_ _T_|_n_ * [`sizeof(`_T_`)` if _T_ is a primitive type; otherwise _T_`::SERIALIZED_SIZE`]|_n_ elements, each of type _T_|
|
||||
|`Data`|Array of _n_ _T_|Sum of the serialized sizes of the elements in the array|_n_ elements, each of type _T_|
|
||||
|
||||
#### 5.1.4. Data Hash
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/RecvBuffApp/")
|
||||
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SendBuffApp/")
|
||||
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/SignalGen/")
|
||||
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TypeDemo/")
|
||||
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/DpDemo/")
|
||||
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/BlockDriver/")
|
||||
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Top/")
|
||||
|
||||
|
||||
23
Ref/DpDemo/CMakeLists.txt
Normal file
23
Ref/DpDemo/CMakeLists.txt
Normal file
@ -0,0 +1,23 @@
|
||||
####
|
||||
# F Prime CMakeLists.txt:
|
||||
#
|
||||
# SOURCES: list of source files (to be compiled)
|
||||
# AUTOCODER_INPUTS: list of files to be passed to the autocoders
|
||||
# DEPENDS: list of libraries that this module depends on
|
||||
#
|
||||
# More information in the F´ CMake API documentation:
|
||||
# https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/
|
||||
#
|
||||
####
|
||||
|
||||
register_fprime_library(
|
||||
AUTOCODER_INPUTS
|
||||
"${CMAKE_CURRENT_LIST_DIR}/DpDemo.fpp"
|
||||
SOURCES
|
||||
"${CMAKE_CURRENT_LIST_DIR}/DpDemo.cpp"
|
||||
)
|
||||
|
||||
set(SOURCE_FILES
|
||||
"${CMAKE_CURRENT_LIST_DIR}/DpDemo.fpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/DpDemo.cpp"
|
||||
)
|
||||
246
Ref/DpDemo/DpDemo.cpp
Normal file
246
Ref/DpDemo/DpDemo.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
// ======================================================================
|
||||
// \title DpDemo.cpp
|
||||
// \author jawest
|
||||
// \brief cpp file for DpDemo component implementation class
|
||||
// ======================================================================
|
||||
|
||||
#include "Ref/DpDemo/DpDemo.hpp"
|
||||
|
||||
namespace Ref {
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Component construction and destruction
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
DpDemo ::DpDemo(const char* const compName) : DpDemoComponentBase(compName) {
|
||||
this->selectedColor = DpDemo_ColorEnum::RED;
|
||||
this->numRecords = 0;
|
||||
this->dpPriority = 0;
|
||||
}
|
||||
|
||||
DpDemo ::~DpDemo() {}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Handler implementations for typed input ports
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DpDemo ::run_handler(FwIndexType portNum, U32 context) {
|
||||
// If a Data product is being generated, store records
|
||||
if (this->dpInProgress) {
|
||||
this->dpContainer.serializeRecord_StringRecord(Fw::String("Test string"));
|
||||
this->dpContainer.serializeRecord_BooleanRecord(true);
|
||||
this->dpContainer.serializeRecord_I32Record(-100);
|
||||
this->dpContainer.serializeRecord_F64Record(1.25);
|
||||
this->dpContainer.serializeRecord_U32ArrayRecord(DpDemo_U32Array(1, 2, 3, 4, 5));
|
||||
this->dpContainer.serializeRecord_F32ArrayRecord(DpDemo_F32Array(1.1f, 2.2f, 3.3f));
|
||||
this->dpContainer.serializeRecord_BooleanArrayRecord(DpDemo_BooleanArray(true, false));
|
||||
// Array Records
|
||||
// Array record of strings
|
||||
Fw::String str0("String array element 0");
|
||||
Fw::String str1("String array element 1");
|
||||
Fw::String str2("String array element 2");
|
||||
const Fw::StringBase* strings[3] = { &str0, &str1, &str2 };
|
||||
this->dpContainer.serializeRecord_StringArrayRecord(strings, 3);
|
||||
// Array record of arrays
|
||||
const DpDemo_StringArray arrayArray[1] = {
|
||||
DpDemo_StringArray(
|
||||
Fw::String("0 - String array record element 0"),
|
||||
Fw::String("0 - String array record element 1")
|
||||
)
|
||||
};
|
||||
this->dpContainer.serializeRecord_ArrayArrayRecord(arrayArray, 1);
|
||||
// Array record of structs
|
||||
const DpDemo_StructWithStringMembers structArray[2] = {
|
||||
DpDemo_StructWithStringMembers(
|
||||
Fw::String("0 - String member"),
|
||||
DpDemo_StringArray(
|
||||
Fw::String("0 - String array element 0"),
|
||||
Fw::String("0 - String array element 1")
|
||||
)
|
||||
),
|
||||
DpDemo_StructWithStringMembers(
|
||||
Fw::String("1 - String member"),
|
||||
DpDemo_StringArray(
|
||||
Fw::String("1 - String array element 0"),
|
||||
Fw::String("1 - String array element 1")
|
||||
)
|
||||
)
|
||||
};
|
||||
this->dpContainer.serializeRecord_StructArrayRecord(structArray, 2);
|
||||
this->dpContainer.serializeRecord_ArrayOfStringArrayRecord(
|
||||
DpDemo_ArrayOfStringArray(
|
||||
DpDemo_StringArray(
|
||||
Fw::String("0 - String array element 0"),
|
||||
Fw::String("0 - String array element 1")
|
||||
),
|
||||
DpDemo_StringArray(
|
||||
Fw::String("1 - String array element 0"),
|
||||
Fw::String("1 - String array element 1")
|
||||
),
|
||||
DpDemo_StringArray(
|
||||
Fw::String("2 - String array element 0"),
|
||||
Fw::String("2 - String array element 1")
|
||||
)
|
||||
)
|
||||
);
|
||||
this->dpContainer.serializeRecord_ArrayOfStructsRecord(
|
||||
DpDemo_ArrayOfStructs(
|
||||
DpDemo_StructWithStringMembers(
|
||||
Fw::String("0 - String member"),
|
||||
DpDemo_StringArray(
|
||||
Fw::String("0 - String array element 0"),
|
||||
Fw::String("0 - String array element 1")
|
||||
)
|
||||
),
|
||||
DpDemo_StructWithStringMembers(
|
||||
Fw::String("1 - String member"),
|
||||
DpDemo_StringArray(
|
||||
Fw::String("1 - String array element 0"),
|
||||
Fw::String("1 - String array element 1")
|
||||
)
|
||||
),
|
||||
DpDemo_StructWithStringMembers(
|
||||
Fw::String("2 - String member"),
|
||||
DpDemo_StringArray(
|
||||
Fw::String("2 - String array element 0"),
|
||||
Fw::String("2 - String array element 1")
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
this->dpContainer.serializeRecord_EnumArrayRecord(DpDemo_EnumArray(DpDemo_ColorEnum::RED, DpDemo_ColorEnum::GREEN, DpDemo_ColorEnum::BLUE));
|
||||
this->dpContainer.serializeRecord_StructWithEverythingRecord(DpDemo_StructWithEverything(
|
||||
-1,
|
||||
2.5,
|
||||
Fw::String("String Member"),
|
||||
false,
|
||||
this->selectedColor,
|
||||
{
|
||||
DpDemo_U32Array(1, 2, 3, 4, 5),
|
||||
DpDemo_U32Array(6, 7, 8, 9, 10)
|
||||
},
|
||||
DpDemo_F32Array(4.4f, 5.5f, 6.6f),
|
||||
DpDemo_U32Array(6, 7, 8, 9, 10),
|
||||
DpDemo_EnumArray(DpDemo_ColorEnum::RED, DpDemo_ColorEnum::GREEN, DpDemo_ColorEnum::BLUE),
|
||||
DpDemo_StringArray(
|
||||
Fw::String("String array element 0"),
|
||||
Fw::String("String array element 1")
|
||||
),
|
||||
DpDemo_BooleanArray(true, false),
|
||||
DpDemo_StructWithStringMembers(
|
||||
Fw::String("String member"),
|
||||
DpDemo_StringArray(
|
||||
Fw::String("String array element 0"),
|
||||
Fw::String("String array element 1")
|
||||
)
|
||||
),
|
||||
DpDemo_ArrayOfStringArray(
|
||||
DpDemo_StringArray(
|
||||
Fw::String("0 - String array element 0"),
|
||||
Fw::String("0 - String array element 1")
|
||||
),
|
||||
DpDemo_StringArray(
|
||||
Fw::String("1 - String array element 0"),
|
||||
Fw::String("1 - String array element 1")
|
||||
),
|
||||
DpDemo_StringArray(
|
||||
Fw::String("2 - String array element 0"),
|
||||
Fw::String("2 - String array element 1")
|
||||
)
|
||||
)
|
||||
));
|
||||
this->log_ACTIVITY_LO_DpComplete(this->numRecords);
|
||||
this->cleanupAndSendDp();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Handler implementations for commands
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DpDemo ::SelectColor_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, Ref::DpDemo_ColorEnum color) {
|
||||
this->selectedColor = color;
|
||||
log_ACTIVITY_HI_ColorSelected(color);
|
||||
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
|
||||
}
|
||||
|
||||
void DpDemo ::Dp_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, DpDemo_DpReqType reqType, U32 priority) {
|
||||
|
||||
// make sure DPs are available
|
||||
if (!this->isConnected_productGetOut_OutputPort(0) || !this->isConnected_productRequestOut_OutputPort(0)) {
|
||||
this->log_WARNING_HI_DpsNotConnected();
|
||||
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
this->numRecords = 15; // 15 records in current demo
|
||||
FwSizeType dpSize = DpDemo_StringAlias::SERIALIZED_SIZE +
|
||||
sizeof(DpDemo_BoolAlias) +
|
||||
sizeof(DpDemo_I32Alias) +
|
||||
sizeof(DpDemo_F64Alias) +
|
||||
DpDemo_U32Array::SERIALIZED_SIZE +
|
||||
DpDemo_F32Array::SERIALIZED_SIZE +
|
||||
DpDemo_BooleanArray::SERIALIZED_SIZE +
|
||||
DpDemo_EnumArray::SERIALIZED_SIZE +
|
||||
DpDemo_StringArray::SERIALIZED_SIZE +
|
||||
DpDemo_StructWithEverything::SERIALIZED_SIZE +
|
||||
DpDemo_StructWithStringMembers::SERIALIZED_SIZE +
|
||||
(DpDemo_StringArray::SERIALIZED_SIZE * 3) +
|
||||
(DpDemo_StringArray::SERIALIZED_SIZE * 1) +
|
||||
(DpDemo_StructWithStringMembers::SERIALIZED_SIZE * 2) +
|
||||
DpDemo_ArrayOfStringArray::SERIALIZED_SIZE +
|
||||
(numRecords * sizeof(FwDpIdType));
|
||||
|
||||
this->dpPriority = static_cast<FwDpPriorityType>(priority);
|
||||
this->log_ACTIVITY_LO_DpMemRequested(dpSize);
|
||||
if(reqType == DpDemo_DpReqType::IMMEDIATE) {
|
||||
Fw::Success stat = this->dpGet_DpDemoContainer(dpSize, this->dpContainer);
|
||||
// make sure we got the memory we wanted
|
||||
if (Fw::Success::FAILURE == stat) {
|
||||
this->log_WARNING_HI_DpMemoryFail();
|
||||
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
|
||||
} else {
|
||||
this->dpInProgress = true;
|
||||
this->log_ACTIVITY_LO_DpStarted(numRecords);
|
||||
this->log_ACTIVITY_LO_DpMemReceived(this->dpContainer.getBuffer().getSize());
|
||||
// override priority with requested priority
|
||||
this->dpContainer.setPriority(priority);
|
||||
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
|
||||
}
|
||||
}
|
||||
else if (reqType == DpDemo_DpReqType::ASYNC) {
|
||||
this->dpRequest_DpDemoContainer(dpSize);
|
||||
}
|
||||
else {
|
||||
// should never get here
|
||||
FW_ASSERT(0, reqType.e);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Handler implementations for data products
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void DpDemo ::dpRecv_DpDemoContainer_handler(DpContainer& container, Fw::Success::T status) {
|
||||
// Make sure we got the buffer we wanted or quit
|
||||
if (Fw::Success::SUCCESS == status) {
|
||||
this->dpContainer = container;
|
||||
this->dpInProgress = true;
|
||||
// set previously requested priority
|
||||
this->dpContainer.setPriority(this->dpPriority);
|
||||
this->log_ACTIVITY_LO_DpStarted(this->numRecords);
|
||||
} else {
|
||||
this->log_WARNING_HI_DpMemoryFail();
|
||||
// cleanup
|
||||
this->dpInProgress = false;
|
||||
this->numRecords = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DpDemo ::cleanupAndSendDp() {
|
||||
this->dpSend(this->dpContainer);
|
||||
this->dpInProgress = false;
|
||||
this->numRecords = 0;
|
||||
}
|
||||
|
||||
} // namespace Ref
|
||||
212
Ref/DpDemo/DpDemo.fpp
Normal file
212
Ref/DpDemo/DpDemo.fpp
Normal file
@ -0,0 +1,212 @@
|
||||
module Ref {
|
||||
@ DP Demo
|
||||
active component DpDemo {
|
||||
|
||||
enum ColorEnum {
|
||||
RED
|
||||
GREEN
|
||||
BLUE
|
||||
}
|
||||
|
||||
enum DpReqType {
|
||||
IMMEDIATE
|
||||
ASYNC
|
||||
}
|
||||
|
||||
type StringAlias = string
|
||||
type BoolAlias = bool
|
||||
type I32Alias = I32
|
||||
type F64Alias = F64
|
||||
|
||||
@ Array of floats
|
||||
array F32Array = [3] F32
|
||||
|
||||
@ Array of integers
|
||||
array U32Array = [5] U32
|
||||
|
||||
@ Array of strings
|
||||
array StringArray = [2] string
|
||||
|
||||
@ Array of array of strings
|
||||
array ArrayOfStringArray = [3] StringArray
|
||||
|
||||
@ Array of booleans
|
||||
array BooleanArray = [2] bool
|
||||
|
||||
@ Array of enumerations
|
||||
array EnumArray = [3] ColorEnum
|
||||
|
||||
array ArrayOfStructs = [3] StructWithStringMembers
|
||||
|
||||
struct ColorInfoStruct {
|
||||
Color: ColorEnum
|
||||
}
|
||||
|
||||
struct StructWithStringMembers {
|
||||
stringMember: string,
|
||||
stringArrayMember: StringArray
|
||||
}
|
||||
|
||||
struct StructWithEverything {
|
||||
integerMember: I32Alias,
|
||||
floatMember: F32,
|
||||
stringMember: string,
|
||||
booleanMember: bool,
|
||||
enumMember: ColorEnum,
|
||||
arrayMemberU32: [2] U32Array,
|
||||
F32Array: F32Array,
|
||||
U32Array: U32Array,
|
||||
enumArray: EnumArray
|
||||
stringArray: StringArray,
|
||||
booleanArray: BooleanArray,
|
||||
structWithStrings: StructWithStringMembers
|
||||
nestedArrays: ArrayOfStringArray
|
||||
}
|
||||
|
||||
@ Select color
|
||||
async command SelectColor(color: ColorEnum) opcode 0
|
||||
|
||||
@ Command for generating a DP
|
||||
sync command Dp(reqType: DpReqType, $priority: U32)
|
||||
|
||||
@ Color selected event
|
||||
event ColorSelected(color: ColorEnum) severity activity high id 0 format "Color selected {}"
|
||||
|
||||
@ DP started event
|
||||
event DpStarted(records: U32) \
|
||||
severity activity low \
|
||||
id 1 \
|
||||
format "Writing {} DP records"
|
||||
|
||||
@ DP complete event
|
||||
event DpComplete(records: U32) \
|
||||
severity activity low \
|
||||
id 2 \
|
||||
format "Finished writing {} DP records"
|
||||
|
||||
event DpRecordFull(records: U32, bytes: U32) \
|
||||
severity warning low \
|
||||
id 3 \
|
||||
format "DP container full with {} records and {} bytes. Closing DP."
|
||||
|
||||
event DpMemRequested($size: FwSizeType) \
|
||||
severity activity low \
|
||||
id 4 \
|
||||
format "Requesting {} bytes for DP"
|
||||
|
||||
event DpMemReceived($size: FwSizeType) \
|
||||
severity activity low \
|
||||
id 5 \
|
||||
format "Received {} bytes for DP"
|
||||
|
||||
event DpMemoryFail \
|
||||
severity warning high \
|
||||
id 6 \
|
||||
format "Failed to acquire a DP buffer"
|
||||
|
||||
event DpsNotConnected \
|
||||
severity warning high \
|
||||
id 7 \
|
||||
format "DP Ports not connected!"
|
||||
|
||||
@ Example port: receiving calls from the rate group
|
||||
sync input port run: Svc.Sched
|
||||
|
||||
# @ Example parameter
|
||||
# param PARAMETER_NAME: U32
|
||||
|
||||
###############################################################################
|
||||
# Standard AC Ports: Required for Channels, Events, Commands, and Parameters #
|
||||
###############################################################################
|
||||
@ Port for requesting the current time
|
||||
time get port timeCaller
|
||||
|
||||
@ Port for sending command registrations
|
||||
command reg port cmdRegOut
|
||||
|
||||
@ Port for receiving commands
|
||||
command recv port cmdIn
|
||||
|
||||
@ Port for sending command responses
|
||||
command resp port cmdResponseOut
|
||||
|
||||
@ Port for sending textual representation of events
|
||||
text event port logTextOut
|
||||
|
||||
@ Port for sending events to downlink
|
||||
event port logOut
|
||||
|
||||
@ Port for sending telemetry channels to downlink
|
||||
telemetry port tlmOut
|
||||
|
||||
@ Port to return the value of a parameter
|
||||
param get port prmGetOut
|
||||
|
||||
@ Port to set the value of a parameter
|
||||
param set port prmSetOut
|
||||
|
||||
@ Data product get port
|
||||
product get port productGetOut
|
||||
|
||||
@ Data product request port
|
||||
product request port productRequestOut
|
||||
|
||||
@ Data product receive port
|
||||
async product recv port productRecvIn
|
||||
|
||||
@ Data product send port
|
||||
product send port productSendOut
|
||||
|
||||
@ Data product record - struct record
|
||||
product record ColorInfoStructRecord: ColorInfoStruct id 0
|
||||
|
||||
@ Data product record - enum
|
||||
product record ColorEnumRecord: ColorEnum id 1
|
||||
|
||||
@ Data product record - string
|
||||
product record StringRecord: StringAlias id 2
|
||||
|
||||
@ Data product record - boolean
|
||||
product record BooleanRecord: BoolAlias id 3
|
||||
|
||||
@ Data product record - I32
|
||||
product record I32Record: I32Alias id 4
|
||||
|
||||
@ Data product record - F64
|
||||
product record F64Record: F64Alias id 5
|
||||
|
||||
@ Data product record - U32 array record
|
||||
product record U32ArrayRecord: U32Array id 6
|
||||
|
||||
@ Data product record - F32 array record
|
||||
product record F32ArrayRecord: F32Array id 7
|
||||
|
||||
@ Data product record - boolean array record
|
||||
product record BooleanArrayRecord: BooleanArray id 8
|
||||
|
||||
@ Data product record - enum array record
|
||||
product record EnumArrayRecord: EnumArray id 9
|
||||
|
||||
@ Data product record - string array record
|
||||
product record StringArrayRecord: string array id 10
|
||||
|
||||
@ Data product record - array record (structs)
|
||||
product record StructArrayRecord: StructWithStringMembers array id 11
|
||||
|
||||
@ Data product record - array record (arrays)
|
||||
product record ArrayArrayRecord: StringArray array id 12
|
||||
|
||||
@ Data product record - array record (string arrays)
|
||||
product record ArrayOfStringArrayRecord: ArrayOfStringArray id 13
|
||||
|
||||
@ Data product record - struct record
|
||||
product record StructWithEverythingRecord: StructWithEverything id 14
|
||||
|
||||
@ Data product record - array of structs
|
||||
product record ArrayOfStructsRecord: ArrayOfStructs id 15
|
||||
|
||||
@ Data product container
|
||||
product container DpDemoContainer id 0 default priority 10
|
||||
|
||||
}
|
||||
}
|
||||
77
Ref/DpDemo/DpDemo.hpp
Normal file
77
Ref/DpDemo/DpDemo.hpp
Normal file
@ -0,0 +1,77 @@
|
||||
// ======================================================================
|
||||
// \title DpDemo.hpp
|
||||
// \author jawest
|
||||
// \brief hpp file for DpDemo component implementation class
|
||||
// ======================================================================
|
||||
|
||||
#ifndef Ref_DpDemo_HPP
|
||||
#define Ref_DpDemo_HPP
|
||||
|
||||
#include "Ref/DpDemo/DpDemoComponentAc.hpp"
|
||||
|
||||
namespace Ref {
|
||||
|
||||
class DpDemo final : public DpDemoComponentBase {
|
||||
public:
|
||||
// ----------------------------------------------------------------------
|
||||
// Component construction and destruction
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
//! Construct DpDemo object
|
||||
DpDemo(const char* const compName //!< The component name
|
||||
);
|
||||
|
||||
//! Destroy DpDemo object
|
||||
~DpDemo();
|
||||
|
||||
private:
|
||||
// ----------------------------------------------------------------------
|
||||
// Handler implementations for commands
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
//! Handler implementation for run
|
||||
//!
|
||||
//! Example port: receiving calls from the rate group
|
||||
void run_handler(FwIndexType portNum, //!< The port number
|
||||
U32 context //!< The call order
|
||||
) override;
|
||||
|
||||
//! Handler implementation for command SelectColor
|
||||
//!
|
||||
//! Select color
|
||||
void SelectColor_cmdHandler(FwOpcodeType opCode, //!< The opcode
|
||||
U32 cmdSeq, //!< The command sequence number
|
||||
Ref::DpDemo_ColorEnum color) override;
|
||||
|
||||
//! Handler implementation for command Dp
|
||||
//!
|
||||
//! Command for generating a DP
|
||||
void Dp_cmdHandler(FwOpcodeType opCode, //!< The opcode
|
||||
U32 cmdSeq, //!< The command sequence number
|
||||
DpDemo_DpReqType reqType,
|
||||
U32 priority) override;
|
||||
|
||||
private:
|
||||
// ----------------------------------------------------------------------
|
||||
// Handler implementations for data products
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
//! Receive a container of type DpDemoContainer
|
||||
void dpRecv_DpDemoContainer_handler(DpContainer& container, //!< The container
|
||||
Fw::Success::T status //!< The container status
|
||||
) override;
|
||||
|
||||
// DP cleanup helper
|
||||
void cleanupAndSendDp();
|
||||
|
||||
// Member variables
|
||||
DpDemo_ColorEnum selectedColor;
|
||||
U32 numRecords;
|
||||
U32 dpPriority;
|
||||
DpContainer dpContainer;
|
||||
bool dpInProgress;
|
||||
};
|
||||
|
||||
} // namespace Ref
|
||||
|
||||
#endif
|
||||
59
Ref/DpDemo/test/int/dp_demo_integration_test.py
Normal file
59
Ref/DpDemo/test/int/dp_demo_integration_test.py
Normal file
@ -0,0 +1,59 @@
|
||||
import os
|
||||
import json
|
||||
from fprime_gds.executables.data_product_writer import DataProductWriter
|
||||
|
||||
|
||||
def test_dp_send(fprime_test_api):
|
||||
"""Test that DPs are generated and received on the ground"""
|
||||
|
||||
# Run Dp command to send a data product
|
||||
fprime_test_api.send_and_assert_command("Ref.dpDemo.Dp", ["IMMEDIATE", 1])
|
||||
# Wait for DpStarted event
|
||||
result = fprime_test_api.await_event("Ref.dpDemo.DpStarted", start=0, timeout=5)
|
||||
assert result
|
||||
# Wait for DpComplete event
|
||||
result = fprime_test_api.await_event("Ref.dpDemo.DpComplete", start=0, timeout=10)
|
||||
assert result
|
||||
# Check for FileWritten event and capture the name of the file that was created
|
||||
file_result = fprime_test_api.await_event(
|
||||
"DataProducts.dpWriter.FileWritten", start=0, timeout=10
|
||||
)
|
||||
dp_file_path = file_result.get_display_text().split().pop()
|
||||
# Verify that the file exists
|
||||
# Assumes that we are running the test from the Ref directory
|
||||
assert os.path.isfile(dp_file_path)
|
||||
|
||||
|
||||
def test_dp_decode(fprime_test_api):
|
||||
"""Test that we can decode DPs on the ground via fprime_dp_writer"""
|
||||
|
||||
# Run Dp command to send a data product
|
||||
fprime_test_api.send_and_assert_command("Ref.dpDemo.Dp", ["IMMEDIATE", 1])
|
||||
# Check for FileWritten event and capture the name of the file that was created
|
||||
file_result = fprime_test_api.await_event(
|
||||
"DataProducts.dpWriter.FileWritten", start=0, timeout=10
|
||||
)
|
||||
dp_file_path = file_result.get_display_text().split().pop()
|
||||
# Verify that the file exists
|
||||
# Assumes that we are running the test from the Ref directory
|
||||
assert os.path.isfile(dp_file_path)
|
||||
# Decode DP with fprime-dp-writer tool
|
||||
json_dict = fprime_test_api.pipeline.dictionary_path
|
||||
decoded_file_name = os.path.basename(dp_file_path).replace(".fdp", ".json")
|
||||
DataProductWriter(json_dict, dp_file_path).process()
|
||||
assert os.path.isfile(decoded_file_name)
|
||||
with open("./DpDemo/test/int/dp_ref_output.json", "r") as ref_file, open(
|
||||
decoded_file_name, "r"
|
||||
) as output_file:
|
||||
ref_json = json.load(ref_file)
|
||||
output_json = json.load(output_file)
|
||||
# Remove fields that we expect to be different
|
||||
exclude = ["Seconds", "USeconds", "TimeBase", "Context", "headerHash"]
|
||||
assert len(ref_json) > 0 and len(output_json) > 0
|
||||
for f in exclude:
|
||||
assert isinstance(ref_json[0], dict) and isinstance(output_json[0], dict)
|
||||
assert f in ref_json[0] and f in output_json[0]
|
||||
ref_json[0].pop(f)
|
||||
output_json[0].pop(f)
|
||||
# Check that the JSON strings are the same
|
||||
assert json.dumps(ref_json) == json.dumps(output_json)
|
||||
303
Ref/DpDemo/test/int/dp_ref_output.json
Normal file
303
Ref/DpDemo/test/int/dp_ref_output.json
Normal file
@ -0,0 +1,303 @@
|
||||
[
|
||||
{
|
||||
"PacketDescriptor": 5,
|
||||
"Id": 2576,
|
||||
"Priority": 1,
|
||||
"Seconds": 131176,
|
||||
"USeconds": 2435760640,
|
||||
"TimeBase": 2418,
|
||||
"Context": 210,
|
||||
"ProcTypes": 0,
|
||||
"UserData": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"DpState": 0,
|
||||
"DataSize": 1212,
|
||||
"headerHash": 2646027546,
|
||||
"dataHash": 4072048964
|
||||
},
|
||||
{
|
||||
"dataId": 2578,
|
||||
"data": "Test string"
|
||||
},
|
||||
{
|
||||
"dataId": 2579,
|
||||
"data": true
|
||||
},
|
||||
{
|
||||
"dataId": 2580,
|
||||
"data": -100
|
||||
},
|
||||
{
|
||||
"dataId": 2581,
|
||||
"data": 1.25
|
||||
},
|
||||
{
|
||||
"dataId": 2582,
|
||||
"data": [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
]
|
||||
},
|
||||
{
|
||||
"dataId": 2583,
|
||||
"data": [
|
||||
1.100000023841858,
|
||||
2.200000047683716,
|
||||
3.299999952316284
|
||||
]
|
||||
},
|
||||
{
|
||||
"dataId": 2584,
|
||||
"data": [
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
{
|
||||
"dataId": 2586,
|
||||
"size": 3,
|
||||
"data": [
|
||||
"String array element 0",
|
||||
"String array element 1",
|
||||
"String array element 2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"dataId": 2588,
|
||||
"size": 1,
|
||||
"data": [
|
||||
[
|
||||
"0 - String array record element 0",
|
||||
"0 - String array record element 1"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"dataId": 2587,
|
||||
"size": 2,
|
||||
"data": [
|
||||
[
|
||||
{
|
||||
"stringMember": "0 - String member"
|
||||
},
|
||||
{
|
||||
"stringArrayMember": [
|
||||
"0 - String array element 0",
|
||||
"0 - String array element 1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"stringMember": "1 - String member"
|
||||
},
|
||||
{
|
||||
"stringArrayMember": [
|
||||
"1 - String array element 0",
|
||||
"1 - String array element 1"
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"dataId": 2589,
|
||||
"data": [
|
||||
[
|
||||
"0 - String array element 0",
|
||||
"0 - String array element 1"
|
||||
],
|
||||
[
|
||||
"1 - String array element 0",
|
||||
"1 - String array element 1"
|
||||
],
|
||||
[
|
||||
"2 - String array element 0",
|
||||
"2 - String array element 1"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"dataId": 2591,
|
||||
"data": [
|
||||
[
|
||||
{
|
||||
"stringMember": "0 - String member"
|
||||
},
|
||||
{
|
||||
"stringArrayMember": [
|
||||
"0 - String array element 0",
|
||||
"0 - String array element 1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"stringMember": "1 - String member"
|
||||
},
|
||||
{
|
||||
"stringArrayMember": [
|
||||
"1 - String array element 0",
|
||||
"1 - String array element 1"
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"stringMember": "2 - String member"
|
||||
},
|
||||
{
|
||||
"stringArrayMember": [
|
||||
"2 - String array element 0",
|
||||
"2 - String array element 1"
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"dataId": 2585,
|
||||
"data": [
|
||||
"RED",
|
||||
"GREEN",
|
||||
"BLUE"
|
||||
]
|
||||
},
|
||||
{
|
||||
"dataId": 2590,
|
||||
"data": [
|
||||
{
|
||||
"integerMember": -1
|
||||
},
|
||||
{
|
||||
"floatMember": 2.5
|
||||
},
|
||||
{
|
||||
"stringMember": "String Member"
|
||||
},
|
||||
{
|
||||
"booleanMember": false
|
||||
},
|
||||
{
|
||||
"enumMember": "RED"
|
||||
},
|
||||
{
|
||||
"arrayMemberU32": [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
]
|
||||
},
|
||||
{
|
||||
"arrayMemberU32": [
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10
|
||||
]
|
||||
},
|
||||
{
|
||||
"F32Array": [
|
||||
4.400000095367432,
|
||||
5.5,
|
||||
6.599999904632568
|
||||
]
|
||||
},
|
||||
{
|
||||
"U32Array": [
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10
|
||||
]
|
||||
},
|
||||
{
|
||||
"enumArray": [
|
||||
"RED",
|
||||
"GREEN",
|
||||
"BLUE"
|
||||
]
|
||||
},
|
||||
{
|
||||
"stringArray": [
|
||||
"String array element 0",
|
||||
"String array element 1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"booleanArray": [
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
{
|
||||
"structWithStrings": [
|
||||
{
|
||||
"stringMember": "String member"
|
||||
},
|
||||
{
|
||||
"stringArrayMember": [
|
||||
"String array element 0",
|
||||
"String array element 1"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nestedArrays": [
|
||||
[
|
||||
"0 - String array element 0",
|
||||
"0 - String array element 1"
|
||||
],
|
||||
[
|
||||
"1 - String array element 0",
|
||||
"1 - String array element 1"
|
||||
],
|
||||
[
|
||||
"2 - String array element 0",
|
||||
"2 - String array element 1"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -58,6 +58,11 @@ module Ref {
|
||||
stack size Default.STACK_SIZE \
|
||||
priority 97
|
||||
|
||||
instance dpDemo: Ref.DpDemo base id 0x0A10 \
|
||||
queue size Default.QUEUE_SIZE \
|
||||
stack size Default.STACK_SIZE \
|
||||
priority 96
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Queued component instances
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
@ -41,6 +41,7 @@ module Ref {
|
||||
instance sendBuffComp
|
||||
instance typeDemo
|
||||
instance systemResources
|
||||
instance dpDemo
|
||||
instance linuxTimer
|
||||
instance comDriver
|
||||
instance cmdSeq
|
||||
@ -93,6 +94,7 @@ module Ref {
|
||||
rateGroup2Comp.RateGroupMemberOut[1] -> sendBuffComp.SchedIn
|
||||
rateGroup2Comp.RateGroupMemberOut[2] -> SG3.schedIn
|
||||
rateGroup2Comp.RateGroupMemberOut[3] -> SG4.schedIn
|
||||
rateGroup2Comp.RateGroupMemberOut[4] -> dpDemo.run
|
||||
|
||||
# Rate group 3
|
||||
rateGroupDriverComp.CycleOut[Ports_RateGroups.rateGroup3] -> rateGroup3Comp.CycleIn
|
||||
@ -132,7 +134,13 @@ module Ref {
|
||||
DataProducts.dpMgr.productResponseOut -> SG1.productRecvIn
|
||||
# Send filled DP
|
||||
SG1.productSendOut -> DataProducts.dpMgr.productSendIn
|
||||
|
||||
# Synchronous request
|
||||
dpDemo.productGetOut -> DataProducts.dpMgr.productGetIn
|
||||
# Send filled DP
|
||||
dpDemo.productSendOut -> DataProducts.dpMgr.productSendIn
|
||||
# Asynchronous request
|
||||
dpDemo.productRequestOut -> DataProducts.dpMgr.productRequestIn
|
||||
DataProducts.dpMgr.productResponseOut -> dpDemo.productRecvIn
|
||||
}
|
||||
|
||||
connections ComCcsds_CdhCore{
|
||||
@ -151,7 +159,7 @@ module Ref {
|
||||
# File Downlink <-> ComQueue
|
||||
FileHandling.fileDownlink.bufferSendOut -> ComCcsds.comQueue.bufferQueueIn[ComCcsds.Ports_ComBufferQueue.FILE]
|
||||
ComCcsds.comQueue.bufferReturnOut[ComCcsds.Ports_ComBufferQueue.FILE] -> FileHandling.fileDownlink.bufferReturn
|
||||
|
||||
|
||||
# Router <-> FileUplink
|
||||
ComCcsds.fprimeRouter.fileOut -> FileHandling.fileUplink.bufferSendIn
|
||||
FileHandling.fileUplink.bufferSendOut -> ComCcsds.fprimeRouter.fileBufferReturnIn
|
||||
@ -165,4 +173,4 @@ module Ref {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,8 +20,8 @@ Flask-Compress==1.15
|
||||
Flask-RESTful==0.3.10
|
||||
fprime-fpl-layout==1.0.3
|
||||
fprime-fpl-write-pic==1.0.3
|
||||
fprime-fpp==3.0.0a16
|
||||
fprime-gds==4.0.0a9
|
||||
fprime-fpp==3.0.0a18
|
||||
fprime-gds==4.0.0a10
|
||||
fprime-tools==4.0.0a9
|
||||
fprime-visual==1.0.2
|
||||
gcovr==8.2
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user