1
0
Fork 0
This commit is contained in:
Kekskurse 2020-11-30 22:55:25 +01:00
parent 1370b30eb1
commit 6123dc7fd9
31 changed files with 6643 additions and 6 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
public
release.sh
newContent

View File

@ -1,14 +1,35 @@
---
title: "MQTT at Home"
date: 2020-10-28T21:32:53+02:00
draft: true
date: 2020-11-26T21:32:53+02:00
draft: false
description: "How I use MQTT at Home to connect stuff."
tags: ["MQTT", "IoT", "Blog"]
tags: ["MQTT", "IoT", "Blog", "Go"]
categories: ["Programming"]
startpage: true
lang: gb
---
Ok i live in a small appartment, but at least I have three Window and a little bit stuff to connect with each other. I startes with [Ikea TRÅDFRI](https://www.ikea.com/de/de/cat/ikea-home-smart-beleuchtung-36812/) and some selfe made components based Arudino/Wemos. About one year ago I tried [zigbee2mqtt](https://www.zigbee2mqtt.io/) to connect the ikea bulbs to MQTT without using my own buggy code. I used a MQTT-Broker on a Virtual Server somewhere in the internet and develop some PHP-Application with lumen (some of them running in kubernetes) to connect everything.
After some issues with my Internet Provider I beginn with a easyer and locale alternative. I already used a Raspberry Pi for zigbee2mqtt so i want to run everything on it. On the other hand I want a secound MQTT Server in the Internet(tm) to connect from other networks. Also I like the idear of smaller "services" managed single features.
I still use [Mqtt Dash](https://play.google.com/store/apps/details?id=net.routix.mqttdash&hl=de&gl=US) at my Android Device do control most things.
## Basic Setup
First i setup [supervisord](http://supervisord.org/) on the pi to managed all scripts. I develope the new Services in golang, so first i build a small wrapper arround [paho.mqtt.golang](https://github.com/eclipse/paho.mqtt.golang), so all Services has the same configure also for the Last Will and Testament. It connected without crdentials to a mqtt server running on the same pi (localhost). Than i could start creating single services. One react to all incomming MQTT-Message if a button is pressed and change the light-modus. The light-modus are topics with retained messages. Another services subscribed to this topic and send the mqtt messages to zigbee2mqtt which changed the light bulbs.
## MQTT Bridge
For all topics contained a state like the light-modus i created a set topic. The light modus for the "main" room could be `light-modus/main`, to change it i published a message to `light-modus/main/set`. I used another service just mirrow the incomming messages at the set topic (not retained) and send it to the original topic (as retained messages).
The [Mosquito MQTT Broker](https://mosquitto.org/) has a feature to setup a bridge between two MQTT Server. So i setup another instanc of it at a VM in the internet. After that i can configure on the MQTT Broker on my locale pi to connect to the remote mqtt server. I relay messages from status topics (like light-modus), sensor and device informations (from zigbee2mqtt) and subscripe to some */set topics. With this setup everything works fine without internet in my apparment. But as long as the internet connection is avalible I can publish messages to the online mqtt server which would be recived locale.
## Automation
All Automation Services are also written in go, and had a feature toggle as retained mqtt topic (with a seperate /set topic). With this I can change the behavior of it. For example i had a service checking if I'm currenlty in im appartment and the value of the lumex sensor falls below a special value. If that happends it will turn on the light. But I dont always want that to happend to I can toggle this feature.
Also all status information are avalible as retained messages at the MQTT-Broker. So each service can restart without any issues.
## Interface
I still use [Mqtt Dash](https://play.google.com/store/apps/details?id=net.routix.mqttdash&hl=de&gl=US) at my Android Device do control most things. Some information like the room temperature are already stored in a graphite database to have access via [grafana](https://grafana.com/). In the feature I want to create some status dashboard based on the last will of the service and some zigbee2mqtt messages. Also maybe a webpage connecting to the broker to controll the light with a tablet.

View File

@ -0,0 +1,16 @@
---
title: "Herbstspaziergang"
date: 2020-11-30T16:31:55+02:00
draft: false
categories: ["Images"]
description: "Image Gallery"
tags: [""]
startpage: false
lang: img
gallery: "/img/2020/11/herbst-spaziergang/DSC07221_1.jpg"
---
# Gallery
{{< gallery dir="img/2020/11/herbst-spaziergang" caption-position="none" caption-effect="fade" />}} {{< load-photoswipe >}}
# GPS Track
{{< gpx gpx="/img/2020/11/herbst-spaziergang/track.gpx" >}}

View File

@ -0,0 +1,28 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-gpx/1.4.0/gpx.min.js"></script>
<div id="mymap" class="mymap" style="min-height: 500px;"></div>
<style type="text/css">
.mymap img {
border: 0px;
}
</style>
<script>
var map = L.map('mymap');
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data &copy; <a href="http://www.osm.org">OpenStreetMap</a>'
}).addTo(map);
var gpx = '{{ .Get "gpx" }}'; // URL to your GPX file or the GPX itself
new L.GPX(gpx, {
marker_options: {
startIconUrl: '/img/general/pin-icon-start.png',
endIconUrl: '/img/general/pin-icon-end.png',
shadowUrl: '/img/general/pin-shadow.png'
},
async: true
}).on('loaded', function(e) {
map.fitBounds(e.target.getBounds());
}).addTo(map);
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 MiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 960 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
static/img/general/ssp.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
static/img/general/ssp2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
static/img/general/ssp3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 KiB

View File

@ -12,10 +12,44 @@
{{- if isset .Site.Params "subtitle" -}}
<p>{{ .Site.Params.Subtitle | markdownify }}</p>
{{- end -}}
</div>
<img src="/img/general/ssp3.jpg" style="max-width:100%;">
<h1>Blog</h1>
<ul class="posts">
{{ $pages := where (where .Site.RegularPages "Type" "in" .Site.Params.mainSections) ".Params.startpage" "==" true }}
{{ $paginator := .Paginate (where $pages "Params.hidden" "ne" true) }}
{{ range $paginator.Pages }}
{{- if (not (in (.Site.Params.excludedTypes | default (slice "page")) .Type)) -}}
<li class="post">
<a href="{{ .RelPermalink }}">{{.Title}}</a>
<span class="meta">
{{ dateFormat "Jan 2, 2006" .Date }} {{ if .Draft }} <span class="draft-label">DRAFT</span> {{ end }}
</span>
</li>
{{- end -}}
{{- end -}}
</ul>
<h1>Bilder</h1>
<ul class="posts">
{{ $pages2 := where (where .Site.RegularPages "Type" "in" .Site.Params.mainSections) ".Params.gallery" "!=" nil }}
{{ range first 3 $pages2 }}
<li class="post">
<a href="{{ .RelPermalink }}">{{.Title}}</a>
<span class="meta">
{{ dateFormat "Jan 2, 2006" .Date }} {{ if .Draft }} <span class="draft-label">DRAFT</span> {{ end }}
</span>
</li>
{{- end -}}
</ul>
<!--<h1>Blog</h1>
{{ $pages := where (where .Site.RegularPages "Type" "in" .Site.Params.mainSections) ".Params.startpage" "==" true }}
{{ $paginator := .Paginate (where $pages "Params.hidden" "ne" true) }}
{{ range $paginator.Pages }}
@ -31,7 +65,7 @@
</div>
<a href="{{ .RelPermalink }}">Read more ⟶</a>
</section>
{{ end }}
{{ end }}!-->
{{ template "partials/paginator.html" . }}
</main>
{{ partial "footer.html" . }}