137 lines
4.2 KiB
C++
137 lines
4.2 KiB
C++
#include "../include/ePowerSwitchFront.h"
|
|
#include "../include/ePowerSwitchConfig.h"
|
|
#include "m_epics_ca.h"
|
|
#include "tmfe.h"
|
|
#include <format>
|
|
#include <sstream>
|
|
|
|
/**
|
|
* @brief local function: append an integer to the end of a string.
|
|
* @param str string prefix
|
|
* @param value integer to append
|
|
* @return "str" + integer
|
|
*/
|
|
std::string format(std::string str, int value) {
|
|
std::stringstream ss;
|
|
ss << str;
|
|
ss << value;
|
|
return ss.str();
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
if (argv[0][0] == '.') {
|
|
TMFE::Instance()->Msg(MERROR, __FUNCTION__,
|
|
"Relative paths are strongly not recommended; "
|
|
"please use an absolute path");
|
|
}
|
|
|
|
std::string frontendName;
|
|
std::string equipmentName;
|
|
|
|
if (argc == 1) {
|
|
frontendName = DEFAULT_FRONTEND_NAME;
|
|
TMFE::Instance()->Msg(MINFO, __FUNCTION__,
|
|
"no frontend name provided; %s will be used",
|
|
DEFAULT_FRONTEND_NAME);
|
|
equipmentName = DEFAULT_EQUIPMENT_NAME;
|
|
TMFE::Instance()->Msg(MINFO, __FUNCTION__,
|
|
"no equipment name provided; %s will be used",
|
|
DEFAULT_EQUIPMENT_NAME);
|
|
}
|
|
if (argc == 2) {
|
|
frontendName = std::string(argv[1]);
|
|
argv++;
|
|
argc--;
|
|
TMFE::Instance()->Msg(MINFO, __FUNCTION__,
|
|
"no equipment name provided; %s will be use",
|
|
DEFAULT_EQUIPMENT_NAME);
|
|
} else if (argc == 3) {
|
|
frontendName = std::string(argv[1]);
|
|
equipmentName = std::string(argv[2]);
|
|
argv += 2;
|
|
argc -= 2;
|
|
}
|
|
|
|
auto front = new ePowerSwitchFrontend(frontendName, equipmentName);
|
|
front->FeMain(argc, argv);
|
|
}
|
|
|
|
ePowerSwitchEquipment::ePowerSwitchEquipment(std::string equipmentName,
|
|
const char *equipmentFileName)
|
|
: TMFeEquipment(equipmentName.c_str(), equipmentFileName),
|
|
outletNumberRecord(mEpicsCa<int>(
|
|
std::string_view(EPOWERSWITCH_SOCKETNUMBER_INFO_PREFIX), true)) {
|
|
fEqConfReadConfigFromOdb = false;
|
|
fEqConfPeriodMilliSec = 1000;
|
|
fEqConfLogHistory = 1;
|
|
fEqConfReadOnlyWhenRunning = false;
|
|
fEqConfWriteEventsToOdb = true;
|
|
|
|
this->numberOfOutlet = 0;
|
|
}
|
|
|
|
void ePowerSwitchEquipment::HandlePeriodic() {
|
|
updateSocketNumber();
|
|
refreshAllSockets();
|
|
}
|
|
|
|
void ePowerSwitchEquipment::refreshSocket(int socketId) {
|
|
std::string varname = format("Socket ", socketId);
|
|
|
|
int midasSocketState = 0; // default => turn off
|
|
fOdbEqVariables->RI(varname.c_str(), &midasSocketState, true);
|
|
|
|
if (midasSocketState != this->outletLastState.at(socketId)) {
|
|
this->outletCommandRecords.at(socketId)->put(&midasSocketState);
|
|
}
|
|
|
|
this->outletLastState.at(socketId) = midasSocketState;
|
|
}
|
|
|
|
void ePowerSwitchEquipment::refreshAllSockets() {
|
|
for (int i = 0; i < this->numberOfOutlet; i++) {
|
|
refreshSocket(i);
|
|
}
|
|
}
|
|
|
|
void ePowerSwitchEquipment::updateSocketNumber() {
|
|
int epicsOutletNumber = 0;
|
|
|
|
if (!outletNumberRecord.connected())
|
|
return;
|
|
int returnCode = outletNumberRecord.get(&epicsOutletNumber);
|
|
|
|
if (returnCode < 0) {
|
|
printf("error\n");
|
|
return;
|
|
}
|
|
|
|
for (int i = this->numberOfOutlet; i < epicsOutletNumber; i++) {
|
|
std::string epicsRecordName =
|
|
format(EPOWERSWITCH_SOCKET_COMMAND_PREFIX, i);
|
|
|
|
this->outletCommandRecords.push_back(
|
|
new mEpicsCa<int>(epicsRecordName.c_str(), true));
|
|
this->outletLastState.push_back(0);
|
|
|
|
printf("new socket created\n");
|
|
}
|
|
|
|
for (int i = epicsOutletNumber; i < this->numberOfOutlet; i++) {
|
|
mEpicsCa<int> *ptr = this->outletCommandRecords.back();
|
|
delete ptr;
|
|
|
|
this->outletCommandRecords.pop_back();
|
|
this->outletLastState.pop_back();
|
|
printf("old socket destroyed\n");
|
|
}
|
|
|
|
this->numberOfOutlet = epicsOutletNumber;
|
|
}
|
|
|
|
ePowerSwitchFrontend::ePowerSwitchFrontend(std::string frontendName,
|
|
std::string equipmentName) {
|
|
FeSetName(frontendName.c_str());
|
|
FeAddEquipment(new ePowerSwitchEquipment(equipmentName.c_str(), __FILE__));
|
|
} |