Milfra Motion Sensor Light Switch (MFA05)

I’ll post my yaml file when I get home from work.

FYI I was never able to OTA the esphome bin file when the switch had tasmota on it. I had to open it up and flash via UART. There are no pin headers, only solder pads. So, some light soldering may (will) be required.

# https://templates.blakadder.com/cloudfree_SWM1.html
# https://templates.blakadder.com/milfra_MFA05.html

# | GPIO   | Component |
# | ------ | --------- |
# | GPIO0  | button |
# | GPIO5  | motion |
# | GPIO12 | relay |
# | GPIO13 | blue led |
# | GPIO14 | light sensor |
# | GPIO16 | green led |

# GPIO16 boots HIGH which means the green led is ON.
# This is an issue because of the green led takes precendence over the blue led
# To deal with this, GPIO16 must be set LOW after boot which is done using the output component.
# This component defaults to OFF so the user DOES NOT need to use
#    (I) output.turn_off
#     or (II) digitalWrite(16, LOW) after boot




substitutions:
  node_name: cloudfree-motion-light-switch
  friendly_name: CloudFree Motion Light Switch


esphome:
  name: ${node_name}
  build_path: ./build/${node_name}
  comment: CloudFree SWM1 Motion Light Switch
  name_add_mac_suffix: true


esp8266:
  board: esp01_1m


wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: ${node_name}_AP
    password: !secret wifi_password
    ap_timeout: 3min


api:
  encryption:
    key: !secret esphome_encryption_key
  reboot_timeout: 0s


captive_portal:

improv_serial:

logger:

ota:


button:
  - platform: restart
    id: restart_button
    name: "${friendly_name} Restart"

  - platform: safe_mode
    id: restart_button_safe_mode
    name: "${friendly_name} Restart (Safe Mode)"


text_sensor:
  - platform: version
    name: "${friendly_name} ESPHome Version"

  - platform: wifi_info
    ip_address:
      name: "${friendly_name} IP Address"
    mac_address:
      name: "${friendly_name} MAC Address"


number:
  - platform: template # time the relay is ON when triggered by motion
    id: motion_delay
    name: ${friendly_name} Motion Delay
    optimistic: true
    restore_value: true
    entity_category: config
    step: 5
    min_value: 15
    max_value: 300
    initial_value: 30
    mode: box
    unit_of_measurement: s

  - platform: template # time the relay is ON when triggered by button
    id: button_delay
    name: ${friendly_name} Button Delay
    optimistic: true
    restore_value: true
    entity_category: config
    step: 5
    min_value: 60
    max_value: 600
    initial_value: 180
    mode: box
    unit_of_measurement: s

  - platform: template # cooldown time when physical button is pressed
    id: motion_cooldown
    name: ${friendly_name} Motion Cooldown
    optimistic: true
    restore_value: true
    entity_category: config
    step: 5
    min_value: 10
    max_value: 300
    initial_value: 60
    mode: box
    unit_of_measurement: s


output:
  - platform: gpio # green LED
    id: green_led
    pin: GPIO16


light:
  - platform: status_led # blue LED
    id: blue_status
    name: ${friendly_name} Blue LED
    pin:
      number: GPIO13
      inverted: true
    effects:
      - strobe:
          name: Fast Flash
          colors:
            - state: true
              duration: 250ms
            - state: false
              duration: 250ms


binary_sensor:
  - platform: gpio # physical button
    id: relay_button
    pin:
      number: GPIO0
      mode: INPUT_PULLUP
      inverted: True
    on_multi_click:
      - timing: # toggle relay & motion / button timeouts
          - ON for at most 1s
          - OFF for at least 0.2s
        then:
          - switch.toggle: relay
          - if:
              condition:
                - switch.is_on: motion_enabled
              then:
                - script.execute: cooldown
              else:
                if:
                  condition:
                    not:
                      - script.is_running: cooldown
                  then:
                    - script.execute: button_timeout
          - delay: 100ms
          - wait_until:
              condition:
                - not:
                    script.is_running: cooldown
                - not:
                    script.is_running: button_timeout
          - if:
              condition:
                - binary_sensor.is_off: motion
              then:
                - switch.turn_off: relay
      - timing: # enable / disable motion
          - ON for 2s to 5s
        then:
          - script.execute: motion_toggle
      - timing: # software restart
          - ON for 6s to 9s
        then:
          - button.press: restart_button
      - timing: # software restart into safe mode
          - ON for at least 10s
        then:
          - button.press: restart_button_safe_mode

  - platform: gpio # motion sensor
    id: motion
    name: ${friendly_name} Motion
    pin:
      number: GPIO5
      inverted: true
    device_class: motion
    filters:
      - delayed_off: 5s
    on_press:
      - script.stop: motion_timeout
      - if:
          condition:
            - switch.is_on: motion_enabled
          then:
            - switch.turn_on: relay
    on_release:
      - script.execute: motion_timeout

  - platform: gpio # light sensor
    id: daylight
    name: ${friendly_name} Daylight
    pin: GPIO14
    device_class: light
    filters:
      - delayed_on: 5s
      - delayed_off: 5s
    on_press:
      - if:
          condition:
            - switch.is_on: nightlight_enabled
          then:
            - light.turn_off: blue_status
    on_release:
      - if:
          condition:
            - switch.is_on: nightlight_enabled
          then:
            - light.turn_on: blue_status


switch:
  - platform: gpio # relay
    id: relay
    name: ${friendly_name}
    pin: GPIO12

  - platform: template # enable / disable motion
    id: motion_enabled
    name: ${friendly_name} Motion Enabled
    restore_state: true
    optimistic: true
    entity_category: config
    device_class: switch

  - platform: template # enable / disable nightlight
    id: nightlight_enabled
    name: ${friendly_name} Nightlight Enabled
    restore_state: true
    optimistic: true
    entity_category: config
    device_class: switch


script:
  # not in motion sensor on_release because of an issue with on_press not cancelling the delay
  - id: motion_timeout
    mode: restart
    then:
      # subtract 5 for the delayed_off of the motion sensor
      - delay:  !lambda 'return (id(motion_delay).state - 5) * 1000;'
      - if:
          condition:
            - switch.is_on: motion_enabled
          then:
            - switch.turn_off: relay

  - id: motion_toggle
    mode: queued
    then:
      - switch.toggle: motion_enabled
      - if:
          condition:
            - switch.is_off: relay
          then:
            - light.turn_on:
                id: blue_status
                effect: Fast Flash
            - delay: 1600ms
            - light.turn_off: blue_status

  # if mode: restart, this causes motion to not be re-enabled
  - id: cooldown
    mode: single 
    then:
      - switch.turn_off: motion_enabled
      - delay: !lambda 'return id(motion_cooldown).state * 1000;'
      - switch.turn_on: motion_enabled

  - id: button_timeout
    mode: restart
    then:
      - delay: !lambda 'return id(button_delay).state * 1000;'

[EDIT: include yaml file]

5 Likes