How to parse bitfield from Modbus register

Yeah i do not have that option at all. I contacted enervent and they said it needs software updates.

Both, eair and motherboard updates they said.

MD SW version 1.27
MD HW version C 1.02

Hmm, bummer!
Did they specify how those updates can be done? I mean, I don’t see any option to trigger that from either the eAir controller or through my.enervent.com.

It is done with usb Stick. I presume they will do it themself, price, i dont know… After i asked is it free, they have not contacted back :smiley:

Edit: i just called them, they will send usb Stick and sdcard for the controller :slight_smile: for free.

Have you guys checked the physicall state of the eAir controller battery ? After 3years, mine is allready swollen a bit, so i took it out. Works fine without, in its gradle of course.
I heard that this is common problem and some have had burning controllers etc…

Just checked the one on mine: no signs of swelling.
But mine is brand new anyway. :man_shrugging:t3:

1 Like

To continue on the original topic, I finally managed to get those bitfield modbus registers into use, based on the tip from @Edwin_D:

First I changed the sensor to use big-endian byte order, to better match what the Enervent modbus registers are handing out:

- name: "Enervent Status"
  address: 44
  data_type: custom
  input_type: holding
  count: 1
  structure: ">H"

Then I created a template sensor with attributes for each mode, using the bitwise_and filter:

- sensor:
  - name: "Enervent status map"
    state: "{{ states('sensor.enervent_status') }}"
    attributes:
      max_cooling: "{% if states('sensor.enervent_status') | int | bitwise_and(1) %}on{% else %}off{% endif %}"
      max_heating: "{% if states('sensor.enervent_status') | int | bitwise_and(2) %}on{% else %}off{% endif %}"
      stopped_due_to_alarm: "{% if states('sensor.enervent_status') | int | bitwise_and(4) %}on{% else %}off{% endif %}"
      stopped_by_request: "{% if states('sensor.enervent_status') | int | bitwise_and(8) %}on{% else %}off{% endif %}"
      away_mode: "{% if states('sensor.enervent_status') | int | bitwise_and(16) %}on{% else %}off{% endif %}"
      temp_boosting: "{% if states('sensor.enervent_status') | int | bitwise_and(64) %}on{% else %}off{% endif %}"
      co2_boosting: "{% if states('sensor.enervent_status') | int | bitwise_and(128) %}on{% else %}off{% endif %}"
      rh_boosting: "{% if states('sensor.enervent_status') | int | bitwise_and(256) %}on{% else %}off{% endif %}"
      manual_boosting_mode: "{% if states('sensor.enervent_status') | int | bitwise_and(512) %}on{% else %}off{% endif %}"
      overpressure_mode: "{% if states('sensor.enervent_status') | int | bitwise_and(1024) %}on{% else %}off{% endif %}"
      cooker_hood_mode: "{% if states('sensor.enervent_status') | int | bitwise_and(2048) %}on{% else %}off{% endif %}"

I’ve only tested Away mode, Manual boosting & overpressure modes, as those can be directly enabled from the panel. But given the bit order, the other states should work just the same.

Based on the verified logic it’s then easy to create template sensors for individual modes.
For example:

- binary_sensor:
  - name: "Enervent away mode"
    state: "{% if states('sensor.enervent_status') | int | bitwise_and(16) %}on{% else %}off{% endif %}"
    icon: mdi:home-export-outline

I hope this helps someone who’s trying to integrate their Enervent ventilator to Home Assistant! :slightly_smiling_face:

[edit: fixed a copy-paste mistake ]

4 Likes

Hmm… for some reason my Enervent modbus connection dies after a day or so. Reloading modbus from developer tools does not help, only restarting homeassistant works ?

2022-11-30 09:21:52.760 ERROR (SyncWorker_8) [homeassistant.components.modbus.modbus] Pymodbus: enervent: Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 8 bytes (0 received)

I haven’t had much luck with reloading modbus yaml through Developer Tools either. Seems like you need to restart Home Assistant every time you make some changes to the config.
Haven’t had any disconnection issues on my end but, with a previous version of Home Assistant the connection was lost when I tried to reload modbus yaml.

Have you been able to add those preset modes (away etc.) to climate cards ? If so, how ?

Not exactly.
I’m using a vertical stack to group all things related to the Enervent ventilator. I have button cards mapped to those switches (modbus coil registers) for the preset modes I expect to be using.
Here’s a screen shot.

2 Likes

Yeah, i gave up and configured my own with mushroom cards…

kuva

1 Like

I recently change to HASS OS, and there restart via developer tools work. I Also learned that there is service to restart modbus connection. I was wondering if its possible to make automation to check whether connection is up or not, and use that modbus restart service. I just dont know how to check if connection is up…

Dunno. The Enervent modbus integration has been working most reliably for me, so I don’t feel like I need to take any extra measures to ensure a stable connection. I only used the Developer Tools reload functionality to apply changes I had made to the configuration files.

My connection goes down daily :confused: I added automation to just restart modbus @6am. Some sort of solution …

@stniemin Do you have these in your setup :

2023-02-08 17:08:46.932 WARNING (MainThread) [homeassistant.components.sensor] Sensor sensor.enervent_supply_air_fan_speed has device class None, state class None and unit % thus indicating it has a numeric value; however, it has the non-numeric value: unavailable (<class 'str'>); Please update your configuration if your entity is manually configured, otherwise create a bug report at https://github.com/home-assistant/core/issues?q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+modbus%22
2023-02-08 17:08:46.941 WARNING (MainThread) [homeassistant.components.sensor] Sensor sensor.enervent_extract_air_fan_speed has device class None, state class None and unit % thus indicating it has a numeric value; however, it has the non-numeric value: unavailable (<class 'str'>); Please update your configuration if your entity is manually configured, otherwise create a bug report at https://github.com/home-assistant/core/issues?q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+modbus%22
2023-02-08 17:08:46.945 WARNING (MainThread) [homeassistant.components.sensor] Sensor sensor.enervent_outside_air_temperature has device class temperature, state class None and unit °C thus indicating it has a numeric value; however, it has the non-numeric value: unavailable (<class 'str'>); Please update your configuration if your entity is manually configured, otherwise create a bug report at https://github.com/home-assistant/core/issues?q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+modbus%22

No, I don’t. But then, my Enervent ventilator’s availability seems to be 100%.
Are your Enervent ventilator and HA server both plugged in on ethernet? Could network issues explain the occasional connection failures?

I haven’t defined those device_class state_class attributes to fan sensors either. Perhaps it would be a good practice to add them. :thinking:

Apparently the time had come to service the ventilator’s filters for the first time. I hadn’t noticed this before as the control panel is not in a place where it could be seen. The modbus fields had the alert info, but I hadn’t used them for anything yet.
So, it was time to create this markdown card - to keep myself informed of such alerts in the future:

type: markdown
content: |
  {% if is_state('sensor.enervent_alarm_1_state', '1') %}
    <ha-alert alert-type="info">
      There is an alert that is acknowledged, but hasn't been cleared.
      [{{states('sensor.enervent_alarm_1_year') }}.{{states('sensor.enervent_alarm_1_month') }}.{{states('sensor.enervent_alarm_1_year') | int + 2000 }} {{states('sensor.enervent_alarm_1_hour') }}.{{states('sensor.enervent_alarm_1_minute') }}]
    </ha-alert>
  {% endif %}
  {% if is_state('sensor.enervent_alarm_1_state', '2') %}
    <ha-alert alert-type="warning">
      There is a new alert, waiting to be acknowledged<br/>
      date: {{states('sensor.enervent_alarm_1_year') }}.{{states('sensor.enervent_alarm_1_month') }}.{{states('sensor.enervent_alarm_1_year') | int + 2000 }} {{states('sensor.enervent_alarm_1_hour') }}.{{states('sensor.enervent_alarm_1_minute') }}
      
      {% if is_state('sensor.enervent_alarm_1_type', '1') %}Alert type: TE05_L{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '2') %}Alert type: TE10_L{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '3') %}Alert type: TE10_H{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '4') %}Alert type: TE20_H{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '5') %}Alert type: TE30_L{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '6') %}Alert type: TE30_H{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '7') %}Alert type: HP/MDX{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '8') %}Alert type: SLP{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '9') %}Alert type: TE45_L{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '10') %}Alert type: LTO{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '11') %}Alert type: COOL{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '12') %}Alert type: EMERGENCY_STOP{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '14') %}Alert type: SERVICE{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '15') %}Alert type: PDS10{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '16') %}Alert type: SPLY_FILT_H{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '17') %}Alert type: EXT_FILT_H{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '20') %}Alert type: TF_PRES{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '21') %}Alert type: PF_PRES{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '22') %}Alert type: TE50_H{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '24') %}Alert type: TE52_H{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '25') %}Alert type: TF_ROTATION{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '26') %}Alert type: PF_ROTATION{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '27') %}Alert type: TE02_H{% endif %}
      {% if is_state('sensor.enervent_alarm_1_type', '28') %}Alert type: SERVICE_CONSTANT_DUCT_PRES{% endif %}
    </ha-alert>
  {% endif %}

It took a while to write the ifs and alarm specific notes. Hope this will save the time for someone else!

3 Likes

Come to think of it, I might as well create an automation to send a mobile notification when the alarm_1 state changes.

Hm, they changed something in modbus integration, mine does not work at all anymore :confused:

There’s one breaking change announced for Modbus with the latest release, but that shouldn’t affect things yet.

Mine is still working.
Are you getting some modbus specific errors?