Merge branch 'v1.5' of github.com:mz-automation/libiec61850 into v1.5

pull/345/head
Michael Zillgith 3 years ago
commit 03a2137087

@ -0,0 +1,407 @@
#ifndef PYIEC61850_CONTROLACTIONHANDLER_HPP
#define PYIEC61850_CONTROLACTIONHANDLER_HPP
#include "eventHandler.hpp"
/*
* Abstract class for processing the received 'Control' check events.
*/
class CheckHandlerForPython: public EventHandler {
public:
virtual ~CheckHandlerForPython() {}
virtual void setReceivedData(void *i_data_p)
{
// copy the received data
ControlAction *l_my_data_p = static_cast<ControlAction*>(i_data_p);
_libiec61850_control_action = *l_my_data_p;
}
void setMmsValue(MmsValue *i_data_value)
{
_libiec61850_mms_value = i_data_value;
}
void setIedServer(IedServer *i_ied_server)
{
// copy the pointer and get to server
IedServer *l_my_server_p = i_ied_server;
_libiec61850_ied_server = *l_my_server_p;
}
void setTest(bool i_test)
{
_libiec61850_test = i_test;
}
void setInterlockCheck(bool i_interlock_check)
{
_libiec61850_interlock_check = i_interlock_check;
}
CheckHandlerResult getCheckHandlerResult()
{
return _libiec61850_check_handler_result;
}
CheckHandlerResult _libiec61850_check_handler_result; // Should be set during "trigger" callback function
ControlAction _libiec61850_control_action;
MmsValue* _libiec61850_mms_value;
IedServer _libiec61850_ied_server;
bool _libiec61850_test;
bool _libiec61850_interlock_check;
};
/*
* Abstract class for processing the received 'Control' wait for execution events.
*/
class WaitForExecutionHandlerForPython: public EventHandler {
public:
virtual ~WaitForExecutionHandlerForPython() {}
virtual void setReceivedData(void *i_data_p)
{
// copy the received data
ControlAction *l_my_data_p = static_cast<ControlAction*>(i_data_p);
_libiec61850_control_action = *l_my_data_p;
}
void setMmsValue(MmsValue *i_data_value)
{
_libiec61850_mms_value = i_data_value;
}
void setIedServer(IedServer *i_ied_server)
{
// copy the pointer and get to server
IedServer *l_my_server_p = i_ied_server;
_libiec61850_ied_server = *l_my_server_p;
}
void setTest(bool i_test)
{
_libiec61850_test = i_test;
}
void setSynchroCheck(bool i_synchro_check)
{
_libiec61850_synchro_check = i_synchro_check;
}
ControlHandlerResult getControlHandlerResult()
{
return _libiec61850_control_handler_result;
}
ControlHandlerResult _libiec61850_control_handler_result; // Should be set during "trigger" callback function
ControlAction _libiec61850_control_action;
MmsValue* _libiec61850_mms_value;
IedServer _libiec61850_ied_server;
bool _libiec61850_test;
bool _libiec61850_synchro_check;
};
/*
* Abstract class for processing the received 'Control' events.
*/
class ControlHandlerForPython: public EventHandler {
public:
virtual ~ControlHandlerForPython() {}
virtual void setReceivedData(void *i_data_p)
{
// copy the received data
ControlAction *l_my_data_p = static_cast<ControlAction*>(i_data_p);
_libiec61850_control_action = *l_my_data_p;
}
void setMmsValue(MmsValue *i_data_value)
{
_libiec61850_mms_value = i_data_value;
}
void setIedServer(IedServer *i_ied_server)
{
// copy the pointer and get to server
IedServer *l_my_server_p = i_ied_server;
_libiec61850_ied_server = *l_my_server_p;
}
void setTest(bool i_test)
{
_libiec61850_test = i_test;
}
ControlHandlerResult getControlHandlerResult()
{
return _libiec61850_control_handler_result;
}
ControlHandlerResult _libiec61850_control_handler_result; // Should be set during "trigger" callback function
ControlAction _libiec61850_control_action;
MmsValue* _libiec61850_mms_value;
IedServer _libiec61850_ied_server;
bool _libiec61850_test;
};
/*
* Class for the subscription to the 'Control' events
*/
class ControlSubscriberForPython: public EventSubscriber {
public:
ControlSubscriberForPython(): EventSubscriber()
{
m_ied_server = nullptr;
m_control_object = nullptr;
m_perform_check_handler_p = nullptr;
m_wait_handler_p = nullptr;
m_control_handler_p = nullptr;
}
virtual ~ControlSubscriberForPython() {
if (m_perform_check_handler_p) {
delete m_perform_check_handler_p;
}
m_perform_check_handler_p = nullptr;
if (m_wait_handler_p) {
delete m_wait_handler_p;
}
m_wait_handler_p = nullptr;
if (m_control_handler_p) {
delete m_control_handler_p;
}
m_control_handler_p = nullptr;
}
// Getters
CheckHandlerForPython *getCheckHandler()
{
return m_perform_check_handler_p;
}
WaitForExecutionHandlerForPython *getWaitHandler()
{
return m_wait_handler_p;
}
ControlHandlerForPython *getControlHandler()
{
return m_control_handler_p;
}
// Subscriber: assign callbacks to IedServer
virtual bool subscribe()
{
// preconditions
if (nullptr == m_ied_server) {
fprintf(stderr, "ControlSubscriber::subscribe() failed: 'ied server' is null\n");
return false;
}
if (nullptr == m_control_object) {
fprintf(stderr, "ControlSubscriber::subscribe() failed: 'control object' is null\n");
return false;
}
// install the libiec61850 callbacks for the different control states, if handler are set:
// the 'function pointer' is the 'static' method of this class
if (m_perform_check_handler_p) {
IedServer_setPerformCheckHandler(m_ied_server,
m_control_object,
(ControlPerformCheckHandler) ControlSubscriberForPython::triggerPerformCheckHandler,
&m_ied_server);
}
if (m_wait_handler_p){
IedServer_setWaitForExecutionHandler(m_ied_server,
m_control_object,
(ControlWaitForExecutionHandler) ControlSubscriberForPython::triggerWaitForExecutionHandler,
&m_ied_server);
}
if (m_control_handler_p) {
IedServer_setControlHandler(m_ied_server,
m_control_object,
(ControlHandler) ControlSubscriberForPython::triggerControlHandler,
&m_ied_server);
}
char *l_object_ref = ModelNode_getObjectReference( (ModelNode*) m_control_object, NULL);
std::string objs(l_object_ref);
std::string dirs = std::string(ModelNode_getObjectReference( (ModelNode*) m_control_object, NULL));
return (EventSubscriber::registerNewSubscriber(this, l_object_ref));
}
// Static method: it is the control perform check 'callback' for libiec61850 in C
static CheckHandlerResult triggerPerformCheckHandler(ControlAction action, void* parameter, MmsValue* ctlVal, bool test, bool interlockCheck)
{
PyThreadStateLock PyThreadLock;
// Preconditions
if (nullptr == parameter) {
fprintf(stderr, "ControlSubscriber::triggerPerformCheckHandler() failed: input object is null\n");
return CONTROL_HARDWARE_FAULT; // Status may not
}
DataObject* control_object = ControlAction_getControlObject(action);
std::string l_object_ref = ModelNode_getObjectReference( (ModelNode*) control_object, NULL);
// Search the appropriate 'EventSubscriber' object
ControlSubscriberForPython *l_registered_subscriber = (ControlSubscriberForPython*) EventSubscriber::findSubscriber(l_object_ref);
if (l_registered_subscriber) {
CheckHandlerForPython *l_perform_check_handler_p = l_registered_subscriber->getCheckHandler();
if (l_perform_check_handler_p) {
l_perform_check_handler_p->setReceivedData(&action);
l_perform_check_handler_p->setMmsValue(ctlVal);
l_perform_check_handler_p->setIedServer((IedServer*) parameter);
l_perform_check_handler_p->setTest(test);
l_perform_check_handler_p->setInterlockCheck(interlockCheck);
l_perform_check_handler_p->trigger();
fprintf(stderr, "triggerPerformCheckHandler::triggerPerformCheckHandler() end\n");
return l_perform_check_handler_p->getCheckHandlerResult();
}
else {
fprintf(stderr, "ControlSubscriber::triggerPerformCheckHandler() failed: EventHandler is undefined\n");
return CONTROL_HARDWARE_FAULT;
}
}
else {
fprintf(stderr, "ControlSubscriber::triggerPerformCheckHandler() failed: subscriber is not registered\n");
return CONTROL_HARDWARE_FAULT;
}
}
// Static method: it is the control wait for execution 'callback' for libiec61850 in C
static ControlHandlerResult triggerWaitForExecutionHandler(ControlAction controlAction, void* parameter, MmsValue* value, bool test, bool synchroCheck)
{
PyThreadStateLock PyThreadLock;
// Preconditions
if (nullptr == parameter) {
fprintf(stderr, "ControlSubscriber::triggerWaitForExecutionHandler() failed: input object is null\n");
return CONTROL_RESULT_FAILED;
}
DataObject* control_object = ControlAction_getControlObject(controlAction);
std::string l_object_ref = ModelNode_getObjectReference( (ModelNode*) control_object, NULL);
// Search the appropriate 'EventSubscriber' object
ControlSubscriberForPython *l_registered_subscriber = (ControlSubscriberForPython*) EventSubscriber::findSubscriber(l_object_ref);
if (l_registered_subscriber) {
WaitForExecutionHandlerForPython *l_wait_handler_p = l_registered_subscriber->getWaitHandler();
if (l_wait_handler_p) {
l_wait_handler_p->setReceivedData(&controlAction);
l_wait_handler_p->setMmsValue(value);
l_wait_handler_p->setIedServer((IedServer*) parameter);
l_wait_handler_p->setTest(test);
l_wait_handler_p->setSynchroCheck(synchroCheck);
l_wait_handler_p->trigger();
fprintf(stderr, "triggerWaitForExecutionHandler::triggerWaitForExecutionHandler() end\n");
return l_wait_handler_p->getControlHandlerResult();
}
else {
fprintf(stderr, "ControlSubscriber::triggerWaitForExecutionHandler() failed: EventHandler is undefined\n");
return CONTROL_RESULT_FAILED;
}
}
else {
fprintf(stderr, "ControlSubscriber::triggerWaitForExecutionHandler() failed: subscriber is not registered\n");
return CONTROL_RESULT_FAILED;
}
}
// Static method: it is the control 'callback' for libiec61850 in C
static ControlHandlerResult triggerControlHandler(ControlAction controlAction, void* parameter, MmsValue* value, bool test)
{
PyThreadStateLock PyThreadLock;
// Preconditions
if (nullptr == parameter) {
fprintf(stderr, "ControlSubscriber::triggerControlHandler() failed: input object is null\n");
return CONTROL_RESULT_FAILED;
}
DataObject* control_object = ControlAction_getControlObject(controlAction);
std::string l_object_ref = ModelNode_getObjectReference( (ModelNode*) control_object, NULL);
// Search the appropriate 'EventSubscriber' object
ControlSubscriberForPython *l_registered_subscriber = (ControlSubscriberForPython*) EventSubscriber::findSubscriber(l_object_ref);
if (l_registered_subscriber) {
ControlHandlerForPython *l_control_handler_p = l_registered_subscriber->getControlHandler();
if (l_control_handler_p) {
l_control_handler_p->setReceivedData(&controlAction);
l_control_handler_p->setMmsValue(value);
l_control_handler_p->setIedServer((IedServer*) parameter);
l_control_handler_p->setTest(test);
l_control_handler_p->trigger();
fprintf(stderr, "triggerControlHandler::triggerControlHandler() end\n");
return l_control_handler_p->getControlHandlerResult();
}
else {
fprintf(stderr, "ControlSubscriber::triggerControlHandler() failed: EventHandler is undefined\n");
return CONTROL_RESULT_FAILED;
}
}
else {
fprintf(stderr, "ControlSubscriber::triggerControlHandler() failed: subscriber is not registered\n");
return CONTROL_RESULT_FAILED;
}
}
// Setters
void setIedServer(const IedServer &i_ied_server)
{
m_ied_server = i_ied_server;
}
void setControlObject(DataObject *i_control_object)
{
m_control_object = i_control_object;
}
void setCheckHandler(CheckHandlerForPython* i_check_handler_p)
{
m_perform_check_handler_p = i_check_handler_p;
}
void setWaitHandler(WaitForExecutionHandlerForPython* i_wait_handler_p)
{
m_wait_handler_p = i_wait_handler_p;
}
void setControlHandler(ControlHandlerForPython* i_control_handler_p)
{
m_control_handler_p = i_control_handler_p;
}
private:
// Parameters
IedServer m_ied_server;
DataObject* m_control_object;
CheckHandlerForPython* m_perform_check_handler_p;
WaitForExecutionHandlerForPython* m_wait_handler_p;
ControlHandlerForPython* m_control_handler_p;
};
#endif

@ -6,7 +6,6 @@
#include <string>
#include <Python.h>
class PyThreadStateLock
{
public:
@ -25,7 +24,6 @@ private:
};
class EventHandler {
public:
EventHandler() {}
@ -118,7 +116,7 @@ class EventSubscriber {
m_subscriber_map.erase(l_it);
}
else {
fprintf(stderr, "EventSubscriber::unregisterSubscriber() failed: '%s' is not registered\n");
fprintf(stderr, "EventSubscriber::unregisterSubscriber() failed: '%s' is not registered\n", i_subscriber_id.c_str());
}
}

@ -26,6 +26,8 @@ DataAttribute* toDataAttribute(DataObject * DO)
{ return (DataAttribute*)DO;}
DataAttribute* toDataAttribute(ModelNode * MN)
{ return (DataAttribute*)MN;}
DataObject* toDataObject(ModelNode * MN)
{ return (DataObject*)MN;}
%}
%apply int *OUTPUT {IedClientError* error};
@ -55,6 +57,7 @@ ModelNode* toModelNode(LogicalNode *);
ModelNode* toModelNode(DataObject *);
DataAttribute* toDataAttribute(DataObject *);
DataAttribute* toDataAttribute(ModelNode *);
DataObject* toDataObject(ModelNode *);
char* toCharP(void *);
/* Goose Subscriber section */
@ -99,17 +102,23 @@ void GooseSubscriber_setDstMac(GooseSubscriber subscriber,
%feature("director") RCBHandler;
%feature("director") GooseHandler;
%feature("director") CommandTermHandler;
%feature("director") CheckHandlerForPython;
%feature("director") WaitForExecutionHandlerForPython;
%feature("director") ControlHandlerForPython;
%{
#include "eventHandlers/eventHandler.hpp"
#include "eventHandlers/reportControlBlockHandler.hpp"
#include "eventHandlers/gooseHandler.hpp"
#include "eventHandlers/commandTermHandler.hpp"
#include "eventHandlers/controlActionHandler.hpp"
std::map< std::string, EventSubscriber*> EventSubscriber::m_subscriber_map = {};
%}
%include "eventHandlers/eventHandler.hpp"
%include "eventHandlers/reportControlBlockHandler.hpp"
%include "eventHandlers/gooseHandler.hpp"
%include "eventHandlers/commandTermHandler.hpp"
%include "eventHandlers/controlActionHandler.hpp"
/* Goose Publisher section */
%{
@ -145,3 +154,9 @@ void CommParameters_setDstAddress(CommParameters *gooseCommParameters,
uint8_t dst_mac_4,
uint8_t dst_mac_5);
/* Wrapper for synchronous functions */
%{
#include "servicePythonWrapper.hpp"
%}
%include "servicePythonWrapper.hpp"

@ -0,0 +1,63 @@
#ifndef PYIEC61850_SERVICEPYTHONWRAPPER_HPP
#define PYIEC61850_SERVICEPYTHONWRAPPER_HPP
#include "iec61850_client.h"
#include <Python.h>
class PyThreadStateSave
{
public:
PyThreadStateSave(void)
{
if (PyGILState_Check())
state = PyEval_SaveThread();
else
state = nullptr;
}
~PyThreadStateSave(void)
{
if (state)
PyEval_RestoreThread(state);
}
private:
PyThreadState* state;
};
/*
Wrapping of synchronous functions to prevent deadlocks
*/
static MmsValue*
pyWrap_IedConnection_readObject(IedConnection con, IedClientError* error, const char* objRef, FunctionalConstraint fc)
{
PyThreadStateSave gilStateSave;
return IedConnection_readObject(con, error, objRef, fc);
}
static void
pyWrap_IedConnection_writeObject(IedConnection con, IedClientError* error, const char* objectReference,
FunctionalConstraint fc, MmsValue* value)
{
PyThreadStateSave gilStateSave;
IedConnection_writeObject(con, error, objectReference, fc, value);
}
static void
pyWrap_IedConnection_setRCBValues(IedConnection con, IedClientError* error, ClientReportControlBlock rcb, uint32_t parametersMask,
bool singleRequest)
{
PyThreadStateSave gilStateSave;
IedConnection_setRCBValues(con, error, rcb, parametersMask, singleRequest);
}
static ClientReportControlBlock
pyWrap_IedConnection_getRCBValues(IedConnection con, IedClientError* error, const char* rcbReference,
ClientReportControlBlock updateRcb)
{
PyThreadStateSave gilStateSave;
return IedConnection_getRCBValues(con, error, rcbReference, updateRcb);
}
#endif
Loading…
Cancel
Save