#include "ePowerSwitchEquipment.h" #include "ePowerSwitchEquipmentConfig.h" #include "tmfe.h" #include /** * @brief Insert a integer value between two string * @param str1 first string * @param int value to insert * @param str2 second string * * @return a new string instance */ std::string insert(const std::string *str1, int value, const std::string *str2) { return *str1 + std::to_string(value) + *str2; } ePowerSwitchEquipment::ePowerSwitchEquipment(std::string equipmentName, const char *equipmentFileName) : TMFeEquipment(equipmentName.c_str(), equipmentFileName), outletNumberRecord(mEpicsCa( std::string_view(EPOWERSWITCH_OUTLETNUMBER_INFO_PREFIX))) { fEqConfPeriodMilliSec = 1000; // refresh rate of midas frontend fEqConfLogHistory = 60; // enable history system, generate one event per minutes fEqConfReadOnlyWhenRunning = false; // allow to write values when running fEqConfWriteEventsToOdb = true; // allow to write event to the odb this->numberOfOutlet = 0; } void ePowerSwitchEquipment::HandlePeriodic() { updateOutletNumber(); refreshAllOutlets(); } void ePowerSwitchEquipment::refreshOutlet(int outletId) { std::string usernameVarname; { static const std::string str1 = "Outlet "; static const std::string str2 = " name"; usernameVarname = insert(&str1, outletId, &str2); } std::string requestedVarname; { static const std::string str1 = "|-> "; static const std::string str2 = " requested"; requestedVarname = insert(&str1, outletId, &str2); } std::string currentVarname; { static const std::string str1 = "\\-> "; static const std::string str2 = " current"; currentVarname = insert(&str1, outletId, &str2); } std::string midasUsername; { static const std::string str1 = "Outlet "; static const std::string str2 = ""; midasUsername = insert(&str1, outletId, &str2); } std::string midasRequestedOutletState = std::string("Off"); MVOdbError ovbError; fOdbEqVariables->RS(usernameVarname.c_str(), &midasUsername, true, midasUsername.length() + 1, &ovbError); if (ovbError.fError) { fMfe->Msg(MERROR, __FUNCTION__, ovbError.fErrorString); exit(EXIT_FAILURE); } fOdbEqVariables->RS(requestedVarname.c_str(), &midasRequestedOutletState, true, midasRequestedOutletState.length() + 1, &ovbError); if (ovbError.fError) { fMfe->Msg(MERROR, __FUNCTION__, ovbError.fErrorString); exit(EXIT_FAILURE); } std::string defaultCurrentState = "unknow"; fOdbEqVariables->RS(currentVarname.c_str(), &defaultCurrentState, true, defaultCurrentState.length() + 1, &ovbError); if (ovbError.fError) { fMfe->Msg(MERROR, __FUNCTION__, ovbError.fErrorString); exit(EXIT_FAILURE); } std::string epicsCurrentOutletState; int mepicscaReturnCode = this->outletGetRecords.at(outletId)->get(&epicsCurrentOutletState); if (mepicscaReturnCode != CM_SUCCESS) return; if (epicsCurrentOutletState != midasRequestedOutletState) { mepicscaReturnCode = this->outletSetRecords.at(outletId)->put( &midasRequestedOutletState); if (mepicscaReturnCode != CM_SUCCESS) return; } fOdbEqVariables->WS(currentVarname.c_str(), epicsCurrentOutletState.c_str(), epicsCurrentOutletState.length() + 1, &ovbError); if (ovbError.fError) { fMfe->Msg(MERROR, __FUNCTION__, ovbError.fErrorString); exit(EXIT_FAILURE); } } void ePowerSwitchEquipment::refreshAllOutlets() { for (int i = 0; i < this->numberOfOutlet; i++) { refreshOutlet(i); } } void ePowerSwitchEquipment::updateOutletNumber() { int epicsOutletNumber = 0; int returnCode = outletNumberRecord.get(&epicsOutletNumber); if (returnCode != CM_SUCCESS) return; if (this->numberOfOutlet < epicsOutletNumber) fMfe->Msg(MDEBUG, __FUNCTION__, "Outlet number increasing, creating %d new outlet(s)", epicsOutletNumber - this->numberOfOutlet); /* This for loop will only iterate if the condition on top of this comment is true */ for (int i = this->numberOfOutlet; i < epicsOutletNumber; i++) { std::string epicsSetRecordName; { static const std::string *str1 = &EPOWERSWITCH_OUTLET_SET_PREFIX; static const std::string str2 = ""; epicsSetRecordName = insert(str1, i, &str2); } this->outletSetRecords.push_back( std::make_unique>( epicsSetRecordName.c_str())); std::string epicsGetRecordName; { static const std::string *str1 = &EPOWERSWITCH_OUTLET_GET_PREFIX; static const std::string str2 = ""; epicsGetRecordName = insert(str1, i, &str2); } this->outletGetRecords.push_back( std::make_unique>( epicsGetRecordName.c_str())); } if (this->numberOfOutlet > epicsOutletNumber) fMfe->Msg(MDEBUG, __FUNCTION__, "Outlet number decreasing, destroying %d outlet(s)", this->numberOfOutlet - epicsOutletNumber); /* This for loop will only iterate if the condition on top of this comment is true */ for (int i = epicsOutletNumber; i < this->numberOfOutlet; i++) { std::string requestedVarname; std::string currentVarname; { static const std::string str1 = "Outlet "; static const std::string str2a = " current"; static const std::string str2b = " requested"; requestedVarname = insert(&str1, i, &str2a); currentVarname = insert(&str1, i, &str2b); } MVOdbError ovbError; fOdbEqVariables->Delete(requestedVarname.c_str(), &ovbError); if (ovbError.fError) { fMfe->Msg(MERROR, __FUNCTION__, ovbError.fErrorString); exit(EXIT_FAILURE); } fOdbEqVariables->Delete(currentVarname.c_str(), &ovbError); if (ovbError.fError) { fMfe->Msg(MERROR, __FUNCTION__, ovbError.fErrorString); exit(EXIT_FAILURE); } this->outletSetRecords.pop_back(); this->outletGetRecords.pop_back(); } this->numberOfOutlet = epicsOutletNumber; }