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 ## 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}` 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: 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/pv {
opcua/apl/0/tv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "tv", "value": 22.574615478515625} "server": "apl",
opcua/apl/0/qv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "qv", "value": NaN} "ns": 0,
opcua/apl/0/pv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "pv", "value": 19.849281311035156} "d": "pv",
opcua/apl/0/sv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "sv", "value": 1688.5152587890625} "value": 19.833280563354492,
opcua/apl/0/tv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "tv", "value": 22.574615478515625} "status": "Good",
opcua/apl/0/qv {"serverName": "apl", "nameSpaceIndex": 0, "variableName": "qv", "value": NaN} "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}` 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: 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 {
opcua/apl {"pv": 19.844480514526367, "sv": 1689.9193115234375, "tv": 22.68524169921875, "qv": NaN} "pv": {
opcua/apl {"pv": 19.844480514526367, "sv": 1689.9193115234375, "tv": 22.68524169921875, "qv": NaN} "value": 19.835201263427734,
opcua/apl {"pv": 19.844480514526367, "sv": 1689.93701171875, "tv": 22.620391845703125, "qv": 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.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(): 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('') # await client.set_security_string('')
async with client: 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() value = await node.read_value()
displayName = (await node.read_display_name()).Text displayName = (await node.read_display_name()).Text
print(dir(node))
print(f"{displayName=} = {value=}") 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()) asyncio.run(test())

View File

@ -1,21 +1,25 @@
import re import re
import json import json
from AbstractDataObject import AbstractDataObject from AbstractDataObject import AbstractDataObject
from datetime import datetime
class FlatDataObject(AbstractDataObject): class FlatDataObject(AbstractDataObject):
def __init__(self, serverName, nameSpaceIndex, variableName, value): def __init__(self, serverName, nameSpaceIndex, variableName, dataValue):
super().__init__(serverName + '/' + str(nameSpaceIndex) + '/' + variableName) super().__init__(serverName + '/' + str(nameSpaceIndex) + '/' + variableName)
self.serverName = serverName self.serverName = serverName
self.nameSpaceIndex = nameSpaceIndex self.nameSpaceIndex = nameSpaceIndex
self.variableName = variableName self.variableName = variableName
self.value = value self.dataValue = dataValue
def getPayload(self): def getPayload(self):
payload = { payload = {
"serverName": self.serverName, "server": self.serverName,
"nameSpaceIndex": self.nameSpaceIndex, "ns": self.nameSpaceIndex,
"variableName": self.variableName, "d": self.variableName,
"value": self.value "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) return json.dumps(payload)

View File

@ -36,13 +36,14 @@ class OpcUaRequester(threading.Thread):
try: try:
logger.debug(f"Trying {self.name} {self.url} ns={nodeSpec['ns']};{nodeSpec['n']}") logger.debug(f"Trying {self.name} {self.url} ns={nodeSpec['ns']};{nodeSpec['n']}")
node = client.get_node(f"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 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: if self.flat:
self.queue.put(FlatDataObject(self.name, nodeSpec['ns'], displayName, value)) self.queue.put(FlatDataObject(self.name, nodeSpec['ns'], displayName, dataValue))
else: else:
dataObject.add(displayName, value) dataObject.add(displayName, dataValue)
self.stats.incOpcUaRequests() self.stats.incOpcUaRequests()
except ua.UaError as e: except ua.UaError as e:
self.stats.incOpcUaErrors() self.stats.incOpcUaErrors()

View File

@ -1,15 +1,22 @@
import re import re
import json import json
from AbstractDataObject import AbstractDataObject from AbstractDataObject import AbstractDataObject
from datetime import datetime
class StructuredDataObject(AbstractDataObject): class StructuredDataObject(AbstractDataObject):
def __init__(self, topicPart): def __init__(self, topicPart):
super().__init__(topicPart) super().__init__(topicPart)
self.keyValuePairs = {} self.keyValuePairs = {}
def add(self, key, value): def add(self, key, dataValue):
self.keyValuePairs[key] = value 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): def getPayload(self):
return json.dumps(self.keyValuePairs) return json.dumps(self.keyValuePairs)

View File

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