Skip to content
 
 

Repository files navigation

OPCUA Client over Asyncua

This is an hacs integration using asyncua to connect various industrial PLC to HA. My initial approach was to develop a gateway which connect the PLC over RESTful API. After a couple of integration for projects, I found that it would be beneficial to the community to have a custom integration in HA for OPC UA servers.

I found an older project which uses the python-opcua, which is deprecated and decided to start a new integration using opcua-asyncio.

Buy me a beer


Table of contents

Installation Asyncua-Coordinator Subscription Mode Sensor Binary-Sensor Switch Directory Donate


Installation

With HACS
  1. If HACS is not installed yet, download it following the instructions on https://hacs.xyz/docs/setup/download/
  2. Proceed to the HACS initial configuration following the instructions on https://hacs.xyz/docs/configuration/basic
  3. Copy this project directory, https://github.com/KVSoong/asyncua.
  4. Navigate to HACS in HA and select Integration.
  5. At the top right corner, select the vertical 3 dots and click Custom repositories.
  6. Paste the link in the Repository input field and select Integration for the Categeroy dropdown select.
  7. Click Add to add this repository to your HA.
  8. Once added, you should see this custom repository installed. It should prompt you to restart.
  9. Once restarted, you should be able to connect to a OPCUA server.

Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.


Asyncua Coordinator

This integration is developed with the option to connect to multiple OPCUA servers, as it is commonly used in an industrial environment.

Paste the following lines to your configuration.yaml file. Remove or add more OPCUA servers as required. Specify a unique name for each server, under the key name.

asyncua:
  - name: "plc-01" # Unique name to identify the server. Will be used by the sensors to indicate which server to get the node value.
    url: "opc.tcp://localhost:4840/" # URL of the server.
    scan_interval: 10 # Optional. Interval for coordinator to read from OPCUA. Default is set at 30s.
    username: admin # Optional username
    password: admin # Optional password
  - name: "plc-02"
    url: "opc.tcp://localhost2:4840/"
    scan_interval: 10
    username: admin
    password: admin
Options (YAML + descriptions)
Name Type Requirement Description
name string Required Unique identifier for each OPCUA Server
url string Required OPCUA server URL within the same network
scan_interval int Optional Polling interval in seconds to refresh data. Ignored when subscribe: true. Default: 30s
subscribe bool Optional Enable OPC UA subscription mode for push-based updates instead of polling. Default: false
subscribe_period int Optional Publishing interval in milliseconds for the OPC UA subscription. Only used when subscribe: true. Default: 500
username string Optional Username to connect to the server
password string Optional Password to connect to the server

Subscription Mode

By default this integration polls the OPC UA server on a fixed scan_interval. When you need data to update instantly - as soon as the value changes on the server - you can enable subscription mode instead.

In subscription mode the integration keeps a single persistent connection to the server and registers an OPC UA subscription. The server then pushes change notifications to HA automatically, so entities update in near real-time without any polling overhead.

Configuration

Replace scan_interval with subscribe: true on the hub:

asyncua:
  - name: "plc-01"
    url: "opc.tcp://localhost:4840/"
    subscribe: true
    subscribe_period: 100 # Optional. Publishing interval in ms. Default is 500ms.

Note: scan_interval is ignored when subscribe: true.

What is subscribe_period?

subscribe_period sets the OPC UA publishing interval (in milliseconds). This controls how frequently the server batches and sends change notifications to HA. A lower value means lower latency; a higher value reduces network messages when many nodes change at once.

Value Effect
100 Up to ~100ms latency, suitable for fast-changing values
500 (default) Good balance for most home automation use cases
1000+ Reduced traffic when many nodes change frequently

Sensors Entities

This entity allows you to create any type of device class sensor specified in homeassistant. To add a custom sensor entity, paste the following example into your configuration.yaml file and update the values.

sensor:
  - platform: asyncua
    nodes:
      - name: sensor-01 # Name of the sensor
        unique_id: sensor-01 # Unique ID of the sensor
        device_class: temperature # Device class according to Homeassistant sensors
        hub: plc-01 # OPCUA unique name defined in the coordinator that serve the data.
        nodeid: "ns=1;s=3000" # Node id from OPCUA server
        unit_of_measurement: °C # Optional unit of measurement.
      - name: sensor-02
        unique_id: sensor-02
        device_class: temperature
        hub: plc-02
        nodeid: "ns=1;s=3000"
        unit_of_measurement: °C
Options (YAML + descriptions)
Name Type Requirement Description
name string Required Unique identifier for each sensor
unique_id string Optional Entity ID stored in homeassistant
device_class string Optional sensors available in homeassistant
hub string Required Corresponded OPCUA hub defined in asyncua-coordinator name key
nodeid string Required node id address of a single node
unit_of_measurement string Optional to allow historical statistic graph if device_class is not defined

Binary Sensors Entities

This entity allows you to create any type of device class binary sensor specified in homeassistant. To add a custom binary sensor entity, paste the following example into your configuration.yaml file and update the values.

binary_sensor:
  - platform: asyncua
    nodes:
      - name: "binary-sensor-01" # Unique id for the binary sensor
        unique_id: "binary-sensor-01" # Homeassistnat unique_id
        device_class: "power" # Device class according to Homeassistant binary sensors
        hub: "plc-01" # Defined Asyncua coordinator
        nodeid: "ns=1;s=1000" # Node id from OPCUA server
      - name: "binary-sensor-01" 
        unique_id: "binary-sensor-01" 
        device_class: "power"
        hub: "plc-01"
        nodeid: "ns=1;s=1000"
Options (YAML + descriptions)
Name Type Requirement Description
name string Required Unique identifier for each binary sensor
unique_id string Optional Entity ID stored in homeassistant
device_class string Optional binary sensors available in homeassistant
hub string Required Corresponded OPCUA hub defined in asyncua-coordinator name key
nodeid string Required node id address of a single node

Switch Entities

This entity allow you to create a switch entity which can be a representative of a contactor or relay in a automation environment. Node id address for DO(digital output) to set the new value and also an optional DI(digital input) can be used to read the real state of the node. If DI is not specified, DO node address is used instead to check the state of the node. To add a custom binary sensor entity, paste the following example into your configuration.yaml file and update the values.

switch:
  - platform: asyncua
    nodes:
      - name: "switch-01" # Unique id for the binary sensor
        unique_id: "switch-01"  # Homeassistnat unique_id
        hub: "plc-01 "   # Defined Asyncua coordinator
        nodeid: "ns=1;s=1000"  # DO node id from OPCUA server
        nodeid_switch_di: "ns=1;s=2000" # DI node id from OPCUA server
      - name: "switch-02"
        unique_id: "switch-02"
        hub: "plc-01 "
        nodeid: "ns=1;s=1001"
        nodeid_switch_di: "ns=1;s=2001"
Options (YAML + descriptions)
Name Type Requirement Description
name string Required Unique identifier for each switch
unique_id string Optional Entity ID stored in homeassistant
hub string Required Corresponded OPCUA hub defined in asyncua-coordinator name key
nodeid string Required node id address for the digital output
nodeid_switch_di string Optional node id address for the digital input. If not specified, nodeid_switch_do node is used for the latest state

Organizing subdirectories for custom sensors and binary_sensor

Will be included in the future.

Set values to node

To set a new value to a node, a service can be called from Developer Tools -> Services -> asyncua: set value.

  1. Ensure that a valid asyncua-coordnator is created.

  2. Paste the following code sample in UI Mode and make the necessary changes

    hub: plc-01
    nodeid: ns=1;s=1000
    value: false
  3. In YAML Mode, paste the following code sample and make the necessary changes

    service: asyncua.set_value
    target: {}
    data:
      hub: plc-01
      nodeid: ns=1;s=1000
      value: false

📂 Directory Structure

To better organize entities and avoid clumping them in a single configuration.yaml file, you can include the following lines in the configuration.yaml file, and create the directory stucture as shown in the tree below.

home-assistant/
├── asyncua-binary-sensor/
|   ├── sensor-01.yaml
|   ├── ...
|   └── sensor-n.yaml
├── asyncua-sensor/
|   ├── sensor-01.yaml
|   ├── ...
|   └── sensor-n.yaml
├── asyncua-switch/
|   ├── switch-01.yaml
|   ├── ...
|   └── switch-n.yaml
└── configuration.yaml
Configuration YAML

Include the following lines in the configuration.yaml file to import the entites in each directory.

binary_sensor asyncua: !include_dir_merge_list asyncua-binary-sensor/
sensor asyncua: !include_dir_merge_list asyncua-sensor/
switch asyncua: !include_dir_merge_list asyncua-switch/
Binary Sensor YAML
- platform: asyncua
  nodes:
    - name: "binary-sensor-01" # Unique id for the binary sensor
      unique_id: "binary-sensor-01" # Homeassistnat unique_id
      device_class: "power" # Device class according to Homeassistant binary sensors
      hub: "plc-01" # Defined Asyncua coordinator
      nodeid: "ns=1;s=1000" # Node id from OPCUA server
    - name: "binary-sensor-01" 
      unique_id: "binary-sensor-01" 
      device_class: "power"
      hub: "plc-01"
      nodeid: "ns=1;s=1000"
Sensor YAML
- platform: asyncua
  nodes:
    - name: sensor-01 # Name of the sensor
      unique_id: sensor-01 # Unique ID of the sensor
      device_class: temperature # Device class according to Homeassistant sensors
      hub: plc-01 # OPCUA unique name defined in the coordinator that serve the data.
      nodeid: "ns=1;s=3000" # Node id from OPCUA server
      unit_of_measurement: °C # Optional unit of measurement.
    - name: sensor-02
      unique_id: sensor-02
      device_class: temperature
      hub: plc-02
      nodeid: "ns=1;s=3000"
      unit_of_measurement: °C
Switch YAML
- platform: asyncua
  nodes:
    - name: "switch-01" # Unique id for the binary sensor
      unique_id: "switch-01"  # Homeassistnat unique_id
      hub: "plc-01 "   # Defined Asyncua coordinator
      nodeid: "ns=1;s=1000"  # DO node id from OPCUA server
      nodeid_switch_di: "ns=1;s=2000" # DI node id from OPCUA server
    - name: "switch-02"
      unique_id: "switch-02"
      hub: "plc-01 "
      nodeid: "ns=1;s=1001"
      nodeid_switch_di: "ns=1;s=2001"

About

OPCUA client using asyncua library

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages