substitutions:
  # -----------------------------
  # Config
  # -----------------------------
  devicename:           fingerprintdoor
  reader_rx_pin:        GPIO16
  reader_tx_pin:        GPIO17
  reader_sensor_pin:    GPIO5
  door_sensor_pin:      GPIO4

# --------------------------------------------------------

esphome:
  name: $devicename

esp32:
  board: nodemcu-32s
  framework:
    type: arduino

# Enable logging
logger:

ota:
  password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Fingerprintdoor Fallback Hotspot"
    password: !secret ota_password

captive_portal:

web_server:
  port: 80

# MQTT Actions    
mqtt:
  broker: !secret mqtt_ip
  username: !secret mqtt_user
  password: !secret mqtt_password
  client_id: $devicename
  id: mqtt_client
  discovery: false
  on_json_message:
    topic: $devicename/led/command
    then:
      # Debug
      - lambda: |-
          std::string scol = x["color"];
          std::string seff = x["effect"];
          std::string sspd = x["speed"];
          std::string scnt = x["count"];

          const char * col = scol.c_str();
          const char * eff = seff.c_str();
          const char * spd = sspd.c_str();
          const char * cnt = scnt.c_str();

          ESP_LOGD("main", "JSON Cmd received: Color: %s | Effect: %s | Speed:%s | Count:%s", col, eff, spd , cnt);
      - fingerprint_grow.aura_led_control:
          state: !lambda |-
            std::string str = x["effect"];
            std::transform(str.begin(), str.end(), str.begin(), ::toupper);
            
            uint8_t eff  = 0x03;
            if(str == "BREATHING")
            {
              eff = 0x01;
              return eff;
            }
            else if (str == "FLASHING"){
              eff = 0x02;
              return eff;
            }
            else if (str == "ALWAYS_ON"){
              eff = 0x03;
              return eff;
            }
            else if (str == "ALWAYS_OFF"){
              eff = 0x04;
              return eff;
            }
            else if (str == "GRADUAL_ON"){
              eff = 0x05;
              return eff;
            }
            else if (str == "GRADUAL_OFF"){
              eff = 0x06;
              return eff;
            }
            return 0;
          speed: !lambda return x["speed"];
          color: !lambda |-
            std::string str = x["color"];
            std::transform(str.begin(), str.end(), str.begin(), ::toupper);
            
            uint8_t color  = 0x01;
            if(str == "RED")
            {
              color = 0x01;
              return color;
            }
            else if (str == "BLUE"){
              color = 0x02;
              return color;
            }
            else if (str == "PURPLE"){
              color = 0x03;
              return color;
            }
            else if (str == "GREEN"){
              color = 0x04;
              return color;
            }
            else if (str == "YELLOW"){
              color = 0x05;
              return color;
            }
            else if (str == "CYAN"){
              color = 0x06;
              return color;
            }
            else if (str == "WHITE"){
              color = 0x07;
              return color;
            }
            return color;
          count: !lambda return x["count"];
      - text_sensor.template.publish:
          id: led_color
          state: !lambda |-
            std::string str = x["effect"];
            std::string color = x["color"];
            std::transform(str.begin(), str.end(), str.begin(), ::toupper);
            if(str == "ALWAYS_OFF" || str == "GRADUAL_OFF")
            {
              return "off";
            }
            else
            { 
              return color;
            }
      # show on webserver
      - text_sensor.template.publish:
          id: led_state
          state: !lambda |-
            std::string str = x["effect"];
            std::transform(str.begin(), str.end(), str.begin(), ::toupper);
            if(str == "ALWAYS_OFF" || str == "GRADUAL_OFF")
            {
              return "off";
            }
            else
            { 
              return "on";
            }
      - mqtt.publish_json:
          topic: $devicename/led/
          qos: 1
          #retain: true
          payload: |-
            root["led_state"] = id(led_state).state;
            root["color"] = id(led_color).state;

# Fingerpint functions
text_sensor:
  # ENROLL
  - platform: mqtt_subscribe
    name: "MQTT Sub Fingerprint enroll"
    id: mqtt_sub_enr
    qos: 0
    topic: $devicename/enroll
    on_value:
      - if:
          condition:
            lambda: 'return atoi(id(mqtt_sub_enr).state.c_str()) > 0;'
          then:
            - lambda: |-
                ESP_LOGD("main", "Enroll Finger ID: %s", x.c_str());
            - fingerprint_grow.aura_led_control:
                state: BREATHING
                speed: 100
                color: WHITE
                count: 4
            - fingerprint_grow.enroll:
                finger_id: !lambda return atoi(x.c_str());
                num_scans: 2
            - text_sensor.template.publish:
                id: fingerprint_state
                state: "Place a finger on the reader"
          else:
          - logger.log: "Error, try again!"
        

  # CANCEL ENROLL      
  - platform: mqtt_subscribe
    name: "MQTT Sub Fingerprint cancel"
    id: mqtt_sub_abrt
    qos: 0
    topic: $devicename/cancel_enroll
    on_value:
      - text_sensor.template.publish:
            id: fingerprint_state
            state: "cancelling enrollment"
      - fingerprint_grow.cancel_enroll:
      
  # DELETE ID
  - platform: mqtt_subscribe
    name: "MQTT Sub Fingerprint delete"
    id: mqtt_sub_del
    qos: 0
    topic: $devicename/delete
    on_value:
      - lambda: |-
            ESP_LOGD("main", "Delete Finger ID: %s", x.c_str());
      - fingerprint_grow.delete:
          finger_id: !lambda return atoi(x.c_str());
          # Update the template text sensor for visual feedback
      - text_sensor.template.publish:
          id: fingerprint_state
          state: !lambda 'return "Deleted " + to_string(x.c_str());'
      - fingerprint_grow.aura_led_control:
          state: FLASHING
          speed: 50
          color: WHITE
          count: 2

  # DELETE ALL!!!
  - platform: mqtt_subscribe
    name: "MQTT Sub Fingerprint delete all"
    id: mqtt_sub_del_all
    qos: 0
    topic: $devicename/deleteall
    on_value:
      - fingerprint_grow.delete_all:
      # Update the template text sensor for visual feedback
      - text_sensor.template.publish:
          id: fingerprint_state
          state: !lambda 'return "Deleted ALL";'
      - fingerprint_grow.aura_led_control:
          state: FLASHING
          speed: 50
          color: WHITE
          count: 6

  - platform: template
    name: "Fingerprint Log"
    id: fingerprint_state

  - platform: template
    name: "LED color"
    id: led_color

  - platform: template
    name: "LED state"
    id: led_state         

#########################

sensor:
  - platform: wifi_signal
    name: "WiFi Signal Sensor"
    update_interval: 90s
    state_topic: $devicename/rssi
  - platform: uptime
    name: Uptime Sensor

uart:
  rx_pin: $reader_rx_pin
  tx_pin: $reader_tx_pin
  baud_rate: 57600

binary_sensor:
  - platform: gpio
    pin: $reader_sensor_pin
    name: Touch Sensor
    device_class: motion
    state_topic: $devicename/touch
    filters:
      - invert:
      - delayed_on: 20ms
      - delayed_off: 400ms
      - delayed_on_off: 100ms

  # Door Sensor - GPIO connected to GND over reed sensor    
  - platform: gpio
    pin:
      number: $door_sensor_pin
      mode:
        input: true
        pullup: true
    name: "Main Door"
    device_class: door
    state_topic: $devicename/door
    filters:
      - delayed_on: 10ms
    

# BUTTONS
button:
  - platform: restart
    name: "ESP Restart"
    id: restart_button

fingerprint_grow:
  sensing_pin: $reader_sensor_pin
  on_finger_scan_matched:
    - fingerprint_grow.aura_led_control:
        state: BREATHING
        speed: 200
        color: GREEN
        count: 1
    - lambda: |-
          std::string fid = to_string(finger_id);
          std::string conf = to_string(confidence);
          const char * cfid = fid.c_str();
          const char * cconf = conf.c_str();

          ESP_LOGD("main", "Authorized finger %s, confidence %s", cfid, cconf );
      # Pushing a tag_scanned event based on finger_id only if confidence is greater than ...
    - if:
        condition:
          lambda: 'return confidence < 200;'
        then:
          - logger.log: "Known finger found"
          # todo - push confidence and finger ID to MQTT
          - mqtt.publish_json:
                topic: $devicename/finger/
                qos: 1
                payload: |-
                  root["finger_id"] = to_string(finger_id);
                  root["confidence"] = to_string(confidence);
                  root["msg"] = "Authorized finger " + to_string(finger_id) + ", confidence " + to_string(confidence);
  on_finger_scan_unmatched:
    - fingerprint_grow.aura_led_control:
        state: FLASHING
        speed: 25
        color: RED
        count: 2
    - lambda: |-
          ESP_LOGD("main", "Unauthorized finger");
    - mqtt.publish_json:
                topic: $devicename/finger/
                qos: 1
                payload: |-
                  root["msg"] = "Unauthorized finger";
  on_enrollment_scan:
    - fingerprint_grow.aura_led_control:
        state: FLASHING
        speed: 25
        color: BLUE
        count: 2
    - fingerprint_grow.aura_led_control:
        state: ALWAYS_ON
        speed: 0
        color: PURPLE
        count: 0
    - text_sensor.template.publish:
        id: fingerprint_state
        state: !lambda 'return "Enrolling into slot " + to_string(finger_id) + ", scanned " + to_string(scan_num) + " time(s)"; '   
  on_enrollment_done:
    - fingerprint_grow.aura_led_control:
        state: BREATHING
        speed: 100
        color: BLUE
        count: 2
    - text_sensor.template.publish:
        id: fingerprint_state
        state: !lambda 'return "Enrolled into slot " + to_string(finger_id);'

  on_enrollment_failed:
    - fingerprint_grow.aura_led_control:
        state: FLASHING
        speed: 25
        color: RED
        count: 6
    - if:
        condition:
          not:
            # Checks if enroll canceled
            text_sensor.state:
              id: fingerprint_state
              state: "cancelling enrollment"
        then:
          - text_sensor.template.publish:
              id: fingerprint_state
              state: !lambda 'return "Failed to enroll into slot " + to_string(finger_id);'
          # Retry enrollment into the same slot
          - delay: 3s
          - text_sensor.template.publish:
              id: fingerprint_state
              state: !lambda 'return "Retrying enrollment into slot " + to_string(finger_id) + " in 3 seconds...";'
          - delay: 3s
          - fingerprint_grow.enroll: !lambda 'return finger_id;'
        else:
          - logger.log: "Enrollment aborted"
          - text_sensor.template.publish:
              id: fingerprint_state
              state: "Enrollment canceled"