nD-enerserve Forums

Full Version: 230VAC Energiemessung und Schaltung
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Ich habe den SmartPi für einen Einsatz von nur einer Phase 230 VAC vorgesehen. Will im Winter die 230 VAC Leistungsaufnahme des Wohnmobils messen. Das WoMo steht zur Überwinterung an einem Ort, wo ich keinen direkten Internetzugang habe. Dazu wird über ein UMTS-Stick die Verbindung zum Raspberry Pi per SMS erstellt. Den aktuellen kumulierten Leistungswert will ich über SMS abrufen können, weiter will ich per SMS die 230 VAC Speisung zum Wohnmobil ein- und ausschalten. Weitere Funktionen werden sich noch ergeben.

Ich verwende auf meinen Raspberry Pi das wvdial über einen HUAWEI LTE Stick E3372h-607 und Swisscom SIM Prepaid. Über PuTTY und WinSCP und Yaler (Yaler is a relay infrastructure for secure access) kann ich erfolgreich darauf zugreifen. 
Zusätzlich habe ich mit SMSTools3 und Scripting eine Steuerung mit SMS erstellt. Den aktuellen Energiewert und Tageswert in kWh kann ich per SMS zu jeder Zeit abrufen.

Vielen Dank an Alle die im Internet Beiträge veröffentlichen - daraus ergeben sich immer wieder Ideen wie die Programmierung erfolgen kann.

Prinzipschaltbild:

[attachment=107]

Aufbaubild:                                                           SMS Leistungsabfrage pro Tag und Monat:

[attachment=106]                 [attachment=108]

Nachfolgend die wichtigsten Programmteile die ich dazu erstellt habe.

Automatischer Reboot des Raspberry Pi mit rc.local:
Code:
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
 printf "My IP address is %s\n" "$_IP"
fi

echo "++++++++++++++ rc.local wird ausgeführt"  > /home/pi/boot.log
sleep 10
lsusb >> /home/pi/boot.log
echo "------------- rc.local usb_modeswitch"  >> /home/pi/boot.log
usb_modeswitch -v 12d1 -p 1f01 -M "55534243123456780000000000000011063000000100010000000000000000"
sleep 3
lsusb >> /home/pi/boot.log
sleep 3
echo "------------- rc.local sms3 restart"  >> /home/pi/boot.log
sudo /etc/init.d/sms3 restart >> /home/pi/boot.log
sleep 3
echo "------------- rc.local wvdial.conf copy"  >> /home/pi/boot.log
sudo cp /etc/wvdial.conf.org /etc/wvdial.conf
sleep 3
echo "------------- rc.local start wvdial"  >> /home/pi/boot.log
sudo wvdial swisscom >> /home/pi/boot.log &
sleep 20
/usr/local/bin/send_sms.sh 4179XXXXXXX "SMS Server wurde gestartet"
echo "------------- rc.local wird verlassen"  >> /home/pi/boot.log

exit 0

sms_handler.sh
Code:
#!/bin/bash

TOOLS_DIR=/usr/local/bin

# this file should contain variable $PHONE with your phone number
. ${TOOLS_DIR}/sms.conf

FWD_NUMBER=$PHONE
timestamp=`date "+%Y%m%d-%H%M%S"`
SMS_PROG=${TOOLS_DIR}/send_sms.sh

#run this script only when a message was received.
if [ "$1" != "RECEIVED" ]; then exit; fi;

#Extract data from the SMS file
SENDER=`formail -zx From: < $2`
TEXT=`formail -I "" <$2 | sed -e"1d"`
mon_tag=${TEXT:8:10}
TEXT=${TEXT:0:7}

TMPINFILE=/tmp/sms_in_${SENDER}_${timestamp}.txt
TMPOUTFILE=/tmp/sms_out_${SENDER}_${timestamp}.txt

CURRENT=$(date -u '+%F')
akttimestamp=`date "+%d.%m.%Y %H:%M:%S"`
echo  $akttimestamp > $TMPINFILE

if [ "$SENDER" = "$FWD_NUMBER" ] ; then
       case "$TEXT" in
       "cmd#011")
               if [ "$mon_tag" == "Er1" ] || [ "$mon_tag" == "Ar1" ]
               then
                 sudo /usr/local/bin/gpio_ausgang.py  ${mon_tag} >> $TMPINFILE 2>&1
               else
                 sudo /usr/local/bin/gpio_ausgang.py RelStatus >> $TMPINFILE 2>&1
               fi
               echo "Result: $?" >> $TMPINFILE
       ;;
       "cmd#021")
               if [ "$mon_tag" == "Er2" ] || [ "$mon_tag" == "Ar2" ]
               then
                 sudo /usr/local/bin/gpio_ausgang.py  ${mon_tag} >> $TMPINFILE 2>&1
               else
                 sudo /usr/local/bin/gpio_ausgang.py RelStatus >> $TMPINFILE 2>&1
               fi
               echo "Result: $?" >> $TMPINFILE
       ;;
       "cmd#031")
               if [ "$mon_tag" == "Ersm" ] || [ "$mon_tag" == "Arsm" ]
               then
                 sudo /usr/local/bin/gpio_ausgang.py  ${mon_tag} >> $TMPINFILE 2>&1
               else
                 sudo /usr/local/bin/gpio_ausgang.py RelStatus >> $TMPINFILE 2>&1
               fi
               sudo /usr/local/bin/gpio_ausgang.py EINRSPI >> $TMPINFILE 2>&1
               echo "Result: $?" >> $TMPINFILE
       ;;
       "cmd#050")
               sudo /usr/local/bin/gpio_ausgang.py RelStatus >> $TMPINFILE 2>&1
               echo "Result: $?" >> $TMPINFILE
       ;;
       "cmd#111")
               sudo /usr/local/bin/tag_monat_energie.py ${mon_tag} >> $TMPINFILE 2>&1
               echo "Result: $?" >> $TMPINFILE
       ;;
       "cmd#997")
               sudo /etc/init.d/sms3 restart >> $TMPINFILE 2>&1
               echo "Result: $?" >> $TMPINFILE
       ;;  
       "cmd#998")
               sudo reboot
       ;;
       "cmd#999")
               sudo shutdown -h now
       ;;
       *)
               echo "Available CMD list:" > $TMPINFILE
               echo "cmd#011 - Relais 1 Er1/Ar1 " >> $TMPINFILE
               echo "cmd#021 - Relais 2 Er2/Ar2 " >> $TMPINFILE
               echo "cmd#031 - Relais SMPi Ersm/Arsm " >> $TMPINFILE
               echo "cmd#050 - Relais Status " >> $TMPINFILE
               echo "cmd#111 - Leistung YYYYMM Tag/Mon " >> $TMPINFILE
               echo "cmd#997 - Restart SMS3 " >> $TMPINFILE
               echo "cmd#998 - Reboot RPi " >> $TMPINFILE
               echo "cmd#999 - Shutdown RPi " >> $TMPINFILE
       ;;
       esac
else
       echo "SMS from: $SENDER" > $TMPINFILE
       echo "Text: $TEXT" >> $TMPINFILE
fi

echo "To: $FWD_NUMBER" > $TMPOUTFILE
echo "" >> $TMPOUTFILE
cat $TMPINFILE >> $TMPOUTFILE
cp $TMPOUTFILE /var/spool/sms/outgoing/

gpio_ausgang.py
Code:
#!/usr/bin/env python
#coding: utf8
#
# Bruno Solothurnmann
# August 2018
#

import time
import RPi.GPIO as GPIO
import sys

def main():
   script = sys.argv[0]
   befehl = sys.argv[1]

   try:
       GPIO.setwarnings(False)
       # Zählweise der Pins festlegen
       GPIO.setmode(GPIO.BOARD)

       # Pin 31 (GPIO 06) als Ausgang festlegen - Ansteuerung LED SmartPI)
       GPIO.setup(31, GPIO.OUT)
       # Pin 32 (GPIO 12) als Ausgang festlegen - Ansteuerung Relais SmartPI)
       GPIO.setup(32, GPIO.OUT)
       # Pin 18 (GPIO 24) als Ausgang festlegen - Ansteuerung Relais 2 (externe Platine)
       GPIO.setup(18, GPIO.OUT)
       # Pin 22 (GPIO 25) als Ausgang festlegen - Ansteuerung Relais 1 (externe Platine)
       GPIO.setup(22, GPIO.OUT)

       if befehl  == "Er1":   #                 Relais 1 und LED SmartPi einschalten
           GPIO.output(22, GPIO.HIGH)
           GPIO.output(31, GPIO.HIGH)
           print "Relais 1 Ein"
       elif befehl == "Ar1":   #                 Relais 1 und LED SmartPi ausschalten
           GPIO.output(22, GPIO.LOW)
           GPIO.output(31, GPIO.LOW)
           print "Relais 1 Aus"
       elif befehl == "Er2":  #                 Relais 2 einschalten
           GPIO.output(18, GPIO.HIGH)
           print "Relais 2 Ein"
       elif befehl == "Ar2":  #                 Releais 2 ausschalten
           GPIO.output(18, GPIO.LOW)
           print "Relais 2 Aus"
       elif befehl == "Ersm":  #                 Relais SmartPi einschalten
           GPIO.output(32, GPIO.HIGH)
           print "Relais SmartPi Ein"
       elif befehl == "Arsm":  #                 Relais SmartPi ausschalten
           GPIO.output(32, GPIO.LOW)
           print "Relais SmartPi Aus"
       elif befehl == "RelStatus":  #             Relais Status
          if GPIO.input(22) == GPIO.HIGH:
            print "Relais 1 Ein"
          else:
            print "Relais 1 Aus"
          if GPIO.input(18) == GPIO.HIGH:
            print "Relais 2 Ein"
          else:
            print "Relais 2 Aus"
          if GPIO.input(32) == GPIO.HIGH:
            print "Relais SmartPi Ein"
          else:
            print "Relais SmartPi Aus"
       else:
           print "Befehl = " + befehl

   except:
           # this catches ALL other exceptions including errors.  
           # You won't get any error messages for debugging  
           # so only use it once your code is working  
           print "Other error or exception occurred!"  
           
if (__name__ == "__main__" ):
   main();

tag_monat_energie.py
Code:
#!/usr/bin/env python
#coding: utf8
#
# Bruno Solothurnmann
# August 2018
# Ausgabe der Tages- und Monatswerte in kWh von der SmartPi SQLite DB
#
# Aufruf: /usr/local/bin/tag_monat_energie.py (Bereich) (Tag_Monat)
# Bereich in YYYYMM  
# und Tag_Monat in Tag oder Monat
#

import time
import sys
import sqlite3

def main():
   script = sys.argv[0]
   bereich = sys.argv[1]
   tag_monat = sys.argv[2]

   try:
      sqlite_file = '/var/smartpi/db/smartpi_logdata_%s.db' % (bereich)
      conn = sqlite3.connect(sqlite_file)
      c = conn.cursor()
      if tag_monat  == "Tag":
        sql_text = "SELECT strftime('%d.%m.%Y',date),sum(energy_pos_balanced) FROM smartpi_logdata_{} WHERE date BETWEEN '2018-08-01 00:00:01' AND '2022-08-31 23:59:59' GROUP BY strftime('%d-%m-%Y',date)".format(bereich)
      elif tag_monat == "Mon":
        sql_text = "SELECT strftime('%m.%Y',date),sum(energy_pos_balanced) FROM smartpi_logdata_{} WHERE date BETWEEN '2018-08-01 00:00:01' AND '2022-08-31 23:59:59' GROUP BY strftime('%m-%Y',date)".format(bereich)
      else:
        print "Nur Tag oder Mon zugelassen"
        sys.exit()
      c.execute(sql_text)
      all_rows = c.fetchall()

      for member in all_rows:
         dat =  member[0]
         wert = float(member[1])/1000
         wert = "{:.3f}".format(wert)
         if tag_monat  == "Tag":
            print "Tag " + dat + " " + wert + " kWh"
         else:
            print "Monat " + dat + " " + wert + " kWh"

   except:
           print "Other error or exception occurred!"

   finally:
      conn.close()

if (__name__ == "__main__" ):
   main();
Über die SQL-Abfrage sind die kumulierten Daten aus der SQLite DB sehr rasch verfügbar. 
Eine Erweiterung habe ich noch vor, die erstellten Daten in eine weitere SQLite DB zu schreiben. Damit können dann auch entsprechende Graphen erstellt werden.

Ich bin kein Profi in der Programmierung - es funktioniert aber seit Tagen ohne Probleme.
Gerne stehe ich für Fragen und Erklärungen zur Verfügung.

Gruss, Bruno