diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..79be94a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,21 @@ +name: CI + +on: + pull_request: + +jobs: + ci: + name: Building ${{ matrix.file }} + runs-on: ubuntu-latest + strategy: + matrix: + file: + - Integrations/ESPHome/MSR-1.yaml + - Integrations/ESPHome/MSR-1_BLE.yaml + steps: + - name: Checkout source code + uses: actions/checkout@v4.1.7 + - name: Build ESPHome firmware to verify configuration + uses: esphome/build-action@v3.1.0 + with: + yaml_file: ${{ matrix.file }} \ No newline at end of file diff --git a/Integrations/ESPHome/MSR-1.yaml b/Integrations/ESPHome/MSR-1.yaml index 5a2fda4..416d812 100644 --- a/Integrations/ESPHome/MSR-1.yaml +++ b/Integrations/ESPHome/MSR-1.yaml @@ -1,7 +1,7 @@ #Define Project substitutions: name: apollo-msr-1 - version: "24.7.3.1" + version: "24.7.5.1" device_description: ${name} made by Apollo Automation - version ${version}. esphome: @@ -82,26 +82,12 @@ api: ota: - platform: esphome password: "apolloautomation" - id: ota_default - - platform: http_request - id: ota_managed - -http_request: - useragent: esphome/device - timeout: 10s - verify_ssl: false - -update: - - platform: http_request - id: firmware_update - name: Firmware Update - source: https://apolloautomation.github.io/MSR-1/artifact/manifest.json - - wifi: + power_save_mode: none + # Enable fallback hotspot (captive portal) in case wifi connection fails ap: ssid: "Apollo MSR1 Hotspot" @@ -111,7 +97,7 @@ captive_portal: web_server: port: 80 - + # Set Up Key Ports For Communication @@ -339,7 +325,6 @@ binary_sensor: pin: number: GPIO9 inverted: true - ignore_strapping_warning: true mode: input: true pullup: true diff --git a/Integrations/ESPHome/MSR-1_BLE.yaml b/Integrations/ESPHome/MSR-1_BLE.yaml new file mode 100644 index 0000000..77c4da5 --- /dev/null +++ b/Integrations/ESPHome/MSR-1_BLE.yaml @@ -0,0 +1,571 @@ +#Define Project +substitutions: + name: apollo-msr-1 + version: "24.7.5.1" + device_description: ${name} made by Apollo Automation - version ${version}. + +esphome: + name: "${name}" + friendly_name: Apollo Multisensor Mk1 (MSR-1) + comment: Apollo Multisensor Mk1 (MSR-1) + name_add_mac_suffix: true + platformio_options: + board_build.flash_mode: dio + + on_boot: + - priority: 900.0 + then: + - lambda: |- + id(radar_bluetooth).turn_off(); + + project: + name: "ApolloAutomation.MSR-1" + version: "${version}" + + min_version: 2024.6.0 + +# Define Board +esp32: + board: esp32-c3-devkitm-1 + framework: + type: arduino + +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" + +bluetooth_proxy: + active: true + +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 + 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 + + +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;'