Cybele
Cybele copied to clipboard
Glance Clock
Hi, does the Glance Clock integration work? If so then I'm happy to muddle through working out how to use it and writing up a Readme
Hi!
Yep I've been using it for quite a while now. I wouldn't call it clean and it could definitely use more error handling but it has stood the test of time
Thank you!
To make this a bit easier, here's what I'm currently using to talk to the GlanceClock.
I hope that it will be at least somewhat helpful even though its's just unpolished copy paste
Click Me
Notify example from my home assistant configuration:
- data:
topic: "cybele/glanceclock/ffffffffff/notify"
data_template:
payload: >
{
"message": "{{ trigger.to_state.attributes.friendly_name }}: {{ trigger.to_state.state }}",
"animation": "Wheel",
"color": "RoyalBlue",
"sound": "NoneSound",
"repeatCount": 3
}
service: mqtt.publish
SetBrightness Example:
- data:
topic: "cybele/glanceclock/ffffffffff/setBrightness"
payload_template: >
{% if states.input_boolean.glance_clock_bad_bright.state == "on" %}
{"value": "auto", "auto": {"min": 24, "max": 132}}
{% else %}
{"value": "auto", "auto": {"min": 1, "max": 24}}
{% endif %}
saveForecastScene example taken from a node-red function node
const output = [];
const now = Math.round((Date.now() / 1000) - (new Date().getTimezoneOffset() *60));
const nowDate = new Date();
const temperatureScene = {
timestamp: now,
maxColor: "#FF0000",
minColor: "#0000FF",
max: 22, //wohlfühlbereich
min: 6,
template: [0xC2,0x8F,0x20,0x08,0xC2,0xB0],
values: []
};
const temp = {
min: null,
max: null
}
const isNight = nowDate.getHours() >= 23 || nowDate.getHours() < 6 //used to not light up the room at night
Object.keys(msg.payload.temperature).forEach(k => {
temp.min = temp.min ? Math.min(temp.min, msg.payload.temperature[k]) : msg.payload.temperature[k];
temp.max = temp.max ? Math.max(temp.max, msg.payload.temperature[k]) : msg.payload.temperature[k];
temperatureScene.values[parseInt(k)] = Math.round(msg.payload.temperature[k])
});
if(temp.max > 9 || temp.min < 0) {
temperatureScene.template = temperatureScene.template.filter(e => e !== 0x20);
}
temperatureScene.min = Math.round(temp.min);
temperatureScene.max = Math.round(temp.max);
output.push({
payload: {
scene: temperatureScene,
displayMode: isNight ? "text" : "both",
sceneSlot: 1
}
});
const precipationScene = {
timestamp: now,
maxColor: "#0000FF",
minColor: "#000000",
max: 1, //1mm in einer Stunde
min: 0,
template: [0xC2,0x95,0x20,0x08,0x6d,0x6d],
values: []
};
const precip = {
min: null,
max: null
};
Object.keys(msg.payload.precipitation).forEach(k => {
precip.min = precip.min ? Math.min(precip.min, msg.payload.precipitation[k]) : msg.payload.precipitation[k];
precip.max = precip.max ? Math.max(precip.max, msg.payload.precipitation[k]) : msg.payload.precipitation[k];
precipationScene.values[parseInt(k)] = Math.round(msg.payload.precipitation[k])
});
if(precip.max > 9) {
precipationScene.template = precipationScene.template.filter(e => e !== 0x20);
}
precipationScene.min = Math.round(precip.min);
precipationScene.max = Math.round(precip.max) >= 1 ? Math.round(precip.max) : 1;
output.push({
payload: {
scene: precipationScene,
displayMode: isNight ? "text" : "both",
sceneSlot: 2
}
});
function msToBeaufort(ms) {
return Math.ceil(Math.cbrt(Math.pow(ms/0.836, 2)));
}
/*
const windScene = {
timestamp: now,
maxColor: "#00FF00",
minColor: "#000000",
max: 9, //Windstärke
min: 0,
template: [0xC2,0x98,0x20,0x08],
values: []
};
const wind = {
min: null,
max: null
}
Object.keys(msg.payload.wind_speed).forEach(k => {
wind.min = wind.min ? Math.min(wind.min, msg.payload.wind_speed[k]) : msg.payload.wind_speed[k];
wind.max = wind.max ? Math.max(wind.max, msg.payload.wind_speed[k]) : msg.payload.wind_speed[k];
windScene.values[parseInt(k)] = msToBeaufort(msg.payload.wind_speed[k])
});
if(wind.max > 9) {
windScene.template = windScene.template.filter(e => e !== 0x20);
}
windScene.min = Math.round(wind.min);
windScene.max = Math.round(wind.max) >= 1 ? Math.round(wind.max) : 1;
output.push({
payload: {
scene: windScene,
displayMode: "both",
sceneSlot: 3
}
});
const cloudsScene = {
timestamp: now,
maxColor: "#000000",
minColor: "#FFFFFF",
max: 100, //100% Wolkendecke
min: 0,
template: [0xC2,0x99,0x20,0x08,0x25],
values: []
};
const clouds = {
min: null,
max: null
};
Object.keys(msg.payload.cloud_coverage).forEach(k => {
clouds.min = clouds.min ? Math.min(clouds.min, msg.payload.cloud_coverage[k]) : msg.payload.cloud_coverage[k];
clouds.max = clouds.max ? Math.max(clouds.max, msg.payload.cloud_coverage[k]) : msg.payload.cloud_coverage[k];
cloudsScene.values[parseInt(k)] = Math.round(msg.payload.cloud_coverage[k])
});
if(clouds.max > 99) {
cloudsScene.template = cloudsScene.template.filter(e => e !== 0x20);
}
cloudsScene.min = clouds.min;
cloudsScene.max = clouds.max >= 1 ? clouds.max : 1;
output.push({
payload: {
scene: cloudsScene,
displayMode: "both",
sceneSlot: 4
}
});
*/
return [output];
SetTimer Payload Example:
{
"intervals": [{
"duration": totalTime
}]
}
StopTimer Payload:
{ "action": "stop"}
Be advised that sometimes (I think it's caused by too many invalid requests/connection attempts) the clock looses its pairing information and needs to re-paired.
Unfortunately, this fails silently and can only be noticed by observing that data pushed to it doesn't appear anymore.
The pairing process is still rather tedious for some reason but has been at least mostly reproducible.
For best results, try turning bluetooth off and on again. That seems to help. Pairing looks more or less like this:
run bluetoothctl. In bluetoothctl do:
agent off
power off
power on
agent on
default-agent
menu scan
transport le
back
scan on
//The terminal will most likely be spammed by advertisements. Ignore that
<wait a few moments>
pair MAC_OF_YOUR_CLOCK
//enter pin displayed on the clock
//The clock should confirm pairing on its display. if not do "remove MAC_OF_YOUR_CLOCK" and try again from the start
hi @Hypfer @anthonyangel !
First, thanks for the project !
i've just got the Glance Clock, run successfully the Cybele Project, but it doesn't start any action to my clock
my config.json:
{
"mqtt": {
"url": "mqtt://USER:PASS@MQTT_IP"
},
"dongles": [
{
"hciDevice": "hci0",
"mode": "le",
"services": [],
"devices": [
{
"type": "GlanceClockDevice",
"friendlyName": "GlanceClock_F3",
"mac": "F1:95:1D:7F:D2:F3"
}
]
}
]
}
bluetoot is connected :
Agent registered
[CHG] Controller 00:1A:7D:DA:71:15 Pairable: yes
[GlanceClock_F3]# paired-devices
Device F1:95:1D:7F:D2:F3 GlanceClock_F3
[GlanceClock_F3]# info F1:95:1D:7F:D2:F3
Device F1:95:1D:7F:D2:F3 (random)
Name: GlanceClock_F3
Alias: GlanceClock_F3
Appearance: 0x0100
Paired: yes
Trusted: yes
Blocked: no
Connected: yes
LegacyPairing: no
UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb)
UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
UUID: Device Information (0000180a-0000-1000-8000-00805f9b34fb)
UUID: Battery Service (0000180f-0000-1000-8000-00805f9b34fb)
UUID: Vendor specific (5075f606-1e0e-11e7-93ae-92361f002671)
UUID: Vendor specific (8e400001-f315-4f60-9fb8-838830daea50)
ManufacturerData Key: 0x004c
ManufacturerData Value:
02 15 50 75 f6 06 1e 0e 11 e7 93 ae 92 36 1f 00 ..Pu.........6..
26 71 00 01 00 01 c3 &q.....
The node app.js | grep "F1:95:1D
does'nt show anything. I've tryied to publish to cybele/glanceclock/F1:95:1D:7F:D2:F3/notify
but no effect, netiher on the log of app.js, neither on the clock
Could you help me please ? 🙏🏻
find the solution !
the mac adress in the topic name must be in lowercase and without underscore
thanks again for the Cybele project ❤️