|  | 
         |
         |  | 
         | Inhalt: | 
         |  | 
         | Motivation bzw. Hintergrund | 
         | Einstieg in die Scriptsprache | 
         | Sensordaten einsammeln und in eine Datenbank schreiben | 
         | Lego Roboter mit PyBricks | 
         |  | 
         |
         |  | 
         | Für mich hat Python inzwischen den Stellenwert angenommen, den zuvor Perl als Scriptsprache inne hatte. Ich verwende die Scriptsprache | 
         | nzwischen für nahezu jegliche Automatismen, CGI und fü alles, was sich sonst im Rahmen vorhandener "Alltagsprobleme" ergibt, | 
         | für die ich eine programmatische Lösung brauche. | 
         |  | 
         | Ein dickes Plus ist auch hier die Möglichkeit den Code plattformübergreifend (gut es gibt da Codefragmente, die angepasst werden müssen) | 
         | einsetzen zu können. | 
         |  | 
         |
         |  | 
         | Wie schon beschrieben, seid Ihr als Python Einsteiger auf meinen Seiten sicher falsch, wenngleich der beschriebene Code sicher nicht | 
         | sonderlich kompliziert ist. Da es gerade als Anfänger manchmal nicht einfach ist die richtige Einführung in eine Sprache zu finden möchte | 
         | ich Euch an dieser Stelle nicht ganz im "Regen" stehen lassen. Da ich eher ein "old style" Lernender bin, setze ich bei Themen, die ich | 
         | mir aneignen möchte zunächst mal auf Bücher. Im Falle von Python finde ich das Buch "Python 3 - Das umfassende Handbuch" von | 
         | Johannes Ernesti und Peter Kaiser, inzwischen in der 7. Auflage im Rheinwerk Verlag erschienen, super. Gut finde ich bei dem Verlag auch, | 
         | daß man die dort erhältlichen Bücher im "Bundle" d. h. als Druck- und Ebookausgabe kaufen kann und sich so die digitale Ausgabe | 
         | dann eben z. B. auch auf sein Tablet laden kann, um das Buch immer dabei zu haben. Wenn Ihr Euch hingegen neue Themen lieber über | 
         | Videos aneignen möchtet kann ich Euch "The Morpheus Tutorials" empfehlen. In seinem YouTube Channel erklärt der Autor aus | 
         | meiner Sicht sehr gut alle möglichen Themen rund ums große Themenfeld Informatik, das Pythontutorial finde ich im Kanal ebenfalls sehr | 
         | gut gelungen! Mir gefällt vor allem, daß die Kapitel sehr kurz gehalten wurden, so daß man die Geschwindigkeit des "Voranschreitens" | 
         | selbst bestimmen kann. | 
         |  | 
         | Nach diesen einführenden Informationen möchte ich auch hier kurz zeigen, wie das übliche "Hallo Welt" in Python funktioniert. Unter | 
         | Windows nutzt Ihr als Einsteiger am besten die sogenannte Python Shell.Den Interpreter bekommt Ihr auf den Downloadseiten des Projekts | 
         | Python.org. Wenn Ihr diese Shell startet und folgende Zeile eingebt, wird "Hallo Welt!" ausgegeben: | 
         |  | 
         |  | 
         |  | 
         |  | 
         | Da ich gerade solche Skriptsprachen wie Python selten unter Windows, sondern eher auf unseren Linuxservern zur Erledigung | 
         | verschiedener Aufgaben einsetze, möchte ich Euch auch kurz zeigen, wie dieses "Hallo Welt" auf einem Linux System (nachfolgender | 
         | Screenshot stammt von einem CentOS 8 System) aussieht. Für diejenigen unter Euch, die vielleicht keine oder kaum Erfahrung mit | 
         | Linux/UNIX haben, werden auch die Berechtigungen (unter Linux muss die Datei auch ausführbar sein und Sie muss auch in der ersten | 
         | Zeile des Codes den Interpreter angegeben haben) und der Code mit Kommentaren angegeben. | 
         |  | 
         |  | 
         |  | 
         | Soviel zu einem kleinen Einstieg und als Erläuterung, wie ich Python auf unseren Systemen einsetze. | 
         |  | 
         |
         |  | 
         | Problemstellung: | 
         |  | 
         | Für unsere Familie habe ich den Raspberry und insbeondere auch den Raspberry Zero als kleines Stück Hardware dafür entdeckt, daß | 
         | man an diesen Einplatinenrechner relativ einfach Sensoren anschließen kann, die man dann mittels wenig Code einfach auslesen und etwa | 
         | auf einer Webseite wieder ausgeben kann. Verfügbar sind aber auch das sogenannte Enviro Phat, ein Zusatzmodul, welches man auf den | 
         | Rasberry aufsteckt, und über das mehrere Sensoren kombiniert werden können. Zur Darstellung der Daten kommt ein "Miniwebserver" | 
         | (das sogenannte Framework Flask) zum Einsatz. Bei mir sieht das dann erst einmal wie folgt aus: | 
         |  | 
         |  | 
         |  | 
         | Ziel war es diese Informationen einzusammeln und in unsere zentrale Datenbank (bei uns ist das ein MySQL Datenbanksystem zu schreiben. | 
|  | 
         | Umsetzung: | 
         |  | 
         | Das Skript, welches dieses leistet sieht wie folgt aus: | 
         |  | 
         | #!/usr/bin/python | 
         |  | 
         | # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 
         | # +                                                                                            + | 
         | # +        Python Script for catching weather data from our balcony sensor and store it        + | 
         | # +              at our internal MySQL Database (db: wetter_db, table: log_balkon)             + | 
         | # +                                                                                            + | 
         | # + Author      :    Stefan Feeser                          + | 
         | # + Date        :    11.07.2019                                                                + | 
         | # + Version     :    0.1                                                                       + | 
         | # + Copyright   :    Family Feeser, 2019                                                       + | 
         | # + Changes     :    11.07.2019    Creation of the script                                      + | 
         | # +                                                                                            + | 
         | # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 
         |  | 
         | import sys | 
         | import time | 
         | import urllib2 | 
         | import re | 
         | import MySQLdb | 
         |  | 
         | # | 
         | # ++++++++++++++++++++++++++++++++   D E K L A R A T I O N E N   +++++++++++++++++++++++++++++++ | 
         | # | 
         |  | 
         | flt_temp = 0.0 | 
         | flt_pressure = 0.0 | 
         | int_countrows = 0 | 
         | str_datum = "" | 
         | str_indat = "" | 
         | str_inzeit = "" | 
         | str_url = "http://192.168.0.168:2600/" | 
         | str_lines = "" | 
         | str_error = "" | 
         | str_element = "" | 
         | str_help = "" | 
         | str_logfile = "/data/logs/get-weatherdata-balcony.log" | 
         | str_server = '' | 
         | str_port = 'Port' | 
         | str_username = '' | 
         | str_password = '' | 
         | str_db = 'wetter_db' | 
         | str_sql = "select count(log_balkon_id) from log_balkon;" | 
         | str_line = "" | 
         | obj_response = "" | 
         | obj_loghandle = "" | 
         |  | 
         | # | 
         | # ++++++++++++++++++++++++++++++++   H a u p t p r o g r a m m   +++++++++++++++++++++++++++++++ | 
         | # | 
         |  | 
         | # Start Logging Informations | 
         |  | 
         | obj_loghandle = open(str_logfile,"a") | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Start fetching weatherdata from our balcony sensor.\n") | 
         |  | 
         | # Fetching weatherinformations from our sensor | 
         |  | 
         | try: | 
         | obj_response = urllib2.urlopen(str_url, timeout = 5) | 
         | for str_lines in obj_response: | 
         | if re.search("\ | Temperatur",str_lines): | 
         | str_lines = re.sub("\ | Temperatur:\\ | ","",str_lines) | 
         | str_lines = re.sub("\","",str_lines) | 
         | str_lines = re.sub("^\s*","",str_lines) | 
         | str_lines = re.sub("\s*$","",str_lines) | 
         | str_lines = re.sub("\n","",str_lines) | 
         | flt_temp = float(str_lines) | 
         | elif re.search("\ | Luftdruck",str_lines): | 
         | str_lines = re.sub("\ | Luftdruck:\\ | ","",str_lines) | 
         | str_lines = re.sub("\","",str_lines) | 
         | str_lines = re.sub("^\s*","",str_lines) | 
         | str_lines = re.sub("\s*$","",str_lines) | 
         | str_lines = re.sub("\n","",str_lines) | 
         | flt_pressure = float(str_lines) | 
         | else: | 
         | continue | 
         | except (urllib2.HTTPError, urllib2.URLError) as str_error: | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : An error occured while trying to connect to URL (Errorcode: " + str(str_error) + "\n") | 
         | obj_loghandle.close() | 
         | sys.exit(1) | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Received URL Information (Sensordata from balcony)\n") | 
         | #print("Temperatur: " + str(flt_temp) + ", Luftdruck: " + str(flt_pressure) + "\n") | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Script identified Temperature (" + str(flt_temp) + ") and Pressure (" + str(flt_pressure) + ").\n") | 
         |  | 
         | # Opening database connection to our Weatherdatabase and check about the amount of data | 
         |  | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Initializing Database connection and checking entries.\n") | 
         | obj_db = MySQLdb.connect(host=str_server, | 
         | user=str_username, | 
         | passwd=str_password, | 
         | db=str_db) | 
         | obj_cursor = obj_db.cursor() | 
         | obj_cursor.execute(str_sql) | 
         | for str_row in obj_cursor.fetchall(): | 
         | int_countrows = str_row[0] | 
         | int_lauf = int(int_countrows) + 1 | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Script identified " + str(int_countrows) + " Rows at the database, will continue with ID " | 
		 | + str(int_lauf) + ".\n") | 
         | obj_db.close() | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Databaseconnection got closed.\n") | 
         |  | 
         | # Preparing insert statement based on the fetched values | 
         |  | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Preparing insert statement.\n") | 
         | str_indat = time.strftime("%Y-%m-%d") | 
         | str_inzeit = time.strftime("%H:%M:%S") | 
         | str_sql = "insert into log_balkon values(" + str(int_lauf) + ",'" + str_indat + "','" + str_inzeit + | 
		 | "'," + str(round(flt_temp,6)) + "," + str(round(flt_pressure,6)) + ",NULL);" | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Insert statement created: " + str_sql + "\n") | 
         |  | 
         | # Create a database object | 
         |  | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Creating Database connection.\n") | 
         | obj_db = MySQLdb.connect(host=str_server, | 
         | user=str_username, | 
         | passwd=str_password, | 
         | db=str_db) | 
         | # Create a cursor object to execute queries | 
         |  | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Creating cursor.\n") | 
         | obj_cursor = obj_db.cursor() | 
         |  | 
         | # Send the insert statement | 
         |  | 
         | try: | 
         | obj_cursor.execute(str_sql) | 
         | obj_db.commit() | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Insert successful.\n") | 
         | except: | 
         | obj_db.rollback() | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Rollback happened.\n") | 
         |  | 
         | # Close connection | 
         |  | 
         | obj_db.close() | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Databaseconnection got closed.\n") | 
         |  | 
         | # Finalizing Script (Closing Logfile and take care on a save exit) | 
         |  | 
         | str_datum = time.strftime("%d.%m.%Y - %H:%M:%S") | 
         | obj_loghandle.write(str_datum + " : Script will end. Closing Logfile.\n") | 
         | obj_loghandle.close() | 
         | sys.exit(0) | 
         |  | 
         | Es sei angemerkt, dass sich insbesondere das Datenbankmodul und das Modul für Webabfragen geändert haben, da der Code in der | 
         | vorliegenden Form schon etwas in die Jahre gekommen ist. Ich werde das gelegentlich anpassen. | 
         |  | 
         | Was anhand des Codes aber hoffentlich ersichtlich ist, das zunächst ein Logfile initialisiert und über dieses alle Aufgaben | 
         | protokolliert werden. Im Anschluss werden die Webinformationen (Sensordaten) über eine Art Curl für Python geholt und aufbereitet. | 
         | Danach werden diese Daten dann in die Datenbank geschrieben, was gefordert wurde. | 
         |  | 
         | Um das Holen der Sensordaten und das Schreiben in die Datenbank zu festgelegten Zeiten zu erreichen, habe ich einen Crontabeintrag erstellt: | 
|  | 
         |  | 
         |  | 
         | Auch an dieser Stelle sei angemerkt, dass wir inzwischen andere Server nutzen und die Crontabeinträge inzwischen auch deutlich | 
         | umfangreicher geworden sind. Nachfolgend ein Screenshot unserer Weboberfläche. | 
         |  | 
         |  | 
         |  | 
         |
         |  | 
         | Wie schon auf unseren C/C++ Seiten erwähnt, haben wir PyBricks für uns entdeckt. Die Webseite (funktioniert nur  mit den Browsern | 
         | Chrome oder Edge) fungiert dabei als sogenannte IDE (Integrated Develop Environment), Dokumentationsseite, sowie Interface zu | 
         | verschiedenen Lego Microcontroller Systemen in einem. Erste Erfahrungen haben wir mit dem Lego Basic Powered Up Hub und dem | 
		 | Lego Boost Hub gemacht. An den Powered Up Hub, der nachfolgend auch abgebildet ist, haben wir eine externe LED angeschlossen | 
		 | und den nach dem Bild angegebenen Code in den Editor des Browsers kopiert. Drückt man hier den Playbutton, wird das Programm | 
		 | via Bluetooth an den Hub übertragen und in unserem Fall leuchten die LEDs fünfmal kurz auf und gehen danach auch wieder aus. | 
         |  | 
         |  | 
         |  | 
         |  | 
         |  | 
         | ↑ zurück zum Beginn der Seite | 
         |  |