Skip to content

Instantly share code, notes, and snippets.

@WarriorRocker
Created December 27, 2022 18:20
Show Gist options
  • Save WarriorRocker/dc26cc361f5826ba3f9aab3237eb269a to your computer and use it in GitHub Desktop.
Save WarriorRocker/dc26cc361f5826ba3f9aab3237eb269a to your computer and use it in GitHub Desktop.
Eufy 11S RoboVac with ESPHome and Home Assistant
# Eufy 11s v0.1.1
substitutions:
# Eufy interface
gpio_ir_pin: GPIO5
gpio_power_pin: GPIO4
gpio_brushes_pin: GPIO0
gpio_vacuum_pin: GPIO13
gpio_charging_pin: GPIO12
gpio_battery_pin: A0
esphome:
name: eufy_r2
platform: ESP8266
board: d1_mini
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Eufy-R2 Fallback Hotspot"
password: !secret cap_password
# Enable Captive Portal for fallback hotspot
captive_portal:
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: !secret eufy_enc_key
# Enable over-the-air updates
ota:
password: !secret ota_password
# Enable web server interface
web_server:
globals:
- id: internal_state
type: float
restore_value: no
initial_value: "0"
binary_sensor:
- platform: gpio
id: "power"
name: "Power"
pin:
number: $gpio_power_pin
mode: INPUT_PULLUP
inverted: True
- platform: gpio
id: "brushes"
name: "Brushes"
pin:
number: $gpio_brushes_pin
mode: INPUT_PULLUP
inverted: True
- platform: gpio
id: "vacuum"
name: "Vacuum"
pin:
number: $gpio_vacuum_pin
mode: INPUT_PULLUP
inverted: True
- platform: gpio
id: "charging"
name: "Charging"
pin:
number: $gpio_charging_pin
mode: INPUT_PULLUP
inverted: True
sensor:
- platform: adc
pin: VCC
id: "vcc_voltage"
name: "VCC Voltage"
update_interval: 60s
- platform: adc
pin: $gpio_battery_pin
id: "battery_voltage"
name: "Battery Voltage"
update_interval: 60s
filters:
- lambda: return x * 9 * 0.77;
- platform: template
id: "battery_level"
name: "Battery Level"
update_interval: 60s
accuracy_decimals: 0
lambda: return min(max((id(battery_voltage).state - 20.5) / 1.7 * 100.0, 0.0), 100.0);
- platform: template
id: "state"
name: "State"
update_interval: 500ms
accuracy_decimals: 0
lambda: |-
id(internal_state) = -1; // Set Unknown state
if (id(power).state == 1) { // Check if power on
id(internal_state) = 1; // Set Idle state
if (id(brushes).state == 1) { // Check if brushes on
id(internal_state) = 3; // Set Cleaning state
if (id(vacuum).state == 0) { // Check if vacuum off
id(internal_state) = 4; // Set Homing state
}
}
else { // Not brushes on
if (id(charging).state == 1) { // Check if charging on
id(internal_state) = 2; // Set Charging State
if (id(battery_level).state >= 100.0) { // Check if fully charged
id(internal_state) = 5; // Set Charged state
}
}
}
}
else { // Not powered on
id(internal_state) = 0; // Set Off state
if (id(charging).state == 1) { // Check if charging on
id(internal_state) = 2; // Set Charging state
if (id(battery_level).state >= 100.0) { // Check if fully charged
id(internal_state) = 5; // Set Charged state
}
}
}
if (id(state).state != id(internal_state)) { // Check if state has changed
return {id(internal_state)}; // Return updated state
}
return {}; // Return no state change
text_sensor:
- platform: template
id: "status"
name: "Status"
update_interval: 500ms
lambda: |-
if ((id(internal_state) == -1) && (id(status).state != "Unknown")) {
return {"Unknown"};
}
if ((id(internal_state) == 0) && (id(status).state != "Off")) {
return {"Off"};
}
if ((id(internal_state) == 1) && (id(status).state != "Idle")) {
return {"Idle"};
}
if ((id(internal_state) == 2) && (id(status).state != "Charging")) {
return {"Charging"};
}
if ((id(internal_state) == 3) && (id(status).state != "Cleaning")) {
return {"Cleaning"};
}
if ((id(internal_state) == 4) && (id(status).state != "Homing")) {
return {"Homing"};
}
if ((id(internal_state) == 5) && (id(status).state != "Charged")) {
return {"Charged"};
}
return {};
remote_transmitter:
pin:
number: $gpio_ir_pin
inverted: True
carrier_duty_percent: 100%
switch:
- platform: template
id: "action_start"
name: "Start"
icon: "mdi:play"
lambda: return (id(state).state == 3);
turn_on_action:
- remote_transmitter.transmit_raw:
carrier_frequency: 38kHz
repeat:
times: 3
code: [
3000, -3000, 500, -500, 500, -1500, 500, -1500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -500, 500, -500,
500, -1500, 500, -500, 500, -1500, 500, -1500, 500, -1500,
500, -500, 500, -500, 500, -500, 500, -500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -1500, 500, -500,
500, -500, 500, -500, 500, -1500, 500, -500, 500, -500,
500, -500, 500, -1500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -500, 500, -500, 500, -500, 500
]
- platform: template
id: "action_stop"
name: "Stop"
icon: "mdi:stop"
lambda: return ((id(state).state == 0) || (id(state).state == 1));
turn_on_action:
- remote_transmitter.transmit_raw:
carrier_frequency: 38kHz
repeat:
times: 3
code: [
3000, -3000, 500, -500, 500, -1500, 500, -1500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -500, 500, -500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -1500, 500, -500,
500, -500, 500, -500, 500, -1500, 500, -500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -1500, 500, -1500, 500, -500,
500, -1500, 500, -1500, 500, -500, 500, -500, 500
]
- platform: template
id: "action_forward"
name: "Forward"
icon: "mdi:chevron-up"
lambda: return false;
turn_on_action:
- remote_transmitter.transmit_raw:
carrier_frequency: 38kHz
code: [
3000, -3000, 500, -500, 500, -1500, 500, -1500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -500, 500, -500,
500, -500, 500, -1500, 500, -500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -500, 500, -500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -500, 500, -1500,
500, -500, 500, -500, 500, -1500, 500, -500, 500, -1500,
500, -1500, 500, -500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -1500, 500, -500, 500, -1500,
500, -500, 500, -1500, 500, -500, 500, -500, 500
]
- platform: template
id: "action_backward"
name: "Backward"
icon: "mdi:chevron-down"
lambda: return false;
turn_on_action:
- remote_transmitter.transmit_raw:
carrier_frequency: 38kHz
code: [
3000, -3000, 500, -500, 500, -1500, 500, -1500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -500, 500, -500,
500, -1500, 500, -1500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -500, 500, -500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -1500, 500, -500,
500, -500, 500, -500, 500, -500, 500, -500, 500, -1500,
500, -1500, 500, -500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -500, 500, -500, 500, -500, 500, -500,
500, -500, 500, -1500, 500, -500, 500, -1500, 500
]
- platform: template
id: "action_left"
name: "Left"
icon: "mdi:chevron-left"
lambda: return false;
turn_on_action:
- remote_transmitter.transmit_raw:
carrier_frequency: 38kHz
code: [
3000, -3000, 500, -500, 500, -1500, 500, -1500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -500, 500, -500,
500, -500, 500, -1500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -500, 500, -500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -1500, 500, -500,
500, -500, 500, -500, 500, -500, 500, -1500, 500, -500,
500, -500, 500, -1500, 500, -500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -1500, 500, -500, 500, -500,
500, -1500, 500, -500, 500, -1500, 500, -500, 500
]
- platform: template
id: "action_right"
name: "Right"
icon: "mdi:chevron-right"
lambda: return false;
turn_on_action:
- remote_transmitter.transmit_raw:
carrier_frequency: 38kHz
code: [
3000, -3000, 500, -500, 500, -1500, 500, -1500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -500, 500, -500,
500, -1500, 500, -1500, 500, -500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -500, 500, -500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -1500, 500, -500,
500, -500, 500, -500, 500, -500, 500, -1500, 500, -1500,
500, -500, 500, -500, 500, -500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -500, 500, -500, 500, -500, 500, -500,
500, -500, 500, -500, 500, -500, 500, -500, 500
]
- platform: template
id: "action_home"
name: "Home"
icon: "mdi:home"
lambda: return ((id(state).state == 2) || (id(state).state == 4) || (id(state).state == 5));
turn_on_action:
- remote_transmitter.transmit_raw:
carrier_frequency: 38kHz
repeat:
times: 3
code: [
3000, -3000, 500, -500, 500, -1500, 500, -1500, 500, -500,
500, -1500, 500, -500, 500, -500, 500, -500, 500, -1500,
500, -1500, 500, -1500, 500, -500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -500, 500, -500, 500, -500,
500, -500, 500, -500, 500, -500, 500, -1500, 500, -1500,
500, -500, 500, -500, 500, -500, 500, -1500, 500, -1500,
500, -500, 500, -1500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -1500, 500, -1500, 500, -1500, 500, -1500,
500, -1500, 500, -500, 500, -1500, 500, -1500, 500, -1500,
500, -500, 500, -1500, 500, -500, 500, -500, 500
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment