diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08b572d..d11a794 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,10 @@ jobs: - Integrations/ESPHome/MSR-1.yaml - Integrations/ESPHome/MSR-1_BLE.yaml - Integrations/ESPHome/MSR-1_Factory.yaml + esphome-version: + - stable + - beta + - dev steps: - name: Checkout source code uses: actions/checkout@v4.1.7 diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index 2969680..e27e5ac 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,12 +1,11 @@ substitutions: - name: apollo-msr-1 - version: "25.2.20.2" + version: "25.2.27.1" device_description: ${name} made by Apollo Automation - version ${version}. esp32: board: esp32-c3-devkitm-1 framework: - type: arduino + type: esp-idf captive_portal: web_server: @@ -245,7 +244,10 @@ binary_sensor: device_class: occupancy icon: mdi:motion-sensor lambda: |- - if ((id(radar_has_target).state) && ((id(radar_detection_distance).state < id(radar_z1_end).state) && (id(radar_detection_distance).state > id(radar_z1_start).state))){ + bool still_in_zone = id(radar_has_still_target).state && (id(still_distance).state >= id(radar_z1_start).state) && (id(still_distance).state <= id(radar_z1_end).state); + bool moving_in_zone = id(radar_has_moving_target).state && (id(moving_distance).state >= id(radar_z1_start).state) && (id(moving_distance).state <= id(radar_z1_end).state); + + if (still_in_zone || moving_in_zone) { return true; } else { return false; @@ -256,7 +258,10 @@ binary_sensor: device_class: occupancy icon: mdi:motion-sensor lambda: |- - if ((id(radar_has_target).state) && ((id(radar_z1_end).state < id(radar_detection_distance).state) && (id(radar_detection_distance).state < id(radar_z2_end).state))) { + bool still_in_zone = id(radar_has_still_target).state && (id(still_distance).state > id(radar_z1_end).state) && (id(still_distance).state <= id(radar_z2_end).state); + bool moving_in_zone = id(radar_has_moving_target).state && (id(moving_distance).state > id(radar_z1_end).state) && (id(moving_distance).state <= id(radar_z2_end).state); + + if (still_in_zone || moving_in_zone) { return true; } else { return false; @@ -267,7 +272,10 @@ binary_sensor: device_class: occupancy icon: mdi:motion-sensor lambda: |- - if ((id(radar_has_target).state) && ((id(radar_z2_end).state < id(radar_detection_distance).state) && (id(radar_detection_distance).state < id(radar_z3_end).state))) { + bool still_in_zone = id(radar_has_still_target).state && (id(still_distance).state > id(radar_z2_end).state) && (id(still_distance).state <= id(radar_z3_end).state); + bool moving_in_zone = id(radar_has_moving_target).state && (id(moving_distance).state > id(radar_z2_end).state) && (id(moving_distance).state <= id(radar_z3_end).state); + + if (still_in_zone || moving_in_zone) { return true; } else { return false; @@ -303,6 +311,26 @@ sensor: - platform: internal_temperature name: "ESP Temperature" id: sys_esp_temperature + filters: + - lambda: |- + static float last_reported_value = 0.0; + float current_value = x; + + // Check if the reduce_db_reporting switch is on + if (id(reduce_db_reporting).state) { + // Apply delta filter: only report if the value has changed by 2 or more + if (abs(current_value - last_reported_value) >= 5.0) { + last_reported_value = current_value; // Update the last reported value + return current_value; + } else { + // Return the last reported value without updating if change is less than 2 + return {}; // Discard the update + } + } else { + // If reduce_db_reporting is off, report the current value normally + last_reported_value = current_value; + return current_value; + } - platform: uptime @@ -332,18 +360,101 @@ sensor: moving_distance: name: Radar Moving Distance id: moving_distance + filters: + - lambda: |- + static float last_reported_value = 0.0; + float current_value = x; + + // Check if the radar_has_moving_target sensor is off + if (!id(radar_has_moving_target).state) { + return NAN; + } + + // Check if the reduce_db_reporting switch is on + if (id(reduce_db_reporting).state) { + // Apply delta filter: only report if the value has changed by 2 or more + if (abs(current_value - last_reported_value) >= 5.0) { + last_reported_value = current_value; // Update the last reported value + return current_value; + } else { + // Return the last reported value without updating if change is less than 2 + return {}; // Discard the update + } + } else { + // If reduce_db_reporting is off, report the current value normally + last_reported_value = current_value; + return current_value; + } still_distance: name: Radar Still Distance id: still_distance + filters: + - lambda: |- + static float last_reported_value = 0.0; + float current_value = x; + + // Check if the radar_has_still_target sensor is off + if (!id(radar_has_still_target).state) { + return NAN; + } + + // Check if the reduce_db_reporting switch is on + if (id(reduce_db_reporting).state) { + // Apply delta filter: only report if the value has changed by 2 or more + if (abs(current_value - last_reported_value) >= 5.0) { + last_reported_value = current_value; // Update the last reported value + return current_value; + } else { + // Return the last reported value without updating if change is less than 2 + return {}; // Discard the update + } + } else { + // If reduce_db_reporting is off, report the current value normally + last_reported_value = current_value; + return current_value; + } moving_energy: name: Radar Move Energy id: radar_moving_energy + filters: + - lambda: |- + if (id(reduce_db_reporting).state) return {}; + return x; still_energy: name: Radar Still Energy id: radar_still_energy + filters: + - lambda: |- + if (id(reduce_db_reporting).state) return {}; + return x; detection_distance: name: Radar Detection Distance id: radar_detection_distance + filters: + - lambda: |- + static float last_reported_value = 0.0; + float current_value = x; + + // Check if the radar_has_target sensor is off + if (!id(radar_has_target).state) { + return NAN; + } + + // Check if the reduce_db_reporting switch is on + if (id(reduce_db_reporting).state) { + // Apply delta filter: only report if the value has changed by 2 or more + if (abs(current_value - last_reported_value) >= 5.0) { + last_reported_value = current_value; // Update the last reported value + return current_value; + } else { + // Return the last reported value without updating if change is less than 2 + return {}; // Discard the update + } + } else { + // If reduce_db_reporting is off, report the current value normally + last_reported_value = current_value; + return current_value; + } g0: move_energy: name: g0 move energy @@ -412,39 +523,76 @@ sensor: - platform: ltr390 id: ltr_390 - uv_index: - name: "LTR390 UV Index" - id: ltr390uvindex light: name: "LTR390 Light" id: ltr390light - update_interval: 5s + filters: + - lambda: |- + static float last_reported_value = 0.0; + float current_value = x; + + // Check if the reduce_db_reporting switch is on + if (id(reduce_db_reporting).state) { + // Apply delta filter: only report if the value has changed by 2 or more + if (abs(current_value - last_reported_value) >= 20.0) { + last_reported_value = current_value; // Update the last reported value + return current_value; + } else { + // Return the last reported value without updating if change is less than 2 + return {}; // Discard the update + } + } else { + // If reduce_db_reporting is off, report the current value normally + last_reported_value = current_value; + return current_value; + } + uv_index: + name: "LTR390 UV Index" + id: ltr390uvindex + filters: + - lambda: |- + static float last_reported_value = 0.0; + float current_value = x; + + // Check if the reduce_db_reporting switch is on + if (id(reduce_db_reporting).state) { + // Apply delta filter: only report if the value has changed by 2 or more + if (abs(current_value - last_reported_value) >= 20.0) { + last_reported_value = current_value; // Update the last reported value + return current_value; + } else { + // Return the last reported value without updating if change is less than 2 + return {}; // Discard the update + } + } else { + // If reduce_db_reporting is off, report the current value normally + last_reported_value = current_value; + return current_value; + } light: - - platform: neopixelbus + - platform: esp32_rmt_led_strip id: rgb_light - type: GRB - variant: WS2812x - pin: GPIO3 - num_leds: 1 name: "RGB Light" - method: - type: esp32_rmt - channel: 0 + pin: GPIO3 + default_transition_length: 0s + chipset: WS2812 + num_leds: 3 + rgb_order: grb effects: - pulse: name: "Slow Pulse" transition_length: 1000ms update_interval: 1000ms - min_brightness: 0% + min_brightness: 50% max_brightness: 100% - pulse: name: "Fast Pulse" transition_length: 100ms update_interval: 100ms min_brightness: 50% - max_brightness: 100% + max_brightness: 100% button: - platform: restart @@ -489,6 +637,13 @@ switch: - platform: factory_reset id: factory_reset_switch internal: true + - platform: template + name: "Reduce DB Reporting" + id: reduce_db_reporting + icon: mdi:database + restore_mode: RESTORE_DEFAULT_OFF + optimistic: true + entity_category: "config" text_sensor: - platform: ld2410 diff --git a/Integrations/ESPHome/MSR-1.yaml b/Integrations/ESPHome/MSR-1.yaml index 9536c4c..74519d0 100644 --- a/Integrations/ESPHome/MSR-1.yaml +++ b/Integrations/ESPHome/MSR-1.yaml @@ -1,11 +1,5 @@ -#Define Project -substitutions: - name: apollo-msr-1 - version: "25.2.20.2" - device_description: ${name} made by Apollo Automation - version ${version}. - esphome: - name: "${name}" + name: apollo-msr-1 friendly_name: Apollo Multisensor Mk1 (MSR-1) comment: Apollo Multisensor Mk1 (MSR-1) name_add_mac_suffix: true @@ -22,561 +16,25 @@ esphome: name: "ApolloAutomation.MSR-1" version: "${version}" - min_version: 2024.6.0 - -# Define Board -esp32: - board: esp32-c3-devkitm-1 - framework: - type: arduino + min_version: 2025.2.0 dashboard_import: package_import_url: github://ApolloAutomation/MSR-1/Integrations/ESPHome/MSR-1.yaml import_full_config: false - -globals: - - id: cycleCounter - type: int - restore_value: no - initial_value: '0' - - id: button_press_timestamp - restore_value: no - type: uint32_t - initial_value: '0' - -# Enable Home Assistant API -# Also Add Buzzer Service Connection -api: - on_client_connected: - - delay: 1s - - light.turn_off: rgb_light - - lambda: 'id(cycleCounter) = 30;' - services: - - service: play_buzzer - variables: - song_str: string - then: - - rtttl.play: - rtttl: !lambda 'return song_str;' - - #Co2 Calibration Service - - service: calibrate_co2_value - variables: - co2_ppm: float - then: - - scd4x.perform_forced_calibration: - value: !lambda 'return co2_ppm;' - id: scd40 - - #Setting HLK Password - - service: set_ld2410_bluetooth_password - variables: - password: string - then: - - bluetooth_password.set: - id: ld2410_radar - password: !lambda 'return password;' - - ota: - platform: esphome password: "apolloautomation" - wifi: - power_save_mode: none - - # Enable fallback hotspot (captive portal) in case wifi connection fails ap: ssid: "Apollo MSR1 Hotspot" captive_portal: - web_server: port: 80 - - -# Set Up Key Ports For Communication -i2c: - sda: GPIO1 - scl: GPIO0 - id: bus_a - -uart: - tx_pin: GPIO21 - rx_pin: GPIO20 - baud_rate: 256000 - parity: NONE - stop_bits: 1 - -# Numbers For Configuration -number: - - platform: ld2410 - timeout: - name: Radar Timeout - max_move_distance_gate: - name: Radar Max Move Distance - max_still_distance_gate: - name: Radar Max Still Distance - g0: - move_threshold: - name: g0 move threshold - still_threshold: - name: g0 still threshold - g1: - move_threshold: - name: g1 move threshold - still_threshold: - name: g1 still threshold - g2: - move_threshold: - name: g2 move threshold - still_threshold: - name: g2 still threshold - g3: - move_threshold: - name: g3 move threshold - still_threshold: - name: g3 still threshold - g4: - move_threshold: - name: g4 move threshold - still_threshold: - name: g4 still threshold - g5: - move_threshold: - name: g5 move threshold - still_threshold: - name: g5 still threshold - g6: - move_threshold: - name: g6 move threshold - still_threshold: - name: g6 still threshold - g7: - move_threshold: - name: g7 move threshold - still_threshold: - name: g7 still threshold - g8: - move_threshold: - name: g8 move threshold - still_threshold: - name: g8 still threshold - - - platform: template - name: BME280 Humidity Offset - id: bme280_humidity_offset - restore_value: true - initial_value: -18.86 - min_value: -70.0 - max_value: 70.0 - entity_category: "CONFIG" - unit_of_measurement: "%" - optimistic: true - update_interval: never - step: 0.1 - mode: box - - - platform: template - name: BME280 Temperature Offset - id: bme280_temperature_offset - restore_value: true - initial_value: 14.54 - min_value: -70.0 - max_value: 70.0 - entity_category: "CONFIG" - unit_of_measurement: "°C" - optimistic: true - update_interval: never - step: 0.1 - mode: box -# Setting start of zone 1 occupancy - - platform: template - name: "Radar Zone 1 Start" - id: radar_z1_start - device_class: distance - min_value: 0 - max_value: 800 - step: 1 - mode: box - update_interval: never - optimistic: true - restore_value: true - initial_value: 0 - icon: "mdi:arrow-collapse-right" - entity_category: CONFIG - unit_of_measurement: "cm" - - # Setting ending of zone 1 occupancy - - platform: template - name: "Radar End Zone 1" - id: radar_z1_end - device_class: distance - min_value: 0 - max_value: 800 - step: 1 - mode: box - update_interval: never - optimistic: true - restore_value: true - initial_value: 50 - icon: "mdi:arrow-collapse-right" - entity_category: CONFIG - unit_of_measurement: "cm" - - # Setting ending of zone 2 occupancy - - platform: template - name: "Radar End Zone 2" - id: radar_z2_end - device_class: distance - min_value: 0 - max_value: 800 - step: 1 - mode: box - update_interval: never - optimistic: true - restore_value: true - initial_value: 150 - icon: "mdi:arrow-collapse-right" - entity_category: CONFIG - unit_of_measurement: "cm" - - # Setting ending of zone 3 occupancy - - platform: template - name: "Radar End Zone 3" - id: radar_z3_end - device_class: distance - min_value: 0 - max_value: 800 - step: 1 - mode: box - update_interval: never - optimistic: true - restore_value: true - initial_value: 250 - icon: "mdi:arrow-collapse-right" - entity_category: CONFIG - unit_of_measurement: "cm" - -# Buzzer -output: - - platform: ledc - pin: GPIO10 - id: buzzer -rtttl: - output: buzzer - - - -binary_sensor: - - platform: status - name: Online - id: ink_ha_connected - - platform: ld2410 - has_target: - name: Radar Target - id: radar_has_target - has_moving_target: - name: Radar Moving Target - id: radar_has_moving_target - has_still_target: - name: Radar Still Target - id: radar_has_still_target - ## Set Up Radar Zones Based On Distance - - platform: template - name: "Radar Zone 1 Occupancy" - id: radar_zone_1_occupancy - device_class: occupancy - icon: mdi:motion-sensor - lambda: |- - if ((id(radar_has_target).state) && ((id(radar_detection_distance).state < id(radar_z1_end).state) && (id(radar_detection_distance).state > id(radar_z1_start).state))){ - return true; - } else { - return false; - } - - platform: template - name: "Radar Zone 2 Occupancy" - id: radar_zone_2_occupancy - device_class: occupancy - icon: mdi:motion-sensor - lambda: |- - if ((id(radar_has_target).state) && ((id(radar_z1_end).state < id(radar_detection_distance).state) && (id(radar_detection_distance).state < id(radar_z2_end).state))) { - return true; - } else { - return false; - } - - platform: template - name: "Radar Zone 3 Occupancy" - id: radar_zone_3_occupancy - device_class: occupancy - icon: mdi:motion-sensor - lambda: |- - if ((id(radar_has_target).state) && ((id(radar_z2_end).state < id(radar_detection_distance).state) && (id(radar_detection_distance).state < id(radar_z3_end).state))) { - return true; - } else { - return false; - } - - platform: gpio - pin: - number: GPIO9 - inverted: true - ignore_strapping_warning: true - mode: - input: true - pullup: true - id: reset_button - on_press: - then: - - lambda: |- - id(button_press_timestamp) = millis(); - - on_release: - then: - - lambda: |- - if (millis() - id(button_press_timestamp) >= 5000) { - // Remove Wifi - id(factory_reset_switch).turn_on(); - - } - -ld2410: - id: ld2410_radar - -sensor: - - - platform: internal_temperature - name: "ESP Temperature" - id: sys_esp_temperature - - - - platform: uptime - name: Uptime - id: sys_uptime - update_interval: 60s - - - platform: wifi_signal - name: RSSI - id: wifi_signal_db - update_interval: 60s - entity_category: "diagnostic" - - - platform: scd4x - id: scd40 - co2: - name: "CO2" - id: "co2" - automatic_self_calibration: false - update_interval: 60s - measurement_mode: "periodic" - i2c_id: bus_a - ambient_pressure_compensation_source: bme280pressure - - - - platform: ld2410 - moving_distance: - name: Radar Moving Distance - id: moving_distance - still_distance: - name: Radar Still Distance - id: still_distance - moving_energy: - name: Radar Move Energy - id: radar_moving_energy - still_energy: - name: Radar Still Energy - id: radar_still_energy - detection_distance: - name: Radar Detection Distance - id: radar_detection_distance - g0: - move_energy: - name: g0 move energy - still_energy: - name: g0 still energy - g1: - move_energy: - name: g1 move energy - still_energy: - name: g1 still energy - g2: - move_energy: - name: g2 move energy - still_energy: - name: g2 still energy - g3: - move_energy: - name: g3 move energy - still_energy: - name: g3 still energy - g4: - move_energy: - name: g4 move energy - still_energy: - name: g4 still energy - g5: - move_energy: - name: g5 move energy - still_energy: - name: g5 still energy - g6: - move_energy: - name: g6 move energy - still_energy: - name: g6 still energy - g7: - move_energy: - name: g7 move energy - still_energy: - name: g7 still energy - g8: - move_energy: - name: g8 move energy - still_energy: - name: g8 still energy - - - platform: bme280_i2c - id: bme_280 - temperature: - name: "BME280 Temperature" - id: bme280temperature - filters: - - lambda: return x - id(bme280_temperature_offset).state; - pressure: - name: "BME280 Pressure" - id: bme280pressure - humidity: - name: "BME280 Humidity" - id: bme280humidity - filters: - - lambda: return x - id(bme280_humidity_offset).state; - update_interval: 60s - i2c_id: bus_a - address: 0x76 - - - - platform: ltr390 - id: ltr_390 - uv_index: - name: "LTR390 UV Index" - id: ltr390uvindex - light: - name: "LTR390 Light" - id: ltr390light - update_interval: 5s - - -light: - - platform: neopixelbus - id: rgb_light - type: GRB - variant: WS2812x - pin: GPIO3 - num_leds: 1 - name: "RGB Light" - method: - type: esp32_rmt - channel: 0 - effects: - - pulse: - name: "Slow Pulse" - transition_length: 1000ms - update_interval: 1000ms - min_brightness: 0% - max_brightness: 100% - - pulse: - name: "Fast Pulse" - transition_length: 100ms - update_interval: 100ms - min_brightness: 50% - max_brightness: 100% - -button: - - platform: restart - icon: mdi:power-cycle - name: "ESP Reboot" - - - platform: factory_reset - disabled_by_default: True - name: "Factory Reset ESP" - id: factory_reset_all - - - platform: ld2410 - factory_reset: - name: "Factory Reset Radar" - restart: - name: "Restart Radar" - query_params: - name: query params - - platform: template - name: "Calibrate SCD40 To 420ppm" - id: set_SCD40_calibrate - on_press: - - scd4x.perform_forced_calibration: - value: 420 - id: scd40 - - -switch: - - platform: ld2410 - bluetooth: - name: "Radar Control Bluetooth" - id: radar_bluetooth - engineering_mode: - name: "Radar Engineering Mode" - - platform: template - name: "Startup Light Blink" - id: startup_light_blink - icon: mdi:lightbulb - restore_mode: RESTORE_DEFAULT_ON - optimistic: true - entity_category: "config" - - platform: factory_reset - id: factory_reset_switch - internal: true - -text_sensor: - - platform: ld2410 - version: - name: "Radar Firmware Version" - -select: - - platform: ld2410 - distance_resolution: - name: "Radar Distance Resolution" - disabled_by_default: true - - - -#Used To Control RGB Light On Startup. Tells User Status Of Device -interval: - - interval: 1s - then: - - if: - condition: - - binary_sensor.is_off: ink_ha_connected - - lambda: 'return id(cycleCounter) < 30;' - - switch.is_on: startup_light_blink - - then: - - light.toggle: - id: rgb_light - - lambda: 'id(cycleCounter) += 1;' - - - interval: 1s - then: - - if: - condition: - - binary_sensor.is_off: ink_ha_connected - - lambda: 'return id(cycleCounter) > 30;' - - lambda: 'return id(cycleCounter) < 31;' - - switch.is_on: startup_light_blink - - then: - - light.turn_off: - id: rgb_light - - lambda: 'id(cycleCounter) += 1;' +packages: + core: !include Core.yaml \ No newline at end of file diff --git a/Integrations/ESPHome/MSR-1_BLE.yaml b/Integrations/ESPHome/MSR-1_BLE.yaml index c5ed017..eb0a071 100644 --- a/Integrations/ESPHome/MSR-1_BLE.yaml +++ b/Integrations/ESPHome/MSR-1_BLE.yaml @@ -1,5 +1,5 @@ esphome: - name: "${name}" + name: apollo-msr-1 friendly_name: Apollo Multisensor Mk1 (MSR-1) comment: Apollo Multisensor Mk1 (MSR-1) name_add_mac_suffix: true @@ -13,10 +13,10 @@ esphome: id(radar_bluetooth).turn_off(); project: - name: "ApolloAutomation.MSR-1" + name: "ApolloAutomation.MSR-1_BLE" version: "${version}" - min_version: 2024.6.4 + min_version: 2025.2.0 dashboard_import: package_import_url: github://ApolloAutomation/MSR-1/Integrations/ESPHome/MSR-1_BLE.yaml diff --git a/Integrations/ESPHome/MSR-1_Factory.yaml b/Integrations/ESPHome/MSR-1_Factory.yaml index c9164f3..15b9697 100644 --- a/Integrations/ESPHome/MSR-1_Factory.yaml +++ b/Integrations/ESPHome/MSR-1_Factory.yaml @@ -1,5 +1,5 @@ esphome: - name: "${name}" + name: apollo-msr-1 friendly_name: Apollo Multisensor Mk1 (MSR-1) comment: Apollo Multisensor Mk1 (MSR-1) name_add_mac_suffix: true @@ -13,10 +13,10 @@ esphome: id(radar_bluetooth).turn_off(); project: - name: "ApolloAutomation.MSR-1" + name: "ApolloAutomation.MSR-1_Factory" version: "${version}" - min_version: 2024.6.4 + min_version: 2025.2.0 dashboard_import: package_import_url: github://ApolloAutomation/MSR-1/Integrations/ESPHome/MSR-1.yaml