EVA ICS documentation

EVA ICS is a platform for automated control and monitoring systems development, for any needs, from home/office to industrial setups. It is completely free for non-commercial use as well as for commercial, on condition that enterprise integrates it on its own. The product is distributed as a free software and is available under Apache License 2.0.

Automated control systems are facing a new stage of evolution: IoT-devices become interesting for those, who have never dealt with automation, cheap programmable devices become reliable enough for industrial use, commercial solutions move away from old protocols and involve computer networks instead. We do not reform automation – we change the approach: taking the classical technology as a basis, we simplify everything else to the maximum. Automation is simple and available for everyone!

Note

This is the main EVA ICS documentation site. For troubleshooting, firstly check the EVA ICS Knowledge base.

What is EVA

  • Universal controllers for management and monitoring of all your equipment, on the basis of which you can develop your own automation applications easily and quickly.
  • Notification system, that instantly informs applications on current events.
  • Logic Manager programming logic controllers used for automatic data processing and decision-making.
  • EVA JS Framework and SFA Templates, allowing quick development of the interfaces for a specific configuration.

EVA can be installed either partially or fully, it can be scaled up to many servers or all components can be installed onto the only one. The system is designed in such a way, that it can work on any hardware: from fat servers to mini-computers with only one smart card in the “read-only” mode.

Architecture of EVA provides a high scalability: one system can support dozens and even hundreds of thousands of devices through processing events via separate subsystems and collecting all data to a unified database.

The latest EVA ICS version is 3.3.2. CHANGELOG

What you get with EVA

Installation

All you need to install EVA is to download the latest update from https://www.eva-ics.com/, unpack the archive to any folder and everything is almost ready to use.

Note

Each EVA ICS installation (node) can run multiple components. Despite they share node resources, they still act as independent processes and require inter-connection set up.

System Requirements

Important

Before installation, set the proper host name. It will be used to identify node controllers. Changing host name later will require manually removing/appending all static links between EVA ICS controllers.

  • Python version 3 (3.6+)
  • Python virtual environment modules (python3-virtualenv)
  • Linux or UNIX-compatible system
  • For SFA PVT to work with images: libjpeg-dev and libjpeg8-dev (for PIL / pillow installation)
  • realpath (available in all modern Linux distributions)
  • EVA ICS can run on any Linux or UNIX-compatible system, but for the smooth install we recommend Ubuntu or Debian.
  • Install system package libow-dev to let EVA ICS install owfs module.
  • To sync item status between the controllers in different networks - MQTT-server (e.g. mosquitto) or to communicate with other equipment and 3rd party software.

Warning

Installation scripts try to install all required Python modules automatically, but some of them can have problems installing with pip - install can fail or be slow. It’s better to install these modules manually, before running EVA installation scripts. Currently the problems can be expected on ARM systems with:

  • pandas (python3-pandas)
  • cryptography (python3-cryptography)

To let EVA ICS venv use system site modules, read instructions below.

Optional modules (can be disabled in venv configuration):

  • onewire required for 1-Wire via OWFS
  • pymodbus required for Modbus master/slave functions
  • pysnmp required for SNMP client/server functions
  • pillow required for SFA PVT image processing

Important

Make sure host temp directory has enough free space to build required Python modules. You may change temp directory location by setting TMPDIR environment variable.

Using installer

Supported Linux distributions:

  • Debian/Ubuntu/Raspbian
  • Fedora
Automatic and unattended

Install required system packages, setup EVA ICS components:

sudo -s
curl geteva.cc | sh /dev/stdin -a
Customized

Customize API keys:

sudo -s
curl geteva.cc | env MASTERKEY=123 DEFAULTKEY=qwerty sh /dev/stdin -a

More options, interactive setup:

sudo -s
curl geteva.cc -o install.sh
sh install.sh --help

E.g. install required system packages, setup Universal Controller only, use external MQTT server and predefined API keys:

sudo -s
curl geteva.cc | \
    env MASTERKEY=mykey DEFAULTKEY=mydefaultkey sh /dev/stdin \
        --autostart --logrotate --bash-completion \
        -- --auto -p uc --mqtt eva:password@192.168.1.100 --mqtt-announce --mqtt-discovery

Manual installation

Note

If you are going to run any controllers under restricted user account, make sure it has a valid shell set.

Preparing the system

Install required system packages and heavy Python modules from the OS repository. here is an example how to install them on Debian-based Linux (i.e. Ubuntu):

apt install -y curl gcc python3 python3-dev python3-virtualenv python3-distutils jq libow-dev libjpeg-dev libjpeg8-dev
Configuring MQTT broker

MQTT broker is used when EVA ICS controllers are located in different networks and can not exchange data with P2P connections.

Note

Starting from EVA ICS 3.2.3, MQTT broker for inter-connection of controllers which run on a single host/network is no longer required.

If EVA ICS node is already set up without MQTT configuration, you can add it later with easy-setup or manually, using eva ns command.

Installing local MQTT server

If you plan to use local MQTT server, here is an example how to install mosquitto MQTT server on Debian-based Linux (i.e. Ubuntu):

apt install -y mosquitto
# stop mosquitto
/etc/init.d/mosquitto stop
# let the server listen to localhost only
echo "bind_address 127.0.0.1" >> /etc/mosquitto/mosquitto.conf
# start mosquitto back
/etc/init.d/mosquitto start
# make sure mosquitto is running
ps auxw|grep mosquitto

Options for EVA ICS:

  • MQTT host: localhost
  • MQTT port: 1883 (default)
  • MQTT user, password: leave empty
  • MQTT space: leave empty
  • MQTT SSL: leave empty (answer ‘n’ if using easy-setup)
Cloud service provider as MQTT broker

Note

Cloud IoT services provide restricted broker functionality and don’t guarantee event/message ordering. This means some state messages between controllers may be lost (discarded by controller core if newer message with the same topic is already received).

Downloading and extracting EVA ICS distribution

Go to EVA ICS website, download most recent distribution and unpack it e.g. to /opt/eva:

cd /opt
curl https://get.eva-ics.com/3.x.x/stable/eva-3.x.x-xxxxxxxxxx.tgz -o eva.tgz
tar xzvf eva.tgz
mv eva-3.x.x eva
cd eva
Customizing Python virtual environment

Starting from 3.2.1, EVA ICS uses Python virtual environment (venv). This makes software installation more stable, as it uses only tested versions of 3rd party libraries.

EVA ICS installation script automatically creates Python virtual environment in ./python3 folder. It can be customized/recreated later manually, using command:

./install/build-venv

or

eva feature setup venv

If you want to rebuild venv from scratch, delete python3 folder completely.

On some systems (e.g. ARM-based computers) venv installation can be tricky: you can expect slow installation time or problems with some heavy modules (e.g. pandas, cryptography).

To solve this:

  • If you already run the installation and it has failed, delete ./python3 folder.

  • Go to ./etc folder, copy venv-dist to venv and customize virtual environment options.

    • USE_SYSTEM_PIP=1 allows to use system-installed pip3 (apt-get install python3-pip) in case installation script has a problems downloading / installing it.
    • PYTHON=python3 here you may specify custom Python executable.
    • SYSTEM_SITE_PACKAGES=1 virtual environment will use system site packages if their versions match with requested.
    • SKIP here you can specify the packages (in quotes, space separated), which should be skipped (e.g. pandas cryptography and install it with apt-get install python3-pandas python3-cryptography instead). To let venv use system package, SYSTEM_SITE_PACKAGES=1 should also be present.
    • EXTRA extra modules to install, e.g. required by PHIs, used by logic macros or macro extensions etc.
    • PIP_EXTRA_OPTIONS specify extra options for pip3, e.g. -v for verbose installation.

Note

Customize venv only if you have serious problems installing EVA ICS with default options, as the system may became unstable when versions of 3rd party libraries are different from tested.

Options, specified in ./etc/venv are also used by EVA ICS update scripts, which check/rebuild venv on every system update.

Installing

Warning

If you want to run some components under restricted users, create var and log folders in EVA installation dir and make sure the restricted users have an access to these folders before running easy-setup. If you’ve customized ini files in etc, make sure the restricted user has an access to both <component>.ini and <component>_apikeys.ini.

If you want to make some initial customization, e.g. name the controllers different from the host name, make changes in etc/uc.ini, etc/lm.ini and etc/sfa.ini configs first.

  • For the interactive setup, run ./easy-setup in EVA folder and follow the instructions.
  • For the automatic setup, run ./easy-setup -h in EVA folder and choose the installation type.

Setup log rotation by placing etc/logrotate.d/eva-* files to /etc/logrotate.d system folder. Correct the paths to EVA files if necessary.

cp ./etc/logrotate.d/eva-* /etc/logrotate.d/

Setup automatic launch at boot time by placing EVADIR/sbin/eva-control start command into system startup e.g. either to /etc/rc.local on System V, or for systems with systemd (all modern Linux distributions):

cp ./etc/systemd/eva-ics.service /etc/systemd/system/
systemctl enable eva-ics
Unicode

EVA ICS supports unicode out-of-the-box. If your system has problems, rebuild locales and then restart EVA ICS controllers:

sudo dpkg-reconfigure locales
sudo eva server restart

Updating

Warning

Before updating from the previous version, read update manifest.

Using EVA Shell
  • Backup everything in system shell
  • Launch EVA Shell (/opt/eva/bin/eva-shell or eva -I)
  • Backup configuration (type backup save command in EVA Shell)
  • Type update command in EVA Shell

Note

EVA ICS repository URL has been changed to https://get.eva-ics.com. If you’ve got “Update completed” message but update process hasn’t even been started, try executing update command specifying EVA ICS repository directly:

update -u https://get.eva-ics.com

Using system shell
  • Backup everything
  • Run the following command:
curl -s <UPDATE_SCRIPT_URL> | bash /dev/stdin
#e.g.
#curl -s https://get.eva-ics.com/3.3.2/stable/update.sh | bash /dev/stdin
  • If updating from 3.0.2 or below, you may also want to enable controller watchdog (copy etc/watchdog-dist to etc/watchdog and edit the options if required)

Note

The system downgrade is officially not supported and not recommended.

With a pre-downloaded tarball

Put update.sh and the new version tarball to EVA ICS root directory (/opt/eva). Run the update:

./update.sh

The script will use tarball located in EVA ICS directory. If the required version tarball file doesn’t exists, it will be downloaded.

To prepare Python venv and explore new version files (e.g. may be required for the offline updating), run

env CHECK_ONLY=1 bash update-xxxxxxx.sh

The script will exit after preparing the virtual environment. The new version files will be kept in _update directory.

Intermediate versions

It is usually absolutely safe to update old EVA ICS installations to newer version without applying all intermediate updates.

However, it is highly recommended to read update manifests for all skipped versions and combine before / after update instructions.

Moving to another folder

EVA ICS doesn’t depend on any system paths, this allows to easy rename or move its folder or clone the installation. Just do the following:

  • stop EVA ICS (./sbin/eva-control stop)
  • rename, move or copy EVA ICS folder
  • if you’ve copied the folder, edit configuration files to make sure components use different ports and/or interfaces
  • start EVA ICS back (./sbin/eva-control start)
  • correct logrotate and on-boot startup paths

Setting up additional features

Some optional features require installing additional modules and system libraries and putting the proper settings in EVA ICS configuration files.

This process can be automated with “eva feature” command, which provides small code snippets to quickly setup or remove a chosen feature.

For example, to setup net-snmp library (speeds up some supported SNMP PHI modules), type:

eva feature setup netsnmp

Full list of feature snippets can be obtained with command:

eva feature list-available

Watchdog

Watchdog process is started automatically for each EVA controller and tests it with the specified interval. Controller should respond to API call test within the specified API timeout or it is forcibly restarted.

Watchdog configuration is located in file etc/watchdog and has the following params:

  • WATCHDOG_INTERVAL checking frequency (default: 30 sec)
  • WATCHDOG_MAX_TIMEOUT maximum API timeout (default: 5 sec)
  • WATCHDOG_DUMP if the controller is not responding, try to create crash dump before restarting (default: no).

How to assign IDs to items

All system items including macros have their own ids. Item id should be unique within one server in simple layout. When using enterprise layout, it is possible for items to have the same id in different groups, however full item id (group/id) should be always unique within one controller.

Note

Before adding items, consider what kind of layout you want to use: simple or enterprise

Starting from 3.2.0, the default item layout is enterprise. The simple layout is deprecated.

Item groups can coincide and often it is convenient to make them similar: for example, if you set groups=security/# in API key config file, you will allow the key to access all the items in the security group and its subgroups regardless of whether it is macro, sensor or logic variable. To set access to a group of particular items, use oids, e.g. groups=sensor:security/#.

This does not apply to decision rules and macros: a unique id is generated for each rule automatically, macro id should be always unique.

Note

The triple underline (___) is used by system and should not be used in item IDs or groups.

Cloud setup

Configuring LM and SFA as primary

Logic Manager and SCADA Final Aggregator nodes can monitor and control items on different nodes. Universal Controller instances can be connected to both, while LM PLC instances can be connected to SFA only.

The components can be connected to each other either P2P, via HTTP or via MQTT. Usually in production setups, MQTT is the most secure and recommended way, unless for components running on the localhost.

On the primary node (the node you want to connect other nodes to), MQTT notifier can be configured either with “easy-setup” or manually. Let’s manually configure MQTT notifier for SFA, with automatic discovery feature:

eva -I # go interactive
ns sfa
create eva_1 mqtt:MQTT_HOST # set login/password/SSL if required
set eva_1 discovery_enabled 1
test eva_1 # test should pass
enable eva_1
server restart

After restart, SFA is ready to accept cloud member controllers.

Configuring UC and LM PLC as secondaries

To automatically connect controllers from the secondary node, they must have the same “default” API key. So, secondary node installation should look like:

sudo -s
curl geteva.cc | env DEFAULTKEY=qwerty sh /dev/stdin -a

Setting the same master key is insecure and not recommended unless all nodes are in absolutely trusted environment.

The local components’ default key can be quickly changed later with a command:

eva feature setup default_key key=NEW_SECRET_DEFAULT_KEY

Automatic default cloud configuration for the local UC and LM PLC instances:

eva feature setup default_cloud mqtt=user:password@192.168.1.12

Manual MQTT notifier configuration (e.g. for UC):

eva -I # go interactive
ns uc
create eva_1 mqtt:MQTT_HOST # set login/password/SSL if required
set eva_1 announce_interval 30 # announce itself every 30 seconds
set eva_1 api_enabled 1 # accept API calls via MQTT
subscribe server eva_1 # subscribe to server events
subscribe state eva_1 -g '#' # subscribe to item states from all groups
test eva_1 # test should pass
enable eva_1
server restart

After restart, the controller will be seen in connected LM PLC and SFA as “dynamic”. That means the controller record disappears after each restart. To set controller connection permanent, set its property “static” to “true” (or “1”):

eva sfa controller set uc/ucnode1 static 1 -y

The secondary controller is also set automatically as static, when the primary one is configured as a Cloud manager and the secondary’s property “masterkey” is set.

Cloud manager

A primary SCADA Final Aggregator instance is called cloud manager. There can be more than one Cloud manager in the cloud, having different secondary controllers with different permissions connected.

The cloud manager (enabled by default in etc/sfa.ini section “cloud”, option “cloud_manager = yes”), provides two features:

  • The cloud manager interface is enabled on SFA node at http://SFA_IP:SFA_PORT/cloudmanager/ (the default port is 8828).
  • SFA can set “masterkey” property for secondary controllers collected. This allows SFA to send them managing and advanced control commands.

Cloud manager allows to manage the whole cloud from the one node. Cloud manager is required for IaC and deployment.

Master key for components of a specified node connected can be automatically set with a command:

eva feature setup node_masterkey node=plant1,key=NODE_MASTER_KEY
Cloud updates

A command, run on Cloud manager node:

eva sfa cloud update

allows to run updates on all nodes connected.

  • Despite EVA ICS never applies update unless the system is checked and ready, the cloud update should be used with extremely caution in production setups.
  • All nodes should have either the Internet connection or a valid local mirror set up.
  • The nodes are always updated to the latest EVA ICS version available, so if your setup requires particular versions for all of them, consider using the local mirror.
  • As industrial computers may be slow and controllers may be busy, sometimes “cloud update” could produce false warnings and errors, e.g. when it expects a remote controller to already have a new version installed, while it was not even shot down for update yet. It is recommended to play with “–shutdown-delay” and “–check-timeout” command options to find the best combination for your setup.

Log file customization

Perform these on the installed Python modules to avoid any extra information in logs:

  • dist-packages/ws4py/websocket.py and dist-packages/ws4py/manager.py - replace all logger.error calls to logger.info

  • dist-packages/urllib3/connectionpool.py - if you set up the controllers to bypass SSL verifications (don’t do this on production!), remove or comment

    if not conn.is_verified:warnings.warn((….

Using NGINX as a frontend for SFA interface

Note

To properly log IP addresses of the requests, make sure the front-end sets X-Real-IP header and set [webapi]/x_real_ip=yes option in etc/sfa.ini configuration file.

External authentication

Suppose NGINX operates on 8443 port with SSL, and SCADA Final Aggregator - without SSL. Let’s make the task even more complicated: let NGINX receive the request not directly, but via port forwarding from the router listening on an external domain (i.e. port 35200).

Additionally, we want to authorize:

  • by IP address or
  • basic auth by username/password or
  • by cookie-token (required for EVA Android Client since it passes basic auth only when the server is requested for the first time)

The server should allow access upon the authorization of any type.

Our final config for all of this should look like:

map $cookie_letmein $eva_hascookie {
  "STRONGSECRETRANDOMTOKEN" "yes";
  default           "no";
}

geo $eva_ip_based {
  192.168.1.0/24 "yes"; # our internal network
  default        "no";
}

map $eva_hascookie$eva_ip_based $eva_authentication {
  "yesyes" "off"; # cookie and IP matched - OK
  "yesno"  "off"; # cookie matched, IP did not - OK
  "noyes"  "off"; # cookie did not match, IP did - OK
  default  "?"; # everything else - demand the password
}

upstream eva-sfa {
        server 127.0.0.1:8828;
}

server {
    listen 192.168.1.1:8443;
    server_name  eva;
    ssl                  on;
    ssl_certificate /opt/eva/etc/eva.crt;
    ssl_certificate_key /opt/eva/etc/eva.key;
    ssl_session_timeout  1m;

    # proxy for HTTP
    location / {
        auth_basic $eva_authentication;
        auth_basic_user_file /opt/eva/etc/htpasswd;
        add_header Set-Cookie "letmein=STRONGSECRETRANDOMTOKEN;path=/";
        proxy_buffers 16 16k;
        proxy_buffer_size 16k;
        proxy_busy_buffers_size 240k;
        proxy_pass http://eva-sfa;
        # a few variables for backend, though in fact EVA requires X-Real-IP only
        proxy_set_header X-Host $host;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Frontend "nginx";
        proxy_redirect http://internal.eva.domain/ui/ https://external.eva.domain:35200/ui/;
    }

    # proxy for WebSocket
    location /ws {
        auth_basic $eva_authentication;
        auth_basic_user_file /opt/eva3/etc/htpasswd;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_buffers 16 16k;
        proxy_buffer_size 16k;
        proxy_busy_buffers_size 240k;
        proxy_pass http://eva-sfa;
        proxy_set_header X-Host $host;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Frontend "nginx";
    }
}
Using HTTP basic auth for EVA ICS authentication

The following example demonstrates how to use basic authentication and automatically log in user into SFA UI.

Firstly, set user_hook option in ./etc/sfa.ini, this will allow EVA ICS to sync htpasswd file with SFA users (make sure htpasswd program is installed as well).

[server]
.......
user_hook = /opt/eva/xbin/htpasswd.sh /opt/eva/etc/htpasswd

Then, front-end config (e.g. for NGINX) should look like:

upstream eva-sfa {
        server 127.0.0.1:8828;
    }

server {
    listen 80 default_server;

    location / {
        auth_basic $eva_authentication;
        auth_basic_user_file /opt/eva/etc/htpasswd;
        rewrite ^/pvt/(.+)$ /pvt?f=$1 last;
        proxy_buffers 16 16k;
        proxy_buffer_size 16k;
        proxy_busy_buffers_size 240k;
        proxy_pass http://eva-sfa;
        proxy_set_header X-Host $host;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto http;
        proxy_set_header X-Port $server_port;
        proxy_set_header X-Frontend "nginx";
    }

    location /ws {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_buffering off;
        proxy_pass http://eva-sfa;
        proxy_set_header X-Host $host;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto http;
        proxy_set_header X-Port $server_port;
        proxy_set_header X-Frontend "nginx";
    }
}

With such setup, EVA JS Framework-based interface doesn’t perform any authentication, $eva.start() function is called as soon as UI is loaded. API method login called by framework function will automatically log in user using basic authentication credentials provided to front-end server.

Serving local mirror

If secondary nodes have unstable, slow or no Internet connection, the local mirror can be configured. The mirror can be hosted by nodes, where SCADA Final Aggregator is set up. The SFA node, which hosts the mirror, must have the Internet connection.

The mirror hosts both EVA ICS distribution and all required Python modules + their dependencies.

After creation / update, the mirror hosts EVA ICS version / build, which the primary node has got. It is possible to host the mirror for a single version only.

For the secondary nodes with the Internet connection, using mirrors is not required.

Installing

The mirror is automatically created with a command:

eva mirror update

The same command is also used to update mirror files.

Note

If the mirror wasn’t used before, the local SFA controller must be restarted to serve the mirror directory:

eva sfa server restart

The mirror should be updated every time after the host node is update. There is also “-M” flag for “eva update” command to perform the mirror update automatically.

Configuring mirror

The local mirror duplicates settings from “etc/venv”. Modules from “SKIP” section are not mirrored, modules from “EXTRA” section are included.

This means if any node uses extra Python modules, it is better to include them in “EXTRA” section of “etc/venv” of the node the mirror is configured on.

Note

After adding extra modules, update mirror with “eva mirror update” command.

If secondary nodes have different Python version than the mirror node, put Python versions (comma-separated) into “etc/eva_shell.ini” before creating / updating the mirror:

[update]
mirror_extra_python_versions = 3.7, 3.9

This will ask “mirror update” to download binary modules for the specified Python versions as well.

Configuring secondary nodes

After updating, EVA shell tries to determine the local SFA IP address / port and automatically gives configuration instructions. In complicated setups, IP/port may differ and need to be corrected manually.

Note

The mirror can be used only by secondary nodes with the same CPU architecture.

If the mirror is set up properly, the following url should display a web page with EVA ICS version and build:

http://<SFA_IP>:<PORT>/mirror/
Automatic setup

On secondary node, type:

eva mirror set http://<SFA_IP>:<PORT>/mirror/

Note that the above command overrides PIP_EXTRA_OPTIONS in etc/venv.

To switch back to the default EVA ICS and PyPi mirrors, type:

eva mirror set default
Manual setup
Setting up PyPi mirror location

On secondary nodes, open “etc/venv” file and add PIP_EXTRA_OPTIONS field, as given by mirror update command. If the field already exists, merge existing options with the new:

PIP_EXTRA_OPTIONS=”-i http://<SFA_IP>:<PORT>/mirror/pypi/local –trusted-host <SFA_IP>”
Setting up EVA ICS repository location

Secondary nodes must to be updated with “-u http://<SFA_IP>:<PORT>/mirror/eva” extra option for “eva update” command.

It is also possible to configure the default repository location, by editing the file “etc/eva_shell.ini” (copy it from eva-shell.ini-dist, if doesn’t exists), section “update”, field “url”:

[update]
url = http://<SFA_IP>:<PORT>/mirror/eva
Removing

Remove “mirror” in EVA ICS directory:

rm -rf /opt/eva/mirror

Optionally, restart the local SFA instance after.

EVA ICS CHANGELOG

3.3.2 (2021-03-01)

Common
  • RedHat Enterprise Linux 8 is now officially supported
  • fix: hosts_allow / hosts_assign in JRPC calls
  • fix: cmd wait delay
  • fix: allow ACL OID groups without masks
  • fix: test command don’t report number of active threads any more for API keys without “sysfunc” permission
  • fix: JSON logging
  • fix: improved stability of controller pools
  • deprecated: RESTful and direct API, including CS_EVENT_API in Core scripts
  • 1-Wire OWFS libraries are now optional by default
  • Python 3.9 support
  • local mirror feature (mirroring EVA ICS repo and PyPi)
  • packages deployment
  • “feature setup/remove” - execute common setup tasks with a single command from EVA shell.
  • “value” field in state and history databases increased to 8192 bytes
  • cmd API function accepts args as a list
  • cmd API function accepts STDIN data
  • xc/cmd moved to runtime
  • file get/put functions support of binary data
  • install option “–skip-venv”. “–skip-check” no longer skips venv building
  • deep code audit and tons of bug fixes
  • Core scripts:
    • new event CS_EVENT_SYSTEM (invoked on startup / shutdown)
    • new event CS_EVENT_RPC (replaces deprecated CS_EVENT_API)
    • new event CS_EVENT_PERIODIC
    • logger object
  • Core Plugins API v2, new functions:
    • create_db_engine
    • format_db_uri
    • get_thread_local
    • has_thread_local
    • set_thread_local
    • clear_thread_local
    • sendmail
  • “set_user_password” SYS API function now allows logged in users to change their passwords
  • “list_tokens”/”drop_tokens” API functions
  • state_history API function can return data for disconnected / deleted items
  • new argument for state_history: z (time zone)
  • update with pre-downloaded tarballs
  • mailer feature available in all controller types (used by core plugins)
  • “cdata” (custom data) API key field
  • “file_put” method automatically creates required directories
  • “shutdown_core” method now executes background shutdown, plus has got an extra option “t” to specify shutdown delay (useful for MQTT API call)
  • “import_module” function in cloud deployment and device template files
  • “history” CLI command bar charts output
  • “watch” CLI command
  • “slog” CLI command (displays state log)
  • JSON RPC additionally accepts requests to the root URI (required by some clients), accepts and trying to fix malformed requests
  • JSON RPC API via HTTP GET
  • Active Directory credentials caching
  • user ACL combining
  • items_deny / groups_deny key ACL properties
  • Read-only mode for tokens, “set_token_readonly” API function
  • MQTT notifiers: ping interval to auto-restore connection
  • MQTT notifiers: subscribe_all option
  • db notifiers: simple cleaning
  • signed releases
UC
  • fix: Modbus/UDP (server) packet processing
  • fix: Modbus serial custom byte size
  • fix: update_if_action logic
  • deprecated: old format of device templates
  • deprecated: multi-update scripts
  • deprecated: direct eva.uc.modbus import in Modbus PHIs
  • deprecated: direct eva.uc.owfs import in OWFS PHIs
  • data pullers
  • DriverAPI v10: Modbus and OWFS helper tools
  • UC API: new function “state_log”
  • auto_off unit state processor can be cancelled / modified while running
  • “server cleanup” CLI command (cleans state db)
  • new device template format (equal to IaC deploy)
  • default timeout for Modbus / OWFS reduced to 1s to avoid critical events
  • unit MQTT control / update commands can be sent in JSON
  • strict device deployment files schema check (new format only)
  • Modbus virtual port API methods and CLI data types (u16, i16, u32, i32, u64, i64, f64) and bit getters / setters
LM PLC
  • fix: “out” variable is now correctly set if macro raises an exception
  • new config option “plc/use_core_pool”
  • LM API: new function “state_log”
  • LVar variable logic: normal (default) or simple
  • SSL, TLS and SMTP auth support for mailer
  • macro function “cmd”: new argument “stdin_data”
  • macro function “sha256sum”
  • macro function “get_directory”
  • decision rules prop “for_prop_bit” to check individual bits
  • CLI/API option to auto-enable created rules/jobs
  • CLI: quick creation of rules with no condition
  • LVar deletion by group (“destroy_lvar” API method and CLI)
  • Cache remote state for LM PLC items
SFA
  • SFA API: new function “state_log”
  • PVT serving as /pvt/path/to/file
  • File uploads
  • connected controllers in “test” API method ($eva.server_info.connected in EVA JS Framework)
  • data serve as locale support
  • cloud deploy: “status” and “value” props in deployment files
  • cloud deploy: trigger item update after deployment
  • cloud deploy: module uploads and binary files support
  • cloud deploy: skip busy drivers/PHIs during undeployment
  • cloud deploy: skip existing items during deployment (optionally)
  • cloud deploy: local functions (“sleep”, “system”)
  • cloud deploy: local cloud manager API calls and “local” controller section
  • cloud deploy: file masks in upload-remote
  • cloud deploy: accepts deployment YAML from STDIN
  • cloud deploy: custom before/after deploy timeouts
  • cloud deploy: API keys and local user accounts deployment
  • strict device deployment files schema check
  • cloud updates

3.3.1 (2020-08-26)

Common
  • fix: auth tokens are now always correctly destroyed at logout
  • new generic extension engine: restarting controller after PHI, LPI & LM PLC Ext module updates is no longer necessary (just load the new module)
  • “interval” notifier property allows to schedule item state telemetry notifications with the specified time interval.
  • MS Active Directory authentication support
  • custom primary log formats (e.g. JSON logs)
  • extended API logging, ACI (API Call Info) core object, “api_log_get” SYS API function
  • Core plug-ins
  • JSON notifiers “list” method to send all data in list format
UC
  • Added “enable” flag in API and CLI to enable unit actions / sensor updates right after creation.
  • Driver API 9: PHI & LPI mods config validation, Ethernet/IP client helper
LM PLC
  • Extension API 7: config validation
SFA
  • supervisor features: API lock/unlock, broadcast messages
  • SFA templates “get_aci” and “import_module” functions
  • before/after deploy API calls can be skipped in case of failure

3.3.0 (2020-02-05)

Common
  • Faster node interconnect protocol (via msgpack)
  • MQTT inter-connect API encryption strength increased to AES256
  • Core workers are now async to improve system performance
  • Controller auto-discovery in local network via UPnP
  • Core scripts
UC
  • Fixed PHI update timers
  • push_phi_state API method
  • Driver API 8: timeout helper, PHI state push
  • item “update_delay” property is removed
LM
  • Fixed cycle timers. As new cycle algorithm has near 100% precision, “avg” is not reported any longer. “value” field in API response is removed as well.
  • Extension API v6: persistent data storage

3.2.5 (2019-10-03)

Common
  • Google Cloud IoT Core support
  • fix: startup timeouts
LM PLC
  • Rule chill-out logic corrected
Cloud manager
  • First public beta

3.2.4 (2019-07-30)

Common
  • Core and controller interconnect stability improvements
  • IOTE cloud support
  • InfluxDB integration
  • Prometheus integration
  • Logging to syslog
  • Autocompletion files for ZSH
  • server events
  • CLI edit command for controller server config
UC
  • Driver API 7: shared namespaces
LM PLC
  • Direct use of macro functions (as @function)
  • rule, job and cycle creation with human readable input
SFA
  • edit ui / edit pvt commands in EVA shell

3.2.3 (2019-06-24)

Common
  • MQTT server is not required anymore for local host/network installations, controllers can exchange information in real-time via P2P sockets (turned on automatically if MQTT server for controller is not specified).
  • state_history method can now return chart image (SVG/PNG)
UC
  • get_phi_ports API method - get ports of loaded PHI
  • phi_discover API method - search for equipment supported by PHI module
  • Modbus values reported to UC slave can now be automatically converted to signed and divided (or multiplied).
LM PLC
  • set_job_prop macro function
  • cycle can now run macros with args and kwargs
SFA
  • easy-setup now creates default user (operator)
  • “as” parameter for .json and .yml files changes their format on the flow
  • JS SFA Framework is now deprecated. Use EVA JS Framework instead: https://github.com/alttch/eva-js-framework

3.2.2 (2019-05-21)

UC
  • Driver API 5: “unload” method, unit values in PHIs.
LM PLC
  • scheduled jobs
SFA
  • evaHI integration
  • transparent authentication on secondary UI pages

3.2.1 (2019-04-16)

Common
  • fixes: small fixes in CLI
  • fixes: code refactoring, performance optimization
  • EVA ICS now loads 3rd party libraries from virtualenv which increases system stability as only tested version of libraries are used.
  • Support for AWS IoT
  • Modbus slave register monitoring functions
  • increment/decrement functions for lvars and shared macro variables
  • read-only permissions for API keys

3.2.0 (2019-04-02)

Common
  • Core, API and CLI performance improvements
  • fixes: correct backup/restore if configuration folders are symlinks
  • fixes: correct restore if –runtime flag is specified
  • fixes: LM PLC locking problems
  • notifier performance improvements
  • CLI improvements
  • private Cloud support (nodes run API calls via MQTT)
  • automatic node discovery
  • license changed to Apache License 2.0
  • new SYS API function: shutdown_core
  • controller/node autodiscovery
  • enterprise layout is now default item layout
  • using item ids in API key properties is not allowed any longer in enterprise layout, item oid (type:group/id) must always be specified
  • X-Auth-Key header authorization support
  • JSON RPC 2.0 API
  • JSON notifiers will send JSON RPC 2.0 notifications to the target uri, if method param is set
  • RESTful API
  • API session tokens
  • Database support for MySQL and PostgreSQL
  • supervisord support
UC
  • warning: API function set_driver renamed to assign_driver
  • new API functions: list_device_tpl, set_driver_prop, set_phi_prop
  • 1-Wire OWFS support (virtual buses, PHIs), OWFS API functions
  • Modbus slave support
  • Driver API v4
LM PLC
  • new API functions: enable_controller, disable_controller, matest_controller, set_ext_prop
  • kwargs in macros (kwargs dict, plus all keyword arguments are available as variables)
  • set_rule_prop now accepts “condition” and “for_oid”
  • cycles, cycle control API and macro functions
  • removed deprecated dm_rule* ACL
  • removed deprecated get/post functions (use requests.get/post instead)
  • Extension API v4
SFA
  • new API functions: enable_controller, disable_controller, list_cycles
  • SFA framework: code optimization, cycle states (warning: some functions are incompatible with previous version, use eva_sfa.3.1.js library or call the functions in new format only, look UPDATE.rst for more info)
  • SFA framework: data exchange optimization with eva_sfa_state_updates variable
  • removed deprecated dm_rule* ACL and rule control functions
  • SFA templates: request now contains full request object
  • SFA templates: new function api_call (call any SFA API method)
Deprecated (will be removed in 3.3.0)
  • macro “argv” variable (replaced with “args”)
  • PHP API client no longer supported (use JSON RPC)
  • removed deprecated HTTP/POST and HTTP/GET notifiers

3.1.1 (2018-10-22)

Common
  • fixes: interactive prompt behavior
  • fixes: API client libs check result of “phi_test” and “phi_exec” functions
  • history for interactive shell mode (to turn off set EVA_CLI_DISABLE_HISTORY=1 system environment variable)
  • new management CLI: eva-shell (interactive by default)
  • backup/restore operations (with eva-shell)
  • dynamic API key management via CLI and API
UC
  • fixes: device commands in enterprise layout
  • performance improvements
  • “update” command without params starts item passive update
  • batch commands in UDP API (separated with new line)
  • encryption and authentication in UDP API
  • custom packet handlers in UDP API
  • new API function: “test_controller”, detailed info in “list controllers”
  • MQTT tools for PHIs
  • test-phi CLI tool
LM PLC
  • fixes: double quoted macro arguments in DM rules
  • fixes: gain param in “tts” and “audio” extensions
  • “action_toggle” macro func, “toggle” acts as an alias for unit oids
  • “shared” and “value” macro funcs default return values
  • new API function: “test_controller”, detailed info in “list controllers”
  • new LPI: usp (unit single port)
  • test-ext CLI tool
SFA
  • new API function: “test_controller”, detailed info in “list controllers”
  • SFA framework fixes and improvements

3.1.0 (2018-09-01)

UC drivers, device templates, state history, charts and other new features

Core
  • working with locks now require allow=lock apikey permission
  • new notifier type: db, used to store item state history
  • SYS API functions: notifiers, enable_notifier, disable_notifier. the enable/disable API functions change notifier status only temporary, until the controller is restarted
  • MQTT SSL support
  • JSON notifiers. GET/POST notifiers are marked as deprecated and should not be used any more.
  • exec function (cmd, run) string arguments split with ‘ ‘ now support the spaces inside (e.g. ‘this is “third argument”’)
UC
  • new uc-cmd cli
  • old uc-cmd renamed to uc-api
  • UC drivers: logical to physical (LPI) and physical (PHI) interfaces
  • native Modbus support (drivers only)
  • device templates
  • new function “state_history” in UC API
  • EVA_ITEM_OID var in the environment of UC scripts
  • action status label (case insensitive) may be used instead of number, if the label is not defined, API returns 404 error
  • new key permission: “device”, allows calling device management functions.
  • uc-tpl device template validator and generator (alpha)
  • unit and sensor items now have physical location. If location is specified as coordinates (x:y or x:y:z), loc_x, loc_y and loc_z props become available
  • UC EI now should be enabled/disabled in uc.ini
LM PLC
  • new lm-cmd cli
  • old lm-cmd renamed to lm-api
  • macro extensions
  • macro function “unlock” now return false if the lock hasn’t been locked or doesn’t exist
  • unlock macro function may throw an exception if the controller forbids its functionality, in case the controller has no master key defined
  • new functions “state_history” in LM API and “history” (equivalent) in macros
  • new functions: status, value, nstatus, nvalue with oid support
  • new DM rule events: on nstatus, nvalue change (for units)
  • device management functions: “create_device”, “update_device”, “destroy_device”
  • “set_rule_prop” macro function
  • “alias” macro function
  • rule filter in LM EI
  • LM EI now should be enabled/disabled in lm.ini
SFA
  • fixes: rule management functions
  • new sfa-cmd cli
  • sfa-cmd renamed to sfa-api
  • new function “state_history” in SFA API and SFA Framework
  • all functions now accept item oids
  • “result” function returns the result of macro execution if macro action uuid or macro id (in the oid format) specified
  • state API function accepts “full” parameter
  • full SFA states now have item descriptions and status labels (for units)
  • SFA API groups function now accept “g” parameter to filter group list (with MQTT-style wildcards)
  • SFA rpvt function to load documents from remote servers
  • SFA cvars are automatically available in SFA Framework app. Note: SFA cvars are public and may be obtained with any valid API key
  • SFA Framework is now jQuery 3 compatible, included jQuery lib updated to 3.3.1
  • SFA Framework item states now also have description and status labels fields
  • eva_sfa_groups function, returns item groups list (with optional filter)
  • eva_sfa_chart function, displays item state charts
  • eva_sfa_popup function, displays popups and info windows
  • new ws event: server restart and eva_sfa_server_restart_handler in a framework. SFA API function “notify_restart” allows to notify clients about the server restart w/o actual restarting (e.g. when restarting frontend)
  • jinja2 templates for SFA ui and PVT files (all files with .j2 extension are served as templates). index.j2 has more priority than index.html
API Client
  • new API function call result: “result_invalid_params” (11)
Common
  • new notifier management CLI (old CLI tools available in legacy folder)
  • watchdog to test/automatically restart controllers in case of failure
  • oid support in API keys
  • other stability improvements

3.0.2 (2018-06-23)

Bugfix release, some new urgent features, stability improvements

EVA documentation is now available in reStructuredText format and at https://eva-ics.readthedocs.io

Emergency interfaces
  • fixes: correct display of long item names
  • fixes: various bug fixes
  • refresh buttons on item pages
  • LM EI: reset button and expire timer in LM EI show/hide when prop changed
Core
  • fixes: remove empty controller group when all objects are deleted
  • fixes: remote items correctly display state in list_remote
  • fixes: disabled sensors and lvars should not react to expiration
  • each set_prop call now logs what’s actually changed
  • added item oid (type:group/item_id) - reserved for the future releases
  • added stop_on_critical option in config (default: yes), server will be restarted via safe-run if critical exception occur
  • uptime in dump and test API function, last 100 exceptions are now stored in a dump, dumps are now compressed with gzip
  • API functions now support JSON requests
UC
  • action_toggle function to quickly toggle status of simple units
LM PLC
  • list_remote returns array + controller_id property instead of dict
  • result function in macro api. terminate and result function accept action uuid as a param
  • on_set lm rule (status changed to 1)
  • new LM API and macro functions: clear (set lvar value to 0), toggle (toggles lvar value between 0 and 1)
  • cmd macro function now accepts full controller id (uc/controller_id) as well as short
  • new macro functions for file management: ls, open_oldest, open_newest
SFA
  • fixes: dm_rule_props acl in SFA
  • list_remote returns array instead of dict + controller_id property
  • list_macros contains now controller property
  • append_controller now tries to autodetect controller type if no type is specified
  • sfa pvt access logs
  • reset, toggle, clear, action_toggle, result and terminate by uuid funcs in sfa & sfa framework
  • reload_clients command and sfa framework reload event handler
  • eva_sfa_expires_in function in a framework to work with timers
  • log processing functions in a framework
  • wildcard masks in eva_sfa_state and eva_sfa_register_update_state
Common
  • easy-setup.sh - an interactive/automatic script to quickly set up the current host
  • ability to run controllers under restricted user

3.0.1 (2018-02-21)

Minor release with some urgent features

Core
  • EVA_ITEM_PARENT_GROUP variable in script ENV which contains the parent group of the item
  • cvars now can be set as global or assigned to the specified item group i.e. ‘VAR1’ - global cvar, available to the all scripts, ‘group1/VAR2’ - variable available only to scripts from group ‘group1’ (as ‘VAR2’), ‘group2/VAR2’ - variable available only to group ‘group2’ (also as ‘VAR2’). Used by UC scripts to let one script manage different items
UC
  • ‘update_delay’ prop - item passive update may start with a delay to prevent multiple updates running simultaneously producing high system load
  • ‘clone’ function in UC API and uc-cmd to clone items
  • ‘clone_group’ function - clones all matching items in a group
  • ‘destroy_group’ function destroys all items in the specified group
LM PLC
  • item id in LM rules match by simple mask (i.e. ‘*id’* or ‘id’* or ‘*id’)

3.0.0 (2017-10-19)

First public release

Security

Common recommendations

Traditionally, automation systems and protocols have been designed as not completely secure. As for reliability, you may agree that it would be a pity if the motor or door gets stuck because of incorrect access rights to a file or an expired SSL certificate.

Universal Controller, Logic Manager, SCADA Final Aggregator subsystems, as well as their interfaces, openly exchange API keys. If you do not use SSL, these keys can easily be caught. That is why only a separate secure network should be used to connect the controllers in the working configuration. Alternatively, you should install as many controllers as possible on the same server. Built-in web interfaces of the individual subsystems are called Emergency Interfaces. Therefore, they can only be used during primary setup, testing as well as in case of emergency but not on a regular basis.

All programs and extensions which use API calls should be connected at least via SSL or, ideally, in a separate secure network.

If you use secure networks or separate VLANs, it is not recommended to use SSL for API calls to avoid making setup complex and increasing load on your equipment.

Network design

The recommended enterprise configuration of the system is represented in the following scheme:

secure network design
  • Public network external network (company’s local network); applications working in a public network (usually SCADA interfaces), should be protected from unauthorized access as much as possible: they should use SSL and complex passwords and be regularly updated with the latest security patches.
  • Supervisory network network accessed by authorized company employees only; it includes MQTT (event server), PLC (Logic Manager), custom automation applications and “public” interfaces of Universal Controller subsystems. The security policies are minimal. They are used not as means for protection against hacking, but rather for eliminating the possibility of component malfunction. Passwords/keys can be simple, pure HTTP without SSL can be used in order to reduce the load and avoid system failure because of incorrect certificates.
  • Direct control network network in which only item management controllers operate, e.g. “productional” Universal Controller interfaces, TCP/IP-controlled relays, network sensor controllers etc.

In many setups, you may combine Supervisory network and Direct control network into a single network. As for security, this decision is not that bad, if the primary goal to divide these networks is comfortable maintenance.

Primary EVA interface is itself rather secure. Still, when connecting via insecure networks, especially via external Internet connection, it is highly recommended to:

  • use frontend (NGINX, Apache)
  • use SSL only (if frontend is present - use it for SSL processing)
  • use firewall and forward only one port to the server with an interface

It is strongly recommended to access enterprise configurations with VPN only.

It is not recommended to keep debugging mode enabled in the production system, because some important data may be recorded in the log files.

Should I run it as root?

  • Universal Controller is designed to be run on virtual machines, microcomputers, and embedded systems. If server directly controls connected devices, you should run it as root in order to avoid any device access errors. UC security bottleneck (when working under root) - API and UC EI interface. However, you should use API in Supervisory network only and UC EI interface should be turned off and used only in case of emergency.
  • Logic Manager does not require direct access to the equipment, that is why it can be run as root on the selected system (if really required) or as a restricted user on the common-purpose servers. If Logic Manager API and interface are available only in Supervisory network, this issue is not critical for security.
  • All external interfaces of the system, including SCADA Final Aggregator, should be run only under restricted users and protected with additional frontend and/or firewall.

API recommendations

X-Real-IP HTTP header

HTTP API uses X-Real-IP header variable to determine real IP address of client when working behind frontend. This can be used by attacker to compromise real IP address and bypass hosts_allow/hosts_assign key access control lists. Frontend should always clear X-Real-IP header variable and set it to the real ip of remote client.

X-Real-IP feature is disabled by default. To enable it, set param x_real_ip=yes in webapi section of controller configuration file.

Universal Controller API keys
  • The key should contain at least 14 characters, including numbers, lowercase, and uppercase letters. Default keys generated during easy setup are random sha256 64-byte length hashes, which’s more than enough for security unless they’re transferred between controllers in an insecure network and sniffed.
  • As far as day-to-day tasks are concerned, it is recommended to use API key masterkey (as well as all keys with master rights) only locally or for the system configuration/emergency situations.
  • For the use of UC EI it is recommended to create operator key with groups = #, sysfunc = yes permissions.
  • When connecting to Logic Manager and SCADA Final Aggregator it is recommended to create a separate key with rights for certain item groups, sysfunc = no, optionally allow = cmd.
  • All external applications should have their own keys with restricted access rights to the required functions and items only.
  • After installation, make sure that etc/uc_apikeys.ini file has 0600 permissions (and owned by the user you are running the controller under)
Logic Manager API keys
  • After the initial configuration is complete, it is recommended to connect external applications only via keys with certain rights. Master key should not be used.
SCADA Final Aggregator interfaces
  • If interface is available from within a public network, you should always use frontend with additional authentication
  • Private data should be stored on SFA PVT server or protected in other way.
Common API security recommendations

If server is present in several VLANs, make sure that API listens only on Supervisory network address. If you do not use UDP API or Connecting equipment with drivers in Universal Controller, disable them in the controller configuration. Do not enable the remote file control function unless it’s necessary for external apps.

Developer mode

Every component may be started in a “developer mode”: if enabled, all data, including API keys, is openly written in the log file. That is why we do not advise you to enable it unless you are our developer or integrator. Still, as far as the whole system code is open, you can try to enable it on your own responsibility. Never enable developer mode on the working system and avoid enabling debug mode as well.

If you contacted the product vendor or integrator who explained to you how to make a system “dump”, you should delete it from the system immediately after the file is no longer required. “dump” contains plenty of confidential data, including all API KEYS. Never give dump files to unauthorized persons! This is the same as giving away all configuration files, including the keys.

Dump file should be sent only via secure channels or in an encrypted form.

Notification system

The Notification System is embedded in all EVA subsystems. All the events of these subsystems are sent to the notification servers via objects called “notifiers” which contain the configuration of the notification endpoints.

Event structure

Each event includes the following data:

  • Event subject (not to be confused with MQTT subject)
  • Notification space May be used to divide the controlled structure into sectors, e.g. city1/office1, plant1 etc. By dividing spaces you can separate one EVA installation from another using the same notification server, e.g. to create your own multi-control and multi-monitoring systems.
  • Event data (usually JSON dict with) data on what’s actually happened
Event subjects

There are several event subjects in EVA. Each notification endpoint can be subscribed either to one of them or to several ones.

state - item state change event

The event notifications with the “state” subject are sent by Universal Controller and Logic Manager whenever the items change their status.

Notification sends data similar to those, one can get using UC API or LM API state. There is one difference for a sensors:: sensor with error status (status = -1) does not send its value data until the value is null. This was done specifically for the logic components to work correctly with the old value until the sensor status data is updated correctly and the sensor is back online or until the data is expired.

action - unit and macro action events

Every time the unit action or macro action changes its status, the notification server receives “action” event notification.

Notification sends data similar to ones that can be obtained using UC API result command.

log - logged event

When the system or you add record to the logs, the notification system sends ‘log’ event notification. The log notification data have the following format:

{
 "h": "<SYSTEM_NAME>",
 "l": <LEVEL>,
 "p": "<PRODUCT_CODE>",
 "msg": "<message body>",
 "mod": "<MODULE>",
 "th": "<MODULE_THREAD>",
 "t": <TIME(UNIX_TIMESTAMP)>,
 "dt": <TIME RFC3339>
}
  • SYSTEM_NAME the name specified in the configuration file of controller (or hostname by default)
  • LEVEL 10 - DEBUG, 20 - INFO, 30 - WARNING, 40 - ERROR or 50 for CRITICAL
  • PRODUCT_CODE “uc” for Universal Controller, “lm” for Logic Manager, “sfa” for SCADA Final Aggregator
  • MODULE a specific system module, e.g. ‘unit’
  • MODULE_THREAD the module thread, e.g. “_t_action_processor_lamp1”

Important: the system does not send the log records related to the notification system itself. They are not visible via EI interfaces and are written only into the local log files. This was done for the notification system not to send the records in cycles.

server - server events

Server events are used to notify controllers and clients about system events. Event format is simple:

{
  "s": "server",
  "d": "<event>"
}

Event data for MQTT notifiers is packed as dict:

{
  "s": "server",
  "d": {
    ... system data ...
    e: "<event>"
    }
}

Configuring the notification endpoints

Configuration is done using the console commands uc-notifier for Universal Controller, lm-notifier for Logic Manager and sfa-notifier for SCADA Final Aggregator or eva ns <uc|lm|sfa>. Therefore, even if two controllers are set up in the same folder on the same server, they have different notification endpoints configurations.

Basic Configuration

Let’s play with notification system e.g. of Universal Controller. This command will give us the list of notifiers, including their types, IDs, status and endpoint target.

# eva ns uc list

Type ID Status Target
mqtt eva_1 Enabled eva:test@localhost:1883/lab

Let’s test the endpoint (for mqtt the system will try to publish [space]/test)

# eva ns uc test eva_1 OK

To create the new notifier configuration, run:

eva ns uc create [-s SPACE] [-t SEC] [-y] ID PROPS

where

  • ID the unique ID of the notifier
  • PROPS endpoint properties, e.g. mqtt:[username:password]@host:[port]
  • -s SPACE notification space
  • -t SEC timeout (optional)

Option “-y” enables the notification configuration right after creation (by default all notifiers are created as disabled)

The notifier configuration params may be viewed with props and changed with set notifier CLI commands. To apply the changes you must restart the controller.

Except for endpoint configuration, notifiers have some additional params:

  • collect_logs this should be set to “true” for SCADA Final Aggregator MQTT notifiers if you want to collect the logs of other controllers and have the records available locally in SFA.
  • interval when set, notifier will send subscribed item states with the specified interval
  • notify_key notification key for custom http endpoints
  • skip_test if “true”, the endpoint won’t be tested at the controller start (the controller keeps the notifier active but puts error into the log)
Subscribing the notifier to events

By default, the new notifier is not subscribed to any events. You can review all the subscriptions using “get_config” command.

To subscribe notifier to the new subject, run:

eva ns uc subscribe <subject> <notifier_id> [args]

(where subject is “state”, “log” or “action”)

When subscribing notifier to logs, you may use optional -l LEVEL param (10 - DEBUG, 20 - INFO, default, 30 - WARNING, 40 - ERROR, 50 - CRITICAL).

When subscribing notifier to state changes, you may also always specify item types (comma separated) or use ‘#’ for all types with -v TYPE param, groups with -g GROUPS. Optionally you may specify the particular items to subscribe notifier to with -I ITEMS.

Note

For each “state” subscription you must specify either type and groups or item IDs.

Example:

eva ns uc subscribe state test1 -v ‘#’ -g ‘hall/#’

subscribes the notifier test1 to the events of the status change of all the items in the hall group subgroups.

Subscription to “action” requires the params similar to “state”. Additionally, -a ‘#’ should be specified to subscribe to all the action statuses or -a state1,state2,state3… to subscribe to the certain statuses of the queued actions:.

For example, the following command will subscribe the notifier to the events of all failed actions:

eva ns uc subscribe action test2 -v '#' -g '#' -a dead,refused,canceled,ignored,failed,terminated

Once created, the subscription can’t be changed, but new subscription to the same subject replaces the configuration of the previous one.

To unsubscribe the notifier from the subject, run:

eva ns uc unsubscribe [subject] <notifier_id>

If the subject is not specified, the notifier will be unsubscribed from all notification subjects.

The controller should be restarted to apply the new subscriptions configuration.

MQTT (mqtt)

MQTT is a major endpoint type used to link several EVA subsystems. For instance, it enables Logic Manager and SCADA Final Aggregator controllers to receive the latest item status from Universal Controller servers when set on a nodes in different networks. We test and use EVA with mosquitto server, but you can use any server supporting MQTT protocol. As far as MQTT is the major type of the EVA notification system, let us examine it in detailed.

MQTT and state notifications

Items in MQTT form a subject hive so-called “EVA hive”. Hive may have a space e.g. “plant1/” to separate several EVA systems which use the same MQTT server.

Item’s state is stored in a hive with the subject SPACE/item_type/group/item_id and contains the item state data and some configuration params in JSON array.

By default, MQTT notifier creates a subscription per item to avoid processing of unnecessary topics. If the cloud contains lots of items which need to be synchronized with the local controller, sometimes it is useful to set subscribe_all notifier option to true. If set, notifier is subscribed to all possible item state and control topics using wildcards. This may cause more overhead on the controller side, but reduces MQTT server load.

MQTT and action notifications

Unit action notifications are sent to the topic

SPACE/unit/group/UNIT_ID/action

Logic macros action notifications are sent to the topic

SPACE/lmacro/group/UNIT_ID/action

These messages include the serialized action information in JSON format. As soon as action state is changed, the new notification is sent.

MQTT and log notifications

Log messages are sent to the MQTT server as JSON with the following MQTT subject:

SPACE/log

It means that the common log subject is created for one EVA space.

Any EVA server (usually it’s a job for SCADA Final Aggregator) can be a log collector, collecting the reports from MQTT server (space/log), pass them further via the local notification system and have them available via API. In order to enable this function, set param collect_logs to true in the notifier configuration:

sfa-notifier set eva_1 collect_logs true
Setting up MQTT SSL

If MQTT server requires SSL connection, the following notifier properties should be set:

  • ca_certs CA certificates file (e.g. for Debian/Ubuntu: /etc/ssl/certs/ca-certificates.crt), required. SSL client connection is enabled as soon as this property is set.
  • certfile SSL certificate file, if required for authentication
  • keyfile SSL key file for SSL cert
Setting up MQTT QoS

You may specify different MQTT QoS for events with different subjects.

To set the same QoS for all events, use command:

eva ns uc <notifier_id> set qos <Q>

(where Q = 0, 1 or 2)

To set QoS for the specified subject, use command:

eva ns uc <notifier_id> set qos.<subject> <Q>

e.g.

eva ns uc eva_1 set qos.log 0

Quick facts about MQTT QoS:

  • 0 the minimum system/network load but does not guarantee message delivery
  • 1 guarantees message delivery
  • 2 the maximum system/network load which provides 100% guarantee of message delivery and guarantees the particular message has been delivered only once and has no duplicates.
Use MQTT for updating item states

MQTT is the only EVA notifier type performing two functions at once: both sending and receiving messages.

Control and monitoring items can use MQTT to change their state (for synchronization) if the external controller can send active notifications under this protocol.

The items change their state to the state received from MQTT, if someone sends its state update to EVA hive with status or value subtopics. Setting item state with primary topic (using JSON dict) is not recommended.

To let the item receive MQTT state updates, set its mqtt_update configuration param to the local MQTT notifier ID, as well as additionally optionally specify MQTT QoS using a semicolon (i.e. eva_1:2). QoS=1 is used by default.

State updates should be sent either to MQTT topics “path/to/unit/status” and “path/to/unit/value” or as JSON message to “path/to/item”. In example, to set sensor “env/temp” value to 25:

  • MQTT topic: sensor/env/temp

  • MQTT payload:

    { "value": 25 }
    

As item value is always stored / exchanged as a string, it can be set via MQTT in any convertible format.

Note

There is also a configuration parameter mqtt_update_default which can be set in etc/uc.ini (default e.g. to eva_1:2) and applied to all newly created items.

One item can be subscribed to a single MQTT notifier to get the state updates, but different items on the same controller can be subscribed to different MQTT notifiers.

MQTT and unit actions

MQTT can be also used as API to send actions to the units. In order to send an action to the unit via MQTT, send a message with the following subject: [space]/<group>/<unit_id>/control and:

  • either in a form of text messages “status [value] [priority]”. If you want to skip value, but keep priority, set it to null, i.e. “status 0 null 50”. “value” and “priority” parameters are optional. If value should be omitted, set it to “none”.

  • or in JSON format (fields “value” and “priority” are optional):

    { "status": 1, "value": "", "priority": 100 }
    

In case you need 100% reliability, it is not recommended to control units via MQTT, because MQTT can only guarantee that the action has been received by MQTT server, but not by the target Universal Controller. Additionally, you cannot obtain action uuid and further monitor it.

To let unit responding to MQTT control messages, set its configuration param mqtt_control to the local MQTT ID. You may specify QoS as well via semicolon, similarly as for mqtt_update.

IoT Cloud setup

Special properties of MQTT notifiers allow to set up a cloud and connect EVA ICS nodes via MQTT instead of HTTP:

  • announce_interval if greater than zero, controller will announce itself with a chosen interval (in seconds) via MQTT to other cloud members.
  • api_enabled allows controller to execute API calls from other cloud members via MQTT.
  • discovery enabled controller will connect other nodes in cloud as soon as discover them.

To use auto discovery feature, API key named default must be present and equal on all nodes.

API calls via MQTT are encrypted with strong AES256 algorithm, this allows to use any 3rd party MQTT servers without any risk.

Optionally, controller can be a member of different clouds via different MQTT notifiers.

DB Notifiers

RDBMS (SQLite, MySQL, PosgreSQL)

EVA ICS has a special notifier type: db, which is used to store items’ state history. State history can be obtained later via API calls or EVA JS Framework for analysis and e.g. to build graphical charts.

To create db notifier, specify notifier props as db:<db_uri>, e.g. db:runtime/db/history1.db, where runtime/db/history1.db - database file in runtime folder.

DB notifier properties:

  • keep keep records for the specified number of seconds. If keep time is not specified, EVA keeps records for last 86400 seconds (24 hours).
  • simple_cleaning by default, records are analyzed before deletion to make sure each item will have at least one state metric in database after cleanup. This may cause additional overhead for the heavy loaded setups. Setting the property to true tells EVA to delete old records with a single query, ignoring that some of the items could have no records left after.

After creating db notifier, don’t forget to subscribe it to state events. Events action and log are ignored.

If easy-setup is used for EVA installation, notifier called db_1 for SFA is created automatically, default History database format is sqlite3.

Note

To create default (sqlite) db notifier, you may specify either database absolute path or relative to EVA ICS directory. sqlite:/// prefix is optional and will be added automatically if missing.

EVA ICS db notifiers work via SQL Alchemy, so MySQL and PosgreSQL data storage is also supported.

E.g. to use MySQL, specify db uri as:

mysql+pymysql://username:password@host/database

(pymysql Python module is required)

or

mysql+mysqldb://username:password@host/database

(mysqlclient Python module is required)

If you get “failed to create state_history table” error with MySQL/MariaDB, try setting:

set global innodb_file_format=Barracuda;
set global innodb_large_prefix=1;
set global innodb_default_row_format=dynamic;

or put these options to database server configuration file.

InfluxDB

Item state metrics can be stored to InfluxDB time series database.

Consider InfluxDB is installed on local host, without password authentication. Firstly, create database for EVA ICS:

influx
> create database eva

Then create InfluxDB notifier, e.g. for SCADA Final Aggregator:

eva ns sfa create influx_local 'influxdb:http://127.0.0.1:8086#eva'
eva ns sfa test influx_local
eva ns sfa subscribe state influx_local -g '#'
eva ns sfa enable influx_local
eva sfa server restart

That’s it. After restart, SCADA Final Aggregator immediately starts sending metrics to the specified InfluxDB.

Then you can downsample metrics of the required item, e.g. let’s downsample sensor:env/temp1 to 30 minutes:

CREATE RETENTION POLICY "daily" ON "eva" DURATION 1D REPLICATION 1
CREATE CONTINUOUS QUERY "downsampled_env_temp1_30m" ON "eva" BEGIN
  SELECT mode(status) as "status",mean(value) as value
  INTO "daily"."sensor:env/temp1"
  FROM "sensor:env/temp1"
  GROUP BY time(30m)
END

After, you can tell state_history SFA API function to select metrics from daily retention policy, specifying additional parameter o={ “rp”: “daily” }.

Warning

It is highly recommended to set notifier “interval” property, to properly handle states for the rarely updated items.

Prometheus

EVA ICS can export metrics for Prometheus time series database.

To enable metrics export, create notifier for Prometheus (in the example below we’ll secure it with user/password authentication):

eva ns sfa create pr1 prometheus:
eva ns sfa test pr1
eva ns sfa set pr1 username prometheus
eva ns sfa set pr1 password 123
eva ns sfa subscribe state pr1 -g '#'
eva ns sfa enable pr1
eva sfa server restart

After controller restart, metrics are available at URI /ns/<notifier_id>/metrics. As Prometheus collect metrics by itself, EVA ICS Prometheus notifier just exports subscribed item states to the specified metrics URI every time when it’s requested.

For the example above, Prometheus job config will look like:

scrape_configs:
# .....
  - job_name: 'eva'
    scrape_interval: 5s
    metrics_path: /ns/pr1/metrics
    basic_auth:
      username: 'prometheus'
      password: '123'
    static_configs:
      - targets: ['localhost:8828']

Notes about using EVA ICS and Prometheus:

  • As Prometheus doesn’t support “/” and “.*” for metrics, EVA item properties are exported as e.g. sensor:env:hum1_int:value
  • Only float and null item values are exported
  • To enable metric help, set item description

3rd party Clouds

Google Cloud Platform IoT Core

Controllers can communicate with GCP IoT Core using gcpiot notifiers:

  • Send telemetry of EVA ICS items to GCP devices
  • Receive commands from GCP
Configuration

To enable this functionality, firstly you must generate RSA256 key pair.

As GCP IoT Core doesn’t support groups, create YAML key-value map file which looks like:

env.pressure: sensor:env/air_pressure
env.temperature: sensor:env/temperature
cctv1: unit:equipment/cctv
lamp1: unit:lights/lamp1

Then configure GCP IoT:

  • Create IoT registry in your project. Specify default telemetry topic from which you can obtain data via Pub/Sub. Make sure MQTT option is checked.

  • Create IoT gateway:

    • gateway name should match EVA ICS notifier id (e.g. gcpiot)
    • set Device authentication method to Association only
    • paste public key you’ve generated, make sure RSA256 is selected.
  • Create corresponding IoT devices. Enter Device ID only, leave other fields blank.

  • Go back to IoT gateway and bind all created devices.

Configure EVA ICS, e.g. let’s create notifier for Universal Controller:

eva -I
ns uc
create gcpiot gcpiot:PROJECT_ID/REGION/REGISTRY
# set CA certificate file
set gcpiot ca_certs /etc/ssl/certs/ca-certificates.crt
# set generated private RSA256 key file for auth
set gcpiot keyfile /path/to/private.pem
# set mapping file
set gcpiot mapfile /path/to/mapfile.yml
# test it
test gcpiot
# subscribe notifier to items
subscribe state gcpiot -g '#'
# set API key if you plan to execute commands
# you may use use $key_id to specify key id instead of API key itself
set gcpiot apikey $default
# enable notifier
enable gcpiot
# restart controller
server restart
Commands

You may send commands as to EVA ICS controller (Gateway->Send command) as to the individual devices.

  • All commands must be sent in JSON RPC 2.0 format.
  • You may send any API command, e.g. for the above example: for Common methods and for UC API.
  • API key in params is not required if set in notifier configuration, but may be overriden if specified.
  • If you send command to the particular IoT device (EVA ICS item), parameter “i” (item oid) is automatically added to the request.

E.g., let’s toggle unit:equipment/cctv:

{"jsonrpc": "2.0", "method": "action_toggle" }

HTTP Notifiers

JSON

HTTP notifications (aka web hooks) are used by applications, which, for some reasons, cannot work with MQTT in real time, e.g. servers containing third-party or your own web applications.

JSON notifier send POST request to specified URI with data:

  • k notification key the remote app may use to authorize the sender (if set)
  • space notification space (if set)
  • subject event subject
  • data event data array

Your application must respond with JSON if the event has been processed successfully (if empty response body is received, request is considered as successful):

{ "ok" : true }

or if your app failed to process it:

{ "ok" : false }

or with HTTP status 202 (Accepted).

The event data field is always an array and may contain either one event or several ones.

When EVA controllers test remote http-json endpoint, they send notifications with subject=”test” and the remote app should always respond with { “ok”: True } and HTTP status 200 (OK).

Example of custom notification processing server with Python and Flask:

from flask import Flask, app, request, jsonify

app = Flask(__name__)

@app.route('/json', methods=['POST'])
def j():
    data = request.json
    # process notification request
    return jsonify({'ok': True})
NDJSON

If notification endpoint accepts only list (ndjson) data, set method=list in JSON notifier properties. In this case, all above fields are included in each notification data row.

This allows to send, process and collect EVA ICS logs, state telemetry and other data as HTTP NDJSON (Newline Delimited JSON) stream, which is compatible with various data collectors, processors and aggregators.

JSON RPC

If notifier method property is set to jsonrpc, JSON RPC 2.0 call is performed. For JSON RPC, errors must be specified in “error” field of the response. For successful calls, the “result” field in response may contain any data.

Example:

from flask import Flask, app, jsonify, request, abort, Response

app = Flask(__name__)

@app.route('/jsonrpc', methods=['POST'])
def jrpc():
    payload = request.json
    result = []
    for p in payload if isinstance(payload, list) else [payload]:
        if p.get('jsonrpc') != '2.0': abort(400)
        r = None
        if p.get('method') == 'notify':
            data = p.get('params')
            # process data
            i = p.get('id')
            if i:
                r = { "jsonrpc": "2.0", "result": { "ok": True }, "id": i}
        else:
            i = p.get('id')
            if i:
                r = { "jsonrpc": "2.0", "error":
                        { "code": 404, "message": "method not found" },
                        "id": i}
        if not isinstance(payload, list):
            result = r
        else:
            result.append(r)
    if result:
        return jsonify(result)
    else:
        return Response(None, 202)
Basic authentication

All HTTP notifiers support basic authentication. To start using it, set username and password notifier properties.

Data pullers

Data pullers are external programs, used to pull state from the equipment as fast as possible. Data pullers are usually used in high-load environments.

Configuration

Data pullers are defined in Universal Controller configuration, section [datapullers] as <name> = <cmd>, where:

  • name data puller name (unique)
  • cmd data puller startup command

e.g.

[datapullers]
dp1 = /opt/dp1/datapuller -c /opt/dp1/config.yml
dp2 = /opt/dp2/datapuller -c /etc/dp2.ini
dp3 = datapuller3

Execution

All data pullers are started automatically at Universal Controller start. Data pullers can be stopped or restarted later using UC API functions or CLI (eva uc datapuller).

Universal Controller always tries to kill data puller and its child subprocesses on stop / shutdown. However to avoid critical situations, data puller SHOULD exit manually, if STDOUT / STDERR are not available any longer (standard programs do that by default).

Data exchange

Basics

Data puller is a program, or a shell script, written in any language, which repeatedly pulls the equipment, collects and processes data and then sends it to stdout. Data pulling should be done in an infinite loop. Start / stop operations are handled by Universal Controller.

When stop (SIGTERM signal) is received, data puller has 1 second to shut down itself gracefully, otherwise it (and its child processes) will be forcibly killed.

If data puller process exits or crashes, it will be automatically restarted. The automatic restart is performed with 1-second delay.

The idea of data pullers is developing small programs in low-level programming languages to let EVA ICS receive only modified data. Data pullers are good for Ethernet/IP and Modbus slave equipment, as well as for SNMP-enabled equipment without a support of SNMP traps or any other equipment, which is unable to send any state events.

Health check

If there are no events, data puller SHOULD send .ping or empty string to STDOUT, otherwise it will be considered as dead after period equal to a default controller timeout and automatically restarted:

.ping
Data output

Data puller should collect data and output to STDOUT update commands in format, equal to UC UDP API:

<item_id> u <status> <value>
# e.g.
sensor:tests/test1 u 1 777.555

If status or value need to be skipped, they should be set to “None”:

sensor:tests/test1 u None 777.555

Data pullers SHOULD:

  • collect and output all available data on startup
  • during the execution, send to Universal Controller only modified data
  • manually handle logic mapping, e.g. converting Modbus registers or Ethernet/IP tags to EVA ICS items states.
Logging

Data puller can send messages to Universal Controller logs. If stdout line starts with .log, it’s considered to be the log command:

.log <level> <message>
# e.g.
.log warning Some warning information

Where level is the level of the message (debug, info, warning, error or critical, first letter is enough e.g. w for warning).

Data puller can also print messages to STDERR, they will be automatically logged with error level.

Environment variables

All cvars and other EVA ICS core variables are available in the datapuller process system environment.

Pulr

Pulr is a free data pulling tool, 100% compatible with EVA ICS. Refer to Pulr documentation about the tool configuration, here are few remarks how to use it:

  • In Pulr configuration, set output: eva/datapuller to output data in EVA ICS native format.
  • Set beacon value less than Universal Controller default timeout, otherwise the Pulr subprocesses will be killed and continuously restarted.
  • All fields in process sections must have set-id param, to convert pulled data IDs into EVA ICS item IDs (<unit|sensor>:<group>/<id>)
  • set-id must end with either .status or .value to set the proper EVA ICS items state fields. If no ending is specified, item state value is updated.

Pulr supports SNMP (v2), Modbus (TCP/UDP) and Ethernet/IP (Allen-Bradley compatible) field buses.

Command line interfaces

EVA command line apps

EVA apps are used to configure the system and call controller API functions from the command line or by external scripts. All of the following apps are located in bin folder.

EVA shell

EVA shell (eva-shell, eva -I or eva for single commands) is the primary CLI tool. It allows you to manage local system as well as calling other tools/subshells directly from CLI interactive command line.

With EVA shell you can install updates, backup and restore configuration, start and stop EVA components.

EVA shell provides commands for all EVA ICS API methods, auto completion for everything, command repeat, batch commands and is the recommended way to configure, manage and monitor EVA ICS nodes from command line.

EVA shell

with EVA shell, IoT management is a joy

Universal Controller
Logic Manager
SCADA Final Aggregator
Other
  • test-uc-xc a special app to test UC item scripts. Launches an item script with UC cvars and EVA paths set in the environment.
  • sbin/layout-converter allows to convert simple item layout to enterprise.

Device control apps

EVA distribution includes pre-installed samples for device controlling. All sample scripts are located in xbin folder

TCP/IP controlled relays
  • EG-PM2-LAN controls EG-PM2-LAN Smart PSU
  • SR-201 controls the SR-201 relay controllers - a quite popular and simple solution with TCP/IP management option
1-Wire (direct access via GPIO)
  • w1_ds2408 controls Dallas DS2408-based relays on the local 1-Wire bus
  • w1_therm monitors Dallas DS18S20, DS18B20 and other compatible temperature sensors on the local 1-Wire bus
  • w1_ls displays the devices connected to the local 1-Wire bus

Tutorial

In this section, we will focus on EVA configuration which is illustrated by the following example.

Note

Examples for the particular equipment can be also found in integrations section of EVA ICS documentation.

There is a room and some equipment:

  • Internal ventilation system, powered via SR-201 controlled relay, port 1
  • External ventilation system, powered via SR-201 controlled relay, port 2
  • Air temperature sensor Dallas DS18S20
  • a motion sensor in the hall connected to AKCP SensorProbe
  • a light in the hall connected to Denkovi SmartDEN IP-16R, port 2
  • and some alarm system installed on a remote server and called by its own API (via GET request). As soon as the alarm is activated, it switches on the alarm siren and sends an SMS to the operator.

Our task is to automate the above:

  • To switch on the internal ventilation every night for the period from 9pm till 7am.
  • To switch on ventilation in the daytime, if the air temperature is above 25 degrees for more than 5 minutes in a row.
  • If the sensor detects a motion, do the following:
    • if the alarm is on - send an API request to the alarm system
    • if the alarm is off - turn on the light in the hall
  • The user should be able to control the ventilation system with web interface, see the temperature, manage alarm and lighting

Let’s do this step by step, from equipment configuration to interface development. Let’s Suppose that EVA has already been installed and everything is located on a single server, including MQTT server with eva:secret access and all the data will be sent into plant1 subject.

EVA bin folder is included in system PATH.

All operations will be done using command line applications.

Universal Controller configuration

So, let us proceed with our configuration. Connect the equipment to Universal Controller and configure the notification system.

Connecting ventilation

create two units for ventilation:

eva uc create unit:ventilation/vi -y # internal
eva uc create unit:ventilation/ve -y # external
Method 1: with scripts

As a first step, create the variable for controlling SR-201 in order not to write the full relay control commands anew:

eva uc cvar set REL1_CMD "SR-201 192.168.22.3"

As far as both ventilation systems are connected via the same relay, and it displays the states of all ports at once, let’s create a multiupdate for updating their status with a single command:

eva uc create mu:ventilation/mu1 -y
eva uc config set mu:ventilation/mu1 items unit:ventilation/vi,unit:ventilation/ve

and the script for this multiupdate named xc/uc/mu1_update:

#!/bin/sh

${REL1_CMD} | head -2

Note

After creating a script file, don’t forget to set its executable permissions (chmod +x scriptfile)

Let’s check the script:

test-uc-xc xc/uc/mu1_update
Reading custom vars from /opt/eva/runtime/uc_cvars.json

REL1_CMD = "SR-201 192.168.22.3"

Starting 'xc/uc/mu1_update'

stime: 1507923323.396813
etime: 1507923323.400836
duration: 0.004023 sec  ( 4.022598 msec )
exitcode: 0

---- STDOUT ----
0
0

---- STDERR ----
----------------

Then we need to create two scripts for the relay control.

For internal ventilation, named xc/uc/vi

#!/bin/sh

${REL1_CMD} 1 $2

and for external ventilation, named xc/uc/ve

#!/bin/sh

${REL1_CMD} 2 $2

Enable the ventilation control:

eva uc action enable unit:ventilation/vi
eva uc action enable unit:ventilation/ve

set a multiupdate to update unit states every 30 seconds

eva uc config set mu:ventilation/mu1 update_interval 30 -y
Method 2: with driver

Starting from EVA 3.1 you can use pre-made drivers. Let’s do the above with driver.

Download PHI module:

eva uc phi download https://get.eva-ics.com/phi/relays/sr201.py

Load PHI module to controller. As sr201 PHI provides aao_get feature, set update=30 to update all items which use drivers with this PHI every 30 seconds:

eva uc phi load relay1 sr201 -c host=192.168.22.3,update=30 -y

Let’s test it:

eva uc phi test relay1 self

After loading sr201 PHI automatically created driver “relay1.default” with “basic” LPI. As we have a simple logic, let’s use it as-is. Set driver to both ventilation units:

eva uc driver assign unit:ventilation/vi relay1.default -c port=1 -y
eva uc driver assign unit:ventilation/ve relay1.default -c port=2 -y
Connecting a temperature sensor

Create sensor in UC:

eva uc create sensor:env/temp1

(Consider Linux w1-gpio and w1-therm kernel modules are already loaded)

Let’s find our sensor on a 1-Wire bus:

./xbin/w1_ls
28-000006ef85d7
Method 1: with scripts

Here it is. Create a script named xc/uc/temp1_update

#!/bin/sh

VALUE=`w1_therm 28-000006ef85d7` && echo 1 ${VALUE} || echo -1

Let the temperature update every 20 seconds:

eva uc config set sensor:env/temp1 update_interval 20 -y
Method 2: with driver

Download PHI module:

eva uc phi download https://get.eva-ics.com/phi/sensors/env/w1_ds18n20.py

Load PHI module to controller. This is universal PHI which means you don’t need to specify particular sensor address when loading, it should be specified later when you set driver to sensor:

eva uc phi load w1t w1_ds18n20 -y

After loading w1_ds18n20 PHI automatically created driver “w1t.default” with “sensor” LPI. As we have a simple logic, let’s use it as-is. Set driver to sensor:

eva uc driver assign sensor:env/temp1 w1t.default -c port=28-000006ef85d7 -y

As this PHI doesn’t provide aao_get feature and we can’t ask it to update sensors automatically, set update_interval sensor property to let it passively update itself every 20 seconds:

eva uc config set sensor:env/temp1 update_interval 20 -y
Connecting a motion sensor

Create a sensor in UC:

eva uc create sensor:security/motion1 -y

and configure the sensors controller to send Connecting equipment with drivers to our server IP.

Method 1: with SNMP trap parser

Switch on the debugging mode and look into the log file:

eva uc debug on
tail -f log/uc.log|grep "snmp trap data"

Let someone walk near the sensor and we’ll catch SNMP trap data:

2017-10-13 18:52:42,568 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.2.1.1.3.0 = 549411751
2017-10-13 18:52:42,569 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.4.1.3854.1.0.301
2017-10-13 18:52:42,571 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.6.3.18.1.3.0 = 192.168.22.95
2017-10-13 18:52:42,572 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.6.3.18.1.4.0 =
2017-10-13 18:52:42,574 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.6.3.1.1.4.3.0 = 1.3.6.1.4.1.3854.1
2017-10-13 18:52:42,576 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.4.1.3854.1.7.1.0 = 4
2017-10-13 18:52:42,579 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.4.1.3854.1.7.2.0 = 1
2017-10-13 18:52:42,581 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.4.1.3854.1.7.3.0 = 0
2017-10-13 18:52:42,583 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.4.1.3854.1.7.4.0 = 0
2017-10-13 18:52:42,584 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.4.1.3854.1.7.5.0 = Motion1
2017-10-13 18:52:42,586 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.4.1.3854.1.7.6.0 = MD Hall
2017-10-13 18:52:44,583 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.2.1.1.3.0 = 549411951
2017-10-13 18:52:44,584 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.4.1.3854.1.0.301
2017-10-13 18:52:44,586 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.6.3.18.1.3.0 = 192.168.22.95
2017-10-13 18:52:44,588 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.6.3.18.1.4.0 =
2017-10-13 18:52:44,589 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.6.3.1.1.4.3.0 = 1.3.6.1.4.1.3854.1
2017-10-13 18:52:44,591 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.4.1.3854.1.7.1.0 = 2
2017-10-13 18:52:44,594 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.4.1.3854.1.7.2.0 = 0
2017-10-13 18:52:44,596 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.4.1.3854.1.7.3.0 = 0
2017-10-13 18:52:44,597 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.4.1.3854.1.7.4.0 = 0
2017-10-13 18:52:44,598 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.4.1.3854.1.7.5.0 = Motion1
2017-10-13 18:52:44,602 plant1  DEBUG uc traphandler_t_dispatcher: snmp trap data 1.3.6.1.4.1.3854.1.7.6.0 = MD Hall

As we can see, the sensor sends SNMP OID 1.3.6.1.4.1.3854.1.7.1.0 = 4 when there is some activity and 1.3.6.1.4.1.3854.1.7.1.0 = 2 when the activity is finished. If we disconnect the sensor from the sensorProbe, trap with the same OID and value 7 will be received.

switch off the debugging mode

eva uc debug off

append one ident var to let it parse only “its own” traps:

eva uc config set sensor:security/motion1 snmp_trap.ident_vars "1.3.6.1.4.1.3854.1.7.6.0=MD Hall" -y

and use SNMP OID 1.3.6.1.4.1.3854.1.7.1.0 to monitor it:

eva uc config set sensor:security/motion1 snmp_trap.set_down 1.3.6.1.4.1.3854.1.7.1.0=7 -y
eva uc config set sensor:security/motion1 snmp_trap.set_if 1,1:1.3.6.1.4.1.3854.1.7.1.0=4 -y
eva uc config set sensor:security/motion1 snmp_trap.set_if 1,0:1.3.6.1.4.1.3854.1.7.1.0=2 -y

The final sensor configuration will look like:

eva uc config get sensor:security/motion1
{
   "description": "",
   "expires": 0,
   "mqtt_update": null,
   "snmp_trap": {
       "ident_vars": {
           "1.3.6.1.4.1.3854.1.7.6.0": "MD Hall"
       },
       "set_down": {
           "1.3.6.1.4.1.3854.1.7.1.0": "7"
       },
       "set_if": [
           {
               "status": 1,
               "value": "1",
               "vars": {
                   "1.3.6.1.4.1.3854.1.7.1.0": "4"
               }
           },
           {
               "status": 1,
               "value": "0",
               "vars": {
                   "1.3.6.1.4.1.3854.1.7.1.0": "2"
               }
           }
       ]
   },
   "update_exec": null,
   "update_interval": 0,
   "update_timeout": null,
   "virtual": false
}

The sensor is ready. It doesn’t require any passive update script since its state is updated with SNMP traps by the equipment.

Method 2: with driver

Download PHI module:

eva uc phi download https://get.eva-ics.com/phi/sensors/alarm/akcp_md.py

Load PHI module to controller. Consider motion sensor is connected to AKCP sensor controller port #1 and it has IP address 192.168.22.5.

eva uc phi load md1 akcp_md -c host=192.168.22.5,sp=1 -y

If one port is specified, akcp_md creates a driver with ssp LPI, which doesn’t need any additional options. Just set it to our sensor:

eva uc driver assign sensor:security/motion1 md1.default -y

The sensor is ready. It doesn’t require any passive updates since its state is updated with SNMP traps parsed by driver.

Connecting a hall light

Create hall light unit:

eva uc create unit:light/lamp1 -y
eva uc action enable unit:light/lamp1

Let it turn off automatically after 10 mins of inactivity:

eva uc config set unit:light/lamp1 auto_off 600 -y

and enable the actions to be always executed:

eva uc config set unit:light/lamp1 action_always_exec 1 -y
Method 1: with scripts

So, now we have to connect the lamp to Denkovi IP-16R relay. Connect it similarly to ventilation:

eva uc cvar set REL2_CMD "snmpset -v2c -c private 192.168.22.4 .1.3.6.1.4.1.42505.6.2.3.1.3"
eva uc cvar set REL2_UPDATE_CMD "snmpget -v2c -c public 192.168.22.4 .1.3.6.1.4.1.42505.6.2.3.1.3"

This relay returns the status of each port separately. Additionally, there is only one connected device and, therefore, we won’t create a multiupdate for the unit and let it update the state with its own update script.

Create a script named xc/uc/lamp1_update

#!/bin/sh

${REL1_UPDATE_CMD}.1 | cut -d: -f2 | awk '{ print $1 }'

and the action script xc/uc/lamp1

#!/bin/sh

${RELAY1_CMD}.1 i $2

Let’s update the lamp state every 30 seconds:

eva uc config set unit:light/lamp1 update_interval 30 -y
Method 2: with driver

Download PHI module:

eva uc phi download https://get.eva-ics.com/phi/relays/dae_ip16r.py

Load PHI module to controller. This is universal PHI which means you don’t need to specify particular relay host when loading, it may be specified later when you set driver to sensor. But in our example we have only one relay of such type, so let’s specify all options in PHI config:

eva uc phi load relay2 dae_ip16r -c host=192.168.22.4,retries=2 -y

After loading dae_ip16r PHI automatically created driver “relay2.default” with “basic” LPI. As we have a simple logic, let’s use it as-is. Set driver to lamp unit:

eva uc driver assign unit:light/lamp1 relay2.default -c port=2 -y

Let’s update the lamp state every 30 seconds:

eva uc config set unit:light/lamp1 update_interval 30 -y

Now open UC EI, check the setup, switch on/off the units, see how the sensor values are updated.

API keys configuration

Note

If you’ve used “easy setup” for the EVA installation, you can skip this step because all controllers are already connected.

Connect Logic Manager and SCADA Final Aggregator to this controller. Create two API keys for them in etc/uc_apikeys.ini:

[lm]
key = secret_for_lm
groups = #
sysfunc = no
hosts_allow = 127.0.0.1

[sfa]
key = secret_for_sfa
groups = #
sysfunc = no
hosts_allow = 127.0.0.1

After adding the new keys, you need to restart UC, which we’ll do later. Firstly, you should connect it to MQTT.

Notification system configuration

Note

If you’ve used “easy setup” for the EVA installation, you can skip this step because all controllers are already connected.

To let the item states be transferred from UC to other controllers in real time, configure its notification system. Connect the server to the local MQTT:

eva ns uc create eva_1 mqtt:eva:secret@localhost -s plaint1 -y
eva ns uc subscribe state eva_1 -v '#' -g '#'

eva ns uc config eva_1
{
    "enabled": true,
    "events": [
        {
            "groups": [
                "#"
            ],
            "subject": "state",
            "types": [
                "#"
            ]
        }
    ],
    "host": "localhost",
    "id": "eva_1",
    "password": "secret",
    "space": "plant1",
    "type": "mqtt",
    "username": "eva"
}

Looks good. Now restart UC:

eva uc server restart

The configuration of Universal Controller is complete. Let’s proceed to Logic Manager configuration.

Logic Manager configuration

So, let us proceed with our configuration. As soon as Universal Controller is already configured, let us move on with Logic Manager.

Configuring notification system and API key for SFA

Note

If you’ve used “easy setup” for the EVA installation, you can skip this step because all controllers are already connected.

The first step is to connect the server to the local MQTT to allow Logic Manager to receive UC item states in real time:

eva ns lm create eva_1 mqtt:eva:secret@localhost -s plant1 -y

then subscribe the notification system to receive the states of the local logic variables which will be created later:

eva ns lm subscribe state eva_1 -v lvar -g '#'
eva ns lm config eva_1
{
    "enabled": true,
    "events": [
        {
            "groups": [
                "#"
            ],
            "subject": "state",
            "types": [
                "#"
            ]
        }
    ],
    "host": "localhost",
    "id": "eva_1",
    "password": "secret",
    "space": "plant1",
    "type": "mqtt",
    "username": "eva"
}

Add API key for SCADA Final Aggregator in etc/lm_apikeys.ini:

[sfa]
key = secret_for_sfa2
groups = #
hosts_allow = 127.0.0.1

Restart LM PLC:

eva lm server restart
Connecting UC controller

Note

If you’ve used “easy setup” for the EVA installation, you can skip this step because all controllers are already connected.

Connect the local UC to Logic Manager using the key we’ve created in etc/uc_apikeys.ini in the previous part of the tutorial:

eva lm controller append http://localhost:8812 -a secret_for_lm -m eva_1 -y
eva lm -J remote -p S
[
    {
        "controller_id": "uc/uc1",
        "group": "security",
        "id": "motion1",
        "oid": "sensor:security/motion1",
        "status": 1,
        "type": "sensor",
        "value": "0"
    },
    {
        "controller_id": "uc/uc1",
        "group": "env",
        "id": "temp1",
        "oid": "sensor:env/temp1",
        "status": 1,
        "type": "sensor",
        "value": "25.4"
    }
]

Looks correct, sensors are loaded, let’s check the units:

eva lm remote -p U

Let LM PLC reload the items from the connected controller every 60 seconds, if new ones are added in future:

eva lm controller set uc1 reload_interval 60 -y
Building logic

We have two tasks: to switch on the inside ventilation if the temperature is above 25 degrees, and handle the events received from the motion sensor. Do not forget that the inside ventilation should be off from 9pm till 7am. Though this will be later implemented via eva sfa (sfa-cmd) and system cron, we should get it prepared now.

Ventilation logic

We chose our example, as far as the boundary conditions of the sensor is a very common problem for such tasks.

If we solve this problem by creating the following two rules:

  • if the temperature is above 25 degrees, the fan is switched on
  • if below - switched off

the following problem may occur: if the temperature will hover around 25 degrees, the ventilation system will constantly switch on and off. Therefore, a breakdown is highly possible. We can also simply set up chillout_time in the rule.

Due to the flexibility of EVA there is a number of solutions of this problem:

Option 1:

Ventilation is switched on, if the temperature is above 25 degrees, and switched off if it is below e.g. 25.5. The logic will have half a degree gap for the equipment not to be overloaded. If the temperature changes not that quickly, this option would be the best one.

Option 2:

  • Create the rule without a condition activated whenever the env/temp1 sensor changes its value
  • The stop-start logic, as well as the temperature monitoring logic, is fully transferred to the macro executed by the above rule.
  • macro reads the value of lvar ventilation/start_temp (to avoid hardcoding 25 in a macro code and let it have an ability to be changed from outside)
  • To avoid the continuous running of macro, use the rule prop chillout_time. Or even
  • Use unit_status macro function to get the current ventilation status and use macro lock function to block its changing too often e.g. for 5 minutes

The macro code will look like:

if status('unit:ventilation/vi') and \
    value('sensor:env/temp1') < value('ventilation/start_temp'):
  try: lock('ventilation/vi/control', 5, 300)
  except: exit()
  stop('ventilation/vi')
elif not status('unit:ventilation/vi') and \
    value('sensor:env/temp1') >= value('ventilation/start_temp'):
  try: lock('ventilation/vi/control', 5, 300)
  except: exit()
  start('ventilation/vi')

Option 3

Increase update_interval prop of env/temp1 sensor e.g. to 300 seconds. This option will work, though it is not that good because the system will obtain the current temperature with a 5 min delay (or we need to duplicate the sensor in UC and create a quicker one).

Option 4

Add a 5 minutes delay at the end of xc/uc/vi action script, allow vi queues (set action_queue=1 unit prop), and start ventilation from the macro in the following way:

try: lock('ventilation-example3', 5, 10)
except: exit()
# clean up all queued action
q_clean('ventilation/vi')
# exec our action
start('ventilation/vi')
unlock('ventilation-example3')

Not bad, but we loose an ability to exec the actions with w param and get the correct completion status.

Option 5

Use system crontab to copy env/temp1 value to some logic variable every 5 minutes. Then work only with this logic variable. This option is too awkward, the logic of the system crontabs will sooner or later turn into the script hell. Therefore, we will use cron only for the time schedule-based logic, everything else will be done using EVA.

Option 6 - the best one

There are more than 10 options to solve our problem, but we will choose the best one: delayed start. Moreover, we have a condition to run ventilation only in 5 minutes after the temperature becomes >=25. So, we will use this option. The other ones have been reviewed just because this is a tutorial.

Create two logic variables:

eva lm create lvar:ventilation/vi_auto -y
eva lm create lvar:ventilation/vi_timer -y
eva lm set lvar:ventilation/vi_auto -s 1 -v 1

The first one will act as a flag for the ventilation control macro: if the flag is on 1, the control is possible, if off - the ventilation should not be touched. The second variable will act as a delayed start timer.

Create a control macro which satisfies for our current task and the scheduled ventilation switching. We will give it two parameters: the first - what to do with ventilation (0 - switch off, 1 - switch on), the second - who runs it: temperature event, our delayed start timer or a system cron:

eva lm macro create control/vi_control -y

Put a macro code in xc/lm/vi_control.py file

if _1: # if anyone asks to switch on the ventilation
    if _2 == 'event': # if it's an event
    reset('ventilation/vi_timer') # reset delayed start timer
    elif _2 == 'timer': # if it's a timer
        if value('ventilation/vi_auto'):
            start('ventilation/vi') # start ventilation if allowed
    elif _2 == 'cron': # if it's a system cron
        # disable the ventilation automation for everyone but cron
        clear('ventilation/vi_auto', 0):
        start('ventilation/vi') # start ventilation
else: # if it's a command to switch off
    clear('ventilation/vi_timer') # stop the delayed start timer
    if value('ventilation/vi_auto') or _2 == 'cron':
        # in case the command is send by cron or
        # if allowed to stop - stop it
        stop('ventilation/vi')
    if _2 == 'cron':
        # if the ventilation is switched off by cron
        # then enable automation back for everyone
        set('ventilation/vi_auto', 1)

The macro requires 3 rules:

The first one will match if the temperature is above or equal to 25 degrees and activates the delayed start timer (we’ll run this command in EVA shell interactive mode, to avoid screening of special symbols):

eva lm -I
rule create if sensor:env/temp1.value >= 25 then v1_control(1, event)
rule enable <rule_uuid>

The second one will match if the temperature is below 25 degrees and switches the ventilation off (if it’s allowed):

rule create if sensor:env/temp1.value < 25 then vi_control(0, event)
rule enable <rule_uuid>

The third rule will run the macro to turn the ventilation on as soon as the delayed start timer finishes the countdown:

rule create if lvar:ventilation/vi.status == -1 then vi_control(1, timer)
rule enable <rule_uuid>
Motion sensor logic

We will need one variable identifying whether the alarm is switched on or not:

eva lm create lvar:security/alarm_enabled -y
eva lm set lvar:security/alarm_enabled -s 1 -v 0

Additionally, we will need two macros. The first one will send API call to alarm system:

eva lm macro create security/alarm_start -y

put its code to xc/lm/alarm_start.py:

# do not send API calls more than once in 30 minutes
try: lock('alarm-start', expires = 1800)
except: exit()
# call the alarm system API
requests.get('http://alarmserver/api/activate?apikey=blahblahblah')

The second one will check whether the alarm is switched, to either switch on the alarm system or just turn on the lighting:

eva lm macro create security/motion1_handler -y

put its code to xc/lm/motion1_handler.py:

if value('security/alarm_enabled'):
    run('security/alarm_start')
else:
    start('light/lamp1')

Plus the additional rule executing motion1_handler macro when the motion sensor detects an activity:

eva lm rule create
eva lm rule set <rule_uuid> oid sensor:security/motion1/value
eva lm rule set <rule_uuid> condition 'x=1'
eva lm rule set <rule_uuid> macro motion1_handler
eva lm rule enable <rule_uuid> -y

The logic is set up. We can review and test it in LM EI and configure SCADA Final Aggregator configuration to interact with the external applications (in our case - the system cron, for the scheduled ventilation control) and serve the system web interface.

SCADA Final Aggregator configuration

So, let us proceed with our configuration. Universal Controller has already been set up and Logic Manager as well. Therefore, let us move on to SCADA Final Aggregator configuration.

Since the logic has already been implemented, we have only two tasks: to interconnect all the controllers and connect the system cron that will control the ventilation schedule.

Notification system configuration

Note

If you’ve used “easy setup” for the EVA installation, you can skip this step because all controllers are already connected.

The first step is to connect the server to the local MQTT to allow SCADA Final Aggregator to get the state of UC and LM PLC items in real time:

eva ns sfa create eva_1 mqtt:eva:secret@localhost -s plant1 -y

We won’t subscribe the notifier to anything, because all the data are received from it, and there is nothing to send instead.

eva ns sfa config eva_1
{
    "enabled": true,
    "host": "localhost",
     "id": "eva_1",
    "password": "secret",
    "space": "plant1",
    "type": "mqtt",
    "username": "eva"
}

Restart SFA:

eva sfa server restart
Connecting controllers

Note

If you’ve used “easy setup” for the EVA installation, you can skip this step because all controllers are already connected.

The next step is to connect the local UC and LM PLC to SCADA Final Aggregator with the keys created specifically for SFA:

eva sfa controller append http://localhost:8812 -a secret_for_sfa -m eva_1 -y
eva sfa controller append http://localhost:8817 -a secret_for_sfa2 -m eva_1 -y
eva sfa -J remote -p S
[
    {
        "controller_id": "uc/uc1",
        "group": "security",
        "id": "motion1",
        "oid": "sensor:security/motion1",
        "status": 1,
        "type": "sensor",
        "value": "0"
    },
    {
        "controller_id": "uc/uc1",
        "group": "env",
        "id": "temp1",
        "oid": "sensor:env/temp1",
        "status": 1,
        "type": "sensor",
        "value": "25.4"
    }
]

Looks fine, sensors are loaded, let’s check units and logic variables:

eva sfa -J remote -p U
eva sfa -J remote -p LV

Let SFA reload the items from the connected controllers every 60 seconds, if new ones are added in future:

eva sfa controller set uc/uc1 reload_interval 60 -y
eva sfa controller set lm/lm1 reload_interval 60 -y
Connecting external applications

There is only one external application - system cron. We won’t connect it via SFA API, but simply by running eva sfa (sfa-cmd) console application.

We provide this example for one reason: you should always connect your external applications to SFA only. Controllers may be changed and, therefore, the setup may be extended: for example, one Logic Manager may be replaced by the three ones installed on the different servers. However, the local SFA will never be changed. All you need is to connect new controllers to it, and EVA item infrastructure will be available again by its usual ID.

The next step it to connect cron for it to run ventilation control macro (edit /etc/crontab or user’s crontab):

0 7 * * *    root   /path/to/eva sfa macro run control/vi_control -a "0 cron"
0 21 * * *    root   /path/to/eva sfa macro run control/vi_control -a "1 cron"

As you can see, there is no rocket science here. SCADA Final Aggregator is configured by a few commands and immediately starts collecting the data and events. In turn, it will save you a lot of time by structuring your setup. Now let’s create User interface that will be served by SFA.

Building an interface with EVA JS Framework

So, let us proceed with our configuration. Universal Controller, Logic Manager and SCADA Final Aggregator have already been configured.

The last step is to create the user interface with EVA JS Framework.

Configuring authentication keys

Note

If you’ve used “easy setup” for the EVA installation, you can skip this step because all controllers are already connected.

Create an SFA API key named operator in etc/sfa_apikeys.ini:

[operator]
key = opsecret
groups = #
pvt = #
hosts_allow = 0.0.0.0/0

and restart SFA:

eva sfa server restart
Configuring users

Create a login for the user to use with operator key:

eva sfa user create john verysecret operator
Framework installation

EVA JS Framework is not included in EVA ICS distribution and should be downloaded manually. Let’s download pre-built JavaScript, full version:

curl https://raw.githubusercontent.com/alttch/eva-js-framework/master/dist/eva.min.js \
    -o /opt/eva/ui/eva.min.js
Create a web application

We’ll use EVA JS Framework to write a simple web application to manage our example setup. Create a new index.html file and put it to ui folder:

If the item ids or other information should be hidden from unauthorized users, the additional .js files with such data may be served by SFA PVT or frontend server with additional authentication.

We’ll use jQuery in this example but of course any JavaScript library can be used, as well as Vanilla JS.

<html>
 <head>
   <title>Plant1 interface</title>
   <script src="jquery.min.js"></script>
   <script src="eva.min.js"></script>
 </head>
<body>
<!-- simple authentication form -->
 <div id="loginform">
    <form onsubmit="do_login(); return false">
    Login:
        <input type="text" size="10" name="login" id="i_login" value="" />
        <br />
    Password:
        <input type="password" size="10" name="password"
            id="i_password" value="" /><br />
         <input type="submit" name="submit" value="GO" />
    </form>
 </div>
 <!-- interface and controls -->
 <div id="interface" style="display: none">
  <div>Temperature: <span id="temp1"></span></div>
  <div>Internal ventilation:
    <a onclick="$eva.call('action_toggle', 'ventilation/vi')" href="#">
        <span id="vi"></span></a>
  </div>
  <div>External ventilation:
    <a onclick="$eva.call('action_toggle', 'ventilation/ve')" href="#">
        <span id="ve"></span></a>
  </div>
  <div>Hall light:
    <a onclick="$eva.call('action_toggle', 'light/lamp1')" href="#">
        <span id="lamp1"></span></a>
  </div>
  <div>Alarm system:
    <a onclick="$eva.call('toggle', 'security/alarm_enabled')" href="#">
        <span id="alarm_enabled"></span></a>
  </div>
  <div style="margin-top: 30px">
    <a onclick="do_logout()" href="#">logout</a>
  </div>
 </div>
 <script type="text/javascript">

 var ed_labels = [ 'DISABLED', 'ENABLED' ];

 // function starting EVA JS Framework after the
 // authentication form has been submitted
 function do_login() {
   $('#loginform').hide();
   $eva.login = $('#i_login').val();
   $eva.password = $('#i_password').val();
   $eva.start();
 }

 // Logout function
 function do_logout() {
   $eva.stop().then(show_login_form).catch(show_login_form);
 }

 // function displaying the authentication form
 function show_login_form(data) {
   $eva.password = '';
   $eva.erase_token_cookies();
   $('#interface').hide();
   $('#i_login').val(eva_sfa_login);
   $('#i_password').val('');
   $('#loginform').show();
   }

 // after the page is loaded
 $(document).ready(function() {
   // after the authentication succeeds the main interface is displayed
   $eva.on('login.success', function(data) { $('#interface').show(); });
   // if there is a login error
   $eva.on('login.failed', function(err) {
       // end session and display the authentication form,
       // if auth data is incorrect
       if (err.code == 2) {
           show_login_form();
           } else {
           // otherwise - repeat the attempts every 2 seconds
           // until the server responds
           setTimeout(function() { $eva.start() }, 1 * 2000);
           }
       }
   // register the event handlers
   $eva.watch(
        'sensor:env/temp1', function(state) {$('#temp1').html(state.value)})
   $eva.watch(
        'unit:ventilation/vi',
        function(state) {$('#vi').html(ed_labels[state.status])});
   $eva.watch(
        'unit:ventilation/ve',
        function(state) {$('#ve').html(ed_labels[state.status])});
   $eva.watch(
        'unit:light/lamp1',
        function(state) {$('#lamp1').html(ed_labels[state.status])});
   $eva.watch(
        'lvar:security/alarm_enabled',
        function(state) {$('#alarm_enabled').html(ed_labels[state.value])});
 })
 </script>
</body>
</html>

Our setup is complete. Interface is available at the following address:

http(s)://<IP_address_SFA:Port>/

The default port for SFA is 8828.

Authentication

API keys

Default and custom API keys

API keys are the primary entities of EVA ICS authentication and access control checking.

After the installation, the following API keys are created automatically:

  • masterkey primary (super) key with an unlimited access to any resource. One master key always should be present in the controller configuration.
  • default default key for controller inter-connections. Has an access to all items, no access to system and master functions and has allow=cmd,[device]
  • operator default user key. Similar to the default key, but with allow=lock

Custom API keys can be created either in the controller key configuration (etc/<controller>_apikeys.ini, static, requires controller restart on changes), with Common methods key management functions or with command-line interface (dynamic, stored either in “db” or in “userdb”). Master keys can be created only in the controller key configuration file, the default master key (with id masterkey) can also be changed for all installed components at once, using eva masterkey CLI command.

Note

Each EVA ICS component has own key set, even if all components are running under the same installation. Sharing API keys configurations and/or database is not recommended.

All API keys are loaded and cached during the controller startup, to speed up API responses.

API key properties and ACL

The current ACL can be obtained with “test” API/CLI command. Key properties can be modified with Common methods key management functions or with command-line interface. “Static” keys, defined in the key configuration files, can not be re-configured dynamically.

API key properties:

  • allow key allow list:

    • cmd access to remote command call service functions
    • lock access to lock management functions
    • device (for Universal Controller only) access to device templates functions
  • cdata list of custom data. Can be set to any custom values (up to 16384 characters), appears in serialized ACL as-is. The field is a list, if set from string, it is automatically split with commas.

  • dynamic read-only value, specifying is the key “dynamic” (True, stored in the db) or “static” (False, defined in the key config file)

  • groups comma-separated item groups the key has an access to (despite of item types). MQTT-style wildcards (‘#’, ‘+’) are allowed (e.g. “#” = access to the all items).

  • groups_deny comma-separated item groups the key has no access to (e.g. wildcard is used in groups but some groups are excluded from ACL). The key still has read-only access if allowed with other ACL properties.

  • groups_ro same as groups but for read-only access.

  • hosts_allow comma-separated list of hosts/networks the key has the access from.

  • hosts_assign comma-separated list of hosts/networks to automatically set the key for any non-authenticated API requests

  • id key ID, unique

  • items, items_ro same as groups, but grant an access to the specified items. Wildcards aren’t possible.

  • items_deny same as groups_deny but for individual items

  • key key itself (up to 64 characters). Filled with 32 random chars automatically after creation

  • master key is the master key if set to True

  • pvt, rpvt comma-separated lists for SFA PVT/RPVT ACLs.

Users

Unlike the typical approach, when a user is the primary authentication entity and can have one or multiple API keys, EVA ICS authentication works in the opposite way: API keys are the primary entities and there could be one or more users linked to the each one. Consider, for the users, API keys act as ACL groups.

The approach may look strange, but there’s a strong reason to work in this way: all external resources (EVA ICS controller inter-connections, 3rd party apps) should always use API keys only, while user accounts are generally used only for authentication via web-interfaces. Majority EVA ICS installations have no user accounts at all, while all setups require API keys for control and management.

When such approach is used, there’s also no reason to have “service” user accounts for the service functions.

Users can be created with Common methods user management functions or with command-line interface.

API calls can not be performed with user accounts directly, the users must login and obtain API session tokens.

Combined ACLs

As API keys are used as user ACLs, a user can have more than one API key assigned locally or with Active Directory groups.

If more than one key (so more than one ACL) is assigned:

  • item ACLs, cdata and allow/assign hosts/networks are merged as-is, including deny ACLs
  • special ACLs are merged with higher access level (e.g. if one of keys has master access, the combined ACL will have master access as well)
  • to assign multiple API keys to a local user, separate them either with commas (in CLI) or send as list (create_user API function).
  • key id in reports and test API function has the value “comb:KEY_1+KEY_2+…KEY_N”
  • the key gets an additional field combined_from which contains a list of key ids the ACLs are combined from.

Only authenticated users can have combined access. Combined API keys are generated for internal purposes only and there is no way to obtain them for direct API requests (use users’ session tokens instead).

IaC and deployment

EVA ICS supports infrastructure-as-code paradigm, providing a way to deploy items and their params from deployment files in YAML format.

Live deployment examples can be found in EVA ICS demos:

Deployment is possible only on SFA servers.

Note

To allow deployment, SFA must have child controllers connected in management mode (connected controllers master keys should be set). Also, cloud manager feature should be enabled in SFA configuration file.

Deployment configuration file

Deployment configurations are stored in YAML files, which have the following format:

Controllers

Section controller contains:

Common variables setup

Here’s an example to set two cvar values:

controller:
    uc/controller1:
        cvar:
            var1: value1
            var2: value2
Driver setup

Here is an example, which:

  • Loads two PHI vrtrelay modules into Universal Controller uc/controller1 as vr1 and vr2. The second module has configuration option state_full=true.
  • Creates vr1.opener driver using vr1 PHI module and multistep LPI.
controller:
    uc/controller1:
        phi:
            vr1:
                module: vrtrelay
                # src: path/to/module
            vr2:
                module: vrtrelay
                config:
                    state_full: true
        driver:
            vr1.opener:
                module: multistep
                config:
                    bose: true

“src” field tells deployment function to get PHI module from file or URL and upload it to the target controller.

API keys and local users

Keys can contain any valid key properties, local user accounts MUST have both “password” and “key” properties set.

controller:
  uc/controller1:
    key:
      tkey1:
        key: verysecret1
        groups:
          - plant1/#
          - plant2/#
        sysfunc: true
        allow:
          - lock
          - cmd
      tkey2:
        key: verysecret2
        groups: "#"
        allow:
          - device
    user:
      test1:
        password: "iu4i32j432s"
        key: tkey1
      test2:
        password: "u89132u2183"
        key:
          - tkey1
          - tkey2
Uploading files

Local files can be uploaded into remote controller runtime directory:

controller:
    uc/controller1:
        upload-runtime:
            - localfile:remotefile
            - localfile2:path/to/remotefile2

File list: local/remote files, separated with “:”. If remote directory doesn’t exist, it will be created automatically.

It’s possible to use masks for local files, e.g. in the example below, contents of “bundle” directory will be uploaded to remote node “runtime/upload”, directory structure will be duplicated as-is.

controller:
    uc/controller1:
        upload-runtime:
            - bundle/*:upload/

Note

To upload directory contents recursively, set file mask to **

It’s possible to keep content in the deployment file as well. In this case, use “file_put” API function to create the remote file:

controller:
  uc/controller1:
    before-deploy:
      - api: file_put
        i: upload/test.yml
        m: |
          test: true
          test2: false
          tags:
            - valid: true
              x: 2
            - valid: true
              x: 3

File paths:

  • if the file path starts with http: or https:, it’s processed as URI
  • if the file path starts with “/”, it’s considered as absolute
  • if the file path starts with “./” it’s relative to the current directory
  • otherwise, the file path is relative to the directory where the deployment file is located
Before/After deploy
Remote calls

Note

EVA ICS architecture does not allow Cloud Manager to execute API calls on remote SFAs. Use the remote node UC or LM instance to act as the agent for that.

Controller API calls may be automatically executed after deployment is complete:

controller:
    lm/lm1:
        before-deploy:
            - api: reset
              i: timers/timer1
        after-deploy:
            - { api: clear, i: timers/timer1 }
            - { api: reload_controller, i: uc/uc1 }
            - { api: reload_controller, i: uc/uc2 }
            - api: custom_fn
              _pass: true
              param1: 123
              param2: "x"

API calls are always executed in the specified order, one-by-one, api: field contains API function to execute, others specify function parameters. The special parameter _pass in the last call allows deployment to ignore failed API call (warning will be printed).

Custom API call timeout can be defined with special parameter _timeout.

Note

It is usually recommended to call reload_controller for Logic Manager to let it instantly load newly deployed items from connected UCs for EVA ICS prior to 3.3.2.

Starting from 3.3.2, if units or sensors were deployed, all LM PLCs, listed in “controller” section, are reloaded automatically. If a LM PLC has no deployment configuration, it should be listed as an empty dict:

controller:
  lm/lm1: {}
Local calls

Sometimes it’s useful to call local SFA function deployment process. This can be done with directive “cm-api” which has the same format as “api” for remote calls:

controller:
    lm/lm1:
        before-deploy:
            - api: reset
              i: timers/timer1
            # just for a test
            - cm-api: reload_controller
              i: lm/lm1

The local calls can be also merged into “local” controller section. The section can contain any before/after deploy commands, which are executed on local SFA:

controller:
  local:
    after-deploy:
      - install-pkg: test.evapkg
        o: { x: 2 }
        w: 5

The “local” section is always executed after all other controllers’ sections.

Additionally, local SFA resources, allowed to be deployed:

  • API keys
  • user accounts
Installing packages

A package can be installed during any deployment stage.

Syntax:

controller:
  uc/uc1:
    after-deploy:
      - install-pkg: /path/to/package.evapkg
        o: { x: 2 }
        w: 5
Additional deploy functions
sleep

Delays execution of next before/after deploy commands. E.g. let’s reload remote UC and wait 5 seconds until its core is restarted:

controller:
  uc/uc1:
    after-deploy:
      - api: shutdown_core
      - function: sleep
        args: [ 5 ]
system

Executes (local) system command:

controller:
  uc/uc1:
    after-deploy:
      - function: system
        args: [ 'ls' ]
Loops, conditions and variables

Deployment files are pre-processed as Jinja2 templates and may contain any valid Jinja2 tags and variables.

The pre-set variable “time_ns” contains current UNIX timestamp (in nanoseconds), which can be used e.g. as “no-cache” value for bypassing cache of proxied external resources.

It’s also possible to import any external Python module with “import_module” function:

{%- set io=import_module('io') %}
{%- set units=io.open('units.list').readlines() %}
unit:
  {%- for u in units %}
  {{ u.strip() }}:
    controller: uc/uc1
  {%- endfor %}
Items

Control and monitoring items can be deployed with unit, sensor and lvar sections. All sections are similar, the format is:

unit:
    group1/u1:
        controller: uc/uc1
        action_enabled: true
        update_interval: 0
        status: 0 # initial status, optional
        driver:
            id: vr1.default
            config:
                port: 1

All child fields specify item properties, except:

  • Field controller specifies controller, where item should be deployed
  • For units and sensors, driver field may be used to assign driver to the item.

Note

It is not necessary to list the target controller in “controller” section, unless it needs to be additionally configured (e.g. load drivers/PHIs)

If action_exec or update_exec values are started with ^ symbol, it tells deployment tool to upload local file on the controller.

Setting “status” field to “update” asks the controller to trigger item update after deployment:

unit:
    group1/u1:
        controller: uc/uc1
        # ....
        status: update

The second example shows how to deploy a sensor and logical variable:

sensor:
    group1/s1:
        controller: uc/uc1
        driver:
            id: somedriver.default
            config:
                port: 1
        value: 77 # initial value, optional, initial status for sensor
                  # is not required (automatically set to 1 - enabled)

lvar:
    group1/timer1:
        controller: lm/lm1
        expires: 30
        status: 0 # initial status, optional
        value: 77 # initial value, optional
Macros

Logic macros are deployed in lmacro section:

lmacro:
    group1/macro1:
        controller: lm/lm1
        action_exec: ^macro1.py

All child fields specify item properties, except:

  • Field controller specifies Logic Manager, where macro should be deployed

If field action_exec value is started with ^ symbol, it tells deployment tool to upload local file on the controller.

Note

To make deployment process more easy, it is recommended to start it in directory, where macro files are located.

Logical rules

Decision-making matrix can be configured with dmatrix_rule section.

Rule example:

dmatrix-rule:
  5ef9b8fd-d527-44ce-ae89-9629afd40d76:
      controller: lm/farm-scada
      description: light normal
      enabled: true
      oid: "sensor:#/ldr.value"
      condition: x = 1
      break_after_exec: true
      macro: stop_lamp
      macro_kwargs:
        lamp_id: 1

All child fields specify item properties, except:

  • Field controller specifies Logic Manager, where rule should be configured

Rule UUID should be pre-generated with any UUID generator, e.g. with uuidgen Linux console command.

Scheduled jobs

Jobs can be deployed the similar way as rules:

job:
  e407f61c-a251-455b-92bc-9eee9adcb93b:
    controller: lm/lab-ws2
    description: "scheduled job 1"
    enabled: true
    macro: do_scheduled_task
    macro_args: [ 'task1' ]
    every: "wednesday at 12:00"
Cycles
lcycle:
  test:
    controller: lm/lab-ws2
    description: "scheduled job 1"
    interval: 1
    macro: do_cycle1
    macro_args: [ 'task1' ]

How to deploy configuration

Currently there is no API functions for deploy EVA ICS configuration. The item configuration can be deployed either via CLI or during installation.

Deployment via CLI
Deploying

Deployment configuration can be applied using eva sfa cloud deploy command. When deployed with CLI, deployment file may contain variables.

Example:

unit:
    light/room1:
        controller: uc/{{ srv }}

Here is srv variable defined. To set its value, e.g. to “uc1”, use -c srv=uc1 command line argument. If multiple variable values are set, they should be comma separated, e.g.: -c srv1=uc1,srv2=uc2 etc.

There’s also command line argument -u which tells CLI to try undeploying target configuration before doing deployment of it. Undeployment process ignores missing items and deletes only existing.

Undeploying

Deployment configuration can be removed with eva sfa cloud undeploy command. Custom variable values can be set in the same way as during deployment.

Deployment during installation

Configuration also can be deployed with easy-setup during SFA installation. Use –deploy FILE command line argument to specify path to the deployment file.

Complex deployments
Bare-metal

Sometimes deployment is more complex than just creating items. In this case deployment scripts are used to prepare environment, call eva sfa cloud deploy command and finish deployment.

Containers

There is no problems when the regular bare-metal or virtual machine installation is performed, but if EVA ICS is being installed into Docker machine or Kubernetes cluster, there is a special environment variable after_install, which tells EVA ICS Docker image to execute deployment script after installation process is finished. Here’s an example part of docker-compose file:

eva-scada:
    environment:
        - after_install=/deploy/deploy.sh
Devices

Starting from EVA ICS 3.3.2, device template format is equal to IaC files.

For cvar deployment, a proper “controller” property should be present in the device template. In “unit” and “sensor” sections, “controller” property is not required and ignored if present.

FAQ

Is this a “smart home”?

EVA ICS is a universal system used for the construction of both “smart home” and automated control system (ICS) in an industrial enterprise.

In fact, most products positioning themselves as “smart home” are just dumb control panels with a web interface. Moving light switch from the wall to the screen doesn’t make it “smart”. In turn, our system is equipped with a powerful and constantly evolving Logic Manager for automatic decision-making.

Is this IoT?

In a way, yes. As far as IoT is a part of the automation process, we are a part of IoT, in turn. However, from the thousands of components positioning themselves as “IoT”, we choose only those working:

  • Reliably
  • Safely
  • Autonomously

And, most preferably, having an open API to be connected to any system.

The classic situation typical for IoT market involves controlling your device via the Internet with the help of software on the developer servers (aka “clouds”). As you can see it is:

  • Unreliable
  • Dangerous
  • Not autonomous

Moreover, you can’t seriously use it even at home. Our system doesn’t require registration, we don’t need your phone number, email or home address - just download, install and use it. The system works only for you and sends data to no one but you. The code is fully open, so that you can control everything that’s going on. The system doesn’t require Internet access. Everything works fine in the secure local network.

If the system is free and open, what is your interest?

We have been engaged in the automation activities for both private and enterprise sectors for many years. Our clients work with different systems, including previous versions of EVA ICS. The development of EVA ICS v3 is the step towards unification of all configurations that we support and use ourselves.

We decided to distribute the new system completely free of charge, but we provide commercial support for setups where reliability is of critical importance. We are also developing and integrating complex configurations, create additional commercial EVA applications and interfaces for specific systems.

In addition, if:

  • you want to become a system integrator and provide commercial support * you want to distribute our system together with your device
  • you want to make us an offer we can’t refuse

you should contact us and we will make a suitable offer to you.

Is EVA ICS complicated and difficult to learn?

We try to keep our system simple and user-friendly, even for those who have never encountered the process automation.

Is it reliable?

It is reliable enough for home and office setups, as well as for small industrial configurations, but if you use EVA on an enterprise, you should perfectly understand EVA ICS platform principles.

How about security?

Traditionally, automation systems and protocols have been designed as not completely secure. As for reliability, you may agree that it would be a pity if motor or door gets stuck because of incorrect access rights to a folder or an expired SSL certificate. We recommend to have an optimal balance between stability and security and it’s really different for every setup.

What programming languages can I use to write scripts and macros?

As for scripts - you can use any. A script or a program runs as a separate process in the system. It’s only necessary that it reads the input parameters correctly and writes the result in an appropriate format. If you need speed - PERL or DASH are preferred. If speed is not so important, you may use BASH or even PHP.

Logic Manager macros are written in Python, but in most cases, you’ll need to call the internal macro functions only.

Besides, you can create your own applications working through API. The distribution includes API clients for Python and PHP.

What if I have zero experience in programming?

Programming for EVA is only about creating item management scripts. You can find plenty of examples in the documentation.

Additionally you need to program Logic Manager macros for process automation. However, most macros have a very simple structure and call the in-built set of functions.

For example, a macro that runs a pump for watering plants:

# call API action for pump1, controller will be identified automatically
start('farm/pumps/pump1')
# reset the timer for watering
reset('farm/pump1_run')
# message to the log file
info('watering cycle has been started')
# assign "watering" value to the production cycle variable
set('farm/pump1_cycle', 'WATERING')

As you can see, it is not rocket science.

What automation is all about? What are automation components?

The automation components mostly look like relay block, “smart” sockets, “smart” switches - however, there is still some kind of relay inside. Usually, there are 3 ports in the relay: input, two outputs, and two states: open and closed. In the first state, the signal passes through the first output, in the second one - through the second. This is the main principle automation is based on.

Sometimes equipment may include controlled resistors, so that additional parameters (e.g. light dimmer) should be set. In this case, you should send additional value to the controller, e.g. to set a definite percent of capacity.

Our system works not with relay, but with endpoint equipment that is automated. The relay ports are programmed and switched with the help of scripts, which are written once during installation. Thereafter, the system works with the units.

Besides, any automation system has its “eyes” and “ears” for receiving data from the environment and making its own decisions - humidity and temperature sensors, motion sensors etc.

In EVA, all decisions are made either by the user or Logic Manager subsystem.

Is EVA ICS IEC 61131-3 compliant?

EVA Logic Manager is a “cloud” PLC and can’t handle events in real-time. EVA ICS is not a hardware PLC replacement, it brings together equipment of different kind and automates the tasks usually performed by the system operator manually.

However new local nearly real-time PLC and support of ST and FBD languages are planned in the next releases. We are hardly working on it!

Where is the interface? I want a web interface!

Each automated setup needs an interface. EVA has a very powerful SCADA Final Aggregator component, which combines the whole setup itself and provides a flexible EVA JS Framework which allows you to create a modern websocket-powered web interface with a few strings of JavaScript:

$eva.apikey = 'MY_VERY_SECRET_KEY';
$eva.watch'sensor:env/temperature1',
    function(state) {
        document.getElementById('temp1').innerHTML = state.value;
    }
$eva.start();

no rocket science as well.

Why EVA ICS has 3 different APIs?

EVA ICS goal is to allow any possible client perform API calls.

We have the plan to keep only JSON RPC API in EVA ICS v4. Starting from EVA ICS 3.3.2, there is a way for the old hardware to send JSON RPC requests via HTTP/GET, so direct API calls are deprecated.

High-load environments

Tuning EVA ICS

To use EVA ICS in high-load environments, remember the following:

  • Always turn off debug mode. Debug mode significantly slows down all EVA ICS components.
  • Make sure no notifiers are subscribed to the frequently (more than ~10 times per second) updated item states. If you need to synchronize states of such items, reduce remote controller reload intervals instead but set them higher than 1 second.
  • Unsubscribe notifiers from INFO log messages and actions
  • Replace db_updates = instant in Universal Controller configurations with on_exit or manual.
  • If instant state database updates are strongly required, switch to MySQL or PostgreSQL (use option db instead of db_file in controller config).
  • If you don’t need action history, set keep_action_history in controllers’ configuration to zero to disable it.
  • Turn off logging (comment log_file property in configuration file) and reduce keep_logmem value.
  • Increase logging level to warning or error using logging_level config option in [server] section.
  • If you use passive updates, set polldelay to the minimal value (0.001 - 0.005 for 1-5ms)
  • If HTTP API respond too slow, try increasing value of thread_pool option in [webapi] config section.
  • Modbus slave and some utility workers use twisted reactor thread pool. In case the software reacts or performs regular tasks slowly, but system load is still low, try increasing value of reactor_thread_pool option in [server] section.
  • If item states should be collected from the equipment which doesn’t send events (e.g. Ethernet/IP, Modbus slaves, SNMP without traps), it’s recommended to use data pullers.

Hardware

Thanks to EVA ICS architecture and optimization for modern multi-core CPUs, the platform can provide good results even on a microcomputers. System components and CLI tools may require more time to launch on architectures different than Intel x86_64, but the regular performance should not be affected even on an embedded ARM-based systems.

According to tests, EVA ICS can show bad performance (slow startup/shutdown) on industrial and micro computers if they have:

  • small amount of RAM (minimum 512 MB is recommended)
  • slow SSD drive or SD card.

We strongly recommend using at least UHS-I SD cards which can show a speed up to 100 MB/s.

Benchmarks

Benchmark tests for Universal Controller can be performed with tests/benchmark-uc-crt tool. Benchmark results may be different on a systems with different background load, so please stop all unnecessary processes before starting a test.

The primary parameter for UC which is benign benchmarked is a time, required for the controller to:

  • obtain item state from driver
  • perform a simple in-core event handling (convert item value to float and then compare with a float number) with self thread-locking
  • get action request from event handler and execute it using another driver

The time between a moment when the first driver gets new item value and a moment when the second driver is ready to call equipment action is named Core Reaction Time (CRT).

The benchmark tool for Universal Controller turns on internal controller benchmark, performs 1000 CRT tests with 30ms delays on a single sensor/unit pair and displays the average CRT value in milliseconds.

The benchmark is performed on virtual drivers, so the actual system reaction time may be higher than CRT, depending on the equipment connected.

Warning

It’s not recommended to perform a real benchmarking tests on SOHO and light industry relays due to their limited lifetime (~100-200k switches)

Below are benchmark results on a test systems (lower CRT is better):

System CPU Cores EVA ICS CRT, ms
VMWare ESXi 5.5 Intel Xeon E5630 2.53GHz 1 3.1.1 2018101701 4.5
VMWare ESXi 5.5 Intel Xeon E5630 2.53GHz 4 3.1.1 2018101701 3
VMWare ESXi 5.5 Intel Xeon D-1528 1.90GHz 1 3.1.1 2018101701 5
VMWare ESXi 5.5 Intel Xeon D-1528 1.90GHz 4 3.1.1 2018101701 3.5
Supermicro X9SXX Intel Xeon E3-1230 V2 3.30GHz 8 3.1.1 2018101701 4
Supermicro E100 Intel Atom E3940 1.60GHz 4 3.1.1 2018101701 8.5
Raspberry Pi 1A ARMv6 rev 7 v6l 1 3.1.1 2018101701 110
Raspberry Pi 2B ARMv7 rev 5 v7l 4 3.1.1 2018101701 22.5
Raspberry Pi 3B+ ARMv7 rev 4 v7l 4 3.1.1 2018101701 21
UniPi Axon S115 ARMv8 Cortex-A53 4 3.1.1 2018101701 27

According to tests, EVA ICS 3.2 is about 15% faster than 3.1.1

Universal Controller

EVA Universal Controller (UC) is a control and monitoring subsystem.

It should be installed if you actually want to control something. UC is controlled via UC EI web interface or eva uc (uc-cmd) console application. Additionally, it can be integrated into other subsystems and third-party programs using UC API.

Universal Controller subsystem

You may use Universal Controller independently or integrate it with other EVA subsystems.

Units receive control actions, the controller forms them into queues and executes them using external scripts. If necessary, it terminates the current script and keeps the command history.

Additionally, Universal Controller collects data from the connected items using active and passive status updates.

Universal Controller can control equipment directly and/or act as a gateway for other local controllers.

Item status and values are stored in the local database. Other subsystems or third-party programs can read them using UC API.

Units and sensors are controlled via UC EI interface, configured via UC API. States are controlled and updated using drivers and item scripts.

All changes of item status, current control commands, and progress logs are sent to the notification system.

UC POLL DELAY

EVA is a real-time system. Being one of its essential components, UC also follows this rule. The value of poll delay is set in configuration in seconds (milliseconds using dot), e.g. 0.01.

The value of POLL DELAY means that all timeouts and events in the system should fulfill their functions for not more than TIME_SET + POLL DELAY.

Reducing POLL DELAY will increase the CPU load on the server; in turn, if increased, the UC reaction time will be longer. Recommended values: 0.1 for home and office, 0.01 and less - for industrial applications.

The optimum value of POLL DELAY for UC can be set via eva sfa, or by manually calling UC API functions and comparing reaction/execution time of the commands.

The minimum value of POLL DELAY is 0.001 (1 millisecond).

etc/uc.ini configuration file

uc.ini - primary configuration file of UC server

[server]
; system name (default - hostname)
; name = eva-uc1
; system polldelay
polldelay = 0.01
; pid file (default var/uc.pid)
pid_file = var/uc.pid
; log file
log_file = log/uc.log
; custom primary log format (use double %)
;log_format = { "loggerName":"%%(name)s", "timestamp":"%%(asctime)s", "pathName":"%%(pathname)s", "logRecordCreationTime":"%%(created)f", "functionName":"%%(funcName)s", "levelNo":"%%(levelno)s", "lineNo":"%%(lineno)d", "time":"%%(msecs)d", "levelName":"%%(levelname)s", "message":"%%(message)s" }
; logging to local syslog
;syslog = yes
; logging to non-standard (/dev/log) local syslog socket
;syslog = /var/run/syslog
; logging to remote syslog
;syslog = hostname:514
; db updates - instant, manual or on_exit
; custom syslog format (use double %)
;syslog_format = EVA: { "loggerName":"%%(name)s", "timestamp":"%%(asctime)s", "pathName":"%%(pathname)s", "logRecordCreationTime":"%%(created)f", "functionName":"%%(funcName)s", "levelNo":"%%(levelno)s", "lineNo":"%%(lineno)d", "time":"%%(msecs)d", "levelName":"%%(levelname)s", "message":"%%(message)s" }
db_update = instant
; db file, default runtime/db/uc.db
db_file = runtime/db/uc.db
; use MySQL instead of SQLite
;db = mysql+pymysql://user:password@localhost/dbname
; user db file, default = db_file
; one user db may be used by multiple controllers at once
;userdb_file = runtime/db/users.db
; use MySQL instead of SQLite
;userdb = mysql+pymysql://user:password@localhost/dbname
; launch external script/program when user is created/got new
; password/destroyed. additional arguments:
;    1) create | set_password | destroy
;    2) user
;    3) password (for create and set_password operations)
;user_hook = /opt/eva/xbin/htpasswd.sh /opt/eva/etc/htpasswd
; keep action history in seconds
keep_action_history = 86400
; action cleaner interval, in seconds
action_cleaner_interval = 60
; keep memory log in seconds
keep_logmem = 86400
; keep extended API call log in user db in seconds (0 = disable logging)
;keep_api_log = 0
; notify state on start
notify_on_start = yes
; debug mode
debug = no
; show error traceback
;show_traceback = yes
; logging level, info, warning, error or critical
;logging_level = info
; create crash dump on critical errors
dump_on_critical = yes
; stop server on critical errors (will be restarted via safe-run)
; always - stop on all critical errors
; core - core errors only (ignore driver critical errors)
; no - don't stop
stop_on_critical = always
; default timeout
timeout = 5
; layout (simple or enterprise)
layout = enterprise

; primary thread pool, min workers. comment to pre-spawn all workers
;pool_min_size = 0
; primary thread pool, max workers. comment to use automatic value (nCPUs * 5)
;pool_max_size = 100
; reactor thread pool size (used by Modbus slave and some utility workers)
;reactor_thread_pool = 15

; exec commands before/after config/db save,
; e.g. mount -o remount,rw / (then back to ro)

;exec_before_save =
;
;exec_after_save =

; default mqtt notifier for updates for new items
;mqtt_update_default = eva_1:2

; plugins, comma separated
;plugins =

;[msad]
; user authentication via MS Active Directory
;host = ad.yourdomain.com
;domain = yourdomain.com
;key_prefix =
;ou = EVA
;ca = /path/to/ca-file.crt
; cache credentials for the specified time (seconds)
; default: 86400 (1 day), 0 to disable caching
;cache_time = 86400

[upnp]
; allow UPnP discovery of this controller
listen = 0.0.0.0

[sysapi]
; enable remote file management functions
file_management = yes
; allow entering setup mode
setup_mode = yes
; allow rpvt
;rpvt = yes

[webapi]
; web api listen on IP/port
listen = 0.0.0.0:8812
;ssl_listen = 0.0.0.0:8813
;ssl_module = builtin
;ssl_cert = test.crt
;ssl_key = test.key
;ssl_chain = test.pam
; session timeout, set to non-zero to enable API session tokens
session_timeout = 3600
; session tokens will expire even if active requests are received
;session_no_prolong = yes
; server thread pool
;thread_pool = 15
; uncomment to disable UC EI
;ei_enabled = no
; uncomment to use frontend X-Real-IP header to get client real IP address
;x_real_ip = yes

[mailer]
; mailer for mail() macro function
smtp = localhost:25
from = eva@eva3-uc1
default_rcp = admin@localhost, root@localhost
;ssl = yes
;tls = yes
;login = smtp_login
;password = smtp_password

[snmptrap]
; snmp trap handler, default community is eva
listen = 127.0.0.1:162
community = eva
; hosts, allowed to send snmp traps
hosts_allow = 127.0.0.0/8

[udpapi]
; udp api
listen = 127.0.0.1:8881
; hosts, allowed to send UDP commands
hosts_allow = 127.0.0.0/8
hosts_allow_encrypted = 0.0.0.0/0

[modbus]
; modbus slave configuration
; first number indicates modbus address (hex or decimal)
; multiple values can be specified
; modbus slave memory space size: 10000 registers (starting from 0) for each
; type (holding, input, coils, discrete inputs)
;tcp0 = 0x01,0.0.0.0:502
;udp0 = 0x01,0.0.0.0:502
; framer for serial: rtu, ascii or binary
;serial0 = 0x01,rtu:/dev/ttyS0:9600:8:N:1
;serial1 = 0x05,rtu:/dev/ttyS1:9600:8:N:1

[datapullers]
;dp1 = /opt/dp/datapuller1 -c /opt/dp/config.yml
;dp2 = /opt/dp2/datapuller2
;dp3 = datapuller3 -c /etc/dp3.ini

runtime/uc_cvars.json variables file

uc_cvars.json - file containing user variables passed to all commands and item scripts within the system environment.

The file contains a JSON dict:

{
 "VAR1": "value1",
 "VAR2": "value2"
}

Variables can be changed while the server is running via Common methods as well as eva uc cvar_get and cvar_set commands.

For example, let’s create a variable:

eva uc cvar set RELAY1_CMD "snmpset -v1 -c private 192.168.1.208 .1.3.6.1.4.1.19865.1.2."

After UC is started, it will become available for system environment, and unit management script on the port 2 of the given relay will be the following:

#!/bin/sh
${RELAY1_CMD}.1.2.0 i $2

It’s possible to assign different values for the variables used for different object groups with the same names, e.g. group1/VAR1, group2/VAR1 etc. In this case the variable will be available only for the specified group.

etc/uc_apikeys.ini API keys file

API access keys are stored into etc/uc_apikeys.ini file. At least one full access key named masterkey should be present for proper functioning. Important: with master key and API anyone can receive full access to the system similar to root user (or the user UC is run under), that is why it is recommended to use this key only in supervisory networks or even restrict its use to local host only.

[masterkey]
; the default master key is eva, change it!
key = eva
master = yes
hosts_allow = 127.0.0.1

;[key1]
;key = key1secret
;groups = group1/#, group2, group3/+/somegroup
;hosts_allow = 0.0.0.0/0

;[key2]
;key = key2secret
;items = unit1, unit2
;sysfunc = yes
;allow = cmd, lock, device
;hosts_allow = 0.0.0.0/0
; key will be assigned to requests from these hosts if no key provided
;hosts_assign = 192.168.1.1

;[lm]
;key = lmsecret
;groups = #
;sysfunc = yes
;allow = cmd
;hosts_allow = 127.0.0.1, 192.168.0.0/16

;[sfa]
;key = sfasecret
;groups = #
;hosts_allow = 127.0.0.1, 192.168.0.0/16

Action queues

All the unit control actions are queued right after they’re created. Item status update actions are not queued and just run in accordance with the set intervals.

Before execution, the control action is placed in two queues:

  • global queue for all actions
  • certain unit queue

All actions have their “priority” set when they are generated. The default priority is 100. The lower means the higher priority of queued action execution.

Queued action can have the following status:

  • created action has just been created and has not been queued yet
  • pending the action is placed in the global queue. The previous action status, as well as this one, are rarely found because UC API waits for the command to be placed in the queue of a certain unit and then returns the result
  • queued the action has already passed the global queue and is now waiting to be executed in the queue of a certain unit
  • refused unit rejected the action execution because of the item configuration value action_enabled=False
  • dead API failed to wait until the action is placed to the queue of a certain unit and, therefore, marked it as “dead”. Virtually, such status clearly indicates that server is seriously overloaded
  • canceled the command is canceled either from the outside or due to either unit already running the other action (in case action_queue=0 and queue is disabled) or the unit has got new action to execute and action_queue=2 (cancel and terminate the pending actions after getting a new one)
  • ignored the unit rejected the action execution, because its status/value are the same as requested to be changed to, and action_always_exec=False
  • running the action is being executed
  • failed the controller failed to execute the command
  • terminated the controller terminated the action execution due to timeout or by the external request
  • completed the action finished successfully

Startup and shutdown

To manage UC controller server, use:

  • eva uc server start start UC server
  • eva uc server stop stop UC server
  • eva uc server restart restart UC server
  • eva uc server reload restart controller only (without watchdogs)

The controller startup/shutdown is also performed by ./sbin/eva-control which is configured during the system setup.

Logic Manager

EVA Logic Manager (LM PLC) - is a programmable logic controller.

This subsystem is designed to automatically manage hardware and decision-making process when the metrics are changed. Unlike standard PL controllers, LM PLC is a network-based controller, its mission is to control equipment in local networks and work as cloud controller via the Internet.

LM PLC operations can be event-based, cycle-based, and called manually by used.

LM PLC is customized and controlled via LM EI web interface or eva lm (lm-cmd) console application. It can also be integrated into other subsystems and third-party programs using LM API.

Additionally, you can use console applications for better control of the decision-making rules.

LM PLC additionally introduces one more control and monitoring item: logic variable (lvar). Logic variables are used to save and exchange system status data as well as function as flags and timers for organizing production cycles.

Any change in the status of units, sensors or logic variables is analyzed by the decision-making matrix of a certain LM controller. In case the rule conditions match, the controller calls the indicated macro that performs the specified actions.

Logic variables statuses are stored in the local database and can be accessed via LM API by other subsystems or third-party programs. Status changes are sent via notification system. To let LM PLC operate with the items of UCs in real time, it should be connected to MQTT server.

Since LM PLC is a part of EVA platform, its operating principles, settings, and configuration files generally match the other components.

etc/lm.ini configuration file

lm.ini - primary configuration file of LM PLC

[server]
; system name (default - hostname)
; name = eva3-lm1
; system polldelay
polldelay = 0.01
; pid file (default var/lm.pid)
pid_file = var/lm.pid
; log file
log_file = log/lm.log
; custom primary log format (use double %)
;log_format = { "loggerName":"%%(name)s", "timestamp":"%%(asctime)s", "pathName":"%%(pathname)s", "logRecordCreationTime":"%%(created)f", "functionName":"%%(funcName)s", "levelNo":"%%(levelno)s", "lineNo":"%%(lineno)d", "time":"%%(msecs)d", "levelName":"%%(levelname)s", "message":"%%(message)s" }
; logging to local syslog
;syslog = yes
; logging to non-standard (/dev/log) local syslog socket
;syslog = /var/run/syslog
; logging to remote syslog
;syslog = hostname:514
; custom syslog format (use double %)
;syslog_format = EVA: { "loggerName":"%%(name)s", "timestamp":"%%(asctime)s", "pathName":"%%(pathname)s", "logRecordCreationTime":"%%(created)f", "functionName":"%%(funcName)s", "levelNo":"%%(levelno)s", "lineNo":"%%(lineno)d", "time":"%%(msecs)d", "levelName":"%%(levelname)s", "message":"%%(message)s" }
; db updates - instant, manual or on_exit
db_update = instant
; db file, default runtime/db/lm.db
db_file = runtime/db/lm.db
; use MySQL instead of SQLite
;db = mysql+pymysql://user:password@localhost/dbname
; user db file, default = db_file
; one user db may be used by multiple controllers at once
;userdb_file = runtime/db/users.db
; use MySQL instead of SQLite
;userdb = mysql+pymysql://user:password@localhost/dbname
; launch external script/program when user is created/got new
; password/destroyed. additional arguments:
;    1) create | set_password | destroy
;    2) user
;    3) password (for create and set_password operations)
;user_hook = /opt/eva/xbin/htpasswd.sh /opt/eva/etc/htpasswd
; keep action history in seconds
keep_action_history = 86400
; action cleaner interval, in seconds
action_cleaner_interval = 60
; keep memory log in seconds
keep_logmem = 86400
; keep extended API call log in user db in seconds (0 = disable logging)
;keep_api_log = 0
; notify state on start
notify_on_start = yes
; debug mode
debug = no
; show error traceback
;show_traceback = yes
; logging level, info, warning, error or critical
;logging_level = info
; create crash dump on critical errors
dump_on_critical = yes
; stop server on critical errors (will be restarted via safe-run)
stop_on_critical = yes
; default timeout
timeout = 5
; layout (simple or enterprise)
layout = enterprise

; primary thread pool, min workers. comment to pre-spawn all workers
;pool_min_size = 0
; primary thread pool, max workers. comment to use automatic value (nCPUs * 5)
;pool_max_size = 100

; exec commands before/after config/db save,
; e.g. mount -o remount,rw / (then back to ro)

;exec_before_save =
;
;exec_after_save =

; default mqtt notifier for updates for new items
;mqtt_update_default = eva_1:2

; plugins, comma separated
;plugins =

;[plc]
; set "no" to let LM PLC launch macros without thread pool
; (e.g. useful for handling rare bulk events), default is "yes"
;use_core_pool = yes
; cache state of remote items into local db (seconds ttl), off by default
;cache_remote_state = 86400

;[msad]
; user authentication via MS Active Directory
;host = ad.yourdomain.com
;domain = yourdomain.com
;key_prefix =
;ou = EVA
;ca = /path/to/ca-file.crt
; cache credentials for the specified time (seconds)
; default: 86400 (1 day), 0 to disable caching
;cache_time = 86400

[upnp]
; allow UPnP discovery of this controller
listen = 0.0.0.0
; discover controllers via UPnP on all interfaces, or list, comma separated
discover_on = all

[sysapi]
; enable remote file management functions
file_management = yes
; allow entering setup mode
setup_mode = yes
; allow rpvt
;rpvt = yes

[webapi]
; web api listen on IP/port
listen = 0.0.0.0:8817
;ssl_listen = 0.0.0.0:8818
;ssl_module = builtin
;ssl_cert = test.crt
;ssl_key = test.key
;ssl_chain = test.pam
; session timeout, set to non-zero to enable API session tokens
session_timeout = 3600
; session tokens will expire even if active requests are received
;session_no_prolong = yes
; server thread pool
;thread_pool = 15
; uncomment to disable LM EI
;ei_enabled = no
; uncomment to use frontend X-Real-IP header to get client real IP address
;x_real_ip = yes

[mailer]
; mailer for mail() macro function
smtp = localhost:25
from = eva@eva3-lm1
default_rcp = admin@localhost, root@localhost
;ssl = yes
;tls = yes
;login = smtp_login
;password = smtp_password

[cloud]
;default_key = default

runtime/lm_cvars.json variables file

lm_cvars.json - file containing user variables passed to all logic control macros.

The file contains a JSON dict:

{
 "VAR1": "value1",
 "VAR2": "value2"
}

Variables can be changed while the server is running via Common methods as well as eva lm cvar get and cvar set commands.

etc/lm_apikeys.ini API keys file

API access keys are stored into etc/lm_apikeys.ini file. At least one full access key named masterkey should be present for proper functioning. Important: with master key and API anyone can receive full access to the system similar to root user (or the user LM is run under), that is why it is recommended to use this key only in supervisory networks or even restrict its usage to local host only.

[masterkey]
; the default master key is eva, change it!
key = eva
master = yes
hosts_allow = 127.0.0.1

;[key1]
;key = key1secret
;groups = group1/#, group2, group3/+/somegroup
;hosts_allow = 0.0.0.0/0

;[key2]
;key = key2secret
;items = macro1, lvar1, lvar2
;sysfunc = yes
;allow = cmd
;hosts_allow = 0.0.0.0/0
; key will be assigned to requests from these hosts if no key provided
;hosts_assign = 192.168.1.1

;[sfa]
;key = sfasecret
;groups = #
;hosts_allow = 127.0.0.1, 192.168.0.0/16

Connecting UC controllers

Logic macros and decision-making matrix work only with the items known to the controller, so Logic Manager loads information about units and sensors from the connected Universal Controllers.

Prior to UC connection, it is necessary to connect LM PLC to MQTT server, where other controllers will send the events. Logic Manager reads the list of items and their initial status from the connected controllers; further status monitoring is performed via MQTT. In case MQTT server is inaccessible or has data exchange problems, states of the items are updated on every remote controller reload (reload_interval prop).

To connect UC controllers you should use eva lm console command or LM API append_controller function.

When connecting, it is necessary to indicate minimum URI of the connected controller and API KEY functioning either as a master key or the key with access to certain items. If Logic Manager and UC keys are the same, the key can be set as $key (\$key in the command line). In this case, LM will use the local key of its own configuration.

eva lm controller append http://localhost:8812 -a secretkey -y

Configurations of connected controllers are stored in the following folder: runtime/lm_remote_uc.d/

Logic Manager automatically loads the connected controller data (its ID) and saves configuration to runtime/lm_remote_uc.d/ID.json file.

Items from remote controllers are loaded at the LM PLC start and then refreshed with reload_interval frequency set individually for each connected controller. If LM PLC fails to get the item list during loading, it will use the existing one.

To control the list of the received items you can use eva lm or LM API function list_remote:

eva lm remote -p unit
eva lm remote -p sensor

All connected controllers have the following properties that can be changed while LM PLC is running:

  • description optional description of the controller
  • key API key used to access the connected controller
  • mqtt_update MQTT notifier through which items update their status
  • reload_interval interval (seconds) to reload the item list from the server, 0 - load the list only at the start
  • ssl_verify either verify or not the SSL certificate validity when working through https://. May be True (verify) or False (not verify) The certificate is verified by default.
  • timeout request timeout (seconds)
  • uri API URI of the connected controller (proto://host:port, without /uc-api/)

Parameters are displayed with eva lm command or Logic Manager list_controller_props function, modified with set_controller_prop. Function list_controllers displays the list of all connected controllers.

To remove the connected controller use remove_controller function.

When managing the connected controllers, ID can be either the controller ID only or the full ID in the following format: controller_type/ID (i.e. uc/controller1).

Macro execution queues

Prior to execution, the macros are put into global queue. The macros are executed progressively without waiting for the completion of the previous macro. The queue is used for reporting only and reserved for some internal functions. If a macro is required to block execution of the other ones, one should use lock and unlock macro functions operating similarly to SYS API locking.

The status of the macro in queue is similar to the status of the Universal Controller actions.

Startup and shutdown

To manage LM controller server, use:

  • eva lm server start start LM server
  • eva lm server stop stop LM server
  • eva lm server restart restart LM server
  • eva lm server reload restart controller only (without watchdogs)

The controller startup/shutdown is also performed by ./sbin/eva-control which is configured during the system setup.

SCADA Final Aggregator

SCADA Final Aggregator (SFA) is a subsystem usually installed directly in the host wherein the user interface or third-party applications are installed.

It aggregates all the control and monitoring items, logic macros and decision rules from all connected UC and LM PLC controllers into one place. As a result, the final interface or application doesn’t need to know on which controller the item is present, it does all the function calls directly to SFA. Ids of the items should be always specified in oid form (type:group/id) and be unique in the whole installation.

SCADA Final Aggregator

Example of the controller aggregation with the use of two SFA servers

SFA is set up and controlled with eva sfa console application and SFA API. The API doesn’t have a user interface by default, it’s developed specifically for certain installation certain installation using SFA Templates (server-side part) and EVA JS Framework (client-side part).

All changes of item status, actions, and logs are sent to the notification system. In addition, SFA can function as the notification aggregator e. g. by transferring MQTT messages to other application via HTTP or redirecting them to other MQTT servers. SFA usually has several or all available controllers connected. At least one MQTT server should be installed in the setup to let it work in real time.

Since SFA is a part of EVA platform, its operating principles, settings, and configuration files generally match the other components.

etc/sfa.ini configuration file

sfa.ini - primary configuration file of SFA

[server]
; system name (default - hostname)
; name = eva3-sfa1
; system polldelay
polldelay = 0.01
; pid file (default var/sfa.pid)
pid_file = var/sfa.pid
; log file
log_file = log/sfa.log
; custom primary log format (use double %)
;log_format = { "loggerName":"%%(name)s", "timestamp":"%%(asctime)s", "pathName":"%%(pathname)s", "logRecordCreationTime":"%%(created)f", "functionName":"%%(funcName)s", "levelNo":"%%(levelno)s", "lineNo":"%%(lineno)d", "time":"%%(msecs)d", "levelName":"%%(levelname)s", "message":"%%(message)s" }
; logging to local syslog
;syslog = yes
; logging to non-standard (/dev/log) local syslog socket
;syslog = /var/run/syslog
; logging to remote syslog
;syslog = hostname:514
; custom syslog format (use double %)
;syslog_format = EVA: { "loggerName":"%%(name)s", "timestamp":"%%(asctime)s", "pathName":"%%(pathname)s", "logRecordCreationTime":"%%(created)f", "functionName":"%%(funcName)s", "levelNo":"%%(levelno)s", "lineNo":"%%(lineno)d", "time":"%%(msecs)d", "levelName":"%%(levelname)s", "message":"%%(message)s" }
; db updates - instant, manual or on_exit
db_update = instant
; db file, default runtime/db/sfa.db
db_file = runtime/db/sfa.db
; use MySQL instead of SQLite
;db = mysql+pymysql://user:password@localhost/dbname
; user db file, default = db_file
; one user db may be used by multiple controllers at once
;userdb_file = runtime/db/users.db
; use MySQL instead of SQLite
;userdb = mysql+pymysql://user:password@localhost/dbname
; keep action history in seconds
; launch external script/program when user is created/got new
; password/destroyed. additional arguments:
;    1) create | set_password | destroy
;    2) user
;    3) password (for create and set_password operations)
;user_hook = /opt/eva/xbin/htpasswd.sh /opt/eva/etc/htpasswd
; keep action history in seconds
keep_action_history = 86400
; action cleaner interval, in seconds
action_cleaner_interval = 60
; keep memory log in seconds
keep_logmem = 86400
; keep extended API call log in user db in seconds (0 = disable logging)
;keep_api_log = 0
; debug mode
debug = no
; show error traceback
;show_traceback = yes
; logging level, info, warning, error or critical
;logging_level = info
; create crash dump on critical errors
dump_on_critical = yes
; stop server on critical errors (will be restarted via safe-run)
stop_on_critical = yes
; default timeout
timeout = 5

; primary thread pool, min workers. comment to pre-spawn all workers
;pool_min_size = 0
; primary thread pool, max workers. comment to use automatic value (nCPUs * 5)
;pool_max_size = 100

; exec commands before/after config/db save,
; e.g. mount -o remount,rw / (then back to ro)

;exec_before_save =
;
;exec_after_save =

; default mqtt notifier for updates for new items
;mqtt_update_default = eva_1:2

; plugins, comma separated
;plugins =

;[msad]
; user authentication via MS Active Directory
;host = ad.yourdomain.com
;domain = yourdomain.com
;key_prefix =
;ou = EVA
;ca = /path/to/ca-file.crt
; cache credentials for the specified time (seconds)
; default: 86400 (1 day), 0 to disable caching
;cache_time = 86400

[upnp]
; discover controllers via UPnP on all interfaces, or list, comma separated
discover_on = all

[sysapi]
; enable remote file management functions
file_management = yes
; allow entering setup mode
setup_mode = yes

[webapi]
; web api listen on IP/port
listen = 0.0.0.0:8828
;ssl_listen = 0.0.0.0:8829
;ssl_module = builtin
;ssl_cert = test.crt
;ssl_key = test.key
;ssl_chain = test.pam
; session timeout, set to non-zero to enable API session tokens
; note: SFA Framework will not work without sessions
session_timeout = 3600
; session tokens will expire even if active requests are received
;session_no_prolong = yes
; server thread pool
;thread_pool = 15

; uncomment to use frontend X-Real-IP header to get client real IP address
;x_real_ip = yes

[mailer]
; mailer for mail() macro function
smtp = localhost:25
from = eva@eva3-sfa
default_rcp = admin@localhost, root@localhost
;ssl = yes
;tls = yes
;login = smtp_login
;password = smtp_password

[cloud]
; enable cloud manager services
;cloud_manager = yes
;default_key = default

runtime/sfa_cvars.json variables file

sfa_cvars.json - file containing user variables. All SFA user variables are directly available in SFA Templates and EVA JS Framework after login with any valid user or API key.

The file contains a JSON dict:

{
 "VAR1": "value1",
 "VAR2": "value2"
}

Variables can be changed while the server is running via Common methods as well as eva sfa cvar get and cvar set commands.

etc/sfa_apikeys.ini API keys file

API access keys are stored into etc/sfa_apikeys.ini file. At least one full access key named masterkey should be present for proper functioning. Important: with master key and API anyone can receive the full access to the system similar to root user (or the user SFA is run under), that is why it is recommended to use this key only in supervisory networks or even restrict its use to local host only.

[masterkey]
; the default master key is eva, change it!
key = eva
master = yes
hosts_allow = 127.0.0.1

;[key1]
;key = key1secret
;groups = group1/#, group2, group3/+/somegroup
;pvt = #
;rpvt = 127.0.0.1/#
;hosts_allow = 0.0.0.0/0
; key will be assigned to requests from these hosts if no key provided
;hosts_assign = 192.168.1.1

;[key2]
;key = key2secret
;items = macro1, lvar1, lvar2
;sysfunc = yes
;allow = cmd
;pvt = dir1/#, file1, dir2/file2, dir3/+/content.js
;rpvt = 127.0.0.1:8080/file1.png 127.0.0.1:8080/img/#
;hosts_allow = 0.0.0.0/0

Connecting UC and LM PLC controllers

SFA works only with the items known to the controller. Prior to connecting UC and LM PLC remote controllers, it is necessary to connect SFA to MQTT server (via its notification system), to which other controllers will send the events. SFA reads the list of items, macros, rules and the initial item status from the connected controllers; further status updates are performed via MQTT.

For timers to be displayed correctly in the user interface, it is important to maximally synchronize the system time between LM PLC and SFA, if LM PLC controllers are set up on the remote servers.

To connect the controllers you should use eva sfa (sfa-cmd) console command or SFA API append_controller function.

When connecting, it is necessary to indicate minimum URI of the connected controller and API KEY functioning either as a master key or the key with access to certain items. If Logic Manager and UC keys are the same, the key can be set as $key (\$key in the command line). In this case, LM will use the local key of its own configuration.

eva sfa append_controller -u http://localhost:8812 -a secretkey -y
eva sfa append_controller -u http://localhost:8817 -a secretkey -y

You may specify a controller type with -g argument (-g uc or -g lm). If the group is not specified, SFA tries to automatically detect the remote controller type.

Configurations of the connected controllers are stored in the folder runtime/sfa_remote_uc.d/ for UC and runtime/sfa_remote_lm.d/ for LM PLC.

SFA automatically loads the connected controller data (its id) and saves the configuration to runtime/sfa_remote_<type>.d/<ID>.json.

Items from remote controllers are loaded at the SFA start and then refreshed with reload_interval frequency set individually for each connected controller. If SFA fails to get the item list during loading, it will use the existing one.

To control the list of the received items you can use eva sfa or SFA API function list_remote:

eva sfa remote -p unit
eva sfa remote -p sensor
efa sfa remote -p lvar

The available logic macros are listed by the command

eva sfa macro list

Note

Macros from system group and its subgroups are not loaded to SFA

All connected controllers have the following properties that can be changed while SFA is running:

  • description optional description of the controller
  • key API key used to access the connected controller
  • mqtt_update MQTT notifier through which items update their status
  • reload_interval interval (seconds) to reload the item list from the server, 0 - load the list only at the start
  • ssl_verify either verify or not the SSL certificate validity when working through https://. May be True (verify) or False (not verify) The certificate is verified by default.
  • timeout request timeout (seconds)
  • uri API URI of the connected controller (proto://host:port, without /uc-api/ or /lm-api/)

Parameters are displayed with eva sfa command or SCADA Final Aggregator list_controller_props function, modified with set_controller_prop. Function list_controllers displays the list of all connected controllers.

To remove the connected controller use remove_controller function.

When managing the connected controllers, ID should be always provided in the full format: controller_type/ID (i.e. uc/controller1).

Interface

SFA interface is always specifically designed for a certain installation using SFA Templates, EVA JS Framework and SFA PVT. Interface files are stored in ui folder, interface is available at http(s)://<IP_address_SFA:Port>/ (redirects to /ui/) or http(s)://<IP_address_SFA:Port>/ui/.

Startup and shutdown

To manage SFA controller server, use:

  • eva sfa server start start SFA server
  • eva sfa server stop stop SFA server
  • eva sfa server restart restart SFA server
  • eva sfa server reload restart controller only (without watchdogs)

The controller startup/shutdown is also performed by ./sbin/eva-control which is configured during the system setup.

Control and monitoring items

An item in EVA means any object which can be controlled or monitored. Universal Controller has 2 native item types: unit and sensor, plus multi-updates, which can contain multiple items at once.

Logic Manager has one native item type lvar (logic variable), additionally it loads remote units and sensors from connected UCs. SCADA Final Aggregator has no native item types and loads everything from the connected remote controllers.

The configurations of items are stored in runtime folder, from where the controllers loads .json files. Each item has multiple parameters which can be predefined or customized. All customized parameters can be displayed with the help of API list_props or EVA console tools In case the configuration file settings are changed manually or by 3rd party software, controller should be restarted to reload the configurations.

Common item parameters

  • id item ID, e.g. ‘lamp1’. When using simple layout, must be unique within one controller, even if items are in different groups. This creates some complications when designing the whole installation architecture but allows to keep EVA configuration and item scripts organized in a simple way and makes system administration and support much easier.
  • group item group, i.e. ‘hall/lamps’. Assigned at the time of item creation, the group can’t be changed later to avoid synchronization problems.
  • full_id full item id (i.e. ‘hall/lamps/lamp1’), read-only. Must be unique within one controller despite of layout used.
  • oid object id, unique within the whole installation, same as full_id, but also contains the item type: ‘unit:hall/lamps/lamp1’, read-only
  • description item description

Note

All EVA functions, commands and parameters can accept oid as the item identifier.

Item layout

EVA ICS allows to use two types of item layouts: simple and enterprise. if the system is not being used yet and there are no items created, layout can be set in Universal Controller and Logic Manager configuration files (option within [server]: layout=<simple|enterprise>). Otherwise you should use sbin/layout-converter tool to convert simple layout to enterprise. Inverse conversion is not possible.

Benefits of simple layout:

  • Good to use in simple installations or in the installations where each component has no similar items. Each item should have its own unique ID, despite that items are located in different groups.
  • When doing controller maintenance tasks, you can address each item by its ID instead of full ID or oid.
  • Item configuration files are named as <ID>.json and can be easily located.

Benefit of enterprise layout: different items in different groups can have the same IDs. Ideal for setups where multiple similar components are managed by one controller.

In general, simple layout should be used only for testing and simple temporary setups. For usage in production environment, enterprise layout is always recommended.

Unit

A unit is a physical item, a device that we control. A unit is not a relay port, a dimmer or a controlled resistor. This is an object, for example: an electric lamp chain, a door, ventilation, a window, a pump or a boiler.

The unit can be controlled with one relay (e.g. a lamp chain: we control the whole chain by turning on/off the relay port) or with several ones (controlling e.g. a garage door often requires two relays: the first one starts the motor, the second one chooses the direction of movement). However, a door is one unit with “open” or “closed” statuses.

All units are connected to Universal Controller subsystems, which control them and form the single “unit” with one or several relays/programmable switches using control scripts. One Universal Controller can work with multiple units, but one unit should be connected to only one Universal Controller in order to avoid conflicts. Nevertheless, for reliability, one unit can be connected to several controllers, if its state is correctly synchronized via MQTT.

Each unit has its unique ID, for example “lamp1”. ID can include numbers, uppercase and lowercase Latin characters and some special characters like minus (-) or dot (.).

Unit parameters are set via configuration.

Status of the unit state

Status of the unit state is always an integer (a positive number or 0), and is by default 0 - unit is “off” (inactive) and 1 - “on” (active).

A unit can have other statuses: for example, a dimmer can include status 2 - enabled at 10% of the capacity, 3 - enabled at 50% of the capacity, window can be fully open or 50%. In the item configuration, you can assign a label to each status for enhancing its usability in interfaces.

Status -1 indicates that unit has an error status. It is set from the outside or by the system itself if the unit wasn’t updated for more than “expires” (value from item config) seconds.

Value of the unit state

Sometimes it’s not necessary to create multiple new statuses for the unit. In such cases, the unit also has a “value” parameter (which can include both numbers and letters). For instance, a motor can be controlled by two unit statuses - 0 and 1, i.e. turned on/off, but Its speed is set by value. You can also use value to control e.g. dimmers.

EVA does not use unit value for internal control and monitoring logic (except in your custom macros), that is why you can set it to any value or several values separating them with special characters for further processing.

Units in EVA hive

All units have OIDs like unit:group/unit_id e.g. unit:light/room1/lamp1

For synchronization via MQTT, the following subjects are used for units

  • [space/]unit/<group>/<unit_id>/status unit status, integer
  • [space/]unit/<group>/<unit_id>/value unit value
  • [space/]unit/<group>/<unit_id>/nstatus new unit status (different from status if action is started), integer
  • [space/]unit/<group>/<unit_id>/nvalue new unit value
  • [space/]unit/<group>/<unit_id>/action_enabled are actions enabled for the unit or not (boolean, True/False)
Unit parameters
  • expires integer value, time (seconds) after which the item state is considered “expired”. If the item state was not updated during this period, the state automatically is set to -1 (error), value is deleted (set to null). If ‘expires’ param is set to 0, this feature is disabled. The minimum expiration step is 0.1 sec.

  • mqtt_update = “notifier:qos” if set, the item can receive active state updates through notification from the specified MQTT server. Example: “eva_1:2”. State updates should be sent either to MQTT topics “path/to/unit/status” and “path/to/unit/value” or as JSON message to “path/to/unit”. In example, to set unit “tests/unit1” status to 1:

    • MQTT topic: unit/tests/unit1

    • MQTT payload:

      { "status": 1 }
      

    There is also a configuration parameter mqtt_update_default which can be set in etc/uc.ini (default e.g. to eva_1:2) and applied to all newly created items.

  • snmp_trap if set, the item can receive active state updates via Connecting equipment with drivers.

  • update_delay delay in seconds before triggered update is launched

  • update_exec a script for passive update of the item state, “xc/uc/ITEMID_update” by default.

  • update_interval integer value, time (seconds) interval between the calls for passive update of the item. Set 0 to disable passive updates. Minimum step is 0.1 sec.

  • update_timeout integer, value, time (seconds) in which the script of the passive update should finish its work or it will be terminated.

  • action_allow_termination boolean, allow currect running action termination by external request.

  • action_always_exec boolean, always execute the actions, even if the intended status is similar to the current one

  • action_enabled boolean, allow or deny new actions queue/execution

  • action_exec a script which performs the action, “xc/uc/ITEMID” by default.

  • action_queue={0|1|2}

    • 0 action queue is disabled, if the action is running, new actions are not accepted
    • 1 action queue is enabled, all new actions are put in queue and executed in a normal way
    • 2 queue is disabled, new action terminates the current running one and then is executed
  • action_timeout integer, value, time (seconds) in which the script of the action should finish its work or it will be terminated.

  • auto_off integer, the simple automation parameter: the command to turn the unit off (call an action to set status = 0) will be executed after the indicated period of time (in seconds) after the last action performed for this unit. Set 0 to disable this feature. Minimum step is 0.1 sec.

  • location you can specify units’ physical location, as GPS coordinates or in custom format. To specify GPS coordinates, set the parameter to value longitude:latitude or longitude:latitude:altitude. If you choose to set location as GPS or some other coords, full unit state is appended with virtual parameters loc_x, loc_y (and if altitude is specified - loc_z). These virtual parameters are parsed automatically from location and can be used later e.g. to filter units by location or to put units on geographical map.

  • maintenance_duration integer, if greater than zero, item can enter maintenance mode on the specified amount of seconds. During maintenance mode all item updates are ignored, however actions still can be executed. If expires property is also set, item state expire after maintenance_end + expires seconds.

  • mqtt_control = “notifier:qos” item gets actions through notifications from a specified MQTT server, for example “eva_1:2”, actions should be sent to path/to/unit/control (e.g. unit/hall/lamps/lamp1/control).

    The message should be:

    • either in a form of text messages “status [value] [priority]”. If you want to skip value, but keep priority, set it to null, i.e. “status 0 null 50”.

    • or in JSON format (fields “value” and “priority” are optional):

      { "status": 1, "value": "", "priority": 100 }
      
  • modbus_status, modbus_value update item state from Modbus slave memory space.

  • notify_events 2 (default) - send notifications about all events, 1 - about state only, 0 - disable all event notifications.

  • status_labels “labels” used to display the unit statuses by the interfaces. Labels can be changed via UC API or eva uc, in the following way: status:number = label, e.g. “status:0” = “stop”. By default the unit has labels “status:0” = “OFF”, “status:1” = “ON”. Status labels can be used as status param to execute unit actions, in this case controllers check the status match to the specified label (case insensitive).

  • term_kill_interval integer, difference (in seconds) between stopping and forcible stopping the action or update script. Tip: sometimes it is useful to catch SIGTERM in the script to exit it gracefully. Cannot exceed the value of timeout** 2, where timeout** default timeout, set in a controller config.

  • update_exec_after_action boolean, start passive update immediately after the action is completed (to ensure the unit state has been changed correctly)

  • update_if_action boolean, allow or deny passive updates while the action is being executed

  • update_state_after_action boolean, if action is completed successfully, the controller assumes that its actual unit state has been changed correctly and sets it without calling/waiting for the state update.

Sensor

The sensor value is the parameter measured by the sensor: temperature, humidity, pressure etc.

In terms of automation the difference between sensor item and unit item is obvious: we change the unit state by ourselves and monitor it only for the sake of checking the control operations, while the sensor state is changed by the environment.

Regarding the system itself, unit and sensor are similar items: both have status and value, the item status is monitored actively (by UC API, MQTT message, SNMP traps) or passively (by calling the external script).

The sensor can have 3 statuses:

  • 1 sensor is working and collecting data
  • 0 sensor is disabled, the value updates are ignored (this status can be set via API or by the user)
  • -1 sensor error (“expires” timer went off, the status was set because the connection with a physical sensor got lost during passive or active update etc), when the sensor is in this status, its value is not sent via notification system to let other components work with the last valid data.

Note

The sensor error state is automatically cleared if new value data arrives.

Important: the sensor error can be set even if the sensor is disabled. It means that the disabled sensor can be switched to “error” and then to “work” mode by the system itself. Why it works that way? According to the logic of the system, the sensor error is an emergency situation that should affect its status even if it is disabled and requires an immediate attention of the user.

Sensors (and sometimes units) can be placed on the same detector, controller or bus queried by a single command. EVA can use multi-updates in order to update several items at once.

Since the system does not control, but only monitors the sensor, it can be easily connected to several Universal Controllers at once if the equipment allows making parallel queries of the state or sending active updates to several addresses at once.

Note

The sensor doesn’t set its status to ‘-1’ on expires if its status is 0 (disabled)

Sensors in EVA hive

All sensors have OIDs like sensor:group/sensor_id e.g. sensor:temp/t1

For synchronization via MQTT, the following subjects are used for units

  • [space/]sensor/<group>/<sensor_id>/status sensor status, integer
  • [space/]sensor/<group>/<sensor_id>/value sensor value
Sensor parameters

Sensors have the same parameters as units, except they don’t have action_*, auto_off, mqtt_control, modbus_status and status_labels.

Validation of state value

State value of units and sensors can be validated before Universal Controller perform item update.

To validate item value, the following item properties are used:

  • value_in_range_max value should be less
  • value_in_range_max_eq value should be less or equal than specified max.
  • value_in_range_min value should be greater
  • value_in_range_min_eq value should be greater or equal than specified max.

or virtual parameter value_condition, which can be set in human readable way, e.g. 20<x<=200.

If value validation is set and item receive state value which is not numeric or doesn’t feet the specified range, item keep previous state value and get status -1 (error).

Item status is set back to normal as soon as any valid state update is received.

Logic variable

EVA Logic Manager uses the logic variables (lvars) to make decisions and organize production cycle timers.

The parameters of logic variables are set in their configurations.

Actually lvars are similar to sensors, but with the following differences:

  • The system architecture implies that the sensor value is changed depending on the environment; the logic variables are set by the user or the system itself.
  • The logic variables, as well as the sensors, have statuses -1, 0 and 1. However, if the status is 0 (variable is disabled) it stops responding to any value-only changes.
  • The logic variables exchange two more parameters with the notification system: “expires” (time in seconds after the variable is set, and then takes the null value and -1 status) and set_time - time when the value was set for the last time.

The same logic variable can be declared on several logic controllers, but the “expires” configuration value should remain the same because each controller processes it autonomously. The variable becomes “expired” once it is declared as such by any controller.

Note

LVar doesn’t set its status to ‘-1’ on expires if its status is 0 (disabled)

The logic variable values can be synchronized via MQTT server or set via API or external scripts - similar to sensors.

You can use several logic variables as timers in order to organize production cycles. For example, there are three cycles: the pump No.1 operates in the first one, the pump No. 2 in the second one, and both pumps are disabled in the third one. In order to organize such cycle, let us create three variables: cycle1, cycle2, cycle_stop with “expires” values equal to the duration of each cycle in seconds.

Then - in the decision-making matrix you should specify the rules and macros run as soon as each cycle is finished. The macros run and stop the pumps as well as reset the timer variables of the next cycle: as soon as cycle_stop is finished, the pump No.1 is run, the cycle1 timer variable is reset; as soon as the cycle1 is finished, the pump No. 2 is run and cycle2 variable is reset; as soon as cycle2 is finished, both pumps are disabled and cycle_stop is reset.

In order to synchronize timer values with interfaces and the third-party applications, use LM API test command that displays the system information, including local time on the server on which the controller is installed.

However, when used in industrial configurations, it is recommended to synchronize time on all computers without any additional software hotfixes.

LVars in EVA hive

All logic variables have OIDs like lvar:group/lvar_id e.g. lvar:service/var1

For synchronization via MQTT, the following subjects are used for units

  • [space/]lvar/<group>/<lvar_id>/status lvar status, integer
  • [space/]lvar/<group>/<lvar_id>/value lvar value
  • [space/]lvar/<group>/<lvar_id>/set_time last set time (Unix timestamp)
  • [space/]lvar/<group>/<lvar_id>/expires value expiration time (seconds)
Examples using LVars

You can use lvar as a

  • Variable To use lvar as a shared variable to exchange some information between controllers, apps and SCADA interfaces, just set its value (and status if you want) and that’s it.
  • Timer
    • Set expires configuration param
    • Use reset to set lvar status/value to 1 and reset the expiration timer
    • Use clear to set lvar status to 0 and stop it reacting to expiration (when used with lvar which have expires param set, clear changes its status instead of value)
    • Use decision rules with the conditions on_set and on_expire to run the macros when the timer is set/expired
    • if the timer has status set to 1, it’s running
    • if status is 0, it’s disabled with clear function
    • if status is -1 and value is null (empty), the timer is expired
  • Flag
    • Use lvar as a simple boolean variable to exchange the information True/False, yes/no, enabled/disabled etc.
    • Use reset to set lvar value to 1 which should be considered as True
    • Use clear to set lvar value to 0 which should be considered as False
    • Use toggle to toggle lvar value between 0 and 1
    • Use constructions like if value(‘lvar_id’): in macros to determine is the ‘flag’ lvar is set or not.
LVar parameters

As LVars behavior is similar to sensors except the values are set by user/system, they have the same parameters, except lvars can’t be updated via SNMP traps / MQTT.

LVars also have an additional parameter logic.

Simple logic

If lvar property logic is set to ‘simple’, it bypasses built-in logic behavior conditions:

  • LVar status can be set to any integer

  • Status “0” is considered as normal and:

    • Lvar value can be updated even if LVar status is 0
    • LVar is considered as expired even if LVar status is 0
  • When LVar becomes expired, its value is cleared, but the status is kept

Simple logic is useful to use LVars as simple double data holding registers (integer + any value) for various tasks.

Multi-updates

Warning

Starting from EVA ICS 3.3.2, multi-updates are deprecated

Multi-updates allow Universal Controller updating the state of several items with the use of one script. This could be reasonable in case all items are placed on the same bus or external controller and queried by a single command.

Multi-update is an independent item in the system with its own configuration and without status and value. In turn, it updates statuses of the included items.

Multi-updates in EVA hive

All multi-updates have OIDs like mu:group/mu_id e.g. mu:environment/mu1

Multi-updates don’t have their own state, so they are not synchronized between servers.

Multiupdate parameters

Multi-updates have the same parameters as sensors, except that “expires”, “mqtt_update” and “snmp_trap”, plus some additional:

  • items = item1, item2, item3… - the list of items for updating, can be changed via UC API and eva uc as follows:

    • -p “item+” -v “item_id” add item for update
    • -p “item-” -v “item_id” delete item
    • -p “items” -v “item1,item2,item3…” replace the whole list
  • update_allow_check - boolean, the multi-update will be performed only in case the passive state updates are currently allowed for all included items (i.e. if some of them run actions at this moment and have update_if_action=False, multi-update will be not executed)

Device

Multiple CVARs, units and sensors can be merged in logical groups called devices. It’s completely up to you how to merge items into device, but it’s recommended to keep them in one or several separate item groups.

Device templates are stored in runtime/tpl folder in YAML (default) or JSON format.

You can use uc-tpl command line tool to create device templates using the existing items and eva uc or device management UC API functions to create, update and destroy devices.

Device management requires master key or a key with allow=device permission.

Note

Starting from EVA ICS 3.3.2, device template format is equal to IaC and deployment files. The old format is deprecated.

Device example

Let’s imagine we have some hardware device, which has 1 relay and 2 sensors. We have a lot of devices like this and we want to create them using template.

Create one instance of device in Universal Controller defining all its items:

  • sensor:device1/device1.sensor1
  • sensor:device1/device1.sensor2
  • unit:device1/device1.relay1

Configure all defined items, then run:

uc-tpl generate -i sensor:device1/device1.sensor1,sensor:device1/device1.sensor2,unit:device1/device1.relay1

This will output device JSON template. Use -t param to output template to file or copy/paste it from the screen. You can use -c param to ask the tool automatically prepare template variables, but in our example it will just replace all 1 to {{ ID }}. We don’t want it to be done this way because we have sensor1 and relay1 items, so let’s edit the template manually:

{
    "sensors": [
        {
            "group": "device{{ ID }}",
            "id": "device{{ ID }}.sensor1"
        },
        {
            "group": "device{{ ID }}",
            "id": "device{{ ID }}.sensor2"
        }
    ],
    "units": [
        {
            "group": "device{{ ID }}",
            "id": "device{{ ID }}.relay1"
        }
    ]
}

(template will also contain items’ configurations which are omitted in the example)

Save the final template as runtime/tpl/mydevice.json folder, and then

# execute this command to create new device "device5"
eva uc device create mydevice -C ID=5 -y
# execute this command to destroy "device5"
eva uc device destroy mydevice -C ID=5

Configurations of the newly created items of device5 are exact copies of the items of device1. The only configuration difference is the params where we’ve put template variables instead of part or full param value (in our example: {{ ID }}).

Note

Device templates are actually jinja2 templates, so you can use any jinja2 syntax in them (loops, conditions and etc.)

Device limitations

Cloud Manager

If cloud_manager option is enabled in SCADA Final Aggregator configuration file, you may monitor and manage the whole your EVA ICS setup via web interface.

Cloud manager can be accessed at http://<SFA_IP>:8828/cloudmanager by users with master key assigned. You may create such user in CLI or use master API key to login.

Dashboard

Cloud Manager Dashboard

Cloud Manager dashboard display all resources, available for SCADA Final Aggregator where Cloud Manager is running on.

Controller management

Connected controllers can be also managed. SCADA Final Aggregator must know controller master API key to connect and manage remote controller.

If Cloud Manager was not enabled during the installation, you should specify master key manually by pressing “edit” button in the controller table. By default, local master key is used.

Cloud Manager Dashboard

Drivers

Universal Controller uses 2 ways for controlling and monitoring items: item scripts and drivers. Drivers are the most advanced way, they are faster, contain all process logic and can be used to work with devices on a single bus, providing locking/unlocking mechanisms.

Code of driver is executed directly inside the controller core and unlike script can’t be terminated, unless it gets termination signal and decides to stop. If driver process causes timeout and there is no way to stop it, controller raises a critical exception and may terminate itself.

You should always use only reliable and tested drivers, otherwise your system may become unstable.

Structure

Each driver contains 2 modules: LPI (logical to physical interface) and PHI (physical interface). To load new driver into controller, follow the steps:

List the available PHI mods:

eva uc phi mods

Get PHI module information:

eva uc phi modinfo <phi_module>

If the desired PHI is not listed, download it and put to xc/drivers/phi folder. Official PHI modules are available at https://www.eva-ics.com/phi. You may either download the module manually or use

eva uc phi download <phi_module_uri>

command. Note that UC host doesn’t need to have a direct connection to the host you download PHI from, module is downloaded first to the host where eva CLI (or eva uc) is started, verified and then automatically uploaded to the controller.

Execute the command to list PHI configuration variables:

eva uc phi modhelp <phi_module> cfg

This will display the configuration variables, used when PHI is loaded (port numbers, default values etc.). Variables marked required=True should be always defined otherwise controller will fail to load PHI.

Load PHI with the following command:

eva uc phi load <phi_id> <phi_module> [-c config] [-y]
# example
eva uc phi load v1 vrtrelay -c default_status=1,update=5 -y

Param -y is used to ask the controller to save driver configuration right after PHI is loaded.

After the successful load, PHI will automatically create the most suitable driver for itself, called <phi_id>.default. This usually provides basic driver logic and doesn’t mean the driver is suitable for your task. You may replace it’s LPI module or define a different driver with another LPI.

To assign driver to the specified item, use the command:

eva uc driver assign <item_id> <driver_id> [-c config] [-y]
# example, set test_lamp to 5th relay port of driver v1
eva uc driver assign unit:lamps/test_lamp v1.default -c port=5

Param -y is used to ask the controller to save item configuration right after driver is assigned.

Param -c is used to set driver configuration for the specified item: set port, logic etc.

Advanced usage: EVA item can have different drivers or scripts for actions and updates. To assign different drivers, modify item properties action_exec, update_exec, action_driver_config and update_driver_config (e.g. with eva uc config props). Driver is assigned to the property with |driver_id value, e.g. |v1.default.

Note

All custom-defined user variables are always passed to driver function calls, which allows to set some device-specific or logic-specific options as global or for the particular item group.

Drivers and actions

How the driver handles action commands

Note that params started with _ are passed to PHI calls directly (without _ prefix), this allows specifying different hosts, bus addresses (if PHI is developed as “universal”) without a need to load different drivers for each item.

Drivers and updates

How the driver handles update commands

Use commands eva uc phi unload and eva uc phi unlink to unload and unlink unnecessary PHI modules, but note that driver and PHI can’t be unloaded while they’re assigned to items. You must first assign a different driver to the item or use eva uc driver unassign command.

You can load PHIs/drivers with the same IDs even if they are already present in the system without unloading them first. In this case, new modules/configuration replace the old ones.

Logical to physical interfaces (LPI)

LPI module handles the whole driver logic and doesn’t contain any code, specific for the equipment. All it needs is to process the logic and call the assigned PHI.

When the controller loads new PHI, it creates a driver called <phi_id>.default, assigning LPI to provide basic functionality, but you may want to replace it or use different logic for different items.

To list available LPI mods, use the command:

eva uc lpi mods

To get module information, use the command:

eva uc lpi modinfo <lpi_module>

Currently we don’t provide any additional LPI modules or SDK, all available mods are included in EVA ICS distribution.

To get additional module info, use the following commands:

# list module configuration options
eva uc lpi modhelp <lpi_module> cfg

# list module options used when action is called
eva uc lpi modhelp <lpi_module> action

# list module options used when state update is called
eva uc lpi modhelp <lpi_module> update

Configuration options are used when you load a driver (e.g. to modify LPI default behavior), separated with commas.

Action and update options are used when you assign a driver to the specified item; separate them with commas. Options marked required=True should be always defined.

Let’s see what modules are available.

basic LPI

Basic status on/off LPI module, used to control simple devices which have only status 0 (OFF) and 1 (ON), i.e. lamps, relay ports (directly) etc.

Used in default drivers for relay, sockets and similar PHIs, doesn’t need to be configured when loaded.

When assigning driver containing basic LPI mod to the specified item (eva uc driver assign), the assign configuration should contain port number (-c port=N) which usually matches the physical relay port.

Port number can be specified as a list (-c port=N1|N2|N3), in this case all listed ports will be used in commands.

Note

If relay port number is specified as i:N e.g. i:2, LPI commands will consider it is inverted (falling edge) meaning 0 is for on and 1 is for off. This works both for basic as well as for any other relay control LPI.

sensor LPI

Basic sensor monitiring, used to get data from specified sensors.

Used in default drivers for sensors, doesn’t need to be configured when loaded.

LPI doesn’t provide action functionality. When assigning driver containing sensor LPI mod to the specified item (eva uc driver assign), the assign configuration should contain port or bus address number.

ssp LPI

Similar to sensor LPI, but doesn’t contain any options at all. Used when PHI can work only with one physical equipment (e.g. sensor with TCP/IP API) and all equipment options are already set in PHI.

esensor LPI

Sensor monitoring with advanced functions. Can monitor physical sensor groups returning average, maximum or minimum value. Can ignore sensor values if they seem to be invalid in case one or several sensor in a group fail (while there are enough working sensors in a group).

Configuration options (set with eva uc driver load):

  • skip_err If True, failed physical sensor in a group will be skipped, otherwise EVA sensor item gets error value.
  • gpf Group port function, get values from the sensors in a group, then return:
    • avg average value
    • max maximum value
    • min minimum value
    • first first available value from any working physical sensor
  • max_diff maximum value difference until the sensor in a group is marked as failed and its value is ignored. E.g.: set this option 10 and let it poll the temperature sensors group. All sensors with temperature difference 10 degrees or more from the average are ignored.

Update options (set with eva uc driver assign):

  • port driver port or ports (array). If you use multiple ports (group), they should be separated with pipes (|) for the items. Group separation for EVA multiupdate items should be made with double pipes (||)
  • any configuration option (optional). E.g. if gpf=avg is defined, it overwrites default LPI behavior for the specified item.
multistep LPI

Module used for such common tasks as door or window opening. To use this module you must connect your equipment to 2 relay ports: one will give power to motors, the second will set the direction.

AC motor circiut

AC motor circuit

Configuration options (set with eva uc driver load):

  • bose (break on state error). The module requires to know the current door or window position is. If you set this option to True and the current item status is error, the action will be not executed. Otherwise LPI will pass and consider the item status is 0.
  • logic default or rdc (reversible DC motor circuit). If set to rdc, LPI will set port = 1, dport = 0 for “opening” and port = 0, dport = 1 for “closing”.
reversible DC motor circuit

Reversible DC motor circiut

Action options (set with eva uc driver assign):

  • port contains one or several (separated with |) relay ports used to power a motor (or plus for reversible DC).
  • dport contains one or several (separated with |) relay ports used to set a direction (or minus for reversible DC).
  • steps list of float numbers, contains time (in seconds) of power access period to the motor to reach the next step. E.g. you have a door with 3 positions: closed, half-open and completely open. steps option will contain 2 numbers (e.g. 20|25) which tells LPI the door state from 0 to 1 is changed by running motor for 20 seconds, the state from 1 to 2 is changed by running motor for 25 seconds, so LPI can automatically calculate the full opening/closing cycle is 45 seconds.
  • warmup float number (seconds). LPI will add this value to the time for running the motor if the state is neither fully open nor fully closed, to let it “warm up” before doing actual work.
  • tuning float number (seconds). LPI will add this value to the time, if action is open full or close full to make sure the door is fully open/closed.
  • ts (to-start) number which indicates the following: e.g. you have a door with status from 0 (fully closed) to 5 (fully open) and defined the middle states with steps. But when calling action “set this door to 2” you can’t be sure the door position is equal when setting it from fully open and fully closed. But if you set e.g. ts=2 and the current status is greater than 2, it will tell LPi firstly to completely close the door (go to status=0) and then go to status=2.
  • te (to-end) same as ts but in an opposite way: set the status number, starting from which the door will be fully open first, then go to the desired status.

Note

LPI will completely refuse to run the action if it calculates that therese is not enough time to complete it. Set unit action_timeout to the proper value.

Update options:

The module doesn’t provide any state update functionality. If you want to sync door/window item states with real, use separate reed switch sensor.

Loading driver with the chosen LPI

Firstly, you can list available LPIs with the command:

eva uc lpi mods

Consider the desired PHI is already loaded. To load the driver and combine PHI+LPI, use the command:

eva uc driver load <phi_id>.<lpi_id> <lpi_module> [-c config] [-y]
# in example, for PHI loaded as "v1":
eva uc driver load v1.ms multistep -c bose=true -y

Physical interfaces (PHI)

PHIs are modules, which contain no data processing logic but code to work directly with hardware equipment.

We provide a basic set of PHIs for the popular automation equipment (at https://www.eva-ics.com/phi), but if your equipment isn’t supported, it’s not so hard to develop your own PHI.

We’ve already described how to get and load PHIs, here is some additional important information.

Universal PHIs

If the word “universal” is listed in PHI features, it means the module can be loaded once and provide interface for all supported equipment. E.g. let’s take a look on sr201 PHI module which provides support for SR-201 compatible relays:

# get PHI module info
eva uc phi modinfo sr201

# get PHI configuration help
eva uc phi modhelp sr201 cfg

# get PHI options for obtaining the data
eva uc phi modhelp sr201 get

# get PHI options for setting the data
eva uc phi modhelp sr201 set

All of cfg, get and set have an option host which should be defined ether in PHI configutation (eva uc phi load with host config option or in item driver configuration (eva uc driver assign with _host config option). Setting different host option value in item driver configuration lets one sr201 PHI manage all available SR-201 relays.

Physical events

If the word “events” is listed in PHI features, it means the module can handle hardware events e.g. react to the alarm sensors or update item state when an external event is received.

Drivers and events

How the driver handles physical events

In practice, it means PHI provides data, obtained from the hardware, to controller and asks it to update all items using drivers which contain PHI module which have an event.

When doing update, drivers LPI modules don’t ask PHI to get hardware data working only with data already provided by the hardware.

Drivers and multi updates

If the word “aao_get” is listed in PHI features, it means you don’t need to create multiupdates in Universal Controller to update several items at once. “aao_get” (all-at-once-get) means PHI can obtain all hardware data itself and then ask the controller to update all items using drivers which contain PHI equally to updating on physical events.

How to use this feature: All PHIs with “aao_get” feature also have configuration param named update which means how frequently (in seconds) PHI should collect data from the equipment and initiate item updates. update value should be defined in PHI load config and be greater than zero.

Example:

eva uc phi load relay2 sr201 -c host=192.168.20.2,update=5 -y

As soon as the driver is assigned to item (eva uc driver assign), it starts getting state updates every 5 seconds.

Testing PHIs and additional PHI commands

As soon as PHI is loaded, you can test how it works. All PHI modules respond to the command:

eva uc phi test <phi_id> self

which returns result “OK” or “FAILED”.

PHI can provide additional testing; to get a list of testing commands, execute:

eva uc phi test <phi_id> help

Some PHIs can provide additional commands to set up or control the hardware equipment. To get a list of these commands, execute:

eva uc phi exec <phi_id> help

Example: PHI module dae_ro16_modbus has a command to change Modbus unit ID of the hardware equipment. Let’s change unit ID to 5:

eva uc phi exec <phi_id> id 5

The module will flash new unit ID into hardware and change unit ID in self configuration. Don’t forget to restart the hardware to let it be accessed with new unit ID and save PHI config (eva uc save).

Item scripts

Item scripts are used to update items’ state and execute actions. Scripts are placed in xc folder (xc/uc for Universal Controller, xc/lm for Logic Manager) and may be either written in any scripting language or be binary executables. The script file should have exec permissions.

Universal Controller has 2 ways for controlling and monitoring items: drivers and item scripts. Sometimes item scripts are harder to implement as you must define all logic by yourself, as well as implement hardware calls, they are also slower because controller needs to execute an external process. But item scripts are more reliable than drivers because the external process can be easily terminated/killed by timeout, so if you don’t have a driver for your equipment or the driver is unstable, it is a good idea to use scripts.

All the examples provided in this documentation are written in the classic Bourne shell (bash). It is recommended to use dash or perl in heavy loaded production systems to provide better startup speed. Experience has shown that the modern systems do not require the use of the lower-level languages compiled into executable files: it complicates integration and servicing; on the other hand, the difference in program operation is only a few milliseconds.

The script always has max execution time (timeout) specified in item configuration (or default controller timeout). After that the system terminates the script operation: firstly - voluntary, by sending SIGTERM, then - forcibly by sending SIGKILL (this in-between time may be changed in item configuration with param term_kill_interval)

Script or program always gets the environment variables:

  • all variables from the controller var file (uc_cvars or lm_cvars)
  • PATH variable with additional EVA bin and xbin subfolders
  • EVA_ITEM_ID item ID which the script is executed for
  • EVA_ITEM_OID item OID (type:group/id)
  • EVA_ITEM_TYPE item type: unit, sensor or lvar, (lvars can also be updated with scripts)
  • EVA_ITEM_GROUP full item group
  • EVA_ITEM_PARENT_GROUP the nearest parent group of the item (e.g. building1/env/room1/temp1 - room1)
  • EVA_ITEM_FULL_ID full item ID
  • EVA_ITEM_STATUS current item status
  • EVA_ITEM_VALUE current item state value

The system considers the script to be successful if its exit code is 0.

Item actions

Item actions are used to control the units. After the unit action has been called, the controller executes the appropriate script. By default, control scripts are placed in xc/uc/ folder and named ID, where ID is a unit ID, for example, xc/uc/lamp1. This may be changed in the item configuration to let e.g. one script execute actions for a group of units.

The startup parameters of the action script include:

  • param1 unit ID
  • param2 new unit status
  • param3 new unit value

Note

If unit action is called without value, action control script is called with previous known unit value

A simple example script: send toe command to X10 controller via mochad

#!/bin/sh
[ $2 -eq 0 ] && CMD="off" || CMD="on"
echo "pl $1 $CMD" | nc localhost 1099

Such script is actually universal for X10 (in case units are named according to X10 - a1-aX)

Another example: activate the third EG-PM2-LAN plug. Here we access EG1_IP variable from uc_cvars

#!/bin/sh

EG-PM2-LAN $EG1_IP 3 $2

Another example: control the relay (4 modules, 1 relay block) by Denkovi AE

#!/bin/sh

${RELAY1_CMD}.1.4.0 i $2

where in uc_cvars:

RELAY1_CMD = snmpset -v1 -c private RELAY_IP_ADDRESS .1.3.6.1.4.1.19865.1.2

In the previous examples, we used the same command for turning the units on/off. Let us review a more complex logic. The next example shows how EVA can shut down the remote server machine and turn it on via Wake on LAN (tip: such script requires more action_timeout in unit config):

#!/bin/sh

case $2 in
0)
  ssh eva@${SERVER_IP} "sudo /sbin/poweroff"
   ;;
1)
  wakeonlan ${SERVER_MAC}
   ;;
esac

In the queue history script is marked as completed if it completed independently with 0 code, failed - if the code differs from 0.

The script or program can display anything on stdout/stderr. This data, as well as the exit code, will be recorded in “out” and “err” fields of the result dict.

Sometimes it is useful to catch SIGTERM in the script/program, e.g. if you operate a motor that must be stopped after the script gets a termination signal. Warning:, the system does not track/stop child processes executed after SIGTERM is sent to the script.

Passive updates of item state

Passive updates are used to collect the state of the equipment which doesn’t report its state by itself. By default, scripts for passive updating of item state are named ID_update, where ID is a item ID, for example: lamp1_update.

The status update script is executed:

  • Every X seconds, if update_interval specified in the config is more than 0
  • After the unit action succeeds (if update_exec_after_action=true in config)

The system considers the script was executed successfully if its exit code is 0, otherwise, its new item state is ignored.

Passive update scripts get the following parameters:

  • param1 item ID
  • param2 “update”

Script should print on stdout only the new status and (optionally) value, separated by space, e.g.

0 NEW_VALUE

For the sensor, its data should be printed as:

1 VALUE

where 1 means the sensor is working properly.

Let us analyze an example of a simple script, e. g. state update of the sensor that monitors the remote machine

#!/bin/sh

ping -W1 -c1 ${SERVER_IP} > /dev/null 2>&1 && echo "1 1"||echo "1 0"

Unit status - the third EG-PM2-LAN plug

#!/bin/sh

EG-PM2-LAN evacc-rl5|cut -d, -f3

Update state of the relay (4 modules, 1 relay block) by Denkovi AE

#!/bin/sh

${RELAY1_UPDATE_CMD}.2.0|awk -F\  '{ print $4 }'

where in uc_cvars:

RELAY1_UPDATE_CMD = snmpget -v2c -c public RELAY_IP_ADDRESS .1.3.6.1.4.1.42505.6.2.3.1.3
Multiupdate scripts

Multiupdates allow updating the state of several items with one script which works like a normal passive update script and outputs the states of the monitored items line-by-line:

item1_status item1_value
item2_status item2_value
.....

The order of the output should correspond to the order of the items in the multiupdate.

By default, multiupdate scripts are named ID_update, where ID is a multiupdate ID, for example, xc/uc/temperatures_update for mu ID = temperatures.

For example, let’s update all 8 units connected to the relay controlled by DS2408

#!/bin/sh

w1_ds2408 28-999999999999 || exit 1

The script output will be as approximately follows:

1
0
1
1
1
1
0
1

where each row contains the status of the unit connected to the corresponding relay port.

Commands

Commands are used if you need to run some commands remotely on the server where EVA controller is installed. Commands are executed with controller cli tools, with SYS API function :ref:cmd<cmd> or with macro function.

For command scripts:

  • Configurations are absent. Scripts are named as xc/cmd/SCRIPT_NAME
  • Script timeout is set when it is started

Example of a command usage: a speaker is connected to a remote machine. We want to play some sound as an additional feedback after the certain macros or actions are executed

xc/cmd/play_snd

#!/bin/sh

GAIN=-7

killall play > /dev/null 2>&1 && killall -9 play > /dev/null 2>&1
play /data/snd/$1.wav gain ${GAIN}

when you call the command, the sound file_name will be played. If you want to wait until the playback is over add w=15 to API call i.e. to wait 15 seconds before continuing.

Modbus

Universal Controller provides native support of Modbus protocol for Modbus physical interfaces (PHIs). Core support is provided with pymodbus Python module, but with additional functionality, such as bus locking, automatic retry attempts, virtual ports for drivers etc.

Universal Controller works as Modbus master, connection links to all slave devices should be defined as virtual ports. After that, defined virtual ports and Modbus unit IDs should be set in corresponding PHI modules load configurations.

Defining Modbus virtual port

Before using any Modbus PHI, you must define Modbus virtual port. Modbus PHIs work with Modbus virtual ports only, while UC handles all hardware calls and responses.

List of the defined Modbus virtual ports can be obtained with command:

eva uc modbus list

To create new Modbus virtual port, execute the following command:

eva uc modbus create [-l] [-t SEC] [-r RETRIES] [-d SEC] [-y] ID PARAMS

where:

  • -l lock port on operations, which means to wait while Modbus port is used by another controller thread (driver command)
  • -t SEC Modbus operations timeout (in seconds, default: default timeout)
  • -r RETRIES retry attempts for each operation (default: no retries)
  • -d SEC delay between virtual port operations (default: 20ms)
  • -y save Modbus port config after creation
  • ID virtual port ID which will be used later in PHI configurations
  • PARAMS Modbus params

Modbus params should contain the configuration of hardware Modbus port. The following hardware port types are supported:

  • tcp , udp Modbus protocol implementations for TCP/IP networks. The params should be specified as: <protocol>:<host>[:port], e.g. tcp:192.168.11.11:502
  • rtu, ascii, binary Modbus protocol implementations for the local bus connected with USB or serial port. The params should be specified as: <protocol>:<device>:<speed>:<data>:<parity>:<stop> e.g. rtu:/dev/ttyS0:9600:8:E:1

As soon as the port is created, it can be used by PHI. Let’s create Modbus TCP port and load dae_ro16_modbus PHI module:

eva uc modbus create p1 tcp:192.168.11.11:502 -y
eva uc phi load r1 dae_ro16_modbus -c port=p1,unit=1 -y

As the result, controller creates a driver r1.default which can be set to item to work with any relay port of unit #1 of the Modbus relay 192.168.11.11 connected via TCP.

Warning

UC will grant Modbus port access to PHI only if it has enough timeout to wait for the longest possible call. It means operation timeout (action_timeout, update_timeout) in item should be greater than modbus_port_timeout*(1+modbus_port_retries). If the command max timeout is less than this value, attempts to access Modbus virtual port return an error.

If you need to change Modbus port params or options, you can always create new Modbus virtual port with the same ID, without deleting the previous one. Port configuration and options will be overwritten.

Testing Modbus virtual port

To test defined Modbus virtual port, execute the following command:

eva uc modbus test <ID>
# e.g.
eva uc modbus test p1

The command connects UC to Modbus port and checks the operation status.

Note

As Modbus UDP doesn’t require a port to be connected, test command always return “OK” result.

Deleting Modbus virtual port

To delete Modbus virtual port, execute the command:

eva uc modbus destroy <ID>
# e.g.
eva uc modbus destroy p1

Note that controller doesn’t check if the port is in use or not, so double check this manually before deleting it.

Generic Modbus drivers

If equipment has no dedicated PHI, generic Modbus PHIs can be used.

Note

The generic Modbus drivers don’t support bulk get/set requests and are not recommended for heavy production setups.

But for the most cases it’s possible to use the generic drivers for equipment monitoring and control only, fetching real-time data with external high-speed data pullers.

The modules are called:

  • modbus_sensor generic module for Modbus sensors
  • modbus_xvunit generic module for Modbus units

Both modules support widely-used Modbus data types, starting from simple coils and 16-bit unsigned integers and up to signed / unsigned 64-bit integers (4 x 16-bit registers) and 32-bit floats (2x 16-bit registers, IEEE 754-encoded). Refer to module help for more details.

modbus_xvunit supports both standard and “always-on” units, the last ones are used for complicated equipment, where only unit value is used, while the unit status is always 1.

Example: let’s create a sensor and bind IEEE 754-float to it, stored in the equipment holding registers 5 and 6. Consider Modbus virtual port “p1” is already defined.

# download PHI module if not downloaded yet
eva uc phi download https://get.eva-ics.com/phi/modbus/modbus_sensor.py
# load PHI, if not loaded yet
# here port = Modbus virtual port
eva uc phi load ms1 modbus_sensor -c port=p1,unit=1 -y
eva uc create sensor:tests/s1 -yE
# and here port = register number
# don't forget that extra PHI params (type, multiplier etc.) should be
# prefixed with an underscore
eva uc driver assign sensor:tests/s1 ms1.default -c port=h5,_type=f32 -y
# update the sensor state every 500 milliseconds
eva uc config set sensor:tests/s1 update_interval 0.5 -y

Another example: let’s create a unit with status 0/1 (OFF/ON) stored as 5th bit of holding register 1000:

# download PHI module if not downloaded yet
eva uc phi download https://get.eva-ics.com/phi/modbus/modbus_xvunit.py
# load PHI, if not loaded yet
# here port = Modbus virtual port
eva uc phi load m1 modbus_xvunit -c port=p1,unit=1 -y
eva uc create unit:tests/u1 -yE
# and here port = register number
eva uc driver assign unit:tests/u1 m1.default -c port=h1000/5 -y
# update the unit state every 5 seconds
eva uc config set unit:tests/u1 update_interval 5 -y
# update unit state after each action to make sure the state is properly set
eva uc config set unit:tests/u1 update_exec_after_action 1 -y
# execute test action
eva uc action toggle unit:tests/u1 -w 5

Modbus slave

Universal Controller can work as Modbus slave. Ports, the slave listens to, are set in etc/uc.ini. Modbus over TCP, UDP and serial ports (rtu/ascii/binary) is supported.

Controller uses single memory space for all ports it listens to, ports can have different Modbus addresses. Memory space has 10 000 holding registers, 10 000 coils, 10 000 input registers and 10 000 discrete inputs.

Units can listen to memory space changes and automatically update their status and value as soon as Modbus register is being changed. To activate state updates via Modbus slave memory space, set unit modbus_status and/or modbus_value properties to the corresponding registers, using before the number c for coil and h for holding register, e.g. c5 for 5th coil register, h50 for 50th holding register etc.

As Modbus values can be only integers, you may specify divider (or multiplier as well). To convert unsigned integer to signed, specify “S” before address. E.g. you have Modbus temperature sensor which stores its value every X seconds to holding register 5 on Universal Controller, multiplied by 100 and as signed integer. To automatically convert this value, set modbus_value = hS5/100

Sensors can update their value only. Don’t forget to enable sensor (set its status to 1) manually.

More complex data processing can be performed via PHI modules.

OWFS (1-Wire)

Universal Controller provides native support of 1-Wire technology for OWFS physical interfaces (PHIs). Core support is provided with OWFS.

For the simple setups, when 1-Wire bus is connected via system GPIO, PHIs can access it directly. But when 1-Wire is accessed via I2C, USB or other external bus, OWFS is preferred.

EVA ICS provides additional functionality for OWFS, such as bus locking, automatic retry attempts, virtual ports for drivers etc.

Setup

Starting from EVA ICS 3.3.2, OWFS libraries are not installed by default.

Automatic setup
eva feature setup owfs

Note

Automatic setup is not supported on RedHat Enterprise Linux 8

Manual setup
apt -y install libow-dev
# or for Fedora
yum install -y owfs-libs owfs-devel

and add Python library to EVA ICS venv: set EXTRA=”onewire==0.2” in /opt/eva/etc/venv and rebuild EVA ICS venv (/opt/eva/install/build-venv).

Defining OWFS bus

Before using any OWFS PHI, you must define OWFS bus. OWFS PHIs work with defined buses only, while UC handles all hardware calls and responses.

List of the defined OWFS buses be obtained with command:

eva uc owfs list

To define new OWFS bus, execute the following command:

eva uc owfs create [-h] [-l] [-t SEC] [-r RETRIES] [-d SEC] [-y] ID LOCATION

where:

  • -l lock bus on operations, which means to wait while OWFS bus is used by another controller thread (driver command)
  • -t SEC operations timeout (in seconds, default: default timeout)
  • -r RETRIES retry attempts for each operation (default: no retries)
  • -d SEC delay between operations (default: 50ms)
  • -y save OWFS config after creation
  • ID bus ID which will be used later in PHI configurations
  • LOCATION OWFS location

OWFS location should contain the configuration of OWFS port. Actually it’s equal to standard OWFS params, except first are not required:

# defines owfs bus on I2C#1
eva uc owfs create local1 "i2c=/dev/i2c-1:ALL" -y
# defines owfs bus on I2C#0 (force)
eva uc owfs create local2 "/dev/i2c-0 --w1" -y
# define owfs bus on local owserver
eva uc owfs create local3 localhost:4304 -y

As soon as the bus is defined, it can be used by PHI.

eva uc owfs scan local1 -a PIO
# 05.4AEC29CDBAAB  DS2405
# download PHI if not installed yet
eva uc phi download https://get.eva-ics.com/phi/relays/ow_ds2405.py
# load PHI
eva uc phi load relay1 ow_ds2405 -c owfs=local1,path=05.4AEC29CDBAAB -y

As the result, controller creates a driver relay.default which can be set to item.

Warning

UC will grant OWFS bus access to PHI only if it has enough timeout to wait for the longest possible call. It means operation timeout (action_timeout, update_timeout) in item should be greater than owfs_bus_timeout*(1+owfs_bus_retries). If the command max timeout is less than this value, attempts to access OWFS bus return an error.

If you need to change OWFS bus params or options, you can always define new OWFS bus with the same ID, without deleting the previous one. Bus configuration and options will be overwritten.

Scanning OWFS for devices

With scan command you can scan OWFS bus for the devices which have e.g. specified attributes:

eva uc owfs scan <ID> [options]
# e.g. let's find all 1-Wire equipment which has "temperature" property:
eva uc owfs scan local1 -a temperature

Deleting OWFS bus

To delete (undefine) OWFS bus, execute the command:

eva uc owfs destroy <ID>
# e.g.
eva uc owfs destroy local1

Note that controller doesn’t check if the port is in use or not, so double check this manually before deleting it.

Also note that some bus types lock system ow libraries and can not be recreated until Universal Controller process is restarted.

SNMP

Collecting and sending data

SNMP get and set commands are processed either with item scripts or with drivers.

Connecting equipment with drivers

Supported SNMP equipment can be quickly connected with corresponding PHI modules. Some modules support net-snmp. This library is faster than pysnmp installed by default, but requires additional system setup:

eva feature setup netsnmp

or manually:

  • add python3-netsnmp==1.1a1 to EXTRA section of “etc/venv” configuration file
  • install required system libraries:
apt -y install libsnmp-dev
# or for Fedora
yum install -y net-snmp-devel
  • rebuild EVA ICS venv (/opt/eva/install/build-venv).

Universal processing

SNMP traps

Active item updates can be done using SNMP traps notifications.

Usually each automation device sends SNMP traps in its specific format and the data should be parsed individually for subsequent processing. You can use a third-party server to receive traps, for example, snmptrapd or trap handler included in EVA Universal Controller.

Built-in trap handler should be enabled in UC configuration file. Usually, SNMP traps server listen on the port 162. The embedded SNMP traps handler can work with SNMP v1 and SNMP v2c protocols.

Both units and sensors can update their state through SNMP traps processing. After the item configuration param snmp_trap is set up, it automatically subscribes to the incoming notifications and accept only the relevant ones.

Currently EVA works with SNMP OIDs only - all snmp variables should be created in this format. To change snmp_trap variable and its child elements you may use eva uc console app or UC API set_prop function. In this tutorial we’ll configure SNMP-traps handler with eva uc.

ident_vars - identifying the trap

snmp_trap.ident_vars variable is used by the handler to filter trap notifications and parse only those ones directly related to the item. You should use it if, for example, the source sends the state change notifications with the same OID for different items, but the trap contains some tokens or item IDs identifying that the notification is addressed to the particular item. You can set several ident vars (separated by a comma) at once. The notification will be processed only if all ident_vars match the trap.

Example:

eva uc config set unit1 snmp_trap.ident_vars 1.3.6.1.4.1.3856.1.7.11.0=14,1.3.6.1.4.1.3856.1.7.11.1=U1

Result:

eva uc -J config props unit1
{
"snmp_trap": {
       "ident_vars": {
           "1.3.6.1.4.1.3856.1.7.11.0": "14",
           "1.3.6.1.4.1.3856.1.7.11.0": "U1"
       },
    }
}

To reset ident_vars variable, run the command without -v key.

set_down - handling the failures

When the controller receives trap notification indicating that the item is not available or disabled, its status is set to -1.

This can be made with set_down variable, which’s set similarly to ident_vars. If there are several OID, they should be listed and separated by commas when setting up. The handler assigns an error status to the item only if all set_down variables match the trap.

Example:

eva uc config set unit1 snmp_trap.set_down 1.3.6.1.4.1.3855.1.7.9.0=7

Result:

eva uc -J config props unit1
{
"snmp_trap": {
   "set_down": {
       "1.3.6.1.4.1.3855.1.7.9.0": "7"
   }
}

To reset set_down variable, run the command without -v key.

set_status - setting the item status

If the source device sends trap notifications with variable having the item status in the format similar to EVA, the handler can immediately change the status to the assigned one. Each item can have only one set_status variable containing OID where item status is being set in a trap.

Example:

eva uc config set unit1 snmp_trap.set_status 1.3.6.1.4.1.3855.1.7.17.1

Result:

eva uc -J config props unit1
{
"snmp_trap": {
   "set_status": "1.3.6.1.4.1.3855.1.7.17.1"
   }
}

To reset set_status variable, run the command without -v key.

set_value - setting the item value

If the source device sends trap notifications with the variable having the item value (usually, these are various sensor controllers which e.g. send current temperature every minute), the handler can immediately change the value to the assigned one. Each item can have only one set_value variable containing OID where item value is set in a trap.

Example:

eva uc config set unit1 snmp_trap.set_value 1.3.6.1.4.1.3855.1.7.17.2

Result:

eva uc -J config props unit1
{
"snmp_trap": {
   "set_value": "1.3.6.1.4.1.3855.1.7.17.2"
   }
}

To reset set_value variable, run the command without -v key.

set_if - conditional state updates

If the received trap notification contains certain variables but none of them can be used to set status and/or value as-is, you can define your own rules and set the item status/value according to them.

This operates similarly to set_down, the only difference is that set_down sets the item status to -1, while set_if allows you to set the status and/or value on your own.

The variable is set as follows:

status,value:OID=val1,OID2=val2,OID3=val3

If you don’t need to set status or value, set it to null when defining.

For example, let’s add two conditions:

eva uc config set unit1 snmp_trap.set_if 1,null:1.3.6.1.4.1.3855.1.7.1.0=4
eva uc config set unit1 snmp_trap.set_if null,10:1.3.6.1.4.1.3855.1.7.1.0=2

Result:

eva uc -J config props unit1
{
"snmp_trap": {
    "set_if": [
        {
               "value": "10",
               "vars": {
                   "1.3.6.1.4.1.3855.1.7.1.0": "2"
                }
        },
        {
            "status": 1,
            "vars": {
                "1.3.6.1.4.1.3855.1.7.1.0": "4"
            }
        }]
    }
}

When the controller receives a trap with OID 1.3.6.1.4.1.3855.1.7.1.0=2, the value of the item is set to 10. When OID 1.3.6.1.4.1.3855.1.7.1.0=4, the status is set to 1.

One item can have multiple set_if conditions but they can only be added. You can delete the condition only by deleting the entire set_if variable by running the command without -v key.

Disabling SNMP traps processing

To disable SNMP traps processing for a single item, delete its snmp_traps variable:

eva uc config set unit1 snmp_trap ''

Virtual items

Universal Controller items may be either virtual or real. You may toggle the item by changing configuration while the server is running.

Virtual drivers

If you want to build a virtual setup, the best idea is to use virtual drivers . EVA ICS distribution includes 2 virtual PHIs (drivers) which cover all typical needs:

  • vrtrelay Virtual relay driver
  • vrtsensors Virtual sensor pool driver

Both PHIs work like the real ones so all you need to switch your setup to production - assign “real” drivers to items or just load “real” PHIs with the same IDs.

Logic macros

In Logic Manager macros can be triggered on the list of events, third-party applications or user via LM EI interface or LM API functions.

Macro code is a file written in Python and located in the folder xc/lm/ under the name <macro_id>.py, i.e. test.py for “test” macro. Macro id should be unique within the single LM PLC, full id (group/id) - within the whole installation.

Additionally, each macro is automatically appended with common.py file located in the same folder enabling to quickly assign common functions to several macros without using modules.

Macros are compiled into byte-code each time after macros file or common.py file are changed. Compilation or execution errors can be viewed in the log files of the controller.

Contents

Executing macros

To execute a macro, use macro run command of eva lm or LM API run function.

Note

If you need to execute or use a single macro function, you may do this directly, adding “@” symbol to function name, e.g. @action_toggle, @start, etc.

Debugging macros

Macro compilation and execution errors are written into the logs of the controller on DEBUG level, the exceptions are also added to err field of the execution result.

To receive information about errors you may run the following command:

eva lm -J run <macro_id> -w 3600 | jq -r .err

Macros configuration

After the macro code is placed into xc/lm/<macro_id>.py file, it should be appended to the controller using create_macro LM API function or with eva lm.

After the macro configuration is created, you may view its params using list_macro_props and change them with set_macro_prop.

Parameters:

  • id macros id, can’t be modified after the macro is created
  • action_enabled true means macro can be executed (true by default)
  • action_exec controller gets the code of the macro from the file <macro_id>.py by default, use this parameter to assign another file
  • description macro description
  • group macro group (in difference to other objects, macro group can be changed after creation)
  • pass_errors if true, in case the function called by macro is completed with an exception, the controller ignores this and continues the code execution (false by default)
  • send_critical if true, allows to send critical events to controller core with critical(msg, send_event=True)

Common principles of macros operation

Macros are launched simultaneously: system does not wait for the completion of the macro and launches its next copy or another macro in parallel. If you want only one copy of macro to operate at the certain point of time or to block execution of other macros, use macro lock and unlock functions.

The system architecture does not provide the possibility to stop macro from outside, that is why macros should have minimum internal logic and cycles.

All the logic should be implemented in the decision-making matrix. The working cycles should be implemented with logic variables timers.

System macros

On startup

If defined, macro named system/autoexec is launched automatically at the controller startup. This macro is not always the first one executed, as far as some initial decision-making rules may call assigned macros, or some events may be handled before. In case a macro is launched later than logic variables or other loadable items update their status (e. g. due to slow connection with MQTT server) it’s recommended to use sleep function to do a small delay.

Macros from system group are considered as the local system macros and aren’t synchronized to SFA.

Example of autoexec macro usage:

# both cycle timers are expired
if is_expired('timers/timer1') and is_expired('timers/timer2'):
    # launch the first cycle process
    action('pumps/pump1', on)
    # start the first cycle timer
    reset('timers/timer1')
On shutdown

If defined, macro named system/shutdown is launched automatically at the controller shutdown. This macro can, for example, gracefully stop cycles and set/reset required logic variables. The macro should end its work in default controller timeout.

Macros and security

As all Python features are available for macros, including execution of external programs or working with any local files, the code of macros should be edited only by system administrator.

If access permissions to individual macros are configured via API keys, you should take into account the following: if a macro runs other macros using run function, these macros will be executed even if the API key allows to run only the initial macro.

Macros built-ins

Macros can execute any Python functions or use Python modules installed on the local server. In addition, macros have a set of built-in functions and variables.

Built-in functions are included for quick access to the most frequently used Python functions such as LM API and UC API. When calling API function, item id is always transmitted in full. When calling other macros and working with logic variables, it’s possible to use the short ids only.

Variables

Macros have the following built-in variables:

  • on alias to integer 1
  • off alias to integer 0
  • yes alias to boolean True
  • no alias to boolean False
  • _source item generated the event, used by the system to call the macro. You may directly access the item and e.g. use its internal variables such as _source.item_id, _source.full_id, _source.oid etc.
  • _polldelay controller poll delay
  • _timeout controller default timeout
  • args array list of arguments the macro is being executed with
  • kwargs dict of keyword arguments the macro is being executed with
  • _0 current macro id (i.e. ‘test’)
  • _00 current macro full id (i.e. ‘group1/test’)
  • _1, _2, … _9 first 9 arguments the macro is being executed with
  • out macro may use this variable to output the data which will be set to out field of the execution result
  • is_shutdown contains a function which returns True if macro caller got a core shutdown or cycle stop event.
  • all lm_cvars variables

Note

if macro arguments or lm_cvars are numbers, they are automatically converted to float type

Extending macros functionality

Macros function set can be extended with pre-made or custom macro extensions. As soon as extension is loaded, its functions become available in all macros without a need to restart LM PLC.

Also, macro can import any local Python module. The following modules are pre-imported:

General functions

alias - create object alias
alias('rpush', 'roboger_local_push')

Parameters:

  • alias_obj alias object
  • src_obj source object

Returns:

True if alias is set. Doesn’t raise any exceptions, safe to use in common files

cmd - execute a remote system command

Executes a command script on the server where the controller is installed.

r = cmd('uc/mws1-v1', 'test', wait=5)

Parameters:

  • controller_id controller id to execute command on
  • command name of the command script

Optionally:

  • args string of command arguments, separated by spaces (passed to the script)
  • wait wait (in seconds) before API call sends a response. This allows to try waiting until command finish
  • timeout maximum time of command execution. If the command fails to finish within the specified time (in sec), it will be terminated
  • stdin_data data to be passed to script STDIN

Returns:

Serialized command action object (dict)

{
    "args": [],
    "cmd": "test",
    "err": "some text to stderr\n",
    "exitcode": 0,
    "out": "test script start\nparam 1:  ( > 0 will generate \"failed\" status)\nparam 2: \nparam 3: \ndelay 3 sec\nscript finish\n",
    "status": "completed",
    "time": {
        "completed": 1553466937.5606368,
        "created": 1553466934.5421243,
        "running": 1553466934.5424464
    },
    "timeout": 5.0
}

Raises:

  • ResourceNotFound command script or controller is not found
date - date/time
r = date()

Returns:

Serialized date/time object (dict)

{
    "day": 14,
    "hour": 0,
    "minute": 47,
    "month": 5,
    "second": 16,
    "timestamp": 1557787636.680612,
    "weekday": 1,
    "year": 2019
}
decrement_shared - decrement value of the shared variable

Decrement value of the variable, shared between controller macros. Initial value must be number

decrement_shared('counter1')

Parameters:

  • name variable name
exit - finish macro execution
exit(1)

Parameters:

  • code macro exit code (default: 0, no errors)
get_directory - get path to EVA ICS directory

Parameters:

  • tp directory type: eva, runtime, ui, pvt or xc

Raises:

  • LookupError if directory type is invalid
increment_shared - increment value of the shared variable

Increment value of the variable, shared between controller macros. Initial value must be number

increment_shared('counter1')

Parameters:

  • name variable name
ls - list files in directory

If recursive is true, the pattern “**” will match any files and zero or more directories and subdirectories.

r = ls('/opt/i/*.jpg')

Parameters:

  • mask path and mask (e.g. /opt/data/*.jpg)
  • recursive if True, perform a recursive search

Returns:

dict with fields ‘name’ ‘file’, ‘size’ and ‘time’ { ‘c’: created, ‘m’: modified }

[
    {
        "file": "/opt/i/20170926_004347.jpg",
        "name": "20170926_004347.jpg",
        "size": 6464873,
        "time": {
            "c": 1553460493.280853,
            "m": 1506379536.0
        }
    },
    {
        "file": "/opt/i/20171017_095941.jpg",
        "name": "20171017_095941.jpg",
        "size": 1650389,
        "time": {
            "c": 1553460493.2968528,
            "m": 1510695841.0
        }
    },
    {
        "file": "/opt/i/20171029_194029.jpg",
        "name": "20171029_194029.jpg",
        "size": 3440296,
        "time": {
            "c": 1553460493.324853,
            "m": 1510695762.0
        }
    },
    {
        "file": "/opt/i/20170926_004334.jpg",
        "name": "20170926_004334.jpg",
        "size": 6523001,
        "time": {
            "c": 1553460493.1648533,
            "m": 1506379526.0
        }
    }
]
mail - send email message

The function uses [mailer] section of the LM PLC configuration to get sender address and list of the recipients (if not specified).

mail(subject='we have a problem', text='sensor 5 is down')

Optionally:

  • subject email subject
  • text email text
  • rcp recipient or array of the recipients

Raises:

  • FunctionFailed mail is not sent
open_newest - open newest file by mask
i = open_newest('/opt/i/*.jpg', 'rb').read()
print(r)

None

Parameters:

  • mask path and mask (e.g. /opt/data/*.jpg)

Optionally:

  • mode file open mode (default: ‘r’)

Returns:

file descriptor

Raises:

  • Exception exceptions equal to Python “open” function
open_oldest - open oldest file by mask
i = open_oldest('/opt/i/*.jpg', 'rb').read()
print(r)

None

Parameters:

  • mask path and mask (e.g. /opt/data/*.jpg)

Optionally:

  • mode file open mode (default: ‘r’)

Returns:

file descriptor

Raises:

  • Exception exceptions equal to Python “open” function
ping - ping remote host

Requires fping tool

Parameters:

  • host host name or IP to ping
  • timeout ping timeout in milliseconds (default: 1000)
  • count number of packets to send (default: 1)

Returns:

True if host is alive, False if not

run - execute another macro

Execute a macro with the specified arguments.

r = run('tests/test1', kwargs={'v1': 'test', 'v2': 999}, wait=2)

Parameters:

  • macro macro id

Optionally:

  • args macro arguments, array or space separated
  • kwargs macro keyword arguments, name=value, comma separated or dict
  • wait wait for the completion for the specified number of seconds
  • uuid action UUID (will be auto generated if none specified)
  • priority queue priority (default is 100, lower is better)

Returns:

Serialized macro action object (dict)

{
    "args": [],
    "err": "",
    "exitcode": 0,
    "finished": true,
    "finished_in": 0.0047829,
    "item_group": "tests",
    "item_id": "test1",
    "item_oid": "lmacro:tests/test1",
    "item_type": "lmacro",
    "kwargs": {
        "v1": "test",
        "v2": 999
    },
    "out": "",
    "priority": 100,
    "status": "completed",
    "time": {
        "completed": 1559869087.3697698,
        "created": 1559869087.364987,
        "pending": 1559869087.3653126,
        "queued": 1559869087.3661342,
        "running": 1559869087.3669574
    },
    "uuid": "fc0e8c8e-9c93-49c4-bb30-e7905fedc33f"
}

Raises:

  • ResourceNotFound macro is not found
set_shared - set value of the shared variable

Set value of the variable, shared between controller macros

set_shared('var1', 777)

Parameters:

  • name variable name

Optionally:

  • value value to set. If empty, varible is deleted
sha256sum - calculate SHA256 sum

Parameters:

  • value value to calculate
  • hexdigest return binary digest or hex (True, default)

Returns:

sha256 digest

shared - get value of the shared variable

Get value of the variable, shared between controller macros

r = shared('var1')
print(r)

777

Parameters:

  • name variable name

Optionally:

  • default value if variable doesn’t exist

Returns:

variable value, None (or default) if variable doesn’t exist

sleep - pause operations

Unlike standard time.sleep(…), breaks pause when controller shutdown event is received.

sleep(0.1)

Parameters:

  • t number of seconds to sleep

Optionally:

  • safe break on shutdown event (default is True)

Returns:

True if sleep is finished, False if shutdown event is received

system - execute the command in a subshell
r = system('touch /tmp/1.dat')
print(r)

0

Returns:

shell exit code (0 - no error)

time - current time in seconds since Epoch

Return the current time in seconds since the Epoch. Fractions of a second may be present if the system clock provides them.

r = time()
print(r)

1553461581.549374

Item functions

history - get item state history

To use this function, DB or TSDB notifier in LM PLC must be present. (notifier can share DB with SFA in read/only mode).

r = history('lvar:tests/test1', t_start='2019-03-24')

Parameters:

  • item_id item ID, or multiple IDs (list or comma separated)

Optionally:

  • t_start time frame start, ISO or Unix timestamp
  • t_end time frame end, optional (default: current time), ISO or Unix timestamp
  • limit limit history records
  • prop item property (‘status’ or ‘value’
  • time_format time format, ‘iso’ or ‘raw’ (default) for timestamp
  • fill fill frame with the specified interval (e.g. 1T - 1 minute, 2H - 2 hours etc.), optional. If specified, t_start is required
  • fmt output format, ‘list’ (default) or ‘dict’
  • db notifier ID which keeps history for the specified item(s) (default: db_1)

Returns:

list of dicts or dict of lists

{
    "status": [
        1,
        1,
        1,
        1
    ],
    "t": [
        1553461864.9564857,
        1553461878.8139935,
        1553461883.1168087,
        1553461887.6495461
    ],
    "value": [
        0.0,
        0.0,
        1.0,
        1.0
    ]
}
lvar_status - get lvar status
r = lvar_status('tests/test1')
print(r)

1

Parameters:

  • lvar_id lvar id

Returns:

lvar status (integer)

Raises:

  • ResourceNotFound lvar is not found
lvar_value - get lvar value
r = lvar_value('tests/test1')
print(r)

1.0

Parameters:

  • lvar_id lvar id

Returns:

lvar value

sensor_status - get sensor status
r = sensor_status('env/temp_test')
print(r)

1

Parameters:

  • sensor_id sensor id

Returns:

sensor status (integer)

Raises:

  • ResourceNotFound sensor is not found
sensor_value - get sensor value
r = sensor_value('env/temp_test')
print(r)

191.0

Parameters:

  • sensor_id sensor id

Optionally:

  • default value if null (default is empty string)

Returns:

sensor value

Raises:

  • ResourceNotFound sensor is not found
state - get item state
r = state('sensor:env/temp1')

Parameters:

  • item_id item id (oid required)

Returns:

item status/value dict

{
    "status": 1,
    "value": 55.0
}

Raises:

  • ResourceNotFound item is not found
status - get item status
r = status('unit:tests/unit1')
print(r)

0

Parameters:

  • item_id item id (oid required)

Returns:

item status (integer)

Raises:

  • ResourceNotFound item is not found
unit_nstatus - get unit nstatus

nstatus is the status which is set to unit after the current running action is completed.

the function may be called with an alias “nstatus(…)”

r = unit_nstatus('tests/unit1')
print(r)

0

Parameters:

  • unit_id unit id

Returns:

unit nstatus (integer)

Raises:

  • ResourceNotFound unit is not found
unit_nvalue - get unit nvalue

nvalue is the value which is set to unit after the current running action is completed.

the function may be called with an alias “nvalue(…)”

r = unit_nvalue('tests/unit1')
print(r)

Parameters:

  • unit_id unit id

Returns:

unit nvalue

Raises:

  • ResourceNotFound unit is not found
unit_status - get unit status
r = unit_status('tests/unit1')
print(r)

0

Parameters:

  • unit_id unit id

Returns:

unit status (integer)

Raises:

  • ResourceNotFound unit is not found
unit_value - get unit value
r = unit_value('tests/unit1')
print(r)

Parameters:

  • unit_id unit id

Optionally:

  • default value if null (default is empty string)

Returns:

unit value

Raises:

  • ResourceNotFound unit is not found
value - get item value
r = value('sensor:env/temp_test')
print(r)

191.0

Parameters:

  • item_id item id (oid required)

Optionally:

  • default value if null (default is empty string)

Returns:

item value

Raises:

  • ResourceNotFound item is not found

LVar functions

clear - reset lvar value

Set lvar value to 0 or stop timer lvar (set timer status to 0)

clear('tests/test1')

Parameters:

  • lvar_id lvar id

Raises:

  • FunctionFailed lvar value set error
  • ResourceNotFound lvar is not found
decrement - decrement lvar value

Decrement value of lvar. Initial value should be number

decrement('tests/test1')

Parameters:

  • lvar_id lvar id

Raises:

  • FunctionFailed lvar value decrement error
  • ResourceNotFound lvar is not found
expires - set lvar expiration time
expires('timers/timer1', 30)

Parameters:

  • lvar_id lvar id

Optionally:

  • etime time (in seconds), default is 0 (never expires)

Raises:

  • FunctionFailed lvar expiration set error
  • ResourceNotFound lvar is not found
increment - increment lvar value

Increment value of lvar. Initial value should be number

increment('tests/test1')

Parameters:

  • lvar_id lvar id

Raises:

  • FunctionFailed lvar value increment error
  • ResourceNotFound lvar is not found
is_expired - is lvar (timer) expired
r = is_expired('nogroup/timer1')
print(r)

True

Parameters:

  • lvar_id lvar id

Returns:

True, if timer has expired

Raises:

  • ResourceNotFound lvar is not found
reset - reset lvar value

Set lvar value to 1 or start lvar timer

reset('tests/test1')

Parameters:

  • lvar_id lvar id

Raises:

  • FunctionFailed lvar value set error
  • ResourceNotFound lvar is not found
set - set lvar value
set('tests/test1', value=1)

Parameters:

  • lvar_id lvar id

Optionally:

  • value lvar value (if not specified, lvar is set to null)

Raises:

  • FunctionFailed lvar value set error
  • ResourceNotFound lvar is not found
toggle - toggle lvar value

Change lvar value to opposite boolean (0->1, 1->0)

toggle('tests/test1')

Parameters:

  • lvar_id lvar id

Raises:

  • FunctionFailed lvar value set error
  • ResourceNotFound lvar is not found

Unit control

action - unit control action

The call is considered successful when action is put into the action queue of selected unit.

r = action('tests/unit1', status=1, wait=5)

Parameters:

  • unit_id unit id
  • status desired unit status

Optionally:

  • value desired unit value
  • wait wait for the completion for the specified number of seconds
  • uuid action UUID (will be auto generated if none specified)
  • priority queue priority (default is 100, lower is better)

Returns:

Serialized action object (dict)

{
    "err": "",
    "exitcode": 0,
    "finished": true,
    "finished_in": 0.0149484,
    "item_group": "tests",
    "item_id": "unit1",
    "item_oid": "unit:tests/unit1",
    "item_type": "unit",
    "nstatus": 1,
    "nvalue": null,
    "out": "",
    "priority": 100,
    "status": "completed",
    "time": {
        "completed": 1559869105.9634602,
        "created": 1559869105.9485118,
        "pending": 1559869105.9487257,
        "queued": 1559869105.9491074,
        "running": 1559869105.949467
    },
    "uuid": "4bce26a6-7203-4a3c-a123-14c144dcc613"
}

Raises:

  • FunctionFailed action is “dead”
  • ResourceNotFound unit is not found
action_toggle - toggle unit status

Create unit control action to toggle its status (1->0, 0->1). if using OID, you can also call “toggle(..)” with the same effect.

r = action_toggle('tests/unit1', wait=5)

Parameters:

  • unit_id unit id

Optionally:

  • value desired unit value
  • wait wait for the completion for the specified number of seconds
  • uuid action UUID (will be auto generated if none specified)
  • priority queue priority (default is 100, lower is better)

Returns:

Serialized action object (dict)

{
    "err": "",
    "exitcode": 0,
    "item_group": "tests",
    "item_id": "unit1",
    "item_oid": "unit:tests/unit1",
    "item_type": "unit",
    "nstatus": 0,
    "nvalue": "",
    "out": "",
    "priority": 100,
    "status": "completed",
    "time": {
        "completed": 1553465690.1327171,
        "created": 1553465690.1081843,
        "pending": 1553465690.1084123,
        "queued": 1553465690.1089923,
        "running": 1553465690.1094682
    },
    "uuid": "0982213a-6c8f-4df3-8581-d1281d0f41dc"
}

Raises:

  • FunctionFailed action is “dead”
  • ResourceNotFound unit is not found
is_busy - is unit busy
r = is_busy('tests/unit1')
print(r)

False

Parameters:

  • unit_id unit id

Returns:

True, if unit is busy (action is executed)

Raises:

  • ResourceNotFound unit is not found
kill - kill unit actions

Apart from canceling all queued commands, this function also terminates the current running action.

kill('tests/unit1')

Parameters:

  • unit_id unit id

Raises:

  • ResourceNotFound unit is not found
q_clean - clean action queue of unit

Cancels all queued actions, keeps the current action running.

q_clean('tests/unit1')

Parameters:

  • unit_id unit id

Raises:

  • ResourceNotFound unit is not found
result - get action status

Checks the result of the action by its UUID or returns the actions for the specified unit.

r = result(unit_id='tests/unit1')

Parameters:

  • unit_id unit id or
  • uuid action uuid

Optionally:

  • group filter by unit group
  • status filter by action status: Q for queued, R for running, F for finished

Returns:

list or single serialized action object

[
    {
        "err": "",
        "exitcode": 0,
        "finished": true,
        "finished_in": 0.0147429,
        "item_group": "tests",
        "item_id": "unit1",
        "item_oid": "unit:tests/unit1",
        "item_type": "unit",
        "nstatus": 0,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "completed",
        "time": {
            "completed": 1559869099.8924437,
            "created": 1559869099.8777008,
            "pending": 1559869099.8778677,
            "queued": 1559869099.8782423,
            "running": 1559869099.8786528
        },
        "uuid": "d5b82c8c-9a95-482a-9063-e3048addc741"
    },
    {
        "err": "",
        "exitcode": 0,
        "finished": true,
        "finished_in": 0.0149484,
        "item_group": "tests",
        "item_id": "unit1",
        "item_oid": "unit:tests/unit1",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "completed",
        "time": {
            "completed": 1559869105.9634602,
            "created": 1559869105.9485118,
            "pending": 1559869105.9487257,
            "queued": 1559869105.9491074,
            "running": 1559869105.949467
        },
        "uuid": "4bce26a6-7203-4a3c-a123-14c144dcc613"
    }
]

Raises:

  • ResourceNotFound unit or action is not found
start - start unit

Create unit control action to set its status to 1

r = start('tests/unit1', wait=5)

Parameters:

  • unit_id unit id

Optionally:

  • value desired unit value
  • wait wait for the completion for the specified number of seconds
  • uuid action UUID (will be auto generated if none specified)
  • priority queue priority (default is 100, lower is better)

Returns:

Serialized action object (dict)

{
    "err": "",
    "exitcode": 0,
    "finished": true,
    "finished_in": 0.0179181,
    "item_group": "tests",
    "item_id": "unit1",
    "item_oid": "unit:tests/unit1",
    "item_type": "unit",
    "nstatus": 1,
    "nvalue": null,
    "out": "",
    "priority": 100,
    "status": "completed",
    "time": {
        "completed": 1559869092.8558156,
        "created": 1559869092.8378975,
        "pending": 1559869092.838309,
        "queued": 1559869092.8390505,
        "running": 1559869092.8402033
    },
    "uuid": "bf74b19c-2af1-40f6-9ec6-5f74bb572558"
}

Raises:

  • FunctionFailed action is “dead”
  • ResourceNotFound unit is not found
stop - stop unit

Create unit control action to set its status to 0

r = stop('tests/unit1', wait=5)

Parameters:

  • unit_id unit id

Optionally:

  • value desired unit value
  • wait wait for the completion for the specified number of seconds
  • uuid action UUID (will be auto generated if none specified)
  • priority queue priority (default is 100, lower is better)

Returns:

Serialized action object (dict)

{
    "err": "",
    "exitcode": 0,
    "finished": true,
    "finished_in": 0.0147429,
    "item_group": "tests",
    "item_id": "unit1",
    "item_oid": "unit:tests/unit1",
    "item_type": "unit",
    "nstatus": 0,
    "nvalue": null,
    "out": "",
    "priority": 100,
    "status": "completed",
    "time": {
        "completed": 1559869099.8924437,
        "created": 1559869099.8777008,
        "pending": 1559869099.8778677,
        "queued": 1559869099.8782423,
        "running": 1559869099.8786528
    },
    "uuid": "d5b82c8c-9a95-482a-9063-e3048addc741"
}

Raises:

  • FunctionFailed action is “dead”
  • ResourceNotFound unit is not found
terminate - terminate action execution

Terminates or cancel the action if it is still queued

try:
terminate(unit_id='tests/unit1')
except ResourceNotFound:
print('no action running')

Parameters:

  • unit_id action uuid or
  • uuid unit id

Raises:

  • ResourceNotFound if unit/action is not found or action is already finished

Rule management

set_rule_prop - set rule prop
set_rule_prop('28af95b2-e087-47b3-a6cd-15fe21d06c4a', 'condition', 'x < 5')

Parameters:

  • rule_id rule id (uuid)
  • prop property to set
  • value value to set

Optionally:

  • save save rule config after the operation

Raises:

  • ResourceNotFound rule is not found

Scheduled job management

set_job_prop - set job prop
set_job_prop('6970e296-5cb4-4448-9f2a-1ab2a14ed7f1', 'enabled', True)

Parameters:

  • job_id job id (uuid)
  • prop property to set
  • value value to set

Optionally:

  • save save job config after the operation

Raises:

  • ResourceNotFound job is not found

Devices

deploy_device - deploy device items from template

Deploys the device from the specified template.

deploy_device('uc/mws1-v1', 'device1', cfg={ 'ID': 5 })

Parameters:

  • controller_id controller id to deploy device on
  • device_tpl device template (runtime/tpl/<TEMPLATE>.yml|yaml|json, without extension)

Optionally:

  • cfg device config (var=value, comma separated or dict)
  • save save items configuration on disk immediately after operation

Raises:

  • ResourceNotFound device template or controller is not found
  • FunctionFailed device deploy error
undeploy_device - undeploy device items config from template
undeploy_device('uc/mws1-v1', 'device1', cfg={ 'ID': 5 })

Parameters:

  • controller_id controller id to deploy device on
  • device_tpl device template (runtime/tpl/<TEMPLATE>.yml|yaml|json, without extension)

Optionally:

  • cfg device config (var=value, comma separated or dict)

Raises:

  • ResourceNotFound device template or controller is not found
update_device - update device items config from template
update_device('uc/mws1-v1', 'device1', cfg={ 'ID': 5 })

Parameters:

  • controller_id controller id to deploy device on
  • device_tpl device template (runtime/tpl/<TEMPLATE>.yml|yaml|json, without extension)

Optionally:

  • cfg device config (var=value, comma separated or dict)
  • save save items configuration on disk immediately after operation

Raises:

  • ResourceNotFound device template or controller is not found
  • FunctionFailed device update error

Logic cycles

get_cycle_info - get cycle information
r = get_cycle_info('tests/cycle1')

Parameters:

  • cycle_id cycle id

Returns:

dict with cycle information

{
    "description": "",
    "full_id": "tests/cycle1",
    "group": "tests",
    "ict": 20,
    "id": "cycle1",
    "interval": 0.01,
    "iterations": 0,
    "macro": "tests/test",
    "oid": "lcycle:tests/cycle1",
    "on_error": null,
    "status": 0,
    "type": "lcycle"
}

Raises:

  • ResourceNotFound cycle is not found
is_cycle_running - get cycle running status
r = is_cycle_running('tests/cycle1')
print(r)

True

Parameters:

  • cycle_id cycle id

Returns:

True if cycle is runing

Raises:

  • ResourceNotFound cycle is not found
list_cycle_props - list cycle props
r = list_cycle_props('tests/cycle1')

Parameters:

  • cycle_id cycle id

Returns:

dict with cycle props

{
    "autostart": false,
    "description": "",
    "ict": 20,
    "interval": 0.01,
    "macro": "tests/test",
    "on_error": null
}

Raises:

  • ResourceNotFound cycle is not found
reset_cycle_stats - reset cycle stats
reset_cycle_stats('tests/cycle1')

Parameters:

  • cycle_id cycle id

Raises:

  • ResourceNotFound cycle is not found
set_cycle_prop - set cycle prop
set_cycle_prop('tests/cycle1', 'ict', 20)

Parameters:

  • cycle_id cycle id
  • prop property to set
  • value value to set

Optionally:

  • save save cycle config after the operation

Raises:

  • ResourceNotFound cycle is not found
start_cycle - start cycle
start_cycle('tests/cycle1')

Parameters:

  • cycle_id cycle id

Raises:

  • ResourceNotFound cycle is not found
stop_cycle - stop cycle
stop_cycle('tests/cycle1', wait=True)

Parameters:

  • cycle_id cycle id

Optionally:

  • wait wait for cycle stop (default is False)

Raises:

  • ResourceNotFound cycle is not found

Locking functions

lock - acquire lock
lock('lock1', expires=1)

Parameters:

  • lock_id lock id

Optionally:

  • timeout max timeout to wait
  • expires time after which token is automatically unlocked (if absent, token may be unlocked only via unlock function)

Returns:

True if lock is acquired

Raises:

  • FunctionFailed function failed to acquire lock
unlock - release lock

Releases the previously acquired lock.

unlock('lock1')

Parameters:

  • l lock id

Returns:

True if lock is released

Raises:

  • ResourceNotFound lock is not found
  • FunctionFailed function failed to release lock

Logging

debug - put debug message to log file
debug('this is a test debug message')

Parameters:

  • msg message text
info - put info message to log file

Additionally, print() function is alias to info()

info('this is a test debug message')

Parameters:

  • msg message text
warning - put warning message to log file
info('this is a test debug message')

Parameters:

  • msg message text
error - put error message to log file
error('this is a test debug message')

Parameters:

  • msg message text
critical - put critical message to log file
critical('this is a test debug message')

Parameters:

  • msg message text

Optionally:

  • send_event if True, critical event to core is sent (requires send_critical=true in macro props)

Decision-making matrix

Decision-making matrix is a set of rules and conditions under that Logic Manager runs the specified macros when certain events occur.

To manage the decision rules you may use eva lm (lm-cmd) console applications, LM API functions or an appropriate LM EI interface section.

Rule configuration is stored in runtime/lm_dmatrix_rule.d/ folder.

Event analysis algorithms

Event means any change of the item state. The events are analyzed and processed in the following way:

  • A specific ID is assigned to each event by which you can monitor its processing in the logs.

  • The system takes the list of all rules sorted by their priority (the lower the value, the higher the priority) and description.

  • Each rule is analyzed separately, in the order of priority

  • Firstly, it’s checked whether the rule corresponds to the type, group, ID and property of the item that sent the event

  • Then, the system is verifying whether the current item state matches the rule conditions and the previous one is out of its range

    • For example, there is a temperature sensor; the condition 25 <= x <= 28 is specified in the rule; it will match only once - as soon as the transmitted temperature reaches 25-28 degrees. The rule will match again if the temperature exceeds this range and returns back.
    • When the controller is just started, the previous state is unknown or usually outdated. In this case, the system acts according to the configuration property of the rule for_initial: if it’s set to skip, the rule is ignored, if only or any, it’s verified and the rule matches if the current state matches the range.
    • If for_initial is set to only in the rule configuration, the rule is being checked only once, after the controller is started and the initial states of the items are received.
    • Logic variables always have an initial value stored in the local base, that’s why for_initial should always be any for them to let the rules work correctly, unless you really know what you do.
    • If the rule matches, a macro (if specified) with the specified arguments is executed.
    • If chillout_time > 0 in the configuration, the rule is ignored after the match for the specified time. If rule matched during chill-out, macro is executed once, after chill-out period ends.

Rule creation

Rules can be created with either LM API create_rule function or with EVA shell.

To configure rule you may specify condition and action, or you may set rule parameters one-by-one after the rule is created.

To specify condition and action during rule creation, use the following format. Note that controller doesn’t check is condition item and/or macro exists on the moment of rule creation:

rule create if <condition> [then <action>]

Example, start unit unit:ventilation/v1 (call start macro function) if value of sensor:env/temp is more than 25:

rule create if sensor:env/temp.value > 25 then @start('unit:ventilation/v1')

Another example. Run macro macro1 if value of lvar lvar:tests/lvar1 is more than 25 but less than 35:

rule create if 35 > lvar:tests/lvar1.value > 25 then macro1()

Check only 3rd bit of value:

rule create if sensor:env/plc_state.b3 == 1 then macro1()

Note

New rule is always created as “disabled” and you must enable it with “rule enable” CLI command or call LM API function set_rule_prop, setting enabled=True.

Rule configuration

Unmodifiable rule parameters:

  • id rule id, always generated automatically when it is created
  • chillout_ends_in a virtual parameter specifying for how long (in seconds) the rule is ignored, if chillout_time is set

Modifiable Parameters:

  • break_after_exec if True and the rule matches, further rules for the event are ignored
  • chillout_time the rule is ignored for a specified time (in seconds) after match
  • condition “virtual” parameter which allows get/set rule condition in the readable format (e.g. 25 < x <= 28)
  • description rule description
  • enabled if True, rule is enabled (new rules are disabled by default)
  • for_initial can be skip, only or any (default is skip). Indicates the rule processing algorithm when the server is started and the initial item states are received
  • for_item_group the rule matches only for a specific group of items (# or null - for all groups)
  • for_item_id the rule matches only for a specific item (# or null - for all items), may contain the mask *id, id* or *id*, i.e. *.temperature
  • for_item_type the rule matches only for a specific type of items (# or null - for all types)
  • for_oid “virtual” parameter which allows get/set rule condition in the readable format (e.g. sensor:group1/#.value)
  • for_prop the state property of the item (status or value) the rule is checking. For unit state, nstatus and nvalue properties may be additionally used.
  • for_prop_bit if set to a number (0-X), only state Xth bit is compared. Obviously, the compassion condition should be set either == 0 or == 1.
  • in_range_max matches when x < value
  • in_range_max_eq matches when x <= value (in_range_max should be specified)
  • in_range_min matches when x > value
  • in_range_min_eq matches when x >= value (in_range_min should be specified)
  • macro macro that is executed when the rule conditions match
  • macro_args arguments the macro is executed with
  • macro_kwargs keyword arguments the macro is executed with
  • priority the rule priority (integer; the lower the value, the higher the priority, 100 by default)

Tips for rule configuration

  • to set “x == value” condition via lm_api: if the value is numeric, use “value <= x <= value”. If the value is string, you may set only in_range_min_eq
  • if you set a field for_expire (with any value, i.e. Y) in a rule change request, the system automatically sets the rule to for_prop = status, x <= -1, which means the rule match when the item state is expired. This is useful to configure the rule to check for the lvar timers expiration as well as checking for units and sensors error states
  • if you set a field for_set (with any value, i.e. Y) in a rule change request, the system automatically sets the rule to for_prop = status, x == 1, which means the rule match when the item state is set. This is useful to configure the rule to check for the lvar timers reset as well as working with a logical flags
  • if the rule has no in_range_min and in_range_max conditions, it will match each time when the item changes its status (for_prop == status) or value (for_prop == value)

If rule option for_initial is set to any or only, it is possible to cache previous item state to prevent false rule triggering. This may cause additional system overload.

To enable state cache, set “cache_remote_state” option in section “plc” of lm.ini to desired cache time-to-live in seconds (e.g. 604800 = time-to-live 1 week) and restart the controller.

Or use “feature” command:

eva feature setup lm_state_cache ttl=604800

Scheduled jobs

Scheduled jobs are similar to decision-making rules except they’re triggered when the specified time comes.

To manage scheduled jobs you may use eva lm (lm-cmd) console applications, LM API functions or an appropriate LM EI interface section.

Jobs configuration is stored in runtime/lm_job.d/ folder.

Job creation

Jobs can be created with either LM API create_job function or with EVA shell.

To configure job you may specify action and schedule, or you may set job parameters one-by-one after the job is created.

To specify action and schedule during job creation, use the following format. Note that controller doesn’t check is macro exists on the moment of job creation:

eva -I
lm
job create [action] [every <schedule>]

Example, start unit unit:ventilation/v1 (call start macro function) every 5 minutes.

job create @start('unit:ventilation/v1') every 5 minutes

Another example, run macro macro1 every hour:

job create macro1(1, 2, x=test) every hour

Note

New job is always created as “disabled” and you must enable it with “job enable” CLI command or call LM API function set_job_prop, setting enabled=True.

Job configuration

  • description job description
  • enabled if True, job is enabled (new jobs are disabled by default)
  • every schedule interval
  • macro macro that is executed
  • macro_args arguments the macro is executed with
  • macro_kwargs keyword arguments the macro is executed with

Job schedule interval

Schedule interval (every parameter) is set in a human-readable format. Examples:

  • second execute job every second
  • 5 seconds execute job every 5 seconds
  • 2 minutes at :30 execute job every 2 minutes at 30th second
  • 5 hours execute job every 5 hours
  • 2 days execute job every 2 days
  • wednesday at 13:15 execute job every Wednesday at 13:15

Logic cycles

Logic Manager allows to define logic cycles. Logic cycle is a loop which run specified macro as a worker with a chosen interval.

Logic Manager can create new cycles, start, stop them and reset their stats. Cycle information is replicated to SCADA Final Aggregator nodes, however SFA can access logic cycles read-only.

Cycle control from SFA nodes (and UI) is possible only by calling pre-made LM PLC macros, which can use macro control functions to manage cycles.

Note

For the heavy industry processes we strongly recommend to use dedicated hardware production cycle controllers and control/monitor them using EVA ICS as a supervisor only.

Cycle creation

Cycles can be created with either LM API create_cycle function or with EVA shell.

To configure cycle you may specify action and interval, or you may set cycle parameters one-by-one after the cycle is created.

To specify action and interval during cycle creation, use the following format:

eva -I
lm
cycle create <cycle_id> [action] [interval <seconds>]

Example, start unit unit:lamp/lamp1 (call start macro function) with interval 0.5 seconds.

cycle create cycle1 @start('unit:lamp/lamp1') interval 0.5

Another example, run macro macro1 every 100 milliseconds:

cycle create cycle2 macro1(1, 2, x=test) interval 0.1

Note

Cycle ID must be unique within a Logic Manager.

Cycle configuration

Each lcycle object has the following parameters:

  • autostart cycle will start automatically as soon as LM PLC server is started

  • ict interval notify counter. Every ict iterations notification is being performed.

  • iterations (read-only) cycle iterations since the last start/stats reset

  • interval cycle interval, in seconds

  • macro macro, which is called as a worker

  • on_error macro, which is called if cycle error has been occurred

  • status (read-only) cycle status, changed when start/stop commands are executed. Can be:

    • 0 cycle is stopped
    • 1 cycle is running
    • 2 cycle got “stop” command and will stop as soon as current iteration finish

Note

When cycle is running, attempts to change parameters ict, interval or macro will return an error.

on_error macro

Macro, defined in on_error cycle property is called when:

  • exception worker macro raised an exception, on_error macro args contain:
    • _1 “exception” word
    • _2 exception object
  • timeout/exec error macro execution took more time than cycle loop interval is set to, or worker macro exited with non-zero code. on_error macro args contain:
    • _1 “timeout” or “exec_error” word
    • _2 serialized worker macro execution result

the macro can e.g. stop cycle execution, send critical event to controller core or just log an error and let cycle continue.

Performance

Theoretically, cycle interval can be up to 1ms (1kHz worker frequency), but don’t expect stable cycle loops on a slow/busy hardware. In real life, software controllers handle well production loops up to 200/300ms (3-5Hz), with lower values (~100ms = 10Hz) users may expect 2-3% of iteration loss. Stable logic-rich cycles with the interval, lower than 20ms (50Hz), are nearly impossible.

If worker macro perform a calls between EVA ICS nodes, don’t forget about network timeouts.

To let cycle run with a maximum precision and avoid timeout errors, it is strongly recommended for the low-interval cycles:

Cycles vs jobs

Both cycles and Scheduled jobs do similar functions: start macros with the specified interval.

When you should use cycles

  • you need to have complete control and monitoring on the interval loop
  • you need to periodically stop / start interval loop manually
  • interval is in seconds or milliseconds

usage example: automation loops.

When jobs are better

  • you need a simple instrument to run the task periodically
  • you need to start a task with the specified time schedule, e.g. every day at 9:00
  • interval is in seconds, minutes or hours, precision is not important

usage examples: statistic tasks, cleaners, system checkers.

UI basics

HMI applications are served by SCADA Final Aggregator from EVA_DIR/ui directory and available by default at:

http://SFA_IP:8828/ui/

Typically, EVA ICS UI applications are completely written in JavaScript. The file, called “ui/index.html” (or “ui/index.j2”) should be the application entry point.

The applications are usually coded in HTML+JavaScript. The UI applications should use SFA API methods to authenticate, obtain data and execute various actions.

Development

EVA ICS provides the following tools to simplify UI development:

  • EVA JS Framework - provides high-level JavaScript API with various typical HMI features, such as authentication, data synchronization, events, actions etc.
  • Serving structured data in convenient ways.
  • SFA Templates - server-side templates for HTML, JS and other text files.
  • SFA PVT - a special API to keep sensitive information securely and let it be accessible only to authenticated users.
  • HMI file uploads - file upload API.
  • API session tokens - use session-bound tokens to authenticate API calls
  • Ready-to-use applications for Mobile clients.

Some of ready-to-use HMI applications are available at EVA ICS download page.

Custom error pages

HTTP error responses (400, 403, 404, 405, 409 and 500) can be customized with custom error pages. To customize an error response, create file EVA_DIR/ui/errors/<code>.html, e.g. EVA_DIR/ui/errors/404.html for HTTP Error 404 (Not Found).

Custom error pages can have .j2 extensions as well. In this case, they are processed as SFA Templates.

UI Favicon

If there is no way to define icon path with “link” HTML tag, put a file named “favicon.ico” in EVA_DIR/ui/ directory to override the default favicon.

SFA Templates

SCADA Final Aggregator uses jinja2 template engine to serve server-side templates. You can use SFA templates for regular HTML, javascript and JSON data files. Both ui and pvt folders can contain template files, the difference is only that templates in ui are public while templates in pvt are served via SFA PVT.

Template files

All files with .j2 extension are processed as templates, index.j2 has more priority than index.html as the primary interface page.

Templates support all jinja2 functions and features, plus have some specific built-in variables and functions.

Template variables

The following variables are available in all templates:

  • All custom user-defined variables
  • server contains a dict with a system and current API key info (equal to SFA API test function result) plus an additional key remote_ip which contains either request IP address or value of X-Real-IP variable (if set by frontend server).
  • request contains CherryPy request object, e.g. display user agent:
{{ request.headers.get('User-Agent') }}

Template functions

All templates have the following built-in functions. Template functions never raise exceptions, instead they return None values.

groups

Get list of item groups

groups(g=None, p=None, k=None)

where:

The function is similar to SFA API groups except that if API key is not specified, the current key is used.

state

Get list of items and their state

state(i=None, g=None, p=None, k=None):

where:

  • i full item id (group/id), optional
  • g filter by group (use MQTT-style wildcards)
  • p item type (U for unit, S for sensor, LV for lvar), required if ID is not in oid format
  • k API key (use key ID instead of key itself)

The function is similar to SFA API state except that if API key is not specified, the current key is used.

api_call

Allows to call any SFA API method directly.

api_call(method, params={}, k=None)

where:

  • method API method to call
  • params API call parameters
  • k API key (use key ID instead of key itself)

Example. Let’s warn user when specified UC controller is not connected:

{%- set controller = api_call(
            'get_controller', { 'i': 'uc/mws1-v1' }, 'masterkey') %}
{%- if not controller.connected %}
    UC controller is not connected
{%- endif %}
get_aci

Get current API call info. Valid params are:

  • id unique API request ID
  • u current user
  • utp current user type
  • key_id current API key id

Example:

Logged in as: {{ get_aci('u') }}
import_module

Import any available Python module (mapped to importlib.import_module)

Example:

{% set os=import_module('os') %}
Server PID: {{ os.getpid() }}

SFA PVT

While developing the interfaces for SCADA Final Aggregator you face the issue of the private data protection: the UI is loaded with the javascript application that runs in the browser and requires authentication to access the SFA API functions. However, the application may contain components which an unauthorized user should not see: plans of the building, security cam footages, even the list of the managed items may be confidential.

One way to solve this problem is to use the frontend server for such content. However, frontend is not always necessary and, in our case, the content structure often requires the access rights to certain parts to be set on the front-end. Therefore, it may involve duplicating user base and difficult integration of the additional authentication methods.

In most cases, it would be sufficient to delineate access to such content with the help of SFA PVT server. The access rights to the certain files and catalogs are regulated with pvt parameter in SFA API keys.

The PVT server interface is available at http(s)://<IP_address_SFA:Port>/pvt, and the private content should be placed in pvt folder of EVA root directory.

pvt parameter of API keys supports MQTT-style wildcards, i.e.:

pvt = map.jpg, c1/#, +/content.js

will give the key access to map.jpg, all files and subfolders of c1 folder as well as content.js file in any first-level folder.

If the client is authenticated in advance, the future requests do not require k=APIKEY param.

Loading files from PVT Server

The file can be loaded with the following request:

http(s)://<IP_address_SFA:Port>/pvt?k=APIKEY&f=FILE

or

http(s)://<IP_address_SFA:Port>/pvt/FILE?k=APIKEY

where

  • k valid API key
  • f a full relative file path, i.e. map.jpg or c2/content.js

Receiving the file list

Use c=list request param to receive the file list by the specified mask:

http(s)://<IP_address_SFA:Port>/pvt?k=APIKEY&f=FILEMASK&c=list

The mask should be included in the pvt key access right parameter, for example

pvt = c1/*.json ; or c1/# for all files and masks

The complete request example:

http(s)://<IP_address_SFA:Port>/pvt?k=APIKEY&f=c1/*.png&c=list

which return JSON array:

[{
     "name": "1.png",
     "size": 2443,
     "time": {
         "c": 1507735364.2441583,
         "m": 1507734605.1451921
     }
 },
 {
     "name": "2.png",
     "size": 2231,
     "time": {
         "c": 1507735366.5561802,
         "m": 1507735342.923956
     }
 }]

where

  • size file size (in bytes)
  • time/c inode creation time (ctime, UNIX timestamp)
  • time/m file modification time (mtime)

Receiving the newest and the oldest file

Use c=newest (c=oldest) param to do the typical job of the management interfaces - receiving the newest file from the specified folder.

http(s)://<IP_address_SFA:Port>/pvt?k=APIKEY&f=FILEMASK&c=newest

Example: there is a monitoring camera that uploads a file to the folder on the server every 10 seconds. The uploaded files are named, i.e. TIMESTAMP.jpg or ID.jpg.

Connect the file with these images to pvt:

cd pvt
ln -sf /path/to/camerafolder cam1

and easily receive the newest file with the following request:

http(s)://<IP_address_SFA:Port>/pvt?k=APIKEY&f=cam1/*.jpg&c=newest

Image Processing

Use ic=resize to ask the server to preprocess the image file. To let the server process images, Python PIL (pillow) library should be installed. EVA installer automatically installs the library using pip3.

Please, make sure that system has at least libjpeg-dev and libjpeg8-dev before EVA setup, otherwise, PIL won’t work with JPEG images.

In case you miss this and server returns an error (“decoder not available”), reinstall pillow:

<EVA_DIR>/python3/bin/pip3 install --no-cache-dir -I pillow

If everything is installed correctly, you can receive the processed image using the following request:

http(s)://<IP_address_SFA:Port>/pvt?k=APIKEY&f=FILE&ic=resize:XxYxQ:encoder

where:

  • X and Y - image maximum width/height
  • Q image quality
  • encode image encoder

I.e. let’s get an image pvt/cam/1.jpg, resize it to 800x600 as max, and convert to JPEG with 90% quality:

http(s)://<IP_address_SFA:Port>/pvt?k=APIKEY&f=cam1/1.jpg&ic=resize:800x600x90:jpeg

We may combine ic with c param, allowing us to receive the newest file by the mask. The request

http(s)://<IP_address_SFA:Port>/pvt?k=APIKEY&f=cam1/*.jpg&c=newest&ic=resize:800x600x50:jpeg

will return the newest jpeg file from cam1 folder having scaled the image size to max 800x600 (proportionally) and reduced its quality to 50%. If the newest file cannot be processed (for example, the image isn’t completely loaded by cam yet and the file is locked), the server will attempt to process the previous one.

If the content is processed immediately before its loading by the interface, the server won’t need to generate the unnecessary images, especially if every client demands a specific format.

The maximum size of source file for the image processing is 10 megabytes.

Disabling cache

To ensure the request cashing is disabled, add nocache parameter with any value:

http(s)://<IP_address_SFA:Port>/pvt?k=APIKEY&f=FILE&nocache=VALUE

if you use this parameter for requests, web browser will not cache a file (if random value is used). Besides, the server will set Cache-Control, Expires and Pragma headers to the values which prohibit any caching.

Remote content

SFA PVT can act as a proxy, fetching allowed resources in local network and displaying them to user.

This can be done with request

http(s)://<IP_address_SFA:Port>/rpvt?k=APIKEY&f=http://remote_host/folder/file&nocache=some_random_value

Param nocache is optional. If user is logged in, param k can be omitted.

Example: you have a chart on storage server in local network displaying storage usage. The chart is located at http://192.168.1.20/charts/zfs.png

Append the following permission string to API key:

rpvt = 192.168.1.20/charts/#

This will grant access to all files on the specified host in /charts/ folder.

Then include remote chart in your interface:

<img src="/rpvt?k=APIKEY&f=192.168.1.20/charts/zfs.png" />

As you see, the remote client doesn’t need to have a direct access to 192.168.1.20 web server, /rpvt API call acts for him as a content proxy.

To use remote content feature, you must follow the rules:

  • protocol (http/https) doesn’t need to be specified in rpvt API key param.
  • f param of /rpvt request may contain uri protocol (e.g. http://192.168.1.20/charts/zfs.png). If the protocol is not specified, SFA uses plain HTTP without SSL.
  • You can not specify http(s) port in f param of /rpvt unless it’s also specified in rpvt API key param.
  • ic option is used for image processing, same as for local PVT file.
  • Avoid using rpvt = #, this will allow /rpvt to work as http proxy for any local and Internet resource and may open a security hole.

Serving structured data

Structured data (YAML and JSON files) is very typical for UI development to keep settings, texts and other structured information.

EVA ICS provides a feature, called “serve as”, which allows to convert any structured data file on-the-flow and load it into UI applications in the most convenient way.

This feature is supported by both public UI (“/ui” URLs) and SFA PVT and enabled automatically for all files with suffixes “.yml”, “.yaml” and “.json”.

Format conversion

To convert a structured file into another format, request it as:

/ui/filename.yml?as=FMT

where FMT:

  • yml (or yaml) - convert the file into YAML
  • json - convert the file into JSON
  • js - convert the file into JavaScript (requires either “var” or “func” as the additional parameter)

e.g. let’s convert YAML, which is usually more human-editable and preferred to keep configs, into JSON:

/ui/filename.yml?as=json

The file can also be converted on-the-flow to JavaScript variable, or, as copying JavaScript arrays and dicts is usually tricky, into the function, which returns the structured data on every call:

/ui/filename.yml?as=js&func=myfunc

Multi-language

Usage

An additional argument “lang” can be used to apply the chosen locale on all string fields of structured data file. Multi-line strings are processed correctly, string formatting (left and right white spaces) is preserved:

/ui/test.yml?as=json&lang=LANG

(as seen from the above example, “lang” can be combined with “as”).

Firstly, a locale file should be created. Create a directory EVA_DIR/pvt/locales (used for both UI and SFA PVT). After, create inside that directory language directories with LC_MESSAGES subdirectory inside each one. So the tree should look like e.g. (“cs” is for Czech language):

pvt
└── locales
    └── cs
        └── LC_MESSAGES
            ├── messages.po
            ├── tests
            └────── test.po

“.po” files are standard Gettext files, which look like:

msgid "this is a test"
msgstr "je to test"

or e.g. for Japanese (UTF-8):

#, fuzzy
msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"

msgid "this is a test"
msgstr "これはテストです"

(note that if diacritic is used e.g. in Czech lang messages, the file should specify UTF-8 encoding as well)

The files can be compiled with “msgfmt” Linux command from “gettext” package (installed by default by majority Linux distributions):

msgfmt file.po -o file.mo

EVA ICS uses the following strategy to find locale files. E.g. if the document

/ui/tests/test.yml?as=json&lang=cs

is served, the message files are looked up in the following order:

  • EVA_DIR/pvt/locales/cs/LC_MESSAGES/tests/test.mo
  • EVA_DIR/pvt/locales/cs/LC_MESSAGES/tests.mo
  • EVA_DIR/pvt/locales/cs/LC_MESSAGES/messages.mo

(the last file is the standard common message file). If no message file is found, the strings are served as-is, without any conversion.

Note

Altrenatively, locale files can be kept in EVA_DIR/ui/locales. SCADA Final Aggregator automatically searches for the locale files in “ui” if no locale files found in “pvt”.

The option “-o EVA_DIR/ui/locales” for gen-intl can be used to automatically generate / compile locale files in EVA_DIR/ui/locales.

Generating

To auto-generate / update “.po” files from JSON or YAML strings, a supplied tool “gen-intl” can be used (multiple languages can be specified at once):

/opt/eva/bin/gen-intl test.yml -l cs generate

The above command will auto-generate or update “test.po” file and put it to the corresponding locale path. E.g. if the file absolute path is /opt/eva/ui/tests/test.yml, the result “.po” file will be written to /opt/eva/pvt/locales/cs/LC_MESSAGES/tests/test.po.

After editing, compile “.po” file manually with “msgfmt”, or run

/opt/eva/bin/gen-intl test.yml -l cs compile
Locale cache

Message files are cached by EVA ICS gettext library, until the SCADA Final Aggregator server is restarted.

The cache can be turned off by setting development mode (development = yes) in [server] section of etc/sfa.ini configuration file.

On production, the API method clear_lang_cache can be used, either by calling it manually or during a deployment.

HMI file uploads

SCADA Final Aggregator has a special HTTP method to handle uploads.

http(s)://<IP_address_SFA:Port>/upload

The method accepts standard multipart-form data requests and processes them with Logic macros.

File upload form

How does it work

An upload form can be either standard HTML web-form or AJAX-based. Here is an example of the standard one:

<form action="/upload" method="POST" enctype="multipart/form-data">
    Select file to upload:
    <input type="file" name="ufile">
    <input type="hidden" name="rdr" value="/ui/upload_example.html">
    <input type="hidden" name="process_macro_id" value="tests/upload_handler">
    <input type="submit" value="Upload file" name="submit">
</form>

What happens, when a file is uploaded and the method is called:

  • The form parameters are checked (“ufile” and “process_macro_id” are mandatory)
  • If there is a file to upload chosen, the macro with id, specified in “process_macro_id” is called.
  • If there is “rdr” form parameter set, the method performs redirect to the specified URI
  • Otherwise, the method returns JSON output of macro execution result:
{
    "args": [],
    "err": "",
    "exitcode": 0,
    "finished": true,
    "finished_in": 0.0034916,
    "item_group": "nogroup",
    "item_id": "m1",
    "item_oid": "lmacro:nogroup/m1",
    "item_type": "lmacro",
    "kwargs": {
        "content": "<binary>",
        "data": {
            "aci": {
                "id": "6d7dca71-865b-4aac-8f1d-5c4f4a979c68",
                "key_id": "masterkey"
            },
            "content_type": "image/jpeg",
            "file_name": "wpbig.jpg",
            "form": {
                "submit": "OK"
            },
            "sha256": "0393e47ec35f73e12d333bb719d30e3959bd140bf952c69b4139b956957a8c4c",
            "system_name": "sfa/lab-ws2"
        }
    },
    "out": "",
    "priority": 100,
    "status": "completed",
    "time": {
        "completed": 1607025058.628277,
        "created": 1607025058.6247854,
        "pending": 1607025058.6249535,
        "queued": 1607025058.625362,
        "running": 1607025058.6257577
    },
    "uuid": "19a71537-cfea-4154-b1f4-dc0897216abe"
}
Errors
  • 400 (Bad Request) - invalid HTTP request or “ufile” or “process_macro_id” parameters are not set
  • 404 (Not Found) - the macro with the specified id is not found
  • 403 (Forbidden) - the user has no access to the requested macro
  • 500 (API Error) - all other errors

In case if the file is not specified and “rdr” param is not set, the method returns:

{ "ok": false }
Additional form parameters
  • k API key (set automatically by EVA JS Framework version 0.3.9 or above)
  • w seconds to wait until macro execution is completed
  • p: macro queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”
  • all other parameters are sent to macro as a dict data[“form”]

Processing macro

When the file upload is complete, Logic macro is being called, so the content is actually transferred for processing to the Logic Manager where the macro is located.

The macro automatically gets these parameters:

  • content content of the uploaded file (binary)

  • data upload information data:

    • aci API call info dict
    • content_type file content type, reported by client
    • file_name file name, reported by client
    • form the dict of all additional upload form parameters
    • sha256 SHA256-checksum of the uploaded file (calculated by SFA)
    • system_name system name, the file is coming from

Here’s an example of the very simple macro, which stores uploaded files in /tmp:

print(f'uploading file {data["file_name"]}')
assert data['sha256'] == sha256sum(content)
with open('/tmp/' + data['file_name'], 'wb') as fh:
    fh.write(content)
    out = 'upload completed'

Security and file upload limits

  • To upload files, the user should have an access to the corresponding processing macro
  • There’s no built-in limitations for uploaded file size, but the limit can be set using SFA HTTP front-end.

API session tokens

Special API methods login and logout (present in all EVA ICS APIs, /r/token resource for RESTful) allow to open API session and use server-generated API token instead of API key.

To enable tokens, set parameter session_timeout greater than zero in [webapi] section of controller configuration (enabled in SFA by default).

Also, API session tokens are required by EVA JS Framework, which uses them to handle interface sessions.

Usage

Token has no restrictions and can be used as usual API key, the only one difference is that token has expiration time or can be purged by owner earlier.

SFA Templates and SFA PVT methods additionally accept authentication tokens set in auth cookie. After successful login, EVA JS Framework automatically sets this cookie for URI paths /ui, /pvt and /rpvt.

Expiration

Token will expire and become invalid, if:

  • it hasn’t been used for a time, longer, than specified session_timeout
  • the time, passed since token generation is greater than session_timeout and session_no_prolong = yes is set in controller configuration
  • API method logout (DELETE /r/token for RESTful) was called
  • on any API key modification, which is token assigned to
  • on any user account modification, which the token is assigned to (if token was obtained with user credentials)
  • the controller was restarted.

Read-only mode

The client can ask the server to set read-only mode for the current token, e.g. after an idle period. This can be performed by calling “set_token_readonly” API method.

In read-only mode, only read-only API calls are accepted, others return “result_token_restricted”(15) API error.

To exit read-only mode, user must either authenticate again and obtain a new token or re-use the existing one by calling “login” API method with params a=CURRENT_TOKEN and either “u” and “p” (if token was assigned to user account) or “k” (if token was assigned directly to API key).

Supervisors

Starting from 3.3.1 SCADA Final Aggregator API keys can have a special permission allow=supervisor, which provides the following features:

API locks

Supervisor can use SFA API to set supervisor lock and switch the server API in read-only mode. In read-only mode SFA API denies an access to functions, which modify item states (unit actions, set/reset/clear/toggle for lvars, macro run etc.) except caller is in the lock scope.

When supervisor lock is set, API function test returns field supervisor_lock with lock information. When there is no lock set, supervisor_lock field is null.

Supervisor lock can be cleared by any user, which is in the unlock scope. There is also not necessary clearing existing lock to set the new one - if user or API key is in the unlock scope, the lock can be overriden.

Both lock and unlock scopes can be:

  • null any supervisor can pass
  • k only supervisors with the same API key as the lock owner has
  • u only lock-owning user

To set user scope (“u”), API call must be performed with valid user token. Lock owner is set automatically using API call access data (key / user). Users with master key can override lock owner, setting lock user and key ID to any values.

Supervisor lock is automatically cleared when the server is restarted.

Note

Users with master key are not affected with supervisor locks in any way and can pass / unlock them without any restrictions.

As soon as supervisor lock is set, EVA JS Framework receives an event supervisor.lock with lock information dict as the function argument and a message or informational popup can be displayed for logged in users.

When supervisor lock is cleared, EVA JS Framework receives an event supervisor.unlock.

Note

To let EVA JS framework receive supervisor events, it should be updated to version 0.3.7 or above.

Broadcast messages

Supervisor can send broadcast message to all logged in users. The message is received by EVA JS Framework with event supervisor_message and the following dictionary structure as the function argument:

  • sender message sender
    • key_id sender API key ID
    • u sender user
  • text message text

Users with master key can override message sender.

CLI

All supervisor methods can be also executed from the command line. See “eva sfa supervisor” command for more details.

MS Active Directory authentication

To authenticate EVA ICS users, Microsoft Active Directory can be used.

Active Directory support is not configured by default.

Automatic setup

eva feature setup msad host=192.168.1.15,domain=myorganization.com,key_prefix=msad_

Manual setup

System setup

Install LDAP and SASL2 development libraries

apt -y install libsasl2-dev libldap2-dev libssl-dev
# or for Fedora
yum install -y openldap-devel openssl-devel

Append easyad module to EVA ICS Python venv (/opt/eva/etc/venv) extras

EXTRA="easyad==1.0.9"

Rebuild EVA ICS venv

/opt/eva/install/build-venv
EVA Controller configuration

Put the following block in controller configuration (e.g. for SFA edit /opt/eva/etc/sfa.ini)

[msad]
host = ad.yourdomain.com
domain = yourdomain.com
key_prefix =
ou = EVA
;ca = /path/to/ca-file.crt
; cache credentials for the specified time (seconds)
; default: 86400 (1 day), 0 to disable caching
;cache_time = 86400

Host and domain should always be specified. Default key prefix is empty, default organizational unit is EVA. CA file is not used by default.

Restart the controller

eva sfa server restart

Active Directory configuration

Log into Active Directory domain controller, open Active Directory Users and Computers and create organizational unit (default - EVA)

create AD OU

Create security groups inside organizational unit. Group name should match EVA ICS API key ID

create AD group

Assign security group to domain user. If multiple security groups are assigned, EVA ICS will use combined ACL. If API key with any required ID doesn’t exist, authentication attempt is considered as failed, despite user has more groups assigned.

Usage

Authentication

After OU security group is assigned to Active Directory user, its credentials can be immediately used for authentication in EVA ICS. It’s not necessary to create user in EVA ICS controller.

If user with the same login exists in EVA ICS controller, local user has higher priority. If the provided password doesn’t match local, the local record is ignored and attempt to authenticate via Active Directory is performed.

Key prefixes

if key_prefix is specified in the controller configuration file, EVA ICS will look for API key with id {key_prefix}{AD security group}, e.g.

  • key_prefix = msad_
  • user has assigned security group EVA/operator
  • EVA ICS controller API key should have id msad_operator

Mobile clients

Android

EVA ICS Control Center client

You can use official EVA ICS Control Center client to access SFA UI from Android-based mobile phones.

_images/evacc.png

The client is evaHI-based application, so it can be configured in the same way.

SFA automatically maps ui/.evahi directory to /.evahi URI. If front-end server is used, URI should be accessible without user authentication to let all application features work properly.

EVA JS Framework function $eva.hiQR can be used to generate configuration QR code for the current authenticated user.

Building own client

You can easily build custom Android client for your EVA ICS UI, customizing application class, name, menu, icons. Please refer to evaHI building instructions.

Authentication

evaHI sends username/password only if basic authentication is set up. However API login method automatically detects evaHI client (by HTTP User-Agent header) and ask it to provide authentication credentials.

If there is no front-end with basic authentication set up for all clients, you may display log in form for all, but let evaHI-based clients to try logging in automatically via EVA JS Framework:

if ($eva.in_evaHI) {
    $eva.start();
} else {
    // show login form
}

Apple iOS and other mobile platforms

Currently we have no plans to release native iOS client, iPhone users may access SFA UI via 3rd-party apps or built-in mobile browser.

AKCP

AKCP sensors can be integrated into Universal Controller with either SNMP traps or corresponding PHI modules.

Both ways require sensors to be connected to AKCP SensorProbe or SecurityProbe device, which acts as SNMP bridge.

Equipment supported

  • AKCP_MD00 motion detector
  • AKCP_SK00 smoke detector
  • AKCP_THSXX temperature/humidity sensor

Setup

All AKCP sensors send SNMP traps on connect/failure, detector sensors also send traps on event.

Both ways (using SNMP trap parser or PHIs), require SNMP trap handler to be properly configured and set in AKCP SensorProbe/SecurityProbe as a trap handler server (section [snmptrap] of etc/uc.ini configuration file).

Consider AKCP SensorProbe IP is 192.168.1.100, motion detector is installed on port 1, smoke detector - on port 2, temperature/humidity sensor - on port 4.

# motion detector
eva uc phi download https://get.eva-ics.com/phi/sensors/alarm/akcp_md.py
# PHI module is loaded for the particular SensorProbe/port
eva uc phi load md1 akcp_md -c host=192.168.1.100,sp=1 -y
# create motion sensor
eva uc create sensor:security/motion1 -y
# assign driver to sensor
eva uc driver assign sensor:security/motion1 md1.default -y

# smoke detector
eva uc phi download https://get.eva-ics.com/phi/sensors/alarm/akcp_sk.py
eva uc phi load sk1 akcp_sk -c host=192.168.1.100,sp=2 -y
# create smoke sensor
eva uc create sensor:security/smoke1 -y
# assign driver to sensor
eva uc driver assign sensor:security/smoke1 sk1.default -y

# temperature/humidity sensor
eva uc phi download https://get.eva-ics.com/phi/sensors/env/akcp_ths.py
# PHI for AKCP_THSXX provides 2 virtual ports: t and h
eva uc phi load ths1 akcp_ths -c host=192.168.1.100,sp=4,retries=3 -y
# create temperature and humidity sensors
eva uc create sensor:env/temp1 -y
eva uc create sensor:env/hum1 -y
# assign driver to sensors
eva uc driver assign sensor:env/temp1 ths1.default -c port=t -y
eva uc driver assign sensor:env/hum1 ths1.default -c port=h -y
# setup sensors to update state every 30 seconds
config set sensor:env/temp1 update_interval 30 -y
config set sensor:env/hum1 update_interval 30 -y

Performance tuning

If AKCP_THSXX PHI becomes slow, it’s recommended to install python3-netsnmp module, which is much faster than native SNMP implementation:

Put python3-netsnmp to EXTRA var in /opt/eva/etc/venv, then run

/opt/eva/install/build-venv

You will also probably need libsnmp-dev system package. Check module setup output for details.

Arduino

You may connect Arduino or similar boards to Universal Controller to handle events from connected sensors or receive commands for locally connected relays, motors etc.

Receiving commands from EVA ICS

There’s no common way controlling embedded boards from EVA ICS. You may define any API inside a board, then just use external scripts or develop own PHI module to link Universal Controller and board.

Sending data to EVA ICS UC

It’s highly recommended to use UC UDP API to communicate with Universal Controller to avoid Arduino board freezing.

To enable UDP API, you must firstly configure listen and hosts_allow options in etc/uc.ini (don’t forget to restart Universal Controller after configuration is modified).

Example. Consider there are 2 motion (PIR) sensors connected with Arduino board on pins #2 and #3, the board has Ethernet shield to send events via UDP protocol, there is also a signal LED connected to board pin #7.

On events, the board updates states of EVA ICS sensors sensor:security/motion1 and sensor:security/motion2. We’ll use plain (unencrypted) UDP API and Universal Controller will receive state updates without API key.

Setup EVA ICS UC

Create 2 sensors:

# create sensors
eva uc create sensor:security/motion1 -y
eva uc create sensor:security/motion2 -y

# enable sensors (set status to 1)
eva uc update sensor:security/motion1 -s1
eva uc update sensor:security/motion2 -s1

Sensors will get value “1” when motion is detected by PIR and “0” when motion is over.

Setup Arduino
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

// motion sensors pins
int mPin1 = 2;
int mPin2 = 3;

// motion sensor states
int mNow1 = 1;
int mNow2 = 1;

// previous motion sensor states
int mOld1 = 0;
int mOld2 = 0;

// signal LED pin
int lPin = 7;

int toLedSeconds = 0;

// EVA ICS UC IP
IPAddress aSrvIP(192, 168, 1, 11);
int aSrvPort = 8881;

byte mac[] = {  
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x01 };

EthernetUDP Udp;

void(* resetFunc) (void) = 0;

void setup() {
  pinMode (mPin1,INPUT);
  pinMode (mPin2, INPUT);
  pinMode (lPin, OUTPUT);
  Serial.begin(9600);
  Serial.print("Waiting for sensor calibration...");
  for (int i=10;i>0;i--) {
    Serial.print(i,DEC);
    Serial.print(" ");
    digitalWrite(lPin,HIGH);
    delay(500);
    digitalWrite(lPin,LOW);
    delay(500);
  }
  Serial.println();
  Serial.println("Motion sensor calibration check...");
  while ((mNow1+mNow2)!=0) {
    updateSensors();
    delay(10);
  }
  Serial.print("Configuring ethernet...");
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed, restarting in 5 seconds");
    for (int i=0;i<2;i++) {
     digitalWrite(lPin,HIGH);
     delay(500);
     digitalWrite(lPin,LOW);
     delay(500);
    }
    delay(3000);
    resetFunc();
    return;
    }
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("Started");
  // blink signal LED 3 times
  Udp.begin(aSrvPort);
  for (int i=0;i<3;i++) {
    digitalWrite(lPin,HIGH);
    delay(200);
    digitalWrite(lPin,LOW);
    delay(200);
  }
}

void updateSensors() {
  mNow1 = digitalRead(mPin1);
  mNow2 = digitalRead(mPin2);
}

void sendNotify(char* sensor,int value) {
  char p[100];
  char v[10];
  strcpy(p,sensor);
  strcat(p," u None ");
  itoa(value,v,10);
  strcat(p,v);
  strcat(p,0);
  Udp.beginPacket(aSrvIP,aSrvPort);
  Udp.write(p);
  Udp.endPacket();
}

void loop() {
  updateSensors();
  if (mNow1!=mOld1) {
    mOld1=mNow1;
    Serial.print("Motion sensor 1 value change: ");
    Serial.println(mNow1,DEC);
    if (mNow1>0) toLedSeconds=3000;
    sendNotify("sensor:security/motion1",mNow1);
  }
  if (mNow2!=mOld2) {
    mOld2=mNow2;
    Serial.print("Motion sensor 2 value change: ");
    Serial.println(mNow2,DEC);
    if (mNow2>0) toLedSeconds=3000;
    sendNotify("sensor:security/motion2",mNow2);
  }
  if (toLedSeconds--==3000) digitalWrite(lPin,HIGH);
  if (toLedSeconds==0) digitalWrite(lPin,LOW);
  delay(1);
}

Amazon Web Services

AWS IoT as MQTT broker

MQTT broker is used when EVA ICS controllers are located in different networks and can not exchange data with P2P connections.

Instead of setting up dedicated MQTT server, you can use cloud-based service, e.g. AWS IoT.

  • Create AWS IoT Core “thing”
  • Apply the following policy:
{
    "Version": "2012-10-17",
    "Statement": [{
        "Effect": "Allow",
        "Action":["iot:*"],
        "Resource": ["*"]
    }]
}
During installation

Options for EVA ICS installation (easy-setup):

  • MQTT host: AWS IoT endpoint host (XXXXXXXXX.iot.XXXXXXXXX.amazonaws.com)
  • MQTT port: 8883
  • MQTT user, password: leave empty
  • MQTT space: leave empty
  • MQTT SSL: should be enabled (answer ‘y’ if using easy-setup; when notifier is configured later, SSL is automatically enabled as soon as ca_certs property is set)
  • MQTT CA file, cert file, key file: provided by AWS (use private key file as key file)
  • Disable MQTT retain (answer ‘y’ in easy-setup) to make sure no topics with retain flag will be sent to MQTT broker (otherwise EVA ICS controller will be instantly disconnected)
  • Use MQTT QoS 0 or 1 (default)
  • It’s recommended to create “things” for each EVA ICS controller. After setup, MQTT cert file and key file can be changed with CLI (eva ns [controller_type]…). Don’t forget to restart the controller to apply notifier configuration.
After installation

If no MQTT broker is set up, just run easy-setup again and follow the instructions.

If you want to set up additional MQTT broker, let’s create new MQTT notifier, e.g. for Logic Manager:

eva -I
ns lm
# create new notifier called e.g. "cmq"
# replace XXXXXXXXX.iot.XXXXXXXXX.amazonaws.com with your AWS endpoint
create cmq mqtt:XXXXXXXXX.iot.XXXXXXXXX.amazonaws.com:8883
# disable MQTT retain - required
set cmq retain_enabled 0
# announce controller every 5 seconds
set cmq announce_interval 5
# accept API calls
set cmq api_enabled 1
# discover other controllers
set cmq discovery_enabled 1
# Turn SSL on, set CA file provided by AWS
set cmq ca_certs /path/to/cafile
# Set cert and key file, both provided by AWS
set cmq keyfile /path/to/keyfile
set cmq certfile /path/to/certfile
# Test it, should work
test cmq
# if it works - subscribe notifier to item states
subscribe state cmq -g '#'
# restart controller server
server restart

Amazon Polly TTS

if you want to use Amazon Polly Text-to-Speech engine with EVA ICS, refer to Text-to-Speech documentation.

CCTV Cameras

EVA ICS has built-in tools to put image from CCTV cameras on HMI dashboards.

Uploaded images

Consider there’s a camera in a local network, which continuously uploads images to local folder on the host where SCADA Final Aggregator is installed.

You can insert newest uploaded image into web interface via SFA PVT:

Step 1: Setup source

Setup CCTV camera to upload images via FTP or SCP to pvt folder e.g. /opt/eva/pvt/camera1 or make there a symlink to the folder where images are located.

Step 2: set API key permissions

E.g. you want to obtain camera image from pvt folder with API key operator or with user this API key is assigned to:

eva -I
sfa
key set operator pvt "camera1/#" -y

Step 3: insert image into web UI

Let’s insert image, compress it to 90% and resize to 640x400. Camera image URL will be:

/pvt?k=APIKEY&f=camera1/*.jpg&c=newest&ic=resize:640x400:90:jpeg&nocache=RANDOM

If you use EVA JS Framework or ready-made HMI application, parameter k=APIKEY is not required. Parameter nocache should always be present to let JavaScript reload image into web browser.

Image in local network

Consider there’s a CCTV camera in local network on IP address 192.168.1.110, which provides current image at (e.g.):

http://192.168.1.110/axis-cgi/jpg/image.cgi # old AXIS cameras
http://192.168.1.110/onvif/snapshot/pic.jpg # modern ONVIF cameras

You can insert image into web interface with SFA RPVT tool:

Step 1: set API key permissions

E.g. you want to obtain camera image with API key operator or with user this API key is assigned to:

eva -I
sfa
key set operator rpvt "192.168.1.110/onvif/snapshot/#" -y

Step 2: insert image into web UI

/pvt?k=APIKEY&f=http://192.168.1.110/onvif/snapshot/pic.jpg&ic=resize:640x400:90:jpeg&nocache=RANDOM

As well as for pvt, if you use EVA JS Framework or ready-made HMI application, parameter k=APIKEY is not required.

Image in 3rd party network

Consider SCADA Final Aggregator is installed in Cloud or in the network A, which doesn’t have direct access to CCTV camera in network B.

If Universal Controller or Logic Manager is installed in network B and connected to SCADA Final Aggregator, we can ask controller in network B to be our agent and provide camera image (as well as any other resource from network B) for SFA.

CCTV agent schema

The task we are going to solve is pretty complex but it allows to transfer image from camera without VPN, port-forwarding. But keep resources in network B secure and avoid any unauthorized access.

Step 1: prepare agent controller

Put rpvt = yes to [sysapi] section of /opt/eva/etc/uc.ini (for UC or lm.ini for LM PLC) to enable rpvt agent feature. Restart the controller to activate it:

eva uc server restart

Step 2: configure access from SFA to agent controller

Consider SFA is connected to UC with API key named default. Set up API key permissions on a node in network B:

eva -I
uc
key set default rpvt "192.168.1.110/onvif/snapshot/#" -y

Now remote SFA in network A can call agent controller in network B to get image from http://192.168.1.110/onvif/snapshot/pic.jpg. As well as ask agent controller to resize and compress it before transferring.

Step 3: set SFA API key permissions

E.g. you want to obtain camera image from SFA in network A with API key operator or with user this API key is assigned to:

eva -I
sfa
key set operator rpvt "uc/controller_id:129.168.1.110/onvif/snapshot/#"

Where controller_id - ID of agent controller in network B, as it seen by SFA (verify it with command eva sfa controller list).

Step 4: insert image into web UI

/rpvt&k=APIKEY&f=uc/controller_id:192.168.1.110/onvif/snapshot/pic.jpg&ic=resize:640x400x90:jpeg&nocache=NOCACHE

Note that image is resized and compressed on the agent controller, which reduces network bandwidth and speed up resource loading. Make sure agent controller host as enough CPU resources to serve the image.

Image from password-protected camera

Camera image URL can be password protected, usually with basic authentication. As SFA PVT can not obtain resources from password-protected URLs, you need to proxy camera image to SFA or agent controller host.

We recommend to use a tiny tool called CCTV proxy which can easily solve this problem. Note that image from camera will be available for anyone who’s logged into the host where SFA or agent controller is installed, so it’s highly recommend to check shell permissions for all users and set up CCTV proxy to listen on 127.0.0.1 only.

Video streams

Video stream from modern cameras can be inserted into web UI with <video /> HTML5 tag. However as video stream (and possible required transcoding) eats a lot of resources, we strongly recommend to insert static images only, refreshing them with the required period, unless you have a dedicated server for CCTV and video stream is really required on HMI dashboard.

EVA ICS doesn’t provide any tools for video stream proxying/transcoding.

Denkovi

Denkovi Electronics is a hardware developer/vendor, which is focused on relay modules and accessories.

Equipment supported

  • dae_ip16r smartDEN-IP-16R 16-port TCP/IP controlled relay
  • dae_pbro5ip DAE-PB-RO5-DAEnetIP4 5-port TCP/IP controlled relay
  • dae_ro16_modbus DAE-RO16-MODBUS 16-port Modbus relay
  • dae_ip32in smartDEN IP-32IN (digital inputs only)

Relay setup

Connect relay module to local network, make sure SNMP API is enabled.

Let’s connect smartDEN-IP-16R 16-port relay to Universal Controller. Consider relay module has IP address 192.168.1.100, SNMP community is default (private):

eva uc phi download https://get.eva-ics.com/phi/relays/dae_ip16r.py
eva uc phi load relay1 dae_ip16r -c host=192.168.1.100 -y
# create units
eva uc create unit:lights/lamp1 -y
eva uc create unit:lights/lamp2 -y
# assign driver. consider lamp1 is on port 1, lamp 2 on port 2
eva uc driver assign unit:lights/lamp1 relay1.default -c port=1 -y
eva uc driver assign unit:lights/lamp2 relay1.default -c port=2 -y
# enable unit actions
eva uc action enable unit:lights/lamp1
eva uc action enable unit:lights/lamp2

smartDEN IP-32IN setup

Connect module to local network, make sure SNMP API is enabled. To let Universal Controller receive SNMP traps from digital inputs, open module web admin -> Digital Inputs and select the ports you want to receive traps from. Make sure trap value is 2 (both). Then enter SNMP traps section and enter Universal Controller IP address and SNMP trap community (default is eva).

PHI ports are 1-16 for digital inputs, a1-a8 for analog inputs and t1-t8 for temperature sensor (B57500M) inputs.

Consider we want to monitor digital input 2, analog input 3 and temperature sensor input 4. Module IP address is 192.168.1.100, SNMP read community is default (public):

eva uc phi download https://get.eva-ics.com/phi/sensors/misc/dae_ip32in.py
eva uc phi load ip32in dae_ip32in -c host=192.168.1.100 -y
# create sensors
eva uc create sensor:inputs/din2 -y
eva uc create sensor:inputs/ain3 -y
eva uc create sensor:env/temp4 -y
# enable sensors
eva uc update sensor:inputs/din2 -s1
eva uc update sensor:inputs/ain3 -s1
eva uc update sensor:env/temp4 -s1
# assign driver
eva uc driver assign sensor:inputs/din2 ip32in.default -c port=2 -y
eva uc driver assign sensor:inputs/ain3 ip32in.default -c port=a3 -y
eva uc driver assign sensor:env/temp4 ip32in.default -c port=t4 -y
# Consider, when DIN2 is modified, SNMP trap is being sent to UC, but let's
# update sensor every 10 seconds anyway, in case if trap is lost:
eva uc config set sensor:inputs/din2 update_interval 10 -y
# analog input sensor will be updated every 500ms
eva uc config set sensor:inputs/ain3 update_interval 0.5 -y
# temperature sensor will be updated every 30 seconds
eva uc config set sensor:env/temp4 update_interval 30 -y

Note

Module returns value “- - -” if temperature sensor is not connected, but PHI module will set sensor status to -1 (error).

Performance tuning

If PHIs become slow, it’s recommended to install python3-netsnmp module, which is much faster than native SNMP implementation:

Put python3-netsnmp to EXTRA var in /opt/eva/etc/venv, then run

/opt/eva/install/build-venv

You will also probably need libsnmp-dev system package. Check module setup output for details.

Energenie EG-PM2-LAN

EG-PM2-LAN is an affordable smart power switch solution, which can be integrated with EVA ICS.

Setup

The switch API is pretty slow and it’s not recommended to fetch it on every state update request. To solve this, EG-PM2-LAN EVA PHI module has 2 different features:

  • cache=N socket state is cached for N seconds and unit gets cached state on updates.
  • update=N PHI performs item state updates by itself, update_interval item parameter is not required.

Additionally, PHI module has parameter skip_logout, which can be used to skip logout HTTP call and speed up API even more. Note, that if this parameter is set, you can not login to switch from another device, except the one Universal Controller is installed on.

Consider EG-PM2-LAN switch is set up with IP 192.168.1.100 and password 123. We’ll use update feature and set skip_logiut. Update interval will be set to 60 seconds, that’s more than enough, as only EVA ICS can control the switch and states may differ only if switch reboot has been occurred.

eva uc phi download https://get.eva-ics.com/phi/relays/eg_pm2lan.py
eva uc phi load eg1 eg_pm2lan -c host=192.168.1.100,pw=123,skip_logout=1,update=60 -y
# create unit for port 1
eva uc create unit:control/u1 -y
# assign driver to unit 1
eva uc driver assign unit:control/u1 eg1.default -c port=1 -y
# create unit for port 2
eva uc create unit:control/u2 -y
# assign driver to unit 2
eva uc driver assign unit:control/u2 eg1.default -c port=2 -y
# enable unit actions
eva uc action enable unit:control/u1
eva uc action enable unit:control/u2
# ... repeat the steps for ports 3 and 4 if required ...

Ethernet/IP

Drivers

EVA ICS provides two generic universal PHI modules for Ethernet/IP devices: enip_sensor and enip_xvunit. The modules are easy to integrate and provide basic support of Ethernet/IP-enabled devices.

Logic

EVA ICS sensors have “values” and item “status” is used only as an error indicator. En/IP tags can be mapped to sensor values as-is with enip_sensor PHI module.

EVA ICS units have both “status” and “value” fields, which form a complete item state. So En/IP tag mapping logic is a little bit more complicated:

  • If En/IP tag (integer) should be mapped to unit status (ON/OFF/other modes), it’s mapped to unit status with enip_xvunit PHI module as-is.
  • If En/IP tag is used as an operation mode, it can be mapped to unit value with additional enip_xvunit instance, loaded with xv=true configuration param. Status of the unit, assigned to driver with such PHI module can be either 1 (OK) or -1 (ERROR), tag value is mapped to unit value as-is. Such units don’t perform “toggle” actions, general actions should be executed with status=1 and value=<DESIRED_TAG_VALUE>

The above logic is used only for generic enip_sensor and enip_xvunit modules. Other modules may have different logic mapping, depending on connected equipment and tasks.

Setup

Automatic setup
eva feature setup cpppo_enip mods=1
Manual setup
Required libraries

Both PHI modules require cpppo Python library. The library isn’t installed by default. Set EXTRA=”cpppo==4.0.6” in /opt/eva/etc/venv and rebuild EVA ICS venv (/opt/eva/install/build-venv).

Downloading PHIs
eva uc phi download https://get.eva-ics.com/phi/enip/enip_sensor.py
eva uc phi download https://get.eva-ics.com/phi/enip/enip_xvunit.py
Creating tag lists

If bulk updates are planned, both PHIs require tag lists - lists of CIP tags to poll from/to the En/IP equipment. Tag lists are simple text files, with one tag per line. If tag contains an array, element index should be specified.

If bulk updates are not required or performed with data pullers, the tag lists are not required.

TAG1
TAG2
TAG3[0]

If setting tags is planned (working with enip_xvunit), it’s highly recommended to set variable types, at least for the integer tags:

TAG1:UINT
TAG2:UINT
TAG3[0]:SINT

Valid types are: REAL, SINT, USINT, INT, UINT, DINT, UDINT, BOOL, WORD, DWORD, IPADDR, STRING, SSTRING.

Another way is to specify “_type” driver configuration variable, while assigning the driver to items.

Configuring

Both modules support update param, which allows to pull tags from the equipment with a single request and update all assigned EVA ICS items.

Let’s load PHI for sensors:

eva uc phi load es1 enip_sensor -c host=HOST_OR_IP_OF_EQUIPMENT,taglist=/PATH/TO/TAGLIST,update=1 --save

# create a couple of sensors

eva uc create sensor:tests/test1 --enable --save
eva uc create sensor:tests/test2 --enable --save

# assign driver to sensors
eva uc driver assign sensor:tests/test1 es1.default -c port=TEST1_TAG --save
eva uc driver assign sensor:tests/test2 es1.default -c port=TEST2_TAG --save

# trigger the first sensor state update. all other updates will be received
# automatically, every second

eva uc update sensor:tests/test1
eva uc update sensor:tests/test2

Elastic (ELK)

EVA ICS logs can be viewed/processed with Elastic.

EVA ICS can output JSON logs to syslog, but ELK syslog agent can not parse JSON syslog messages. This document explains how to setup ELK to parse EVA ICS file logs.

Prepare EVA ICS

For all configured node components (“/opt/eva/etc/uc.ini”, “lm.ini” and “sfa.ini”): set log format to

log_format = { "loggerName":"%%(name)s", "@timestamp":"%%(asctime)s", "pathName":"%%(pathname)s", "logRecordCreationTime":"%%(created)f", "functionName":"%%(funcName)s", "levelNo":"%%(levelno)s", "lineNo":"%%(lineno)d", "time":"%%(msecs)d", "levelName":"%%(levelname)s", "message":"%%(message)s" }

make sure “log_file” options are also set, and restart EVA ICS services

eva server restart

Configure ELK

  • Install ELK stack on some machine
  • On the main Elastic dashboard, press “add data”
_images/add-data.png
  • Select “Logstash logs”
_images/select-logstash.png
  • Follow the given instructions and setup filebeat on all EVA ICS nodes.
  • Add the following section into “/etc/filebeat/filebeat.yml” on each EVA ICS node:
- type: log
  enabled: true
  paths:
    - /opt/eva/log/*.log
  json.keys_under_root: true
  json.message_key: "message"
  json.overwrite_keys: true
  • Configure “output.elasticsearch” section to let filebeat sink logs into the ElasticSearch instance.
  • Restart filebeat:
systemctl restart filebeat
  • EVA ICS log messages should immediately appear in ElasticSearch/Kibana.

Google Cloud Platform

Google Cloud IoT Core

EVA ICS controllers can act as a gateway and send telemetry to GCP IoT core as well as receive control commands.

Configuration and examples are specified in Google Cloud Platform IoT Core notifier documentation.

Google Cloud TTS

if you want to use Google Cloud Text-to-Speech engine with EVA ICS, refer to Text-to-Speech documentation.

Grafana

Grafana is well-known open platform for beautiful analytics and monitoring.

Grafana dashboard

Data

  • It’s recommended to exchange data with Grafana either via InfluxDB or via Prometheus.
  • After database notifier creation, EVA ICS immediately starts sending metrics to the specified database.
  • Create data source in Grafana.
  • EVA ICS item metrics automatically appear in Grafana and ready to be selected.
  • To put current item state on Grafana dashboard (e.g. to gauge), use last value, e.g. for InfluxDB:
SELECT last("value") FROM "sensor:env/temp1"

Controls

Custom UI

You can develop any custom EVA ICS UI and then put it into iframe on Grafana dashboard via Grafana AJAX Plugin.

  • Install EVA JS Framework
  • Develop custom web UI and put it into /opt/eva/ui folder
  • Install AJAX plugin:
grafana-cli plugins install ryantxu-ajax-panel
systemctl restart grafana-server
  • Create new visualization in Grafana and embed your custom web UI via iframe.
HMI Block UI
cd /opt/eva/ui
mkdir -p apps
cd apps
git clone https://github.com/alttch/eva-hmi-block_ui.git
grafana-cli plugins install ryantxu-ajax-panel
systemctl restart grafana-server
  • Create new visualization in Grafana and embed your custom web UI via iframe. Look HMI Block UI embedding documentation section for example.

Custom resources

To put custom resource on dashboard (e.g. chart from private local network or camera image), use AJAX plugin together with SFA PVT.

Philips Hue

EVA ICS can work with Philips Hue via Hue bridge.

Setup

Connect LEDs to Hue bridge.

Note

In EVA ICS all LEDs have common single format, where unit status is 0 for OFF, 1 for ON and unit value is 24-bit hexadecimal color code.

Philips Hue uses XYB palette which can not be properly converted back to hexadecimal RGB. For that reason, only unit status (0/1) is updated in case if Hue LED is additionally controlled by 3rd party or native Philips app.

Let’s connect the bulb to Universal Controller:

eva uc phi download https://get.eva-ics.com/phi/lights/philips_hue_leds.py
# PHI module for Philips Hue supports "discover" command, so we can discover
# the bridge in network to obtain its IP
eva uc phi discover philips_hue_leds
# consider the bridge has IP address 192.168.1.100. To make a link between
# PHI and Hue Bridge, you must either specify "user" configuration param or
# press "link" button on Hue bridge and load PHI within 30 seconds.
eva uc phi load hue1 philips_hue_leds -c host=192.168.1.100 -y
# create unit
eva uc create unit:lights/lamp1 -y
# list available PHI ports
eva uc phi ports hue1
# assign driver, e.g. to port 1
eva uc driver assign unit:lights/lamp1 hue1.default -c port=1 -y
# enable unit actions
eva uc action enable unit:lights/lamp1
# turn the bulb on and set it to, e.g. red:
eva uc action exec unit:lights/lamp1 1 -v "#FF0000" -w 5

Note

PHI tries to delete specified (or created) user, when unloading.

LoRaWAN

EVA ICS can work as LoRaWAN application server for private LoRa networks. PHI modules can either collect metrics from MQTT server or receive direct HTTP push messages with state payload.

LoRaWAN network scheme

Requirements

Hardware

To connect LoRaWAN sensors, you need LoRa gateway and LoRa network server installed. For both tests and production we use MikroTik LoRa products, but you may use any gateway, available on the market.

Network server

Here’s an example, how to configure lightweight gotthardp LoRaWAN Server with EVA ICS:

Installation

The software has pre-built deb packages for Debian & Ubuntu. Please refer to installation manual how to install them.

After installing and starting server, everything is configured via web interface at http://localhost:8080, default username/password is admin/admin.

Network configuration

Open Intrastructure->Network page and create new LoRa network:

_images/network.png

Open Intrastructure->Gateways and append your gateways.

_images/gateway.png
Append EVA ICS back-end

We’ll use PHI for RAK7204 environmental sensor. It allows sensor state to be pushed from network server directly to PHI. Go to the server console, where EVA ICS is installed, and type:

# download PHI module
eva uc phi download https://get.eva-ics.com/phi/sensors/lora/lora_rak7204.py
# load PHI module into EVA UC. we'll use sensor DevEUI as module id
eva uc phi load A123456789123456 lora_rak7204
# PHI provides an access to all ports of RAK7204. In this example we'll use
# ports "temp" (temperature) and "gas" (gas resistance)
eva uc create sensor:env/temp1
eva uc create sensor:env/gas1
# enable sensors
eva uc update sensor:env/temp1 -s1
eva uc update sensor:env/gas1 -s1
# assign driver to sensors
eva uc driver assign sensor:env/temp1 A123456789123456.default -c port=temp
eva uc driver assign sensor:env/gas1 A123456789123456.default -c port=gas
# done. The driver will update sensors as soon as it receive telemetry
# from LoRa network server. Let's save controller config:
eva uc save

Now go back to LoRaWAN network server web interface, open Backends->Handlers and create “eva” application. Make sure “data” and “deveui” fields are selected:

_images/handlers.png

Then open Backends->Connectors and create connector to EVA UC:

_images/connector.png

don’t forget to configure connector authentication. EVA ICS API key should have either permission to all items or to items with group “phi” and item id “A123456789123456” (PHI id we are going to push data in).

_images/connector_auth.png
Append sensor to network server

Go to Devices->Profiles and create profile for the sensors, don’t forget to select “eva” as back-end application:

_images/profile.png

Then go to Devices->Comissioned and add the sensor:

_images/device.png

Note

If you need to add multiple sensors, it’s better to use LoRaWAN network server API instead of the web interface.

That’s all. After the sensor join your LoRa network and send state telemetry, sensors “env/temp1” and “env/gas1” immediately update their values. You may also check PHI module state manually:

eva uc phi test A123456789123456 get

Nanoleaf

Nanoleaf is a beautiful mosaic LED system, which can be connected to EVA ICS via its local API.

Setup

Make sure Nanoleaf is connected to the network.

Note

In EVA ICS all LEDs have common single format, where unit status is 0 for OFF, 1 for ON and unit value is 24-bit hexadecimal color code.

Nanoleaf PHI also supports color profiles, you may set them with unit value. Additionally, profile brighness can be specified after comma, e.g. “Snowfall,50”

Let’s connect Nanoleaf to Universal Controller:

eva uc phi download https://get.eva-ics.com/phi/lights/nanoleaf.py
# PHI module for Nanoleaf supports "discover" command, so we can discover
# the equipment in network to obtain its IP
eva uc phi discover nanoleaf
# consider Nanoleaf has IP address 192.168.1.100. To make a link between
# PHI and equipment, you must either specify authentication token with
# "token" config param or press power button for 7 seconds before loading
# PHI module
eva uc phi load nano1 nanoleaf -c host=192.168.1.100 -y
# create unit
eva uc create unit:lights/nl1 -y
# assign driver
eva uc driver assign unit:lights/nl1 nano1.default -y
# turn Nanoleaf on and set it to, e.g. red:
eva uc action exec unit:lights/nl1 1 -v "#FF0000" -w 5
# enable unit actions
eva uc action enable unit:lights/n1
# change Nanoleaf color profile to Snowfall with 50% brighness.
eva uc action exec unit:lights/nl1 1 -v "Snowfall,50" -w 5

Note

PHI tries to delete specified (or created) token, when unloading.

Node-Red

Node-Red is a popular logic / event management software, which can be used in EVA ICS together with Logic Manager or replace it.

EVA ICS and Node-Red are perfectly compatible. The primary recommended channel for data communication is MQTT server, while EVA ICS units can be controlled either via MQTT or with JSON RPC API (third-party Node-Red component required: https://flows.nodered.org/node/node-red-contrib-jsonrpc).

This example is considered to be correct for the EVA ICS instance / cloud, containing at least one MQTT notifier.

Note

In production environments, it is highly recommended to extend Node-Red with third-party custom components, which should provide access control and action logging.

Configuring EVA ICS

Create a virtual sensor and a virtual unit:

# create a sensor, no virtual driver required
eva uc create sensor:tests/temp -yE
# load a virtual relay driver for units
eva uc phi load vr1 vrtrelay -y
# create a unit
eva uc create unit:tests/vent -yE
# assign the virtual driver to the unit
eva uc driver assign unit:tests/vent vr1.default -c port=1 -y
# allow controlling the unit via MQTT
eva uc config set unit:tests/vent mqtt_control eva_1:2 -y

Collecting events in Node-Red

Let us collect events from sensor:tests/temp via MQTT. Drop “mqtt in” component on the flow dashboard:

_images/mqtt-in.png

If there is no MQTT server configured yet in Node-Red, press “edit” button and define a new one:

_images/mqtt-server-setup-1.png _images/mqtt-server-setup-2.png

Set MQTT topic, note that “:” in EVA ICS item oid should be replaced with “/”. Set output to “a parsed JSON object”:

_images/mqtt-in-topic.png

Processing events

Put a processing component on the flow, e.g. a switch, and connect the node with MQTT input:

_images/switch-connect.png

Let us configure the switch to flow the output one if the sensor value is above or equal 25 and the output two otherwise.

The serialized sensor MQTT event, sent by Universal Controller, looks like:

{
    "c": "uc/lab-ws2",
    "status": 1,
    "t": 1611264802.9571016,
    "value": "25"
}

So:

  • Set the Property to “payload.value”
  • Set condition value type to “number” to parse sensor value as float:
_images/switch-configure.png

Defining control templates

The next step is to define a control template. Drop “template” component on the flow dashboard:

_images/template-drop.png

Edit the template node. Let us use the template to turn a unit on by sending an action to set its status to “1”:

  • Set name to “ON”
  • Set “Output as” to “parsed JSON”
  • Put { “status”: 1 } JSON into the template body
_images/template-edit.png

Repeat the same for “OFF” (status=0) action.

Controlling equipment

Note

In production environments it is better to use JSON RPC calls to control units, as MQTT actions do not provide any result / feedback.

Put “mqtt out” component on the flow:

_images/mqtt-out.png

Edit the node, set MQTT topic to “unit/tests/vent/control” (note that “:” should be replaced to “/” as well and the “/control” suffix is added):

_images/mqtt-out-setup.png

Deploying

Make sure all the flow nodes are connected and press “Deploy” button. Node-Red flow is ready to process events.

_images/deploy.png

Roboger

Roboger is a free robots event messaging service, which can be easily integrated with EVA ICS logic macros.

Servers supported

Logic Manager supports both roboger.com and local Roboger server instances.

Setup

Preparing system

Logic Manager has pre-installed Roboger extension called rpush, which uses local Roboger client configuration settings from /usr/local/etc/roboger_push.ini. The easiest way to create Roboger push configuration is installing Roboger push CLI:

curl -s https://raw.githubusercontent.com/alttch/roboger/master/bin/install-roboger-push | sudo bash /dev/stdin YOUR_ROBOGER_ADDRESS
Preparing LM extension

rpush extension requires pyrpush module. Append “pyrpush” to EXTRA variable of /opt/eva/etc/venv and then rebuild EVA ICS venv:

/opt/eva/install/build-venv
Loading LM extension

As Logic Manager uses local Roboger push configuration file, no extra configuration is required. Just type:

eva lm ext load roboger rpush -y

and it’s ready to use.

Using in macros

After the extension is loaded, function roboger_push becomes available in all logic macros:

roboger_push(msg='test error', level='error')

The function parameters are equal to params of pyrpush.push function.

Raspberry Pi

Raspberry Pi micro-computer, as well as any clone, home or industrial, can be used to run any of EVA ICS components.

Hardware recommendations

To get max performance and avoid slowdowns, Raspberry Pi 3 or newer model is highly recommended. It’s also recommended to install at least UHS-I Class SD Card or faster.

Installation

Proceed with installation. Note that as soon as Raspbian Linux is detected, EVA ICS installer script install pandas and cryptography Python modules with apt (pandas installation is very slow, cryptography has known problems when compiling from source). If your computer uses any Raspbian clone, which is not detected properly, append –force-os raspbian to EVA ICS installer (run all commands as root):

curl geteva.cc | sudo sh /dev/stdin -a --force-os raspbian

It’s also recommended to double-check is UTF-8 locale supported properly and if no - reconfigure it with

dpkg-reconfigure locales

GPIO

Raspberry Pi GPIO can be used with ready-to-use EVA ICS PHIs. All GPIO PHIs require gpiozero Python module, so instal it first.

Put “gpiozero pigpio RPi.GPIO” to EXTRA var in /opt/eva/etc/venv, then run

/opt/eva/install/build-venv

There are 3 primary PHIs for GPIO bus:

  • gpio_button handles GPIO inputs
  • gpio_out handles GPIO outputs
  • gpio_power similar to gpio_out but sets GPIO OUT to 1 as soon as Universal Controller is started (e.g. used to give power to other controlled equipment).

Example, let’s put a hardware button (or any other input) on GPIO port 20 and monitor it (you will probably need to run all commands as root, also you may type eva uc -I to start interactive Universal Controller shell):

eva uc phi download https://get.eva-ics.com/phi/gpio/gpio_button.py
# gpio_buttons PHI module requires all ports to be listed in load config.
eva uc phi load gbuttons gpio_button -c port=20 -y
# create button sensor
eva uc create sensor:buttons/button20 -y
# assign driver to sensor
eva uc driver assign sensor:buttons/button20 gbuttons.default -c port=20 -y

That’s all. When button is pressed, value of sensor:buttons/button20 is set to 1.

Sonoff

Sonoff is a line of smart power control equipment, which can be integrated with EVA ICS.

Setup

Note

EVA ICS can work only with Sonoff equipment running Tasmota firmware.

All Sonoff equipment is controlled via 2 PHI modules:

  • sonoff_basic all Sonoff single-port equipment
  • sonoff_mch all Sonoff multi-port equipment

As Sonoff exchange data via MQTT only, you must setup MQTT notifier for Universal Controller first. Note that PHI modules always require full MQTT topic despite notifier space is set.

For the initial integrations, we recommend simple MQTT server mosquitto, which is included in all popular Linux distributions and is very easy to configure.

Let’s configure notifier if it doesn’t exists yet. Consider we have MQTT server setup on IP 192.168.100.1 with username eva and password 123:

eva ns uc create eva_1 mqtt:eva:123@192.168.100.1
eva ns uc test eva_1
eva ns uc enable eva_1
# restart controller if everything is okay
eva uc server restart

After MQTT server / notifier is set up, configure Sonoff connection to MQTT server and set the control / monitoring topic, e.g. to equipment/sonoff1. We’ll use in this example notifier named eva_1, which is default notifier in EVA ICS controllers. If you use different notifier ID, it should be specified in n config param of PHI module.

Let’s connect the single-port Sonoff to Universal Controller:

eva uc phi download https://get.eva-ics.com/phi/relays/sonoff_basic.py
eva uc phi load sonoff1 sonoff_basic -c t=equipment/sonoff1 -y
# create unit
eva uc create unit:lights/lamp1 -y
# assign driver
# note: if sonoff_mch module is used, you must also specify "-c port=N"
# param, where N is port number
eva uc driver assign unit:lights/lamp1 sonoff1.default -y
# enable unit actions
eva uc action enable unit:lights/lamp1

Text-to-Speech

EVA ICS can talk. This is perfect feature to provide e.g. action feedbacks or warn about alerts.

Speech voice is generated by Logic Manager using tts macro extension, which provides an interface to TTSBroker library.

Supported TTS providers: Amazon AWS (Polly), Google Cloud (Google TTS Engine), IBM Watson.

Configure audio hardware

Logic Manager must be installed on a node which has sound card installed, or stream audio to another host e.g. via PulseAudio.

If your hardware host doesn’t have audio output, any modern USB Audio Device card can be used. Connect card to free USB slot, then connect it to (optional) amplifier and speaker.

Obtain cloud provider key

You must obtain cloud key from supported TTS provider. Key is stored in JSON format on a host where Logic Manager is installed.

Google provides cloud keys for service accounts already in JSON format. Amazon provides only API keys, to pack it to JSON, use format (don’t forget to set proper region):

{
  "aws_access_key_id":"mykey",
  "aws_secret_access_key":"mysecretkey",
  "region_name":"us-west-1"
}

For IBM Watson, JSON key should look like:

{
  "url": "https://stream.watsonplatform.net/text-to-speech/api",
  "username": "myusername",
  "password": "mypassword"
}

Create TTS configuration

If you don’t like default TTS settings, you may create optional configuration file for defaults, e.g. let’s configure Google TTS to generate voices with voice=en-US-Wavenet-F

{
  "voice": "en-US-Wavenet-F"
}

Name file as you wish and put to the path Logic Manager has access to.

All available options:

  • Google

    • pitch pitch (default: 0)
    • rate speaking rate (default: 1.0)
    • lang language (default: en-US)
    • voice tts voice (default: en-US-Wavenet-A)
  • AWS

    • voice tts voice (default: Joanna)
  • IBM

    • voice tts voice (default: en-US_AllisonVoice)

Install TTSBroker Python module

Put EXTRA=”soundfile sounddevice ttsbroker oauth2client” to /opt/eva/etc/venv and rebuild Python venv:

/opt/eva/install/build-venv

Module oauth2client is required by gcloud provider. If you want to use polly provider (AWS), add boto3 module. For IBM watson no extra modules are required.

Note

If external playback command is used, sounddevice module is not required.

Load tts macro extension

eva -I
lm
ext load t1 tts -c p=gcloud,k=/path-to-cloudkey.json -y

All extension options:

  • p TTS provider (gcloud, polly or watson)
  • k Cloud key file
  • sdir path to pre-generated files
  • cdir path to cache directory
  • cf cache format (wav, or ogg, default: wav)
  • o TTS configuration file
  • g default gain (-10..inf)
  • cmd external playback command (e.g. play %f)
  • d playback device, if no external command provided (list: /opt/eva/python3/bin/python -m sounddevice)

Option sdir is used as “permanent cache” for audio files, e.g. you may put sdir on read-only partition, cdir on RAM drive and then periodically copy cached files from cdir to sdir.

Warning

Refer to TTS provider license about caching, storing, redistributing and playing rights for the audio files generated with TTS engine.

Use loaded function

As soon as macro extension is loaded, function <ext_id>_say becomes available in all macros.

Create optional alias:

eva -I
lm
macro edit common.py
alias('say', 't1_say')

Function arguments are equal to TTSBroker say:

  • text text to say
  • gain gain control (-10..inf), float, 0 - default volume
  • options audio generation options
  • use_cache set False to skip looking for a data in the local storage/cache
  • store_cache set False to skip saving a data in the local cache
  • cache set both use_cache and store_cache
  • generate_only set True to skip playback
  • wait block thread and wait until playback finish
  • cmd external playback command

Test it:

eva -I
lm
macro run @say -a "'this is a test, I can talk'" -w 5

If there’s no sound, check controller log files and hardware connection. If sound is generated but playback is broken, try changing extension playback device or use external playback command.

Combine with macro

Now you can create macro with voice feedback, e.g. let’s create macro which turns on 2 lamps:

start('unit:lamps/lamp1')
start('unit:lamps/lamp2')
say('lamps are turned on')

UniPi

UniPi is a hardware developer/vendor, which is focused on industrial microcomputers.

Hardware recommendations

To get max performance and avoid slowdowns, it’s highly recommended to use at least UHS-I Class SD Card or faster for UniPi Neuron series.

Installation

Local

You may install EVA ICS directly on UniPi computers. As UniPi uses non-standard Raspbian distribution, append –force-os raspbian to EVA ICS installer (run all commands as root):

curl geteva.cc | sudo sh /dev/stdin -a --force-os raspbian

It’s also recommended to double-check is UTF-8 locale supported properly and if no - reconfigure it with

dpkg-reconfigure locales
Remote

Universal Controller talks with UniPi via Modbus. To let UniPi Modbus daemon answer remote requests, change LISTEN_IP in /etc/default/unipitcp:

LISTEN_IP=0.0.0.0

then restart UniPi Modbus daemon:

systemctl restart unipitcp.service

1-Wire

If installed locally, EVA ICS can use UniPi 1-Wire bus directly.

For Neuron series, owfs virtual bus for Universal Controller must be created as:

eva uc owfs create local1 "i2c=/dev/i2c-1:ALL" -y

For Axon series:

eva uc owfs create local1 "/dev/i2c-0 --w1" -y

Inputs/outputs

EVA ICS has 4 pre-built PHI modules for UniPi (model Axon S115), which can be also used as the templates for other UniPi models. As all models use very similar Modbus register maps, PHIs are compatible or require only slight modifications.

  • unipi_axon_s115_ain analog input
  • unipi_axon_s115_aout analog output
  • unipi_axon_s115_din digital inputs
  • unipi_axon_s115_dout digital outputs

It is also possible to use generic Modbus drivers for any UniPi model. Refer to UniPi documentation for the register mapping and register types.

Consider, UniPi has IP address 192.168.1.100 and EVA ICS Universal Controller is installed on remote host (for local installation use “localhost” or “127.0.0.1” for Modbus virtual port configuration). If your UniPi has RS485 port, you may also connect device via RS485-1 (default).

# create Modbus virtual port
eva uc modbus create upi1 tcp:192.168.1.100:502 -y
eva uc modbus test upi1

# download PHIs
eva uc phi download https://get.eva-ics.com/phi/unipi/axon/unipi_axon_s115_ain.py
eva uc phi download https://get.eva-ics.com/phi/unipi/axon/unipi_axon_s115_aout.py
eva uc phi download https://get.eva-ics.com/phi/unipi/axon/unipi_axon_s115_din.py
eva uc phi download https://get.eva-ics.com/phi/unipi/axon/unipi_axon_s115_dout.py

# load PHIs
eva uc phi load upi1_ain unipi_axon_s115_ain -c port=upi1,unit=1 -y
eva uc phi load upi1_aout unipi_axon_s115_aout -c port=upi1,unit=1 -y
# DIN/DOUT PHIs can update states by themselves, let's update them every
# second
eva uc phi load upi1_din unipi_axon_s115_din -c port=upi1,unit=1,update=1 -y
eva uc phi load upi1_dout unipi_axon_s115_dout -c port=upi1,unit=1,update=1 -y

# let's create sensors for DIN2 and 3 and AIN
eva uc create sensor:upi1/din2 -y
eva uc create sensor:upi1/din3 -y
eva uc create sensor:upi1/ain -y

# assign drivers to sensors
eva uc driver assign sensor:upi1/din2 upi1_din.default -c port=2 -y
eva uc driver assign sensor:upi1/din3 upi1_din.default -c port=3 -y
eva uc driver assign sensor:upi1/ain upi1_ain.default -y

# PHI for AIN doesn't update the state, so set sensor to update it e.g.
# every second:
eva uc config set sensor:upi1/ain update_interval 1 -y

# let's create units for DOUT2 and 3 and AOUT
eva uc create unit:upi1/dout2 -y
eva uc create unit:upi1/dout3 -y
eva uc create unit:upi1/aout -y

# enable unit actions
eva uc action enable unit:upi1/dout2
eva uc action enable unit:upi1/dout3
eva uc action enable unit:upi1/aout

# assign drivers to units
eva uc driver assign unit:upi1/dout2 upi1_dout.default -c port=2 -y
eva uc driver assign unit:upi1/dout3 upi1_dout.default -c port=3 -y
eva uc driver assign unit:upi1/aout upi1_aout.default -y

# let's set analog output to 3.3 volts
eva uc action exec unit:upi1/aout 1 -v 3.3

UPnP

EVA ICS controllers

Starting from version 3.2.6, controllers can find each other in local network via UPnP and automatically connect peer-to-peer without MQTT server.

To perform this, controllers send SSDP broadcast requests to non-standard SSDP UDP port 1912 for Universal Controller and 1917 for Logic Manager. Requests are performed on controller start and then repeated with 2-minute interval.

Notes
  • To let controller be discovered by other, listen option must be configured in [upnp] section of controller configuration file (starting from 3.3.0 - enabled by default).
  • To let controller (LM PLC or SFA) discover others, discover_on option must be set in [upnp] section of controller configuration file either to “all” (scan all interfaces) or to the list of network interfaces (comma separated).
  • To let controller connect to the discovered one, both must have equal default API key. API key hosts_allow permission should include the proper IP addresses or networks.
  • Discovered controllers are marked as dynamic, their configuration is not saved (until marked as static or controller masterkey is set in SFA, when cloud_manager mode is enabled).
  • If controllers have static IP addresses (or static leases, assigned by DHCP server), it’s highly recommended to mark them as static as soon as they were discovered.
Request example
M-SEARCH * HTTP/1.1
Host: ......
Man: "ssdp:discover"
ST: altertech_evaics[:uc|lm]
Response
HTTP/1.1 200 OK
Ext:
Host: <hostname>
Location: http(s)://IP:PORT
EVA-version: <version>
EVA-build: xxxxxxxx
EVA-product: <uc|lm>
EVA-controller-id: <uc|lm>/<system name>
EVA-host: <system name>
ST: altertech_evaics:<uc|lm>
USN: uuid:UNIQUE_INSTALLATION_ID
Cache-control: max-age: 60

3rd-party equipment

Some of EVA ICS PHI modules support “discover” command, which allows to automatically find UPnP-enabled equipment in local network via SSDP protocol.

Built-in SSDP function discover, located in eva.uc.drivers.tools.ssdp module can be used in custom PHI modules as well. Refer to Developing own PHI (Physical Interface) for EVA ICS. HOWTO for more info.

Xiaomi Yeelight

Yeelight is an affordable LED bulb with remote control via WiFi, which can be integrated with EVA ICS.

Setup

Firstly, bulb LAN control must be turned on (see https://www.yeelight.com/en_US/developer for more info).

After, corresponding EVA ICS PHI module can be loaded and assigned to unit.

Note

In EVA ICS all LEDs have common single format, where unit status is 0 for OFF, 1 for ON and unit value is 24-bit hexadecimal color code.

Yeelight works in 2 modes: default (yellow-white) and color. If white color tone hex code is set to unit value, PHI module uses bulb API methods to put it in default mode and control brightness/temperature only, otherwise color mode is set and color LEDs are used.

Let’s connect the bulb to Universal Controller:

eva uc phi download https://get.eva-ics.com/phi/lights/yeelight.py
# PHI module for Yeelight supports "discover" command, so we can discover
# the bulb in network to obtain its IP
eva uc phi discover yeelight
# consider the bulb has IP address 192.168.1.100
eva uc phi load ye1 yeelight -c host=192.168.1.100 -y
# create unit
eva uc create unit:lights/lamp1 -y
# assign driver
eva uc driver assign unit:lights/lamp1 ye1.default -y
# enable unit actions
eva uc action enable unit:lights/lamp1
# turn the bulb on and set it to, e.g. red:
eva uc action exec unit:lights/lamp1 1 -v "#FF0000" -w 5

PHI module has additional configuration param smooth=T, where T is time in milliseconds.

Common methods

Common methods are present in all EVA controllers. They are used to manage controller itself.

RESTful API equivalent calls can be found in corresponding component RESTful API docs.

API basics

JSON RPC

JSON RPC 2.0 protocol is the primary EVA ICS API protocol. Note that default JSON RPC result is { “ok”: true } (instead of { “result”: “OK” } in the direct API). There’s no { result: “ERROR” } responses, as JSON RPC sends errors in “error” field.

If JSON RPC request is called without ID and server should not return a result, it will return http response with a code 202 Accepted.

Note

JSON RPC is recommended way to use EVA ICS API, unless direct method calling or RESTful is really required.

JSON RPC API URL:

http://<ip_address:port>/jrpc

or

http://<ip_address:port>

(all POST requests to the root URI are processed as JSON RPC)

JSON RPC payload encoding

EVA ICS supports JSON RPC payloads, encoded as generic JSON and as MessagePack. MessagePack encoding works faster, requires less bandwidth and is highly recommended to use.

To call API methods with MessagePack-encoded payloads, use Content-Type: application/msgpack HTTP request header.

JSON RPC error responses

JSON RPC calls return error codes equal to the codes of EVA API Client:

  • 1 the item or resource is not found
  • 2 access is denied with the set API key
  • 6 Attempt to call undefined API method/function
  • 10 API function failed (all errors not listed here fall within this category)
  • 11 API function is called with invalid params
  • 12 API function attempted to create resource which already exists and can’t be recreated until deleted/removed
  • 13 the resource is busy (in use) and can not be accessed/recreated or deleted at this moment
  • 14 the method is not implemented in/for requested resource

Response field “message” may contain additional information about error.

Warning

It’s highly not recommended to perform long API calls, calling API functions from JavaScript in a web browser (e.g. giving “w” param to action methods to wait until action finish). Web browser may repeat API call continuously, which may lead to absolutely unexpected behavior.

JSON RPC via HTTP GET

Embedded equipment sometimes can send HTTP GET requests only. JSON RPC API supports such calls as well.

To make JSON RPC API request with HTTP get, send it to:

http://<ip_address:port>/jrpc?i=ID&m=METHOD&p=PARAMS

where:

  • ID request ID (any custom value). If not specified, API response isn’t sent back
  • METHOD JSON RPC method to call
  • PARAMS method params, as url-encoded JSON

E.g. the following HTTP GET request will invoke method “test” with request id=1 and params { “k”: “mykey” }:

http://<ip_address:port>/jrpc?i=1&m=test&p=%7B%22k%22%3A%22mykey%22%7D

Note

JSON RPC API calls via HTTP GET are insecure, limited to 2048 bytes and can not be batch. Use JSON RPC via HTTP POST with JSON or MessagePack payload always when possible.

Direct API

Warning

Direct method calling is deprecated and scheduled to be removed (not implemented) in EVA ICS v4. Use JSON RPC API, whenever it is possible.

Common methods functions are called through URL request

http://<ip_address:port>/sys-api/function

If SSL is allowed in the controller configuration file, you can also use https calls.

Direct API responses

Good for backward compatibility with any devices, as all API functions can be called using GET and POST. When POST is used, the parameters can be passed to functions either as multipart/form-data or as JSON.

API key can be sent in request parameters, session (if enabled and user is logged in) or in HTTP X-Auth-Key header.

Standard responses in status/body:

  • 200 OK { “result”: “OK” } API call completed successfully.

Standard error responses in status:

  • 400 Bad Request Invalid request params
  • 403 Forbidden the API key has no access to this function or resource
  • 404 Not Found method or resource/object doesn’t exist
  • 405 Method Not Allowed API function/method not found or HTTP method is not either GET or POST
  • 409 Conflict resource/object already exists or is locked
  • 500 API Error API function execution has been failed. Check input parameters and server logs.

In case API function has been failed, response body will contain JSON data with _error field, which contains error message.

{
    "_error": "unable to add object, already present",
    "result": "ERROR"
}

Contents

General functions

test - test API/key and get system info

Test can be executed with any valid API key of the controller the function is called to.

For SFA, the result section “connected” contains connection status of remote controllers. The API key must have an access either to “uc” and “lm” groups (“remote_uc:uc” and “remote_lm:lm”) or to particular controller oids.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 104
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "test",
    "params": {
        "k": "qwerty"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 104' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "test", "params": {"k": "qwerty"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 104' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "test", "params": {"k": "qwerty"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "test",
  "params": {
    "k": "qwerty"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:104 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '104', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'test', 'params': {'k': 'qwerty'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 1034
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "acl": {
            "allow": {
                "cmd": false,
                "device": false,
                "lock": true
            },
            "cdata": "",
            "groups": [
                "#"
            ],
            "groups_ro": [],
            "items": [],
            "items_ro": [],
            "key_id": "operator",
            "master": false,
            "pvt": [
                "#"
            ],
            "sysfunc": true
        },
        "controller": "uc/lab-ws2",
        "db_update": 1,
        "debug": true,
        "development": true,
        "layout": "enterprise",
        "log_level": 20,
        "ok": true,
        "polldelay": 0.01,
        "product_build": 2020103101,
        "product_code": "uc",
        "product_name": "EVA Universal Controller",
        "setup_mode": false,
        "system": "lab-ws2",
        "threads": 53,
        "time": 1604179751.2266004,
        "uptime": 2474,
        "version": "3.3.2"
    }
}

Parameters:

  • k any valid API key

Returns:

JSON dict with system info and current API key permissions (for masterkey only { “master”: true } is returned)

save - save database and runtime configuration

All modified items, their status, and configuration will be written to the disk. If exec_before_save command is defined in the controller’s configuration file, it’s called before saving and exec_after_save after (e.g. to switch the partition to write mode and back to read-only).

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 103
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "save",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 103' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "save", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 103' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "save", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "save",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:103 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '103', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'save', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with sysfunc=yes permissions
clear_lang_cache - Clear language cache

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 115
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "clear_lang_cache",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 115' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "clear_lang_cache", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 115' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "clear_lang_cache", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "clear_lang_cache",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:115 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '115', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'clear_lang_cache', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}
cmd - execute a remote system command

Executes a command script on the server where the controller is installed.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 178
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "cmd",
    "params": {
        "a": "0 2 3",
        "c": "test",
        "k": "mykey",
        "t": 10,
        "w": 5
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 178' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "cmd", "params": {"a": "0 2 3", "c": "test", "k": "mykey", "t": 10, "w": 5}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 178' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "cmd", "params": {"a": "0 2 3", "c": "test", "k": "mykey", "t": 10, "w": 5}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "cmd",
  "params": {
    "a": "0 2 3",
    "c": "test",
    "k": "mykey",
    "t": 10,
    "w": 5
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:178 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '178', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'cmd', 'params': {'a': '0 2 3', 'c': 'test', 'k': 'mykey', 't': 10, 'w': 5}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 579
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "args": [
            "0",
            "2",
            "3"
        ],
        "cmd": "test",
        "err": "some text to stderr\n",
        "exitcode": 0,
        "out": "test script start\nparam 1: 0 ( > 0 will generate \"failed\" status)\nparam 2: 2\nparam 3: 3\ndelay 3 sec\nscript finish\n",
        "status": "completed",
        "time": {
            "completed": 1604180400.947191,
            "created": 1604180395.8823428,
            "running": 1604180395.8826754
        },
        "timeout": 10.0
    }
}

Parameters:

  • k API key with allow=cmd permissions
  • c name of the command script

Optionally:

  • a string of command arguments, separated by spaces (passed to the script) or array (list)
  • w wait (in seconds) before API call sends a response. This allows to try waiting until command finish
  • t maximum time of command execution. If the command fails to finish within the specified time (in sec), it will be terminated
  • s STDIN data
install_pkg - install a package

Installs the package

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 188
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "install_pkg",
    "params": {
        "i": "test",
        "k": "mykey",
        "m": "<base64-encoded package>",
        "w": 5
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 188' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "install_pkg", "params": {"i": "test", "k": "mykey", "m": "<base64-encoded package>", "w": 5}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 188' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "install_pkg", "params": {"i": "test", "k": "mykey", "m": "<base64-encoded package>", "w": 5}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "install_pkg",
  "params": {
    "i": "test",
    "k": "mykey",
    "m": "<base64-encoded package>",
    "w": 5
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:188 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '188', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'install_pkg', 'params': {'i': 'test', 'k': 'mykey', 'm': '<base64-encoded package>', 'w': 5}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 428
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "call_for": "test",
        "err": null,
        "exitcode": 0,
        "finished": true,
        "function": "install_pkg",
        "out": null,
        "time": {
            "completed": 1609392604.4225385,
            "created": 1609392604.4218152,
            "running": 1609392604.4218833
        },
        "uuid": "19242b7a-999d-4eac-8c04-7375241c86a5"
    }
}

Parameters:

  • k API key with master permissions
  • i package name
  • m package content (base64-encoded tar/tgz)
  • o package setup options
  • w wait (in seconds) before API call sends a response. This allows to try waiting until the package is installed
list_plugins - get list of loaded core plugins

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 111
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_plugins",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 111' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_plugins", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 111' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_plugins", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_plugins",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:111 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '111', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_plugins', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 235
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "author": "Altertech",
            "license": "MIT",
            "name": "autotest",
            "ready": true,
            "version": "1.0.0"
        }
    ]
}

Parameters:

  • k API key with master permissions

Returns:

list with plugin module information

set_debug - switch debugging mode

Enables and disables debugging mode while the controller is running. After the controller is restarted, this parameter is lost and controller switches back to the mode specified in the configuration file.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 133
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_debug",
    "params": {
        "debug": "true",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 133' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_debug", "params": {"debug": "true", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 133' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_debug", "params": {"debug": "true", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_debug",
  "params": {
    "debug": "true",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:133 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '133', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_debug', 'params': {'debug': 'true', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • debug true for enabling debug mode, false for disabling
shutdown_core - shutdown the controller

Controller process will be exited and then (should be) restarted by watchdog. This allows to restart controller remotely.

For MQTT API calls a small shutdown delay usually should be specified to let the core send the correct API response.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 112
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "shutdown_core",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 112' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "shutdown_core", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 112' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "shutdown_core", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "shutdown_core",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:112 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '112', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'shutdown_core', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • t shutdown delay (seconds)
login - log in and get authentication token

Obtains authentication token which can be used in API calls instead of API key.

If both k and u args are absent, but API method is called with HTTP request, which contain HTTP header for basic authorization, the function will try to parse it and log in user with credentials provided.

If authentication token is specified, the function will check it and return token information if it is valid.

If both token and credentials (user or API key) are specified, the function will return the token to normal mode.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 87
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "login",
    "params": {
        "p": "123",
        "u": "test"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 87' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "login", "params": {"p": "123", "u": "test"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 87' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "login", "params": {"p": "123", "u": "test"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "login",
  "params": {
    "p": "123",
    "u": "test"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:87 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '87', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'login', 'params': {'p': '123', 'u': 'test'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 165
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "key": "test",
        "token": "token:pRe3FIEoLSRVD9FbTsTXhaYKm4lNwNiE",
        "user": "test"
    }
}

Parameters:

  • k valid API key or
  • u user login
  • p user password
  • a authentication token

Returns:

A dict, containing API key ID and authentication token

logout - log out and purge authentication token

Purges authentication token

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Length: 110
Content-Type: application/json
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "logout",
    "params": {
        "k": "token:pRe3FIEoLSRVD9FbTsTXhaYKm4lNwNiE"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 110' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "logout", "params": {"k": "token:pRe3FIEoLSRVD9FbTsTXhaYKm4lNwNiE"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 110' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "logout", "params": {"k": "token:pRe3FIEoLSRVD9FbTsTXhaYKm4lNwNiE"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "logout",
  "params": {
    "k": "token:pRe3FIEoLSRVD9FbTsTXhaYKm4lNwNiE"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:110 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '110', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'logout', 'params': {'k': 'token:pRe3FIEoLSRVD9FbTsTXhaYKm4lNwNiE'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid token
set_token_readonly - Set token read-only

Applies read-only mode for token. In read-only mode, only read-only functions work, others return result_token_restricted(15).

The method works for token-authenticated API calls only.

To exit read-only mode, user must either re-login or, to keep the current token, call “login” API method with both token and user credentials.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Length: 151
Content-Type: application/json
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_token_readonly",
    "params": {
        "k": "token:pRe3FIEoLSRVD9FbTsTXhaYKm4lNwNiE"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 151' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_token_readonly", "params": {"k": "token:pRe3FIEoLSRVD9FbTsTXhaYKm4lNwNiE"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 151' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_token_readonly", "params": {"k": "token:pRe3FIEoLSRVD9FbTsTXhaYKm4lNwNiE"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_token_readonly",
  "params": {
    "k": "token:pRe3FIEoLSRVD9FbTsTXhaYKm4lNwNiE"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:151 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '151', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_token_readonly', 'params': {'k': 'token:pRe3FIEoLSRVD9FbTsTXhaYKm4lNwNiE'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

CVARs

get_cvar - get the value of user-defined variable

Note

Even if different EVA controllers are working on the same server, they have different sets of variables To set the variables for each subsystem, use SYS API on the respective address/port.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 128
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_cvar",
    "params": {
        "i": "test",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 128' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_cvar", "params": {"i": "test", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 128' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_cvar", "params": {"i": "test", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_cvar",
  "params": {
    "i": "test",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:128 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '128', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_cvar', 'params': {'i': 'test', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 89
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "test": "some_value"
    }
}

Parameters:

  • k API key with master permissions

Optionally:

  • i variable name

Returns:

Dict containing variable and its value. If no varible name was specified, all cvars are returned.

set_cvar - set the value of user-defined variable

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 155
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_cvar",
    "params": {
        "i": "test",
        "k": "mykey",
        "v": "some_value"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 155' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_cvar", "params": {"i": "test", "k": "mykey", "v": "some_value"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 155' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_cvar", "params": {"i": "test", "k": "mykey", "v": "some_value"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_cvar",
  "params": {
    "i": "test",
    "k": "mykey",
    "v": "some_value"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:155 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '155', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_cvar', 'params': {'i': 'test', 'k': 'mykey', 'v': 'some_value'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i variable name

Optionally:

  • v variable value (if not specified, variable is deleted)

Locking functions

get_lock - get lock status

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 131
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_lock",
    "params": {
        "k": "mykey",
        "l": "mylock1"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 131' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_lock", "params": {"k": "mykey", "l": "mylock1"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 131' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_lock", "params": {"k": "mykey", "l": "mylock1"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_lock",
  "params": {
    "k": "mykey",
    "l": "mylock1"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:131 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '131', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_lock', 'params': {'k': 'mykey', 'l': 'mylock1'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 132
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "id": "mylock1",
        "locked": true,
        "type": "lock"
    }
}

Parameters:

  • k API key with allow=lock permissions
  • l lock id
lock - acquire lock

Locks can be used similarly to file locking by the specific process. The difference is that SYS API tokens can be:

  • centralized for several systems (any EVA server can act as lock server)
  • removed from outside
  • automatically unlocked after the expiration time, if the initiator failed or forgot to release the lock

used to restrict parallel process starting or access to system files/resources. LM PLC macro share locks with extrnal scripts.

Note

Even if different EVA controllers are working on the same server, their lock tokens are stored in different bases. To work with the token of each subsystem, use SYS API on the respective address/port.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 160
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "lock",
    "params": {
        "e": 1,
        "k": "mykey",
        "l": "mylock1",
        "t": 15
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 160' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "lock", "params": {"e": 1, "k": "mykey", "l": "mylock1", "t": 15}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 160' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "lock", "params": {"e": 1, "k": "mykey", "l": "mylock1", "t": 15}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "lock",
  "params": {
    "e": 1,
    "k": "mykey",
    "l": "mylock1",
    "t": 15
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:160 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '160', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'lock', 'params': {'e': 1, 'k': 'mykey', 'l': 'mylock1', 't': 15}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with allow=lock permissions
  • l lock id

Optionally:

  • t maximum time (seconds) to acquire lock
  • e time after which lock is automatically released (if absent, lock may be released only via unlock function)
unlock - release lock

Releases the previously acquired lock.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 129
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "unlock",
    "params": {
        "k": "mykey",
        "l": "mylock1"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 129' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "unlock", "params": {"k": "mykey", "l": "mylock1"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 129' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "unlock", "params": {"k": "mykey", "l": "mylock1"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "unlock",
  "params": {
    "k": "mykey",
    "l": "mylock1"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:129 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '129', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'unlock', 'params': {'k': 'mykey', 'l': 'mylock1'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with allow=lock permissions
  • l lock id

Logging

log - put message to log file

An external application can put a message in the logs on behalf of the controller.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 168
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "log",
    "params": {
        "k": "mykey",
        "l": "warning",
        "m": "local file system is full"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 168' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "log", "params": {"k": "mykey", "l": "warning", "m": "local file system is full"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 168' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "log", "params": {"k": "mykey", "l": "warning", "m": "local file system is full"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "log",
  "params": {
    "k": "mykey",
    "l": "warning",
    "m": "local file system is full"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:168 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '168', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'log', 'params': {'k': 'mykey', 'l': 'warning', 'm': 'local file system is full'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with sysfunc=yes permissions
  • l log level
  • m message text
log_debug - put debug message to log file

An external application can put a message in the logs on behalf of the controller.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 143
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "log_debug",
    "params": {
        "k": "mykey",
        "m": "test debug message"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 143' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "log_debug", "params": {"k": "mykey", "m": "test debug message"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 143' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "log_debug", "params": {"k": "mykey", "m": "test debug message"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "log_debug",
  "params": {
    "k": "mykey",
    "m": "test debug message"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:143 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '143', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'log_debug', 'params': {'k': 'mykey', 'm': 'test debug message'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with sysfunc=yes permissions
  • m message text
log_info - put info message to log file

An external application can put a message in the logs on behalf of the controller.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 141
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "log_info",
    "params": {
        "k": "mykey",
        "m": "test info message"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 141' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "log_info", "params": {"k": "mykey", "m": "test info message"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 141' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "log_info", "params": {"k": "mykey", "m": "test info message"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "log_info",
  "params": {
    "k": "mykey",
    "m": "test info message"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:141 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '141', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'log_info', 'params': {'k': 'mykey', 'm': 'test info message'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with sysfunc=yes permissions
  • m message text
log_warning - put warning message to log file

An external application can put a message in the logs on behalf of the controller.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 147
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "log_warning",
    "params": {
        "k": "mykey",
        "m": "test warning message"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 147' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "log_warning", "params": {"k": "mykey", "m": "test warning message"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 147' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "log_warning", "params": {"k": "mykey", "m": "test warning message"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "log_warning",
  "params": {
    "k": "mykey",
    "m": "test warning message"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:147 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '147', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'log_warning', 'params': {'k': 'mykey', 'm': 'test warning message'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with sysfunc=yes permissions
  • m message text
log_error - put error message to log file

An external application can put a message in the logs on behalf of the controller.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 143
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "log_error",
    "params": {
        "k": "mykey",
        "m": "test error message"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 143' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "log_error", "params": {"k": "mykey", "m": "test error message"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 143' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "log_error", "params": {"k": "mykey", "m": "test error message"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "log_error",
  "params": {
    "k": "mykey",
    "m": "test error message"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:143 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '143', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'log_error', 'params': {'k': 'mykey', 'm': 'test error message'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with sysfunc=yes permissions
  • m message text
log_critical - put critical message to log file

An external application can put a message in the logs on behalf of the controller.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 149
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "log_critical",
    "params": {
        "k": "mykey",
        "m": "test critical message"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 149' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "log_critical", "params": {"k": "mykey", "m": "test critical message"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 149' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "log_critical", "params": {"k": "mykey", "m": "test critical message"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "log_critical",
  "params": {
    "k": "mykey",
    "m": "test critical message"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:149 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '149', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'log_critical', 'params': {'k': 'mykey', 'm': 'test critical message'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with sysfunc=yes permissions
  • m message text
log_get - get records from the controller log

Log records are stored in the controllers’ memory until restart or the time (keep_logmem) specified in controller configuration passes.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 165
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "log_get",
    "params": {
        "k": "mykey",
        "l": "warning",
        "n": 3,
        "t": 3600
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 165' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "log_get", "params": {"k": "mykey", "l": "warning", "n": 3, "t": 3600}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 165' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "log_get", "params": {"k": "mykey", "l": "warning", "n": 3, "t": 3600}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "log_get",
  "params": {
    "k": "mykey",
    "l": "warning",
    "n": 3,
    "t": 3600
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:165 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '165', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'log_get', 'params': {'k': 'mykey', 'l': 'warning', 'n': 3, 't': 3600}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 1034
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "dt": "2020-10-31T22:53:39.653032+01:00",
            "h": "lab-ws2",
            "l": 30,
            "lvl": "warning",
            "mod": "sysapi",
            "msg": "test warning message",
            "p": "uc",
            "t": 1604181219.6530318,
            "th": "CP Server Thread-14"
        },
        {
            "dt": "2020-10-31T22:53:39.666849+01:00",
            "h": "lab-ws2",
            "l": 40,
            "lvl": "error",
            "mod": "sysapi",
            "msg": "test error message",
            "p": "uc",
            "t": 1604181219.6668491,
            "th": "CP Server Thread-17"
        },
        {
            "dt": "2020-10-31T22:53:39.680672+01:00",
            "h": "lab-ws2",
            "l": 50,
            "lvl": "critical",
            "mod": "sysapi",
            "msg": "test critical message",
            "p": "uc",
            "t": 1604181219.6806724,
            "th": "CP Server Thread-6"
        }
    ]
}

Parameters:

  • k API key with sysfunc=yes permissions

Optionally:

  • l log level (10 - debug, 20 - info, 30 - warning, 40 - error, 50 - critical)
  • t get log records not older than t seconds
  • n the maximum number of log records you want to obtain
log_rotate - rotate log file

Deprecated, not required since 3.3.0

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 109
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "log_rotate",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 109' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "log_rotate", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 109' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "log_rotate", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "log_rotate",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:109 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '109', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'log_rotate', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with sysfunc=yes permissions
api_log_get - get API call log
  • API call with master permission returns all records requested
  • API call with other API key returns records for the specified key only
  • API call with an authentication token returns records for the current authorized user

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 110
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "api_log_get",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 110' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "api_log_get", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 110' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "api_log_get", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "api_log_get",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:110 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '110', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'api_log_get', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 21292
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "auth": "key",
            "func": "get_lock",
            "gw": "http",
            "id": "621c849e-0a97-4233-b83a-860065cf4b50",
            "ip": "127.0.0.1",
            "ki": "masterkey",
            "params": "{\"l\":\"mylock1\"}",
            "status": "OK",
            "t": 1604180395.8382585,
            "tf": 1604180395.8424263,
            "u": null,
            "utp": null
        },
        {
            "auth": "key",
            "func": "unlock",
            "gw": "http",
            "id": "25f11256-1d08-468d-b067-3e8d2b501397",
            "ip": "127.0.0.1",
            "ki": "masterkey",
            "params": "{\"l\":\"mylock1\"}",
            "status": "OK",
            "t": 1604180395.8515046,
            "tf": 1604180395.8559692,
            "u": null,
            "utp": null
        }
    ]
}

Parameters:

  • k any valid API key

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • n records limit
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • f record filter (requires API key with master permission)

Returns:

List of API calls

Note: API call params are returned as string and can be invalid JSON data as they’re always truncated to 512 symbols in log database

Record filter should be specified either as string (k1=val1,k2=val2) or as a dict. Valid fields are:

  • gw: filter by API gateway
  • ip: filter by caller IP
  • auth: filter by authentication type
  • u: filter by user
  • utp: filter by user type
  • ki: filter by API key ID
  • func: filter by API function
  • params: filter by API call params (matches if field contains value)
  • status: filter by API call status

API keys

create_key - create API key

API keys are defined statically in etc/<controller>_apikeys.ini file as well as can be created with API and stored in user database.

Keys with master permission can not be created.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 157
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create_key",
    "params": {
        "i": "testkey",
        "k": "mykey",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 157' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create_key", "params": {"i": "testkey", "k": "mykey", "save": "true"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 157' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create_key", "params": {"i": "testkey", "k": "mykey", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create_key",
  "params": {
    "i": "testkey",
    "k": "mykey",
    "save": "true"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:157 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '157', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create_key', 'params': {'i': 'testkey', 'k': 'mykey', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 504
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "allow": [],
        "cdata": "",
        "dynamic": true,
        "groups": [],
        "groups_ro": [],
        "hosts_allow": [
            "0.0.0.0/0"
        ],
        "hosts_assign": [],
        "id": "testkey",
        "items": [],
        "items_ro": [],
        "key": "Oq9pP0OJMsBeB7YiH4PTSkZTiXxDsVgA6k4ngKifEoWR9UavxnceFgyyzIjfoIOf",
        "master": false,
        "pvt": [],
        "rpvt": [],
        "sysfunc": false
    }
}

Parameters:

  • k API key with master permissions
  • i API key ID
  • save save configuration immediately

Returns:

JSON with serialized key object

destroy_key - delete API key

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 134
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "destroy_key",
    "params": {
        "i": "testkey",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 134' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "destroy_key", "params": {"i": "testkey", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 134' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "destroy_key", "params": {"i": "testkey", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "destroy_key",
  "params": {
    "i": "testkey",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:134 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '134', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'destroy_key', 'params': {'i': 'testkey', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i API key ID
list_key_props - list API key permissions

Lists API key permissons (including a key itself)

Note

API keys, defined in etc/<controller>_apikeys.ini file can not be managed with API.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 137
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_key_props",
    "params": {
        "i": "testkey",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 137' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_key_props", "params": {"i": "testkey", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 137' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_key_props", "params": {"i": "testkey", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_key_props",
  "params": {
    "i": "testkey",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:137 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '137', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_key_props', 'params': {'i': 'testkey', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 503
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "allow": [],
        "cdata": "",
        "dynamic": true,
        "groups": [],
        "groups_ro": [],
        "hosts_allow": [
            "0.0.0.0/0"
        ],
        "hosts_assign": [],
        "id": "testkey",
        "items": [],
        "items_ro": [],
        "key": "Oq9pP0OJMsBeB7YiH4PTSkZTiXxDsVgA6k4ngKifEoWR9UavxnceFgyyzIjfoIOf",
        "master": false,
        "pvt": [],
        "rpvt": [],
        "sysfunc": true
    }
}

Parameters:

  • k API key with master permissions
  • i API key ID
  • save save configuration immediately
list_keys - list API keys

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 108
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_keys",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 108' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_keys", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 108' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_keys", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_keys",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:108 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '108', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_keys', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 1530
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "cdata": "",
            "dynamic": false,
            "key_id": "masterkey",
            "master": true
        },
        {
            "allow": {
                "cmd": true,
                "device": true,
                "lock": false
            },
            "cdata": "",
            "dynamic": true,
            "groups": [
                "#"
            ],
            "groups_ro": [],
            "items": [],
            "items_ro": [],
            "key_id": "default",
            "master": false,
            "sysfunc": false
        },
        {
            "allow": {
                "cmd": false,
                "device": false,
                "lock": true
            },
            "cdata": "",
            "dynamic": true,
            "groups": [
                "#"
            ],
            "groups_ro": [],
            "items": [],
            "items_ro": [],
            "key_id": "operator",
            "master": false,
            "pvt": [
                "#"
            ],
            "sysfunc": true
        },
        {
            "allow": {
                "cmd": false,
                "device": false,
                "lock": false
            },
            "cdata": "",
            "dynamic": true,
            "groups": [],
            "groups_ro": [],
            "items": [],
            "items_ro": [],
            "key_id": "testkey",
            "master": false,
            "sysfunc": true
        }
    ]
}

Parameters:

  • k API key with master permissions
regenerate_key - regenerate API key

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 137
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "regenerate_key",
    "params": {
        "i": "testkey",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 137' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "regenerate_key", "params": {"i": "testkey", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 137' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "regenerate_key", "params": {"i": "testkey", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "regenerate_key",
  "params": {
    "i": "testkey",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:137 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '137', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'regenerate_key', 'params': {'i': 'testkey', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 142
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "key": "GmCnj0BUfYpaGowgjSdc5iShhqq5N7m4JrTR3pT3ocF9SH5QYnDhCaSDP3eNOEXm"
    }
}

Parameters:

  • k API key with master permissions
  • i API key ID

Returns:

JSON dict with new key value in “key” field

set_key_prop - set API key permissions

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 204
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_key_prop",
    "params": {
        "i": "testkey",
        "k": "mykey",
        "p": "sysfunc",
        "save": "true",
        "v": "true"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 204' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_key_prop", "params": {"i": "testkey", "k": "mykey", "p": "sysfunc", "save": "true", "v": "true"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 204' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_key_prop", "params": {"i": "testkey", "k": "mykey", "p": "sysfunc", "save": "true", "v": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_key_prop",
  "params": {
    "i": "testkey",
    "k": "mykey",
    "p": "sysfunc",
    "save": "true",
    "v": "true"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:204 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '204', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_key_prop', 'params': {'i': 'testkey', 'k': 'mykey', 'p': 'sysfunc', 'save': 'true', 'v': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i API key ID
  • p property
  • v value (if none, permission will be revoked)
  • save save configuration immediately

User accounts

create_user - create user account

Note

All changes to user accounts are instant, if the system works in read/only mode, set it to read/write before performing user management.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 190
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create_user",
    "params": {
        "a": "testkey",
        "k": "mykey",
        "p": "verysecretpassword",
        "u": "test"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 190' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create_user", "params": {"a": "testkey", "k": "mykey", "p": "verysecretpassword", "u": "test"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 190' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create_user", "params": {"a": "testkey", "k": "mykey", "p": "verysecretpassword", "u": "test"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create_user",
  "params": {
    "a": "testkey",
    "k": "mykey",
    "p": "verysecretpassword",
    "u": "test"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:190 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '190', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create_user', 'params': {'a': 'testkey', 'k': 'mykey', 'p': 'verysecretpassword', 'u': 'test'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 112
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "key_id": "testkey",
        "user": "test"
    }
}

Parameters:

  • k API key with master permissions
  • u user login
  • p user password
  • a API key to assign (key id, not a key itself)
destroy_user - delete user account

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 132
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "destroy_user",
    "params": {
        "k": "mykey",
        "u": "test"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 132' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "destroy_user", "params": {"k": "mykey", "u": "test"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 132' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "destroy_user", "params": {"k": "mykey", "u": "test"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "destroy_user",
  "params": {
    "k": "mykey",
    "u": "test"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:132 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '132', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'destroy_user', 'params': {'k': 'mykey', 'u': 'test'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • u user login
get_user - get user account info

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 128
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_user",
    "params": {
        "k": "mykey",
        "u": "test"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 128' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_user", "params": {"k": "mykey", "u": "test"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 128' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_user", "params": {"k": "mykey", "u": "test"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_user",
  "params": {
    "k": "mykey",
    "u": "test"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:128 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '128', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_user', 'params': {'k': 'mykey', 'u': 'test'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 112
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "key_id": "testkey",
        "user": "test"
    }
}

Parameters:

  • k API key with master permissions
  • u user login
list_users - list user accounts

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 109
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_users",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 109' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_users", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 109' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_users", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_users",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:109 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '109', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_users', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 140
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "key_id": "testkey",
            "user": "test"
        }
    ]
}

Parameters:

  • k API key with master permissions
set_user_key - assign API key to user

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 158
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_user_key",
    "params": {
        "a": "masterkey",
        "k": "mykey",
        "u": "test"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 158' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_user_key", "params": {"a": "masterkey", "k": "mykey", "u": "test"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 158' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_user_key", "params": {"a": "masterkey", "k": "mykey", "u": "test"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_user_key",
  "params": {
    "a": "masterkey",
    "k": "mykey",
    "u": "test"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:158 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '158', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_user_key', 'params': {'a': 'masterkey', 'k': 'mykey', 'u': 'test'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • u user login
  • a API key to assign (key id, not a key itself) or multiple keys, comma separated
set_user_password - set user password

Either master key and user login must be specified or a user must be logged in and a session token used

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 160
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_user_password",
    "params": {
        "k": "mykey",
        "p": "qwerty",
        "u": "test"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 160' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_user_password", "params": {"k": "mykey", "p": "qwerty", "u": "test"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 160' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_user_password", "params": {"k": "mykey", "p": "qwerty", "u": "test"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_user_password",
  "params": {
    "k": "mykey",
    "p": "qwerty",
    "u": "test"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:160 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '160', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_user_password', 'params': {'k': 'mykey', 'p': 'qwerty', 'u': 'test'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k master key or token
  • u user login
  • p new password
list_tokens - List active session tokens

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 110
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_tokens",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 110' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_tokens", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 110' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_tokens", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_tokens",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:110 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '110', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_tokens', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 497
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "ki": "operator",
            "m": 1,
            "t": 1609942450.07001,
            "token": "token:5mdAIZcGxMobNvYLWHqncAzYRxGiEDjM",
            "u": "test",
            "utp": null
        },
        {
            "ki": "operator",
            "m": 1,
            "t": 1609942451.0943265,
            "token": "token:QmO6vhSR1xPVIVO6AdXgRokkpHrCrwUO",
            "u": "test",
            "utp": null
        }
    ]
}

Parameters:

  • k API key with master permissions
drop_tokens - Drop session token(s)

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 131
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "drop_tokens",
    "params": {
        "k": "mykey",
        "u": "test"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 131' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "drop_tokens", "params": {"k": "mykey", "u": "test"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 131' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "drop_tokens", "params": {"k": "mykey", "u": "test"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "drop_tokens",
  "params": {
    "k": "mykey",
    "u": "test"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:131 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '131', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'drop_tokens', 'params': {'k': 'mykey', 'u': 'test'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • a session token or
  • u user name or
  • i API key id

Notifier management

disable_notifier - disable notifier

Note

The notifier is disabled until controller restart. To disable notifier permanently, use notifier management CLI.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 137
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "disable_notifier",
    "params": {
        "i": "eva_1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 137' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "disable_notifier", "params": {"i": "eva_1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 137' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "disable_notifier", "params": {"i": "eva_1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "disable_notifier",
  "params": {
    "i": "eva_1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:137 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '137', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'disable_notifier', 'params': {'i': 'eva_1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i notifier ID
enable_notifier - enable notifier

Note

The notifier is enabled until controller restart. To enable notifier permanently, use notifier management CLI.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "enable_notifier",
    "params": {
        "i": "eva_1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "enable_notifier", "params": {"i": "eva_1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "enable_notifier", "params": {"i": "eva_1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "enable_notifier",
  "params": {
    "i": "eva_1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'enable_notifier', 'params': {'i': 'eva_1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i notifier ID
get_notifier - get notifier configuration

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 133
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_notifier",
    "params": {
        "i": "eva_1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 133' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_notifier", "params": {"i": "eva_1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 133' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_notifier", "params": {"i": "eva_1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_notifier",
  "params": {
    "i": "eva_1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:133 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '133', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_notifier', 'params': {'i': 'eva_1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 613
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "api_enabled": true,
        "enabled": false,
        "events": [
            {
                "groups": [
                    "#"
                ],
                "subject": "state",
                "types": [
                    "#"
                ]
            },
            {
                "level": 20,
                "subject": "log"
            },
            {
                "subject": "server"
            }
        ],
        "host": "localhost",
        "id": "eva_1",
        "retain_enabled": true,
        "type": "mqtt"
    }
}

Parameters:

  • k API key with master permissions
  • i notifier ID
list_notifiers - list notifiers

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 113
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_notifiers",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 113' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_notifiers", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 113' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_notifiers", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_notifiers",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:113 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '113', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_notifiers', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 729
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "api_enabled": true,
            "enabled": false,
            "events": [
                {
                    "groups": [
                        "#"
                    ],
                    "subject": "state",
                    "types": [
                        "#"
                    ]
                },
                {
                    "level": 20,
                    "subject": "log"
                },
                {
                    "subject": "server"
                }
            ],
            "host": "localhost",
            "id": "eva_1",
            "retain_enabled": true,
            "type": "mqtt"
        }
    ]
}

Parameters:

  • k API key with master permissions

File management

file_put - put file to runtime folder

Puts a new file into runtime folder. If the file with such name exists, it will be overwritten. As all files in runtime are text, binary data can not be put.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 184
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "file_put",
    "params": {
        "i": "xc/uc/test_action_script",
        "k": "mykey",
        "m": "/bin/sh\\n\\nexit 0"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 184' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "file_put", "params": {"i": "xc/uc/test_action_script", "k": "mykey", "m": "/bin/sh\\n\\nexit 0"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 184' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "file_put", "params": {"i": "xc/uc/test_action_script", "k": "mykey", "m": "/bin/sh\\n\\nexit 0"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "file_put",
  "params": {
    "i": "xc/uc/test_action_script",
    "k": "mykey",
    "m": "/bin/sh\\n\\nexit 0"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:184 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '184', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'file_put', 'params': {'i': 'xc/uc/test_action_script', 'k': 'mykey', 'm': '/bin/sh\\n\\nexit 0'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i relative path (without first slash)
  • m file content (plain text or base64-encoded)
  • b if True - put binary file (decode base64)
file_set_exec - set file exec permission

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 174
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "file_set_exec",
    "params": {
        "e": "true",
        "i": "xc/uc/test_action_script",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 174' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "file_set_exec", "params": {"e": "true", "i": "xc/uc/test_action_script", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 174' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "file_set_exec", "params": {"e": "true", "i": "xc/uc/test_action_script", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "file_set_exec",
  "params": {
    "e": "true",
    "i": "xc/uc/test_action_script",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:174 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '174', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'file_set_exec', 'params': {'e': 'true', 'i': 'xc/uc/test_action_script', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i relative path (without first slash)
  • e false for 0x644, true for 0x755 (executable)
file_get - get file contents from runtime folder

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 148
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "file_get",
    "params": {
        "i": "xc/uc/test_action_script",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 148' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "file_get", "params": {"i": "xc/uc/test_action_script", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 148' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "file_get", "params": {"i": "xc/uc/test_action_script", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "file_get",
  "params": {
    "i": "xc/uc/test_action_script",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:148 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '148', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'file_get', 'params': {'i': 'xc/uc/test_action_script', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 200
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "content_type": "text/plain",
        "data": "/bin/sh\\n\\nexit 0",
        "e": false,
        "file": "xc/uc/test_action_script"
    }
}

Parameters:

  • k API key with master permissions
  • i relative path (without first slash)
  • b if True - force getting binary file (base64-encode content)

Core scripts

list_corescript_mqtt_topics - List MQTT topics core scripts react on

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 126
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_corescript_mqtt_topics",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 126' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_corescript_mqtt_topics", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 126' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_corescript_mqtt_topics", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_corescript_mqtt_topics",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:126 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '126', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_corescript_mqtt_topics', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 55
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": []
}

Parameters:

  • k API key with master permissions
reload_corescripts - Reload core scripts if some was added or deleted

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 117
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "reload_corescripts",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 117' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "reload_corescripts", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 117' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "reload_corescripts", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "reload_corescripts",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:117 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '117', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'reload_corescripts', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
subscribe_corescripts_mqtt - Subscribe core scripts to MQTT topic

The method subscribes core scripts to topic of default MQTT notifier (eva_1). To specify another notifier, set topic as <notifer_id>:<topic>

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 173
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "subscribe_corescripts_mqtt",
    "params": {
        "k": "mykey",
        "q": 2,
        "t": "some/test/topic"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 173' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "subscribe_corescripts_mqtt", "params": {"k": "mykey", "q": 2, "t": "some/test/topic"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 173' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "subscribe_corescripts_mqtt", "params": {"k": "mykey", "q": 2, "t": "some/test/topic"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "subscribe_corescripts_mqtt",
  "params": {
    "k": "mykey",
    "q": 2,
    "t": "some/test/topic"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:173 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '173', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'subscribe_corescripts_mqtt', 'params': {'k': 'mykey', 'q': 2, 't': 'some/test/topic'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • t MQTT topic (“+” and “#” masks are supported)
  • q MQTT topic QoS
  • save save core script config after modification
unsubscribe_corescripts_mqtt - Unsubscribe core scripts from MQTT topic

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 159
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "unsubscribe_corescripts_mqtt",
    "params": {
        "k": "mykey",
        "t": "some/test/topic"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 159' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "unsubscribe_corescripts_mqtt", "params": {"k": "mykey", "t": "some/test/topic"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 159' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "unsubscribe_corescripts_mqtt", "params": {"k": "mykey", "t": "some/test/topic"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "unsubscribe_corescripts_mqtt",
  "params": {
    "k": "mykey",
    "t": "some/test/topic"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:159 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '159', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'unsubscribe_corescripts_mqtt', 'params': {'k': 'mykey', 't': 'some/test/topic'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • t MQTT topic (“+” and “#” masks are allowed)
  • save save core script config after modification

UC API

Universal Controller API is used to control and manage units and sensors

This document describes API methods for direct and JSON RPC calls. For RESTful API look UC RESTful API.

API basics

JSON RPC

JSON RPC 2.0 protocol is the primary EVA ICS API protocol. Note that default JSON RPC result is { “ok”: true } (instead of { “result”: “OK” } in the direct API). There’s no { result: “ERROR” } responses, as JSON RPC sends errors in “error” field.

If JSON RPC request is called without ID and server should not return a result, it will return http response with a code 202 Accepted.

Note

JSON RPC is recommended way to use EVA ICS API, unless direct method calling or RESTful is really required.

JSON RPC API URL:

http://<ip_address:8812>/jrpc

or

http://<ip_address:8812>

(all POST requests to the root URI are processed as JSON RPC)

JSON RPC payload encoding

EVA ICS supports JSON RPC payloads, encoded as generic JSON and as MessagePack. MessagePack encoding works faster, requires less bandwidth and is highly recommended to use.

To call API methods with MessagePack-encoded payloads, use Content-Type: application/msgpack HTTP request header.

JSON RPC error responses

JSON RPC calls return error codes equal to the codes of EVA API Client:

  • 1 the item or resource is not found
  • 2 access is denied with the set API key
  • 6 Attempt to call undefined API method/function
  • 10 API function failed (all errors not listed here fall within this category)
  • 11 API function is called with invalid params
  • 12 API function attempted to create resource which already exists and can’t be recreated until deleted/removed
  • 13 the resource is busy (in use) and can not be accessed/recreated or deleted at this moment
  • 14 the method is not implemented in/for requested resource

Response field “message” may contain additional information about error.

Warning

It’s highly not recommended to perform long API calls, calling API functions from JavaScript in a web browser (e.g. giving “w” param to action methods to wait until action finish). Web browser may repeat API call continuously, which may lead to absolutely unexpected behavior.

JSON RPC via HTTP GET

Embedded equipment sometimes can send HTTP GET requests only. JSON RPC API supports such calls as well.

To make JSON RPC API request with HTTP get, send it to:

http://<ip_address:8812>/jrpc?i=ID&m=METHOD&p=PARAMS

where:

  • ID request ID (any custom value). If not specified, API response isn’t sent back
  • METHOD JSON RPC method to call
  • PARAMS method params, as url-encoded JSON

E.g. the following HTTP GET request will invoke method “test” with request id=1 and params { “k”: “mykey” }:

http://<ip_address:8812>/jrpc?i=1&m=test&p=%7B%22k%22%3A%22mykey%22%7D

Note

JSON RPC API calls via HTTP GET are insecure, limited to 2048 bytes and can not be batch. Use JSON RPC via HTTP POST with JSON or MessagePack payload always when possible.

Direct API

Warning

Direct method calling is deprecated and scheduled to be removed (not implemented) in EVA ICS v4. Use JSON RPC API, whenever it is possible.

UC API functions are called through URL request

http://<ip_address:8812>/uc-api/function

If SSL is allowed in the controller configuration file, you can also use https calls.

Direct API responses

Good for backward compatibility with any devices, as all API functions can be called using GET and POST. When POST is used, the parameters can be passed to functions either as multipart/form-data or as JSON.

API key can be sent in request parameters, session (if enabled and user is logged in) or in HTTP X-Auth-Key header.

Standard responses in status/body:

  • 200 OK { “result”: “OK” } API call completed successfully.

Standard error responses in status:

  • 400 Bad Request Invalid request params
  • 403 Forbidden the API key has no access to this function or resource
  • 404 Not Found method or resource/object doesn’t exist
  • 405 Method Not Allowed API function/method not found or HTTP method is not either GET or POST
  • 409 Conflict resource/object already exists or is locked
  • 500 API Error API function execution has been failed. Check input parameters and server logs.

In case API function has been failed, response body will contain JSON data with _error field, which contains error message.

{
    "_error": "unable to add object, already present",
    "result": "ERROR"
}

Contents

Item functions

action - unit control action

The call is considered successful when action is put into the action queue of selected unit.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 154
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "action",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey",
        "s": 1
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 154' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "action", "params": {"i": "unit:tests/unit1", "k": "mykey", "s": 1}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 154' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "action", "params": {"i": "unit:tests/unit1", "k": "mykey", "s": 1}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "action",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey",
    "s": 1
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:154 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '154', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'action', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey', 's': 1}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 623
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "err": "",
        "exitcode": null,
        "finished": true,
        "finished_in": 0.002784,
        "item_group": "tests",
        "item_id": "unit1",
        "item_oid": "unit:tests/unit1",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "refused",
        "time": {
            "created": 1604183929.5239828,
            "pending": 1604183929.5248153,
            "refused": 1604183929.5267668
        },
        "uuid": "f18e9f9d-2c37-427a-b54f-aa95125c417c"
    }
}

Parameters:

  • k valid API key
  • i unit id

Optionally:

  • s desired unit status
  • v desired unit value
  • w wait for the completion for the specified number of seconds
  • u action UUID (will be auto generated if none specified)
  • p queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”

Returns:

Serialized action object. If action is marked as dead, an error is returned (exception raised)

action_toggle - toggle unit status

Create unit control action to toggle its status (1->0, 0->1)

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 145
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "action_toggle",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 145' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "action_toggle", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 145' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "action_toggle", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "action_toggle",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:145 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '145', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'action_toggle', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 622
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "err": "",
        "exitcode": null,
        "finished": true,
        "finished_in": 0.0027514,
        "item_group": "tests",
        "item_id": "unit1",
        "item_oid": "unit:tests/unit1",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "refused",
        "time": {
            "created": 1604183929.566067,
            "pending": 1604183929.566936,
            "refused": 1604183929.5688183
        },
        "uuid": "891646ec-69f7-4946-940b-18af3fe8c997"
    }
}

Parameters:

  • k valid API key
  • i unit id

Optionally:

  • w wait for the completion for the specified number of seconds
  • u action UUID (will be auto generated if none specified)
  • p queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”

Returns:

Serialized action object. If action is marked as dead, an error is returned (exception raised)

disable_actions - disable unit actions

Disables unit to run and queue new actions.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 147
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "disable_actions",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 147' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "disable_actions", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 147' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "disable_actions", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "disable_actions",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:147 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '147', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'disable_actions', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i unit id
enable_actions - enable unit actions

Enables unit to run and queue new actions.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 146
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "enable_actions",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 146' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "enable_actions", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 146' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "enable_actions", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "enable_actions",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:146 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '146', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'enable_actions', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i unit id
groups - get item group list

Get the list of item groups. Useful e.g. for custom interfaces.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 126
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "groups",
    "params": {
        "k": "mykey",
        "p": "unit"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 126' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "groups", "params": {"k": "mykey", "p": "unit"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 126' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "groups", "params": {"k": "mykey", "p": "unit"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "groups",
  "params": {
    "k": "mykey",
    "p": "unit"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:126 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '126', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'groups', 'params': {'k': 'mykey', 'p': 'unit'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 76
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        "tests"
    ]
}

Parameters:

  • k valid API key
  • p item type (unit [U] or sensor [S])
kill - kill unit actions

Apart from canceling all queued commands, this function also terminates the current running action.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "kill",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "kill", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "kill", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "kill",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'kill', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i unit id

Returns:

If the current action of the unit cannot be terminated by configuration, the notice “pt” = “denied” will be returned additionally (even if there’s no action running)

q_clean - clean action queue of unit

Cancels all queued actions, keeps the current action running.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 139
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "q_clean",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 139' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "q_clean", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 139' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "q_clean", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "q_clean",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:139 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '139', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'q_clean', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i unit id
result - get action status

Checks the result of the action by its UUID or returns the actions for the specified unit.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 105
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "result",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 105' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "result", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 105' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "result", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "result",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:105 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '105', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'result', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 1379
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "err": "",
            "exitcode": null,
            "finished": true,
            "finished_in": 0.0049543,
            "item_group": "tests",
            "item_id": "unit1",
            "item_oid": "unit:tests/unit1",
            "item_type": "unit",
            "nstatus": 1,
            "nvalue": null,
            "out": "",
            "priority": 100,
            "status": "refused",
            "time": {
                "created": 1604184438.5920656,
                "pending": 1604184438.5939715,
                "refused": 1604184438.59702
            },
            "uuid": "c02301d3-d780-4b2e-8e06-364ecd77ad92"
        },
        {
            "err": "",
            "exitcode": null,
            "finished": true,
            "finished_in": 0.0035744,
            "item_group": "tests",
            "item_id": "unit1",
            "item_oid": "unit:tests/unit1",
            "item_type": "unit",
            "nstatus": 1,
            "nvalue": null,
            "out": "",
            "priority": 100,
            "status": "refused",
            "time": {
                "created": 1604184438.6366618,
                "pending": 1604184438.6380665,
                "refused": 1604184438.6402361
            },
            "uuid": "49870d59-955a-42d8-96a1-7ca803146f0c"
        }
    ]
}

Parameters:

  • k valid API key

Optionally:

  • u action uuid or
  • i unit id
  • g filter by unit group
  • s filter by action status: Q for queued, R for running, F for finished

Returns:

list or single serialized action object

start_item_maintenance - start item maintenance mode

During maintenance mode all item updates are ignored, however actions still can be executed

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 158
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "start_item_maintenance",
    "params": {
        "i": "sensor:tests/sensor1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 158' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "start_item_maintenance", "params": {"i": "sensor:tests/sensor1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 158' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "start_item_maintenance", "params": {"i": "sensor:tests/sensor1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "start_item_maintenance",
  "params": {
    "i": "sensor:tests/sensor1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:158 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '158', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'start_item_maintenance', 'params': {'i': 'sensor:tests/sensor1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k masterkey
  • i item ID
state - get item state

State of the item or all items of the specified type can be obtained using state command.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 127
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "state",
    "params": {
        "k": "mykey",
        "p": "sensor"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 127' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "state", "params": {"k": "mykey", "p": "sensor"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 127' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "state", "params": {"k": "mykey", "p": "sensor"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "state",
  "params": {
    "k": "mykey",
    "p": "sensor"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:127 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '127', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'state', 'params': {'k': 'mykey', 'p': 'sensor'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 1568
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "full_id": "clone_of_tests/sensor1",
            "group": "clone_of_tests",
            "id": "sensor1",
            "oid": "sensor:clone_of_tests/sensor1",
            "status": 0,
            "type": "sensor",
            "value": ""
        },
        {
            "full_id": "clone_of_tests/sensor5",
            "group": "clone_of_tests",
            "id": "sensor5",
            "oid": "sensor:clone_of_tests/sensor5",
            "status": 0,
            "type": "sensor",
            "value": ""
        },
        {
            "full_id": "clone_of_tests/t5",
            "group": "clone_of_tests",
            "id": "t5",
            "oid": "sensor:clone_of_tests/t5",
            "status": 0,
            "type": "sensor",
            "value": ""
        },
        {
            "full_id": "tests/sensor1",
            "group": "tests",
            "id": "sensor1",
            "oid": "sensor:tests/sensor1",
            "status": 1,
            "type": "sensor",
            "value": "29.445"
        },
        {
            "full_id": "tests/sensor5",
            "group": "tests",
            "id": "sensor5",
            "oid": "sensor:tests/sensor5",
            "status": 0,
            "type": "sensor",
            "value": ""
        },
        {
            "full_id": "tests/t5",
            "group": "tests",
            "id": "t5",
            "oid": "sensor:tests/t5",
            "status": 0,
            "type": "sensor",
            "value": ""
        }
    ]
}

Parameters:

  • k valid API key
  • p item type (unit [U] or sensor [S])

Optionally:

  • i item id
  • g item group
  • full return full state
state_history - get item state history

State history of one item or several items of the specified type can be obtained using state_history command.

If master key is used, the method attempts to get stored state for an item even if it doesn’t present currently in system.

The method can return state log for disconnected items as well.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 149
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "state_history",
    "params": {
        "i": "sensor:tests/sensor1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 149' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "state_history", "params": {"i": "sensor:tests/sensor1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 149' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "state_history", "params": {"i": "sensor:tests/sensor1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "state_history",
  "params": {
    "i": "sensor:tests/sensor1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:149 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '149', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'state_history', 'params': {'i': 'sensor:tests/sensor1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 344
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "status": [
            1,
            1,
            1
        ],
        "t": [
            1604184434.4534957,
            1604184435.6571898,
            1604184439.1233687
        ],
        "value": [
            29.445,
            29.445,
            29.445
        ]
    }
}

Parameters:

  • k valid API key
  • a history notifier id (default: db_1)
  • i item oids or full ids, list or comma separated

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • l records limit (doesn’t work with “w”)
  • x state prop (“status” or “value”)
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • z Time zone (pytz, e.g. UTC or Europe/Prague)
  • w fill frame with the interval (e.g. “1T” - 1 min, “2H” - 2 hours etc.), start time is required, set to 1D if not specified
  • g output format (“list”, “dict” or “chart”, default is “list”)
  • c options for chart (dict or comma separated)
  • o extra options for notifier data request

Returns:

history data in specified format or chart image.

For chart, JSON RPC gets reply with “content_type” and “data” fields, where content is image content type. If PNG image format is selected, data is base64-encoded.

Options for chart (all are optional):

If option “w” (fill) is used, number of digits after comma may be specified. E.g. 5T:3 will output values with 3 digits after comma.

Additionally, SI prefix may be specified to convert value to kilos, megas etc, e.g. 5T:k:3 - divide value by 1000 and output 3 digits after comma. Valid prefixes are: k, M, G, T, P, E, Z, Y.

If binary prefix is required, it should be followed by “b”, e.g. 5T:Mb:3 - divide value by 2^20 and output 3 digits after comma.

state_log - get item state log

State log of a single item or group of the specified type can be obtained using state_log command.

note: only SQL notifiers are supported

Difference from state_history method:

  • state_log doesn’t optimize data to be displayed on charts * the data is returned from a database as-is * a single item OID or OID mask (e.g. sensor:env/#) can be specified

note: the method supports MQTT-style masks but only masks with wildcard-ending, like “type:group/subgroup/#” are supported.

The method can return state log for disconnected items as well.

For wildcard fetching, API key should have an access to the whole chosen group.

note: record limit means the limit for records, fetched from the database, but repeating state records are automatically grouped and the actual number of returned records can be lower than requested.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 143
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "state_log",
    "params": {
        "i": "sensor:tests/test1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 143' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "state_log", "params": {"i": "sensor:tests/test1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 143' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "state_log", "params": {"i": "sensor:tests/test1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "state_log",
  "params": {
    "i": "sensor:tests/test1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:143 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '143', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'state_log', 'params': {'i': 'sensor:tests/test1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 812
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "oid": "sensor:tests/test1",
            "status": 1,
            "t": 1607295099.9760036,
            "value": null
        },
        {
            "oid": "sensor:tests/test1",
            "status": 1,
            "t": 1607295103.9991317,
            "value": 25.0
        },
        {
            "oid": "sensor:tests/test1",
            "status": 1,
            "t": 1607295107.0097003,
            "value": 258.0
        },
        {
            "oid": "sensor:tests/test1",
            "status": 1,
            "t": 1607295110.0616019,
            "value": 359.0
        },
        {
            "oid": "sensor:tests/test1",
            "status": 1,
            "t": 1607295713.5383759,
            "value": 772.0
        }
    ]
}

Parameters:

  • k valid API key
  • a history notifier id (default: db_1)
  • i item oid or oid mask (type:group/subgroup/#)

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • l records limit (doesn’t work with “w”)
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • z Time zone (pytz, e.g. UTC or Europe/Prague)
  • o extra options for notifier data request

Returns:

state log records (list)

stop_item_maintenance - stop item maintenance mode

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 157
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "stop_item_maintenance",
    "params": {
        "i": "sensor:tests/sensor1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 157' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "stop_item_maintenance", "params": {"i": "sensor:tests/sensor1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 157' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "stop_item_maintenance", "params": {"i": "sensor:tests/sensor1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "stop_item_maintenance",
  "params": {
    "i": "sensor:tests/sensor1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:157 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '157', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'stop_item_maintenance', 'params': {'i': 'sensor:tests/sensor1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k masterkey
  • i item ID
terminate - terminate action execution

Terminates or cancel the action if it is still queued

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 141
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "terminate",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 141' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "terminate", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 141' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "terminate", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "terminate",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:141 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '141', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'terminate', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • u action uuid or
  • i unit id

Returns:

An error result will be returned eitner if action is terminated (Resource not found) or if termination process is failed or denied by unit configuration (Function failed)

update - update the status and value of the item

Updates the status and value of the item. This is one of the ways of passive state update, for example with the use of an external controller.

Note

Calling without s and v params will force item to perform passive update requesting its status from update script or driver.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 179
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "update",
    "params": {
        "i": "sensor:tests/sensor1",
        "k": "mykey",
        "s": 1,
        "v": 29.445
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 179' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "update", "params": {"i": "sensor:tests/sensor1", "k": "mykey", "s": 1, "v": 29.445}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 179' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "update", "params": {"i": "sensor:tests/sensor1", "k": "mykey", "s": 1, "v": 29.445}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "update",
  "params": {
    "i": "sensor:tests/sensor1",
    "k": "mykey",
    "s": 1,
    "v": 29.445
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:179 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '179', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'update', 'params': {'i': 'sensor:tests/sensor1', 'k': 'mykey', 's': 1, 'v': 29.445}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i item id

Optionally:

  • s item status
  • v item value

Item management

list - list items

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 103
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 103' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 103' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:103 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '103', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 2611
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "description": "",
            "full_id": "tests/mu1",
            "group": "tests",
            "id": "mu1",
            "oid": "mu:tests/mu1",
            "type": "mu"
        },
        {
            "description": "",
            "full_id": "clone_of_tests/sensor1",
            "group": "clone_of_tests",
            "id": "sensor1",
            "oid": "sensor:clone_of_tests/sensor1",
            "type": "sensor"
        },
        {
            "description": "",
            "full_id": "clone_of_tests/sensor5",
            "group": "clone_of_tests",
            "id": "sensor5",
            "oid": "sensor:clone_of_tests/sensor5",
            "type": "sensor"
        },
        {
            "description": "",
            "full_id": "clone_of_tests/t5",
            "group": "clone_of_tests",
            "id": "t5",
            "oid": "sensor:clone_of_tests/t5",
            "type": "sensor"
        },
        {
            "description": "",
            "full_id": "tests/sensor1",
            "group": "tests",
            "id": "sensor1",
            "oid": "sensor:tests/sensor1",
            "type": "sensor"
        },
        {
            "description": "",
            "full_id": "tests/sensor5",
            "group": "tests",
            "id": "sensor5",
            "oid": "sensor:tests/sensor5",
            "type": "sensor"
        },
        {
            "description": "",
            "full_id": "tests/t5",
            "group": "tests",
            "id": "t5",
            "oid": "sensor:tests/t5",
            "type": "sensor"
        },
        {
            "description": "",
            "full_id": "clone_of_tests/clone_of_unit1",
            "group": "clone_of_tests",
            "id": "clone_of_unit1",
            "oid": "unit:clone_of_tests/clone_of_unit1",
            "type": "unit"
        },
        {
            "description": "",
            "full_id": "clone_of_tests/unit1",
            "group": "clone_of_tests",
            "id": "unit1",
            "oid": "unit:clone_of_tests/unit1",
            "type": "unit"
        },
        {
            "description": "",
            "full_id": "tests/clone_of_unit1",
            "group": "tests",
            "id": "clone_of_unit1",
            "oid": "unit:tests/clone_of_unit1",
            "type": "unit"
        },
        {
            "description": "",
            "full_id": "tests/unit1",
            "group": "tests",
            "id": "unit1",
            "oid": "unit:tests/unit1",
            "type": "unit"
        }
    ]
}

Parameters:

  • k API key with master permissions

Optionally:

  • p filter by item type
  • g filter by item group
  • x serialize specified item prop(s)

Returns:

the list of all item available

create - create new item

Creates new item.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 166
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create",
    "params": {
        "i": "sensor:tests/sensor1",
        "k": "mykey",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 166' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create", "params": {"i": "sensor:tests/sensor1", "k": "mykey", "save": "true"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 166' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create", "params": {"i": "sensor:tests/sensor1", "k": "mykey", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create",
  "params": {
    "i": "sensor:tests/sensor1",
    "k": "mykey",
    "save": "true"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:166 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '166', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create', 'params': {'i': 'sensor:tests/sensor1', 'k': 'mykey', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 253
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "full_id": "tests/sensor1",
        "group": "tests",
        "id": "sensor1",
        "oid": "sensor:tests/sensor1",
        "status": 0,
        "type": "sensor",
        "value": ""
    }
}

Parameters:

  • k API key with master permissions
  • i item oid (type:group/id)

Optionally:

  • g item group
  • e enabled actions/updates
  • save save multi-update configuration immediately
create_mu - create multi-update

Creates new multi-update.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 161
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create_mu",
    "params": {
        "i": "mu:tests/mu1",
        "k": "mykey",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 161' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create_mu", "params": {"i": "mu:tests/mu1", "k": "mykey", "save": "true"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 161' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create_mu", "params": {"i": "mu:tests/mu1", "k": "mykey", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create_mu",
  "params": {
    "i": "mu:tests/mu1",
    "k": "mykey",
    "save": "true"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:161 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '161', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create_mu', 'params': {'i': 'mu:tests/mu1', 'k': 'mykey', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 233
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "full_id": "tests/mu1",
        "group": "tests",
        "id": "mu1",
        "oid": "mu:tests/mu1",
        "status": 0,
        "type": "mu",
        "value": ""
    }
}

Parameters:

  • k API key with master permissions
  • i multi-update id

Optionally:

  • g multi-update group
  • save save multi-update configuration immediately
create_sensor - create new sensor

Creates new sensor.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 166
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create_sensor",
    "params": {
        "i": "tests/sensor5",
        "k": "mykey",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 166' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create_sensor", "params": {"i": "tests/sensor5", "k": "mykey", "save": "true"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 166' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create_sensor", "params": {"i": "tests/sensor5", "k": "mykey", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create_sensor",
  "params": {
    "i": "tests/sensor5",
    "k": "mykey",
    "save": "true"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:166 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '166', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create_sensor', 'params': {'i': 'tests/sensor5', 'k': 'mykey', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 253
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "full_id": "tests/sensor5",
        "group": "tests",
        "id": "sensor5",
        "oid": "sensor:tests/sensor5",
        "status": 0,
        "type": "sensor",
        "value": ""
    }
}

Parameters:

  • k API key with master permissions
  • i sensor id

Optionally:

  • g sensor group
  • e enabled updates
  • save save sensor configuration immediately
create_unit - create new unit

Creates new unit.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 162
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create_unit",
    "params": {
        "i": "tests/unit1",
        "k": "mykey",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 162' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create_unit", "params": {"i": "tests/unit1", "k": "mykey", "save": "true"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 162' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create_unit", "params": {"i": "tests/unit1", "k": "mykey", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create_unit",
  "params": {
    "i": "tests/unit1",
    "k": "mykey",
    "save": "true"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:162 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '162', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create_unit', 'params': {'i': 'tests/unit1', 'k': 'mykey', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 320
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "action_enabled": false,
        "full_id": "tests/unit1",
        "group": "tests",
        "id": "unit1",
        "nstatus": 0,
        "nvalue": "",
        "oid": "unit:tests/unit1",
        "status": 0,
        "type": "unit",
        "value": ""
    }
}

Parameters:

  • k API key with master permissions
  • i unit id

Optionally:

  • g unit group
  • e enabled actions
  • save save unit configuration immediately
destroy - delete item or group

Deletes the item or the group (and all the items in it) from the system.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 139
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "destroy",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 139' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "destroy", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 139' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "destroy", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "destroy",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:139 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '139', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'destroy', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i item id
  • g group (either item or group must be specified)
get_config - get item configuration

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 142
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_config",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 142' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_config", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 142' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_config", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_config",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:142 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '142', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_config', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 448
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "action_enabled": true,
        "full_id": "tests/unit1",
        "group": "tests",
        "id": "unit1",
        "maintenance_duration": 0,
        "notify_events": 2,
        "oid": "unit:tests/unit1",
        "type": "unit",
        "value_in_range_max": null,
        "value_in_range_max_eq": false,
        "value_in_range_min": null,
        "value_in_range_min_eq": false
    }
}

Parameters:

  • k API key with master permissions
  • i item id

Returns:

complete item configuration

list_props - list item properties

Get all editable parameters of the item confiugration.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 142
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_props",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 142' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_props", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 142' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_props", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_props",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:142 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '142', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_props', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 1158
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "action_allow_termination": false,
        "action_always_exec": false,
        "action_driver_config": null,
        "action_enabled": true,
        "action_exec": null,
        "action_queue": 0,
        "action_timeout": null,
        "auto_off": 0,
        "description": "",
        "expires": 0,
        "location": null,
        "maintenance_duration": 0,
        "modbus_status": null,
        "modbus_value": null,
        "mqtt_control": null,
        "mqtt_update": null,
        "notify_events": 2,
        "snmp_trap": null,
        "status_labels": {
            "0": "OFF",
            "1": "ON"
        },
        "term_kill_interval": null,
        "update_driver_config": null,
        "update_exec": null,
        "update_exec_after_action": false,
        "update_if_action": false,
        "update_interval": 0,
        "update_state_after_action": true,
        "update_timeout": null,
        "value_condition": "",
        "value_in_range_max": null,
        "value_in_range_max_eq": false,
        "value_in_range_min": null,
        "value_in_range_min_eq": false
    }
}

Parameters:

  • k API key with master permissions
  • i item id
save_config - save item configuration

Saves item. configuration on disk (even if it hasn’t been changed)

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 143
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "save_config",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 143' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "save_config", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 143' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "save_config", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "save_config",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:143 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '143', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'save_config', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i item id
set_prop - set item property

Set configuration parameters of the item.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 202
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_prop",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey",
        "p": "action_allow_termination",
        "v": "true"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 202' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_prop", "params": {"i": "unit:tests/unit1", "k": "mykey", "p": "action_allow_termination", "v": "true"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 202' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_prop", "params": {"i": "unit:tests/unit1", "k": "mykey", "p": "action_allow_termination", "v": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_prop",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey",
    "p": "action_allow_termination",
    "v": "true"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:202 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '202', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_prop', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey', 'p': 'action_allow_termination', 'v': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i item id
  • p property name (or empty for batch set)

Optionally:

  • v propery value (or dict for batch set)
  • save save configuration after successful call
clone - clone item

Creates a copy of the item.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 179
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "clone",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey",
        "n": "unit:tests/clone_of_unit1"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 179' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "clone", "params": {"i": "unit:tests/unit1", "k": "mykey", "n": "unit:tests/clone_of_unit1"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 179' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "clone", "params": {"i": "unit:tests/unit1", "k": "mykey", "n": "unit:tests/clone_of_unit1"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "clone",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey",
    "n": "unit:tests/clone_of_unit1"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:179 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '179', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'clone', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey', 'n': 'unit:tests/clone_of_unit1'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 346
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "action_enabled": true,
        "full_id": "tests/clone_of_unit1",
        "group": "tests",
        "id": "clone_of_unit1",
        "nstatus": 0,
        "nvalue": "",
        "oid": "unit:tests/clone_of_unit1",
        "status": 0,
        "type": "unit",
        "value": ""
    }
}

Parameters:

  • k API key with master permissions
  • i item id
  • n new item id

Optionally:

  • g group for new item
  • save save multi-update configuration immediately
clone_group - clone group

Creates a copy of all items from the group.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 163
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "clone_group",
    "params": {
        "g": "tests",
        "k": "mykey",
        "n": "clone_of_tests"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 163' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "clone_group", "params": {"g": "tests", "k": "mykey", "n": "clone_of_tests"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 163' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "clone_group", "params": {"g": "tests", "k": "mykey", "n": "clone_of_tests"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "clone_group",
  "params": {
    "g": "tests",
    "k": "mykey",
    "n": "clone_of_tests"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:163 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '163', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'clone_group', 'params': {'g': 'tests', 'k': 'mykey', 'n': 'clone_of_tests'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • g group to clone
  • n new group to clone to

Optionally:

  • p item ID prefix, e.g. device1. for device1.temp1, device1.fan1
  • r iem ID prefix in the new group, e.g. device2 (both prefixes must be specified)
  • save save configuration immediately

1-Wire bus via OWFS

create_owfs_bus - create OWFS bus

Creates (defines) OWFS bus with the specified configuration.

Parameter “location” (“n”) should contain the connection configuration, e.g. “localhost:4304” for owhttpd or “i2c=/dev/i2c-1:ALL”, “/dev/i2c-0 –w1” for local 1-Wire bus via I2C, depending on type.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 266
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create_owfs_bus",
    "params": {
        "d": 0.3,
        "i": "bus_local",
        "k": "mykey",
        "l": "true",
        "n": "localhost:4304",
        "r": 5,
        "save": "true",
        "t": 1
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 266' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create_owfs_bus", "params": {"d": 0.3, "i": "bus_local", "k": "mykey", "l": "true", "n": "localhost:4304", "r": 5, "save": "true", "t": 1}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 266' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create_owfs_bus", "params": {"d": 0.3, "i": "bus_local", "k": "mykey", "l": "true", "n": "localhost:4304", "r": 5, "save": "true", "t": 1}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create_owfs_bus",
  "params": {
    "d": 0.3,
    "i": "bus_local",
    "k": "mykey",
    "l": "true",
    "n": "localhost:4304",
    "r": 5,
    "save": "true",
    "t": 1
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:266 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '266', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create_owfs_bus', 'params': {'d': 0.3, 'i': 'bus_local', 'k': 'mykey', 'l': 'true', 'n': 'localhost:4304', 'r': 5, 'save': 'true', 't': 1}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i bus ID which will be used later in PHI configurations, required
  • n OWFS location

Optionally:

  • l lock port on operations, which means to wait while OWFS bus is used by other controller thread (driver command)
  • t OWFS operations timeout (in seconds, default: default timeout)
  • r retry attempts for each operation (default: no retries)
  • d delay between bus operations (default: 50ms)
  • save save OWFS bus config after creation

Returns:

If bus with the selected ID is already defined, error is not returned and bus is recreated.

destroy_owfs_bus - delete OWFS bus

Deletes (undefines) OWFS bus.

Note

In some cases deleted OWFS bus located on I2C may lock libow library calls, which require controller restart until you can use (create) the same I2C bus again.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 141
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "destroy_owfs_bus",
    "params": {
        "i": "bus_local",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 141' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "destroy_owfs_bus", "params": {"i": "bus_local", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 141' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "destroy_owfs_bus", "params": {"i": "bus_local", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "destroy_owfs_bus",
  "params": {
    "i": "bus_local",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:141 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '141', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'destroy_owfs_bus', 'params': {'i': 'bus_local', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i bus ID
get_owfs_bus - get OWFS bus configuration

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 137
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_owfs_bus",
    "params": {
        "i": "bus_local",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 137' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_owfs_bus", "params": {"i": "bus_local", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 137' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_owfs_bus", "params": {"i": "bus_local", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_owfs_bus",
  "params": {
    "i": "bus_local",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:137 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '137', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_owfs_bus', 'params': {'i': 'bus_local', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 214
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "delay": 0.3,
        "id": "bus_local",
        "location": "localhost:4304",
        "lock": true,
        "retries": 5,
        "timeout": 1.0
    }
}

Parameters:

  • k API key with master permissions
  • i bus ID
list_owfs_buses - list OWFS buses

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 114
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_owfs_buses",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 114' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_owfs_buses", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 114' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_owfs_buses", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_owfs_buses",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:114 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '114', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_owfs_buses', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 258
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "delay": 0.3,
            "id": "bus_local",
            "location": "localhost:4304",
            "lock": true,
            "retries": 5,
            "timeout": 1.0
        }
    ]
}

Parameters:

  • k API key with master permissions
scan_owfs_bus - scan OWFS bus

Scan OWFS bus for connected 1-Wire devices.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 138
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "scan_owfs_bus",
    "params": {
        "i": "bus_local",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 138' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "scan_owfs_bus", "params": {"i": "bus_local", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 138' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "scan_owfs_bus", "params": {"i": "bus_local", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "scan_owfs_bus",
  "params": {
    "i": "bus_local",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:138 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '138', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'scan_owfs_bus', 'params': {'i': 'bus_local', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 238
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "path": "10.67C6697351FF",
            "type": "DS18S20"
        },
        {
            "path": "05.4AEC29CDBAAB",
            "type": "DS2405"
        }
    ]
}

Parameters:

  • k API key with master permissions
  • i bus ID

Optionally:

  • p specified equipment type (e.g. DS18S20,DS2405), list or comma separated
  • a Equipment attributes (e.g. temperature, PIO), list comma separated
  • n Equipment path
  • has_all Equipment should have all specified attributes
  • full obtain all attributes plus values

Returns:

If both “a” and “full” args are specified. the function will examine and values of attributes specified in “a” param. (This will poll “released” bus, even if locking is set up, so be careful with this feature in production environment).

Bus acquire error can be caused in 2 cases:

  • bus is locked * owfs resource not initialized (libow or location problem)
test_owfs_bus - test OWFS bus

Verifies OWFS bus checking library initialization status.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 138
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "test_owfs_bus",
    "params": {
        "i": "bus_local",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 138' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "test_owfs_bus", "params": {"i": "bus_local", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 138' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "test_owfs_bus", "params": {"i": "bus_local", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "test_owfs_bus",
  "params": {
    "i": "bus_local",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:138 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '138', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'test_owfs_bus', 'params': {'i': 'bus_local', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i bus ID

Modbus ports

create_modbus_port - create virtual Modbus port

Creates virtual Modbus port with the specified configuration.

Modbus params should contain the configuration of hardware Modbus port. The following hardware port types are supported:

  • tcp , udp Modbus protocol implementations for TCP/IP networks. The params should be specified as: <protocol>:<host>[:port], e.g. tcp:192.168.11.11:502
  • rtu, ascii, binary Modbus protocol implementations for the local bus connected with USB or serial port. The params should be specified as: <protocol>:<device>:<speed>:<data>:<parity>:<stop> e.g. rtu:/dev/ttyS0:9600:8:E:1

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 273
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create_modbus_port",
    "params": {
        "d": 0.2,
        "i": "mbp1",
        "k": "mykey",
        "l": "true",
        "p": "udp:192.168.33.33:502",
        "r": 3,
        "save": "true",
        "t": 0.5
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 273' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create_modbus_port", "params": {"d": 0.2, "i": "mbp1", "k": "mykey", "l": "true", "p": "udp:192.168.33.33:502", "r": 3, "save": "true", "t": 0.5}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 273' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create_modbus_port", "params": {"d": 0.2, "i": "mbp1", "k": "mykey", "l": "true", "p": "udp:192.168.33.33:502", "r": 3, "save": "true", "t": 0.5}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create_modbus_port",
  "params": {
    "d": 0.2,
    "i": "mbp1",
    "k": "mykey",
    "l": "true",
    "p": "udp:192.168.33.33:502",
    "r": 3,
    "save": "true",
    "t": 0.5
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:273 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '273', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create_modbus_port', 'params': {'d': 0.2, 'i': 'mbp1', 'k': 'mykey', 'l': 'true', 'p': 'udp:192.168.33.33:502', 'r': 3, 'save': 'true', 't': 0.5}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i virtual port ID which will be used later in PHI configurations, required
  • p Modbus params

Optionally:

  • l lock port on operations, which means to wait while Modbus port is used by other controller thread (driver command)
  • t Modbus operations timeout (in seconds, default: default timeout)
  • r retry attempts for each operation (default: no retries)
  • d delay between virtual port operations (default: 20ms)
  • save save Modbus port config after creation

Returns:

If port with the selected ID is already created, error is not returned and port is recreated.

destroy_modbus_port - delete virtual Modbus port

Deletes virtual Modbus port.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 139
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "destroy_modbus_port",
    "params": {
        "i": "mbp1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 139' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "destroy_modbus_port", "params": {"i": "mbp1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 139' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "destroy_modbus_port", "params": {"i": "mbp1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "destroy_modbus_port",
  "params": {
    "i": "mbp1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:139 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '139', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'destroy_modbus_port', 'params': {'i': 'mbp1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i virtual port ID
get_modbus_port - get virtual Modbus port configuration

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 135
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_modbus_port",
    "params": {
        "i": "mbp1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 135' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_modbus_port", "params": {"i": "mbp1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 135' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_modbus_port", "params": {"i": "mbp1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_modbus_port",
  "params": {
    "i": "mbp1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:135 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '135', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_modbus_port', 'params': {'i': 'mbp1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 214
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "delay": 0.2,
        "id": "mbp1",
        "lock": true,
        "params": "udp:192.168.33.33:502",
        "retries": 3,
        "timeout": 0.5
    }
}

Parameters:

  • k API key with master permissions
  • i port ID
list_modbus_ports - list virtual Modbus ports

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 116
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_modbus_ports",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 116' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_modbus_ports", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 116' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_modbus_ports", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_modbus_ports",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:116 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '116', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_modbus_ports', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 457
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "delay": 0.02,
            "id": "local",
            "lock": false,
            "params": "tcp:localhost:5502",
            "retries": 0,
            "timeout": 4.0
        },
        {
            "delay": 0.2,
            "id": "mbp1",
            "lock": true,
            "params": "udp:192.168.33.33:502",
            "retries": 3,
            "timeout": 0.5
        }
    ]
}

Parameters:

  • k API key with master permissions
  • i virtual port ID
read_modbus_port - read Modbus register(s) from remote slave

Modbus registers must be specified as list or comma separated memory addresses predicated with register type (h - holding, i - input, c - coil, d - discrete input).

Address ranges can be specified, e.g. h1000-1010,c10-15 will return values of holding registers from 1000 to 1010 and coil registers from 10 to 15

Float32 numbers are returned as Python-converted floats and may have broken precision. Consider converting back to f32 on the client side.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 181
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "read_modbus_port",
    "params": {
        "i": "h10-12,c5-6",
        "k": "mykey",
        "p": "local",
        "s": 1
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 181' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "read_modbus_port", "params": {"i": "h10-12,c5-6", "k": "mykey", "p": "local", "s": 1}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 181' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "read_modbus_port", "params": {"i": "h10-12,c5-6", "k": "mykey", "p": "local", "s": 1}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "read_modbus_port",
  "params": {
    "i": "h10-12,c5-6",
    "k": "mykey",
    "p": "local",
    "s": 1
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:181 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '181', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'read_modbus_port', 'params': {'i': 'h10-12,c5-6', 'k': 'mykey', 'p': 'local', 's': 1}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 550
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "addr": "c5",
            "type": "coil",
            "value": 0
        },
        {
            "addr": "c6",
            "type": "coil",
            "value": 0
        },
        {
            "addr": "h10",
            "type": "u16",
            "value": 0
        },
        {
            "addr": "h11",
            "type": "u16",
            "value": 0
        },
        {
            "addr": "h12",
            "type": "u16",
            "value": 0
        }
    ]
}

Parameters:

  • k API key with master permissions
  • p Modbus virtual port
  • s Slave ID
  • i Modbus register(s)
  • f data type (u16, i16, u32, i32, u64, i64, f32 or bit)
  • c count, if register range not specified

Optionally:

  • t max allowed timeout for the operation
test_modbus_port - test virtual Modbus port

Verifies virtual Modbus port by calling connect() Modbus client method.

Note

As Modbus UDP doesn’t require a port to be connected, API call always returns success unless the port is locked.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "test_modbus_port",
    "params": {
        "i": "mbp1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "test_modbus_port", "params": {"i": "mbp1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "test_modbus_port", "params": {"i": "mbp1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "test_modbus_port",
  "params": {
    "i": "mbp1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'test_modbus_port', 'params': {'i': 'mbp1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i virtual port ID
write_modbus_port - write Modbus register(s) to remote slave

Modbus registers must be specified as list or comma separated memory addresses predicated with register type (h - holding, c - coil).

To set bit, specify register as hX/Y where X = register number, Y = bit number (supports u16, u32, u64 data types)

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 193
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "write_modbus_port",
    "params": {
        "i": "h10",
        "k": "mykey",
        "p": "local",
        "s": 1,
        "v": 2522
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 193' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "write_modbus_port", "params": {"i": "h10", "k": "mykey", "p": "local", "s": 1, "v": 2522}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 193' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "write_modbus_port", "params": {"i": "h10", "k": "mykey", "p": "local", "s": 1, "v": 2522}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "write_modbus_port",
  "params": {
    "i": "h10",
    "k": "mykey",
    "p": "local",
    "s": 1,
    "v": 2522
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:193 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '193', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'write_modbus_port', 'params': {'i': 'h10', 'k': 'mykey', 'p': 'local', 's': 1, 'v': 2522}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • p Modbus virtual port
  • s Slave ID
  • i Modbus register address
  • v register value(s) (integer or hex or list)
  • z if True, use 0x05-06 commands (write single register/coil)
  • f data type (u16, i16, u32, i32, u64, i64, f32), ignored if z=True

Optionally:

  • t max allowed timeout for the operation
get_modbus_slave_data - get Modbus slave data

Get data from Modbus slave memory space

Modbus registers must be specified as list or comma separated memory addresses predicated with register type (h - holding, i - input, c - coil, d - discrete input).

Address ranges can be specified, e.g. h1000-1010,c10-15 will return values of holding registers from 1000 to 1010 and coil registers from 10 to 15

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 154
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_modbus_slave_data",
    "params": {
        "i": "h1000-1005,c10-15",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 154' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_modbus_slave_data", "params": {"i": "h1000-1005,c10-15", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 154' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_modbus_slave_data", "params": {"i": "h1000-1005,c10-15", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_modbus_slave_data",
  "params": {
    "i": "h1000-1005,c10-15",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:154 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '154', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_modbus_slave_data', 'params': {'i': 'h1000-1005,c10-15', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 923
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "addr": "c10",
            "value": 0
        },
        {
            "addr": "c11",
            "value": 0
        },
        {
            "addr": "c12",
            "value": 0
        },
        {
            "addr": "c13",
            "value": 0
        },
        {
            "addr": "c14",
            "value": 0
        },
        {
            "addr": "c15",
            "value": 0
        },
        {
            "addr": "h1000",
            "value": 0
        },
        {
            "addr": "h1001",
            "value": 0
        },
        {
            "addr": "h1002",
            "value": 0
        },
        {
            "addr": "h1003",
            "value": 0
        },
        {
            "addr": "h1004",
            "value": 0
        },
        {
            "addr": "h1005",
            "value": 0
        }
    ]
}

Parameters:

  • k API key with master permissions
  • i Modbus register(s)

Physical interfaces (PHIs)

exec_phi - execute additional PHI commands

Execute PHI command and return execution result (as-is). help command returns all available commands.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 198
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "exec_phi",
    "params": {
        "a": "/opt/firmware/fw.dat",
        "c": "update_firmware",
        "i": "test1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 198' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "exec_phi", "params": {"a": "/opt/firmware/fw.dat", "c": "update_firmware", "i": "test1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 198' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "exec_phi", "params": {"a": "/opt/firmware/fw.dat", "c": "update_firmware", "i": "test1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "exec_phi",
  "params": {
    "a": "/opt/firmware/fw.dat",
    "c": "update_firmware",
    "i": "test1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:198 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '198', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'exec_phi', 'params': {'a': '/opt/firmware/fw.dat', 'c': 'update_firmware', 'i': 'test1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 96
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "output": "not implemented"
    }
}

Parameters:

  • k API key with master permissions
  • i PHI id
  • c command to exec
  • a command argument
get_phi - get loaded PHI information

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 128
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_phi",
    "params": {
        "i": "test1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 128' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_phi", "params": {"i": "test1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 128' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_phi", "params": {"i": "test1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_phi",
  "params": {
    "i": "test1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:128 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '128', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_phi', 'params': {'i': 'test1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 955
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "api": 9,
        "author": "Altertech Group, https://www.altertech.com/",
        "can_discover": null,
        "can_get_ports": true,
        "cfg": {
            "default_status": 0
        },
        "description": "Emulates 16-port relay",
        "equipment": [
            "virtual"
        ],
        "features": [
            "aao_get",
            "aao_set",
            "push",
            "action",
            "port_get",
            "port_set"
        ],
        "help": "\nSimple 16-port virtual relay, may be used for the various tests/debugging.\n",
        "id": "test1",
        "license": "Apache License 2.0",
        "lpi_default": "basic",
        "mod": "vrtrelay",
        "mods_required": [],
        "oid": "phi:uc/lab-ws2/test1",
        "required": [
            "action",
            "port_get",
            "port_set"
        ],
        "version": "1.4.0"
    }
}

Parameters:

  • k API key with master permissions
  • i PHI ID
get_phi_ports - get list of PHI ports

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 134
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_phi_ports",
    "params": {
        "i": "test1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 134' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_phi_ports", "params": {"i": "test1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 134' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_phi_ports", "params": {"i": "test1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_phi_ports",
  "params": {
    "i": "test1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:134 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '134', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_phi_ports', 'params': {'i': 'test1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 2128
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "description": "virtual relay port #1",
            "name": "port #1",
            "port": "1"
        },
        {
            "description": "virtual relay port #2",
            "name": "port #2",
            "port": "2"
        },
        {
            "description": "virtual relay port #3",
            "name": "port #3",
            "port": "3"
        },
        {
            "description": "virtual relay port #4",
            "name": "port #4",
            "port": "4"
        },
        {
            "description": "virtual relay port #5",
            "name": "port #5",
            "port": "5"
        },
        {
            "description": "virtual relay port #6",
            "name": "port #6",
            "port": "6"
        },
        {
            "description": "virtual relay port #7",
            "name": "port #7",
            "port": "7"
        },
        {
            "description": "virtual relay port #8",
            "name": "port #8",
            "port": "8"
        },
        {
            "description": "virtual relay port #9",
            "name": "port #9",
            "port": "9"
        },
        {
            "description": "virtual relay port #10",
            "name": "port #10",
            "port": "10"
        },
        {
            "description": "virtual relay port #11",
            "name": "port #11",
            "port": "11"
        },
        {
            "description": "virtual relay port #12",
            "name": "port #12",
            "port": "12"
        },
        {
            "description": "virtual relay port #13",
            "name": "port #13",
            "port": "13"
        },
        {
            "description": "virtual relay port #14",
            "name": "port #14",
            "port": "14"
        },
        {
            "description": "virtual relay port #15",
            "name": "port #15",
            "port": "15"
        },
        {
            "description": "virtual relay port #16",
            "name": "port #16",
            "port": "16"
        }
    ]
}

Parameters:

  • k API key with master permissions
  • i PHI id
list_phi - list loaded PHIs

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 107
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_phi",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 107' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_phi", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 107' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_phi", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_phi",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:107 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '107', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_phi', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 137
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "id": "test1",
            "mod": "vrtrelay"
        }
    ]
}

Parameters:

  • k API key with master permissions
  • full get exntended information
list_phi_mods - get list of available PHI modules

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 112
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_phi_mods",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 112' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_phi_mods", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 112' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_phi_mods", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_phi_mods",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:112 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '112', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_phi_mods', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 5587
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "api": 9,
            "author": "Altertech, https://www.altertech.com/",
            "can_discover": null,
            "can_get_ports": true,
            "description": "Ethernet/IP sensors generic",
            "equipment": [
                "Ethernet/IP"
            ],
            "features": [
                "aao_get",
                "port_get",
                "value"
            ],
            "help": "\nEthernet/IP sensors driver\n\nTag list file: text file with one tag per line\n\nIf timeout it specified, it MUST be small enough, otherwise PHI will\nnot even try to connect to En/IP equipment (default is core timeout - 2 sec).\n",
            "id": null,
            "license": "GNU GPL v3",
            "lpi_default": "sensor",
            "mod": "enip_sensor",
            "mods_required": [
                ""
            ],
            "oid": null,
            "required": [
                "port_get",
                "value"
            ],
            "version": "1.0.3"
        },
        {
            "api": 9,
            "author": "Altertech, https://www.altertech.com/",
            "can_discover": null,
            "can_get_ports": true,
            "description": "Ethernet/IP units generic",
            "equipment": [
                "Ethernet/IP"
            ],
            "features": [
                "aao_get",
                "aao_set",
                "action",
                "port_get",
                "port_set"
            ],
            "help": "\nEthernet/IP units driver\n\nTag list file: text file with one tag per line\n\nIn case of problems, it's highly recommended to specify tag variable type, as\nTAG:TYPE. Valid types are:\n\nREAL, SINT, USINT, INT, UINT, DINT, UDINT, BOOL, WORD, DWORD, IPADDR, STRING,\nSSTRING\n\nIf timeout it specified, it MUST be small enough, otherwise PHI will\nnot even try to connect to En/IP equipment (default is core timeout - 2 sec).\n",
            "id": null,
            "license": "GNU GPL v3",
            "lpi_default": "basic",
            "mod": "enip_xvunit",
            "mods_required": [
                ""
            ],
            "oid": null,
            "required": [
                "action",
                "port_get",
                "port_set"
            ],
            "version": "1.0.3"
        },
        {
            "api": 5,
            "author": "Altertech Group, https://www.altertech.com/",
            "can_discover": [
                "net"
            ],
            "can_get_ports": false,
            "description": "Nanoleaf LEDs",
            "equipment": [
                "Nanoleaf LEDs"
            ],
            "features": [
                "action",
                "port_get",
                "port_set",
                "status",
                "value"
            ],
            "help": "\nNanoleaf (https://nanoleaf.me/) LEDs control.\n\nIf token is not specified, Nanoleaf power button must be pressed for 7 seconds\nbefore loading PHI.\n\nIf unit value is specified as RGB hex, PHI sets its color, otherwise chosen\neffect is applied.\n",
            "id": null,
            "license": "Apache License 2.0",
            "lpi_default": "usp",
            "mod": "nanoleaf",
            "mods_required": [],
            "oid": null,
            "required": [
                "action",
                "port_get",
                "port_set",
                "status",
                "value"
            ],
            "version": "1.0.3"
        },
        {
            "api": 9,
            "author": "Altertech Group, https://www.altertech.com/",
            "can_discover": null,
            "can_get_ports": true,
            "description": "Emulates 16-port relay",
            "equipment": [
                "virtual"
            ],
            "features": [
                "aao_get",
                "aao_set",
                "push",
                "action",
                "port_get",
                "port_set"
            ],
            "help": "\nSimple 16-port virtual relay, may be used for the various tests/debugging.\n",
            "id": null,
            "license": "Apache License 2.0",
            "lpi_default": "basic",
            "mod": "vrtrelay",
            "mods_required": [],
            "oid": null,
            "required": [
                "action",
                "port_get",
                "port_set"
            ],
            "version": "1.4.0"
        },
        {
            "api": 9,
            "author": "Altertech Group, https://www.altertech.com/",
            "can_discover": null,
            "can_get_ports": true,
            "description": "Emulates virtual sensors",
            "equipment": [
                "virtual"
            ],
            "features": [
                "aao_get",
                "push",
                "port_get",
                "value"
            ],
            "help": "\nSimple virtual sensor controller, may be used for the various tests/debugging.\nWhen loaded, simulates sensors with ports 1000..1010, which may be extended,\nalso any labels for the sensors (including strings) may be used. Virtual\nsensors can be set to float values only.\n",
            "id": null,
            "license": "Apache License 2.0",
            "lpi_default": "sensor",
            "mod": "vrtsensors",
            "mods_required": [],
            "oid": null,
            "required": [
                "port_get",
                "value"
            ],
            "version": "1.3.0"
        }
    ]
}

Parameters:

  • k API key with master permissions
load_phi - load PHI module

Loads Physical Interface.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 211
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "load_phi",
    "params": {
        "c": "default_status=0",
        "i": "test1",
        "k": "mykey",
        "m": "vrtrelay",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 211' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "load_phi", "params": {"c": "default_status=0", "i": "test1", "k": "mykey", "m": "vrtrelay", "save": "true"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 211' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "load_phi", "params": {"c": "default_status=0", "i": "test1", "k": "mykey", "m": "vrtrelay", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "load_phi",
  "params": {
    "c": "default_status=0",
    "i": "test1",
    "k": "mykey",
    "m": "vrtrelay",
    "save": "true"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:211 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '211', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'load_phi', 'params': {'c': 'default_status=0', 'i': 'test1', 'k': 'mykey', 'm': 'vrtrelay', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 955
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "api": 9,
        "author": "Altertech Group, https://www.altertech.com/",
        "can_discover": null,
        "can_get_ports": true,
        "cfg": {
            "default_status": 0
        },
        "description": "Emulates 16-port relay",
        "equipment": [
            "virtual"
        ],
        "features": [
            "aao_get",
            "aao_set",
            "push",
            "action",
            "port_get",
            "port_set"
        ],
        "help": "\nSimple 16-port virtual relay, may be used for the various tests/debugging.\n",
        "id": "test1",
        "license": "Apache License 2.0",
        "lpi_default": "basic",
        "mod": "vrtrelay",
        "mods_required": [],
        "oid": "phi:uc/lab-ws2/test1",
        "required": [
            "action",
            "port_get",
            "port_set"
        ],
        "version": "1.4.0"
    }
}

Parameters:

  • k API key with master permissions
  • i PHI ID
  • m PHI module

Optionally:

  • c PHI configuration
  • save save driver configuration after successful call
modhelp_phi - get PHI usage help

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 155
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "modhelp_phi",
    "params": {
        "c": "cfg",
        "k": "mykey",
        "m": "vrtrelay"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 155' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "modhelp_phi", "params": {"c": "cfg", "k": "mykey", "m": "vrtrelay"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 155' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "modhelp_phi", "params": {"c": "cfg", "k": "mykey", "m": "vrtrelay"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "modhelp_phi",
  "params": {
    "c": "cfg",
    "k": "mykey",
    "m": "vrtrelay"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:155 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '155', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'modhelp_phi', 'params': {'c': 'cfg', 'k': 'mykey', 'm': 'vrtrelay'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 561
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "help": "ports status on load (default: 0)",
            "name": "default_status",
            "required": false,
            "type": "int"
        },
        {
            "help": "full state (status/value)",
            "name": "state_full",
            "required": false,
            "type": "bool"
        },
        {
            "help": "send updates to items every N sec",
            "name": "update",
            "required": false,
            "type": "float"
        }
    ]
}

Parameters:

  • k API key with master permissions
  • m PHI module name (without .py extension)
  • c help context (cfg, get or set)
modinfo_phi - get PHI module info

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 135
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "modinfo_phi",
    "params": {
        "k": "mykey",
        "m": "vrtrelay"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 135' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "modinfo_phi", "params": {"k": "mykey", "m": "vrtrelay"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 135' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "modinfo_phi", "params": {"k": "mykey", "m": "vrtrelay"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "modinfo_phi",
  "params": {
    "k": "mykey",
    "m": "vrtrelay"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:135 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '135', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'modinfo_phi', 'params': {'k': 'mykey', 'm': 'vrtrelay'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 854
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "api": 9,
        "author": "Altertech Group, https://www.altertech.com/",
        "can_discover": null,
        "can_get_ports": true,
        "description": "Emulates 16-port relay",
        "equipment": [
            "virtual"
        ],
        "features": [
            "aao_get",
            "aao_set",
            "push",
            "action",
            "port_get",
            "port_set"
        ],
        "help": "\nSimple 16-port virtual relay, may be used for the various tests/debugging.\n",
        "license": "Apache License 2.0",
        "lpi_default": "basic",
        "mod": "vrtrelay",
        "mods_required": [],
        "oid": null,
        "required": [
            "action",
            "port_get",
            "port_set"
        ],
        "version": "1.4.0"
    }
}

Parameters:

  • k API key with master permissions
  • m PHI module name (without .py extension)
phi_discover - discover installed equipment supported by PHI module

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "phi_discover",
    "params": {
        "k": "mykey",
        "m": "nanoleaf"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "phi_discover", "params": {"k": "mykey", "m": "nanoleaf"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "phi_discover", "params": {"k": "mykey", "m": "nanoleaf"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "phi_discover",
  "params": {
    "k": "mykey",
    "m": "nanoleaf"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'phi_discover', 'params': {'k': 'mykey', 'm': 'nanoleaf'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 371
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "!opt": "cols",
            "value": [
                "IP",
                "Name"
            ]
        },
        {
            "!load": {
                "host": "10.90.1.81"
            },
            "IP": "10.90.1.81",
            "Name": "Nanoleaf Light Panels 54:e7:31"
        }
    ]
}

Parameters:

  • k API key with master permissions
  • m PHI module name (without .py extension)

Optionally:

  • x interface to perform discover on
  • w max time for the operation
push_phi_state - push state to PHI module

Allows to perform update of PHI ports by external application.

If called as RESTful, the whole request body is used as a payload (except fields “k”, “save”, “kind” and “method”, which are reserved)

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 156
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "push_phi_state",
    "params": {
        "i": "test1",
        "k": "mykey",
        "p": "test"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 156' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "push_phi_state", "params": {"i": "test1", "k": "mykey", "p": "test"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 156' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "push_phi_state", "params": {"i": "test1", "k": "mykey", "p": "test"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "push_phi_state",
  "params": {
    "i": "test1",
    "k": "mykey",
    "p": "test"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:156 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '156', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'push_phi_state', 'params': {'i': 'test1', 'k': 'mykey', 'p': 'test'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k masterkey or a key with the write permission on “phi” group
  • i PHI id
  • p state payload, sent to PHI as-is
put_phi_mod - upload PHI module

Allows to upload new PHI module to xc/drivers/phi folder.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 171
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "put_phi_mod",
    "params": {
        "c": "<MODULE_CONTENT>",
        "k": "mykey",
        "m": "gpio_button"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 171' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "put_phi_mod", "params": {"c": "<MODULE_CONTENT>", "k": "mykey", "m": "gpio_button"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 171' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "put_phi_mod", "params": {"c": "<MODULE_CONTENT>", "k": "mykey", "m": "gpio_button"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "put_phi_mod",
  "params": {
    "c": "<MODULE_CONTENT>",
    "k": "mykey",
    "m": "gpio_button"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:171 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '171', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'put_phi_mod', 'params': {'c': '<MODULE_CONTENT>', 'k': 'mykey', 'm': 'gpio_button'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 902
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
        "result": {
            "api": 1,
            "author": "Altertech Group, https://www.altertech.com/",
            "description": "GPIO buttons",
            "equipment": [
                "GPIO buttons"
            ],
            "features": [
                "events"
            ],
            "help": " Handling pressed events from GPIO buttons.\n\nPHI doesn't provide any control/monitoring functions, each button can be\nconfigured as unit (via basic LPI) or sensor (via sensor) and contain its port\nin update_driver_config, update_interval should be set to 0.\n",
            "license": "Apache License 2.0",
            "lpi_default": "sensor",
            "mod": "gpio_button",
            "mods_required": [
                "gpiozero"
            ],
            "oid": null,
            "required": [],
            "version": "1.0.0"
        }
}

Parameters:

  • k API key with master permissions
  • m PHI module name (without .py extension)
  • c module content

Optionally:

  • force overwrite PHI module file if exists
set_phi_prop - set PHI configuration property

appends property to PHI configuration and reloads module

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 204
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_phi_prop",
    "params": {
        "i": "test1",
        "k": "mykey",
        "p": "default_status",
        "save": "true",
        "v": 1
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 204' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_phi_prop", "params": {"i": "test1", "k": "mykey", "p": "default_status", "save": "true", "v": 1}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 204' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_phi_prop", "params": {"i": "test1", "k": "mykey", "p": "default_status", "save": "true", "v": 1}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_phi_prop",
  "params": {
    "i": "test1",
    "k": "mykey",
    "p": "default_status",
    "save": "true",
    "v": 1
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:204 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '204', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_phi_prop', 'params': {'i': 'test1', 'k': 'mykey', 'p': 'default_status', 'save': 'true', 'v': 1}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i PHI ID
  • p property name (or empty for batch set)

Optionally:

  • v propery value (or dict for batch set)
  • save save configuration after successful call
test_phi - test PHI

Get PHI test result (as-is). All PHIs respond to self command, help command returns all available test commands.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 150
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "test_phi",
    "params": {
        "c": "self",
        "i": "test1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 150' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "test_phi", "params": {"c": "self", "i": "test1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 150' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "test_phi", "params": {"c": "self", "i": "test1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "test_phi",
  "params": {
    "c": "self",
    "i": "test1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:150 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '150', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'test_phi', 'params': {'c': 'self', 'i': 'test1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 83
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "output": "OK"
    }
}

Parameters:

  • k API key with master permissions
  • i PHI id
  • c test command
unload_phi - unload PHI

Unloads PHI. PHI should not be used by any driver (except default, but the driver should not be in use by any item).

If driver <phi_id.default> (which’s loaded automatically with PHI) is present, it will be unloaded as well.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 131
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "unload_phi",
    "params": {
        "i": "test1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 131' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "unload_phi", "params": {"i": "test1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 131' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "unload_phi", "params": {"i": "test1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "unload_phi",
  "params": {
    "i": "test1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:131 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '131', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'unload_phi', 'params': {'i': 'test1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i PHI ID

LPI and drivers

assign_driver - assign driver to item

Sets the specified driver to item, automatically updating item props:

  • action_driver_config,**update_driver_config** to the specified configuration * action_exec, update_exec to do all operations via driver function calls (sets both to |<driver_id>)

To unassign driver, set driver ID to empty/null.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 213
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "assign_driver",
    "params": {
        "c": "port=5,dport=6,steps=1|1|2",
        "d": "test1.my",
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 213' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "assign_driver", "params": {"c": "port=5,dport=6,steps=1|1|2", "d": "test1.my", "i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 213' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "assign_driver", "params": {"c": "port=5,dport=6,steps=1|1|2", "d": "test1.my", "i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "assign_driver",
  "params": {
    "c": "port=5,dport=6,steps=1|1|2",
    "d": "test1.my",
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:213 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '213', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'assign_driver', 'params': {'c': 'port=5,dport=6,steps=1|1|2', 'd': 'test1.my', 'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k masterkey
  • i item ID
  • d driver ID (if none - all above item props are set to null)
  • c configuration (e.g. port number)

Optionally:

  • save save item configuration after successful call
get_driver - get loaded driver information

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 134
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_driver",
    "params": {
        "i": "test1.my",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 134' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_driver", "params": {"i": "test1.my", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 134' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_driver", "params": {"i": "test1.my", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_driver",
  "params": {
    "i": "test1.my",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:134 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '134', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_driver', 'params': {'i': 'test1.my', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 3218
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "api": 9,
        "author": "Altertech Group, https://www.altertech.com/",
        "cfg": {},
        "connections": {
            "dport": "destination",
            "port": "power"
        },
        "description": "Multistep LPI (opener)",
        "features": [
            "action",
            "action_mp",
            "port_set",
            "aao_set"
        ],
        "help": "\nSolves typical logic task: turning the motor direction and run the motor for\nthe specified number of seconds, to control i.e. window opening, door opening,\nmanipulators of the robots.\n\nThe duration of the motor work is specified in 'steps' unit driver\nconfiguration param, each step corresponds to the next status.\n\nWarmup is used to let the motor additional number of seconds for the starting\nstates between first and last.\n\nTuning is used to make sure the motor drivers the target to starting and\nfinishing position (i.e. completely opens/closes the door).\n\nts and te. Sometimes it's pretty hard to calculate the proper position for the\nmiddle states. In this case LPI will ask motor to go all the way to the start\nstate (if target status <= ts) and then back to the target, or all the way to\nthe end and to the target (if target status >= te).\n\nUnit driver config fields should have property 'port' with a\nport label/number for PHI. 'io_label' prop allows to rename 'port', 'dport'\ni.e. to 'socket', 'dsocket' for a more fancy unit configuration.  Each port and\ndport may be specified as a single value or contain an array of values, in this\ncase multiple ports are used simultaneously.\n\nFor reversible DC motor schema use \"port\" for plus (up) and \"dport\" for minus\n(down).\n\nYou may set i: before the port label/number, i.e. i:2, to return/use inverted\nport state. This works both for power and direction ports.\n",
        "id": "test1.my",
        "license": "Apache License 2.0",
        "logic": "multistep with delays",
        "lpi_id": "my",
        "mod": "multistep",
        "oid": "driver:uc/lab-ws2/test1.my",
        "phi": {
            "api": 9,
            "author": "Altertech Group, https://www.altertech.com/",
            "can_discover": null,
            "can_get_ports": true,
            "cfg": {
                "default_status": 1
            },
            "description": "Emulates 16-port relay",
            "equipment": [
                "virtual"
            ],
            "features": [
                "aao_get",
                "aao_set",
                "push",
                "action",
                "port_get",
                "port_set"
            ],
            "help": "\nSimple 16-port virtual relay, may be used for the various tests/debugging.\n",
            "id": "test1",
            "license": "Apache License 2.0",
            "lpi_default": "basic",
            "mod": "vrtrelay",
            "mods_required": [],
            "oid": "phi:uc/lab-ws2/test1",
            "required": [
                "action",
                "port_get",
                "port_set"
            ],
            "version": "1.4.0"
        },
        "phi_id": "test1",
        "version": "1.2.1"
    }
}

Parameters:

  • k API key with master permissions
  • i PHI ID
list_drivers - list loaded drivers

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 111
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_drivers",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 111' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_drivers", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 111' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_drivers", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_drivers",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:111 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '111', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_drivers', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 869
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "features": [
                "status",
                "status_mp",
                "mu_status",
                "mu_status_mp",
                "port_get",
                "aao_get",
                "action",
                "action_mp",
                "port_set",
                "aao_set",
                "events",
                "value"
            ],
            "id": "test1.default",
            "lpi_id": "default",
            "mod": "basic",
            "phi_id": "test1"
        },
        {
            "features": [
                "action",
                "action_mp",
                "port_set",
                "aao_set"
            ],
            "id": "test1.my",
            "lpi_id": "my",
            "mod": "multistep",
            "phi_id": "test1"
        }
    ]
}

Parameters:

  • k API key with master permissions
  • full get exntended information
list_lpi_mods - get list of available LPI modules

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 112
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_lpi_mods",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 112' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_lpi_mods", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 112' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_lpi_mods", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_lpi_mods",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:112 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '112', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_lpi_mods', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 8988
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "api": 9,
            "author": "Altertech Group, https://www.altertech.com/",
            "connections": {
                "port": "primary"
            },
            "description": "Basic LPI for simple devices",
            "features": [
                "status",
                "status_mp",
                "mu_status",
                "mu_status_mp",
                "port_get",
                "aao_get",
                "action",
                "action_mp",
                "port_set",
                "aao_set",
                "events",
                "value"
            ],
            "help": "\nBasic LPI for simple unit status control (on/off) and monitoring. Support\nstatus 0 and 1. Unit driver config fields should have property 'port' with a\nport label/number for PHI. 'io_label' prop allows to rename 'port' e.g. to\n'socket' for a more fancy unit configuration. Each port may be specified as a\nsingle value or contain an array of values, in this case multiple ports are\nused simultaneously.\n\nYou may set i: before the port label/number, e.g. i:2, to return/use inverted\nport state.\n",
            "id": null,
            "license": "Apache License 2.0",
            "logic": "basic status on/off",
            "lpi_id": null,
            "mod": "basic",
            "oid": null,
            "phi_id": null,
            "version": "1.3.0"
        },
        {
            "api": 9,
            "author": "Altertech Group, https://www.altertech.com/",
            "connections": {
                "port": "primary"
            },
            "description": "test LPI mod",
            "features": [
                "status",
                "status_mp",
                "mu_status",
                "mu_status_mp",
                "port_get",
                "aao_get",
                "action",
                "action_mp",
                "port_set",
                "aao_set",
                "events",
                "value"
            ],
            "help": "\nBasic LPI for simple unit status control (on/off) and monitoring. Support\nstatus 0 and 1. Unit driver config fields should have property 'port' with a\nport label/number for PHI. 'io_label' prop allows to rename 'port' e.g. to\n'socket' for a more fancy unit configuration. Each port may be specified as a\nsingle value or contain an array of values, in this case multiple ports are\nused simultaneously.\n\nYou may set i: before the port label/number, e.g. i:2, to return/use inverted\nport state.\n",
            "id": null,
            "license": "Apache License 2.0",
            "logic": "basic status on/off",
            "lpi_id": null,
            "mod": "btest",
            "oid": null,
            "phi_id": null,
            "version": "1.3.0"
        },
        {
            "api": 9,
            "author": "Altertech Group, https://www.altertech.com/",
            "connections": {
                "port": "primary"
            },
            "description": "Enhanced sensor LPI",
            "features": [
                "value",
                "value_mp",
                "mu_value",
                "mu_value_mp",
                "port_get",
                "aao_get",
                "cfg",
                "events"
            ],
            "help": "\nEnhanced LPI to work with groups of sensors, supports various typical\nfunctions: working with a sensor groups, returning the average, max or min\ngroup value etc. Can use 'max_diff' param to control the maximum difference of\nthe sensor value in a group and automatically remove possible broken sensors\nfrom the result (if the number of good sensors in a group is more than broken).\n\nFor multiupdates all ports specified in mu should be lists.\n\nThis LPI is dedicated to work with a groups of sensors and doesn't support\nsingle sensor event processing.\n",
            "id": null,
            "license": "Apache License 2.0",
            "logic": "single and group polling",
            "lpi_id": null,
            "mod": "esensor",
            "oid": null,
            "phi_id": null,
            "version": "1.2.0"
        },
        {
            "api": 9,
            "author": "Altertech Group, https://www.altertech.com/",
            "connections": {
                "dport": "destination",
                "port": "power"
            },
            "description": "Multistep LPI (opener)",
            "features": [
                "action",
                "action_mp",
                "port_set",
                "aao_set"
            ],
            "help": "\nSolves typical logic task: turning the motor direction and run the motor for\nthe specified number of seconds, to control i.e. window opening, door opening,\nmanipulators of the robots.\n\nThe duration of the motor work is specified in 'steps' unit driver\nconfiguration param, each step corresponds to the next status.\n\nWarmup is used to let the motor additional number of seconds for the starting\nstates between first and last.\n\nTuning is used to make sure the motor drivers the target to starting and\nfinishing position (i.e. completely opens/closes the door).\n\nts and te. Sometimes it's pretty hard to calculate the proper position for the\nmiddle states. In this case LPI will ask motor to go all the way to the start\nstate (if target status <= ts) and then back to the target, or all the way to\nthe end and to the target (if target status >= te).\n\nUnit driver config fields should have property 'port' with a\nport label/number for PHI. 'io_label' prop allows to rename 'port', 'dport'\ni.e. to 'socket', 'dsocket' for a more fancy unit configuration.  Each port and\ndport may be specified as a single value or contain an array of values, in this\ncase multiple ports are used simultaneously.\n\nFor reversible DC motor schema use \"port\" for plus (up) and \"dport\" for minus\n(down).\n\nYou may set i: before the port label/number, i.e. i:2, to return/use inverted\nport state. This works both for power and direction ports.\n",
            "id": null,
            "license": "Apache License 2.0",
            "logic": "multistep with delays",
            "lpi_id": null,
            "mod": "multistep",
            "oid": null,
            "phi_id": null,
            "version": "1.2.1"
        },
        {
            "api": 9,
            "author": "Altertech Group, https://www.altertech.com/",
            "connections": {
                "port": "primary"
            },
            "description": "Basic sensor LPI",
            "features": [
                "value",
                "mu_value",
                "port_get",
                "aao_get",
                "cfg",
                "events"
            ],
            "help": "\nBasic LPI to work with sensors, doesn't process sensor value in any way,\nreturning it to controller as-is. ",
            "id": null,
            "license": "Apache License 2.0",
            "logic": "single polling",
            "lpi_id": null,
            "mod": "sensor",
            "oid": null,
            "phi_id": null,
            "version": "1.2.0"
        },
        {
            "api": 9,
            "author": "Altertech Group, https://www.altertech.com/",
            "connections": {
                "port": "primary"
            },
            "description": "Single port sensor LPI",
            "features": [
                "value",
                "port_get",
                "events",
                "ssp"
            ],
            "help": "\nLPI to work with sensor PHIs which provide state for single sensor only\n(port=1), doesn't process sensor value in any way, returning it to controller\nas-is. ",
            "id": null,
            "license": "Apache License 2.0",
            "logic": "single port",
            "lpi_id": null,
            "mod": "ssp",
            "oid": null,
            "phi_id": null,
            "version": "1.2.0"
        },
        {
            "api": 9,
            "author": "Altertech Group, https://www.altertech.com/",
            "connections": {
                "port": "primary"
            },
            "description": "Single port unit LPI",
            "features": [
                "status",
                "port_get",
                "port_set",
                "events",
                "usp",
                "value",
                "action"
            ],
            "help": "\nLPI to work with unit PHIs which provide/manage state for single unit only\n(port=1), doesn't process unit status in any way, returning it to controller\nas-is. For unit actions port is not required, however LPI sets it to 1 when\ntransmitting to PHIs.\n",
            "id": null,
            "license": "Apache License 2.0",
            "logic": "single port, basic status on/off",
            "lpi_id": null,
            "mod": "usp",
            "oid": null,
            "phi_id": null,
            "version": "1.3.0"
        }
    ]
}

Parameters:

  • k API key with master permissions
load_driver - load a driver

Loads a driver, combining previously loaded PHI and chosen LPI module.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 177
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "load_driver",
    "params": {
        "i": "my",
        "k": "mykey",
        "m": "multistep",
        "p": "test1"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 177' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "load_driver", "params": {"i": "my", "k": "mykey", "m": "multistep", "p": "test1"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 177' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "load_driver", "params": {"i": "my", "k": "mykey", "m": "multistep", "p": "test1"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "load_driver",
  "params": {
    "i": "my",
    "k": "mykey",
    "m": "multistep",
    "p": "test1"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:177 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '177', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'load_driver', 'params': {'i': 'my', 'k': 'mykey', 'm': 'multistep', 'p': 'test1'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 3218
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "api": 9,
        "author": "Altertech Group, https://www.altertech.com/",
        "cfg": {},
        "connections": {
            "dport": "destination",
            "port": "power"
        },
        "description": "Multistep LPI (opener)",
        "features": [
            "action",
            "action_mp",
            "port_set",
            "aao_set"
        ],
        "help": "\nSolves typical logic task: turning the motor direction and run the motor for\nthe specified number of seconds, to control i.e. window opening, door opening,\nmanipulators of the robots.\n\nThe duration of the motor work is specified in 'steps' unit driver\nconfiguration param, each step corresponds to the next status.\n\nWarmup is used to let the motor additional number of seconds for the starting\nstates between first and last.\n\nTuning is used to make sure the motor drivers the target to starting and\nfinishing position (i.e. completely opens/closes the door).\n\nts and te. Sometimes it's pretty hard to calculate the proper position for the\nmiddle states. In this case LPI will ask motor to go all the way to the start\nstate (if target status <= ts) and then back to the target, or all the way to\nthe end and to the target (if target status >= te).\n\nUnit driver config fields should have property 'port' with a\nport label/number for PHI. 'io_label' prop allows to rename 'port', 'dport'\ni.e. to 'socket', 'dsocket' for a more fancy unit configuration.  Each port and\ndport may be specified as a single value or contain an array of values, in this\ncase multiple ports are used simultaneously.\n\nFor reversible DC motor schema use \"port\" for plus (up) and \"dport\" for minus\n(down).\n\nYou may set i: before the port label/number, i.e. i:2, to return/use inverted\nport state. This works both for power and direction ports.\n",
        "id": "test1.my",
        "license": "Apache License 2.0",
        "logic": "multistep with delays",
        "lpi_id": "my",
        "mod": "multistep",
        "oid": "driver:uc/lab-ws2/test1.my",
        "phi": {
            "api": 9,
            "author": "Altertech Group, https://www.altertech.com/",
            "can_discover": null,
            "can_get_ports": true,
            "cfg": {
                "default_status": 0
            },
            "description": "Emulates 16-port relay",
            "equipment": [
                "virtual"
            ],
            "features": [
                "aao_get",
                "aao_set",
                "push",
                "action",
                "port_get",
                "port_set"
            ],
            "help": "\nSimple 16-port virtual relay, may be used for the various tests/debugging.\n",
            "id": "test1",
            "license": "Apache License 2.0",
            "lpi_default": "basic",
            "mod": "vrtrelay",
            "mods_required": [],
            "oid": "phi:uc/lab-ws2/test1",
            "required": [
                "action",
                "port_get",
                "port_set"
            ],
            "version": "1.4.0"
        },
        "phi_id": "test1",
        "version": "1.2.1"
    }
}

Parameters:

  • k API key with master permissions
  • i LPI ID
  • m LPI module
  • p PHI ID

Optionally:

  • c Driver (LPI) configuration, optional
  • save save configuration after successful call
modhelp_lpi - get LPI usage help

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 156
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "modhelp_lpi",
    "params": {
        "c": "cfg",
        "k": "mykey",
        "m": "multistep"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 156' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "modhelp_lpi", "params": {"c": "cfg", "k": "mykey", "m": "multistep"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 156' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "modhelp_lpi", "params": {"c": "cfg", "k": "mykey", "m": "multistep"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "modhelp_lpi",
  "params": {
    "c": "cfg",
    "k": "mykey",
    "m": "multistep"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:156 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '156', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'modhelp_lpi', 'params': {'c': 'cfg', 'k': 'mykey', 'm': 'multistep'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 426
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "help": "allow action even if current status is error",
            "name": "bose",
            "required": false,
            "type": "bool"
        },
        {
            "help": "default: default circuit, rdc: reversible DC",
            "name": "logic",
            "required": false,
            "type": "enum:str:default,rdc"
        }
    ]
}

Parameters:

  • k API key with master permissions
  • m LPI module name (without .py extension)
  • c help context (cfg, action or update)
modinfo_lpi - get LPI module info

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "modinfo_lpi",
    "params": {
        "k": "mykey",
        "m": "multistep"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "modinfo_lpi", "params": {"k": "mykey", "m": "multistep"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "modinfo_lpi", "params": {"k": "mykey", "m": "multistep"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "modinfo_lpi",
  "params": {
    "k": "mykey",
    "m": "multistep"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'modinfo_lpi', 'params': {'k': 'mykey', 'm': 'multistep'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 2047
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "api": 9,
        "author": "Altertech Group, https://www.altertech.com/",
        "connections": {
            "dport": "destination",
            "port": "power"
        },
        "description": "Multistep LPI (opener)",
        "features": [
            "action",
            "action_mp",
            "port_set",
            "aao_set"
        ],
        "help": "\nSolves typical logic task: turning the motor direction and run the motor for\nthe specified number of seconds, to control i.e. window opening, door opening,\nmanipulators of the robots.\n\nThe duration of the motor work is specified in 'steps' unit driver\nconfiguration param, each step corresponds to the next status.\n\nWarmup is used to let the motor additional number of seconds for the starting\nstates between first and last.\n\nTuning is used to make sure the motor drivers the target to starting and\nfinishing position (i.e. completely opens/closes the door).\n\nts and te. Sometimes it's pretty hard to calculate the proper position for the\nmiddle states. In this case LPI will ask motor to go all the way to the start\nstate (if target status <= ts) and then back to the target, or all the way to\nthe end and to the target (if target status >= te).\n\nUnit driver config fields should have property 'port' with a\nport label/number for PHI. 'io_label' prop allows to rename 'port', 'dport'\ni.e. to 'socket', 'dsocket' for a more fancy unit configuration.  Each port and\ndport may be specified as a single value or contain an array of values, in this\ncase multiple ports are used simultaneously.\n\nFor reversible DC motor schema use \"port\" for plus (up) and \"dport\" for minus\n(down).\n\nYou may set i: before the port label/number, i.e. i:2, to return/use inverted\nport state. This works both for power and direction ports.\n",
        "license": "Apache License 2.0",
        "logic": "multistep with delays",
        "mod": "multistep",
        "oid": null,
        "version": "1.2.1"
    }
}

Parameters:

  • k API key with master permissions
  • m LPI module name (without .py extension)
set_driver_prop - set driver (LPI) configuration property

appends property to LPI configuration and reloads module

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 200
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_driver_prop",
    "params": {
        "i": "test1.my",
        "k": "mykey",
        "p": "bose",
        "save": "true",
        "v": 1
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 200' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_driver_prop", "params": {"i": "test1.my", "k": "mykey", "p": "bose", "save": "true", "v": 1}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 200' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_driver_prop", "params": {"i": "test1.my", "k": "mykey", "p": "bose", "save": "true", "v": 1}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_driver_prop",
  "params": {
    "i": "test1.my",
    "k": "mykey",
    "p": "bose",
    "save": "true",
    "v": 1
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:200 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '200', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_driver_prop', 'params': {'i': 'test1.my', 'k': 'mykey', 'p': 'bose', 'save': 'true', 'v': 1}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i driver ID
  • p property name (or empty for batch set)

Optionally:

  • v propery value (or dict for batch set)
  • save save driver configuration after successful call
unload_driver - unload driver

Unloads driver. Driver should not be used by any item.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 137
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "unload_driver",
    "params": {
        "i": "test1.my",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 137' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "unload_driver", "params": {"i": "test1.my", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 137' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "unload_driver", "params": {"i": "test1.my", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "unload_driver",
  "params": {
    "i": "test1.my",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:137 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '137', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'unload_driver', 'params': {'i': 'test1.my', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i driver ID

Data pullers

get_datapuller - Get data puller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 134
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_datapuller",
    "params": {
        "i": "test",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 134' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_datapuller", "params": {"i": "test", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 134' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_datapuller", "params": {"i": "test", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_datapuller",
  "params": {
    "i": "test",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:134 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '134', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_datapuller', 'params': {'i': 'test', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 178
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "active": true,
        "cmd": "/opt/test.sh -F /op/test.ini",
        "name": "test",
        "pid": 2398316
    }
}

Parameters:

  • k API key with master permissions
  • i data puller name

Returns:

Data puller info

list_datapullers - List data pullers

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 115
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_datapullers",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 115' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_datapullers", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 115' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_datapullers", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_datapullers",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:115 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '115', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_datapullers', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 214
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "active": true,
            "cmd": "/opt/test.sh -F /op/test.ini",
            "name": "test",
            "pid": 2398316
        }
    ]
}

Parameters:

  • k API key with master permissions

Returns:

List of all configured data pullers

restart_datapuller - Restart data puller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 138
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "restart_datapuller",
    "params": {
        "i": "test",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 138' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "restart_datapuller", "params": {"i": "test", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 138' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "restart_datapuller", "params": {"i": "test", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "restart_datapuller",
  "params": {
    "i": "test",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:138 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '138', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'restart_datapuller', 'params': {'i': 'test', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i data puller name
start_datapuller - Start data puller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "start_datapuller",
    "params": {
        "i": "test",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "start_datapuller", "params": {"i": "test", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "start_datapuller", "params": {"i": "test", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "start_datapuller",
  "params": {
    "i": "test",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'start_datapuller', 'params': {'i': 'test', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i data puller name
stop_datapuller - Stop data puller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 135
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "stop_datapuller",
    "params": {
        "i": "test",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 135' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "stop_datapuller", "params": {"i": "test", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 135' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "stop_datapuller", "params": {"i": "test", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "stop_datapuller",
  "params": {
    "i": "test",
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:135 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '135', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'stop_datapuller', 'params': {'i': 'test', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i data puller name

Devices

deploy_device - deploy device items from template

Deploys the device from the specified template.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 188
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "deploy_device",
    "params": {
        "c": "PORT=2,ID=5",
        "k": "mykey",
        "save": "true",
        "t": "device1"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 188' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "deploy_device", "params": {"c": "PORT=2,ID=5", "k": "mykey", "save": "true", "t": "device1"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 188' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "deploy_device", "params": {"c": "PORT=2,ID=5", "k": "mykey", "save": "true", "t": "device1"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "deploy_device",
  "params": {
    "c": "PORT=2,ID=5",
    "k": "mykey",
    "save": "true",
    "t": "device1"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:188 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '188', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'deploy_device', 'params': {'c': 'PORT=2,ID=5', 'k': 'mykey', 'save': 'true', 't': 'device1'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with allow=device permissions
  • t device template (runtime/tpl/<TEMPLATE>.yml|yaml|json, without extension)

Optionally:

  • c device config (var=value, comma separated or dict)
  • save save items configuration on disk immediately after operation
list_device_tpl - list device templates

List available device templates from runtime/tpl

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 114
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_device_tpl",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 114' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_device_tpl", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 114' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_device_tpl", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_device_tpl",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:114 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '114', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_device_tpl', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 138
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "name": "device1",
            "type": "YAML"
        }
    ]
}

Parameters:

  • k API key with masterkey permissions
undeploy_device - delete device items

Works in an opposite way to deploy_device - deploy device items from template function, destroying all items specified in the template.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 166
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "undeploy_device",
    "params": {
        "c": "PORT=2,ID=5",
        "k": "mykey",
        "t": "device1"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 166' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "undeploy_device", "params": {"c": "PORT=2,ID=5", "k": "mykey", "t": "device1"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 166' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "undeploy_device", "params": {"c": "PORT=2,ID=5", "k": "mykey", "t": "device1"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "undeploy_device",
  "params": {
    "c": "PORT=2,ID=5",
    "k": "mykey",
    "t": "device1"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:166 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '166', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'undeploy_device', 'params': {'c': 'PORT=2,ID=5', 'k': 'mykey', 't': 'device1'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with allow=device permissions
  • t device template (runtime/tpl/<TEMPLATE>.yml|yaml|json, without extension)

Optionally:

  • c device config (var=value, comma separated or dict)

Returns:

The function ignores missing items, so no errors are returned unless device configuration file is invalid.

update_device - update device items

Works similarly to deploy_device - deploy device items from template function but doesn’t create new items, updating the item configuration of the existing ones.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 188
Host: localhost:8812

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "update_device",
    "params": {
        "c": "PORT=2,ID=5",
        "k": "mykey",
        "save": "true",
        "t": "device1"
    }
}

curl

curl -i -X POST http://localhost:8812/jrpc -H 'Accept: application/json' -H 'Content-Length: 188' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "update_device", "params": {"c": "PORT=2,ID=5", "k": "mykey", "save": "true", "t": "device1"}}'

wget

wget -S -O- http://localhost:8812/jrpc --header='Accept: application/json' --header='Content-Length: 188' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "update_device", "params": {"c": "PORT=2,ID=5", "k": "mykey", "save": "true", "t": "device1"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "update_device",
  "params": {
    "c": "PORT=2,ID=5",
    "k": "mykey",
    "save": "true",
    "t": "device1"
  }
}' | http POST http://localhost:8812/jrpc Accept:application/json Content-Length:188 Content-Type:application/json

python-requests

requests.post('http://localhost:8812/jrpc', headers={'Accept': 'application/json', 'Content-Length': '188', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'update_device', 'params': {'c': 'PORT=2,ID=5', 'k': 'mykey', 'save': 'true', 't': 'device1'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with allow=device permissions
  • t device template (runtime/tpl/<TEMPLATE>.yml|yaml|json, without extension)

Optionally:

  • c device config (var=value, comma separated or dict)
  • save save items configuration on disk immediately after operation

UC UDP API

UC UDP API enables to call API action and update functions by sending a simple UDP packet.

Basics

As there is no feedback in UDP, it is not recommended to use UDP API in cases where reliability is critical, but its usability for programmable microcontrollers sometimes takes advantage.

To update the status of the item send the following UDP packet to API port:

<ID> u <status> [value]

(ID - item id, value - optional parameter).

To send action for the unit send the following UDP packet to API port:

<ID> <status> [value] [priority]

(value and priority** optional parameters).

If you needs to skip the parameter, set it to ‘None’. For example:

sensor1 u None 29.55

will keep sensor1 status and set value 29.55;

or

unit1 1 None 50

will run the action for unit1 for changing its status to 1, without changing the value, with priority 50.

Batch commands

You can specify multiple commands in one packet separating them with NL (n) symbol. Example:

sensor1 u 1 29.55
sensor2 u 1 26
sensor3 u 1 38

Encryption and authentication

You may specify in controller configuration to accept only encrypted packets from the specified hosts or networks. By default it’s recommended to accept unencrypted packets without authentication only in trusted networks. The packet is encrypted and signed with API key and can not be decrypted and used without having it, so API key acts both for encryption and authentication.

Encrypted packet format is:

|KEY_ID|ENCRYPTED_DATA

Where KEY_ID is API key ID and ENCRYPTED_DATA - UDP API packet (which may contain either single or multiple commands at once). The data is encrypted using Fernet - a symmetric encryption method which uses 128-bit AES in CBC mode and PKCS7 padding, with HMAC using SHA256 for authentication.

Fernet requires 32-bit base64-encoded key, so before data encryption, API key should be converted with the following: base64encode(sha256sum(api_key)).

Python example:

import hashlib
import base64

from cryptography.fernet import Fernet

api_key = 'mysecretapikey'
data = 'sensor1 u 1 29.55'

encryption_key = base64.b64encode(hashlib.sha256(api_key.encode()).digest())
ce = Fernet(encryption_key)

result = ce.encrypt(data.encode())

Fernet implementation is simple and pre-made libraries are available for all major programming languages.

Custom packets

You can send a custom packet to let it be parsed by loaded PHI.

Custom packet format is (\x = hex):

\x01 HANDLER_ID \x01 DATA

DATA is always transmitted to handler in binary format. Encryption, authentication and batch commands in custom packets are not supported.

LM API

Logic Manager API is used to manage lvars, rules and other logic elements

This document describes API methods for direct and JSON RPC calls. For RESTful API look LM RESTful API.

API basics

JSON RPC

JSON RPC 2.0 protocol is the primary EVA ICS API protocol. Note that default JSON RPC result is { “ok”: true } (instead of { “result”: “OK” } in the direct API). There’s no { result: “ERROR” } responses, as JSON RPC sends errors in “error” field.

If JSON RPC request is called without ID and server should not return a result, it will return http response with a code 202 Accepted.

Note

JSON RPC is recommended way to use EVA ICS API, unless direct method calling or RESTful is really required.

JSON RPC API URL:

http://<ip_address:8817>/jrpc

or

http://<ip_address:8817>

(all POST requests to the root URI are processed as JSON RPC)

JSON RPC payload encoding

EVA ICS supports JSON RPC payloads, encoded as generic JSON and as MessagePack. MessagePack encoding works faster, requires less bandwidth and is highly recommended to use.

To call API methods with MessagePack-encoded payloads, use Content-Type: application/msgpack HTTP request header.

JSON RPC error responses

JSON RPC calls return error codes equal to the codes of EVA API Client:

  • 1 the item or resource is not found
  • 2 access is denied with the set API key
  • 6 Attempt to call undefined API method/function
  • 10 API function failed (all errors not listed here fall within this category)
  • 11 API function is called with invalid params
  • 12 API function attempted to create resource which already exists and can’t be recreated until deleted/removed
  • 13 the resource is busy (in use) and can not be accessed/recreated or deleted at this moment
  • 14 the method is not implemented in/for requested resource

Response field “message” may contain additional information about error.

Warning

It’s highly not recommended to perform long API calls, calling API functions from JavaScript in a web browser (e.g. giving “w” param to action methods to wait until action finish). Web browser may repeat API call continuously, which may lead to absolutely unexpected behavior.

JSON RPC via HTTP GET

Embedded equipment sometimes can send HTTP GET requests only. JSON RPC API supports such calls as well.

To make JSON RPC API request with HTTP get, send it to:

http://<ip_address:8817>/jrpc?i=ID&m=METHOD&p=PARAMS

where:

  • ID request ID (any custom value). If not specified, API response isn’t sent back
  • METHOD JSON RPC method to call
  • PARAMS method params, as url-encoded JSON

E.g. the following HTTP GET request will invoke method “test” with request id=1 and params { “k”: “mykey” }:

http://<ip_address:8817>/jrpc?i=1&m=test&p=%7B%22k%22%3A%22mykey%22%7D

Note

JSON RPC API calls via HTTP GET are insecure, limited to 2048 bytes and can not be batch. Use JSON RPC via HTTP POST with JSON or MessagePack payload always when possible.

Direct API

Warning

Direct method calling is deprecated and scheduled to be removed (not implemented) in EVA ICS v4. Use JSON RPC API, whenever it is possible.

LM API functions are called through URL request

http://<ip_address:8817>/lm-api/function

If SSL is allowed in the controller configuration file, you can also use https calls.

Direct API responses

Good for backward compatibility with any devices, as all API functions can be called using GET and POST. When POST is used, the parameters can be passed to functions either as multipart/form-data or as JSON.

API key can be sent in request parameters, session (if enabled and user is logged in) or in HTTP X-Auth-Key header.

Standard responses in status/body:

  • 200 OK { “result”: “OK” } API call completed successfully.

Standard error responses in status:

  • 400 Bad Request Invalid request params
  • 403 Forbidden the API key has no access to this function or resource
  • 404 Not Found method or resource/object doesn’t exist
  • 405 Method Not Allowed API function/method not found or HTTP method is not either GET or POST
  • 409 Conflict resource/object already exists or is locked
  • 500 API Error API function execution has been failed. Check input parameters and server logs.

In case API function has been failed, response body will contain JSON data with _error field, which contains error message.

{
    "_error": "unable to add object, already present",
    "result": "ERROR"
}

Contents

LVar functions

clear - clear lvar state

set status (if expires lvar param > 0) or value (if expires isn’t set) of a logic variable to 0. Useful when lvar is used as a timer to stop it, or as a flag to set it False.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 132
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "clear",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 132' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "clear", "params": {"i": "tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 132' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "clear", "params": {"i": "tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "clear",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:132 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '132', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'clear', 'params': {'i': 'tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i lvar id
decrement - decrement lvar value

Decrement value of a logic variable. Initial value should be number

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "decrement",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "decrement", "params": {"i": "tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "decrement", "params": {"i": "tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "decrement",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'decrement', 'params': {'i': 'tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i lvar id
groups - get item group list

Get the list of item groups. Useful e.g. for custom interfaces.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 105
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "groups",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 105' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "groups", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 105' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "groups", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "groups",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:105 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '105', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'groups', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 76
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        "tests"
    ]
}

Parameters:

  • k valid API key
  • p item type (must be set to lvar [LV])
increment - increment lvar value

Increment value of a logic variable. Initial value should be number

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "increment",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "increment", "params": {"i": "tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "increment", "params": {"i": "tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "increment",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'increment', 'params': {'i': 'tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i lvar id
reset - reset lvar state

Set status and value of a logic variable to 1. Useful when lvar is being used as a timer to reset it, or as a flag to set it True.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 132
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "reset",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 132' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "reset", "params": {"i": "tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 132' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "reset", "params": {"i": "tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "reset",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:132 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '132', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'reset', 'params': {'i': 'tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i lvar id
set - set lvar state

Set status and value of a logic variable.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 163
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey",
        "s": 1,
        "v": 29
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 163' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set", "params": {"i": "tests/lvar1", "k": "mykey", "s": 1, "v": 29}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 163' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set", "params": {"i": "tests/lvar1", "k": "mykey", "s": 1, "v": 29}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey",
    "s": 1,
    "v": 29
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:163 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '163', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set', 'params': {'i': 'tests/lvar1', 'k': 'mykey', 's': 1, 'v': 29}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i lvar id

Optionally:

  • s lvar status
  • v lvar value
state - get lvar state

State of lvar or all lvars can be obtained using state command.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 104
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "state",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 104' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "state", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 104' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "state", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "state",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:104 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '104', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'state', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 666
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "expires": 15.0,
            "full_id": "tests/lvar1",
            "group": "tests",
            "id": "lvar1",
            "oid": "lvar:tests/lvar1",
            "set_time": 1604185854.291637,
            "status": 1,
            "type": "lvar",
            "value": "0"
        },
        {
            "expires": 0,
            "full_id": "tests/lvar5",
            "group": "tests",
            "id": "lvar5",
            "oid": "lvar:tests/lvar5",
            "set_time": 1604185854.0752258,
            "status": 1,
            "type": "lvar",
            "value": ""
        }
    ]
}

Parameters:

  • k valid API key

Optionally:

  • p item type (none or lvar [LV])
  • i item id
  • g item group
  • full return full state
state_history - get item state history

State history of one item or several items of the specified type can be obtained using state_history command.

If master key is used, the method attempts to get stored state for an item even if it doesn’t present currently in system.

The method can return state log for disconnected items as well.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 145
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "state_history",
    "params": {
        "i": "lvar:tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 145' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "state_history", "params": {"i": "lvar:tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 145' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "state_history", "params": {"i": "lvar:tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "state_history",
  "params": {
    "i": "lvar:tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:145 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '145', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'state_history', 'params': {'i': 'lvar:tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 787
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "status": [
            -1,
            -1,
            1,
            1,
            1,
            1,
            1,
            1,
            1,
            1
        ],
        "t": [
            1604185850.3238852,
            1604185851.9794078,
            1604185854.0263395,
            1604185854.1407351,
            1604185854.1557796,
            1604185854.2269773,
            1604185854.242243,
            1604185854.2968373,
            1604185854.3143985,
            1604185855.1648626
        ],
        "value": [
            null,
            null,
            null,
            0.0,
            0.0,
            1.0,
            1.0,
            0.0,
            0.0,
            0.0
        ]
    }
}

Parameters:

  • k valid API key
  • a history notifier id (default: db_1)
  • i item oids or full ids, list or comma separated

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • l records limit (doesn’t work with “w”)
  • x state prop (“status” or “value”)
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • z Time zone (pytz, e.g. UTC or Europe/Prague)
  • w fill frame with the interval (e.g. “1T” - 1 min, “2H” - 2 hours etc.), start time is required, set to 1D if not specified
  • g output format (“list”, “dict” or “chart”, default is “list”)
  • c options for chart (dict or comma separated)
  • o extra options for notifier data request

Returns:

history data in specified format or chart image.

For chart, JSON RPC gets reply with “content_type” and “data” fields, where content is image content type. If PNG image format is selected, data is base64-encoded.

Options for chart (all are optional):

If option “w” (fill) is used, number of digits after comma may be specified. E.g. 5T:3 will output values with 3 digits after comma.

Additionally, SI prefix may be specified to convert value to kilos, megas etc, e.g. 5T:k:3 - divide value by 1000 and output 3 digits after comma. Valid prefixes are: k, M, G, T, P, E, Z, Y.

If binary prefix is required, it should be followed by “b”, e.g. 5T:Mb:3 - divide value by 2^20 and output 3 digits after comma.

state_log - get item state log

State log of a single item or group of the specified type can be obtained using state_log command.

note: only SQL notifiers are supported

Difference from state_history method:

  • state_log doesn’t optimize data to be displayed on charts * the data is returned from a database as-is * a single item OID or OID mask (e.g. sensor:env/#) can be specified

note: the method supports MQTT-style masks but only masks with wildcard-ending, like “type:group/subgroup/#” are supported.

The method can return state log for disconnected items as well.

For wildcard fetching, API key should have an access to the whole chosen group.

note: record limit means the limit for records, fetched from the database, but repeating state records are automatically grouped and the actual number of returned records can be lower than requested.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 141
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "state_log",
    "params": {
        "i": "lvar:tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 141' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "state_log", "params": {"i": "lvar:tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 141' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "state_log", "params": {"i": "lvar:tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "state_log",
  "params": {
    "i": "lvar:tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:141 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '141', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'state_log', 'params': {'i': 'lvar:tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 661
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "oid": "lvar:tests/lvar1",
            "status": 1,
            "t": 1607295624.8417337,
            "value": null
        },
        {
            "oid": "lvar:tests/lvar1",
            "status": 1,
            "t": 1607295636.6316836,
            "value": "value1"
        },
        {
            "oid": "lvar:tests/lvar1",
            "status": 1,
            "t": 1607295637.536753,
            "value": "value2"
        },
        {
            "oid": "lvar:tests/lvar1",
            "status": 1,
            "t": 1607295638.475802,
            "value": "value3"
        }
    ]
}

Parameters:

  • k valid API key
  • a history notifier id (default: db_1)
  • i item oid or oid mask (type:group/subgroup/#)

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • l records limit (doesn’t work with “w”)
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • z Time zone (pytz, e.g. UTC or Europe/Prague)
  • o extra options for notifier data request

Returns:

state log records (list)

toggle - toggle lvar state

switch value of a logic variable between 0 and 1. Useful when lvar is being used as a flag to switch it between True/False.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 133
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "toggle",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 133' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "toggle", "params": {"i": "tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 133' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "toggle", "params": {"i": "tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "toggle",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:133 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '133', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'toggle', 'params': {'i': 'tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i lvar id

LVar management

list - list lvars

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 103
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 103' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 103' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:103 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '103', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 624
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "description": "",
            "expires": 0,
            "full_id": "tests/lvar1",
            "group": "tests",
            "id": "lvar1",
            "oid": "lvar:tests/lvar1",
            "set_time": 1604185854.291637,
            "type": "lvar"
        },
        {
            "description": "",
            "expires": 0,
            "full_id": "tests/lvar5",
            "group": "tests",
            "id": "lvar5",
            "oid": "lvar:tests/lvar5",
            "set_time": 1604185854.0752258,
            "type": "lvar"
        }
    ]
}

Parameters:

  • k API key with master permissions

Optionally:

  • g filter by item group
  • x serialize specified item prop(s)

Returns:

the list of all lvars available

create - alias for create_lvar

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 157
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create",
    "params": {
        "i": "tests/lvar5",
        "k": "mykey",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 157' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create", "params": {"i": "tests/lvar5", "k": "mykey", "save": "true"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 157' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create", "params": {"i": "tests/lvar5", "k": "mykey", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create",
  "params": {
    "i": "tests/lvar5",
    "k": "mykey",
    "save": "true"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:157 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '157', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create', 'params': {'i': 'tests/lvar5', 'k': 'mykey', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 305
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "expires": 0,
        "full_id": "tests/lvar5",
        "group": "tests",
        "id": "lvar5",
        "oid": "lvar:tests/lvar5",
        "set_time": 1604185854.0752258,
        "status": 1,
        "type": "lvar",
        "value": ""
    }
}
create_lvar - create lvar

Create new lvar

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 162
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create_lvar",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 162' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create_lvar", "params": {"i": "tests/lvar1", "k": "mykey", "save": "true"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 162' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create_lvar", "params": {"i": "tests/lvar1", "k": "mykey", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create_lvar",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey",
    "save": "true"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:162 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '162', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create_lvar', 'params': {'i': 'tests/lvar1', 'k': 'mykey', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 304
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "expires": 0,
        "full_id": "tests/lvar1",
        "group": "tests",
        "id": "lvar1",
        "oid": "lvar:tests/lvar1",
        "set_time": 1604185854.015231,
        "status": 1,
        "type": "lvar",
        "value": ""
    }
}

Parameters:

  • k API key with master permissions
  • i lvar id

Optionally:

  • g lvar group
  • save save lvar configuration immediately
destroy - alias for destroy_lvar

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 139
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "destroy",
    "params": {
        "i": "lvar:tests/lvar5",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 139' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "destroy", "params": {"i": "lvar:tests/lvar5", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 139' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "destroy", "params": {"i": "lvar:tests/lvar5", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "destroy",
  "params": {
    "i": "lvar:tests/lvar5",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:139 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '139', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'destroy', 'params': {'i': 'lvar:tests/lvar5', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}
destroy_lvar - delete lvar

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 144
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "destroy_lvar",
    "params": {
        "i": "lvar:tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 144' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "destroy_lvar", "params": {"i": "lvar:tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 144' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "destroy_lvar", "params": {"i": "lvar:tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "destroy_lvar",
  "params": {
    "i": "lvar:tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:144 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '144', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'destroy_lvar', 'params': {'i': 'lvar:tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i lvar id
get_config - get lvar configuration

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 142
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_config",
    "params": {
        "i": "lvar:tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 142' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_config", "params": {"i": "lvar:tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 142' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_config", "params": {"i": "lvar:tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_config",
  "params": {
    "i": "lvar:tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:142 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '142', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_config', 'params': {'i': 'lvar:tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 290
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "expires": 0,
        "full_id": "tests/lvar1",
        "group": "tests",
        "id": "lvar1",
        "notify_events": 2,
        "oid": "lvar:tests/lvar1",
        "set_time": 1604185854.291637,
        "type": "lvar"
    }
}

Parameters:

  • k API key with master permissions
  • i lvaar id

Returns:

complete lvar configuration.

list_props - list lvar properties

Get all editable parameters of the lvar confiugration.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 142
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_props",
    "params": {
        "i": "lvar:tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 142' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_props", "params": {"i": "lvar:tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 142' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_props", "params": {"i": "lvar:tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_props",
  "params": {
    "i": "lvar:tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:142 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '142', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_props', 'params': {'i': 'lvar:tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 295
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "description": "",
        "expires": 0,
        "mqtt_update": null,
        "notify_events": 2,
        "set_time": 1604185854.291637,
        "update_exec": null,
        "update_interval": 0,
        "update_timeout": null
    }
}

Parameters:

  • k API key with master permissions
  • i item id
save_config - save lvar configuration

Saves lvar. configuration on disk (even if it hasn’t been changed)

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 143
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "save_config",
    "params": {
        "i": "lvar:tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 143' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "save_config", "params": {"i": "lvar:tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 143' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "save_config", "params": {"i": "lvar:tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "save_config",
  "params": {
    "i": "lvar:tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:143 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '143', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'save_config', 'params': {'i': 'lvar:tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i lvar id
set_prop - set lvar property

Set configuration parameters of the lvar.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 181
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_prop",
    "params": {
        "i": "lvar:tests/lvar1",
        "k": "mykey",
        "p": "expires",
        "v": 15
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 181' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_prop", "params": {"i": "lvar:tests/lvar1", "k": "mykey", "p": "expires", "v": 15}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 181' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_prop", "params": {"i": "lvar:tests/lvar1", "k": "mykey", "p": "expires", "v": 15}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_prop",
  "params": {
    "i": "lvar:tests/lvar1",
    "k": "mykey",
    "p": "expires",
    "v": 15
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:181 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '181', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_prop', 'params': {'i': 'lvar:tests/lvar1', 'k': 'mykey', 'p': 'expires', 'v': 15}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i item id
  • p property name (or empty for batch set)

Optionally:

  • v propery value (or dict for batch set)
  • save save configuration after successful call

Decision matrix rules

create_rule - create new rule

Creates new decision rule. Rule id (UUID) is generated automatically unless specified.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 110
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create_rule",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 110' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create_rule", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 110' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create_rule", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create_rule",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:110 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '110', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create_rule', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 812
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "break_after_exec": false,
        "chillout_ends_in": 0,
        "chillout_time": 0,
        "condition": "",
        "description": "",
        "enabled": false,
        "for_initial": "skip",
        "for_item_group": null,
        "for_item_id": null,
        "for_item_type": null,
        "for_oid": "#:#/#.status",
        "for_prop": "status",
        "id": "7117bf3f-aa34-45f3-9ec0-c1ef459aea1b",
        "in_range_max": null,
        "in_range_max_eq": false,
        "in_range_min": null,
        "in_range_min_eq": false,
        "macro": null,
        "macro_args": [],
        "macro_kwargs": {},
        "oid": "dmatrix_rule:dm_rules/7117bf3f-aa34-45f3-9ec0-c1ef459aea1b",
        "priority": 100,
        "type": "dmatrix_rule"
    }
}

Parameters:

  • k API key with master permissions

Optionally:

  • u rule UUID to set
  • v rule properties (dict) or human-readable input
  • e enable rule after creation
  • save save rule configuration immediately
destroy_rule - delete rule

Deletes decision rule.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 164
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "destroy_rule",
    "params": {
        "i": "4c6e8c99-56fe-490c-8442-4936ba777498",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 164' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "destroy_rule", "params": {"i": "4c6e8c99-56fe-490c-8442-4936ba777498", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 164' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "destroy_rule", "params": {"i": "4c6e8c99-56fe-490c-8442-4936ba777498", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "destroy_rule",
  "params": {
    "i": "4c6e8c99-56fe-490c-8442-4936ba777498",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:164 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '164', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'destroy_rule', 'params': {'i': '4c6e8c99-56fe-490c-8442-4936ba777498', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i rule id
get_rule - get rule information

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 160
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_rule",
    "params": {
        "i": "4c6e8c99-56fe-490c-8442-4936ba777498",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 160' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_rule", "params": {"i": "4c6e8c99-56fe-490c-8442-4936ba777498", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 160' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_rule", "params": {"i": "4c6e8c99-56fe-490c-8442-4936ba777498", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_rule",
  "params": {
    "i": "4c6e8c99-56fe-490c-8442-4936ba777498",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:160 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '160', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_rule', 'params': {'i': '4c6e8c99-56fe-490c-8442-4936ba777498', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 810
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "break_after_exec": false,
        "chillout_ends_in": 0,
        "chillout_time": 0,
        "condition": "",
        "description": "",
        "enabled": false,
        "for_initial": null,
        "for_item_group": null,
        "for_item_id": null,
        "for_item_type": null,
        "for_oid": "#:#/#.status",
        "for_prop": "status",
        "id": "4c6e8c99-56fe-490c-8442-4936ba777498",
        "in_range_max": null,
        "in_range_max_eq": false,
        "in_range_min": null,
        "in_range_min_eq": false,
        "macro": null,
        "macro_args": [],
        "macro_kwargs": {},
        "oid": "dmatrix_rule:dm_rules/4c6e8c99-56fe-490c-8442-4936ba777498",
        "priority": 100,
        "type": "dmatrix_rule"
    }
}

Parameters:

  • k valid API key
  • i rule id
list_rule_props - list rule properties

Get all editable parameters of the decision rule.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 167
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_rule_props",
    "params": {
        "i": "4c6e8c99-56fe-490c-8442-4936ba777498",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 167' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_rule_props", "params": {"i": "4c6e8c99-56fe-490c-8442-4936ba777498", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 167' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_rule_props", "params": {"i": "4c6e8c99-56fe-490c-8442-4936ba777498", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_rule_props",
  "params": {
    "i": "4c6e8c99-56fe-490c-8442-4936ba777498",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:167 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '167', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_rule_props', 'params': {'i': '4c6e8c99-56fe-490c-8442-4936ba777498', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 616
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "break_after_exec": false,
        "chillout_time": 0,
        "condition": "",
        "description": "",
        "enabled": false,
        "for_initial": null,
        "for_item_group": null,
        "for_item_id": null,
        "for_item_type": null,
        "for_oid": "#:#/#.status",
        "for_prop": "status",
        "in_range_max": null,
        "in_range_max_eq": false,
        "in_range_min": null,
        "in_range_min_eq": false,
        "macro": null,
        "macro_args": [],
        "macro_kwargs": {},
        "priority": 100
    }
}

Parameters:

  • k valid API key
  • i rule id
list_rules - get rules list

Get the list of all available decision rules.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 109
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_rules",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 109' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_rules", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 109' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_rules", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_rules",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:109 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '109', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_rules', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 3517
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "break_after_exec": false,
            "chillout_ends_in": 0,
            "chillout_time": 0,
            "condition": "",
            "description": "",
            "enabled": false,
            "for_initial": "skip",
            "for_item_group": null,
            "for_item_id": null,
            "for_item_type": null,
            "for_oid": "#:#/#.status",
            "for_prop": "status",
            "id": "a198960a-d94e-4be1-9f1e-092c140eaa1a",
            "in_range_max": null,
            "in_range_max_eq": false,
            "in_range_min": null,
            "in_range_min_eq": false,
            "macro": null,
            "macro_args": [],
            "macro_kwargs": {},
            "oid": "dmatrix_rule:dm_rules/a198960a-d94e-4be1-9f1e-092c140eaa1a",
            "priority": 100,
            "type": "dmatrix_rule"
        },
        {
            "break_after_exec": false,
            "chillout_ends_in": 0,
            "chillout_time": 0,
            "condition": "",
            "description": "",
            "enabled": false,
            "for_initial": null,
            "for_item_group": null,
            "for_item_id": null,
            "for_item_type": null,
            "for_oid": "#:#/#.status",
            "for_prop": "status",
            "id": "4c6e8c99-56fe-490c-8442-4936ba777498",
            "in_range_max": null,
            "in_range_max_eq": false,
            "in_range_min": null,
            "in_range_min_eq": false,
            "macro": null,
            "macro_args": [],
            "macro_kwargs": {},
            "oid": "dmatrix_rule:dm_rules/4c6e8c99-56fe-490c-8442-4936ba777498",
            "priority": 100,
            "type": "dmatrix_rule"
        },
        {
            "break_after_exec": false,
            "chillout_ends_in": 0,
            "chillout_time": 0,
            "condition": "",
            "description": "",
            "enabled": false,
            "for_initial": "skip",
            "for_item_group": null,
            "for_item_id": null,
            "for_item_type": null,
            "for_oid": "#:#/#.status",
            "for_prop": "status",
            "id": "9c0ce971-b19f-4b4a-9586-3c4898ca46d8",
            "in_range_max": null,
            "in_range_max_eq": false,
            "in_range_min": null,
            "in_range_min_eq": false,
            "macro": null,
            "macro_args": [],
            "macro_kwargs": {},
            "oid": "dmatrix_rule:dm_rules/9c0ce971-b19f-4b4a-9586-3c4898ca46d8",
            "priority": 100,
            "type": "dmatrix_rule"
        },
        {
            "break_after_exec": false,
            "chillout_ends_in": 0,
            "chillout_time": 0,
            "condition": "",
            "description": "",
            "enabled": false,
            "for_initial": "skip",
            "for_item_group": null,
            "for_item_id": null,
            "for_item_type": null,
            "for_oid": "#:#/#.status",
            "for_prop": "status",
            "id": "7117bf3f-aa34-45f3-9ec0-c1ef459aea1b",
            "in_range_max": null,
            "in_range_max_eq": false,
            "in_range_min": null,
            "in_range_min_eq": false,
            "macro": null,
            "macro_args": [],
            "macro_kwargs": {},
            "oid": "dmatrix_rule:dm_rules/7117bf3f-aa34-45f3-9ec0-c1ef459aea1b",
            "priority": 100,
            "type": "dmatrix_rule"
        }
    ]
}

Parameters:

  • k valid API key
set_rule_prop - set rule parameters

Set configuration parameters of the decision rule.

Note

Master key is required for batch set.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 237
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_rule_prop",
    "params": {
        "i": "4c6e8c99-56fe-490c-8442-4936ba777498",
        "k": "mykey",
        "p": "for_initial",
        "save": "true",
        "v": "any"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 237' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_rule_prop", "params": {"i": "4c6e8c99-56fe-490c-8442-4936ba777498", "k": "mykey", "p": "for_initial", "save": "true", "v": "any"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 237' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_rule_prop", "params": {"i": "4c6e8c99-56fe-490c-8442-4936ba777498", "k": "mykey", "p": "for_initial", "save": "true", "v": "any"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_rule_prop",
  "params": {
    "i": "4c6e8c99-56fe-490c-8442-4936ba777498",
    "k": "mykey",
    "p": "for_initial",
    "save": "true",
    "v": "any"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:237 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '237', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_rule_prop', 'params': {'i': '4c6e8c99-56fe-490c-8442-4936ba777498', 'k': 'mykey', 'p': 'for_initial', 'save': 'true', 'v': 'any'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i rule id
  • p property name (or empty for batch set)

Optionally:

  • v propery value (or dict for batch set)
  • save save configuration after successful call

Logic cycles

create_cycle - create new cycle

Creates new cycle.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 144
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create_cycle",
    "params": {
        "i": "tests/test_cycle",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 144' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create_cycle", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 144' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create_cycle", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create_cycle",
  "params": {
    "i": "tests/test_cycle",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:144 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '144', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create_cycle', 'params': {'i': 'tests/test_cycle', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 439
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "description": "",
        "full_id": "tests/test_cycle",
        "group": "tests",
        "ict": 100,
        "id": "test_cycle",
        "interval": 1,
        "iterations": 0,
        "macro": null,
        "macro_args": [],
        "macro_kwargs": {},
        "oid": "lcycle:tests/test_cycle",
        "on_error": null,
        "status": 0,
        "type": "lcycle"
    }
}

Parameters:

  • k API key with master permissions
  • i cycle id

Optionally:

  • g cycle group
  • v cycle properties (dict) or human-readable input
destroy_cycle - delete cycle

Deletes cycle. If cycle is running, it is stopped before deletion.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 145
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "destroy_cycle",
    "params": {
        "i": "tests/test_cycle",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 145' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "destroy_cycle", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 145' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "destroy_cycle", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "destroy_cycle",
  "params": {
    "i": "tests/test_cycle",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:145 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '145', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'destroy_cycle', 'params': {'i': 'tests/test_cycle', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i cycle id
get_cycle - get cycle information

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 141
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_cycle",
    "params": {
        "i": "tests/test_cycle",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 141' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_cycle", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 141' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_cycle", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_cycle",
  "params": {
    "i": "tests/test_cycle",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:141 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '141', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_cycle', 'params': {'i': 'tests/test_cycle', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 453
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "description": "",
        "full_id": "tests/test_cycle",
        "group": "tests",
        "ict": 100,
        "id": "test_cycle",
        "interval": 1,
        "iterations": 0,
        "macro": "tests/test_macro",
        "macro_args": [],
        "macro_kwargs": {},
        "oid": "lcycle:tests/test_cycle",
        "on_error": null,
        "status": 0,
        "type": "lcycle"
    }
}

Parameters:

  • k valid API key
  • i cycle id

Returns:

field “value” contains real average cycle interval

groups_cycle - get cycle groups list

Get the list of cycles. Useful e.g. for custom interfaces.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 111
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "groups_cycle",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 111' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "groups_cycle", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 111' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "groups_cycle", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "groups_cycle",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:111 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '111', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'groups_cycle', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 76
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        "tests"
    ]
}

Parameters:

  • k valid API key
list_cycle_props - get cycle configuration properties

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 148
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_cycle_props",
    "params": {
        "i": "tests/test_cycle",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 148' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_cycle_props", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 148' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_cycle_props", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_cycle_props",
  "params": {
    "i": "tests/test_cycle",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:148 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '148', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_cycle_props', 'params': {'i': 'tests/test_cycle', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 302
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "autostart": false,
        "description": "",
        "ict": 100,
        "interval": 1,
        "macro": "tests/test_macro",
        "macro_args": [],
        "macro_kwargs": {},
        "notify_events": 2,
        "on_error": null
    }
}

Parameters:

  • k API key with master permissions
  • i cycle id
list_cycles - get cycle list

Get the list of all available cycles.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 110
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_cycles",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 110' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_cycles", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 110' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_cycles", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_cycles",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:110 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '110', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_cycles', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 973
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "description": "",
            "full_id": "tests/cycle1",
            "group": "tests",
            "ict": 100,
            "id": "cycle1",
            "interval": 1,
            "iterations": 0,
            "macro": null,
            "macro_args": [],
            "macro_kwargs": {},
            "oid": "lcycle:tests/cycle1",
            "on_error": null,
            "status": 0,
            "type": "lcycle"
        },
        {
            "description": "",
            "full_id": "tests/test_cycle",
            "group": "tests",
            "ict": 100,
            "id": "test_cycle",
            "interval": 1,
            "iterations": 0,
            "macro": "tests/test_macro",
            "macro_args": [],
            "macro_kwargs": {},
            "oid": "lcycle:tests/test_cycle",
            "on_error": null,
            "status": 0,
            "type": "lcycle"
        }
    ]
}

Parameters:

  • k valid API key

Optionally:

  • g filter by group
reset_cycle_stats - reset cycle statistic

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 149
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "reset_cycle_stats",
    "params": {
        "i": "tests/test_cycle",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 149' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "reset_cycle_stats", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 149' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "reset_cycle_stats", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "reset_cycle_stats",
  "params": {
    "i": "tests/test_cycle",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:149 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '149', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'reset_cycle_stats', 'params': {'i': 'tests/test_cycle', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i cycle id
set_cycle_prop - set cycle property

Set configuration parameters of the cycle.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 225
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_cycle_prop",
    "params": {
        "i": "tests/test_cycle",
        "k": "mykey",
        "p": "macro",
        "save": "true",
        "v": "tests/test_macro"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 225' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_cycle_prop", "params": {"i": "tests/test_cycle", "k": "mykey", "p": "macro", "save": "true", "v": "tests/test_macro"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 225' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_cycle_prop", "params": {"i": "tests/test_cycle", "k": "mykey", "p": "macro", "save": "true", "v": "tests/test_macro"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_cycle_prop",
  "params": {
    "i": "tests/test_cycle",
    "k": "mykey",
    "p": "macro",
    "save": "true",
    "v": "tests/test_macro"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:225 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '225', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_cycle_prop', 'params': {'i': 'tests/test_cycle', 'k': 'mykey', 'p': 'macro', 'save': 'true', 'v': 'tests/test_macro'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i item id
  • p property name (or empty for batch set)

Optionally:

  • v propery value (or dict for batch set)
  • save save configuration after successful call
start_cycle - start cycle

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 143
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "start_cycle",
    "params": {
        "i": "tests/test_cycle",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 143' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "start_cycle", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 143' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "start_cycle", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "start_cycle",
  "params": {
    "i": "tests/test_cycle",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:143 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '143', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'start_cycle', 'params': {'i': 'tests/test_cycle', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i cycle id
stop_cycle - stop cycle

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 142
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "stop_cycle",
    "params": {
        "i": "tests/test_cycle",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 142' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "stop_cycle", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 142' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "stop_cycle", "params": {"i": "tests/test_cycle", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "stop_cycle",
  "params": {
    "i": "tests/test_cycle",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:142 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '142', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'stop_cycle', 'params': {'i': 'tests/test_cycle', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i cycle id

Optionally:

  • wait wait until cycle is stopped

Logic macros

create_macro - create new macro

Creates new macro. Macro code should be put in xc/lm manually.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 144
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create_macro",
    "params": {
        "i": "tests/test_macro",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 144' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create_macro", "params": {"i": "tests/test_macro", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 144' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create_macro", "params": {"i": "tests/test_macro", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create_macro",
  "params": {
    "i": "tests/test_macro",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:144 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '144', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create_macro', 'params': {'i': 'tests/test_macro', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 252
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "action_enabled": true,
        "full_id": "tests/test_macro",
        "group": "tests",
        "id": "test_macro",
        "oid": "lmacro:tests/test_macro",
        "type": "lmacro"
    }
}

Parameters:

  • k API key with master permissions
  • i macro id

Optionally:

  • g macro group
destroy_macro - delete macro

Deletes macro.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 145
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "destroy_macro",
    "params": {
        "i": "tests/test_macro",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 145' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "destroy_macro", "params": {"i": "tests/test_macro", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 145' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "destroy_macro", "params": {"i": "tests/test_macro", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "destroy_macro",
  "params": {
    "i": "tests/test_macro",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:145 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '145', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'destroy_macro', 'params': {'i': 'tests/test_macro', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i macro id
get_macro - get macro information

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 141
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_macro",
    "params": {
        "i": "tests/test_macro",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 141' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_macro", "params": {"i": "tests/test_macro", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 141' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_macro", "params": {"i": "tests/test_macro", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_macro",
  "params": {
    "i": "tests/test_macro",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:141 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '141', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_macro', 'params': {'i': 'tests/test_macro', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 317
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "action_enabled": true,
        "description": "",
        "full_id": "tests/test_macro",
        "group": "tests",
        "id": "test_macro",
        "oid": "lmacro:tests/test_macro",
        "src": "out='test passed'\n",
        "type": "lmacro"
    }
}

Parameters:

  • k valid API key
  • i macro id
groups_macro - get macro groups list

Get the list of macros. Useful e.g. for custom interfaces.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 111
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "groups_macro",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 111' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "groups_macro", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 111' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "groups_macro", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "groups_macro",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:111 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '111', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'groups_macro', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 76
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        "tests"
    ]
}

Parameters:

  • k valid API key
list_macro_props - get macro configuration properties

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 148
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_macro_props",
    "params": {
        "i": "tests/test_macro",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 148' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_macro_props", "params": {"i": "tests/test_macro", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 148' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_macro_props", "params": {"i": "tests/test_macro", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_macro_props",
  "params": {
    "i": "tests/test_macro",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:148 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '148', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_macro_props', 'params': {'i': 'tests/test_macro', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 256
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "action_enabled": true,
        "action_exec": null,
        "description": "",
        "notify_events": 2,
        "pass_errors": false,
        "send_critical": false,
        "src": ""
    }
}

Parameters:

  • k API key with master permissions
  • i macro id
list_macros - get macro list

Get the list of all available macros.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 110
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_macros",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 110' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_macros", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 110' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_macros", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_macros",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:110 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '110', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_macros', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 580
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "action_enabled": true,
            "description": "",
            "full_id": "tests/test1",
            "group": "tests",
            "id": "test1",
            "oid": "lmacro:tests/test1",
            "type": "lmacro"
        },
        {
            "action_enabled": true,
            "description": "",
            "full_id": "tests/test_macro",
            "group": "tests",
            "id": "test_macro",
            "oid": "lmacro:tests/test_macro",
            "type": "lmacro"
        }
    ]
}

Parameters:

  • k valid API key

Optionally:

  • g filter by group
result - macro execution result

Get macro execution results either by action uuid or by macro id.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 138
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "result",
    "params": {
        "i": "tests/test_macro",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 138' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "result", "params": {"i": "tests/test_macro", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 138' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "result", "params": {"i": "tests/test_macro", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "result",
  "params": {
    "i": "tests/test_macro",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:138 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '138', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'result', 'params': {'i': 'tests/test_macro', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 55
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": []
}

Parameters:

  • k valid API key

Optionally:

  • u action uuid or
  • i macro id
  • g filter by unit group
  • s filter by action status: Q for queued, R for running, F for finished

Returns:

list or single serialized action object

run - execute macro

Execute a macro with the specified arguments.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 135
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "run",
    "params": {
        "i": "tests/test_macro",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 135' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "run", "params": {"i": "tests/test_macro", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 135' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "run", "params": {"i": "tests/test_macro", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "run",
  "params": {
    "i": "tests/test_macro",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:135 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '135', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'run', 'params': {'i': 'tests/test_macro', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 628
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "args": [],
        "err": "",
        "exitcode": null,
        "finished": false,
        "finished_in": null,
        "item_group": "tests",
        "item_id": "test_macro",
        "item_oid": "lmacro:tests/test_macro",
        "item_type": "lmacro",
        "kwargs": {},
        "out": "",
        "priority": 100,
        "status": "queued",
        "time": {
            "created": 1604185854.8309932,
            "pending": 1604185854.8320856,
            "queued": 1604185854.8345957
        },
        "uuid": "117b6422-f9a1-47be-9158-a4f34d9f5202"
    }
}

Parameters:

  • k valid API key
  • i macro id

Optionally:

  • a macro arguments, array or space separated
  • kw macro keyword arguments, name=value, comma separated or dict
  • w wait for the completion for the specified number of seconds
  • u action UUID (will be auto generated if none specified)
  • p queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”
set_macro_prop - set macro configuration property

Set configuration parameters of the macro.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 219
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_macro_prop",
    "params": {
        "i": "tests/test_macro",
        "k": "mykey",
        "p": "pass_errors",
        "save": "true",
        "v": "true"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 219' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_macro_prop", "params": {"i": "tests/test_macro", "k": "mykey", "p": "pass_errors", "save": "true", "v": "true"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 219' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_macro_prop", "params": {"i": "tests/test_macro", "k": "mykey", "p": "pass_errors", "save": "true", "v": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_macro_prop",
  "params": {
    "i": "tests/test_macro",
    "k": "mykey",
    "p": "pass_errors",
    "save": "true",
    "v": "true"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:219 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '219', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_macro_prop', 'params': {'i': 'tests/test_macro', 'k': 'mykey', 'p': 'pass_errors', 'save': 'true', 'v': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i item id
  • p property name (or empty for batch set)

Optionally:

  • v propery value (or dict for batch set)
  • save save configuration after successful call

Macro extensions

get_ext - get loaded extension information

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 129
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_ext",
    "params": {
        "i": "test_a",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 129' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_ext", "params": {"i": "test_a", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 129' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_ext", "params": {"i": "test_a", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_ext",
  "params": {
    "i": "test_a",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:129 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '129', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_ext', 'params': {'i': 'test_a', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 824
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "api": 7,
        "author": "Altertech Group, https://www.altertech.com/",
        "cfg": {
            "sdir": "/opt/data/snd"
        },
        "description": "Play audio file",
        "help": "\nPlays audio file inside the specified directory. The file path should be\nrelative to the directory root, witout a starting slash.\n\nIf external playback command is not specified, \"sounddevice\" and \"soundfile\"\npython modules must be present in system.\n\nParams for external command: %f - file, %g - gain, e.g. \"play %f gain %g\", if\nno %f is specified, file name is automatically added to the end.\n",
        "id": "test_a",
        "license": "Apache License 2.0",
        "mod": "audio",
        "mods_required": [],
        "version": "1.3.0"
    }
}

Parameters:

  • k API key with master permissions
  • i extension ID
list_ext - get list of available macro extensions

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 107
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_ext",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 107' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_ext", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 107' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_ext", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_ext",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:107 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '107', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_ext', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 135
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "id": "test_a",
            "mod": "audio"
        }
    ]
}

Parameters:

  • k API key with master permissions

Optionally:

  • full get full information
list_ext_mods - get list of available extension modules

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 112
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_ext_mods",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 112' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_ext_mods", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 112' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_ext_mods", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_ext_mods",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:112 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '112', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_ext_mods', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 3342
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "api": 7,
            "author": "Altertech Group, https://www.altertech.com/",
            "description": "Play audio file",
            "help": "\nPlays audio file inside the specified directory. The file path should be\nrelative to the directory root, witout a starting slash.\n\nIf external playback command is not specified, \"sounddevice\" and \"soundfile\"\npython modules must be present in system.\n\nParams for external command: %f - file, %g - gain, e.g. \"play %f gain %g\", if\nno %f is specified, file name is automatically added to the end.\n",
            "id": null,
            "license": "Apache License 2.0",
            "mod": "audio",
            "mods_required": [],
            "version": "1.3.0"
        },
        {
            "api": 7,
            "author": "Altertech Group, https://www.altertech.com/",
            "description": "Generic macro extension, don't use",
            "help": "\nThis is generic extension for using as a base for all other LM PLC macro\nextensions. For a list of the available functions look directly into\nthe extension code or to EVA ICS documentation.\n",
            "id": null,
            "license": "Apache License 2.0",
            "mod": "generic",
            "mods_required": [],
            "version": "3.3.2"
        },
        {
            "api": 7,
            "author": "Altertech Group, https://www.altertech.com/",
            "description": "Autotest",
            "help": "\nTest ext\n",
            "id": null,
            "license": "Apache License 2.0",
            "mod": "myext",
            "mods_required": [],
            "version": "1.0.1"
        },
        {
            "api": 7,
            "author": "Altertech Group, https://www.altertech.com/",
            "description": "Push client for Roboger",
            "help": "\nPush client for Roboger event pager (https://www.roboger.com,\nhttps://github.com/alttch/roboger). Refer to pyrpush module documentation for\nmore info: https://pypi.org/project/pyrpush/\n",
            "id": null,
            "license": "Apache License 2.0",
            "mod": "rpush",
            "mods_required": [
                "pyrpush"
            ],
            "version": "1.4.0"
        },
        {
            "api": 7,
            "author": "Altertech Group, https://www.altertech.com/",
            "description": "Run macro on remote LM PLC",
            "help": "\nAllows to run macros on remote LM PLC\n",
            "id": null,
            "license": "Apache License 2.0",
            "mod": "run_remote",
            "mods_required": [],
            "version": "1.3.0"
        },
        {
            "api": 7,
            "author": "Altertech Group, https://www.altertech.com/",
            "description": "Text-to-speech via ttsbroker",
            "help": "\nText-to-speech engine via ttsbroker Python module. Refer to module\ndocumentation for more info: https://pypi.org/project/ttsbroker/\n\nParams for external command: %f - file, if no %f is specified, file name is\nautomatically added to the end.\n",
            "id": null,
            "license": "Apache License 2.0",
            "mod": "tts",
            "mods_required": [
                "ttsbroker"
            ],
            "version": "1.3.0"
        }
    ]
}

Parameters:

  • k API key with master permissions
load_ext - load extension module

Loads:doc:macro extension</lm/ext>.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 211
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "load_ext",
    "params": {
        "c": "sdir=/opt/data/snd",
        "i": "test_a",
        "k": "mykey",
        "m": "audio",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 211' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "load_ext", "params": {"c": "sdir=/opt/data/snd", "i": "test_a", "k": "mykey", "m": "audio", "save": "true"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 211' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "load_ext", "params": {"c": "sdir=/opt/data/snd", "i": "test_a", "k": "mykey", "m": "audio", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "load_ext",
  "params": {
    "c": "sdir=/opt/data/snd",
    "i": "test_a",
    "k": "mykey",
    "m": "audio",
    "save": "true"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:211 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '211', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'load_ext', 'params': {'c': 'sdir=/opt/data/snd', 'i': 'test_a', 'k': 'mykey', 'm': 'audio', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 824
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "api": 7,
        "author": "Altertech Group, https://www.altertech.com/",
        "cfg": {
            "sdir": "/opt/data/snd"
        },
        "description": "Play audio file",
        "help": "\nPlays audio file inside the specified directory. The file path should be\nrelative to the directory root, witout a starting slash.\n\nIf external playback command is not specified, \"sounddevice\" and \"soundfile\"\npython modules must be present in system.\n\nParams for external command: %f - file, %g - gain, e.g. \"play %f gain %g\", if\nno %f is specified, file name is automatically added to the end.\n",
        "id": "test_a",
        "license": "Apache License 2.0",
        "mod": "audio",
        "mods_required": [],
        "version": "1.3.0"
    }
}

Parameters:

  • k API key with master permissions
  • i extension ID
  • m extension module

Optionally:

  • c extension configuration
  • save save extension configuration after successful call
modhelp_ext - get extension usage help

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 158
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "modhelp_ext",
    "params": {
        "c": "functions",
        "k": "mykey",
        "m": "audio"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 158' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "modhelp_ext", "params": {"c": "functions", "k": "mykey", "m": "audio"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 158' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "modhelp_ext", "params": {"c": "functions", "k": "mykey", "m": "audio"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "modhelp_ext",
  "params": {
    "c": "functions",
    "k": "mykey",
    "m": "audio"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:158 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '158', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'modhelp_ext', 'params': {'c': 'functions', 'k': 'mykey', 'm': 'audio'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 124
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "play(soundfile, gain=0, wait=True)": "Play audio file"
    }
}

Parameters:

  • k API key with master permissions
  • m extension name (without .py extension)
  • c help context (cfg or functions)
modinfo_ext - get extension module info

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 132
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "modinfo_ext",
    "params": {
        "k": "mykey",
        "m": "audio"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 132' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "modinfo_ext", "params": {"k": "mykey", "m": "audio"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 132' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "modinfo_ext", "params": {"k": "mykey", "m": "audio"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "modinfo_ext",
  "params": {
    "k": "mykey",
    "m": "audio"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:132 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '132', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'modinfo_ext', 'params': {'k': 'mykey', 'm': 'audio'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 736
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "api": 7,
        "author": "Altertech Group, https://www.altertech.com/",
        "description": "Play audio file",
        "help": "\nPlays audio file inside the specified directory. The file path should be\nrelative to the directory root, witout a starting slash.\n\nIf external playback command is not specified, \"sounddevice\" and \"soundfile\"\npython modules must be present in system.\n\nParams for external command: %f - file, %g - gain, e.g. \"play %f gain %g\", if\nno %f is specified, file name is automatically added to the end.\n",
        "license": "Apache License 2.0",
        "mod": "audio",
        "mods_required": [],
        "version": "1.3.0"
    }
}

Parameters:

  • k API key with master permissions
  • m extension module name (without .py extension)
set_ext_prop - set extension configuration property

appends property to extension configuration and reloads module

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 192
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_ext_prop",
    "params": {
        "i": "test_a",
        "k": "mykey",
        "p": "d",
        "save": "true",
        "v": 2
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 192' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_ext_prop", "params": {"i": "test_a", "k": "mykey", "p": "d", "save": "true", "v": 2}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 192' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_ext_prop", "params": {"i": "test_a", "k": "mykey", "p": "d", "save": "true", "v": 2}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_ext_prop",
  "params": {
    "i": "test_a",
    "k": "mykey",
    "p": "d",
    "save": "true",
    "v": 2
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:192 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '192', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_ext_prop', 'params': {'i': 'test_a', 'k': 'mykey', 'p': 'd', 'save': 'true', 'v': 2}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i extension id
  • p property name (or empty for batch set)

Optionally:

  • v propery value (or dict for batch set)
  • save save configuration after successful call
unload_ext - unload macro extension

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 132
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "unload_ext",
    "params": {
        "i": "test_a",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 132' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "unload_ext", "params": {"i": "test_a", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 132' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "unload_ext", "params": {"i": "test_a", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "unload_ext",
  "params": {
    "i": "test_a",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:132 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '132', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'unload_ext', 'params': {'i': 'test_a', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i extension ID

Remote controllers

append_controller - connect remote UC via HTTP

Connects remote UC controller to the local.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 192
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "append_controller",
    "params": {
        "a": "secretkey",
        "k": "mykey",
        "save": "true",
        "u": "localhost"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 192' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "append_controller", "params": {"a": "secretkey", "k": "mykey", "save": "true", "u": "localhost"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 192' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "append_controller", "params": {"a": "secretkey", "k": "mykey", "save": "true", "u": "localhost"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "append_controller",
  "params": {
    "a": "secretkey",
    "k": "mykey",
    "save": "true",
    "u": "localhost"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:192 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '192', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'append_controller', 'params': {'a': 'secretkey', 'k': 'mykey', 'save': 'true', 'u': 'localhost'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 624
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
        "result": {
            "build": "2019031405",
            "connected": true,
            "description": "",
            "enabled": true,
            "full_id": "uc/ws1-v1",
            "group": "uc",
            "id": "ws1-v1",
            "managed": false,
            "mqtt_update": null,
            "oid": "remote_uc:uc/ws1-v1",
            "proto": "http",
            "static": true,
            "type": "remote_uc",
            "version": "3.2.0"
        }
}

Parameters:

  • k API key with master permissions
  • u UC API uri (proto://host:port, port not required if default)
  • a remote controller API key ($key to use local key)

Optionally:

  • m ref:MQTT notifier<mqtt_> to exchange item states in real time (default: eva_1)
  • s verify remote SSL certificate or pass invalid
  • t timeout (seconds) for the remote controller API calls
  • save save connected controller configuration on the disk immediately after creation
disable_controller - disable connected controller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 167
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "disable_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 167' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "disable_controller", "params": {"i": "uc/ws1-v1", "k": "mykey", "save": "true"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 167' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "disable_controller", "params": {"i": "uc/ws1-v1", "k": "mykey", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "disable_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey",
    "save": "true"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:167 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '167', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'disable_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id

Optionally:

  • save save configuration after successful call
enable_controller - enable connected controller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 166
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "enable_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 166' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "enable_controller", "params": {"i": "uc/ws1-v1", "k": "mykey", "save": "true"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 166' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "enable_controller", "params": {"i": "uc/ws1-v1", "k": "mykey", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "enable_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey",
    "save": "true"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:166 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '166', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'enable_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id

Optionally:

  • save save configuration after successful call
get_controller - get connected controller information

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 139
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 139' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 139' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:139 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '139', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 512
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
        "result": {
            "build": "2019031405",
            "connected": true,
            "description": "",
            "enabled": true,
            "full_id": "uc/ws1-v1",
            "group": "uc",
            "id": "ws1-v1",
            "managed": false,
            "mqtt_update": null,
            "oid": "remote_uc:uc/ws1-v1",
            "proto": "http",
            "static": true,
            "type": "remote_uc",
            "version": "3.2.0"
        }
}

Parameters:

  • k API key with master permissions
  • i controller id
list_controller_props - get controller connection parameters

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 146
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_controller_props",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 146' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_controller_props", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 146' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_controller_props", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_controller_props",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:146 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '146', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_controller_props', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 431
Content-Type: application/json
Expires: 0
Pragma: no-cache


{
    "id": 1,
    "jsonrpc": "2.0",
        "result": {
                "description": "",
                "enabled": true,
                "key": "secretkey",
                "mqtt_update": null,
                "reload_interval": 300,
                "retries": 2,
                "ssl_verify": true,
                "static": true,
                "timeout": 5.0,
                "uri": "http://localhost:8812"
            }
}

Parameters:

  • k API key with master permissions
  • i controller id
list_controllers - get controllers list

Get the list of all connected UC controllers.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 115
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_controllers",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 115' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_controllers", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 115' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_controllers", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_controllers",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:115 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '115', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_controllers', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 529
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "build": "2020103101",
            "connected": true,
            "description": "",
            "enabled": true,
            "full_id": "uc/lab-ws2",
            "group": "uc",
            "id": "lab-ws2",
            "managed": false,
            "mqtt_update": "eva_1",
            "oid": "remote_uc:uc/lab-ws2",
            "proto": "mqtt",
            "static": true,
            "type": "remote_uc",
            "version": "3.3.2"
        }
    ]
}

Parameters:

  • k API key with master permissions
list_remote - get a list of items from connected UCs

Get a list of the items loaded from the connected UC controllers. Useful to debug the controller connections.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_remote",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_remote", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_remote", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_remote",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_remote', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 1628
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
        "result":
            [
                {
                    "controller_id": "uc/ws1-v1",
                    "description": "",
                    "full_id": "env/temp_test",
                    "group": "env",
                    "id": "temp_test",
                    "loc_x": null,
                    "loc_y": null,
                    "loc_z": null,
                    "location": "",
                    "oid": "sensor:env/temp_test",
                    "status": 0,
                    "type": "sensor",
                    "value": "null"
                },
                {
                    "action_enabled": true,
                    "controller_id": "uc/ws1-v1",
                    "description": "",
                    "full_id": "nogroup/test2",
                    "group": "nogroup",
                    "id": "test2",
                    "loc_x": null,
                    "loc_y": null,
                    "loc_z": null,
                    "location": "",
                    "nstatus": -1,
                    "nvalue": "null",
                    "oid": "unit:nogroup/test2",
                    "status": -1,
                    "status_labels": [
                        {
                            "label": "OFF",
                            "status": 0
                        },
                        {
                            "label": "ON",
                            "status": 1
                        }
                    ],
                    "type": "unit",
                    "value": "null"
                }
            ]
}

Parameters:

  • k API key with master permissions

Optionally:

  • i controller id
  • g filter by item group
  • p filter by item type
reload_controller - reload controller

Reloads items from connected UC

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 142
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "reload_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 142' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "reload_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 142' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "reload_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "reload_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:142 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '142', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'reload_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id
remove_controller - disconnect controller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 142
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "remove_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 142' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "remove_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 142' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "remove_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "remove_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:142 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '142', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'remove_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id
set_controller_prop - set controller connection parameters

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 217
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_controller_prop",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey",
        "p": "reload_interval",
        "save": "true",
        "v": 60
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 217' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_controller_prop", "params": {"i": "uc/ws1-v1", "k": "mykey", "p": "reload_interval", "save": "true", "v": 60}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 217' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_controller_prop", "params": {"i": "uc/ws1-v1", "k": "mykey", "p": "reload_interval", "save": "true", "v": 60}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_controller_prop",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey",
    "p": "reload_interval",
    "save": "true",
    "v": 60
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:217 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '217', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_controller_prop', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey', 'p': 'reload_interval', 'save': 'true', 'v': 60}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id
  • p property name (or empty for batch set)

Optionally:

  • v propery value (or dict for batch set)
  • save save configuration after successful call
test_controller - test connection to remote controller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 140
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "test_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 140' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "test_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 140' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "test_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "test_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:140 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '140', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'test_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id
upnp_rescan_controllers - rescan controllers via UPnP

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 122
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "upnp_rescan_controllers",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 122' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "upnp_rescan_controllers", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 122' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "upnp_rescan_controllers", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "upnp_rescan_controllers",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:122 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '122', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'upnp_rescan_controllers', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions

Scheduled jobs

create_job - create new job

Creates new scheduled job. Job id (UUID) is generated automatically unless specified.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 109
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "create_job",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 109' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "create_job", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 109' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "create_job", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "create_job",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:109 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '109', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'create_job', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 373
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "description": "",
        "enabled": false,
        "every": "",
        "id": "b09cc59d-4be0-4797-b98d-f43b0bcef355",
        "last": null,
        "macro": null,
        "macro_args": [],
        "macro_kwargs": {},
        "oid": "job:jobs/b09cc59d-4be0-4797-b98d-f43b0bcef355",
        "type": "job"
    }
}

Parameters:

  • k API key with master permissions

Optionally:

  • u job UUID to set
  • v job properties (dict) or human-readable input
  • e enable job after creation
  • save save job configuration immediately
destroy_job - delete job

Deletes scheduled job.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 163
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "destroy_job",
    "params": {
        "i": "9c6e8c99-56fe-490c-8442-4936ba777499",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 163' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "destroy_job", "params": {"i": "9c6e8c99-56fe-490c-8442-4936ba777499", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 163' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "destroy_job", "params": {"i": "9c6e8c99-56fe-490c-8442-4936ba777499", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "destroy_job",
  "params": {
    "i": "9c6e8c99-56fe-490c-8442-4936ba777499",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:163 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '163', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'destroy_job', 'params': {'i': '9c6e8c99-56fe-490c-8442-4936ba777499', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i job id
get_job - get job information

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 159
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_job",
    "params": {
        "i": "9c6e8c99-56fe-490c-8442-4936ba777499",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 159' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_job", "params": {"i": "9c6e8c99-56fe-490c-8442-4936ba777499", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 159' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_job", "params": {"i": "9c6e8c99-56fe-490c-8442-4936ba777499", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_job",
  "params": {
    "i": "9c6e8c99-56fe-490c-8442-4936ba777499",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:159 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '159', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_job', 'params': {'i': '9c6e8c99-56fe-490c-8442-4936ba777499', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 401
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "description": "",
        "enabled": false,
        "every": "",
        "id": "9c6e8c99-56fe-490c-8442-4936ba777499",
        "last": null,
        "macro": null,
        "macro_args": [
            "test"
        ],
        "macro_kwargs": {},
        "oid": "job:jobs/9c6e8c99-56fe-490c-8442-4936ba777499",
        "type": "job"
    }
}

Parameters:

  • k API key with master permissions
  • i job id
list_job_props - list job properties

Get all editable parameters of the scheduled job.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 166
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_job_props",
    "params": {
        "i": "9c6e8c99-56fe-490c-8442-4936ba777499",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 166' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_job_props", "params": {"i": "9c6e8c99-56fe-490c-8442-4936ba777499", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 166' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_job_props", "params": {"i": "9c6e8c99-56fe-490c-8442-4936ba777499", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_job_props",
  "params": {
    "i": "9c6e8c99-56fe-490c-8442-4936ba777499",
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:166 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '166', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_job_props', 'params': {'i': '9c6e8c99-56fe-490c-8442-4936ba777499', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 266
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "description": "",
        "enabled": false,
        "every": "",
        "macro": null,
        "macro_args": [
            "test"
        ],
        "macro_kwargs": {},
        "notify_events": 2
    }
}

Parameters:

  • k API key with master permissions
  • i job id
list_jobs - get jobs list

Get the list of all available scheduled jobs.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 108
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_jobs",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 108' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_jobs", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 108' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_jobs", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_jobs",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:108 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '108', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_jobs', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 1965
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "description": "",
            "enabled": false,
            "every": "",
            "id": "66c93cce-501f-4002-8141-c7e51f584d6f",
            "last": null,
            "macro": null,
            "macro_args": [],
            "macro_kwargs": {},
            "oid": "job:jobs/66c93cce-501f-4002-8141-c7e51f584d6f",
            "type": "job"
        },
        {
            "description": "",
            "enabled": false,
            "every": "",
            "id": "484ed7f9-0fed-4502-8f01-9f9dd2d78108",
            "last": null,
            "macro": null,
            "macro_args": [],
            "macro_kwargs": {},
            "oid": "job:jobs/484ed7f9-0fed-4502-8f01-9f9dd2d78108",
            "type": "job"
        },
        {
            "description": "",
            "enabled": false,
            "every": "",
            "id": "3c8b8a7c-b4d8-411b-8d3e-cd64bd2734cd",
            "last": null,
            "macro": null,
            "macro_args": [],
            "macro_kwargs": {},
            "oid": "job:jobs/3c8b8a7c-b4d8-411b-8d3e-cd64bd2734cd",
            "type": "job"
        },
        {
            "description": "",
            "enabled": false,
            "every": "",
            "id": "9c6e8c99-56fe-490c-8442-4936ba777499",
            "last": null,
            "macro": null,
            "macro_args": [
                "test"
            ],
            "macro_kwargs": {},
            "oid": "job:jobs/9c6e8c99-56fe-490c-8442-4936ba777499",
            "type": "job"
        },
        {
            "description": "",
            "enabled": false,
            "every": "",
            "id": "b09cc59d-4be0-4797-b98d-f43b0bcef355",
            "last": null,
            "macro": null,
            "macro_args": [],
            "macro_kwargs": {},
            "oid": "job:jobs/b09cc59d-4be0-4797-b98d-f43b0bcef355",
            "type": "job"
        }
    ]
}

Parameters:

  • k API key with master permissions
set_job_prop - set job parameters

Set configuration parameters of the scheduled job.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 236
Host: localhost:8817

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_job_prop",
    "params": {
        "i": "9c6e8c99-56fe-490c-8442-4936ba777499",
        "k": "mykey",
        "p": "macro_args",
        "save": "true",
        "v": "test"
    }
}

curl

curl -i -X POST http://localhost:8817/jrpc -H 'Accept: application/json' -H 'Content-Length: 236' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_job_prop", "params": {"i": "9c6e8c99-56fe-490c-8442-4936ba777499", "k": "mykey", "p": "macro_args", "save": "true", "v": "test"}}'

wget

wget -S -O- http://localhost:8817/jrpc --header='Accept: application/json' --header='Content-Length: 236' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_job_prop", "params": {"i": "9c6e8c99-56fe-490c-8442-4936ba777499", "k": "mykey", "p": "macro_args", "save": "true", "v": "test"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_job_prop",
  "params": {
    "i": "9c6e8c99-56fe-490c-8442-4936ba777499",
    "k": "mykey",
    "p": "macro_args",
    "save": "true",
    "v": "test"
  }
}' | http POST http://localhost:8817/jrpc Accept:application/json Content-Length:236 Content-Type:application/json

python-requests

requests.post('http://localhost:8817/jrpc', headers={'Accept': 'application/json', 'Content-Length': '236', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_job_prop', 'params': {'i': '9c6e8c99-56fe-490c-8442-4936ba777499', 'k': 'mykey', 'p': 'macro_args', 'save': 'true', 'v': 'test'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i job id
  • p property name (or empty for batch set)

Optionally:

  • v propery value (or dict for batch set)
  • save save configuration after successful call

SFA API

SCADA Final Aggregator API is used to manage EVA ICS cloud and aggregated resources.

This document describes API methods for direct and JSON RPC calls. For RESTful API look SFA RESTful API.

API basics

JSON RPC

JSON RPC 2.0 protocol is the primary EVA ICS API protocol. Note that default JSON RPC result is { “ok”: true } (instead of { “result”: “OK” } in the direct API). There’s no { result: “ERROR” } responses, as JSON RPC sends errors in “error” field.

If JSON RPC request is called without ID and server should not return a result, it will return http response with a code 202 Accepted.

Note

JSON RPC is recommended way to use EVA ICS API, unless direct method calling or RESTful is really required.

JSON RPC API URL:

http://<ip_address:8828>/jrpc

or

http://<ip_address:8828>

(all POST requests to the root URI are processed as JSON RPC)

JSON RPC payload encoding

EVA ICS supports JSON RPC payloads, encoded as generic JSON and as MessagePack. MessagePack encoding works faster, requires less bandwidth and is highly recommended to use.

To call API methods with MessagePack-encoded payloads, use Content-Type: application/msgpack HTTP request header.

JSON RPC error responses

JSON RPC calls return error codes equal to the codes of EVA API Client:

  • 1 the item or resource is not found
  • 2 access is denied with the set API key
  • 6 Attempt to call undefined API method/function
  • 10 API function failed (all errors not listed here fall within this category)
  • 11 API function is called with invalid params
  • 12 API function attempted to create resource which already exists and can’t be recreated until deleted/removed
  • 13 the resource is busy (in use) and can not be accessed/recreated or deleted at this moment
  • 14 the method is not implemented in/for requested resource

Response field “message” may contain additional information about error.

Warning

It’s highly not recommended to perform long API calls, calling API functions from JavaScript in a web browser (e.g. giving “w” param to action methods to wait until action finish). Web browser may repeat API call continuously, which may lead to absolutely unexpected behavior.

JSON RPC via HTTP GET

Embedded equipment sometimes can send HTTP GET requests only. JSON RPC API supports such calls as well.

To make JSON RPC API request with HTTP get, send it to:

http://<ip_address:8828>/jrpc?i=ID&m=METHOD&p=PARAMS

where:

  • ID request ID (any custom value). If not specified, API response isn’t sent back
  • METHOD JSON RPC method to call
  • PARAMS method params, as url-encoded JSON

E.g. the following HTTP GET request will invoke method “test” with request id=1 and params { “k”: “mykey” }:

http://<ip_address:8828>/jrpc?i=1&m=test&p=%7B%22k%22%3A%22mykey%22%7D

Note

JSON RPC API calls via HTTP GET are insecure, limited to 2048 bytes and can not be batch. Use JSON RPC via HTTP POST with JSON or MessagePack payload always when possible.

Direct API

Warning

Direct method calling is deprecated and scheduled to be removed (not implemented) in EVA ICS v4. Use JSON RPC API, whenever it is possible.

SFA API functions are called through URL request

http://<ip_address:8828>/sfa-api/function

If SSL is allowed in the controller configuration file, you can also use https calls.

Direct API responses

Good for backward compatibility with any devices, as all API functions can be called using GET and POST. When POST is used, the parameters can be passed to functions either as multipart/form-data or as JSON.

API key can be sent in request parameters, session (if enabled and user is logged in) or in HTTP X-Auth-Key header.

Standard responses in status/body:

  • 200 OK { “result”: “OK” } API call completed successfully.

Standard error responses in status:

  • 400 Bad Request Invalid request params
  • 403 Forbidden the API key has no access to this function or resource
  • 404 Not Found method or resource/object doesn’t exist
  • 405 Method Not Allowed API function/method not found or HTTP method is not either GET or POST
  • 409 Conflict resource/object already exists or is locked
  • 500 API Error API function execution has been failed. Check input parameters and server logs.

In case API function has been failed, response body will contain JSON data with _error field, which contains error message.

{
    "_error": "unable to add object, already present",
    "result": "ERROR"
}

Contents

Item functions

action - create unit control action

The call is considered successful when action is put into the action queue of selected unit.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 154
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "action",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey",
        "s": 1
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 154' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "action", "params": {"i": "unit:tests/unit1", "k": "mykey", "s": 1}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 154' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "action", "params": {"i": "unit:tests/unit1", "k": "mykey", "s": 1}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "action",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey",
    "s": 1
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:154 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '154', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'action', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey', 's': 1}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 623
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "err": "",
        "exitcode": null,
        "finished": true,
        "finished_in": 0.002784,
        "item_group": "tests",
        "item_id": "unit1",
        "item_oid": "unit:tests/unit1",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "refused",
        "time": {
            "created": 1604183929.5239828,
            "pending": 1604183929.5248153,
            "refused": 1604183929.5267668
        },
        "uuid": "f18e9f9d-2c37-427a-b54f-aa95125c417c"
    }
}

Parameters:

  • k valid API key
  • i unit id

Optionally:

  • s desired unit status
  • v desired unit value
  • w wait for the completion for the specified number of seconds
  • u action UUID (will be auto generated if none specified)
  • p queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”

Returns:

Serialized action object. If action is marked as dead, an error is returned (exception raised)

action_toggle - toggle unit status

Create unit control action to toggle its status (1->0, 0->1)

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 145
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "action_toggle",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 145' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "action_toggle", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 145' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "action_toggle", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "action_toggle",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:145 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '145', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'action_toggle', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 622
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "err": "",
        "exitcode": null,
        "finished": true,
        "finished_in": 0.0027514,
        "item_group": "tests",
        "item_id": "unit1",
        "item_oid": "unit:tests/unit1",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "refused",
        "time": {
            "created": 1604183929.566067,
            "pending": 1604183929.566936,
            "refused": 1604183929.5688183
        },
        "uuid": "891646ec-69f7-4946-940b-18af3fe8c997"
    }
}

Parameters:

  • k valid API key
  • i unit id

Optionally:

  • w wait for the completion for the specified number of seconds
  • u action UUID (will be auto generated if none specified)
  • p queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”

Returns:

Serialized action object. If action is marked as dead, an error is returned (exception raised)

disable_actions - disable unit actions

Disables unit to run and queue new actions.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 147
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "disable_actions",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 147' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "disable_actions", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 147' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "disable_actions", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "disable_actions",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:147 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '147', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'disable_actions', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i unit id
enable_actions - enable unit actions

Enables unit to run and queue new actions.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 146
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "enable_actions",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 146' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "enable_actions", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 146' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "enable_actions", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "enable_actions",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:146 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '146', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'enable_actions', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i unit id
groups - get item group list

Get the list of item groups. Useful e.g. for custom interfaces.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 126
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "groups",
    "params": {
        "k": "mykey",
        "p": "unit"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 126' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "groups", "params": {"k": "mykey", "p": "unit"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 126' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "groups", "params": {"k": "mykey", "p": "unit"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "groups",
  "params": {
    "k": "mykey",
    "p": "unit"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:126 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '126', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'groups', 'params': {'k': 'mykey', 'p': 'unit'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 102
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        "clone_of_tests",
        "tests"
    ]
}

Parameters:

  • k valid API key
  • p item type (unit [U], sensor [S] or lvar [LV])
kill - kill unit actions

Apart from canceling all queued commands, this function also terminates the current running action.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "kill",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "kill", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "kill", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "kill",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'kill', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i unit id

Returns:

If the current action of the unit cannot be terminated by configuration, the notice “pt” = “denied” will be returned additionally (even if there’s no action running)

q_clean - clean action queue of unit

Cancels all queued actions, keeps the current action running.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 139
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "q_clean",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 139' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "q_clean", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 139' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "q_clean", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "q_clean",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:139 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '139', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'q_clean', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i unit id
result - get action status or macro run result

Checks the result of the action by its UUID or returns the actions for the specified unit or execution result of the specified macro.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 138
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "result",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 138' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "result", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 138' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "result", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "result",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:138 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '138', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'result', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 1379
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "err": "",
            "exitcode": null,
            "finished": true,
            "finished_in": 0.0049543,
            "item_group": "tests",
            "item_id": "unit1",
            "item_oid": "unit:tests/unit1",
            "item_type": "unit",
            "nstatus": 1,
            "nvalue": null,
            "out": "",
            "priority": 100,
            "status": "refused",
            "time": {
                "created": 1604184438.5920656,
                "pending": 1604184438.5939715,
                "refused": 1604184438.59702
            },
            "uuid": "c02301d3-d780-4b2e-8e06-364ecd77ad92"
        },
        {
            "err": "",
            "exitcode": null,
            "finished": true,
            "finished_in": 0.0035744,
            "item_group": "tests",
            "item_id": "unit1",
            "item_oid": "unit:tests/unit1",
            "item_type": "unit",
            "nstatus": 1,
            "nvalue": null,
            "out": "",
            "priority": 100,
            "status": "refused",
            "time": {
                "created": 1604184438.6366618,
                "pending": 1604184438.6380665,
                "refused": 1604184438.6402361
            },
            "uuid": "49870d59-955a-42d8-96a1-7ca803146f0c"
        }
    ]
}

Parameters:

  • k valid API key

Optionally:

  • u action uuid or
  • i unit/macro oid (either uuid or oid must be specified)
  • g filter by unit group
  • s filter by action status: Q for queued, R for running, F for finished

Returns:

list or single serialized action object

state - get item state

State of the item or all items of the specified type can be obtained using state command.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 127
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "state",
    "params": {
        "k": "mykey",
        "p": "sensor"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 127' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "state", "params": {"k": "mykey", "p": "sensor"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 127' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "state", "params": {"k": "mykey", "p": "sensor"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "state",
  "params": {
    "k": "mykey",
    "p": "sensor"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:127 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '127', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'state', 'params': {'k': 'mykey', 'p': 'sensor'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 1556
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "controller_id": "uc/lab-ws2",
            "full_id": "clone_of_tests/sensor1",
            "group": "clone_of_tests",
            "id": "sensor1",
            "oid": "sensor:clone_of_tests/sensor1",
            "status": 0,
            "type": "sensor",
            "value": ""
        },
        {
            "controller_id": "uc/lab-ws2",
            "full_id": "clone_of_tests/sensor5",
            "group": "clone_of_tests",
            "id": "sensor5",
            "oid": "sensor:clone_of_tests/sensor5",
            "status": 0,
            "type": "sensor",
            "value": ""
        },
        {
            "controller_id": "uc/lab-ws2",
            "full_id": "clone_of_tests/t5",
            "group": "clone_of_tests",
            "id": "t5",
            "oid": "sensor:clone_of_tests/t5",
            "status": 0,
            "type": "sensor",
            "value": ""
        },
        {
            "controller_id": "uc/lab-ws2",
            "full_id": "tests/sensor1",
            "group": "tests",
            "id": "sensor1",
            "oid": "sensor:tests/sensor1",
            "status": 1,
            "type": "sensor",
            "value": "29.445"
        },
        {
            "controller_id": "uc/lab-ws2",
            "full_id": "tests/sensor5",
            "group": "tests",
            "id": "sensor5",
            "oid": "sensor:tests/sensor5",
            "status": 0,
            "type": "sensor",
            "value": ""
        }
    ]
}

Parameters:

  • k valid API key
  • p item type (unit [U], sensor [S] or lvar [LV])

Optionally:

  • i item id
  • g item group
  • full return full state
state_history - get item state history

State history of one item or several items of the specified type can be obtained using state_history command.

If master key is used, the method attempts to get stored state for an item even if it doesn’t present currently in system.

The method can return state log for disconnected items as well.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 149
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "state_history",
    "params": {
        "i": "sensor:env/temp_test",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 149' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "state_history", "params": {"i": "sensor:env/temp_test", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 149' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "state_history", "params": {"i": "sensor:env/temp_test", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "state_history",
  "params": {
    "i": "sensor:env/temp_test",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:149 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '149', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'state_history', 'params': {'i': 'sensor:env/temp_test', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 344
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "status": [
            1,
            1,
            1
        ],
        "t": [
            1604184434.4534957,
            1604184435.6571898,
            1604184439.1233687
        ],
        "value": [
            29.445,
            29.445,
            29.445
        ]
    }
}

Parameters:

  • k valid API key
  • a history notifier id (default: db_1)
  • i item oids or full ids, list or comma separated

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • l records limit (doesn’t work with “w”)
  • x state prop (“status” or “value”)
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • z Time zone (pytz, e.g. UTC or Europe/Prague)
  • w fill frame with the interval (e.g. “1T” - 1 min, “2H” - 2 hours etc.), start time is required, set to 1D if not specified
  • g output format (“list”, “dict” or “chart”, default is “list”)
  • c options for chart (dict or comma separated)
  • o extra options for notifier data request

Returns:

history data in specified format or chart image.

For chart, JSON RPC gets reply with “content_type” and “data” fields, where content is image content type. If PNG image format is selected, data is base64-encoded.

Options for chart (all are optional):

If option “w” (fill) is used, number of digits after comma may be specified. E.g. 5T:3 will output values with 3 digits after comma.

Additionally, SI prefix may be specified to convert value to kilos, megas etc, e.g. 5T:k:3 - divide value by 1000 and output 3 digits after comma. Valid prefixes are: k, M, G, T, P, E, Z, Y.

If binary prefix is required, it should be followed by “b”, e.g. 5T:Mb:3 - divide value by 2^20 and output 3 digits after comma.

state_log - get item state log

State log of a single item or group of the specified type can be obtained using state_log command.

note: only SQL notifiers are supported

Difference from state_history method:

  • state_log doesn’t optimize data to be displayed on charts * the data is returned from a database as-is * a single item OID or OID mask (e.g. sensor:env/#) can be specified

note: the method supports MQTT-style masks but only masks with wildcard-ending, like “type:group/subgroup/#” are supported.

The method can return state log for disconnected items as well.

For wildcard fetching, API key should have an access to the whole chosen group.

note: record limit means the limit for records, fetched from the database, but repeating state records are automatically grouped and the actual number of returned records can be lower than requested.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 143
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "state_log",
    "params": {
        "i": "sensor:tests/test1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 143' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "state_log", "params": {"i": "sensor:tests/test1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 143' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "state_log", "params": {"i": "sensor:tests/test1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "state_log",
  "params": {
    "i": "sensor:tests/test1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:143 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '143', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'state_log', 'params': {'i': 'sensor:tests/test1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 361
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "oid": "sensor:tests/test1",
            "status": 1,
            "t": 1607295696.9975107,
            "value": 359.0
        },
        {
            "oid": "sensor:tests/test1",
            "status": 1,
            "t": 1607295713.5487244,
            "value": 772.0
        }
    ]
}

Parameters:

  • k valid API key
  • a history notifier id (default: db_1)
  • i item oid or oid mask (type:group/subgroup/#)

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • l records limit (doesn’t work with “w”)
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • z Time zone (pytz, e.g. UTC or Europe/Prague)
  • o extra options for notifier data request

Returns:

state log records (list)

terminate - terminate action execution

Terminates or cancel the action if it is still queued

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 141
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "terminate",
    "params": {
        "i": "unit:tests/unit1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 141' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "terminate", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 141' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "terminate", "params": {"i": "unit:tests/unit1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "terminate",
  "params": {
    "i": "unit:tests/unit1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:141 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '141', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'terminate', 'params': {'i': 'unit:tests/unit1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • u action uuid or
  • i unit id

Returns:

An error result will be returned eitner if action is terminated (Resource not found) or if termination process is failed or denied by unit configuration (Function failed)

clear - clear lvar state

set status (if expires lvar param > 0) or value (if expires isn’t set) of a logic variable to 0. Useful when lvar is used as a timer to stop it, or as a flag to set it False.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 132
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "clear",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 132' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "clear", "params": {"i": "tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 132' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "clear", "params": {"i": "tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "clear",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:132 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '132', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'clear', 'params': {'i': 'tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i lvar id
decrement - decrement lvar value

Decrement value of a logic variable. Initial value should be number

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "decrement",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "decrement", "params": {"i": "tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "decrement", "params": {"i": "tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "decrement",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'decrement', 'params': {'i': 'tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i lvar id
increment - increment lvar value

Increment value of a logic variable. Initial value should be number

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "increment",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "increment", "params": {"i": "tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "increment", "params": {"i": "tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "increment",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'increment', 'params': {'i': 'tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i lvar id
reset - reset lvar state

Set status and value of a logic variable to 1. Useful when lvar is being used as a timer to reset it, or as a flag to set it True.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 132
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "reset",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 132' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "reset", "params": {"i": "tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 132' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "reset", "params": {"i": "tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "reset",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:132 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '132', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'reset', 'params': {'i': 'tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i lvar id
set - set lvar state

Set status and value of a logic variable.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 163
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey",
        "s": 1,
        "v": 29
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 163' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set", "params": {"i": "tests/lvar1", "k": "mykey", "s": 1, "v": 29}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 163' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set", "params": {"i": "tests/lvar1", "k": "mykey", "s": 1, "v": 29}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey",
    "s": 1,
    "v": 29
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:163 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '163', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set', 'params': {'i': 'tests/lvar1', 'k': 'mykey', 's': 1, 'v': 29}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i lvar id

Optionally:

  • s lvar status
  • v lvar value
toggle - clear lvar state

set status (if expires lvar param > 0) or value (if expires isn’t set) of a logic variable to 0. Useful when lvar is used as a timer to stop it, or as a flag to set it False.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 133
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "toggle",
    "params": {
        "i": "tests/lvar1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 133' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "toggle", "params": {"i": "tests/lvar1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 133' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "toggle", "params": {"i": "tests/lvar1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "toggle",
  "params": {
    "i": "tests/lvar1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:133 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '133', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'toggle', 'params': {'i': 'tests/lvar1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k valid API key
  • i lvar id

Logic cycles

get_cycle - get cycle information

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 137
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_cycle",
    "params": {
        "i": "tests/cycle1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 137' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_cycle", "params": {"i": "tests/cycle1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 137' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_cycle", "params": {"i": "tests/cycle1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_cycle",
  "params": {
    "i": "tests/cycle1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:137 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '137', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_cycle', 'params': {'i': 'tests/cycle1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 368
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "controller_id": "lm/lab-ws2",
        "description": "",
        "full_id": "tests/cycle1",
        "group": "tests",
        "id": "cycle1",
        "interval": 1.0,
        "iterations": 0,
        "oid": "lcycle:tests/cycle1",
        "status": 0,
        "type": "lcycle",
        "value": null
    }
}

Parameters:

  • k valid API key
  • i cycle id

Returns:

field “value” contains real average cycle interval

groups_cycle - get cycle groups list

Get the list of cycles. Useful e.g. for custom interfaces.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 111
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "groups_cycle",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 111' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "groups_cycle", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 111' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "groups_cycle", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "groups_cycle",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:111 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '111', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'groups_cycle', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 76
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        "tests"
    ]
}

Parameters:

  • k valid API key
list_cycles - get cycle list

Get the list of all available cycles.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 110
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_cycles",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 110' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_cycles", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 110' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_cycles", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_cycles",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:110 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '110', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_cycles', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 432
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "controller_id": "lm/lab-ws2",
            "description": "",
            "full_id": "tests/cycle1",
            "group": "tests",
            "id": "cycle1",
            "interval": 1.0,
            "iterations": 0,
            "oid": "lcycle:tests/cycle1",
            "status": 0,
            "type": "lcycle",
            "value": null
        }
    ]
}

Parameters:

  • k valid API key

Optionally:

  • g filter by group
  • i filter by controller

Logic macros

groups_macro - get macro groups list

Get the list of macros. Useful e.g. for custom interfaces.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 111
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "groups_macro",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 111' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "groups_macro", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 111' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "groups_macro", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "groups_macro",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:111 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '111', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'groups_macro', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 76
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        "tests"
    ]
}

Parameters:

  • k valid API key
list_macros - get macro list

Get the list of all available macros.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 110
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_macros",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 110' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_macros", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 110' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_macros", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_macros",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:110 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '110', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_macros', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 355
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "action_enabled": true,
            "controller_id": "lm/lab-ws2",
            "description": "",
            "full_id": "tests/test1",
            "group": "tests",
            "id": "test1",
            "oid": "lmacro:tests/test1",
            "type": "lmacro"
        }
    ]
}

Parameters:

  • k valid API key

Optionally:

  • g filter by group
  • i filter by controller
run - execute macro

Execute a macro with the specified arguments.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 130
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "run",
    "params": {
        "i": "tests/test1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 130' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "run", "params": {"i": "tests/test1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 130' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "run", "params": {"i": "tests/test1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "run",
  "params": {
    "i": "tests/test1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:130 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '130', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'run', 'params': {'i': 'tests/test1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 616
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "args": [],
        "err": "",
        "exitcode": null,
        "finished": false,
        "finished_in": null,
        "item_group": "tests",
        "item_id": "test1",
        "item_oid": "lmacro:tests/test1",
        "item_type": "lmacro",
        "kwargs": {},
        "out": "",
        "priority": 100,
        "status": "queued",
        "time": {
            "created": 1604186270.96511,
            "pending": 1604186270.9661834,
            "queued": 1604186270.9684315
        },
        "uuid": "143f37f7-48ec-4062-a217-0f1c157f71fc"
    }
}

Parameters:

  • k valid API key
  • i macro id

Optionally:

  • a macro arguments, array or space separated
  • kw macro keyword arguments, name=value, comma separated or dict
  • w wait for the completion for the specified number of seconds
  • u action UUID (will be auto generated if none specified)
  • p queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”

Supervisor functions

supervisor_lock - set supervisor API lock

When supervisor lock is set, SFA API functions become read-only for all users, except users in the lock scope.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 114
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "supervisor_lock",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 114' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "supervisor_lock", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 114' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "supervisor_lock", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "supervisor_lock",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:114 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '114', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'supervisor_lock', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with allow=supervisor permissions
  • l lock scope (null = any supervisor can pass, u = only owner can pass, k = all users with owner’s API key can pass)
  • c unlock/override scope (same as lock type)
  • u lock user (requires master key)
  • p user type (null for local, “msad” for Active Directory etc.)
  • a lock API key ID (requires master key)
supervisor_unlock - clear supervisor API lock

API key should have permission to clear existing supervisor lock

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 116
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "supervisor_unlock",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 116' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "supervisor_unlock", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 116' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "supervisor_unlock", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "supervisor_unlock",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:116 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '116', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'supervisor_unlock', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with allow=supervisor permissions

Returns:

Successful result is returned if lock is either cleared or not set

supervisor_message - send broadcast message

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 154
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "supervisor_message",
    "params": {
        "k": "mykey",
        "m": "hello this is a test"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 154' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "supervisor_message", "params": {"k": "mykey", "m": "hello this is a test"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 154' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "supervisor_message", "params": {"k": "mykey", "m": "hello this is a test"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "supervisor_message",
  "params": {
    "k": "mykey",
    "m": "hello this is a test"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:154 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '154', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'supervisor_message', 'params': {'k': 'mykey', 'm': 'hello this is a test'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with allow=supervisor permissions
  • m message text
  • u message sender user (requires master key)
  • a message sender API key (requires master key)

Remote controllers

append_controller - connect remote controller via HTTP

Connects remote controller to the local.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 211
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "append_controller",
    "params": {
        "a": "secretkey",
        "g": "uc",
        "k": "mykey",
        "save": "true",
        "u": "localhost"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 211' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "append_controller", "params": {"a": "secretkey", "g": "uc", "k": "mykey", "save": "true", "u": "localhost"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 211' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "append_controller", "params": {"a": "secretkey", "g": "uc", "k": "mykey", "save": "true", "u": "localhost"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "append_controller",
  "params": {
    "a": "secretkey",
    "g": "uc",
    "k": "mykey",
    "save": "true",
    "u": "localhost"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:211 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '211', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'append_controller', 'params': {'a': 'secretkey', 'g': 'uc', 'k': 'mykey', 'save': 'true', 'u': 'localhost'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 624
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
        "result": {
            "build": "2019031405",
            "connected": true,
            "description": "",
            "enabled": true,
            "full_id": "uc/ws1-v1",
            "group": "uc",
            "id": "ws1-v1",
            "managed": false,
            "mqtt_update": null,
            "oid": "remote_uc:uc/ws1-v1",
            "proto": "http",
            "static": true,
            "type": "remote_uc",
            "version": "3.2.0"
        }
}

Parameters:

  • k API key with master permissions
  • u Controller API uri (proto://host:port, port not required if default)
  • a remote controller API key ($key to use local key)

Optionally:

  • m ref:MQTT notifier<mqtt_> to exchange item states in real time (default: eva_1)
  • s verify remote SSL certificate or pass invalid
  • t timeout (seconds) for the remote controller API calls
  • g controller type (“uc” or “lm”), autodetected if none
  • save save connected controller configuration on the disk immediately after creation
disable_controller - disable connected controller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 167
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "disable_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 167' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "disable_controller", "params": {"i": "uc/ws1-v1", "k": "mykey", "save": "true"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 167' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "disable_controller", "params": {"i": "uc/ws1-v1", "k": "mykey", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "disable_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey",
    "save": "true"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:167 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '167', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'disable_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id

Optionally:

  • save save configuration after successful call
enable_controller - enable connected controller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 166
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "enable_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey",
        "save": "true"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 166' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "enable_controller", "params": {"i": "uc/ws1-v1", "k": "mykey", "save": "true"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 166' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "enable_controller", "params": {"i": "uc/ws1-v1", "k": "mykey", "save": "true"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "enable_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey",
    "save": "true"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:166 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '166', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'enable_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey', 'save': 'true'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id

Optionally:

  • save save configuration after successful call
get_controller - get connected controller information

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 139
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "get_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 139' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "get_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 139' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "get_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "get_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:139 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '139', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'get_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 512
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
        "result": {
            "build": "2019031405",
            "connected": true,
            "description": "",
            "enabled": true,
            "full_id": "uc/ws1-v1",
            "group": "uc",
            "id": "ws1-v1",
            "managed": false,
            "mqtt_update": null,
            "oid": "remote_uc:uc/ws1-v1",
            "proto": "http",
            "static": true,
            "type": "remote_uc",
            "version": "3.2.0"
        }
}

Parameters:

  • k API key with master permissions
  • i controller id
list_controller_props - get controller connection parameters

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 146
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_controller_props",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 146' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_controller_props", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 146' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_controller_props", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_controller_props",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:146 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '146', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_controller_props', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 431
Content-Type: application/json
Expires: 0
Pragma: no-cache


{
    "id": 1,
    "jsonrpc": "2.0",
        "result": {
                "description": "",
                "enabled": true,
                "key": "secretkey",
                "mqtt_update": null,
                "reload_interval": 300,
                "retries": 2,
                "ssl_verify": true,
                "static": true,
                "timeout": 5.0,
                "uri": "http://localhost:8812"
            }
}

Parameters:

  • k API key with master permissions
  • i controller id
list_controllers - get controllers list

Get the list of all connected controllers.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 115
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_controllers",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 115' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_controllers", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 115' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_controllers", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_controllers",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:115 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '115', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_controllers', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 997
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": [
        {
            "build": "2020103101",
            "connected": true,
            "description": "",
            "enabled": true,
            "full_id": "lm/lab-ws2",
            "group": "lm",
            "id": "lab-ws2",
            "managed": true,
            "mqtt_update": "eva_1",
            "oid": "remote_lm:lm/lab-ws2",
            "proto": "mqtt",
            "static": true,
            "type": "remote_lm",
            "version": "3.3.2"
        },
        {
            "build": "2020103101",
            "connected": true,
            "description": "",
            "enabled": true,
            "full_id": "uc/lab-ws2",
            "group": "uc",
            "id": "lab-ws2",
            "managed": true,
            "mqtt_update": "eva_1",
            "oid": "remote_uc:uc/lab-ws2",
            "proto": "mqtt",
            "static": true,
            "type": "remote_uc",
            "version": "3.3.2"
        }
    ]
}

Parameters:

  • k API key with master permissions
  • g filter by group (“uc” or “lm”)
list_remote - get a list of items from connected controllers

Get a list of the items loaded from the connected controllers. Useful to debug the controller connections.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 136
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "list_remote",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 136' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "list_remote", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 136' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "list_remote", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "list_remote",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:136 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '136', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'list_remote', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 1628
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
        "result":
            [
                {
                    "controller_id": "uc/ws1-v1",
                    "description": "",
                    "full_id": "env/temp_test",
                    "group": "env",
                    "id": "temp_test",
                    "loc_x": null,
                    "loc_y": null,
                    "loc_z": null,
                    "location": "",
                    "oid": "sensor:env/temp_test",
                    "status": 0,
                    "type": "sensor",
                    "value": "null"
                },
                {
                    "action_enabled": true,
                    "controller_id": "uc/ws1-v1",
                    "description": "",
                    "full_id": "nogroup/test2",
                    "group": "nogroup",
                    "id": "test2",
                    "loc_x": null,
                    "loc_y": null,
                    "loc_z": null,
                    "location": "",
                    "nstatus": -1,
                    "nvalue": "null",
                    "oid": "unit:nogroup/test2",
                    "status": -1,
                    "status_labels": [
                        {
                            "label": "OFF",
                            "status": 0
                        },
                        {
                            "label": "ON",
                            "status": 1
                        }
                    ],
                    "type": "unit",
                    "value": "null"
                }
            ]
}

Parameters:

  • k API key with master permissions

Optionally:

  • i controller id
  • g filter by item group
  • p filter by item type
matest_controller - test management API connection to remote controller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 142
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "matest_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 142' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "matest_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 142' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "matest_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "matest_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:142 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '142', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'matest_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id
reload_controller - reload controller

Reloads items from connected controller. If controller ID “ALL” is specified, all connected controllers are reloaded.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 142
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "reload_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 142' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "reload_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 142' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "reload_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "reload_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:142 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '142', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'reload_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id
remove_controller - disconnect controller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 142
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "remove_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 142' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "remove_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 142' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "remove_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "remove_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:142 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '142', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'remove_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id
set_controller_prop - set controller connection parameters

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 217
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "set_controller_prop",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey",
        "p": "reload_interval",
        "save": "true",
        "v": 60
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 217' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "set_controller_prop", "params": {"i": "uc/ws1-v1", "k": "mykey", "p": "reload_interval", "save": "true", "v": 60}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 217' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "set_controller_prop", "params": {"i": "uc/ws1-v1", "k": "mykey", "p": "reload_interval", "save": "true", "v": 60}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "set_controller_prop",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey",
    "p": "reload_interval",
    "save": "true",
    "v": 60
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:217 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '217', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'set_controller_prop', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey', 'p': 'reload_interval', 'save': 'true', 'v': 60}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id
  • p property name (or empty for batch set)

Optionally:

  • v propery value (or dict for batch set)
  • save save configuration after successful call
test_controller - test connection to remote controller

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 140
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "test_controller",
    "params": {
        "i": "uc/ws1-v1",
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 140' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "test_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 140' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "test_controller", "params": {"i": "uc/ws1-v1", "k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "test_controller",
  "params": {
    "i": "uc/ws1-v1",
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:140 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '140', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'test_controller', 'params': {'i': 'uc/ws1-v1', 'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
  • i controller id
upnp_rescan_controllers - rescan controllers via UPnP

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 122
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "upnp_rescan_controllers",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 122' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "upnp_rescan_controllers", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 122' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "upnp_rescan_controllers", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "upnp_rescan_controllers",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:122 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '122', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'upnp_rescan_controllers', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions

Connected clients

notify_restart - notify connected clients about server restart

Sends a server restart event to all connected clients asking them to prepare for server restart.

All the connected clients receive the event with subject=”server” and data=”restart”. If the clients use EVA JS Framework, they can catch server.restart event.

Server restart notification is sent automatically to all connected clients when the server is restarting. This API function allows to send server restart notification without actual server restart, which may be useful e.g. for testing, handling frontend restart etc.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 113
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "notify_restart",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 113' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "notify_restart", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 113' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "notify_restart", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "notify_restart",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:113 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '113', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'notify_restart', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions
reload_clients - ask connected clients to reload

Sends reload event to all connected clients asking them to reload the interface.

All the connected clients receive the event with subject=”reload” and data=”asap”. If the clients use EVA JS Framework, they can catch server.reload event.

http

POST /jrpc HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 113
Host: localhost:8828

{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "reload_clients",
    "params": {
        "k": "mykey"
    }
}

curl

curl -i -X POST http://localhost:8828/jrpc -H 'Accept: application/json' -H 'Content-Length: 113' -H 'Content-Type: application/json' --data-raw '{"id": 1, "jsonrpc": "2.0", "method": "reload_clients", "params": {"k": "mykey"}}'

wget

wget -S -O- http://localhost:8828/jrpc --header='Accept: application/json' --header='Content-Length: 113' --header='Content-Type: application/json' --post-data='{"id": 1, "jsonrpc": "2.0", "method": "reload_clients", "params": {"k": "mykey"}}'

httpie

echo '{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "reload_clients",
  "params": {
    "k": "mykey"
  }
}' | http POST http://localhost:8828/jrpc Accept:application/json Content-Length:113 Content-Type:application/json

python-requests

requests.post('http://localhost:8828/jrpc', headers={'Accept': 'application/json', 'Content-Length': '113', 'Content-Type': 'application/json'}, json={'id': 1, 'jsonrpc': '2.0', 'method': 'reload_clients', 'params': {'k': 'mykey'}})

response

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 79
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "ok": true
    }
}

Parameters:

  • k API key with master permissions

API Clients

All EVA API servers were designed as a simple and user-friendly way to work from a command line using traditional calling methods of Linux http requests: GET, wget, lynx, curl etc. That is why JSON incoming data is always duplicated with the traditional GET/POST request parameters.

API outgoing data is always in JSON format, which can easily be parsed with the use of jq (usually available in all modern Linux distributions), for example:

curl -s 'http://localhost:8812/uc-api/test?k=APIKEY' | jq .version -r

You may call API functions via HTTP GET or HTTP POST - all functions respond similarly regardless of the request method. You may use www-form as well as JSON for POST.

If you want to integrate EVA API in your Python or PHP application, EVA can offer ready-made client libraries.

EVA JS Framework

EVA JS Framework and EVA JS Toolbox are used to build web browser interfaces with HTML and JavaScript .

Framework also can be used in Node.js apps.

Note

Starting from EVA ICS 3.2.3 JavaScript Framework is not installed by default. Previous EVA SFA Framework is deprecated and no longer supported.

Framework requires fetch function, which is available in all modern web browsers. For old browsers polyfill should be used, unfetch is a recommended one.

API client for Python

API client for Python has already been installed on all EVA servers and is used by the system itself. If you want to use the client module on another system, just create eva/client folder, copy lib/eva/client/apiclient.py file into it and create an empty file __init__.py. Other files in this folder are used by the system for a higher level of access to API, which is not publicly documented.

Example of working with API from Python is located in include/python/ folder of EVA.

API classes for Python

API has two classes:

eva.client.apiclient.APIClient()

and

eva.client.apiclient.APIClientLocal(product, dir_eva=None)

APIClientLocal class may be used on the servers where EVA is installed. When specifying product=’<subsystem code>’ parameter (e.g. product = ‘uc’) API is automatically initialized by loading parameters and keys specifically from configuration files of the controller. If you load the apiclient.py module from lib/eva/client/ folder, it is not necessary to set dir_eva parameter. Otherwise, it should point to EVA root folder.

APIClient class should always be initialized manually.

API requires jsonpickle and requests modules.

API initialization

API is initialized with the use of the following functions:

  • set_key(key) set API key.
  • set_uri(uri) set the root API URI (i.e., http://localhost:8812). You don’t need to specify the full path to API.
  • set_timeout(timeout) set maximum request timeout (seconds), 5 seconds by default.
  • set_product(product) set controller type: uc for Universal Controller, lm for Logic Manager, sfa for SCADA Final Aggregator. The client automatically identifies which API is to be called - either Common methods one or the one of the certain controller - that is why this parameter is required.
  • ssl_verify(v) to verify or not SSL certificate validity while working through https://. Can be True (check) or False (don’t check). The certificate is verified by default.

Example:

from eva.client.apiclient import APIClient
api = APIClient()
api.set_key(APIKEY)
api.set_uri('http://192.168.0.77:8812')
api.set_product('uc')
API function call

API functions are invoked by calling the call function:

APIClient.call(func, params=None, timeout=None)

where:

  • params the dict of the request parameters (if required)
  • timeout - maximum time (in seconds) to wait for the API response (if not set - the default timeout is used or the one set during API client initialization).

Example:

from eva.client.apiclient import APIClientLocal
api = APIClientLocal('uc')
code, result = api.call('state', { 'i': 'unit1' })

The function returns a tuple of two variables:

  • code API call result
  • result the result itself (JSON response converted to Python dict or array).
API result codes

Result codes are stored in module variables (i.e. apiclient.result_ok)

# the call succeeded
result_ok = 0
# the item or resource is not found
result_not_found = 1
# access is denied with the set API key
result_forbidden = 2
# server responded with error http status (e.g. API function crashed)
result_api_error = 3
# unknown error: all errors not listed here fall within this category
result_unknown_error = 4
# API is not initialized - URI is not set
result_not_ready = 5
# Attempt to call undefined API function
result_func_unknown = 6
# server connection failed
result_server_error = 7
# the server request exceeded the time set in timeout
result_server_timeout = 8
# API response cannot be parsed or is invalid
result_bad_data = 9
# API function failed
result_func_failed = 10
# API function is called with invalid params
result_invalid_params = 11
# API function attempted to create resource which already exists and can't
# be recreated until deleted/removed
result_invalid_params = 12
# the resource is busy (in use) and can not be accessed/recreated or
# deleted at this moment
result_busy = 13
# the method is not implemented in/for requested resource
result_not_implemented = 14
# the token, used for API call, is valid, but currently restricted
result_token_restricted = 15

In case of error, result is an empty dict or contains field “error” which is filled with error message from server (if available).

JSON RPC API client

As EVA ICS uses standard JSON RPC 2.0 protocol, any 3rd party JSON RPC client may be used. In the example below, we’ll use simple JSON RPC client for Python 3.

Installing

Install Python 3 module:

pip3 install jsonrpcclient
Usage example

Let’s call UC API method state and obtain state of sensors:

from jsonrpcclient import request as rpc

r = rpc('http://localhost:8812/jrpc', 'state', k='YOUR_API_KEY', p='sensor')
for s in r.data.result:
    print(s['oid'])

Note

If using custom API client, you may still put API key to X-Auth-Key request header. This is against JSON RPC standard, so if you want to keep it right, you must have k in params of each request.

API result codes

JSON RPC API responds in standard JSON RPC way with HTTP code 200 (OK). In case JSON RPC request has no id, no body is returned and HTTP response code will be 202 (Accepted).

In case of API method errors, HTTP code is still 200 (OK). Error codes can be found in the response body.

RESTful API

Warning

RESTful API is deprecated and scheduled to be removed (not implemented) in EVA ICS v4. Use JSON RPC API, whenever it is possible.

UC RESTful API

Universal Controller API is used to control and manage units and sensors

This document describes API methods for RESTful calls. For direct and JSON RPC calls look UC API.

RESTful API basics

Warning

RESTful API is deprecated and scheduled to be removed (not implemented) in EVA ICS v4. Use JSON RPC API, whenever it is possible.

Majority EVA ICS API components and items support REST. Parameters for POST, PUT, PATCH and DELETE requests can be sent in both JSON and multipart/form-data. For JSON, Content-Type: application/json header must be specified.

Requests

API key can be sent in HTTP X-Auth-Key header (preferred) or in request parameters (as k).

  • GET request is used to get information about resource or list of resources of the specified type.
  • POST request is used to perform special API calls and create resources in case when resource id is generated by server. In the last case, response always contains additional field Location which points to the resource created.
  • PUT request is used to create new resources. If resource already exists, the server could refuse recreating it, responding with 409 Conflict HTTP error.
  • PATCH request is used to modify resource parameters.
  • DELETE request is used to delete resource.

For resource creation and modification, multiple parameters can be specified in a single request. For majority requests of such purpose, a special parameter “save” is used to tell server (if “save”: true) to save the resource configuration immediately after its modification.

For the group-related calls, put trailing slash at the end of the request URL:

/r/<resource_type>/<group>/
Responses

Success responses:

  • 200 OK API call completed successfully
  • 201 Created API call completed successfully, Response header Location contains either uri to the newly created object or resource is accessible by the effective request uri. For resources created with PUT, body contains either serialized resource object or resource type and id
  • 202 Accepted The server accepted command and will process it later.
  • 204 No Content API call completed successfully, no content to return

Error responses:

  • 403 Forbidden the API key has no access to this function or resource
  • 404 Not Found resource doesn’t exist
  • 405 Method Not Allowed API function/method not found
  • 409 Conflict resource/object already exists or is locked
  • 500 API Error API function execution has been failed. Check input parameters and server logs.

Response body may contain additional information encoded in JSON. { “result”: “OK” } and { “result”: “ERROR” } in body are not returned.

Long API calls
  • Long API calls should be avoided at any cost.
  • All critical action and command methods have an option to obtain action ID and check for the result later.
  • If long API calls are performed between controllers (e.g. action methods with wait param), remote controller timeout should be always greater than max. expected “wait” timeout in API call, otherwise client controller will repeat API calls continuously, up to max retries for the target controller.

Contents

General functions
test API/key and get system info

Test can be executed with any valid API key of the controller the function is called to.

For SFA, the result section “connected” contains connection status of remote controllers. The API key must have an access either to “uc” and “lm” groups (“remote_uc:uc” and “remote_lm:lm”) or to particular controller oids.

http

GET /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/core -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/core --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/core X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/core', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "acl": {
        "key_id": "masterkey",
        "master": true
    },
    "db_update": 1,
    "debug": true,
    "file_management": true,
    "layout": "enterprise",
    "polldelay": 0.001,
    "product_build": 2019031405,
    "product_code": "uc",
    "product_name": "EVA Universal Controller",
    "setup_mode": false,
    "system": "mws1-v1",
    "time": 1552867566.880533,
    "uptime": 990,
    "version": "3.2.0"
}

Parameters:

  • API Key any valid API key

Returns:

JSON dict with system info and current API key permissions (for masterkey only { “master”: true } is returned)

save database and runtime configuration

All modified items, their status, and configuration will be written to the disk. If exec_before_save command is defined in the controller’s configuration file, it’s called before saving and exec_after_save after (e.g. to switch the partition to write mode and back to read-only).

http

POST /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "save" }

curl

curl -i -X POST http://localhost:8812/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "save"}'

wget

wget -S -O- http://localhost:8812/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "save"}'

httpie

echo '{
  "method": "save"
}' | http POST http://localhost:8812/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'save'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with sysfunc=yes permissions
execute a remote system command

Executes a command script on the server where the controller is installed.

http

POST /r/cmd/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "a": "0 2 3", "w": 5, "t": 10 }

curl

curl -i -X POST http://localhost:8812/r/cmd/test -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"a": "0 2 3", "t": 10, "w": 5}'

wget

wget -S -O- http://localhost:8812/r/cmd/test --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"a": "0 2 3", "t": 10, "w": 5}'

httpie

echo '{
  "a": "0 2 3",
  "t": 10,
  "w": 5
}' | http POST http://localhost:8812/r/cmd/test Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/cmd/test', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'a': '0 2 3', 't': 10, 'w': 5})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "args": [
        "0",
        "2",
        "3"
    ],
    "cmd": "test",
    "err": "some text to stderr\n",
    "exitcode": 0,
    "out": "test script start\nparam 1: 0 ( > 0 will generate \"failed\" status)\nparam 2: 2\nparam 3: 3\ndelay 3 sec\nscript finish\n",
    "status": "completed",
    "time": {
        "completed": 1552863480.7081513,
        "created": 1552863480.6993306,
        "running": 1552863480.7001197
    },
    "timeout": 10.0
}

Parameters:

  • API Key API key with allow=cmd permissions

Optionally:

  • a string of command arguments, separated by spaces (passed to the script) or array (list)
  • w wait (in seconds) before API call sends a response. This allows to try waiting until command finish
  • t maximum time of command execution. If the command fails to finish within the specified time (in sec), it will be terminated
  • s STDIN data
get list of loaded core plugins

http

GET /r/plugin HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/plugin -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/plugin --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/plugin X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/plugin', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "author": "Altertech, https://www.altertech.com/",
        "license": "Apache License 2.0",
        "name": "test",
        "version": "0.0.1"
    }
]

Parameters:

  • API Key API key with master permissions

Returns:

list with plugin module information

install a package

Installs the package

Parameters:

  • API Key API key with master permissions
  • m package content (base64-encoded tar/tgz)
  • o package setup options
  • w wait (in seconds) before API call sends a response. This allows to try waiting until the package is installed
shutdown the controller

Controller process will be exited and then (should be) restarted by watchdog. This allows to restart controller remotely.

For MQTT API calls a small shutdown delay usually should be specified to let the core send the correct API response.

http

POST /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "shutdown" }

curl

curl -i -X POST http://localhost:8812/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "shutdown"}'

wget

wget -S -O- http://localhost:8812/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "shutdown"}'

httpie

echo '{
  "method": "shutdown"
}' | http POST http://localhost:8812/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'shutdown'})

response

HTTP/1.1 202 Accepted
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • t shutdown delay (seconds)
switch debugging mode

Enables and disables debugging mode while the controller is running. After the controller is restarted, this parameter is lost and controller switches back to the mode specified in the configuration file.

http

PATCH /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "debug": true }

curl

curl -i -X PATCH http://localhost:8812/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"debug": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"debug": true}'

httpie

echo '{
  "debug": true
}' | http PATCH http://localhost:8812/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'debug': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • debug true for enabling debug mode, false for disabling
log in and get authentication token

Obtains authentication token which can be used in API calls instead of API key.

If both k and u args are absent, but API method is called with HTTP request, which contain HTTP header for basic authorization, the function will try to parse it and log in user with credentials provided.

If authentication token is specified, the function will check it and return token information if it is valid.

If both token and credentials (user or API key) are specified, the function will return the token to normal mode.

http

POST /r/token HTTP/1.1
Host: localhost:8812
Content-Type: application/json

{ "u": "admin", "p": "123" }

curl

curl -i -X POST http://localhost:8812/r/token -H 'Content-Type: application/json' --data-raw '{"p": "123", "u": "admin"}'

wget

wget -S -O- http://localhost:8812/r/token --header='Content-Type: application/json' --post-data='{"p": "123", "u": "admin"}'

httpie

echo '{
  "p": "123",
  "u": "admin"
}' | http POST http://localhost:8812/r/token Content-Type:application/json

python-requests

requests.post('http://localhost:8812/r/token', headers={'Content-Type': 'application/json'}, json={'p': '123', 'u': 'admin'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "key": "masterkey",
    "token": "token:1c166529bc3b06dac6e0fbaefee38ebe77c455480e11ff4431de2b10a5508899",
    "user": "admin"
}

Parameters:

  • API Key valid API key or
  • u user login
  • p user password
  • a authentication token

Returns:

A dict, containing API key ID and authentication token

log out and purge authentication token

Purges authentication token

http

DELETE /r/token HTTP/1.1
Host: localhost:8812
X-Auth-Key: token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7

curl

curl -i -X DELETE http://localhost:8812/r/token -H 'X-Auth-Key: token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/token --header='X-Auth-Key: token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7'

httpie

http DELETE http://localhost:8812/r/token X-Auth-Key:token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7

python-requests

requests.delete('http://localhost:8812/r/token', headers={'X-Auth-Key': 'token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid token
Set token read-only

Applies read-only mode for token. In read-only mode, only read-only functions work, others return result_token_restricted(15).

The method works for token-authenticated API calls only.

To exit read-only mode, user must either re-login or, to keep the current token, call “login” API method with both token and user credentials.

Item functions
clean action queue of unit

Cancels all queued actions, keeps the current action running.

http

POST /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "q_clean" }

curl

curl -i -X POST http://localhost:8812/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "q_clean"}'

wget

wget -S -O- http://localhost:8812/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "q_clean"}'

httpie

echo '{
  "method": "q_clean"
}' | http POST http://localhost:8812/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'q_clean'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
disable unit actions

Disables unit to run and queue new actions.

http

PATCH /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "action_enabled": false }

curl

curl -i -X PATCH http://localhost:8812/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"action_enabled": false}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"action_enabled": false}'

httpie

echo '{
  "action_enabled": false
}' | http PATCH http://localhost:8812/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'action_enabled': False})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
enable unit actions

Enables unit to run and queue new actions.

http

PATCH /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "action_enabled": true }

curl

curl -i -X PATCH http://localhost:8812/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"action_enabled": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"action_enabled": true}'

httpie

echo '{
  "action_enabled": true
}' | http PATCH http://localhost:8812/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'action_enabled': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
get action status

Checks the result of the action by its UUID or returns the actions for the specified unit.

http

GET /r/action HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/action -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/action --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/action X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/action', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "err": "",
        "exitcode": null,
        "finished": true,
        "finished_in": 0.0006144,
        "item_group": "tests",
        "item_id": "unit1",
        "item_oid": "unit:tests/unit1",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "refused",
        "time": {
            "created": 1559868829.0452583,
            "pending": 1559868829.0455182,
            "refused": 1559868829.0458727
        },
        "uuid": "70db470b-7d7e-4698-a001-01958c0ff3a7"
    },
    {
        "err": "",
        "exitcode": -15,
        "finished": true,
        "finished_in": 1.301712,
        "item_group": "tests",
        "item_id": "unit3",
        "item_oid": "unit:tests/unit3",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "terminated",
        "time": {
            "created": 1559868829.0540679,
            "pending": 1559868829.054227,
            "queued": 1559868829.05472,
            "running": 1559868829.0551677,
            "terminated": 1559868830.35578
        },
        "uuid": "18bcbf97-d35d-4f18-8354-d18d092df5f7"
    },
    {
        "err": "",
        "exitcode": null,
        "finished": true,
        "finished_in": 0.0010161,
        "item_group": "tests",
        "item_id": "unit1",
        "item_oid": "unit:tests/unit1",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "refused",
        "time": {
            "created": 1559868829.087297,
            "pending": 1559868829.0876813,
            "refused": 1559868829.088313
        },
        "uuid": "3737a15b-515c-4e85-be2a-c937392851fa"
    },
    {
        "err": "",
        "exitcode": null,
        "finished": true,
        "finished_in": 0.000658,
        "item_group": "tests",
        "item_id": "unit3",
        "item_oid": "unit:tests/unit3",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "refused",
        "time": {
            "created": 1559868829.0973055,
            "pending": 1559868829.0975406,
            "refused": 1559868829.0979636
        },
        "uuid": "17570e18-03ca-4772-8665-90af574325b9"
    }
]

Parameters:

  • API Key valid API key

Optionally:

  • g filter by unit group
  • s filter by action status: Q for queued, R for running, F for finished

Returns:

list or single serialized action object

get item group list

Get the list of item groups. Useful e.g. for custom interfaces.

http

GET /r/unit/@groups HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/unit/@groups -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/unit/@groups --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/unit/@groups X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/unit/@groups', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    "room1",
    "test_device_5",
    "test_device_7",
    "tests"
]

Parameters:

  • API Key valid API key
get item state

State of the item or all items of the specified type can be obtained using state command.

http

GET /r/sensor HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/sensor -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/sensor --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/sensor X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/sensor', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "full_id": "tests/sensor1",
        "group": "tests",
        "id": "sensor1",
        "oid": "sensor:tests/sensor1",
        "status": 1,
        "type": "sensor",
        "value": 29.445
    },
    {
        "full_id": "tests/sensor2",
        "group": "tests",
        "id": "sensor2",
        "oid": "sensor:tests/sensor2",
        "status": 1,
        "type": "sensor",
        "value": 29.445
    }
]

Parameters:

  • API Key valid API key

Optionally:

get item state history

State history of one item or several items of the specified type can be obtained using state_history command.

If master key is used, the method attempts to get stored state for an item even if it doesn’t present currently in system.

The method can return state log for disconnected items as well.

http

GET /r/sensor/tests/sensor2@history HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/sensor/tests/sensor2@history -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/sensor/tests/sensor2@history --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/sensor/tests/sensor2@history X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/sensor/tests/sensor2@history', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "status": [
        null,
        null,
        1,
        null,
        1
    ],
    "t": [
        1552865635.6868849,
        1552866234.5211835,
        1552866297.7497892,
        1552866495.7593722,
        1552866511.8293397,
        1552866513.8805466
    ],
    "value": [
        29.445,
        29.42,
        28,
        29.11,
        29.42,
        29.441
    ]
}

Parameters:

  • API Key valid API key
  • a history notifier id (default: db_1)

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • l records limit (doesn’t work with “w”)
  • x state prop (“status” or “value”)
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • z Time zone (pytz, e.g. UTC or Europe/Prague)
  • w fill frame with the interval (e.g. “1T” - 1 min, “2H” - 2 hours etc.), start time is required, set to 1D if not specified
  • g output format (“list”, “dict” or “chart”, default is “list”)
  • c options for chart (dict or comma separated)
  • o extra options for notifier data request

Returns:

history data in specified format or chart image.

For chart, JSON RPC gets reply with “content_type” and “data” fields, where content is image content type. If PNG image format is selected, data is base64-encoded.

Options for chart (all are optional):

If option “w” (fill) is used, number of digits after comma may be specified. E.g. 5T:3 will output values with 3 digits after comma.

Additionally, SI prefix may be specified to convert value to kilos, megas etc, e.g. 5T:k:3 - divide value by 1000 and output 3 digits after comma. Valid prefixes are: k, M, G, T, P, E, Z, Y.

If binary prefix is required, it should be followed by “b”, e.g. 5T:Mb:3 - divide value by 2^20 and output 3 digits after comma.

get item state log

State log of a single item or group of the specified type can be obtained using state_log command.

note: only SQL notifiers are supported

Difference from state_history method:

  • state_log doesn’t optimize data to be displayed on charts * the data is returned from a database as-is * a single item OID or OID mask (e.g. sensor:env/#) can be specified

note: the method supports MQTT-style masks but only masks with wildcard-ending, like “type:group/subgroup/#” are supported.

The method can return state log for disconnected items as well.

For wildcard fetching, API key should have an access to the whole chosen group.

note: record limit means the limit for records, fetched from the database, but repeating state records are automatically grouped and the actual number of returned records can be lower than requested.

http

GET /r/sensor/tests/test1@log HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/sensor/tests/test1@log -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/sensor/tests/test1@log --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/sensor/tests/test1@log X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/sensor/tests/test1@log', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "oid": "sensor:tests/test1",
        "status": 1,
        "t": 1607295099.9760036,
        "value": null
    },
    {
        "oid": "sensor:tests/test1",
        "status": 1,
        "t": 1607295103.9991317,
        "value": 25.0
    },
    {
        "oid": "sensor:tests/test1",
        "status": 1,
        "t": 1607295107.0097003,
        "value": 258.0
    },
    {
        "oid": "sensor:tests/test1",
        "status": 1,
        "t": 1607295110.0616019,
        "value": 359.0
    }
]

Parameters:

  • API Key valid API key
  • a history notifier id (default: db_1)

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • l records limit (doesn’t work with “w”)
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • z Time zone (pytz, e.g. UTC or Europe/Prague)
  • o extra options for notifier data request

Returns:

state log records (list)

kill unit actions

Apart from canceling all queued commands, this function also terminates the current running action.

http

POST /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "kill" }

curl

curl -i -X POST http://localhost:8812/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "kill"}'

wget

wget -S -O- http://localhost:8812/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "kill"}'

httpie

echo '{
  "method": "kill"
}' | http POST http://localhost:8812/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'kill'})

response

HTTP/1.1 202 Accepted
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key

Returns:

If the current action of the unit cannot be terminated by configuration, the notice “pt” = “denied” will be returned additionally (even if there’s no action running)

start item maintenance mode

During maintenance mode all item updates are ignored, however actions still can be executed

http

PATCH /r/sensor/tests/sensor1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "maintenance": true }

curl

curl -i -X PATCH http://localhost:8812/r/sensor/tests/sensor1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"maintenance": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/sensor/tests/sensor1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"maintenance": true}'

httpie

echo '{
  "maintenance": true
}' | http PATCH http://localhost:8812/r/sensor/tests/sensor1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/sensor/tests/sensor1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'maintenance': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key masterkey
stop item maintenance mode

http

PATCH /r/sensor/tests/sensor1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "maintenance": false }

curl

curl -i -X PATCH http://localhost:8812/r/sensor/tests/sensor1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"maintenance": false}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/sensor/tests/sensor1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"maintenance": false}'

httpie

echo '{
  "maintenance": false
}' | http PATCH http://localhost:8812/r/sensor/tests/sensor1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/sensor/tests/sensor1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'maintenance': False})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key masterkey
terminate action execution

Terminates or cancel the action if it is still queued

http

POST /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "terminate" }

curl

curl -i -X POST http://localhost:8812/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "terminate"}'

wget

wget -S -O- http://localhost:8812/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "terminate"}'

httpie

echo '{
  "method": "terminate"
}' | http POST http://localhost:8812/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'terminate'})

response

HTTP/1.1 202 Accepted
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key

Returns:

An error result will be returned eitner if action is terminated (Resource not found) or if termination process is failed or denied by unit configuration (Function failed)

toggle unit status

Create unit control action to toggle its status (1->0, 0->1)

http

POST /r/action HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "i": "unit:tests/unit3", "s": "toggle" }

curl

curl -i -X POST http://localhost:8812/r/action -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"i": "unit:tests/unit3", "s": "toggle"}'

wget

wget -S -O- http://localhost:8812/r/action --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"i": "unit:tests/unit3", "s": "toggle"}'

httpie

echo '{
  "i": "unit:tests/unit3",
  "s": "toggle"
}' | http POST http://localhost:8812/r/action Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/action', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'i': 'unit:tests/unit3', 's': 'toggle'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Location: /r/action/17570e18-03ca-4772-8665-90af574325b9
Pragma: no-cache

{
    "err": "",
    "exitcode": null,
    "finished": true,
    "finished_in": 0.000658,
    "item_group": "tests",
    "item_id": "unit3",
    "item_oid": "unit:tests/unit3",
    "item_type": "unit",
    "nstatus": 1,
    "nvalue": null,
    "out": "",
    "priority": 100,
    "status": "refused",
    "time": {
        "created": 1559868829.0973055,
        "pending": 1559868829.0975406,
        "refused": 1559868829.0979636
    },
    "uuid": "17570e18-03ca-4772-8665-90af574325b9"
}

Parameters:

  • API Key valid API key

Optionally:

  • w wait for the completion for the specified number of seconds
  • p queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”

Returns:

Serialized action object. If action is marked as dead, an error is returned (exception raised)

unit control action

The call is considered successful when action is put into the action queue of selected unit.

http

POST /r/action HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "s": 1, "i": "unit:tests/unit3", "s": 1 }

curl

curl -i -X POST http://localhost:8812/r/action -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"i": "unit:tests/unit3", "s": 1}'

wget

wget -S -O- http://localhost:8812/r/action --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"i": "unit:tests/unit3", "s": 1}'

httpie

echo '{
  "i": "unit:tests/unit3",
  "s": 1
}' | http POST http://localhost:8812/r/action Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/action', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'i': 'unit:tests/unit3', 's': 1})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Location: /r/action/18bcbf97-d35d-4f18-8354-d18d092df5f7
Pragma: no-cache

{
    "err": "",
    "exitcode": null,
    "finished": false,
    "finished_in": null,
    "item_group": "tests",
    "item_id": "unit3",
    "item_oid": "unit:tests/unit3",
    "item_type": "unit",
    "nstatus": 1,
    "nvalue": null,
    "out": "",
    "priority": 100,
    "status": "running",
    "time": {
        "created": 1559868829.0540679,
        "pending": 1559868829.054227,
        "queued": 1559868829.05472,
        "running": 1559868829.0551677
    },
    "uuid": "18bcbf97-d35d-4f18-8354-d18d092df5f7"
}

Parameters:

  • API Key valid API key

Optionally:

  • s desired unit status
  • v desired unit value
  • w wait for the completion for the specified number of seconds
  • p queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”

Returns:

Serialized action object. If action is marked as dead, an error is returned (exception raised)

update the status and value of the item

Updates the status and value of the item. This is one of the ways of passive state update, for example with the use of an external controller.

Note

Calling without s and v params will force item to perform passive update requesting its status from update script or driver.

http

POST /r/sensor/tests/sensor2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "s": 1, "v": 29.445 }

curl

curl -i -X POST http://localhost:8812/r/sensor/tests/sensor2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"s": 1, "v": 29.445}'

wget

wget -S -O- http://localhost:8812/r/sensor/tests/sensor2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"s": 1, "v": 29.445}'

httpie

echo '{
  "s": 1,
  "v": 29.445
}' | http POST http://localhost:8812/r/sensor/tests/sensor2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/sensor/tests/sensor2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'s': 1, 'v': 29.445})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key

Optionally:

  • s item status
  • v item value
Item management
list items

Parameters:

  • API Key API key with master permissions

Optionally:

  • x serialize specified item prop(s)

Returns:

the list of all item available

create multi-update

Creates new multi-update.

http

PUT /r/mu/tests/mu2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "update_timeout": 10, "update_interval": 5 }

curl

curl -i -X PUT http://localhost:8812/r/mu/tests/mu2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"save": true, "update_interval": 5, "update_timeout": 10}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/mu/tests/mu2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"save": true, "update_interval": 5, "update_timeout": 10}'

httpie

echo '{
  "save": true,
  "update_interval": 5,
  "update_timeout": 10
}' | http PUT http://localhost:8812/r/mu/tests/mu2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/mu/tests/mu2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'save': True, 'update_interval': 5, 'update_timeout': 10})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "config_changed": false,
    "description": "",
    "full_id": "tests/mu2",
    "group": "tests",
    "id": "mu2",
    "oid": "mu:tests/mu2",
    "status": 0,
    "type": "mu",
    "value": "null",
    "virtual": false
}

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save multi-update configuration immediately
create new sensor

Creates new sensor.

http

PUT /r/sensor/tests/sensor7 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "update_timeout": 10, "update_interval": 5 }

curl

curl -i -X PUT http://localhost:8812/r/sensor/tests/sensor7 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"save": true, "update_interval": 5, "update_timeout": 10}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/sensor/tests/sensor7 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"save": true, "update_interval": 5, "update_timeout": 10}'

httpie

echo '{
  "save": true,
  "update_interval": 5,
  "update_timeout": 10
}' | http PUT http://localhost:8812/r/sensor/tests/sensor7 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/sensor/tests/sensor7', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'save': True, 'update_interval': 5, 'update_timeout': 10})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "config_changed": false,
    "description": "",
    "full_id": "tests/sensor7",
    "group": "tests",
    "id": "sensor7",
    "loc_x": null,
    "loc_y": null,
    "loc_z": null,
    "location": "",
    "oid": "sensor:tests/sensor7",
    "status": 0,
    "type": "sensor",
    "value": "null",
    "virtual": false
}

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save sensor configuration immediately
create new unit

Creates new unit.

http

PUT /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "update_timeout": 10, "action_enabled": true }

curl

curl -i -X PUT http://localhost:8812/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"action_enabled": true, "save": true, "update_timeout": 10}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"action_enabled": true, "save": true, "update_timeout": 10}'

httpie

echo '{
  "action_enabled": true,
  "save": true,
  "update_timeout": 10
}' | http PUT http://localhost:8812/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'action_enabled': True, 'save': True, 'update_timeout': 10})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "action_enabled": true,
    "config_changed": false,
    "description": "",
    "full_id": "tests/unit3",
    "group": "tests",
    "id": "unit3",
    "loc_x": null,
    "loc_y": null,
    "loc_z": null,
    "location": "",
    "nstatus": 0,
    "nvalue": "null",
    "oid": "unit:tests/unit3",
    "status": 0,
    "status_labels": [
        {
            "label": "OFF",
            "status": 0
        },
        {
            "label": "ON",
            "status": 1
        }
    ],
    "type": "unit",
    "value": "null",
    "virtual": false
}

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save unit configuration immediately
get item configuration

http

GET /r/unit/tests/unit3@config HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/unit/tests/unit3@config -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/unit/tests/unit3@config --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/unit/tests/unit3@config X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/unit/tests/unit3@config', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "action_enabled": true,
    "full_id": "tests/unit3",
    "group": "tests",
    "id": "unit3",
    "oid": "unit:tests/unit3",
    "type": "unit",
    "update_timeout": 10.0
}

Parameters:

  • API Key API key with master permissions

Returns:

complete item configuration

list item properties

Get all editable parameters of the item confiugration.

http

GET /r/unit/tests/unit1@props HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/unit/tests/unit1@props -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/unit/tests/unit1@props --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/unit/tests/unit1@props X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/unit/tests/unit1@props', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "action_allow_termination": false,
    "action_always_exec": false,
    "action_driver_config": null,
    "action_enabled": true,
    "action_exec": null,
    "action_queue": 0,
    "action_timeout": null,
    "auto_off": 0,
    "description": "",
    "expires": 0,
    "location": null,
    "mqtt_control": null,
    "mqtt_update": null,
    "snmp_trap": null,
    "status_labels": {
        "0": "OFF",
        "1": "ON"
    },
    "term_kill_interval": null,
    "update_driver_config": null,
    "update_exec": null,
    "update_exec_after_action": false,
    "update_if_action": false,
    "update_interval": 0,
    "update_state_after_action": true,
    "update_timeout": null,
    "virtual": false
}

Parameters:

  • API Key API key with master permissions
save item configuration

Saves item. configuration on disk (even if it hasn’t been changed)

http

POST /r/unit/tests/unit1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "save" }

curl

curl -i -X POST http://localhost:8812/r/unit/tests/unit1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "save"}'

wget

wget -S -O- http://localhost:8812/r/unit/tests/unit1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "save"}'

httpie

echo '{
  "method": "save"
}' | http POST http://localhost:8812/r/unit/tests/unit1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/unit/tests/unit1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'save'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
set item property

Set configuration parameters of the item.

http

PATCH /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "action_allow_termination": true, "action_timeout": 10, "update_interval": 10 }

curl

curl -i -X PATCH http://localhost:8812/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"action_allow_termination": true, "action_timeout": 10, "update_interval": 10}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"action_allow_termination": true, "action_timeout": 10, "update_interval": 10}'

httpie

echo '{
  "action_allow_termination": true,
  "action_timeout": 10,
  "update_interval": 10
}' | http PATCH http://localhost:8812/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'action_allow_termination': True, 'action_timeout': 10, 'update_interval': 10})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
clone group

Creates a copy of all items from the group.

http

POST /r/unit/tests/ HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "clone", "n": "clone_tests" }

curl

curl -i -X POST http://localhost:8812/r/unit/tests/ -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "clone", "n": "clone_tests"}'

wget

wget -S -O- http://localhost:8812/r/unit/tests/ --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "clone", "n": "clone_tests"}'

httpie

echo '{
  "method": "clone",
  "n": "clone_tests"
}' | http POST http://localhost:8812/r/unit/tests/ Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/unit/tests/', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'clone', 'n': 'clone_tests'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • n new group to clone to

Optionally:

  • p item ID prefix, e.g. device1. for device1.temp1, device1.fan1
  • r iem ID prefix in the new group, e.g. device2 (both prefixes must be specified)
  • save save configuration immediately
clone item

Creates a copy of the item.

http

POST /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "clone", "n": "tests/clone_of_unit3" }

curl

curl -i -X POST http://localhost:8812/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "clone", "n": "tests/clone_of_unit3"}'

wget

wget -S -O- http://localhost:8812/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "clone", "n": "tests/clone_of_unit3"}'

httpie

echo '{
  "method": "clone",
  "n": "tests/clone_of_unit3"
}' | http POST http://localhost:8812/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'clone', 'n': 'tests/clone_of_unit3'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "action_enabled": true,
    "full_id": "tests/clone_of_unit3",
    "group": "tests",
    "id": "clone_of_unit3",
    "nstatus": 0,
    "nvalue": "null",
    "oid": "unit:tests/clone_of_unit3",
    "status": 0,
    "type": "unit",
    "value": "null"
}

Parameters:

  • API Key API key with master permissions
  • n new item id

Optionally:

  • save save multi-update configuration immediately
1-Wire bus via OWFS
create OWFS bus

Creates (defines) OWFS bus with the specified configuration.

Parameter “location” (“n”) should contain the connection configuration, e.g. “localhost:4304” for owhttpd or “i2c=/dev/i2c-1:ALL”, “/dev/i2c-0 –w1” for local 1-Wire bus via I2C, depending on type.

http

PUT /r/owfs/bus1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "n": "localhost:4304", "l": true, "t": 1, "r": 5, "d": 0.3, "save": true }

curl

curl -i -X PUT http://localhost:8812/r/owfs/bus1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"d": 0.3, "l": true, "n": "localhost:4304", "r": 5, "save": true, "t": 1}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/owfs/bus1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"d": 0.3, "l": true, "n": "localhost:4304", "r": 5, "save": true, "t": 1}'

httpie

echo '{
  "d": 0.3,
  "l": true,
  "n": "localhost:4304",
  "r": 5,
  "save": true,
  "t": 1
}' | http PUT http://localhost:8812/r/owfs/bus1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/owfs/bus1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'d': 0.3, 'l': True, 'n': 'localhost:4304', 'r': 5, 'save': True, 't': 1})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "delay": 0.3,
    "id": "bus1",
    "location": "localhost:4304",
    "lock": true,
    "retries": 5,
    "timeout": 1.0
}

Parameters:

  • API Key API key with master permissions
  • n OWFS location

Optionally:

  • l lock port on operations, which means to wait while OWFS bus is used by other controller thread (driver command)
  • t OWFS operations timeout (in seconds, default: default timeout)
  • r retry attempts for each operation (default: no retries)
  • d delay between bus operations (default: 50ms)
  • save save OWFS bus config after creation

Returns:

If bus with the selected ID is already defined, error is not returned and bus is recreated.

delete OWFS bus

Deletes (undefines) OWFS bus.

Note

In some cases deleted OWFS bus located on I2C may lock libow library calls, which require controller restart until you can use (create) the same I2C bus again.

http

DELETE /r/owfs/bus1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/owfs/bus1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/owfs/bus1 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/owfs/bus1 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/owfs/bus1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get OWFS bus configuration

http

GET /r/owfs/bus1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/owfs/bus1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/owfs/bus1 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/owfs/bus1 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/owfs/bus1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "delay": 0.3,
    "id": "bus1",
    "location": "localhost:4304",
    "lock": true,
    "retries": 5,
    "timeout": 1.0
}

Parameters:

  • API Key API key with master permissions
list OWFS buses

http

GET /r/owfs HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/owfs -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/owfs --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/owfs X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/owfs', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "delay": 0.3,
        "id": "bus1",
        "location": "localhost:4304",
        "lock": true,
        "retries": 5,
        "timeout": 1.0
    },
    {
        "delay": 0.3,
        "id": "bus_local",
        "location": "localhost:4304",
        "lock": true,
        "retries": 5,
        "timeout": 1.0
    },
    {
        "delay": 0.05,
        "id": "bus_local1",
        "location": "localhost:4304",
        "lock": false,
        "retries": 0,
        "timeout": 4.0
    },
    {
        "delay": 0.05,
        "id": "test",
        "location": "localhost:4304",
        "lock": true,
        "retries": 0,
        "timeout": 4.0
    }
]

Parameters:

  • API Key API key with master permissions
scan OWFS bus

Scan OWFS bus for connected 1-Wire devices.

http

POST /r/owfs/bus_local HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "scan" }

curl

curl -i -X POST http://localhost:8812/r/owfs/bus_local -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "scan"}'

wget

wget -S -O- http://localhost:8812/r/owfs/bus_local --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "scan"}'

httpie

echo '{
  "method": "scan"
}' | http POST http://localhost:8812/r/owfs/bus_local Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/owfs/bus_local', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'scan'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "path": "22.765A2E63339F",
        "type": "DS1822"
    },
    {
        "path": "28.4AEC29CDBAAB",
        "type": "DS18B20"
    },
    {
        "path": "10.67C6697351FF",
        "type": "DS18S20"
    },
    {
        "path": "05.F2FBE3467CC2",
        "type": "DS2405"
    },
    {
        "path": "29.54F81BE8E78D",
        "type": "DS2408"
    }
]

Parameters:

  • API Key API key with master permissions

Optionally:

  • p specified equipment type (e.g. DS18S20,DS2405), list or comma separated
  • a Equipment attributes (e.g. temperature, PIO), list comma separated
  • n Equipment path
  • has_all Equipment should have all specified attributes
  • full obtain all attributes plus values

Returns:

If both “a” and “full” args are specified. the function will examine and values of attributes specified in “a” param. (This will poll “released” bus, even if locking is set up, so be careful with this feature in production environment).

Bus acquire error can be caused in 2 cases:

  • bus is locked * owfs resource not initialized (libow or location problem)
test OWFS bus

Verifies OWFS bus checking library initialization status.

http

POST /r/owfs/bus1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "test" }

curl

curl -i -X POST http://localhost:8812/r/owfs/bus1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "test"}'

wget

wget -S -O- http://localhost:8812/r/owfs/bus1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "test"}'

httpie

echo '{
  "method": "test"
}' | http POST http://localhost:8812/r/owfs/bus1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/owfs/bus1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'test'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
Modbus ports
create virtual Modbus port

Creates virtual Modbus port with the specified configuration.

Modbus params should contain the configuration of hardware Modbus port. The following hardware port types are supported:

  • tcp , udp Modbus protocol implementations for TCP/IP networks. The params should be specified as: <protocol>:<host>[:port], e.g. tcp:192.168.11.11:502
  • rtu, ascii, binary Modbus protocol implementations for the local bus connected with USB or serial port. The params should be specified as: <protocol>:<device>:<speed>:<data>:<parity>:<stop> e.g. rtu:/dev/ttyS0:9600:8:E:1

http

PUT /r/modbus/mbp2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "p": "udp:192.168.33.33:502", "l": true, "t": 0.5, "r": 3, "d": 0.2, "save": true }

curl

curl -i -X PUT http://localhost:8812/r/modbus/mbp2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"d": 0.2, "l": true, "p": "udp:192.168.33.33:502", "r": 3, "save": true, "t": 0.5}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/modbus/mbp2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"d": 0.2, "l": true, "p": "udp:192.168.33.33:502", "r": 3, "save": true, "t": 0.5}'

httpie

echo '{
  "d": 0.2,
  "l": true,
  "p": "udp:192.168.33.33:502",
  "r": 3,
  "save": true,
  "t": 0.5
}' | http PUT http://localhost:8812/r/modbus/mbp2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/modbus/mbp2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'d': 0.2, 'l': True, 'p': 'udp:192.168.33.33:502', 'r': 3, 'save': True, 't': 0.5})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "delay": 0.2,
    "id": "mbp2",
    "lock": true,
    "params": "udp:192.168.33.33:502",
    "retries": 3,
    "timeout": 0.5
}

Parameters:

  • API Key API key with master permissions
  • p Modbus params

Optionally:

  • l lock port on operations, which means to wait while Modbus port is used by other controller thread (driver command)
  • t Modbus operations timeout (in seconds, default: default timeout)
  • r retry attempts for each operation (default: no retries)
  • d delay between virtual port operations (default: 20ms)
  • save save Modbus port config after creation

Returns:

If port with the selected ID is already created, error is not returned and port is recreated.

delete virtual Modbus port

Deletes virtual Modbus port.

http

DELETE /r/modbus/mbp2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/modbus/mbp2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/modbus/mbp2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/modbus/mbp2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/modbus/mbp2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get virtual Modbus port configuration

http

GET /r/modbus/mbp2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/modbus/mbp2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/modbus/mbp2 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/modbus/mbp2 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/modbus/mbp2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "delay": 0.2,
    "id": "mbp2",
    "lock": true,
    "params": "udp:192.168.33.33:502",
    "retries": 3,
    "timeout": 0.5
}

Parameters:

  • API Key API key with master permissions
list virtual Modbus ports

http

GET /r/modbus HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/modbus -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/modbus --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/modbus X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/modbus', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "delay": 0.2,
        "id": "mbp1",
        "lock": true,
        "params": "udp:192.168.33.33:502",
        "retries": 3,
        "timeout": 0.5
    },
    {
        "delay": 0.2,
        "id": "mbp2",
        "lock": true,
        "params": "udp:192.168.33.33:502",
        "retries": 3,
        "timeout": 0.5
    },
    {
        "delay": 0.02,
        "id": "test",
        "lock": false,
        "params": "tcp:192.168.1.1",
        "retries": 0,
        "timeout": 4.0
    }
]

Parameters:

  • API Key API key with master permissions
read Modbus register(s) from remote slave

Modbus registers must be specified as list or comma separated memory addresses predicated with register type (h - holding, i - input, c - coil, d - discrete input).

Address ranges can be specified, e.g. h1000-1010,c10-15 will return values of holding registers from 1000 to 1010 and coil registers from 10 to 15

Float32 numbers are returned as Python-converted floats and may have broken precision. Consider converting back to f32 on the client side.

http

GET /r/modbus/local/1/h10-12,c5-6 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/modbus/local/1/h10-12,c5-6 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/modbus/local/1/h10-12,c5-6 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/modbus/local/1/h10-12,c5-6 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/modbus/local/1/h10-12,c5-6', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "addr": "c5",
        "value": 0
    },
    {
        "addr": "c6",
        "value": 0
    },
    {
        "addr": "h10",
        "value": 25
    },
    {
        "addr": "h11",
        "value": 0
    },
    {
        "addr": "h12",
        "value": 0
    }
]

Parameters:

  • API Key API key with master permissions
  • f data type (u16, i16, u32, i32, u64, i64, f32 or bit)
  • c count, if register range not specified

Optionally:

  • t max allowed timeout for the operation
test virtual Modbus port

Verifies virtual Modbus port by calling connect() Modbus client method.

Note

As Modbus UDP doesn’t require a port to be connected, API call always returns success unless the port is locked.

http

POST /r/modbus/mbp2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "test" }

curl

curl -i -X POST http://localhost:8812/r/modbus/mbp2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "test"}'

wget

wget -S -O- http://localhost:8812/r/modbus/mbp2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "test"}'

httpie

echo '{
  "method": "test"
}' | http POST http://localhost:8812/r/modbus/mbp2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/modbus/mbp2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'test'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
write Modbus register(s) to remote slave

Modbus registers must be specified as list or comma separated memory addresses predicated with register type (h - holding, c - coil).

To set bit, specify register as hX/Y where X = register number, Y = bit number (supports u16, u32, u64 data types)

http

PUT /r/modbus/local/1/h10 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "v": 2522 }

curl

curl -i -X PUT http://localhost:8812/r/modbus/local/1/h10 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"v": 2522}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/modbus/local/1/h10 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"v": 2522}'

httpie

echo '{
  "v": 2522
}' | http PUT http://localhost:8812/r/modbus/local/1/h10 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/modbus/local/1/h10', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'v': 2522})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • v register value(s) (integer or hex or list)
  • z if True, use 0x05-06 commands (write single register/coil)
  • f data type (u16, i16, u32, i32, u64, i64, f32), ignored if z=True

Optionally:

  • t max allowed timeout for the operation
get Modbus slave data

Get data from Modbus slave memory space

Modbus registers must be specified as list or comma separated memory addresses predicated with register type (h - holding, i - input, c - coil, d - discrete input).

Address ranges can be specified, e.g. h1000-1010,c10-15 will return values of holding registers from 1000 to 1010 and coil registers from 10 to 15

http

GET /r/modbus-slave/h1000-1005,c10-15 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/modbus-slave/h1000-1005,c10-15 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/modbus-slave/h1000-1005,c10-15 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/modbus-slave/h1000-1005,c10-15 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/modbus-slave/h1000-1005,c10-15', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "addr": "c10",
        "value": 0
    },
    {
        "addr": "c11",
        "value": 0
    },
    {
        "addr": "c12",
        "value": 0
    },
    {
        "addr": "c13",
        "value": 0
    },
    {
        "addr": "c14",
        "value": 0
    },
    {
        "addr": "c15",
        "value": 0
    },
    {
        "addr": "h1000",
        "value": 0
    },
    {
        "addr": "h1001",
        "value": 0
    },
    {
        "addr": "h1002",
        "value": 0
    },
    {
        "addr": "h1003",
        "value": 0
    },
    {
        "addr": "h1004",
        "value": 0
    },
    {
        "addr": "h1005",
        "value": 0
    }
]

Parameters:

  • API Key API key with master permissions
Physical interfaces (PHIs)
delete PHI module file

Deletes PHI module file, if the module is loaded, all its instances should be unloaded first.

http

DELETE /r/phi-module/gpio_power HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/phi-module/gpio_power -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/phi-module/gpio_power --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/phi-module/gpio_power X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/phi-module/gpio_power', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
discover installed equipment supported by PHI module

http

GET /r/phi-module/nanoleaf@discover HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/phi-module/nanoleaf@discover -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/phi-module/nanoleaf@discover --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/phi-module/nanoleaf@discover X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/phi-module/nanoleaf@discover', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Content-Type: application/json
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
Content-Length: 411

[
    {
        "!opt": "cols",
        "value": [
            "IP",
            "Name"
        ]
    },
    {
        "!load": {
            "host": "192.168.25.81"
        },
        "IP": "192.168.25.81",
        "Name": "Nanoleaf Light Panels 54:e2:31"
    },
    {
        "!load": {
            "host": "10.90.1.82"
        },
        "IP": "10.90.1.82",
        "Name": "Nanoleaf Light Panels 54:f2:36"
    }
]

Parameters:

  • API Key API key with master permissions

Optionally:

  • x interface to perform discover on
  • w max time for the operation
execute additional PHI commands

Execute PHI command and return execution result (as-is). help command returns all available commands.

http

POST /r/phi/test1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "c": "update_firmware", "a": "/opt/firmware/fw.dat", "method": "exec" }

curl

curl -i -X POST http://localhost:8812/r/phi/test1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"a": "/opt/firmware/fw.dat", "c": "update_firmware", "method": "exec"}'

wget

wget -S -O- http://localhost:8812/r/phi/test1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"a": "/opt/firmware/fw.dat", "c": "update_firmware", "method": "exec"}'

httpie

echo '{
  "a": "/opt/firmware/fw.dat",
  "c": "update_firmware",
  "method": "exec"
}' | http POST http://localhost:8812/r/phi/test1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/phi/test1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'a': '/opt/firmware/fw.dat', 'c': 'update_firmware', 'method': 'exec'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "output": "not implemented"
}

Parameters:

  • API Key API key with master permissions
  • c command to exec
  • a command argument
get PHI module info

http

GET /r/phi-module/vrtrelay HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/phi-module/vrtrelay -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/phi-module/vrtrelay --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/phi-module/vrtrelay X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/phi-module/vrtrelay', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "api": 1,
    "author": "Altertech Group, https://www.altertech.com/",
    "description": "Emulates 16-port relay",
    "equipment": [
        "virtual"
    ],
    "features": [
        "port_get",
        "port_set",
        "aao_set",
        "aao_get"
    ],
    "help": "\nSimple 16-port virtual relay, may be used for the various tests/debugging.\n",
    "license": "Apache License 2.0",
    "lpi_default": "basic",
    "mod": "vrtrelay",
    "mods_required": [],
    "oid": null,
    "required": [
        "port_get",
        "port_set"
    ],
    "version": "1.0.1"
}

Parameters:

  • API Key API key with master permissions
get PHI usage help

http

GET /r/phi-module/vrtrelay?help=cfg HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i 'http://localhost:8812/r/phi-module/vrtrelay?help=cfg' -H 'X-Auth-Key: mykey'

wget

wget -S -O- 'http://localhost:8812/r/phi-module/vrtrelay?help=cfg' --header='X-Auth-Key: mykey'

httpie

http 'http://localhost:8812/r/phi-module/vrtrelay?help=cfg' X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/phi-module/vrtrelay?help=cfg', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "help": "ports status on load (default: -1)",
        "name": "default_status",
        "required": false,
        "type": "int"
    },
    {
        "help": "send updates to items every N sec",
        "name": "update",
        "required": false,
        "type": "float"
    }
]

Parameters:

  • API Key API key with master permissions
get list of PHI ports

http

GET /r/phi/test1@ports HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/phi/test1@ports -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/phi/test1@ports --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/phi/test1@ports X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/phi/test1@ports', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "description": "virtual relay port #1",
        "name": "port #1",
        "port": "1"
    },
    {
        "description": "virtual relay port #2",
        "name": "port #2",
        "port": "2"
    },
    {
        "description": "virtual relay port #3",
        "name": "port #3",
        "port": "3"
    },
    {
        "description": "virtual relay port #4",
        "name": "port #4",
        "port": "4"
    },
    {
        "description": "virtual relay port #5",
        "name": "port #5",
        "port": "5"
    },
    {
        "description": "virtual relay port #6",
        "name": "port #6",
        "port": "6"
    },
    {
        "description": "virtual relay port #7",
        "name": "port #7",
        "port": "7"
    },
    {
        "description": "virtual relay port #8",
        "name": "port #8",
        "port": "8"
    },
    {
        "description": "virtual relay port #9",
        "name": "port #9",
        "port": "9"
    },
    {
        "description": "virtual relay port #10",
        "name": "port #10",
        "port": "10"
    },
    {
        "description": "virtual relay port #11",
        "name": "port #11",
        "port": "11"
    },
    {
        "description": "virtual relay port #12",
        "name": "port #12",
        "port": "12"
    },
    {
        "description": "virtual relay port #13",
        "name": "port #13",
        "port": "13"
    },
    {
        "description": "virtual relay port #14",
        "name": "port #14",
        "port": "14"
    },
    {
        "description": "virtual relay port #15",
        "name": "port #15",
        "port": "15"
    },
    {
        "description": "virtual relay port #16",
        "name": "port #16",
        "port": "16"
    }
]

Parameters:

  • API Key API key with master permissions
get list of available PHI modules

http

GET /r/phi-module HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/phi-module -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/phi-module --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/phi-module X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/phi-module', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "api": 1,
        "author": "Altertech Group, https://www.altertech.com/",
        "description": "EG-PM2-LAN smart PDU",
        "equipment": [
            "EG-PM2-LAN"
        ],
        "features": [
            "aao_get",
            "port_set",
            "cache"
        ],
        "help": "\nPHI for Energenie (Gembird) EG-PM2-LAN smart PDU. You may use 'skip_logout'\nparam to let PHI skip logout procedure after the requests. This speed up the\nfunctions however may cause the equipment to be locked to UC IP only.\n",
        "id": null,
        "license": "https://www.eva-ics.com/license",
        "lpi_default": "basic",
        "mod": "eg_pm2lan",
        "mods_required": [],
        "oid": null,
        "required": [
            "aao_get",
            "port_set",
            "status",
            "action"
        ],
        "version": "1.0.2"
    },
    {
        "api": 3,
        "author": "Altertech Group, https://www.altertech.com/",
        "description": "1-Wire OWFS universal sensor driver",
        "equipment": [
            "Any 1-Wire sensor"
        ],
        "features": [
            "port_get",
            "universal"
        ],
        "help": "\nPHI for Maxim Integrated 1-Wire DS18N20 equipment working via OWFS.\n\nCan be used for various types of sensors as attr (e.g. \"temperature\" or\n\"voltage\") is specified by user. This is unversal PHI, owfs bus, path and attr\ncan be specified in EVA ICS sensor configuration.\n",
        "id": null,
        "license": "Apache License 2.0",
        "lpi_default": "sensor",
        "mod": "ow_sensor",
        "mods_required": [],
        "oid": null,
        "required": [
            "port_get",
            "value"
        ],
        "version": "1.0.0"
    }
]

Parameters:

  • API Key API key with master permissions
get loaded PHI information

http

GET /r/phi/test1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/phi/test1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/phi/test1 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/phi/test1 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/phi/test1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "api": 1,
    "author": "Altertech Group, https://www.altertech.com/",
    "cfg": {
        "default_status": 0
    },
    "description": "Emulates 16-port relay",
    "equipment": [
        "virtual"
    ],
    "features": [
        "port_get",
        "port_set",
        "aao_set",
        "aao_get"
    ],
    "help": "\nSimple 16-port virtual relay, may be used for the various tests/debugging.\n",
    "id": "test1",
    "license": "Apache License 2.0",
    "lpi_default": "basic",
    "mod": "vrtrelay",
    "mods_required": [],
    "oid": "phi:uc/mws1-v1/test1",
    "required": [
        "port_get",
        "port_set"
    ],
    "version": "1.0.1"
}

Parameters:

  • API Key API key with master permissions
list loaded PHIs

http

GET /r/phi HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/phi -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/phi --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/phi X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/phi', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "id": "test",
        "mod": "vrtrelay"
    },
    {
        "id": "test1",
        "mod": "vrtrelay"
    },
    {
        "id": "test2",
        "mod": "vrtrelay"
    }
]

Parameters:

  • API Key API key with master permissions
  • full get exntended information
load PHI module

Loads Physical Interface.

http

PUT /r/phi/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "m": "vrtrelay", "c": "default_status=0", "save": true }

curl

curl -i -X PUT http://localhost:8812/r/phi/test2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"c": "default_status=0", "m": "vrtrelay", "save": true}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/phi/test2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"c": "default_status=0", "m": "vrtrelay", "save": true}'

httpie

echo '{
  "c": "default_status=0",
  "m": "vrtrelay",
  "save": true
}' | http PUT http://localhost:8812/r/phi/test2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/phi/test2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'c': 'default_status=0', 'm': 'vrtrelay', 'save': True})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "api": 1,
    "author": "Altertech Group, https://www.altertech.com/",
    "cfg": {
        "default_status": 0
    },
    "description": "Emulates 16-port relay",
    "equipment": [
        "virtual"
    ],
    "features": [
        "port_get",
        "port_set",
        "aao_set",
        "aao_get"
    ],
    "help": "\nSimple 16-port virtual relay, may be used for the various tests/debugging.\n",
    "id": "test2",
    "license": "Apache License 2.0",
    "lpi_default": "basic",
    "mod": "vrtrelay",
    "mods_required": [],
    "oid": "phi:uc/mws1-v1/test2",
    "required": [
        "port_get",
        "port_set"
    ],
    "version": "1.0.1"
}

Parameters:

  • API Key API key with master permissions
  • m PHI module

Optionally:

  • c PHI configuration
  • save save driver configuration after successful call
push state to PHI module

Allows to perform update of PHI ports by external application.

If called as RESTful, the whole request body is used as a payload (except fields “k”, “save”, “kind” and “method”, which are reserved)

http

POST /r/phi/test1/state HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "1": 1, "2": 0, "3": 1 }

curl

curl -i -X POST http://localhost:8812/r/phi/test1/state -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"1": 1, "2": 0, "3": 1}'

wget

wget -S -O- http://localhost:8812/r/phi/test1/state --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"1": 1, "2": 0, "3": 1}'

httpie

echo '{
  "1": 1,
  "2": 0,
  "3": 1
}' | http POST http://localhost:8812/r/phi/test1/state Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/phi/test1/state', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'1': 1, '2': 0, '3': 1})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key masterkey or a key with the write permission on “phi” group
set PHI configuration property

appends property to PHI configuration and reloads module

http

PATCH /r/phi/test1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "default_status": 1 }

curl

curl -i -X PATCH http://localhost:8812/r/phi/test1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"default_status": 1, "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/phi/test1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"default_status": 1, "save": true}'

httpie

echo '{
  "default_status": 1,
  "save": true
}' | http PATCH http://localhost:8812/r/phi/test1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/phi/test1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'default_status': 1, 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
test PHI

Get PHI test result (as-is). All PHIs respond to self command, help command returns all available test commands.

http

POST /r/phi/test1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "c": "self", "method": "test" }

curl

curl -i -X POST http://localhost:8812/r/phi/test1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"c": "self", "method": "test"}'

wget

wget -S -O- http://localhost:8812/r/phi/test1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"c": "self", "method": "test"}'

httpie

echo '{
  "c": "self",
  "method": "test"
}' | http POST http://localhost:8812/r/phi/test1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/phi/test1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'c': 'self', 'method': 'test'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "output": "OK"
}

Parameters:

  • API Key API key with master permissions
unload PHI

Unloads PHI. PHI should not be used by any driver (except default, but the driver should not be in use by any item).

If driver <phi_id.default> (which’s loaded automatically with PHI) is present, it will be unloaded as well.

http

DELETE /r/phi/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/phi/test2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/phi/test2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/phi/test2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/phi/test2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
upload PHI module

Allows to upload new PHI module to xc/drivers/phi folder.

http

PUT /r/phi-module/gpio_button HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "c": "<MODULE_CONTENT>" }

curl

curl -i -X PUT http://localhost:8812/r/phi-module/gpio_button -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"c": "<MODULE_CONTENT>"}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/phi-module/gpio_button --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"c": "<MODULE_CONTENT>"}'

httpie

echo '{
  "c": "<MODULE_CONTENT>"
}' | http PUT http://localhost:8812/r/phi-module/gpio_button Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/phi-module/gpio_button', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'c': '<MODULE_CONTENT>'})

response

HTTP/1.1 201 Created
Content-Type: application/json
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0

{
    "api": 1,
    "author": "Altertech Group, https://www.altertech.com/",
    "description": "GPIO buttons",
    "equipment": [
        "GPIO buttons"
    ],
    "features": [
        "events"
    ],
    "help": " Handling pressed events from GPIO buttons.\n\nPHI doesn't provide any control/monitoring functions, each button can be\nconfigured as unit (via basic LPI) or sensor (via sensor) and contain its port\nin update_driver_config, update_interval should be set to 0.\n",
    "license": "Apache License 2.0",
    "lpi_default": "sensor",
    "mod": "gpio_button",
    "mods_required": [
        "gpiozero"
    ],
    "oid": null,
    "required": [],
    "version": "1.0.0"
}

Parameters:

  • API Key API key with master permissions
  • c module content

Optionally:

  • force overwrite PHI module file if exists
LPI and drivers
assign driver to item

Sets the specified driver to item, automatically updating item props:

  • action_driver_config,**update_driver_config** to the specified configuration * action_exec, update_exec to do all operations via driver function calls (sets both to |<driver_id>)

To unassign driver, set driver ID to empty/null.

http

POST /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "c": "port=5", "method": "assign_driver", "d": "test2.my" }

curl

curl -i -X POST http://localhost:8812/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"c": "port=5", "d": "test2.my", "method": "assign_driver"}'

wget

wget -S -O- http://localhost:8812/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"c": "port=5", "d": "test2.my", "method": "assign_driver"}'

httpie

echo '{
  "c": "port=5",
  "d": "test2.my",
  "method": "assign_driver"
}' | http POST http://localhost:8812/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'c': 'port=5', 'd': 'test2.my', 'method': 'assign_driver'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key masterkey
  • d driver ID (if none - all above item props are set to null)
  • c configuration (e.g. port number)

Optionally:

  • save save item configuration after successful call
get LPI module info

http

GET /r/lpi-module/multistep HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/lpi-module/multistep -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/lpi-module/multistep --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/lpi-module/multistep X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/lpi-module/multistep', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "api": 1,
    "author": "Altertech Group, https://www.altertech.com/",
    "connections": {
        "dport": "destination",
        "port": "power"
    },
    "description": "Multistep LPI (opener)",
    "features": [
        "action",
        "action_mp",
        "port_set",
        "aao_set"
    ],
    "help": "\nSolves typical logic task: turning the motor direction and run the motor for\nthe specified number of seconds, to control i.e. window opening, door opening,\nmanipulators of the robots.\n\nThe duration of the motor work is specified in 'steps' unit driver\nconfiguration param, each step corresponds to the next status.\n\nWarmup is used to let the motor additional number of seconds for the starting\nstates between first and last.\n\nTuning is used to make sure the motor drivers the target to starting and\nfinishing position (i.e. completely opens/closes the door).\n\nts and te. Sometimes it's pretty hard to calculate the proper position for the\nmiddle states. In this case LPI will ask motor to go all the way to the start\nstate (if target status <= ts) and then back to the target, or all the way to\nthe end and to the target (if target status >= te).\n\nUnit driver config fields should have property 'port' with a\nport label/number for PHI. 'io_label' prop allows to rename 'port', 'dport'\ni.e. to 'socket', 'dsocket' for a more fancy unit configuration.  Each port and\ndport may be specified as a single value or contain an array of values, in this\ncase multiple ports are used simultaneously.\n\nYou may set i: before the port label/number, i.e. i:2, to return/use inverted\nport state. This works both for power and direction ports.\n",
    "license": "Apache License 2.0",
    "logic": "multistep with delays",
    "mod": "multistep",
    "oid": null,
    "version": "1.0.0"
}

Parameters:

  • API Key API key with master permissions
get LPI usage help

http

GET /r/lpi-module/multistep?help=cfg HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i 'http://localhost:8812/r/lpi-module/multistep?help=cfg' -H 'X-Auth-Key: mykey'

wget

wget -S -O- 'http://localhost:8812/r/lpi-module/multistep?help=cfg' --header='X-Auth-Key: mykey'

httpie

http 'http://localhost:8812/r/lpi-module/multistep?help=cfg' X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/lpi-module/multistep?help=cfg', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "help": "allow action even if current status is error",
        "name": "bose",
        "required": false,
        "type": "bool"
    }
]

Parameters:

  • API Key API key with master permissions
get list of available LPI modules

http

GET /r/lpi-module HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/lpi-module -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/lpi-module --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/lpi-module X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/lpi-module', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "api": 1,
        "author": "Altertech Group, https://www.altertech.com/",
        "connections": {
            "port": "primary"
        },
        "description": "Basic LPI for simple devices",
        "features": [
            "status",
            "status_mp",
            "mu_status",
            "mu_status_mp",
            "port_get",
            "aao_get",
            "action",
            "action_mp",
            "port_set",
            "aao_set",
            "events"
        ],
        "help": "\nBasic LPI for simple unit status control (on/off) and monitoring. Support\nstatus 0 and 1. Unit driver config fields should have property 'port' with a\nport label/number for PHI. 'io_label' prop allows to rename 'port' i.e. to\n'socket' for a more fancy unit configuration. Each port may be specified as a\nsingle value or contain an array of values, in this case multiple ports are\nused simultaneously.\n\nYou may set i: before the port label/number, i.e. i:2, to return/use inverted\nport state.\n",
        "id": null,
        "license": "Apache License 2.0",
        "logic": "basic status on/off",
        "lpi_id": null,
        "mod": "basic",
        "oid": null,
        "phi_id": null,
        "version": "1.0.0"
    }
]

Parameters:

  • API Key API key with master permissions
get loaded driver information

http

GET /r/driver/test2.my HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/driver/test2.my -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/driver/test2.my --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/driver/test2.my X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/driver/test2.my', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "api": 1,
    "author": "Altertech Group, https://www.altertech.com/",
    "cfg": {},
    "connections": {
        "dport": "destination",
        "port": "power"
    },
    "description": "Multistep LPI (opener)",
    "features": [
        "action",
        "action_mp",
        "port_set",
        "aao_set"
    ],
    "help": "\nSolves typical logic task: turning the motor direction and run the motor for\nthe specified number of seconds, to control i.e. window opening, door opening,\nmanipulators of the robots.\n\nThe duration of the motor work is specified in 'steps' unit driver\nconfiguration param, each step corresponds to the next status.\n\nWarmup is used to let the motor additional number of seconds for the starting\nstates between first and last.\n\nTuning is used to make sure the motor drivers the target to starting and\nfinishing position (i.e. completely opens/closes the door).\n\nts and te. Sometimes it's pretty hard to calculate the proper position for the\nmiddle states. In this case LPI will ask motor to go all the way to the start\nstate (if target status <= ts) and then back to the target, or all the way to\nthe end and to the target (if target status >= te).\n\nUnit driver config fields should have property 'port' with a\nport label/number for PHI. 'io_label' prop allows to rename 'port', 'dport'\ni.e. to 'socket', 'dsocket' for a more fancy unit configuration.  Each port and\ndport may be specified as a single value or contain an array of values, in this\ncase multiple ports are used simultaneously.\n\nYou may set i: before the port label/number, i.e. i:2, to return/use inverted\nport state. This works both for power and direction ports.\n",
    "id": "test2.my",
    "license": "Apache License 2.0",
    "logic": "multistep with delays",
    "lpi_id": "my",
    "mod": "multistep",
    "oid": "driver:uc/mws1-v1/test2.my",
    "phi": {
        "api": 1,
        "author": "Altertech Group, https://www.altertech.com/",
        "cfg": {
            "default_status": 0
        },
        "description": "Emulates 16-port relay",
        "equipment": [
            "virtual"
        ],
        "features": [
            "port_get",
            "port_set",
            "aao_set",
            "aao_get"
        ],
        "help": "\nSimple 16-port virtual relay, may be used for the various tests/debugging.\n",
        "id": "test2",
        "license": "Apache License 2.0",
        "lpi_default": "basic",
        "mod": "vrtrelay",
        "mods_required": [],
        "oid": "phi:uc/mws1-v1/test2",
        "required": [
            "port_get",
            "port_set"
        ],
        "version": "1.0.1"
    },
    "phi_id": "test2",
    "version": "1.0.0"
}

Parameters:

  • API Key API key with master permissions
list loaded drivers

http

GET /r/driver HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/driver -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/driver --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/driver X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/driver', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "features": [
            "action",
            "action_mp",
            "port_set",
            "aao_set"
        ],
        "id": "test.bose",
        "lpi_id": "bose",
        "mod": "multistep",
        "phi_id": "test"
    },
    {
        "features": [
            "status",
            "status_mp",
            "mu_status",
            "mu_status_mp",
            "port_get",
            "aao_get",
            "action",
            "action_mp",
            "port_set",
            "aao_set",
            "events"
        ],
        "id": "test.default",
        "lpi_id": "default",
        "mod": "basic",
        "phi_id": "test"
    }
]

Parameters:

  • API Key API key with master permissions
  • full get exntended information
load a driver

Loads a driver, combining previously loaded PHI and chosen LPI module.

http

PUT /r/driver/test2.my HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "m": "multistep" }

curl

curl -i -X PUT http://localhost:8812/r/driver/test2.my -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"m": "multistep"}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/driver/test2.my --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"m": "multistep"}'

httpie

echo '{
  "m": "multistep"
}' | http PUT http://localhost:8812/r/driver/test2.my Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/driver/test2.my', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'m': 'multistep'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "api": 1,
    "author": "Altertech Group, https://www.altertech.com/",
    "cfg": {},
    "connections": {
        "dport": "destination",
        "port": "power"
    },
    "description": "Multistep LPI (opener)",
    "features": [
        "action",
        "action_mp",
        "port_set",
        "aao_set"
    ],
    "help": "\nSolves typical logic task: turning the motor direction and run the motor for\nthe specified number of seconds, to control i.e. window opening, door opening,\nmanipulators of the robots.\n\nThe duration of the motor work is specified in 'steps' unit driver\nconfiguration param, each step corresponds to the next status.\n\nWarmup is used to let the motor additional number of seconds for the starting\nstates between first and last.\n\nTuning is used to make sure the motor drivers the target to starting and\nfinishing position (i.e. completely opens/closes the door).\n\nts and te. Sometimes it's pretty hard to calculate the proper position for the\nmiddle states. In this case LPI will ask motor to go all the way to the start\nstate (if target status <= ts) and then back to the target, or all the way to\nthe end and to the target (if target status >= te).\n\nUnit driver config fields should have property 'port' with a\nport label/number for PHI. 'io_label' prop allows to rename 'port', 'dport'\ni.e. to 'socket', 'dsocket' for a more fancy unit configuration.  Each port and\ndport may be specified as a single value or contain an array of values, in this\ncase multiple ports are used simultaneously.\n\nYou may set i: before the port label/number, i.e. i:2, to return/use inverted\nport state. This works both for power and direction ports.\n",
    "id": "test2.my",
    "license": "Apache License 2.0",
    "logic": "multistep with delays",
    "lpi_id": "my",
    "mod": "multistep",
    "oid": "driver:uc/mws1-v1/test2.my",
    "phi": {
        "api": 1,
        "author": "Altertech Group, https://www.altertech.com/",
        "cfg": {
            "default_status": 0
        },
        "description": "Emulates 16-port relay",
        "equipment": [
            "virtual"
        ],
        "features": [
            "port_get",
            "port_set",
            "aao_set",
            "aao_get"
        ],
        "help": "\nSimple 16-port virtual relay, may be used for the various tests/debugging.\n",
        "id": "test2",
        "license": "Apache License 2.0",
        "lpi_default": "basic",
        "mod": "vrtrelay",
        "mods_required": [],
        "oid": "phi:uc/mws1-v1/test2",
        "required": [
            "port_get",
            "port_set"
        ],
        "version": "1.0.1"
    },
    "phi_id": "test2",
    "version": "1.0.0"
}

Parameters:

  • API Key API key with master permissions
  • m LPI module

Optionally:

  • c Driver (LPI) configuration, optional
  • save save configuration after successful call
set driver (LPI) configuration property

appends property to LPI configuration and reloads module

http

PATCH /r/driver/test1.my HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "bose": 1 }

curl

curl -i -X PATCH http://localhost:8812/r/driver/test1.my -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"bose": 1, "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/driver/test1.my --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"bose": 1, "save": true}'

httpie

echo '{
  "bose": 1,
  "save": true
}' | http PATCH http://localhost:8812/r/driver/test1.my Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/driver/test1.my', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'bose': 1, 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save driver configuration after successful call
unload driver

Unloads driver. Driver should not be used by any item.

http

DELETE /r/driver/test2.my HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/driver/test2.my -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/driver/test2.my --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/driver/test2.my X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/driver/test2.my', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
Data pullers
Get data puller

http

GET /r/datapuller/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/datapuller/test -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/datapuller/test --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/datapuller/test X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/datapuller/test', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "active": true,
    "cmd": "/opt/dp/1.sh",
    "name": "test"
}

Parameters:

  • API Key API key with master permissions

Returns:

Data puller info

List data pullers

http

GET /r/datapuller HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/datapuller -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/datapuller --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/datapuller X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/datapuller', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "active": true,
        "cmd": "/opt/dp/1.sh",
        "name": "test"
    }
]

Parameters:

  • API Key API key with master permissions

Returns:

List of all configured data pullers

Restart data puller

http

POST /r/datapuller/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "cmd": "restart" }

curl

curl -i -X POST http://localhost:8812/r/datapuller/test -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"cmd": "restart"}'

wget

wget -S -O- http://localhost:8812/r/datapuller/test --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"cmd": "restart"}'

httpie

echo '{
  "cmd": "restart"
}' | http POST http://localhost:8812/r/datapuller/test Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/datapuller/test', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'cmd': 'restart'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
Start data puller

http

POST /r/datapuller/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "cmd": "start" }

curl

curl -i -X POST http://localhost:8812/r/datapuller/test -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"cmd": "start"}'

wget

wget -S -O- http://localhost:8812/r/datapuller/test --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"cmd": "start"}'

httpie

echo '{
  "cmd": "start"
}' | http POST http://localhost:8812/r/datapuller/test Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/datapuller/test', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'cmd': 'start'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
Stop data puller

http

POST /r/datapuller/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "cmd": "stop" }

curl

curl -i -X POST http://localhost:8812/r/datapuller/test -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"cmd": "stop"}'

wget

wget -S -O- http://localhost:8812/r/datapuller/test --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"cmd": "stop"}'

httpie

echo '{
  "cmd": "stop"
}' | http POST http://localhost:8812/r/datapuller/test Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/datapuller/test', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'cmd': 'stop'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
Devices
delete device items

Works in an opposite way to deploy_device - deploy device items from template function, destroying all items specified in the template.

http

POST /r/device-tpl/device1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "c": "PORT=2,ID=5", "method": "undeploy", "c": "PORT=3,ID=7" }

curl

curl -i -X POST http://localhost:8812/r/device-tpl/device1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"c": "PORT=3,ID=7", "method": "undeploy"}'

wget

wget -S -O- http://localhost:8812/r/device-tpl/device1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"c": "PORT=3,ID=7", "method": "undeploy"}'

httpie

echo '{
  "c": "PORT=3,ID=7",
  "method": "undeploy"
}' | http POST http://localhost:8812/r/device-tpl/device1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/device-tpl/device1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'c': 'PORT=3,ID=7', 'method': 'undeploy'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with allow=device permissions
  • t device template (runtime/tpl/<TEMPLATE>.yml|yaml|json, without extension)

Optionally:

  • c device config (var=value, comma separated or dict)

Returns:

The function ignores missing items, so no errors are returned unless device configuration file is invalid.

deploy device items from template

Deploys the device from the specified template.

http

POST /r/device-tpl/device1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "deploy", "c": "PORT=3,ID=7", "save": true }

curl

curl -i -X POST http://localhost:8812/r/device-tpl/device1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"c": "PORT=3,ID=7", "method": "deploy", "save": true}'

wget

wget -S -O- http://localhost:8812/r/device-tpl/device1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"c": "PORT=3,ID=7", "method": "deploy", "save": true}'

httpie

echo '{
  "c": "PORT=3,ID=7",
  "method": "deploy",
  "save": true
}' | http POST http://localhost:8812/r/device-tpl/device1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/device-tpl/device1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'c': 'PORT=3,ID=7', 'method': 'deploy', 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with allow=device permissions

Optionally:

  • c device config (var=value, comma separated or dict)
  • save save items configuration on disk immediately after operation
list device templates

List available device templates from runtime/tpl

http

GET /r/device-tpl HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/device-tpl -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/device-tpl --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/device-tpl X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/device-tpl', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "name": "asic",
        "type": "JSON"
    },
    {
        "name": "device1",
        "type": "YAML"
    },
    {
        "name": "weatherapp",
        "type": "JSON"
    }
]

Parameters:

  • API Key API key with masterkey permissions
update device items

Works similarly to deploy_device - deploy device items from template function but doesn’t create new items, updating the item configuration of the existing ones.

http

POST /r/device-tpl/device1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "update", "c": "PORT=3,ID=7", "save": true }

curl

curl -i -X POST http://localhost:8812/r/device-tpl/device1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"c": "PORT=3,ID=7", "method": "update", "save": true}'

wget

wget -S -O- http://localhost:8812/r/device-tpl/device1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"c": "PORT=3,ID=7", "method": "update", "save": true}'

httpie

echo '{
  "c": "PORT=3,ID=7",
  "method": "update",
  "save": true
}' | http POST http://localhost:8812/r/device-tpl/device1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/device-tpl/device1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'c': 'PORT=3,ID=7', 'method': 'update', 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with allow=device permissions
  • t device template (runtime/tpl/<TEMPLATE>.yml|yaml|json, without extension)

Optionally:

  • c device config (var=value, comma separated or dict)
  • save save items configuration on disk immediately after operation
CVARs
get the value of user-defined variable

Note

Even if different EVA controllers are working on the same server, they have different sets of variables To set the variables for each subsystem, use SYS API on the respective address/port.

http

GET /r/cvar/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/cvar/test -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/cvar/test --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/cvar/test X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/cvar/test', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "test": "some_value"
}

Parameters:

  • API Key API key with master permissions

Optionally:

Returns:

Dict containing variable and its value. If no varible name was specified, all cvars are returned.

set the value of user-defined variable

http

PUT /r/cvar/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "v": "some_value" }

curl

curl -i -X PUT http://localhost:8812/r/cvar/test -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"v": "some_value"}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/cvar/test --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"v": "some_value"}'

httpie

echo '{
  "v": "some_value"
}' | http PUT http://localhost:8812/r/cvar/test Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/cvar/test', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'v': 'some_value'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "test": "some_value"
}

Parameters:

  • API Key API key with master permissions

Optionally:

  • v variable value (if not specified, variable is deleted)
Locking functions
acquire lock

Locks can be used similarly to file locking by the specific process. The difference is that SYS API tokens can be:

  • centralized for several systems (any EVA server can act as lock server)
  • removed from outside
  • automatically unlocked after the expiration time, if the initiator failed or forgot to release the lock

used to restrict parallel process starting or access to system files/resources. LM PLC macro share locks with extrnal scripts.

Note

Even if different EVA controllers are working on the same server, their lock tokens are stored in different bases. To work with the token of each subsystem, use SYS API on the respective address/port.

http

PUT /r/lock/mylock1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "e": 1, "t": 15 }

curl

curl -i -X PUT http://localhost:8812/r/lock/mylock1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"e": 1, "t": 15}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/lock/mylock1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"e": 1, "t": 15}'

httpie

echo '{
  "e": 1,
  "t": 15
}' | http PUT http://localhost:8812/r/lock/mylock1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/lock/mylock1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'e': 1, 't': 15})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": "mylock1",
    "type": "lock"
}

Parameters:

  • API Key API key with allow=lock permissions

Optionally:

  • t maximum time (seconds) to acquire lock
  • e time after which lock is automatically released (if absent, lock may be released only via unlock function)
get lock status

http

GET /r/lock/mylock1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/lock/mylock1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/lock/mylock1 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/lock/mylock1 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/lock/mylock1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": "mylock1",
    "locked": true,
    "type": "lock"
}

Parameters:

  • API Key API key with allow=lock permissions
release lock

Releases the previously acquired lock.

http

DELETE /r/lock/mylock1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/lock/mylock1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/lock/mylock1 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/lock/mylock1 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/lock/mylock1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with allow=lock permissions
Logging
put message to log file

An external application can put a message in the logs on behalf of the controller.

http

POST /r/log/warning HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "m": "local file system is full" }

curl

curl -i -X POST http://localhost:8812/r/log/warning -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"m": "local file system is full"}'

wget

wget -S -O- http://localhost:8812/r/log/warning --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"m": "local file system is full"}'

httpie

echo '{
  "m": "local file system is full"
}' | http POST http://localhost:8812/r/log/warning Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/log/warning', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'m': 'local file system is full'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with sysfunc=yes permissions
  • l log level
  • m message text
put debug message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
put info message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
put warning message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
put error message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
put critical message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
get records from the controller log

Log records are stored in the controllers’ memory until restart or the time (keep_logmem) specified in controller configuration passes.

http

GET /r/log/warning?t=3600&n=3 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i 'http://localhost:8812/r/log/warning?t=3600&n=3' -H 'X-Auth-Key: mykey'

wget

wget -S -O- 'http://localhost:8812/r/log/warning?t=3600&n=3' --header='X-Auth-Key: mykey'

httpie

http 'http://localhost:8812/r/log/warning?t=3600&n=3' X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/log/warning?t=3600&n=3', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "h": "mws1-v1",
        "l": 30,
        "mod": "sysapi",
        "msg": "test warning message",
        "p": "uc",
        "t": 1552863481.1394246,
        "th": "CP Server Thread-15"
    },
    {
        "h": "mws1-v1",
        "l": 40,
        "mod": "sysapi",
        "msg": "test error message",
        "p": "uc",
        "t": 1552863481.1516943,
        "th": "CP Server Thread-16"
    },
    {
        "h": "mws1-v1",
        "l": 50,
        "mod": "sysapi",
        "msg": "test critical message",
        "p": "uc",
        "t": 1552863481.1631815,
        "th": "CP Server Thread-17"
    }
]

Parameters:

  • API Key API key with sysfunc=yes permissions

Optionally:

  • t get log records not older than t seconds
  • n the maximum number of log records you want to obtain
rotate log file

Deprecated, not required since 3.3.0

http

POST /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "log_rotate" }

curl

curl -i -X POST http://localhost:8812/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "log_rotate"}'

wget

wget -S -O- http://localhost:8812/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "log_rotate"}'

httpie

echo '{
  "method": "log_rotate"
}' | http POST http://localhost:8812/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'log_rotate'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with sysfunc=yes permissions
get API call log
  • API call with master permission returns all records requested
  • API call with other API key returns records for the specified key only
  • API call with an authentication token returns records for the current authorized user

http

GET /r/core@apilog HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/core@apilog -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/core@apilog --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/core@apilog X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/core@apilog', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "auth": "key",
        "func": "login",
        "gw": "http",
        "id": "a4ac6da7-2fa8-4938-8613-48e6495158b1",
        "ip": "127.0.0.1",
        "ki": "operator",
        "params": "{\"u\":\"ttt\",\"p\":\"<hidden>\"}",
        "status": "OK",
        "t": 1596055098.3651853,
        "tf": 1596055098.3837607,
        "u": "ttt",
        "utp": null
    },
    {
        "auth": "key",
        "func": "list_key_props",
        "gw": "http",
        "id": "35685960-cc2f-4fb6-8efc-c4ebca8bf9b5",
        "ip": "127.0.0.1",
        "ki": "masterkey",
        "params": "{\"i\":\"operator\"}",
        "status": "OK",
        "t": 1596055125.9569867,
        "tf": 1596055125.9690392,
        "u": null,
        "utp": null
    },
    {
        "auth": "key",
        "func": "action_toggle",
        "gw": "http",
        "id": "1bdc23da-95a1-4b41-b354-3f3c62e24405",
        "ip": "127.0.0.1",
        "ki": "masterkey",
        "params": "{\"i\":\"unit:light/hall\",\"p\":null,\"w\":null,\"q\":null,\"u\":null}",
        "status": "OK",
        "t": 1596055185.7343063,
        "tf": 1596055185.7551231,
        "u": null,
        "utp": null
    }
]

Parameters:

  • API Key any valid API key

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • n records limit
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • f record filter (requires API key with master permission)

Returns:

List of API calls

Note: API call params are returned as string and can be invalid JSON data as they’re always truncated to 512 symbols in log database

Record filter should be specified either as string (k1=val1,k2=val2) or as a dict. Valid fields are:

  • gw: filter by API gateway
  • ip: filter by caller IP
  • auth: filter by authentication type
  • u: filter by user
  • utp: filter by user type
  • ki: filter by API key ID
  • func: filter by API function
  • params: filter by API call params (matches if field contains value)
  • status: filter by API call status
API keys
create API key

API keys are defined statically in etc/<controller>_apikeys.ini file as well as can be created with API and stored in user database.

Keys with master permission can not be created.

http

PUT /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "sysfunc": true, "allow": "cmd" }

curl

curl -i -X PUT http://localhost:8812/r/key/testkey2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"allow": "cmd", "save": true, "sysfunc": true}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/key/testkey2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"allow": "cmd", "save": true, "sysfunc": true}'

httpie

echo '{
  "allow": "cmd",
  "save": true,
  "sysfunc": true
}' | http PUT http://localhost:8812/r/key/testkey2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/key/testkey2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'allow': 'cmd', 'save': True, 'sysfunc': True})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "allow": [
        "cmd"
    ],
    "dynamic": true,
    "groups": [],
    "hosts_allow": [
        "0.0.0.0/0"
    ],
    "hosts_assign": [],
    "id": "testkey2",
    "items": [],
    "key": "443e342f7e49566fafc1cbe928878b0c18510bb2979ceca7aceb5e45b2b96280",
    "master": false,
    "pvt": [],
    "rpvt": [],
    "sysfunc": true
}

Parameters:

  • API Key API key with master permissions
  • save save configuration immediately

Returns:

JSON with serialized key object

delete API key

http

DELETE /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/key/testkey2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/key/testkey2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/key/testkey2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/key/testkey2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
list API key permissions

Lists API key permissons (including a key itself)

Note

API keys, defined in etc/<controller>_apikeys.ini file can not be managed with API.

http

GET /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/key/testkey2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/key/testkey2 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/key/testkey2 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/key/testkey2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "allow": [
        "cmd"
    ],
    "dynamic": true,
    "groups": [],
    "hosts_allow": [
        "0.0.0.0/0"
    ],
    "hosts_assign": [],
    "id": "testkey2",
    "items": [],
    "key": "443e342f7e49566fafc1cbe928878b0c18510bb2979ceca7aceb5e45b2b96280",
    "master": false,
    "pvt": [],
    "rpvt": [],
    "sysfunc": true
}

Parameters:

  • API Key API key with master permissions
  • save save configuration immediately
list API keys

http

GET /r/key HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/key -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/key --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/key X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/key', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "dynamic": false,
        "key_id": "masterkey",
        "master": true
    },
    {
        "allow": {
            "cmd": true,
            "device": true,
            "lock": false
        },
        "dynamic": true,
        "groups": [
            "#"
        ],
        "items": [],
        "key_id": "default",
        "master": false,
        "sysfunc": false
    },
    {
        "allow": {
            "cmd": true,
            "device": true,
            "lock": false
        },
        "dynamic": false,
        "groups": [
            "#"
        ],
        "items": [],
        "key_id": "lm",
        "master": false,
        "sysfunc": false
    },
    {
        "allow": {
            "cmd": false,
            "device": true,
            "lock": true
        },
        "dynamic": false,
        "groups": [
            "#"
        ],
        "items": [],
        "key_id": "operator",
        "master": false,
        "sysfunc": true
    },
    {
        "allow": {
            "cmd": false,
            "device": false,
            "lock": false
        },
        "dynamic": false,
        "groups": [
            "#"
        ],
        "items": [],
        "key_id": "sfa",
        "master": false,
        "sysfunc": false
    },
    {
        "allow": {
            "cmd": false,
            "device": false,
            "lock": false
        },
        "dynamic": true,
        "groups": [],
        "items": [
            "item1"
        ],
        "key_id": "t4",
        "master": false,
        "sysfunc": true
    },
    {
        "allow": {
            "cmd": false,
            "device": false,
            "lock": false
        },
        "dynamic": false,
        "groups": [],
        "items": [
            "sensor:sensors/sensor1"
        ],
        "key_id": "test",
        "master": false,
        "sysfunc": false
    },
    {
        "allow": {
            "cmd": false,
            "device": false,
            "lock": false
        },
        "dynamic": true,
        "groups": [],
        "items": [],
        "key_id": "testkey",
        "master": false,
        "sysfunc": true
    },
    {
        "allow": {
            "cmd": true,
            "device": false,
            "lock": false
        },
        "dynamic": true,
        "groups": [],
        "items": [],
        "key_id": "testkey2",
        "master": false,
        "sysfunc": true
    }
]

Parameters:

  • API Key API key with master permissions
regenerate API key

http

POST /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "regenerate" }

curl

curl -i -X POST http://localhost:8812/r/key/testkey2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "regenerate"}'

wget

wget -S -O- http://localhost:8812/r/key/testkey2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "regenerate"}'

httpie

echo '{
  "method": "regenerate"
}' | http POST http://localhost:8812/r/key/testkey2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/key/testkey2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'regenerate'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "key": "3dbcd3d24c6dc878cebe369eb9fdb95ae99fee14e99cdfd911b83629688d2854"
}

Parameters:

  • API Key API key with master permissions

Returns:

JSON dict with new key value in “key” field

set API key permissions

http

PATCH /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "sysfunc": true }

curl

curl -i -X PATCH http://localhost:8812/r/key/testkey2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"save": true, "sysfunc": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/key/testkey2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"save": true, "sysfunc": true}'

httpie

echo '{
  "save": true,
  "sysfunc": true
}' | http PATCH http://localhost:8812/r/key/testkey2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/key/testkey2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'save': True, 'sysfunc': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • p property
  • v value (if none, permission will be revoked)
  • save save configuration immediately
User accounts
assign API key to user

http

PATCH /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "a": "masterkey" }

curl

curl -i -X PATCH http://localhost:8812/r/user/test2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"a": "masterkey"}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/user/test2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"a": "masterkey"}'

httpie

echo '{
  "a": "masterkey"
}' | http PATCH http://localhost:8812/r/user/test2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/user/test2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'a': 'masterkey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • a API key to assign (key id, not a key itself) or multiple keys, comma separated
create user account

Note

All changes to user accounts are instant, if the system works in read/only mode, set it to read/write before performing user management.

http

PUT /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "p": "verysecretpassword", "a": "testkey" }

curl

curl -i -X PUT http://localhost:8812/r/user/test2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"a": "testkey", "p": "verysecretpassword"}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/user/test2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"a": "testkey", "p": "verysecretpassword"}'

httpie

echo '{
  "a": "testkey",
  "p": "verysecretpassword"
}' | http PUT http://localhost:8812/r/user/test2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/user/test2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'a': 'testkey', 'p': 'verysecretpassword'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "key": "testkey",
    "user": "test2"
}

Parameters:

  • API Key API key with master permissions
  • p user password
  • a API key to assign (key id, not a key itself)
delete user account

http

DELETE /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/user/test2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/user/test2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/user/test2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/user/test2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get user account info

http

GET /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/user/test2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/user/test2 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/user/test2 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/user/test2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "key": "testkey",
    "user": "test2"
}

Parameters:

  • API Key API key with master permissions
list user accounts

http

GET /r/user HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/user -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/user --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/user X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/user', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "key_id": "test",
        "user": "divisor"
    },
    {
        "key_id": "testkey",
        "user": "test"
    },
    {
        "key_id": "testkey",
        "user": "test2"
    }
]

Parameters:

  • API Key API key with master permissions
set user password

Either master key and user login must be specified or a user must be logged in and a session token used

http

PATCH /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "p": "qwerty" }

curl

curl -i -X PATCH http://localhost:8812/r/user/test2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"p": "qwerty"}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/user/test2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"p": "qwerty"}'

httpie

echo '{
  "p": "qwerty"
}' | http PATCH http://localhost:8812/r/user/test2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/user/test2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'p': 'qwerty'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key master key or token
  • p new password
List active session tokens

Parameters:

  • API Key API key with master permissions
Drop session token(s)

Parameters:

  • API Key API key with master permissions
  • a session token or
  • u user name or
  • i API key id
Notifier management
disable notifier

Note

The notifier is disabled until controller restart. To disable notifier permanently, use notifier management CLI.

http

PATCH /r/notifier/eva_1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "enabled": false }

curl

curl -i -X PATCH http://localhost:8812/r/notifier/eva_1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"enabled": false}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/notifier/eva_1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"enabled": false}'

httpie

echo '{
  "enabled": false
}' | http PATCH http://localhost:8812/r/notifier/eva_1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/notifier/eva_1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'enabled': False})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
enable notifier

Note

The notifier is enabled until controller restart. To enable notifier permanently, use notifier management CLI.

http

PATCH /r/notifier/eva_1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "enabled": true }

curl

curl -i -X PATCH http://localhost:8812/r/notifier/eva_1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"enabled": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/notifier/eva_1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"enabled": true}'

httpie

echo '{
  "enabled": true
}' | http PATCH http://localhost:8812/r/notifier/eva_1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/notifier/eva_1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'enabled': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get notifier configuration

http

GET /r/notifier/eva_1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/notifier/eva_1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/notifier/eva_1 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/notifier/eva_1 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/notifier/eva_1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "announce_interval": 5.0,
    "api_enabled": true,
    "enabled": false,
    "events": [
        {
            "groups": [
                "#"
            ],
            "subject": "state",
            "types": [
                "#"
            ]
        },
        {
            "level": 30,
            "subject": "log"
        }
    ],
    "host": "mws1-v1",
    "id": "eva_1",
    "password": "test",
    "qos": {
        "action": 2,
        "log": 2,
        "state": 2,
        "system": 2
    },
    "type": "mqtt",
    "username": "eva"
}

Parameters:

  • API Key API key with master permissions
list notifiers

http

GET /r/notifier HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/notifier -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/notifier --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/notifier X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/notifier', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "db": "db1.db",
        "enabled": true,
        "events": [
            {
                "groups": [
                    "#"
                ],
                "subject": "state",
                "types": [
                    "#"
                ]
            }
        ],
        "id": "db_1",
        "keep": 86400,
        "type": "db"
    },
    {
        "announce_interval": 5.0,
        "api_enabled": true,
        "enabled": false,
        "events": [
            {
                "groups": [
                    "#"
                ],
                "subject": "state",
                "types": [
                    "#"
                ]
            },
            {
                "level": 30,
                "subject": "log"
            }
        ],
        "host": "mws1-v1",
        "id": "eva_1",
        "password": "test",
        "qos": {
            "action": 2,
            "log": 2,
            "state": 2,
            "system": 2
        },
        "type": "mqtt",
        "username": "eva"
    }
]

Parameters:

  • API Key API key with master permissions
File management
put file to runtime folder

Puts a new file into runtime folder. If the file with such name exists, it will be overwritten. As all files in runtime are text, binary data can not be put.

http

PUT /r/runtime/xc/uc/test_action_script2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "m": "/bin/sh\n\nexit 0", "e": true }

curl

curl -i -X PUT http://localhost:8812/r/runtime/xc/uc/test_action_script2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"e": true, "m": "/bin/sh\n\nexit 0"}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/runtime/xc/uc/test_action_script2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"e": true, "m": "/bin/sh\n\nexit 0"}'

httpie

echo '{
  "e": true,
  "m": "/bin/sh\n\nexit 0"
}' | http PUT http://localhost:8812/r/runtime/xc/uc/test_action_script2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/runtime/xc/uc/test_action_script2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'e': True, 'm': '/bin/sh\n\nexit 0'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": "xc/uc/test_action_script2",
    "type": "runtime"
}

Parameters:

  • API Key API key with master permissions
  • m file content (plain text or base64-encoded)
  • b if True - put binary file (decode base64)
set file exec permission

http

PATCH /r/runtime/xc/uc/test_action_script2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "e": true, "e": true }

curl

curl -i -X PATCH http://localhost:8812/r/runtime/xc/uc/test_action_script2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"e": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/runtime/xc/uc/test_action_script2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"e": true}'

httpie

echo '{
  "e": true
}' | http PATCH http://localhost:8812/r/runtime/xc/uc/test_action_script2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/runtime/xc/uc/test_action_script2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'e': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • e false for 0x644, true for 0x755 (executable)
delete file from runtime folder

http

DELETE /r/runtime/xc/uc/test_action_script2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/runtime/xc/uc/test_action_script2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/runtime/xc/uc/test_action_script2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/runtime/xc/uc/test_action_script2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/runtime/xc/uc/test_action_script2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get file contents from runtime folder

http

GET /r/runtime/xc/uc/test_action_script2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/runtime/xc/uc/test_action_script2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/runtime/xc/uc/test_action_script2 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/runtime/xc/uc/test_action_script2 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/runtime/xc/uc/test_action_script2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "data": "/bin/sh\n\nexit 0",
    "e": true,
    "file": "xc/uc/test_action_script2"
}

Parameters:

  • API Key API key with master permissions
  • b if True - force getting binary file (base64-encode content)
Core scripts
List MQTT topics core scripts react on

http

GET /r/corescript/mqtt-topics HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/corescript/mqtt-topics -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/corescript/mqtt-topics --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/corescript/mqtt-topics X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/corescript/mqtt-topics', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "qos": 2,
        "topic": "eva_1:cluster/#"
    },
    {
        "qos": 2,
        "topic": "test/test2"
    },
    {
        "qos": 1,
        "topic": "ttt/ttt"
    }
]

Parameters:

  • API Key API key with master permissions
Reload core scripts if some was added or deleted

http

POST /r/corescript HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "reload" }

curl

curl -i -X POST http://localhost:8812/r/corescript -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "reload"}'

wget

wget -S -O- http://localhost:8812/r/corescript --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "reload"}'

httpie

echo '{
  "method": "reload"
}' | http POST http://localhost:8812/r/corescript Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/corescript', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'reload'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
Subscribe core scripts to MQTT topic

The method subscribes core scripts to topic of default MQTT notifier (eva_1). To specify another notifier, set topic as <notifer_id>:<topic>

http

POST /r/corescript HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "q": 2, "method": "mqtt-subscribe", "t": "some/test/topic2" }

curl

curl -i -X POST http://localhost:8812/r/corescript -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "mqtt-subscribe", "q": 2, "t": "some/test/topic2"}'

wget

wget -S -O- http://localhost:8812/r/corescript --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "mqtt-subscribe", "q": 2, "t": "some/test/topic2"}'

httpie

echo '{
  "method": "mqtt-subscribe",
  "q": 2,
  "t": "some/test/topic2"
}' | http POST http://localhost:8812/r/corescript Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/corescript', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'mqtt-subscribe', 'q': 2, 't': 'some/test/topic2'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • t MQTT topic (“+” and “#” masks are supported)
  • q MQTT topic QoS
  • save save core script config after modification
Unsubscribe core scripts from MQTT topic

http

POST /r/corescript HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "mqtt-unsubscribe", "t": "some/test/topic2" }

curl

curl -i -X POST http://localhost:8812/r/corescript -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "mqtt-unsubscribe", "t": "some/test/topic2"}'

wget

wget -S -O- http://localhost:8812/r/corescript --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "mqtt-unsubscribe", "t": "some/test/topic2"}'

httpie

echo '{
  "method": "mqtt-unsubscribe",
  "t": "some/test/topic2"
}' | http POST http://localhost:8812/r/corescript Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/corescript', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'mqtt-unsubscribe', 't': 'some/test/topic2'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • t MQTT topic (“+” and “#” masks are allowed)
  • save save core script config after modification

LM RESTful API

Logic Manager API is used to manage lvars, rules and other logic elements

This document describes API methods for RESTful calls. For direct and JSON RPC calls look LM API.

RESTful API basics

Warning

RESTful API is deprecated and scheduled to be removed (not implemented) in EVA ICS v4. Use JSON RPC API, whenever it is possible.

Majority EVA ICS API components and items support REST. Parameters for POST, PUT, PATCH and DELETE requests can be sent in both JSON and multipart/form-data. For JSON, Content-Type: application/json header must be specified.

Requests

API key can be sent in HTTP X-Auth-Key header (preferred) or in request parameters (as k).

  • GET request is used to get information about resource or list of resources of the specified type.
  • POST request is used to perform special API calls and create resources in case when resource id is generated by server. In the last case, response always contains additional field Location which points to the resource created.
  • PUT request is used to create new resources. If resource already exists, the server could refuse recreating it, responding with 409 Conflict HTTP error.
  • PATCH request is used to modify resource parameters.
  • DELETE request is used to delete resource.

For resource creation and modification, multiple parameters can be specified in a single request. For majority requests of such purpose, a special parameter “save” is used to tell server (if “save”: true) to save the resource configuration immediately after its modification.

For the group-related calls, put trailing slash at the end of the request URL:

/r/<resource_type>/<group>/
Responses

Success responses:

  • 200 OK API call completed successfully
  • 201 Created API call completed successfully, Response header Location contains either uri to the newly created object or resource is accessible by the effective request uri. For resources created with PUT, body contains either serialized resource object or resource type and id
  • 202 Accepted The server accepted command and will process it later.
  • 204 No Content API call completed successfully, no content to return

Error responses:

  • 403 Forbidden the API key has no access to this function or resource
  • 404 Not Found resource doesn’t exist
  • 405 Method Not Allowed API function/method not found
  • 409 Conflict resource/object already exists or is locked
  • 500 API Error API function execution has been failed. Check input parameters and server logs.

Response body may contain additional information encoded in JSON. { “result”: “OK” } and { “result”: “ERROR” } in body are not returned.

Long API calls
  • Long API calls should be avoided at any cost.
  • All critical action and command methods have an option to obtain action ID and check for the result later.
  • If long API calls are performed between controllers (e.g. action methods with wait param), remote controller timeout should be always greater than max. expected “wait” timeout in API call, otherwise client controller will repeat API calls continuously, up to max retries for the target controller.

Contents

General functions
test API/key and get system info

Test can be executed with any valid API key of the controller the function is called to.

For SFA, the result section “connected” contains connection status of remote controllers. The API key must have an access either to “uc” and “lm” groups (“remote_uc:uc” and “remote_lm:lm”) or to particular controller oids.

http

GET /r/core HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/core -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/core --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/core X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/core', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "acl": {
        "key_id": "masterkey",
        "master": true
    },
    "db_update": 1,
    "debug": true,
    "file_management": true,
    "layout": "enterprise",
    "polldelay": 0.01,
    "product_build": 2019031405,
    "product_code": "lm",
    "product_name": "EVA Logic Manager",
    "setup_mode": false,
    "system": "ws1-v1",
    "time": 1553193499.7972682,
    "uptime": 658,
    "version": "3.2.0"
}

Parameters:

  • API Key any valid API key

Returns:

JSON dict with system info and current API key permissions (for masterkey only { “master”: true } is returned)

save database and runtime configuration

All modified items, their status, and configuration will be written to the disk. If exec_before_save command is defined in the controller’s configuration file, it’s called before saving and exec_after_save after (e.g. to switch the partition to write mode and back to read-only).

http

POST /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "save" }

curl

curl -i -X POST http://localhost:8812/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "save"}'

wget

wget -S -O- http://localhost:8812/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "save"}'

httpie

echo '{
  "method": "save"
}' | http POST http://localhost:8812/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'save'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with sysfunc=yes permissions
execute a remote system command

Executes a command script on the server where the controller is installed.

http

POST /r/cmd/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "a": "0 2 3", "w": 5, "t": 10 }

curl

curl -i -X POST http://localhost:8812/r/cmd/test -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"a": "0 2 3", "t": 10, "w": 5}'

wget

wget -S -O- http://localhost:8812/r/cmd/test --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"a": "0 2 3", "t": 10, "w": 5}'

httpie

echo '{
  "a": "0 2 3",
  "t": 10,
  "w": 5
}' | http POST http://localhost:8812/r/cmd/test Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/cmd/test', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'a': '0 2 3', 't': 10, 'w': 5})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "args": [
        "0",
        "2",
        "3"
    ],
    "cmd": "test",
    "err": "some text to stderr\n",
    "exitcode": 0,
    "out": "test script start\nparam 1: 0 ( > 0 will generate \"failed\" status)\nparam 2: 2\nparam 3: 3\ndelay 3 sec\nscript finish\n",
    "status": "completed",
    "time": {
        "completed": 1552863480.7081513,
        "created": 1552863480.6993306,
        "running": 1552863480.7001197
    },
    "timeout": 10.0
}

Parameters:

  • API Key API key with allow=cmd permissions

Optionally:

  • a string of command arguments, separated by spaces (passed to the script) or array (list)
  • w wait (in seconds) before API call sends a response. This allows to try waiting until command finish
  • t maximum time of command execution. If the command fails to finish within the specified time (in sec), it will be terminated
  • s STDIN data
get list of loaded core plugins

http

GET /r/plugin HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/plugin -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/plugin --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/plugin X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/plugin', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "author": "Altertech, https://www.altertech.com/",
        "license": "Apache License 2.0",
        "name": "test",
        "version": "0.0.1"
    }
]

Parameters:

  • API Key API key with master permissions

Returns:

list with plugin module information

install a package

Installs the package

Parameters:

  • API Key API key with master permissions
  • m package content (base64-encoded tar/tgz)
  • o package setup options
  • w wait (in seconds) before API call sends a response. This allows to try waiting until the package is installed
shutdown the controller

Controller process will be exited and then (should be) restarted by watchdog. This allows to restart controller remotely.

For MQTT API calls a small shutdown delay usually should be specified to let the core send the correct API response.

http

POST /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "shutdown" }

curl

curl -i -X POST http://localhost:8812/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "shutdown"}'

wget

wget -S -O- http://localhost:8812/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "shutdown"}'

httpie

echo '{
  "method": "shutdown"
}' | http POST http://localhost:8812/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'shutdown'})

response

HTTP/1.1 202 Accepted
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • t shutdown delay (seconds)
switch debugging mode

Enables and disables debugging mode while the controller is running. After the controller is restarted, this parameter is lost and controller switches back to the mode specified in the configuration file.

http

PATCH /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "debug": true }

curl

curl -i -X PATCH http://localhost:8812/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"debug": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"debug": true}'

httpie

echo '{
  "debug": true
}' | http PATCH http://localhost:8812/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'debug': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • debug true for enabling debug mode, false for disabling
log in and get authentication token

Obtains authentication token which can be used in API calls instead of API key.

If both k and u args are absent, but API method is called with HTTP request, which contain HTTP header for basic authorization, the function will try to parse it and log in user with credentials provided.

If authentication token is specified, the function will check it and return token information if it is valid.

If both token and credentials (user or API key) are specified, the function will return the token to normal mode.

http

POST /r/token HTTP/1.1
Host: localhost:8817
Content-Type: application/json

{ "u": "admin", "p": "123" }

curl

curl -i -X POST http://localhost:8817/r/token -H 'Content-Type: application/json' --data-raw '{"p": "123", "u": "admin"}'

wget

wget -S -O- http://localhost:8817/r/token --header='Content-Type: application/json' --post-data='{"p": "123", "u": "admin"}'

httpie

echo '{
  "p": "123",
  "u": "admin"
}' | http POST http://localhost:8817/r/token Content-Type:application/json

python-requests

requests.post('http://localhost:8817/r/token', headers={'Content-Type': 'application/json'}, json={'p': '123', 'u': 'admin'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "key": "masterkey",
    "token": "token:1c166529bc3b06dac6e0fbaefee38ebe77c455480e11ff4431de2b10a5508899",
    "user": "admin"
}

Parameters:

  • API Key valid API key or
  • u user login
  • p user password
  • a authentication token

Returns:

A dict, containing API key ID and authentication token

log out and purge authentication token

Purges authentication token

http

DELETE /r/token HTTP/1.1
Host: localhost:8812
X-Auth-Key: token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7

curl

curl -i -X DELETE http://localhost:8812/r/token -H 'X-Auth-Key: token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/token --header='X-Auth-Key: token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7'

httpie

http DELETE http://localhost:8812/r/token X-Auth-Key:token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7

python-requests

requests.delete('http://localhost:8812/r/token', headers={'X-Auth-Key': 'token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid token
Set token read-only

Applies read-only mode for token. In read-only mode, only read-only functions work, others return result_token_restricted(15).

The method works for token-authenticated API calls only.

To exit read-only mode, user must either re-login or, to keep the current token, call “login” API method with both token and user credentials.

LVar functions
clear lvar state

set status (if expires lvar param > 0) or value (if expires isn’t set) of a logic variable to 0. Useful when lvar is used as a timer to stop it, or as a flag to set it False.

http

POST /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "s": "clear" }

curl

curl -i -X POST http://localhost:8817/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"s": "clear"}'

wget

wget -S -O- http://localhost:8817/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"s": "clear"}'

httpie

echo '{
  "s": "clear"
}' | http POST http://localhost:8817/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'s': 'clear'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
decrement lvar value

Decrement value of a logic variable. Initial value should be number

http

POST /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "v": "!decrement" }

curl

curl -i -X POST http://localhost:8817/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"v": "!decrement"}'

wget

wget -S -O- http://localhost:8817/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"v": "!decrement"}'

httpie

echo '{
  "v": "!decrement"
}' | http POST http://localhost:8817/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'v': '!decrement'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
get item group list

Get the list of item groups. Useful e.g. for custom interfaces.

http

GET /r/lvar/@groups HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lvar/@groups -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lvar/@groups --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lvar/@groups X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lvar/@groups', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    "nogroup",
    "tests",
    "timers"
]

Parameters:

  • API Key valid API key
get item state history

State history of one item or several items of the specified type can be obtained using state_history command.

If master key is used, the method attempts to get stored state for an item even if it doesn’t present currently in system.

The method can return state log for disconnected items as well.

http

GET /r/lvar/lvar:tests/lvar1@history HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lvar/lvar:tests/lvar1@history -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lvar/lvar:tests/lvar1@history --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lvar/lvar:tests/lvar1@history X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lvar/lvar:tests/lvar1@history', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "status": [
        1,
        1,
        1
    ],
    "t": [
        1553193500.1192024,
        1553193500.199146,
        1553193500.2409995
    ],
    "value": [
        1.0,
        null,
        null
    ]
}

Parameters:

  • API Key valid API key
  • a history notifier id (default: db_1)

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • l records limit (doesn’t work with “w”)
  • x state prop (“status” or “value”)
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • z Time zone (pytz, e.g. UTC or Europe/Prague)
  • w fill frame with the interval (e.g. “1T” - 1 min, “2H” - 2 hours etc.), start time is required, set to 1D if not specified
  • g output format (“list”, “dict” or “chart”, default is “list”)
  • c options for chart (dict or comma separated)
  • o extra options for notifier data request

Returns:

history data in specified format or chart image.

For chart, JSON RPC gets reply with “content_type” and “data” fields, where content is image content type. If PNG image format is selected, data is base64-encoded.

Options for chart (all are optional):

If option “w” (fill) is used, number of digits after comma may be specified. E.g. 5T:3 will output values with 3 digits after comma.

Additionally, SI prefix may be specified to convert value to kilos, megas etc, e.g. 5T:k:3 - divide value by 1000 and output 3 digits after comma. Valid prefixes are: k, M, G, T, P, E, Z, Y.

If binary prefix is required, it should be followed by “b”, e.g. 5T:Mb:3 - divide value by 2^20 and output 3 digits after comma.

get item state log

State log of a single item or group of the specified type can be obtained using state_log command.

note: only SQL notifiers are supported

Difference from state_history method:

  • state_log doesn’t optimize data to be displayed on charts * the data is returned from a database as-is * a single item OID or OID mask (e.g. sensor:env/#) can be specified

note: the method supports MQTT-style masks but only masks with wildcard-ending, like “type:group/subgroup/#” are supported.

The method can return state log for disconnected items as well.

For wildcard fetching, API key should have an access to the whole chosen group.

note: record limit means the limit for records, fetched from the database, but repeating state records are automatically grouped and the actual number of returned records can be lower than requested.

http

GET /r/lvar/tests/lvar1@log HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lvar/tests/lvar1@log -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lvar/tests/lvar1@log --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lvar/tests/lvar1@log X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lvar/tests/lvar1@log', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "oid": "lvar:tests/lvar1",
        "status": 1,
        "t": 1607295624.8417337,
        "value": null
    },
    {
        "oid": "lvar:tests/lvar1",
        "status": 1,
        "t": 1607295636.6316836,
        "value": "value1"
    },
    {
        "oid": "lvar:tests/lvar1",
        "status": 1,
        "t": 1607295637.536753,
        "value": "value2"
    },
    {
        "oid": "lvar:tests/lvar1",
        "status": 1,
        "t": 1607295638.475802,
        "value": "value3"
    }
]

Parameters:

  • API Key valid API key
  • a history notifier id (default: db_1)

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • l records limit (doesn’t work with “w”)
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • z Time zone (pytz, e.g. UTC or Europe/Prague)
  • o extra options for notifier data request

Returns:

state log records (list)

get lvar state

State of lvar or all lvars can be obtained using state command.

http

GET /r/lvar HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lvar -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lvar --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lvar X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lvar', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "expires": 0,
        "full_id": "nogroup/flag1",
        "group": "nogroup",
        "id": "flag1",
        "oid": "lvar:nogroup/flag1",
        "set_time": 1528751049.3848495,
        "status": 1,
        "type": "lvar",
        "value": "1"
    },
    {
        "expires": 5.0,
        "full_id": "nogroup/timer1",
        "group": "nogroup",
        "id": "timer1",
        "oid": "lvar:nogroup/timer1",
        "set_time": 1552049990.9313273,
        "status": -1,
        "type": "lvar",
        "value": "null"
    },
    {
        "expires": 15.0,
        "full_id": "tests/lvar1",
        "group": "tests",
        "id": "lvar1",
        "oid": "lvar:tests/lvar1",
        "set_time": 1553193500.1979027,
        "status": 1,
        "type": "lvar",
        "value": "null"
    },
    {
        "expires": 30.0,
        "full_id": "tests/lvar2",
        "group": "tests",
        "id": "lvar2",
        "oid": "lvar:tests/lvar2",
        "set_time": 1553193499.8252523,
        "status": 1,
        "type": "lvar",
        "value": "null"
    },
    {
        "expires": 100.0,
        "full_id": "timers/timer1",
        "group": "timers",
        "id": "timer1",
        "oid": "lvar:timers/timer1",
        "set_time": 1552062897.9593153,
        "status": -1,
        "type": "lvar",
        "value": "null"
    }
]

Parameters:

  • API Key valid API key

Optionally:

increment lvar value

Increment value of a logic variable. Initial value should be number

http

POST /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "v": "!increment" }

curl

curl -i -X POST http://localhost:8817/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"v": "!increment"}'

wget

wget -S -O- http://localhost:8817/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"v": "!increment"}'

httpie

echo '{
  "v": "!increment"
}' | http POST http://localhost:8817/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'v': '!increment'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
reset lvar state

Set status and value of a logic variable to 1. Useful when lvar is being used as a timer to reset it, or as a flag to set it True.

http

POST /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "s": "reset" }

curl

curl -i -X POST http://localhost:8817/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"s": "reset"}'

wget

wget -S -O- http://localhost:8817/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"s": "reset"}'

httpie

echo '{
  "s": "reset"
}' | http POST http://localhost:8817/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'s': 'reset'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
set lvar state

Set status and value of a logic variable.

http

POST /r/lvar/lvar:tests/lvar1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "s": 1, "v": 29.445 }

curl

curl -i -X POST http://localhost:8817/r/lvar/lvar:tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"s": 1, "v": 29.445}'

wget

wget -S -O- http://localhost:8817/r/lvar/lvar:tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"s": 1, "v": 29.445}'

httpie

echo '{
  "s": 1,
  "v": 29.445
}' | http POST http://localhost:8817/r/lvar/lvar:tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/lvar/lvar:tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'s': 1, 'v': 29.445})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key

Optionally:

  • s lvar status
  • v lvar value
toggle lvar state

switch value of a logic variable between 0 and 1. Useful when lvar is being used as a flag to switch it between True/False.

http

POST /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "s": "toggle" }

curl

curl -i -X POST http://localhost:8817/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"s": "toggle"}'

wget

wget -S -O- http://localhost:8817/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"s": "toggle"}'

httpie

echo '{
  "s": "toggle"
}' | http POST http://localhost:8817/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'s': 'toggle'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
LVar management
list lvars

Parameters:

  • API Key API key with master permissions

Optionally:

  • x serialize specified item prop(s)

Returns:

the list of all lvars available

create lvar

Create new lvar

http

PUT /r/lvar/tests/lvar2 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "expires": 30 }

curl

curl -i -X PUT http://localhost:8817/r/lvar/tests/lvar2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"expires": 30, "save": true}'

wget

wget -S -O- --method=PUT http://localhost:8817/r/lvar/tests/lvar2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"expires": 30, "save": true}'

httpie

echo '{
  "expires": 30,
  "save": true
}' | http PUT http://localhost:8817/r/lvar/tests/lvar2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8817/r/lvar/tests/lvar2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'expires': 30, 'save': True})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "config_changed": false,
    "description": "",
    "expires": 30.0,
    "full_id": "tests/lvar2",
    "group": "tests",
    "id": "lvar2",
    "oid": "lvar:tests/lvar2",
    "set_time": 1553193499.8252523,
    "status": 1,
    "type": "lvar",
    "value": "null"
}

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save lvar configuration immediately
delete lvar

http

DELETE /r/lvar/tests/lvar2 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8817/r/lvar/tests/lvar2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8817/r/lvar/tests/lvar2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8817/r/lvar/tests/lvar2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8817/r/lvar/tests/lvar2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get lvar configuration

http

GET /r/lvar/tests/lvar2@config HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lvar/tests/lvar2@config -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lvar/tests/lvar2@config --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lvar/tests/lvar2@config X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lvar/tests/lvar2@config', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "expires": 30.0,
    "full_id": "tests/lvar2",
    "group": "tests",
    "id": "lvar2",
    "oid": "lvar:tests/lvar2",
    "set_time": 1553193499.8252523,
    "type": "lvar"
}

Parameters:

  • API Key API key with master permissions

Returns:

complete lvar configuration.

list lvar properties

Get all editable parameters of the lvar confiugration.

http

GET /r/lvar/tests/lvar1@props HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lvar/tests/lvar1@props -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lvar/tests/lvar1@props --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lvar/tests/lvar1@props X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lvar/tests/lvar1@props', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "description": "",
    "expires": 0,
    "mqtt_update": null,
    "set_time": 1553193500.117168,
    "update_exec": null,
    "update_interval": 0,
    "update_timeout": null
}

Parameters:

  • API Key API key with master permissions
save lvar configuration

Saves lvar. configuration on disk (even if it hasn’t been changed)

http

POST /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "save" }

curl

curl -i -X POST http://localhost:8817/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "save"}'

wget

wget -S -O- http://localhost:8817/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "save"}'

httpie

echo '{
  "method": "save"
}' | http POST http://localhost:8817/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'save'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
set lvar property

Set configuration parameters of the lvar.

http

PATCH /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "expires": 15 }

curl

curl -i -X PATCH http://localhost:8817/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"expires": 15}'

wget

wget -S -O- --method=PATCH http://localhost:8817/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"expires": 15}'

httpie

echo '{
  "expires": 15
}' | http PATCH http://localhost:8817/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8817/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'expires': 15})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
Decision matrix rules
create new rule

Creates new decision rule. Rule id (UUID) is generated automatically unless specified.

http

POST /r/dmatrix_rule HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i -X POST http://localhost:8817/r/dmatrix_rule -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/dmatrix_rule --header='X-Auth-Key: mykey'

httpie

http POST http://localhost:8817/r/dmatrix_rule X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/dmatrix_rule', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Location: /r/dmatrix_rule/cc7de0ba-04a1-4161-ad73-588861b6e1ef
Pragma: no-cache

{
    "break_after_exec": false,
    "chillout_ends_in": 0,
    "chillout_time": 0,
    "condition": "",
    "description": "",
    "enabled": false,
    "for_initial": "skip",
    "for_item_group": null,
    "for_item_id": null,
    "for_item_type": null,
    "for_oid": "#:#/#/status",
    "for_prop": "status",
    "id": "cc7de0ba-04a1-4161-ad73-588861b6e1ef",
    "in_range_max": null,
    "in_range_max_eq": false,
    "in_range_min": null,
    "in_range_min_eq": false,
    "macro": null,
    "macro_args": [],
    "macro_kwargs": {},
    "oid": "dmatrix_rule:dm_rules/cc7de0ba-04a1-4161-ad73-588861b6e1ef",
    "priority": 100,
    "type": "dmatrix_rule"
}

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save rule configuration immediately
delete rule

Deletes decision rule.

http

DELETE /r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get rule information

http

GET /r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "break_after_exec": false,
    "chillout_ends_in": 0,
    "chillout_time": 0,
    "condition": "",
    "description": "",
    "enabled": false,
    "for_initial": "skip",
    "for_item_group": null,
    "for_item_id": null,
    "for_item_type": null,
    "for_oid": "#:#/#/status",
    "for_prop": "status",
    "id": "4c6e8c99-56fe-490c-8442-4936ba777498",
    "in_range_max": null,
    "in_range_max_eq": false,
    "in_range_min": null,
    "in_range_min_eq": false,
    "macro": null,
    "macro_args": [],
    "macro_kwargs": {},
    "oid": "dmatrix_rule:dm_rules/4c6e8c99-56fe-490c-8442-4936ba777498",
    "priority": 100,
    "type": "dmatrix_rule"
}

Parameters:

  • API Key valid API key
get rules list

Get the list of all available decision rules.

http

GET /r/dmatrix_rule HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/dmatrix_rule -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/dmatrix_rule --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/dmatrix_rule X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/dmatrix_rule', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "break_after_exec": false,
        "chillout_ends_in": 0,
        "chillout_time": 0,
        "condition": "",
        "description": "",
        "enabled": false,
        "for_initial": "skip",
        "for_item_group": null,
        "for_item_id": null,
        "for_item_type": null,
        "for_oid": "#:#/#/status",
        "for_prop": "status",
        "id": "4c6e8c99-56fe-490c-8442-4936ba777498",
        "in_range_max": null,
        "in_range_max_eq": false,
        "in_range_min": null,
        "in_range_min_eq": false,
        "macro": null,
        "macro_args": [],
        "macro_kwargs": {},
        "oid": "dmatrix_rule:dm_rules/4c6e8c99-56fe-490c-8442-4936ba777498",
        "priority": 100,
        "type": "dmatrix_rule"
    },
    {
        "break_after_exec": false,
        "chillout_ends_in": 0,
        "chillout_time": 0,
        "condition": "",
        "description": "",
        "enabled": false,
        "for_initial": "skip",
        "for_item_group": null,
        "for_item_id": null,
        "for_item_type": null,
        "for_oid": "#:#/#/status",
        "for_prop": "status",
        "id": "9b317323-00e5-4e11-8573-33cdcada1d12",
        "in_range_max": null,
        "in_range_max_eq": false,
        "in_range_min": null,
        "in_range_min_eq": false,
        "macro": null,
        "macro_args": [],
        "macro_kwargs": {},
        "oid": "dmatrix_rule:dm_rules/9b317323-00e5-4e11-8573-33cdcada1d12",
        "priority": 100,
        "type": "dmatrix_rule"
    },
    {
        "break_after_exec": false,
        "chillout_ends_in": 0,
        "chillout_time": 0,
        "condition": "",
        "description": "",
        "enabled": false,
        "for_initial": "skip",
        "for_item_group": null,
        "for_item_id": null,
        "for_item_type": null,
        "for_oid": "#:#/#/status",
        "for_prop": "status",
        "id": "cc7de0ba-04a1-4161-ad73-588861b6e1ef",
        "in_range_max": null,
        "in_range_max_eq": false,
        "in_range_min": null,
        "in_range_min_eq": false,
        "macro": null,
        "macro_args": [],
        "macro_kwargs": {},
        "oid": "dmatrix_rule:dm_rules/cc7de0ba-04a1-4161-ad73-588861b6e1ef",
        "priority": 100,
        "type": "dmatrix_rule"
    }
]

Parameters:

  • API Key valid API key
list rule properties

Get all editable parameters of the decision rule.

http

GET /r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498@props HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498@props -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498@props --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498@props X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498@props', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "break_after_exec": false,
    "chillout_time": 0,
    "condition": "",
    "description": "",
    "enabled": false,
    "for_initial": "skip",
    "for_item_group": null,
    "for_item_id": null,
    "for_item_type": null,
    "for_oid": "#:#/#/status",
    "for_prop": "status",
    "in_range_max": null,
    "in_range_max_eq": false,
    "in_range_min": null,
    "in_range_min_eq": false,
    "macro": null,
    "macro_args": [],
    "macro_kwargs": {},
    "priority": 100
}

Parameters:

  • API Key valid API key
set rule parameters

Set configuration parameters of the decision rule.

Note

Master key is required for batch set.

http

PATCH /r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "for_initial": "any", "enabled": true }

curl

curl -i -X PATCH http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"enabled": true, "for_initial": "any", "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"enabled": true, "for_initial": "any", "save": true}'

httpie

echo '{
  "enabled": true,
  "for_initial": "any",
  "save": true
}' | http PATCH http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8817/r/dmatrix_rule/4c6e8c99-56fe-490c-8442-4936ba777498', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'enabled': True, 'for_initial': 'any', 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key

Optionally:

  • save save configuration after successful call
Logic cycles
create new cycle

Creates new cycle.

http

PUT /r/lcycle/tests/test_cycle2 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i -X PUT http://localhost:8817/r/lcycle/tests/test_cycle2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=PUT http://localhost:8817/r/lcycle/tests/test_cycle2 --header='X-Auth-Key: mykey'

httpie

http PUT http://localhost:8817/r/lcycle/tests/test_cycle2 X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8817/r/lcycle/tests/test_cycle2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "full_id": "tests/test_cycle2",
    "group": "tests",
    "ict": 100,
    "id": "test_cycle2",
    "interval": 1,
    "macro": null,
    "oid": "lcycle:tests/test_cycle2",
    "on_error": null,
    "status": 0,
    "type": "lcycle",
    "value": "1.0000"
}

Parameters:

  • API Key API key with master permissions

Optionally:

delete cycle

Deletes cycle. If cycle is running, it is stopped before deletion.

http

DELETE /r/lcycle/tests/test_cycle2 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8817/r/lcycle/tests/test_cycle2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8817/r/lcycle/tests/test_cycle2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8817/r/lcycle/tests/test_cycle2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8817/r/lcycle/tests/test_cycle2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get cycle configuration properties

http

GET /r/lcycle/tests/test_cycle@props HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lcycle/tests/test_cycle@props -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lcycle/tests/test_cycle@props --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lcycle/tests/test_cycle@props X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lcycle/tests/test_cycle@props', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "autostart": false,
    "description": "",
    "ict": 20,
    "interval": 1,
    "macro": "tests/test_macro",
    "on_error": null
}

Parameters:

  • API Key API key with master permissions
get cycle groups list

Get the list of cycles. Useful e.g. for custom interfaces.

http

GET /r/lcycle/@groups HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lcycle/@groups -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lcycle/@groups --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lcycle/@groups X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lcycle/@groups', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    "tests"
]

Parameters:

  • API Key valid API key
get cycle information

http

GET /r/lcycle/tests/test_cycle HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lcycle/tests/test_cycle -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lcycle/tests/test_cycle --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lcycle/tests/test_cycle X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lcycle/tests/test_cycle', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "description": "",
    "full_id": "tests/test_cycle",
    "group": "tests",
    "ict": 20,
    "id": "test_cycle",
    "interval": 1,
    "iterations": 0,
    "macro": "tests/test_macro",
    "oid": "lcycle:tests/test_cycle",
    "on_error": null,
    "status": 1,
    "type": "lcycle"
}

Parameters:

  • API Key valid API key

Returns:

field “value” contains real average cycle interval

get cycle list

Get the list of all available cycles.

http

GET /r/lcycle HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lcycle -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lcycle --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lcycle X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lcycle', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "description": "",
        "full_id": "tests/cycle1",
        "group": "tests",
        "ict": 20,
        "id": "cycle1",
        "interval": 0.01,
        "iterations": 275,
        "macro": "tests/test",
        "oid": "lcycle:tests/cycle1",
        "on_error": null,
        "status": 0,
        "type": "lcycle"
    },
    {
        "description": "test 2Hz cycle",
        "full_id": "tests/test1",
        "group": "tests",
        "ict": 100,
        "id": "test1",
        "interval": 0.5,
        "iterations": 0,
        "macro": "tests/test1",
        "oid": "lcycle:tests/test1",
        "on_error": null,
        "status": 0,
        "type": "lcycle"
    }
]

Parameters:

  • API Key valid API key

Optionally:

reset cycle statistic

http

POST /r/lcycle/tests/test_cycle HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "reset" }

curl

curl -i -X POST http://localhost:8817/r/lcycle/tests/test_cycle -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "reset"}'

wget

wget -S -O- http://localhost:8817/r/lcycle/tests/test_cycle --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "reset"}'

httpie

echo '{
  "method": "reset"
}' | http POST http://localhost:8817/r/lcycle/tests/test_cycle Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/lcycle/tests/test_cycle', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'reset'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
set cycle property

Set configuration parameters of the cycle.

http

PATCH /r/lcycle/tests/test_cycle HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "ict": 20, "macro": "tests/test_macro" }

curl

curl -i -X PATCH http://localhost:8817/r/lcycle/tests/test_cycle -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"ict": 20, "macro": "tests/test_macro", "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8817/r/lcycle/tests/test_cycle --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"ict": 20, "macro": "tests/test_macro", "save": true}'

httpie

echo '{
  "ict": 20,
  "macro": "tests/test_macro",
  "save": true
}' | http PATCH http://localhost:8817/r/lcycle/tests/test_cycle Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8817/r/lcycle/tests/test_cycle', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'ict': 20, 'macro': 'tests/test_macro', 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
start cycle

http

POST /r/lcycle/tests/test_cycle HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "start" }

curl

curl -i -X POST http://localhost:8817/r/lcycle/tests/test_cycle -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "start"}'

wget

wget -S -O- http://localhost:8817/r/lcycle/tests/test_cycle --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "start"}'

httpie

echo '{
  "method": "start"
}' | http POST http://localhost:8817/r/lcycle/tests/test_cycle Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/lcycle/tests/test_cycle', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'start'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
stop cycle

http

POST /r/lcycle/tests/test_cycle HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "stop" }

curl

curl -i -X POST http://localhost:8817/r/lcycle/tests/test_cycle -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "stop"}'

wget

wget -S -O- http://localhost:8817/r/lcycle/tests/test_cycle --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "stop"}'

httpie

echo '{
  "method": "stop"
}' | http POST http://localhost:8817/r/lcycle/tests/test_cycle Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/lcycle/tests/test_cycle', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'stop'})

response

HTTP/1.1 202 Accepted
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key

Optionally:

  • wait wait until cycle is stopped
Logic macros
create new macro

Creates new macro. Macro code should be put in xc/lm manually.

http

PUT /r/lmacro/tests/test_macro2 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i -X PUT http://localhost:8817/r/lmacro/tests/test_macro2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=PUT http://localhost:8817/r/lmacro/tests/test_macro2 --header='X-Auth-Key: mykey'

httpie

http PUT http://localhost:8817/r/lmacro/tests/test_macro2 X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8817/r/lmacro/tests/test_macro2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "action_enabled": true,
    "full_id": "tests/test_macro2",
    "group": "tests",
    "id": "test_macro2",
    "oid": "lmacro:tests/test_macro2",
    "type": "lmacro"
}

Parameters:

  • API Key API key with master permissions

Optionally:

delete macro

Deletes macro.

http

DELETE /r/lmacro/tests/test_macro2 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8817/r/lmacro/tests/test_macro2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8817/r/lmacro/tests/test_macro2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8817/r/lmacro/tests/test_macro2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8817/r/lmacro/tests/test_macro2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
execute macro

Execute a macro with the specified arguments.

http

POST /r/lmacro/tests/test_macro HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "run" }

curl

curl -i -X POST http://localhost:8817/r/lmacro/tests/test_macro -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "run"}'

wget

wget -S -O- http://localhost:8817/r/lmacro/tests/test_macro --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "run"}'

httpie

echo '{
  "method": "run"
}' | http POST http://localhost:8817/r/lmacro/tests/test_macro Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/lmacro/tests/test_macro', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'run'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Location: /r/action/68574286-35f8-4b52-b8e0-f51c6dafddf5
Pragma: no-cache

{
    "args": [],
    "err": "",
    "exitcode": null,
    "finished": false,
    "finished_in": null,
    "item_group": "tests",
    "item_id": "test_macro",
    "item_oid": "lmacro:tests/test_macro",
    "item_type": "lmacro",
    "kwargs": {},
    "out": "",
    "priority": 100,
    "status": "running",
    "time": {
        "created": 1559868831.9411464,
        "pending": 1559868831.9414475,
        "queued": 1559868831.9422777,
        "running": 1559868831.9430113
    },
    "uuid": "68574286-35f8-4b52-b8e0-f51c6dafddf5"
}

Parameters:

  • API Key valid API key

Optionally:

  • a macro arguments, array or space separated
  • kw macro keyword arguments, name=value, comma separated or dict
  • w wait for the completion for the specified number of seconds
  • p queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”
get macro configuration properties

http

GET /r/lmacro/tests/test_macro@props HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lmacro/tests/test_macro@props -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lmacro/tests/test_macro@props --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lmacro/tests/test_macro@props X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lmacro/tests/test_macro@props', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "action_enabled": true,
    "action_exec": null,
    "description": "",
    "pass_errors": false,
    "send_critical": false
}

Parameters:

  • API Key API key with master permissions
get macro groups list

Get the list of macros. Useful e.g. for custom interfaces.

http

GET /r/lmacro/@groups HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lmacro/@groups -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lmacro/@groups --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lmacro/@groups X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lmacro/@groups', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    "tests"
]

Parameters:

  • API Key valid API key
get macro information

http

GET /r/lmacro/tests/test_macro HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lmacro/tests/test_macro -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lmacro/tests/test_macro --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lmacro/tests/test_macro X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lmacro/tests/test_macro', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "action_enabled": true,
    "description": "",
    "full_id": "tests/test_macro",
    "group": "tests",
    "id": "test_macro",
    "oid": "lmacro:tests/test_macro",
    "type": "lmacro"
}

Parameters:

  • API Key valid API key
get macro list

Get the list of all available macros.

http

GET /r/lmacro HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/lmacro -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/lmacro --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/lmacro X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/lmacro', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "action_enabled": true,
        "description": "",
        "full_id": "tests/test1",
        "group": "tests",
        "id": "test1",
        "oid": "lmacro:tests/test1",
        "type": "lmacro"
    },
    {
        "action_enabled": true,
        "description": "",
        "full_id": "tests/test2",
        "group": "tests",
        "id": "test2",
        "oid": "lmacro:tests/test2",
        "type": "lmacro"
    },
    {
        "action_enabled": true,
        "description": "",
        "full_id": "tests/test_macro",
        "group": "tests",
        "id": "test_macro",
        "oid": "lmacro:tests/test_macro",
        "type": "lmacro"
    },
    {
        "action_enabled": true,
        "description": "",
        "full_id": "tests/test_macro2",
        "group": "tests",
        "id": "test_macro2",
        "oid": "lmacro:tests/test_macro2",
        "type": "lmacro"
    }
]

Parameters:

  • API Key valid API key

Optionally:

macro execution result

Get macro execution results either by action uuid or by macro id.

http

GET /r/action?i=tests%2Ftest_macro HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i 'http://localhost:8817/r/action?i=tests%2Ftest_macro' -H 'X-Auth-Key: mykey'

wget

wget -S -O- 'http://localhost:8817/r/action?i=tests%2Ftest_macro' --header='X-Auth-Key: mykey'

httpie

http 'http://localhost:8817/r/action?i=tests%2Ftest_macro' X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/action?i=tests%2Ftest_macro', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "args": [],
        "err": "",
        "exitcode": 0,
        "finished": true,
        "finished_in": 0.0097811,
        "item_group": "tests",
        "item_id": "test_macro",
        "item_oid": "lmacro:tests/test_macro",
        "item_type": "lmacro",
        "kwargs": {},
        "out": "test passed",
        "priority": 100,
        "status": "completed",
        "time": {
            "completed": 1559868831.1551707,
            "created": 1559868831.1453896,
            "pending": 1559868831.1458647,
            "queued": 1559868831.1469553,
            "running": 1559868831.1479862
        },
        "uuid": "7707c382-eefa-48d2-9b5e-92d114af4e85"
    }
]

Parameters:

  • API Key valid API key

Optionally:

  • g filter by unit group
  • s filter by action status: Q for queued, R for running, F for finished

Returns:

list or single serialized action object

set macro configuration property

Set configuration parameters of the macro.

http

PATCH /r/lmacro/tests/test_macro HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "pass_errors": true }

curl

curl -i -X PATCH http://localhost:8817/r/lmacro/tests/test_macro -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"pass_errors": true, "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8817/r/lmacro/tests/test_macro --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"pass_errors": true, "save": true}'

httpie

echo '{
  "pass_errors": true,
  "save": true
}' | http PATCH http://localhost:8817/r/lmacro/tests/test_macro Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8817/r/lmacro/tests/test_macro', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'pass_errors': True, 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
Macro extensions
get extension module info

http

GET /r/ext-module/audio HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/ext-module/audio -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/ext-module/audio --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/ext-module/audio X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/ext-module/audio', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "api": 1,
    "author": "Altertech Group, https://www.altertech.com/",
    "description": "Play audio file",
    "help": "\nPlays audio file inside the specified directory. The file path should be\nrelative to the directory root, witout a starting slash.\n",
    "license": "Apache License 2.0",
    "mod": "audio",
    "mods_required": [
        "soundfile",
        "sounddevice"
    ],
    "version": "1.0.0"
}

Parameters:

  • API Key API key with master permissions
get extension usage help

http

GET /r/ext-module/audio?help=functions HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i 'http://localhost:8817/r/ext-module/audio?help=functions' -H 'X-Auth-Key: mykey'

wget

wget -S -O- 'http://localhost:8817/r/ext-module/audio?help=functions' --header='X-Auth-Key: mykey'

httpie

http 'http://localhost:8817/r/ext-module/audio?help=functions' X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/ext-module/audio?help=functions', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "play(soundfile, gain=0, wait=True)": "Play sound file"
}

Parameters:

  • API Key API key with master permissions
get list of available extension modules

http

GET /r/ext-module HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/ext-module -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/ext-module --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/ext-module X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/ext-module', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "api": 1,
        "author": "Altertech Group, https://www.altertech.com/",
        "description": "Play audio file",
        "help": "\nPlays audio file inside the specified directory. The file path should be\nrelative to the directory root, witout a starting slash.\n",
        "id": null,
        "license": "Apache License 2.0",
        "mod": "audio",
        "mods_required": [
            "soundfile",
            "sounddevice"
        ],
        "version": "1.0.0"
    },
    {
        "api": 1,
        "author": "Altertech Group, https://www.altertech.com/",
        "description": "Push client for Roboger",
        "help": "\nPush client for Roboger event pager (https://www.roboger.com,\nhttps://github.com/alttch/roboger). Refer to pyrpush module documentation for\nmore info: https://pypi.org/project/pyrpush/\n",
        "id": null,
        "license": "Apache License 2.0",
        "mod": "rpush",
        "mods_required": [
            "pyrpush"
        ],
        "version": "1.0.0"
    },
    {
        "api": 1,
        "author": "Altertech Group, https://www.altertech.com/",
        "description": "Run macro on remote LM PLC",
        "help": "\nAllows to run macros on remote LM PLC\n",
        "id": null,
        "license": "Apache License 2.0",
        "mod": "run_remote",
        "mods_required": [],
        "version": "1.0.0"
    },
    {
        "api": 1,
        "author": "Altertech Group, https://www.altertech.com/",
        "description": "Text-to-speech via ttsbroker",
        "help": "\nText-to-speech engine via ttsbroker Python module. Refer to module\ndocumentation for more info: https://pypi.org/project/ttsbroker/\n",
        "id": null,
        "license": "Apache License 2.0",
        "mod": "tts",
        "mods_required": [
            "ttsbroker"
        ],
        "version": "1.0.0"
    }
]

Parameters:

  • API Key API key with master permissions
get list of available macro extensions

http

GET /r/ext HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/ext -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/ext --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/ext X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/ext', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "id": "a1",
        "mod": "audio"
    },
    {
        "id": "test_a",
        "mod": "audio"
    },
    {
        "id": "test_a2",
        "mod": "audio"
    }
]

Parameters:

  • API Key API key with master permissions

Optionally:

get loaded extension information

http

GET /r/ext/test_a HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/ext/test_a -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/ext/test_a --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/ext/test_a X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/ext/test_a', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "api": 1,
    "author": "Altertech Group, https://www.altertech.com/",
    "cfg": {
        "sdir": "/opt/data/snd"
    },
    "description": "Play audio file",
    "help": "\nPlays audio file inside the specified directory. The file path should be\nrelative to the directory root, witout a starting slash.\n",
    "id": "test_a",
    "license": "Apache License 2.0",
    "mod": "audio",
    "mods_required": [
        "soundfile",
        "sounddevice"
    ],
    "version": "1.0.0"
}

Parameters:

  • API Key API key with master permissions
load extension module

Loads:doc:macro extension</lm/ext>.

http

PUT /r/ext/test_a2 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "m": "audio", "c": "sdir=/opt/data/snd", "save": true }

curl

curl -i -X PUT http://localhost:8817/r/ext/test_a2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"c": "sdir=/opt/data/snd", "m": "audio", "save": true}'

wget

wget -S -O- --method=PUT http://localhost:8817/r/ext/test_a2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"c": "sdir=/opt/data/snd", "m": "audio", "save": true}'

httpie

echo '{
  "c": "sdir=/opt/data/snd",
  "m": "audio",
  "save": true
}' | http PUT http://localhost:8817/r/ext/test_a2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8817/r/ext/test_a2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'c': 'sdir=/opt/data/snd', 'm': 'audio', 'save': True})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "api": 1,
    "author": "Altertech Group, https://www.altertech.com/",
    "cfg": {
        "sdir": "/opt/data/snd"
    },
    "description": "Play audio file",
    "help": "\nPlays audio file inside the specified directory. The file path should be\nrelative to the directory root, witout a starting slash.\n",
    "id": "test_a2",
    "license": "Apache License 2.0",
    "mod": "audio",
    "mods_required": [
        "soundfile",
        "sounddevice"
    ],
    "version": "1.0.0"
}

Parameters:

  • API Key API key with master permissions
  • m extension module

Optionally:

  • c extension configuration
  • save save extension configuration after successful call
set extension configuration property

appends property to extension configuration and reloads module

http

PATCH /r/ext/test_a HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "d": 2, "save": true }

curl

curl -i -X PATCH http://localhost:8817/r/ext/test_a -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"d": 2, "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8817/r/ext/test_a --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"d": 2, "save": true}'

httpie

echo '{
  "d": 2,
  "save": true
}' | http PATCH http://localhost:8817/r/ext/test_a Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8817/r/ext/test_a', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'d': 2, 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
unload macro extension

http

DELETE /r/ext/test_a2 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8817/r/ext/test_a2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8817/r/ext/test_a2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8817/r/ext/test_a2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8817/r/ext/test_a2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
Remote controllers
connect remote UC via HTTP

Connects remote UC controller to the local.

http

POST /r/controller/uc HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "u": "localhost", "a": "secretkey", "save": true }

curl

curl -i -X POST http://localhost:8817/r/controller/uc -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"a": "secretkey", "save": true, "u": "localhost"}'

wget

wget -S -O- http://localhost:8817/r/controller/uc --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"a": "secretkey", "save": true, "u": "localhost"}'

httpie

echo '{
  "a": "secretkey",
  "save": true,
  "u": "localhost"
}' | http POST http://localhost:8817/r/controller/uc Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/controller/uc', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'a': 'secretkey', 'save': True, 'u': 'localhost'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Location: /r/controller/uc/ws1-v1
Pragma: no-cache

{
    "build": "2019031405",
    "connected": true,
    "description": "",
    "enabled": true,
    "full_id": "uc/ws1-v1",
    "group": "uc",
    "id": "ws1-v1",
    "managed": false,
    "mqtt_update": null,
    "oid": "remote_uc:uc/ws1-v1",
    "proto": "http",
    "static": true,
    "type": "remote_uc",
    "version": "3.2.0"
}

Parameters:

  • API Key API key with master permissions
  • u UC API uri (proto://host:port, port not required if default)
  • a remote controller API key ($key to use local key)

Optionally:

  • m ref:MQTT notifier<mqtt_> to exchange item states in real time (default: eva_1)
  • s verify remote SSL certificate or pass invalid
  • t timeout (seconds) for the remote controller API calls
  • save save connected controller configuration on the disk immediately after creation
disable connected controller

http

PATCH /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "enabled": false }

curl

curl -i -X PATCH http://localhost:8817/r/controller/uc/ws1-v1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"enabled": false, "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8817/r/controller/uc/ws1-v1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"enabled": false, "save": true}'

httpie

echo '{
  "enabled": false,
  "save": true
}' | http PATCH http://localhost:8817/r/controller/uc/ws1-v1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8817/r/controller/uc/ws1-v1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'enabled': False, 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
disconnect controller

http

DELETE /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8817/r/controller/uc/ws1-v1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8817/r/controller/uc/ws1-v1 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8817/r/controller/uc/ws1-v1 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8817/r/controller/uc/ws1-v1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
enable connected controller

http

PATCH /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "enabled": true }

curl

curl -i -X PATCH http://localhost:8817/r/controller/uc/ws1-v1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"enabled": true, "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8817/r/controller/uc/ws1-v1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"enabled": true, "save": true}'

httpie

echo '{
  "enabled": true,
  "save": true
}' | http PATCH http://localhost:8817/r/controller/uc/ws1-v1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8817/r/controller/uc/ws1-v1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'enabled': True, 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
get a list of items from connected UCs

Get a list of the items loaded from the connected UC controllers. Useful to debug the controller connections.

http

GET /r/controller/uc/ws1-v1@items HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/controller/uc/ws1-v1@items -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/controller/uc/ws1-v1@items --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/controller/uc/ws1-v1@items X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/controller/uc/ws1-v1@items', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "controller_id": "uc/ws1-v1",
        "description": "",
        "full_id": "env/temp_test",
        "group": "env",
        "id": "temp_test",
        "loc_x": null,
        "loc_y": null,
        "loc_z": null,
        "location": "",
        "oid": "sensor:env/temp_test",
        "status": 0,
        "type": "sensor",
        "value": "null"
    },
    {
        "action_enabled": true,
        "controller_id": "uc/ws1-v1",
        "description": "",
        "full_id": "nogroup/test2",
        "group": "nogroup",
        "id": "test2",
        "loc_x": null,
        "loc_y": null,
        "loc_z": null,
        "location": "",
        "nstatus": -1,
        "nvalue": "null",
        "oid": "unit:nogroup/test2",
        "status": -1,
        "status_labels": [
            {
                "label": "OFF",
                "status": 0
            },
            {
                "label": "ON",
                "status": 1
            }
        ],
        "type": "unit",
        "value": "null"
    }
]

Parameters:

  • API Key API key with master permissions

Optionally:

  • g filter by item group
  • p filter by item type
get connected controller information

http

GET /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/controller/uc/ws1-v1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/controller/uc/ws1-v1 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/controller/uc/ws1-v1 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/controller/uc/ws1-v1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "build": "2019031405",
    "connected": true,
    "description": "",
    "enabled": true,
    "full_id": "uc/ws1-v1",
    "group": "uc",
    "id": "ws1-v1",
    "managed": false,
    "mqtt_update": null,
    "oid": "remote_uc:uc/ws1-v1",
    "proto": "http",
    "static": true,
    "type": "remote_uc",
    "version": "3.2.0"
}

Parameters:

  • API Key API key with master permissions
get controller connection parameters

http

GET /r/controller/uc/ws1-v1@props HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/controller/uc/ws1-v1@props -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/controller/uc/ws1-v1@props --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/controller/uc/ws1-v1@props X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/controller/uc/ws1-v1@props', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "description": "",
    "enabled": true,
    "key": "secretkey",
    "mqtt_update": null,
    "reload_interval": 300,
    "retries": 2,
    "ssl_verify": true,
    "static": true,
    "timeout": 5.0,
    "uri": "http://localhost:8812"
}

Parameters:

  • API Key API key with master permissions
get controllers list

Get the list of all connected UC controllers.

http

GET /r/controller HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/controller -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/controller --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/controller X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/controller', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[]

Parameters:

  • API Key API key with master permissions
reload controller

Reloads items from connected UC

http

POST /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "reload" }

curl

curl -i -X POST http://localhost:8817/r/controller/uc/ws1-v1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "reload"}'

wget

wget -S -O- http://localhost:8817/r/controller/uc/ws1-v1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "reload"}'

httpie

echo '{
  "method": "reload"
}' | http POST http://localhost:8817/r/controller/uc/ws1-v1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/controller/uc/ws1-v1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'reload'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
rescan controllers via UPnP

http

POST /r/controller HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "upnp-rescan" }

curl

curl -i -X POST http://localhost:8817/r/controller -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "upnp-rescan"}'

wget

wget -S -O- http://localhost:8817/r/controller --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "upnp-rescan"}'

httpie

echo '{
  "method": "upnp-rescan"
}' | http POST http://localhost:8817/r/controller Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/controller', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'upnp-rescan'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
set controller connection parameters

http

PATCH /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "reload_interval": 60 }

curl

curl -i -X PATCH http://localhost:8817/r/controller/uc/ws1-v1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"reload_interval": 60, "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8817/r/controller/uc/ws1-v1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"reload_interval": 60, "save": true}'

httpie

echo '{
  "reload_interval": 60,
  "save": true
}' | http PATCH http://localhost:8817/r/controller/uc/ws1-v1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8817/r/controller/uc/ws1-v1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'reload_interval': 60, 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
test connection to remote controller

http

POST /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "test" }

curl

curl -i -X POST http://localhost:8817/r/controller/uc/ws1-v1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "test"}'

wget

wget -S -O- http://localhost:8817/r/controller/uc/ws1-v1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "test"}'

httpie

echo '{
  "method": "test"
}' | http POST http://localhost:8817/r/controller/uc/ws1-v1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/controller/uc/ws1-v1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'test'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
Scheduled jobs
create new job

Creates new scheduled job. Job id (UUID) is generated automatically unless specified.

http

POST /r/job HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i -X POST http://localhost:8817/r/job -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/job --header='X-Auth-Key: mykey'

httpie

http POST http://localhost:8817/r/job X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8817/r/job', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Location: /r/job/32ec1063-26cc-4f73-ba40-73ffc2e1787b
Pragma: no-cache

{
    "description": "",
    "enabled": false,
    "every": "",
    "id": "32ec1063-26cc-4f73-ba40-73ffc2e1787b",
    "last": null,
    "macro": null,
    "macro_args": [],
    "macro_kwargs": {},
    "oid": "job:jobs/32ec1063-26cc-4f73-ba40-73ffc2e1787b",
    "type": "job"
}

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save job configuration immediately
delete job

Deletes scheduled job.

http

DELETE /r/job/9c6e8c99-56fe-490c-8442-4936ba777499 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get job information

http

GET /r/job/9c6e8c99-56fe-490c-8442-4936ba777499 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "description": "",
    "enabled": true,
    "every": "",
    "id": "9c6e8c99-56fe-490c-8442-4936ba777499",
    "last": null,
    "macro": "tests/test1",
    "macro_args": [
        "test"
    ],
    "macro_kwargs": {},
    "oid": "job:jobs/9c6e8c99-56fe-490c-8442-4936ba777499",
    "type": "job"
}

Parameters:

  • API Key API key with master permissions
get jobs list

Get the list of all available scheduled jobs.

http

GET /r/job HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/job -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/job --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/job X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/job', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "description": "",
        "enabled": false,
        "every": "",
        "id": "9d8a338f-cdc4-46ac-8610-ba3b1597c73e",
        "last": null,
        "macro": null,
        "macro_args": [],
        "macro_kwargs": {},
        "oid": "job:jobs/9d8a338f-cdc4-46ac-8610-ba3b1597c73e",
        "type": "job"
    },
    {
        "description": "",
        "enabled": false,
        "every": "",
        "id": "7545a768-ce67-44ad-9544-2a54ad6c7e83",
        "last": null,
        "macro": null,
        "macro_args": [],
        "macro_kwargs": {},
        "oid": "job:jobs/7545a768-ce67-44ad-9544-2a54ad6c7e83",
        "type": "job"
    }
]

Parameters:

  • API Key API key with master permissions
list job properties

Get all editable parameters of the scheduled job.

http

GET /r/job/9c6e8c99-56fe-490c-8442-4936ba777499@props HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey

curl

curl -i http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499@props -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499@props --header='X-Auth-Key: mykey'

httpie

http http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499@props X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499@props', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "description": "",
    "enabled": true,
    "every": "",
    "macro": "tests/test1",
    "macro_args": [
        "test"
    ],
    "macro_kwargs": {}
}

Parameters:

  • API Key API key with master permissions
set job parameters

Set configuration parameters of the scheduled job.

http

PATCH /r/job/9c6e8c99-56fe-490c-8442-4936ba777499 HTTP/1.1
Host: localhost:8817
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "macro": "tests/test1", "enabled": true }

curl

curl -i -X PATCH http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"enabled": true, "macro": "tests/test1", "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"enabled": true, "macro": "tests/test1", "save": true}'

httpie

echo '{
  "enabled": true,
  "macro": "tests/test1",
  "save": true
}' | http PATCH http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8817/r/job/9c6e8c99-56fe-490c-8442-4936ba777499', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'enabled': True, 'macro': 'tests/test1', 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
CVARs
get the value of user-defined variable

Note

Even if different EVA controllers are working on the same server, they have different sets of variables To set the variables for each subsystem, use SYS API on the respective address/port.

http

GET /r/cvar/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/cvar/test -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/cvar/test --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/cvar/test X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/cvar/test', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "test": "some_value"
}

Parameters:

  • API Key API key with master permissions

Optionally:

Returns:

Dict containing variable and its value. If no varible name was specified, all cvars are returned.

set the value of user-defined variable

http

PUT /r/cvar/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "v": "some_value" }

curl

curl -i -X PUT http://localhost:8812/r/cvar/test -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"v": "some_value"}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/cvar/test --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"v": "some_value"}'

httpie

echo '{
  "v": "some_value"
}' | http PUT http://localhost:8812/r/cvar/test Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/cvar/test', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'v': 'some_value'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "test": "some_value"
}

Parameters:

  • API Key API key with master permissions

Optionally:

  • v variable value (if not specified, variable is deleted)
Locking functions
acquire lock

Locks can be used similarly to file locking by the specific process. The difference is that SYS API tokens can be:

  • centralized for several systems (any EVA server can act as lock server)
  • removed from outside
  • automatically unlocked after the expiration time, if the initiator failed or forgot to release the lock

used to restrict parallel process starting or access to system files/resources. LM PLC macro share locks with extrnal scripts.

Note

Even if different EVA controllers are working on the same server, their lock tokens are stored in different bases. To work with the token of each subsystem, use SYS API on the respective address/port.

http

PUT /r/lock/mylock1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "e": 1, "t": 15 }

curl

curl -i -X PUT http://localhost:8812/r/lock/mylock1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"e": 1, "t": 15}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/lock/mylock1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"e": 1, "t": 15}'

httpie

echo '{
  "e": 1,
  "t": 15
}' | http PUT http://localhost:8812/r/lock/mylock1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/lock/mylock1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'e': 1, 't': 15})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": "mylock1",
    "type": "lock"
}

Parameters:

  • API Key API key with allow=lock permissions

Optionally:

  • t maximum time (seconds) to acquire lock
  • e time after which lock is automatically released (if absent, lock may be released only via unlock function)
get lock status

http

GET /r/lock/mylock1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/lock/mylock1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/lock/mylock1 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/lock/mylock1 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/lock/mylock1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": "mylock1",
    "locked": true,
    "type": "lock"
}

Parameters:

  • API Key API key with allow=lock permissions
release lock

Releases the previously acquired lock.

http

DELETE /r/lock/mylock1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/lock/mylock1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/lock/mylock1 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/lock/mylock1 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/lock/mylock1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with allow=lock permissions
Logging
put message to log file

An external application can put a message in the logs on behalf of the controller.

http

POST /r/log/warning HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "m": "local file system is full" }

curl

curl -i -X POST http://localhost:8812/r/log/warning -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"m": "local file system is full"}'

wget

wget -S -O- http://localhost:8812/r/log/warning --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"m": "local file system is full"}'

httpie

echo '{
  "m": "local file system is full"
}' | http POST http://localhost:8812/r/log/warning Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/log/warning', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'m': 'local file system is full'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with sysfunc=yes permissions
  • l log level
  • m message text
put debug message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
put info message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
put warning message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
put error message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
put critical message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
get records from the controller log

Log records are stored in the controllers’ memory until restart or the time (keep_logmem) specified in controller configuration passes.

http

GET /r/log/warning?t=3600&n=3 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i 'http://localhost:8812/r/log/warning?t=3600&n=3' -H 'X-Auth-Key: mykey'

wget

wget -S -O- 'http://localhost:8812/r/log/warning?t=3600&n=3' --header='X-Auth-Key: mykey'

httpie

http 'http://localhost:8812/r/log/warning?t=3600&n=3' X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/log/warning?t=3600&n=3', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "h": "mws1-v1",
        "l": 30,
        "mod": "sysapi",
        "msg": "test warning message",
        "p": "uc",
        "t": 1552863481.1394246,
        "th": "CP Server Thread-15"
    },
    {
        "h": "mws1-v1",
        "l": 40,
        "mod": "sysapi",
        "msg": "test error message",
        "p": "uc",
        "t": 1552863481.1516943,
        "th": "CP Server Thread-16"
    },
    {
        "h": "mws1-v1",
        "l": 50,
        "mod": "sysapi",
        "msg": "test critical message",
        "p": "uc",
        "t": 1552863481.1631815,
        "th": "CP Server Thread-17"
    }
]

Parameters:

  • API Key API key with sysfunc=yes permissions

Optionally:

  • t get log records not older than t seconds
  • n the maximum number of log records you want to obtain
rotate log file

Deprecated, not required since 3.3.0

http

POST /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "log_rotate" }

curl

curl -i -X POST http://localhost:8812/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "log_rotate"}'

wget

wget -S -O- http://localhost:8812/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "log_rotate"}'

httpie

echo '{
  "method": "log_rotate"
}' | http POST http://localhost:8812/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'log_rotate'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with sysfunc=yes permissions
get API call log
  • API call with master permission returns all records requested
  • API call with other API key returns records for the specified key only
  • API call with an authentication token returns records for the current authorized user

http

GET /r/core@apilog HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/core@apilog -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/core@apilog --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/core@apilog X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/core@apilog', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "auth": "key",
        "func": "login",
        "gw": "http",
        "id": "a4ac6da7-2fa8-4938-8613-48e6495158b1",
        "ip": "127.0.0.1",
        "ki": "operator",
        "params": "{\"u\":\"ttt\",\"p\":\"<hidden>\"}",
        "status": "OK",
        "t": 1596055098.3651853,
        "tf": 1596055098.3837607,
        "u": "ttt",
        "utp": null
    },
    {
        "auth": "key",
        "func": "list_key_props",
        "gw": "http",
        "id": "35685960-cc2f-4fb6-8efc-c4ebca8bf9b5",
        "ip": "127.0.0.1",
        "ki": "masterkey",
        "params": "{\"i\":\"operator\"}",
        "status": "OK",
        "t": 1596055125.9569867,
        "tf": 1596055125.9690392,
        "u": null,
        "utp": null
    },
    {
        "auth": "key",
        "func": "action_toggle",
        "gw": "http",
        "id": "1bdc23da-95a1-4b41-b354-3f3c62e24405",
        "ip": "127.0.0.1",
        "ki": "masterkey",
        "params": "{\"i\":\"unit:light/hall\",\"p\":null,\"w\":null,\"q\":null,\"u\":null}",
        "status": "OK",
        "t": 1596055185.7343063,
        "tf": 1596055185.7551231,
        "u": null,
        "utp": null
    }
]

Parameters:

  • API Key any valid API key

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • n records limit
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • f record filter (requires API key with master permission)

Returns:

List of API calls

Note: API call params are returned as string and can be invalid JSON data as they’re always truncated to 512 symbols in log database

Record filter should be specified either as string (k1=val1,k2=val2) or as a dict. Valid fields are:

  • gw: filter by API gateway
  • ip: filter by caller IP
  • auth: filter by authentication type
  • u: filter by user
  • utp: filter by user type
  • ki: filter by API key ID
  • func: filter by API function
  • params: filter by API call params (matches if field contains value)
  • status: filter by API call status
API keys
create API key

API keys are defined statically in etc/<controller>_apikeys.ini file as well as can be created with API and stored in user database.

Keys with master permission can not be created.

http

PUT /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "sysfunc": true, "allow": "cmd" }

curl

curl -i -X PUT http://localhost:8812/r/key/testkey2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"allow": "cmd", "save": true, "sysfunc": true}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/key/testkey2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"allow": "cmd", "save": true, "sysfunc": true}'

httpie

echo '{
  "allow": "cmd",
  "save": true,
  "sysfunc": true
}' | http PUT http://localhost:8812/r/key/testkey2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/key/testkey2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'allow': 'cmd', 'save': True, 'sysfunc': True})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "allow": [
        "cmd"
    ],
    "dynamic": true,
    "groups": [],
    "hosts_allow": [
        "0.0.0.0/0"
    ],
    "hosts_assign": [],
    "id": "testkey2",
    "items": [],
    "key": "443e342f7e49566fafc1cbe928878b0c18510bb2979ceca7aceb5e45b2b96280",
    "master": false,
    "pvt": [],
    "rpvt": [],
    "sysfunc": true
}

Parameters:

  • API Key API key with master permissions
  • save save configuration immediately

Returns:

JSON with serialized key object

delete API key

http

DELETE /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/key/testkey2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/key/testkey2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/key/testkey2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/key/testkey2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
list API key permissions

Lists API key permissons (including a key itself)

Note

API keys, defined in etc/<controller>_apikeys.ini file can not be managed with API.

http

GET /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/key/testkey2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/key/testkey2 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/key/testkey2 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/key/testkey2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "allow": [
        "cmd"
    ],
    "dynamic": true,
    "groups": [],
    "hosts_allow": [
        "0.0.0.0/0"
    ],
    "hosts_assign": [],
    "id": "testkey2",
    "items": [],
    "key": "443e342f7e49566fafc1cbe928878b0c18510bb2979ceca7aceb5e45b2b96280",
    "master": false,
    "pvt": [],
    "rpvt": [],
    "sysfunc": true
}

Parameters:

  • API Key API key with master permissions
  • save save configuration immediately
list API keys

http

GET /r/key HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/key -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/key --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/key X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/key', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "dynamic": false,
        "key_id": "masterkey",
        "master": true
    },
    {
        "allow": {
            "cmd": true,
            "device": true,
            "lock": false
        },
        "dynamic": true,
        "groups": [
            "#"
        ],
        "items": [],
        "key_id": "default",
        "master": false,
        "sysfunc": false
    },
    {
        "allow": {
            "cmd": true,
            "device": true,
            "lock": false
        },
        "dynamic": false,
        "groups": [
            "#"
        ],
        "items": [],
        "key_id": "lm",
        "master": false,
        "sysfunc": false
    },
    {
        "allow": {
            "cmd": false,
            "device": true,
            "lock": true
        },
        "dynamic": false,
        "groups": [
            "#"
        ],
        "items": [],
        "key_id": "operator",
        "master": false,
        "sysfunc": true
    },
    {
        "allow": {
            "cmd": false,
            "device": false,
            "lock": false
        },
        "dynamic": false,
        "groups": [
            "#"
        ],
        "items": [],
        "key_id": "sfa",
        "master": false,
        "sysfunc": false
    },
    {
        "allow": {
            "cmd": false,
            "device": false,
            "lock": false
        },
        "dynamic": true,
        "groups": [],
        "items": [
            "item1"
        ],
        "key_id": "t4",
        "master": false,
        "sysfunc": true
    },
    {
        "allow": {
            "cmd": false,
            "device": false,
            "lock": false
        },
        "dynamic": false,
        "groups": [],
        "items": [
            "sensor:sensors/sensor1"
        ],
        "key_id": "test",
        "master": false,
        "sysfunc": false
    },
    {
        "allow": {
            "cmd": false,
            "device": false,
            "lock": false
        },
        "dynamic": true,
        "groups": [],
        "items": [],
        "key_id": "testkey",
        "master": false,
        "sysfunc": true
    },
    {
        "allow": {
            "cmd": true,
            "device": false,
            "lock": false
        },
        "dynamic": true,
        "groups": [],
        "items": [],
        "key_id": "testkey2",
        "master": false,
        "sysfunc": true
    }
]

Parameters:

  • API Key API key with master permissions
regenerate API key

http

POST /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "regenerate" }

curl

curl -i -X POST http://localhost:8812/r/key/testkey2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "regenerate"}'

wget

wget -S -O- http://localhost:8812/r/key/testkey2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "regenerate"}'

httpie

echo '{
  "method": "regenerate"
}' | http POST http://localhost:8812/r/key/testkey2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/key/testkey2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'regenerate'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "key": "3dbcd3d24c6dc878cebe369eb9fdb95ae99fee14e99cdfd911b83629688d2854"
}

Parameters:

  • API Key API key with master permissions

Returns:

JSON dict with new key value in “key” field

set API key permissions

http

PATCH /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "sysfunc": true }

curl

curl -i -X PATCH http://localhost:8812/r/key/testkey2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"save": true, "sysfunc": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/key/testkey2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"save": true, "sysfunc": true}'

httpie

echo '{
  "save": true,
  "sysfunc": true
}' | http PATCH http://localhost:8812/r/key/testkey2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/key/testkey2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'save': True, 'sysfunc': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • p property
  • v value (if none, permission will be revoked)
  • save save configuration immediately
User accounts
assign API key to user

http

PATCH /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "a": "masterkey" }

curl

curl -i -X PATCH http://localhost:8812/r/user/test2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"a": "masterkey"}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/user/test2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"a": "masterkey"}'

httpie

echo '{
  "a": "masterkey"
}' | http PATCH http://localhost:8812/r/user/test2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/user/test2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'a': 'masterkey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • a API key to assign (key id, not a key itself) or multiple keys, comma separated
create user account

Note

All changes to user accounts are instant, if the system works in read/only mode, set it to read/write before performing user management.

http

PUT /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "p": "verysecretpassword", "a": "testkey" }

curl

curl -i -X PUT http://localhost:8812/r/user/test2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"a": "testkey", "p": "verysecretpassword"}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/user/test2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"a": "testkey", "p": "verysecretpassword"}'

httpie

echo '{
  "a": "testkey",
  "p": "verysecretpassword"
}' | http PUT http://localhost:8812/r/user/test2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/user/test2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'a': 'testkey', 'p': 'verysecretpassword'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "key": "testkey",
    "user": "test2"
}

Parameters:

  • API Key API key with master permissions
  • p user password
  • a API key to assign (key id, not a key itself)
delete user account

http

DELETE /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/user/test2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/user/test2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/user/test2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/user/test2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get user account info

http

GET /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/user/test2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/user/test2 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/user/test2 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/user/test2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "key": "testkey",
    "user": "test2"
}

Parameters:

  • API Key API key with master permissions
list user accounts

http

GET /r/user HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/user -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/user --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/user X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/user', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "key_id": "test",
        "user": "divisor"
    },
    {
        "key_id": "testkey",
        "user": "test"
    },
    {
        "key_id": "testkey",
        "user": "test2"
    }
]

Parameters:

  • API Key API key with master permissions
set user password

Either master key and user login must be specified or a user must be logged in and a session token used

http

PATCH /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "p": "qwerty" }

curl

curl -i -X PATCH http://localhost:8812/r/user/test2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"p": "qwerty"}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/user/test2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"p": "qwerty"}'

httpie

echo '{
  "p": "qwerty"
}' | http PATCH http://localhost:8812/r/user/test2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/user/test2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'p': 'qwerty'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key master key or token
  • p new password
List active session tokens

Parameters:

  • API Key API key with master permissions
Drop session token(s)

Parameters:

  • API Key API key with master permissions
  • a session token or
  • u user name or
  • i API key id
Notifier management
disable notifier

Note

The notifier is disabled until controller restart. To disable notifier permanently, use notifier management CLI.

http

PATCH /r/notifier/eva_1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "enabled": false }

curl

curl -i -X PATCH http://localhost:8812/r/notifier/eva_1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"enabled": false}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/notifier/eva_1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"enabled": false}'

httpie

echo '{
  "enabled": false
}' | http PATCH http://localhost:8812/r/notifier/eva_1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/notifier/eva_1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'enabled': False})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
enable notifier

Note

The notifier is enabled until controller restart. To enable notifier permanently, use notifier management CLI.

http

PATCH /r/notifier/eva_1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "enabled": true }

curl

curl -i -X PATCH http://localhost:8812/r/notifier/eva_1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"enabled": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/notifier/eva_1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"enabled": true}'

httpie

echo '{
  "enabled": true
}' | http PATCH http://localhost:8812/r/notifier/eva_1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/notifier/eva_1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'enabled': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get notifier configuration

http

GET /r/notifier/eva_1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/notifier/eva_1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/notifier/eva_1 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/notifier/eva_1 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/notifier/eva_1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "announce_interval": 5.0,
    "api_enabled": true,
    "enabled": false,
    "events": [
        {
            "groups": [
                "#"
            ],
            "subject": "state",
            "types": [
                "#"
            ]
        },
        {
            "level": 30,
            "subject": "log"
        }
    ],
    "host": "mws1-v1",
    "id": "eva_1",
    "password": "test",
    "qos": {
        "action": 2,
        "log": 2,
        "state": 2,
        "system": 2
    },
    "type": "mqtt",
    "username": "eva"
}

Parameters:

  • API Key API key with master permissions
list notifiers

http

GET /r/notifier HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/notifier -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/notifier --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/notifier X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/notifier', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "db": "db1.db",
        "enabled": true,
        "events": [
            {
                "groups": [
                    "#"
                ],
                "subject": "state",
                "types": [
                    "#"
                ]
            }
        ],
        "id": "db_1",
        "keep": 86400,
        "type": "db"
    },
    {
        "announce_interval": 5.0,
        "api_enabled": true,
        "enabled": false,
        "events": [
            {
                "groups": [
                    "#"
                ],
                "subject": "state",
                "types": [
                    "#"
                ]
            },
            {
                "level": 30,
                "subject": "log"
            }
        ],
        "host": "mws1-v1",
        "id": "eva_1",
        "password": "test",
        "qos": {
            "action": 2,
            "log": 2,
            "state": 2,
            "system": 2
        },
        "type": "mqtt",
        "username": "eva"
    }
]

Parameters:

  • API Key API key with master permissions
File management
put file to runtime folder

Puts a new file into runtime folder. If the file with such name exists, it will be overwritten. As all files in runtime are text, binary data can not be put.

http

PUT /r/runtime/xc/uc/test_action_script2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "m": "/bin/sh\n\nexit 0", "e": true }

curl

curl -i -X PUT http://localhost:8812/r/runtime/xc/uc/test_action_script2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"e": true, "m": "/bin/sh\n\nexit 0"}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/runtime/xc/uc/test_action_script2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"e": true, "m": "/bin/sh\n\nexit 0"}'

httpie

echo '{
  "e": true,
  "m": "/bin/sh\n\nexit 0"
}' | http PUT http://localhost:8812/r/runtime/xc/uc/test_action_script2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/runtime/xc/uc/test_action_script2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'e': True, 'm': '/bin/sh\n\nexit 0'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": "xc/uc/test_action_script2",
    "type": "runtime"
}

Parameters:

  • API Key API key with master permissions
  • m file content (plain text or base64-encoded)
  • b if True - put binary file (decode base64)
set file exec permission

http

PATCH /r/runtime/xc/uc/test_action_script2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "e": true, "e": true }

curl

curl -i -X PATCH http://localhost:8812/r/runtime/xc/uc/test_action_script2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"e": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/runtime/xc/uc/test_action_script2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"e": true}'

httpie

echo '{
  "e": true
}' | http PATCH http://localhost:8812/r/runtime/xc/uc/test_action_script2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/runtime/xc/uc/test_action_script2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'e': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • e false for 0x644, true for 0x755 (executable)
delete file from runtime folder

http

DELETE /r/runtime/xc/uc/test_action_script2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/runtime/xc/uc/test_action_script2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/runtime/xc/uc/test_action_script2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/runtime/xc/uc/test_action_script2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/runtime/xc/uc/test_action_script2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get file contents from runtime folder

http

GET /r/runtime/xc/uc/test_action_script2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/runtime/xc/uc/test_action_script2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/runtime/xc/uc/test_action_script2 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/runtime/xc/uc/test_action_script2 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/runtime/xc/uc/test_action_script2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "data": "/bin/sh\n\nexit 0",
    "e": true,
    "file": "xc/uc/test_action_script2"
}

Parameters:

  • API Key API key with master permissions
  • b if True - force getting binary file (base64-encode content)
Core scripts
List MQTT topics core scripts react on

http

GET /r/corescript/mqtt-topics HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/corescript/mqtt-topics -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/corescript/mqtt-topics --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/corescript/mqtt-topics X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/corescript/mqtt-topics', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "qos": 2,
        "topic": "eva_1:cluster/#"
    },
    {
        "qos": 2,
        "topic": "test/test2"
    },
    {
        "qos": 1,
        "topic": "ttt/ttt"
    }
]

Parameters:

  • API Key API key with master permissions
Reload core scripts if some was added or deleted

http

POST /r/corescript HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "reload" }

curl

curl -i -X POST http://localhost:8812/r/corescript -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "reload"}'

wget

wget -S -O- http://localhost:8812/r/corescript --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "reload"}'

httpie

echo '{
  "method": "reload"
}' | http POST http://localhost:8812/r/corescript Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/corescript', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'reload'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
Subscribe core scripts to MQTT topic

The method subscribes core scripts to topic of default MQTT notifier (eva_1). To specify another notifier, set topic as <notifer_id>:<topic>

http

POST /r/corescript HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "q": 2, "method": "mqtt-subscribe", "t": "some/test/topic2" }

curl

curl -i -X POST http://localhost:8812/r/corescript -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "mqtt-subscribe", "q": 2, "t": "some/test/topic2"}'

wget

wget -S -O- http://localhost:8812/r/corescript --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "mqtt-subscribe", "q": 2, "t": "some/test/topic2"}'

httpie

echo '{
  "method": "mqtt-subscribe",
  "q": 2,
  "t": "some/test/topic2"
}' | http POST http://localhost:8812/r/corescript Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/corescript', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'mqtt-subscribe', 'q': 2, 't': 'some/test/topic2'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • t MQTT topic (“+” and “#” masks are supported)
  • q MQTT topic QoS
  • save save core script config after modification
Unsubscribe core scripts from MQTT topic

http

POST /r/corescript HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "mqtt-unsubscribe", "t": "some/test/topic2" }

curl

curl -i -X POST http://localhost:8812/r/corescript -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "mqtt-unsubscribe", "t": "some/test/topic2"}'

wget

wget -S -O- http://localhost:8812/r/corescript --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "mqtt-unsubscribe", "t": "some/test/topic2"}'

httpie

echo '{
  "method": "mqtt-unsubscribe",
  "t": "some/test/topic2"
}' | http POST http://localhost:8812/r/corescript Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/corescript', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'mqtt-unsubscribe', 't': 'some/test/topic2'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • t MQTT topic (“+” and “#” masks are allowed)
  • save save core script config after modification

SFA RESTful API

SCADA Final Aggregator API is used to manage EVA ICS cloud and aggregated resources.

This document describes API methods for RESTful calls. For direct and JSON RPC calls look SFA API.

RESTful API basics

Warning

RESTful API is deprecated and scheduled to be removed (not implemented) in EVA ICS v4. Use JSON RPC API, whenever it is possible.

Majority EVA ICS API components and items support REST. Parameters for POST, PUT, PATCH and DELETE requests can be sent in both JSON and multipart/form-data. For JSON, Content-Type: application/json header must be specified.

Requests

API key can be sent in HTTP X-Auth-Key header (preferred) or in request parameters (as k).

  • GET request is used to get information about resource or list of resources of the specified type.
  • POST request is used to perform special API calls and create resources in case when resource id is generated by server. In the last case, response always contains additional field Location which points to the resource created.
  • PUT request is used to create new resources. If resource already exists, the server could refuse recreating it, responding with 409 Conflict HTTP error.
  • PATCH request is used to modify resource parameters.
  • DELETE request is used to delete resource.

For resource creation and modification, multiple parameters can be specified in a single request. For majority requests of such purpose, a special parameter “save” is used to tell server (if “save”: true) to save the resource configuration immediately after its modification.

For the group-related calls, put trailing slash at the end of the request URL:

/r/<resource_type>/<group>/
Responses

Success responses:

  • 200 OK API call completed successfully
  • 201 Created API call completed successfully, Response header Location contains either uri to the newly created object or resource is accessible by the effective request uri. For resources created with PUT, body contains either serialized resource object or resource type and id
  • 202 Accepted The server accepted command and will process it later.
  • 204 No Content API call completed successfully, no content to return

Error responses:

  • 403 Forbidden the API key has no access to this function or resource
  • 404 Not Found resource doesn’t exist
  • 405 Method Not Allowed API function/method not found
  • 409 Conflict resource/object already exists or is locked
  • 500 API Error API function execution has been failed. Check input parameters and server logs.

Response body may contain additional information encoded in JSON. { “result”: “OK” } and { “result”: “ERROR” } in body are not returned.

Long API calls
  • Long API calls should be avoided at any cost.
  • All critical action and command methods have an option to obtain action ID and check for the result later.
  • If long API calls are performed between controllers (e.g. action methods with wait param), remote controller timeout should be always greater than max. expected “wait” timeout in API call, otherwise client controller will repeat API calls continuously, up to max retries for the target controller.

Contents

General functions
test API/key and get system info

Test can be executed with any valid API key of the controller the function is called to.

The result section “controllers” contains connection status of remote controllers. The API key must have an access either to “uc” and “lm” groups (“remote_uc:uc” and “remote_lm:lm”) or to particular controller oids.

http

GET /r/core HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/core -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/core --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/core X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/core', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "acl": {
        "key_id": "masterkey",
        "master": true
    },
    "cloud_manager": true,
    "db_update": 1,
    "debug": true,
    "file_management": true,
    "polldelay": 0.01,
    "product_build": 2019032301,
    "product_code": "sfa",
    "product_name": "EVA SCADA Final Aggregator",
    "setup_mode": false,
    "system": "mws1-v1",
    "time": 1553393178.4744968,
    "uptime": 2,
    "version": "3.2.0"
}

Parameters:

  • API Key any valid API key

Returns:

JSON dict with system info and current API key permissions (for masterkey only { “master”: true } is returned)

save database and runtime configuration

All modified items, their status, and configuration will be written to the disk. If exec_before_save command is defined in the controller’s configuration file, it’s called before saving and exec_after_save after (e.g. to switch the partition to write mode and back to read-only).

http

POST /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "save" }

curl

curl -i -X POST http://localhost:8812/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "save"}'

wget

wget -S -O- http://localhost:8812/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "save"}'

httpie

echo '{
  "method": "save"
}' | http POST http://localhost:8812/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'save'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with sysfunc=yes permissions
execute a remote system command

Executes a command script on the server where the controller is installed.

http

POST /r/cmd/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "a": "0 2 3", "w": 5, "t": 10 }

curl

curl -i -X POST http://localhost:8812/r/cmd/test -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"a": "0 2 3", "t": 10, "w": 5}'

wget

wget -S -O- http://localhost:8812/r/cmd/test --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"a": "0 2 3", "t": 10, "w": 5}'

httpie

echo '{
  "a": "0 2 3",
  "t": 10,
  "w": 5
}' | http POST http://localhost:8812/r/cmd/test Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/cmd/test', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'a': '0 2 3', 't': 10, 'w': 5})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "args": [
        "0",
        "2",
        "3"
    ],
    "cmd": "test",
    "err": "some text to stderr\n",
    "exitcode": 0,
    "out": "test script start\nparam 1: 0 ( > 0 will generate \"failed\" status)\nparam 2: 2\nparam 3: 3\ndelay 3 sec\nscript finish\n",
    "status": "completed",
    "time": {
        "completed": 1552863480.7081513,
        "created": 1552863480.6993306,
        "running": 1552863480.7001197
    },
    "timeout": 10.0
}

Parameters:

  • API Key API key with allow=cmd permissions

Optionally:

  • a string of command arguments, separated by spaces (passed to the script) or array (list)
  • w wait (in seconds) before API call sends a response. This allows to try waiting until command finish
  • t maximum time of command execution. If the command fails to finish within the specified time (in sec), it will be terminated
  • s STDIN data
get list of loaded core plugins

http

GET /r/plugin HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/plugin -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/plugin --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/plugin X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/plugin', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "author": "Altertech, https://www.altertech.com/",
        "license": "Apache License 2.0",
        "name": "test",
        "version": "0.0.1"
    }
]

Parameters:

  • API Key API key with master permissions

Returns:

list with plugin module information

install a package

Installs the package

Parameters:

  • API Key API key with master permissions
  • m package content (base64-encoded tar/tgz)
  • o package setup options
  • w wait (in seconds) before API call sends a response. This allows to try waiting until the package is installed
shutdown the controller

Controller process will be exited and then (should be) restarted by watchdog. This allows to restart controller remotely.

For MQTT API calls a small shutdown delay usually should be specified to let the core send the correct API response.

http

POST /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "shutdown" }

curl

curl -i -X POST http://localhost:8812/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "shutdown"}'

wget

wget -S -O- http://localhost:8812/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "shutdown"}'

httpie

echo '{
  "method": "shutdown"
}' | http POST http://localhost:8812/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'shutdown'})

response

HTTP/1.1 202 Accepted
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • t shutdown delay (seconds)
switch debugging mode

Enables and disables debugging mode while the controller is running. After the controller is restarted, this parameter is lost and controller switches back to the mode specified in the configuration file.

http

PATCH /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "debug": true }

curl

curl -i -X PATCH http://localhost:8812/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"debug": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"debug": true}'

httpie

echo '{
  "debug": true
}' | http PATCH http://localhost:8812/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'debug': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • debug true for enabling debug mode, false for disabling
log in and get authentication token

Obtains authentication token which can be used in API calls instead of API key.

If both k and u args are absent, but API method is called with HTTP request, which contain HTTP header for basic authorization, the function will try to parse it and log in user with credentials provided.

If authentication token is specified, the function will check it and return token information if it is valid.

If both token and credentials (user or API key) are specified, the function will return the token to normal mode.

http

POST /r/token HTTP/1.1
Host: localhost:8828
Content-Type: application/json

{ "u": "admin", "p": "123" }

curl

curl -i -X POST http://localhost:8828/r/token -H 'Content-Type: application/json' --data-raw '{"p": "123", "u": "admin"}'

wget

wget -S -O- http://localhost:8828/r/token --header='Content-Type: application/json' --post-data='{"p": "123", "u": "admin"}'

httpie

echo '{
  "p": "123",
  "u": "admin"
}' | http POST http://localhost:8828/r/token Content-Type:application/json

python-requests

requests.post('http://localhost:8828/r/token', headers={'Content-Type': 'application/json'}, json={'p': '123', 'u': 'admin'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "key": "masterkey",
    "token": "token:1c166529bc3b06dac6e0fbaefee38ebe77c455480e11ff4431de2b10a5508899",
    "user": "admin"
}

Parameters:

  • API Key valid API key or
  • u user login
  • p user password
  • a authentication token

Returns:

A dict, containing API key ID and authentication token

log out and purge authentication token

Purges authentication token

http

DELETE /r/token HTTP/1.1
Host: localhost:8812
X-Auth-Key: token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7

curl

curl -i -X DELETE http://localhost:8812/r/token -H 'X-Auth-Key: token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/token --header='X-Auth-Key: token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7'

httpie

http DELETE http://localhost:8812/r/token X-Auth-Key:token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7

python-requests

requests.delete('http://localhost:8812/r/token', headers={'X-Auth-Key': 'token:c063c19fb54dd6b773b4f236f26ea7e5fbaa96f48b103221ae1107420096aef7'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid token
Set token read-only

Applies read-only mode for token. In read-only mode, only read-only functions work, others return result_token_restricted(15).

The method works for token-authenticated API calls only.

To exit read-only mode, user must either re-login or, to keep the current token, call “login” API method with both token and user credentials.

Item functions
clean action queue of unit

Cancels all queued actions, keeps the current action running.

http

POST /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "q_clean" }

curl

curl -i -X POST http://localhost:8828/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "q_clean"}'

wget

wget -S -O- http://localhost:8828/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "q_clean"}'

httpie

echo '{
  "method": "q_clean"
}' | http POST http://localhost:8828/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'q_clean'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
create unit control action

The call is considered successful when action is put into the action queue of selected unit.

http

POST /r/action HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "s": 1, "i": "unit:tests/unit3", "s": 1 }

curl

curl -i -X POST http://localhost:8828/r/action -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"i": "unit:tests/unit3", "s": 1}'

wget

wget -S -O- http://localhost:8828/r/action --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"i": "unit:tests/unit3", "s": 1}'

httpie

echo '{
  "i": "unit:tests/unit3",
  "s": 1
}' | http POST http://localhost:8828/r/action Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/action', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'i': 'unit:tests/unit3', 's': 1})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Location: /r/action/751955a9-9eb6-451b-8069-706bd445a9f7
Pragma: no-cache

{
    "err": "",
    "exitcode": null,
    "finished": true,
    "finished_in": 0.0009174,
    "item_group": "tests",
    "item_id": "unit3",
    "item_oid": "unit:tests/unit3",
    "item_type": "unit",
    "nstatus": 1,
    "nvalue": null,
    "out": "",
    "priority": 100,
    "status": "refused",
    "time": {
        "created": 1559868835.769016,
        "pending": 1559868835.769214,
        "refused": 1559868835.7699335
    },
    "uuid": "751955a9-9eb6-451b-8069-706bd445a9f7"
}

Parameters:

  • API Key valid API key

Optionally:

  • s desired unit status
  • v desired unit value
  • w wait for the completion for the specified number of seconds
  • p queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”

Returns:

Serialized action object. If action is marked as dead, an error is returned (exception raised)

disable unit actions

Disables unit to run and queue new actions.

http

PATCH /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "action_enabled": false }

curl

curl -i -X PATCH http://localhost:8828/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"action_enabled": false}'

wget

wget -S -O- --method=PATCH http://localhost:8828/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"action_enabled": false}'

httpie

echo '{
  "action_enabled": false
}' | http PATCH http://localhost:8828/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8828/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'action_enabled': False})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
enable unit actions

Enables unit to run and queue new actions.

http

PATCH /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "action_enabled": true }

curl

curl -i -X PATCH http://localhost:8828/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"action_enabled": true}'

wget

wget -S -O- --method=PATCH http://localhost:8828/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"action_enabled": true}'

httpie

echo '{
  "action_enabled": true
}' | http PATCH http://localhost:8828/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8828/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'action_enabled': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
get action status or macro run result

Checks the result of the action by its UUID or returns the actions for the specified unit or execution result of the specified macro.

http

GET /r/action?i=unit%3Atests%2Funit1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i 'http://localhost:8828/r/action?i=unit%3Atests%2Funit1' -H 'X-Auth-Key: mykey'

wget

wget -S -O- 'http://localhost:8828/r/action?i=unit%3Atests%2Funit1' --header='X-Auth-Key: mykey'

httpie

http 'http://localhost:8828/r/action?i=unit%3Atests%2Funit1' X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/action?i=unit%3Atests%2Funit1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "err": "",
        "exitcode": null,
        "finished": true,
        "finished_in": 0.0006144,
        "item_group": "tests",
        "item_id": "unit1",
        "item_oid": "unit:tests/unit1",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "refused",
        "time": {
            "created": 1559868829.0452583,
            "pending": 1559868829.0455182,
            "refused": 1559868829.0458727
        },
        "uuid": "70db470b-7d7e-4698-a001-01958c0ff3a7"
    },
    {
        "err": "",
        "exitcode": null,
        "finished": true,
        "finished_in": 0.0010161,
        "item_group": "tests",
        "item_id": "unit1",
        "item_oid": "unit:tests/unit1",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "refused",
        "time": {
            "created": 1559868829.087297,
            "pending": 1559868829.0876813,
            "refused": 1559868829.088313
        },
        "uuid": "3737a15b-515c-4e85-be2a-c937392851fa"
    },
    {
        "err": "",
        "exitcode": null,
        "finished": true,
        "finished_in": 0.0005889,
        "item_group": "tests",
        "item_id": "unit1",
        "item_oid": "unit:tests/unit1",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "refused",
        "time": {
            "created": 1559868835.75104,
            "pending": 1559868835.751197,
            "refused": 1559868835.7516289
        },
        "uuid": "d2aab822-ec47-4370-8145-f8f455db4d27"
    },
    {
        "err": "",
        "exitcode": null,
        "finished": true,
        "finished_in": 0.001091,
        "item_group": "tests",
        "item_id": "unit1",
        "item_oid": "unit:tests/unit1",
        "item_type": "unit",
        "nstatus": 1,
        "nvalue": null,
        "out": "",
        "priority": 100,
        "status": "refused",
        "time": {
            "created": 1559868835.7902575,
            "pending": 1559868835.7906036,
            "refused": 1559868835.7913485
        },
        "uuid": "8038de65-3833-4aa5-94c1-c0f0e86eb3fe"
    }
]

Parameters:

  • API Key valid API key

Optionally:

  • g filter by unit group
  • s filter by action status: Q for queued, R for running, F for finished

Returns:

list or single serialized action object

get item group list

Get the list of item groups. Useful e.g. for custom interfaces.

http

GET /r/unit/@groups HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/unit/@groups -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/unit/@groups --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/unit/@groups X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/unit/@groups', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    "mb",
    "room1",
    "tests"
]

Parameters:

  • API Key valid API key
get item state

State of the item or all items of the specified type can be obtained using state command.

http

GET /r/sensor HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/sensor -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/sensor --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/sensor X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/sensor', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "controller_id": "uc/mws1-v1",
        "full_id": "env/temp_test",
        "group": "env",
        "id": "temp_test",
        "oid": "sensor:env/temp_test",
        "status": 1,
        "type": "sensor",
        "value": "191"
    },
    {
        "controller_id": "uc/mws1-v1",
        "full_id": "room1/lamps",
        "group": "room1",
        "id": "lamps",
        "oid": "sensor:room1/lamps",
        "status": 0,
        "type": "sensor",
        "value": "null"
    },
    {
        "controller_id": "uc/mws1-v1",
        "full_id": "room2/h",
        "group": "room2",
        "id": "h",
        "oid": "sensor:room2/h",
        "status": 0,
        "type": "sensor",
        "value": "null"
    },
    {
        "controller_id": "uc/mws1-v1",
        "full_id": "room2/lamps",
        "group": "room2",
        "id": "lamps",
        "oid": "sensor:room2/lamps",
        "status": 0,
        "type": "sensor",
        "value": "null"
    }
]

Parameters:

  • API Key valid API key

Optionally:

get item state history

State history of one item or several items of the specified type can be obtained using state_history command.

If master key is used, the method attempts to get stored state for an item even if it doesn’t present currently in system.

The method can return state log for disconnected items as well.

http

GET /r/sensor/env/temp_test@history HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/sensor/env/temp_test@history -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/sensor/env/temp_test@history --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/sensor/env/temp_test@history X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/sensor/env/temp_test@history', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "status": [
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1
    ],
    "t": [
        1553390125.8643427,
        1553390140.929797,
        1553390334.862889,
        1553390589.4016967,
        1553390732.9677052,
        1553391169.14625,
        1553391188.7430675,
        1553391215.390878,
        1553391623.3912942,
        1553391746.352703,
        1553391851.0065582,
        1553391951.145705,
        1553391968.589165,
        1553392069.766155,
        1553392157.956836,
        1553392366.729588,
        1553392495.9142005,
        1553392581.9080076,
        1553393041.2446685,
        1553393176.3235447
    ],
    "value": [
        19.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0,
        191.0
    ]
}

Parameters:

  • API Key valid API key
  • a history notifier id (default: db_1)

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • l records limit (doesn’t work with “w”)
  • x state prop (“status” or “value”)
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • z Time zone (pytz, e.g. UTC or Europe/Prague)
  • w fill frame with the interval (e.g. “1T” - 1 min, “2H” - 2 hours etc.), start time is required, set to 1D if not specified
  • g output format (“list”, “dict” or “chart”, default is “list”)
  • c options for chart (dict or comma separated)
  • o extra options for notifier data request

Returns:

history data in specified format or chart image.

For chart, JSON RPC gets reply with “content_type” and “data” fields, where content is image content type. If PNG image format is selected, data is base64-encoded.

Options for chart (all are optional):

If option “w” (fill) is used, number of digits after comma may be specified. E.g. 5T:3 will output values with 3 digits after comma.

Additionally, SI prefix may be specified to convert value to kilos, megas etc, e.g. 5T:k:3 - divide value by 1000 and output 3 digits after comma. Valid prefixes are: k, M, G, T, P, E, Z, Y.

If binary prefix is required, it should be followed by “b”, e.g. 5T:Mb:3 - divide value by 2^20 and output 3 digits after comma.

get item state log

State log of a single item or group of the specified type can be obtained using state_log command.

note: only SQL notifiers are supported

Difference from state_history method:

  • state_log doesn’t optimize data to be displayed on charts * the data is returned from a database as-is * a single item OID or OID mask (e.g. sensor:env/#) can be specified

note: the method supports MQTT-style masks but only masks with wildcard-ending, like “type:group/subgroup/#” are supported.

The method can return state log for disconnected items as well.

For wildcard fetching, API key should have an access to the whole chosen group.

note: record limit means the limit for records, fetched from the database, but repeating state records are automatically grouped and the actual number of returned records can be lower than requested.

http

GET /r/sensor/tests/test1@log HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/sensor/tests/test1@log -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/sensor/tests/test1@log --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/sensor/tests/test1@log X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/sensor/tests/test1@log', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "oid": "sensor:tests/test1",
        "status": 1,
        "t": 1607295696.9975107,
        "value": 359.0
    },
    {
        "oid": "sensor:tests/test1",
        "status": 1,
        "t": 1607295713.5487244,
        "value": 772.0
    }
]

Parameters:

  • API Key valid API key
  • a history notifier id (default: db_1)

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • l records limit (doesn’t work with “w”)
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • z Time zone (pytz, e.g. UTC or Europe/Prague)
  • o extra options for notifier data request

Returns:

state log records (list)

kill unit actions

Apart from canceling all queued commands, this function also terminates the current running action.

http

POST /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "kill" }

curl

curl -i -X POST http://localhost:8828/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "kill"}'

wget

wget -S -O- http://localhost:8828/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "kill"}'

httpie

echo '{
  "method": "kill"
}' | http POST http://localhost:8828/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'kill'})

response

HTTP/1.1 202 Accepted
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key

Returns:

If the current action of the unit cannot be terminated by configuration, the notice “pt” = “denied” will be returned additionally (even if there’s no action running)

terminate action execution

Terminates or cancel the action if it is still queued

http

POST /r/unit/tests/unit3 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "terminate" }

curl

curl -i -X POST http://localhost:8828/r/unit/tests/unit3 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "terminate"}'

wget

wget -S -O- http://localhost:8828/r/unit/tests/unit3 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "terminate"}'

httpie

echo '{
  "method": "terminate"
}' | http POST http://localhost:8828/r/unit/tests/unit3 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/unit/tests/unit3', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'terminate'})

response

HTTP/1.1 202 Accepted
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key

Returns:

An error result will be returned eitner if action is terminated (Resource not found) or if termination process is failed or denied by unit configuration (Function failed)

toggle unit status

Create unit control action to toggle its status (1->0, 0->1)

http

POST /r/action HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "i": "unit:tests/unit3", "s": "toggle" }

curl

curl -i -X POST http://localhost:8828/r/action -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"i": "unit:tests/unit3", "s": "toggle"}'

wget

wget -S -O- http://localhost:8828/r/action --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"i": "unit:tests/unit3", "s": "toggle"}'

httpie

echo '{
  "i": "unit:tests/unit3",
  "s": "toggle"
}' | http POST http://localhost:8828/r/action Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/action', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'i': 'unit:tests/unit3', 's': 'toggle'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Location: /r/action/afaab4be-67b5-4906-a32d-1339bcbae5a3
Pragma: no-cache

{
    "err": "",
    "exitcode": null,
    "finished": true,
    "finished_in": 0.0006881,
    "item_group": "tests",
    "item_id": "unit3",
    "item_oid": "unit:tests/unit3",
    "item_type": "unit",
    "nstatus": 1,
    "nvalue": null,
    "out": "",
    "priority": 100,
    "status": "refused",
    "time": {
        "created": 1559868835.8054502,
        "pending": 1559868835.805737,
        "refused": 1559868835.8061383
    },
    "uuid": "afaab4be-67b5-4906-a32d-1339bcbae5a3"
}

Parameters:

  • API Key valid API key

Optionally:

  • w wait for the completion for the specified number of seconds
  • p queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”

Returns:

Serialized action object. If action is marked as dead, an error is returned (exception raised)

clear lvar state

set status (if expires lvar param > 0) or value (if expires isn’t set) of a logic variable to 0. Useful when lvar is used as a timer to stop it, or as a flag to set it False.

http

POST /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "s": "clear" }

curl

curl -i -X POST http://localhost:8828/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"s": "clear"}'

wget

wget -S -O- http://localhost:8828/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"s": "clear"}'

httpie

echo '{
  "s": "clear"
}' | http POST http://localhost:8828/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'s': 'clear'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
clear lvar state

set status (if expires lvar param > 0) or value (if expires isn’t set) of a logic variable to 0. Useful when lvar is used as a timer to stop it, or as a flag to set it False.

http

POST /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "s": "toggle" }

curl

curl -i -X POST http://localhost:8828/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"s": "toggle"}'

wget

wget -S -O- http://localhost:8828/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"s": "toggle"}'

httpie

echo '{
  "s": "toggle"
}' | http POST http://localhost:8828/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'s': 'toggle'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
decrement lvar value

Decrement value of a logic variable. Initial value should be number

http

POST /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "v": "!decrement" }

curl

curl -i -X POST http://localhost:8828/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"v": "!decrement"}'

wget

wget -S -O- http://localhost:8828/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"v": "!decrement"}'

httpie

echo '{
  "v": "!decrement"
}' | http POST http://localhost:8828/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'v': '!decrement'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
increment lvar value

Increment value of a logic variable. Initial value should be number

http

POST /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "v": "!increment" }

curl

curl -i -X POST http://localhost:8828/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"v": "!increment"}'

wget

wget -S -O- http://localhost:8828/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"v": "!increment"}'

httpie

echo '{
  "v": "!increment"
}' | http POST http://localhost:8828/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'v': '!increment'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
reset lvar state

Set status and value of a logic variable to 1. Useful when lvar is being used as a timer to reset it, or as a flag to set it True.

http

POST /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "s": "reset" }

curl

curl -i -X POST http://localhost:8828/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"s": "reset"}'

wget

wget -S -O- http://localhost:8828/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"s": "reset"}'

httpie

echo '{
  "s": "reset"
}' | http POST http://localhost:8828/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'s': 'reset'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key
set lvar state

Set status and value of a logic variable.

http

POST /r/lvar/tests/lvar1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "s": 1, "v": 29 }

curl

curl -i -X POST http://localhost:8828/r/lvar/tests/lvar1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"s": 1, "v": 29}'

wget

wget -S -O- http://localhost:8828/r/lvar/tests/lvar1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"s": 1, "v": 29}'

httpie

echo '{
  "s": 1,
  "v": 29
}' | http POST http://localhost:8828/r/lvar/tests/lvar1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/lvar/tests/lvar1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'s': 1, 'v': 29})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key valid API key

Optionally:

  • s lvar status
  • v lvar value
Logic cycles
get cycle groups list

Get the list of cycles. Useful e.g. for custom interfaces.

http

GET /r/lcycle/@groups HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/lcycle/@groups -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/lcycle/@groups --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/lcycle/@groups X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/lcycle/@groups', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    "tests"
]

Parameters:

  • API Key valid API key
get cycle information

http

GET /r/lcycle/tests/cycle1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/lcycle/tests/cycle1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/lcycle/tests/cycle1 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/lcycle/tests/cycle1 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/lcycle/tests/cycle1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "controller_id": "lm/mws1-v1",
    "description": "",
    "full_id": "tests/cycle1",
    "group": "tests",
    "id": "cycle1",
    "interval": 0.01,
    "oid": "lcycle:tests/cycle1",
    "type": "lcycle"
}

Parameters:

  • API Key valid API key

Returns:

field “value” contains real average cycle interval

get cycle list

Get the list of all available cycles.

http

GET /r/lcycle HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/lcycle -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/lcycle --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/lcycle X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/lcycle', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "controller_id": "lm/mws1-v1",
        "description": "",
        "full_id": "tests/cycle1",
        "group": "tests",
        "id": "cycle1",
        "interval": 0.01,
        "oid": "lcycle:tests/cycle1",
        "status": 0,
        "type": "lcycle",
        "value": "0,0.0100,"
    },
    {
        "controller_id": "lm/mws1-v1",
        "description": "test 2Hz cycle",
        "full_id": "tests/test1",
        "group": "tests",
        "id": "test1",
        "interval": 0.5,
        "oid": "lcycle:tests/test1",
        "status": 0,
        "type": "lcycle",
        "value": "0,0.5000,"
    }
]

Parameters:

  • API Key valid API key

Optionally:

  • i filter by controller
Logic macros
execute macro

Execute a macro with the specified arguments.

http

POST /r/lmacro/tests/test1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "run" }

curl

curl -i -X POST http://localhost:8828/r/lmacro/tests/test1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "run"}'

wget

wget -S -O- http://localhost:8828/r/lmacro/tests/test1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "run"}'

httpie

echo '{
  "method": "run"
}' | http POST http://localhost:8828/r/lmacro/tests/test1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/lmacro/tests/test1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'run'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Location: /r/action/6ea7dc1f-2934-45da-8209-d29d7d1d9259
Pragma: no-cache

{
    "args": [],
    "err": "",
    "exitcode": 0,
    "finished": true,
    "finished_in": 0.0030398,
    "item_group": "tests",
    "item_id": "test1",
    "item_oid": "lmacro:tests/test1",
    "item_type": "lmacro",
    "kwargs": {},
    "out": "",
    "priority": 100,
    "status": "completed",
    "time": {
        "completed": 1559868836.280482,
        "created": 1559868836.2774422,
        "pending": 1559868836.2777095,
        "queued": 1559868836.2782526,
        "running": 1559868836.2789273
    },
    "uuid": "6ea7dc1f-2934-45da-8209-d29d7d1d9259"
}

Parameters:

  • API Key valid API key

Optionally:

  • a macro arguments, array or space separated
  • kw macro keyword arguments, name=value, comma separated or dict
  • w wait for the completion for the specified number of seconds
  • p queue priority (default is 100, lower is better)
  • q global queue timeout, if expires, action is marked as “dead”
get macro groups list

Get the list of macros. Useful e.g. for custom interfaces.

http

GET /r/lmacro/@groups HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/lmacro/@groups -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/lmacro/@groups --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/lmacro/@groups X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/lmacro/@groups', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    "nogroup",
    "tests"
]

Parameters:

  • API Key valid API key
get macro list

Get the list of all available macros.

http

GET /r/lmacro HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/lmacro -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/lmacro --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/lmacro X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/lmacro', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "action_enabled": true,
        "controller_id": "lm/mws1-v1",
        "description": "",
        "full_id": "nogroup/lr",
        "group": "nogroup",
        "id": "lr",
        "oid": "lmacro:nogroup/lr",
        "type": "lmacro"
    },
    {
        "action_enabled": true,
        "controller_id": "lm/mws1-v1",
        "description": "test macro",
        "full_id": "tests/test",
        "group": "tests",
        "id": "test",
        "oid": "lmacro:tests/test",
        "type": "lmacro"
    },
    {
        "action_enabled": true,
        "controller_id": "lm/mws1-v1",
        "description": "",
        "full_id": "tests/test1",
        "group": "tests",
        "id": "test1",
        "oid": "lmacro:tests/test1",
        "type": "lmacro"
    },
    {
        "action_enabled": true,
        "controller_id": "lm/mws1-v1",
        "description": "",
        "full_id": "tests/test2",
        "group": "tests",
        "id": "test2",
        "oid": "lmacro:tests/test2",
        "type": "lmacro"
    }
]

Parameters:

  • API Key valid API key

Optionally:

  • i filter by controller
Supervisor functions
set supervisor API lock

When supervisor lock is set, SFA API functions become read-only for all users, except users in the lock scope.

http

PATCH /r/core HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "supervisor_lock": {} }

curl

curl -i -X PATCH http://localhost:8828/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"supervisor_lock": {}}'

wget

wget -S -O- --method=PATCH http://localhost:8828/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"supervisor_lock": {}}'

httpie

echo '{
  "supervisor_lock": {}
}' | http PATCH http://localhost:8828/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8828/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'supervisor_lock': {}})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with allow=supervisor permissions

Notes:

supervisor_lock should be a dictionary. If the dictionary is empty, default lock is set.

  • attribute “l” = “<k|u>” sets lock scope (key / user)
  • attribute “c” = “<k|u>” set unlock/override scope

attribute “o” overrides lock owner (master key is required) with sub-attributes:

  • “u” = user
  • “utp” = user type (null for local, “msad” for Active Directory etc.)
  • “key_id” = API key ID
clear supervisor API lock

API key should have permission to clear existing supervisor lock

http

PATCH /r/core HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "supervisor_lock": null }

curl

curl -i -X PATCH http://localhost:8828/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"supervisor_lock": null}'

wget

wget -S -O- --method=PATCH http://localhost:8828/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"supervisor_lock": null}'

httpie

echo '{
  "supervisor_lock": null
}' | http PATCH http://localhost:8828/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8828/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'supervisor_lock': None})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with allow=supervisor permissions

Returns:

Successful result is returned if lock is either cleared or not set

send broadcast message

http

POST /r/core HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "m": "hello this is a test", "method": "supervisor_message" }

curl

curl -i -X POST http://localhost:8828/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"m": "hello this is a test", "method": "supervisor_message"}'

wget

wget -S -O- http://localhost:8828/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"m": "hello this is a test", "method": "supervisor_message"}'

httpie

echo '{
  "m": "hello this is a test",
  "method": "supervisor_message"
}' | http POST http://localhost:8828/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'m': 'hello this is a test', 'method': 'supervisor_message'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with allow=supervisor permissions
  • m message text

Notes:

If master key is used, sender can be overriden with “sender” argument, which should be a dictionary and contain:

  • u = message sender user
  • key_id = message sender API key ID
Remote controllers
connect remote controller via HTTP

Connects remote controller to the local.

http

POST /r/controller/uc HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "u": "localhost", "a": "secretkey", "save": true }

curl

curl -i -X POST http://localhost:8828/r/controller/uc -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"a": "secretkey", "save": true, "u": "localhost"}'

wget

wget -S -O- http://localhost:8828/r/controller/uc --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"a": "secretkey", "save": true, "u": "localhost"}'

httpie

echo '{
  "a": "secretkey",
  "save": true,
  "u": "localhost"
}' | http POST http://localhost:8828/r/controller/uc Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/controller/uc', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'a': 'secretkey', 'save': True, 'u': 'localhost'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Location: /r/controller/uc/ws1-v1
Pragma: no-cache

{
    "build": "2019031405",
    "connected": true,
    "description": "",
    "enabled": true,
    "full_id": "uc/ws1-v1",
    "group": "uc",
    "id": "ws1-v1",
    "managed": false,
    "mqtt_update": null,
    "oid": "remote_uc:uc/ws1-v1",
    "proto": "http",
    "static": true,
    "type": "remote_uc",
    "version": "3.2.0"
}

Parameters:

  • API Key API key with master permissions
  • u Controller API uri (proto://host:port, port not required if default)
  • a remote controller API key ($key to use local key)

Optionally:

  • m ref:MQTT notifier<mqtt_> to exchange item states in real time (default: eva_1)
  • s verify remote SSL certificate or pass invalid
  • t timeout (seconds) for the remote controller API calls
  • g controller type (“uc” or “lm”), autodetected if none
  • save save connected controller configuration on the disk immediately after creation
disable connected controller

http

PATCH /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "enabled": false }

curl

curl -i -X PATCH http://localhost:8828/r/controller/uc/ws1-v1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"enabled": false, "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8828/r/controller/uc/ws1-v1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"enabled": false, "save": true}'

httpie

echo '{
  "enabled": false,
  "save": true
}' | http PATCH http://localhost:8828/r/controller/uc/ws1-v1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8828/r/controller/uc/ws1-v1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'enabled': False, 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
disconnect controller

http

DELETE /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8828/r/controller/uc/ws1-v1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8828/r/controller/uc/ws1-v1 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8828/r/controller/uc/ws1-v1 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8828/r/controller/uc/ws1-v1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
enable connected controller

http

PATCH /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "enabled": true }

curl

curl -i -X PATCH http://localhost:8828/r/controller/uc/ws1-v1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"enabled": true, "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8828/r/controller/uc/ws1-v1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"enabled": true, "save": true}'

httpie

echo '{
  "enabled": true,
  "save": true
}' | http PATCH http://localhost:8828/r/controller/uc/ws1-v1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8828/r/controller/uc/ws1-v1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'enabled': True, 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
get a list of items from connected controllers

Get a list of the items loaded from the connected controllers. Useful to debug the controller connections.

http

GET /r/controller/uc/ws1-v1@items HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/controller/uc/ws1-v1@items -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/controller/uc/ws1-v1@items --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/controller/uc/ws1-v1@items X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/controller/uc/ws1-v1@items', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: GET, HEAD, POST
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "controller_id": "uc/ws1-v1",
        "description": "",
        "full_id": "env/temp_test",
        "group": "env",
        "id": "temp_test",
        "loc_x": null,
        "loc_y": null,
        "loc_z": null,
        "location": "",
        "oid": "sensor:env/temp_test",
        "status": 0,
        "type": "sensor",
        "value": "null"
    },
    {
        "action_enabled": true,
        "controller_id": "uc/ws1-v1",
        "description": "",
        "full_id": "nogroup/test2",
        "group": "nogroup",
        "id": "test2",
        "loc_x": null,
        "loc_y": null,
        "loc_z": null,
        "location": "",
        "nstatus": -1,
        "nvalue": "null",
        "oid": "unit:nogroup/test2",
        "status": -1,
        "status_labels": [
            {
                "label": "OFF",
                "status": 0
            },
            {
                "label": "ON",
                "status": 1
            }
        ],
        "type": "unit",
        "value": "null"
    }
]

Parameters:

  • API Key API key with master permissions

Optionally:

  • g filter by item group
  • p filter by item type
get connected controller information

http

GET /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/controller/uc/ws1-v1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/controller/uc/ws1-v1 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/controller/uc/ws1-v1 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/controller/uc/ws1-v1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "build": "2019031405",
    "connected": true,
    "description": "",
    "enabled": true,
    "full_id": "uc/ws1-v1",
    "group": "uc",
    "id": "ws1-v1",
    "managed": false,
    "mqtt_update": null,
    "oid": "remote_uc:uc/ws1-v1",
    "proto": "http",
    "static": true,
    "type": "remote_uc",
    "version": "3.2.0"
}

Parameters:

  • API Key API key with master permissions
get controller connection parameters

http

GET /r/controller/uc/ws1-v1@props HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/controller/uc/ws1-v1@props -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/controller/uc/ws1-v1@props --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/controller/uc/ws1-v1@props X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/controller/uc/ws1-v1@props', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "description": "",
    "enabled": true,
    "key": "secretkey",
    "mqtt_update": null,
    "reload_interval": 300,
    "retries": 2,
    "ssl_verify": true,
    "static": true,
    "timeout": 5.0,
    "uri": "http://localhost:8812"
}

Parameters:

  • API Key API key with master permissions
get controllers list

Get the list of all connected controllers.

http

GET /r/controller HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey

curl

curl -i http://localhost:8828/r/controller -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8828/r/controller --header='X-Auth-Key: mykey'

httpie

http http://localhost:8828/r/controller X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8828/r/controller', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "build": "2019032301",
        "connected": true,
        "description": "",
        "enabled": true,
        "full_id": "lm/mws1-v1",
        "group": "lm",
        "id": "mws1-v1",
        "managed": false,
        "mqtt_update": "eva_1",
        "oid": "remote_lm:lm/mws1-v1",
        "proto": "http",
        "static": true,
        "type": "remote_lm",
        "version": "3.2.0"
    },
    {
        "build": "2019032301",
        "connected": true,
        "description": "",
        "enabled": true,
        "full_id": "uc/mws1-v1",
        "group": "uc",
        "id": "mws1-v1",
        "managed": false,
        "mqtt_update": "eva_1",
        "oid": "remote_uc:uc/mws1-v1",
        "proto": "http",
        "static": true,
        "type": "remote_uc",
        "version": "3.2.0"
    }
]

Parameters:

  • API Key API key with master permissions
reload controller

Reloads items from connected controller. If controller ID “ALL” is specified, all connected controllers are reloaded.

http

POST /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "reload" }

curl

curl -i -X POST http://localhost:8828/r/controller/uc/ws1-v1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "reload"}'

wget

wget -S -O- http://localhost:8828/r/controller/uc/ws1-v1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "reload"}'

httpie

echo '{
  "method": "reload"
}' | http POST http://localhost:8828/r/controller/uc/ws1-v1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/controller/uc/ws1-v1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'reload'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
rescan controllers via UPnP

http

POST /r/controller HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "upnp-rescan" }

curl

curl -i -X POST http://localhost:8828/r/controller -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "upnp-rescan"}'

wget

wget -S -O- http://localhost:8828/r/controller --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "upnp-rescan"}'

httpie

echo '{
  "method": "upnp-rescan"
}' | http POST http://localhost:8828/r/controller Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/controller', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'upnp-rescan'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
set controller connection parameters

http

PATCH /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "reload_interval": 60 }

curl

curl -i -X PATCH http://localhost:8828/r/controller/uc/ws1-v1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"reload_interval": 60, "save": true}'

wget

wget -S -O- --method=PATCH http://localhost:8828/r/controller/uc/ws1-v1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"reload_interval": 60, "save": true}'

httpie

echo '{
  "reload_interval": 60,
  "save": true
}' | http PATCH http://localhost:8828/r/controller/uc/ws1-v1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8828/r/controller/uc/ws1-v1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'reload_interval': 60, 'save': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions

Optionally:

  • save save configuration after successful call
test connection to remote controller

http

POST /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "test" }

curl

curl -i -X POST http://localhost:8828/r/controller/uc/ws1-v1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "test"}'

wget

wget -S -O- http://localhost:8828/r/controller/uc/ws1-v1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "test"}'

httpie

echo '{
  "method": "test"
}' | http POST http://localhost:8828/r/controller/uc/ws1-v1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/controller/uc/ws1-v1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'test'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
test management API connection to remote controller

http

POST /r/controller/uc/ws1-v1 HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "matest" }

curl

curl -i -X POST http://localhost:8828/r/controller/uc/ws1-v1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "matest"}'

wget

wget -S -O- http://localhost:8828/r/controller/uc/ws1-v1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "matest"}'

httpie

echo '{
  "method": "matest"
}' | http POST http://localhost:8828/r/controller/uc/ws1-v1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/controller/uc/ws1-v1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'matest'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
Connected clients
ask connected clients to reload

Sends reload event to all connected clients asking them to reload the interface.

All the connected clients receive the event with subject=”reload” and data=”asap”. If the clients use EVA JS Framework, they can catch server.reload event.

http

POST /r/core HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "reload_clients" }

curl

curl -i -X POST http://localhost:8828/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "reload_clients"}'

wget

wget -S -O- http://localhost:8828/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "reload_clients"}'

httpie

echo '{
  "method": "reload_clients"
}' | http POST http://localhost:8828/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'reload_clients'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
notify connected clients about server restart

Sends a server restart event to all connected clients asking them to prepare for server restart.

All the connected clients receive the event with subject=”server” and data=”restart”. If the clients use EVA JS Framework, they can catch server.restart event.

Server restart notification is sent automatically to all connected clients when the server is restarting. This API function allows to send server restart notification without actual server restart, which may be useful e.g. for testing, handling frontend restart etc.

http

POST /r/core HTTP/1.1
Host: localhost:8828
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "notify_restart" }

curl

curl -i -X POST http://localhost:8828/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "notify_restart"}'

wget

wget -S -O- http://localhost:8828/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "notify_restart"}'

httpie

echo '{
  "method": "notify_restart"
}' | http POST http://localhost:8828/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8828/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'notify_restart'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
CVARs
get the value of user-defined variable

Note

Even if different EVA controllers are working on the same server, they have different sets of variables To set the variables for each subsystem, use SYS API on the respective address/port.

http

GET /r/cvar/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/cvar/test -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/cvar/test --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/cvar/test X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/cvar/test', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "test": "some_value"
}

Parameters:

  • API Key API key with master permissions

Optionally:

Returns:

Dict containing variable and its value. If no varible name was specified, all cvars are returned.

set the value of user-defined variable

http

PUT /r/cvar/test HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "v": "some_value" }

curl

curl -i -X PUT http://localhost:8812/r/cvar/test -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"v": "some_value"}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/cvar/test --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"v": "some_value"}'

httpie

echo '{
  "v": "some_value"
}' | http PUT http://localhost:8812/r/cvar/test Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/cvar/test', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'v': 'some_value'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "test": "some_value"
}

Parameters:

  • API Key API key with master permissions

Optionally:

  • v variable value (if not specified, variable is deleted)
Locking functions
acquire lock

Locks can be used similarly to file locking by the specific process. The difference is that SYS API tokens can be:

  • centralized for several systems (any EVA server can act as lock server)
  • removed from outside
  • automatically unlocked after the expiration time, if the initiator failed or forgot to release the lock

used to restrict parallel process starting or access to system files/resources. LM PLC macro share locks with extrnal scripts.

Note

Even if different EVA controllers are working on the same server, their lock tokens are stored in different bases. To work with the token of each subsystem, use SYS API on the respective address/port.

http

PUT /r/lock/mylock1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "e": 1, "t": 15 }

curl

curl -i -X PUT http://localhost:8812/r/lock/mylock1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"e": 1, "t": 15}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/lock/mylock1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"e": 1, "t": 15}'

httpie

echo '{
  "e": 1,
  "t": 15
}' | http PUT http://localhost:8812/r/lock/mylock1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/lock/mylock1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'e': 1, 't': 15})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": "mylock1",
    "type": "lock"
}

Parameters:

  • API Key API key with allow=lock permissions

Optionally:

  • t maximum time (seconds) to acquire lock
  • e time after which lock is automatically released (if absent, lock may be released only via unlock function)
get lock status

http

GET /r/lock/mylock1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/lock/mylock1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/lock/mylock1 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/lock/mylock1 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/lock/mylock1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": "mylock1",
    "locked": true,
    "type": "lock"
}

Parameters:

  • API Key API key with allow=lock permissions
release lock

Releases the previously acquired lock.

http

DELETE /r/lock/mylock1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/lock/mylock1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/lock/mylock1 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/lock/mylock1 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/lock/mylock1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with allow=lock permissions
Logging
put message to log file

An external application can put a message in the logs on behalf of the controller.

http

POST /r/log/warning HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "m": "local file system is full" }

curl

curl -i -X POST http://localhost:8812/r/log/warning -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"m": "local file system is full"}'

wget

wget -S -O- http://localhost:8812/r/log/warning --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"m": "local file system is full"}'

httpie

echo '{
  "m": "local file system is full"
}' | http POST http://localhost:8812/r/log/warning Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/log/warning', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'m': 'local file system is full'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with sysfunc=yes permissions
  • l log level
  • m message text
put debug message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
put info message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
put warning message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
put error message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
put critical message to log file

An external application can put a message in the logs on behalf of the controller.

Parameters:

  • API Key API key with sysfunc=yes permissions
  • m message text
get records from the controller log

Log records are stored in the controllers’ memory until restart or the time (keep_logmem) specified in controller configuration passes.

http

GET /r/log/warning?t=3600&n=3 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i 'http://localhost:8812/r/log/warning?t=3600&n=3' -H 'X-Auth-Key: mykey'

wget

wget -S -O- 'http://localhost:8812/r/log/warning?t=3600&n=3' --header='X-Auth-Key: mykey'

httpie

http 'http://localhost:8812/r/log/warning?t=3600&n=3' X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/log/warning?t=3600&n=3', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "h": "mws1-v1",
        "l": 30,
        "mod": "sysapi",
        "msg": "test warning message",
        "p": "uc",
        "t": 1552863481.1394246,
        "th": "CP Server Thread-15"
    },
    {
        "h": "mws1-v1",
        "l": 40,
        "mod": "sysapi",
        "msg": "test error message",
        "p": "uc",
        "t": 1552863481.1516943,
        "th": "CP Server Thread-16"
    },
    {
        "h": "mws1-v1",
        "l": 50,
        "mod": "sysapi",
        "msg": "test critical message",
        "p": "uc",
        "t": 1552863481.1631815,
        "th": "CP Server Thread-17"
    }
]

Parameters:

  • API Key API key with sysfunc=yes permissions

Optionally:

  • t get log records not older than t seconds
  • n the maximum number of log records you want to obtain
rotate log file

Deprecated, not required since 3.3.0

http

POST /r/core HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "log_rotate" }

curl

curl -i -X POST http://localhost:8812/r/core -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "log_rotate"}'

wget

wget -S -O- http://localhost:8812/r/core --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "log_rotate"}'

httpie

echo '{
  "method": "log_rotate"
}' | http POST http://localhost:8812/r/core Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/core', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'log_rotate'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with sysfunc=yes permissions
get API call log
  • API call with master permission returns all records requested
  • API call with other API key returns records for the specified key only
  • API call with an authentication token returns records for the current authorized user

http

GET /r/core@apilog HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/core@apilog -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/core@apilog --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/core@apilog X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/core@apilog', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "auth": "key",
        "func": "login",
        "gw": "http",
        "id": "a4ac6da7-2fa8-4938-8613-48e6495158b1",
        "ip": "127.0.0.1",
        "ki": "operator",
        "params": "{\"u\":\"ttt\",\"p\":\"<hidden>\"}",
        "status": "OK",
        "t": 1596055098.3651853,
        "tf": 1596055098.3837607,
        "u": "ttt",
        "utp": null
    },
    {
        "auth": "key",
        "func": "list_key_props",
        "gw": "http",
        "id": "35685960-cc2f-4fb6-8efc-c4ebca8bf9b5",
        "ip": "127.0.0.1",
        "ki": "masterkey",
        "params": "{\"i\":\"operator\"}",
        "status": "OK",
        "t": 1596055125.9569867,
        "tf": 1596055125.9690392,
        "u": null,
        "utp": null
    },
    {
        "auth": "key",
        "func": "action_toggle",
        "gw": "http",
        "id": "1bdc23da-95a1-4b41-b354-3f3c62e24405",
        "ip": "127.0.0.1",
        "ki": "masterkey",
        "params": "{\"i\":\"unit:light/hall\",\"p\":null,\"w\":null,\"q\":null,\"u\":null}",
        "status": "OK",
        "t": 1596055185.7343063,
        "tf": 1596055185.7551231,
        "u": null,
        "utp": null
    }
]

Parameters:

  • API Key any valid API key

Optionally:

  • s start time (timestamp or ISO or e.g. 1D for -1 day)
  • e end time (timestamp or ISO or e.g. 1D for -1 day)
  • n records limit
  • t time format (“iso” or “raw” for unix timestamp, default is “raw”)
  • f record filter (requires API key with master permission)

Returns:

List of API calls

Note: API call params are returned as string and can be invalid JSON data as they’re always truncated to 512 symbols in log database

Record filter should be specified either as string (k1=val1,k2=val2) or as a dict. Valid fields are:

  • gw: filter by API gateway
  • ip: filter by caller IP
  • auth: filter by authentication type
  • u: filter by user
  • utp: filter by user type
  • ki: filter by API key ID
  • func: filter by API function
  • params: filter by API call params (matches if field contains value)
  • status: filter by API call status
API keys
create API key

API keys are defined statically in etc/<controller>_apikeys.ini file as well as can be created with API and stored in user database.

Keys with master permission can not be created.

http

PUT /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "sysfunc": true, "allow": "cmd" }

curl

curl -i -X PUT http://localhost:8812/r/key/testkey2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"allow": "cmd", "save": true, "sysfunc": true}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/key/testkey2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"allow": "cmd", "save": true, "sysfunc": true}'

httpie

echo '{
  "allow": "cmd",
  "save": true,
  "sysfunc": true
}' | http PUT http://localhost:8812/r/key/testkey2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/key/testkey2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'allow': 'cmd', 'save': True, 'sysfunc': True})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "allow": [
        "cmd"
    ],
    "dynamic": true,
    "groups": [],
    "hosts_allow": [
        "0.0.0.0/0"
    ],
    "hosts_assign": [],
    "id": "testkey2",
    "items": [],
    "key": "443e342f7e49566fafc1cbe928878b0c18510bb2979ceca7aceb5e45b2b96280",
    "master": false,
    "pvt": [],
    "rpvt": [],
    "sysfunc": true
}

Parameters:

  • API Key API key with master permissions
  • save save configuration immediately

Returns:

JSON with serialized key object

delete API key

http

DELETE /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/key/testkey2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/key/testkey2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/key/testkey2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/key/testkey2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
list API key permissions

Lists API key permissons (including a key itself)

Note

API keys, defined in etc/<controller>_apikeys.ini file can not be managed with API.

http

GET /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/key/testkey2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/key/testkey2 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/key/testkey2 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/key/testkey2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "allow": [
        "cmd"
    ],
    "dynamic": true,
    "groups": [],
    "hosts_allow": [
        "0.0.0.0/0"
    ],
    "hosts_assign": [],
    "id": "testkey2",
    "items": [],
    "key": "443e342f7e49566fafc1cbe928878b0c18510bb2979ceca7aceb5e45b2b96280",
    "master": false,
    "pvt": [],
    "rpvt": [],
    "sysfunc": true
}

Parameters:

  • API Key API key with master permissions
  • save save configuration immediately
list API keys

http

GET /r/key HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/key -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/key --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/key X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/key', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "dynamic": false,
        "key_id": "masterkey",
        "master": true
    },
    {
        "allow": {
            "cmd": true,
            "device": true,
            "lock": false
        },
        "dynamic": true,
        "groups": [
            "#"
        ],
        "items": [],
        "key_id": "default",
        "master": false,
        "sysfunc": false
    },
    {
        "allow": {
            "cmd": true,
            "device": true,
            "lock": false
        },
        "dynamic": false,
        "groups": [
            "#"
        ],
        "items": [],
        "key_id": "lm",
        "master": false,
        "sysfunc": false
    },
    {
        "allow": {
            "cmd": false,
            "device": true,
            "lock": true
        },
        "dynamic": false,
        "groups": [
            "#"
        ],
        "items": [],
        "key_id": "operator",
        "master": false,
        "sysfunc": true
    },
    {
        "allow": {
            "cmd": false,
            "device": false,
            "lock": false
        },
        "dynamic": false,
        "groups": [
            "#"
        ],
        "items": [],
        "key_id": "sfa",
        "master": false,
        "sysfunc": false
    },
    {
        "allow": {
            "cmd": false,
            "device": false,
            "lock": false
        },
        "dynamic": true,
        "groups": [],
        "items": [
            "item1"
        ],
        "key_id": "t4",
        "master": false,
        "sysfunc": true
    },
    {
        "allow": {
            "cmd": false,
            "device": false,
            "lock": false
        },
        "dynamic": false,
        "groups": [],
        "items": [
            "sensor:sensors/sensor1"
        ],
        "key_id": "test",
        "master": false,
        "sysfunc": false
    },
    {
        "allow": {
            "cmd": false,
            "device": false,
            "lock": false
        },
        "dynamic": true,
        "groups": [],
        "items": [],
        "key_id": "testkey",
        "master": false,
        "sysfunc": true
    },
    {
        "allow": {
            "cmd": true,
            "device": false,
            "lock": false
        },
        "dynamic": true,
        "groups": [],
        "items": [],
        "key_id": "testkey2",
        "master": false,
        "sysfunc": true
    }
]

Parameters:

  • API Key API key with master permissions
regenerate API key

http

POST /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "regenerate" }

curl

curl -i -X POST http://localhost:8812/r/key/testkey2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "regenerate"}'

wget

wget -S -O- http://localhost:8812/r/key/testkey2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "regenerate"}'

httpie

echo '{
  "method": "regenerate"
}' | http POST http://localhost:8812/r/key/testkey2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/key/testkey2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'regenerate'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "key": "3dbcd3d24c6dc878cebe369eb9fdb95ae99fee14e99cdfd911b83629688d2854"
}

Parameters:

  • API Key API key with master permissions

Returns:

JSON dict with new key value in “key” field

set API key permissions

http

PATCH /r/key/testkey2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "save": true, "sysfunc": true }

curl

curl -i -X PATCH http://localhost:8812/r/key/testkey2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"save": true, "sysfunc": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/key/testkey2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"save": true, "sysfunc": true}'

httpie

echo '{
  "save": true,
  "sysfunc": true
}' | http PATCH http://localhost:8812/r/key/testkey2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/key/testkey2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'save': True, 'sysfunc': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • p property
  • v value (if none, permission will be revoked)
  • save save configuration immediately
User accounts
assign API key to user

http

PATCH /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "a": "masterkey" }

curl

curl -i -X PATCH http://localhost:8812/r/user/test2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"a": "masterkey"}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/user/test2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"a": "masterkey"}'

httpie

echo '{
  "a": "masterkey"
}' | http PATCH http://localhost:8812/r/user/test2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/user/test2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'a': 'masterkey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • a API key to assign (key id, not a key itself) or multiple keys, comma separated
create user account

Note

All changes to user accounts are instant, if the system works in read/only mode, set it to read/write before performing user management.

http

PUT /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "p": "verysecretpassword", "a": "testkey" }

curl

curl -i -X PUT http://localhost:8812/r/user/test2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"a": "testkey", "p": "verysecretpassword"}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/user/test2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"a": "testkey", "p": "verysecretpassword"}'

httpie

echo '{
  "a": "testkey",
  "p": "verysecretpassword"
}' | http PUT http://localhost:8812/r/user/test2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/user/test2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'a': 'testkey', 'p': 'verysecretpassword'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "key": "testkey",
    "user": "test2"
}

Parameters:

  • API Key API key with master permissions
  • p user password
  • a API key to assign (key id, not a key itself)
delete user account

http

DELETE /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/user/test2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/user/test2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/user/test2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/user/test2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get user account info

http

GET /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/user/test2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/user/test2 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/user/test2 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/user/test2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "key": "testkey",
    "user": "test2"
}

Parameters:

  • API Key API key with master permissions
list user accounts

http

GET /r/user HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/user -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/user --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/user X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/user', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "key_id": "test",
        "user": "divisor"
    },
    {
        "key_id": "testkey",
        "user": "test"
    },
    {
        "key_id": "testkey",
        "user": "test2"
    }
]

Parameters:

  • API Key API key with master permissions
set user password

Either master key and user login must be specified or a user must be logged in and a session token used

http

PATCH /r/user/test2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "p": "qwerty" }

curl

curl -i -X PATCH http://localhost:8812/r/user/test2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"p": "qwerty"}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/user/test2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"p": "qwerty"}'

httpie

echo '{
  "p": "qwerty"
}' | http PATCH http://localhost:8812/r/user/test2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/user/test2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'p': 'qwerty'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key master key or token
  • p new password
List active session tokens

Parameters:

  • API Key API key with master permissions
Drop session token(s)

Parameters:

  • API Key API key with master permissions
  • a session token or
  • u user name or
  • i API key id
Notifier management
disable notifier

Note

The notifier is disabled until controller restart. To disable notifier permanently, use notifier management CLI.

http

PATCH /r/notifier/eva_1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "enabled": false }

curl

curl -i -X PATCH http://localhost:8812/r/notifier/eva_1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"enabled": false}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/notifier/eva_1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"enabled": false}'

httpie

echo '{
  "enabled": false
}' | http PATCH http://localhost:8812/r/notifier/eva_1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/notifier/eva_1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'enabled': False})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
enable notifier

Note

The notifier is enabled until controller restart. To enable notifier permanently, use notifier management CLI.

http

PATCH /r/notifier/eva_1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "enabled": true }

curl

curl -i -X PATCH http://localhost:8812/r/notifier/eva_1 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"enabled": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/notifier/eva_1 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"enabled": true}'

httpie

echo '{
  "enabled": true
}' | http PATCH http://localhost:8812/r/notifier/eva_1 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/notifier/eva_1', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'enabled': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get notifier configuration

http

GET /r/notifier/eva_1 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/notifier/eva_1 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/notifier/eva_1 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/notifier/eva_1 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/notifier/eva_1', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "announce_interval": 5.0,
    "api_enabled": true,
    "enabled": false,
    "events": [
        {
            "groups": [
                "#"
            ],
            "subject": "state",
            "types": [
                "#"
            ]
        },
        {
            "level": 30,
            "subject": "log"
        }
    ],
    "host": "mws1-v1",
    "id": "eva_1",
    "password": "test",
    "qos": {
        "action": 2,
        "log": 2,
        "state": 2,
        "system": 2
    },
    "type": "mqtt",
    "username": "eva"
}

Parameters:

  • API Key API key with master permissions
list notifiers

http

GET /r/notifier HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/notifier -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/notifier --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/notifier X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/notifier', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "db": "db1.db",
        "enabled": true,
        "events": [
            {
                "groups": [
                    "#"
                ],
                "subject": "state",
                "types": [
                    "#"
                ]
            }
        ],
        "id": "db_1",
        "keep": 86400,
        "type": "db"
    },
    {
        "announce_interval": 5.0,
        "api_enabled": true,
        "enabled": false,
        "events": [
            {
                "groups": [
                    "#"
                ],
                "subject": "state",
                "types": [
                    "#"
                ]
            },
            {
                "level": 30,
                "subject": "log"
            }
        ],
        "host": "mws1-v1",
        "id": "eva_1",
        "password": "test",
        "qos": {
            "action": 2,
            "log": 2,
            "state": 2,
            "system": 2
        },
        "type": "mqtt",
        "username": "eva"
    }
]

Parameters:

  • API Key API key with master permissions
File management
put file to runtime folder

Puts a new file into runtime folder. If the file with such name exists, it will be overwritten. As all files in runtime are text, binary data can not be put.

http

PUT /r/runtime/xc/uc/test_action_script2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "m": "/bin/sh\n\nexit 0", "e": true }

curl

curl -i -X PUT http://localhost:8812/r/runtime/xc/uc/test_action_script2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"e": true, "m": "/bin/sh\n\nexit 0"}'

wget

wget -S -O- --method=PUT http://localhost:8812/r/runtime/xc/uc/test_action_script2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"e": true, "m": "/bin/sh\n\nexit 0"}'

httpie

echo '{
  "e": true,
  "m": "/bin/sh\n\nexit 0"
}' | http PUT http://localhost:8812/r/runtime/xc/uc/test_action_script2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.put('http://localhost:8812/r/runtime/xc/uc/test_action_script2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'e': True, 'm': '/bin/sh\n\nexit 0'})

response

HTTP/1.1 201 Created
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "id": "xc/uc/test_action_script2",
    "type": "runtime"
}

Parameters:

  • API Key API key with master permissions
  • m file content (plain text or base64-encoded)
  • b if True - put binary file (decode base64)
set file exec permission

http

PATCH /r/runtime/xc/uc/test_action_script2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "e": true, "e": true }

curl

curl -i -X PATCH http://localhost:8812/r/runtime/xc/uc/test_action_script2 -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"e": true}'

wget

wget -S -O- --method=PATCH http://localhost:8812/r/runtime/xc/uc/test_action_script2 --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --body-data='{"e": true}'

httpie

echo '{
  "e": true
}' | http PATCH http://localhost:8812/r/runtime/xc/uc/test_action_script2 Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.patch('http://localhost:8812/r/runtime/xc/uc/test_action_script2', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'e': True})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • e false for 0x644, true for 0x755 (executable)
delete file from runtime folder

http

DELETE /r/runtime/xc/uc/test_action_script2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i -X DELETE http://localhost:8812/r/runtime/xc/uc/test_action_script2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- --method=DELETE http://localhost:8812/r/runtime/xc/uc/test_action_script2 --header='X-Auth-Key: mykey'

httpie

http DELETE http://localhost:8812/r/runtime/xc/uc/test_action_script2 X-Auth-Key:mykey

python-requests

requests.delete('http://localhost:8812/r/runtime/xc/uc/test_action_script2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
get file contents from runtime folder

http

GET /r/runtime/xc/uc/test_action_script2 HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/runtime/xc/uc/test_action_script2 -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/runtime/xc/uc/test_action_script2 --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/runtime/xc/uc/test_action_script2 X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/runtime/xc/uc/test_action_script2', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

{
    "data": "/bin/sh\n\nexit 0",
    "e": true,
    "file": "xc/uc/test_action_script2"
}

Parameters:

  • API Key API key with master permissions
  • b if True - force getting binary file (base64-encode content)
Core scripts
List MQTT topics core scripts react on

http

GET /r/corescript/mqtt-topics HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey

curl

curl -i http://localhost:8812/r/corescript/mqtt-topics -H 'X-Auth-Key: mykey'

wget

wget -S -O- http://localhost:8812/r/corescript/mqtt-topics --header='X-Auth-Key: mykey'

httpie

http http://localhost:8812/r/corescript/mqtt-topics X-Auth-Key:mykey

python-requests

requests.get('http://localhost:8812/r/corescript/mqtt-topics', headers={'X-Auth-Key': 'mykey'})

response

HTTP/1.1 200 OK
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json
Expires: 0
Pragma: no-cache

[
    {
        "qos": 2,
        "topic": "eva_1:cluster/#"
    },
    {
        "qos": 2,
        "topic": "test/test2"
    },
    {
        "qos": 1,
        "topic": "ttt/ttt"
    }
]

Parameters:

  • API Key API key with master permissions
Reload core scripts if some was added or deleted

http

POST /r/corescript HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "reload" }

curl

curl -i -X POST http://localhost:8812/r/corescript -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "reload"}'

wget

wget -S -O- http://localhost:8812/r/corescript --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "reload"}'

httpie

echo '{
  "method": "reload"
}' | http POST http://localhost:8812/r/corescript Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/corescript', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'reload'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
Subscribe core scripts to MQTT topic

The method subscribes core scripts to topic of default MQTT notifier (eva_1). To specify another notifier, set topic as <notifer_id>:<topic>

http

POST /r/corescript HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "q": 2, "method": "mqtt-subscribe", "t": "some/test/topic2" }

curl

curl -i -X POST http://localhost:8812/r/corescript -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "mqtt-subscribe", "q": 2, "t": "some/test/topic2"}'

wget

wget -S -O- http://localhost:8812/r/corescript --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "mqtt-subscribe", "q": 2, "t": "some/test/topic2"}'

httpie

echo '{
  "method": "mqtt-subscribe",
  "q": 2,
  "t": "some/test/topic2"
}' | http POST http://localhost:8812/r/corescript Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/corescript', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'mqtt-subscribe', 'q': 2, 't': 'some/test/topic2'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • t MQTT topic (“+” and “#” masks are supported)
  • q MQTT topic QoS
  • save save core script config after modification
Unsubscribe core scripts from MQTT topic

http

POST /r/corescript HTTP/1.1
Host: localhost:8812
X-Auth-Key: mykey
Content-Type: application/json

{ "method": "mqtt-unsubscribe", "t": "some/test/topic2" }

curl

curl -i -X POST http://localhost:8812/r/corescript -H 'Content-Type: application/json' -H 'X-Auth-Key: mykey' --data-raw '{"method": "mqtt-unsubscribe", "t": "some/test/topic2"}'

wget

wget -S -O- http://localhost:8812/r/corescript --header='Content-Type: application/json' --header='X-Auth-Key: mykey' --post-data='{"method": "mqtt-unsubscribe", "t": "some/test/topic2"}'

httpie

echo '{
  "method": "mqtt-unsubscribe",
  "t": "some/test/topic2"
}' | http POST http://localhost:8812/r/corescript Content-Type:application/json X-Auth-Key:mykey

python-requests

requests.post('http://localhost:8812/r/corescript', headers={'Content-Type': 'application/json', 'X-Auth-Key': 'mykey'}, json={'method': 'mqtt-unsubscribe', 't': 'some/test/topic2'})

response

HTTP/1.1 204 No Content
Allow: DELETE, GET, HEAD, PATCH, POST, PUT
Cache-Control: no-cache, no-store, must-revalidate
Expires: 0
Pragma: no-cache

Parameters:

  • API Key API key with master permissions
  • t MQTT topic (“+” and “#” masks are allowed)
  • save save core script config after modification

Extending HOWTO

There are several different ways to extend EVA ICS functionality, each one is preferred for certain tasks.

Tips and tricks

  • put development = yes in [server] section of etc/<controller>.ini. This option automatically enables traceback logging and debug mode (don’t use on production!)
  • instead of e.g. eva uc server start, run eva uc server launch to output everything to the system console.
  • use debuggers and profilers. We use and recommend ipdb and ppTOP.
  • don’t be surprised that the system performance is much slower, when debug mode is enabled.
  • EVA ICS uses asyncio only for the internal code. All user scripts and extensions are executed in separate threads. So keep your code thread-safe.
  • Invent own bus connections only if there is no virtual bus provided.

I/O

Logic

Plug-ins

  • Core plug-ins - applications and function libraries that run inside EVA ICS. This is the most advanced way to extend EVA ICS functionality: plug-ins can implement all of the above plus much and much more.

Extensions as packages

See Packages

Core scripts

Note

Core scripts are generally unsafe, can crash the controller and should be written/used with care and only in cases, when there’s no alternative standard safe solution.

What are EVA ICS core scripts

  • Core scripts are Python 3 scripts, which run directly inside core of the controller and are launched on particular events.
  • Core scripts are similar to web server modules, where request and response data are processed by the chain of module libraries. In EVA ICS core script chains process events.
  • All core scripts are always executed on all events. Core scripts are executed by alphabetical order, one by one.
  • You may combine handling of the multiple events inside one core script file.
  • Code of the special file common.py is included in all core scripts.

What are core scripts for

Core scripts are not recommended for the enterprise-level configurations, it’s a vehicle to quickly implement:

  • data collection from HTTP/POST and MQTT, without drivers
  • simple automation tasks without Logic Manager
  • custom API methods and extensions of EVA ICS functionality.

Core script globals and functions

  • All API functions of current controller are directly available to call

  • print function is mapped to logging.info

  • spawn(func, *args, **kwargs) run function in background as a controller thread

  • logging, time, json (rapidjson) and eva.apikey modules are imported by default.

  • dir_eva EVA ICS directory

  • event event info name space

  • g special name space, shared across all core scripts

  • masterkey controller master key

  • product controller info name space:

    • product.code “uc”, “lm” or “sfa”
    • product.build current EVA ICS build
  • system_name system name

Core script events

A special core script globals name space event contains the event info core script was called for:

State event

Triggered when any item (unit, sensor or lvar) changes its state (status or value).

event.type == CS_EVENT_STATE
  • event.source source item object
  • event.data serialized item state (dict)
API event

Warning

API events are deprecated. Use CS_EVENT_RPC instead

Triggered when HTTP/POST request is performed on /r/cs/somepath.

event.type == CS_EVENT_API
  • event.topic relative API URI without method prefix (e.g. tests/test1 for /r/cs/tests/test1)
  • event.topic_p uri split by ‘/’ (list object)
  • event.data JSON payload data (fields “k”, “save”, “kind” and “method” are reserved and removed)
  • event.k current call API key

Note

Only HTTP/POST RESTful-like API calls are supported

RPC event

Replaces API events in EVA ICS 3.3.2 and above. Triggered when JSON RPC API method starting with “cs_” is called.

event.type == CS_EVENT_RPC
  • event.topic method name, without “cs_” prefix.
  • event.data params

E.g. the following JSON RPC API request:

{
    "jsonrpc": "2.0",
    "method": "cs_myfunc",
    "params":
        {
            "param1": "value1",
            "param2": "value2"
        }
}

will generate an event with event.topic=”myfunc” and event.data containing the params.

Core scripts can not return API responses. Also note that core scripts should handle any authentication by themselves.

Periodic event

Periodic events allow core scripts to act as scheduled jobs.

Currently periodic events are launched every minute only. However it is highly recommended to check the event topic to have corescripts backward-compatible with the future EVA ICS releases.

event.type == CS_EVENT_PERIODIC
  • event.topic “M” for every-minute event.
  • event.iteration iteration since controller start

Example:

if event.type == CS_EVENT_PERIODIC and event.topic == 'M':
    if event.iteration > 0 and not event.iteration % 10:
        print('another 10 minutes have passed')
MQTT event

Triggered when MQTT message is received and its topic matches subscribed.

To let core scripts react to MQTT events, they must be subscribed to MQTT topics, either with SYS API method subscribe_corescripts_mqtt or with “eva <controller> corescript mqtt-subscribe <topic>” console command (“+” and “#” MQTT masks are supported).

event.type == CS_EVENT_MQTT
  • event.topic MQTT topic
  • event.topic_p topic split by ‘/’ (list object)
  • event.data MQTT message data
  • event.qos MQTT message QoS
  • event.retain is MQTT topic retained (1) or regular (0)
System event

Triggered on system events

event.type == CS_EVENT_SYSTEM
  • event.topic event topic:
    • startup triggered after controller startup
    • shutdown triggered before controller shutdown

Note

‘shutdown’ event blocks controller shutdown process until all core scripts are completed. The script chain must finish in 30 seconds, otherwise the controller suicides itself and kills own process with SIGKILL signal.

Logging

Core script globals contain pre-defined “logger” variable, which points to eva.core logger object.

logger.warning('This is core script')

Creating and managing core script files

  • Core scripts are available for all controllers and stored in xc/{controller}/cs (e.g. xc/uc/cs for Universal Controller).
  • Core script files should have .py extension.
  • If core script code is modified, controller reloads it automatically. However if core script is added or deleted, it’s required to either exec reload_corescripts Common methods method (or eva <controller> corescript reload console command) or restart the controller.

Code examples

Core script code should be always started with “if”, checking event type:

# turn on the lights when motion sensor is triggered
if event.type == CS_EVENT_STATE and \
   event.source.oid == 'sensor:security/motion1' and \
   event.data['value'] == '1':
     action(k=masterkey, i='unit:light/hall', s=1)

Note

  • Item status/value can be obtained by accessing event.source.status and event.source.value fields as well. However it’s highly recommended to use event.data dict instead - it contains “fixed” state snapshot. Actual item state can be modified while core script is running.
  • In core scripts, item state value is always a string
# print API payload to logs
if event.type == CS_EVENT_API:
  print(event.topic)
  print(event.data)
# update sensor state according to MQTT JSON message { "temperature": N }
if event.type == CS_EVENT_MQTT and event.topic == 'some/device/telemetry':
  update(
   k=masterkey,
   i='sensor:env/temp1',
   s=1,
   v=json.loads(event.data)['temperature'])

Developing own PHI (Physical Interface) for EVA ICS. HOWTO

PHI (Physical interface) is a low level driver which communicates directly with an equipment. PHI should not contain any logic, its job is only to get/set an equipment to the state requested by LPI.

Required variables in a header

PHI info
  • __author__ module author
  • __copyright__ copyright
  • __license__ module license
  • __version__ module version
  • __description__ module description (keep it short)
PHI system info

the next fields are processed by controller, so make them exactly as required

  • __equipment__ supported equipment (list or string)
  • __api__ module API (integer number), current is 10
  • __required__ features required from LPI (Logical to Physical Interface, list):
  • aao_get get and process all ports at once (bulk)
  • aao_set set all ports at once (bulk)
  • action unit actions
  • events event processing
  • port_get get single port data
  • port_set set single port data
  • push accept state payload via push_phi_state API method
  • status process item status
  • value process item values
  • __mods_required__ required python modules (not included neither in standard Python install nor in EVA ICS)
  • __lpi_default__ if specified, the default driver will be created for this PHI when loaded.
  • __features__ own features provided (list, features from __required__ are automatically included):
  • aao_get PHI can return state of all ports at once but can work with a single ports as well
  • aao_set PHI can set state of all ports at once but can work with a single ports as well
  • universal PHI is universal and process cfg in requests.
  • cache PHI supports state caching (useful for slow devices)
  • __discover__ string or list, which describes how “discover” method (if implemented) will search for the equipment: net for network or EVA ICS bus name (modbus, owfs etc.)
  • __shared_namespaces__ list of shared namespaces used by PHI. If you are going to use shared namespaces, listing them in this variable is required, otherwise PHI will have no access to them.
PHI help

Each PHI module should contain 4 help variables:

  • __config__help__ module configuration help (on load)
  • __get_help__ additional configuration params possible for LPI to send with get command
  • __set_help__ additional configuration params possible for LPI to send with set command
  • __discover_help__ help for “discover” method

First variable should be human readable, others may copy, join or process the first one or each other in any way.

All variables should be in list format, containing dictionaries with the following context:

  • name property name
  • help property description (help)
  • type property type
  • required True if property is required, False if it’s optional
  • default default value (for required only)

Property type may be:

  • bool boolean (True/False)
  • str string
  • url string containing url
  • int integer
  • uint unsigned integer (greater or equal to 0)
  • hex hexadecimal number
  • bin binary number
  • float float number
  • ufloat unsigned float (greater or equal to 0)
  • any any type
  • list:type list of variables with type specified
  • enum:type:a,b,c list of the permitted specified type values

If the property accepts multiple types, they should be listed via or (|) symbol.

The last one variable is

  • __help__

It should contain the extended PHI description and operation manual. May be in any variable format and use restructured text directives for formatting.

Classes and modules

It’s allowed to import any Python system module or module installed by EVA ICS. If PHI requires installing more modules, they should be listed in PHI help file and in __mods_required__ variable.

Warning

All non-standard modules (not included neither in Python install nor in EVA ICS) should be imported with try/catch with importlib, their unavailability shouldn’t block loading PHI for informational puproses.

Importing modules eva.uc.drivers.tools, eva.tools, eva.traphandler, eva.uc.modbus, eva.uc.smbus and functions from eva.uc.driverapi:

  • get_version() get Driver API version
  • get_polldelay() get EVA poll delay
  • get_timeout() get default timeout
  • get_system_name() get system name
  • critical() send EVA critical call
  • log_traceback() log traceback debug info
  • lock(l, timeout, expires) acquire lock “eva:phi:l”, wait max timeout sec, lock automatically expires in expires sec. Timeout and expiration time can’t be longer than default controller timeout.
  • unlock(l) release lock “eva:phi:l
  • handle_phi_event(phi, port, data) ask Driver API to handle event (see below)

is highly welcome. Importing other EVA modules or Driver API functions is not recommended unless you really know what you do.

The main class is defined as:

from eva.uc.drivers.phi.generic_phi import PHI as GenericPHI
from eva.uc.driverapi import phi_constructor

class PHI(GenericPHI):
    #<your code>

Constructor

The constructor should set the above constants to class variables to let them be serialized by parent class if requested:

@phi_constructor
def __init__(self, **kwargs):
    # your code, e.g. parsing self.phi_cfg

Decorator @phi_constructor automatically invokes parent constructor and handles special init requests.

If the constructor faces a problem (e.g. parsing a config or checking equipment, e.g. local bus) it may set self.ready=False to abort controller loading the module.

If PHI methods get/set can’t work with single ports at all (e.g. equipment returns state of all ports at once only), constructor should set variables:

The parent constructor sets the variable self.phi_cfg to phi_cfg or to {}, so it’s safe to work with it with self.phi_cfg.get(cfgvar).

Primary methods

The following methods should be defined. cfg param may contain configuration params which should override the default ones for the current call.

# if PHI can read data from the equipment
def get(self, port=None, cfg=None, timeout=0):
    #<your code>
    #should return a single state value or a dict { 'port': value } (for
    # bulk or ssp/usp), port should always be a string
    #
    #should return None if failed, integer for status, string for values
    #
    #if PHI supports aao_get feature, it should return all port states when
    #no port is specified in request.
    #
    # for unit status, "value" should be integer. if unit PHI has "value"
    # feature, it should return either (status, value) tuple or a dict
    # {'port':(status,value}

# if PHI can write data to the equipment
def set(self, port=None, data=None, cfg=None, timeout=0):
    #<your code>
    #should return True (or result) if passed, False or None if failed
    #
    #If PHI supports aao_set feature, it should deal with a list of ports,
    #if no - with a single port only. If both port_set and aao_set are
    #specified in features, PHI should deal with both single port and list
    #of ports
    #
    #on bulk requests, both port and data are lists
    #
    #if unit PHI has "value" feature, the data contains either single or
    #multiple (status, value) tuples

Note

If unit action is called without value, PHI set method is called with previous known unit value

port and data may be integers, string, contain lists or be set as None. PHI should always be ready to any incoming params and handle the missing or incorrect by itself. If port contains a list, data always contain a list too.

cfg may contain equipment configuration options. If the driver is universal, it should handle them properly.

Warning

watch out for the timeout - if it’s expired, the controller may crash or be forcedly restarted. Always calculate the remaining time for the external calls and return error as soon as it comes closer to expiration.

Method test should perform a self-test (equipment test) if cmd==’self’, other methods are variable and may be used e.g. for debugging. If command is not understood by the method, it’s a rule of good taste to return a help text (dict { ‘command’: ‘command help’ }).

def test(self, cmd=None):
    #<your code>

Method exec may be implemented to perform some actions on the equipment, e.g. changing the equipment settings or manage the firmware. You can implement any commands in any form you wish using cmd and args params.

def exec(self, cmd=None, args=None):
    #<your code>

The method should be used for real commands only, all the tests (e.g. testing get method, obtaining equipment info for testing or informational purposes) should be implemented in test. After the command execution, the method should return OK on success or FAILED on failure. If command is not understood by the method, it’s a rule of good taste to return a help text (dict { ‘command’: ‘command help’ }).

The following methods may be used to call or register/unregister anything on driver load/unload:

def start(self):
    #<your code>

def stop(self):
    #<your code>

def unload(self):
    # called when PHI is unloaded from the controller
    #<your code>

Parent methods

Parent class provides the following useful functions:

  • self.set_cached_state(data) set driver cached state (any format)
  • self.get_cached_state() return the state cached before. If the cache is expired (self.cache param handled by parent), the method return None

Warning

If get_cached_state() method is used, PHI should return a copy of cached object

All the logging should be done with the following methods:

  • self.log_debug(msg)
  • self.log_info(msg)
  • self.log_warning(msg)
  • self.log_error(msg)
  • self.log_critical(msg)
  • self.critical(msg)

The last two methods do the same, logging an event and calling controller critical() method.

  • self.get_shared_namespace(namespace_id) returns namespace object, shared between all PHIs.

Optional methods

get_phi_ports

The method should be implemented if you want to let PHI to respond to API “get_phi_ports” method.

def get_ports(self):
    #<your code>

The method should return list of dictionaries with “port”, “name” and “description” fields. Are fields are required and should be strings.

If hardware equipment always has fixed amount of ports and they all are used for the same purpose (e.g. relay), you may use parent function generate_port_list:

def get_ports(self):
    return self.generate_port_list(
        port_max=16, description='relay port #{}')

# parent function has the following params:
# def generate_port_list(
#       port_min=1, port_max=1, name='port #{}', description='port #{}')
discover

The method should be implemented if you want let PHI to respond to API “phi_discover” method and should return all supported equipment discovered, including parameters for PHI loading.

“discover” method should be always implemented as static as it is always called on module, before PHI is loaded and primary class is created. If PHI implements discovery, __discover__ header should always be present in module.

__discover__ = 'net'

# ............

    @staticmethod
    def discover(interface=None, timeout=0):
        # interface - network or bus name, can be list or string
        #<your code>

The method should return array of dictionaries, which may contain any fields. Field !load is required and should contain dictionary with PHI loading params, e.g. { ‘host’: ‘<ip_of_hardware>’ }.

You may specify result column ordering for EVA ICS interfaces. For that, a special record:

[{ '!opt': 'cols', 'value': [<columns>]}]

must be present as first in a result. A special column ‘!load’ in a column list is not required.

Config validation

Optional method validate_config can be implemented to automatically validate module configuration.

class eva.x.GenericX
validate_config(config={}, config_type='config', ignore_private=False, **kwargs)

Validates module config

Does nothing by default. Can e.g. call self.validate_config_whi to validate config with module help info, validate config with JSON schema or do everything manually

Note: “driver_assign” always assigns the same parameters for “action” and “state” by default. Consider either ignoring config_type=’state’ validation or allow action parameters there.

Parameters:
  • config – config to validate (may be modified on-the-flow to convert variable types for extension config)
  • config_type – validation config type (‘config’, ‘state’, ‘action’ etc., matches help variable)
  • ignore_private – allow any private (starting with “_”) parameters as they’re usually passed as-is to lower level extension (e.g. LPI -> PHI)
  • kwargs – reserved for the future
Returns:

True if config is validated

Raises:

eva.exceptions.InvalidParameter – if config contains invalid params

validate_config_whi(config=None, config_type='config', allow_extra=False, ignore_private=False, xparams=[])

Validate config with module help info

Help info: module help info variable (e.g. __config_help__ for config)

Parameters:
  • config – config to validate
  • config_type – config type (help var to parse, default is ‘config’)
  • allow_extra – allow any extra params in config
  • xparams – list of allowed extra params
Returns:

True if config is validated. Config dict variables are automatically parsed and converted to the required types (except extra params if not listed)

Raises:

eva.exceptions.InvalidParameter – if configuration is invalid

Working with unit values

For units, method get can return either single integer (status) or a state tuple (status, value). If value is set to None, it is ignored and only status is updated. LPI automatically detects output data and parses either status or (status, value) pair.

For method set, by default data contains either status (integer) or a list of integers only. To accept extended state (status, value tuple or a list of tuples) for set, value string must be specified in __required__ header list variable.

Handling timeouts

Starting from DriverAPI v8, timeout handling can be easily performed with timeouter library (https://github.com/alttch/timeouter). The library is included into EVA ICS by default and can be imported by any PHI module.

When PHI is executed, timeouter library is already initialized for the running thread, and you may use its methods:

import timeouter as to
from eva.uc.driverapi import log_traceback

# .........

   def get(self, port=None, cfg=None, timeout=0):
      # Some call requires 3 seconds, abort if we will be out of time
      if not to.has(3): return None
      # does the same
      if to.get() < 3: return None
      try:
         # .... perform some calls
         # calculate timeout for external call:
         # e.g. you must specify timeout for some function, which will
         # perform 3 retries (4 total attempts) to get data from the
         # equipment:
         somefunc(retries=3, timeout=to.get(laps=4))

         # raises eva.exceptions.TimeoutException
         # if timeout has expired
         to.check()
      except:
         log_traceback()
         return None

Parameter timeout for get/set functions is filled for the backward compatibility.

Note

Allowed timeout is always slightly lower than specified in action_timeout/update_timeout, as some part of time is used to execute driver LPI code.

Handling events

Incoming events

If the equipment sends any event, PHI should ask Driver API to handle it. This can be done with method

eva.uc.driverapi.handle_phi_event(phi, port, data)

where:

  • phi = self
  • port = port, where the event has happened
  • data = port state values, as much as possible (dict {‘port’: state })

The controller will call update() method for all items using the caller PHI for updating, providing LPIs state data to let them process the event with minimized amount of additional PHI.get() calls.

Value -1 can be used to set unit error status, value False to set sensor error status.

State push

External applications can push state directly to PHI module. The module should handle state push by itself, calling handle_phi_event for each modified port if required.

Application calls push_phi_state method (see UC API doc), providing state payload, which should be parsed and processed by PHI module. The following method should be implemented:

class PHI(GenericPHI):

    # class code

  def push_state(self, payload):
     # process payload, return True if OK, False if failed
     return True

The method receives external state payload as-is. State payload can be in any format, acceptable by PHI.

SNMP traps

First you need to subscribe to EVA trap handler. Import eva.traphandler mod and modify PHI start and stop methods:

import eva.traphandler

class PHI(GenericPHI):

    # class code

    def start(self):
        #<your code>
        eva.traphandler.subscribe(self)

    def stop(self):
        #<your code>
        eva.traphandler.unsubscribe(self)

EVA trap handler calls method process_snmp_trap(data) for each object subscribed, so let’s create it inside a primary class:

def process_snmp_trap(self, host, data):
    #<your code>

host IP address of the host where SNMP trap is coming from.

data a dict with name/value pairs, where name is SNMP numeric OID without a first dot, and value is always a string. Check if this trap belongs to your device and perform the required actions. Don’t worry about the timeout (except for the actual reaction time on a trap event) because every method is being executed in its own thread.

EVA traphandler doesn’t care about the method return value and you must process all the errors by yourself.

Schedule updates

If the equipment doesn’t send any events, PHI can initiate updating the items by itself. To perform this, PHI should support aao_get feature and be loaded with update=N config param. Updates, intervals as well as the whole update process are handled by parent class.

Working with I2C/SMBus

It’s highly recommended to use internal UC locking for I2C bus. Then you can use any module available to work with I2C/SMBus. As there are a lot of modules with similar functions, you can choose it on your own. See the code example below:

# ...........
# we'll use smbus2 module in this example
__mods_required__ = ['smbus2']
# ...........
# import i2c locker module
import eva.uc.i2cbus

@phi_constructor
def __init__(self, **kwargs):
    # code
    try:
        self.smbus2 = importlib.import_module('smbus2')
    except:
        self.log_error('unable to load smbus2 python module')
        self.ready = False
        return

def get(self, port=None, cfg=None, timeout=0):
    if not eva.uc.i2cbus.lock(self.bus):
        self.log_error('unable to lock I2C bus')
        return None
    bus = self.smbus2.SMBus(self.bus)
    # perform some operations, then release the bus for other threads
    eva.i2cbus.release(self.bus)
    return result

All I2C/SMBus exceptions, timeouts and retries should be handled by the code of your PHI.

Working with Modbus

Working with Modbus is pretty easy. PHIs don’t need to care about the Modbus connection and data exchange at all, everything is managed by eva.uc.drivers.tools.modbus module. The module provides methods for reading all popular data types (booleans, 16-, 32- and 64-bit signed/unsigned integers and IEEE 754 floats).

Note

Direct import of eva.uc.modbus is deprecated since EVA ICS 3.3.2 (DriverAPI v10)

# everything you need is just import module
import eva.uc.drivers.tools.modbus as modbus
from eva.uc.driverapi import log_traceback

@phi_constructor
def __init__(self, **kwargs):
    # ....
    # it's recommended to force aao_get in Modbus PHI to let it read states
    # with one modbus request
    self.modbus_port_id = self.phi_cfg.get('port')
    # check in constructor if the specified modbus port is defined
    if not modbus.is_port(self.modbus_port_id):
        self.log_error('modbus port ID not specified or invalid')
        self.ready = False
        return
    # store unit id PHI is loaded for
    try:
        self.unit_id = int(self.phi_cfg.get('unit'))
    except:
        self.ready = False
        return

def get(self, port=None, cfg=None, timeout=0):
    try:
        modbus_port = modbus.get_port(self.modbus_port_id, timeout)
    except Exception as e:
        self.log_error(e)
        log_traceback()
        return None
    # The port object is a regular pymodbus object
    # (https://pymodbus.readthedocs.io) and supports all pymodbus functions.
    # All the functions are wrapped with EVA modbus module which handles
    # all errors and retry attempts. The ports PHI gets are always in the
    # connected state. The port methods can be used for bulk or complicated
    # requests

    # For single values of standard data types, modbus tool module is
    # recommended

    # read 16 coils, starting from 0
    try:
        coils = modbus.read_bool(modbus_port, 'c0', 16, unit=self.unit_id)
    except:
        return None
    finally:
        # Release modbus port as soon as possible to let other components
        # work with it while your PHI is processing the data
        modbus_port.release()

    # let's convert 16 booleans to 16 port states
    result = {}
    try:
        for i in range(16):
            result[str(i + 1)] = 1 if coils[i] else 0
    except:
        result = None
    return result

The variable client_type of the port object (modbus_port.client_type) holds the port type (tcp, udp, rtu, ascii or binary). This can be used to make PHI work with the equipment of the same type which uses e.g. different registers for different connection types.

Working with Ethernet/IP

The standard way to work with Ethernet/IP devices in EVA ICS is cpppo Python module. The module isn’t installed by default. Set EXTRA=”cpppo” in /opt/eva/etc/venv and rebuild EVA ICS venv (/opt/eva/install/build-venv).

Here is helper usage example:

# ........
from eva.uc.driverapi import log_traceback

class PHI(GenericPHI):

    def get(self, port=None, cfg=None, timeout=0):
        # do not import anything in the main module code as cpppo module
        # isn't included by default
        from eva.uc.drivers.tools.cpppo_enip import operate
        try:
            result, failures = operate(
                host=self.phi_cfg['host'],
                port=self.phi_cfg['port'],
                tags=[port])
            if failures:
                raise RuntimeError
            else:
                # the module example returns unit status (int)
                return int(result[0][0])
        except:
            log_traceback()
            return None

    def set(self, port=None, data=None, cfg=None, timeout=0):
        from eva.uc.drivers.tools.cpppo_enip import operate
        try:
            _, failures = operate(
                host=self.phi_cfg['host'],
                port=self.phi_cfg['port'],
                tags=[f'{port}={data}'])
            if failures:
                raise RuntimeError
            else:
                return True
        except:
            log_traceback()
            return False

The helper function arguments are similar to cpppo.server.enip.client command line arguments. Refer to function pydoc or CLI help for more details.

The above method is simple but it isn’t recommended for the high load environments, as “operate” functions creates new connector for each request. To reuse connections, it’s recommended to use SafeProxy class. Refer to eva.uc.drivers.tools.cpppo_enip pydoc for more info.

Working with Modbus slave memory space

Universal Controller can perform basic data processing as Modbus slave, custom PHI can do this more flexible. E.g. there’s temperature sensor, which reports its value multiplied by 100. As Modbus registers don’t support floats, custom PHI module can listen to the register and automatically divide value by 100 before sending update to UC item.

Multiple items and PHIs can watch the same register and perform data processing independently.

import eva.uc.modbus as modbus

@phi_constructor
def __init__(self, **kwargs):
# ....

def start(self):
    # watch changes of Modbus slave register
    # addr - value from 0 to 9999
    # self.process_modbus - function to process Modbus data
    # register - 'h' for holding (default), 'i' for input,
    #            'c' for coil and 'd' for discrete input
    modbus.register_handler(addr, self.process_modbus, register='h')

def stop(self):
    # don't forget to unregister handler when PHI is unloaded
    modbus.unregister_handler(addr, self.process_modbus, register='h')

def process_modbus(self, addr, values):
    # the function is called as soon as watched Modbus register is changed
    # parameters: addr - memory address, values - values written (list)
    #
    # values of holding and input registers are arrays of 2-byte integers
    # values of coils and discrete inputs - arrays of booleans (True/False)
    #
    # as input registers and discrete inputs are read-only for external
    # devices, they can be changed only by another local PHI module or UC
    # itself
    #
    _data = values[0]
    self.log_debug('got data: {} from {}'.format(_data, addr))
    # process the data
    # ...

PHI can also manipulate data in Modbus slave memory blocks manually, to do this use functions:

get_data(addr, register='h', count=1)
# and
set_data(addr, values, register='h')
# ("values" should be a list (of unsigned integers or booleans, depending
# on memory block type)

Working with 1-Wire via OWFS

As EVA ICS has virtual OWFS buses, you don’t need to initialize OWFS by yourself. Import eva.uc.drivers.tools.owfs module to get an access to all defined virtual OWFS buses.

Methods available:

  • owfs.is_bus(bus_id) returns True if bus is defined
  • bus = owfs.get_bus(bus_id) get bus. If locking is defined, the bus becomes exclusively locked.
  • bus.read(path, attr) read equipment attribute value
  • bus.write(path, attr, value) write equipment attribute value
  • bus.release() Release bus. As bus may be locked for others, the method should be always called immediately after the work with bus is finished.

Note

Direct import of eva.uc.owfs is deprecated since EVA ICS 3.3.2 (DriverAPI v10)

# everything you need is just import module
import eva.uc.drivers.tools.owfs as owfs
from eva.uc.driverapi import log_traceback

@phi_constructor
def __init__(self, **kwargs):
    # ....
    # it's recommended to force aao_get in Modbus PHI (list it in
    # __required__) to let it read states # with one modbus request
    self.owfs_bus = self.phi_cfg.get('owfs')
    # check in constructor if the specified modbus port is defined
    if not owfs.is_bus(self.owfs_bus):
        self.log_error('owfs bus ID not specified or invalid')
        self.ready = False
        return
    # store path of equipment PHI is loaded for
    self.path = self.phi_cfg.get('path')
    if not self.path:
        self.log_error('owfs path is not specified')
        self.ready = False
        return

def get(self, port=None, cfg=None, timeout=0):
    try:
        bus = owfs.get_bus(self.owfs_bus)
    except Exceptions as e:
        self.log_error(e)
        log_traceback()
        return None
    try:
        value = bus.read(path, 'temperature')
        if not value:
            raise Exception('can not obtain temperature value')
        return {'temperature': value}
    except:
        return None
    finally:
        bus.release()

Working with SNMP

Performing get/set calls

EVA ICS has bindings to primary pysnmp methods, which can be found in eva.uc.drivers.tools.snmp module. Pysnmp is a reach-feature SNMP module and is included in setup by default, however this module is not recommended to use on a slow hardware in production.

The rule of good taste is to check if alternative (faster) SNMP module is present (such as e.g. python3-netsnmp) and use it for a regular get/set functions instead:

import eva.uc.drivers.tools.snmp as snmp
try:
    import netsnmp
except:
    netsnmp = None

#....................................
#....................................
#....................................

if netsnmp:
    # ... use netsnmp module
else:
    # ... use default pysnmp module

Note

It is always better to perform a single getbulk request rather than using get/walk SNMP methods.

SNMP MIBs

As PHI is always written for the specific known equipment, there’s usually no need to use SNMP MIBs and dotted number SNMP OIDs are used instead.

If you plan to use SNMP MIBs, you should warn user to download them and place to the proper location or include MIB directly into PHI code to generate it on the flow.

Working with MQTT

The best way to work with MQTT is to use EVA ICS notification system connections. Instead of creating own MQTT connection and manage topics, let EVA core do its job. If your equipment and EVA ICS use different MQTT servers, just create new MQTT notifier to equipment server in EVA ICS without any subscriptions.

Note

If space is specified in EVA MQTT notifier, all topics should be relative, e.g. if space=test, MQTT can send and subscribe only to topics below the space level: equipment1/POWER will send/subscribe to test/equipment1/POWER.

Use eva.uc.drivers.tools.mqtt.MQTT class to deal with notifiers. If no notifier_id is specified eva_1 notifier is used.

Warning

MQTT custom handlers may be started in different threads. Don’t forget to use locking mechanisms if required.

Let’s deal with an equipment which has MQTT topic topic/POWER with values ON/OFF:

# everything you need is just import class
from eva.uc.drivers.tools.mqtt import MQTT
# and a function to handle events
from eva.uc.driverapi import handle_phi_event

@phi_constructor
def __init__(self, **kwargs):
# ....
self.topic = self.phi_cfg.get('t')
self.mqtt = MQTT(self.phi_cfg.get('n'))
self.current_status = { '1': None }
if self.topic is None or self.mqtt is None:
    self.ready = False

def get(self, port=None, cfg=None, timeout=0):
    # as we can not query equipment, return saved status instead
    return self.current_status


def set(self, port=None, data=None, cfg=None, timeout=0):
    # .... check data, prepare
    try:
        state = int(data)
    except:
        return False
    # then use MQTT.send function to send data to desired topic
    self.mqtt.send(self.topic + '/POWER', 'ON' if state else 'OFF')
    return True

def start(self):
    # register a custom handler for MQTT topic
    self.mqtt.register(self.topic + '/POWER', self.mqtt_handler)

def stop(self):
    # don't forget to unregister a custom handler when PHI is unloaded
    self.mqtt.unregister(self.topic + '/POWER', self.mqtt_handler)

def mqtt_state_handler(self, data, topic, qos, retain):
    # update current status
    self.current_status['1'] = 1 if data == 'ON' else 0
    # then handle PHI event
    handle_phi_event(self, 1, self.get())

Working with UDP API

You may use EVA UDP API to receive custom UDP packets and then parse them in PHI. This allows to create various hardware bridges e.g. from 315/433/866 MHz radio protocols, obtaining radio packets with custom programmed hardware appliance and then send them to EVA ICS to handle.

Custom packet format is (\x = hex):

\x01 HANDLER_ID \x01 DATA

DATA is always transmitted to handler in binary format. UDP API encryption, authentication and batch commands in custom packets are not supported (unless managed by handler).

Warning

UDP API custom handlers may be started in different threads. Don’t forget to use locking mechanisms if required.

import eva.udpapi as udp

@phi_constructor
def __init__(self, **kwargs):
# ....

def start(self):
    # subscribe to UDP API using PHI ID as handler ID
    udp.subscribe(__name__, self.udp_handler)

def stop(self):
    # don't forget to unsubscribe when PHI is unloaded
    udp.unsubscribe(__name__, self.udp_handler)

def udp_handler(self, data, address):
    _data = data.decode()
    self.log_debug('got data: {} from {}'.format(_data, address))
    # process the data
    # ...

Discovering SSDP hardware

If “discover” method is implemented and discovers hardware equipment via SSDP, driver tool can be used:

def discover(interface=None, timeout=0):
    import eva.uc.drivers.tools.ssdp as ssdp
    result = ssdp.discover(
        'upnp:all',
        interface=interface,
        timeout=timeout,
        discard_headers=[
            'Cache-control', 'Ext', 'Location', 'Host'
        ])
    # if upnp:all is used - filter result to leave only supported hardware

# eva.uc.drivers.tools.ssdp.discover function has the following params:
# def discover(st,
#             ip='239.255.255.250',
#             port=1900,
#             mx=True,
#             interface=None,
#             trailing_crlf=True,
#             parse_data=True,
#             discard_headers=['Cache-control', 'Host'],
#             timeout=None)
# where
#   mx                  send MX header or not
#   trailing_crlf       append trailing CR/LF at the end of request
#   parse_data          try parsing data automatically
#   discard_headers     discard specified headers if data is parsed

Shared namespaces

Some equipment modules or system libraries don’t allow to retake ownership on the particular device once it’s initialized until the process restart. As the result, phi reload and phi set (set command reloads PHI module with the new params) methods for such devices will not work.

There are tons of libraries and buses and we can not integrate everything in EVA ICS to provide native functions. For that, we offer you to use shared namespaces.

Shared namespace is a simple object, shared between all PHIs in system. Namespace ids you plan to use should be always listed in __shared_namespaces__ module header.

After, you can obtain shared namespace at any time, by calling self.get_shared_namespace(namespace_id).

Namespace object methods:

  • has(obj_id) returns True if namespace has specified object
  • set(obj_id, val) set namespace object to the specified value * get(obj_id, default=None) get namespace object, set it to default value if doesn’t exist.
  • locker threading.RLock() object which can be used to safely manipulate objects inside namespace.

Warning

Don’t manipulate thread-unsafe objects inside namespace without thread-locking.

Example:

__shared_namespaces__ = ['gpiozero']

# ......

ns = self.get_shared_namespace('gpiozero')
with ns.locker:
    d_id = 'port_'.format(port)
    if ns.has(d_id):
        gpio_device = ns.get(d_id)
    else:
        gpio_device = gpiozero.DigitalOutputDevice(port)
        ns.set(d_id, gpio_device)

Asynchronous I/O

Calls to PHIs are always synchronous. If equipment can set multiple ports at once or PHI can provide asynchronous features itself, it should have aao_get/aao_set in __features__ or __required__ lists.

The difference between last two is that __required__ requires parent LPI to have a feature for working with multiple ports at once and PHI get/set methods always get list of ports/data.

While __features__ allows LPI to send multi-port command, however it can be single as well. In this case get/set methods of PHI should manually check incoming data format (single value or list).

You, as PHI developer, always choose by yourself the way how to work with multiple hardware ports at once: get/set multiple registers or special “group” registers (e.g. for Modbus or SNMP), use asynchronous HTTP API calls or launch multiple threads. However, using aao_get/aao_set is always good practice and recommended if possible.

Exceptions

The methods of PHI should not raise any exceptions and handle/log all errors by themselves.

Testing

Use bin/test-phi command-line tool to perform PHI module tests. The tool requires test scenario file, which may contain the following functions:

  • debug() turn on debug mode (verbose output), equal to -D command-line option
  • nodebug() turn off debug mode
  • modbus(params) create virtual Modbus port with ID default
  • load(phi_mod, phi_cfg=None) load PHI module for tests. PHI cfg may be specified either as string or as dictionary
  • get(port=None, cfg=None, timeout=None) call PHI get function
  • set(port=None, data=None, cfg=None, timeout=None) call PHI set function
  • test(cmd=None) call PHI test function
  • exec(cmd=None, args=None) call PHI exec function
  • sleep(seconds) delay execution for a given number of seconds (alias for time.sleep)

additionally, each function automatically prints the result. Test scenario is actually a Python code and may contain any Python logic, additional module imports etc.

Example test scenario. Let’s test dae_ro16_modbus module:

debug()
modbus('tcp:192.168.55.11:502')
load('dae_ro16_modbus', 'port=default,unit=1')
if test('self') != 'OK': exit(1)
set(port=2,data=1)
set(port=5,data=1)
get()
set(port=2,data=0)

DriverAPI resources

import eva.uc.driverapi as da
eva.uc.driverapi.critical()

Ask the core to raise critical exception

eva.uc.driverapi.get_driver(driver_id)

Get driver module by id

eva.uc.driverapi.get_phi(phi_id)

Get PHI module by id

eva.uc.driverapi.get_polldelay()

Get UC poll delay

eva.uc.driverapi.get_sleep_step()

Get the default sleep step

eva.uc.driverapi.get_system_name()

Get EVA ICS node name

eva.uc.driverapi.get_timeout()

Get the default core timeout

eva.uc.driverapi.get_version()

Get DriverAPI version

eva.uc.driverapi.handle_phi_event(phi, port=None, data=None)

Ask the core to handle PHI event

Parameters:
  • phi – PHI module the event is from (usually =self)
  • port – the port, where the event is happened
  • data – { port: value } dict with the maximum of state ports available which may be changed because of the event
eva.uc.driverapi.lock(l, timeout=None, expires=None)

Acquire a core lock

Parameters:
  • l – lock ID/name
  • timeout – timeout to acquire the lock
  • expires – lock auto-expiration time
eva.uc.driverapi.log_traceback()

Ask the core to log traceback of the latest error

eva.uc.driverapi.lpi_constructor(f)

LPI constructor decorator

Automatically calls parent construction, handles “info_only” module loads

eva.uc.driverapi.phi_constructor(f)

PHI constructor decorator

Automatically calls parent construction, handles “info_only” module loads

eva.uc.driverapi.transform_value(value, multiply=None, divide=None, round_to=None)

Generic value transformer

Parameters:
  • multiply – multiply the value on
  • divide – divide the value on
  • round_to – round the value to X digits after comma
eva.uc.driverapi.unlock(l)

Release a core lock

Parameters:l – lock ID/name

Macro extensions

As macros are written in Python, you can use any Python module to extend your macros. Additionally Logic Manager has ability to extend macros with extensions.

Modules are more flexible and are a standard Python way to extend your software. However macro extensions are more simple, standardized and easy to configure. As the goal is to keep macro code as simple as possible, macro extensions are the best choice in many cases.

Loading macro extension

Macro extensions are stored in xc/extensions folder. To list available macro extension modules, use command:

eva lm ext mods

Next command returns extension info:

eva lm ext modinfo <ext_module>

To get information about extension configuration and functions provided, use commands:

eva lm ext modhelp <ext_module> cfg
eva lm ext modhelp <ext_module> functions

To load/unload macro extension, use command:

# load
eva lm ext load [-c CONFIG] [-y] <ext_id> <ext_module>
# unload
eva lm ext unload <ext_id>

where:

  • -c CONFIG extension configuration options, comma separated
  • -y save extension config after successful load

Extension functions

When extension is loaded, its functions become available in all macros automatically with names <ext_id>_<function>.

E.g. when extension audio is loaded with ID a1, its function play is available as a1_play. This allows you to load one extension multiple times and have different functionality according to specified configuration without need to configure module/class params in macros.

If you want to make a short alias for extension function, use alias (e.g. in xc/lm/common.py):

alias('play', 'a1_play')

Unlike play=a1_play alias doesn’t throw an exception and let macros work even if extension is failed to load or its functions are not available.

Included extensions

The following extensions are included in EVA ICS distribution by default:

Developing your own extension

Create new Python file in xc/extensions folder.

Required variables in a header
  • __author__ module author
  • __copyright__ copyright
  • __license__ module license
  • __version__ module version
  • __description__ module description (keep it short)
  • __api__ module API (integer number), current is 7
  • __mods_required__ required python modules (included neither in standard Python install nor in EVA ICS)
  • __config__help__ module configuration help (on load)
  • __functions__ exported functions
  • __help__ should contain the extended description and operation manual. May be in any variable format and use restructured text directives for formatting.
Configuration variable

Configuration variable (__config_help__) should be in list format, containing dictionaries with the following context:

  • name property name
  • help property description (help)
  • type property type
  • required True if property is required, False if it’s optional
  • default default value (for required only)

Property type may be:

  • bool boolean (True/False)
  • str string
  • url string containing url
  • int integer
  • uint unsigned integer (greater or equal to 0)
  • hex hexadecimal number
  • bin binary number
  • float float number
  • ufloat unsigned float (greater or equal to 0)
  • list:type list of variables with type specified
  • enum:type:a,b,c list of permitted specified type values

If a property accepts multiple types, they should be listed via or (|) symbol.

Exported functions

Exported functions (__functions__) variable is a dictionary in format:

{ 'function(params)': 'description' }
# e.g.
{
    'func1(param1, param2=0, param3=True)': 'This function does something',
    'func2(param1=0)': 'This function does something else'
}

All exported functions should be defined in a primary extension class.

Classes and modules

It’s allowed to import any Python system module or module installed by EVA ICS. If extension requires installing more modules, they should be listed in extension help and in __mods_required__ variable.

Warning

All non-standard modules (not included neither in Python install nor in EVA ICS) should be imported with try/catch with importlib, their unavailability shouldn’t block loading extension for informational purposes.

Importing EVA modules and functions from eva.lm.extapi:

  • get_version() get Extension API version
  • get_polldelay() get EVA poll delay
  • get_timeout() get default timeout
  • critical() send EVA critical call
  • log_traceback() log traceback debug info

is highly welcome.

The main class is defined as:

from eva.lm.extensions.generic import LMExt as GenericExt
from eva.lm.extapi import ext_constructor

class LMExt(GenericExt):
    #<your code>
Constructor

The constructor should set the above constants to class variables to let them be serialized by parent class if requested:

@ext_constructor
def __init__(self, **kwargs):
    # your code, e.g. parsing self.cfg

Decorator @ext_constructor automatically invokes parent constructor and handles special init requests.

If the constructor faces a problem (i.e. parsing a config or checking required modules) it may set self.ready=False to abort controller loading the extension.

Persistent data

Special dict variable self.data is used to keep extension persistent data. This data is automatically saved on controller stop or when save API / CLI command is called and automatically loaded on controller start.

Requirements:

  • self.data should always be a dict
  • dict keys, as well as keys of the sub-dicts must be strings
  • data is stored in JSON format, so should contain only numbers, strings and booleans, lists and dicts
  • it’s highly recommended to use self.data_lock before accessing self.data
  • to tell controller that data is modified and should be saved, set self.data_modified to True

Code example:

# read data
with self.data_lock:
   value = data.get('key')

# write data
with self.data_lock:
   data['key'] = 'value'
   self.data_modified = True

Warning

When extesion is unloaded, its data file is deleted

Exceptions

There’s no standard way to handle exceptions, however if any of exported functions raise them, this should be specified in extension help and readme file.

Config validation

Optional method validate_config can be implemented to automatically validate module configuration.

class eva.x.GenericX
validate_config(config={}, config_type='config', ignore_private=False, **kwargs)

Validates module config

Does nothing by default. Can e.g. call self.validate_config_whi to validate config with module help info, validate config with JSON schema or do everything manually

Note: “driver_assign” always assigns the same parameters for “action” and “state” by default. Consider either ignoring config_type=’state’ validation or allow action parameters there.

Parameters:
  • config – config to validate (may be modified on-the-flow to convert variable types for extension config)
  • config_type – validation config type (‘config’, ‘state’, ‘action’ etc., matches help variable)
  • ignore_private – allow any private (starting with “_”) parameters as they’re usually passed as-is to lower level extension (e.g. LPI -> PHI)
  • kwargs – reserved for the future
Returns:

True if config is validated

Raises:

eva.exceptions.InvalidParameter – if config contains invalid params

validate_config_whi(config=None, config_type='config', allow_extra=False, ignore_private=False, xparams=[])

Validate config with module help info

Help info: module help info variable (e.g. __config_help__ for config)

Parameters:
  • config – config to validate
  • config_type – config type (help var to parse, default is ‘config’)
  • allow_extra – allow any extra params in config
  • xparams – list of allowed extra params
Returns:

True if config is validated. Config dict variables are automatically parsed and converted to the required types (except extra params if not listed)

Raises:

eva.exceptions.InvalidParameter – if configuration is invalid

Testing

Use bin/test-ext command-line tool to perform PHI module tests. The tool requires test Python file, which loads extension as _ and contains all its functions (e.g. __test for extension.test):

print('Testing extension')
__test(params)
__func2(params)
__func3(params)
print('Test completed')

Core plug-ins

Developing core plug-ins is the most advanced way to extend EVA ICS functionality. You can create own API methods, functions for Logic macros and SFA Templates plus much and much more.

Guide by example

Note

All plugin objects and custom API functions are always registered as x_{plugin}_{name}

"""
EVA ICS plugin example

To load the plugin, put its name to controller config, section [server]

e.g. edit etc/uc.ini:

...........................................
[server]
plugins = my ; plugin list, comma separated
...........................................

Plugins can be one-file, in this case they can be just put into plugins
(/opt/eva/plugins) directory and named e.g. "my.py".

If your plugin is more complex or you want to redistribute it e.g. via PyPi -
create Python module called "evacontrib.<yourpluginname>" and install it either
globally or in EVA ICS venv.

Plugin configuration

Put a section [plugin.<pluginname>] in controller config, e.g. for this plugin:

......
[plugin.my]
var1 = value1
var2 = value2
......
"""

# plugin header, required
__author__ = 'Altertech, https://www.altertech.com/'
__copyright__ = 'Copyright (C) 2012-2021 Altertech'
__license__ = 'Apache License 2.0'
__version__ = "3.3.2"

# import EVA ICS Plugin API library
import eva.pluginapi as pa
"""
"flags" namespace can be defined, EVA ICS uses this namespace to determine
plugin status:

flags.ready = True # means plugin is correctly initialized and works properly
"""
from types import SimpleNamespace
flags = SimpleNamespace(ready=False)

# init plugin logger
logger = pa.get_logger()


def init(config, **kwargs):
    """
    Called by EVA ICS core when the initial configuration is loaded. All
    methods are optional, if the method doesn't exist in plugin, no exception
    is raised

    All methods should have **kwargs in argument list to accept extra arguments
    from future Plugin API versions

    Args:
        config: plugin configuration (comes as key/value dict)
    """
    # require Plugin API version 1+
    pa.check_version(1)
    # this feature is only for LM PLC
    try:
        pa.check_product('lm')
        # register new lmacro function "mytest"
        pa.register_lmacro_object('mytest', mytest)
        # register lmacro object "weekend"
        pa.register_lmacro_object('weekend', weekend)
    except:
        pass
    # this feature is only for SFA
    try:
        pa.check_product('sfa')
        # register SFA Templates function "weekend_days"
        pa.register_sfatpl_object('weekend_days', get_weekend)
    except:
        pass
    """
    register API extension blueprint

    currently only JSON RPC and direct API calling methods can be registered
    """
    pa.register_apix(MyAPIFuncs(), sys_api=False)
    flags.ready = True


def before_start(**kwargs):
    """
    Called right before controller start
    """
    logger.info('plugin my before start called')


def start(**kwargs):
    """
    Called after controller start
    """
    logger.info('plugin my start called')


def before_stop(**kwargs):
    """
    Called right before controller stop
    """
    logger.info('plugin my before stop called')


def stop(**kwargs):
    """
    Called after controller stop
    """
    logger.info('plugin my stop called')


def dump(**kwargs):
    """
    Called after controller stop
    """
    return 'something'


def handle_state_event(source, data, **kwargs):
    """
    Called when any state event is received

    Args:
        source: event source item (object)
        data: serialized item state dict
    """
    logger.info(f'event from {source.oid}')
    logger.info(data)


# custom plugin code

weekend = ['Sat', 'Sun']


# the function we registered for SFA TPL
def get_weekend():
    return ','.join(weekend)


# the function we registered for LM PLC macros
def mytest():
    logger.info('something')


# APIX blueprint to implement new API functions
class MyAPIFuncs(pa.APIX):

    # log API call as DEBUG
    @pa.api_log_d
    # require master key
    @pa.api_need_master
    def my_square(self, **kwargs):
        # parse incoming params
        x = pa.parse_api_params(kwargs, 'x', 'N')
        if x < 0:
            raise pa.InvalidParameter('x < 0')
        # return some result
        # if API method produces no result, it SHOULD return True
        return {
            'result': x * x,
            'you': pa.get_aci('key_id'),
            'me': [pa.get_directory('eva'),
                   pa.get_product().build]
        }

    # log API call as INFO
    @pa.api_log_i
    # require master key
    @pa.api_need_master
    def my_test(self, **kwargs):
        # let's return the result of test_phi API function
        return pa.api_call('test_phi', i='ct1', c='self')

Resources

class eva.pluginapi.APIX

API blueprint extension class

exception eva.pluginapi.AccessDenied(msg='', kb=None)

raised when call has no access to the resource

__str__()

Return str(self).

exception eva.pluginapi.FunctionFailed(msg='', kb=None)

raised with function failed with any reason

__str__()

Return str(self).

exception eva.pluginapi.InvalidParameter
__str__()

Return str(self).

__weakref__

list of weak references to the object (if defined)

class eva.pluginapi.MQTT(notifier_id)

MQTT helper class

Parameters:notifier_id – MQTT notifier to use (default: eva_1)
__init__(notifier_id)
Parameters:notifier_id – MQTT notifier to use (default: eva_1)
__weakref__

list of weak references to the object (if defined)

register(topic, func, qos=1)

Register MQTT topic handler

send(topic, data, retain=None, qos=1)

Send MQTT message

unregister(topic, func)

Unregister MQTT topic handler

exception eva.pluginapi.MethodNotFound

raised when requested method is not found

__str__()

Return str(self).

__weakref__

list of weak references to the object (if defined)

exception eva.pluginapi.MethodNotImplemented(msg='', kb=None)

raised when requested method exists but requested functionality is not implemented

__str__()

Return str(self).

exception eva.pluginapi.ResourceAlreadyExists(msg='', kb=None)

raised when requested resource already exists

__str__()

Return str(self).

exception eva.pluginapi.ResourceBusy(msg='', kb=None)

raised when requested resource is busy (e.g. can’t be changed)

__str__()

Return str(self).

exception eva.pluginapi.ResourceNotFound(msg='', kb=None)

raised when requested resource is not found

__str__()

Return str(self).

exception eva.pluginapi.TimeoutException(msg='', kb=None)

raised when call is timed out

eva.pluginapi.api_call(method, key_id=None, **kwargs)

Call controller API method

Parameters:
  • key_id – API key ID. If key_id is None, masterkey is used
  • other – passed to API method as-is
Returns:

API function result

Raises:

eva.exceptions

eva.pluginapi.api_log_d(f)

API method decorator to log API call as DEBUG

eva.pluginapi.api_log_i(f)

API method decorator to log API call as INFO

eva.pluginapi.api_log_w(f)

API method decorator to log API call as WARNING

eva.pluginapi.api_need_cmd(f)

API method decorator to pass if API key has “cmd” allowed

eva.pluginapi.api_need_file_management(f)

API method decorator to pass if file management is allowed in server config

eva.pluginapi.api_need_lock(f)

API method decorator to pass if API key has “lock” allowed

eva.pluginapi.api_need_master(f)

API method decorator to pass if API key is masterkey

eva.pluginapi.api_need_rpvt(f)

API method decorator to pass if rpvt is allowed in server config

eva.pluginapi.api_need_sysfunc(f)

API method decorator to pass if API key has “sysfunc” allowed

eva.pluginapi.check_product(code)

Check controller type

Parameters:code – required controller type (uc, lm or sfa)
Raises:RuntimeError – if current controller type is wrong
eva.pluginapi.check_version(min_version)

Check plugin API version

Parameters:min_version – min Plugin API version required
Raises:RuntimeError – if Plugin API version is too old
eva.pluginapi.clear_thread_local(var, mod=None)

Check if thread-local variable exists

Parameters:
  • var – variable name
  • mod – self module name (optional)
Returns:

True if exists

eva.pluginapi.create_db_engine(db_uri, timeout=None)

Create SQLAlchemy database Engine

  • database timeout is set to core timeout, if not specified
  • database pool size is auto-configured
  • for all engines, except SQLite, “READ UNCOMMITED” isolation level is used
eva.pluginapi.critical()

Send critical event

eva.pluginapi.format_db_uri(db_uri)

Formats short database URL to SQLAlchemy URI

  • if no DB engine specified, SQLite is used
  • if relative SQLite db path is used, it’s created under EVA dir
eva.pluginapi.get_aci(field, default=None)

get API call info field

Parameters:
  • field – ACI field
  • default – default value if ACI field isn’t set
Returns:

None if ACI field isn’t set

eva.pluginapi.get_db()

get SQLAlchemy connection to primary DB

eva.pluginapi.get_directory(tp)

Get path to EVA ICS directory

Parameters:tp – directory type: eva, runtime, ui, pvt or xc
Raises:LookupError – if directory type is invalid
eva.pluginapi.get_item(i)

Get controller item

Parameters:i – item oid
Returns:None if item is not found
eva.pluginapi.get_logger(mod=None)

Get plugin logger

Parameters:mod – self module name (optional)
Returns:logger object
eva.pluginapi.get_masterkey()

get master API key

Returns:master API key
eva.pluginapi.get_plugin_db(db, mod=None)

Get plugin custom database SQLAlchemy connection

The connection object is stored as thread-local and re-used if possible

Parameters:db – SQLAlchemy DB engine
eva.pluginapi.get_polldelay()

Get core poll delay

eva.pluginapi.get_product()

Get product object

Returns:namespace(name, code, build)
eva.pluginapi.get_sleep_step()

Get core sleep step

eva.pluginapi.get_system_name()

Get system name (host name)

eva.pluginapi.get_thread_local(var, default=None, mod=None)

Get thread-local variable

Parameters:
  • var – variable name
  • default – default, if doesn’t exists
  • mod – self module name (optional)
Returns:

variable value or None if variable isn’t set

eva.pluginapi.get_timeout()

Get default timeout

eva.pluginapi.get_userdb()

get SQLAlchemy connection to user DB

eva.pluginapi.get_version()

Get Plugin API version

eva.pluginapi.has_thread_local(var, mod=None)

Check if thread-local variable exists

Parameters:
  • var – variable name
  • mod – self module name (optional)
Returns:

True if exists

eva.pluginapi.key_by_id(key_id)

get API key by API key ID

Returns:API key
eva.pluginapi.key_check(*args, ro_op=False, **kwargs)

check API key access

Arguments are ACL which can be combined

Parameters:
  • k – API key, required
  • items – item objects
  • oid – OID (mqtt-style masks allowed)
  • allow – check allows
  • pvt_file – access to pvt resource
  • pvt_file – access to rpvt resource
  • ip – caller IP
  • master – is master access required
  • sysfunc – is sysfunc required
  • ro_op – is item operation read-only
eva.pluginapi.key_check_master(*args, ro_op=False, **kwargs)

check master API key access

Parameters:
  • k – API key, required
  • ro_op – is item operation read-only
eva.pluginapi.key_id(k)

get key ID by API key

Returns:API key ID
eva.pluginapi.log_traceback()

Log traceback

eva.pluginapi.parse_api_params(params, names='', types='', defaults=None)

calls parse_function_params but omits API key

eva.pluginapi.parse_function_params(params, names, types='', defaults=None, e=<class 'eva.tools.InvalidParameter'>, ignore_extra=False)
Parameters:
  • names – parameter names (list or string if short) S: equal to ‘save’ Y: equal to ‘full’ J: equal to ‘_j’ F: equal to ‘force’
  • values – parameter values R: required, any not null and non-empty string r: required, but empty strings are possible s: required, should be string S: required, should be non-empty string b: boolean (or 0/1 or boolean-like strings) B: boolean (or 0/1 or boolean-like strings), required i: integer, can be None f or n: float(number), can be None I: integer, required F or N: float(number), required D: dict, required T: tuple, required X: set, required L: list, required . (dot): optional o: oid, can be null O: OID required
  • params – dict
  • defaults – dict (name/value)
  • e – exception to raise
class eva.pluginapi.partial

partial(func, *args, **keywords) - new function with partial application of the given arguments and keywords.

__call__(*args, **kwargs)

Call self as a function.

__delattr__(name, /)

Implement delattr(self, name).

__getattribute__(name, /)

Return getattr(self, name).

__new__(**kwargs)

Create and return a new object. See help(type) for accurate signature.

__reduce__()

Helper for pickle.

__repr__()

Return repr(self).

__setattr__(name, value, /)

Implement setattr(self, name, value).

args

tuple of arguments to future partial calls

func

function object to use in future partial calls

keywords

dictionary of keyword arguments to future partial calls

eva.pluginapi.register_apix(o, sys_api=False, mod=None)

Register API extension (APIX) object

All object methods (except internal and private) are automatically exposed as API functions

Functions are registered as x_{plugin}_{fn}

Parameters:
  • o – APIX object
  • sys_api – if True, object functions are registered as SYS API
  • mod – self module name (optional)
eva.pluginapi.register_lmacro_object(n, o, mod=None)

Register custom object for LM PLC macros

Object is registered as x_{plugin}_{n}

Parameters:
  • n – object name
  • o – object itself
  • mod – self module name (optional)
eva.pluginapi.register_sfatpl_object(n, o, mod=None)

Register custom object for SFA Templates

Object is registered as x_{plugin}_{n}

Parameters:
  • n – object name
  • o – object itself
  • mod – self module name (optional)
eva.pluginapi.sendmail(subject=None, text=None, rcp=None)

send email message

The function uses [mailer] section of the LM PLC configuration to get sender address and list of the recipients (if not specified).

Optional:
subject: email subject text: email text rcp: recipient or array of the recipients
Raises:FunctionFailed – mail is not sent
eva.pluginapi.set_aci(field, value)

set API call info field

Parameters:
  • field – ACI field
  • value – field value
Returns:

True if value is set, False for error (e.g. ACI isn’t initialized)

eva.pluginapi.set_thread_local(var, value=None, mod=None)

Set thread-local variable

Parameters:
  • var – variable name
  • value – value to set
  • mod – self module name (optional)
eva.pluginapi.snmp_get(oid, host, port=161, community='public', timeout=0, retries=0, rf=<class 'str'>, snmp_ver=2, walk=False)
Parameters:
  • oid – SNMP OID or MIB name
  • host – target host
  • port – target port (default: 161)
  • community – SNMP community (default: public)
  • timeout – max SNMP timeout
  • retries – max retry count (default: 0)
  • rf – return format: str, float, int or None
  • snmp_ver – SNMP version (default: 2)
  • walk – if True, SNMP walk will be performed
Returns:

If rf is set to None, raw pysnmp object is returned, otherwise parsed to float, int or str

If walk is requested, list of pysnmp objects is returned

eva.pluginapi.snmp_set(oid, value, host, port=161, community='private', timeout=0, retries=0, snmp_ver=2)
Parameters:
  • oid – SNMP OID or MIB name
  • value – value to set
  • host – target host
  • port – target port (default: 161)
  • community – SNMP community (default: public)
  • timeout – max SNMP timeout
  • retries – max retry count (default: 0)
  • snmp_ver – SNMP version (default: 2)
Returns:

True if value is set, False if not

eva.pluginapi.spawn(f, *args, **kwargs)

Run function as a thread in EVA ICS thread pool

Parameters:
  • f – callable
  • args/kwargs – passed to function as-is
Returns:

concurrent.futures Future object

eva.pluginapi.upnp_discover(st, ip='239.255.255.250', port=1900, mx=True, interface=None, trailing_crlf=True, parse_data=True, discard_headers=['Cache-control', 'Host'], timeout=None)

discover uPnP equipment

Parameters:
  • st – service type
  • ip – multicast ip
  • port – multicast port
  • mx – use MX header (=timeout)
  • interface – network interface (None - scan all)
  • trailing_crlf – put trailing CRLF at the end of msg
  • parse_data – if False, raw data will be returned
  • discard_headers – headers to discard (if parse_data is True)
  • timeout – socket timeout (for a single interface)
Returns:

list of dicts, where IP=equipment IP, otherwise dict, where key=equipment IP addr, value=raw ssdp reply. Note: if data is parsed, all variables are converted to lowercase and capitalized.

Return type:

if data is parsed

Packages

Custom extensions and other data can be packed into packages.

Package format

EVA ICS packages have very simple format:

  • The package should be tar or tgz archive, which is extracted to EVA_DIR as-is
  • The package MUST contain the file, called setup.py
  • The package SHOULD have the suffix .evapkg

Setting up packages

Packages can be installed either via install_pkg API method of any controller or with IaC deployment (in this case, only Universal Controller or Logic Manager packages can be installed, or the controller should have corresponding writing permissions to install e.g. UI files).

Setup file format

The Setup file should be called “setup.py” and is launched as EVA ICS corescript (so it has the access to all core script methods). The script is launched with the event:

event.type == CS_EVENT_PKG_INSTALL

The variable event.data contains package setup params, specified in the API call option “o”.

The script also has the special method extract_package. When called, this method extracts contents of the uploaded package to EVA ICS directory.

Note

Setup script has no access to the package files, except calling extraction method. The package is uploaded to controller’s memory and there is no temporary file written.

Here is a very simple example of the package setup script:

if event.type == CS_EVENT_PKG_INSTALL:
    logger.warning(f'installing package with options: {event.data}')
    extract_package()

The package setup script SHOULD check event type, as it can be launched with other core script events later (functionality is reserved for the further EVA ICS versions).

Keeping setup core script after install

Sometimes it is useful to keep setup core script code after the package installation is completed. To do that, the function “keep_me()” can be used:

# ... perform setup tasks
keep_me()

When called, the new core script is created from the setup corescript code, for the controller the package is installed on. This can be useful if the package requires performing additional tasks, e.g. starts / stops some service at the controller startup / shutdown.

Installing additional Python modules

The function “pip_install” allows installing additional Python modules, calling “pip install” command from EVA ICS venv. Note that modules will not be kept if EVA ICS venv is rebuilt from scratch later.

# ... perform setup tasks
pip_install('flask')

Manipulating with configuration files

The setup core script automatically has configuration helpers in globals. These helpers are already in globals and should not be imported manually.

class ConfigFile(fname, init_if_missing=False, backup=True)

A helper to manage .ini files

Example

with ConfigFile(‘uc.ini’) as cf:
cf.set(‘plugin.my’, ‘field1’, ‘value1’)
add_section(section, values)

Add section with dict of values

append(section, name, value)

Append value to array field (in .ini configs, arrays are string fields with values, separated with commas)

delete(section, name)

Delete field from section

get_section(section)

Get dict of section values

is_changed()

Returns True, if configuration file was changed and will be saved after the statement exit

remove(section, name, value)

Remove value from array field

remove_section(section)

Remove section

replace_section(section, values)

Replace section with dict of values

set(section, name, value)

Set section field value

class ShellConfigFile(fname, init_if_missing=False, backup=True)

A helper to manage shell scripts configuration files

Example

with ShellConfigFile(‘venv’) as cf:
cf.set(‘SYSTEM_SITE_PACKAGES’, 0)
append(name, value)

Append value to array field (in shell configs, arrays are string fields with values, separated with spaces)

delete(name)

Delete field

get(name)

Get field value

is_changed()

Returns True, if configuration file was changed and will be saved after the statement exit

remove(name, value)

Remove value from array field

set(name, value)

Set field to value