Connect to a node with a String identifier - opc-ua

I'm trying to write a generic OPC-UA connector with Eclipse Milo.
Reading data from nodes already works fine when I'm using numeric nodeIDs, such as ns=0;i=2258. In milo I can simple construct the nodeID like this for example:
NodeId nodeIdentifier = new NodeId(Unsigned.ushort(nameSpaceID), uint(nodeID));
and it works fine.
But when I'm trying to connect to a note with a string identifier of a production node that only have a string identifier like shown in this image
the process fails with a StatusCode{name=Bad_NodeIdUnknown, value=0x80340000, quality=bad} exception.
I create the nodeIdentifier like this NodeId nodeIdentifier = NodeId.parse(nodeIDString);
and the parsed value looked like this:
ns=1;s=t|023_Messwert

First things first, you can’t just decide to use a string-based NodeId because you feel like it. If the server is exposing it as an integer-based NodeId then that’s what you have to use, as is the case with the CurrentTime Node being identified by ns=0;i=2258.
Parsing a string-based NodeId via NodeId.parse will work fine as long as it’s in the right format. What value are you trying to parse?

Related

Pass string parameter to remote process in kdb

I am trying to pass a variable that is string to the ipc query. This does not work for me.
Example:
[`EDD.RDB; "?[`tab;enlist(like;`OrderId;",("string Number),");();(?:;`Actions)]"]
I am trying to query this RDB where OrderId like Number(string)
Number is a parameter but when I passed as string to the remote process, Number is not string any more. I tried to put string in front but still get the same result.
What I want to pass to remote process is this:
Number:"abc"
"?[`tab;enlist(like;`OrderId;"abc");();(?:;`Actions)]"
EDIT as you have updated your question.
It's hard to give a solid answer here as your example is lacking information.
What you have posted is not a valid IPC call in KDB+. I suspect what you may be trying to run is something like:
h(`EDD.RDB; "?[`tab;enlist(like;`OrderId;",("string Number),");();(?:;`Actions)]"])
Assuming Number is an int (e.g. Number:123) then in that case you could rewrite it as:
h(`EDD.RDB;"select distinct Actions from t where orderID like \"",string[Number],"\"")
Which is easier to read and work with. Assuming Number is defined on the client side then the above should return an answer.
If you do want to use functional form then you could try something like:
"?[`tab;enlist (like;`orderID;string[",string[Number],"]);1b;(enlist`Actions)!enlist`Actions]"
As your query string.
If Number is already a string on your process, e.g Number:"123" then you should be able to either:
h(`EDD.RDB;"select distinct Actions from t where orderID like \"",Number,"\"")
OR
h(`EDD.RDB;"?[`tab;enlist (like;`orderID;string[",Number,"]);1b;(enlist`Actions)!enlist`Actions]")
Does the IPC query have to be string? Passing parameters would be cleaner using (func;params) syntax for IPC.
handleToRdb ({[number] ?[`tab;enlist(like;`OrderId;number);();(?:;`Actions)]};"abc")

operator does not exist: # timestamp without time zone

In a parameterized query issued from c# code to PostgreSQL 10.14 via dotConnect 7.7.832 .NET connector, I select either a parameter value or the local timestamp, if the parameter is NULL:
using (var cmd = new PgSqlCommand("select COALESCE(#eventTime, LOCALTIMESTAMP)", connection)
When executed, this statement throws the error in subject. If I comment out the corresponding parameter
cmd.Parameters.Add("#eventTime", PgSqlType.TimeStamp).Value = DateTime.Now;
and hardcode
using (var cmd = new PgSqlCommand("select COALESCE('11/6/2020 2:36:58 PM', LOCALTIMESTAMP)", connection)
or if I cast the parameter
using (var cmd = new PgSqlCommand("select COALESCE(cast(#eventTime as timestamp without time zone), LOCALTIMESTAMP)", connection)
then it works. Can anyone explain what # operator in the error is referring to and why the error?
In the case that doesn't work, your .Net connection library seems to be passing an SQL command containing a literal # to the database, rather than substituting it. The database assumes you are trying to use # as a user defined operator, as it doesn't know what else it could possibly be. But no such operator has been defined.
Why is it doing that? I have no idea. That is a question about your .Net connection library, not about PostgreSQL itself, so you might want to add tag.
The error message you get from the database should include the text of the query it received (as opposed to the text you think it was sent) and it is often useful to see that in situations like this. If that text is not present in the client's error message (some connection libraries do not faithfully pass this info along) you should be able to pull it directly from the PostgreSQL server's log file.

unable to set db using string while coding in python

I would like to know if there is a way to set db using a variable
For example: I am coding in Python, and I connect using client = MongoClient(uri). All goes fine.
There are 4 dbs: test1,test2,test3,test4.
I am able to list them all.
dblist = client.list_database_names()
print(dblist)
All goes fine.
Now, Instead of connecting/ using
db = client.test1
Is there a way to use a string rather than actual name of the db?
such as str = 'test1', and then db=client.str.
(this doesn't work)
In my program , I display the list of dbs first and then I am taking user input on the db , and proceed with further flow, but unable to do so.
Please help.
You cannot add string as an name when it comes to that. However there is another function that takes string of the name of certain database and gets the database.
db=client.get_database('test')
Here is the documentation: https://api.mongodb.com/python/current/api/pymongo/mongo_client.html

OPC UA How to read a datatype from the server

I can't seem to figure this one out:
Before writing to a tag I need to know what data type it is expecting(the value that mywrite function receives is always a string).
I realise you have to read the datatype from the server and here's my code to do so, but I'm at a loss as to how to use the information returned:
var nodesToRead = BuildReadValueIdCollection(node.DisplayName, Attributes.DataType);
DataValueCollection readResults;
DiagnosticInfoCollection diag;
_session.Read(
requestHeader: null,
maxAge: 0,
timestampsToReturn: TimestampsToReturn.Neither,
nodesToRead: nodesToRead,
results: out readResults,
diagnosticInfos: out diag);
var val = readResults[0];
What do I do with val to determine what the datatype is?
Do I use Val.Value or Val.WrappedValue or Val.WrappedValue.Value (whatever the difference is ?)
The tag I've been using to test has returned Val = "i=6".....
What is this referring to?
What datatype is "6" and
how do I convert val to something I can use.
Any help would be greatly appreciated.
Thanks
Reading from the DataType attribute returns a NodeID of the OPC UA type. It can be one of the "standard" types defined in the OPC UA spec, or something specific to the server. The standard types reside in namespace 0, which is your case (as there is no "ns=..." part in the displayed Node ID), and "i=6" stands for Int32.
There are many types with pre-defined Node IDs, and you need to consult the OPC UA specs, or the nodeset files that come with the stacks/SDKs (e.g. Opc.Ua.NodeSet.xml), to figure out what they mean.
The value is a NodeId referring to the data type node. You can compare the value to known NodeId values (DataTypeIds in .NET or something, not sure about this right away) or you will need to find the data type node from the address space.
In recent version, node-opcua client has been extended with a utility function ClientSession#getBuiltInDataType that does this for you.
var nodeId = coerceNodeId("ns=411;s=Scalar_Simulation_Int64");
session.getBuiltInDataType(nodeId,function(err,dataType){
if(!err){
console.log("Use data Type",dataType," to write into UAVariable", nodeId.toString();
}
});
We use this extension method to determine the C# type of nodes:
public static Type GetSystemType(this Session session, NodeId nodeId)
{
var currentValue = session.ReadValue(nodeId);
var builtInType = currentValue.WrappedValue.TypeInfo.BuiltInType;
var valueRank = currentValue.WrappedValue.TypeInfo.ValueRank;
return TypeInfo.GetSystemType(builtInType, valueRank);
}
It is somewhat a hack but it works well.

Integers in TextNodes w/ Python minidom

I am working on an API using SOAP and WSDL. The WSDL expects integers to come through. I am fairly new to ALL of this, and constructing XML in Python. I have chosen to use minidom to create my SOAP message. So using minidom, to get a value into a node I found I have to do this:
weight_node = xml_file.createElement("web:Weight")
weight_contents = xml_file.createTextNode(weight)
weight_node.appendChild(weight_contents)
So say weight needs to go in as an integer and IS an integer. The function is 'createTextNode' does this mean its going to be text, or what I put in there has to be text? Again I am fairly new to all of this. So if what I have explained seems way off base, please speak up.