- 04 Aug 2020
INDI: The Instrument Neutral Distributed Interface
LBTI software is built on the INDI communication protocol as defined by Elwood Downey. The protocol is defined here
The INDI messaging protocol is based around a "Publish and Subscribe" mechanism. For a more detailed explantion of this design pattern, see here
for a more thorough dicussion. This page will sum up the INDI implementation.
INDI software is made up of "clients" and "drivers" ("servers"). These are programs written to communicate with each other by using a broker, as specified by pub/sub. The broker in the case of INDI is called "indiserver", and all messages are routed through it. Indiserver is also the parent process which starts and stops all INDI drivers running on the local machine, as well as being able to be connected to other indiservers on other machines. For now, we will only focus on the messaging responsibilities of indiserver and how it supports the INDI protocol. For our purposes, clients will tend to be GUIs or terminal programs to control the system, and drivers will be interfaces between the software and the hardware (cameras, motors, sensors, etc.)
Each INDI message can contain either text, numbers, switches, lights, or BLOBS.
- Text: the most generic as it can be any stream of characters.
- Number: any real or floating point type number.
- Switch: This can hold either "On" or "Off", this is the equivalent of "bool".
- Light: An indicator showing either "On" or "Off".
- BLOB: Binary data, used to represent images or files.
These should all be self-explanatory, aside from BLOB. The underlying message format of INDI is XML, and as such, INDI messages must be well-formed XML documents. Since this is a text protocol, binary data can be supported, but in order to prevent the XML parser from failing, the data is encoded using Uuencoding. An introduction to uuencoding can be found here
. A more in-depth discussion on BLOBS will be found in the next section.
As mentioned above, the indiserver starts all the INDI drivers. It does this so it can manage each driver's stdin, stdout, and stderr. Each driver simply sends the INDI messages via stdout, and receives messages via stdin. These come from or are sent to the indiserver which is acting as a broker (or proxy) for the INDI messages, and it sends them to the INDI driver by using these standard channels all processes have. Stderr is also managed by the indiserver, but it is used to send error messages to the indiserver log. What this means, is that these standard communication channels are not used to output information to the world, and there is no command line invocation possible, since the driver is not started from a terminal.
Pub/sub frowns upon polling; messages are sent between clients and drivers only when some state (implemented as a "property") in the driver changes, or when a client is asking about the initial state of the driver. This condition is predisposed on the client first asking (subscribing) for the said state. Below, the types of messages will be enumerated.
INDI Subscription (indiserver left out for clarity)
INDI Publish (indiserver left out for clarity)
INDI Request Update (indiserver left out for clarity)
- A client sends a "GET" so that it can be notified of the initial values for the driver's properties ("DEF") as well as know when those properties change ("SET")
- The client may send an empty "GET" to indicate that it wants to know when any and all properties owned by the driver change.
- The driver will respond with a "DEF" for the requested property (or properties). The property should contain the current state for that value. For example, issuing a "GET" for a temperature sensor property should return that property with the current temperature read from that sensor.
- In keeping with the pub/sub design pattern, once a "GET" has been processed, the client will receive any new updates for that particular property via "SET" messages.
- The terminal program "getindi" is a well-behaved client, and as such issues a "GET" to receive the information about the properties it shows.
- This is the "subcribe" part of the protocol.
- Sent from a driver back to a client as a response to a "GET".
- This property (or series of properties) holds the current state of what information was requested.
- Keep in mind that this may be the only time a client sees this particular information if the driver never has it change.
- A driver will send a "SET" whenever a property has updated information in it.
- Every client which has sent a "GET" regarding this property will receive a "SET" for it.
- This is the "publish" part of the protocol.
- A good example would be a temerature which is rising or falling. A client would send a "GET" and receive the initial temp value, and then subsquently receive a "SET" every time that temperature changes.
- This is sent by a client to a driver; it is a request to change a property. As an example, if a client sends a "NEW" with a motor position, the INDI driver will move the motor.
- When the driver receives the request, it may send back an intitial "Busy" state if the operation will take some time. This is optional.
- It must send back a response to show the client (and any other clients!) that the value has either been updated successfully (state = Ok), or an error has occurred (state=Alert).
- Sent from a driver back to a client to send the notification that a property no longer exists.
- Not used very often.
- Sent from a client to enable the receipt of BLOB data.
- BLOBS are not enabled by default; the client must let the indiserver know it wants to receive them.
- Used for image data.
- A generic message that can be sent from client to driver or vice-versa.
- Can also be sytem wide and not tied to a particular driver or client.
- Only used for informational purposes.
As stated above, these messages are passed between clients and drivers and can potentially be seen by all clients and drivers. On top of this foundation the framework of the LBTI software is built.