Code Niederschlagsmeser an Rapberry Pi

python

#1

Liebes Sensemap/Sensebox-Team,

ich möchte fragen ob ihr mal einen Blick auf mein Python-Skript für
den Import der Daten des Niederschlagsmessers an meiner RasPi-Wetterstation werfen könnt. Dazu muss ich sagen, dass ich wenige Grundkenntnisse im Programmieren habe, bisher aber ganz gut durchgeschliddert bin.

Die Datei getInfo_zeroTestRain_SenseBox.py soll die Bewegung der Regenwippe zählen
und gibt alle fünf Sekunden den entsprechenden Wert aus. Anschließend
wird der Wert wieder auf Null gesetzt. Das funktioniert soweit (auf Komandozeile ohne die Angaben zur Sensemap getestet)

getInfo_zeroTestRain_SenseBox.py ist um die Angaben von Sensemap
ergänzt. Die Angaben habe ich aus anderen Skripten kopiert die bei mir
erfolgreich laufen und regelmäßig Daten senden. Die Sensor_ID habe ich
angepasst. Beim Ausführen bekomme ich den folgenden Fehler:

root@pi:~/Raspberry-Weather/production# python getInfo_zeroTestRain_SenseBox.py
()
Traceback (most recent call last):
File “getInfo_zeroTestRain_SenseBox.py”, line 55, in
status=readInfo() #get the readings
File “getInfo_zeroTestRain_SenseBox.py”, line 44, in readInfo
send_to_opensensemap(rainfall, sensebox_id =
“59592d0994f05200114428e8”, sensor_id = “5ca64511cbf9ae001ac2f6d1”)
File “getInfo_zeroTestRain_SenseBox.py”, line 18, in send_to_opensensemap
data = “{“value”:%.1f}” % float(value)
TypeError: float() argument must be a string or a number

Ich verstehe das so, dass eine Fließkommazahl erwartet, aber wohl
keine übergeben wird. Allerdings sollte rainfall eine Zahl enthalten?

Hier das Skript:

#!/usr/bin/python

import sys
from gpiozero import Button
import subprocess
import re
import os
import time
import datetime
import urllib2

interval =  5 # measurements recorded every 5 seconds
BUCKET_SIZE = 1,65289
rain_count = 0

def send_to_opensensemap(value, sensebox_id, sensor_id):
	opensensemap_url = "https://ingress.opensensemap.org/boxes/%s/%s" % (sensebox_id, sensor_id)
	data = "{\"value\":%.1f}" % float(value)
	try:
		req = urllib2.Request(opensensemap_url, data, {'Content-Type': 'application/json'})
		f = urllib2.urlopen(req)
		f.read()
		f.close()
	except urllib2.HTTPError as error:
		print error.code, error.reason

def bucket_tipped():
    global rain_count
    rain_count = rain_count + 1

def reset_rainfall():
    global rain_count
    rain_count = 0

def readInfo():
    while True:
        start_time = time.time()
        while time.time() - start_time <= interval:
            rainfall = rain_count * BUCKET_SIZE
        
        print(rainfall)
            
        if ( rainfall > 0 ): 
	    send_to_opensensemap(rainfall, sensebox_id = "59592d0994f05200114428e8", sensor_id = "5ca64511cbf9ae001ac2f6d1")
	else:
            print "Failed to get reading. Try again!"
	    sys.exit(1)

        if time.time() - start_time > interval:
            reset_rainfall()

rain_sensor = Button(6)
rain_sensor.when_pressed = bucket_tipped

status=readInfo() #get the readings

Ich würde mich über Kommentare freuen. :slight_smile:


#2

Hallo Marcel,

kannst du noch einmal deinen Beitrag editieren und deinen Code besser formatieren?

Verwende dafür einfach statt > am Anfang und Ende drei ```. Leider lassen sich deine Einrückungen nicht mehr nachvollziehen.

Ein paar erste Anmerkungen:

  • Eine Messung alle 5 Sekunden erscheint mir recht häufig. Mach doch lieber alle 30 oder 60 Sekunden.
  • Du verwendest urllib2 um die Daten an die openSenseMap zu senden. Schau dir mal requests (https://3.python-requests.org/) an. Diese Library vereinfacht das ganze erheblich
  • Du mischt anscheinend Python 2 und 3 Code
  • Zu deinem Fehler: Du solltest dafür sorgen, dass der Parameter value nicht None ist.

#3

Hallo Gerald,

danke für die Anmerkungen. Ich habe meinen Beitrag entsprechend formatiert.

Die fünf Sekunden sind noch ein Überbleibsel vom Test. Ich hatte daran gedacht später alle 5 Minuten die Messung zu übertragen, aber das ist wahrscheinlich zu lange.

Ich hatte 2017 mal Kontakt per eMail mit dem Team. Damals wurde mir diese Variante mitgeteilt. Wenn sie noch Gültigkeit hat, würde ich sie gerne weiterverwenden. Wie gesagt, ich kenne mich wenig aus. Das ist warscheinlich auch der Grund für die Vermischung von Python 2 und 3. Die Zählroutine stammt zum Beispiel von hier: https://projects.raspberrypi.org/en/projects/build-your-own-weather-station/9

Wenn ich value durch rainfall ersetze sollte es klappen, oder?


#4

Das war dann wohl ich :wink: Glaube damals hab ich mir das ganze auch nur irgendwie zusammengebastelt, würde das heute allerdings anders machen. Wenn du mir einmal noch deine Python Version mitteilst (/usr/bin/python --version), kann ich später nochmal schauen was alles verbessert werden kann.


#5

Hallo @gerald,

danke für das Angebot. Das wäre wirklich toll. :smile: Die Pythonversion ist Python 2.7.9.


#6

Das ganze ist erstmal ungetestet, habe keinen Raspberry zur Hand, sollte so aber eigentlich funktionieren. Wenn er meckert, dass er requests nicht finden kann, solltest du das per pip install requests nachinstallieren.

Bei der BUCKET_SIZE bin ich mal davon ausgegangen, dass es eine Kommazahl sein soll? Die muss man in Python mit einem Punkt schreiben.

#!/usr/bin/python

import sys
import time
import requests
from gpiozero import Button

sensebox_id = "59592d0994f05200114428e8"
sensor_id = "5ca64511cbf9ae001ac2f6d1"
interval = 5  # measurements recorded every 5 seconds
BUCKET_SIZE = 1.65289
rain_count = 0


def upload_value(value):
    url = "https://ingress.opensensemap.org/boxes/%s/%s" % (
        sensebox_id, sensor_id)
    r = requests.post(url, json={'value': value})
    if r.status_code != requests.codes.ok:
        print("Error %d: %s" % (r.status_code, r.text))


def bucket_tipped():
    global rain_count
    rain_count = rain_count + 1


def reset_rainfall():
    global rain_count
    rain_count = 0


def read_info():
    rainfall = 0
    while True:
        start_time = time.time()
        while time.time() - start_time <= interval:
            rainfall = rain_count * BUCKET_SIZE

        print(rainfall)

        if (rainfall > 0):
            upload_value(rainfall)
        else:
            print("Failed to get reading. Try again!")
            sys.exit(1)

        if time.time() - start_time > interval:
            reset_rainfall()


if __name__ == '__main__':
    rain_sensor = Button(6)
    rain_sensor.when_pressed = bucket_tipped

    read_info()  # get the readings


#7

Lieber Gerald,

super und so schnell. Ich habe eben deine Zeilen getestet und sie funktionieren. :slight_smile:
Spaßenshalber habe ich aber auch mal meinen Code ausprobiert, aber vorher das Komma durch einen Punkt ersetzt und siehe da, er funktioniert auch. Das freut mich natürlich auch. :slight_smile: Jetzt muss es nur noch regnen.:cloud_with_rain::cloud_with_lightning_and_rain::cloud_with_rain::sun_behind_rain_cloud: