#include "ACUHandler.h" #include "OBSWConfig.h" ACUHandler::ACUHandler(object_id_t objectId, object_id_t comIF, CookieIF *comCookie, FailureIsolationBase *customFdir) : GomspaceDeviceHandler(objectId, comIF, comCookie, cfg, customFdir), coreHk(this), auxHk(this) { cfg.maxConfigTableAddress = ACU::MAX_CONFIGTABLE_ADDRESS; cfg.maxHkTableAddress = ACU::MAX_HKTABLE_ADDRESS; cfg.hkTableSize = ACU::HK_TABLE_SIZE; cfg.cfgTableSize = ACU::CONFIG_TABLE_SIZE; } ACUHandler::~ACUHandler() {} ReturnValue_t ACUHandler::buildNormalDeviceCommand(DeviceCommandId_t *id) { *id = GOMSPACE::REQUEST_HK_TABLE; return buildCommandFromCommand(*id, nullptr, 0); } void ACUHandler::fillCommandAndReplyMap() { GomspaceDeviceHandler::fillCommandAndReplyMap(); } void ACUHandler::letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) { parseHkTableReply(packet); if (debugMode) { #if OBSW_VERBOSE_LEVEL >= 1 PoolReadGuard pg0(&auxHk); PoolReadGuard pg1(&coreHk); if (pg0.getReadResult() != returnvalue::OK or pg1.getReadResult() != returnvalue::OK) { return; } for (size_t idx = 0; idx < 3; idx++) { float tempC = coreHk.temperatures[idx] * 0.1; sif::info << "ACU: Temperature " << idx << ": " << tempC << " °C" << std::endl; } sif::info << "ACU: Ground Watchdog Timer Count: " << auxHk.wdtCntGnd.value << std::endl; sif::info << "ACU: Ground watchdog timer, seconds left before reboot: " << auxHk.wdtGndLeft.value << std::endl; #endif } } void ACUHandler::letChildHandleConfigReply(DeviceCommandId_t id, const uint8_t *packet) { handleDeviceTm(util::DataWrapper(packet, ACU::CONFIG_TABLE_SIZE), id); } LocalPoolDataSetBase *ACUHandler::getDataSetHandle(sid_t sid) { if (sid == coreHk.getSid()) { return &coreHk; } else if (sid == auxHk.getSid()) { return &auxHk; } return nullptr; } ReturnValue_t ACUHandler::parseHkTableReply(const uint8_t *packet) { PoolReadGuard pg0(&coreHk); PoolReadGuard pg1(&auxHk); auto res0 = pg0.getReadResult(); auto res1 = pg1.getReadResult(); if (res0 != returnvalue::OK) { return res0; } if (res1 != returnvalue::OK) { return res1; } for (size_t idx = 0; idx < 6; idx++) { coreHk.currentInChannels[idx] = as(packet + (idx * 2)); } for (size_t idx = 0; idx < 6; idx++) { coreHk.voltageInChannels[idx] = as(packet + 0xc + (idx * 2)); } coreHk.vcc = as(packet + 0x1a); coreHk.vbat = as(packet + 0x18); for (size_t idx = 0; idx < 3; idx++) { coreHk.temperatures[idx] = as(packet + 0x1c + (idx * 2)) * 0.1; } coreHk.mpptMode = packet[0x22]; for (size_t idx = 0; idx < 6; idx++) { coreHk.vboostInChannels[idx] = as(packet + 0x24 + (idx * 2)); } for (size_t idx = 0; idx < 6; idx++) { coreHk.powerInChannels[idx] = as(packet + 0x30 + (idx * 2)); } for (size_t idx = 0; idx < 3; idx++) { auxHk.dacEnables[idx] = *(packet + 0x3c + idx); } for (size_t idx = 0; idx < 6; idx++) { auxHk.dacRawChannelVals[idx] = as(packet + 0x40 + (idx * 2)); } auxHk.bootCause = as(packet + 0x50); coreHk.bootcnt = as(packet + 0x54); coreHk.uptime = as(packet + 0x58); auxHk.resetCause = as(packet + 0x5c); coreHk.mpptTime = as(packet + 0x5e); coreHk.mpptPeriod = as(packet + 0x60); for (size_t idx = 0; idx < 8; idx++) { auxHk.deviceTypes[idx] = *(packet + 0x64 + idx); } for (size_t idx = 0; idx < 8; idx++) { auxHk.devicesStatus[idx] = *(packet + 0x6c + idx); } auxHk.wdtCntGnd = as(packet + 0x74); auxHk.wdtGndLeft = as(packet + 0x78); coreHk.setValidity(true, true); auxHk.setValidity(true, true); return returnvalue::OK; } ReturnValue_t ACUHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { using namespace ACU; localDataPoolMap.emplace(pool::ACU_CURRENT_IN_CHANNELS, new PoolEntry(6)); localDataPoolMap.emplace(pool::ACU_VOLTAGE_IN_CHANNELS, new PoolEntry(6)); localDataPoolMap.emplace(pool::ACU_VCC, new PoolEntry({0})); localDataPoolMap.emplace(pool::ACU_VBAT, new PoolEntry({0})); localDataPoolMap.emplace(pool::ACU_TEMPERATURES, new PoolEntry(3)); localDataPoolMap.emplace(pool::ACU_MPPT_MODE, new PoolEntry({0})); localDataPoolMap.emplace(pool::ACU_VBOOST_IN_CHANNELS, new PoolEntry(6)); localDataPoolMap.emplace(pool::ACU_POWER_IN_CHANNELS, new PoolEntry(6)); localDataPoolMap.emplace(pool::ACU_DAC_ENABLES, new PoolEntry(3)); localDataPoolMap.emplace(pool::ACU_DAC_RAW_CHANNELS, new PoolEntry(6)); localDataPoolMap.emplace(pool::ACU_BOOTCAUSE, new PoolEntry({0})); localDataPoolMap.emplace(pool::ACU_BOOTCNT, new PoolEntry({0})); localDataPoolMap.emplace(pool::ACU_UPTIME, new PoolEntry({0})); localDataPoolMap.emplace(pool::ACU_RESET_CAUSE, new PoolEntry({0})); localDataPoolMap.emplace(pool::ACU_MPPT_TIME, new PoolEntry({0})); localDataPoolMap.emplace(pool::ACU_MPPT_PERIOD, new PoolEntry({0})); localDataPoolMap.emplace(pool::ACU_DEVICES, new PoolEntry(8)); localDataPoolMap.emplace(pool::ACU_DEVICES_STATUS, new PoolEntry(8)); localDataPoolMap.emplace(pool::ACU_WDT_CNT_GND, new PoolEntry({0})); localDataPoolMap.emplace(pool::ACU_WDT_GND_LEFT, new PoolEntry({0})); poolManager.subscribeForDiagPeriodicPacket( subdp::DiagnosticsHkPeriodicParams(coreHk.getSid(), false, 10.0)); poolManager.subscribeForRegularPeriodicPacket( subdp::RegularHkPeriodicParams(auxHk.getSid(), false, 30.0)); return returnvalue::OK; } void ACUHandler::printChannelStats() { PoolReadGuard pg(&coreHk); sif::info << "ACU Info: Current [mA], Voltage [mV]" << std::endl; for (size_t idx = 0; idx < 6; idx++) { sif::info << std::setw(8) << std::left << "Channel " << idx << std::dec << "| " << static_cast(coreHk.currentInChannels[idx]) << std::setw(15) << std::right << coreHk.voltageInChannels[idx] << std::endl; } } void ACUHandler::setDebugMode(bool enable) { this->debugMode = enable; } ReturnValue_t ACUHandler::printStatus(DeviceCommandId_t cmd) { ReturnValue_t result = returnvalue::OK; switch (cmd) { case (GOMSPACE::PRINT_SWITCH_V_I): { PoolReadGuard pg(&coreHk); result = pg.getReadResult(); if (result != returnvalue::OK) { break; } printChannelStats(); break; } default: { return DeviceHandlerIF::COMMAND_NOT_SUPPORTED; } } if (result != returnvalue::OK) { sif::warning << "Reading PDU1 HK table failed!" << std::endl; } return result; }