Skip to content

Adding HTTP, JSON, XML and Raw TCP Devices ​

Last updated

These drivers have no tags until you describe them. For HTTP/REST, Custom JSON and Custom XML, fill in Base URL, HTTP method and the Tag map table under Settings → Driver Settings (or in the Add Device wizard): one row per tag with its Tag name, Endpoint or URL (a path such as /status is added to the base URL; a full http://… URL replaces it), the JSON path or XPath, and the Data type. Raw TCP, and request headers or a POST body, are set with Advanced Driver Settings. Until a tag is mapped, subscribing it reads Bad.

HTTP / REST API and Custom JSON ​

The two cards are the same driver. It polls JSON endpoints and extracts values by dot path or JSONPath.

json
{
  "driverConfig": {
    "base_url": "http://192.168.1.80/api",
    "headers": { "Authorization": "Bearer abc123" },
    "tags": [
      { "path": "Oven/Temp", "endpoint": "/status", "json_path": "zones.0.temperature", "data_type": "float" },
      { "path": "Oven/Door", "endpoint": "/status", "json_path": "door.open", "data_type": "bool" },
      { "path": "Oven/Recipe", "url": "http://192.168.1.80/api/recipe", "json_path": "name", "data_type": "string" }
    ]
  }
}
KeyMeaning
base_urlDefault http://<IP Address>:<Port>. HTTPS URLs work; certificates are verified, so a self-signed certificate fails.
methodGET (default) or POST; POST sends body as JSON.
headersExtra request headers (API keys).
tags[].pathTag path in Scada.Ink.
tags[].endpoint / tags[].urlAppended to base_url, or a full URL that overrides it.
tags[].json_pathDot path; numeric parts index arrays (zones.0.temperature). Empty = whole response. Or a JSONPath starting with $ — see below.
tags[].data_typefloat, int, bool (true/1/yes/on), string.

JSONPath (when the path starts with $). The tag's value is the first match.

PathSelects
$.data.temperaturea key
$['odd key'].valuea key with spaces or dots in it
$.zones[0].temp, $.zones[-1].tempan array element (negative counts from the end)
$.zones[*].tempevery element (the first is used)
$..temperaturethe key at any depth
$.zones[?(@.name=='Zone 2')].tempa filter: ==, !=, <, <=, >, >= against a quoted string, number, true, false or null; && and || combine terms; [?(@.on)] keeps elements whose on is present and true

A JSONPath that can't be parsed is logged and reads Uncertain.

  • Each poll fetches each distinct URL once, however many tags use it.
  • Connect (and a liveness check before every poll) sends GET base_url; any status below 500 counts as up.
  • A missing JSON path reads Uncertain; a failed request reads Bad. Timeout 10 seconds.
  • Read-only.

Custom XML ​

Same idea for XML responses:

json
{
  "driverConfig": {
    "base_url": "http://192.168.1.81/status.xml",
    "tags": [
      { "path": "Chiller/SupplyTemp", "xml_path": "//SupplyTemp", "attr": "value", "data_type": "float" },
      { "path": "Chiller/Mode", "xml_path": "Status.Mode", "data_type": "string" }
    ]
  }
}
  • An xml_path with no /, [ or @ is a dot-separated path of child elements from the root, matched case-insensitively (Status.Mode).
  • Anything else is XPath. Element names match on their local name, so namespaces never need to be spelled out (mt: prefixes are ignored). The first match is the value.
  • attr reads an attribute of the matched element instead of its text.
  • method and headers as for HTTP. namespace is still accepted but no longer needed. Read-only.

XPath supported

PathSelects
//Temperaturethe first Temperature element anywhere
/Status/Zone/Temp, Zone/Tempa path from the root (a relative path starts at the root element)
//Sensor[@name='oven']/Valueattribute test: =, !=, <, <=, >, >= (numbers compare as numbers)
//Zone[Name='Soak']/Tempchild element text test; [text()='x'] tests the element's own text
//Zone[2], //Zone[last()], //Zone[last()-1]position, counted among that step's matches (so //Zone[1] is the first Zone in the document)
//Item[@id], //Item[Name]has the attribute / child
//Item[contains(@id,'load')], [starts-with(@id,'X')], [not(@x='1')]functions
//Item[@a='1' and @b='2'], [@a='1' or @a='2']combined (no parentheses)
/Status/Zone[2]/@setpoint, //Mode/text()an attribute or the text itself
//*[@id='x'], .any element; the current element

Raw TCP ​

Opens one TCP connection and, for each tag on every poll, sends a request and parses the reply.

json
{
  "driverConfig": {
    "encoding": "ascii",
    "delimiter": "\n",
    "tags": [
      { "path": "Sensor/Temp", "request": "READ TEMP\r\n", "response_offset": 0, "response_length": 6, "data_type": "float" },
      { "path": "Sensor/Setpoint", "request": "READ SP\r\n", "data_type": "float", "write_request": "SET SP {value}\r\n" }
    ]
  }
}
KeyMeaning
encodingascii: requests are text, the reply is read up to delimiter, offsets are character positions after trimming. hex: requests are hex bytes ("A5 01 03 00"), up to 1024 reply bytes are read, offsets are byte positions.
delimiterASCII mode: the text that ends a reply. Default \n; use \r\n or \r to match your device. Empty reads up to 1024 bytes instead.
requestWhat to send. Empty = read the next message the device sends on its own, one delimited line in ASCII mode.
response_offset, response_lengthSlice of the reply to use.
data_typeint, float, bool, string. In hex mode int is an unsigned integer of the slice, float needs 4 (float32) or 8 (float64) bytes.
byte_orderbig (default) or little, hex mode.
write_requestTemplate for writes; {value} is replaced. Without it the tag isn't writable.
connect_timeout, read_timeoutSeconds, default 10 and 5.

Tags are polled in order on one connection, so a slow reply delays the rest.

Troubleshooting ​

SymptomCauseFix
All tags Bad right after creatingNo tags configured, or tag paths don't match tags[].path.Add the mapping; subscribe the exact path.
HTTP Error at connectbase_url unreachable or returns 5xx.Open the URL from a PC; check headers.
HTTP value UncertainThe JSON path doesn't exist in the response, or a JSONPath has a syntax error (logged as Bad JSON path).Check the response structure; array indexes are numbers.
XML value UncertainNothing matched the path, or the XPath has a syntax error (logged as Bad path).Open the URL in a browser and check element names and attribute values; quotes in predicates must be paired.
XML log Fetch/parse errorResponse isn't valid XML.Check the URL returns XML, not HTML.
Raw TCP values Bad after a timeoutThe ASCII reply never contains delimiter, or wrong request.Set delimiter to what the device ends replies with; use hex encoding for binary protocols.

See also ​

Scada.Ink Help Center