Temperatursensor und D2C Nachrichten Senden
Table of Contents
Einleitung
In diesem Tutorial geht es darum, einen Raspberry Pi 3 mit dem Clouddienst Microsoft Azure zu verbinden. Im ersten Teil des Tutorials haben wir einen Client auf dem Raspberry Pi programmiert, diesen mit einem Azure IoT Hub verbunden und Cloud-To-Device Nachrichten empfangen. Jetzt erweitern wir das ganze um einen Temperatursensor, dessen Daten wir dann an Azure senden.

Voraussetzungen:
Dieses Tutorial geht davon aus, das Erfahrung mit Programmierung vorhanden sind, setzt aber keine Erfahrungen mit Raspbian, GPIO Mikroprozessoren (Pi, Arduino etc.) oder Python voraus. Da das Tutorial auf dem Code des ersten Teils aufbaut empfiehlt es sich diesen zuerst durch zuarbeiten, oder den fertigen Code herunterzuladen.
Ziel:
Ziel ist es device-to-cloud Nachrichten an Microsoft Azure IoT Hub zu versenden, die Daten vom Raspberry Pi in die Cloud senden. Um dem ganzen Funktion zu geben schließen wir außerdem einen Temperatursensor an.
Beispiel Nutzungen:
– Außen Temperatursensor
– Bewegungsmelder für eine Hundeklappe
– Verkehrszähler an einer stark befahrenen Straße
Vorbereitung:
Raspberry Pi vorbereiten (Um den Temperatursensor nutzen zu können)
Der in diesem Tutorial verwendete Temperatursensor DS18B20 verwendet das 1-Wire Bus Interface, bevor wir dieses an unserem Raspberry Pi nutzen können, müssen wir dieses dafür vorbereiten. Dafür nutzen wir folgenden Konsolenbefehl um die Konfiguration des Raspberries zu verändern
sudo nano /boot/config.txt
Dies
öffnet die Datei im nano Editor und erlaubt uns diese zu verändern.
Wir suchen nun innerhalb dieser Datei nach der Zeile, die
dtoverlay=w1-gpio
enthält, existiert sie nicht fügen
wir sie ganz am Ende der Datei hinzu und speichern das ganze. Damit
die Änderungen in Kraft treten müssen wir den Pi neu starten.
Wir bauen jetzt noch einen Schaltkreis mit dem Temperatursensor auf, dafür nutzen wir neben diesem einen GND Pol, einen 3.3V Pol des Pis, sowie den GPIO Pin 4. zwischen dem Kontakt mit dem 3.3V pol und dem Mittleren Füßchen des Sensors wird ein 4.7 Kohm Widerstand eingesetzt. An dem Ende, das nicht mit den 3.3V verbunden ist legen wir das Kable an, das zum GPIO Pin 4 führt.

Nachdem wir diesen Schaltkreis aufgebaut haben können wir mittels einiger Befehle testen, ob unsere Einstellungen korrekt sind.
sudo modprobe w1-gpio
sudo modprobe w1-therm
cd /sys/bus/w1/devices
ls
Dies wird alle Geräte, die über den 1-Wire Bus angeschlossen sind anzeigen. Der Temperatursensor wird eine ID haben, die mit einer 28 anfängt, der viele Nummern folgen. Nun können wir testen ob der Sensor arbeitet, indem wir das Folgende eintippen, dabei wird XXXX durch die Zahlen, die der 28 folgen ersetzt.
cd 28-xxxx
cat w1_slave
Nun sollte man das folgende erhalten. Geschieht das, arbeitet der Sensor
a3 01 4b 46 7f ff 0e 10
d8 : crc=d8 YES
a3 01 4b 46 7f ff 0e 10 d8 t=32768
Den Temperatursensor in den Bisherigen Code einbinden:
Wir öffnen nun wieder unseren Code vom ersten Tutorial und ergänzen diesen um einige imports, da diese für die Verwendung des Temperatursensors von Nöten sind.
# Import Libraries
import os
import glob
import time
Nun müssen wir noch die folgenden Funktionen in unseren Code einfügen, damit wir die Temperatur auslesen können
# Initialize the GPIO Pins
os.system('modprobe w1-gpio') # Turns on the GPIO module
os.system('modprobe w1-therm') # Turns on the Temperature module
# Finds the correct device file that holds the temperature data
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
# A function that reads the sensors data
def read_temp_raw():
f = open(device_file, 'r') # Opens the temperature device file
lines = f.readlines() # Returns the text
f.close()
return lines
# Convert the value of the sensor into a temperature
def read_temp():
lines = read_temp_raw() # Read the temperature 'device file'
# While the first line does not contain 'YES', wait for 0.2s
# and then read the device file again.
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_temp_raw()
# Look for the position of the '=' in the second line of the
# device file.
equals_pos = lines[1].find('t=')
# If the '=' is found, convert the rest of the line after the
# '=' into degrees Celsius, then degrees Fahrenheit
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
#temp_f = temp_c * 9.0 / 5.0 + 32.0
return temp_c #, temp_f
Sobald diese Funktionen Teil des Codes sind ist es uns möglich die Temperatur auszulesen. Man kann dies nun einfach testen, indem man in der While-Schleife, die die bisher nur ein Delay enthält folgendes einfügt:
s = str(read_temp())
print(s)
Jetzt wird nach jeder Wartezeit die aktuelle Temperatur ausgegeben. Dabei sollte man die Wartezeit auf 15 Sekunden erhöhen.
Nachrichten vom Pi senden
Einfache Nachrichten:
Um nun die Temperatur auch in die Cloud zu bekommen müssen wir unserem Client ein paar neue Methoden zur Verfügung stellen, dazu gehört eine sendText(str) und eine sendKeyValuePair(key, value) methode. Zuerst wollen wir die einfachere sendText Methode erstellen. Diese wandelt den übergebenen String in eine IoTHubMessage und schickt diese dann mittels CLIENT.send_event_async an den Server. Da wir in dieser send methode eine Callback Methode angeben müssen erstellen wir auch diese
#Gibt aus, ob die nachricht erfolgreich gesendet wurde
def send_confirm_callback(message, result, context):
print("Nachricht ID %s Status %s" %(message.message_id, result))
# Funktion um einen String an den verbundenen IoT Hub zu schicken
def sendText(str):
global CLIENT, send_confirm_callback
#aus der Bibliothek passende funktioählen, um ein objekt vom richtigen
typen zu
msg = IoTHubMessage(str)
# es gibt weitere optionale parameter, diese könnten mit dem folgenden
code gesetzt werden
# msg.message_id = "id"
# msg.correlation_id = "cid"
print("schicke die Nachricht [%s]..." % (str))
CLIENT.send_event_async(msg, send_confirm_callback, 0)
Key Value Pair als Nachricht verschicken
Außer einfachen Nachrichten können wir diesen auch noch ein Key, Value Paar anhängen um das Handlen der Nachrichten im Hub später einfacher zu haben. Auch in dieser wird zuerst eine IoTHubMessage erzeugt, dieser werden dann Attribute hinzugefügt bevor sie verschickt wird.
# Methode um Key, Valu paare an den IoT Hub zu schicken
def sendKeyValuePair(key, value):
global CLIENT, send_confirm_callback, MSGID
msg_txt = ("%s, %s" %(key, value))
msg = IoTHubMessage(msg_txt)
msg.message_id = str(MSGID)
propmap = msg.properties() propmap.add(key,value)
CLIENT.send_event_async(msg, send_confirm_callback,0)
Um nun die Temperatur als Key Value Paar an den Server zu schicken erzeugen wir uns noch eine weitere Funktion, die den Aufruf der Sendefunktion und das umwandeln der Temperatur in einen String übernimmt. Außerdem kümmert sie sich darum, dass aufsteigende Nachrichten IDs vergeben werden.
def sendTemp():
global MSGID
s = str(read_temp())
sendKeyValuePair("Temperatur",s)
MSGID += 1
Jetzt muss nur noch die Schleife nach angepasst werden und wir senden regelmäßig die Aktuelle Temperatur an die Cloud. Mittels dem was wir im letzten Tutorial gelernt haben können wir das senden sogar ferngesteuert machen. Dafür ändern wir nur die gotMail Methode wie folgt und schreiben dies hier in die While-Schleife
while True:
if SENDING:
sendTemp()
time.sleep(15)
else:
time.sleep(1)
In der Funktion gotMail müssen wir folgendes ergänzen:
global SENDING
if msg == "temperature" or msg == "temp":
print(read_temp())
s = str(read_temp())
sendText(s)
elif msg == "start" or msg == "start sending":
SENDING = True
elif msg == "stop" or msg == "stop sending":
SENDING = False
Weitere Tutorials
Schnellstart Tutorial
Tutorial 1: C2D Nachrichten empfangen
Tutorial 3: Daten per Mail versenden