JSON is a recursive notation. Any object field or array element in a JSON document can have any type as its value, including other objects and arrays, to arbitrary depth. To process the incoming JSON message, the parser recursively visits every field and array element in the document, and executes callback functions that you provide at every level.
There are four callback functions that are called during this descent. It is the responsibility of the system integrator to provide these callbacks.
app.ObjectProcessor
is called when a JSON object type is encountered during
processing. Normally this function can be omitted. The default
behaviour is to continue the recursion. If you supply this
function and it returns a boolean false, all
further processing on this object will be stopped.
app.ArrayProcessor
is called when a JSON array type is encountered during
processing. Normally this function can be omitted. The default
behaviour is to continue the recursion. If you supply this
function and it returns a boolean false, all
further processing on this array will be stopped.
app.PropertyProcessor
is called when a JSON property type is encountered during
processing. A JSON property is a field of a JSON object.
Normally this function can be omitted. The default behaviour is
to continue the recursion. If you supply this function and it
returns a boolean false, all further
processing on this array will be stopped.
app.ValueProcessor
is called when a JSON field with a scalar value (not an array
or object) is encountered during processing. This function can
be omitted. The default behaviour is to write the value to a
data point whose name is computed from the JSON path to this
property, in the default data domain.
When a point name is computed from a JSON path, the default behaviour is
to construct the point by concatenating the default domain, a colon and the
path field names separated by dot characters. For array elements, the
default is to append an open bracket ( [ ), an index
starting at zero, and a closed bracket ( ] ) to the
preceding path. The parser provides two callbacks to modify this
behaviour:
app.TopicNameModifier
accepts a topic string and a JSON document. It returns a
string, representing a modified topic name that should be used
instead of the original topic for this message. Use this to
change point names and topics based on the contents of the JSON
document. This can be useful when a device transmits data for
different subsystems via the same topic, differentiating the
subsystems through a name in the JSON payload.
app.PointNameModifier
accepts a path of elements separated by slash characters. It
must return a fully qualified point name (including the domain:
prefix). If the point name contains dot characters then a
hierarchy will be created in the data engine by splitting on the
dots if a value is written to this point. This function can be
omitted. The default behaviour is to call
app.PointNameFromTopic for this JSON
path.
app.ArrayValueNamer
accepts a parent path and a numeric index, starting at zero.
It must return a path formed from the input path and index. For
example, if path is Plant1/Temperatures and the index is 1, then
some possible return values could be:
Plant1/Temperatures[1]
|
Plant1/Temperatures-1
|
Plant1/Temperatures01
|
This function can be omitted. The default behaviour is to append
[ + to
the JSON path.index + ]
When a topic is identified as producing a specific schema for the first time, that topic is associated with that schema to speed up processing for subsequent messages. When that association is made, a callback will be executed if it is defined:
app.TopicInitialization
runs when a topic is first identified as producing a specific
schema. This gives the integrator the opportunity to log a
message or run some special processing. Particularly, this is
where an association can be made between data points and publish
formats using the app.RegisterPoint
function, providing for bi-directional communication with the
device via MQTT. app.TopicInitialization
supplies both the original topic the produced this message and
the topic as modified by
app.TopicNameModifier.
When the callback functions run, the following variables are defined to provide context for the callback:
input
is an object of type JsonParserData with
the following members:
input.Json
is the JToken object representing the root of the JSON
document. This is typically a JObject or a JArray. For
more information on these types, consult the Newtonsoft.Json documentation.
input.Level
is the current processing level in the recursive
processing, where the root is level 0.
topic
is the full name of the MQTT topic on which this message was
delivered.
app
is an object that supplies methods and data members:
app.ProcessJson()
Start the recursive processing of the JSON
message.
app.PointNameModifier()
The point name modifier method described
above.
app.ObjectProcessor()
The object processor method described
above.
app.ArrayProcessor()
The array processor method described
above.
app.PropertyProcessor()
The property processor method described
above.
app.ValueProcessor()
The value processor method described
above.
app.ArrayValueNamer()
The array value naming method described
above.
app.TopicInitialization()
The topic initialization method described
above.
app.ExcludePaths
An array of strings representing the full JSON paths
to fields that should not be processed. You would use
this, for example, to ignore a field that contains a
date that you do not want to be written to a data point.
Instead, you would extract that date and use it as the
timestamp when writing other data points.
app.DefaultDomain
A read-only string representing the data domain
configured for the MQTT broker or client. If there is no
default domain configured for this broker or client,
then the first element of a path (topic or JSON path)
will be used as the domain name when creating DataHub data
points.
app.RegisterPoint
There are multiple forms of this function with
different signatures. This function associates a data
point with a publish format. If the point name is null,
or the form of app.RegisterPoint
does not accept a point name, then the data point name
is formed by concatenating the topic and path arguments
separated by a slash and then calling the PointNameModifier
function on the result. The full topic is formed by
concatenating the topic and
jsonPath arguments. If the
jsonPath is null then it is
ignored. Whenever the data point changes in the DataHub
data engine, the point value will be written to the full
topic.
app.WritePoint
There are multiple forms of this function with
different signatures. This function writes a value to a
DataHub data point with the given
and
quality.
At least one of
timestamp,
jsonPath,
and
pointName
must be a non-empty string. The target point name will
be determined as follows:basepointName
If
is not null and
topicapp.PointNameModifier is set,
a point name will be created from
and
topic
using jsonPathapp.PointNameModifier,
otherwise
If
is null, a point name will be created from
pointNametopic
using jsonPathPointNameFromTopic,
otherwise
will be used without modification. In this case
pointName
must be a fully qualified name, including the
pointNamedomain: prefix.
app.WritePoint(
Writes a value to a DataHub point with pointName,
value)quality =
PointQuality.Good and a timestamp of the
current system time.
app.WritePoint(
Writes a value to a DataHub point with the provided
pointName,
value,
quality,
timestamp)
and
quality.
timestamp
app.WritePoint(
Writes a value to a DataHub point with
topic,
jsonPath,
value) and a
quality =
PointQuality.Good
of the current system time.timestamp
app.WritePoint(
Writes a value to a DataHub point with the provided
topic,
jsonPath,
value,
quality,
timestamp)
and
quality.
timestamp
app.WritePoint(
Writes a value to a DataHub point with
topic,
jsonPath,
property) and a
quality =
PointQuality.Good
of the current system time. The value written to the
data point is the value of the
timestampJProperty property.
app.WritePoint(
Writes a value to a DataHub data point with the given
basePointName,
property,
quality,
timestamp)
and
quality.
The value is provided as a timestampJProperty
rather than a simple value. The value written to the
data point is the value of the
JProperty.
DataPoint
app.ReadPoint(
Reads a single data point from the DataHub data engine.
This returns a pointName)DataPoint instance
from which the value can be extracted using
point.DblVal,
point.StrVal, etc. The available
members of a DataPoint are listed
in the Common Formulas table, under
Points, in the Advanced JSON
Message Format window.
DataPoint[]
app.ReadPoints(
Reads multiple data points from the DataHub data engine.
This is much more efficient than reading multiple points
one at a time using pointNames)ReadPoint. The
list of
can be any
pointNamesIEnumerable
type.string
DataPoint[]
app.GetChildren(
Retrieves the current names and values for all child
points of the
parentname,
pattern,
includeLeaves,
includeBranches,
recursive),
a fully qualified point name, including the
parentname
prefix. The
domain:
is a globbing pattern, not a regular expression. See the
patternshell_match function
for the matching rules. Use the asterisk character (
* ) to retrieve all child points.
For
and
includeLeaves,
an entry of includeBranchestrue or
false indicates whether to
retrieve leaf or branch points, respectively. For
,
an entry of recursivetrue or
false indicates whether to
recursively descend into all descendent children of the
parent point. If
is recursivefalse,
GetChildren will return only
the immediate children of the parent point.
DataPoint[]
app.GetRegisteredPoints()
Returns a list of the points that have been configured
for this connection.
app.Log(
Logs a message. During testing this will write the
message)
to the test output pane. At runtime this will write the
message
to the DataHub Event Log. This function does not add a
newline at the end of the message.message
app.Debug(
Logs a
message)
only during testing. At runtime this will do
nothing.message
string
app.PointNameFromTopic(
Constructs a point name given an MQTT topic or JSON
path. MQTT topics and JSON paths are sequences of path
elements separated by forward slash characters. The
first character should not be a slash. The path is
converted to a DataHub point name by concatenating the
default domain (see topic)app.DefaultDomain), a
colon character ( : ), and the path
elements separated by dot characters. If a path element
contains a dot, it will be converted to a slash in the
point name. If no default domain is set then the first
element of the
will be used as the domain name, and the point name will
be constructed from all subsequent path elements. If the
first element in the
topic
name is topicapp.DefaultDomain, it is
removed from the resulting point name to avoid having it
included twice.
string
app.TopicFromPointName(
Constructs a topic name from a point name. The point
name
(pointName))
should be fully qualified, including the
pointName. All
dot characters in the point name will be converted to
slash characters in the resulting topic name. If the
point name contains a slash character, it will be
converted to a dot in the topic name. If the domain name
of the point is domain:
prefixapp.DefaultDomain
then the domain name is omitted from the resulting
topic. Otherwise, the domain name in the point will be
treated like any other path element.
For the Message
options, the variable msg contains client information for
use when configuring the Advanced Parser.
msg A global variable that contains client information:
msg.ClientId The client ID of the connection. In the DataHub broker
this is the ID of the client that originated a message.
In a DataHub client, this is the client ID from the
connection configuration.
msg.IpAddress In the DataHub broker, this is the IP address of the
connected client. In the DataHub client, this is the
hostname from the connection configuration.
msg.Username In the DataHub broker, this is the user name that the
client used to log in, or null if
there is no username. In the DataHub client, this is the
username from the connection configuration, or
null if no username is
configured.
If your script references a data point structure, such as that returned by
app.ReadPoint or in the point
variable in a publish format, you can access some of the metadata associated
with the point. This information can be read by your script, but must not be
modified.
point.MetaInfo The engineering unit information for the point. This could be
null. The following fields are available:
Eu A string defining the engineering units, such as
m/s or
kPa.
Description A string describing the point.
EuHigh A double containing the upper bound of the engineering
unit range.
EuLow A double containing the lower bound of the engineering
unit range.
InstrumentHigh A double containing the upper bound of the raw
measurement range.
InstrumentLow A double containing the lower bound of the raw
measurement range.
ContactCloseLabel A string containing the label to use for a Boolean
value of true.
ContactOpenLabel A string containing the label to use for a Boolean
value of false.
Starting with DataHub version 11, the following will also be available:
point.Origin The information indicating the source of the most recent value
written to this point. This could be null. The following fields
are available:
Label A string containing the label of the connection that
originated the value. This could be
nullor an empty string. .
Description A string containing the description of the connection
that originated the value. This could be
nullor an empty string.
User A string containing the name of the user credential
associated with the connection. This could be
nullor an empty string.
Host A string containing the IP address or DNS name of the
computer that originated an inbound connection, or the
IP address or DNS name of the computer to which an
outbound connection is targeted. This could be
nullor an empty string.
Type A string containing the type of connection that
originated this value. This could be
nullor an empty string.
RefCount An integer that approximately indicates the number of
points that share this origin. This is primarily used
internally, and is not expected to be exact.
Examples
var pt = app.ReadPoint(point.FullName);
var metadata = pt.MetaInfo;
if (metadata != null)
{
app.Log(LogLevel.Info, "Description: " + metadata.Description);
}