Pi Hole ist ein AdBlocker der arbeitet wie eine FireWall. Werbung gelangt gar nicht erst in Dein Netzwerk. Zusätzlich hast Du eine gut ausgebaute Oberfläche, mit der Du überblick über die Geschehnisse behältst.

Ich habe einen interessanten Block entdeckt, der das Vorgehen bei der Installation auf Deutsch erklärt. Da ich es selber auch nicht besser machen kann, werde ich diese Beschreibung hier verlinken.

kuketz-blog.de – Pi Hole (Installieren und Einrichten)

Ich wünsche Euch viel Erfolg mit dem Projekt, und berichtet gerne in unserem Forum über Eure Erfolge.

VG

Thomas

Hallo liebe Maker,

leider geht unser Projekt zur Zeit nur schleppend voran. Aber es ist Licht am Ende des Tunnels. Anfang der kommenden Woche werde ich weitere Infos über unser neues Heim bekommen.

Bis dahin gibt es aber noch Programm. Leider haben wir zur Zeit keine Möglichkeit uns zu treffen. Das soll sich aber wieder ändern. 

In diesem Kontext möchte ich um Eure Unterstützung bitte. Freundlicherweise stellt uns die Firma AladoIT eine Ecke ihres Standes auf dem Hiller Markt (Gewerbezelt) zur Verfügung, in der wir basteln, bauen und präsentieren können.

Vorgesehen sind die Themen:

  • 3D Druck
  • CNC Steuerungen
  • Kinect – 3D Scann 
  • Robotik (Lego MindStorm)
  • Raspberry Pi mit Cam
  • ESP32 und MicroPythen
  • Schulprojekte
  • usw.

 

Hiller Markt Webseite

 

Viele liebe Grüße

Thomas

Sehr schöne Anleitung.
Gut erklärt und schnell umzusetzen.

Zitat der Seite (linux-tips-and-tricks.de):

Die Dokumentation von raspiBackup ist durch Erweiterungswünsche von Benutzern mittlerweile sehr umfangreich geworden. Auf dieser Seite wird deshalb kurz und knapp Schritt für Schritt erklärt wie man in 5 Minuten raspiBackup installiert und konfiguriert und dann ein Backup der Raspberry erstellen kann. Der Restore ist dann hier für die unterschiedlichen Benutzer mit ihren jeweiligen primären Platformen (Linux, Mac oder Windows) beschrieben. Nachdem man dann sowohl den Backup als auch den Restore getestet hat und geprüft hat welche Services vor dem Backup gestoppt werden müssen lässt man dann raspiBackup automatisch im gewünschten Intervall per crontab laufen. Danach kann man in einer stillen Stunde sämtliche Möglichkeiten von raspiBackup hier nachlesen und die Konfiguration den speziellen Bedürfnissen anpassen. In jedem Falle sollte jeder sich die FAQs durchlesen.

ESP-WROOM-32

Hallo zusammen,

hier eine gute Anleitung auf deutsch, wie Ihr das MicroPhython auf dem ESP installiert und die ersten Gehversuche macht.

Ein ESP32 mit MicroPython (Video – YouTube)

Hier noch die wichtigsten Links:

https://micropython.org/download#esp32

Python 3.x.x für OS?

Hier die schnelle Übersicht zu ganz einfachen Befehlen …

Welcome to MicroPython on the ESP32!

For generic online docs please visit http://docs.micropython.org/


https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki


For access to the hardware use the ‘machine’ module:

import machine                // besser: from machine import Pin (spart Speicher)

pin12 = machine.Pin(12, machine.Pin.OUT)

pin12.value(1)

pin13 = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_UP)

print(pin13.value())

i2c = machine.I2C(scl=machine.Pin(21), sda=machine.Pin(22))

i2c.scan()

i2c.writeto(addr, b'1234')

i2c.readfrom(addr, 4)

 

Basic WiFi configuration:

import network

sta_if = network.WLAN(network.STA_IF); sta_if.active(True)

sta_if.scan()                             # Scan for available access points

sta_if.connect("<AP_name>", "<password>") # Connect to an AP

sta_if.isconnected()                      # Check for successful connection

 

Control commands:

  CTRL-A        -- on a blank line, enter raw REPL mode

  CTRL-B        -- on a blank line, enter normal REPL mode

  CTRL-C        -- interrupt a running program

  CTRL-D        -- on a blank line, do a soft reset of the board

  CTRL-E        -- on a blank line, enter paste mode

For further help on a specific object, type help(obj)

For a list of available modules, type help(‘modules’)

—————————————————————————

MicroPython

Shell:

screen /dev/tty.ESPPORT 115200           // Shell starten und mit dem ESP verbinden default:115200 dann 2-3 mal "CTRL + C" drücken ...

>>>Befehl

Beispiel:

>>>print("Hallo")

——————————————————————————————

noch etwas netter ist die RShell

Aufrufen mit:

rshell --buffer-ssize=30 -p /dev/tty.ESPPORT         //(bei mir z.B.: /dev/tty.SLAB_USBtoUART)

Befehle in der RSHELL:

boards                       // zeigt Dir alle angeschlossenen Boards und die Namen

ls "boardname"          // z.B.: "ls pyboard" - listet die Dateien auf dem Board. Wenn Ihr noch //nichts gemacht habt dann findet Ihr da nur die boot.py 

                                // Die boot.py wird bei jedem Start des Boards ausgeführt. Auch nach dem aufwachen aus dem DeepSleep Modus.

                                // Euer Programm steht dann in der Regel in der main.py

edit /pyboard/boot.py            // ruft die Datei boot.py im StandartEditor auf. Exit mit :q! für nicht speichern

Etwas netter ist es wenn Ihr einen anderen Editor benutzt. Verlasst die rshell und startet sie neu mit dem Befehl:

rshell --buffer-size=30 -p /dev/tty.ESPPORT -a -e nano

// damit macht Ihr für die aktuelle Sitzung den Editor "nano" zum StandartEditor

——————————————————————————————–

Aufrufen einer KomandoOberfläche (REPL):

REPL                              // hier könnt Ihr wieder direkt Befehle ausführen

ESP-WROOM-32

http://esp-idf.readthedocs.io/en/latest/api-reference/index.html

https://www.espressif.com/en/products/hardware/esp32/resources

https://www.bluetooth.com/specifications/gatt/services

https://www.instructables.com/id/ESP32ESP8266-Weather-ForecasterPredictor/

https://www.instructables.com/id/IOT-Made-Simple-Playing-With-the-ESP32-on-Arduino-/

 

Small WeatherStation for ESP32 with BMP180 and SSD1306

 

/* Last udpate: Added enumerated weather types, improved efficiency

* Last update: 25-March-2018, with improved forecast rules *  

* ESP32 and BMP180 or BME280 and OLED SH1106 or SSD1306 display Weather Forecaster  

* Using air pressure changes to predict weather based on an advanced set of forecasting rules.  

* The ‘MIT License (MIT) Copyright (c) 2016 by David Bird’. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated  

* documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish,   

* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the  

* following conditions:     

* The above copyright (‘as annotated’) notice and this permission notice shall be included in all copies or substantial portions of the Software and where the    

* software use is visible to an end-user.   

* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    

* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER     

* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 

* See more at http://dsbird.org.uk*/

#include “SSD1306.h” // Version 4 or higher

#include “OLEDDisplayUi.h” // Version 4 or higher#include <WiFi.h>

#include “time.h”

#include <Wire.h>//

#include <Adafruit_BME280.h>

#include <Adafruit_BMP085.h> // If using BMP180 or BMP085 and update line: 173/174 accordingly e.g. BME and BME or BMP and BMP 

#define icon_width  40#

define icon_height 40 // Define each of the *icons for displayconst uint8_t rain_icon[] PROGMEM = {  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0x81, 0xFF, 0xFF, 0xFF, 0x3F, 0x04, 0xFE, 0xFF, 0xFF, 0xDF, 0xF0, 0xFC,   0xFF, 0xFF, 0xE7, 0xFF, 0xFB, 0xFF, 0xFF, 0xFB, 0xFF, 0xF3, 0xFF, 0xFF,   0xFD, 0xFF, 0xE7, 0xFF, 0xFF, 0xFD, 0xFF, 0x0F, 0xFE, 0x0F, 0xF8, 0xFF,   0x8F, 0xFC, 0xE7, 0xFB, 0xFF, 0xC7, 0xF9, 0xF7, 0xE3, 0xFF, 0xC3, 0xF3,   0xF3, 0xDF, 0xFF, 0xE8, 0xE7, 0xF9, 0xFF, 0xFF, 0xFE, 0xEF, 0xFD, 0xFF,   0xFF, 0xFF, 0xE7, 0xF9, 0xFF, 0xFF, 0xFF, 0xF7, 0xFB, 0xFF, 0xFF, 0xFF,   0xF3, 0xFB, 0xFF, 0xFF, 0xFF, 0xF9, 0xF7, 0xFF, 0xFF, 0xFF, 0xFC, 0xCF,   0xFF, 0xFF, 0x3F, 0xFE, 0x3F, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x7D, 0xBF,   0xEF, 0xFF, 0xFF, 0xBE, 0xDF, 0xF7, 0xFF, 0x7F, 0xDF, 0xEF, 0xFB, 0xFF,   0xBF, 0xEF, 0xF7, 0xFD, 0xFF, 0xDF, 0xF7, 0xFB, 0xFE, 0xFF, 0xEF, 0xFB,   0x7D, 0xFF, 0xFF, 0xF7, 0xFD, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };const uint8_t sunny_icon[] PROGMEM = {  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF,   0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF,   0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFD, 0xDF, 0xFF, 0xE3, 0xFF, 0xF8, 0x8F,   0xFF, 0xE3, 0x7F, 0xF0, 0x07, 0xFF, 0xE3, 0x3F, 0xF8, 0x0F, 0xFE, 0xFF,   0x1F, 0xFC, 0x1F, 0x7C, 0x00, 0x0E, 0xFE, 0x3F, 0x18, 0x00, 0x1C, 0xFF,   0x7F, 0xCC, 0xFF, 0xB1, 0xFF, 0xFF, 0xE6, 0xFF, 0xE7, 0xFF, 0xFF, 0xF3,   0xFF, 0xCF, 0xFF, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0xFF, 0xF9, 0xFF, 0x9F,   0xFF, 0xFF, 0xF9, 0xFF, 0x9F, 0xFF, 0xFF, 0xF9, 0xFF, 0x9F, 0xFF, 0x01,   0xF9, 0xFF, 0x9F, 0x80, 0x01, 0xF9, 0xFF, 0x9F, 0x80, 0x01, 0xF9, 0xFF,   0x9F, 0x80, 0xFF, 0xF9, 0xFF, 0x9F, 0xFF, 0xFF, 0xF1, 0xFF, 0x8F, 0xFF,   0xFF, 0xF1, 0xFF, 0x8F, 0xFF, 0xFF, 0xE3, 0xFF, 0xE7, 0xFF, 0xFF, 0xC7,   0xFF, 0xF3, 0xFF, 0xFF, 0x8D, 0xFF, 0xD8, 0xFF, 0xFF, 0x38, 0x00, 0x8C,   0xFF, 0x7F, 0x70, 0x00, 0x07, 0xFF, 0x3F, 0xF8, 0xFF, 0x0F, 0xFE, 0x1F,   0xFC, 0xE3, 0x1F, 0xFC, 0x0F, 0xFE, 0xE3, 0x3F, 0xF8, 0x07, 0xFF, 0xE3,   0x7F, 0xF0, 0x8F, 0xFF, 0xE3, 0xFF, 0xF8, 0xDF, 0xFF, 0xE3, 0xFF, 0xFD,   0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF,   0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };const uint8_t mostlysunny_icon[] PROGMEM = {  0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFD, 0x7E,   0xFF, 0xFF, 0xFF, 0xFB, 0xBF, 0xEF, 0xFF, 0xFF, 0x17, 0xE0, 0xF7, 0xFF,   0xFF, 0xCF, 0x9F, 0xF9, 0xFF, 0xFF, 0xE6, 0x3F, 0xFD, 0xFF, 0xFF, 0xF5,   0x7F, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFE, 0xFF, 0xFF, 0xF9, 0xFF, 0x00,   0xFF, 0xFF, 0xFD, 0x7F, 0x08, 0xFC, 0xFF, 0xFD, 0xBF, 0xE1, 0xF9, 0xFF,   0xFD, 0xCF, 0xFF, 0xF7, 0xFF, 0xFD, 0xF7, 0xFF, 0xE7, 0xFF, 0xF9, 0xFB,   0xFF, 0xCF, 0xFF, 0xF3, 0xFB, 0xFF, 0x1F, 0xFC, 0x17, 0xF0, 0xFF, 0x1F,   0xF9, 0xC7, 0xF7, 0xFF, 0x8F, 0xF3, 0xEF, 0xC7, 0xFF, 0x87, 0xE7, 0xE7,   0xBF, 0xFF, 0xD1, 0xCF, 0xF3, 0xFF, 0xFF, 0xFD, 0xDF, 0xFB, 0xFF, 0xFF,   0xFF, 0xCF, 0xF3, 0xFF, 0xFF, 0xFF, 0xEF, 0xF7, 0xFF, 0xFF, 0xFF, 0xE7,   0xF7, 0xFF, 0xFF, 0xFF, 0xF3, 0xEF, 0xFF, 0xFF, 0xFF, 0xF9, 0x9F, 0xFF,   0xFF, 0x7F, 0xFC, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };  const uint8_t cloudy_icon[] PROGMEM = {  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x7F, 0x78, 0xFC, 0xFF,   0xFF, 0xBF, 0xFF, 0xF9, 0xFF, 0xFF, 0xCF, 0xFF, 0xF7, 0xFF, 0xFF, 0xF7,   0xFF, 0xE7, 0xFF, 0xFF, 0xFB, 0xFF, 0xCF, 0xFF, 0xFF, 0xFB, 0xFF, 0x1F,   0xFC, 0x3F, 0xF0, 0xFF, 0xE7, 0xFB, 0xCF, 0xF7, 0xFF, 0xF3, 0xF7, 0xEF,   0xCF, 0xFF, 0xF9, 0xEF, 0xF7, 0xBF, 0xFF, 0xFD, 0xCF, 0xF3, 0xFF, 0xFF,   0xFD, 0xDF, 0xFB, 0xFF, 0xFF, 0xFF, 0xDF, 0xFB, 0xFF, 0xFF, 0xFF, 0xEF,   0xF7, 0xFF, 0xFF, 0xFF, 0xE7, 0xF7, 0xFF, 0xFF, 0xFF, 0xF3, 0xEF, 0xFF,   0xFF, 0xFF, 0xF9, 0x9F, 0xFF, 0xFF, 0x7F, 0xFC, 0x7F, 0x00, 0x00, 0x00,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };const uint8_t tstorms_icon[] PROGMEM = {  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0x81, 0xFF, 0xFF, 0xFF, 0x3F, 0x04, 0xFE, 0xFF, 0xFF, 0xDF, 0xF0, 0xFC,   0xFF, 0xFF, 0xE7, 0xFF, 0xFB, 0xFF, 0xFF, 0xFB, 0xFF, 0xF3, 0xFF, 0xFF,   0xFD, 0xFF, 0xE7, 0xFF, 0xFF, 0xFD, 0xFF, 0x0F, 0xFE, 0x0F, 0xF8, 0xFF,   0x8F, 0xFC, 0xE7, 0xFB, 0xFF, 0xC7, 0xF9, 0xF7, 0xE3, 0xFF, 0xC3, 0xF3,   0xF3, 0xDF, 0xFF, 0xE8, 0xE7, 0xF9, 0xFF, 0xFF, 0xFE, 0xEF, 0xFD, 0xFF,   0xFF, 0xFF, 0xE7, 0xF9, 0xFF, 0xFF, 0xFF, 0xF7, 0xFB, 0xFF, 0xFF, 0xFF,   0xF3, 0xFB, 0xFF, 0xFF, 0xFF, 0xF9, 0xF7, 0xFF, 0xFF, 0xFF, 0xFC, 0xCF,   0xFF, 0xFF, 0x3F, 0xFE, 0x3F, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x7F, 0x7F,   0xFF, 0xFF, 0xFF, 0xBF, 0xBF, 0xFF, 0xFF, 0xFF, 0xDF, 0x8F, 0xFF, 0xFF,   0xFF, 0xEF, 0xF7, 0xFF, 0xFF, 0xFF, 0xF7, 0xFB, 0xFF, 0xFF, 0xFF, 0x4F,   0xF7, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xFF, 0xFF, 0xDF, 0xF1, 0xFF,   0xFF, 0xFF, 0xDF, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,   0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF,   0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };  String      time_str, weather_text, weather_extra_text;int         last_reading_hour, reading_hour, hr_cnt;const char* ssid     = “UT-VNet”;const char* password = “43246641485350293845”;enum image_names { // enumerated table used to point to images                  rain_img, sunny_img, mostlysunny_img, cloudy_img, tstorms_img,                 } image;// Define and enumerated type and assign values to expected weather types.// These values help to determine the average weather preceeding a ‘no-change’ forecast e.g. rain, rain then mostlysun = -1 (-1 + -1 + 1) resulting on balance = more rainenum weather_type {unknown     =  4,                   sunny       =  2,                   mostlysunny =  1,                   cloudy      =  0,                   rain        = -1,                   tstorms     = -2                   };enum weather_description {GoodClearWeather, BecomingClearer,                          NoChange, ClearSpells, ClearingWithin12hrs, ClearingAndColder,                          GettingWarmer, WarmerIn2daysRainLikely,                          ExpectRain, WarmerRainWithin36hrs, RainIn18hrs, RainHighWindsClearAndCool,                          GalesHeavyRainSnowInWinter                          };weather_type current_wx; // Enable the current wx to be recordedconst uint8_t* image_table[] PROGMEM = {rain_icon, sunny_icon, mostlysunny_icon, cloudy_icon, tstorms_icon}; // An array of image icons// An array structure to record pressure, temperaturre, humidity and weather statetypedef struct {  float pressure;            // air pressure at the designated hour  float temperature;         // temperature at the designated hour  float humidity;            // humidity at the designated hour  weather_type wx_state_1hr; // weather state at 1-hour  weather_type wx_state_3hr; // weather state at 3-hour point} wx_record_type;wx_record_type reading[24]; // An array covering 24-hours to enable P, T, % and Wx state to be recorded for every hourint wx_average_1hr, wx_average_3hr; // Indicators of average weatherbool look_3hr = true;bool look_1hr = false; SSD1306 display(0x3c, 5,4); // OLED display object definition (address, SDA, SCL)OLEDDisplayUi ui     ( &display );//Adafruit_BME280 bme;Adafruit_BMP085 bme; // If using BMP180 or BMP085WiFiClient client; // wifi client object#define pressure_offset 3.3 // Used to adjust sensor reading to correct pressure for your location/////////////////////////////////////////////////////////////////////////// What’s displayed along the top linevoid msOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) {  display->setTextAlignment(TEXT_ALIGN_LEFT);  display->drawString(0,0, time_str.substring(0,8));  //HH:MM:SS Sat 05-07-17  display->setTextAlignment(TEXT_ALIGN_RIGHT);  display->drawString(128,0, time_str.substring(9));  display->setTextAlignment(TEXT_ALIGN_LEFT);}// This frame draws a weather icon based on 3-hours of data for the predictionvoid drawFrame1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {  float trend  = reading[23].pressure – reading[20].pressure;                          // Trend over the last 3-hours  ForecastToImgTxt(get_forecast_text(reading[23].pressure, trend, look_3hr));          // From forecast and trend determine what image to display  display->drawXbm(x+0,y+15, icon_width, icon_height, image_table[image]);             // Display corresponding image  display->drawStringMaxWidth(x+45,y+12,90,String(reading[23].pressure,1)+” hPA”);     // Show current air pressure   display->drawStringMaxWidth(x+45,y+25,90,String(trend,1)+” “+get_trend_text(trend)); // and pressure trend}// This frame shows a weather description based on 3-hours of data for the predictionvoid drawFrame2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {  float  trend = reading[23].pressure – reading[20].pressure;                             // Get current trend over last 3-hours  weather_description wx_text = get_forecast_text(reading[23].pressure, trend, look_3hr); // Convert to forecast text based on 3-hours  ForecastToImgTxt(wx_text);                                                              // Display corresponding text  display->setFont(ArialMT_Plain_16);  display->drawStringMaxWidth(x+0,y+10,127,weather_text);  display->setFont(ArialMT_Plain_10);}// This frame draws a graph of pressure (delta) change for the last 24-hours, see Annex* for more detailsvoid drawFrame3(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {  int gwidth   = 75; // Graph width in pixels  int gscale   = 30; // Graph height in pixels  int num_bars = 8;  // Number of bars to display  #define yscale 8   // Graph +/- y-axis scale  e.g. 8 displays +/-8 and scales data accordingly  float bar_width = gwidth / (num_bars+1); // Determine bar width based on graph width  x = 30; // Sets position of graph on screen  y = 15; // Sets position of graph on screen  display->drawVerticalLine(x, y, gscale+1);  display->drawString(x-18,y-6,”>+”+String(yscale));  display->drawString(x-8,y+gscale/2-6,”0″);  display->drawString(x-15,y+gscale-6,”<-“+String(yscale));  display->drawString(x-30,y+gscale/2-6,String(hr_cnt%24));  display->drawString(x+2+(bar_width+3)*0, y+gscale,”-24″);  // 24hr marker at bar 0  display->drawString(x+2+(bar_width+3)*2, y+gscale,”-12″);  // 12hr marker at bar 2  display->drawString(x+2+(bar_width+3)*5, y+gscale,”-2″);   // 2hr  marker at bar 5  display->drawString(x+2+(bar_width+3)*7, y+gscale,”0″);    // 0hr  marker at bar 7  int display_points [8] = {0,5,11,17,20,21,22,23}; // Only display time for hours 0,5,11,17,20,21,22,23  float value;  for (int bar_num = 0; bar_num < num_bars; bar_num++){      // Now display a bar at each hour position -24, -18, -12, -6, -3, -2, -1 and 0 hour    value = map(reading[display_points[bar_num]].pressure, reading[23].pressure-yscale, reading[23].pressure+yscale, gscale, 0);    if (value > gscale) value = gscale;                      // Screen scale is 0 to e.g. 40pixels, this stops drawing beyond graph bounds    if (value < 0     ) value = 0;                           // 0 is top of graph, this stops drawing beyond graph bounds    display->drawHorizontalLine(x+bar_num*(bar_width+3)+2, y+value, bar_width);    for (int yplus=gscale; yplus > value; yplus = yplus – 1) {      display->drawHorizontalLine(x+bar_num*(bar_width+3)+2, y + yplus, bar_width);    }  }}// This frame draws a weather icon based on 1-hour of data for the predictionvoid drawFrame4(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {  reading[23].pressure = (reading[23].pressure + read_pressure())/2;                 // Update rolling average, gets reset on the hour transition  float  trend = reading[23].pressure – reading[22].pressure;                        // Get short-term trend for the last 1-hour  weather_description wx_text = get_forecast_text(read_pressure(), trend, look_1hr); // Convert to forecast text based on 1-hours  ForecastToImgTxt(wx_text);  display->drawXbm(x+0,y+15, 40, 40, image_table[image]);           // Display corresponding image  display->drawStringMaxWidth(x+45,y+12,90,”1-Hr forecast”);  display->drawStringMaxWidth(x+45,y+22,90,String(read_pressure(),1)+” hPA”);  display->drawStringMaxWidth(x+47,y+32,90,String(trend,1)+” “+get_trend_text(trend));}// This frame shows a weather description based on 1-hour of data for the predictionvoid drawFrame5(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {  reading[23].pressure = (reading[23].pressure + read_pressure())/2;                 // Update rolling average  float  trend = reading[23].pressure – reading[22].pressure;                        // Get short-term trend  weather_description wx_text = get_forecast_text(read_pressure(), trend, look_1hr); // Convert to forecast text based on 1-hours  ForecastToImgTxt(wx_text);  display->drawString(x+0,y+10,”Short-term forecast:”);  display->setFont(ArialMT_Plain_16);  display->drawStringMaxWidth(x+0,y+18,127,weather_text);  display->setFont(ArialMT_Plain_10);}float read_pressure(){  int reading = (bme.readPressure()/100.0F+pressure_offset)*10; // Rounded result to 1-decimal place  return (float)reading/10;}// Convert pressure trend to textString get_trend_text(float trend){  String trend_str = “Steady”; // Default weather state  if (trend > 3.5)                          { trend_str = “Rising fast”;  }  else if (trend >   1.5  && trend <= 3.5)  { trend_str = “Rising”;       }  else if (trend >   0.25 && trend <= 1.5)  { trend_str = “Rising slow”;  }  else if (trend >  -0.25 && trend <  0.25) { trend_str = “Steady”;       }  else if (trend >= -1.5  && trend < -0.25) { trend_str = “Falling slow”; }  else if (trend >= -3.5  && trend < -1.5)  { trend_str = “Falling”;      }  else if (trend <= -3.5)                   { trend_str = “Falling fast”; }  return trend_str;}// Convert forecast text to a corresponding image for display together with a record of the current weathervoid ForecastToImgTxt(weather_description wx_text){  if      (wx_text == GoodClearWeather)           {image = sunny_img;       current_wx = sunny;        weather_text = “Good clear weather”;}  else if (wx_text == BecomingClearer)            {image = mostlysunny_img; current_wx = mostlysunny;  weather_text = “Becoming clearer”;}  else if (wx_text == NoChange)                   {image = cloudy_img;      current_wx = cloudy;       weather_text = “No change, clearing”;}  else if (wx_text == ClearSpells)                {image = mostlysunny_img; current_wx = mostlysunny;  weather_text = “Clear spells”;}  else if (wx_text == ClearingWithin12hrs)        {image = mostlysunny_img; current_wx = mostlysunny;  weather_text = “Clearing within 12-hrs”;}  else if (wx_text == ClearingAndColder)          {image = mostlysunny_img; current_wx = mostlysunny;  weather_text = “Clearing and colder”;}  else if (wx_text == GettingWarmer)              {image = mostlysunny_img; current_wx = mostlysunny;  weather_text = “Getting warmer”;}  else if (wx_text == WarmerIn2daysRainLikely)    {image = rain_img;        current_wx = rain;         weather_text = “Warmer in 2-days, rain likely”;}  else if (wx_text == ExpectRain)                 {image = rain_img;        current_wx = rain;         weather_text = “Expect rain”;}  else if (wx_text == WarmerRainWithin36hrs)      {image = rain_img;        current_wx = rain;         weather_text = “Warmer, rain within 36-hrs”;}  else if (wx_text == RainIn18hrs)                {image = rain_img;        current_wx = rain;         weather_text = “Rain in 18-hrs”;}  else if (wx_text == RainHighWindsClearAndCool)  {image = rain_img;        current_wx = rain;         weather_text = “Rain, high winds, clear and cool”;}  else if (wx_text == GalesHeavyRainSnowInWinter) {image = tstorms_img;     current_wx = tstorms;      weather_text = “Gales, heavy rain, in winter snow”;}}// Convert pressure and trend to a weather description either for 1 or 3 hours with the boolean true/false switchweather_description get_forecast_text(float pressure_now, float trend, bool range) {  String trend_str = get_trend_text(trend);  weather_description wx_text = NoChange; //As a default forecast   image = cloudy_img; // Generally when there is ‘no change’ then cloudy is the conditions  if (pressure_now >= 1022.68 )                                                          {wx_text = GoodClearWeather;}  if (pressure_now >= 1022.7  && trend_str  == “Falling fast”)                           {wx_text = WarmerRainWithin36hrs;}  if (pressure_now >= 1013.2  && pressure_now <= 1022.68 &&      (trend_str == “Steady” || trend_str == “Rising slow”))                              {wx_text = NoChange; (range?wx_history_3hr():wx_history_1hr()); }  if (pressure_now >= 1013.2 && pressure_now <= 1022.68 &&     (trend_str == “Rising” || trend_str == “Rising fast”))                              {wx_text = GettingWarmer;}  if (pressure_now >= 1013.2 && pressure_now <= 1022.68 && trend_str == “Rising slow”)   {wx_text = BecomingClearer;}  if (pressure_now >= 1013.2 && pressure_now <= 1022.68 &&      (trend_str == “Falling slow” || trend_str == “Falling fast”))                       {wx_text = ExpectRain;}  if (pressure_now >= 1013.2 && pressure_now <= 1022.68 && trend_str  == “Steady”)       {wx_text = ClearSpells; (range?wx_history_3hr():wx_history_1hr());};  if (pressure_now <= 1013.2 && (trend_str == “Falling slow” || trend_str == “Falling”)) {wx_text = RainIn18hrs;}  if (pressure_now <= 1013.2  &&  trend_str == “Falling fast”)                           {wx_text = RainHighWindsClearAndCool;}  if (pressure_now <= 1013.2  &&      (trend_str == “Rising” || trend_str==”Rising slow”||trend_str==”Rising fast”))      {wx_text = ClearingWithin12hrs;}  if (pressure_now <= 1009.14 && trend_str  == “Falling fast”)                           {wx_text = GalesHeavyRainSnowInWinter;}  if (pressure_now <= 1009.14 && trend_str  == “Rising fast”)                            {wx_text = ClearingAndColder;}  return wx_text;}// Convert 1-hr weather history to textvoid wx_history_1hr() {  if      (wx_average_1hr >  0) weather_extra_text = “, expect sun”;  else if (wx_average_1hr == 0) weather_extra_text = “, mainly cloudy”;  else if (wx_average_1hr <  0) weather_extra_text = “, expect rain”;  else weather_extra_text = “”;}// Convert 3-hr weather history to textvoid wx_history_3hr() {  if      (wx_average_3hr >  0) weather_extra_text = “, expect sun”;  else if (wx_average_3hr == 0) weather_extra_text = “, mainly cloudy”;  else if (wx_average_3hr <  0) weather_extra_text = “, expect rain”;  else weather_extra_text = “”;}///////////////////////////////////////////////////////////////////////////////////////////////////////// This array keeps function pointers to all frames// frames are the single views that slide inFrameCallback frames[] = { drawFrame1, drawFrame2, drawFrame3, drawFrame4, drawFrame5};// how many frames are there?int frameCount = 5;// Overlays are statically drawn on top of a frame eg. a clockOverlayCallback overlays[] = { msOverlay };int overlaysCount = 1;void setup() {   float p,t;  Serial.begin(115200);  Wire.begin(5,4);  if (!StartWiFi(ssid,password)) Serial.println(“Failed to start WiFi Service after 20 attempts”);;  configTime(1, 3600, “pool.ntp.org”);  if (!bme.begin()) { Serial.println(“Could not find a sensor, check wiring!”);}    else   {    Serial.println(“Found a sensor continuing”);    while (isnan(bme.readPressure())) { Serial.println(bme.readPressure()); }  }  while (!update_time());  //Get the latest time  for (int i = 0; i <= 23; i++){ // At the start all array values are the same as a baseline     reading[i].pressure     = read_pressure();       // A rounded to 1-decimal place version of pressure    reading[i].temperature  = bme.readTemperature(); // Although not used, but avialable    reading[i].humidity     = bme.readAltitude();    // Although not used, but avialable    reading[i].wx_state_1hr = unknown;               // To begin with      reading[i].wx_state_3hr = unknown;               // To begin with   }                                                  // Note that only 0,5,11,17,20,21,22,23 are used as display positions  last_reading_hour = reading_hour;  wx_average_1hr = 0; // Until we get a better idea  wx_average_3hr = 0; // Until we get a better idea    // An ESP is capable of rendering 60fps in 80Mhz mode but leaves little time for anything else, run at 160Mhz mode or just set it to about 30 fps  ui.setTargetFPS(20);  ui.setIndicatorPosition(BOTTOM);         // You can change this to TOP, LEFT, BOTTOM, RIGHT  ui.setIndicatorDirection(LEFT_RIGHT);    // Defines where the first frame is located in the bar  ui.setFrameAnimation(SLIDE_LEFT);        // You can change the transition that is used SLIDE_LEFT, SLIDE_RIGHT, SLIDE_UP, SLIDE_DOWN  ui.setFrames(frames, frameCount);        // Add frames  ui.setOverlays(overlays, overlaysCount); // Add overlays  ui.init(); // Initialising the UI will init the display too.  display.flipScreenVertically();  display.setFont(ArialMT_Plain_10);  display.setTextAlignment(TEXT_ALIGN_LEFT);}void loop() {  int remainingTimeBudget = ui.update();  update_time_and_data();  if (remainingTimeBudget > 0) { // Do some work here if required    //for (int i = 0; i < 24;i++){    //  Serial.println(String(i)+” “+String(reading[pressure][i]));    //}    delay(remainingTimeBudget);  }}void update_time_and_data(){  while (!update_time());  if (reading_hour != last_reading_hour) { // If the hour has advanced, then shift readings left and record new values at array element [23]    for (int i = 0; i < 23;i++){      reading[i].pressure     = reading[i+1].pressure;      reading[i].temperature  = reading[i+1].temperature;      reading[i].wx_state_1hr = reading[i+1].wx_state_1hr;      reading[i].wx_state_3hr = reading[i+1].wx_state_3hr;    }    reading[23].pressure     = read_pressure(); // Update time=now with current value of pressure    reading[23].wx_state_1hr = current_wx;    reading[23].wx_state_3hr = current_wx;    last_reading_hour        = reading_hour;    hr_cnt++;    wx_average_1hr = reading[22].wx_state_1hr + current_wx;           // Used to predict 1-hour forecast extra text    wx_average_3hr = 0;    for (int i=23;i >= 21; i–){                                      // Used to predict 3-hour forecast extra text       wx_average_3hr = wx_average_3hr + (int)reading[i].wx_state_3hr; // On average the last 3-hours of weather is used for the ‘no change’ forecast – e.g. more of the same?    }  }  }bool update_time(){  struct tm timeinfo;  if(!getLocalTime(&timeinfo)){    Serial.println(“Failed to obtain time”);    return false;  }  //See http://www.cplusplus.com/reference/ctime/strftime/  Serial.println(&timeinfo, “%A, %d %B %y %H:%M:%S”); // Displays: Saturday, 24 June 17 14:05:49  char strftime_buf[64];  strftime(strftime_buf, sizeof(strftime_buf), “%R:%S   %a %d-%m-%y”, &timeinfo);  time_str = strftime_buf;  // Now is this format HH:MM:SS Sat 05-07-17  reading_hour = time_str.substring(0,2).toInt();  return true;}int StartWiFi(const char* ssid, const char* password){  int connAttempts = 0;  Serial.println(“rnConnecting to: “+String(ssid));  WiFi.begin(ssid, password); 

while (WiFi.status() != WL_CONNECTED ) {delay(500);Serial.print(“.”);  if(connAttempts > 20) return false;connAttempts++;}Serial.print(“WiFi connectedrnIP address: “); 

Serial.println(WiFi.localIP());  return true;}/*FRAME-3 description // This frame draws a graph of pressure (delata) change for the last 24-hours, see Annex* for more details// Draws a ‘relative value’ chart using reading[23] as the baseline// +8 |// +7 |–  //    : // +1 |–  —  —  —  —  —  —   //  0 +-24+-18+-12+-8-+-3-+-2-+-1-+-0-+// -1 |  // -2 |//    The ‘reading’ array holds values for Pressure, Temperature, Humidity and Wx State for the last 24-hours//    [00][01][02][03][04][05][06][07][08][09][10][11][12][13][14][15][16][17][18][19][20][21][22][23] Values are shifted left <– each hour//     ^-23Hr              ^-18Hr                  ^-12Hr                  ^-6Hr       ^-3 ^-2 ^-1 ^0Hr//     P  ~ readings in each array position//     T  ~ readings in each array position//     %  ~ readings in each array position//     Wx ~ readings in each array position
// Forecast basics:// Look at the pressure change over3 hours// If pressure is descending, then a low pressure area is approaching // If pressure is ascending , then a low is passing or a high pressure is coming// When pressure is changing rapidly (>6hPa/3 hours), it will be windy (or potentially windy) 
// More detailed:// Pressure falling slowly (0.5 – 3 hPa in 3h): low is weak, dying or moving slowly. You might get some rain but typically no high winds.// Pressure falling moderately (3-6 hPa/3h): rapid movement or deepening low. Moderate winds and rain and a warm front.                                           : the low is passing fast, the day after tomorrow will typically be fine. // Pressure falling fast (6-12 hPa/3h) : Storm conditions highly likely.// Pressure rises are connected with gradually drier weather
 */