Integrations
An integration is how you point HotLoop at a kind of device you know the address of, answer a few questions, see what is actually on it, and keep the points you want. It makes the device and its tags. Entities follow from the tags the way they do for every tag, so the new points are on the entity API, in automations and on dashboards a minute later.
There are three ways a device gets into HotLoop, and they are meant to sit side by side:
| Details | Who starts it | What it needs |
|---|---|---|
| MQTT discovery | The device, by announcing itself on a broker | A publisher that speaks one of the formats |
| Network discovery | The network, by being listened to | Nothing from the device; it tells you what it heard and how HotLoop could talk to it |
| Integrations (this page) | You, with an address | A device that answers its own protocol |
An integration never writes to the device, and nothing it makes is armed. A point that was found is a point nobody has yet decided may be commanded, so every tag a setup creates is read-only until someone arms it, one at a time, in the tag editor, the same as a tag from any other source.
What is here
Section titled “What is here”| Integration | Protocol | Verified against |
|---|---|---|
OPC UA server (opcua) |
OPC UA | Microsoft’s opc-plc 2.12.48 |
SNMP device (snmp) |
SNMP | net-snmp’s snmpd 5.9.4, v1, v2c and v3 |
BACnet/IP device (bacnet) |
BACnet/IP | bacpypes3 0.0.110, an independent BACnet stack |
CODESYS PLC (codesys) |
CODESYS | CODESYS Control for Linux SL 4.22.0.0, running HotLoop’s lab program and a second, much larger program |
More are added on this framework as they can be proven against a real server.
Going the other way
Section titled “Going the other way”An integration brings a device in. To send HotLoop’s readings and events out to a
Kafka broker, see the Kafka API event stream
under historian targets: Apache Kafka and Redpanda, TLS and SASL, readings on one
topic and the system log on another. To send them as OPC UA PubSub (UADP over UDP),
or to read a publisher’s, see OPC UA PubSub:
reading one is a device with the protocol opcua-pubsub, with no setup flow, since
a datagram carries field positions and no names.
For a switch, a UPS, a PDU, a power meter, or anything running an SNMP agent. The questions follow the version: v2c asks for a community, v3 asks for a user and only the passphrases its security level needs. There is no default community.
The probe walks the system group, the interface tables, host resources, the load table and net-snmp’s extend outputs, the objects HotLoop can name, and shows each with what the agent said it holds right now. It suggests the ones a person pointing at a new device wants: the device’s name, location and uptime (shown in seconds, not the agent’s hundredths), each interface’s operational state and error counts, its byte counters (the 64 bit ones where the agent has them), the load averages, and any extend rows. It says in its notes how many suggested points are counters, because a counter on a chart wants a rate.
Anything else the agent has is still readable: set it up by hand as a tag whose address is the OID. See the SNMP driver for what a tag becomes, what a missing object does, and why a wrong v2c community looks like a dead device.
SNMP is read-only here, always. HotLoop does not send SET.
BACnet/IP
Section titled “BACnet/IP”For a building automation controller, a meter, a thermostat: anything on the IP network that speaks BACnet. The questions are the device’s address, the device instance if you know it (and then HotLoop refuses a different device answering at that address), and which network card to send from if the machine has two.
The probe asks the device who it is, reads its object list, and reads every
analog, binary and multi-state object it finds (and the integer, large analog,
accumulator and character string values): name, description, units, present
value and status flags. It shows each with what it read right now, and suggests
the first hundred. Units come across as a label and, where they mean one, a
device class, so a degrees-celsius input is a °C temperature.
It says in its notes how many objects report a fault (they read bad until the device clears it) and how many are out of service (they read uncertain, because the value is what was written to them). A multi-state object’s description lists its states, and its sample shows the state as well as the number.
BACnet is read-only here, always. HotLoop does not write a property, and does not reach a device behind a BACnet router: see the BACnet/IP driver for what is and isn’t covered.
CODESYS
Section titled “CODESYS”For a PLC that runs a CODESYS Control runtime. The questions are the OPC UA ones (address, security, a user name and password if the PLC’s user management is on) and, only if you need them, the part of the application to list, the PLC and application names, and how many elements of an array to list.
The probe connects to the runtime’s OPC UA server, finds the PLC and its application, and lists the variables the application exports (its Symbol Configuration) by the names the programmer wrote, with their types and whether each can be written. It suggests the application’s own variables, not the elements of its buffers, and says in its notes how many arrays it listed in part. A PLC with nothing exported is told how to export something.
Set up with "dashboard": true in the request and the points you keep also get
a dashboard named for the device: a heading, a trend of the numbers that move,
the device’s alarms, and a value card for each point under a heading for its
variable list. It is a first screen made from the program as it is, and it is
edited like any dashboard. Nothing on it commands anything, and every tag is
still read-only until armed.
A PLC with a restarting runtime or a new program downloaded is picked up again by itself: see the CODESYS driver.
The flow
Section titled “The flow”Three calls, in order, and the first two save nothing.
- Ask.
GET /api/integrationslists every integration and its questions. Each question has a kind (text,number,bool,choiceorsecret), a default, whether it is required, and, when it only matters after another answer,showWhen. A screen is drawn from that and nothing else, which is why a new integration needs no new screen. - Look.
POST /api/integrations/{id}/probetakes the answers, checks them, connects to the real device with the integration’s own driver, and reports what it is and what it has: a suggested name, what it says about itself, notes worth reading, and every point it found as a tag-shaped record with asampleof what it read, so you can compare it with the number on the machine’s own display. - Keep.
POST /api/integrations/{id}/setuptakes the same answers and the names of the points to keep (none named keeps the ones markedsuggested), creates the device and its tags and reloads the runtime. The device is enabled and polling. An integration that can lay out a first dashboard (CODESYS) does when the request has"dashboard": true, and answers with the dashboard’s id.
Setup looks at the device again instead of trusting the probe. A client’s idea
of what it found a minute ago is a claim, and the points are checked against the
device as it is when the device is made. A name that isn’t on it is a 400, not
a point skipped, because somebody asked for it by name.
A setup that fails part way (the device saved, the tags didn’t) removes the
device it just made. A device that already exists is refused with a 400
rather than overwritten: to add points to a device you have, use its Browse and
Import.
Answers are checked before anything is tried
Section titled “Answers are checked before anything is tried”The framework checks every answer against its question before an integration sees it, and reports every problem at once, so a form is fixed once:
- a required question that is blank is “X is required”;
- a number must be a whole number inside the question’s range, a choice must be one of its choices, a bool must be a bool;
- an answer to a question the integration doesn’t ask is refused, not ignored,
because a misspelled
pasworddropped without a word is a device that fails to log in with no hint why; - a secret may not be the
[redacted]placeholder the API shows in place of a stored one. Sending it back would store the placeholder as the password; - a question that isn’t showing (
showWhen) is ignored, and isn’t required.
Credentials are held the way a device’s are: sealed at rest when HotLoop has a sealing key, and hidden from every API response and every error. A probe never saves what it was given.
When the device doesn’t answer
Section titled “When the device doesn’t answer”502, with what went wrong: “could not reach the device: …” when nothing
connected, “connected, but could not list its points: …” when it did and
then didn’t answer. That is the device’s answer to read, not a fault in
HotLoop and not a bad request. A closed port, a wrong community or a firewall
all end up here, and the message is the driver’s own.
Where it sits in the product
Section titled “Where it sits in the product”Probe and setup reach across the network from the HotLoop box, so both need
devices.write, the same as saving a device. Listing needs devices.read.
Every product carries them. The routes are in API.md.
Adding one
Section titled “Adding one”An integration is a Go type in internal/integration with three methods and a
Register call in its init:
Info()says what it is: id, name, the driver’s protocol, how to ask for the address, and the questions;Configure()turns checked answers into an address and the driver’s own configuration block, and refuses what a question can’t express;Discover()reaches the real device and reports what is on it.
The framework refuses, at start, an integration that can’t be a catalog
entry: a duplicate id, a protocol the model doesn’t declare, a question with
no label, a choice with no choices, a default that isn’t a valid answer, or a
showWhen that names a question that isn’t there. A test also holds every
integration to a protocol with a driver compiled in.
An integration doesn’t get merged until a test has had it talk to a real
server for that protocol, running in the test lab (test/services/up.sh).
Where there is no real server to run, there is no integration, and the
roadmap says which ones are waiting on hardware.