Viele sagen Weihnachten sei ja an und für sich keine “besondere” Zeit und damit haben sie Recht. Weihnachten ist nichts Besonderes, man MACHT es zu etwas Besonderen. Frohe Weihnachten!
Bewässerung – Teil 1: Ein Prototyp
Als ersten Schritt werde ich einen Prototypen bauen. Normalerweise baut man einen Prototyp ja auf einem Steckbrett . Ich möchte den Prototypen aber ein paar Wochen ausprobieren damit ich sehe wie viel Energie er braucht und wie sich die Messungen verhalten. Deswegen mache ich meinen Prototypen auf einer Lochraster Platine. Außerdem werde ich auf meinem Arduino eine Datenaufzeichnung in einer Datenbank einrichten und eine kleine Webvisualisierung dazu erstellen.
Meine Einkaufsliste dazu:
- ESP8266 Esp-12 Remote Serial Port WIFI Module with IO adapter plate Expansion
- XCSOURCE FT232RL 3.3V 5.5V FTDI USB zu TTL Serielles Adaptermodul Arduino Mini Anschluss TE203
- MTS1EU Greenhouse Sensor Kit Soil Hygrometer Module and DHT11 Temperature/Humidity Module for Arduino. Gewächshaus Pflazen
Zusätzlich noch:
- eine Lochraster Platine
- 3 Stk. 10k Widerstände (oder höherohmig, es müssen nur drei gleiche sein)
- 1 Stk Elektrolytkondesator (> 500 uF)
- 1 Stk. Transistor (z.B. BC547C)
- 1 Stk 3,3K Widerstand
- eine Steckerleiste (2 pins)
- einen Jumper
- und einen Lötkolben.
Ich weiß, über Lötkolben wird viel fachgesimpelt aber mir persönlich reicht eine 22€ Lötstation. Außerdem ist dabei eine recht gute Entlötpumpe dabei und so ein Gerät empfehle ich auch dringend jedem Anfänger. Überschüssiges Geld ist am besten in vernünftigem Lötzinn angelegt. Für die Stromversorgung verwende ich eine USB Powerbank die ich als Werbegeschenk erhalten habe. Man bekommt die zur Zeit eh überall geschenkt, ansonsten erhält man sie auch für unter 10 € im Netz (z.B. hier).
Ich vermeide bei Prototypen stets die Bauteile direkt einzulöten. Deswegen verwende ich gerne Steckerleisten. Diese haben zwar den Nachteil dass man etwas vorsichtig mit dem Aufbau umgehen muß aber dafür kann ich einfach Bauteile für Versuche einfach raus nehmen ohne gleich zum Lötkolben greifen zu müssen.
Das der ESP8266 nur 3,3V verträgt verwende ich den USB zu TTL Konverter auch gleich als Spannungswandler. Dazu muß nur der Jumper auf dem Board auf 3,3 V gesteckt werden. Zum Energiesparen werde ich den ESP in den Deep-Sleep-Modus versetzen. Damit die beiden Sensoren derweilen keinen Strom verbrauchen schalte ich sie über einen Ausgang und einen Transistor weg. Der ESP benötigt bei Verbindungsaufbau zum WLAN relativ viel Strom, deshalb muß parallel zur Versorgung ein Elektrolytkondensator geschaltet werden. Es ist keine Raketenwissenschaft diesen auszulegen, er sollte irgendwas zwischen 400uF und 2200uF bei 6-10V haben. Für das Programmieren muß der CH_PD Pin auf GND gezogen werden. Manche empfehlen dafür einen Taster, ich bevorzuge eine kleine Steckerleiste und einen Jumper.
In der ESP8266 Dokumentation ist beschrieben, dass zum Aufwachen aus dem Deep-Sleep der PIN16 mit CH_PD verbunden sein muß. Leider hat das bei meinem ESP nicht funktioniert. Deshalb verwende ich den RESET für den Wakeup. Ich kann dadurch zwar ein paar Optionen des Deep-Sleep nicht verwenden aber für den Prototypen ist mir das egal.
![Der Prototyp in EAGLE](https://i1.wp.com/www.c-rust.net/stromspielplatz/wp-content/uploads/2015/12/Prototype-300x214.png?resize=607%2C433)
Es bedarf etwas an Tüftelei die Bauelemente auf der Platine sinnvoll zu platzieren, ich habe versucht Platz zu sparen, vor allem weil ich einen relativ kleines Platinenstück übrig hatte.
![Meine Prototyen Platine](https://i2.wp.com/www.c-rust.net/stromspielplatz/wp-content/uploads/2015/12/prototyp-300x225.jpg?resize=300%2C225)
Zum Programmieren des ESP verwende ich meine Arduino IDE. Dazu muß man in der Arduino Software, in den Einstellungen http://arduino.esp8266.com/stable/package_esp8266com_index.json
eintragen. Dann unter Tools > Board „…“ > Board Manager… auswählen, esp8266 anklicken und Install drücken. Danach kann der ESP wie jeder andere Arduino programmiert werden. Zum Programmieren muß der Jumper beim Initialisieren gesetzt sein. Bei mir zickt das Hochladen des Programmes ab und zu. In dem Fall nehme ich einfach kurz die Spannung weg (aber lange genug dass ich der ELKO entlädt) und versuche es nochmal. ACHTUNG, wenn beim Aufwachen aus dem Deep Sleep der Jumper noch immer gesetzt ist dann startet der ESP nicht richtig.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
#include // WLAN Name und Passwort (PSK) const char* ssid = "SSID"; const char* password = "PSK"; WiFiClient client; // Server Adresse des Raspberry char server[] = "10.0.0.3"; int port = 80; //Sollte am Apache ein anderer Port verwendet werden hier anpassen // Update Intervall const unsigned long postingInterval = 1800L * 1000000L; //DHT initiallisieren #include #define DHTPIN 4 #define DHTTYPE DHT11 // DHT 11 DHT dht(DHTPIN, DHTTYPE,16); // needed to avoid link error on ram check extern "C" { #include "user_interface.h" } void setup() { // Pin 12 schaltet in meinem Fall die Sensoren ein/aus pinMode(12, OUTPUT); digitalWrite(12, HIGH); // Serielle Schnittstelle für Debug Zwecke Serial.begin(115200); Serial.println("WLAN Temperatur und Feuchtigkeitslogger - Stromspielplatz"); // WIFI starten WiFi.mode(WIFI_STA); WiFiStart(); // Angstwarten delay(3000); //DHT init dht.begin(); // ADC (Bodenfeuchtigkeit) init pinMode(A0, INPUT); } void loop() { // Sollte beim POST ein Return kommen gebe ich den am Serial aus while (client.available()) { char c = client.read(); Serial.write(c); } // Sensorwerte einlesen float hum = dht.readHumidity(); float temp = dht.readTemperature(); float soil = analogRead(A0); //Debug Serial.println("Humidity:"+String(hum,2)+"\tTemperature:"+String(temp,2)+"\tSoil:"+String(soil,2)); //Werte senden httpRequest(hum,temp,soil); //Sensoren abschalten und Deep Sleep aktivieren delay(500); digitalWrite(12, LOW); ESP.deepSleep(postingInterval, WAKE_NO_RFCAL); delay(1000); } //Daten an Webserver übertragen void httpRequest(float h, float t, float s) { client.stop(); delay(100); //URL mit Vaiablen bauen String url = "/newrecord.php?"; url += "temp="; url += String(t,2); url += "&humidity="; url += String(h,2); url += "&soil="; url += String(s,2); // aufrufen if (client.connect(server, port)) { Serial.println("connecting..."); client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + server + "\r\n" + "Connection: close\r\n\r\n"); Serial.println("data submitted."); delay(10); } else { Serial.println("connection failed"); } } // WIFI Verbindung aufbauen void WiFiStart() { Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println(WiFi.localIP()); } |
Smarte Socken von Netflix
Netflix hat eine Do-It-Yourself Anleitung für smarte Socken online gestellt. Ich bin mir sicher auf die Idee komme ich nochmal zurück…
Automatische Bewässerungsanlange
Also ich liebe ja eigenes Gemüse. Wenn man seine Tomaten frisch vom Strauch pflückt weiß man erst wie gut Tomaten schmecken können. Leider bin ich immer nachlässig was das Gießen angeht. Und ich Hochsommer brauchen so Tomaten wirklich viel Wasser und daher ist es mir passiert, dass die Ernte im letzten Jahr nicht ganz so toll ausgefallen ist wie es hätte sein können.
Daher habe ich beschlossen eine automatische Bewässerungsanlage zu bauen. Ich werde mittels Arduino Boards Feuchtigskeitsmesssonden basteln die die aktuellen Daten mittels WLAN an meine Zentrale, einen Raspberry PI schicken. Die Messsonden sollen autark sein und von ihren Strom aus jeweils einer kleinen Solarzelle beziehen. Der Raspberry zeichnet die Daten auf und agiert als Regler für die Bewässerung. Für das Gießen selbst werde ich eine Schaltung für die Pumpen benötigen da sich eine Versorgung über Schwerkraft vermutlich nicht realisieren läßt.
Zu guter letzt soll das ganze nicht zu viel kosten… I
Adieu meine Magic Karten – Teil 2: Das PHP Script
Nachdem ich das letzte Mal meine Daten aufbereitet habe gehts jetzt an das Script. Ich werde das Script in PHP machen, weil ich die Sprache mag und einigermaßen fit darin bin. Außerdem kann ich sie auf Windows und Linux gleichermaßen benutzen. In dem Fall verwende ich die Netbeans IDE, obwohl natürlich ein einfacher Editor auch reichen würde. Natürlich eignet sich jede andere Programmiersprache auch dafür (so wie Phyton, TCL, was auch immer).
So wie das letzte Mal muß ich mir erst mal den HTML Code ansehen. Ich schaue mir dazu wieder den Quelltext an und suche nach den <TABLE> Tags und werde prompt fündig. Ohne jetzt wieder genauer darauf einzugehen schaue ich mir an woran ich die einzelnen Spalten eindeutig identifizieren kann. Wenn ich so etwas mache dann habe ich immer im Hintergrund eine Textdatei in meinem Notepad++ offen und kopiere mir diese ganzen Infos gleich da rein. Da habe ich alles beieinander und kann mir dann alles Notwendige wieder rauskopieren.
Dann schreibe ich ein Script dass meine CSV Zeile für Zeile durchgeht, die Parameter rausholt. Dann rufe ich die Webseite mit den Parametern auf, parse den Quelltext nach meinen gesuchten Informationen und schreibe diese wieder in eine CSV Datei.
Ich arbeite unten im Code übrigens mit REGEX. Viele mögen das nicht aber ich finde das unheimlich mächtig für solche Aufgaben. Zugegeben es ist ein bißchen kompliziert am Anfang aber es gibt ein paar gute Hilfen. Ich verwende zum Beispiel zum Entwickeln und Testen https://regex101.com/
Damit der unten stehende Code läuft müssen in der php.ini folgende extension aktiviert sein:
- extension=php_openssl.dll
- extension=php_curl.dll
außerdem muß “allow_url_fopen = On” gesetzt sein.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<?php ini_set('auto_detect_line_endings',TRUE); // Für das Einlesen der CSV Datei $input = fopen('C:\temp\magic karten.csv','r'); // Mein CSV das ich im letzten Teil erstellt habe $output = fopen('C:\temp\Kartenpreise.txt', 'wt'); // Meine Zieldatei while ( ($data = fgetcsv($input,1000,',') ) != FALSE ) { $ch = curl_init(); $useragent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)'; $url= utf8_encode("https://www.???.de/?mainPage=advancedSearch&cardName=".str_replace(' ','+',$data[0])."&idExpansion=".$data[3]."&manaCost=&convertedManaCostCompare=%3D&convertedManaCostValue=&powerCompare=%3D&powerValue=&toughnessCompare=%3D&toughnessValue="); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch,CURLOPT_USERAGENT, $useragent); curl_setopt($ch,CURLOPT_RETURNTRANSFER, true); $filestring = curl_exec($ch); curl_close ($ch); usleep(500000); // Der Höflichkeit halber stressen wir den Zielserver nicht allzusehr. $searchpattern = '/<td class="outerBottom col_Odd col_3 cell_[0-9]*_3"><[^>]*>(?<name_eng>.*)<\/a><\/td>\s*<td class="outerBottom col_Even col_4 cell_[0-9]*_4"><[^>]*>(?<name_deu>.*)<\/a><\/td>\s*<td class="outerBottom col_Odd col_5 cell_[0-9]*_5">(?<anz>\S*)<\/td>\s*<td class="outerBottom outerRight col_Even col_6 cell_[0-9]*_6">(?<preis>\S*)/'; if (!preg_match_all($searchpattern, $filestring, $treffer)) { echo $data[0]."\t".$data[2]."\t nicht gefunden\t !!!!!!!!!!\r\n"; continue; } echo $treffer['name_deu'][0]."\t".$treffer['name_eng'][0]."\t".$data[2]."\t".$treffer['anz'][0]."\t".$treffer['preis'][0]."\r\n"; fputs($output, $treffer['name_deu'][0]."\t".$treffer['name_eng'][0]."\t".$data[2]."\t".$treffer['anz'][0]."\t".$treffer['preis'][0]."\r\n"); } ini_set('auto_detect_line_endings',FALSE); fclose($input); fclose($output); ?> |
Als Ergebnis erhaltet ihr eine schöne CSV Datei die ihr wieder in einer Tabellenkalkulation öffnen könnt.
Adieu meine Magic Karten – Teil 1: Ein bißchen Reverse Engineering, Notepad Action und Tabellenkalkulationsmagie
Ich möchte also den Wert meiner Magickarten bestimmen indem ich automatisch mittels Scripting, Daten von einer Webseite abfrage. Dazu habe ich mich erstmal 2 Stunden hingesetzt und die Namen meiner Sammelkarten in eine Tabellenkalkulation abgetippt. Als Knauserer verwende ich privat dazu Openoffice Calc, das reicht für den alltäglichen Bedarf obwohl es leider nicht ganz an den Funktionsumfang von Excel herankommt.
In meiner Tabelle habe ich also den Namen meiner Karte und die Edition eingetragen weil ich gelesen habe dass letztere für den Wert der Karte eine Rolle spielen kann.
![OpenOffice Calc Tabellenblatt](https://i0.wp.com/www.c-rust.net/stromspielplatz/wp-content/uploads/2015/12/Tabelle-300x223.jpg?resize=300%2C223)
Jetzt mache ich mich auf die Suche nach einer geeigneten Seite die mir die Preisdaten liefern soll. Der Einfachheit halber suche ich mir eine Seite die die Daten in der URL übergibt da das für mich einfach zu lesen und sehr transparent ist. Dazu suche ich einfach auf der Seite nach eine x-beliebigen Karte.
In meinem Falls suche ich nach der Karte mit dem malerischen Namen “Holzbrecher” aus der Serie “Nemesis” und erhalte folgendes Ergebnis.
![Testabfrage](https://i1.wp.com/www.c-rust.net/stromspielplatz/wp-content/uploads/2015/12/Testabfrage-300x90.jpg?resize=300%2C90)
Wenn ich mir die übergebenen Parameter nach dem “/?” ansehe dann fällt mir gleich als erstes ins Auge dass der Kartenname im Klartext übergeben wird “cardName=Holzbrecher”. Da die Variablennamen sehr sprechend sind kann sehe ich außerdem dass idExpansion wohl die Serie angiebt, leider aber nicht im Klarnamen sondern diese in eine ID kodiert und die anderen Variablen Suchoptionen sind die man zusätzlich angeben könnte, die für mich aber ohne Belang sind. Außerdem fällt mir auf dass das Suchergebnis in einer schönen Tabelle geliefert wird was mit später das Parsen erleichtert.
Als nächstes muss ich mir also ansehen wie ich an Zuordnung Serienname zu idExpansion komme. Da mir die Seriennamen ja in der HTML Seite angezeigt werden sind diese irgendwo im HTML Quellcode enthalten. Um mir das genauer anzusehen lasse ich mir den Seitenquellcode von der Suchseite anzeigen. Das geht in allen Browsern ähnlich indem man irgendwo auf einen leeren Bereich rechtsklickt und “Seitenquelltext anzeigen” auswählt. Leider erhalte ich den Code fast unformattiert zurück (was nicht unüblich ist) und kann erstmal gar nichts erkennen. Man könnte jetzt mit einem vernünftigen HTML Editor eine Formattierung herstellen lassen, ich gehe aber einen noch einfacheren Weg über mein geliebtes Notepad++.
Ich kopiere also den gesamten Quellcode und füge ihn in ein neues, leeres Dokument ein.Ich suche dann nach dem Namen meiner Serie “Nemesis” und finde dass die Namen in Option Tags eingebettet sind die mir jeweils den Namen und die ID lieferen. (Jedem HTML Programmierer ist das natürlich schon vorher klar 😉 )
Jetzt muß man sich ein bißchen mit HTML auskennen. In HTML sind Formattierung und Elemente immer in Tags eingeschlossen. In meinem Beispiel schauen die Elemente für die auswähbaren Serien so aus:
<option value=”32″>Nemesis</option>
Es ist also immer <option value=”idExpansion”>Klaxtextname
Ich formatieren den Code jetzt etwas um indem ich mittels suchen Ersetzen nach jedem “</option>” einen Zeilenumbruch (\r\n) einfüge
![Umformatieren](https://i1.wp.com/www.c-rust.net/stromspielplatz/wp-content/uploads/2015/12/Suchenersetzen-300x162.jpg?resize=300%2C162)
Wenn ich jetzt durch mein Dokument scrolle sehe ich sehr schnell wo meine gewünschten Daten anfangen und wo sie aufhören. Ich lösche jetzt einfach alles vor dem ersten “<option” und=”” nach=”” dem=”” letzten=”” “<=”” option=””>” händisch raus und habe jetzt nur mehr meine Nutzdaten in meiner Datei. Dabei entferne ich auch gleich noch die erste Zeile “Alle” da diese offenbar ohne Nutzen für mich sein wird.
![Anfang meiner Nutzdaten](https://i2.wp.com/www.c-rust.net/stromspielplatz/wp-content/uploads/2015/12/Anfang-300x178.jpg?resize=300%2C178)
Jetzt muß ich sie nur noch in ein schönes Format bringen um es in meine Tabellenkalkulation importieren zu können. Dazu gehe ich noch ein paar mal mit Suchen&Ersetzen drüber: Ich Ersetze “<option value=”” durch einen Leerstring, “”>” durch einen Tabulator “\t” und “” wieder durch einen Leerstring und erhalte eine schöne Tabstop getrennte Textdatei.
![Tabstopp getrennter Text](https://i2.wp.com/www.c-rust.net/stromspielplatz/wp-content/uploads/2015/12/Tabstopp-getrennter-Text-260x300.jpg?resize=260%2C300)
Jetzt mache ich mit ein bißchen Excel-Magic (Jaja ich weiß, es sollte “Openoffice.Calc Magic” oder noch besser “Tabellenkalkulationsmagic”) Ich importiere diese Liste in meine Tabellenkalkulation in ein separates Blatt und füge in meiner Liste mittels “VERWEIS” die IDs zu meinen Klartextnamen ein.
![Importierte Zuordnungsliste](https://i0.wp.com/www.c-rust.net/stromspielplatz/wp-content/uploads/2015/12/Openoffice-Liste-190x300.jpg?resize=190%2C300)
![Liste mit Verweis](https://i2.wp.com/www.c-rust.net/stromspielplatz/wp-content/uploads/2015/12/Liste-mit-Verweis-281x300.jpg?resize=281%2C300)
Jetzt speichere ich das erstmal im Originalformat und dann gleich das erste Blatt nochmal als CSV und habe meine Daten für den nächsten Schritt aufbereitet. Das nächste Mal gehts weiter mit dem Script.
Adieu meine Magic Karten…
Es ist so weit. Nachdem sie jahrelang einsam in meinem Kasten verstaubt sind habe ich heute beschlossen meine Magic – The Gathering Sammelkarten zu verkaufen. Meine Frau meinte ja ich solle sie einfach wegwerfen aber nachdem ich meine alte Stereoanlage erfolgreich auf willhaben verkauft habe, hat mich der Kapitalismus in seinen Bann gezogen und ich werde auch mein altes Hobby zu Geld machen. Im Ernst, es ist doch sinnbefreit eine Anschaffung die viel Geld gekostet hat einfach in die Tonne zu werfen. Selbst wenn ich nur ein paar EURO bekomme macht es doch Sinn. Die Frage ist nur: Was ist ein angemessener Preis?
Dazu habe ich mir überlegt ich werde den Preis über einen kleinen Robot (ein Script) bestimmen lassen. Eine kleiner Livehack und nebenbei eine gute kleine Programmierfingerübung.