#ifndef MISSION_TCS_HEATERHANDLER_H_ #define MISSION_TCS_HEATERHANDLER_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "events/subsystemIdRanges.h" #include "mission/tcs/defs.h" #include "returnvalues/classIds.h" class PowerSwitchIF; class HealthTableIF; using HeaterPair = std::pair; struct HeaterHelper { public: HeaterHelper(std::array heaters) : heaters(std::move(heaters)) {} std::array heaters = {}; }; /** * @brief This class intends the control of heaters. * * @author J. Meier */ class HeaterHandler : public ExecutableObjectIF, public PowerSwitchIF, public HasModesIF, public ModeTreeChildIF, public ModeTreeConnectionIF, public SystemObject, public HasActionsIF { friend class ThermalController; public: static const uint8_t INTERFACE_ID = CLASS_ID::HEATER_HANDLER; static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); static const ReturnValue_t INIT_FAILED = MAKE_RETURN_CODE(0xA2); static const ReturnValue_t INVALID_SWITCH_NR = MAKE_RETURN_CODE(0xA3); static const ReturnValue_t MAIN_SWITCH_SET_TIMEOUT = MAKE_RETURN_CODE(0xA4); static const ReturnValue_t COMMAND_ALREADY_WAITING = MAKE_RETURN_CODE(0xA5); enum CmdSourceParam : uint8_t { INTERNAL = 0, EXTERNAL = 1 }; enum SwitchState : uint8_t { ON = 1, OFF = 0 }; /** Device command IDs */ static const DeviceCommandId_t SWITCH_HEATER = 0x0; HeaterHandler(object_id_t setObjectId, GpioIF* gpioInterface_, HeaterHelper helper, PowerSwitchIF* mainLineSwitcherObjectId, power::Switch_t mainLineSwitch); ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override; ReturnValue_t getAllSwitchStates(std::array& statesBuf); virtual ~HeaterHandler(); protected: enum SwitchAction : uint8_t { SET_SWITCH_OFF, SET_SWITCH_ON, NONE }; ReturnValue_t switchHeater(heater::Switch heater, SwitchState switchState); HasHealthIF::HealthState getHealth(heater::Switch heater); ReturnValue_t performOperation(uint8_t operationCode = 0) override; ReturnValue_t sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) override; ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) override; /** * @brief This function will be called from the Heater object to check * the current switch state. */ ReturnValue_t getSwitchState(uint8_t switchNr) const override; ReturnValue_t getFuseState(uint8_t fuseNr) const override; uint32_t getSwitchDelayMs(void) const override; MessageQueueId_t getCommandQueue() const override; ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) override; ReturnValue_t initialize() override; private: static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HEATER_HANDLER; static constexpr Event GPIO_PULL_HIGH_FAILED = MAKE_EVENT(0, severity::LOW); static constexpr Event GPIO_PULL_LOW_FAILED = MAKE_EVENT(1, severity::LOW); static constexpr Event HEATER_WENT_ON = event::makeEvent(SUBSYSTEM_ID, 2, severity::INFO); static constexpr Event HEATER_WENT_OFF = event::makeEvent(SUBSYSTEM_ID, 3, severity::INFO); static constexpr Event SWITCH_ALREADY_ON = MAKE_EVENT(4, severity::INFO); static constexpr Event SWITCH_ALREADY_OFF = MAKE_EVENT(5, severity::INFO); static constexpr Event MAIN_SWITCH_TIMEOUT = MAKE_EVENT(6, severity::MEDIUM); //! A faulty heater was one. The SW will autonomously attempt to shut it down. P1: Heater Index static constexpr Event FAULTY_HEATER_WAS_ON = event::makeEvent(SUBSYSTEM_ID, 7, severity::LOW); static const MessageQueueId_t NO_COMMANDER = 0; /** * @brief Struct holding information about a heater command to execute. * * @param action The action to perform. * @param replyQueue The queue of the commander to which status replies * will be sent. * @param active True if command is waiting for execution, otherwise false. * @param waitSwitchOn True if the command is waiting for the main switch being set on. * @param mainSwitchCountdown Sets timeout to wait for main switch being set on. */ struct HeaterWrapper { HeaterWrapper(HeaterPair pair, SwitchState initState) : healthDevice(pair.first), gpioId(pair.second), switchState(initState) {} HealthDevice* healthDevice = nullptr; gpioId_t gpioId = gpio::NO_GPIO; SwitchAction action = SwitchAction::NONE; MessageQueueId_t replyQueue = MessageQueueIF::NO_QUEUE; bool cmdActive = false; SwitchState switchState = SwitchState::OFF; bool waitMainSwitchOn = false; Countdown mainSwitchCountdown; }; using HeaterMap = std::vector; HeaterMap heaterVec = {}; MutexIF* handlerLock = nullptr; static constexpr MutexIF::TimeoutType LOCK_TYPE = MutexIF::TimeoutType::WAITING; static constexpr uint32_t LOCK_TIMEOUT = 20; static constexpr char LOCK_CTX[] = "HeaterHandler"; HeaterHelper helper; ModeHelper modeHelper; /** Size of command queue */ size_t cmdQueueSize = 20; bool waitForSwitchOff = true; bool busyWithSwitchCommanding = false; GpioIF* gpioInterface = nullptr; /** Queue to receive messages from other objects. */ MessageQueueIF* commandQueue = nullptr; /** * Power switcher object which controls the 8V main line of the heater * logic on the TCS board. */ PowerSwitchIF* mainLineSwitcher = nullptr; /** Switch number of the heater power supply switch */ power::Switch_t mainLineSwitch; ActionHelper actionHelper; Countdown heaterCmdBusyCd = Countdown(2000); StorageManagerIF* ipcStore = nullptr; Mode_t mode = HasModesIF::MODE_OFF; Submode_t submode = 0; void readCommandQueue(); /** * @brief Returns the state of a switch (ON - true, or OFF - false). * @param switchNr The number of the switch to check. */ SwitchState getSwitchState(heater::Switch switchNr) const; /** * @brief This function runs commands waiting for execution. */ void handleSwitchHandling(); ReturnValue_t initializeHeaterMap(); /** * @brief Sets all switches to OFF. */ void setInitialSwitchStates(); // HasModesIF implementation void announceMode(bool recursive) override; void getMode(Mode_t* mode, Submode_t* submode) override; // Mode Tree helper overrides object_id_t getObjectId() const override; const HasHealthIF* getOptHealthIF() const override; const HasModesIF& getModeIF() const override; ModeTreeChildIF& getModeTreeChildIF() override; void handleSwitchOnCommand(heater::Switch heaterIdx); void handleSwitchOffCommand(heater::Switch heaterIdx); /** * @brief Checks if all switches are off. * @return True if all switches are off, otherwise false. */ bool allSwitchesOff(); }; #endif /* MISSION_TCS_HEATERHANDLER_H_ */