Integrating Panasonic BalancedHome ERV + Swidget w/ HA

The following describes a method to integrate the Swidget WP100PBA used in Panasonic BalancedHome Energy Recovery Ventilator (ERV) air exchangers with Home Assistant. The WP100PBA does not work with the normal Swidget integration. Integration can be done with RESTful.

Following these steps will allow you to get all data back from the ERV, as well as select the ventilation mode (Heat Exchange, Supply Only, Exhaust Only, Recirc). It should also get you close to commanding on, off, boost from Home Assistant.

Provision the Swidget to your Network

(These steps are from memory and will not be perfect. Refer to the link below for additional information.)

1.) Factory Reset (Hold Reset button until LED is red, then release).
2.) Connect to Swidget hotspot with computer.
3.) Open web browser and navigate to https://10.123.45.1
4.) This part I can’t quite remember but you need to specify the wifi network the swidget should connect to. It will generate a key which is ultimately just the MAC address.
5.) Disable authentication (this will allow the code below to work, it should be able to work with authentication enabled, but this would require modification of the code below).

Home Assistant Config

6.) Add the following code to your configuration.yaml REPLACE the resource IP Address with the device’s IP address. I recommend setting up IP address reservation if using DHCP or set a static IP address. Then power cycle the swidget for it to receive the new IP address.

rest:
  - resource: http://**IPADDRESS**/api/v1/state  # Replace with actual device URL
    scan_interval: 20
    sensor:
      # --- Operational Status ---
      - name: "ERV Ventilation Mode"
        value_template: "{{ value_json.host.components['0'].mode }}"
        icon: mdi:cog-refresh
      - name: "ERV Ventilation Status"
        value_template: "{{ value_json.host.components['0'].status }}"
      - name: "ERV Ventilation Speed"
        value_template: "{{ value_json.host.components['0'].speed }}"
        icon: mdi:speedometer
      - name: "Boost Mode"
        value_template: "{{ value_json.host.components['0'].boost.mode }}"
      - name: "ERV Ventilation Power State"
        value_template: "{{ value_json.host.components['0'].toggle.state }}"

      # --- Power & Duty Cycle ---
      - name: "ERV Current Power"
        value_template: "{{ value_json.host.components['0'].power.current }}"
        device_class: power
        unit_of_measurement: "W"
      - name: "ERV Average Power"
        value_template: "{{ value_json.host.components['0'].power.avg }}"
        device_class: power
        unit_of_measurement: "W"
      - name: "ERV Average On Power"
        value_template: "{{ value_json.host.components['0'].power.avgOn }}"
        device_class: power
        unit_of_measurement: "W"
      - name: "ERV Duty Cycle Minutes"
        value_template: "{{ value_json.host.components['0'].dutyCycle.minutes }}"
        unit_of_measurement: "min"

      # --- Airflow (Exhaust/Supply) ---
      - name: "ERV Exhaust CFM"
        value_template: "{{ value_json.host.components['0'].exhaust.cfm }}"
        unit_of_measurement: "CFM"
      - name: "ERV Supply CFM"
        value_template: "{{ value_json.host.components['0'].supply.cfm }}"
        unit_of_measurement: "CFM"

      # --- Environment (Indoors/Outdoors) ---
      - name: "ERV Indoor Temperature"
        value_template: "{{ value_json.host.components['0'].indoors.temperature }}"
        device_class: temperature
        unit_of_measurement: "°C"
      - name: "ERV Indoor Humidity"
        value_template: "{{ value_json.host.components['0'].indoors.humidity }}"
        device_class: humidity
        unit_of_measurement: "%"
      - name: "ERV Outdoor Temperature"
        value_template: "{{ value_json.host.components['0'].outdoors.temperature }}"
        device_class: temperature
        unit_of_measurement: "°C"
      - name: "ERV Outdoor Humidity"
        value_template: "{{ value_json.host.components['0'].outdoors.humidity }}"
        device_class: humidity
        unit_of_measurement: "%"

      # --- Maintenance & Balancing ---
      - name: "ERV Balancing Offset"
        value_template: "{{ value_json.host.components['0'].balancing.offset }}"
      
      # --- Connectivity ---
      - name: "ERV Device WiFi RSSI"
        value_template: "{{ value_json.connection.rssi }}"
        device_class: signal_strength
        unit_of_measurement: "dBm"
      - name: "ERV Device IP Address"
        value_template: "{{ value_json.connection.ip }}"
      - name: "ERV Device MAC Address"
        value_template: "{{ value_json.connection.mac }}"

    binary_sensor:

      - name: "ERV Filter Replacement Needed"
        value_template: "{{ value_json.host.components['0'].filter.needsReplacement }}"
        device_class: problem
      - name: "ERV Filter Cleaning Needed"
        value_template: "{{ value_json.host.components['0'].filter.needsCleaning }}"
        device_class: problem
      - name: "ERV Self Diagnostic Error"
        value_template: "{{ value_json.insert.errors.self_diag > 0 }}"
        device_class: problem

7.) Reboot home assistant. The data should now be available.
Note : Temperatures and humidities may peg high or become unavailable when there is no airstream (received value is 254).

8.) To configure the ability to send command to change the ventilation mode, add the following to your configuration.yaml file:

rest_command:
  erv_set_mode:
    url: "http://**IPADDRESS**/api/v1/command"
    method: POST
    content_type: "application/json"
    payload: >
      {
        "host": {
          "components": {
            "0": {
              "mode": "{{ mode if mode in ['heatExchange', 'supply', 'exhaust', 'recirculation'] else 'heatExchange' }}"
            }
          }
        }
      }

9.) Create a Dropdown helper with the title “ERV Mode Selector” with the following options:
Heat Exchange
Supply Only
Exhaust Only
Recirculation

10.) Create a new automation using the following yaml:

alias: Update ERV Mode
description: Maps pretty names to technical API values
triggers:
  - entity_id: input_select.erv_mode_selector
    trigger: state
actions:
  - data:
      mode: >
        {% set mapper = {
          'Heat Exchange': 'heatExchange',
          'Supply Only': 'supply',
          'Exhaust Only': 'exhaust',
          'Recirculation': 'recirculation'
        } %} {{ mapper.get(states('input_select.erv_mode_selector'),
        'heatExchange') }}
    action: rest_command.erv_set_mode
mode: single

The above automation will take the selected mode from the dropdown helper and pass it to the ERV.

To create binary sensors to provide true/false indicators of the ERV using the API, you can add the following to your configuration.yaml file:

  template:
  # Convert erv states from API to boolean.
      - binary_sensor:
        - name: "ERV Running Status"
          state: "{{ is_state('sensor.erv_ventilation_power_state', 'on') }}"
      - binary_sensor:
        - name: "ERV Boost Status"
          state: "{{ is_state('sensor.erv_ventilation_status', 'boost') }}"
      - binary_sensor:
        - name: "ERV Defrosting Status"
          state: "{{ is_state('sensor.erv_ventilation_status', 'defrost') }}"
      - binary_sensor:
        - name: "ERV Normal Status"
          state: "{{ is_state('sensor.erv_ventilation_status', 'normal') }}"
      - binary_sensor:
        - name: "ERV Heat Exchanging Status"
          state: "{{ is_state('sensor.erv_ventilation_mode', 'heatExchange') }}"
      - binary_sensor:
        - name: "ERV Exhaust Only Status"
          state: "{{ is_state('sensor.erv_ventilation_mode', 'exhaust') }}"
      - binary_sensor:
        - name: "ERV Supply Only Status"
          state: "{{ is_state('sensor.erv_ventilation_mode', 'supply') }}"
      - binary_sensor:
        - name: "ERV Recirc Status"
          state: "{{ is_state('sensor.erv_ventilation_mode', 'recirculation') }}"

Refer here for additional information:

Note from Swidget: “Swidget provides the Local API documentation as a reference, but cannot offer support for custom implementations built on top of it. If something does not work in your configuration, Swidget will not be able to review or troubleshoot your code.”

Note from Swidget: 3rd Party HACS integration is currently being developed with Swidget’s support, maintained by an independent developer here:

2 Likes