Skip to content

Commit

Permalink
Tidy up the From/ToString functions in IOTypes.h to make them more co…
Browse files Browse the repository at this point in the history
…nsistent
  • Loading branch information
neilstephens committed Aug 9, 2024
1 parent aab46ca commit 872bf31
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 81 deletions.
14 changes: 9 additions & 5 deletions Code/Libs/ODC/IOTypesJSON.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,9 @@ template<> ControlRelayOutputBlock PayloadFromJson(const Json::Value& JLoad)
ControlRelayOutputBlock CROB;
if(JLoad["ControlCode"].isUInt())
CROB.functionCode = static_cast<ControlCode>(JLoad["ControlCode"].asUInt()&0xFF);
else if(!JLoad["ControlCode"].isString() || !ToControlCode(JLoad["ControlCode"].asString(),CROB.functionCode))
else if(JLoad["ControlCode"].isString())
CROB.functionCode = ControlCodeFromString(JLoad["ControlCode"].asString());
else
throw std::invalid_argument("Payload 'ControlCode' is not unsigned integer or valid string.");

if(JLoad.isMember("CommandStatus"))
Expand Down Expand Up @@ -401,10 +403,12 @@ template<> ConnectState PayloadFromJson(const Json::Value& JLoad)
return static_cast<ConnectState>(JLoad.asUInt());
}

ConnectState CS;
if(JLoad.isString() && GetConnectStateFromStringName(JLoad.asString(),CS))
return CS;

if(JLoad.isString())
{
ConnectState CS = ConnectStateFromString(JLoad.asString());
if(CS != ConnectState::UNDEFINED)
return CS;
}
throw std::invalid_argument("Payload not convertable to odc::ConnectState.");
}

Expand Down
8 changes: 4 additions & 4 deletions Code/Ports/PyPort/PyPort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,8 +354,8 @@ std::shared_ptr<odc::EventInfo> PyPort::CreateEventFromStrParams(const std::stri
{
case EventType::ConnectState:
{
ConnectState state; // PORT_UP,CONNECTED,DISCONNECTED,PORT_DOWN
if (!GetConnectStateFromStringName(PayloadStr, state))
ConnectState state = ConnectStateFromString(PayloadStr);
if (state == ConnectState::UNDEFINED)
{
LOGERROR("Invalid Connection State passed from Python Code to ODC - {}", PayloadStr);
return nullptr;
Expand Down Expand Up @@ -406,8 +406,8 @@ std::shared_ptr<odc::EventInfo> PyPort::CreateEventFromStrParams(const std::stri
auto Parts = split(PayloadStr, '|');
if (Parts.size() != 5) throw std::runtime_error("Payload for ControlRelayOutputBlock does not have enough sections " + PayloadStr);

ControlCode ControlCodeResult;
ToControlCode(Parts[1], ControlCodeResult);
ControlCode ControlCodeResult = ControlCodeFromString(Parts[1]);
if(ControlCodeResult == ControlCode::UNDEFINED) throw std::runtime_error("ControlCode field of ControlRelayOutputBlock not in " + Parts[1]);
val.functionCode = ControlCodeResult;

if (Parts[2].find("Count") == std::string::npos) throw std::runtime_error("Count field of ControlRelayOutputBlock not in " + Parts[2]);
Expand Down
2 changes: 1 addition & 1 deletion Code/Ports/SimPort/SimPort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ void SimPort::Build()
std::string error = "";

if (parameters.count("type") != 0)
type = ToEventType(parameters.at("type"));
type = EventTypeFromString(parameters.at("type"));
else
error = "No 'type' parameter found";

Expand Down
6 changes: 3 additions & 3 deletions Code/Ports/SimPort/SimPortCollection.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class SimPortCollection: public ResponderMap< std::weak_ptr<SimPort> >
{
return IUIResponder::GenerateResult("Bad parameter");
}
auto type = ToEventType(params.at("0"));
auto type = EventTypeFromString(params.at("0"));
auto index = params.at("1");
auto period = params.at("2");
if(target->UISetUpdateInterval(type,index,period))
Expand Down Expand Up @@ -119,7 +119,7 @@ class SimPortCollection: public ResponderMap< std::weak_ptr<SimPort> >
{
return IUIResponder::GenerateResult("Bad parameter");
}
auto type = ToEventType(params.at("0"));
auto type = EventTypeFromString(params.at("0"));
auto index = params.at("1");
if(target->UIRelease(type,index))
return IUIResponder::GenerateResult("Success");
Expand Down Expand Up @@ -148,7 +148,7 @@ class SimPortCollection: public ResponderMap< std::weak_ptr<SimPort> >
{
return IUIResponder::GenerateResult("Bad parameter");
}
auto type = ToEventType(params.at("0"));
auto type = EventTypeFromString(params.at("0"));
auto index = params.at("1");
auto value = params.at("2");
std::string quality = "";
Expand Down
4 changes: 1 addition & 3 deletions Code/tests/DNP3Port_tests/TestDNP3EventHandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,8 @@ void CheckPointDB(const std::shared_ptr<DataPort>& port, const std::vector<Paylo
payload_as_expected = true;
break;
}
if constexpr(ET == EventType::OctetString)
if constexpr(ET == EventType::OctetString || ET == EventType::ControlRelayOutputBlock)
UNSCOPED_INFO("Payload is " << ToString(payload) << ", expected " << ToString(expected_payload));
else if constexpr(ET == EventType::ControlRelayOutputBlock)
UNSCOPED_INFO("Payload is " << std::string(payload) << ", expected " << std::string(expected_payload));
else
UNSCOPED_INFO("Payload is " << payload << ", expected " << expected_payload);
}
Expand Down
109 changes: 44 additions & 65 deletions include/opendatacon/IOTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,12 @@ inline bool operator!=(const ControlRelayOutputBlock& lhs, const ControlRelayOut
{
return !(lhs == rhs);
}
inline std::string ToString(const ControlRelayOutputBlock& crob)
{
return std::string(crob);
}

enum class ConnectState {PORT_UP,CONNECTED,DISCONNECTED,PORT_DOWN};
enum class ConnectState {PORT_UP,CONNECTED,DISCONNECTED,PORT_DOWN,UNDEFINED};
inline std::string ToString(const ConnectState cs)
{
ENUMSTRING(cs, ConnectState, PORT_UP)
Expand Down Expand Up @@ -351,89 +355,64 @@ inline QualityFlags QualityFlagsFromString(const std::string& StrQuality)
return QualityResult;
}

#define CHECKENUMSTRING(S,C,X) if (S == #X) return C::X

inline CommandStatus CommandStatusFromString(const std::string& StrCommandStatus)
{
#define CHECKCSSTRING(C,X) if (StrCommandStatus == #X) return C::X
CHECKCSSTRING(CommandStatus,SUCCESS);
CHECKCSSTRING(CommandStatus,TIMEOUT);
CHECKCSSTRING(CommandStatus,NO_SELECT);
CHECKCSSTRING(CommandStatus,FORMAT_ERROR);
CHECKCSSTRING(CommandStatus,NOT_SUPPORTED);
CHECKCSSTRING(CommandStatus,ALREADY_ACTIVE);
CHECKCSSTRING(CommandStatus,HARDWARE_ERROR);
CHECKCSSTRING(CommandStatus,LOCAL);
CHECKCSSTRING(CommandStatus,TOO_MANY_OPS);
CHECKCSSTRING(CommandStatus,NOT_AUTHORIZED);
CHECKCSSTRING(CommandStatus,AUTOMATION_INHIBIT);
CHECKCSSTRING(CommandStatus,PROCESSING_LIMITED);
CHECKCSSTRING(CommandStatus,OUT_OF_RANGE);
CHECKCSSTRING(CommandStatus,DOWNSTREAM_LOCAL);
CHECKCSSTRING(CommandStatus,ALREADY_COMPLETE);
CHECKCSSTRING(CommandStatus,BLOCKED);
CHECKCSSTRING(CommandStatus,CANCELLED);
CHECKCSSTRING(CommandStatus,BLOCKED_OTHER_MASTER);
CHECKCSSTRING(CommandStatus,DOWNSTREAM_FAIL);
CHECKCSSTRING(CommandStatus,NON_PARTICIPATING);
CHECKCSSTRING(CommandStatus,UNDEFINED);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,SUCCESS);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,TIMEOUT);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,NO_SELECT);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,FORMAT_ERROR);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,NOT_SUPPORTED);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,ALREADY_ACTIVE);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,HARDWARE_ERROR);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,LOCAL);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,TOO_MANY_OPS);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,NOT_AUTHORIZED);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,AUTOMATION_INHIBIT);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,PROCESSING_LIMITED);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,OUT_OF_RANGE);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,DOWNSTREAM_LOCAL);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,ALREADY_COMPLETE);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,BLOCKED);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,CANCELLED);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,BLOCKED_OTHER_MASTER);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,DOWNSTREAM_FAIL);
CHECKENUMSTRING(StrCommandStatus,CommandStatus,NON_PARTICIPATING);
return CommandStatus::UNDEFINED;
}

inline EventType EventTypeFromString(const std::string StrEventType)
inline EventType EventTypeFromString(const std::string& StrEventType)
{
auto EventTypeResult = EventType::BeforeRange;
do
{
EventTypeResult = EventTypeResult+1;
auto FindStr = ToString(EventTypeResult);
if(FindStr.length() > StrEventType.length())
continue;
if (StrEventType.find(FindStr, StrEventType.length()-FindStr.length()) != std::string::npos)
if (StrEventType == ToString(EventTypeResult))
break;
} while (EventTypeResult != EventType::AfterRange);
return EventTypeResult;
}

//FIXME: this is an anti-pattern. Should be
// ControlCodeFromString(), returning a ControlCode, UNDEFINED if not found
inline bool ToControlCode(const std::string StrControlCode, ControlCode& ControlCodeResult)
inline ControlCode ControlCodeFromString(const std::string& StrControlCode)
{
#define CHECKCONTROLCODESTRING(X) if (StrControlCode.find(ToString(X)) != std::string::npos) ControlCodeResult = X

ControlCodeResult = ControlCode::UNDEFINED;

CHECKCONTROLCODESTRING(ControlCode::CLOSE_PULSE_ON);
CHECKCONTROLCODESTRING(ControlCode::LATCH_OFF);
CHECKCONTROLCODESTRING(ControlCode::LATCH_ON);
CHECKCONTROLCODESTRING(ControlCode::NUL);
CHECKCONTROLCODESTRING(ControlCode::PULSE_OFF);
CHECKCONTROLCODESTRING(ControlCode::PULSE_ON);
CHECKCONTROLCODESTRING(ControlCode::TRIP_PULSE_ON);

return (ControlCodeResult != ControlCode::UNDEFINED);
}

//FIXME: this is an anti-pattern. Should be
// ConnectStateFromString(), returning a ConnectState, UNDEFINED if not found
inline bool GetConnectStateFromStringName(const std::string StrConnectState, ConnectState& ConnectStateResult)
{
#define CHECKCONNECTSTATESTRING(X) if (StrConnectState.find(ToString(X)) != std::string::npos) {ConnectStateResult = X;return true;}

CHECKCONNECTSTATESTRING(ConnectState::CONNECTED);
CHECKCONNECTSTATESTRING(ConnectState::DISCONNECTED);
CHECKCONNECTSTATESTRING(ConnectState::PORT_DOWN);
CHECKCONNECTSTATESTRING(ConnectState::PORT_UP);

return false;
CHECKENUMSTRING(StrControlCode,ControlCode,CLOSE_PULSE_ON);
CHECKENUMSTRING(StrControlCode,ControlCode,LATCH_OFF);
CHECKENUMSTRING(StrControlCode,ControlCode,LATCH_ON);
CHECKENUMSTRING(StrControlCode,ControlCode,NUL);
CHECKENUMSTRING(StrControlCode,ControlCode,PULSE_OFF);
CHECKENUMSTRING(StrControlCode,ControlCode,PULSE_ON);
CHECKENUMSTRING(StrControlCode,ControlCode,TRIP_PULSE_ON);
return ControlCode::UNDEFINED;
}

inline EventType ToEventType(const std::string& str_type)
inline ConnectState ConnectStateFromString(const std::string StrConnectState)
{
EventType type = EventType::BeforeRange;
if (to_lower(str_type) == "binary")
type = EventType::Binary;
else if (to_lower(str_type) == "analog")
type = EventType::Analog;
return type;
CHECKENUMSTRING(StrConnectState,ConnectState,CONNECTED);
CHECKENUMSTRING(StrConnectState,ConnectState,DISCONNECTED);
CHECKENUMSTRING(StrConnectState,ConnectState,PORT_DOWN);
CHECKENUMSTRING(StrConnectState,ConnectState,PORT_UP);
return ConnectState::UNDEFINED;
}

//Map EventTypes to payload types
Expand Down

0 comments on commit 872bf31

Please sign in to comment.