Created
November 26, 2022 13:50
-
-
Save luiseduardobrito/d6733a884b0e44996d1c8bec52242ace to your computer and use it in GitHub Desktop.
LYWSD02-clock-sync (https://raw.githubusercontent.com/saso5/saso5.github.io/master/LYWSD02-clock-sync/index.html)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>LYWSD02 Clock sync</title> | |
<meta name="viewport" content="width=480"> | |
</head> | |
<body > | |
<h1>LYWSD02 Clock sync </h1> | |
<h2>Xiaomi Mijia BT4.0 Wireless Smart Electric Digital Clock Indoor & Outdoor Hygrometer Thermometer</h2> | |
<img src="https://imgaz3.staticbg.com/thumb/large/oaupload/banggood/images/74/DF/f05ddb02-4334-48a1-8785-39c4a5d9d9c1.jpg.webp" width="300"/> | |
<fieldset> | |
<legend>Time sync:</legend> | |
<label for="zone">Time zone:</label> | |
<input type="number" id="zone" name="zone" min="-12" max="14" value="0" /><br> | |
<label for="30minOffset">Add 30min offset:</label> | |
<input type="checkbox" id="30minOffset" name="30minOffset" /><br> | |
<button onclick="updateTime()">Update time</button> | |
</fieldset> | |
<fieldset> | |
<legend>Update unit:</legend> | |
<input type="radio" id="c" name="unit" value="0" checked> | |
<label for="c">C</label><br> | |
<input type="radio" id="f" name="unit" value="1"> | |
<label for="f">F</label><br> | |
<button onclick="updateUnit()">Update units</button> | |
</fieldset> | |
<fieldset> | |
<legend>Console:</legend> | |
<div id="console"></div> | |
</fieldset> | |
</br></br> | |
<p> | |
<b>Based on code snippets from: </b> | |
<ul> | |
<li><a href="https://web.dev/bluetooth/" target="_blank" rel="noopener">Web.dev</a> | |
<li><a href="https://github.com/h4/lywsd02/blob/master/lywsd02/client.py" target="_blank" rel="noopener">lywsd02</a> | |
</ul> | |
</br> | |
<b>Special thanks to: </b> | |
<ul> | |
<li><a href="https://github.com/dearmash" target="_blank" rel="noopener">Harold De Armas</a> for adding C/F support | |
<li><a href="https://www.linkedin.com/in/mitjapugelj" target="_blank" rel="noopener">Mitja Pugelj</a> my personal hero | |
</ul> | |
</br> | |
</p> | |
<p>Use chrome developers tools for connection issues <a href="chrome://bluetooth-internals/#devices/">chrome://bluetooth-internals/#devices/</a></p> | |
<script> | |
const TIME_SERVICE = 'ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6'; | |
const TIME = 'ebe0ccb7-7a0a-4b0c-8a1a-6ff2997da3a6'; | |
const UNIT = 'ebe0ccbe-7a0a-4b0c-8a1a-6ff2997da3a6'; | |
setTimeZone(); | |
function setTimeZone() { | |
let offset = new Date().getTimezoneOffset(); | |
document.getElementById('zone').value = -(parseInt(offset/60)); | |
} | |
function updateTime() { | |
getCharecteristics(TIME_SERVICE, TIME) | |
.then(function (characteristic) { | |
log('Writting time value...') | |
return characteristic.writeValue(getCurrentTime()); | |
}) | |
.then(function () { | |
log('Time updated.'); | |
}) | |
.catch(function (error) { | |
log(error); | |
}); | |
} | |
function updateUnit() { | |
let unitValue = parseInt(document.querySelector('input[name="unit"]:checked').value); | |
let charPromise = getCharecteristics(TIME_SERVICE, UNIT); | |
let readPromise = charPromise.then(c=>c.readValue()); | |
Promise.all([charPromise, readPromise]) | |
.then(function([characteristic, value]) { | |
let oldValue = value.getUint8(0); | |
log('Writting unit value (' + oldValue + ' -> ' + unitValue + ')...') | |
let buffer = new ArrayBuffer(1); | |
new DataView(buffer).setUint8(0, unitValue); | |
return characteristic.writeValue(buffer); | |
}).then(function() { | |
log('Unit updated'); | |
}).catch(function (error) { | |
log(error); | |
}); | |
} | |
function getCharecteristics(service, characteristic) { | |
if (!('bluetooth' in navigator)) { | |
throw 'Bluetooth API not supported.'; | |
} | |
let options = { | |
acceptAllDevices: true, | |
optionalServices: [service] | |
}; | |
return navigator.bluetooth.requestDevice(options) | |
.then(function (device) { | |
log('Connecting...') | |
return device.gatt.connect(); | |
}) | |
.then(function (server) { | |
log('Getting primary service...') | |
return server.getPrimaryService(service); | |
}) | |
.then(function (service) { | |
log('Getting characteristic...') | |
return service.getCharacteristic(characteristic); | |
}); | |
} | |
function log(message) { | |
let element = document.getElementById('console'); | |
console.log(message); | |
element.innerHTML = message; | |
} | |
function getCurrentTime() { | |
let is30MinOffset = document.getElementById('30minOffset').checked; | |
let dateTime = parseInt(Date.now()/1000) + (is30MinOffset ? 30 * 60 : 0); | |
let buffer = new ArrayBuffer(5); | |
new DataView(buffer).setUint32(0, dateTime, true /* littleEndian */); | |
let zone = parseInt(document.getElementById('zone').value); | |
new DataView(buffer).setUint8(4, zone); | |
return buffer; | |
} | |
</script> | |
<style> | |
body { | |
max-width: 400px; | |
margin: 0 auto; | |
font-family: Lato,'Helvetica Neue',Arial,Helvetica,sans-serif; | |
} | |
fieldset > * { | |
margin: 5px; | |
} | |
</style> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment