I am trying to crawl the objects in the address space. The aim is to store it and then create an XML file with the objects inside. Does anyone know how to do it?
Asked
Active
Viewed 608 times
1
-
This question is recurring one, but usually phrased as "browse all nodes", here is example with C# https://stackoverflow.com/questions/30573689/opc-ua-minimal-code-that-browses-the-root-node-of-a-server – astrowalker Mar 17 '20 at 06:18
-
That question is quite open. Are you talking Objects specifically (i.e., NodeClass Object), or is "objects" in this case a synonym for "item", i.e., Node? What is the objective of your XML? Providing a list of all Object instances that occur anywhere (i.e. it is paramount that you catch all Objects/Nodes ever added to the address space)? Providing a hierarchy of nodes (in which case it should be sufficient to recursively Browse for HierarchicalReferences and Subtypes that point to Objects/Nodes)? – starturtle Apr 04 '20 at 10:04
1 Answers
2
Here is a example in TypeScript, using node-opcua provided as is that could be a good starting point:
import { OPCUAClient, ClientSession, NodeCrawler, CacheNode, UserData, BrowseDirection, NodeClass, CacheNodeVariable, DataType } from "node-opcua";
const endpointUrl = "opc.tcp://opcuademo.sterfive.com:26543";
const js2xml = require("js2xmlparser");
const nodeId = "ns=1;i=1000"; // MyDevices
(async () => {
try {
function onBrowse(crawler: NodeCrawler, cacheNode: CacheNode, userData: UserData) {
if (cacheNode.nodeClass === NodeClass.ReferenceType) {
return;
}
const node: any = { "@": {} };
node["@"].nodeClass = NodeClass[cacheNode.nodeClass];
if (cacheNode.nodeClass === NodeClass.Variable) {
const cacheNodeVariable = (cacheNode as CacheNodeVariable);
node["@"].dataType = DataType[cacheNodeVariable.dataValue.value.dataType];
if (typeof cacheNodeVariable.dataValue.value.value !== "object") {
node["#"] = cacheNodeVariable.dataValue.value.value;
} else {
node.value = cacheNodeVariable.dataValue.value.value;
}
}
const myUserData = {
onBrowse,
root: node,
};
(userData as any).root[cacheNode.browseName.name.toString()] = node;
if (cacheNode.nodeClass === NodeClass.Variable) {
return;
}
NodeCrawler.follow(crawler, cacheNode, myUserData, "Organizes", BrowseDirection.Forward);
NodeCrawler.follow(crawler, cacheNode, myUserData, "HasComponent", BrowseDirection.Forward);
NodeCrawler.follow(crawler, cacheNode, myUserData, "HasProperty", BrowseDirection.Forward);
}
const client = OPCUAClient.create({ endpoint_must_exist: false });
client.on("backoff", () => { console.log("keep trying to connect"); });
const pojo = await client.withSessionAsync(endpointUrl, async (session: ClientSession) => {
const crawler = new NodeCrawler(session);
const userData = { onBrowse, root: {} };
await crawler.crawl(nodeId, userData);
return userData.root;
});
console.log(js2xml.parse("data", pojo));
} catch (err) {
console.log(err);
process.exit(1);
}
})();
This example will produce an output like this
<?xml version='1.0'?>
<data>
<MyDevices nodeClass='Object'>
<FanSpeed nodeClass='Variable' dataType='Double'>1009.7567008059738</FanSpeed>
<PumpSpeed nodeClass='Variable' dataType='Double'>288.4219646868176</PumpSpeed>
<SomeDate nodeClass='Variable' dataType='DateTime'>
<value>Thu Oct 13 2016 10:40:00 GMT+0200 (GMT+02:00)</value>
</SomeDate>
<Pressure nodeClass='Variable' dataType='Double'>0.3612702142780426</Pressure>
<Temperature nodeClass='Variable' dataType='Double'>28.789330946565517</Temperature>
<TemperatureAnalogItem nodeClass='Variable' dataType='Double'>19.418976965847598</TemperatureAnalogItem>
</MyDevices>
</data>

Etienne
- 16,249
- 3
- 26
- 31