# Chapter 5: Rule Engine programming guide

# Overview

(to be added)

# Enapter Dryer Plugin

# Activation Plugin

[d0a09d] $ configure
[d0a09d] conf # set rule-engine plugin dryer enabled true
[d0a09d] conf # save
[d0a09d] conf # commit
[d0a09d] conf # exit

# Available Actions

Action Description
start-dryer Start dryer command
stop-dryer Stop dryer command

# Expressions Available in Conditions

Expression Description Values
online Device online status boolean
state.value Dryer state one of waiting_for_power, waiting_for_pressure, stopped_by_user, starting, drying_0, cooling_0, switching_0, pressurizing_0, finalizing_0, drying_1, cooling_1, switching_1, pressurizing_1, finalizing_1, leak_input, leak_dryer, error
state.seconds_in_state Number of seconds in current state integer
input_pressure Input pressure (bar) float
input_pressure_avg(10) Input pressure (bar) 10 seconds average float
output_pressure Output pressure (bar) float
output_pressure_avg(10) Output pressure (bar) 10 seconds average float
device:is_running() Whether dryer currently running or not boolean

# Example

[d0a09d] conf # set rule-engine rule 10 condition 10 dryer DR if "not device:is_running() and output_pressure_avg(120) < 30"

# Enapter Electrolyser Plugin

# Activation Plugin

[d0a09d] $ configure
[d0a09d] conf # set rule-engine plugin electrolyser enabled true
[d0a09d] conf # save
[d0a09d] conf # commit
[d0a09d] conf # exit

# Available Actions

Action Description
start-electrolyser Start electrolyser command
stop-electrolyser Stop electrolyser command
start-electrolyser-group Start electrolysers group command
stop-electrolyser-group Stop electrolysers group command

# Expressions Available in Conditions

Expression Description Values
online Device online status boolean
state.value Electrolyser state one of none, power_on, wait_start_comm, wait_power_cond, restart_with_max_press, delay_dc_dc, hydration, ramp_up, steady, ramp_down, purge, heating, error, warning
state.seconds_in_state Number of seconds in current state integer
stack_amp Electrolyser stack amperage float
stack_amp_avg(10) Electrolyser stack amperage 10 seconds average float
stack_volt Electrolyser stack voltage float
stack_volt_avg(10) Electrolyser stack voltage 10 seconds average float
device:is_running() Whether electrolyser currently running or not boolean

# Example

[d0a09d] conf # set rule-engine rule 10 condition 10 electrolyser EL if "online and device:is_running() and state.value == 'steady' or stack_amp_avg(45) > 12.5"

# Plug Power Fuel Cell

# Activation Plugin

[d0a09d] $ configure
[d0a09d] conf # set rule-engine plugin pp-fuel-cell enabled true
[d0a09d] conf # save
[d0a09d] conf # commit
[d0a09d] conf # exit

# Available Actions

Action Description
start-fuel-cell Start Fuel Cell command
stop-fuel-cell Stop Fuel Cell command
start-fuel-cell-group Start Fuel Cell group command
stop-fuel-cell-group Stop Fuel Cell group command

# Expressions Available in Conditions

Expression Description Values
online Device online status boolean
state.value Fuel Cell state one of RUN, STANDBY
state.seconds_in_state Number of seconds in current state integer
volt Fuel Cell DC bus voltage (in volts) float
volt_avg(10) Fuel Cell DC bus voltage (in volts) 10 seconds average float
amp Fuel Cell DC bus amperage (in amps) float
amp_avg(10) Fuel Cell DC bus amperage (in amps) 10 seconds average float
watt Fuel Cell current power output (in watt) float
watt_avg(10) Fuel Cell current power output (in watt) 10 seconds average float
device:is_running() Whether fuel cell currently running or not boolean

# Example

[d0a09d] conf # set rule-engine rule 10 condition 10 fuel-cell FC1 if "state.value == 'RUN' and state.seconds_in_state > 300"

# Victron Multiplus Inverter Plugin

# Activation Plugin

[d0a09d] $ configure
[d0a09d] conf # set rule-engine plugin victron-multiplus enabled true
[d0a09d] conf # save
[d0a09d] conf # commit
[d0a09d] conf # exit

# Expressions Available in Conditions

Expression Description Values
online Device online status boolean
state.value Inverter state one of down, startup, off, device_in_slave_mode, invert_full, invert_half, invert_aes, power_assist, bypass, charge_initializing, charge_bulk, charge_absorption, charge_float, charge_storage, charge_repeated_absorption, charge_forced_absorption, charge_equalise, charge_bulk_stopped
state.seconds_in_state Number of seconds in current state integer
ac_l1_voltage AC L1 Voltage float
ac_l1_voltage_avg(10) AC L1 Voltage 10 seconds average float
ac_l1_amperage AC L1 Amperage float
ac_l1_amperage_avg(10) AC L1 Amperage 10 seconds average float
ac_amperage AC Amperage float
ac_amperage_avg(10) AC Amperage 10 seconds average float
ac_freq AC Frequency float
ac_freq_avg(10) AC Frequency 10 seconds average float
dc_voltage DC Voltage float
dc_voltage_avg(10) DC Voltage 10 seconds average float
dc_amperage DC Amperage float
dc_amperage_avg(10) DC Amperage 10 seconds average float
grid_l1_freq Grid L1 Frequency float
grid_l1_freq_avg(10) Grid L1 Frequency 10 seconds average float
grid_l1_voltage Grid L1 Voltage float
grid_l1_voltage_avg(10) Grid L1 Voltage 10 seconds average float
grid_l1_amperage Grid L1 Amperage float
grid_l1_amperage_avg(10) Grid L1 Amperage 10 seconds average float

# Example

[d0a09d] conf # set rule-engine rule 10 condition 10 victron-multiplus VMP if "dc_voltage_avg(120) < 42 and (state.value == 'invert_full' or state.value == 'invert_half')"

# Enapter Tank Module Plugin

# Activation Plugin

[d0a09d] $ configure
[d0a09d] conf # set rule-engine plugin tank enabled true
[d0a09d] conf # save
[d0a09d] conf # commit
[d0a09d] conf # exit

# Expressions Available in Conditions

Expression Description Values
online Device online status boolean
pressure1 Pressure input #1 value float
pressure1_avg(10) Pressure input #1 10 seconds average float
pressure2 Pressure input #2 value float
pressure2_avg(10) Pressure input #2 10 seconds average float
temp1 Temperature input #1 value float
temp1_avg(10) Temperature input #1 10 seconds average float
temp2 Temperature input #2 value float
temp2_avg(10) Temperature input #2 10 seconds average float

# Example

[d0a09d] conf # set rule-engine rule 10 condition 10 tank TNK1 if "pressure1_avg(120) < 30"

# Gas Sensor Plugin

# Activation Plugin

[d0a09d] $ configure
[d0a09d] conf # set rule-engine plugin gas-sensor enabled true
[d0a09d] conf # save
[d0a09d] conf # commit
[d0a09d] conf # exit

# Expressions Available in Conditions

Expression Description Values
online Device online status boolean
ai1 Analog input #1 value float
ai1_avg(10) Analog input #1 value 10 seconds average float
ai1_avg_with_offset(10, 60) Analog input #1 value 10 seconds average with 60 seconds offset float
ai2 Analog input #2 value float
ai2_avg(10) Analog input #2 value 10 seconds average float
ai2_avg_with_offset(10, 60) Analog input #2 value 10 seconds average with 60 seconds offset float
ai3 Analog input #3 value float
ai3_avg(10) Analog input #3 value 10 seconds average float
ai3_avg_with_offset(10, 60) Analog input #3 value 10 seconds average with 60 seconds offset float
ai4 Analog input #4 value float
ai4_avg(10) Analog input #4 value 10 seconds average float
ai4_avg_with_offset(10, 60) Analog input #4 value 10 seconds average with 60 seconds offset float

# Lua Conditions

Lua conditions can be used for programming complex logic dependent of several devices.

For more convenient work on complex scripts Enapter shell support editing values in Vim (default) or Nano editor. To set preferable editor use following command:

[d0a09d] conf # set shell editor nano

or

[d0a09d] conf # set shell editor vi

To edit value use edit command in configuration mode:

[d0a09d] conf # edit rule-engine rule 10-test condition 10 lua

To exit from Vim editor use :wq<Enter>

Lua condition code block expected to return boolean value.

So the most simple Lua condition will be:

return true

# Multiple Electrolysers and Single Dryer Management Example

[d0a09d] $ conf
[d0a09d] conf # set shell editor nano
[d0a09d] conf # set rule-engine plugin electrolyser enabled true
[d0a09d] conf # set rule-engine plugin dryer enabled true
[d0a09d] conf # save
[d0a09d] conf # commit
[d0a09d] conf # exit
[d0a09d] $ conf
[d0a09d] conf # set rule-engine devices electrolyser EL1 enabled true
[d0a09d] conf # set rule-engine devices electrolyser EL1 power 2400
[d0a09d] conf # set rule-engine devices electrolyser EL2 enabled true
[d0a09d] conf # set rule-engine devices electrolyser EL2 power 2400
[d0a09d] conf # set rule-engine devices dryer DR enabled true
[d0a09d] conf # set rule-engine groups electrolyser ELS device EL1
[d0a09d] conf # set rule-engine groups electrolyser ELS device EL2
[d0a09d] conf # set rule-engine rule 10-dryer-management condition 10 lua "return true"
[d0a09d] conf # edit rule-engine rule 10-dryer-management action 10 lua
  -- find dryer by ID
  local dryer = context:get_device("dryer", "DR")
  -- find electrolysers by group ID
  local electrolysers = context:get_group_devices("electrolyser", "ELS")
  local run_dryer = false

  -- iterate over electrolysers and check status
  for _, el in pairs(electrolysers) do
    local el_state = el.state.value

    log("EL: " .. el.id .. " state: " .. tostring(el_state))

    -- set run dryer flag if one of electrolysers is running
    if el:is_running() then
      run_dryer = true
    end
  end

  if run_dryer then
    log("Starting dryer")
    success = dryer:start()
    if not success then
      log("[ERROR] failed to start dryer dryer")
    end
  else
    log("Stopping dryer")
    success = dryer:stop()
    if not success then
      log("[ERROR] failed to stop dryer")
    end
  end

  return true