updated print commands for PDUs
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good

This commit is contained in:
Robin Müller 2021-09-20 11:22:11 +02:00
parent 87d00dbcee
commit 487b6fd5ca
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
7 changed files with 108 additions and 137 deletions

View File

@ -75,10 +75,7 @@ ReturnValue_t GomspaceDeviceHandler::buildCommandFromCommand(
} }
break; break;
} }
case(GOMSPACE::PRINT_OUT_ENB_STATUS): case(GOMSPACE::PRINT_HK_TABLE): {
case(GOMSPACE::PRINT_ALL):
case(GOMSPACE::PRINT_OUT_CURRENTS):
case(GOMSPACE::PRINT_OUT_VOLTAGES): {
result = printStatus(deviceCommand); result = printStatus(deviceCommand);
break; break;
} }
@ -102,10 +99,7 @@ void GomspaceDeviceHandler::fillCommandAndReplyMap(){
this->insertInCommandAndReplyMap(GOMSPACE::PARAM_GET, 3); this->insertInCommandAndReplyMap(GOMSPACE::PARAM_GET, 3);
this->insertInCommandAndReplyMap(GOMSPACE::REQUEST_HK_TABLE, 3); this->insertInCommandAndReplyMap(GOMSPACE::REQUEST_HK_TABLE, 3);
this->insertInCommandMap(GOMSPACE::GNDWDT_RESET); this->insertInCommandMap(GOMSPACE::GNDWDT_RESET);
this->insertInCommandMap(GOMSPACE::PRINT_ALL); this->insertInCommandMap(GOMSPACE::PRINT_HK_TABLE);
this->insertInCommandMap(GOMSPACE::PRINT_OUT_ENB_STATUS);
this->insertInCommandMap(GOMSPACE::PRINT_OUT_VOLTAGES);
this->insertInCommandMap(GOMSPACE::PRINT_OUT_CURRENTS);
} }
ReturnValue_t GomspaceDeviceHandler::scanForReply(const uint8_t *start, ReturnValue_t GomspaceDeviceHandler::scanForReply(const uint8_t *start,

View File

@ -1,7 +1,7 @@
#include <fsfw/datapool/PoolReadGuard.h> #include "OBSWConfig.h"
#include "PDU1Handler.h" #include "PDU1Handler.h"
#include <mission/devices/devicedefinitions/GomSpacePackets.h>
#include <OBSWConfig.h> #include <fsfw/datapool/PoolReadGuard.h>
PDU1Handler::PDU1Handler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) : PDU1Handler::PDU1Handler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) :
GomspaceDeviceHandler(objectId, comIF, comCookie, PDU::MAX_CONFIGTABLE_ADDRESS, GomspaceDeviceHandler(objectId, comIF, comCookie, PDU::MAX_CONFIGTABLE_ADDRESS,
@ -72,27 +72,6 @@ void PDU1Handler::letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *pac
#endif #endif
} }
void PDU1Handler::printOutputSwitchStates() {
sif::info << "PDU1 TCS Board switch: " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledTCSBoard3V3.value) << std::endl;
sif::info << "PDU1 Syrlinks switch: " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledSyrlinks.value) << std::endl;
sif::info << "PDU1 star tracker switch: " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledStarTracker.value) << std::endl;
sif::info << "PDU1 MGT switch: " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledMGT.value) << std::endl;
sif::info << "PDU1 SUS nominal switch: " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledSUSNominal.value) << std::endl;
sif::info << "PDU1 solar cell experiment switch: " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledSolarCellExp.value) << std::endl;
sif::info << "PDU1 PLOC switch: " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledPLOC.value) << std::endl;
sif::info << "PDU1 ACS Side A switch: " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledAcsBoardSideA.value) << std::endl;
sif::info << "PDU1 channel 8 switch: " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledChannel8.value) << std::endl;
}
void PDU1Handler::parseHkTableReply(const uint8_t *packet) { void PDU1Handler::parseHkTableReply(const uint8_t *packet) {
uint16_t dataOffset = 0; uint16_t dataOffset = 0;
PoolReadGuard pg(&pdu1HkTableDataset); PoolReadGuard pg(&pdu1HkTableDataset);
@ -356,14 +335,14 @@ ReturnValue_t PDU1Handler::initializeLocalDataPool(
ReturnValue_t PDU1Handler::printStatus(DeviceCommandId_t cmd) { ReturnValue_t PDU1Handler::printStatus(DeviceCommandId_t cmd) {
switch(cmd) { switch(cmd) {
case(GOMSPACE::PRINT_OUT_ENB_STATUS): { case(GOMSPACE::PRINT_HK_TABLE): {
PoolReadGuard pg(&pdu1HkTableDataset); PoolReadGuard pg(&pdu1HkTableDataset);
ReturnValue_t readResult = pg.getReadResult(); ReturnValue_t readResult = pg.getReadResult();
if(readResult != HasReturnvaluesIF::RETURN_OK) { if(readResult != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Reading PDU1 HK table failed!" << std::endl; sif::warning << "Reading PDU1 HK table failed!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
printOutputSwitchStates(); printHkTable();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
default: { default: {
@ -371,3 +350,53 @@ ReturnValue_t PDU1Handler::printStatus(DeviceCommandId_t cmd) {
} }
} }
} }
void PDU1Handler::printHkTable() {
sif::info << "PDU1 Info: SwitchState, Voltages [mV], Currents [mA]" << std::endl;
sif::info << std::setw(30) << std::left << "TCS Board" << std::dec << "| " <<
unsigned(pdu1HkTableDataset.outEnabledTCSBoard3V3.value) << ", " <<
std::setw(4) << std::right <<
pdu1HkTableDataset.currentOutTCSBoard3V3.value << ", " << std::setw(4) <<
pdu1HkTableDataset.voltageOutTCSBoard3V3.value << std::endl;
sif::info << std::setw(30) << std::left << "Syrlinks" << std::dec << "| " <<
unsigned(pdu1HkTableDataset.outEnabledSyrlinks.value) << ", " <<
std::setw(4) << std::right <<
pdu1HkTableDataset.currentOutSyrlinks.value << ", " << std::setw(4) <<
pdu1HkTableDataset.currentOutSyrlinks.value << std::endl;
sif::info << std::setw(30) << std::left << "Star Tracker" << std::dec << "| " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledStarTracker.value) << ", " <<
std::setw(4) << std::right <<
pdu1HkTableDataset.currentOutStarTracker.value << ", " << std::setw(4) <<
pdu1HkTableDataset.voltageOutStarTracker.value << std::endl;
sif::info << std::setw(30) << std::left << "MGT" << std::dec << "| " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledMGT.value) << ", " <<
std::setw(4) << std::right <<
pdu1HkTableDataset.currentOutMGT.value << ", " << std::setw(4) <<
pdu1HkTableDataset.voltageOutMGT.value << std::endl;
sif::info << std::setw(30) << std::left << "SuS nominal" << std::dec << "| " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledSUSNominal.value) << ", " <<
std::setw(4) << std::right <<
pdu1HkTableDataset.currentOutSUSNominal.value << ", " << std::setw(4) <<
pdu1HkTableDataset.voltageOutSUSNominal.value << std::endl;
sif::info << std::setw(30) << std::left << "Solar Cell Experiment" << std::dec << "| " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledSolarCellExp.value) << ", " <<
std::setw(4) << std::right <<
pdu1HkTableDataset.currentOutSolarCellExp.value << ", " << std::setw(4) <<
pdu1HkTableDataset.voltageOutSolarCellExp.value << std::endl;
sif::info << std::setw(30) << std::left << "PLOC" << std::dec << "| " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledPLOC.value) << ", " <<
std::setw(4) << std::right <<
pdu1HkTableDataset.currentOutPLOC.value << ", " << std::setw(4) <<
pdu1HkTableDataset.voltageOutPLOC.value << std::endl;
sif::info << std::setw(30) << std::left << "ACS Side A" << std::dec << "| " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledAcsBoardSideA.value) << ", " <<
std::setw(4) << std::right <<
pdu1HkTableDataset.currentOutACSBoardSideA.value << ", " << std::setw(4) <<
pdu1HkTableDataset.voltageOutACSBoardSideA.value << std::endl;
sif::info << std::setw(30) << std::left << "Channel 8" << std::dec << "| " <<
static_cast<unsigned int>(pdu1HkTableDataset.outEnabledChannel8.value) << ", " <<
std::setw(4) << std::right <<
pdu1HkTableDataset.currentOutChannel8.value << ", " << std::setw(4) <<
pdu1HkTableDataset.voltageOutChannel8.value << std::right << std::endl;
}

View File

@ -2,7 +2,7 @@
#define MISSION_DEVICES_PDU1Handler_H_ #define MISSION_DEVICES_PDU1Handler_H_
#include "GomspaceDeviceHandler.h" #include "GomspaceDeviceHandler.h"
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h> #include "devicedefinitions/GomspaceDefinitions.h"
/** /**
* @brief This is the device handler for the PDU1. * @brief This is the device handler for the PDU1.
@ -38,7 +38,7 @@ private:
/** Dataset for the housekeeping table of the PDU1 */ /** Dataset for the housekeeping table of the PDU1 */
PDU1::PDU1HkTableDataset pdu1HkTableDataset; PDU1::PDU1HkTableDataset pdu1HkTableDataset;
void printOutputSwitchStates(); void printHkTable();
void parseHkTableReply(const uint8_t *packet); void parseHkTableReply(const uint8_t *packet);
}; };

View File

@ -312,46 +312,14 @@ ReturnValue_t PDU2Handler::initializeLocalDataPool(
ReturnValue_t PDU2Handler::printStatus(DeviceCommandId_t cmd) { ReturnValue_t PDU2Handler::printStatus(DeviceCommandId_t cmd) {
switch(cmd) { switch(cmd) {
case(GOMSPACE::PRINT_ALL): { case(GOMSPACE::PRINT_HK_TABLE): {
PoolReadGuard pg(&pdu2HkTableDataset); PoolReadGuard pg(&pdu2HkTableDataset);
ReturnValue_t readResult = pg.getReadResult(); ReturnValue_t readResult = pg.getReadResult();
if(readResult != HasReturnvaluesIF::RETURN_OK) { if(readResult != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Reading PDU2 HK table failed!" << std::endl; sif::warning << "Reading PDU1 HK table failed!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
printOutputSwitchStates(); printHkTable();
printOutputCurrents();
printOutputVoltages();
return HasReturnvaluesIF::RETURN_OK;
}
case(GOMSPACE::PRINT_OUT_ENB_STATUS): {
PoolReadGuard pg(&pdu2HkTableDataset);
ReturnValue_t readResult = pg.getReadResult();
if(readResult != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Reading PDU2 HK table failed!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
printOutputSwitchStates();
return HasReturnvaluesIF::RETURN_OK;
}
case(GOMSPACE::PRINT_OUT_CURRENTS): {
PoolReadGuard pg(&pdu2HkTableDataset);
ReturnValue_t readResult = pg.getReadResult();
if(readResult != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Reading PDU2 HK table failed!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
printOutputCurrents();
return HasReturnvaluesIF::RETURN_OK;
}
case(GOMSPACE::PRINT_OUT_VOLTAGES): {
PoolReadGuard pg(&pdu2HkTableDataset);
ReturnValue_t readResult = pg.getReadResult();
if(readResult != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Reading PDU2 HK table failed!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
printOutputVoltages();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
default: { default: {
@ -360,67 +328,51 @@ ReturnValue_t PDU2Handler::printStatus(DeviceCommandId_t cmd) {
} }
} }
void PDU2Handler::printOutputSwitchStates() { void PDU2Handler::printHkTable() {
sif::info << "PDU2 Q7S enable state: " << sif::info << "PDU2 Info: SwitchState, Voltages [mV], Currents [mA]" << std::endl;
unsigned(pdu2HkTableDataset.outEnabledQ7S.value) << std::endl; sif::info << std::setw(30) << std::left << "Q7S" << std::dec << "| " <<
sif::info << "PDU2 Payload PCDU channel 1 enable state: " unsigned(pdu2HkTableDataset.outEnabledQ7S.value) << ", " <<
<< unsigned(pdu2HkTableDataset.outEnabledPlPCDUCh1.value) << std::endl; std::setw(4) << std::right <<
sif::info << "PDU2 reaction wheels enable state: " pdu2HkTableDataset.currentOutQ7S.value << ", " << std::setw(4) <<
<< unsigned(pdu2HkTableDataset.outEnabledReactionWheels.value) << std::endl; pdu2HkTableDataset.voltageOutQ7S.value << std::endl;
sif::info << "PDU2 TCS Board 8V heater input enable state: " sif::info << std::setw(30) << std::left << "Payload PCDU Channel 1" << std::dec << "| " <<
<< unsigned(pdu2HkTableDataset.outEnabledTCSBoardHeaterIn.value) << std::endl; unsigned(pdu2HkTableDataset.outEnabledPlPCDUCh1.value) << ", " <<
sif::info << "PDU2 redundant SUS group enable state: " std::setw(4) << std::right <<
<< unsigned(pdu2HkTableDataset.outEnabledSUSRedundant.value) << std::endl; pdu2HkTableDataset.currentOutPayloadPCDUCh1.value << ", " << std::setw(4) <<
sif::info << "PDU2 deployment mechanism enable state: "
<< unsigned(pdu2HkTableDataset.outEnabledDeplMechanism.value) << std::endl;
sif::info << "PDU2 PCDU channel 6 enable state: "
<< unsigned(pdu2HkTableDataset.outEnabledPlPCDUCh6.value) << std::endl;
sif::info << "PDU2 ACS board side B enable state: "
<< unsigned(pdu2HkTableDataset.outEnabledAcsBoardSideB.value) << std::endl;
sif::info << "PDU2 payload camera enable state: "
<< unsigned(pdu2HkTableDataset.outEnabledPayloadCamera.value) << std::endl;
}
void PDU2Handler::printOutputCurrents() {
sif::info << "Printing PDU2 currents [mA]: " << std::endl;
sif::info << "PDU2 Q7S:" <<
pdu2HkTableDataset.currentOutQ7S.value << std::endl;
sif::info << "PDU2 Payload PCDU:" <<
pdu2HkTableDataset.currentOutPayloadPCDUCh1.value << std::endl;
sif::info << "PDU2 RW:" <<
pdu2HkTableDataset.currentOutReactionWheels.value << std::endl;
sif::info << "PDU2 TCS Board Heater In:" <<
pdu2HkTableDataset.currentOutTCSBoardHeaterIn.value << std::endl;
sif::info << "PDU2 SuS Redundant:" <<
pdu2HkTableDataset.currentOutSUSRedundant.value << std::endl;
sif::info << "PDU2 Depl-Mechanism:" <<
pdu2HkTableDataset.currentOutDeplMechanism.value << std::endl;
sif::info << "PDU2 Payload PCDU:" <<
pdu2HkTableDataset.currentOutPayloadPCDUCh6.value << std::endl;
sif::info << "PDU2 ACS Board:" <<
pdu2HkTableDataset.currentOutACSBoardSideB.value << std::endl;
sif::info << "PDU2 Payload Camera:" <<
pdu2HkTableDataset.currentOutPayloadCamera.value << std::endl;
}
void PDU2Handler::printOutputVoltages() {
sif::info << "Printing PDU2 voltages [mV]: " << std::endl;
sif::info << "PDU2 Q7S:" <<
pdu2HkTableDataset.voltageOutQ7S.value << std::endl;
sif::info << "PDU2 Payload PCDU:" <<
pdu2HkTableDataset.voltageOutPayloadPCDUCh1.value << std::endl; pdu2HkTableDataset.voltageOutPayloadPCDUCh1.value << std::endl;
sif::info << "PDU2 RW:" << sif::info << std::setw(30) << std::left << "Reaction Wheels" << std::dec << "| " <<
unsigned(pdu2HkTableDataset.outEnabledReactionWheels.value) << ", " <<
std::setw(4) << std::right <<
pdu2HkTableDataset.currentOutReactionWheels.value << ", " << std::setw(4) <<
pdu2HkTableDataset.voltageOutReactionWheels.value << std::endl; pdu2HkTableDataset.voltageOutReactionWheels.value << std::endl;
sif::info << "PDU2 TCS Board Heater In:" << sif::info << std::setw(30) << std::left << "TCS Board 8V heater input" << std::dec << "| " <<
unsigned(pdu2HkTableDataset.outEnabledTCSBoardHeaterIn.value) << ", " <<
std::setw(4) << std::right <<
pdu2HkTableDataset.currentOutTCSBoardHeaterIn.value << ", " << std::setw(4) <<
pdu2HkTableDataset.voltageOutTCSBoardHeaterIn.value << std::endl; pdu2HkTableDataset.voltageOutTCSBoardHeaterIn.value << std::endl;
sif::info << "PDU2 SuS Redundant:" << sif::info << std::setw(30) << std::left << "Redundant SUS group" << std::dec << "| " <<
unsigned(pdu2HkTableDataset.outEnabledSUSRedundant.value) << ", " <<
std::setw(4) << std::right <<
pdu2HkTableDataset.currentOutSUSRedundant.value << ", " << std::setw(4) <<
pdu2HkTableDataset.voltageOutSUSRedundant.value << std::endl; pdu2HkTableDataset.voltageOutSUSRedundant.value << std::endl;
sif::info << "PDU2 Depl-Mechanism:" << sif::info << std::setw(30) << std::left << "Deployment mechanism" << std::dec << "| " <<
unsigned(pdu2HkTableDataset.outEnabledDeplMechanism.value) << ", " <<
std::setw(4) << std::right <<
pdu2HkTableDataset.currentOutDeplMechanism.value << ", " << std::setw(4) <<
pdu2HkTableDataset.voltageOutDeplMechanism.value << std::endl; pdu2HkTableDataset.voltageOutDeplMechanism.value << std::endl;
sif::info << "PDU2 Payload PCDU:" << sif::info << std::setw(30) << std::left << "Payload PCDU Channel 6" << std::dec << "| " <<
pdu2HkTableDataset.voltageOutPayloadPCDUCh6.value << std::endl; unsigned(pdu2HkTableDataset.outEnabledPlPCDUCh6.value) << ", " <<
sif::info << "PDU2 ACS Board voltage:" << std::setw(4) << std::right <<
pdu2HkTableDataset.currentOutPayloadPCDUCh6.value << ", " << std::setw(4) <<
pdu2HkTableDataset.voltageOutPayloadPCDUCh6.value<< std::endl;
sif::info << std::setw(30) << std::left << "ACS Board Side B" << std::dec << "| " <<
unsigned(pdu2HkTableDataset.outEnabledAcsBoardSideB.value) << ", " <<
std::setw(4) << std::right <<
pdu2HkTableDataset.currentOutACSBoardSideB.value << ", " << std::setw(4) <<
pdu2HkTableDataset.voltageOutACSBoardSideB.value << std::endl; pdu2HkTableDataset.voltageOutACSBoardSideB.value << std::endl;
sif::info << "PDU2 Payload Camera voltage:" << sif::info << std::setw(30) << std::left << "Payload Camera enable state" << std::dec << "| " <<
pdu2HkTableDataset.voltageOutPayloadCamera.value << std::endl; unsigned(pdu2HkTableDataset.outEnabledPayloadCamera.value) << ", " <<
std::setw(4) << std::right <<
pdu2HkTableDataset.currentOutPayloadCamera.value << ", " << std::setw(4) <<
pdu2HkTableDataset.voltageOutPayloadCamera.value << std::right << std::endl;
} }

View File

@ -39,9 +39,7 @@ private:
/** Dataset for the housekeeping table of the PDU2 */ /** Dataset for the housekeeping table of the PDU2 */
PDU2::PDU2HkTableDataset pdu2HkTableDataset; PDU2::PDU2HkTableDataset pdu2HkTableDataset;
void printOutputSwitchStates(); void printHkTable();
void printOutputCurrents();
void printOutputVoltages();
void parseHkTableReply(const uint8_t *packet); void parseHkTableReply(const uint8_t *packet);
}; };

View File

@ -9,7 +9,7 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_GOMSPACEDEFINITIONS_H_ #ifndef MISSION_DEVICES_DEVICEDEFINITIONS_GOMSPACEDEFINITIONS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_GOMSPACEDEFINITIONS_H_ #define MISSION_DEVICES_DEVICEDEFINITIONS_GOMSPACEDEFINITIONS_H_
#include <stdint.h> #include <cstdint>
#include <fsfw/devicehandlers/DeviceHandlerIF.h> #include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h> #include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/datapoollocal/LocalPoolVariable.h> #include <fsfw/datapoollocal/LocalPoolVariable.h>
@ -33,10 +33,8 @@ static const DeviceCommandId_t GNDWDT_RESET = 9; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t PARAM_GET = 0; //!< [EXPORT] : [COMMAND] static const DeviceCommandId_t PARAM_GET = 0; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t PARAM_SET = 255; //!< [EXPORT] : [COMMAND] static const DeviceCommandId_t PARAM_SET = 255; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t REQUEST_HK_TABLE = 16; //!< [EXPORT] : [COMMAND] static const DeviceCommandId_t REQUEST_HK_TABLE = 16; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t PRINT_ALL = 32; //!< [EXPORT] : [COMMAND] //!< [EXPORT] : [COMMAND] Print switch states, voltages and currents to the console
static const DeviceCommandId_t PRINT_OUT_ENB_STATUS = 33; //!< [EXPORT] : [COMMAND] static const DeviceCommandId_t PRINT_HK_TABLE = 32;
static const DeviceCommandId_t PRINT_OUT_CURRENTS = 34; //!< [EXPORT] : [COMMAND]
static const DeviceCommandId_t PRINT_OUT_VOLTAGES = 35; //!< [EXPORT] : [COMMAND]
} }

2
tmtc

@ -1 +1 @@
Subproject commit 58da80cb9e2426e6b9d7fc1efb661077c35541f5 Subproject commit f3a2e755fdc73ee791ea32dc6f2dfce43af70e60