-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.html
564 lines (564 loc) · 27.2 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
<!DOCTYPE html>
<head>
<title>Hemtjänst</title>
<meta name="description" content="Open source, private and secure home automation ecosystem">
<meta charset="UTF-8">
<meta property="og:title" content="Hemtjänst" />
<meta property="og:type" content="website" />
<meta property="og:image" content="https://hemtjan.st/assets/img/hemtjanst.png" />
<meta property="og:description" content="Open source, private and secure home automation ecosystem"/>
<meta property="og:determiner" content="a" />
<meta property="og:locale" content="en_GB" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css" integrity="sha256-8B1OaG0zT7uYA572S2xOxWACq9NXYPQ+U5kHPV1bJN4=" crossorigin="anonymous" />
<link href="https://fonts.googleapis.com/css?family=Fira+Mono|IBM+Plex+Sans+Condensed" rel="stylesheet">
<script defer src="https://use.fontawesome.com/releases/v5.8.1/js/all.js" integrity="sha384-g5uSoOSBd7KkhAMlnQILrecXvzst9TdC09/VM+pjDTCM+1il8RHz5fKANTFFb+gQ" crossorigin="anonymous"></script>
<style type="text/css">
.hero.is-medium {
background: linear-gradient(
rgba(0, 0, 0, 0.6),
rgba(0, 0, 0, 0.6)
), url('https://picsum.photos/id/529/1200/500?blur=2') no-repeat center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
.title {
font-family: 'IBM Plex Sans Condensed', sans-serif;
}
a.button {
font-family: 'IBM Plex Sans Condensed', sans-serif;
}
code {
font-family: 'Fira Mono', monospace;
}
</style>
</head>
<body>
<div class="hero is-medium">
<div class="hero-head">
<nav class="navbar">
<div class="container">
<div class="navbar-brand">
<a class="navbar-item">
</a>
<span class="has-text-white navbar-burger burger" data-target="navbarMenuHeroB">
<span></span>
<span></span>
<span></span>
</span>
</div>
<div id="navbarMenuHeroB" class="navbar-menu">
<div class="navbar-end">
<span class="navbar-item">
<a class="button is-white is-outlined">
<span>Home</span>
</a>
</span>
<span class="navbar-item">
<a class="button is-white is-outlined" href="#bridges">
<span>Bridges</span>
</a>
</span>
<span class="navbar-item">
<a class="button is-white is-outlined" href="#components">
<span>Components</span>
</a>
</span>
<span class="navbar-item">
<a class="button is-white is-outlined" href="#demo">
<span>Demo</span>
</a>
</span>
<span class="navbar-item">
<a class="button is-white" href="https://github.com/hemtjanst">
<span class="icon">
<i class="fab fa-github"></i>
</span>
<span>Source</span>
</a>
</span>
</div>
</div>
</div>
</nav>
</div>
<div class="hero-body">
<div class="container has-text-centered">
<h1 class="title has-text-white">
Hemtjänst
</h1>
<h2 class="subtitle has-text-white">
Private, personal, home automation
</h2>
</div>
</div>
</div>
<section class="section">
<div class="container">
<div class="columns">
<div class="column is-3">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-user-secret"></i>
</p>
<p class="title is-5 has-text-centered">
Private
</p>
<p class="has-text-justified">
Hemtjänst does not require an internet connection to function,
or a subscription to a cloud service. It's a local-first system
that doesn't track you. You own your data and you can do with
it whatever you want.
</p>
</div>
<div class="column is-3">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-american-sign-language-interpreting"></i>
</p>
<p class="title is-5 has-text-centered">
Vendor neutral
</p>
<p class="has-text-justified">
A single protocol lets you control all devices in your
home. Bridges take care of translating
between Hemtjänst and vendor-specific protocols and can also
be used to extend Hemtjänst with new capabilities.
</p>
</div>
<div class="column is-3">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i data-fa-transform="flip-h" class="fas fa-2x fa-history"></i>
</p>
<p class="title is-5 has-text-centered">
Real time
</p>
<p class="has-text-justified">
By leveraging <a href="http://mqtt.org/">MQTT</a> all interactions
feel immediate and real-time. Just like if you were interacting
with a physical device in the real world. Anyone connected to
the broker is immediately notified of any changes.
</p>
</div>
<div class="column is-3">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-key"></i>
</p>
<p class="title is-5 has-text-centered">
Secure
</p>
<p class="has-text-justified">
All components can use TLS to encrypt their communication.
Additionally TLS client certificates or username and password
combinations can be used to gate access as well as
apply ACLs.
</p>
</div>
</div>
</div>
</section>
<hr class="hr">
<section class="section">
<p style="padding-bottom:1em;" class="title has-text-centered"><a class="has-text-black" name="bridges">Bridges</a></p>
<div class="container">
<div class="columns">
<div class="column is-3">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-home"></i>
</p>
<p class="title is-5 has-text-centered">
Apple HomeKit
</p>
<p class="has-text-justified">
<a href="https://hemtjan.st/hemtjanst">Hemtjänst</a>,
the bridge, exposes as many devices as possible
as HomeKit accessories and is a fully functioning HomeKit
bridge. You can pair the <a href="https://www.apple.com/ios/home/">
iOS Home app</a> with Hemtjänst and control your whole house from there.
</p>
</div>
<div class="column is-3">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-lightbulb"></i>
</p>
<p class="title is-5 has-text-centered">
kea Trådfri
</p>
<p class="has-text-justified">
<a href="https://hemtjan.st/sladdlos">Sladdlos</a>
and its sister component <a href="https://hemtjan.st/tradfri-mqtt">
tradfri-mqtt expose</a> devices connected to the TRÅDFRI gateway. This lets you
control any light connected to the Ikea gateway
through Hemtjänst.
</p>
</div>
<div class="column is-3">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-eye"></i>
</p>
<p class="title is-5 has-text-centered">
Rödljus
</p>
<p class="has-text-justified">
<a href="https://hemtjan.st/rodljus">Rödljus</a>
lets you control IR-based devices. It leverages
lircd and an IR-blaster to send comands. It's like pressing
actual buttons on a remote control.
</p>
</div>
<div class="column is-3">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-broadcast-tower"></i>
</p>
<p class="title is-5 has-text-centered">
zVåg
</p>
<p class="has-text-justified">
<a href="https://hemtjan.st/zvag">zVåg</a>
makes devices connected through Z-Wave available to
Hemtjänst. This can be devices like contact sensors, outlets
etc.
</p>
</div>
</div>
<div class="columns">
<div class="column is-3">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-palette"></i>
</p>
<p class="title is-5 has-text-centered">
Färgton
</p>
<p class="has-text-justified">
<a href="https://hemtjan.st/fargton">Färgton</a> emulates a Philips
Hue v2 bridge and API. This lets you use the Hue app to
control compatible Hemtjänst devices, like lightbulbs.
It also means anything in the "Friends of Hue" ecosystem
automatically works with Hemtjänst.
</p>
</div>
<div class="column is-3">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-tachometer-alt"></i>
</p>
<p class="title is-5 has-text-centered">
Sensorer
</p>
<p class="has-text-justified">
<a href="https://hemtjan.st/sensorer">Sensorer</a>
is a <a href="https://prometheus.io/docs/instrumenting/exporters/">
Prometheus exporter</a>. It exposes the data
of sensor-like devices, for example temperature, in
the Prometheus <a href="https://prometheus.io/docs/instrumenting/exposition_formats/">
exposition format</a>. You can use <a href="https://prometheus.io/">Prometheus</a>
to scrape this data and <a href="https://grafana.com/">Grafana</a>
to graph it and get all kinds of insights into your home environment.
</p>
</div>
<div class="column is-3">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fab fa-2x fa-raspberry-pi"></i>
</p>
<p class="title is-5 has-text-centered">
HallonLarm
</p>
<p class="has-text-justified">
<a href="https://hemtjan.st/hallonlarm">HallonLarm</a>
exposes the GPIO pins of a Raspberry Pi as
topics onto the MQTT broker. You can listen for events
or send commands letting you hack together anything
your heart desires.
</p>
</div>
<div class="column is-3">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-pencil-ruler"></i>
</p>
<p class="title is-5 has-text-centered">
Bidans
</p>
<p class="has-text-justified">
Currently a work in progress, Bidans is a ZigBee bridge.
Similar to Zvag, it exposes any ZigBee connected device to
Hemtjänst. This should obviate the need to support different
vendor gateways, like Trådfri, and vastly expand the amount
of supported devices.
</p>
</div>
</div>
<div class="columns">
<div class="column is-offset-2 is-4">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-broom"></i>
</p>
<p class="title is-5 has-text-centered">
Dammsugare
</p>
<p class="has-text-justified">
<a href="https://hemtjan.st/dammsugare">Dammsugare</a>
lets you control a Eufy RoboVac. It leverages
Rödljus under the hood to send the IR commands to turn the
robot on and off.
</p>
</div>
<div class="column is-4">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-wind"></i>
</p>
<p class="title is-5 has-text-centered">
Flakt
</p>
<p class="has-text-justified">
Similar in spirit to dammsugare,
<a href="https://hemtjan.st/flakt">flakt</a>
leverages Rödljus in order to be able to control a tower fan.
</p>
</div>
</div>
</div>
</section>
<hr class="hr">
<section class="section">
<p style="padding-bottom:1em;" class="title has-text-centered"><a class="has-text-black" name="components">Components</a></p>
<div class="container">
<div class="columns">
<div class="column is-offset-2 is-4">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-university"></i>
</p>
<p class="title is-5 has-text-centered">
Bibliotek
</p>
<p class="has-text-justified">
<a href="https://lib.hemtjan.st">Bibliotek</a> is a Go package
that implements the Hemtjänst
protocol as well as its discovery and announce mechanisms.
You can use it to create your own vendor bridges or
extend Hemtjänst with new capabilities.
</p>
</div>
<div class="column is-4">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fab fa-2x fa-js-square"></i>
</p>
<p class="title is-5 has-text-centered">
Hemtjänst-js
</p>
<p class="has-text-justified">
A <a href="https://hemtjan.st/hemtjanst-js">TypeScript library</a>
implementing the Hemtjänst protocol.
From Node you can connect directly to the broker using
TLS, plain TCP or through websockets. In the browser you
can use websockets to connect to the broker.
</p>
</div>
</div>
<div class="columns">
<div class="column is-offset-2 is-4">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-dharmachakra"></i>
</p>
<p class="title is-5 has-text-centered">
Message broker
</p>
<p class="has-text-justified">
The message broker is the central nervous system of Hemtjänst.
Any MQTT v3.1+ broker will do but we happen to be using
<a href="https://mosquitto.org/">Eclipse Mosquitto</a>.
</p>
</div>
<div class="column is-4">
<p class="has-text-centered" style="padding-bottom: 0.5em;">
<i class="fas fa-2x fa-magic"></i>
</p>
<p class="title is-5 has-text-centered">
Node-RED
</p>
<p class="has-text-justified">
<a href="https://nodered.org/">Node-RED</a> is an open source
programming environment for the Internet of Things. It supports
MQTT out of the box letting you interact with all Hemtjänst
devices. Use it to create any kind of automation you want.
</p>
</div>
</div>
</div>
</section>
<hr class="hr">
<section class="section">
<p class="title has-text-centered"><a class="has-text-black" name="demo">Demo</a></p>
<div class="container">
<div class="columns is-desktop">
<div class="column is-offset-2 is-8">
<p style="padding-bottom:2em;" class="has-text-justified">
This is a demonstration of how to turn on a lightbulb with just an MQTT CLI.
It requires minimal understanding of the Hemtjänst protocol and no knowledge
of what IoT protocol the device itself is using.
Libraries like <a href="https://lib.hemtjan.st">bibliotek</a>
take care of the discover/announce flow and keep monitoring for device
updates in the background. The whole flow is shown here for completeness.
If you already know the device topics there is no need for the discover/announce
flow.
</p>
</div>
</div>
</div>
</div>
<div class="columns is-desktop">
<div class="column is-6">
<p class="subtitle is-5">1. Start by subscribing to the announce topic</p>
<pre><code>
mqttcli <span class="has-text-info">sub</span> -t 'announce/#'
</code></pre>
</div>
<div class="column is-6">
<p class="subtitle is-5"> </p>
<p>Once you <span class="has-text-info">pub</span>lish to the
<code>discover</code> topic all devices will announce themselves
to a <code>announce/<id></code> topic. By subscribing to <code>announce/#</code>
we'll receive all mesages published to topics underneath <code>announce/</code>.
The <code>#</code> is the MQTT equivalent of a wildcard.
</p>
</div>
</div>
<div class="columns is-desktop">
<div class="column is-offset-6">
<p class="subtitle is-5">2. Discover all devices</p>
<pre><code>
mqttcli <span class="has-text-info">pub</span> -t 'discover' -r -m ''
</code></pre>
</div>
</div>
<div class="columns is-desktop">
<div class="column is-7">
<p class="subtitle is-5">3. Receive all the device announcements</p>
<pre><code class="lang-json">
...
{
"topic": <span class="has-text-info">"light/grp-193347"</span>,
"name": "Kitchen",
"manufacturer": "IKEA",
"model": "Trådfri Group",
"serialNumber": "193347",
"type": "lightbulb",
"lastWillID": "sladdlos-c7274f9f-471d-4674-8075-81ad4c2d31f0",
"feature": {
"brightness": {
"getTopic": "light/grp-193347/brightness/get",
"setTopic": "light/grp-193347/brightness/set"
},
"colorTemperature": {
"getTopic": "light/grp-193347/colorTemperature/get",
"setTopic": "light/grp-193347/colorTemperature/set"
},
"on": {
"getTopic": <span class="has-text-info">"light/grp-193347/</span><strong><span class="has-text-primary">on/get"</span></strong>,
"setTopic": <span class="has-text-info">"light/grp-193347/</span><strong><span class="has-text-danger">on/set"</span></strong>
}
}
}
{
"name": "Kitchen small_window",
"type": "contactSensor",
"manufacturer": "Telldus",
"model": "Device 23",
"feature": {
"contactSensorState": {}
}
}
...
</code></pre>
</div>
</div>
<div class="columns is-desktop">
<div class="column is-6">
<p class="subtitle is-5">4. Subscribe to the kitchen light on/off state</p>
<pre><code>
mqttcli <span class="has-text-info">sub</span> -t <span class="has-text-info">"light/grp-193347/</span><strong><span class="has-text-primary">on/get"</span></strong>
0
</code></pre>
</div>
<div class="column is-6">
<p class="subtitle is-5">Possible device states</p>
<pre><code>
0: the device is off
1: the device is on
</code></pre>
</div>
</div>
<div class="columns is-desktop">
<div class="column is-offset-6">
<p class="subtitle is-5">5. Turn on the kitchen light</p>
<pre><code>
mqttcli <span class="has-text-info">pub</span> -t <span class="has-text-info">"light/grp-193347/</span><strong><span class="has-text-danger">on/set"</span></strong> -m '1'
</code></pre>
</div>
</div>
<div class="columns is-desktop">
<div class="column is-6">
<p class="subtitle is-5">6. Receive notification that the light has been turned on</p>
<pre><code>
1
</code></pre>
</div>
</div>
<div class="container">
<div class="columns is-desktop">
<div class="column is-offset-2 is-8">
<p style="padding-bottom:2em;" class="has-text-justified">
One important thing to realise is that the value you receive
on the <code>get</code> topic is the actual state of the device. When you
publish to <code>set</code>, a bridge will then send the
actual command to the bulb to turn on. Only once the light is on
does a bridge publish the new state onto the <code>get</code>
topic which you then receive. As such publishing onto <code>get</code>
does not imply an update to <code>set</code>. Only if the device manages
to achieve the new state will you get an update.
<code>get</code> and <code>set</code>
are a bit of a misnomer and are likely to get renamed to something
like <code>current</code> and <code>desired</code>.
</p>
</div>
</div>
</div>
</div>
</section>
<footer class="footer">
<div class="content has-text-centered">
<p>
<strong>Hemtjänst</strong> is made with 💙 in 🇸🇪. All components are
<strong>open source</strong> and licensend under the
<a href="https://www.apache.org/licenses/LICENSE-2.0"> Apache 2 License</a>.
</p>
</div>
</footer>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
if ($navbarBurgers.length > 0) {
$navbarBurgers.forEach( el => {
el.addEventListener('click', () => {
const target = el.dataset.target;
const $target = document.getElementById(target);
el.classList.toggle('is-active');
$target.classList.toggle('is-active');
const $buttons = Array.prototype.slice.call($target.querySelectorAll('.button'), 0);
if ($buttons.length > 0) {
$buttons.forEach( el => {
el.classList.toggle('is-black')
})
}
});
});
}
});
</script>
</body>
</html>