extended output and readme

This commit is contained in:
Wolfgang Hottgenroth 2022-02-22 18:07:21 +01:00
parent 9ce5395547
commit da6574632c
6 changed files with 110 additions and 29 deletions

View File

@ -54,26 +54,88 @@ The attribute `nodes` finally contains the list of variables to be queried. It c
## Example Output
Besides the value itself the output contains the status of the value and a couple of timestamps (from device `t1`, server `t2` and bridge `t3`).
In `flat` mode the final topic will be `${mqtt.publicTopicPrefix}/${opcua.name}/${opcua.node.ns}/${opcua.node.d}`
An example for the MQTT messages according to the above configuration in `flat` mode is:
opcua/apl/0/pv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "pv", "value": 19.849281311035156}
opcua/apl/0/sv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "sv", "value": 1688.5152587890625}
opcua/apl/0/tv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "tv", "value": 22.574615478515625}
opcua/apl/0/qv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "qv", "value": NaN}
opcua/apl/0/pv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "pv", "value": 19.849281311035156}
opcua/apl/0/sv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "sv", "value": 1688.5152587890625}
opcua/apl/0/tv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "tv", "value": 22.574615478515625}
opcua/apl/0/qv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "qv", "value": NaN}
opcua/apl/0/pv {
"server": "apl",
"ns": 0,
"d": "pv",
"value": 19.833280563354492,
"status": "Good",
"t1": "2022-02-22 17:03:41.189000",
"t2": "2022-02-22 17:03:41.189000",
"t3": "2022-02-22 17:03:41.575504"
}
opcua/apl/0/sv {
"server": "apl",
"ns": 0,
"d": "sv",
"value": 1706.15771484375,
"status": "Good",
"t1": "2022-02-22 17:03:41.189000",
"t2": "2022-02-22 17:03:41.189000",
"t3": "2022-02-22 17:03:41.625721"
}
opcua/apl/0/tv {
"server": "apl",
"ns": 0,
"d": "tv",
"value": 23.29559326171875,
"status": "Good",
"t1": "2022-02-22 17:03:41.189000",
"t2": "2022-02-22 17:03:41.189000",
"t3": "2022-02-22 17:03:41.675352"
}
opcua/apl/0/qv {
"server": "apl",
"ns": 0,
"d": "qv",
"value": NaN,
"status": "Good",
"t1": "2022-02-22 17:03:41.189000",
"t2": "2022-02-22 17:03:41.189000",
"t3": "2022-02-22 17:03:41.725487"
}
In `structured` mode the final topic will be `${mqtt.publicTopicPrefix}/${opcua.name}`
An example for the MQTT messages according to the above configuration in `flat` mode is:
opcua/apl {"pv": 19.844480514526367, "sv": 1689.9193115234375, "tv": 22.68524169921875, "qv": NaN}
opcua/apl {"pv": 19.844480514526367, "sv": 1689.9193115234375, "tv": 22.68524169921875, "qv": NaN}
opcua/apl {"pv": 19.844480514526367, "sv": 1689.9193115234375, "tv": 22.68524169921875, "qv": NaN}
opcua/apl {"pv": 19.844480514526367, "sv": 1689.93701171875, "tv": 22.620391845703125, "qv": NaN}
opcua/apl {
"pv": {
"value": 19.835201263427734,
"status": "Good",
"t1": "2022-02-22 16:58:21.188000",
"t2": "2022-02-22 16:58:21.188000",
"t3": "2022-02-22 16:58:22.071619"
},
"sv": {
"value": 1704.4019775390625,
"status": "Good",
"t1": "2022-02-22 16:58:21.188000",
"t2": "2022-02-22 16:58:21.188000",
"t3": "2022-02-22 16:58:22.121559"
},
"tv": {
"value": 23.08197021484375,
"status": "Good",
"t1": "2022-02-22 16:58:21.188000",
"t2": "2022-02-22 16:58:21.188000",
"t3": "2022-02-22 16:58:22.171498"
},
"qv": {
"value": NaN,
"status": "Good",
"t1": "2022-02-22 16:58:21.188000",
"t2": "2022-02-22 16:58:21.188000",
"t3": "2022-02-22 16:58:22.221639"
}
}

View File

@ -4,13 +4,20 @@ from asyncua import Client
async def test():
client = Client(url='opc.tcp://192.168.254.5:4863', timeout=10.0)
client = Client(url='opc.tcp://172.16.3.60:4840', timeout=10.0)
# await client.set_security_string('')
async with client:
node = client.get_node('ns=1;s=t|SERVER::A201CD124/MOT_01.AV_Out#Value')
node = client.get_node('ns=0;i=345')
value = await node.read_value()
displayName = (await node.read_display_name()).Text
print(dir(node))
print(f"{displayName=} = {value=}")
print(f"X1: {await node.read_data_value()}")
print(f"X2: {(await node.read_data_value()).Value.Value}")
print(f"X3: {dir((await node.read_data_value()).StatusCode)}")
print(f"X3: {(await node.read_data_value()).StatusCode.name}")
print(f"X4: {(await node.read_data_value()).SourceTimestamp}")
print(f"X4: {(await node.read_data_value()).ServerTimestamp}")
asyncio.run(test())

View File

@ -1,21 +1,25 @@
import re
import json
from AbstractDataObject import AbstractDataObject
from datetime import datetime
class FlatDataObject(AbstractDataObject):
def __init__(self, serverName, nameSpaceIndex, variableName, value):
def __init__(self, serverName, nameSpaceIndex, variableName, dataValue):
super().__init__(serverName + '/' + str(nameSpaceIndex) + '/' + variableName)
self.serverName = serverName
self.nameSpaceIndex = nameSpaceIndex
self.variableName = variableName
self.value = value
self.dataValue = dataValue
def getPayload(self):
payload = {
"serverName": self.serverName,
"nameSpaceIndex": self.nameSpaceIndex,
"variableName": self.variableName,
"value": self.value
"server": self.serverName,
"ns": self.nameSpaceIndex,
"d": self.variableName,
"value": self.dataValue.Value.Value,
"status": self.dataValue.StatusCode.name,
"t1": str(self.dataValue.SourceTimestamp),
"t2": str(self.dataValue.ServerTimestamp),
"t3": str(datetime.utcnow())
}
return json.dumps(payload)

View File

@ -36,13 +36,14 @@ class OpcUaRequester(threading.Thread):
try:
logger.debug(f"Trying {self.name} {self.url} ns={nodeSpec['ns']};{nodeSpec['n']}")
node = client.get_node(f"ns={nodeSpec['ns']};{nodeSpec['n']}")
value = await node.read_value()
dataValue = await node.read_data_value()
displayName = nodeSpec['d'] if ('d' in nodeSpec) else (await node.read_display_name()).Text
logger.debug(f"Got: {displayName=} = {value=}")
logger.debug(f"Got: {displayName=} = {dataValue.Value.Value=}")
if self.flat:
self.queue.put(FlatDataObject(self.name, nodeSpec['ns'], displayName, value))
self.queue.put(FlatDataObject(self.name, nodeSpec['ns'], displayName, dataValue))
else:
dataObject.add(displayName, value)
dataObject.add(displayName, dataValue)
self.stats.incOpcUaRequests()
except ua.UaError as e:
self.stats.incOpcUaErrors()

View File

@ -1,15 +1,22 @@
import re
import json
from AbstractDataObject import AbstractDataObject
from datetime import datetime
class StructuredDataObject(AbstractDataObject):
def __init__(self, topicPart):
super().__init__(topicPart)
self.keyValuePairs = {}
def add(self, key, value):
self.keyValuePairs[key] = value
def add(self, key, dataValue):
self.keyValuePairs[key] = {
"value": dataValue.Value.Value,
"status": dataValue.StatusCode.name,
"t1": str(dataValue.SourceTimestamp),
"t2": str(dataValue.ServerTimestamp),
"t3": str(datetime.utcnow())
}
def getPayload(self):
return json.dumps(self.keyValuePairs)

View File

@ -11,7 +11,7 @@
"opcua": [
{
"enabled": "true",
"type": "structured",
"type": "flat",
"url": "opc.tcp://172.16.3.60:4840",
"name": "apl",
"period": 1.0,