Balkonbewässerung Symcon und RaspiZeroW (Python)

Hallo,
ich bin gerade dabei, eine Balkonbewässerung zu installieren und zu programmieren.
Eine angepasste Steuerung kommt dann später für ein Tomatenhaus (2x1m) zur Anwendung.

Zum Einsatz kommen:

  • IPS zur Wertvorgabe und zur Anzeige der aktuellen Werte

  • Raspberry Zero W zur Steuerung der Bewässerung

  • Gardena Balkonbewässerung, deren Pumpe über Trafo nach einer Minute abschaltet

  • Bodenfeuchtesensor VH400

  • Temperatursensor DS18B20 für Bodentemperatur im Balkonkasten

  • Temperatur- und Luftfeuchesensor AM2302 (nur im Tomatenhaus, über Variable AM2302 abschaltbar)

  • Durchflusssensor

  • Relais

Von extern (aus ISP) kommen noch hinzu:

  • Regenerkennung
  • Bewässerungsslots (Morgens, Abends)
  • Bodenfeuchte min und max

Das Programm für den Raspberry erfasst momentan nur die Sensorwerte und stellt diese Symcon zur Verfügung.

#!/usr/bin/python
# -*- coding: latin-1 -*-

##########################################################################################
# Raspberry Python-Programm                                                   			 #
#                                                                             			 #
# Beschreibung : diverse Sensoren auslesen und fuer Symcon bereitstellen	  			 #
# Create date  : 2018-02-19																 #
# Last change  : 2018-02-25																 #
# Version      : 0.02																	 #
# Datei        : _symcon.py 															 #
# Autor        : Matthias Herold														 #
# Copyright    : 																		 #
##########################################################################################
#																						 #
# Trigger  : IRQ_1			  			     	              				   			 #
# Interval :																		  	 #
# 																						 #
##########################################################################################
#
# 25.02.2018	GPIOs zugeordnet
# 28.02.2018	globale Variablen eingefuehrt
# 				bedingte Hardwareroutinen
#				bedingte print-Anzeigen
#
#-----------------------------------------------------------------------------------------
#
# PIN-Uebersicht Raspberry Balkon 192.168.xxx.yyy
# 
# 01  3.3VDC								# 02	5.0VDC
# 03  GPIO02								# 04	5.0VDC
# 05  GPIO03								# 06 	GND
# 07  GPIO04 1-W DS18B20 Bodentemperatur	# 08	GPIO15
# 09  GND									# 10	GPIO16
# 11  GPIO17								# 12	GPIO18
# 13  GPIO27								# 14	GND
# 15  GPIO22								# 16 	GPIO23
# 17  3.3VDC								# 18	GPIO24
# 19  GPIO10 MCP3008 VH400					# 20	GND
# 21  GPIO09 MCP3008 VH400					# 22	GPIO25
# 23  GPIO11 MCP3008 VH400					# 24	GPIO08 MCP3008 VH400
# 25  GND									# 26	GPIO07 
# 27  ID_SD									# 28	ID_SC
# 29  GPIO05 								# 30	GND
# 31  GPIO06								# 32	GPIO12
# 33  GPIO13								# 34	GND
# 35  GPIO19 Rel 220V 22 -frei- 			# 36	GPIO16
# 37  GPIO26 Rel 220V 21 Pumpe				# 38	GPIO20
# 39  GND									# 40	GPIO21 IRQ_1 DF_1 Sensor
#
#-----------------------------------------------------------------------------------------
#
# GPIO04 DS18B20
# GPIO08 MCP3008 VH400
# GPIO09 MCP3008 VH400
# GPIO10 MCP3008 VH400
# GPIO11 MCP3008 VH400
# GPIO19 Relais 22 -frei-
# GPIO21 DF_1 Sensor
# GPIO26 Relais 21 Pumpe
#
#-----------------------------------------------------------------------------------------

from MCP3008 import MCP3008
import RPi.GPIO as GPIO  
import requests
import json
from requests.auth import HTTPBasicAuth

import logging
logger = logging.getLogger(__name__)
logger.debug("%s loaded", __name__)

import time
import Adafruit_DHT

# I2C-Daten
#import Adafruit_GPIO.I2C as I2C
#from time import sleep, strftime
#from datetime import datetime
#deviceAddr = 0x20

#i2c = I2C.Device( deviceAddr, -1, False )
#i2c = I2C.Device(deviceAddr,1)

##########################################################################################
#
# define global variables
#
##########################################################################################

url       = 'http://aaa.bbb.ccc.ddd:3777/api/'
user      = 'xxx@yyy.de'
pwd       = 'zzz'

debug     = False # True / False
show      = True # Anzeige der Print-Zeilen

AM2302    = False
DS18B20   = True
VH400     = True

sleeptime = 10   # sek

##########################################################################################
#
# Datenaustasuch Funktion IPSrpc
#
##########################################################################################

# JSON-RPC zu IPS definieren
def IPSrpc(methodIps, paramIps):
	try:
		auth=HTTPBasicAuth(user, pwd)
		headers = {'content-type': 'application/json'}

		payload = {
			"method": methodIps,
			"params": paramIps,
			"jsonrpc": "2.0",
			"id": "0",
		}
		if debug:
			print json.dumps(payload)
		response = requests.post(url, auth=auth, data=json.dumps(payload), headers=headers)
		logger.debug(response)
		if debug:
			print(response)
	except:
		logger.exception("couldn't send IpsRpc")
		return False
	return True

##########################################################################################
#
# Durchflusssensoren vorbereiten
# GPIO21 DF_1 Durchfluss Balkonkasten
#
##########################################################################################

# GPIOs zuweisen
DF_1 = 21

# Variablen fuer Symcon-Uebergabe
ValueDF_1 = 49702

# Variable Menge pro Impuls
MengeImp = 1 # cm3 pro Impuls (Messing)

# Zaehlvariable
Tic = 0

# Variable Counter definieren
# pro Durchflussmesser
CounterDF_1 = 0

# Variable Menge definieren
# pro Durchflussmesser
MengeDF_1 = 0

# GPIO-Pins als Input deklarieren und Pullup-Widerstand aktivieren
GPIO.setmode(GPIO.BCM)
GPIO.setup(DF_1, GPIO.IN, pull_up_down = GPIO.PUD_UP)

# fuer jeden IRQ eine Funktion definieren
# Callback fuer DF_1
def ISR_DF_1(channel):
	# Zugriff auf globale Variablen
	global CounterDF_1
	global MengeDF_1
	CounterDF_1 = CounterDF_1 + 1
	MengeDF_1 = CounterDF_1 * MengeImp
	if show:
		print (
		"Impulse_1: %4f  " % CounterDF_1 +
		"Menge_1: %6.1f l" % MengeDF_1)
	IPSrpc("SetValue", [ValueDF_1, CounterDF_1])

# Interrupts akivieren,
# auf steigende Flanke reagieren 
# ISR deklarieren
# entprellen auf 1ms entprellen
GPIO.add_event_detect(DF_1, GPIO.RISING, callback = ISR_DF_1) #, bouncetime = 1)


try:
    while True:
	start_time = time.time()

	##################################################################################
	#
	# Werte von Symcon holen
	#
	##################################################################################

	BF_min = IPSrpc("GetValue", [46246])
	BF_max = IPSrpc("GetValue", [34065])
	if show:
		print (
		"Bodenfeuchte min: %2d %% " % BF_min +
		"Bodenfeuchte max: %2d %%" % BF_max)

	##################################################################################
	#
	# VH400 auslesen
	# GPIO08.09.10.11
	#
	##################################################################################

	if VH400:
		adc = MCP3008()
		value = adc.read( channel = 0 ) # auszulesender Channel
		v400u = ( value / 1023.0 * 3.3 )
		v400f = ( value / 2.77 / 1023.0 * 3.3 * 100 )
		vwc=(11.6552* v400u **4+7.10835* v400u **2-0.569557)/( v400u **2 + 1)
		if show:
			print(
			"V400 Spannung: %4.1fV  " % v400u +
			"Bodenfeuchte: %3d%%  " % v400f +
			"vol. Bodenfeuchte: %3d%%" % vwc)
		IPSrpc("SetValue", [46226, v400u])
		IPSrpc("SetValue", [38013, v400f])
		IPSrpc("SetValue", [54482, vwc])

	##################################################################################
	#
	# DS18B20 auslesen
	# GPIO04
	#
	##################################################################################

	if DS18B20:
			# 1-wire Slave Datei lesen Sensor_28-031655b44fff
		file = open('/sys/bus/w1/devices/28-031655b44fff/w1_slave')
		filecontent = file.read()
		file.close()
			# Temperaturwerte auslesen und konvertieren
		stringvalue = filecontent.split("
")[1].split(" ")[9]
		tempds = float(stringvalue[2:]) / 1000
		if show:
			print("DS18B20 Bodentemperatur : %4.1f°C" % tempds)
	IPSrpc("SetValue", [30772, tempds])

##########################################################################################

	end_time = time.time()
        delay = float(end_time - start_time)
#        time.sleep(sleeptime - delay)
	time.sleep(sleeptime)

except KeyboardInterrupt:
    GPIO.cleanup()

GPIO.cleanup()           # clean up GPIO on normal exit

Probleme bereitet mir das Abfragen von Werten aus Symcon.
In die Variable BF_min soll per IPSrpc der Wert der IPS-Variable aus 46246 übernommen werden.
BF_min = IPSrpc(„GetValue“, [46246])
Hier passiert aber nichts.

  • Was ist falsch?
  • oder muss ISP die Daten aktiv übermitteln? (Was ich nicht machen möchte)
	##################################################################################
	#
	# Werte von Symcon holen
	#
	##################################################################################

	BF_min = IPSrpc("GetValue", [46246])
	BF_max = IPSrpc("GetValue", [34065])
	if show:
		print (
		"Bodenfeuchte min: %2d %% " % BF_min +
		"Bodenfeuchte max: %2d %%" % BF_max)

Die restliche Programmsteuerung ist noch in Arbeit. Aber zuvor muss die Abfrage von Variablen aus IPS laufen.
Ich hatte auch über MQTT nachgedacht, aber ich bekomme es nicht zum Laufen. Auf dem Symcom-Server läuft auch ein MQTT-Broker zum Spielen. Aber was muss in ISP passieren, damit Werte ausgegeben und eingelesen werden? Und was muss auf dem RasPi wie progammiert werden?

PS: Ich habe den Python-Code in den PHP-Code eingebettet. Gibt es auch eine Einstellung im Forum-Editor für Python-Code?

mfg
Matthias