Merge pull request 'Fixes for Demo' (#2) from mueller/demo-fixes into master

Reviewed-on: #2
This commit is contained in:
Steffen Gaisser 2021-04-29 19:32:56 +02:00
commit fcf2d57253
30 changed files with 199 additions and 365 deletions

1
.gitmodules vendored
View File

@ -13,4 +13,3 @@
[submodule "fsfw"]
path = fsfw
url = https://egit.irs.uni-stuttgart.de/fsfw/fsfw.git

View File

@ -3,6 +3,7 @@
#include <bsp_hosted/core/InitMission.h>
#include <bsp_hosted/fsfwconfig/objects/systemObjectList.h>
#include <bsp_hosted/fsfwconfig/pollingsequence/pollingSequenceFactory.h>
#include <fsfw/modes/HasModesIF.h>
#include <mission/utility/TaskCreation.h>
@ -11,6 +12,7 @@
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include <fsfw/tasks/PeriodicTaskIF.h>
#include <fsfw/tasks/TaskFactory.h>
#include <mission/assemblies/TestAssembly.h>
#ifdef _WIN32
#include <fsfw/osal/windows/winTaskHelpers.h>
@ -185,10 +187,13 @@ void InitMission::createTasks() {
#if OBSW_ADD_DEVICE_HANDLER_DEMO == 1
#ifdef __unix__
currPrio = 40;
currPrio = 60;
#elif _WIN32
currPrio = tasks::makeWinPriority(tasks::PriorityClass::CLASS_HIGH,
tasks::PriorityNumber::HIGHEST);
#endif
FixedTimeslotTaskIF* testDevicesTimeslotTask = taskFactory->createFixedTimeslotTask(
"PST_TEST_TASK", currPrio, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, deadlineMissedFunc);
"PST_TEST_TASK", currPrio, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, deadlineMissedFunc);
result = pst::pollingSequenceDevices(testDevicesTimeslotTask);
if(result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@ -196,6 +201,21 @@ void InitMission::createTasks() {
#else
sif::printError("InitMission::createTasks: Test PST initialization failed!\n");
#endif
}
#if _WIN32
currPrio = tasks::makeWinPriority();
#endif
PeriodicTaskIF* assemblyTask = taskFactory->createPeriodicTask("ASS_TASK", currPrio,
PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, nullptr);
if(assemblyTask == nullptr){
task::printInitError("ASS_TASK", objects::TEST_ASSEMBLY);
}
result = assemblyTask->addComponent(objects::TEST_ASSEMBLY);
if(result != HasReturnvaluesIF::RETURN_OK) {
task::printInitError("ASS_TASK", objects::TEST_ASSEMBLY);
}
#endif /* OBSW_ADD_DEVICE_HANDLER_DEMO == 1 */
@ -247,6 +267,7 @@ void InitMission::createTasks() {
#if OBSW_ADD_DEVICE_HANDLER_DEMO == 1
testDevicesTimeslotTask->startTask();
assemblyTask->startTask();
#endif /* OBSW_ADD_DEVICE_HANDLER_DEMO == 1 */
#if OBSW_ADD_CONTROLLER_DEMO == 1
@ -260,6 +281,30 @@ void InitMission::createTasks() {
#else
sif::printInfo("Tasks started..\n");
#endif
#if OBSW_ADD_DEVICE_HANDLER_DEMO
HasModesIF* assembly = objectManager->get<HasModesIF>(objects::TEST_ASSEMBLY);
if (assembly == nullptr){
return;
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Waiting 5 Seconds and then command Test Assembly to Normal, Dual" << std::endl;
#else
sif::printInfo("Waiting 5 Seconds and then command Test Assembly to Normal, Dual \n");
#endif
TaskFactory::delayTask(5000);
CommandMessage modeMessage;
ModeMessage::setModeMessage(&modeMessage, ModeMessage::CMD_MODE_COMMAND,
DeviceHandlerIF::MODE_NORMAL, TestAssembly::submodes::DUAL);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Commanding Test Assembly to Normal, Dual" << std::endl;
#else
sif::printInfo("Commanding Test Assembly to Normal, Dual \n");
#endif
MessageQueueSenderIF::sendMessage(assembly->getCommandQueue(), &modeMessage,
MessageQueueIF::NO_QUEUE);
#endif /* OBSW_ADD_DEVICE_HANDLER_DEMO */
}

View File

@ -47,8 +47,9 @@ void ObjectFactory::produce(){
}
/* TMTC Reception via UDP socket */
new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_DISTRIBUTOR,
auto tmtcBridge = new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_DISTRIBUTOR,
objects::TM_STORE, objects::TC_STORE);
tmtcBridge->setMaxNumberOfPacketsStored(20);
new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
#endif /* OBSW_ADD_CORE_COMPONENTS == 1 */

View File

@ -145,23 +145,14 @@ void InitMission::createTasks() {
sif::printError("InitMission::createTasks: Test PST initialization failed!\n\r");
#endif
}
PeriodicTaskIF* assemblyTask = taskFactory->createPeriodicTask("ASS_TASK", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, nullptr);
PeriodicTaskIF* assemblyTask = taskFactory->createPeriodicTask("ASS_TASK", 30,
PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, nullptr);
if(assemblyTask == nullptr){
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "InitMission::createTasks: Test Assembly Task creation failed!" << std::endl;
#else
sif::printError("InitMission::createTasks: Test Assembly Task creation failed!\n\r");
#endif
task::printInitError("ASS_TASK", objects::TEST_ASSEMBLY);
}
result = assemblyTask->addComponent(objects::TEST_ASSEMBLY);
if(result != HasReturnvaluesIF::RETURN_OK) {
if(assemblyTask == nullptr){
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "InitMission::createTasks: Test Assembly Task adding failed!" << std::endl;
#else
sif::printError("InitMission::createTasks: Test Assembly Task adding failed!\n\r");
#endif
}
task::printInitError("ASS_TASK", objects::TEST_ASSEMBLY);
}
#endif /* OBSW_ADD_DEVICE_HANDLER_DEMO == 1 */
@ -237,12 +228,14 @@ void InitMission::createTasks() {
TaskFactory::delayTask(5000);
CommandMessage modeMessage;
ModeMessage::setModeMessage(&modeMessage, ModeMessage::CMD_MODE_COMMAND, DeviceHandlerIF::MODE_NORMAL, TestAssembly::submodes::DUAL);
ModeMessage::setModeMessage(&modeMessage, ModeMessage::CMD_MODE_COMMAND,
DeviceHandlerIF::MODE_NORMAL, TestAssembly::submodes::DUAL);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Commanding Test Assembly to Normal, Dual" << std::endl;
#else
sif::printInfo("Commanding Test Assembly to Normal, Dual \n");
#endif
MessageQueueSenderIF::sendMessage(assembly->getCommandQueue(), &modeMessage, MessageQueueIF::NO_QUEUE);
#endif
MessageQueueSenderIF::sendMessage(assembly->getCommandQueue(), &modeMessage,
MessageQueueIF::NO_QUEUE);
#endif /* OBSW_ADD_DEVICE_HANDLER_DEMO */
}

View File

@ -9,7 +9,7 @@
//! Specify the debug output verbose level
#define OBSW_VERBOSE_LEVEL 1
#define OBSW_PRINT_MISSED_DEADLINES 1
#define OBSW_PRINT_MISSED_DEADLINES 0
//! Add core components for the FSFW and for TMTC communication
#define OBSW_ADD_CORE_COMPONENTS 1

View File

@ -136,11 +136,11 @@ switching between FreeRTOS and RTEMS. You can try the following steps:
the OpenOCD folder inside the `scripts/target` folder:
```sh
$_CHIPNAME.cpu configure -event gdb-attach {
$_CHIPNAME.cpu0 configure -event gdb-attach {
halt
}
$_CHIPNAME.cpu configure -event gdb-attach {
$_CHIPNAME.cpu0 configure -event gdb-attach {
reset init
}
```

2
fsfw

@ -1 +1 @@
Subproject commit 2f511523cb71e00b4669db002b171d626a63fddf
Subproject commit 9f8373977179b79fabd5d56bc999d8cac2078d8c

View File

@ -1,197 +0,0 @@
#! /usr/bin/env python3
import string
import sys
import datetime
import collections
import re
import os
import fileinput
import getpass
import MySQLdb
def parseInterfaceDefinitionFile( fwFilename, missionFilename ):
file = open(fwFilename, "r")
interfaces = dict()
allLines = file.readlines()
count = 0
for line in allLines:
match = re.search( '[\s]*([A-Z_0-9]*) = ([0-9]*)\,[\s]*//([A-Z]{1,3})', line)
if match:
count = int(match.group(2));
print("Count is " + str(count))
interfaces.update( {match.group(1): [1, match.group(3)]} )
for line in allLines:
match = re.search( '[\s]*([A-Z_0-9]*),[\s]*//([A-Z]{1,3})', line)
if match:
interfaces.update( {match.group(1): [count, match.group(2)]} )
count += 1
file = open(missionFilename, "r")
allLines = file.readlines()
for line in allLines:
match = re.search( '[\s]*([A-Z_0-9]*) = FW_CLASS_ID_COUNT\,[\s]*//([A-Z]{1,3})', line)
if match:
interfaces.update( {match.group(1): [count, match.group(2)]} )
count += 1
for line in allLines:
match = re.search( '^[\s]*([A-Z_0-9]*),[\s]*//([A-Z]{1,3})', line)
if match:
interfaces.update( {match.group(1): [count, match.group(2)]} )
count += 1
print("Found interfaces : " + str(count - 1))
return interfaces
def returnNumberFromString( aString ):
if aString.startswith('0x'):
return int( aString, 16)
elif aString.isdigit():
return int( aString)
else:
print('Error: Illegeal number representation: ' + aString)
return 0
def convert(name):
singleStrings = name.split('_')
newString = ''
for oneString in singleStrings:
oneString = oneString.lower()
oneString = oneString.capitalize()
newString = newString + oneString
return newString
def buildCheckedString( firstPart, secondPart ):
myStr = firstPart + convert(secondPart)
if len(myStr) > 14:
print( "Error: Entry: " + myStr + " too long. Will truncate.")
myStr = myStr[0:14]
else:
print( "Entry: " + myStr + " is all right.")
return myStr
def cleanUpDescription( descrString ):
description = descrString.lstrip('!<- ')
if description == '':
description = ' '
return description
def parseHeaderFiles( interfaceList, fileList):
dictionnary = dict()
count = 0
currentId = 0
currentName = ""
#Add OK and UNSPECIFIED_FAILED
dictionnary.update( {0: ('OK', 'System-wide code for ok.', 'RETURN_OK', 'HasReturnvaluesIF.h', 'HasReturnvaluesIF')} )
dictionnary.update( {1: ('Failed', 'Unspecified system-wide code for failed.', 'RETURN_FAILED', 'HasReturnvaluesIF.h', 'HasReturnvaluesIF')} )
for fileName in fileList:
file = open(fileName, "r")
oldline = file.readline()
while True:
newline = file.readline()
if not newline: break #EOF
if not oldline == '\n':
twoLines = oldline + ' ' + newline.strip()
else:
twoLines = ''
match1 = re.search ( 'INTERFACE_ID[\s]*=[\s]*CLASS_ID::([a-zA-Z_0-9]*)', twoLines)
if match1:
currentId = interfaceList[match1.group(1)][0]
currentName = interfaceList[match1.group(1)][1]
currentFullName = match1.group(1)
#print( "Current ID: " + str(currentId) )
myId = currentId
match = re.search( '^[\s]*static const ReturnValue_t[\s]*([a-zA-Z_0-9]*)[\s]*=[\s]*MAKE_RETURN_CODE[\s]*\([\s]*([x0-9a-fA-F]{1,4})[\s]*\);[\t ]*(\/\/){0,1}([^\n]*)', twoLines)
if match:
# valueTable.append([])
description = cleanUpDescription(match.group(4))
stringToAdd = buildCheckedString( currentName, match.group(1))
fullId = (myId << 8) + returnNumberFromString(match.group(2))
if fullId in dictionnary:
print('duplicate returncode ' + hex(fullId) + ' from ' + fileName + ' was already in ' + dictionnary[fullId][3])
dictionnary.update( {fullId: (stringToAdd, description, match.group(1), fileName, currentFullName)} )
# valueTable[count].append(fullId)
# valueTable[count].append(stringToAdd)
count = count+1
else:
None
oldline = newline
# valueTable.pop()
return dictionnary
def getHeaderFileList( base ):
#print ( "getHeaderFileList called with" + base )
baseList = os.listdir( base )
fileList = []
for entry in baseList:
#Remove all hidden files:
if ( (os.path.isdir(base + entry) == True) and (entry[0] != ".") and (entry[0] != "_") ):
fileList = fileList + getHeaderFileList(base + entry + "/")
if re.match("[^\.]*\.h", entry) and os.path.isfile(base + entry):
fileList.append(base + entry)
return fileList
def writeEntriesToDB( listOfEntries ):
print ("Connecting to database...")
user = getpass.getpass("User: ")
passwd = getpass.getpass()
conn = MySQLdb.connect(host = "127.0.0.1", user = user, passwd = passwd, db = "flpmib")
written = conn.cursor()
print ("done.")
#delete old entries
print ("Kill old entries.")
written.execute("DELETE FROM txp WHERE TXP_NUMBR = 'DSX00000'")
print("Insert new ones:")
for entry in listOfEntries.items():
written.execute("INSERT INTO txp (txp_numbr, txp_from, txp_to, txp_altxt) VALUES ('DSX00000', %s, %s, %s)", [entry[0], entry[0], entry[1][0]])
conn.commit()
print("Done. That was easy.")
def writeEntriesToOtherDB( listOfEntries ):
print ("Connecting to other database...")
conn = MySQLdb.connect(host = "buggy.irs.uni-stuttgart.de", user = 'returncode', passwd = 'returncode', db = "returncode")
written = conn.cursor()
print ("connected.")
#delete old entries
print ("Kill old entries.")
written.execute("DELETE FROM returncodes WHERE true")
print("Insert new ones:")
for entry in listOfEntries.items():
written.execute("INSERT INTO returncodes (code,name,interface,file,description) VALUES (%s, %s, %s, %s, %s)", [entry[0], entry[1][2], entry[1][4], entry[1][3], entry[1][1]])
conn.commit()
print("Done. That was hard.")
def exportToFile( filename, listOfEntries ):
print ('Exporting to file: ' + filename )
file = open(filename, "w")
for entry in listOfEntries.items():
file.write(hex(entry[0]) + '\t' + entry[1][0] + '\t' + entry[1][1] + '\t' + entry[1][2] + '\t' + entry[1][3] + '\t' + entry[1][4] + '\n' )
file.close()
return
def parseOBSW():
idInterfaceDefinitions = parseInterfaceDefinitionFile( "../../framework/returnvalues/FwClassIds.h", "../../config/returnvalues/classIds.h")
#print ("Dictionary size is " + str(len(idInterfaceDefinitions)) )
for entry in sorted(idInterfaceDefinitions):
print(entry)
myHeaderList = getHeaderFileList( "../../mission/" )
myHeaderList = myHeaderList + getHeaderFileList( "../../framework/" )
myHeaderList = myHeaderList + getHeaderFileList( "../../config/" )
myHeaderList = myHeaderList + getHeaderFileList( "../../bsp_linux/" )
mySecondList = parseHeaderFiles( idInterfaceDefinitions, myHeaderList)
# print(mySecondList[14081])
# print (mySecondList.items()[0][1])
# print( "Found entries:" )
counter = 0
# for entry in sorted(mySecondList):
# print(entry)
for entry in mySecondList.items():
counter = counter + 1
# print( entry[0], entry[1][0], entry[1][1] )
print("Count: ", counter)
if (len(sys.argv) > 1):
exportToFile( str(sys.argv[1]), mySecondList )
else:
print('No export to file requested.')
#writeEntriesToOtherDB( mySecondList )
#writeEntriesToDB( mySecondList )
parseOBSW()

View File

@ -1,16 +1,11 @@
/*
* TestAssembly.cpp
*
* Created on: Apr 20, 2021
* Author: steffen
*/
#include <mission/assemblies/TestAssembly.h>
#include <common/config/commonSystemObjects.h>
#include <fsfw/objectmanager/ObjectManagerIF.h>
TestAssembly::TestAssembly(object_id_t objectId, object_id_t parentId):AssemblyBase(objectId, parentId) {
TestAssembly::TestAssembly(object_id_t objectId, object_id_t parentId):
AssemblyBase(objectId, parentId) {
ModeListEntry newModeListEntry;
newModeListEntry.setObject(objects::TEST_DEVICE_HANDLER_0);
newModeListEntry.setMode(MODE_OFF);
@ -32,9 +27,10 @@ TestAssembly::~TestAssembly() {
ReturnValue_t TestAssembly::commandChildren(Mode_t mode,
Submode_t submode) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "TestAssembly: Received command to go to mode " << mode << " submode " << (int) submode << std::endl;
sif::info << "TestAssembly: Received command to go to mode " << mode <<
" submode " << (int) submode << std::endl;
#else
sif::printInfo("TestAssembly: Received command to go to other mode \n");
sif::printInfo("TestAssembly: Received command to go to mode %d submode %d\n", mode, submode);
#endif
ReturnValue_t result = RETURN_OK;
if(mode == MODE_OFF){
@ -42,52 +38,60 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode,
commandTable[0].setSubmode(SUBMODE_NONE);
commandTable[1].setMode(MODE_OFF);
commandTable[1].setSubmode(SUBMODE_NONE);
}else if(mode == DeviceHandlerIF::MODE_NORMAL){
}
else if(mode == DeviceHandlerIF::MODE_NORMAL) {
if(submode == submodes::SINGLE){
commandTable[0].setMode(MODE_OFF);
commandTable[0].setSubmode(SUBMODE_NONE);
commandTable[1].setMode(MODE_OFF);
commandTable[1].setSubmode(SUBMODE_NONE);
// We try to prefer 0 here but we try to switch to 1 even if it might fail
if(isDeviceAvailable(objects::TEST_DEVICE_HANDLER_0)){
if (childrenMap[objects::TEST_DEVICE_HANDLER_0].mode == MODE_ON){
if(isDeviceAvailable(objects::TEST_DEVICE_HANDLER_0)) {
if (childrenMap[objects::TEST_DEVICE_HANDLER_0].mode == MODE_ON) {
commandTable[0].setMode(mode);
commandTable[0].setSubmode(SUBMODE_NONE);
}else{
}
else {
commandTable[0].setMode(MODE_ON);
commandTable[0].setSubmode(SUBMODE_NONE);
result = NEED_SECOND_STEP;
}
}else{
if (childrenMap[objects::TEST_DEVICE_HANDLER_1].mode == MODE_ON){
}
else {
if (childrenMap[objects::TEST_DEVICE_HANDLER_1].mode == MODE_ON) {
commandTable[1].setMode(mode);
commandTable[1].setSubmode(SUBMODE_NONE);
}else{
}
else{
commandTable[1].setMode(MODE_ON);
commandTable[1].setSubmode(SUBMODE_NONE);
result = NEED_SECOND_STEP;
}
}
}else{
}
else{
// Dual Mode Normal
if (childrenMap[objects::TEST_DEVICE_HANDLER_0].mode == MODE_ON){
if (childrenMap[objects::TEST_DEVICE_HANDLER_0].mode == MODE_ON) {
commandTable[0].setMode(mode);
commandTable[0].setSubmode(SUBMODE_NONE);
}else{
}
else{
commandTable[0].setMode(MODE_ON);
commandTable[0].setSubmode(SUBMODE_NONE);
result = NEED_SECOND_STEP;
}
if (childrenMap[objects::TEST_DEVICE_HANDLER_1].mode == MODE_ON){
if (childrenMap[objects::TEST_DEVICE_HANDLER_1].mode == MODE_ON) {
commandTable[1].setMode(mode);
commandTable[1].setSubmode(SUBMODE_NONE);
}else{
}
else{
commandTable[1].setMode(MODE_ON);
commandTable[1].setSubmode(SUBMODE_NONE);
result = NEED_SECOND_STEP;
}
}
}else{
}
else{
//Mode ON
if(submode == submodes::SINGLE){
commandTable[0].setMode(MODE_OFF);
@ -98,11 +102,13 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode,
if(isDeviceAvailable(objects::TEST_DEVICE_HANDLER_0)){
commandTable[0].setMode(MODE_ON);
commandTable[0].setSubmode(SUBMODE_NONE);
}else{
}
else{
commandTable[1].setMode(MODE_ON);
commandTable[1].setSubmode(SUBMODE_NONE);
}
}else{
}
else{
commandTable[0].setMode(MODE_ON);
commandTable[0].setSubmode(SUBMODE_NONE);
commandTable[1].setMode(MODE_ON);
@ -167,14 +173,15 @@ ReturnValue_t TestAssembly::initialize() {
ReturnValue_t TestAssembly::checkChildrenStateOn(
Mode_t wantedMode, Submode_t wantedSubmode) {
if(submode == submodes::DUAL){
for(const auto& info:childrenMap){
for(const auto& info:childrenMap) {
if(info.second.mode != wantedMode or info.second.mode != wantedSubmode){
return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE;
}
}
return RETURN_OK;
}else if(submode == submodes::SINGLE){
for(const auto& info:childrenMap){
}
else if(submode == submodes::SINGLE) {
for(const auto& info:childrenMap) {
if(info.second.mode == wantedMode and info.second.mode != wantedSubmode){
return RETURN_OK;
}
@ -186,7 +193,8 @@ ReturnValue_t TestAssembly::checkChildrenStateOn(
bool TestAssembly::isDeviceAvailable(object_id_t object) {
if(healthHelper.healthTable->getHealth(object) == HasHealthIF::HEALTHY){
return true;
}else{
}
else{
return false;
}
}

View File

@ -1,10 +1,3 @@
/*
* TestAssembly.h
*
* Created on: Apr 20, 2021
* Author: steffen
*/
#ifndef MISSION_ASSEMBLIES_TESTASSEMBLY_H_
#define MISSION_ASSEMBLIES_TESTASSEMBLY_H_

View File

@ -95,10 +95,13 @@ void ObjectFactory::produceGenericObjects() {
/* Demo device handler object */
size_t expectedMaxReplyLen = 64;
CookieIF* testCookie = new TestCookie(0, expectedMaxReplyLen);
CookieIF* testCookie = new DummyCookie(
static_cast<address_t>(testdevice::DeviceIndex::DEVICE_0), expectedMaxReplyLen);
new TestEchoComIF(objects::TEST_ECHO_COM_IF);
new TestDevice(objects::TEST_DEVICE_HANDLER_0, objects::TEST_ECHO_COM_IF, testCookie,
testdevice::DeviceIndex::DEVICE_0, enableInfoPrintout);
testCookie = new DummyCookie(
static_cast<address_t>(testdevice::DeviceIndex::DEVICE_1), expectedMaxReplyLen);
new TestDevice(objects::TEST_DEVICE_HANDLER_1, objects::TEST_ECHO_COM_IF, testCookie,
testdevice::DeviceIndex::DEVICE_1, enableInfoPrintout);

View File

@ -1,14 +1,14 @@
#include "TestCookie.h"
TestCookie::TestCookie(address_t address, size_t replyMaxLen):
DummyCookie::DummyCookie(address_t address, size_t replyMaxLen):
address(address), replyMaxLen(replyMaxLen) {}
TestCookie::~TestCookie() {}
DummyCookie::~DummyCookie() {}
address_t TestCookie::getAddress() const {
address_t DummyCookie::getAddress() const {
return address;
}
size_t TestCookie::getReplyMaxLen() const {
size_t DummyCookie::getReplyMaxLen() const {
return replyMaxLen;
}

View File

@ -7,10 +7,10 @@
/**
* @brief Really simple cookie which does not do a lot.
*/
class TestCookie: public CookieIF {
class DummyCookie: public CookieIF {
public:
TestCookie(address_t address, size_t maxReplyLen);
virtual ~TestCookie();
DummyCookie(address_t address, size_t maxReplyLen);
virtual ~DummyCookie();
address_t getAddress() const;
size_t getReplyMaxLen() const;

View File

@ -338,6 +338,7 @@ ReturnValue_t TestDevice::scanForReply(const uint8_t *start, size_t len,
}
DeviceCommandId_t pendingCmd = this->getPendingCommand();
switch(pendingCmd) {
case(TEST_NORMAL_MODE_CMD): {

View File

@ -58,7 +58,7 @@ protected:
testdevice::TestDataSet dataset;
//! This is used to reset the dataset after a commanded change has been made.
bool resetAfterChange = false;
bool commandSent = true;
bool commandSent = false;
/** DeviceHandlerBase overrides (see DHB documentation) */

View File

@ -14,35 +14,44 @@ TestEchoComIF::TestEchoComIF(object_id_t objectId):
TestEchoComIF::~TestEchoComIF() {}
ReturnValue_t TestEchoComIF::initializeInterface(CookieIF * cookie) {
TestCookie* testCookie = dynamic_cast<TestCookie*>(cookie);
if(testCookie == nullptr) {
DummyCookie* dummyCookie = dynamic_cast<DummyCookie*>(cookie);
if(dummyCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TestEchoComIF::initializeInterface: Invalid cookie!" << std::endl;
#else
sif::printWarning("TestEchoComIF::initializeInterface: Invalid cookie!\n");
#endif
return NULLPOINTER;
}
auto resultPair = replyMap.emplace(
dummyCookie->getAddress(), ReplyBuffer(dummyCookie->getReplyMaxLen()));
if(not resultPair.second) {
return HasReturnvaluesIF::RETURN_FAILED;
}
replyBuffer.reserve(testCookie->getReplyMaxLen());
replyBuffer.resize(testCookie->getReplyMaxLen());
return RETURN_OK;
}
ReturnValue_t TestEchoComIF::sendMessage(CookieIF *cookie,
const uint8_t * sendData, size_t sendLen) {
if(sendLen > replyBuffer.size()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TestEchoComIF::sendMessage: Send length larger than current reply buffer "
"length. Allocating additional memory!" << std::endl;
#else
sif::printWarning("TestEchoComIF::sendMessage: Send length larger than current reply buffer "
"length. Allocating additional memory!\n");
#endif
replyBuffer.reserve(sendLen);
replyBuffer.resize(sendLen);
DummyCookie* dummyCookie = dynamic_cast<DummyCookie*>(cookie);
if(dummyCookie == nullptr) {
return NULLPOINTER;
}
memcpy(replyBuffer.data(),sendData, sendLen);
dummyBufferSize = sendLen;
ReplyBuffer& replyBuffer = replyMap.find(dummyCookie->getAddress())->second;
if(sendLen > replyBuffer.capacity()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TestEchoComIF::sendMessage: Send length " << sendLen << " larger than "
"current reply buffer length!" << std::endl;
#else
sif::printWarning("TestEchoComIF::sendMessage: Send length %d larger than current "
"reply buffer length!\n", sendLen);
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
replyBuffer.resize(sendLen);
memcpy(replyBuffer.data(), sendData, sendLen);
return RETURN_OK;
}
@ -57,9 +66,14 @@ ReturnValue_t TestEchoComIF::requestReceiveMessage(CookieIF *cookie,
ReturnValue_t TestEchoComIF::readReceivedMessage(CookieIF *cookie,
uint8_t **buffer, size_t *size) {
DummyCookie* dummyCookie = dynamic_cast<DummyCookie*>(cookie);
if(dummyCookie == nullptr) {
return NULLPOINTER;
}
ReplyBuffer& replyBuffer = replyMap.find(dummyCookie->getAddress())->second;
*buffer = replyBuffer.data();
*size = dummyBufferSize;
this->dummyBufferSize = 0;
*size = replyBuffer.size();
dummyReplyCounter ++;
if(dummyReplyCounter == 10) {

View File

@ -45,8 +45,9 @@ private:
MessageQueueIF* tmQueue = nullptr;
size_t replyMaxLen = 0;
std::vector<uint8_t> replyBuffer;
uint32_t dummyBufferSize = 0;
using ReplyBuffer = std::vector<uint8_t>;
std::map<address_t, ReplyBuffer> replyMap;
uint8_t dummyReplyCounter = 0;
uint16_t packetSubCounter = 0;

View File

@ -55,10 +55,10 @@ static constexpr DeviceCommandId_t TEST_NOTIF_SNAPSHOT_SET = 4;
* DEVICE_1: Sets the vector mean values below a treshold (mean less than -20) to trigger a
* set snapshot
*/
static constexpr DeviceCommandId_t TEST_SNAPSHOT = 4;
static constexpr DeviceCommandId_t TEST_SNAPSHOT = 5;
//! Generates a random value for variable 1 of the dataset.
static constexpr DeviceCommandId_t GENERATE_SET_VAR_1_RNG_VALUE = 5;
static constexpr DeviceCommandId_t GENERATE_SET_VAR_1_RNG_VALUE = 6;
/**

View File

@ -15,5 +15,7 @@ def perform_mode_operation_user(tmtc_backend: TmTcHandler, mode: int):
"""
Custom modes can be implemented here
"""
if tmtc_backend:
pass
LOGGER.error(f"Unknown mode {mode}, Configuration error !")
sys.exit()

View File

@ -21,9 +21,9 @@ class FsfwHookBase(TmTcHookBase):
from tmtccmd.defaults.globals_setup import set_default_globals_pre_args_parsing
set_default_globals_pre_args_parsing(gui=gui, apid=0xef)
def add_globals_post_args_parsing(self, args: argparse.Namespace):
def add_globals_post_args_parsing(self, args: argparse.Namespace, json_cfg_path: str = ""):
from tmtccmd.defaults.globals_setup import set_default_globals_post_args_parsing
set_default_globals_post_args_parsing(args=args)
set_default_globals_post_args_parsing(args=args, json_cfg_path=json_cfg_path)
def assign_communication_interface(self, com_if: int, tmtc_printer: TmTcPrinter) -> \
Union[CommunicationInterface, None]:
@ -45,7 +45,7 @@ class FsfwHookBase(TmTcHookBase):
from pus_tm.factory_hook import tm_user_factory_hook
return tm_user_factory_hook(raw_tm_packet=raw_tm_packet)
def set_object_ids(self) -> Dict[int, bytearray]:
def set_object_ids(self) -> Dict[bytes, list]:
from config.object_ids import set_object_ids
return set_object_ids()
@ -60,7 +60,7 @@ class FsfwHookBase(TmTcHookBase):
@staticmethod
def handle_service_3_housekeeping(
object_id: int, set_id: int, hk_data: bytearray, service3_packet: Service3Base
object_id: bytearray, set_id: int, hk_data: bytearray, service3_packet: Service3Base
) -> Tuple[list, list, bytearray, int]:
from pus_tm.service_3_hk_handling import service_3_hk_handling
return service_3_hk_handling(
@ -70,5 +70,8 @@ class FsfwHookBase(TmTcHookBase):
def command_preparation_hook(self) -> Union[None, PusTelecommand]:
pass
def set_json_config_file_path(self) -> str:
return "config/tmtc_config.json"

View File

@ -4,20 +4,17 @@
it to your needs.
"""
import enum
from typing import Dict
class ObjectIds(enum.IntEnum):
PUS_SERVICE_17 = 1
TEST_DEVICE_0 = 2
TEST_DEVICE_1 = 3
SERVICE_17_OBJ_ID = bytes([0x53, 0x00, 0x00, 0x17])
TEST_DEVICE_0_OBJ_ID = bytes([0x44, 0x01, 0xAF, 0xFE])
TEST_DEVICE_1_OBJ_ID = bytes([0x44, 0x02, 0xAF, 0xFE])
def set_object_ids() -> Dict[int, bytearray]:
def set_object_ids() -> Dict[bytes, list]:
object_id_dict = {
ObjectIds.PUS_SERVICE_17: bytearray([0x53, 0x00, 0x00, 0x17]),
ObjectIds.TEST_DEVICE_0: bytearray([0x44, 0x01, 0xAF, 0xFE]),
ObjectIds.TEST_DEVICE_1: bytearray([0x44, 0x02, 0xAF, 0xFE]),
SERVICE_17_OBJ_ID: ["Service 17"],
TEST_DEVICE_0_OBJ_ID: ["Test Device 0"],
TEST_DEVICE_1_OBJ_ID: ["Test Device 1"],
}
return object_id_dict

View File

@ -5,22 +5,14 @@
@author R. Mueller
@date 02.05.2020
"""
from config.object_ids import ObjectIds
from config.object_ids import TEST_DEVICE_0_OBJ_ID, TEST_DEVICE_1_OBJ_ID
from tmtccmd.core.definitions import QueueCommands
from tmtccmd.ecss.tc import PusTelecommand
from tmtccmd.pus_tc.packer import TcQueueT
from tmtccmd.pus_tc.service_200_mode import pack_mode_data
TEST_DEVICE_0_ID = bytearray()
TEST_DEVICE_1_ID = bytearray()
def pack_service_200_commands_into(tc_queue: TcQueueT, op_code: str):
from tmtccmd.core.object_id_manager import get_object_id
global TEST_DEVICE_1_ID, TEST_DEVICE_0_ID
if TEST_DEVICE_0_ID == bytearray() or TEST_DEVICE_1_ID == bytearray:
TEST_DEVICE_0_ID = get_object_id(ObjectIds.TEST_DEVICE_0)
TEST_DEVICE_1_ID = get_object_id(ObjectIds.TEST_DEVICE_1)
if op_code == "0":
pack_service_200_test_into(tc_queue=tc_queue, init_ssc=2000)
@ -29,7 +21,7 @@ def pack_service_200_test_into(init_ssc: int, tc_queue: TcQueueT) -> int:
new_ssc = init_ssc
tc_queue.appendleft((QueueCommands.PRINT, "Testing Service 200"))
# Object ID: DUMMY Device
object_id = TEST_DEVICE_0_ID
object_id = TEST_DEVICE_0_OBJ_ID
# Set On Mode
tc_queue.appendleft((QueueCommands.PRINT, "Testing Service 200: Set Mode On"))
mode_data = pack_mode_data(object_id, 1, 0)

View File

@ -1,7 +1,6 @@
import struct
from tmtccmd.core.definitions import QueueCommands
from tmtccmd.core.object_id_manager import get_object_id
from tmtccmd.ecss.tc import PusTelecommand
from tmtccmd.pus_tc.definitions import TcQueueT
from tmtccmd.pus_tc.service_20_parameter import pack_type_and_matrix_data, \
@ -9,16 +8,14 @@ from tmtccmd.pus_tc.service_20_parameter import pack_type_and_matrix_data, \
from tmtccmd.pus_tc.service_200_mode import pack_mode_data
from tmtccmd.utility.tmtcc_logger import get_logger
from config.object_ids import ObjectIds
from config.object_ids import TEST_DEVICE_0_OBJ_ID
LOGGER = get_logger()
TEST_DEVICE_0_ID = bytearray()
def pack_service20_commands_into(tc_queue: TcQueueT, op_code: str):
global TEST_DEVICE_0_ID
if TEST_DEVICE_0_ID == bytearray():
TEST_DEVICE_0_ID = get_object_id(ObjectIds.TEST_DEVICE_0)
if op_code == "0":
pack_service20_test_into(tc_queue=tc_queue)
@ -26,7 +23,7 @@ def pack_service20_commands_into(tc_queue: TcQueueT, op_code: str):
def pack_service20_test_into(tc_queue: TcQueueT, called_externally: bool = False):
if called_externally is False:
tc_queue.appendleft((QueueCommands.PRINT, "Testing Service 20"))
object_id = TEST_DEVICE_0_ID
object_id = TEST_DEVICE_0_OBJ_ID
# set mode normal
tc_queue.appendleft((QueueCommands.PRINT, "Testing Service 20: Set Normal Mode"))
@ -43,7 +40,7 @@ def pack_service20_test_into(tc_queue: TcQueueT, called_externally: bool = False
def load_param_0_simple_test_commands(tc_queue: TcQueueT):
object_id = TEST_DEVICE_0_ID
object_id = TEST_DEVICE_0_OBJ_ID
parameter_id_0 = pack_parameter_id(domain_id=0, unique_id=0, linear_index=0)
# test checking Load for uint32_t
tc_queue.appendleft((QueueCommands.PRINT, "Testing Service 20: Load uint32_t"))

View File

@ -8,23 +8,15 @@
import struct
from tmtccmd.core.definitions import QueueCommands
from tmtccmd.core.object_id_manager import get_object_id
from tmtccmd.ecss.tc import PusTelecommand
from tmtccmd.pus_tc.definitions import TcQueueT
from pus_tc.service_200_mode import pack_mode_data
import pus_tc.command_data as cmd_data
from config.object_ids import ObjectIds
TEST_DEVICE_0_ID = bytearray()
TEST_DEVICE_1_ID = bytearray()
from config.object_ids import TEST_DEVICE_0_OBJ_ID, TEST_DEVICE_1_OBJ_ID
def pack_service_2_commands_into(tc_queue: TcQueueT, op_code: str):
global TEST_DEVICE_0_ID, TEST_DEVICE_1_ID
if TEST_DEVICE_0_ID == 0 or TEST_DEVICE_1_ID == 0:
TEST_DEVICE_0_ID = get_object_id(ObjectIds.TEST_DEVICE_0)
TEST_DEVICE_1_ID = get_object_id(ObjectIds.TEST_DEVICE_0)
if op_code == "0":
pack_generic_service_2_test_into(0, tc_queue)
else:
@ -33,7 +25,7 @@ def pack_service_2_commands_into(tc_queue: TcQueueT, op_code: str):
def pack_generic_service_2_test_into(init_ssc: int, tc_queue: TcQueueT) -> int:
new_ssc = init_ssc
object_id = TEST_DEVICE_0_ID # dummy device
object_id = TEST_DEVICE_0_OBJ_ID # dummy device
# Set Raw Mode
tc_queue.appendleft((QueueCommands.PRINT, "Testing Service 2: Setting Raw Mode"))
mode_data = pack_mode_data(object_id, 3, 0)

View File

@ -8,11 +8,8 @@ from tmtccmd.ecss.tc import PusTelecommand
from tmtccmd.pus_tc.definitions import TcQueueT
from tmtccmd.pus_tc.service_8_functional_cmd import generate_action_command
from config.object_ids import ObjectIds
# Object IDs
TEST_DEVICE_0_ID = bytearray()
TEST_DEVICE_1_ID = bytearray()
from config.object_ids import TEST_DEVICE_1_OBJ_ID, TEST_DEVICE_0_OBJ_ID
# Set IDs
TEST_SET_ID = 0
@ -25,17 +22,13 @@ PARAM_ACTIVATE_CHANGING_DATASETS = 4
def pack_service_3_commands_into(tc_queue: TcQueueT, op_code: str):
global TEST_DEVICE_0_ID, TEST_DEVICE_1_ID
if TEST_DEVICE_0_ID == bytearray() or TEST_DEVICE_1_ID == bytearray():
TEST_DEVICE_0_ID = get_object_id(ObjectIds.TEST_DEVICE_0)
TEST_DEVICE_1_ID = get_object_id(ObjectIds.TEST_DEVICE_1)
current_ssc = 3000
# TODO: Import this from config instead
device_idx = 0
if device_idx == 0:
object_id = TEST_DEVICE_0_ID
object_id = TEST_DEVICE_0_OBJ_ID
else:
object_id = TEST_DEVICE_1_ID
object_id = TEST_DEVICE_1_OBJ_ID
if op_code == "0":
# This will pack all the tests

View File

@ -1,21 +1,13 @@
from config.object_ids import ObjectIds
import pus_tc.command_data as cmd_data
from pus_tc.service_200_mode import pack_mode_data
from tmtccmd.core.definitions import QueueCommands
from tmtccmd.core.object_id_manager import get_object_id
from tmtccmd.ecss.tc import PusTelecommand
from tmtccmd.pus_tc.definitions import TcQueueT
TEST_DEVICE_0_ID = bytearray()
TEST_DEVICE_1_ID = bytearray()
import pus_tc.command_data as cmd_data
from pus_tc.service_200_mode import pack_mode_data
from config.object_ids import TEST_DEVICE_1_OBJ_ID, TEST_DEVICE_0_OBJ_ID
def pack_service_8_commands_into(tc_queue: TcQueueT, op_code: str):
global TEST_DEVICE_0_ID, TEST_DEVICE_1_ID
if TEST_DEVICE_0_ID == bytearray() or TEST_DEVICE_1_ID == bytearray():
TEST_DEVICE_0_ID = get_object_id(ObjectIds.TEST_DEVICE_0)
TEST_DEVICE_1_ID = get_object_id(ObjectIds.TEST_DEVICE_1)
if op_code == "0":
pack_generic_service_8_test_into(tc_queue=tc_queue)
else:
@ -24,7 +16,7 @@ def pack_service_8_commands_into(tc_queue: TcQueueT, op_code: str):
def pack_generic_service_8_test_into(tc_queue: TcQueueT):
tc_queue.appendleft((QueueCommands.PRINT, "Testing Service 8"))
object_id = TEST_DEVICE_0_ID
object_id = TEST_DEVICE_0_OBJ_ID
# set mode on
tc_queue.appendleft((QueueCommands.PRINT, "Testing Service 8: Set On Mode"))

View File

@ -6,37 +6,34 @@
"""
import struct
from typing import Tuple
from config.object_ids import ObjectIds
from tmtccmd.pus_tm.service_3_housekeeping import Service3Base
from tmtccmd.utility.tmtcc_logger import get_logger
from config.object_ids import TEST_DEVICE_0_OBJ_ID, TEST_DEVICE_1_OBJ_ID
LOGGER = get_logger()
def service_3_hk_handling(
object_id: int, set_id: int, hk_data: bytearray, service3_packet: Service3Base
object_id: bytearray, set_id: int, hk_data: bytearray, service3_packet: Service3Base
) -> Tuple[list, list, bytearray, int]:
"""
This function is called when a Service 3 Housekeeping packet is received.
Please note that the object IDs should be compared by value because direct comparison of
enumerations does not work in Python. For example use:
if object_id.value == ObjectIds.TEST_OBJECT.value
to test equality based on the object ID list.
@param object_id:
@param set_id:
@param hk_data:
@param service3_packet:
@return: Expects a tuple, consisting of two lists, a bytearray and an integer
:param object_id:
:param set_id:
:param hk_data:
:param service3_packet:
:return: Expects a tuple, consisting of two lists, a bytearray and an integer
The first list contains the header columns, the second list the list with
the corresponding values. The bytearray is the validity buffer, which is usually appended
at the end of the housekeeping packet. The last value is the number of parameters.
"""
if object_id == ObjectIds.TEST_DEVICE_0.value or \
object_id == ObjectIds.TEST_DEVICE_1.value:
if set_id:
pass
if service3_packet:
pass
if object_id == TEST_DEVICE_0_OBJ_ID or \
object_id == TEST_DEVICE_1_OBJ_ID:
return handle_test_set_deserialization(hk_data=hk_data)
else:
LOGGER.info("Service3TM: Parsing for this SID has not been implemented.")

View File

@ -14,6 +14,14 @@ def custom_service_8_handling(
@param custom_data:
@return:
"""
if object_id:
pass
if action_id:
pass
if custom_data:
pass
header_list = []
content_list = []
return header_list, content_list

0
tmtc/tmtc_client_cli.py Executable file → Normal file
View File

0
tmtc/tmtc_client_gui.py Executable file → Normal file
View File