Hinzufügen des SDM-220-Zählers zu OpenHab

Published on April 24, 2017

Hinzufügen des SDM-220-Zählers zu OpenHab

  • Tutorial
Fast ein Jahr ist vergangen, seit ich zum ersten Mal einen Stromzähler mit einer RS485 / ModBus-Schnittstelle SDM-220 veröffentlicht habe. Dann gab es einen zweiten Artikel zum Sammeln von Daten und Verarbeiten von Statistiken. Dies ist der dritte, hoffentlich der letzte. Es geht darum, wie der Zähler in OpenHab integriert wird . Das Ergebnis passt zu mir.



Der erste Versuch, Statistiken vom Zähler zu erfassen, wurde mit dem externen Cloud-Dienst ThingSpeak unternommen . Als lokaler Server, der den Zähler abfragt, wurde ein Thin Client (Minicomputer) mit einem auf dem USB-Stick installierten Ubuntu-Server verwendet . Es war der erste Fehler - das Flash-Laufwerk "starb" nach 3 Monaten (Unfall, dachte ich). Ohne irgendwelche Schlussfolgerungen zu ziehen, habe ich das zweite Flash-Laufwerk in 2 Monaten getötet (Muster). In der dritten Version wurde bereits eine USB-Tasche mit einer 2,5 "-Schraube als Speicher verwendet.

Der ThingSpeak-Dienst selbst ermöglicht eine gewisse Verarbeitung, lässt jedoch keine ausreichende Flexibilität bei der Datenmanipulation zu. Daten pro Tag wurden beispielsweise als die Summe der Daten pro Stunde erfasst. Wenn ein Datenpaket nicht vom Server empfangen wurde oder ich beim Testen mehrere Daten gesendet habe, ist ein Fehler aufgetreten. Die Überlegungen, die dvuhtarifny Buchhaltung in Bezug auf die Tageszeit zu halten, haben den Optimismus nicht ergänzt.

Im Allgemeinen habe ich mich für OpenHab entschieden .

Aufgabe eins: Holen Sie sich die Rohdaten von der Theke.


Die Installation von OpenHab selbst ist in der Anleitung beschrieben . Nach der Installation müssen Sie die ModBus-Bindung - Bindung-Modbus1 - 1.9.0 über das Bedienfeld Papier → Bindungen installieren.Der Modbus- Bus wird über den USB-RS485-Adapter abgefragt.



lsusb
Bus 002 Device 002: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
ls /dev/ttyUSB*
/dev/ttyUSB0
sudo adduser openhab dialout
sudo adduser openhab tty

Dann wird empfohlen, Berechtigungen für Java festzulegen (dies wird auch in der OpenHab-Installationsanleitung ausführlich beschrieben):

sudo vi /etc/default/openhab2 
EXTRA_JAVA_OPTS="-Dgnu.io.rxtx.SerialPorts=/dev/ttyUSB0"

Nach diesen Manipulationen müssen Sie die Konfigurationsdatei services / modbus.cfg konfigurieren :

 sudo vi  /etc/openhab2/services/modbus.cfg
#Период опроса счетчика
poll=30000
#Счетчик не позволяет вычитать все регистры за одно обращение, поэтому нужно создать отдельную запись для каждого регистра. Поле start - номер регистра. В строке connection указываем номер и параметры порта (9600,8,n,1), задержку перед чтением каждого регистра и таймаут ответа.
#напряжение - 0x00
serial.slave1.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none
serial.slave1.type=input
serial.slave1.start=0
serial.slave1.length=2
serial.slave1.valuetype=float32
#ток - 0x06
serial.slave2.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none
serial.slave2.type=input
serial.slave2.start=6
serial.slave2.length=2
serial.slave2.valuetype=float32
#активная мощность - 0x0C
serial.slave3.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none
serial.slave3.type=input
serial.slave3.start=12
serial.slave3.length=2
serial.slave3.valuetype=float32
#показания счетчика (активная энергия) - 0x156
serial.slave4.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none
serial.slave4.type=input
serial.slave4.start=342
serial.slave4.length=2
serial.slave4.valuetype=float32

Dann müssen Sie die Datenelemente in der Datei items / sdm220.items erstellen :

sudo vi /etc/openhab2/items/sdm220.items
#Определяем группу для элементов
Group gSDM220
#и указываем, откуда их брать и как выводить, energy - это имя иконки из стандартного набора
Number sdm220_voltage  "Напряжение  [%.1f В]" <energy> (gSDM220) {modbus="slave1:0"}
Number sdm220_current  "Ток  [%.2f А]" <energy> (gSDM220) {modbus="slave2:0"}
Number sdm220_actpower  "Мощность  [%.1f Вт]" <energy> (gSDM220) {modbus="slave3:0"}
Number sdm220_actcounter  "Счетчик электроэнергии  [%.1f кВт*ч]" <energy> (gSDM220) {modbus="slave4:0"}

Es verbleibt das Hinzufügen der aktuellen Messwerte im Dashboard. Bearbeiten Sie dazu die Datei sitemaps / default.sitemap :

sudo vi /etc/openhab2/sitemaps/default.sitemap 
sitemap default label="alk0v SmartHome (default sitemap)" {
    Frame label="Электросчетчик" {
        Text item=sdm220_voltage
        Text item=sdm220_current
        Text item=sdm220_actpower
        Text item=sdm220_actcounter
    }
}

Im Prinzip reicht dies aus, um den aktuellen Zählerstand zu sehen:



Aufgabe zwei: HabPanel-Einrichtung und Visualisierung von Messwerten


OpenHab unterstützt mehrere Control Panels. HabPanel hat mir anscheinend am besten gefallen . Über Paper UI → User Interfaces installieren wir HabPanel - ui-habpanel - 2.0.0 .

Zum Zeichnen von Diagrammen müssen Sie außerdem Daten irgendwo speichern. OpenHab verwendet den Begriff Persistenz für Datenbanken. Ich wollte die MySQL-Datenbank benutzen, die Community diskutierte viele Probleme mit dieser Datenbank, am Ende fand ich Anweisungen , die für mich funktionierten.

Installieren Sie also MySQL Persistence (persistence-mysql - 1.9.0).

Installieren Sie MySQL:

sudo apt-get install mysql-server
sudo mysql -u root -p

Datenbank konfigurieren:

CREATE DATABASE OpenHAB;
CREATE USER 'openhab'@'localhost' IDENTIFIED BY 'YOURPASSWORD';
GRANT ALL PRIVILEGES ON OpenHAB.* TO 'openhab'@'localhost';
quit

Openhab neu starten:

sudo service openhab2 stop
sudo service openhab2 start

Das Recht auf Dienstleistungen / mysql.cfg :

# the database url like 'jdbc:mysql://<host>:<port>/<database>' (without quotes)
url=jdbc:mysql://localhost:3306/openhab
# the database user
user=openhab
# the database password
password=YOURPASSWORD

Regeln Persistenz / mysql.persist . Standardmäßig werden die Werte aller Elemente bei jeder Änderung in die Datenbank eingegeben:

Strategies {
        // if no strategy is specified for an item entry below, the default list will be used
        everyMinute     : "0 * * * * ?"
        every5Minutes : "0 */5 * * * ?"
        everyHour   : "0 0 * * * ?"
        everyDay    : "0 0 0 * * ?"
        default = everyChange
}
Items {
    // persist all items once a day and on every change and restore them from the db at startup
    * : strategy = default, restoreOnStartup
}

Wenn alles korrekt eingerichtet ist, sollten die Artikeltabelle und die ItemXX-Tabellen für jeden Artikel in der Datenbank angezeigt werden.


mysql> use openhab;
Database changed
mysql> show tables;
+-------------------+
| Tables_in_openhab |
+-------------------+
| Item1             |
| Item2             |
| Item3             |
| Item4             |
| Items             |
+-------------------+
5 rows in set (0.00 sec)
mysql> select * from Items;
+--------+--------------------------+
| ItemId | ItemName                 |
+--------+--------------------------+
|      1 | sdm220_voltage           |
|      2 | sdm220_actpower          |
|      3 | sdm220_actcounter        |
|      4 | sdm220_current           |
+--------+--------------------------+
4 rows in set (0.00 sec)

Jetzt können Sie HabPanel mit Schönheit versehen.

Dashboard hinzufügen, neue Widgets hinzufügen. Anzeigen der vom Widget Dummy verwendeten Werte , Anzeigen von Diagrammen - Diagramm . Es ist alles intuitiv. Ich habe die Leistungs- und Spannungsparameter mit zwei verschiedenen Y-Skalen in einen Graphen gebracht.

Geben Sie die MySQL-Datenquelle an:



Passen Sie die Schwellenwerte für die Spannungsachse an:



Fügen Sie Elemente hinzu, geben Sie die Farbe und den Linientyp für sie an, geben Sie die Sekundärachse für die Spannung an:



Erhalten Sie das Ergebnis :)



Die dritte Aufgabe: stündliche und tägliche Erfassung des Stromverbrauchs


Die Anzeige von Zustandsänderungen über die Zeit ist gut, aber ich wollte auch Statistiken über den Verbrauch pro Stunde, Tag und Monat erhalten. Das heißt, die Aufgabe besteht darin, periodisch einige Berechnungen durchzuführen. Hier hilft der Regelmechanismus in OpenHab.

Richten Sie also die Regeln ein .

Zuerst müssen Sie items / sdm220.items neue Elemente hinzufügen :

Number sdm220_hourcounter (gSDM220)
Number sdm220_daycounter (gSDM220)

Dann erstellen wir die Datei rules / energy.rules , in der Sie zwei Regeln angeben müssen: eine wird einmal pro Stunde ausgeführt, die zweite - einmal pro Tag.

rule "Energy by hour"
when
        Time cron "0 0 * * * ?"
then
//вычисление расхода. Из текущих показаний счетчика вычитаются значения из базы на час раньше   
        var hour = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusHours(1), "mysql":).state as DecimalType
//вывод данных в лог для отладки
        logInfo("TEST","sdm220_hourcounter = "+hour)
//присваиваем значение Item
        postUpdate(sdm220_hourcounter, hour)
end
rule "Energy by day"
when
        Time cron "0 0 0 * * ?"
then
        var day = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusDays(1), "mysql":).state as DecimalType
        postUpdate(sdm220_daycounter, day)

Zum Debuggen können Sie die Konsole OpenHab verwenden. Standard Login und Passwort: openhab / habopen. Sie können mit dem folgenden Befehl eine Verbindung herstellen:

ssh -p 8101 openhab@localhost
openhab> log:tail
19:22:00.012 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.526123046875
19:22:00.014 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.861083984375
19:22:09.462 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_current changed from 16.0433025360107421875 to 5.69449329376220703125
19:22:11.500 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_actcounter changed from 2387.51904296875 to 2387.5458984375
19:22:13.532 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_voltage changed from 192.7679595947265625 to 200.4195098876953125
19:22:15.568 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_actpower changed from 2271.8486328125 to 1132.8717041015625
19:23:00.014 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.515869140625
19:23:00.015 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.8769531250

Oder Sie können die Protokolldatei anzeigen:

tail -f /var/log/openhab2/openhab.log
2017-04-18 19:17:45.587 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'energy.rules'
2017-04-18 19:18:00.259 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.571044921875
2017-04-18 19:18:00.272 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.8330078125
2017-04-18 19:19:00.015 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.83789062500
2017-04-18 19:19:00.025 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.557861328125
2017-04-18 19:20:00.013 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.55517578125
2017-04-18 19:20:00.024 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.859130859375

Ich habe vor, den Hauptstromzähler auf einen Zweistarif umzustellen, nach dem der Stromverbrauch im Bereich von 23:00 bis 07:00 Uhr mit dem Faktor 0,5 vergütet wird, also möchte ich den erwarteten Effekt sehen und zwei Tarife beibehalten. Zuerst habe ich einfach zusätzliche Bedingungen für die Zeit zu Items and Rules hinzugefügt und die Tag- und Nachtablesungen in zwei verschiedene Tabellen eingetragen. In der Datenbank war alles schön, aber in der Grafik sah es unbeholfen aus, da die Grafik die letzten beiden Werte mit einer geraden Linie verband:



Ich musste ein wenig verwirrt sein, um meinen Sinn für Schönheit zu amüsieren.

Die endgültigen Skriptregeln für die Kontoführung mit zwei Tarifen sehen also folgendermaßen aus:

rule "Energy by hour"
when
        Time cron "0 0 * * * ?"
then
        var hour = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusHours(1), "mysql":).state as DecimalType
//определяем диапазоны времени
        if(now.getHourOfDay > 7 && now.getHourOfDay < 23)
        {
                logInfo("TEST","sdm220_hourcounter_day = "+hour)
                postUpdate(sdm220_hourcounter_day, hour)
        }
        else
        {
//на границе диапазонов добавляем нулевые значения в график
//так как в таблице в качестве primary key используется timestamp, между добавлениями данных в одну и ту же таблицу стоит пауза в одну секунду
                if(now.getHourOfDay==7)
                {
                        postUpdate(sdm220_hourcounter_night, hour)
                        Thread::sleep(1000)
                        postUpdate(sdm220_hourcounter_night, 0)
                        Thread::sleep(1000)
                        postUpdate(sdm220_hourcounter_day, 0)
                        Thread::sleep(1000)
                        postUpdate(sdm220_hourcounter_day, hour)
                }
                else if(now.getHourOfDay==23)
                {
                        postUpdate(sdm220_hourcounter_day, hour)
                        Thread::sleep(1000)
                        postUpdate(sdm220_hourcounter_day,0)
                        Thread::sleep(1000)
                        postUpdate(sdm220_hourcounter_night, 0)
                        Thread::sleep(1000)
                        postUpdate(sdm220_hourcounter_night, hour)
                }
                else
                {
                        postUpdate(sdm220_hourcounter_night, hour)
                }
        }
        postUpdate(sdm220_hourcounter, hour)
end
rule "Energy by day"
when
        Time cron "0 0 0 * * ?"
then
        var day = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusDays(1), "mysql":).state as DecimalType
        //night counter, 00:00..07:00 + 23:00..00:00
        var day2 = sdm220_actcounter.historicState(now.minusHours(17),"mysql":).state as DecimalType - sdm220_actcounter.historicState(now.minusDays(1), "mysql":).state as DecimalType + sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusHours(1),"mysql":).state as DecimalType
        //day counter, 07:00..23:00
        var day1 = sdm220_actcounter.historicState(now.minusHours(1),"mysql":).state as DecimalType - sdm220_actcounter.historicState(now.minusHours(17),"mysql":).state as DecimalType
        logInfo("TEST","sdm220_daycounter_day = "+day1)
        logInfo("TEST","sdm220_daycounter_night = "+day2)
        logInfo("TEST","sdm220_daycounter = "+day)
        postUpdate(sdm220_daycounter, day)
        postUpdate(sdm220_daycounter_day, day1)
        postUpdate(sdm220_daycounter_night, day2)
end

Fügen Sie vor dem Bearbeiten des Skripts die erforderlichen Elemente hinzu:

Number sdm220_hourcounter_day (gSDM220)
Number sdm220_hourcounter_night (gSDM220)
Number sdm220_daycounter_day (gSDM220)
Number sdm220_daycounter_night (gSDM220)

Der Zeitplan für den stündlichen und täglichen Verbrauch sieht nun so aus:



Vielleicht alles. Die Pläne fügen noch die Berechnung des Strom- und Geldverbrauchs für den Monat zum Tag- und Nachttarif hinzu und erstellen einen Bericht mit Versand per Post.