Skip to main content

Opto 22 groov I/O

The groov_io driver controls and monitors an Opto 22 groov EPIC or groov RIO modular I/O controller over its local REST API. Each digital channel on the controller's I/O modules becomes a GEM zone: a digital output you turn on and off, or a digital input whose contact state GEM watches and reflects live. Analog channels can be read and written on demand from a macro or the Commands page. It is the general-purpose industrial-I/O front end for jobs where GEM needs to throw a real contact or read a hard wired signal — driving a lighting contactor, latching a lock or gate, switching a power circuit, or monitoring a dry-contact input, flow switch, or level sensor.

The controller talks to the groov box over HTTPS on port 443, authenticating with an API key header. It polls the digital modules you declare and writes channel state with short REST calls under the controller's /api/v1/io/local I/O tree.

groov I/O does not auto-discover its module layout

Unlike GEM's plug-and-play relay boards, this driver has no discovery. You must tell it which module slots are populated and what type each one is, using the Module Types attribute, before it will connect. There is no zone auto-creation either — you create one zone per channel by hand and address it moduleId:channel. See Setup below.

How modules, channels, and zones map

One groov EPIC/RIO controller is one GEM device. Inside it, I/O is organized as modules (the physical slots in the rack) and channels (the individual points on each module). GEM addresses a single point as moduleId:channel — both 0-based:

  • 0:4 — module 0, channel 4
  • 1:0 — module 1, channel 0

Every point you want to control or monitor becomes a zone bound to the device, with its Address set to that moduleId:channel string. The Module Types attribute on the device declares which module slots exist and whether each is a digital or analog module, so the driver knows which ones to poll.

  • Digital output channels accept on / off (and the open / close aliases). on and close close the contact (drive the point true); off and open open it (false).
  • Digital input channels are read-only. The driver polls them and writes the result to the bound zone's state as on (contact true) or off (contact false).
  • Analog channels are read and written on demand with the get_analog_value / set_analog_value commands. They are not polled — GEM does not track analog values in the background (see What is and isn't polled).

Prerequisites

  • A groov EPIC or groov RIO controller on the same LAN as GEM, reachable at a known IP (use a DHCP reservation — the driver addresses the controller by IP).
  • The groov REST API enabled on the controller. Turn it on in the controller's groov Manage interface.
  • An API key with read + write scope, generated in groov Manage. GEM sends it on every request; a key with the wrong scope or a revoked key returns 401 / unauthorized.
  • Outbound HTTPS from the GEM controller to the groov box on port 443 (or whatever port you have the REST API listening on).
  • Know your module layout — which slot holds which kind of module (digital in, digital out, analog in, analog out) and the channel count on each. You will enter this as the Module Types map. If you are unsure, add the device with a best-guess map, then run the get_module_types command against it to read the controller's actual module list back.

Setup

  1. Add the device. Go to System → Devices → Add Device on the Devices page and choose the driver Opto 22 groov I/O. Enter the Controller IP Address and the API Key. Leave HTTPS Port at 443 unless the REST API is on a different port.

  2. Fill in Module Types. This attribute is required — the driver refuses to connect without it. Enter a JSON object mapping each module id (as a string) to its type:

    {"0": "digital_output", "1": "digital_input"}

    Supported types are digital_input, digital_output, analog_input, and analog_output. Save and enable the device.

  3. Create a zone per channel. On the Zones page, add a zone bound to the groov device and set its Address to moduleId:channel (e.g. 0:4). The address field hint shows the same format. Pick the subsystem that matches what the point drives — the subsystem list pre-selects a sensible default (Lights, Power, Garages, or a generic relay subsystem) from the driver's hints, but you choose the right home.

  4. Set Normally Closed where needed. On a zone wired to a normally-closed contact, toggle Normally Closed so the polled state reads the way you expect (a resting-closed contact reports as off, an opened one as on). This affects the reported state only — see Digital control and monitoring.

Reading the module layout back

If you are not certain which slot is which, run the get_module_types command against the device — it queries the controller's local rack and returns the module type list, which you can transcribe into the Module Types JSON. get_channel_names and get_module_config (both take a module_id arg) return the per-channel names and configuration for a module, which helps you confirm channel numbering before you assign zone addresses.

Attributes

Device

AttributeUI labelRequiredTypeDefaultNotes
ipController IP AddressyesstringController LAN IP (DHCP reservation recommended).
api_keyAPI Keyyesstring (secure)groov Manage API key with read + write scope. Stored encrypted.
module_typesModule TypesyesjsonJSON map of module id → type (digital_input, digital_output, analog_input, analog_output). Required — the driver will not connect without it.
portHTTPS Portnoint443Port the groov REST API listens on.
status_intervalStatus Poll Interval (ms)noint1000How often the driver polls declared digital modules. Raise it to cut traffic; lower it for snappier input feedback.

Zone

Each zone carries an Address in the form moduleId:channel (e.g. 0:4). Enter it on the Zones page — the field hint shows the same format.

AttributeUI labelTypeDefaultNotes
normally_closedNormally ClosedboolfalseInvert the reported digital state for a normally-closed contact (closed reads off, open reads on). Does not change the direction of on / off commands.

Commands

Send these from the Commands page, a macro, or a control. When you send a verb to a zone, GEM supplies the zone's Address as the address argument for you — you rarely type it by hand.

Digital control

CommandArgsDescription
onaddressDrive the channel true (close the contact).
offaddressDrive the channel false (open the contact).
closeaddressAlias of on — drive the channel true.
openaddressAlias of off — drive the channel false.
set_digital_stateaddress, stateSet an explicit state. state accepts true / false (or on / off).
get_digital_stateaddressRead one digital channel's state now.

Analog

CommandArgsDescription
get_analog_valueaddressRead one analog channel's value.
set_analog_valueaddress, valueWrite an analog output. value is sent as a floating-point number.
get_module_analog_valuesmodule_idRead all analog values on a module at once.

Diagnostics and discovery

CommandArgsDescription
get_module_typesReturn the controller's local module list — use it to build or verify Module Types.
get_module_configmodule_idReturn one module's configuration.
get_channel_namesmodule_idReturn the channel names for a module.
get_module_digital_valuesmodule_idRead all digital channel states on a module — this is the call the background poller uses.

address is the moduleId:channel string; module_id is just the module number. If you call an analog write without a value, or a digital write without a state, the driver rejects it with a "missing value" / "missing state" error.

Digital control and monitoring

Commands are direct. on and close set the channel true (contact closed); off and open set it false (contact open). That mapping is fixed and does not depend on the zone's subsystem, and it is not flipped by the Normally Closed toggle — Normally Closed only affects how the polled state is reported.

Monitoring is by polling. For every module you declare as digital_input or digital_output in Module Types, the driver reads that module's channel states every Status Poll Interval (default 1000 ms) and writes each channel's state onto the zone whose address matches moduleId:channel:

  • Contact true → zone state on; contact false → zone state off.
  • With Normally Closed enabled on that zone, the reading inverts: true → off, false → on.
  • The zone updates only when the state actually changes, so a static input doesn't churn.
groov zones report on / off literally

Some of GEM's relay drivers re-word a relay's state to fit its subsystem (a contact reads as "open" under Gates but "on" under Lights). This driver does not do that — a monitored groov channel always reports plain on / off, whatever subsystem the zone lives in. If you need the semantic open/closed/locked wording, that is a property of relay drivers that opt into it; groov I/O reports the raw digital state. See Relay semantics for the wider picture.

What is and isn't polled

  • Digital input / digital output modules are polled on the status interval and keep their zones' state live.
  • Analog modules are not polled. You can read and write analog channels on demand with get_analog_value / set_analog_value (and get_module_analog_values), but GEM does not track analog values in the background, so an analog input's value is only as fresh as the last time you queried it. Declaring a module as analog_input / analog_output in Module Types is still correct — it just doesn't start a poll.

Known quirks

  • Module Types is mandatory. With it unset the driver logs a missing-module_types warning and never connects — there is no auto-discovery of the rack layout.
  • Channels are 0-based. Addresses are moduleId:channel with both indexes starting at 0, and the channel must exist on that physical module or the write goes nowhere.
  • The self-signed controller certificate is accepted. The driver connects to the groov box's HTTPS API without validating its certificate, so treat the LAN segment between GEM and the controller as semi-trusted.
  • Normally Closed inverts reporting, not commands. It changes how a monitored channel's state is reported; it does not reverse the direction of an on / off command.
  • Only the local rack is addressed. The driver targets the controller's local I/O (/api/v1/io/local); remote/expansion racks addressed by a different device name are not exposed through the standard zone verbs.

Troubleshooting

SymptomCheck
Driver logs "missing module_types" and never connectsSet the Module Types JSON on the device — it maps each module id to digital_input / digital_output / analog_input / analog_output.
Commands return 401 / unauthorizedThe API key is for the wrong scope or has been revoked. Mint a new key in groov Manage with read + write access and update the API Key attribute.
Zone state doesn't flipThe Address must be moduleId:channel (e.g. 0:4), both 0-based, and the channel must exist on that physical module. Confirm the module is declared in Module Types as a digital type — analog modules are not polled.
Input reads invertedToggle Normally Closed on that zone.
Can't tell which slot is whichRun get_module_types against the device to read the controller's module list, and get_channel_names / get_module_config (with a module_id) to confirm channel numbering.
Analog value looks staleAnalog channels aren't polled — read them on demand with get_analog_value (or get_module_analog_values) each time you need a current reading.
  • Devices — adding the controller and setting its attributes.
  • Zones — addresses, subsystems, and per-verb command routing.
  • Subsystems — where the I/O zones live.
  • Commands — how on / off verbs route to a device.
  • Relay semantics — how digital/relay states map to on/off across the system.