Capabilities Declaration

The capabilities[] array tells the CeresFlows backend exactly which commands your firmware implements. The backend uses this information to filter compatible sensor and actuator types when the user configures devices on a controller.


How It Is Used

When a controller is registered or discovered, the backend sends an INFO command. The capabilities array in the response is stored and used to:

  • Show only compatible sensor types in the device wizard
  • Warn the user if they try to assign an incompatible sensor to a controller
  • Display the controller’s feature set in the hardware dashboard

Rules

  1. Only list commands you have actually implemented in your firmware’s command router.
  2. Never list a command you have not implemented — the backend will send it and receive ERR_UNKNOWN_CMD, which it treats as a malfunction.
  3. The capability name must exactly match the command string your router handles (case-sensitive, uppercase).

Full Capability List

These are all valid capability strings recognized by CeresFlows:

Capability StringCommandRequires
ANALOGReads analog voltageAnalog-capable pin
DIGITAL_READReads digital pin stateAny digital pin
DIGITAL_WRITEWrites digital pin state + optional TTLAny digital pin with OUTPUT mode
RELAY_SETAlias for DIGITAL_WRITESame as DIGITAL_WRITE
PWM_WRITEWrites PWM duty cyclePWM-capable pin
SERVO_WRITEWrites servo anglePWM-capable pin + Servo library
DHT_READReads DHT11/DHT221 digital pin + pull-up resistor
ONEWIRE_READ_TEMPReads DS18B20 temperature1 digital pin + pull-up resistor
ONEWIRE_SCANScans for DS18B20 addressesSame as ONEWIRE_READ_TEMP
ULTRASONIC_TRIG_ECHOReads HC-SR04 distance2 digital pins
HX711_READReads HX711 load cell2 digital pins
PULSE_COUNTCounts pulses via interruptInterrupt-capable pin
I2C_TRANSFERUniversal I2C transactionI2C hardware (SDA/SCL)
UART_TRANSFERUniversal UART transactionUART or SoftwareSerial
MODBUS_RTUModbus RTU register readUART or SoftwareSerial
SPI_TRANSFERUniversal SPI transactionSPI hardware

Capabilities by Board

const char* CAPABILITIES[] = {
  "ANALOG", "DIGITAL_READ", "DIGITAL_WRITE", "RELAY_SET",
  "PWM_WRITE", "SERVO_WRITE", "DHT_READ", "ONEWIRE_READ_TEMP",
  "ULTRASONIC_TRIG_ECHO", "I2C_TRANSFER", "MODBUS_RTU",
  "UART_TRANSFER", "PULSE_COUNT", "HX711_READ", "ONEWIRE_SCAN", "SPI_TRANSFER"
};
const int CAPABILITIES_COUNT = 16;
// Same as UNO R4 — ESP32 supports all commands
const char* CAPABILITIES[] = {
  "ANALOG", "DIGITAL_READ", "DIGITAL_WRITE", "RELAY_SET",
  "PWM_WRITE", "SERVO_WRITE", "DHT_READ", "ONEWIRE_READ_TEMP",
  "ULTRASONIC_TRIG_ECHO", "I2C_TRANSFER", "MODBUS_RTU",
  "UART_TRANSFER", "PULSE_COUNT", "HX711_READ", "ONEWIRE_SCAN", "SPI_TRANSFER"
};
const int CAPABILITIES_COUNT = 16;
// Remove commands you haven't implemented.
// ESP8266 can support most commands but has 1 analog pin and limited UART.
const char* CAPABILITIES[] = {
  "ANALOG", "DIGITAL_READ", "DIGITAL_WRITE", "RELAY_SET",
  "DHT_READ", "ONEWIRE_READ_TEMP", "ONEWIRE_SCAN",
  "ULTRASONIC_TRIG_ECHO", "I2C_TRANSFER", "UART_TRANSFER",
  "PULSE_COUNT", "HX711_READ", "SPI_TRANSFER"
};
const int CAPABILITIES_COUNT = 13;
// Keep only what fits in 32 KB Flash and 2 KB RAM.
// Bus commands (I2C, UART, Modbus, SPI) require significant RAM for JSON parsing.
// Test your specific combination before declaring them as capabilities.
const char* CAPABILITIES[] = {
  "ANALOG", "DIGITAL_READ", "DIGITAL_WRITE", "RELAY_SET",
  "DHT_READ", "ONEWIRE_READ_TEMP", "ONEWIRE_SCAN",
  "ULTRASONIC_TRIG_ECHO"
};
const int CAPABILITIES_COUNT = 8;

Building the Capabilities JSON String

String buildCapabilitiesJson() {
  String r = "[";
  for (int i = 0; i < CAPABILITIES_COUNT; i++) {
    r += "\""; r += CAPABILITIES[i]; r += "\"";
    if (i < CAPABILITIES_COUNT - 1) r += ",";
  }
  r += "]";
  return r;
}

This function is used in both the INFO response and the HYDROPONICS_DISCOVERY response.