devices.esphome.io
Alfawise SJ-7
Alfawise SJ-7
Device Type: miscElectrical Standard: globalBoard: esp8266
Alfawise SJ-7 (Essential oil diffuser)
Working
- All essential oil diffuser related controls (ON/OFF; LOW/HIGH; Timer 1H/3H/6H).
- Lava lamp lighting activation, fast/slow color change, I can add stop color change button if needed.
- OTA upgrade.
Not Working
- Use the light like a classic bulb (just on of off and choose a color).
Installation
Flashing
For flashing, you have to solder wires like this:
Use U0TXD, U0RXD, GND (and VCC if you dont want to use the diffuser power supply).
Make sure to ground GPIO0 during boot.
You can use the ESPHome add-on from Home Assistant Community Add-ons
Basic Configuration
# Basic Configsubstitutions: name: alfawise friendly_name: "alfawise SJ-7"
#commands receive_timer1h: "55:AA:03:1F:09:01:2B" receive_timer3h: "55:AA:03:1F:09:02:2C" receive_timer6h: "55:AA:03:1F:09:03:2D" receive_high: "55:AA:03:1F:07:02:2A" receive_low: "55:AA:03:1F:07:01:29" receive_lava_lamp: "55:AA:03:1F:02:01:24" receive_rainbow_slow: "55:AA:03:1F:0C:01:2E" receive_rainbow_fast: "55:AA:03:1F:0C:03:30" receive_lava_lamp_on_diff: "55:AA:02:04:01:06" receive_diff_on_switch: "55:AA:02:03:01:05" receive_light_off_switch: "55:AA:02:04:00:05" receive_light_diff_off_esp: "55:AA:02:1F:0E:2E" receive_diff_off_esp: "55:AA:03:1F:07:00:28" receive_light_off_esp: "55:AA:03:1F:02:00:23"
esphome: name: ${name} includes: - uart_read_line_sensor.h - fake_fan_output.h
on_boot: priority: -100.0 then: - switch.turn_off: power_high - lambda: id(${name}_fan).speed = 0; - switch.turn_off: lava_lamp - switch.turn_on: wifi_blinkin_slow - delay: 5s - switch.turn_off: wifi_blinkin_slow
esp8266: board: esp01_1mdebug:# Enable logginglogger: baud_rate: 0 level: debug esp8266_store_log_strings_in_flash: False
ota: password: "xxx"
uart: id: uart_bus tx_pin: GPIO1 rx_pin: GPIO3 baud_rate: 9600 stop_bits: 1# debug:# direction: BOTH# dummy_receiver: false# after:# delimiter: "\n"# bytes: 256# sequence:# - lambda: UARTDebug::log_hex(direction, bytes, ':');
wifi: ssid: !secret wifi_ssid password: !secret wifi_password ap:
api:web_server: port: 80
# Sync time with Home Assistant.time: - platform: homeassistant id: homeassistant_time
- platform: sntp on_time: # Every 1 seconds - seconds: /1 then: - if: condition: and: - switch.is_off: power_low - switch.is_off: power_high - fan.is_on: ${name}_fan then: - switch.turn_on: update_fan_speed else: - if: condition: and: - switch.is_on: power_low - switch.is_off: power_high - or: - lambda: |- if (id(${name}_fan).speed == 2) { return true; }else{ return false; } - lambda: |- if (id(${name}_fan).speed == 0) { return true; }else { return false; } then: - switch.turn_on: update_fan_speed else: - if: condition: and: - switch.is_off: power_low - switch.is_on: power_high - or: - lambda: |- if (id(${name}_fan).speed ==1) { return true; }else { return false; } - lambda: |- if (id(${name}_fan).speed == 0) { return true; }else { return false; } then: - switch.turn_on: update_fan_speed
# Text sensors with UART received information.text_sensor: - platform: custom lambda: |- auto uart_readline = new UartReadLineSensor(id(uart_bus)); App.register_component(uart_readline); return {uart_readline}; text_sensors: id: "uart_readline" name: ${name} serial
- platform: wifi_info ip_address: name: ${name} ip ssid: name: ${name} ssid bssid: name: ${name} bssid - platform: version name: ${name} ESPHome Version
sensor: # Uptime sensor - platform: uptime name: ${name} uptime unit_of_measurement: days update_interval: 300s accuracy_decimals: 1 filters: - multiply: 0.000011574 # WiFi Signal sensor - platform: wifi_signal name: ${name} signal update_interval: 60s accuracy_decimals: 0
switch: - platform: template id: timer1h name: ${name} Timer 1H icon: mdi:timer-sand-empty disabled_by_default: false optimistic: false assumed_state: false lambda: |- if (id(uart_readline).state == "${receive_timer1h}") { return true; } else if(id(uart_readline).state == "${receive_timer3h}") { return false; } else if(id(uart_readline).state == "${receive_timer6h}") { return false; } else if(id(uart_readline).state == "${receive_light_off_switch}") { return false; } else if(id(uart_readline).state == "${receive_light_diff_off_esp}") { return false; } else if(id(uart_readline).state == "${receive_diff_off_esp}") { return false; } else { return {}; } turn_on_action: then: - if: condition: and: - fan.is_off: ${name}_fan then: - fan.turn_on: id: ${name}_fan speed: 1 - delay: 500ms - uart.write: [0x55, 0xAA, 0x03, 0x09, 0x01, 0x00, 0x0c] - delay: 1h - uart.write: [0x55, 0xaa, 0x03, 0x0e, 0x00, 0x00, 0x10]
- platform: template id: timer3h name: ${name} Timer 3H icon: mdi:timer-sand-complete disabled_by_default: false optimistic: false assumed_state: false lambda: |- if (id(uart_readline).state == "${receive_timer3h}") { return true; } else if(id(uart_readline).state == "${receive_timer1h}") { return false; } else if(id(uart_readline).state == "${receive_timer6h}") { return false; } else if(id(uart_readline).state == "${receive_light_off_switch}") { return false; } else if(id(uart_readline).state == "${receive_light_diff_off_esp}") { return false; } else if(id(uart_readline).state == "${receive_diff_off_esp}") { return false; } else { return {}; } turn_on_action: then: - if: condition: and: - fan.is_off: ${name}_fan then: - fan.turn_on: id: ${name}_fan speed: 1 - delay: 500ms - uart.write: [0x55, 0xAA, 0x03, 0x09, 0x02, 0x00, 0x0d] - delay: 3h - uart.write: [0x55, 0xaa, 0x03, 0x0e, 0x00, 0x00, 0x10] turn_off_action: then: - if: condition: and: - fan.is_on: ${name}_fan then: - uart.write: [0x55, 0xAA, 0x03, 0x09, 0x01, 0x00, 0x0c]
- platform: template id: timer6h name: ${name} Timer 6H icon: mdi:timer-sand disabled_by_default: false optimistic: false assumed_state: false lambda: |- if (id(uart_readline).state == "${receive_timer6h}") { return true; } else if(id(uart_readline).state == "${receive_timer1h}") { return false; } else if(id(uart_readline).state == "${receive_timer3h}") { return false; } else if(id(uart_readline).state == "${receive_light_off_switch}") { return false; } else if(id(uart_readline).state == "${receive_light_diff_off_esp}") { return false; } else if(id(uart_readline).state == "${receive_diff_off_esp}") { return false; } else { return {}; } turn_on_action: then: - if: condition: and: - fan.is_off: ${name}_fan then: - fan.turn_on: id: ${name}_fan speed: 1 - delay: 500ms - uart.write: [0x55, 0xAA, 0x03, 0x09, 0x03, 0x00, 0x0e] - delay: 6h - uart.write: [0x55, 0xaa, 0x03, 0x0e, 0x00, 0x00, 0x10]
turn_off_action: then: - if: condition: and: - fan.is_on: ${name}_fan then: - uart.write: [0x55, 0xAA, 0x03, 0x09, 0x01, 0x00, 0x0c]
- platform: template id: power_high icon: mdi:fan disabled_by_default: true optimistic: false assumed_state: false lambda: |- if (id(uart_readline).state == "${receive_high}") { return true; } else if (id(uart_readline).state == "${receive_diff_on_switch}") { return true; } else if(id(uart_readline).state == "${receive_light_off_switch}") { return false; } else if(id(uart_readline).state == "${receive_light_diff_off_esp}") { return false; } else if(id(uart_readline).state == "${receive_diff_off_esp}") { return false; } else { return {}; } turn_on_action: - uart.write: [0x55, 0xAA, 0x03, 0x07, 0x02, 0x00, 0x0B] turn_off_action: - uart.write: [0x55, 0xaa, 0x03, 0x07, 0x00, 0x00, 0x09]
on_turn_on: - switch.template.publish: id: power_low state: OFF on_turn_off: - switch.template.publish: id: power_low state: OFF
- platform: template disabled_by_default: true id: power_low icon: mdi:fan optimistic: false assumed_state: false lambda: |- if (id(uart_readline).state == "${receive_low}") { return true; } else if(id(uart_readline).state == "${receive_light_off_switch}") { return false; } else if(id(uart_readline).state == "${receive_light_diff_off_esp}") { return false; } else if(id(uart_readline).state == "${receive_diff_off_esp}") { return false; } else { return {}; } turn_on_action: - uart.write: [0x55, 0xaa, 0x03, 0x07, 0x01, 0x00, 0x0A]
turn_off_action: - uart.write: [0x55, 0xaa, 0x03, 0x07, 0x00, 0x00, 0x09]
on_turn_on: - switch.template.publish: id: power_high state: OFF on_turn_off: - switch.template.publish: id: power_high state: OFF
- platform: template disabled_by_default: true id: wifi_blinkin_slow icon: mdi:led-on optimistic: true assumed_state: true turn_on_action: - uart.write: [0x55, 0xaa, 0x03, 0x03, 0x03, 0x00, 0x08] turn_off_action: - uart.write: [0x55, 0xaa, 0x03, 0x03, 0x01, 0x00, 0x06]
- platform: template name: ${name} Lava Lamp id: lava_lamp icon: mdi:lava-lamp optimistic: false assumed_state: false lambda: |- if (id(uart_readline).state == "${receive_lava_lamp}") { return true; } else if (id(uart_readline).state == "${receive_lava_lamp_on_diff}") { return true; } else if(id(uart_readline).state == "${receive_light_off_switch}") { return false; } else if(id(uart_readline).state == "${receive_light_diff_off_esp}") { return false; } else if(id(uart_readline).state == "${receive_light_off_esp}") { return false; } else { return {}; } turn_on_action: - uart.write: [0x55, 0xaa, 0x03, 0x02, 0x00, 0x01, 0x05] - uart.write: [0x55, 0xaa, 0x03, 0x02, 0x01, 0x01, 0x06] turn_off_action: - uart.write: [0x55, 0xaa, 0x03, 0x02, 0x00, 0x01, 0x05] on_turn_on: - switch.template.publish: id: rainbow_fast state: OFF - switch.template.publish: id: rainbow_slow state: OFF on_turn_off: - switch.template.publish: id: rainbow_fast state: OFF - switch.template.publish: id: rainbow_slow state: OFF
- platform: template name: ${name} Rainbow Slow id: rainbow_slow icon: mdi:lightbulb-multiple optimistic: false assumed_state: false lambda: |- if (id(uart_readline).state == "${receive_rainbow_slow}") { return true; } else if(id(uart_readline).state == "${receive_light_off_switch}") { return false; } else if(id(uart_readline).state == "${receive_light_diff_off_esp}") { return false; } else if(id(uart_readline).state == "${receive_light_off_esp}") { return false; } else { return {}; } turn_on_action: - uart.write: [0x55, 0xaa, 0x03, 0x02, 0x00, 0x01, 0x05] - uart.write: [0x55, 0xaa, 0x03, 0x0c, 0x01, 0x00, 0x0f]
turn_off_action: - uart.write: [0x55, 0xaa, 0x03, 0x02, 0x00, 0x01, 0x05]
on_turn_on: - switch.template.publish: id: rainbow_fast state: OFF - switch.template.publish: id: lava_lamp state: OFF on_turn_off: - switch.template.publish: id: rainbow_fast state: OFF - switch.template.publish: id: lava_lamp state: OFF
- platform: template name: ${name} Rainbow Fast id: rainbow_fast icon: mdi:lightbulb-group optimistic: false assumed_state: false lambda: |- if (id(uart_readline).state == "${receive_rainbow_fast}") { return true; } else if(id(uart_readline).state == "${receive_light_off_switch}") { return false; } else if(id(uart_readline).state == "${receive_light_diff_off_esp}") { return false; } else if(id(uart_readline).state == "${receive_light_off_esp}") { return false; } else { return {}; } turn_on_action: - uart.write: [0x55, 0xaa, 0x03, 0x02, 0x00, 0x01, 0x05] - uart.write: [0x55, 0xaa, 0x03, 0x0c, 0x03, 0x00, 0x11]
turn_off_action: - uart.write: [0x55, 0xaa, 0x03, 0x02, 0x00, 0x01, 0x05]
on_turn_on: - switch.template.publish: id: lava_lamp state: OFF - switch.template.publish: id: rainbow_slow state: OFF on_turn_off: - switch.template.publish: id: lava_lamp state: OFF - switch.template.publish: id: rainbow_slow state: OFF
- platform: template disabled_by_default: true id: update_fan_speed optimistic: True turn_on_action: then: - delay: 500ms - if: condition: and: - switch.is_off: power_low - switch.is_off: power_high then: - fan.turn_off: ${name}_fan else: - if: condition: and: - switch.is_on: power_low - switch.is_off: power_high then: - fan.turn_on: id: ${name}_fan speed: 1 else: - if: condition: and: - switch.is_off: power_low - switch.is_on: power_high then: - fan.turn_on: id: ${name}_fan speed: 2 - switch.turn_off: update_fan_speed
output: - platform: custom type: float outputs: id: fanoutput lambda: |- auto ${name}_fan = new FakeFanOutput(); App.register_component(${name}_fan); return {${name}_fan};
fan: - platform: speed output: fanoutput id: ${name}_fan name: "${friendly_name} Fan" speed_count: 2 on_turn_on: then: - if: condition: lambda: return (id(${name}_fan).speed == 0); then: - fan.turn_on: id: ${name}_fan speed: 1 - switch.turn_on: power_low - delay: 500ms - switch.turn_on: timer1h else: - if: condition: lambda: return (id(${name}_fan).speed == 1); then: - switch.turn_on: power_low else: - if: condition: lambda: return (id(${name}_fan).speed == 2); then: - switch.turn_on: power_high - if: condition: and: - switch.is_off: timer1h - switch.is_off: timer3h - switch.is_off: timer6h then: - delay: 500ms - switch.turn_on: timer1h on_turn_off: then: - lambda: id(${name}_fan).speed = 0; - switch.turn_off: power_low - switch.turn_off: power_high on_speed_set: then: - if: condition: and: - lambda: return (id(${name}_fan).speed == 0); - or: - switch.is_on: power_low - switch.is_on: power_high then: - switch.turn_off: power_high - switch.turn_off: power_low else: - if: condition: - lambda: return (id(${name}_fan).speed == 1); - switch.is_off: power_low then: - switch.turn_on: power_low else: - if: condition: - lambda: return (id(${name}_fan).speed == 2); - switch.is_off: power_high then: - switch.turn_on: power_high - if: condition: and: - switch.is_off: timer1h - switch.is_off: timer3h - switch.is_off: timer6h then: - delay: 500ms - switch.turn_on: timer1h
captive_portal:
fake_fan_output.h
#include "esphome.h"using namespace esphome;
class FakeFanOutput : public Component, public FloatOutput { public: void write_state(float state) override { if (state < 0.1) { // OFF
} else if (state < 0.5) { // low speed
} else { // high speed
} }};
uart_read_line_sensor.h
#include "esphome.h"
static int pos = 0;char outputBuffer[3];const int max_line_length = 80;static char buffer[max_line_length];int j = 0;int startMarker = 0x55;int secondMarker = 0xAA;int timeOut = 50;bool receiveUntilTimeout;bool valuesending = false;int timeReceived;
class UartReadLineSensor : public Component, public UARTDevice, public TextSensor { public: UartReadLineSensor(UARTComponent *parent) : UARTDevice(parent) {}
// Helper function for converting byte value to 2-digit hex string void byte2HexStr(byte val, char* outputBuffer){
const char HEX_DIGITS[17] = "0123456789ABCDEF";
byte upper_nibble_index = (val & 0xf0) >> 4; byte lower_nibble_index = val & 0xf;
outputBuffer[0] = HEX_DIGITS[upper_nibble_index]; outputBuffer[1] = HEX_DIGITS[lower_nibble_index]; outputBuffer[2] = '\0'; }
void setup() override { // nothing to do here }
int sendvalue(char* buffer, bool valuesending) { valuesending = true; std::string myStrObject; myStrObject = ""; // buffer size for(int i = max_line_length; i > 0; i--) { if (j == 0) { if (buffer[i] > 0 ) { j = i + 1; break; } } } // convert to hex for(int i = 0; i < j; i++) { byte2HexStr(buffer[i], outputBuffer); myStrObject += outputBuffer; // add separator except for the last element if(i < j - 1) { myStrObject += ":"; } } // publish result publish_state(myStrObject.c_str()); // reset var j = 0; pos = 0; for( int i = 0; i < max_line_length + 1; ++i ) buffer[i] = (char)0; valuesending = false; return 1; }
// Store values int storevalue(char* buffer, int readch, bool UntilTimeout, bool valuesending) { while (valuesending == true) { delay(200); } buffer[pos++] = readch; buffer[pos] = 0; if (UntilTimeout) { receiveUntilTimeout = true; } timeReceived = millis(); return 1; }
void loop() override { int readch; if (available() >= 1 && !receiveUntilTimeout) { readch = Serial.read(); if (readch == startMarker) { storevalue(buffer, readch, true, valuesending); } } if (receiveUntilTimeout) { if (Serial.available() > 0) { readch = Serial.read(); if (readch == startMarker) { sendvalue(buffer,valuesending); } if (readch == secondMarker) { if (pos > 1 ) { sendvalue(buffer,valuesending); storevalue(buffer, 0x55, false, valuesending); } } storevalue(buffer, readch, false, valuesending); } else //Serial.available == 0 and nothing to read { if (millis() - timeReceived >= timeOut) { receiveUntilTimeout = false; sendvalue(buffer,valuesending); } } } }};
Home Assistant integration
Lovelace card
For lovelace card, you need this HACS Addons :
- custom:vertical-stack-in-card https://github.com/ofekashery/vertical-stack-in-card
- custom:fan-percent-button-row https://github.com/finity69x2/fan-percent-button-row
- custom:paper-buttons-row https://github.com/jcwillox/lovelace-paper-buttons-row
File diffuser.png need to be in this path : config/www/
Card config example
type: custom:vertical-stack-in-cardcards: - type: picture-entity entity: switch.schedule_lave_linge image: /local/diffuser.png show_state: false show_name: false tap_action: action: none hold_action: action: none - type: entities entities: - entity: fan.alfawise_sj_7_fan type: custom:fan-percent-button-row name: Diffuser state_color: true isTwoSpeedFan: true customSetpoints: true reverseButtons: true sendStateWithSpeed: false lowPercentage: 50 hiPercentage: 100 width: 35px height: 35px - type: custom:paper-buttons-row buttons: - layout: icon|name icon: mdi:clock-time-two name: Timer style: button: width: 150% justify-content: left tap_action: action: none - entity: switch.alfawise_timer_1h layout: name name: 1H style: button: width: 17% - entity: switch.alfawise_timer_3h layout: name name: 3H style: button: width: 17% - entity: switch.alfawise_timer_6h layout: name name: 6H style: button: width: 17% - type: custom:paper-buttons-row buttons: - layout: icon|name icon: mdi:lightbulb name: Light style: button: width: 150% justify-content: left tap_action: action: none - entity: switch.alfawise_lava_lamp layout: icon style: button: width: 15% - entity: switch.alfawise_rainbow_slow layout: icon style: button: width: 15% - entity: switch.alfawise_rainbow_fast layout: icon style: button: width: 15%
Lovelace card screenshot
Original firmware
I have put a backup of the original firmware, and I also modified the AMA HOME APK but only for reconnect the original firmware to Wifi, ssg360 seems down.
https://github.com/antibill51/Alfawise_SJ-7_HASSIO/tree/master/Original%20firmware
Edit this page on GitHub