Merge branch 'v1.5' of github.com:mz-automation/libiec61850 into v1.5
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
|
@ -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…
Reference in New Issue