Alpha version of the code. Errors are still present in the code and the objects and dataused are picked as a test. Documentation of the code will be also added later.

This commit is contained in:
2021-09-10 17:08:38 +02:00
parent 6a65c7af33
commit d857487d17
357 changed files with 20043 additions and 54 deletions

View File

@ -0,0 +1,213 @@
/*
* ArduinoComIF.cpp
*
* Created on: 02/06/2021
* Author: Marco Modè
*
*/
#include <mission/DeviceHandler/ArduinoComIF.h>
#include <mission/DeviceHandler/ArduinoCookie.h>
#include <fsfw/serialize/SerializeAdapter.h>
//#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/tmtcservices/CommandingServiceBase.h>
#include <fsfw/tmtcpacket/pus/TmPacketStored.h>
// C library headers
#include <stdio.h>
#include <string.h>
#include <vector>
// Linux headers
#include <fcntl.h> // Contains file controls like O_RDWR
#include <errno.h> // Error integer and strerror() function
#include <termios.h> // Contains POSIX terminal control definitions
#include <unistd.h> // write(), read(), close()
#include <algorithm>
#include <cstdint>
ArduinoComIF::ArduinoComIF(object_id_t objectId) :
SystemObject(objectId) {
}
ArduinoComIF::~ArduinoComIF() {
}
ReturnValue_t ArduinoComIF::initializeInterface(CookieIF *cookie) {
ArduinoCookie *Cookie = dynamic_cast<ArduinoCookie*>(cookie);
// The Arduino device which manage the sensors of temperature,
// environmental data and acceleration, sends through serial
// output these data employing a USB port.
// Here it is then set-up the interface to manage this communication.
//
// In typical UNIX style, serial ports are represented by files
// within the operating system.
// These files usually pop-up in /dev/, and begin with the name tty*.
//
// To write/read to a serial port, you write/read to the file.
// Here the serial port parameters are defined exploiting a
// special tty configuration struct.
// Open the serial port. Change device path as needed.
int serial_port = open("/dev/ttyACM0", O_RDWR);
// Create new termios struc, we call it 'tty' for convention.
struct termios tty;
// Read in existing settings, and handle any error.
if (tcgetattr(serial_port, &tty) != 0) {
printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
return 1;
}
// Set-up of the configuration serial port.
tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size
tty.c_cflag |= CS8; // 8 bits per byte (most common)
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ECHOE; // Disable erasure
tty.c_lflag &= ~ECHONL; // Disable new-line echo
tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); // Disable any special handling of received bytes
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
tty.c_cc[VTIME] = 16; // Wait for up to 16 ds (Arduino measurement cycle time), returning as soon as any data is received.
tty.c_cc[VMIN] = 255; // limit number of bytes which can be read in one time by Linux serial port
// Set in/out baud rate to be 115200 bps (same of Arduino)
cfsetispeed(&tty, B115200);
cfsetospeed(&tty, B115200);
// Save tty settings, also checking for error.
if (tcsetattr(serial_port, TCSANOW, &tty) != 0) {
printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
return 1;
}
printf("\nSerial port set. \n");
// End of Linux serial port set-up.
Cookie->Serial_port_number = serial_port;
sif::debug<<"\nDEBUG_COMIF: debug0-IF"<<std::endl;
return RETURN_OK;
}
ReturnValue_t ArduinoComIF::sendMessage(CookieIF *cookie,
const uint8_t *sendData, size_t sendLen) {
sif::debug<<"\nDEBUG_COMIF: debug1-IF"<<std::endl;
return RETURN_OK;
}
ReturnValue_t ArduinoComIF::getSendSuccess(CookieIF *cookie) {
sif::debug<<"\nDEBUG_COMIF: debug2-IF"<<std::endl;
return RETURN_OK;
}
ReturnValue_t ArduinoComIF::requestReceiveMessage(CookieIF *cookie,
size_t requestLen) {
sif::debug<<"\nDEBUG_COMIF: debug3-IF"<<std::endl;
return RETURN_OK;
}
ReturnValue_t ArduinoComIF::readReceivedMessage(CookieIF *cookie,
uint8_t **buffer, size_t *size) {
ArduinoCookie *Cookie = dynamic_cast<ArduinoCookie*>(cookie);
// The buffer array to store the data read are initialized.
// The whole data packet to be read is 2034 bytes, but
// the limit for one reading (VMAX) is 255 bytes.
// Therefore the reading is divided in 8 separate stages
// which employ 8 different buffer array.
// At the end these 8 arrays are concatenated in
// the main buffer array read_buf.
sif::debug<<"\nDEBUG_COMIF: start of copy received data in the buffer"<<std::endl;
uint8_t read_buf[2034]; // 2034 bytes from SPC serial output
uint8_t read_buf1[255]; // 255 bytes
uint8_t read_buf2[255]; // 255 bytes
uint8_t read_buf3[255]; // 255 bytes
uint8_t read_buf4[255]; // 255 bytes
uint8_t read_buf5[255]; // 255 bytes
uint8_t read_buf6[255]; // 255 bytes
uint8_t read_buf7[255]; // 255 bytes
uint8_t read_buf8[249]; // 249 bytes
// The buffer elements are initially set to 0 so we can call printf() easily.
memset(&read_buf, '\0', sizeof(read_buf));
memset(&read_buf1, '\0', sizeof(read_buf));
memset(&read_buf2, '\0', sizeof(read_buf));
memset(&read_buf3, '\0', sizeof(read_buf));
memset(&read_buf4, '\0', sizeof(read_buf));
memset(&read_buf5, '\0', sizeof(read_buf));
memset(&read_buf6, '\0', sizeof(read_buf));
memset(&read_buf7, '\0', sizeof(read_buf));
memset(&read_buf8, '\0', sizeof(read_buf));
// Read bytes. The behaviour of read() (e.g. does it block?, how long does it block for?)
// depends on the configuration settings above, specifically VMIN and VTIME.
int num_bytes1 = read(Cookie->Serial_port_number, &read_buf1,
sizeof(read_buf1));
int num_bytes2 = read(Cookie->Serial_port_number, &read_buf2,
sizeof(read_buf2));
int num_bytes3 = read(Cookie->Serial_port_number, &read_buf3,
sizeof(read_buf3));
int num_bytes4 = read(Cookie->Serial_port_number, &read_buf4,
sizeof(read_buf4));
int num_bytes5 = read(Cookie->Serial_port_number, &read_buf5,
sizeof(read_buf5));
int num_bytes6 = read(Cookie->Serial_port_number, &read_buf6,
sizeof(read_buf6));
int num_bytes7 = read(Cookie->Serial_port_number, &read_buf7,
sizeof(read_buf7));
int num_bytes8 = read(Cookie->Serial_port_number, &read_buf8,
sizeof(read_buf8));
int num_bytes = num_bytes1 + num_bytes2 + num_bytes3 + num_bytes4
+ num_bytes5 + num_bytes6 + num_bytes7 + num_bytes8;
// The 8 buffer arrays are here concatenated in one single vector.
std::copy(read_buf1, read_buf1 + 255, read_buf);
std::copy(read_buf2, read_buf2 + 255, read_buf + 255);
std::copy(read_buf3, read_buf3 + 255, read_buf + 2 * 255);
std::copy(read_buf4, read_buf4 + 255, read_buf + 3 * 255);
std::copy(read_buf5, read_buf5 + 255, read_buf + 4 * 255);
std::copy(read_buf6, read_buf6 + 255, read_buf + 5 * 255);
std::copy(read_buf7, read_buf7 + 255, read_buf + 6 * 255);
std::copy(read_buf8, read_buf8 + 249, read_buf + 7 * 255);
// num_bytes is the number of bytes read (n=0: no bytes received, n=-1: error).
if (num_bytes < 0) {
printf("Error reading: %s", strerror(errno));
return 1;
}
printf("Read %i bytes.\n", num_bytes);
// Definition of buffer array and buffer size to return after reading.
*size = 2034;
/*uint8_t *buf_ptr;
buf_ptr = read_buf;
buffer = &buf_ptr;*/
*buffer = read_buf;
return RETURN_OK;
}

View File

@ -0,0 +1,73 @@
/*
* Title: ArduinoComIF.h
*
* Created on: 02/06/2021
* Author: Marco Modè
*
*/
#ifndef MISSION_DEVICEHANDLER_ARDUINOCOMIF_H_
#define MISSION_DEVICEHANDLER_ARDUINOCOMIF_H_
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
#include <vector>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cstdint>
#include <map>
/**
* @brief Used to simply return sent data from device handler
* @details Assign this com IF in the factory when creating the device handler
* @ingroup test
*/
class ArduinoComIF: public DeviceCommunicationIF, public SystemObject {
public:
ArduinoComIF(object_id_t objectId);
virtual ~ArduinoComIF();
/**
* DeviceCommunicationIF overrides
* (see DeviceCommunicationIF documentation)
*/
ReturnValue_t initializeInterface(CookieIF * cookie) override;
ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t * sendData,
size_t sendLen) override;
ReturnValue_t getSendSuccess(CookieIF *cookie) override;
ReturnValue_t requestReceiveMessage(CookieIF *cookie,
size_t requestLen) override;
ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer,
size_t *size) override;
private:
/**
* Send TM packet which contains received data as TM[17,130].
* Wiretapping will do the same.
* @param data
* @param len
*/
void sendTmPacket(const uint8_t *data,uint32_t len);
AcceptsTelemetryIF* funnel = nullptr;
MessageQueueIF* tmQueue = nullptr;
size_t replyMaxLen = 0;
using ReplyBuffer = std::vector<uint8_t>;
std::map<address_t, ReplyBuffer> replyMap;
uint8_t dummyReplyCounter = 0;
uint16_t packetSubCounter = 0;
};
#endif /* MISSION_DEVICEHANDLER_ARDUINOCOMIF_H_ */

View File

@ -0,0 +1,30 @@
/*
* Cookie.cpp
*
* Created on: 02/06/2021
* Author: Marco Modè
*
*/
#include <mission/DeviceHandler/ArduinoCookie.h>
//The cookie tells to device handler which is the device to communicate with if more
// devices are connected. In this case only one device, the Arduino motherboard, is
// connected. Therefore the cookie adress and MaxLen are set to default.
ArduinoCookie::ArduinoCookie() {}
ArduinoCookie::~ArduinoCookie() {}
/*
address_t ArduinoCookie::getAddress() const {
return address;
}
size_t ArduinoCookie::getReplyMaxLen() const {
return replyMaxLen;
}
int ArduinoCookie::getSerialPort() const {
return Serial_port_number;
}
*/

View File

@ -0,0 +1,36 @@
/*
* ArduinoCookie.h
*
* Created on: 02/06/2021
* Author: Marco Modè
*
*/
#ifndef MISSION_DEVICEHANDLER_ARDUINOCOOKIE_H_
#define MISSION_DEVICEHANDLER_ARDUINOCOOKIE_H_
#include <fsfw/devicehandlers/CookieIF.h>
#include <cstddef>
/**
* @brief Simple cookie which initialie the variables
* for the Linux serial port.
*/
class ArduinoCookie: public CookieIF {
public:
ArduinoCookie();
virtual ~ArduinoCookie();
address_t getAddress() const;
size_t getReplyMaxLen() const;
int getSerialPort() const;
int Serial_port_number;
private:
address_t address = 0;
size_t replyMaxLen = 0;
};
#endif /* MISSION_DEVICEHANDLER_ARDUINOCOOKIE_H_ */

View File

@ -0,0 +1,353 @@
/*
* DeviceHandler.cpp
*
* Created on: 02/06/2021
* Author: Marco Modè
*
*/
#include <mission/DeviceHandler/ArduinoDeviceHandler.h>
#include <OBSWConfig.h>
#include <fsfw/datapool/DataSet.h>
#include <fsfw/datapool/PoolVector.h>
#include <bsp_linux/fsfwconfig/datapool/dataPoolInit.h>
//#include <fsfw/datapool/PoolReadGuard.h>
#include <cstdlib>
ArduinoDH::ArduinoDH(object_id_t objectId, object_id_t comIF, CookieIF *cookie) :
DeviceHandlerBase(objectId, comIF, cookie) {
mode = _MODE_START_UP;
}
ArduinoDH::~ArduinoDH() {
}
/*void ArduinoDH::performOperationHook() {
}*/
void ArduinoDH::doStartUp() {
std::cout<<"Arduino device -> Switching-ON"<<std::endl;
setMode(_MODE_TO_ON);
return;
}
void ArduinoDH::doShutDown() {
std::cout<<"Arduino device -> Switching-OFF"<<std::endl;
setMode(_MODE_SHUT_DOWN);
return;
}
ReturnValue_t ArduinoDH::buildNormalDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t ArduinoDH::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
void ArduinoDH::doTransition(Mode_t modeFrom, Submode_t submodeFrom) {
if (mode == _MODE_TO_NORMAL) {
std::cout<<"Arduino device -> Transition to Normal mode"<<std::endl;
} else {
DeviceHandlerBase::doTransition(modeFrom, submodeFrom);
}
}
ReturnValue_t ArduinoDH::buildCommandFromCommand(
DeviceCommandId_t deviceCommand, const uint8_t *commandData,
size_t commandDataLen) {
return HasActionsIF::EXECUTION_FINISHED;
}
/*ReturnValue_t ArduinoDH::buildNormalModeCommand(
DeviceCommandId_t deviceCommand, const uint8_t *commandData,
size_t commandDataLen) {
return RETURN_OK;
}*/
void ArduinoDH::passOnCommand(DeviceCommandId_t command,
const uint8_t *commandData, size_t commandDataLen) {
}
void ArduinoDH::fillCommandAndReplyMap() {
}
ReturnValue_t ArduinoDH::scanForReply(const uint8_t *start, size_t len,
DeviceCommandId_t *foundId, size_t *foundLen) {
//using namespace testdevice;
/* Unless a command was sent explicitely, we don't expect any replies and ignore
the packet. On a real device, there might be replies which are sent without a previous
command. */
sif::debug<<"\nDEBUG_DH: scan for reply"<<std::endl;
/*if (not commandSent) {
sif::debug<<" DH: scan for reply2"<<std::endl;
return DeviceHandlerBase::IGNORE_FULL_PACKET;
} else {
commandSent = false;
}*/
/*len = 2034;
start = *buffer;*/
foundId = &bufferID;
foundLen = &len;
// start character: '['
if (*start == 91 ){
// buffer length: 2034 bytes
if (*foundLen == len){
return APERIODIC_REPLY;
}
else{
return DeviceHandlerIF::LENGTH_MISSMATCH;
}
}
else {
return RETURN_FAILED;
}
}
ReturnValue_t ArduinoDH::interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) {
sif::debug<<"\nDEBUG_DH: interprete for reply"<<std::endl;
// The data stored in the read buffer are here copied in the variables with the SPC format.
// After copying, the data of temperature, environment and accelerometer are stored in three separated vectors.
for (int i = 0; i < 36; i++) {
memcpy(&Temp_ch.start_string, &packet[27 * i + 0], 8);
memcpy(&Temp_ch.Typ, &packet[27 * i + 8], 1);
memcpy(&Temp_ch.SPCChNumber, &packet[27 * i + 9], 1);
memcpy(&Temp_ch.Value_Cnt, &packet[27 * i + 10], 1);
memcpy(&Temp_ch.temperature, &packet[27 * i + 11], 4);
memcpy(&Temp_ch.Timestamp, &packet[27 * i + 15], 4);
memcpy(&Temp_ch.end_string, &packet[27 * i + 19], 8);
vecTemp.emplace_back(Temp_ch.start_string, Temp_ch.Typ,
Temp_ch.SPCChNumber, Temp_ch.Value_Cnt, Temp_ch.temperature,
Temp_ch.Timestamp, Temp_ch.end_string);
}
for (int j = 0; j < 9; j++) {
memcpy(&Env_ch.start_string, &packet[27 * (36 + j) + 0], 8);
memcpy(&Env_ch.Typ, &packet[27 * (36 + j) + 8], 1);
memcpy(&Env_ch.SPCChNumber, &packet[27 * (36 + j) + 9], 1);
memcpy(&Env_ch.Value_Cnt, &packet[27 * (36 + j) + 10], 1);
memcpy(&Env_ch.Value, &packet[27 * (36 + j) + 11], 4);
memcpy(&Env_ch.Timestamp, &packet[27 * (36 + j) + 15], 4);
memcpy(&Env_ch.end_string, &packet[27 * (36 + j) + 19], 8);
vecEnv.emplace_back(Env_ch.start_string, Env_ch.Typ, Env_ch.SPCChNumber,
Env_ch.Value_Cnt, Env_ch.Value, Env_ch.Timestamp,
Env_ch.end_string);
}
for (int k = 0; k < 15; k++) {
memcpy(&Acc_ch.start_string, &packet[27 * (36 + 9) + 91 * k + 0], 8);
memcpy(&Acc_ch.Typ, &packet[27 * (36 + 9) + 91 * k + 8], 1);
memcpy(&Acc_ch.SPCChNumber, &packet[27 * (36 + 9) + 91 * k + 9], 1);
memcpy(&Acc_ch.Value_Cnt, &packet[27 * (36 + 9) + 91 * k + 10], 1);
memcpy(&Acc_ch.Value, &packet[27 * (36 + 9) + 91 * k + 11], 36);
memcpy(&Acc_ch.Timestamp, &packet[27 * (36 + 9) + 91 * k + 47], 36);
memcpy(&Acc_ch.end_string, &packet[27 * (36 + 9) + 91 * k + 83], 8);
vecAcc.emplace_back(Acc_ch.start_string, Acc_ch.Typ, Acc_ch.SPCChNumber,
Acc_ch.Value_Cnt, Acc_ch.Value, Acc_ch.Timestamp,
Acc_ch.end_string);
}
// All data are here printed to monitor from the three vectors of data measurements.
printf(
"\n***********************************************************************************************\n");
printf("TEMPERATURE parameters are: ");
for (int i = 0; i < 36; i++) {
printf("\n\nStart: %7s", vecTemp[i].start_string);
printf("\nTyp: %u", vecTemp[i].Typ);
printf("\nSPCChNumber: %u", vecTemp[i].SPCChNumber);
printf("\nValue_Cnt: %u", vecTemp[i].Value_Cnt);
printf("\nTemperature: %f", vecTemp[i].temperature);
printf("\nTimestamp: %u", vecTemp[i].Timestamp);
printf("\nEnd: %7s", vecTemp[i].end_string);
}
printf(
"\n\n***********************************************************************************************\n");
printf("ENVIRONMENTAL parameters are: ");
for (int j = 0; j < 3; j++) {
printf("\n\nHUMIDITY: ");
printf("\nStart: %7s", vecEnv[3 * j].start_string);
printf("\nTyp: %u", vecEnv[3 * j].Typ);
printf("\nSPCChNumber: %u", vecEnv[3 * j].SPCChNumber);
printf("\nValue_Cnt: %u", vecEnv[3 * j].Value_Cnt);
printf("\nValue: %f", vecEnv[3 * j].Value);
printf("\nTimestamp: %u", vecEnv[3 * j].Timestamp);
printf("\nEnd: %7s", vecEnv[3 * j].end_string);
printf("\n\nPRESSURE: ");
printf("\nStart: %7s", vecEnv[3 * j + 1].start_string);
printf("\nTyp: %u", vecEnv[3 * j + 1].Typ);
printf("\nSPCChNumber: %u", vecEnv[3 * j + 1].SPCChNumber);
printf("\nValue_Cnt: %u", vecEnv[3 * j + 1].Value_Cnt);
printf("\nValue: %f", vecEnv[3 * j + 1].Value);
printf("\nTimestamp: %u", vecEnv[3 * j + 1].Timestamp);
printf("\nEnd: %7s", vecEnv[3 * j + 1].end_string);
printf("\n\nTEMPERATURE: ");
printf("\nStart: %7s", vecEnv[3 * j + 2].start_string);
printf("\nTyp: %u", vecEnv[3 * j + 2].Typ);
printf("\nSPCChNumber: %u", vecEnv[3 * j + 2].SPCChNumber);
printf("\nValue_Cnt: %u", vecEnv[3 * j + 2].Value_Cnt);
printf("\nValue: %f", vecEnv[3 * j + 2].Value);
printf("\nTimestamp: %u", vecEnv[3 * j + 2].Timestamp);
printf("\nEnd: %7s", vecEnv[3 * j + 2].end_string);
}
printf(
"\n\n***********************************************************************************************\n");
printf("ACCELEROMETER parameters are: ");
for (int k = 0; k < 5; k++) {
switch (k) {
case 0:
printf("\n\nACCELERATION: ");
break;
case 1:
printf("\n\nGYROSCOPE: ");
break;
case 2:
printf("\n\nMAGNETOMETER: ");
break;
case 3:
printf("\n\nLINEAR ACCELERATION: ");
break;
case 4:
printf("\n\nEULER ANGLES: ");
break;
}
printf("\n\nX ==> ");
printf("\nStart: %7s", vecAcc[3 * k].start_string);
printf("\nTyp: %u", vecAcc[3 * k].Typ);
printf("\nSPCChNumber: %u", vecAcc[3 * k].SPCChNumber);
printf("\nValue_Cnt: %u", vecAcc[3 * k].Value_Cnt);
for (int i = 0; i < 9; i++) {
printf("\nMeasurement number: %d", i);
printf("\nValue: %f", vecAcc[3 * k].Value[i]);
printf("\nTimestamp: %u", vecAcc[3 * k].Timestamp[i]);
}
printf("\nEnd: %7s", vecAcc[3 * k].end_string);
printf("\n\nY ==> ");
printf("\nStart: %7s", vecAcc[3 * k + 1].start_string);
printf("\nTyp: %u", vecAcc[3 * k + 1].Typ);
printf("\nSPCChNumber: %u", vecAcc[3 * k + 1].SPCChNumber);
printf("\nValue_Cnt: %u", vecAcc[3 * k + 1].Value_Cnt);
for (int i = 0; i < 9; i++) {
printf("\nMeasurement number: %d", i);
printf("\nValue: %f", vecAcc[3 * k + 1].Value[i]);
printf("\nTimestamp: %u", vecAcc[3 * k + 1].Timestamp[i]);
}
printf("\nEnd: %7s", vecAcc[3 * k + 1].end_string);
printf("\n\nZ ==> ");
printf("\nStart: %7s", vecAcc[3 * k + 2].start_string);
printf("\nTyp: %u", vecAcc[3 * k + 2].Typ);
printf("\nSPCChNumber: %u", vecAcc[3 * k + 2].SPCChNumber);
printf("\nValue_Cnt: %u", vecAcc[3 * k + 2].Value_Cnt);
for (int i = 0; i < 9; i++) {
printf("\nMeasurement number: %d", i);
printf("\nValue: %f", vecAcc[3 * k + 2].Value[i]);
printf("\nTimestamp: %u", vecAcc[3 * k + 2].Timestamp[i]);
}
printf("\nEnd: %7s", vecAcc[3 * k + 2].end_string);
}
std::cout << "\n\nEnd reading data.\n" << std::endl;
// The data are here written to the data pool where they would be available to be used for other objects
DataSet ArduinoDataSet;
PoolVector <float, 36> TempValueVec(datapool::Temperature_value, &ArduinoDataSet, PoolVariableIF::VAR_WRITE);
for (int i = 0; i < 36; i++) {
memcpy(&TempValueVec, &vecTemp[27 * i + 11], 4);
}
ArduinoDataSet.commit(PoolVariableIF::VALID);
PoolVector <unsigned int, 36> TempTimeVec(datapool::Temperature_Timestamp, &ArduinoDataSet, PoolVariableIF::VAR_WRITE);
for (int i = 0; i < 36; i++) {
memcpy(&TempTimeVec, &vecTemp[27 * i + 15], 4);
}
ArduinoDataSet.commit(PoolVariableIF::VALID);
PoolVector <float, 9> EnvValueVec(datapool::Environmental_value, &ArduinoDataSet, PoolVariableIF::VAR_WRITE);
for (int j = 0; j < 9; j++) {
memcpy(&EnvValueVec, &vecEnv[27 * (36 + j) + 11], 4);
}
ArduinoDataSet.commit(PoolVariableIF::VALID);
PoolVector <unsigned int, 9> EnvTimeVec(datapool::Environmental_Timestamp, &ArduinoDataSet, PoolVariableIF::VAR_WRITE);
for (int j = 0; j < 9; j++) {
memcpy(&EnvTimeVec, &vecEnv[27 * (36 + j) + 15], 4);
}
ArduinoDataSet.commit(PoolVariableIF::VALID);
PoolVector <float, 15> AccValueVec(datapool::Accelerometer_value, &ArduinoDataSet, PoolVariableIF::VAR_WRITE);
for (int k = 0; k < 15; k++) {
memcpy(&AccValueVec, &vecAcc[27 * (36 + 9) + 91 * k + 11], 36);
}
ArduinoDataSet.commit(PoolVariableIF::VALID);
PoolVector <unsigned int, 15> AccTimeVec(datapool::Accelerometer_Timestamp, &ArduinoDataSet, PoolVariableIF::VAR_WRITE);
for (int k = 0; k < 15; k++) {
memcpy(&AccTimeVec, &vecAcc[27 * (36 + 9) + 91 * k + 47], 36);
}
ArduinoDataSet.commit(PoolVariableIF::VALID);
sif::debug<<"\nDEBUG_DH: End of copy to datapool"<<std::endl;
return RETURN_OK;
}
ReturnValue_t ArduinoDH::interpretingNormalModeReply() {
return RETURN_OK;
}
/*ReturnValue_t ArduinoDH::interpretingTestReply0(DeviceCommandId_t id,
const uint8_t *packet) {
return RETURN_OK;
}*/
/*ReturnValue_t ArduinoDH::interpretingTestReply1(DeviceCommandId_t id,
const uint8_t *packet) {
return RETURN_OK;
}*/
uint32_t ArduinoDH::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) {
return 0;
}
void ArduinoDH::setNormalDatapoolEntriesInvalid() {
}
// ??remove//
/*void ArduinoDH::enableFullDebugOutput(bool enable) {
this->fullInfoPrintout = enable;
}*/
/*ReturnValue_t ArduinoDH::initializeLocalDataPool(
localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
return RETURN_OK;
}*/
/*ReturnValue_t ArduinoDH::getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
uint16_t startAtIndex) {
return RETURN_OK;
}*/
/*LocalPoolObjectBase* ArduinoDH::getPoolObjectHandle(lp_id_t localPoolId) {
return RETURN_OK;
}*/

View File

@ -0,0 +1,231 @@
/*
* DeviceHandler.h
*
* Created on: 02/06/2021
* Author: Marco Modè
*
*/
#ifndef MISSION_DEVICEHANDLER_ARDUINODEVICEHANDLER_H_
#define MISSION_DEVICEHANDLER_ARDUINODEVICEHANDLER_H_
#include <vector>
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include <fsfw/timemanager/Countdown.h>
/**
* @brief Basic device handler to test device commanding without a physical device.
* @details
* This test device handler provided a basic demo for the device handler object.
* It can also be commanded with the following PUS services, using
* the specified object ID of the test device handler.
*
* 1. PUS Service 8 - Functional commanding
* 2. PUS Service 2 - Device access, raw commanding
* 3. PUS Service 20 - Parameter Management
* 4. PUS Service 3 - Housekeeping
* @author R. Mueller
* @ingroup devices
*/
class ArduinoDH: public DeviceHandlerBase {
public:
/**
* Build the test device in the factory.
* @param objectId This ID will be assigned to the test device handler.
* @param comIF The ID of the Communication IF used by test device handler.
* @param cookie Cookie object used by the test device handler. This is
* also used and passed to the comIF object.
* @param onImmediately This will start a transition to MODE_ON immediately
* so the device handler jumps into #doStartUp. Should only be used
* in development to reduce need of commanding while debugging.
*/
ArduinoDH(object_id_t objectId, object_id_t comIF, CookieIF *cookie);
/**
* This can be used to enable and disable a lot of demo print output.
* @param enable
*/
void enableFullDebugOutput(bool enable);
virtual ~ ArduinoDH();
//! Size of internal buffer used for communication.
static constexpr uint8_t MAX_BUFFER_SIZE = 255;
//! Unique index if the device handler is created multiple times.
/*testdevice::DeviceIndex deviceIdx = testdevice::DeviceIndex::DEVICE_0;*/
// Definiton of data structure for SPC communication. Three different structures are defined for measurements of:
// - Temperature,
// - Environmental data,
// - Accelerometer data.
struct Temperature {
char start_string[8];
uint8_t Typ;
uint8_t SPCChNumber;
uint8_t Value_Cnt;
float temperature;
unsigned int Timestamp;
char end_string[8];
Temperature() = default;
Temperature(const char *_start_string, uint8_t _Typ,
uint8_t _SPCChNumber, uint8_t _Value_Cnt, float _temperature,
unsigned int _Timestamp, const char *_end_string) :
Typ(_Typ), SPCChNumber(_SPCChNumber), Value_Cnt(_Value_Cnt), temperature(
_temperature), Timestamp(_Timestamp) {
strncpy(start_string, _start_string, sizeof(start_string) - 1);
strncpy(end_string, _end_string, sizeof(end_string) - 1);
}
};
struct Environmental {
char start_string[8];
uint8_t Typ;
uint8_t SPCChNumber;
uint8_t Value_Cnt;
float Value;
unsigned int Timestamp;
char end_string[8];
Environmental() = default;
Environmental(const char *_start_string, uint8_t _Typ,
uint8_t _SPCChNumber, uint8_t _Value_Cnt, float _Value,
unsigned int _Timestamp, const char *_end_string) :
Typ(_Typ), SPCChNumber(_SPCChNumber), Value_Cnt(_Value_Cnt), Value(
_Value), Timestamp(_Timestamp) {
strncpy(start_string, _start_string, sizeof(start_string) - 1);
strncpy(end_string, _end_string, sizeof(end_string) - 1);
}
};
struct Accelerometer {
char start_string[8];
uint8_t Typ;
uint8_t SPCChNumber;
uint8_t Value_Cnt;
float Value[9]; //max buffer
unsigned int Timestamp[9]; //max buffer
char end_string[8];
Accelerometer() = default;
Accelerometer(const char *_start_string, uint8_t _Typ,
uint8_t _SPCChNumber, uint8_t _Value_Cnt, const float *_Value,
const unsigned int *_Timestamp, const char *_end_string) :
Typ(_Typ), SPCChNumber(_SPCChNumber), Value_Cnt(_Value_Cnt) {
strncpy(start_string, _start_string, sizeof(start_string) - 1);
memcpy(&Value, _Value, sizeof(Value) - 1);
memcpy(&Timestamp, _Timestamp, sizeof(Timestamp) - 1);
strncpy(end_string, _end_string, sizeof(end_string) - 1);
}
};
// Three vectors are defined to store the three type of classes sequentially
// during the phase of reading copying data from the buffers
std::vector<Temperature> vecTemp;
std::vector<Environmental> vecEnv;
std::vector<Accelerometer> vecAcc;
// Three dummy child structures are defined. They are used to store the three
// different types of data during the measurement loop and then the data are
// copied in the vectors above.
// Then, they are overwritten by the data of next iteration and the process is
// repeated ,until all the data from the buffer are copied to the three vectors
// using the three different structures.
Temperature Temp_ch;
Environmental Env_ch;
Accelerometer Acc_ch;
protected:
DeviceCommandId_t bufferID = 0x01;
//testdevice::TestDataSet dataset;
//! This is used to reset the dataset after a commanded change has been made.
bool resetAfterChange = false;
bool commandSent = false;
/** DeviceHandlerBase overrides (see DHB documentation) */
/**
* Hook into the DHB #performOperation call which is executed
* periodically.
*/
/*void buildNormalModeCommands() override;*/
virtual void doStartUp() override;
virtual void doShutDown() override;
virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id)
override;
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id)
override;
virtual ReturnValue_t buildCommandFromCommand(
DeviceCommandId_t deviceCommand, const uint8_t *commandData,
size_t commandDataLen) override;
virtual void fillCommandAndReplyMap() override;
virtual ReturnValue_t scanForReply(const uint8_t *start, size_t len,
DeviceCommandId_t *foundId, size_t *foundLen) override;
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) override;
virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo)
override;
virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom) override;
virtual void setNormalDatapoolEntriesInvalid() override;
/*virtual ReturnValue_t initializeLocalDataPool(
localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;*/
/*virtual LocalPoolObjectBase* getPoolObjectHandle(lp_id_t localPoolId)
override;*/
/* HasParametersIF overrides */
/*virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) override;*/
uint8_t commandBuffer[MAX_BUFFER_SIZE];
// ******************************************************************
// delete this stuff
bool oneShot = true;
/* Variables for parameter service */
uint32_t testParameter0 = 0;
int32_t testParameter1 = -2;
float vectorFloatParams2[3] = { };
/* Change device handler functionality, changeable via parameter service */
uint8_t periodicPrintout = false;
/*ReturnValue_t buildNormalModeCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData, size_t commandDataLen);*/
/*ReturnValue_t buildTestCommand0(DeviceCommandId_t deviceCommand,
const uint8_t *commandData, size_t commandDataLen);*/
/*ReturnValue_t buildTestCommand1(DeviceCommandId_t deviceCommand,
const uint8_t *commandData, size_t commandDataLen);*/
void passOnCommand(DeviceCommandId_t command, const uint8_t *commandData,
size_t commandDataLen);
ReturnValue_t interpretingNormalModeReply();
/*ReturnValue_t interpretingTestReply0(DeviceCommandId_t id,
const uint8_t *packet);*/
/*ReturnValue_t interpretingTestReply1(DeviceCommandId_t id,
const uint8_t *packet);*/
/*ReturnValue_t interpretingTestReply2(DeviceCommandId_t id,
const uint8_t *packet);*/
/* Some timer utilities */
static constexpr uint8_t divider1 = 2;
PeriodicOperationDivider opDivider1 = PeriodicOperationDivider(divider1);
static constexpr uint8_t divider2 = 10;
PeriodicOperationDivider opDivider2 = PeriodicOperationDivider(divider2);
static constexpr uint32_t initTimeout = 2000;
Countdown countdown1 = Countdown(initTimeout);
// *******************************************************************************
};
#endif /* MISSION_DEVICEHANDLER_ARDUINODEVICEHANDLER_H_ */