Skip to content

NUTController

NUTController is a (client) interface to a Network UPS Tools (NUT) server. Each UPS system published by the NUT server is represented by an entity in Reactor, and its variables and states are presented as attributes on those entities. Using NUTController, you can have Reactor rules react to changes in UPS status and behavior.

Requirements

NUTController requires Reactor build/version 22145 or higher to operate. A NUT server running on a network-accessible host system is also required.

Installation

NUTController is not included in base Reactor distributions. It must be installed separately by downloading the package from the extras subdirectory of the Reactor download server.

Install for Bare-metal Reactor

Not for Docker

These instructions are for users that run Reactor from a bare-metal install: that is, you are not running Reactor in a docker container, you have installed it from a ZIP file. If you are installing this extension for Reactor running in a docker container, please go to the next section.

Once the package file (a ZIP or Gzip'd tar archive) is downloaded:

  1. Create, if it does not already exist, a directory called ext under your Reactor config directory, and go to it:

    cd /path/to/reactor/config
    mkdir ext
    cd ext
    
  2. Unpack the archive (use whichever command is correct for the type of archive downloaded):

    tar xzvf /path/to/NUTController-XXXXX.tar.gz
    # or...
    unzip /path/to/NUTController-XXXXX.zip
    
  3. Run the install script, if it has one (the script will be named install.sh, or install.bat for Windows).

    cd NUTController
    ./install.sh
    

From here, proceed to Configuration below.

Install for Reactor under docker

Once the package file (a ZIP or Gzip'd tar archive) is downloaded:

  1. Create a directory in which to place Reactor's extensions and go to it. This should not be in the same directory as your config and storage directories, or any subdirectory of those. If you have installed other extensions and this directory already exists, just cd to it and go on to the next step.

    cd /path/to/parent/directory
    mkdir reactor-ext
    cd reactor-ext
    
  2. Unpack the archive (use whichever command is correct for the type of archive downloaded):

    tar xzvf /path/to/NUTController-XXXXX.tar.gz
    # or...
    unzip /path/to/NUTController-XXXXX.zip
    
  3. Add a volume bind mount for /opt/reactor/ext to the directory you created in step 1. If you are using docker-compose to manage your Reactor container, that means adding an additional volume line. If you use the docker command line directly to start/stop the container, add another -v option to your command line. Examples for each (marked NEW!) are shown here:

    # For docker-compose, after the /var/reactor line under volumes
    # in your docker-compose.yaml file, add the /opt/reactor/ext
    # line with your directory path on the left side of the ':'
    volumes:
      - /home/username/reactor/data:/var/reactor
      - /home/username/reactor/reactor-ext:/opt/reactor/ext   # NEW!
    
    # For docker on the command line:
    docker run --name reactor -d --restart on-failure -p 8111:8111 -p 8554:8554 \
        -v /home/username/reactor/data:/var/reactor \
        -v /home/username/reactor/reactor-ext:/opt/reactor/ext \   # NEW!
        --mount type=bind,src=/etc/localtime,target=/etc/localtime \
        toggledbits/reactor:latest-amd64
    
  4. Restart the Reactor docker container.

  5. Run the extension's install script if it has one (the script will be named install.sh, or install.bat for Windows). This is best done from inside the docker container (which must be running):

    docker exec -it <container-name> /bin/sh
    cd /opt/reactor/ext/NUTController
    ./install.sh
    exit
    

Note that if the cd /opt/reactor/ext... command fails, your bind mount (step 3) is probably incorrect.

From here, continue to Configuration below.

Configuration

One instance of NUTController is needed for each NUT server you want to connect to. To configure an instance of NUTController:

  1. Make sure your NUT server is running. Also make sure it is configured in netserver mode (in nut.conf), and its LISTEN directive(s) (in upsd.conf) list the IP address of the NUT server host system (i.e. not just localhost, unless Reactor and NUT are running on the same system, in which case localhost is fine). If you're not sure, LISTEN 0.0.0.0 will have the NUT server listen on all host interfaces.
  2. Open your reactor.yaml configuration file on your Reactor host.
  3. In the controllers section, add the following template, substituting your server's IP address:

    controllers:
      - id: nut
        implementation: NUTController
        enabled: true
        config:
          server: 127.0.0.1        # modify the IP address as needed
          #port: 3493              # optional, default shown
          #username: "myuser"      # optional, no user auth if not set (see callout, below)
          #password: "mypassword"  # optional, must be specified if username is used
    

    The configuration lines beginning # are commented out; if you need to use them, remove the # and provide your correct value.

  4. Restart Reactor.

  5. Connect to the Reactor UI using a browser.
  6. In the Entities page, use the controller filter to select your NUT controller instance and display its entities. Each NUT-connected UPS should be shown as a an entity.

Username and Password

It appears that, at the moment, you do not need to set the username and password for NUTController to get UPS states — the NUT server does not require authentication for those queries. There are no operations NUTController can perform at this time that require authentication, so you can safely leave username and password out of your configuration.

Capabilities and Attributes

NUTController UPS entities show the following attributes:

Attribute Type Description
power_source.source string (enum) utility when on mains/utility power, battery when mains/utility has failed and the UPS is supplying power from its battery
battery_power.level real (0.0-1.0) Battery power level (0=empty, 1=full)
battery_power.since timestamp Time when battery power was last reported
battery_maintenance.charging boolean true if the battery is being charged, false otherwise
battery_maintenance.replace boolean true if battery needs to be replaced (depends on UPS functionality and NUT driver for that device; not available on all UPS devices)

In addition, all variables published by NUT are offered as extended attributes on the entity.

The NUTController system entity's sys_system.state attribute is true when the instance has a valid connection to the NUT server, and false when a connection cannot be established. Attributes on UPS entities are not modified by loss of communication (they simply maintain their last known state/value until communication is restored).

Updated: 2023-Jul-29