Allgemeines
- Das System ist im Netzwerk unter der IP http://192.168.178.40/ zu erreichen.
- Shell-User: pi
Einrichtung
RasPi vorbereiten
Anleitung: https://pimylifeup.com/raspberry-pi-serial/
mit diesem Befehl kann ermittelt werden welche Devices verwendet werden:
dmesg | grep tty
Das Ergebnis sieht derartig aus: Die potentiell relevanten Devices sind ttyAMA0 und ttyACM0
[ 0.000000] Kernel command line: bcm2708_fb.fbwidth=656 bcm2708_fb.fbheight=416 bcm2708_fb.fbswap=1 vc_mem.mem_base=0x3ec00000 vc_mem.mem_size=0x40000000 dwc_otg.lpm_enable=0 console=tty1 root=PARTUUID=fcfc0506-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles
[ 0.000358] console [tty1] enabled
[ 0.720357] 3f201000.serial: **ttyAMA0** at MMIO 0x3f201000 (irq = 87, base_baud = 0) is a PL011 rev2
[ 4.021062] cdc_acm 1-1.5:1.0: **ttyACM0**: USB ACM device
Zum Ablegen der Dateien wird ein Webserver benötigt. Dieser kann mit dem folgenden Befehl installiert werden:
sudo apt-get install apache2
Für die Verbindung zwischen Webserver und Python wird Flask verwendet. Dies kann über die folgende Anleitung eingerichtet werden. Achtung: Abweichend zur Anleitung in Flask folgenden Code verwenden um extern aufrufbar zu sein: app.run(host=’0.0.0.0′)
https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d
Zusätzlich sollte der Phyton-Package-Installer installiert weden:
sudo apt-get install python-pip
Nach der Implementierung des unten genannten Scripts werden diverse fehlende Module bemängelt. Diese müssen dann mit „sudo pip install <modulname>“ installiert werden.
Bitte: Beim nächsten Setup die notwendigen Module aufschreiben 🙂
https://pythonspot.com/tag/json/
Verzeichnisse einrichten
Samba einrichten und freigeben:
https://www.elektronik-kompendium.de/sites/raspberry-pi/2007071.htm
Script anlegen
Das Script kann natürlich nach dem Anlegen der Shares auch über einen externen Editor bearbeitet werden.
cd ~/home/shares/pi
Edit Script: nano aqaperla.py
Das folgende Script gibt schon mal die relevanten Werte aus. Diese müssen zum Teil noch konvertiert werden. Zum Beispiel erhält man
Wasser_Vebrauch_24h
: :T
0D 08 02 3A 03 54 0A
Hier sind nur der vierte und fünfte Wert relevant:3A 03 = (48 + 10) + (0 + 3)*256 = 826 lArduinno als Sensor:
#!/usr/bin/python3
from flask import Flask, flash, redirect, render_template, request, session, abort
import os
import urllib2
import time
import requests
import binascii
import struct
import json
tmpl_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
app = Flask(__name__, template_folder=tmpl_dir)
def init_serial():
import serial
# Serial connection
# define serial port (serial port speed 19200 baud, 8 databits, 1 stopbit, no parity)
# serial.Serial parameter: port=None, baudrate=9600, bytesize=EIGHTBITS, parity=PARITY_NONE, stopbits=STOPBITS_ONE, timeout=None, xonxoff=False, rtscts=False, write_timeout=None, dsrdtr=False, inter_byte_timeout=None
port = "/dev/ttyACM0"
speed = 19200
ser = serial.Serial(port, speed, timeout=0.5)
return ser
def ser_cmd():
print 'Init Serial'
#import serial
ser = init_serial()
cmdName = "Wasser_Vebrauch_24h"
cmd = 0x08
ser.flushInput() #flush input buffer, discarding all its contents
ser.flushOutput() #flush output buffer, aborting current output and discard all that is in buffer
start_byte = 0x0D
stop_byte = 0x0A
command = cmd
parameter = 0 # except for reading alarms
crc = 0 # start_byte + cmd + parameter
# build the command: bytearray and CRC
crc = start_byte + command + parameter
arr = bytearray([start_byte, command, parameter, crc, stop_byte])
# send command
ser.write(arr)
# read results
res = ser.read(size=256)
# calculate integer result
x = str(res).strip()
y = x[2:len(x)-1]
z = bytes(res)
a = ''.join( [ "%02X " % ord( b ) for b in z[3:5] ] ).strip()
high = "0x" + a[3:5]
low = "0x" + a[0:2]
print high
print low
print str(int(high, 0) * 256 + int(low, 0))
return "34.4033.value:" + str(int(high, 0) * 256 + int(low, 0))
# close conn
ser.close()
@app.route("/")
def hello2():
return "Hello World!"
@app.route("/hello")
def hello():
return "Hello World!"
@app.route("/wasserverbrauch")
def wasserverbrauch():
print 'Wasser_Vebrauch_24h'
result = ser_cmd()
return result
def serial():
ser = init_serial()
# BWT_AQA_PERLA_S CMD_SAEULE1_SOLLKAPAZITAET 0x02 = 2 // Sollkapazitaet Saeule 1
# BWT_AQA_PERLA_S CMD_SAEULE2_SOLLKAPAZITAET 0x03 = 3 // Sollkapazitaet Saeule 2
# BWT_AQA_PERLA_S CMD_MAX_DURCHFLUSS_HEUTE_LITER 0x05 = 5 // Spitzendurchfluss heute
# BWT_AQA_PERLA_S CMD_MAX_DURCHFLUSS_GESTERN_LITER 0x06 = 6 // Spitzendurchfluss gestern
# BWT_AQA_PERLA_S CMD_MAX_DURCHFLUSS_SEIT_IBN_LITER 0x07 = 7 // Spitzendurchfluss seit IBN
# BWT_AQA_PERLA_S CMD_Wasser_Vebrauch_24h 0x08 = 8 // Verbrauch letzte 24h
# BWT_AQA_PERLA_S CMD_VERBRAUCH_SEIT_IBN 0x10 = 16 // Verbrauchdaten seit IBN Verbrauch
# BWT_AQA_PERLA_S CMD_REGENERATIONEN_SEIT_IBN 0x11 = 17 // Regenerationen seit IBN
# BWT_AQA_PERLA_S CMD_SALZVERBRAUCH_GRAMM_SEIT_IBN 0x13 = 19 // Salztverbrauch seit IBN
# BWT_AQA_PERLA_S CMD_Wasser_Kapazitaet Saeule 1 0x25 = 37 // Kapa Saeule 1
# BWT_AQA_PERLA_S CMD_Wasser\Kapazitaet Saeule 2 0x26 = 38 // Kapa Saeule 2
# BWT_AQA_PERLA_S CMD_ALARM 0x20 = 32 // Alarm --> do not read now
command_set = [0x02, 0x03, 0x05, 0x06, 0x07, 0x08, 0x10, 0x11, 0x13, 0x25, 0x26, 0x12, 0x19, 0x15, 0x21, 0x24] # list of all commands to execute
command_name = ["SAEULE1_SOLLKAPAZITAET", "SAEULE2_SOLLKAPAZITAET", "MAX_DURCHFLUSS_HEUTE_LITER", "MAX_DURCHFLUSS_GESTERN_LITER","MAX_DURCHFLUSS_SEIT_IBN_LITER", "Wasser_Vebrauch_24h", "VERBRAUCH_SEIT_IBN", "REGENERATIONEN_SEIT_IBN","SALZVERBRAUCH_GRAMM_SEIT_IBN", "SAEULE1_RESTKAPAZITAET", "SAEULE2_RESTKAPAZITAET", "REGENERATIONEN_SEIT_SERVICE", "SOFTWARE_VERSION", "IBN_DATUM", "LOG", "KW"]
result_set = [] # will hold the results
# Execute all commands in command_set and save results in result_set
result = ser_cmd(ser, "Wasser_Vebrauch_24h", 0x08)
return result[5]
#json_string = '{"first_name": "Guido", "last_name":"Rossum"}'
#parsed_json = json.loads(json_string)
#f.write(json.dumps(parsed_json))
if __name__ == "__main__":
app.run(host='0.0.0.0')
Script ausführen
Selektiv starten
cd ~/home/shares/pi
python aqaperla.py parameter &
Mit der Erweiterung parameter & wird die Ausführung im Hintergrund gestartet
Bei jedem Start ausführen
Wie Scripts bei jedem Start automatisch geladen werden wird zum Beispiel hier beshrieben: https://wiki.ubuntuusers.de/rc.local/
Dafür muss zunächst die folgende Datei bearbeitet werden:
sudo nano /etc/rc.local
Der Aufruf des Scripts muss einfach vor den Befehl exit 0 eingefügt werden:
python /home/shares/pi/aqaperla.py parameter & # Python für Aqaperla
Speichern + verlassen des Editors: Strg-X –> Y –> Enter
Aqaperla-Schnittstelle
Dieser Artikel enthält eine Liste mit Kommandos für den Aqaperla und eine Strukturbeschreibung der Daten:
https://www.symcon.de/forum/threads/25709-BWT-Aqa-Perla-goes-IP-Symcon/page2
Hier wird ein ausführliches Script vorgestellt. Vermutlich können hieraus auch die Konvertierungsregeln aller Kommandos abgeleitet werden: https://knx-user-forum.de/forum/supportforen/openhab/42254-bwt-aqua-perla-auslesen-jedoch-fehlt-mir-der-aktuelle-durchfluss
Das Github-Projekt
https://github.com/eleven6/bwt-aqaperla/blob/master/v1.0/aqa.py
AqaPerla-Service
https://www.energiesparhaus.at/forum-bwt-aqa-perla-service-selber-machen/34376_2
ESP8266 und PI verbinden
https://tutorials-raspberrypi.de/openhab-raspberry-pi-esp8266-mqtt-nodemcu-homeautomation/
To Dos
- Abrufen aller anderen Werte
- Refactoring Quellcode
- Einbindung in JSON-Stream?
Sicherung
Zum Mounten der Netzlaufwerke folgendes Script (nach diesem Link):
sudo apt-get install cifs-utils keyutils
sudo mkdir /mnt/backups/
Zur Sicherung habe ich den folgenden Code verwendet:
sudo dd bs=4M if=/dev/mmcblk0 of=/mnt/backups/20200504_aqaperla_raspbian.img
zip -9 /mnt/backups/20200504_aqaperla_raspbian.img.zip /mnt/backups/20200504_aqaperla_raspbian.img
Diesee Befehle laufen sehr lange, da die ganze Karte kopiert wird, auch die leeren Blöcke. Mit einer kleineren Karte würde es also schneller gehen.
Weitere Infos aus dem Blog:
- Now you can run „dd if=/dev/mmcblk0 of=/dev/sda bs=1b“
- NOTE: /dev/mmcblk0 refers to the whole SD card and not any one partition
- This will take anywhere from 10 min to an hour depending on the size of the SD card you have. When it’s done you should as a minimum run „fsck /dev/sda2“ since you copied a running „live“ filesystem.
Not only is this a backup of your whole SD card (W95 „/boot“, and Linux ext4 „/“), it can also be used to boot the system.
Gute Seiten dazu:
- https://www.raspberrypi.org/documentation/linux/filesystem/backup.md
- https://raspberrypi.stackexchange.com/questions/3800/find-the-right-device-name-of-an-sd-card-connected-via-a-usb-card-reader
Regenerierungsschritt im Entkalker
- Schritt: <- -> (Säule tauschen?)
- H2O
- NaCL
- ???
- H2O
- – leer –
- H20
Einplanung des Scripts mit Crontab
Die Conttab kann mit folgendem Befehl angezeigt werden:
sudo crontab -e
sudo nicht vergessen!, sonst wird nicht die root-contab angezeigt!!
Schreibe einen Kommentar