Skip to main content

TCP Server Device Core

The TCP Server Device Core for Blue Pill, known as core-skaarhoj-tcpserver, enables users to connect one or multiple TCP clients to the device core, and read/write values to numerous internally stored data types. It's also an implementation of the data register section of the TCP Server device core for UniSketch, mainly for legacy purposes. The key attraction for Blue Pill users is likely the significantly improved capacities:

  • Strings: It supports the read/write operations for 200 strings, which also include titles for each.
  • String Matrix: Users can read/write into a 20x100 string matrix.
  • Integers: This system allows reading and writing of 200 32-bit signed integers, along with titles for each. Every integer can be set with distinct permitted value ranges, such as "-10 to 20".
  • Booleans: It supports read/write operations for 200 boolean values, including titles for each.
  • Option Lists: It allows the read/write of 200 option list values, with titles for each. Each option list can be set with an individual number of options, for example, "On" and "Off" or "Red", "Green", "Blue", "White", etc.
  • Timers: It enables reading and writing of 200 boolean values, which automatically revert to false after a specific time period.
  • Images: It lets users write 100 JPEG images and 100 PNG images into the device core (primarily intended for small images used for display graphics).
  • From UniSketch: The device core implements Mem A-L, Flags 0-63, as well as Shift and State registers, mostly for legacy reasons.

The device core is generally multi-directional. Most values are set to read/write, and alterations from any client - whether the connected TCP clients or the device core clients - are propagated to other connected clients, ensuring synchronization at all times.

Use cases

The Device Core is an essential tool for ad hoc interactions with Reactor, which is the panel management application found on the majority of SKAARHOJ products. This utility is particularly beneficial for addressing custom integration needs. Below are a few examples:

  • Create ad hoc Device Core parameters using integers and option lists. Leverage value ranges and custom options to allow Reactor to control custom applications through TCP.
  • Utilize Reactor's Virtual Triggers to initiate actions on broadcast devices based on strings, integers, booleans, and option list values that are altered via TCP.
    • Use a timer to either send a cut trigger or initiate recording on a device for a specific duration.
    • Regulate a device's volume using an integer within a predetermined range.
    • Select sources using an integer.
    • Enable or disable functions using a boolean or option list.

Basic Configuration

In Reactor you would add the device core to the device list. The setup page looks like this:

image.png

  • Port is the TCP port where the TCP server is created. If you create multiple servers, make sure these ports are different and not used by anything else. Please check the logs of core-skaarhoj-tcpserver under the Packages tab if you experience problems: there will be information about any issues in the logs.
  • The Device ID is usually "1" and is used to reference the parameters inside the core.
  • Max Clients is the maximum number of clients that can connect at the same time. A light weight security measure.
  • Lock to IPs are specific IP addresses which are the only ones allowed to connect. A light weight security measure.

Connect

Using Putty, telnet or nc depending on your platform, you connect to the TCP server by using the IP address of the Blue Pill device hosting the device core and the port number. Here is an example. Connection is silent, there will be no introduction message sent to the connecting client, but typing in "help" and ending with newline (\n or char 10) will show available commands:

image.png

If you are using Putty on Windows, make sure to set it up correctly to send newlines for line endings:

 

 

 

 

 

The most straight forward way to use the device core would be to send one-shot triggers cowboystyle. This requires only a minimum of configuration but provides the least amount of long term convenience. This is probably a good place to get started.

image.png

Notice the meta values here - they are essentially the configuration for the individual requests.

Adding a Cowboy Trigger to a panel is basically a matter of combining this parameter with a SKAARHOJ:Trigger master behavior:

image.png

The Meta value fields are the key to the whole thing. They would look like this:

image.png

  • The Path meta value is the path under the HTTP Target. Here it is "netio.json", could be "directory/file.ext?id=value&...." etc.
  • The Request Type is the type of HTTP request. Standard is GET, but POST, PUT, PATCH, DELETE are other options you can use here.
  • The Header shall be a JSON object where each key in the object corresponds to an HTTP header that will be set for the request
  • The Body shall be any content that is used as the body in the requests as they support it. This is used for POST requests.

The meta fields are in fact so called IO references in Reactor and that means you can insert references to device cores, variables, constants etc. For example, some of these values could be derived from a constant like "Behavior:Const:Body". This is important because the value gets parsed and pasting pure JSON into these fields won't work, so to make sure a complex string like JSON gets correctly picked up, it must be prefixed "String:" as you see in the examples.

Now, go have fun, shoot from the hip and see how far you get that way... :-)

Command Configuration

The device core allows you to configure a number of fixed commands too. The advantage is that you can bundle an A and B command into a single action for toggles etc. Also, this is the way you can use meta values with the \p1,\p2, ... placeholders etc. like you can for the TCP and UDP device cores. Finally, it's actually possible to decode some level of status back from the returned content of the device via a regular expression.

Below you see the example from the cowboy style trigger, but with some level of parameterization applied now:

image.png

  • The Label field will be set as a fixed value in the device core so you can import it as a label in Reactor. This could be used as a title in Reactor.
  • The Command Path A and B are available to easily create toggle functionality. In this case, Command Path A is set to "netio.json"
  • Header is straight forward JSON content type.
  • The Body field has new features: The \d1 and \d2 are two placeholders that allow us to import values from the meta fields of the device core parameters we will use for the fixed commands, namely Toggle, On Trigger and Off Trigger

In reactor this can be applied to a button in this way:

image.png

  • The values for p1 and p2 are 1 and 1. p1 is the ID of the feature we want to turn on and p2 = 1 is the same as "on" according to the protocol.
  • Commands has the value 2 and that is the number of the command from the configuration.

So to make a similar trigger for off, we can use the same command (2) but change the value of "p2" to 0 instead.

Parsing response and periodic requests

It's possible to parse the response of any request and let a matching part of that response get stored in the device core. This is done by the Matching Return Value field that contains a regular expression. You can study the format of regular expressions elsewhere, but they are basically very powerful and advanced string matching patterns.

Whenever the device core receives feedback from the server it will run the regular expressions set up for the command and if there is a match, it will take the value in parenthesis and store as the status value in the corresponding Status parameter. It's both possible for triggered requests as well as for periodic requests.

Here is an example:

image.png

  • Generally, it's really simple. The path is "netio.json", the request type is not even set (so it defaults to GET) and there is no header or body. 
  • The Matching Return Value is "ID"\s*:\s*1\s*,[^\}]*"State"\s*:\s*([0-9]+)\s*, - yes, that's true. Explained a bit more below...
  • The Periodic Request is 3 - so every three seconds we will call this URL, parse it and store the contents in the Status parameters for this command.

Now, the return body from this request would look this way:

{
"Agent":{"Model":"3PF","DeviceName":"PowerBOX-E7","MAC":"24:A4:2C:38:DF:E7","SerialNumber":"24A42C38DFE7","JSONVer":"2.2","Time":"1970-01-01T16:51:29+01:00","Uptime":13889,"Version":"2.4.3","OemID":300,"VendorID":0,"NumOutputs":3},
"Outputs":[
{"ID":1,"Name":"PTZ (T8)","State":1,"Action":6,"Delay":2020},
{"ID":2,"Name":"Power output 2","State":0,"Action":6,"Delay":2020},
{"ID":3,"Name":"PoE Switch","State":0,"Action":6,"Delay":2020}
]}

And the regular expression will match exactly the portion of this JSON response that is highlighted in red. All the "\s*" is precautions to make sure any whitespace doesn't throw our parsing off, and there is an assumption that the ID attribute comes before the State attribute, but otherwise it should be a good example of how a regular expression can be built to provide some robustness towards variations. In the above case we have to bypass the Name attribute for example.

The main point is that the value of the State attribute is what we are after, but only when found for ID 1. To capture that value, we enclose it in parenthesis: "....([0-9]+)...."

And this happens every three seconds, so we are essentially monitoring the device for state change - on a single feature! And this also underlines the reason why SKAARHOJ generally integrates device cores custom to each device: There is just not efficient way to get all the state from any device by manually building up a ton of such expressions, capturing only one aspect at a time. And feedback from devices is the holy grails of quality integrations that are not simple pray-and-forget approaches to control.

But... now you have got it for the occasional case where there is only this type of "workaround" to get the job done.

Placeholders

The Body and the Path of requests are subjected to placeholders (see also the TCP and UDP device cores):

  • \n and \r will send a newline or carriage return (bytes 10 and 13)
  • \xHH will send a byte with the value HH (in hex): so \xFF will send a byte with value “255”
  • \p1 or \p2 (alternatively \d1, \d2, \h1, \h2) will insert a parameter value as defined by the meta value p1 and p2 in the device core parameters Toggle, On Trigger and Off Trigger.
    The difference of using \p, \d and \h is whether the meta value is inserted as the byte value (\p), inserted as a decimal number like “255” or “37” or “3” (\d - there is no leading zeros) or in hexadecimal like FF or D0 or 00 (\h - in this case it’s always two characters and uppercase).