Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06b259cb1b | ||
|
|
a355f64d1a | ||
|
|
5c29cdd52f | ||
|
|
e772c1a351 | ||
|
|
e6f004e811 | ||
|
|
aa929478f6 | ||
|
|
ae17892441 |
No files matched your search
@@ -0,0 +1,91 @@
|
||||
# Wake Up Light II notes
|
||||
|
||||
ESPHome firmware for a Moes Wake Up Light II (Tuya PID `ya39qahrcdhvxowz`), running fully local. This repo is public, so never commit secrets, Wi-Fi details or device keys.
|
||||
|
||||
## Layout
|
||||
|
||||
- `wake-up-light-ii.yaml`: main config.
|
||||
- `alarm_block.yaml`: controls for one alarm, included 4 times.
|
||||
- `alarm_day.yaml`: one weekday switch, included 7 times per alarm.
|
||||
- `components/uart`: ESPHome 2026.10.2's UART component with `patches/wbr3-pa13-pa14-uart.patch` applied. Recheck it when ESPHome updates.
|
||||
|
||||
- `server-example.yaml`: the short YAML that goes on an ESPHome server.
|
||||
- `secrets.yaml`: local only, ignored by git. Needs `wifi_ssid`, `wifi_password`, `ap_password`, `api_encryption_key`.
|
||||
|
||||
## Releasing
|
||||
|
||||
1. Set the `ref` in `wake-up-light-ii.yaml`'s `external_components` to the new tag, then commit and tag that commit.
|
||||
2. Push the branch and the tag. On the owner's PC the first push can fail authentication, and a second try works.
|
||||
3. Update `ref` in the server's YAML, then press Install. OTA works, and the lamp restarts by itself.
|
||||
|
||||
Build from a short folder path: Windows path limits break the libsodium build otherwise.
|
||||
|
||||
## Hardware
|
||||
|
||||
- WBR3 module (RTL8720CF, 2 MiB flash), talking TuyaMCU at 9600 8N1 on PA13 (RX) and PA14 (TX).
|
||||
- Knock sensor: a switch between 3.3V and PA18, using the internal pull-down.
|
||||
- UART flashing needs the module desoldered, because PA00 is on the underside. Adapter TX to PA15, RX to PA16, plus GND and a solid 3.3V. Hold PA00 at 3.3V, then tap CEN to GND. PA13 must not be pulled low.
|
||||
- Serial reads with `ltchiptool` run at about 3 KB/s, so a full 2 MiB backup takes about 16 minutes.
|
||||
- If the serial port says "access denied", another app has it. On the owner's PC that was SignalRGB.
|
||||
|
||||
## Data model
|
||||
|
||||
From Tuya's definition for a sibling product (tuya-local issue #3821). See the README's corrections section for the byte layouts of DP127, DP128 and DP107.
|
||||
|
||||
| DP | Meaning |
|
||||
|---|---|
|
||||
| 101, 102 | Main light, brightness 10-1000 |
|
||||
| 103 | Clock, ASCII HHMMSS |
|
||||
| 104 | Display: 0 off, 1 day, 2 night, 3 auto |
|
||||
| 105, 106 | Radio on, volume 1-16 |
|
||||
| 107 | Stations found, current station |
|
||||
| 109, 122, 123, 124 | Alarms 1 to 4 on |
|
||||
| 116, 117 | Snooze minutes 8-15, snooze action enum |
|
||||
| 121, 128 | Sunset on, sunset settings |
|
||||
| 125 | Online time sync |
|
||||
| 126 | Radio scan |
|
||||
| 127 | Alarm settings, 48 bytes on this unit |
|
||||
| 129, 132 | Ambient light on, colour enum |
|
||||
| 130 | Snooze |
|
||||
| 131 | 24-hour clock |
|
||||
|
||||
## Observed behaviour
|
||||
|
||||
- A raw UART capture of a ring, radio, scan and sunset showed only heartbeats and normal datapoint frames. No other message types, and no datapoints beyond these 22.
|
||||
- There is no "ringing" datapoint. A ring starts with DP101, 105, 121, 129 and 130 all OFF in one burst (3 of 3 rings). Arming an alarm inside its sunrise window sends only DP101, 121 and 129.
|
||||
- The stop and volume buttons send nothing to the chip, and neither did the window where a ring should have stopped by itself. So a hand-stopped alarm can't be detected without extra hardware.
|
||||
- A knock during a ring snoozes it. DP130 then stays ON. Outside an alarm it returns to OFF at once.
|
||||
- DP127 writes are ignored while an alarm is snoozed.
|
||||
- A mode without light sets brightness to 0, and a light mode with brightness 0 falls back to no light, so the firmware sets a level when choosing a light mode.
|
||||
- Byte tests on DP127 with Alarm 4 off: time, days, ring duration, volume, sunrise and (in light modes) brightness are stored as written, with no range check, so the controls must limit them. The time's high byte keeps only its low 4 bits.
|
||||
- Byte 5 is bits: 0 = light, 1 = radio. Above 3 is ignored.
|
||||
- Byte 6: writing 8 or more turns on the radio bit and sets the sound to 1. It's locked at 1 in radio modes.
|
||||
- Byte 8 isn't per alarm. Every DP127 write sets all 4 to the current radio station, so there's no per-alarm station control.
|
||||
- Byte 10 is forced to 0 without the light bit, and writing 0 clears the light bit.
|
||||
- Byte 11: above 1 becomes 1.
|
||||
- Byte 4 is the ring length in minutes: set to 10, a ring ran from 18:16 to 18:26 and the owner saw it stop.
|
||||
- Sound 0 is silent. In Sound + Light mode, the light still came on and no sound played.
|
||||
- Alarm sounds, identified by ear: 1 birds chirping, 2 beach (water and birds), 3 galaxy twinkles, 4 piano and birds, 5 happy harp or high piano, 6 old mechanical alarm clock, 7 old digital alarm clock. Names are in `alarm_block.yaml`. Sunset's sounds 1 to 4 haven't been checked, so they keep their numbers.
|
||||
- Radio Volume and station writes are ignored with the radio off. With it on, both work, and the station stays selected after turning it off.
|
||||
- Keep `default_transition_length` at 0. A transition sends about 50 MCU writes a second.
|
||||
- LibreTiny before v1.14.0 can hang after a software restart or OTA until powered off for about 30 seconds (LibreTiny issue #396). The config pins v1.14.0. Drop the pin once ESPHome defaults to it or newer.
|
||||
- "Last Restart Reason" reports Power-On even after software restarts.
|
||||
- On 2026-11-08, after about 2.5 days of uptime, the chip stopped receiving anything from the MCU while its own writes still went out. The owner saw Ambient Light turn on but not off, and MCU Link was OFF. A software restart fixed it. Since v1.0.4 the firmware restarts itself after 5 minutes without an MCU report, but only if the link worked earlier in that boot. The cause isn't known; suspects are the patched UART0 on PA13/PA14 or a LibreTiny serial issue.
|
||||
|
||||
## Status
|
||||
|
||||
Verified:
|
||||
- Alarm and sunset settings are echoed by the MCU.
|
||||
- Wednesday-only rang on a Wednesday, which fits bit 0 = Monday. A Tuesday-only silent test was skipped.
|
||||
- Sunset starts and stops. Its sound was heard, and a glow was seen but not clearly caused by it.
|
||||
- A manual scan found 2 stations, while a scan started from the firmware found 0.
|
||||
- Next/Previous Station and Radio Station change the MCU's station, with wrap-around. Audio on them wasn't confirmed: the owner heard no radio signal.
|
||||
- Home Assistant is used as the time source when connected, with public NTP as the fallback.
|
||||
|
||||
Not tested:
|
||||
- Radio alarms.
|
||||
- Running without internet, or without Home Assistant.
|
||||
- Bedtime Fade and double knock on the real light.
|
||||
- Whether Ambient Color and Snooze Action labels match what the lamp does.
|
||||
|
||||
Decided against for now: an Alarm Ringing sensor, and a web UI password.
|
||||
@@ -140,13 +140,13 @@ Copy `server-example.yaml` to the server and add `wifi_ssid`, `wifi_password`, `
|
||||
|
||||
Tuya's data model for this family was posted in [tuya-local issue #3821](https://github.com/make-all/tuya-local/issues/3821) for the sibling product `rslo8vqc1xjtaoy9`. It matches what this unit reports, and it replaces the older notes below where they differ.
|
||||
|
||||
- **DP127** is 48 bytes on the unit tested here: 12 bytes per alarm, 4 alarms. Logs cut it off at 16 bytes, which likely explains the older 16-byte notes. Bytes: 0 enabled; 1-2 minutes since midnight; 3 repeat days (bit 0 = Monday, 0 = one time); 4 ring duration; 5 mode (0 sound, 1 sound + light, 2 radio, 3 radio + light); 6 sound; 7 volume; 8 radio station; 9 sunrise minutes; 10 brightness after sunrise; 11 snooze (0 allowed, 1 not).
|
||||
- **DP127** is 48 bytes on the unit tested here: 12 bytes per alarm, 4 alarms. Logs cut it off at 16 bytes, which likely explains the older 16-byte notes. Bytes: 0 enabled; 1-2 minutes since midnight; 3 repeat days (bit 0 = Monday, 0 = one time); 4 ring duration; 5 mode (bit 0 light, bit 1 radio); 6 sound 0-7; 7 volume; 8 current radio station, shared by all alarms; 9 sunrise minutes; 10 brightness after sunrise; 11 snooze (0 allowed, 1 not). The older "8 = FM" sound is really the MCU turning on the radio bit.
|
||||
- **DP128** is 10 bytes: 0 unused; 1 mode, as above; 2 sound 1-4; 3 volume; 4 sound duration; 5 radio station; 6 radio duration; 7 start brightness; 8 sunset duration; 9 snooze. Bytes 4, 6 and 8 should match.
|
||||
- **DP107** is stations found by a scan, then the current station. **DP126** starts (1) or ends (0) a channel search.
|
||||
- **DP117** and **DP132** are enums on this unit, so values count from 0. DP132 runs cycle, red, orange, yellow, green, cyan, blue, purple.
|
||||
- **DP125** is online time synchronization. **DP130** is snooze.
|
||||
|
||||
Observed behaviour on this unit: a mode without light sets brightness to 0, and a light mode with brightness 0 falls back to no light. Alarm stations were reset to 1 while no stations had been scanned. DP127 writes are ignored while an alarm is snoozed. DP130 stays on after snoozing a ringing alarm and returns to off at once otherwise. Default light transitions flood the MCU with writes, so keep them at 0.
|
||||
Observed behaviour on this unit: a mode without light sets brightness to 0, and a light mode with brightness 0 falls back to no light. Every DP127 write sets byte 8 of all four alarms to the current radio station. Most other bytes are stored without any range check. DP127 writes are ignored while an alarm is snoozed. DP130 stays on after snoozing a ringing alarm and returns to off at once otherwise. Default light transitions flood the MCU with writes, so keep them at 0.
|
||||
|
||||
## DP127 alarm structure
|
||||
|
||||
@@ -418,22 +418,17 @@ That manual is for a related model/revision, so use it as behavioral reference r
|
||||
|
||||
## TODO / worthwhile additions
|
||||
|
||||
For this lamp, the most worthwhile additions are:
|
||||
Done: alarm data for all 4 alarms, Alarm 2 settings, sunset settings, ambient colour, snooze controls, grouped web UI, Home Assistant API, Home Assistant as a local time source, next/previous station, and diagnostics including versions and MCU link status.
|
||||
|
||||
Still open:
|
||||
|
||||
- **Finish DP127 decoding:** weekday-bit order and unknown bytes 4, 8 and 11.
|
||||
- **Find Alarm 2 extended settings:** sound, volume, wake-light level and sunrise duration are stored somewhere other than the DP127 middle block on this unit.
|
||||
- **Fully decode DP128:** make sunset/sleep duration, brightness, sound/radio choice and volume writable.
|
||||
- **Decode DP107:** turn the raw FM payload into actual frequency/preset information and add previous/next/scan controls; verify DP126.
|
||||
- **Ambient/color lamp control:** verify DP132 on this revision and expose color/effect controls rather than only DP129 power.
|
||||
- **Snooze:** verify DP116/117/130 from the exact-PID definition and expose them safely.
|
||||
- **Better local web UI:** move to Web Server v3 and group Light / Clock / Alarm 1 / Alarm 2 / Radio / Sunset / Diagnostics.
|
||||
- **Fully autonomous schedules:** add software-only extra alarms or weekday schedules without depending on Tuya cloud/app limits.
|
||||
- **Better clock correction:** configurable local NTP server, LAN-only synchronization, and optional drift measurement/correction.
|
||||
- **Astronomical sunrise/sunset:** use ESPHome's local sun calculations for real dusk/dawn behavior.
|
||||
- **Home Assistant native API:** optional `api:` support while retaining the standalone web UI.
|
||||
- **Diagnostics:** Wi-Fi RSSI, uptime, reboot reason, ESPHome/LibreTiny version, Tuya-link state and raw-packet viewer.
|
||||
- **Identify IC1:** obtain a board with readable top marking or otherwise identify the main appliance MCU.
|
||||
- **Upstream the UART fix:** replace the local PA13/PA14 workaround when ESPHome gains proper LibreTiny alternate-UART pin mapping.
|
||||
- **Astronomical sunrise/sunset:** use ESPHome's local sun calculations for real dusk/dawn behavior.
|
||||
- **Clock drift:** optional drift measurement and correction.
|
||||
- **Fully autonomous schedules:** software-only alarms, if 4 hardware alarms ever aren't enough.
|
||||
- **Identify IC1:** obtain a board with readable top marking or otherwise identify the main appliance MCU.
|
||||
|
||||
FM frequency isn't available: DP107 only holds the station count and current station number.
|
||||
|
||||
## Safety / recovery notes
|
||||
|
||||
|
||||
+20
-39
@@ -117,14 +117,13 @@ select:
|
||||
name: "Alarm ${n} Sound"
|
||||
options:
|
||||
- "Off"
|
||||
- "Sound 1"
|
||||
- "Sound 2"
|
||||
- "Sound 3"
|
||||
- "Sound 4"
|
||||
- "Sound 5"
|
||||
- "Sound 6"
|
||||
- "Sound 7"
|
||||
- "FM Radio"
|
||||
- "Birds"
|
||||
- "Beach"
|
||||
- "Galaxy Twinkles"
|
||||
- "Piano and Birds"
|
||||
- "Happy Harp"
|
||||
- "Mechanical Alarm Clock"
|
||||
- "Digital Alarm Clock"
|
||||
update_interval: 2s
|
||||
web_server:
|
||||
sorting_group_id: group_alarm_${n}
|
||||
@@ -132,22 +131,21 @@ select:
|
||||
lambda: |-
|
||||
if (!id(alarm_raw_valid)) return {};
|
||||
uint8_t s = id(alarm_raw)[${o} + 6];
|
||||
if (s == 0) return std::string("Off");
|
||||
if (s == 8) return std::string("FM Radio");
|
||||
if (s >= 1 && s <= 7) return std::string("Sound ") + std::to_string(s);
|
||||
return {};
|
||||
static const char *const names[8] = {"Off", "Birds", "Beach", "Galaxy Twinkles", "Piano and Birds",
|
||||
"Happy Harp", "Mechanical Alarm Clock", "Digital Alarm Clock"};
|
||||
if (s > 7) return {};
|
||||
return std::string(names[s]);
|
||||
set_action:
|
||||
- lambda: |-
|
||||
if (!id(alarm_raw_valid)) return;
|
||||
uint8_t value = 0;
|
||||
if (x == "Sound 1") value = 1;
|
||||
else if (x == "Sound 2") value = 2;
|
||||
else if (x == "Sound 3") value = 3;
|
||||
else if (x == "Sound 4") value = 4;
|
||||
else if (x == "Sound 5") value = 5;
|
||||
else if (x == "Sound 6") value = 6;
|
||||
else if (x == "Sound 7") value = 7;
|
||||
else if (x == "FM Radio") value = 8;
|
||||
if (x == "Birds") value = 1;
|
||||
else if (x == "Beach") value = 2;
|
||||
else if (x == "Galaxy Twinkles") value = 3;
|
||||
else if (x == "Piano and Birds") value = 4;
|
||||
else if (x == "Happy Harp") value = 5;
|
||||
else if (x == "Mechanical Alarm Clock") value = 6;
|
||||
else if (x == "Digital Alarm Clock") value = 7;
|
||||
id(alarm_raw)[${o} + 6] = value;
|
||||
- script.execute: send_alarm_settings
|
||||
|
||||
@@ -174,7 +172,8 @@ number:
|
||||
- platform: template
|
||||
id: alarm_${n}_wake_brightness
|
||||
name: "Alarm ${n} Wake Light"
|
||||
min_value: 1
|
||||
# Reads 0 in modes without light, where the MCU ignores changes.
|
||||
min_value: 0
|
||||
max_value: 20
|
||||
step: 1
|
||||
update_interval: 2s
|
||||
@@ -211,24 +210,6 @@ number:
|
||||
id(alarm_raw)[${o} + 4] = static_cast<uint8_t>(x);
|
||||
- script.execute: send_alarm_settings
|
||||
|
||||
- platform: template
|
||||
id: alarm_${n}_radio_station
|
||||
name: "Alarm ${n} Radio Station"
|
||||
min_value: 1
|
||||
max_value: 60
|
||||
step: 1
|
||||
update_interval: 2s
|
||||
web_server:
|
||||
sorting_group_id: group_alarm_${n}
|
||||
sorting_weight: 9
|
||||
lambda: |-
|
||||
if (!id(alarm_raw_valid)) return {};
|
||||
return static_cast<float>(id(alarm_raw)[${o} + 8]);
|
||||
set_action:
|
||||
- lambda: |-
|
||||
if (!id(alarm_raw_valid)) return;
|
||||
id(alarm_raw)[${o} + 8] = static_cast<uint8_t>(x);
|
||||
- script.execute: send_alarm_settings
|
||||
|
||||
- platform: template
|
||||
id: alarm_${n}_sunrise_duration
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@ substitutions:
|
||||
packages:
|
||||
lamp:
|
||||
url: https://mangavalk.com/mangavalk/esphome-wake-up-light-ii.git
|
||||
ref: v1.0.0
|
||||
ref: v1.0.4
|
||||
files: [wake-up-light-ii.yaml]
|
||||
refresh: 1d
|
||||
+112
-20
@@ -22,7 +22,7 @@ external_components:
|
||||
- source:
|
||||
type: git
|
||||
url: https://mangavalk.com/mangavalk/esphome-wake-up-light-ii.git
|
||||
ref: v1.0.0
|
||||
ref: v1.0.4
|
||||
components: [uart]
|
||||
refresh: 1d
|
||||
|
||||
@@ -136,6 +136,12 @@ globals:
|
||||
restore_value: no
|
||||
initial_value: '0'
|
||||
|
||||
# When the MCU last sent its once-a-minute clock report.
|
||||
- id: last_mcu_report
|
||||
type: uint32_t
|
||||
restore_value: no
|
||||
initial_value: '0'
|
||||
|
||||
# Last display state the schedule applied: -1 none, 0 day, 1 night.
|
||||
- id: display_schedule_last
|
||||
type: int
|
||||
@@ -165,14 +171,31 @@ time:
|
||||
- script.execute: sync_lamp_clock
|
||||
- script.execute: apply_display_schedule
|
||||
|
||||
on_time:
|
||||
- seconds: 0
|
||||
minutes: 0
|
||||
then:
|
||||
- script.execute: sync_lamp_clock
|
||||
- seconds: 0
|
||||
then:
|
||||
- script.execute: apply_display_schedule
|
||||
# Home Assistant is preferred when connected, so the clock doesn't need internet.
|
||||
- platform: homeassistant
|
||||
id: ha_time
|
||||
on_time_sync:
|
||||
then:
|
||||
- delay: 2s
|
||||
- script.execute: sync_lamp_clock
|
||||
- script.execute: apply_display_schedule
|
||||
|
||||
interval:
|
||||
- interval: 1h
|
||||
then:
|
||||
- script.execute: sync_lamp_clock
|
||||
- interval: 60s
|
||||
then:
|
||||
- script.execute: apply_display_schedule
|
||||
# After about 2.5 days the chip once stopped receiving the MCU's replies,
|
||||
# while sending still worked. A restart fixed it, so restart after 5 quiet
|
||||
# minutes. Only if the link worked earlier this boot, to avoid a restart loop.
|
||||
- lambda: |-
|
||||
uint32_t last = id(last_mcu_report);
|
||||
if (last != 0 && millis() - last > 300000) {
|
||||
ESP_LOGW("mcu", "No report from the MCU for %u s, restarting", (unsigned) ((millis() - last) / 1000));
|
||||
App.safe_reboot();
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Tuya MCU
|
||||
@@ -188,6 +211,7 @@ tuya:
|
||||
datapoint_type: string
|
||||
then:
|
||||
- lambda: |-
|
||||
id(last_mcu_report) = millis();
|
||||
if (x.size() != 6) return;
|
||||
auto d = [](char c) -> int { return (c >= '0' && c <= '9') ? c - '0' : -1; };
|
||||
int h1=d(x[0]), h2=d(x[1]), m1=d(x[2]), m2=d(x[3]), s1=d(x[4]), s2=d(x[5]);
|
||||
@@ -251,14 +275,19 @@ tuya:
|
||||
# [00] enabled
|
||||
# [01:02] time = minutes since midnight, big-endian
|
||||
# [03] repeat days: bit 0 = Monday ... bit 6 = Sunday, 0 = one time
|
||||
# [04] ring duration (Tuya says 10-20, this lamp reports 30)
|
||||
# [05] mode: 0=sound, 1=sound+light, 2=radio, 3=radio+light
|
||||
# [06] sound (this project also observed 8=FM)
|
||||
# [07] sound volume 1..16
|
||||
# [08] radio station 1..60
|
||||
# [09] sunrise lead time in minutes, 10..60
|
||||
# [10] brightness after sunrise, 1..20
|
||||
# [11] snooze: 0=allowed, 1=not allowed
|
||||
# [04] ring duration (Tuya says 10-20, this lamp reports 30; any value is kept)
|
||||
# [05] mode bits: bit 0=light, bit 1=radio. Values above 3 are ignored.
|
||||
# [06] sound 0..7, named in alarm_block.yaml. Writing 8 or more turns on the
|
||||
# radio bit and resets it to 1.
|
||||
# Locked at 1 in radio modes.
|
||||
# [07] volume 1..16 (any value is kept)
|
||||
# [08] radio station. Not per alarm: every write sets all 4 to the current
|
||||
# radio station, so don't try to set it here.
|
||||
# [09] sunrise lead time in minutes, 10..60 (any value is kept)
|
||||
# [10] brightness after sunrise, 1..20. Forced to 0 without the light bit, and
|
||||
# 0 clears the light bit.
|
||||
# [11] snooze: 0=allowed, 1=not allowed. Values above 1 become 1.
|
||||
# The MCU doesn't range-check most bytes, so the controls must.
|
||||
- sensor_datapoint: 127
|
||||
datapoint_type: raw
|
||||
then:
|
||||
@@ -329,7 +358,8 @@ script:
|
||||
then:
|
||||
- lambda: |-
|
||||
if (!id(display_schedule_enabled).state) return;
|
||||
auto now = id(network_time).now();
|
||||
auto now = id(ha_time).now();
|
||||
if (!now.is_valid()) now = id(network_time).now();
|
||||
if (!now.is_valid()) return;
|
||||
int start = id(display_night_start).hour * 60 + id(display_night_start).minute;
|
||||
int end = id(display_night_end).hour * 60 + id(display_night_end).minute;
|
||||
@@ -370,6 +400,21 @@ script:
|
||||
call.set_transition_length(0);
|
||||
call.perform();
|
||||
|
||||
- id: radio_step
|
||||
mode: queued
|
||||
parameters:
|
||||
step: int
|
||||
then:
|
||||
- lambda: |-
|
||||
if (!id(radio_valid) || id(radio_total) == 0) {
|
||||
ESP_LOGW("radio", "No stations found yet; run Radio Scan first");
|
||||
return;
|
||||
}
|
||||
int total = id(radio_total);
|
||||
int next = ((id(radio_current) - 1 + step) % total + total) % total + 1;
|
||||
std::vector<uint8_t> data = {id(radio_total), static_cast<uint8_t>(next)};
|
||||
id(tuya_mcu).set_raw_datapoint_value(107, data);
|
||||
|
||||
- id: radio_sleep
|
||||
mode: restart
|
||||
then:
|
||||
@@ -426,9 +471,10 @@ script:
|
||||
mode: restart
|
||||
then:
|
||||
- lambda: |-
|
||||
auto now = id(network_time).now();
|
||||
auto now = id(ha_time).now();
|
||||
if (!now.is_valid()) now = id(network_time).now();
|
||||
if (!now.is_valid()) {
|
||||
ESP_LOGW("clock", "No valid network time; use the Lamp Clock control in the web UI");
|
||||
ESP_LOGW("clock", "No valid time source; use the Lamp Clock control in the web UI");
|
||||
return;
|
||||
}
|
||||
char buf[7];
|
||||
@@ -932,6 +978,20 @@ text_sensor:
|
||||
sorting_group_id: group_device
|
||||
sorting_weight: 4
|
||||
|
||||
- platform: version
|
||||
name: "ESPHome Version"
|
||||
hide_timestamp: true
|
||||
web_server:
|
||||
sorting_group_id: group_device
|
||||
sorting_weight: 6
|
||||
|
||||
- platform: libretiny
|
||||
version:
|
||||
name: "LibreTiny Version"
|
||||
web_server:
|
||||
sorting_group_id: group_device
|
||||
sorting_weight: 7
|
||||
|
||||
###############################################################################
|
||||
# Device health
|
||||
###############################################################################
|
||||
@@ -969,6 +1029,16 @@ sensor:
|
||||
###############################################################################
|
||||
|
||||
binary_sensor:
|
||||
# The MCU reports its clock every minute, so silence means the link is down.
|
||||
- platform: template
|
||||
name: "MCU Link"
|
||||
device_class: connectivity
|
||||
web_server:
|
||||
sorting_group_id: group_device
|
||||
sorting_weight: 0.5
|
||||
lambda: |-
|
||||
return id(last_mcu_report) != 0 && millis() - id(last_mcu_report) < 150000;
|
||||
|
||||
- platform: gpio
|
||||
name: "Knock"
|
||||
icon: "mdi:gesture-tap"
|
||||
@@ -1049,6 +1119,28 @@ button:
|
||||
on_press:
|
||||
- lambda: id(tuya_mcu).force_set_boolean_datapoint_value(126, false);
|
||||
|
||||
- platform: template
|
||||
name: "Next Station"
|
||||
icon: "mdi:skip-next"
|
||||
web_server:
|
||||
sorting_group_id: group_radio
|
||||
sorting_weight: 2.7
|
||||
on_press:
|
||||
- script.execute:
|
||||
id: radio_step
|
||||
step: 1
|
||||
|
||||
- platform: template
|
||||
name: "Previous Station"
|
||||
icon: "mdi:skip-previous"
|
||||
web_server:
|
||||
sorting_group_id: group_radio
|
||||
sorting_weight: 2.6
|
||||
on_press:
|
||||
- script.execute:
|
||||
id: radio_step
|
||||
step: -1
|
||||
|
||||
- platform: template
|
||||
name: "Start Radio Sleep Timer"
|
||||
icon: "mdi:timer-outline"
|
||||
|
||||
Reference in new issue
Block a user