feature-requests icon indicating copy to clipboard operation
feature-requests copied to clipboard

Set clock on Xiaomi LYWSD02

Open kain opened this issue 4 years ago • 19 comments

Describe the problem you have/What new integration you would like

Synchronize clock on Xiaomi BLE Thermometer LYWSD02 Model via SNTP

Please describe your use case for this integration and alternatives you've tried:

Before you can use this device you must setup it using smartphone and official app to setup clock and timezone. But if this FR will be implemented this step can be skipped. After adding device to ESPhome it can be synced via SNTP and get timezone automatically (from HomeAssistant or configured in YAML via options).

Additional context

Setting timezone can be skipped or forced to another value by supplying option in YAML config. My LYWSD02 clock drift to +1 minute in 1 month, so periodical SNTP syncing would be good too. Syncing frequency can be set in YAML option too. I found working code to set clock and timezone for this device at Mikhail Baranov's github: https://github.com/h4/lywsd02

kain avatar Mar 17 '20 21:03 kain

As a temporary work around for those who do not want to install MiHome you can use GadgetBridge on Android to set the time. Hopefully this gets added as setting the time each month is a bit of a pain.

HarrisonPace avatar Jun 19 '20 05:06 HarrisonPace

I have posted a bounty on this. https://www.bountysource.com/issues/90271090-set-clock-on-xiaomi-lywsd02

regnets avatar Oct 11 '20 11:10 regnets

Another temporary workaround: I've created a one-time script to update the clock that you can run from the browser https://saso5.github.io/LYWSD02-clock-sync/

saso5 avatar Dec 24 '20 12:12 saso5

I have tried https://saso5.github.io/LYWSD02-clock-sync/ but it does not work for New Zealand in the summer time as we are GMT + 13 hours and the script only works up to + 12 hours, any way to adjust it?

mivilleb avatar Jan 14 '21 18:01 mivilleb

It would probably be best to have this conversation on my repo, so as not to spam other people here, but as I'm already replaying, I might as well answer your question :)

I don't think it's my script that has the problem, but the clock doesn't recognize +13 GMT. Maybe try setting it to -11?

saso5 avatar Jan 15 '21 07:01 saso5

Thank you so much, -11 worked, brilliant!

mivilleb avatar Jan 15 '21 09:01 mivilleb

It would probably be best to have this conversation on my repo, so as not to spam other people here, but as I'm already replaying, I might as well answer your question :)

I don't think it's my script that has the problem, but the clock doesn't recognize +13 GMT. Maybe try setting it to -11?

Your script works well but I am having a trouble with MCH-C303 (the 2nd generation LYWSD02) not recognizing negative time zones. -1 converts to +11 AND plus 16 minutes. -2 becomes +10 AND plus 16 minutes etc. I tried reporting it to Xiaomi but they aren't fixing this. Any workaround on this?

I live in -5 and I set +7 to use it for now.

taninc avatar Feb 02 '21 22:02 taninc

I would be happy to test any beta version in my setup. Unfortunately I do not have the spare time to implement this feature myself.

ChefkeGremmen avatar Mar 12 '21 13:03 ChefkeGremmen

Can someone help me in setting the timezone for India which is +530. Any help is much appreciated. Also hope that if I reconnect to the Mi Home App it doesn't reset it to +5.

suhail8487 avatar May 22 '21 18:05 suhail8487

I use Gadgetbridge app, just connect and wait for time to sync.

Joseris avatar May 22 '21 18:05 Joseris

I did that but it only work with timezones which doesn't have 30mins offset. The only app that seems to do the job is MijiaTemp. But I want to use something which is permanent and can be included in Mi Home app

suhail8487 avatar May 22 '21 18:05 suhail8487

These last few comments are not related to esphome. You're in the wrong place for that.

ssieb avatar May 24 '21 04:05 ssieb

Guys, any idea if its possible to create a Custom Switch with this funcionality? I'm trying to do that, but I think that if I extend BLEClient or BLEClientSwitch I can't get access to the write GATT stuff...

marciogranzotto avatar Nov 08 '21 21:11 marciogranzotto

A little addition to the original request. For me it does not necessarily have to sync with SNTP, with HomeAssistant is also fine.

ChefkeGremmen avatar Jan 21 '22 09:01 ChefkeGremmen

I'm also looking for a way to automate the time adjustment... Is it possible to run @saso5's web script from a Home Assistant automation, in an unattended manner? Any thoughts would be appreciated!

TheHomieFox avatar Apr 21 '22 10:04 TheHomieFox

Hi, it would be awsome this could be implemented now with either the new ble proxy capability with home assistant. Anyone knows what thee codes to use to do this?

finipini avatar Sep 07 '22 17:09 finipini

especially now the ble proxy can be active. I'm using https://github.com/sullin/hyg to set clock atm.

lolorc avatar Oct 06 '22 17:10 lolorc

especially now the ble proxy can be active. I'm using https://github.com/sullin/hyg to set clock atm.

Thank you for this finding! Now I'm able to sync clocks time too and do it unattended. Also thanks goes to the author of this mini tool.

Quick how-to if anybody needs it:

  • clone repository: git clone https://github.com/sullin/hyg
  • cd hyg
  • sudo apt install build-essential
  • sudo apt install --no-install-recommends libbluetooth-dev
  • make
  • find your device MAC address: sudo hcitool lescan
  • ./hyg -c -t 02_0042 E7:2E:XX:XX:XX:XX
  • add to crontab (optionally): crontab -e
  • adjust and paste to the end (run at night on 26th day of month): 0 5 26 * * /home/kain/hyg/hyg -c -t 02_0042 E7:2E:XX:XX:XX:XX &>/dev/null

kain avatar Oct 06 '22 19:10 kain

especially now the ble proxy can be active. I'm using https://github.com/sullin/hyg to set clock atm.

Thank you for this finding! Now I'm able to sync clocks time too and do it unattended. Also thanks goes to the author of this mini tool.

Quick how-to if anybody needs it:

  • clone repository: git clone https://github.com/sullin/hyg
  • cd hyg
  • sudo apt install build-essential
  • sudo apt install --no-install-recommends libbluetooth-dev
  • make
  • find your device MAC address: sudo hcitool lescan
  • ./hyg -c -t 02_0042 E7:2E:XX:XX:XX:XX
  • add to crontab (optionally): crontab -e
  • adjust and paste to the end (run at night on 26th day of month): 0 5 26 * * /home/kain/hyg/hyg -c -t 02_0042 E7:2E:XX:XX:XX:XX &>/dev/null

That,s interesting. Can that be done with ble_client ?

finipini avatar Oct 11 '22 20:10 finipini

wold be interested as well to have it as a service in Homeassistant via BLE Proxy, or directly in ESP Home what ever fits better

hwinkel avatar Nov 03 '22 16:11 hwinkel

wold be interested as well to have it as a service in Homeassistant via BLE Proxy, or directly in ESP Home what ever fits better

Yes it would. Maybe we should make this PR there too ?!

finipini avatar Nov 22 '22 17:11 finipini

following.

fire1ce avatar Dec 23 '22 20:12 fire1ce

Hey, I am successfully updating my clock via SNTP directly with an ESP32 using ESPHome.

time:
  - platform: sntp
    id: sntp_time
    servers: "192.168.2.254"
    timezone: "Europe/Berlin"
    on_time:
      - seconds: 0
        minutes: 0
        hours: 3
        days_of_week: SUN
        then:
          - switch.turn_on: lywsd02_ble_connection

esp32_ble_tracker:
  
ble_client:
  - mac_address: E7:2E:00:73:4C:C5
    id:  lywsd02_clock
    on_connect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Connected to lywsd02_clock!");
        - delay: 20s
        - ble_client.ble_write:
            id: lywsd02_clock
            service_uuid: ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6 
            characteristic_uuid: EBE0CCB7-7A0A-4B0C-8A1A-6FF2997DA3A6
            value: !lambda |-
                auto time = id(sntp_time).utcnow();
                uint8_t time_byte1 =  time.timestamp & 0x000000ff;
                uint8_t time_byte2 = (time.timestamp & 0x0000ff00) >> 8;
                uint8_t time_byte3 = (time.timestamp & 0x00ff0000) >> 16;
                uint8_t time_byte4 = (time.timestamp & 0xff000000) >> 24;
                uint8_t timezone_byte = time.timezone_offset() / 3600;
                return {time_byte1, time_byte2, time_byte3, time_byte4, timezone_byte};
        - delay: 20s
        - switch.turn_off: lywsd02_ble_connection
    on_disconnect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Disconnected from lywsd02_clock!");

switch:
  - platform: ble_client
    ble_client_id: lywsd02_clock
    id: "lywsd02_ble_connection"
    restore_mode: ALWAYS_OFF # Disable the client by default, as connection is only triggered via automation

It only connects to the device once a week, then disconnects to save battery. Receiving data works via HomeAssistant with BLE Proxy, so I am only setting the clock manually.

My code is not perfect, I think I could also enable/disable the esp32_ble_tracker via the automation. But I am not sure if that would mess with the bluetooth_proxy.

You could also turn on the lywsd02_ble_connection switch via HomeAssistant and make an automation there. But for me it´s enough that the ESP just silently updates the clock.

Edit: Updated the code to automatically set the timezone and changed the automation to once a week.

ephirial avatar Dec 26 '22 13:12 ephirial

Hey, I am successfully updating my clock via SNTP directly with an ESP32 using ESPHome.

time:
  - platform: sntp
    id: sntp_time
    servers: "192.168.2.254"
    timezone: "Europe/Berlin"

esp32_ble_tracker:
  
ble_client:
  - mac_address: E7:2E:00:73:4C:C5
    id:  lywsd02_clock
    on_connect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Connected to lywsd02_clock!");
        - delay: 20s
        - ble_client.ble_write:
            id: lywsd02_clock
            service_uuid: ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6 
            characteristic_uuid: EBE0CCB7-7A0A-4B0C-8A1A-6FF2997DA3A6
            value: !lambda |-
                auto time = id(sntp_time).utcnow();
                uint8_t time_byte1 =  time.timestamp & 0x000000ff;
                uint8_t time_byte2 = (time.timestamp & 0x0000ff00) >> 8;
                uint8_t time_byte3 = (time.timestamp & 0x00ff0000) >> 16;
                uint8_t time_byte4 = (time.timestamp & 0xff000000) >> 24;
                uint8_t timezone_byte = 0x01;
                return {time_byte1, time_byte2, time_byte3, time_byte4, timezone_byte};
        - delay: 20s
        - switch.turn_off: lywsd02_ble_connection
    on_disconnect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Disconnected from lywsd02_clock!");

switch:
  - platform: ble_client
    ble_client_id: lywsd02_clock
    id: "lywsd02_ble_connection"
    restore_mode: ALWAYS_OFF # Disable the client by default, as connection is only triggered via automation

interval:
  - interval: 4h
    then:
      - switch.turn_on: lywsd02_ble_connection

It only connects to the device within the specified interval, sets the clock, then disconnects to save battery. Receiving data works via HomeAssistant with BLE Proxy, so I am only setting the clock manually. The timezone has to be set in the variable timezone_byte.

My code is not perfect, I think I could also enable/disable the esp32_ble_tracker via the automation. But I am not sure if that would mess with the bluetooth_proxy.

You could also turn on the lywsd02_ble_connection switch via HomeAssistant and make an automation there. But for me it´s enough that the ESP just silently updates the clock every x hours. My interval of 4 hours also might drain the battery too much, once a week is probably fine. But I was still testing this recently.

That works great, Nice job.

Althow i have one problem, can,t get right my time zone ( Europe/Lisbon) . I tryed diferent things but always get One more hour then it should

finipini avatar Dec 28 '22 09:12 finipini

Althow i have one problem, can,t get right my time zone ( Europe/Lisbon) . I tryed diferent things but always get One more hour then it should

It's because of this:

uint8_t timezone_byte = 0x01;

This is the timezone offset, so in this case UTC+1. If you're in UTC timezone, as is the case now for Europe/Lisbon, you need to set this byte to 0.

koenvervloesem avatar Dec 28 '22 09:12 koenvervloesem

Ok, Will try thanks.

finipini avatar Dec 28 '22 11:12 finipini

Thanks @ephirial for your code.

I have LYWSD02 for couple of years and only needed to sync clock after time zone has changed to and from DST. So I modified that code to sync time zone from HomeAssistant. Just had to subtract 30 from received offset to set correct time zone, not sure if it is format or conversion issue:

uint8_t timezone_byte = (time.timezone_offset() & 0x000000ff) - 30;

Also added trigger to sync clock just every Sunday night (this time is in UTC) and not repeatedly every 4 hours:

time:
  - platform: homeassistant
    id: homeassistant_time
    on_time:
      - seconds: 0
        minutes: 0
        hours: 3
        days_of_week: SUN
        then:
          - switch.turn_on: lywsd02_ble_connection

Joseris avatar Dec 28 '22 14:12 Joseris

Thanks @Joseris for your addition! I did not know that you could get the timezone via time.timezone_offset(), of course that is more elegant than setting it manually. When I look at the variable time.timezone_offset(), I get the offset in seconds. So I think this would just have to be divided by 3600?

uint8_t timezone_byte = time.timezone_offset() / 3600;

This works for me, maybe you can try it with your timezone? If you live in a timezone with 30 minute offset, the offset has to be added to the time variable beforehand (you could just add 1800 seconds to time.timestamp). The clock only supports full hour offsets. I think I will update my previous comment with this change and the weekly trigger, my 4 hour trigger is too much.

ephirial avatar Dec 28 '22 15:12 ephirial

You are right, time.timezone_offset() is in seconds. I'm in UTC+2 and dividing by 3600 works for me. Thanks.

Joseris avatar Dec 28 '22 15:12 Joseris

Can someone provide the fully working ESPhome yaml, with the recent changes, eventually as a gist or repo ?

hwinkel avatar Dec 28 '22 15:12 hwinkel