Commit 8b91d7cc authored by Balakrishna Balakrishna's avatar Balakrishna Balakrishna

Merge branch 'master' into feature/opcua

parents da969acf a5ef183a
"""
Simple OPC UA server with one paremeter (temp).
"""
from opcua import Server
from random import randint
import time
server = Server()
url = "opc.tcp://0.0.0.0:4840"
server.set_endpoint(url)
name = "OPCUA_SIMULATION_SERVER"
addspace = server.register_namespace(name)
node = server.get_objects_node()
Param = node.add_object(addspace, "Parameters")
Temp = Param.add_variable(addspace, "Temperature", 0)
Temp.set_writable()
server.start()
print ("started at %s" %url)
while 1:
Temp.set_value(randint(10,50))
time.sleep(10)
...@@ -16,18 +16,26 @@ ...@@ -16,18 +16,26 @@
#include "open62541.h" #include "open62541.h"
// global relay state // global relay state
uint8_t myrelay = 0; uint8_t I2C_0_RELAYS_STATE = 0; // state of 4 relays at I2C slave 0
uint8_t I2C_1_RELAYS_STATE = 0; // state of 4 relays at I2C slave 1
static int setRelayState(int command) { // the default addresses of MOD-IOs
const int I2C_0_ADDR = 0x58;
const int I2C_1_ADDR = 0x59;
// the block device at host machine
static const char I2C_BLOCK_DEVICE_NAME[] = "/dev/i2c-1";
static int setRelayState(int command, int i2c_addr) {
/* /*
* Set relays' state over I2C * Set relays' state over I2C
*/ */
int file; int file;
int adapter_nr = 1; /* probably dynamically determined */
char filename[20]; char filename[20];
// step 1: open device // step 1: open device
snprintf(filename, 19, "/dev/i2c-%d", adapter_nr); snprintf(filename, 19, I2C_BLOCK_DEVICE_NAME);
file = open(filename, O_RDWR); file = open(filename, O_RDWR);
if (file < 0) { if (file < 0) {
/* ERROR HANDLING; you can check errno to see what went wrong */ /* ERROR HANDLING; you can check errno to see what went wrong */
...@@ -36,8 +44,7 @@ static int setRelayState(int command) { ...@@ -36,8 +44,7 @@ static int setRelayState(int command) {
} }
// step 2: address the slave by its address // step 2: address the slave by its address
int addr = 0x58; /* The I2C address */ if (ioctl(file, I2C_SLAVE, i2c_addr) < 0) {
if (ioctl(file, I2C_SLAVE, addr) < 0) {
/* ERROR HANDLING; you can check errno to see what went wrong */ /* ERROR HANDLING; you can check errno to see what went wrong */
printf("Error addressing i2c slave."); printf("Error addressing i2c slave.");
exit(1); exit(1);
...@@ -65,61 +72,109 @@ static void addVariable(UA_Server *server) { ...@@ -65,61 +72,109 @@ static void addVariable(UA_Server *server) {
UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES); UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
// relay 0 // I2C0 / relay 0
UA_VariableAttributes attr0 = UA_VariableAttributes_default; UA_VariableAttributes attr0 = UA_VariableAttributes_default;
UA_Variant_setScalar(&attr0.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); UA_Variant_setScalar(&attr0.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
attr0.description = UA_LOCALIZEDTEXT("en-US","Relay 0"); attr0.description = UA_LOCALIZEDTEXT("en-US","I2C0 / Relay 0");
attr0.displayName = UA_LOCALIZEDTEXT("en-US", "Relay 0"); attr0.displayName = UA_LOCALIZEDTEXT("en-US", "I2C0 / Relay 0");
attr0.dataType = UA_TYPES[UA_TYPES_INT32].typeId; attr0.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
attr0.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; attr0.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
UA_NodeId myIntegerNodeId0 = UA_NODEID_STRING(1, "i2c0.relay0");
UA_NodeId myIntegerNodeId0 = UA_NODEID_STRING(1, "relay0"); UA_QualifiedName myIntegerName0 = UA_QUALIFIEDNAME(1, "I2C0 / Relay 0");
UA_QualifiedName myIntegerName0 = UA_QUALIFIEDNAME(1, "Relay 0");
UA_Server_addVariableNode(server, myIntegerNodeId0, parentNodeId, UA_Server_addVariableNode(server, myIntegerNodeId0, parentNodeId,
parentReferenceNodeId, myIntegerName0, parentReferenceNodeId, myIntegerName0,
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr0, NULL, NULL); UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr0, NULL, NULL);
// relay 1 // I2C0 / relay 1
UA_VariableAttributes attr1 = UA_VariableAttributes_default; UA_VariableAttributes attr1 = UA_VariableAttributes_default;
UA_Variant_setScalar(&attr1.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); UA_Variant_setScalar(&attr1.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
attr1.description = UA_LOCALIZEDTEXT("en-US","Relay 1"); attr1.description = UA_LOCALIZEDTEXT("en-US","I2C0 / Relay 1");
attr1.displayName = UA_LOCALIZEDTEXT("en-US", "Relay 1"); attr1.displayName = UA_LOCALIZEDTEXT("en-US", "I2C0 / Relay 1");
attr1.dataType = UA_TYPES[UA_TYPES_INT32].typeId; attr1.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
attr1.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; attr1.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
UA_NodeId myIntegerNodeId1 = UA_NODEID_STRING(1, "i2c0.relay1");
UA_NodeId myIntegerNodeId1 = UA_NODEID_STRING(1, "relay1"); UA_QualifiedName myIntegerName1 = UA_QUALIFIEDNAME(1, "I2C0 / Relay 1");
UA_QualifiedName myIntegerName1 = UA_QUALIFIEDNAME(1, "Relay 1");
UA_Server_addVariableNode(server, myIntegerNodeId1, parentNodeId, UA_Server_addVariableNode(server, myIntegerNodeId1, parentNodeId,
parentReferenceNodeId, myIntegerName1, parentReferenceNodeId, myIntegerName1,
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr1, NULL, NULL); UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr1, NULL, NULL);
// relay 2 // I2C0 / relay 2
UA_VariableAttributes attr2 = UA_VariableAttributes_default; UA_VariableAttributes attr2 = UA_VariableAttributes_default;
UA_Variant_setScalar(&attr2.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); UA_Variant_setScalar(&attr2.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
attr2.description = UA_LOCALIZEDTEXT("en-US","Relay 2"); attr2.description = UA_LOCALIZEDTEXT("en-US","I2C0 / Relay 2");
attr2.displayName = UA_LOCALIZEDTEXT("en-US", "Relay 2"); attr2.displayName = UA_LOCALIZEDTEXT("en-US", "I2C0 / Relay 2");
attr2.dataType = UA_TYPES[UA_TYPES_INT32].typeId; attr2.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
attr2.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; attr2.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
UA_NodeId myIntegerNodeId2 = UA_NODEID_STRING(1, "i2c0.relay2");
UA_NodeId myIntegerNodeId2 = UA_NODEID_STRING(1, "relay2"); UA_QualifiedName myIntegerName2 = UA_QUALIFIEDNAME(1, "I2C0 / Relay 2");
UA_QualifiedName myIntegerName2 = UA_QUALIFIEDNAME(1, "Relay 2");
UA_Server_addVariableNode(server, myIntegerNodeId2, parentNodeId, UA_Server_addVariableNode(server, myIntegerNodeId2, parentNodeId,
parentReferenceNodeId, myIntegerName2, parentReferenceNodeId, myIntegerName2,
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr2, NULL, NULL); UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr2, NULL, NULL);
// relay 3 // I2C0 / relay 3
UA_VariableAttributes attr3 = UA_VariableAttributes_default; UA_VariableAttributes attr3 = UA_VariableAttributes_default;
UA_Variant_setScalar(&attr3.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); UA_Variant_setScalar(&attr3.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
attr3.description = UA_LOCALIZEDTEXT("en-US","Relay 3"); attr3.description = UA_LOCALIZEDTEXT("en-US","I2C0 / Relay 3");
attr3.displayName = UA_LOCALIZEDTEXT("en-US", "Relay 3"); attr3.displayName = UA_LOCALIZEDTEXT("en-US", "I2C0 / Relay 3");
attr3.dataType = UA_TYPES[UA_TYPES_INT32].typeId; attr3.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
attr3.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; attr3.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
UA_NodeId myIntegerNodeId3 = UA_NODEID_STRING(1, "i2c0.relay3");
UA_NodeId myIntegerNodeId3 = UA_NODEID_STRING(1, "relay3"); UA_QualifiedName myIntegerName3 = UA_QUALIFIEDNAME(1, "I2C0 / Relay 3");
UA_QualifiedName myIntegerName3 = UA_QUALIFIEDNAME(1, "Relay 3");
UA_Server_addVariableNode(server, myIntegerNodeId3, parentNodeId, UA_Server_addVariableNode(server, myIntegerNodeId3, parentNodeId,
parentReferenceNodeId, myIntegerName3, parentReferenceNodeId, myIntegerName3,
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr3, NULL, NULL); UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr3, NULL, NULL);
// I2C1 / relay 0
UA_VariableAttributes attr4 = UA_VariableAttributes_default;
UA_Variant_setScalar(&attr4.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
attr4.description = UA_LOCALIZEDTEXT("en-US","I2C1 / Relay 0");
attr4.displayName = UA_LOCALIZEDTEXT("en-US", "I2C1 / Relay 0");
attr4.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
attr4.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
UA_NodeId myIntegerNodeId4 = UA_NODEID_STRING(1, "i2c1.relay0");
UA_QualifiedName myIntegerName4 = UA_QUALIFIEDNAME(1, "I2C1 / Relay 0");
UA_Server_addVariableNode(server, myIntegerNodeId4, parentNodeId,
parentReferenceNodeId, myIntegerName4,
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr4, NULL, NULL);
// I2C1 / relay 1
UA_VariableAttributes attr5 = UA_VariableAttributes_default;
UA_Variant_setScalar(&attr5.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
attr5.description = UA_LOCALIZEDTEXT("en-US","I2C1 / Relay 1");
attr5.displayName = UA_LOCALIZEDTEXT("en-US", "I2C1 / Relay 1");
attr5.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
attr5.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
UA_NodeId myIntegerNodeId5 = UA_NODEID_STRING(1, "i2c1.relay1");
UA_QualifiedName myIntegerName5 = UA_QUALIFIEDNAME(1, "I2C1 / Relay 1");
UA_Server_addVariableNode(server, myIntegerNodeId5, parentNodeId,
parentReferenceNodeId, myIntegerName5,
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr5, NULL, NULL);
// I2C1 / relay 2
UA_VariableAttributes attr6 = UA_VariableAttributes_default;
UA_Variant_setScalar(&attr6.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
attr6.description = UA_LOCALIZEDTEXT("en-US","I2C1 / Relay 2");
attr6.displayName = UA_LOCALIZEDTEXT("en-US", "I2C1 / Relay 2");
attr6.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
attr6.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
UA_NodeId myIntegerNodeId6 = UA_NODEID_STRING(1, "i2c1.relay2");
UA_QualifiedName myIntegerName6 = UA_QUALIFIEDNAME(1, "I2C1 / Relay 2");
UA_Server_addVariableNode(server, myIntegerNodeId6, parentNodeId,
parentReferenceNodeId, myIntegerName6,
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr6, NULL, NULL);
// I2C1 / relay 3
UA_VariableAttributes attr7 = UA_VariableAttributes_default;
UA_Variant_setScalar(&attr7.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
attr7.description = UA_LOCALIZEDTEXT("en-US","I2C1 / Relay 3");
attr7.displayName = UA_LOCALIZEDTEXT("en-US", "I2C1 / Relay 3");
attr7.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
attr7.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
UA_NodeId myIntegerNodeId7 = UA_NODEID_STRING(1, "i2c1.relay3");
UA_QualifiedName myIntegerName7 = UA_QUALIFIEDNAME(1, "I2C1 / Relay 3");
UA_Server_addVariableNode(server, myIntegerNodeId7, parentNodeId,
parentReferenceNodeId, myIntegerName7,
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr7, NULL, NULL);
} }
/* Connect to variables to physical relays /* Connect to variables to physical relays
...@@ -134,144 +189,207 @@ static void beforeReadTime(UA_Server *server, ...@@ -134,144 +189,207 @@ static void beforeReadTime(UA_Server *server,
// XXX: having afterWriteTime{0..3} is not needed and maybe with introspection of context we can // XXX: having afterWriteTime{0..3} is not needed and maybe with introspection of context we can
// write only one callback function // write only one callback function
static void afterWriteTime0(UA_Server *server, static void afterWriteTimeI2C0_0(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeId, void *nodeContext, const UA_NodeId *nodeId, void *nodeContext,
const UA_NumericRange *range, const UA_DataValue *data) { const UA_NumericRange *range, const UA_DataValue *data) {
//UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "The variable was updated");
if (data->value.type == &UA_TYPES[UA_TYPES_INT32]) { if (data->value.type == &UA_TYPES[UA_TYPES_INT32]) {
UA_Int32 hrValue = *(UA_Int32 *)data->value.data; UA_Int32 hrValue = *(UA_Int32 *)data->value.data;
if (hrValue > 0){ if (hrValue > 0){
myrelay |= 1UL << 0; // relay0 I2C_0_RELAYS_STATE |= 1UL << 0;
setRelayState(myrelay); setRelayState(I2C_0_RELAYS_STATE, I2C_0_ADDR);
} }
else { else {
myrelay &= ~(1UL << 0); // relay0 I2C_0_RELAYS_STATE &= ~(1UL << 0);
setRelayState(myrelay); setRelayState(I2C_0_RELAYS_STATE, I2C_0_ADDR);
} }
} }
} }
static void afterWriteTime1(UA_Server *server, static void afterWriteTimeI2C0_1(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeId, void *nodeContext, const UA_NodeId *nodeId, void *nodeContext,
const UA_NumericRange *range, const UA_DataValue *data) { const UA_NumericRange *range, const UA_DataValue *data) {
//UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "The variable was updated");
if (data->value.type == &UA_TYPES[UA_TYPES_INT32]) { if (data->value.type == &UA_TYPES[UA_TYPES_INT32]) {
UA_Int32 hrValue = *(UA_Int32 *)data->value.data; UA_Int32 hrValue = *(UA_Int32 *)data->value.data;
if (hrValue > 0){ if (hrValue > 0){
myrelay |= 1UL << 1; I2C_0_RELAYS_STATE |= 1UL << 1;
setRelayState(myrelay); setRelayState(I2C_0_RELAYS_STATE, I2C_0_ADDR);
} }
else { else {
myrelay &= ~(1UL << 1); I2C_0_RELAYS_STATE &= ~(1UL << 1);
setRelayState(myrelay); setRelayState(I2C_0_RELAYS_STATE, I2C_0_ADDR);
} }
} }
} }
static void afterWriteTime2(UA_Server *server, static void afterWriteTimeI2C0_2(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeId, void *nodeContext, const UA_NodeId *nodeId, void *nodeContext,
const UA_NumericRange *range, const UA_DataValue *data) { const UA_NumericRange *range, const UA_DataValue *data) {
//UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "The variable was updated");
if (data->value.type == &UA_TYPES[UA_TYPES_INT32]) { if (data->value.type == &UA_TYPES[UA_TYPES_INT32]) {
UA_Int32 hrValue = *(UA_Int32 *)data->value.data; UA_Int32 hrValue = *(UA_Int32 *)data->value.data;
if (hrValue > 0){ if (hrValue > 0){
myrelay |= 1UL << 2; I2C_0_RELAYS_STATE |= 1UL << 2;
setRelayState(myrelay); setRelayState(I2C_0_RELAYS_STATE, I2C_0_ADDR);
} }
else { else {
myrelay &= ~(1UL << 2); I2C_0_RELAYS_STATE &= ~(1UL << 2);
setRelayState(myrelay); setRelayState(I2C_0_RELAYS_STATE, I2C_0_ADDR);
} }
} }
} }
static void afterWriteTime3(UA_Server *server, static void afterWriteTimeI2C0_3(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeId, void *nodeContext, const UA_NodeId *nodeId, void *nodeContext,
const UA_NumericRange *range, const UA_DataValue *data) { const UA_NumericRange *range, const UA_DataValue *data) {
//UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "The variable was updated");
if (data->value.type == &UA_TYPES[UA_TYPES_INT32]) { if (data->value.type == &UA_TYPES[UA_TYPES_INT32]) {
UA_Int32 hrValue = *(UA_Int32 *)data->value.data; UA_Int32 hrValue = *(UA_Int32 *)data->value.data;
if (hrValue > 0){ if (hrValue > 0){
myrelay |= 1UL << 3; I2C_0_RELAYS_STATE |= 1UL << 3;
setRelayState(myrelay); setRelayState(I2C_0_RELAYS_STATE, I2C_0_ADDR);
} }
else { else {
myrelay &= ~(1UL << 3); I2C_0_RELAYS_STATE &= ~(1UL << 3);
setRelayState(myrelay); setRelayState(I2C_0_RELAYS_STATE, I2C_0_ADDR);
}
}
}
// I2C1
static void afterWriteTimeI2C1_0(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeId, void *nodeContext,
const UA_NumericRange *range, const UA_DataValue *data) {
if (data->value.type == &UA_TYPES[UA_TYPES_INT32]) {
UA_Int32 hrValue = *(UA_Int32 *)data->value.data;
if (hrValue > 0){
I2C_1_RELAYS_STATE |= 1UL << 0;
setRelayState(I2C_1_RELAYS_STATE, I2C_1_ADDR);
}
else {
I2C_1_RELAYS_STATE &= ~(1UL << 0);
setRelayState(I2C_1_RELAYS_STATE, I2C_1_ADDR);
}
}
}
static void afterWriteTimeI2C1_1(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeId, void *nodeContext,
const UA_NumericRange *range, const UA_DataValue *data) {
if (data->value.type == &UA_TYPES[UA_TYPES_INT32]) {
UA_Int32 hrValue = *(UA_Int32 *)data->value.data;
if (hrValue > 0){
I2C_1_RELAYS_STATE |= 1UL << 1;
setRelayState(I2C_1_RELAYS_STATE, I2C_1_ADDR);
}
else {
I2C_1_RELAYS_STATE &= ~(1UL << 1);
setRelayState(I2C_1_RELAYS_STATE, I2C_1_ADDR);
}
}
}
static void afterWriteTimeI2C1_2(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeId, void *nodeContext,
const UA_NumericRange *range, const UA_DataValue *data) {
if (data->value.type == &UA_TYPES[UA_TYPES_INT32]) {
UA_Int32 hrValue = *(UA_Int32 *)data->value.data;
if (hrValue > 0){
I2C_1_RELAYS_STATE |= 1UL << 2;
setRelayState(I2C_1_RELAYS_STATE, I2C_1_ADDR);
}
else {
I2C_1_RELAYS_STATE &= ~(1UL << 2);
setRelayState(I2C_1_RELAYS_STATE, I2C_1_ADDR);
}
}
}
static void afterWriteTimeI2C1_3(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeId, void *nodeContext,
const UA_NumericRange *range, const UA_DataValue *data) {
if (data->value.type == &UA_TYPES[UA_TYPES_INT32]) {
UA_Int32 hrValue = *(UA_Int32 *)data->value.data;
if (hrValue > 0){
I2C_1_RELAYS_STATE |= 1UL << 3;
setRelayState(I2C_1_RELAYS_STATE, I2C_1_ADDR);
}
else {
I2C_1_RELAYS_STATE &= ~(1UL << 3);
setRelayState(I2C_1_RELAYS_STATE, I2C_1_ADDR);
} }
} }
} }
static void addValueCallbackToCurrentTimeVariable(UA_Server *server) { static void addValueCallbackToCurrentTimeVariable(UA_Server *server) {
// I2C0
// relay 0 // relay 0
UA_NodeId currentNodeId0 = UA_NODEID_STRING(1, "relay0"); UA_NodeId currentNodeId0 = UA_NODEID_STRING(1, "i2c0.relay0");
UA_ValueCallback callback0 ; UA_ValueCallback callback0 ;
callback0.onRead = beforeReadTime; callback0.onRead = beforeReadTime;
callback0.onWrite = afterWriteTime0; callback0.onWrite = afterWriteTimeI2C0_0;
UA_Server_setVariableNode_valueCallback(server, currentNodeId0, callback0); UA_Server_setVariableNode_valueCallback(server, currentNodeId0, callback0);
// relay 1 // relay 1
UA_NodeId currentNodeId1 = UA_NODEID_STRING(1, "relay1"); UA_NodeId currentNodeId1 = UA_NODEID_STRING(1, "i2c0.relay1");
UA_ValueCallback callback1 ; UA_ValueCallback callback1 ;
callback1.onRead = beforeReadTime; callback1.onRead = beforeReadTime;
callback1.onWrite = afterWriteTime1; callback1.onWrite = afterWriteTimeI2C0_1;
UA_Server_setVariableNode_valueCallback(server, currentNodeId1, callback1); UA_Server_setVariableNode_valueCallback(server, currentNodeId1, callback1);
// relay 2 // relay 2
UA_NodeId currentNodeId2 = UA_NODEID_STRING(1, "relay2"); UA_NodeId currentNodeId2 = UA_NODEID_STRING(1, "i2c0.relay2");
UA_ValueCallback callback2 ; UA_ValueCallback callback2 ;
callback2.onRead = beforeReadTime; callback2.onRead = beforeReadTime;
callback2.onWrite = afterWriteTime2; callback2.onWrite = afterWriteTimeI2C0_2;
UA_Server_setVariableNode_valueCallback(server, currentNodeId2, callback2); UA_Server_setVariableNode_valueCallback(server, currentNodeId2, callback2);
// relay 3 // relay 3
UA_NodeId currentNodeId3 = UA_NODEID_STRING(1, "relay3"); UA_NodeId currentNodeId3 = UA_NODEID_STRING(1, "i2c0.relay3");
UA_ValueCallback callback3 ; UA_ValueCallback callback3 ;
callback3.onRead = beforeReadTime; callback3.onRead = beforeReadTime;
callback3.onWrite = afterWriteTime3; callback3.onWrite = afterWriteTimeI2C0_3;
UA_Server_setVariableNode_valueCallback(server, currentNodeId3, callback3); UA_Server_setVariableNode_valueCallback(server, currentNodeId3, callback3);
}
// I2C1
/** // relay 0
* Now we change the value with the write service. This uses the same service UA_NodeId currentNodeId4 = UA_NODEID_STRING(1, "i2c1.relay0");
* implementation that can also be reached over the network by an OPC UA client. UA_ValueCallback callback4;
*/ callback4.onRead = beforeReadTime;
callback4.onWrite = afterWriteTimeI2C1_0;
static void writeVariable(UA_Server *server) { UA_Server_setVariableNode_valueCallback(server, currentNodeId4, callback4);
UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "relay0");
// relay 1
/* Write a different integer value */ UA_NodeId currentNodeId5 = UA_NODEID_STRING(1, "i2c1.relay1");
UA_Int32 myInteger = 0; UA_ValueCallback callback5;
UA_Variant myVar; callback5.onRead = beforeReadTime;
UA_Variant_init(&myVar); callback5.onWrite = afterWriteTimeI2C1_1;
UA_Variant_setScalar(&myVar, &myInteger, &UA_TYPES[UA_TYPES_INT32]); UA_Server_setVariableNode_valueCallback(server, currentNodeId5, callback5);
UA_Server_writeValue(server, myIntegerNodeId, myVar);
// relay 2
/* Set the status code of the value to an error code. The function UA_NodeId currentNodeId6 = UA_NODEID_STRING(1, "i2c1.relay2");
* UA_Server_write provides access to the raw service. The above UA_ValueCallback callback6;
* UA_Server_writeValue is syntactic sugar for writing a specific node callback6.onRead = beforeReadTime;
* attribute with the write service. */ callback6.onWrite = afterWriteTimeI2C1_2;
UA_WriteValue wv; UA_Server_setVariableNode_valueCallback(server, currentNodeId6, callback6);
UA_WriteValue_init(&wv);
wv.nodeId = myIntegerNodeId; // relay 2
wv.attributeId = UA_ATTRIBUTEID_VALUE; UA_NodeId currentNodeId7 = UA_NODEID_STRING(1, "i2c1.relay3");
wv.value.status = UA_STATUSCODE_BADNOTCONNECTED; UA_ValueCallback callback7;
wv.value.hasStatus = true; callback7.onRead = beforeReadTime;
UA_Server_write(server, &wv); callback7.onWrite = afterWriteTimeI2C1_3;
UA_Server_setVariableNode_valueCallback(server, currentNodeId7, callback7);
/* Reset the variable to a good statuscode with a value */
wv.value.hasStatus = false;
wv.value.value = myVar;
wv.value.hasValue = true;
UA_Server_write(server, &wv);
} }
static volatile UA_Boolean running = true; static volatile UA_Boolean running = true;
static void stopHandler(int sign) { static void stopHandler(int sign) {
...@@ -281,7 +399,7 @@ static void stopHandler(int sign) { ...@@ -281,7 +399,7 @@ static void stopHandler(int sign) {
int main(void) { int main(void) {
// set all relays to OFF at startup // set all relays to OFF at startup
setRelayState(0x00); setRelayState(0x00, I2C_0_ADDR);
signal(SIGINT, stopHandler); signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler); signal(SIGTERM, stopHandler);
...@@ -290,12 +408,8 @@ int main(void) { ...@@ -290,12 +408,8 @@ int main(void) {
UA_ServerConfig_setDefault(UA_Server_getConfig(server)); UA_ServerConfig_setDefault(UA_Server_getConfig(server));
UA_ServerConfig* config = UA_Server_getConfig(server); UA_ServerConfig* config = UA_Server_getConfig(server);
config->verifyRequestTimestamp = UA_RULEHANDLING_ACCEPT; config->verifyRequestTimestamp = UA_RULEHANDLING_ACCEPT;
//#ifdef UA_ENABLE_WEBSOCKET_SERVER
// UA_ServerConfig_addNetworkLayerWS(UA_Server_getConfig(server), 7681, 0, 0, NULL, NULL);
//#endif
addVariable(server); addVariable(server);
writeVariable(server);
addValueCallbackToCurrentTimeVariable(server); addValueCallbackToCurrentTimeVariable(server);
UA_StatusCode retval = UA_Server_run(server, &running); UA_StatusCode retval = UA_Server_run(server, &running);
...@@ -303,7 +417,7 @@ int main(void) { ...@@ -303,7 +417,7 @@ int main(void) {
UA_Server_delete(server); UA_Server_delete(server);
// set all relays to OFF at startup // set all relays to OFF at startup
setRelayState(0x00); setRelayState(0x00, I2C_0_ADDR);
return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE; return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment