swoboda1337 / acurite-esphome

ESPHome AcuRite OOK signal decoder, allowing for an easy integration of 433 MHz AcuRite weather sensors into Home Assistant.
4 stars 0 forks source link
acurite esphome home-assistant lilygo sx1278

ESPHome AcuRite OOK signal decoder, allowing for an easy integration of 433 MHz AcuRite weather sensors into Home Assistant. At the moment the following devices are supported: temperature / humidity sensor, rain gauge, notos weather station, iris weather station, atlas weather station and lightning detector. Support for additional sensors can added if someone is available to test the changes.

The AcuRite component can be run without any sensors configured. Data received from all sensors will still be logged, this can be done to determine ids before setting up the sensor yaml.

A 433 MHz board that provides OOK data over a GPIO is required for this component to work. This component has been tested with the LILYGO LoRa32 V2.1_1.6 board using my SX127x component. Note the small 433 MHz antennas that come with these boards work fine but are not ideal. The antenna gain is really poor and it’s too close to the Wi-Fi antenna which can cause glitches. A proper antenna like the Siretta Tango 9 has better range and doesn’t glitch when Wi-Fi transmits.

Example yaml to use in esphome device config:

external_components:
  - source:
      type: git
      url: https://github.com/swoboda1337/acurite-esphome
      ref: main
    refresh: 1d

acurite:

remote_receiver:
  pin: GPIO32
  filter: 100us
  idle: 800us
  buffer_size: 100000b
  memory_blocks: 8

binary_sensor:
  - platform: acurite
    devices:
      - device: 0x1d2e
        battery_level:
          name: "Battery Level Temp 1"
      - device: 0x1fd2
        battery_level:
          name: "Battery Level Temp 2"
      - device: 0x2838
        battery_level:
          name: "Battery Level Rainfall"
      - device: 0x0083
        battery_level:
          name: "Battery Level Atlas"

sensor:
  - platform: acurite
    devices:
      - device: 0x1d2e
        temperature:
          name: "Temperature 1"
          force_update: true
          filters:
            - timeout: 5min
            - or:
              - throttle: 30min
              - delta: 0.01
        humidity:
          name: "Humidity 1"
          force_update: true
          filters:
            - timeout: 5min
            - or:
              - throttle: 30min
              - delta: 0.01
      - device: 0x1fd2
        temperature:
          name: "Temperature 2"
          force_update: true
          filters:
            - timeout: 5min
            - or:
              - throttle: 30min
              - delta: 0.01
        humidity:
          name: "Humidity 2"
          force_update: true
          filters:
            - timeout: 5min
            - or:
              - throttle: 30min
              - delta: 0.01
      - device: 0x2838
        rain:
          name: "Rainfall"
          force_update: true
          filters:
            - timeout: 5min
            - throttle: 50sec
      - device: 0x0083
        speed:
          name: "Wind speed"
          filters:
            - timeout: 5min
            - or:
              - throttle: 10min
              - delta: 0.01
        direction:  
          name: "Wind direction"
          filters:
            - timeout: 5min
            - or:
              - throttle: 10min
              - delta: 0.01
        lightning:
          name: "Lightning Strikes"
          force_update: true
          filters:
            - timeout: 5min
            - or:
              - throttle: 30min
              - delta: 0.01
        distance:  
          name: "Lightning Distance"
          force_update: true
          filters:
            - timeout: 5min
            - or:
              - throttle: 30min
              - delta: 0.01
        uv:
          name: "UV index"
          filters:
            - timeout: 5min
            - or:
              - throttle: 10min
              - delta: 0.01
        lux:
          name: "Light Intensity"
          filters:
            - timeout: 5min
            - or:
              - throttle: 10min
              - delta: 0.01

It is recommended to use force_update so any statistics sensors in Home Assistant will work correctly. For example if the humidity stays at 99% all day, without force_update, a max/min statistics sensor would show unavailable as no data points will be logged. Using the delta and throttle filters will limit the amount of data being sent up and stored.

As of November 2024, rain sensors no longer store anything in NVM and now output the current device total. This was done to make things more flexible. To restore the previous functionality of a lifetime total a lambda + two globals can be used:

globals:
  - id: rainfall_total
    type: float
    restore_value: yes
  - id: rainfall_current
    type: float
    restore_value: yes

sensor:
  - platform: acurite
    devices:
      - device: 0x2838
        rain:
          name: "Test Backyard Rainfall"
          force_update: true
          filters:
            - lambda: |-
                // update rainfall state and save to nvm
                if (x != id(rainfall_current)) {
                  float delta;
                  if (x >= id(rainfall_current)) {
                    delta = x - id(rainfall_current);
                  } else {
                    delta = x;
                  }
                  id(rainfall_total) += delta; // can apply a calibration value here
                  id(rainfall_current) = x;
                }
                return id(rainfall_total);
            - throttle: 50sec
            - timeout: 5min

An increasing total for rainfall is not very useful by itself. Here are some example sensors that can be added to Home Assistant's configuration.yaml

These sensors are window based and will calculate how much rain had fallen within the window:

sensor:
  - platform: statistics
    name: "AcuRite Rainfall 15Min"
    entity_id: sensor.acurite_rainfall
    state_characteristic: change
    max_age:
      minutes: 15
  - platform: statistics
    name: "AcuRite Rainfall 1Hr"
    entity_id: sensor.acurite_rainfall
    state_characteristic: change
    max_age:
      hours: 1
  - platform: statistics
    name: "AcuRite Rainfall 24Hr"
    entity_id: sensor.acurite_rainfall
    state_characteristic: change
    max_age:
      hours: 24

These sensors will reset at specific times which is useful for daily, weekly or monthly:

utility_meter:
  daily_rainfall:
    source: sensor.acurite_rainfall
    name: AcuRite Rainfall Daily
    always_available: true
    periodically_resetting: false
    cycle: daily
  weekly_rainfall:
    source: sensor.acurite_rainfall
    name: AcuRite Rainfall Weekly
    always_available: true
    periodically_resetting: false
    cycle: weekly
  monthly_rainfall:
    source: sensor.acurite_rainfall
    name: AcuRite Rainfall Monthly
    always_available: true
    periodically_resetting: false
    cycle: monthly

A binary moisture sensor can also be created using a template:

{{states('sensor.acurite_rainfall_15min')|float > 0}}

For lightning detection the following example sensors that can be added to Home Assistant. These sensors will create a daily counter, daily closest distance, most recent distance and a binary sensor indicating if lightning has been detected recently. If there has been no strike today both closest and last will show 40km (max distance):

utility_meter:
  daily_lightning:
    source: sensor.lightning_strikes
    name: "Lightning Strikes Daily"
    always_available: true
    periodically_resetting: true
    cron: "0 0 * * *"

template:
  - trigger:
      - platform: time
        at: '00:00:00'
      - platform: state
        entity_id: sensor.lightning_distance
    sensor:
      - name: "Lightning Distance Last"
        device_class: distance
        unit_of_measurement: "km"
        state: >
            {% if trigger.platform == 'time' %}
                {{ float(40) }}
            {% else %}
                {% if states('sensor.lightning_strikes_daily') | float(0) | float > 0 %}
                    {{ states('sensor.lightning_distance') }}
                {% else %}
                    {{ float(40) }}
                {% endif %}
            {% endif %}
  - trigger:
      - platform: time
        at: '00:00:00'
      - platform: state
        entity_id: sensor.lightning_distance
    sensor:
      - name: "Lightning Distance Closest"
        device_class: distance
        unit_of_measurement: "km"
        state: >
            {% if trigger.platform == 'time' %}
                {{ float(40) }}
            {% else %}
                {% if states('sensor.lightning_strikes_daily') | float(0) | float > 0 %}
                    {{ [states('sensor.lightning_distance') | float(40), this.state | float(40)] | min }}
                {% else %}
                    {{ float(40) }}
                {% endif %}
            {% endif %}

binary_sensor:
  - platform: trend
    sensors:
      lightning_active:
        friendly_name: Lightning Active
        entity_id: sensor.lightning_strikes
        device_class: power
        sample_duration: 1800
        min_gradient: 0.0001
        min_samples: 2
        max_samples: 30