NodeId as string in ModelCompiler OPC UA - github

I am trying to develop a OPC UA server on my own, but since I am quite a newbie in coding, it is quite hard for me.
I have started from the QuickstartApplication found here: https://github.com/OPCFoundation/UA-.NET-Legacy
in particular I edit the ModelDesign.xml file to customize it as I wish
https://github.com/OPCFoundation/UA-.NET-Legacy/blob/master/ComIOP/Common/Common/ModelDesign.xml
I would like to define some nodes with NodeId as string (all the NodeId in the ModelDesign.xml in the example are numeric)
Following this xsd, I have found "StringId" and "NumericId" that look like what was looking for
https://github.com/OPCFoundation/UA-ModelCompiler/blob/master/ModelCompiler/UA%20Model%20Design.xsd
but changing their value in ModelDesign.xml does nothing about the NodeId. There is no error, just the compiler assigns new NodeIds (all numeric) as if it does not consider the changes I have made.
As a compiler, I am using the ModelCompiler found on GitHub
https://github.com/OPCFoundation/UA-ModelCompiler
Can somebody help me, please? How can I customize the NodeId of the nodes?
Thank you
Edo

the best suggestion that I can offer at this stage is to clone the UA-.NETStandard and run the NetCoreConsoleServer in
UA-.NETStandard/SampleApplications/Samples/NetCoreConsoleServer
through the debugger. The boiler node manager, if my memory serves me well, uses stringIDs. The Interface INodeIdFactory in ISystemContext.cs offers some insight in how ID's are generated.
IMHO, the model designer has no switch to enforce string ID's as you know. So you'll need to programmatically allocate stringID's rather than numeric ID's to nodes upon server boot. I haven't figured it out yet either.
So, you may set breakpoints in the BoilerNodeManager.cs and see how the nodeID is actually constructed.

Related

Q: OPC UA location of sensor data

I have done some research on OPC UA and noticed that all sensor data on the Prosys sample server is stored in subfolders of the Object (i=85) folder.
On the OPC UA server of a machine I have seen that the sensor data like the measured value, the unit etc. can ONLY be accessed via the Types (i=86) folder.
The path here would be i=84 -> i=86 -> i=88 -> i=58...
There is really no other path through which you can reach these nodes otherwise.
I have never seen such an implementation.Is this normal that such data is also stored in the Types folder or are there any guidlines that forbid this?
The machine is also a bit older.
Thanks for your help
UPDATE:
the further path of i=58 looks like this, where --(i=45)-> symbolizes the Referencetype from the previous to the following node (in this case i=45, HasSybtype) and the word in the parentheses next to the NodeId is the NodeClass.
i=58 --(i=45)-> ns=2;i=1(ObjectType) --(i=35)-> ns=2;i=2(Object)
--(i=35)-> ns=2;i=3(Object) --(i=47)-> ns=2;s=#setPressure(Variable) --(i=46)-> ns=2;i=5(Variable)
ns=2;s=#setPressure contains the value 250.0 and ns=2;i=5 an Engineering unit
This is not normal. It sounds like a bad implementation done by somebody who didn’t know any better.
Depending on the reference types they used to build this structure you could argue it is forbidden. DataType Nodes should only be the source of HasProperty, HasSubtype, and HasEncoding references.
edit: The path you mention is Root -> Types -> ObjectTypes -> BaseObjectType. Are you sure the Nodes you're finding under here are Variable Nodes with values or are you just seeing additional types defined by this server?

Possibility of a multilanguage 'source' name with Twincat Eventlogger

Roald has written an excellent guide for the Twincat Eventlogger.
https://roald87.github.io/twincat/2020/11/03/twincat-eventlogger-plc-part.html
https://roald87.github.io/twincat/2021/01/20/twincat-eventlogger-hmi-part.html
For us this is exactly what we want, there is however 1 thing I haven't figured out. How to get the sourcename of the alarm in multiple languages in the HMI. params::sourceName gives the path in the software (example: MAIN.fbConveyor1.Cylinder1) This path can be customized when initializing the alarm (as Roald has shown). This doesn't work in my case, since I would like to define a generic alarm (example: "Cilinder not retracted within maximum time") that is instantiated multiple times.
I was thinking of using the source as a way to show the operator where the alarm occurs. We use this way (path) already for saving machine settings among other things. The machines we build are installed all over the world, so multilanguage is a must.
Beckhoff does support multilanguage alarm names (when defined), but the source is not defined, but dynamically generated.
Anyone have an idea how this problem can be solved?
If I understand your question correctly, then being able to parameterize the event text with information of the source of the problem should help you out.
If you define the event text as Cylinder {0} has not retracted in time. then you can add the arguments of that text during runtime.
IF bRaiseAlarm THEN
bRaiseAlarm := FALSE;
fbAlarm.ipArguments.Clear().AddString('Alice');
fbAlarm.Raise(0);
END_IF
However, since this also stated in the articles you mentioned, I am unsure if this would solve your problem.
'Alice' in this example, can be hard to localize. The following options come to my mind.
The string can be based on an ENUM. Enums can have textlist support, so if you add your translations there, that should allow multilingual output. However... this does require a lot of setup, placing translations inside your code, and making sure the PLC application is aware of the language that the parameter should use.
Use tags to mark the source device, as tags can be language invariant. It is not the most user-friendly method, but it could work for you. It would become something like: "Cylinder 'AA.1123' did not retract in time.". 'AA.1123' as a tag would have to be stored inside your PLC code as a string. You will have to trust that your operator can relate the tag back to the actual source.
Hopefully, this helped, or else please help me understand the problem better.

Is there way run uvm_sequences on ovm_agent?

We are in process to migrate our TB to UVM.
I am working on first IP that will be verified using UVM.
I have to find out if it is possible to reuse my uvm_sequences in SOC that remains in OVM mean time.
In case it is possible , like find example how it's done.
Thanks in advance.
You cannot mix OVM and UVM that way. You should be able to write your uvm_sequence in such a way that it work in both by simply changing your u's to o's. You would have to limit your sequence to functionality that exists in both.
If you use UVM RAL. there is a package that integrates that functionality back into OVM.
There is another package, ovm_container, that gives you the functionality of uvm_config_db.

Using HIDAPI, how can you query the raw report descriptor?

I'd like to deconstruct the raw reports received from the hid_read function of hidapi.
As I understand, this can be achieved using the information from the device's report descriptors. But when trying to query for those descriptors, I get lost somewhere between the HID Spec and using the methods available in hidapi.
I would love to see a concrete C or node-hidapi based example that queries and enumerates all the report descriptors for a device — perhaps a mouse to keep things simple?
I asked Alan Ott by email about this, and he responded with no as follows:
HIDAPI does not provide functions for getting or parsing the report
descriptor. Since HIDAPI is for talking to a custom devices, these
devices will likely contain all or mostly vendor-defined report items
anyway.
This isn't exactly what you're looking for, but it will get the same job done. I highly recommend you use libusbx over any other hid library. If you are willing to do so, here is a very blatant example of device enumeration.
Edit:
It appears that libusbx has been merged back into libusb. This is awesome! As the above link is broken, here is the new link.
I had success with using both https://github.com/Orochimarufan/HIDRAW/tree/master/HIDRAW_test (that is hopefully the C code example that you asked about) and RDD! USB HID Report Descriptor Decoder for more descriptive output.

What is scala.mobile supposed to accomplish?

...and why has the package this misleading name (I assumed it had something to do with JavaME or mobile/smart phones)?
I found no references on the internet about scala.mobile.Code or scala.mobile.Location at all nor did I manage to do anything with those classes except getting ClassCastExcetions or NoSuchMethodErrors.
Actually there is not even a single test against scala.mobile in the Scala's test tree which could help understanding that code.
The classes really smell like they were forgotten in the source tree a long time ago and got accidentally released since that.
Maybe I just missed something about them?
Update:
scala.mobile was removed in Scala 2.9.
I just checked the source code.
When Scala changed the name mangling of class files a few years ago and it seems people forgot to update these classes accordingly.
So my answer would be:
At least Location has no purpose, because it is not possible to get anything sensible out of it (except exceptions) and Code without Location is severely limited. It works though if you pass the class literal to Code directly:
import scala.mobile._
val c = new Code(classOf[scala.collection.mutable.StringBuilder])
c.apply[StringBuilder, String]("append")("Foo")
c.apply[String]("toString")() // returns "Foo"
c.apply[Int]("length")() // returns 3
Looks like yet-another implementation in the standard library of reflection-slightly-nicer.
The description of Location pretty much explains what that is about:
The class Location provides a create method to instantiate objects
from a network location by specifying the URL address of the jar/class file.
It might be used by remote actors. Maybe.
As for why it has this misleading name? Well, back in 2004 smart phones had really low penetration, so maybe the association wasn't all that strong.