Node Red Ikea tradfri 2 Tasten Taster

Node Red Ikea tradfri 2 Tasten Taster

Ikea bietet für 6€ einen günstigen ZigBee-fähigen Dimmer an (https://www.ikea.com/de/de/p/tradfri-kabelloser-dimmer-weiss-70408595/). Diesen habe ich über einen ConBee II (Dresden Elektronik) angebunden. Ich möchte ihn über Node Red steuern können. Dafür nutze ich den Adapter node-red-contrib-deconz 1.1.10 und ioBroker mit dem Tradfri Adapter.

Der Taster liefert 6 verschiedene Statuscodes:

  • 1002 – Eingeschalten (I)
  • 2002 – Ausgeschalten (O)
  • 1001 – Start von I wird gedrückt gehalten (Long PRESS)
  • 1003 – Ende von I wird gedrückt gehalten
  • 2001 – Start von O wird gedrückt gehalten (Long PRESS)
  • 2003 Ende von O wird gedrückt gehalten
(c) IKEA 2020

Mit den Werten 1002 und 2002 kann man nun einfach über einen switch ein on/off Beispiel bauen.

hier ein Beispiel für den Heizstrahler der nach dem Anschalten maximal. 15min an sein darf. Das kann durch erneutes drücken wiederholt bzw. auf 15min zurück gesetzt werden. „Display Payload“ ist ein Subflow der den msg.payload auf Status mit schickt und somit unter dem Element anzeigt. Nachfolgend der Code dafür


1
[{"id":"9fd20961.36f768","type":"subflow","name":"Display Payload","info":"","category":"","in":[{"x":50,"y":30,"wires":[]}],"out":[{"x":140,"y":100,"wires":[{"id":"9fd20961.36f768","port":0}]}],"env":[],"color":"#DDAA99","status":{"x":160,"y":30,"wires":[{"id":"9fd20961.36f768","port":0}]}}]

Dimm Funktion

Wir wollen nun aber auch das lange drücken mit Auswerten. Dazu nutze ich zusätzlich noch node-red-contrib-simple-gate um ein Element zu haben, was ähnlich einem Tor steuerbar ist und den Inhalt einfach durchleitet.

Beispiel Gate

Die Idee zum dimmen ist nun folgende: Mit dem langen Drücken von I oder O (1001 bzw. 2001) wird das Gate geöffnet und mit 1003 bzw. 2003 (Loslassen von I bzw. O) wird das Gate geschlossen.
Zyklich wird nun ein Inject (einmal pro Sekunde) auf das Gate geschickt. Kommt es durch wird der Helligkeitswert geändert.

Jetzt muss man vorab noch die „Richtung“, also hoch zählen oder runter zählen definieren. Dazu werten wir auch den Start des langen Drückens mit aus und setzen intern den Wert für die Zählrichtung.

Kommt nun ein Wert durch das Gate wird der aktuelle Wert plus gerechnet mit dem Produkt aus dem Wert wie stark es sich ändern soll und der Richtung (1 für hoch und -1 für runter) also wenn der Wert 50 ist und die Stufenbreite 10 wäre das beim Runter zählen: 50 + (10 * -1) = 40.
Geht der Wert über die Grenze von 1-100 hinaus wird er zurück gesetzt auf den Grenzwert.


1
2
3
4
5
6
7
8
9
10
11
12
var brightness = parseInt(flow.get('Brightness')) || 1;
var step = parseInt(env.get('StepBrightness')) || 10;
var direction = parseInt(msg.payload) || 1;

var newBrightness = brightness + (step *  direction);
if (newBrightness > 100) newBrightness = 100;
if (newBrightness < 1) newBrightness = 1;

flow.set('Brightness', newBrightness); // save new value

msg.payload = newBrightness;
return msg;

Anschließend wird der neue Helligkeitswert aus gegeben.

Doppelklick

Auch einen Doppelklick kann man realisieren. In der Ereignisgetriebenen Entwicklung kennen wir aber nicht die Dimension Zeit. Das heißt wir wissen nicht was man vorher geklickt hat, wie lange das her ist oder wie oft. Daher werden wir vorher ein Subflow bauen, welcher speichert wie oft ein Ereignis in einer bestimmten Zeit kam. Das geht ganz einfach, indem wir den Zeitstempel (Eintreffen eines Events) in ein Array legen und im Flow speichern. Danach werden alle Einträge entfernen, welche älter sind als unser Messzeitraum. Und am Ende zählen wir die Elemente und geben die Zahl aus.

Das sieht erstmal recht unspektakulär aus:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var now = Math.floor(Date.now() / 1000 ) || 0;

function RemoveOld(ts){
    var diff = env.get('TimeRangeInSeconds') || 5;
    var now = Math.floor(Date.now() / 1000 ) || 0;
    var now2 = now - diff;
   
  return Math.floor(ts) > now2;
}

var data = flow.get('data') || "[]";

data = JSON.parse(data);
data.push(now);
data=data.filter(RemoveOld);

msg.payload = data.length;
flow.set('data', JSON.stringify(data));

return msg;

Über Umgebungsvariablen wird hier die Zeit übergeben. Wird der Wert nicht gesetzt wird 5 als Standard angenommen.

Mit diesem Subflow können wir nun den Wert 1002 zählen lassen. Ist dieser größer/gleich 2 können wir ein Doppelklick-Ereignis ausführen. Ich will hier eine definierte Helligkeit setzen.

Der ganze Subflow gibt natürlich auch noch einen Status aus, weswegen die Linien etwas kreuz und quer gehen. Aber hier jetzt endlich der Überblick:

Im oberen Teil ist die simple on/off-Logik, in der Mitte das Dimmen und dadrunter der Doppelklick. Die Initialisierung der Helligkeit findet ganz unten statt wo der Wert einmalig in die Flow-Variable geschrieben wird.

Hier der Code für den gesamten Subflow:


1
[{"id":"549c3f58.ff0c9","type":"subflow","name":"Event per Time","info":"","category":"","in":[{"x":80,"y":180,"wires":[{"id":"8cd4f008.190f"}]}],"out":[{"x":520,"y":180,"wires":[{"id":"8cd4f008.190f","port":0}]}],"env":[{"name":"TimeRangeInSeconds","type":"num","value":"5"}],"color":"#DDAA99","status":{"x":520,"y":120,"wires":[{"id":"8cd4f008.190f","port":0}]}},{"id":"8cd4f008.190f","type":"function","z":"549c3f58.ff0c9","name":"count","func":"var now = Math.floor(Date.now() / 1000 ) || 0; \n\nfunction RemoveOld(ts){\n    var diff = env.get('TimeRangeInSeconds') || 5;\n    var now = Math.floor(Date.now() / 1000 ) || 0;\n    var now2 = now - diff; \n    \n  return Math.floor(ts) > now2;\n}\n\nvar data = flow.get('data') || "[]";\n\ndata = JSON.parse(data);\ndata.push(now);\ndata=data.filter(RemoveOld);\n\nmsg.payload = data.length;\nflow.set('data', JSON.stringify(data));\n\nreturn msg;","outputs":1,"noerr":0,"x":230,"y":180,"wires":[[]]},{"id":"4bf947ab.211498","type":"subflow","name":"Ikea Dimmer","info":"","category":"","in":[{"x":40,"y":300,"wires":[{"id":"7b4c9956.acfc58"}]}],"out":[{"x":1120,"y":340,"wires":[{"id":"32889690.fc46ea","port":0},{"id":"584679a5.c1bed8","port":0},{"id":"62117ea.1e7368","port":0}]},{"x":1320,"y":140,"wires":[{"id":"4a660c11.3eef94","port":0},{"id":"fac64923.bc6848","port":0}]}],"env":[{"name":"StartBrightness","type":"num","value":"50"},{"name":"StepBrightness","type":"num","value":"10"},{"name":"DoubleClickBrithness","type":"str","value":"1"}],"color":"#C0DEED","inputLabels":["Button Event"],"outputLabels":["Brightness","State"],"icon":"node-red-contrib-polymer/ui_radio.png","status":{"x":1420,"y":360,"wires":[{"id":"a5af8864.f47fe8","port":0},{"id":"4a660c11.3eef94","port":0},{"id":"fac64923.bc6848","port":0},{"id":"62117ea.1e7368","port":0}]}},{"id":"be8924a5.85ce88","type":"switch","z":"4bf947ab.211498","name":"Switch an / aus","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"1002","vt":"num"},{"t":"eq","v":"2002","vt":"str"}],"checkall":"true","repair":true,"outputs":2,"x":460,"y":140,"wires":[["32889690.fc46ea","4a660c11.3eef94"],["fac64923.bc6848"]]},{"id":"32889690.fc46ea","type":"change","z":"4bf947ab.211498","name":"Brightness","rules":[{"t":"set","p":"payload","pt":"msg","to":"Brightness","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":80,"wires":[[]]},{"id":"4a660c11.3eef94","type":"change","z":"4bf947ab.211498","name":"true","rules":[{"t":"set","p":"payload","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1090,"y":140,"wires":[[]]},{"id":"fac64923.bc6848","type":"change","z":"4bf947ab.211498","name":"false","rules":[{"t":"set","p":"payload","pt":"msg","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":260,"wires":[[]]},{"id":"51a608f0.19e558","type":"gate","z":"4bf947ab.211498","name":"","controlTopic":"control","defaultState":"closed","openCmd":"open","closeCmd":"close","toggleCmd":"toggle","defaultCmd":"default","persist":false,"x":670,"y":420,"wires":[["584679a5.c1bed8"]]},{"id":"152bae03.a8beb2","type":"change","z":"4bf947ab.211498","name":"Open","rules":[{"t":"set","p":"topic","pt":"msg","to":"control","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"open","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":420,"wires":[["51a608f0.19e558"]]},{"id":"f05a97bf.f288b8","type":"change","z":"4bf947ab.211498","name":"close","rules":[{"t":"set","p":"topic","pt":"msg","to":"control","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"close","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":360,"wires":[["51a608f0.19e558"]]},{"id":"7b4c9956.acfc58","type":"switch","z":"4bf947ab.211498","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"1001","vt":"num"},{"t":"eq","v":"1002","vt":"str"},{"t":"eq","v":"1003","vt":"str"},{"t":"eq","v":"2001","vt":"str"},{"t":"eq","v":"2002","vt":"str"},{"t":"eq","v":"2003","vt":"str"}],"checkall":"false","repair":true,"outputs":6,"x":150,"y":300,"wires":[["152bae03.a8beb2","8669e2f1.85e18"],["be8924a5.85ce88","f86a943.76f5a68"],["f05a97bf.f288b8"],["152bae03.a8beb2","c9fa3fd7.398fa"],["be8924a5.85ce88"],["f05a97bf.f288b8"]]},{"id":"b610e1da.630f1","type":"inject","z":"4bf947ab.211498","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":110,"y":740,"wires":[["435751f4.1dc28"]]},{"id":"435751f4.1dc28","type":"function","z":"4bf947ab.211498","name":"set brightness","func":"flow.set('Brightness', env.get('StartBrightness'));\nreturn msg;","outputs":1,"noerr":0,"x":340,"y":740,"wires":[[]]},{"id":"8669e2f1.85e18","type":"change","z":"4bf947ab.211498","name":"1","rules":[{"t":"set","p":"richtung","pt":"flow","to":"1","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":500,"wires":[[]]},{"id":"c9fa3fd7.398fa","type":"change","z":"4bf947ab.211498","name":"-1","rules":[{"t":"set","p":"richtung","pt":"flow","to":"-1","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":270,"y":540,"wires":[[]]},{"id":"f02ae375.ce76d","type":"inject","z":"4bf947ab.211498","name":"","topic":"","payload":"richtung","payloadType":"flow","repeat":"1","crontab":"","once":false,"onceDelay":0.1,"x":500,"y":480,"wires":[["51a608f0.19e558"]]},{"id":"584679a5.c1bed8","type":"function","z":"4bf947ab.211498","name":"calc Brightness","func":"var brightness = parseInt(flow.get('Brightness')) || 1;\nvar step = parseInt(env.get('StepBrightness')) || 10;\nvar direction = parseInt(msg.payload) || 1;\n\nvar newBrightness = brightness + (step *  direction);\nif (newBrightness > 100) newBrightness=100;\nif (newBrightness < 1) newBrightness = 1;\n\nflow.set('Brightness', newBrightness);\n\nmsg.payload = newBrightness;\nreturn msg;","outputs":1,"noerr":0,"x":860,"y":420,"wires":[["a5af8864.f47fe8","4a660c11.3eef94"]]},{"id":"a5af8864.f47fe8","type":"function","z":"4bf947ab.211498","name":"Status Text","func":"msg.payload = "Brightness " + msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":1150,"y":420,"wires":[[]]},{"id":"f86a943.76f5a68","type":"subflow:549c3f58.ff0c9","z":"4bf947ab.211498","name":"","env":[{"name":"TimeRangeInSeconds","value":"2","type":"num"}],"x":540,"y":580,"wires":[["72e4c98e.d8c378"]]},{"id":"72e4c98e.d8c378","type":"switch","z":"4bf947ab.211498","name":"","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"1","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":750,"y":580,"wires":[["4a660c11.3eef94","62117ea.1e7368"]]},{"id":"62117ea.1e7368","type":"change","z":"4bf947ab.211498","name":"Brightness","rules":[{"t":"set","p":"payload","pt":"msg","to":"DoubleClickBrithness","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":910,"y":580,"wires":[[]]},{"id":"cec0708c.4d36b","type":"comment","z":"4bf947ab.211498","name":"Double Click","info":"","x":550,"y":540,"wires":[]},{"id":"24357078.86ba6","type":"comment","z":"4bf947ab.211498","name":"dimming function","info":"","x":700,"y":380,"wires":[]},{"id":"710c80ee.7da92","type":"comment","z":"4bf947ab.211498","name":"direct Switch","info":"","x":470,"y":100,"wires":[]},{"id":"7b10ac7.5b7b554","type":"comment","z":"4bf947ab.211498","name":"Init Brightness","info":"","x":110,"y":700,"wires":[]}]

Wie ihr seht, hat der Subflow 2 Ausgänge. Der 1. Ausgang steuert die Helligkeit und der 2. den Status an/aus. Diese müssen dann noch verbunden werden. Als Eingang dienst der Ikea-Taster mit seinen 6 Statuscodes.

Veröffentlicht unter Node Red | Verschlagwortet mit , , , | 6 Kommentare

Kontinuierlicher Speedtest / Raspberry Pi

Möchte man kontinuierlich einen Speedtest durchführen, konnte ich bis vor wenigen Monaten den Speedtest bei UniFi nutzen. Leider lassen die jetzt den Speedtest nur noch aller 12h zu – damit ist das ganze zum Monitoren etwas obsolet. Da muss was neues her

Speedtest.net bietet seit neustem eine speedtest-cli an womit man den Test auf einer bash durchführen kann. Das Ergebnis will ich später in einer InfluxDB übertragen. Und um das ganze zu kapseln verwende ich dabei Docker.

Visualisierung mittels Grafana aus der InfluxDB

Es geht also damit los, dass man das Dockerfile anlegen muss. Das muss man in zwei Schritten machen. Beim ersten Start von speedtest-cli wird ein Token abgerufen und lokal gespeichert. Den muss man später noch mit rein kopieren.

FROM arm32v7/debian

RUN apt-get -y update \
     && apt-get -y install gnupg1 apt-transport-https dirmngr curl

RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 379CE192D401AB61 \
     && echo "deb https://ookla.bintray.com/debian buster main" | tee  /etc/apt/sources.list.d/speedtest.list

RUN apt-get update && apt-get -y install speedtest

RUN mkdir -p /root/.config/ookla/
ADD assert/speedtest-cli.json /root/.config/ookla/
ADD assert/start.sh /root/start.sh
ADD assert/createMeasure.sh /root/createMeasure.sh
WORKDIR /root

CMD ["./start.sh"] 

Wir bauen uns also von einem Standard arm32 v7 Debian Image das Image. Dazu bbrauchen wir diverse Pakete zum installieren und fügen dann den Server von Ookla hinzu. Die Zeilen ab „mkdir…“ lässt man am Anfang weg 😃 Nach dem ersten build startet mal mit diesem Image ein Container und startet „speedtest“ – bestätigt die ganzen Fragen und es wird in /root/.config/ookla eine speedtest-cli.json erstellt. Diese muss man nun in einem 2. Terminal Fenster mit docker cp raus kopieren oder man lässt sich einfach den Inhalt anzeigen und erstellt lokal die Datei. Ich habbe diese ins Verzeichnis „assert“ gelegt.
Jetzt kann der Rest auch rein.

start.sh

Da der Speedtest kontinuierlich laufen soll gibt es den Einstiegspunkt start.sh wo nichts anderes passiert als Speedtest starten, warten und das ganze wiederholen:

#!/bin/bash
while true
do
./createMeasure.sh
sleep 600
done 

Die eigentliche Messung und übertragung in die InfluxDB findet dann in der createMeasure.sh statt:

#!/bin/bash

# Ausgabe Datei löschen und neu anlegen
rm -f output.txt
touch output.txt

# Speedtest ausführen, Ausgabe als csv und umleiten in die output.txt
speedtest  --format=csv > output.txt
  
# alle Ergebnisse speichere ich noch zusätzlich 
FILENAME=html/`date +'%Y'`-`date +'%m'`_measure.csv
echo Schreibe nach $FILENAME

LASTLINE=`cat output.txt`
echo $LASTLINE >> $FILENAME
echo Ergebnis\r\n$LASTLINE
 
# Auslesen von PING, Download (DL) und Upload (UL) aus der CSV - Kommawerte werden gelöscht.
PING=`echo $LASTLINE |sed -r 's/"//g' | cut -d"," -f3 |cut -d"." -f1`
DL=`echo $LASTLINE |sed -r 's/"//g' | cut -d"," -f6 |cut -d"." -f1`
UL=`echo $LASTLINE |sed -r 's/"//g' | cut -d"," -f7 |cut -d"." -f1`
 
# DL und UL sind Bit/s und müssen in Byte/s umgerechnet werden
DL=`expr $DL \* 8`
UL=`expr $UL \* 8`
 
# Aufbereiten der Anfragen an Influx
DATA1="Speedtest Ping=$PING"
DATA2="Speedtest Download=$DL"
DATA3="Speedtest Upload=$UL"
 
# Senden. Meine Datenbank heißt hier Hausdaten und die Sammlung Speedtest
echo -e "Sending Data\n$DATA1"
curl -i -XPOST 'http://192.168.103.2:8086/write?db=Hausdaten' --data-binary "$DATA1"
 

echo -e "Sending Data\n$DATA2"
curl -i -XPOST 'http://192.168.103.2:8086/write?db=Hausdaten' --data-binary "$DATA2"
 

echo -e "Sending Data\n$DATA3"
curl -i -XPOST 'http://192.168.103.2:8086/write?db=Hausdaten' --data-binary "$DATA3" 

Docker-compose

Das ganze jetzt noch als docker-compose.

version: "3"
 services:
   speedtest:
     build:
       context: .
     image: speedtest
     volumes:
       - './html/:/root/html/'
     restart: always
     network_mode: "host" 

Das Volume ist dafür da, dass ich die Messwerte nach Monat getrennt raus bekomme als CSV. Zusätzlich werden die Werte ja auch an die InfluxDB übertragen.

Und wer jetzt noch nicht genug hat, kann das ganze natürlich noch auf einem mini-Display visualisieren 😀 https://www.blogyourearth.com/computer/raspberry-pi-internet-geschwindigkeit-monitor/10106

Raspberry Pi – Internet Geschwindigkeit Monitor
(c) BlogYourEarth https://www.blogyourearth.com/computer/raspberry-pi-internet-geschwindigkeit-monitor/10106
Veröffentlicht unter Linux | Verschlagwortet mit , , , | Schreib einen Kommentar

Raspberry4 mit GPIO klappt nicht

Bei Raspbbian (Debian auf dem Raspberry) gibt es das Programm gpio womit man den Ausgang/Eingang etc steuern kann.

Das aber auffällt ist, dass „readall“ nicht funktioniert (Unbekanntes Board 17). Anfangs dachte ich an einen Fehler, aber ein apt upgrade brachte keinen Erfolg. Auch andere Programme zu steuern des GPIO Ports schlugen fehl.

Die Lösung ist eine neue Version per Hand zu installieren.

cd /tmp
wget https://project-downloads.drogon.net/wiringpi-latest.deb
sudo dpkg -i wiringpi-latest.deb

Danach klappt es bei mir mit dem schalten. 😃

Ich steuere jetzt meinen Lüfter auf dem Raspberry Pi mit Node Red 😃 Ein Beschaltungsplan findet man hier. Ich nutze da aber nur den Anteil mit dem Transistor. Den bekommt man z.B. bei ELV für wenige Cent. Etwas Schrumpfschlauch drüber und fertig 😃 Passende Steckbrücken gibt es auch 😃

[{"id":"c071c762.57f998","type":"ui_chart","z":"bdd1b89d.421f98","name":"","group":"64f6d013.8d639","order":3,"width":0,"height":0,"label":"CPU Temp","chartType":"line","legend":"false","xformat":"dd HH:mm","interpolate":"linear","nodata":"","dot":false,"ymin":"20","ymax":"","removeOlder":"2","removeOlderPoints":"","removeOlderUnit":"86400","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"outputs":1,"x":430,"y":240,"wires":[[]]},{"id":"ca9663e7.644d5","type":"ioBroker in","z":"bdd1b89d.421f98","name":"CPU Temp","topic":"moma.0.cpuTemperature.main","payloadType":"value","onlyack":"","func":"all","gap":"","x":100,"y":200,"wires":[["c071c762.57f998","a6b7a76.0ef4558"]]},{"id":"3ce6d04a.15a9a","type":"inject","z":"bdd1b89d.421f98","name":"","topic":"","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":40,"wires":[["90974c36.e234a"]]},{"id":"98ebd182.46717","type":"inject","z":"bdd1b89d.421f98","name":"","topic":"","payload":"1","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":80,"wires":[["90974c36.e234a"]]},{"id":"90974c36.e234a","type":"pi-gpiod out","z":"bdd1b89d.421f98","name":"gpio17 11d","host":"::1","port":8888,"pin":"17","set":true,"level":"0","out":"out","sermin":"1000","sermax":"2000","x":630,"y":40,"wires":[]},{"id":"a6b7a76.0ef4558","type":"function","z":"bdd1b89d.421f98","name":"Steuerung","func":"var temp = parseInt(msg.payload);\nvar result = -1;\nif (temp >= 50) {\n    result = 1;\n}\nif (msg.payload < 45){\n    result = 0;\n}\n\nmsg.payload=result;\nreturn msg;","outputs":1,"noerr":0,"x":290,"y":160,"wires":[["6c03f947.cff3b8"]]},{"id":"6c03f947.cff3b8","type":"switch","z":"bdd1b89d.421f98","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"-1","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":470,"y":140,"wires":[[],["90974c36.e234a","e03796c8.4f0ff8"]]},{"id":"e03796c8.4f0ff8","type":"debug","z":"bdd1b89d.421f98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":710,"y":180,"wires":[]},{"id":"64f6d013.8d639","type":"ui_group","z":"","name":"CPU","tab":"9f7696fe.37b808","disp":true,"width":"6","collapse":false},{"id":"9f7696fe.37b808","type":"ui_tab","z":"","name":"System","icon":"dashboard","disabled":false,"hidden":false}]

Update: Damit die Ansteuerung klappt, habe ich noch pigpiod auf dem Raspberry aktiviert und das entsprechende Node Red Modul benutzt. Damit kann Node Red auch auf einem anderen System laufen!

Veröffentlicht unter Bash, Linux, Linux-Welt | Verschlagwortet mit , , , , , , | Schreib einen Kommentar

Apple Music via Browser

Musik am PC/Mac über den Browser

Mit dem Apple MusicKit ist es möglich Apple Music, jetzt auch über den Browser nutzen zu können. Dafür wurde musi.sh ins Leben gerufen und steht als Open-Source Projekt zur Verfügung auf GitHub.

Mit Musi.sh kann man fast alles was man auch über iTunes mit Apple Music machen kann. Man kann keine Musik kaufe – das ist iTunes 🙂

Neben den eigenen Playlists steht die Liste der Künstler, Alben, Songs und der zuletzte hinzugefügten zur Auswahl.

Die kuratierten Bereiche „Für dich“ und „Entdecken“ (Browse) stehen auch zur Verfügung. Einzig das Radio ist leider nicht verfügbar. Radio soll aber auch noch kommen.

Und wer datenschutzrechtliche Bedenken hat kann die Software ja auch selbst hosten 🙂

….neben der Qualität kann man auch noch last.fm connecten.

Veröffentlicht unter Nützliches | Verschlagwortet mit , , , , | Schreib einen Kommentar

Warum man .gitKeep nicht verwenden sollte

Wer mit Git arbeitet wird irgendwann an den Punkt kommen wo man gerne ein leeres Verzeichnis hinzufügen möchte – aber das geht nicht. Es muss wenigstens eine Datei enthalten sein.

Die einfachste Lösung wäre jetzt, eine leere Datei anzulegen – nennen wir sie einfach .gitkeep

Das nächste Problem kommt nun aber wenn Dateien während der Entwicklung im Ordner angelegt werden. Also muss man diesen Ordner in der .gitignore (im Root Ordner) eintragen.

Es geht aber auch einfach!

einfach und simpel kann man eine .gitignore in diesem Ordner anlegen – wer sagt denn, dass das nur im Rootordner geht?!

Dadurch werden alle Dateien in dem Ordner ignoriert, die Datei selbst kann von Git sofort hinzugefügt werden und man muss sonst nichts machen 🙂

Veröffentlicht unter git, Linux-Welt | Verschlagwortet mit , , | Schreib einen Kommentar