Ich hatte schon immer ein Auge auf die Shelly-Produktfamilie, mit der man bestimmte Geräte zu Hause steuern, bzw. ein- und ausschalten kann.
Und zwar ohne, dass ich mir nen klobigen Stecker zwischen Steckdose und Lampe stecke und ohne dass ich mir eine extra Glühbirne kaufen muss, die WLAN, Bluetooth und LTE eingebaut hat.

Als ich mal den Stromverbrauch einiger Elektrogeräte wie Geschirrspüler und Waschmaschine aufzeichnen wollte (also nicht nur den Gesamtverbrauch in kWh, sondern wann während des Betriebes wie viel Watt gezogen werden), stieß ich wieder auf Shelly.

Sowohl der/die/das Shelly Plug wie auch der/die/das Shelly Plug S (und Shelly Plug Plus S – da konnte ich aber keinen wirklichen Benefit im Vergleich zu den beiden anderen feststellen) können den aktuell anliegenden Verbrauch messen.
Shelly Plug S ist allerdings nur bis zu 2500 Watt ausgelegt, der teurere Shelly Plug ohne S macht bis zu 3500 Watt mit.

Nun habe ich doch den klobigen Stecker zwischen Steckdose und Gerät, aber für diesen Zweck genau das Richtige – ist sowieso hinter nem Schrank ;-)

Toll, dass ich den Shelly Plug sowohl ohne irgendeinen Hersteller-Cloud-Registrierungszwang in Betrieb nehmen kann, als auch ohne irgend einen Cloud-Kram nutzen kann, denn die Shelly-Geräte können unter anderem über MQTT kommunizieren.

Shelly Plug in Betrieb nehmen

Shelly Plug in eine Steckdose einstecken und kurz darauf sollte ein weiteres WLAN-Netzwerk im Äther auftauchen.
 
Mit dem betreffenden WLAN verbinden und im Browser die Adresse http://192.168.33.1 aufrufen – das ist die Standard-IP des Shelly-Gerätes nach Auslieferung.

Nun kann man unter "Internet & Security" > "WiFi mode – Client" Namen und Schlüssel des eigenen WLANs eintragen, so dass sich der Shelly nach einem Neustart mit dem vorhandenen WLAN-Netzwerk verbindet, anstatt einen eigenen WLAN zu generieren. (Dass man den WLAN-Namen selbst eintippen muss, ist etwas unschön, aber wenn alles andere so einfach geht wie hier bei Shelly, dann sei das verziehen).

Nach einem Neustart sollte der Shelly Plug nun im heimischen WLAN mit einer anderen IP-Adresse zu finden sein.
Im Folgenden verwende ich als Beispiel die Adresse 192.168.198.200

Nochmals zurück auf die Einstellungs-Oberfläche in "Internet & Security" > "Advanced – Developer Settings".

Hier aktivieren wir nun ColoT und MQTT, tragen die Adresse des MQTT-Hosts samt Zugangsdaten ein und geben dem Shelly Plug einen Namen (Prefix).

 

Man kann aber auch auf MQTT verzichten.
Unter der Adresse http://SHELLY-IP/status bekommt man den aktuellen Status inklusive aktuellem Verbrauch in Watt als JSON-Antwort zurück und könnte damit weiterarbeiten.

Achtung: Unter dem Menüpunkt "Safety" kann noch angegeben werden, ab wie viel Watt gezogener Leistung sich der Shelly ausschaltet. Dies war bei meinem Shelly Plug S ziemlich tief eingestellt, so dass der Geschirrspüler dann ausgeschaltet wurde, sobald er mit heizen anfing.
Ich weiß nicht, wieso man an dieser Stelle einen kleineren Wert als jenen eintragen sollte, für den der Shelly Plug tatsächlich ausgelegt ist.

Shelly und MQTT

Nun musste ich erst einmal herausfinden, wo hin genau der Shelly Plug seinen Status publisht.
Es handelt sich wohl um ein Gen1-Gerät, zu dem ich hier und hier hilfreiche MQTT-Infos gefunden hatte.

Kurz gesagt kann ich den aktuellen Verbrauch (bzw was der Shelly Plug als letztes an den mqtt-Broker als Verbrauch gesendet hatte) wie folgt abrufen:

mosquitto_sub -h <mqtt_server> -p <port> -u <mqtt_user> -P <mqtt_pass> -t shellies/<shelly prefix>/relay/0/power

# Beispiel:
mosquitto_sub -h 192.168.198.20 -p 1883 -u apfelz -P gehe1m3sPasswd -t shellies/shellyplug/relay/0/power

Hier noch zur Inspiration ein Skript, mit welchem ich den Stromverbrauch eines Gerätes aufzeichne.

Um aufzuzeichnen, wie der Stromverbrauch in den einzelnen Modi Eco/Auto/Intensiv des Geschirrspülers ist, lasse ich das Skript mit powerrecord.pl <shelly prefix> <bezeichnung> den Stromverbrauch mitschneiden und in einer Datenbank speichern.
Jaaa...ich steh' auf perl...

#!/usr/bin/perl

use DBI;
use strict;
use JSON;
use Net::MQTT::Simple;

my $genauigkeit = 5; # Nur neue Werte speichern, wenn mehr als $genauigkeit Watt Abweichung

$SIG{'INT'} = 'INT_handler';

my ($s,$i,$h,$d,$m,$y,$wday,$yday,$isdst) = localtime();
$m++; $y+=1900;

my $shelly = $ARGV[0];
my $bezeichnung = $ARGV[1];

if ($bezeichnung eq "") {
  print "Verwendung: powerrecord.pl <shelly-id> <Profilname zum Speichern>\n";
  print "Beispiel:   powerrecord.pl 'shellyplug-1' 'Geschirrspüler'";
  exit;
  }

# mySQL-Konfiguration
my $db = DBI->connect("DBI:mysql:database=powerrecord;host=127.0.0.1;port=3306", "dbuser", "dbpass", {RaiseError => 0, AutoCommit =>1, mysql_auto_reconnect=>1})
          or die "$d.$m.$y $h:$i Datenbankverbindung konnte nicht hergestellt werden.";
my $getProfil = $db->prepare_cached("SELECT count(id) as anz FROM geraeteprofile WHERE bezeichnung = ?");

# Gibt es bereits ein Profil mit dieser Bezeichnung?
$getProfil->execute($bezeichnung);
my ($dupl) = $getProfil->fetchrow_array();
$getProfil->finish();
if ($dupl > 0) {
  print "Bezeichnung $bezeichnung bereits vorhanden.\n";
  $db->disconnect();
  exit;
  }

# Dann legen wir das Profil nun an
my $insertProfil = $db->prepare_cached("INSERT INTO geraeteprofile (bezeichnung) VALUES (?)");
$insertProfil->execute($bezeichnung);
my $id = $insertProfil->{mysql_insertid};
$insertProfil->finish();

$ENV{MQTT_SIMPLE_ALLOW_INSECURE_LOGIN} = 1;
my $mqtt = Net::MQTT::Simple->new('127.0.0.1:1883');
$mqtt->login("mqttuser", "mqttpass");
$mqtt->subscribe("shellies/$shelly/relay/0/power", \&received);

# Los geht's...
my $last_timestamp = time();
my $last_wert = undef;
my $insertWert   = $db->prepare_cached("INSERT INTO geraeteprofile_aufzeichnung (idProfil, dauer, watt) VALUES (?, ?, ?)");
print "Aufzeichnung gestartet am $d.$m. um $h:$i\nZum Beenden ctrl-C drücken.\n";
while (1) {
  $mqtt->tick();
  sleep(1);
  }

sub received {
  my ($topic, $payload) = @_;
  if ($last_wert ne undef && int($payload) ge $last_wert-$genauigkeit && int($payload) le $last_wert+$genauigkeit) { return; }
  print $payload, " Watt\n";
  my $timediff = time()-$last_timestamp;
  if ($last_wert ne undef) {
    $insertWert->execute($id, $timediff, $last_wert);
    }
  $last_timestamp = time();
  $last_wert = int($payload);
  }

$mqtt->disconnect();
$insertWert->finish();
$db->disconnect();

sub INT_handler {
  my $timediff = time()-$last_timestamp;
  if ($last_wert ne undef) { $insertWert->execute($id, $timediff, $last_wert); }
  $insertWert->finish();
  # Gesamtverbrauch kalkulieren
  my $insertGesamt = $db->prepare_cached("UPDATE geraeteprofile set kwh_gesamt = (select sum(dauer*watt/3600/1000) from geraeteprofile_aufzeichnung where idProfil = ?) where id = ?");
  $insertGesamt->execute($id, $id);
  $insertGesamt->finish();
  $db->disconnect();
  $mqtt->disconnect();
  print "Aufzeichnung beendet.\n";
  exit 0;
  }
sub EXIT {
#  close(MQTT);
  $insertWert->finish();
  $db->disconnect();
  $mqtt->disconnect();
  exit 0;
  }