├── image ├── image.jpg └── Screenshot_5.png ├── esp32-weather-station-color ├── resources │ ├── AZSMZ-11.jpg │ ├── PlaneSpotterWiring.png │ ├── ESP8266ColorDisplayKit.png │ ├── wunderground │ │ ├── big │ │ │ ├── clear.bmp │ │ │ ├── fog.bmp │ │ │ ├── hazy.bmp │ │ │ ├── rain.bmp │ │ │ ├── sleet.bmp │ │ │ ├── snow.bmp │ │ │ ├── sunny.bmp │ │ │ ├── cloudy.bmp │ │ │ ├── tstorms.bmp │ │ │ ├── unknown.bmp │ │ │ ├── chancerain.bmp │ │ │ ├── chancesnow.bmp │ │ │ ├── flurries.bmp │ │ │ ├── chancesleet.bmp │ │ │ ├── chancestorms.bmp │ │ │ ├── mostlycloudy.bmp │ │ │ ├── mostlysunny.bmp │ │ │ ├── partlycloudy.bmp │ │ │ ├── partlysunny.bmp │ │ │ └── chanceflurries.bmp │ │ └── small │ │ │ ├── fog.bmp │ │ │ ├── clear.bmp │ │ │ ├── hazy.bmp │ │ │ ├── rain.bmp │ │ │ ├── sleet.bmp │ │ │ ├── snow.bmp │ │ │ ├── sunny.bmp │ │ │ ├── cloudy.bmp │ │ │ ├── flurries.bmp │ │ │ ├── tstorms.bmp │ │ │ ├── unknown.bmp │ │ │ ├── chancerain.bmp │ │ │ ├── chancesnow.bmp │ │ │ ├── chancesleet.bmp │ │ │ ├── chancestorms.bmp │ │ │ ├── mostlycloudy.bmp │ │ │ ├── mostlysunny.bmp │ │ │ ├── partlycloudy.bmp │ │ │ ├── partlysunny.bmp │ │ │ └── chanceflurries.bmp │ └── moonphases │ │ ├── moonphase_L0.bmp │ │ ├── moonphase_L1.bmp │ │ ├── moonphase_L10.bmp │ │ ├── moonphase_L11.bmp │ │ ├── moonphase_L12.bmp │ │ ├── moonphase_L13.bmp │ │ ├── moonphase_L14.bmp │ │ ├── moonphase_L15.bmp │ │ ├── moonphase_L16.bmp │ │ ├── moonphase_L17.bmp │ │ ├── moonphase_L18.bmp │ │ ├── moonphase_L19.bmp │ │ ├── moonphase_L2.bmp │ │ ├── moonphase_L20.bmp │ │ ├── moonphase_L21.bmp │ │ ├── moonphase_L22.bmp │ │ ├── moonphase_L23.bmp │ │ ├── moonphase_L3.bmp │ │ ├── moonphase_L4.bmp │ │ ├── moonphase_L5.bmp │ │ ├── moonphase_L6.bmp │ │ ├── moonphase_L7.bmp │ │ ├── moonphase_L8.bmp │ │ └── moonphase_L9.bmp ├── TouchControllerWS.h ├── README.md ├── TouchControllerWS.cpp ├── settings.OLD └── settings.h ├── esp8266-weather-station-master ├── resources │ └── CurrentWeatherReflection.jpg ├── examples │ ├── WeatherStationDemoExtendedDST │ │ ├── resources │ │ │ ├── Thumbs.db │ │ │ ├── cover.jpg │ │ │ ├── splash.jpg │ │ │ ├── Boston_EDT.jpg │ │ │ ├── Zurich_CET.jpg │ │ │ ├── conditions.jpg │ │ │ ├── thingspeak.jpg │ │ │ ├── DHT22_sensor.jpg │ │ │ ├── DHT22_update.jpg │ │ │ ├── 1-3_day_forecast.jpg │ │ │ └── 4-6_day_forecast.jpg │ │ ├── WeatherStationImages.h │ │ ├── README.md │ │ ├── settings.h │ │ └── DSEG7Classic-BoldFont.h │ ├── WeatherStationDemo │ │ ├── WeatherStationImages.h │ │ └── WeatherStationDemo.ino │ ├── PlaneSpotterDemo │ │ ├── images.h │ │ ├── AdsbExchangeClient.h │ │ └── AdsbExchangeClient.cpp │ ├── WeatherStationDemoExtended │ │ └── WeatherStationImages.h │ ├── WundergroundAstronomyDemo │ │ └── WundergroundAstronomyDemo.ino │ ├── WundergroundForecastDemo │ │ └── WundergroundForecastDemo.ino │ ├── WundergroundAlertsDemo │ │ └── WundergroundAlertsDemo.ino │ ├── WundergroundHourlyDemo │ │ └── WundergroundHourlyDemo.ino │ ├── WundergroundConditionsDemo │ │ └── WundergroundConditionsDemo.ino │ └── WorldClockDemo │ │ └── WorldClockDemo.ino ├── library.properties ├── library.json ├── platformio.ini ├── lib │ └── readme.txt ├── License ├── src │ ├── NTPClient.h │ ├── TimeClient.h │ ├── ThingspeakClient.h │ ├── WorldClockClient.h │ ├── WundergroundAstronomy.h │ ├── WundergroundHourly.h │ ├── WundergroundConditions.h │ ├── WundergroundForecast.h │ ├── WundergroundAlerts.h │ ├── ThingspeakClient.cpp │ ├── TimeClient.cpp │ ├── NTPClient.cpp │ ├── WorldClockClient.cpp │ ├── WundergroundHourly.cpp │ ├── WundergroundAstronomy.cpp │ ├── WundergroundClient.h │ ├── WundergroundConditions.cpp │ ├── WundergroundAlerts.cpp │ └── WundergroundForecast.cpp └── README.md └── README.md /image/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/image/image.jpg -------------------------------------------------------------------------------- /image/Screenshot_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/image/Screenshot_5.png -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/AZSMZ-11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/AZSMZ-11.jpg -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/PlaneSpotterWiring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/PlaneSpotterWiring.png -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/ESP8266ColorDisplayKit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/ESP8266ColorDisplayKit.png -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/clear.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/clear.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/fog.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/fog.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/hazy.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/hazy.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/rain.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/rain.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/sleet.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/sleet.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/snow.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/snow.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/sunny.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/sunny.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/fog.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/fog.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L0.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L0.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L1.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L10.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L10.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L11.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L11.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L12.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L12.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L13.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L13.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L14.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L14.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L15.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L15.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L16.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L16.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L17.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L17.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L18.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L18.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L19.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L19.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L2.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L20.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L20.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L21.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L21.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L22.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L22.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L23.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L23.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L3.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L4.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L5.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L6.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L7.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L7.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L8.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L8.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/moonphases/moonphase_L9.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/moonphases/moonphase_L9.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/cloudy.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/cloudy.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/tstorms.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/tstorms.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/unknown.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/unknown.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/clear.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/clear.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/hazy.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/hazy.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/rain.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/rain.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/sleet.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/sleet.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/snow.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/snow.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/sunny.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/sunny.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/chancerain.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/chancerain.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/chancesnow.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/chancesnow.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/flurries.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/flurries.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/cloudy.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/cloudy.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/flurries.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/flurries.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/tstorms.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/tstorms.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/unknown.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/unknown.bmp -------------------------------------------------------------------------------- /esp8266-weather-station-master/resources/CurrentWeatherReflection.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp8266-weather-station-master/resources/CurrentWeatherReflection.jpg -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/chancesleet.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/chancesleet.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/chancestorms.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/chancestorms.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/mostlycloudy.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/mostlycloudy.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/mostlysunny.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/mostlysunny.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/partlycloudy.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/partlycloudy.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/partlysunny.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/partlysunny.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/chancerain.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/chancerain.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/chancesnow.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/chancesnow.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/big/chanceflurries.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/big/chanceflurries.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/chancesleet.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/chancesleet.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/chancestorms.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/chancestorms.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/mostlycloudy.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/mostlycloudy.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/mostlysunny.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/mostlysunny.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/partlycloudy.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/partlycloudy.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/partlysunny.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/partlysunny.bmp -------------------------------------------------------------------------------- /esp32-weather-station-color/resources/wunderground/small/chanceflurries.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp32-weather-station-color/resources/wunderground/small/chanceflurries.bmp -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/Thumbs.db -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/cover.jpg -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/splash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/splash.jpg -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/Boston_EDT.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/Boston_EDT.jpg -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/Zurich_CET.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/Zurich_CET.jpg -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/conditions.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/conditions.jpg -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/thingspeak.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/thingspeak.jpg -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/DHT22_sensor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/DHT22_sensor.jpg -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/DHT22_update.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/DHT22_update.jpg -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/1-3_day_forecast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/1-3_day_forecast.jpg -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/4-6_day_forecast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LilyGO/Color-Weather-Station-ESP32/HEAD/esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/resources/4-6_day_forecast.jpg -------------------------------------------------------------------------------- /esp8266-weather-station-master/library.properties: -------------------------------------------------------------------------------- 1 | name=ESP8266 Weather Station 2 | version=1.3.2 3 | author=Daniel Eichhorn 4 | maintainer=Daniel Eichhorn 5 | sentence=ESP8266 based internet connected Weather Station 6 | paragraph=ESP8266 based internet connected Weather Station 7 | category=Display 8 | url=https://github.com/squix78/esp8266-weather-station 9 | architectures=esp8266,esp32 10 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WeatherStation", 3 | "keywords": "embedded, display, oled", 4 | "description": "A wifi connected information display", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/squix78/esp8266-weather-station.git" 8 | }, 9 | "authors": { 10 | "name": "Daniel Eichhorn", 11 | "url": "https://blog.squix.org" 12 | }, 13 | "frameworks": "arduino", 14 | "platforms": [ 15 | "espressif8266", 16 | "espressif32" 17 | ], 18 | "version": "1.3.2" 19 | } 20 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; http://docs.platformio.org/page/projectconf.html 10 | 11 | [env:d1_mini] 12 | platform = espressif8266 13 | board = d1_mini 14 | framework = arduino 15 | upload_speed = 921600 16 | board_f_cpu = 160000000L 17 | lib_deps = JsonStreamingParser 18 | -------------------------------------------------------------------------------- /esp32-weather-station-color/TouchControllerWS.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "SPIFFS.h" 3 | 4 | #include 5 | 6 | #ifndef _TOUCH_CONTROLLERWSH_ 7 | #define _TOUCH_CONTROLLERWSH_ 8 | 9 | typedef void (*CalibrationCallback)(int16_t x, int16_t y); 10 | 11 | class TouchControllerWS { 12 | public: 13 | TouchControllerWS(XPT2046_Touchscreen *touchScreen); 14 | bool loadCalibration(); 15 | bool saveCalibration(); 16 | void startCalibration(CalibrationCallback *callback); 17 | void continueCalibration(); 18 | bool isCalibrationFinished(); 19 | bool isTouched(); 20 | bool isTouched(int16_t debounceMillis); 21 | TS_Point getPoint(); 22 | 23 | private: 24 | XPT2046_Touchscreen *touchScreen; 25 | float dx = 0.0; 26 | float dy = 0.0; 27 | int ax = 0; 28 | int ay = 0; 29 | int state = 0; 30 | long lastStateChange = 0; 31 | long lastTouched = 0; 32 | CalibrationCallback *calibrationCallback; 33 | TS_Point p1, p2; 34 | 35 | }; 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/lib/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for the project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link to executable file. 4 | 5 | The source code of each library should be placed in separate directory, like 6 | "lib/private_lib/[here are source files]". 7 | 8 | For example, see how can be organized `Foo` and `Bar` libraries: 9 | 10 | |--lib 11 | | |--Bar 12 | | | |--docs 13 | | | |--examples 14 | | | |--src 15 | | | |- Bar.c 16 | | | |- Bar.h 17 | | |--Foo 18 | | | |- Foo.c 19 | | | |- Foo.h 20 | | |- readme.txt --> THIS FILE 21 | |- platformio.ini 22 | |--src 23 | |- main.c 24 | 25 | Then in `src/main.c` you should use: 26 | 27 | #include 28 | #include 29 | 30 | // rest H/C/CPP code 31 | 32 | PlatformIO will find your libraries automatically, configure preprocessor's 33 | include paths and build them. 34 | 35 | More information about PlatformIO Library Dependency Finder 36 | - http://docs.platformio.org/page/librarymanager/ldf.html 37 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/License: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/NTPClient.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Arduino.h" 4 | 5 | # if defined(ESP8266) 6 | #include 7 | #endif 8 | # if defined(ESP32) 9 | #include 10 | #endif 11 | #include 12 | 13 | #define SEVENZYYEARS 2208988800UL 14 | #define NTP_PACKET_SIZE 48 15 | 16 | class NTPClient { 17 | private: 18 | WiFiUDP _udp; 19 | 20 | const char* _poolServerName = "time.nist.gov"; // Default time server 21 | int _port = 1337; 22 | int _timeOffset; 23 | 24 | unsigned int _updateInterval = 60000; // In ms 25 | 26 | unsigned long _currentEpoc; // In s 27 | unsigned long _lastUpdate = 0; // In ms 28 | 29 | byte _packetBuffer[NTP_PACKET_SIZE]; 30 | 31 | void sendNTPPacket(IPAddress _timeServerIP); 32 | 33 | public: 34 | NTPClient(int timeOffset); 35 | NTPClient(const char* poolServerName); 36 | NTPClient(const char* poolServerName, int timeOffset); 37 | NTPClient(const char* poolServerName, int timeOffset, int updateInterval); 38 | 39 | void begin(); 40 | void update(); 41 | void forceUpdate(); 42 | 43 | String getHours(); 44 | String getMinutes(); 45 | String getSeconds(); 46 | String getFormattedTime(); 47 | 48 | unsigned long getRawTime(); 49 | }; 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Color-Weather-Station-ESP32 2 | youtube link:https://www.youtube.com/watch?v=gg3Hr2Goizk&feature=youtu.be 3 | 4 | ![image](https://github.com/LilyGO/Color-Weather-Station-ESP32/blob/master/image/Screenshot_5.png) 5 | 6 | This is fork of a Squix Weather Station 7 | https://github.com/ThingPulse/esp8266-weather-station-color 8 | 9 | based on TTGO TM MUSIC ESP32 + 2.4 TFT 10 | 11 | ![image](https://github.com/LilyGO/Color-Weather-Station-ESP32/blob/master/image/image.jpg) 12 | ### If You MCU is ESP32 you must use modified library from esp8266-weather-station-master 13 | 14 | This fork Squix Weather Station 15 | 16 | https://github.com/ThingPulse/esp8266-weather-station-color 17 | Using the TTGO TM Music board 18 | 19 | ### Purchase address 20 | https://ru.aliexpress.com/item/Ttgo-2-4-PCM5102A-SD-ESP32-WiFi-Bluetooth/32848882218.html?spm=a2g0s.9042311.0.0.BYS264 21 | Made on ESP32. 22 | 23 | Arduino is necessary for the firmware. You also need to register for Wunderground (for free, but in English, detailed instructions in the folder with the library (also in English, truth.) The libraries are modified to use ESP32 and the screen from TTGO. 24 | 25 | Suitable for almost any boards on ESP32 and LED screens on controllers compatible with ILI9341. 26 | 27 | The plans to make Russification. Maybe He'll screw it to my first weather station. Precisely supplement with local sensors and prognosis from the histomeo. 28 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/TimeClient.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | #pragma once 26 | 27 | # if defined(ESP8266) 28 | #include 29 | #endif 30 | # if defined(ESP32) 31 | #include 32 | #endif 33 | 34 | #define NTP_PACKET_SIZE 48 35 | 36 | class TimeClient { 37 | 38 | private: 39 | float myUtcOffset = 0; 40 | long localEpoc = 0; 41 | long localMillisAtUpdate; 42 | 43 | const char* ntpServerName = "time.nist.gov"; 44 | unsigned int localPort = 2390; 45 | 46 | byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 47 | 48 | 49 | public: 50 | TimeClient(float utcOffset); 51 | void updateTime(); 52 | 53 | String getHours(); 54 | String getMinutes(); 55 | String getSeconds(); 56 | String getFormattedTime(); 57 | long getCurrentEpoch(); 58 | long getCurrentEpochWithUtcOffset(); 59 | 60 | }; 61 | 62 | -------------------------------------------------------------------------------- /esp32-weather-station-color/README.md: -------------------------------------------------------------------------------- 1 | # ThingPulse ESP8266 Weather Station Color 2 | 3 | 4 | [![ThingPulse logo](https://thingpulse.com/assets/ThingPulse-w300.svg)](https://thingpulse.com) 5 | 6 | ESP8266 Weather Station Color using ILI9341 240x320 TFT display 7 | 8 | ## Hardware Requirements 9 | 10 | The code in this project supports an ILI9341 240x320 TFT display with code running on an ESP8266. To get you up and running in no time we created a kit which contains all the necessary parts including a custom PCB to connect display and WiFi chip: 11 | [https://thingpulse.com/product/esp8266-wifi-color-display-kit-2-4/](https://thingpulse.com/product/esp8266-wifi-color-display-kit-2-4/) 12 | 13 | By buying the kit from us you are supporting future development. Thank you! 14 | 15 | [![ThingPulse ESP8266 Color Display Kit](resources/ESP8266ColorDisplayKit.png)](https://thingpulse.com/product/esp8266-wifi-color-display-kit-2-4/) 16 | 17 | 18 | ## Software Requirements/ Libraries 19 | * Mini Grafx by Daniel Eichhorn 20 | * ESP8266 WeatherStation by Daniel Eichhorn 21 | * Json Streaming Parser by Daniel Eichhorn 22 | * simpleDSTadjust by neptune2 23 | 24 | You also need to get a key for the Wunderground API: [https://www.wunderground.com/weather/api/](https://www.wunderground.com/weather/api/) 25 | 26 | ## Settings 27 | Please have a good look at the [settings.h](./settings.h) file. It offers config options for: 28 | * Location to obtain weather data for 29 | * Clock mode: 12hour (am/pm) or 24hour 30 | * Metric system for temperature 31 | * Timezone and daytime saving options 32 | * API key for the Wunderground service 33 | 34 | ## Wiring 35 | 36 | ![Wiring](resources/PlaneSpotterWiring.png) 37 | 38 | | Wemos D1 Mini | ILI9341 | 39 | | ------------- |:-------------:| 40 | | D4 | T_IRQ | 41 | | D6 | T_DO | 42 | | D7 | T_DIN | 43 | | D3 | T_CS | 44 | | D5 | T_CLK | 45 | | D6 | SDO | 46 | | D8 | LED | 47 | | D5 | SCK | 48 | | D7 | SDI | 49 | | D2 | D/C | 50 | | RST | RESET | 51 | | D1 | CS | 52 | | GND | GND | 53 | | 3V3 | VCC | 54 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemo/WeatherStationImages.h: -------------------------------------------------------------------------------- 1 | #define WiFi_Logo_width 60 2 | #define WiFi_Logo_height 36 3 | const char WiFi_Logo_bits[] PROGMEM = { 4 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 5 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 6 | 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 7 | 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 8 | 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 9 | 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 10 | 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 11 | 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, 12 | 0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C, 13 | 0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00, 14 | 0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C, 15 | 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00, 16 | 0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 17 | 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 18 | 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C, 19 | 0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00, 20 | 0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F, 21 | 0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00, 22 | 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 23 | 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 24 | 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 25 | 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 26 | 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 28 | }; 29 | 30 | const char activeSymbole[] PROGMEM = { 31 | B00000000, 32 | B00000000, 33 | B00011000, 34 | B00100100, 35 | B01000010, 36 | B01000010, 37 | B00100100, 38 | B00011000 39 | }; 40 | 41 | const char inactiveSymbole[] PROGMEM = { 42 | B00000000, 43 | B00000000, 44 | B00000000, 45 | B00000000, 46 | B00011000, 47 | B00011000, 48 | B00000000, 49 | B00000000 50 | }; 51 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/ThingspeakClient.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | # if defined(ESP8266) 31 | #include 32 | #endif 33 | # if defined(ESP32) 34 | #include 35 | #endif 36 | #include 37 | 38 | #define MAX_FORECAST_PERIODS 7 39 | 40 | class ThingspeakClient: public JsonListener { 41 | private: 42 | // Thingspeak has a maximum of 8 fields 43 | String lastFields[8]; 44 | String fieldLabels[8]; 45 | String createdAt; 46 | boolean isHeader = true; 47 | String currentKey = ""; 48 | 49 | public: 50 | ThingspeakClient(); 51 | 52 | void getLastChannelItem(String channelId, String readApiKey); 53 | 54 | String getFieldLabel(int index); 55 | 56 | String getFieldValue(int index); 57 | 58 | String getCreatedAt(); 59 | 60 | virtual void whitespace(char c); 61 | 62 | virtual void startDocument(); 63 | 64 | virtual void key(String key); 65 | 66 | virtual void value(String value); 67 | 68 | virtual void endArray(); 69 | 70 | virtual void endObject(); 71 | 72 | virtual void endDocument(); 73 | 74 | virtual void startArray(); 75 | 76 | virtual void startObject(); 77 | }; 78 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/PlaneSpotterDemo/images.h: -------------------------------------------------------------------------------- 1 | #define WiFi_Logo_width 60 2 | #define WiFi_Logo_height 36 3 | const char WiFi_Logo_bits[] PROGMEM = { 4 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 5 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 6 | 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 7 | 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 8 | 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 9 | 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 10 | 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 11 | 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, 12 | 0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C, 13 | 0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00, 14 | 0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C, 15 | 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00, 16 | 0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 17 | 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 18 | 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C, 19 | 0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00, 20 | 0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F, 21 | 0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00, 22 | 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 23 | 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 24 | 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 25 | 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 26 | 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 28 | }; 29 | 30 | const char emptySymbol[] PROGMEM = { 31 | B00000000, 32 | B00000000, 33 | B00000000, 34 | B00000000, 35 | B00000000, 36 | B00000000, 37 | B00000000, 38 | B00000000 39 | }; 40 | 41 | const char activeSymbol[] PROGMEM = { 42 | B00000000, 43 | B00000000, 44 | B00011000, 45 | B00100100, 46 | B01000010, 47 | B01000010, 48 | B00100100, 49 | B00011000 50 | }; 51 | 52 | const char inactiveSymbol[] PROGMEM = { 53 | B00000000, 54 | B00000000, 55 | B00000000, 56 | B00000000, 57 | B00011000, 58 | B00011000, 59 | B00000000, 60 | B00000000 61 | }; 62 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtended/WeatherStationImages.h: -------------------------------------------------------------------------------- 1 | #define WiFi_Logo_width 60 2 | #define WiFi_Logo_height 36 3 | const char WiFi_Logo_bits[] PROGMEM = { 4 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 5 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 6 | 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 7 | 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 8 | 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 9 | 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 10 | 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 11 | 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, 12 | 0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C, 13 | 0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00, 14 | 0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C, 15 | 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00, 16 | 0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 17 | 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 18 | 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C, 19 | 0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00, 20 | 0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F, 21 | 0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00, 22 | 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 23 | 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 24 | 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 25 | 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 26 | 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 28 | }; 29 | 30 | const char emptySymbol[] PROGMEM = { 31 | B00000000, 32 | B00000000, 33 | B00000000, 34 | B00000000, 35 | B00000000, 36 | B00000000, 37 | B00000000, 38 | B00000000 39 | }; 40 | 41 | const char activeSymbol[] PROGMEM = { 42 | B00000000, 43 | B00000000, 44 | B00011000, 45 | B00100100, 46 | B01000010, 47 | B01000010, 48 | B00100100, 49 | B00011000 50 | }; 51 | 52 | const char inactiveSymbol[] PROGMEM = { 53 | B00000000, 54 | B00000000, 55 | B00000000, 56 | B00000000, 57 | B00011000, 58 | B00011000, 59 | B00000000, 60 | B00000000 61 | }; 62 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/WeatherStationImages.h: -------------------------------------------------------------------------------- 1 | #define WiFi_Logo_width 60 2 | #define WiFi_Logo_height 36 3 | const char WiFi_Logo_bits[] PROGMEM = { 4 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 5 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 6 | 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 7 | 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 8 | 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 9 | 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 10 | 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 11 | 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, 12 | 0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C, 13 | 0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00, 14 | 0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C, 15 | 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00, 16 | 0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 17 | 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 18 | 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C, 19 | 0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00, 20 | 0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F, 21 | 0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00, 22 | 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 23 | 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 24 | 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 25 | 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 26 | 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 28 | }; 29 | 30 | const char emptySymbol[] PROGMEM = { 31 | B00000000, 32 | B00000000, 33 | B00000000, 34 | B00000000, 35 | B00000000, 36 | B00000000, 37 | B00000000, 38 | B00000000 39 | }; 40 | 41 | const char activeSymbol[] PROGMEM = { 42 | B00000000, 43 | B00000000, 44 | B00011000, 45 | B00100100, 46 | B01000010, 47 | B01000010, 48 | B00100100, 49 | B00011000 50 | }; 51 | 52 | const char inactiveSymbol[] PROGMEM = { 53 | B00000000, 54 | B00000000, 55 | B00000000, 56 | B00000000, 57 | B00011000, 58 | B00011000, 59 | B00000000, 60 | B00000000 61 | }; 62 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WorldClockClient.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | # if defined(ESP8266) 31 | #include 32 | #endif 33 | # if defined(ESP32) 34 | #include 35 | #endif 36 | #include 37 | 38 | 39 | class WorldClockClient: public JsonListener { 40 | private: 41 | long millisOfDayAtUpdate = 0; 42 | long localMillisAtUpdate; 43 | boolean isHeader = true; 44 | String currentKey = ""; 45 | String myLanguage; 46 | String myCountry; 47 | String* myTimeZoneIds; 48 | int myNumberOfTimeZoneIds; 49 | String myDateFormat; 50 | 51 | int currentTimeZoneIndex; 52 | long* timeZoneOffsetToUtcMillis; 53 | 54 | public: 55 | WorldClockClient(String language, String country, String dateFormat, int numberOfTimeZones, String* timeZoneIds); 56 | 57 | void updateTime(); 58 | 59 | String getFormattedTime(int timeZoneIndex); 60 | 61 | String getHours(int timeZoneIndex); 62 | 63 | String getMinutes(int timeZoneIndex); 64 | 65 | String getSeconds(int timeZoneIndex); 66 | 67 | long getSecondsOfDay(int timeZoneIndex); 68 | 69 | virtual void whitespace(char c); 70 | 71 | virtual void startDocument(); 72 | 73 | virtual void key(String key); 74 | 75 | virtual void value(String value); 76 | 77 | virtual void endArray(); 78 | 79 | virtual void endObject(); 80 | 81 | virtual void endDocument(); 82 | 83 | virtual void startArray(); 84 | 85 | virtual void startObject(); 86 | }; 87 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WundergroundAstronomy.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | typedef struct WGAstronomy { 32 | String moonPctIlum; 33 | String moonAge; 34 | String moonPhase; 35 | String sunriseTime; 36 | String sunsetTime; 37 | String moonriseTime; 38 | String moonsetTime; 39 | } WGAstronomy; 40 | 41 | class WundergroundAstronomy: public JsonListener { 42 | private: 43 | WGAstronomy *astronomy; 44 | String currentKey; 45 | String currentParent = ""; 46 | String moonPctIlum; // not used 47 | String moonAge; // make this a long? 48 | String moonPhase; 49 | String sunriseTime; 50 | String sunsetTime; 51 | String moonriseTime; 52 | String moonsetTime; 53 | 54 | boolean usePM; 55 | boolean isPM; 56 | 57 | void doUpdate(WGAstronomy *astronomy, String url); 58 | 59 | 60 | public: 61 | WundergroundAstronomy(boolean usePM); 62 | void updateAstronomy(WGAstronomy *astronomy, String apiKey, String language, String country, String city); 63 | void updateAstronomyPWS(WGAstronomy *astronomy, String apiKey, String language, String pws); 64 | void setPM(boolean usePM); 65 | virtual void whitespace(char c); 66 | 67 | virtual void startDocument(); 68 | 69 | virtual void key(String key); 70 | 71 | virtual void value(String value); 72 | 73 | virtual void endArray(); 74 | 75 | virtual void endObject(); 76 | 77 | virtual void endDocument(); 78 | 79 | virtual void startArray(); 80 | 81 | virtual void startObject(); 82 | }; 83 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WundergroundHourly.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | typedef struct WGHourly { 32 | String icon; 33 | String title; 34 | String temp; 35 | String hour; 36 | String PoP; 37 | } WGForecast; 38 | 39 | class WundergroundHourly: public JsonListener { 40 | private: 41 | String currentKey; 42 | String currentParent = ""; 43 | WGHourly *hourlies; 44 | 45 | long localEpoc = 0; 46 | int gmtOffset = 1; 47 | long localMillisAtUpdate; 48 | boolean isMetric = true; 49 | boolean is24Hours = true; 50 | 51 | 52 | void doUpdate(WGHourly *hourlies, String url); 53 | 54 | int currentHour; 55 | 56 | 57 | 58 | public: 59 | WundergroundHourly(boolean isMetric, boolean is24Hours); 60 | void updateHourly(WGHourly *hourlies, String apiKey, String language, String country, String city); 61 | void updateHourlyPWS(WGHourly *hourlies, String apiKey, String language, String pws); 62 | void updateHourlyZMW(WGHourly *hourlies, String apiKey, String language, String zmwCode); 63 | void setMetric(bool isMetric); 64 | void set24Hours(bool use24Hours); 65 | String getMeteoconIcon(String iconText); 66 | 67 | virtual void whitespace(char c); 68 | 69 | virtual void startDocument(); 70 | 71 | virtual void key(String key); 72 | 73 | virtual void value(String value); 74 | 75 | virtual void endArray(); 76 | 77 | virtual void endObject(); 78 | 79 | virtual void endDocument(); 80 | 81 | virtual void startArray(); 82 | 83 | virtual void startObject(); 84 | }; 85 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/PlaneSpotterDemo/AdsbExchangeClient.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #define CURRENT 0 34 | #define TEMP 1 35 | 36 | #define MAX_AGE_MILLIS 15000 37 | 38 | 39 | class AdsbExchangeClient: public JsonListener { 40 | private: 41 | int counter = 0; 42 | String currentKey = ""; 43 | String from[2] = {"", ""}; 44 | String to[2] = {"", ""}; 45 | String altitude[2] = {"", ""}; 46 | double distance[2] = {0.0, 0.0}; 47 | double currentMinDistance = 1000.0; 48 | String aircraftType[2] = {"", ""}; 49 | String operatorCode[2] = {"", ""}; 50 | double heading[2] = {0.0, 0.0}; 51 | long lastSightingMillis = 0; 52 | 53 | public: 54 | AdsbExchangeClient(); 55 | 56 | void updateVisibleAircraft(String searchQuery); 57 | 58 | String getFrom(); 59 | String getFromIcao(); 60 | String getTo(); 61 | String getToIcao(); 62 | String getAltitude(); 63 | double getDistance(); 64 | String getAircraftType(); 65 | String getOperatorCode(); 66 | double getHeading(); 67 | int getNumberOfVisibleAircrafts(); 68 | boolean isAircraftVisible(); 69 | 70 | virtual void whitespace(char c); 71 | 72 | virtual void startDocument(); 73 | 74 | virtual void key(String key); 75 | 76 | virtual void value(String value); 77 | 78 | virtual void endArray(); 79 | 80 | virtual void endObject(); 81 | 82 | virtual void endDocument(); 83 | 84 | virtual void startArray(); 85 | 86 | virtual void startObject(); 87 | }; 88 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WundergroundConditions.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | typedef struct WGConditions { 32 | String currentTemp; 33 | String windSpeed; 34 | String windDir; 35 | String weatherIcon; 36 | String weatherText; 37 | String humidity; 38 | String pressure; 39 | String dewPoint; 40 | String precipitationToday; 41 | String feelslike; 42 | String UV; 43 | String observationTime; 44 | String date; 45 | String observationDate; 46 | } WGConditions; 47 | 48 | class WundergroundConditions: public JsonListener { 49 | private: 50 | boolean isMetric = true; 51 | String currentKey; 52 | String currentParent; 53 | WGConditions *conditions; 54 | 55 | 56 | void doUpdate(WGConditions *conditions, String url); 57 | 58 | public: 59 | WundergroundConditions(boolean isMetric); 60 | void updateConditions(WGConditions *conditions, String apiKey, String language, String country, String city); 61 | void updateConditions(WGConditions *conditions, String apiKey, String language, String zmwCode); 62 | void updateConditionsPWS(WGConditions *conditions, String apiKey, String language, String pws); 63 | void setMetric(boolean isMetric); 64 | String getMeteoconIcon(String icon); 65 | virtual void whitespace(char c); 66 | 67 | virtual void startDocument(); 68 | 69 | virtual void key(String key); 70 | 71 | virtual void value(String value); 72 | 73 | virtual void endArray(); 74 | 75 | virtual void endObject(); 76 | 77 | virtual void endDocument(); 78 | 79 | virtual void startArray(); 80 | 81 | virtual void startObject(); 82 | }; 83 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WundergroundForecast.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | typedef struct WGForecast { 32 | String forecastIcon; 33 | String forecastTitle; 34 | String forecastLowTemp; 35 | String forecastHighTemp; 36 | String forecastDay; 37 | String forecastMonth; 38 | String forecastText; 39 | String PoP; 40 | } WGForecast; 41 | 42 | class WundergroundForecast: public JsonListener { 43 | private: 44 | String currentKey; 45 | String currentParent = ""; 46 | WGForecast *forecasts; 47 | uint8_t maxForecasts; 48 | long localEpoc = 0; 49 | int gmtOffset = 1; 50 | long localMillisAtUpdate; 51 | 52 | boolean isMetric = true; 53 | bool isSimpleForecast = false; 54 | 55 | void doUpdate(WGForecast *forecasts, uint8_t maxForecasts, String url); 56 | 57 | int currentForecastPeriod; 58 | 59 | 60 | 61 | public: 62 | WundergroundForecast(boolean isMetric); 63 | void updateForecast(WGForecast *forecasts, uint8_t maxForecasts, String apiKey, String language, String country, String city); 64 | void updateForecastPWS(WGForecast *forecasts, uint8_t maxForecasts, String apiKey, String language, String pws); 65 | void updateForecastZMW(WGForecast *forecasts, uint8_t maxForecasts, String apiKey, String language, String zmwCode); 66 | void setMetric(bool isMetric); 67 | String getMeteoconIcon(String iconText); 68 | 69 | virtual void whitespace(char c); 70 | 71 | virtual void startDocument(); 72 | 73 | virtual void key(String key); 74 | 75 | virtual void value(String value); 76 | 77 | virtual void endArray(); 78 | 79 | virtual void endObject(); 80 | 81 | virtual void endDocument(); 82 | 83 | virtual void startArray(); 84 | 85 | virtual void startObject(); 86 | }; 87 | -------------------------------------------------------------------------------- /esp32-weather-station-color/TouchControllerWS.cpp: -------------------------------------------------------------------------------- 1 | #include "TouchControllerWS.h" 2 | 3 | TouchControllerWS::TouchControllerWS(XPT2046_Touchscreen *touchScreen) { 4 | this->touchScreen = touchScreen; 5 | } 6 | 7 | bool TouchControllerWS::loadCalibration() { 8 | // always use this to "mount" the filesystem 9 | 10 | bool result = SPIFFS.begin(); 11 | Serial.println("SPIFFS opened: " + result); 12 | 13 | // this opens the file "f.txt" in read-mode 14 | File f = SPIFFS.open("/calibration.txt", "r"); 15 | 16 | if (!f) { 17 | return false; 18 | } else { 19 | 20 | //Lets read line by line from the file 21 | String dxStr = f.readStringUntil('\n'); 22 | String dyStr = f.readStringUntil('\n'); 23 | String axStr = f.readStringUntil('\n'); 24 | String ayStr = f.readStringUntil('\n'); 25 | 26 | dx = dxStr.toFloat(); 27 | dy = dyStr.toFloat(); 28 | ax = axStr.toInt(); 29 | ay = ayStr.toInt(); 30 | 31 | } 32 | f.close(); 33 | } 34 | 35 | bool TouchControllerWS::saveCalibration() { 36 | bool result = SPIFFS.begin(); 37 | 38 | // open the file in write mode 39 | File f = SPIFFS.open("/calibration.txt", "w"); 40 | if (!f) { 41 | Serial.println("file creation failed"); 42 | } 43 | // now write two lines in key/value style with end-of-line characters 44 | f.println(dx); 45 | f.println(dy); 46 | f.println(ax); 47 | f.println(ay); 48 | 49 | f.close(); 50 | } 51 | 52 | void TouchControllerWS::startCalibration(CalibrationCallback *calibrationCallback) { 53 | state = 0; 54 | this->calibrationCallback = calibrationCallback; 55 | } 56 | 57 | void TouchControllerWS::continueCalibration() { 58 | TS_Point p = touchScreen->getPoint(); 59 | 60 | if (state == 0) { 61 | (*calibrationCallback)(10, 10); 62 | if (touchScreen->touched()) { 63 | p1 = p; 64 | state++; 65 | lastStateChange = millis(); 66 | } 67 | 68 | } else if (state == 1) { 69 | (*calibrationCallback)(230, 310); 70 | if (touchScreen->touched() && (millis() - lastStateChange > 1000)) { 71 | 72 | p2 = p; 73 | state++; 74 | lastStateChange = millis(); 75 | dx = 240.0 / abs(p1.y - p2.y); 76 | dy = 320.0 / abs(p1.x - p2.x); 77 | ax = p1.y < p2.y ? p1.y : p2.y; 78 | ay = p1.x < p2.x ? p1.x : p2.x; 79 | } 80 | 81 | } 82 | } 83 | bool TouchControllerWS::isCalibrationFinished() { 84 | return state == 2; 85 | } 86 | 87 | bool TouchControllerWS::isTouched() { 88 | touchScreen->touched(); 89 | } 90 | 91 | bool TouchControllerWS::isTouched(int16_t debounceMillis) { 92 | if (touchScreen->touched() && millis() - lastTouched > debounceMillis) { 93 | lastTouched = millis(); 94 | return true; 95 | } 96 | return false; 97 | } 98 | TS_Point TouchControllerWS::getPoint() { 99 | TS_Point p = touchScreen->getPoint(); 100 | int x = (p.y - ax) * dx; 101 | int y = 320 - (p.x - ay) * dy; 102 | p.x = x; 103 | p.y = y; 104 | return p; 105 | } 106 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WundergroundAlerts.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2017 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | #define MAX_WEATHER_ALERTS 6 // The maximum number of concurrent weather alerts supported by the library 32 | 33 | typedef struct WGAlert { 34 | String activeAlerts; 35 | String activeAlertsMessage; 36 | bool activeAlertsMessageTrunc; 37 | String activeAlertsText; 38 | String activeAlertsStart; 39 | String activeAlertsEnd; 40 | String activeAlertsPhenomena; 41 | String activeAlertsSignificance; 42 | String activeAlertsAttribution; 43 | } WGAlert; 44 | 45 | class WundergroundAlerts: public JsonListener { 46 | private: 47 | String currentKey; 48 | String currentParent = ""; 49 | WGAlert *alerts; 50 | uint8_t maxAlerts; 51 | 52 | 53 | void doUpdate(WGAlert *alerts, uint8_t maxAlerts, String url); 54 | 55 | boolean isAlerts = false; 56 | boolean isAlertUS = false; 57 | boolean isAlertEU = false; 58 | 59 | int activeAlertsCnt; // Number of active alerts 60 | int currentAlert; // For indexing the current active alert 61 | 62 | 63 | public: 64 | WundergroundAlerts(); 65 | void updateAlerts(WGAlert *alert, uint8_t maxAlerts, String apiKey, String language, String country, String city); // Added by fowlerk, 18-Dec-2016 66 | void updateAlertsPWS(WGAlert *alert, uint8_t maxAlerts, String apiKey, String language, String country, String pws); 67 | int getActiveAlertsCnt(); 68 | 69 | virtual void whitespace(char c); 70 | 71 | virtual void startDocument(); 72 | 73 | virtual void key(String key); 74 | 75 | virtual void value(String value); 76 | 77 | virtual void endArray(); 78 | 79 | virtual void endObject(); 80 | 81 | virtual void endDocument(); 82 | 83 | virtual void startArray(); 84 | 85 | virtual void startObject(); 86 | }; 87 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/ThingspeakClient.cpp: -------------------------------------------------------------------------------- 1 | #include "ThingspeakClient.h" 2 | 3 | 4 | ThingspeakClient::ThingspeakClient() { 5 | 6 | } 7 | 8 | void ThingspeakClient::getLastChannelItem(String channelId, String readApiKey) { 9 | JsonStreamingParser parser; 10 | parser.setListener(this); 11 | WiFiClient client; 12 | 13 | // http://api.thingspeak.com/channels/CHANNEL_ID/feeds.json?results=2&api_key=API_KEY 14 | const char host[] = "api.thingspeak.com"; 15 | String url = "/channels/" + channelId +"/feeds.json?results=1&api_key=" + readApiKey; 16 | 17 | const int httpPort = 80; 18 | if (!client.connect(host, httpPort)) { 19 | Serial.println("connection failed"); 20 | return; 21 | } 22 | 23 | 24 | Serial.print("Requesting URL: "); 25 | Serial.println(url); 26 | 27 | // This will send the request to the server 28 | client.print(String("GET ") + url + " HTTP/1.1\r\n" + 29 | "Host: " + host + "\r\n" + 30 | "Connection: close\r\n\r\n"); 31 | 32 | int retryCounter = 0; 33 | while(!client.available()) { 34 | Serial.println("."); 35 | delay(1000); 36 | retryCounter++; 37 | if (retryCounter > 10) { 38 | return; 39 | } 40 | } 41 | 42 | int pos = 0; 43 | boolean isBody = false; 44 | char c; 45 | 46 | int size = 0; 47 | client.setNoDelay(false); 48 | while(client.connected()) { 49 | while((size = client.available()) > 0) { 50 | c = client.read(); 51 | if (c == '{' || c == '[') { 52 | isBody = true; 53 | } 54 | if (isBody) { 55 | parser.parse(c); 56 | } 57 | } 58 | } 59 | } 60 | 61 | void ThingspeakClient::whitespace(char c) { 62 | 63 | } 64 | 65 | void ThingspeakClient::startDocument() { 66 | 67 | } 68 | 69 | void ThingspeakClient::key(String key) { 70 | if (key == "channel") { 71 | isHeader = true; 72 | } else if (key == "feeds") { 73 | isHeader = false; 74 | } 75 | currentKey = key; 76 | } 77 | 78 | void ThingspeakClient::value(String value) { 79 | //Serial.println(currentKey +": " + value); 80 | 81 | for (int i = 1; i < 9; i++) { 82 | String fieldKey = "field" + String(i); 83 | 84 | if (currentKey == fieldKey) { 85 | if (isHeader) { 86 | fieldLabels[i-1] = value; 87 | } else { 88 | lastFields[i-1] = value; 89 | Serial.println(fieldKey + ": " + value); 90 | } 91 | 92 | } 93 | } 94 | 95 | 96 | } 97 | 98 | 99 | String ThingspeakClient::getFieldLabel(int index) { 100 | return fieldLabels[index]; 101 | } 102 | 103 | String ThingspeakClient::getFieldValue(int index) { 104 | return lastFields[index]; 105 | } 106 | 107 | String ThingspeakClient::getCreatedAt() { 108 | return createdAt; 109 | } 110 | 111 | void ThingspeakClient::endArray() { 112 | 113 | } 114 | 115 | void ThingspeakClient::endObject() { 116 | 117 | } 118 | 119 | void ThingspeakClient::endDocument() { 120 | 121 | } 122 | 123 | void ThingspeakClient::startArray() { 124 | 125 | } 126 | 127 | void ThingspeakClient::startObject() { 128 | 129 | } 130 | -------------------------------------------------------------------------------- /esp32-weather-station-color/settings.OLD: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | Copyright (c) 2015 by Daniel Eichhorn 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | The above copyright notice and this permission notice shall be included in all 10 | copies or substantial portions of the Software. 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | SOFTWARE. 18 | See more at http://blog.squix.ch 19 | */ 20 | 21 | #include 22 | 23 | // Setup 24 | #define WIFI_SSID "Home" 25 | #define WIFI_PASS "44332221111" 26 | 27 | const int UPDATE_INTERVAL_SECS = 15 * 60; // Update every 10 minutes 28 | const int SLEEP_INTERVAL_SECS = 0; // Going to Sleep after idle times, set 0 for dont sleep 29 | 30 | 31 | // Pins for the ILI9341 32 | #define TFT_DC 4 //D2 33 | #define TFT_CS 5 //D1 34 | #define TFT_LED 15 //D8 35 | 36 | #define HAVE_TOUCHPAD 37 | #define TOUCH_CS 0 //D3 38 | #define TOUCH_IRQ 2 //D4 39 | 40 | 41 | 42 | // Wunderground Settings 43 | // To check your settings first try them out in your browser: 44 | // http://api.wunderground.com/api/WUNDERGROUND_API_KEY/conditions/q/WUNDERGROUND_COUNTTRY/WUNDERGROUND_CITY.json 45 | // e.g. http://api.wunderground.com/api/808ba87ed77c4511/conditions/q/CH/Zurich.json 46 | // e.g. http://api.wunderground.com/api/808ba87ed77c4511/conditions/q/CA/SAN_FRANCISCO.json <- note that in the US you use the state instead of country code 47 | 48 | const String DISPLAYED_CITY_NAME = "Zabansk"; 49 | const String WUNDERGRROUND_API_KEY = "26523cc7cd6008f5"; 50 | const String WUNDERGRROUND_LANGUAGE = "RS"; 51 | const String WUNDERGROUND_COUNTRY = "Russia"; 52 | const String WUNDERGROUND_CITY = "Yekaterinburg"; 53 | 54 | #define UTC_OFFSET + 5 55 | struct dstRule StartRule = {"CEST", Last, Sun, Mar, 5, 0}; // Central European Summer Time = UTC/GMT +2 hours 56 | struct dstRule EndRule = {"CET", Last, Sun, Oct, 5, 0}; // Central European Time = UTC/GMT +1 hour 57 | 58 | // Settings for Boston 59 | // #define UTC_OFFSET -5 60 | // struct dstRule StartRule = {"EDT", Second, Sun, Mar, 2, 3600}; // Eastern Daylight time = UTC/GMT -4 hours 61 | // struct dstRule EndRule = {"EST", First, Sun, Nov, 1, 0}; // Eastern Standard time = UTC/GMT -5 hour 62 | 63 | // values in metric or imperial system? 64 | bool IS_METRIC = true; 65 | 66 | // Change for 12 Hour/ 24 hour style clock 67 | bool IS_STYLE_12HR = false; 68 | 69 | // change for different ntp (time servers) 70 | #define NTP_SERVERS "ru.pool.ntp.org", "1.ch.pool.ntp.org", "2.ch.pool.ntp.org" 71 | // #define NTP_SERVERS "us.pool.ntp.org", "time.nist.gov", "pool.ntp.org" 72 | 73 | /*************************** 74 | * End Settings 75 | **************************/ 76 | 77 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/README.md: -------------------------------------------------------------------------------- 1 | # Build 2 | 3 | * Stable: [![Build Status](https://api.travis-ci.org/squix78/esp8266-weather-station.svg?branch=master)](https://travis-ci.org/squix78/esp8266-weather-station) 4 | * Development: [![Build Status](https://api.travis-ci.org/squix78/esp8266-weather-station.svg?branch=development)](https://travis-ci.org/squix78/esp8266-weather-station) 5 | 6 | # esp8266-weather-station 7 | This code works best with the TTGO TM Music board. 8 | https://ae01.alicdn.com/kf/HTB1YbI1lMvD8KJjSsplq6yIEFXaU/Ttgo-2-4-PCM5102A-SD-ESP32-WiFi-Bluetooth.jpg 9 | https://ru.aliexpress.com/item/Ttgo-2-4-PCM5102A-SD-ESP32-WiFi-Bluetooth/32848882218.html?spm=a2g0s.9042311.0.0.BYS264 10 | based on ESP32. 11 | 12 | 13 | ## Arduino IDE 14 | 15 | Make sure you use a version of the Arduino IDE which is supported by the ESP8266 platform. You can find it here: https://www.arduino.cc/en/Main/OldSoftwareReleases 16 | 17 | ## Setup Arduino IDE 18 | 19 | * Install the following libraries with your Arduino Library Manager in Sketch > Include Library > Manage Libraries... 20 | 21 | * ESP8266 Weather Station 22 | * Json Streaming Parser (by Daniel Eichhorn) 23 | * ESP8266 Oled Driver for SSD1306 display (by me as well). **Make sure that you use Version 3.0.0 or bigger!** 24 | * Go to http://wunderground.com, create an account and get an API Key 25 | * In the Arduino IDE go to File > Examples > ESP8266 Weather Station 26 | * Enter the Wunderground API Key 27 | * Enter your Wifi credentials 28 | * Adjust the location according to Wunderground API, e.g. Yekaterinburg, RS 29 | * Adjust UTC offset 30 | 31 | ## Setup for PlatformIO 32 | 33 | If you are using the PlatformIO environment for building 34 | * choose one of the available IDE integration or the Atom based IDE 35 | * install libraries 561, 562 and 563 with "platformio lib install" 36 | * adapt the WeatherStationDemo.ino file to your needs (see details above) 37 | 38 | 39 | ## Upgrade 40 | 41 | The ESP8266 Oled Library changed a lot with the latest release of version 3.0.0. We fixed many bugs and improved performance and changed the API a little bit. This means that you might have to adapt your Weather Station Code if you created it using the older 2.x.x version of the library. Either compare your code to the updated WeatherStationDemo or read through the Upgrade Guide here: [Upgrade Guide](https://github.com/squix78/esp8266-oled-ssd1306/blob/master/UPGRADE-3.0.md) 42 | 43 | ## Available Modules 44 | * **TimeClient**: simple class which uses the header date and time to set the clock 45 | * **NTPClient**: a NTP based time class written by Fabrice Weinberg 46 | * **WundergroundClient**: fetches current weather and forecast from wunderground.com 47 | * **ThingspeakClient**: fetches data from Thingspeak which you might have collected with another sensor node and posted there. I use this to measure outdoor temperature and humidity and show it on the WeatherStation with a ClimateNode: https://shop.squix.ch/index.php/esp8266/climatenode.html 48 | 49 | ## Why Weather Station as a library? 50 | 51 | I realized that more and more the Weather Station was becoming a general framework for displaying data over WiFi to one of these pretty displays. But everyone would have different ways or sources for data and having the important part of the library would rather be the classes which fetch the data then the main class. 52 | So if you write data fetchers which might be of interest to others please contact me to integrate them here or offer your code as extension library yourself and call it something like esp8266-weather-station-. 53 | I will gladly list it here as third party library... 54 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WundergroundAstronomyDemo/WundergroundAstronomyDemo.ino: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2017 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at https://blog.squix.org 24 | */ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include "WundergroundAstronomy.h" 31 | 32 | /** 33 | * Wunderground Settings 34 | */ 35 | const String WUNDERGRROUND_API_KEY = ""; 36 | const String WUNDERGR_UND_STATE_OR_COUNTRY = "CH"; 37 | const String WUNDERGR_UND_CITY = "ZURICH"; 38 | const String WUNDERGRROUND_LANGUAGE = "EN"; 39 | const boolean USE_PM = false; 40 | 41 | // initiate the WundergoundClient 42 | WundergroundAstronomy wunderground(USE_PM); 43 | 44 | 45 | /** 46 | * WiFi Settings 47 | */ 48 | const char* ESP_HOST_NAME = "esp-" + ESP.getFlashChipId(); 49 | const char* WIFI_SSID = "yourssid"; 50 | const char* WIFI_PASSWORD = "yourpassw0rd"; 51 | 52 | // initiate the WifiClient 53 | WiFiClient wifiClient; 54 | 55 | 56 | 57 | /** 58 | * Helping funtions 59 | */ 60 | void connectWifi() { 61 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 62 | Serial.print("Connecting to "); 63 | Serial.println(WIFI_SSID); 64 | while (WiFi.status() != WL_CONNECTED) { 65 | delay(500); 66 | Serial.print("."); 67 | } 68 | Serial.println(""); 69 | Serial.println("WiFi connected!"); 70 | Serial.println(WiFi.localIP()); 71 | Serial.println(); 72 | } 73 | 74 | 75 | /** 76 | * SETUP 77 | */ 78 | void setup() { 79 | 80 | Serial.begin(115200); 81 | delay(500); 82 | connectWifi(); 83 | 84 | Serial.println(); 85 | Serial.println("\n\nNext Loop-Step: " + String(millis()) + ":"); 86 | WGAstronomy astronomy; 87 | wunderground.updateAstronomy(&astronomy, WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGR_UND_STATE_OR_COUNTRY, WUNDERGR_UND_CITY); 88 | 89 | Serial.println("moonPctIlum: " + astronomy.moonPctIlum); 90 | Serial.println("moonAge: " + astronomy.moonAge); 91 | Serial.println("moonPhase: " + astronomy.moonPhase); 92 | Serial.println("sunriseTime: " + astronomy.sunriseTime); 93 | Serial.println("sunsetTime: " + astronomy.sunsetTime); 94 | Serial.println("moonriseTime: " + astronomy.moonriseTime); 95 | Serial.println("moonsetTime: " + astronomy.moonsetTime); 96 | 97 | 98 | Serial.println(); 99 | Serial.println("---------------------------------------------------/\n"); 100 | 101 | } 102 | 103 | 104 | /** 105 | * LOOP 106 | */ 107 | void loop() { 108 | 109 | } 110 | -------------------------------------------------------------------------------- /esp32-weather-station-color/settings.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | Copyright (c) 2015 by Daniel Eichhorn 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | The above copyright notice and this permission notice shall be included in all 10 | copies or substantial portions of the Software. 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | SOFTWARE. 18 | See more at http://blog.squix.ch 19 | */ 20 | 21 | #include 22 | 23 | // Setup 24 | #define WIFI_SSID "YourSSID" 25 | #define WIFI_PASS "YourPASS" 26 | 27 | const int UPDATE_INTERVAL_SECS = 15 * 60; // Update every 15 minutes 28 | const int SLEEP_INTERVAL_SECS = 0; // Going to Sleep after idle times, set 0 for dont sleep 29 | 30 | #define TTGO 31 | 32 | #ifndef TTGO 33 | // Pins for the ILI9341 34 | #define TFT_DC 4 //D2 35 | #define TFT_CS 5 //D1 36 | #define TFT_LED 15 //D8 37 | #define TFT_RST 2 //D8 38 | 39 | #define HAVE_TOUCHPAD 40 | 41 | #else 42 | 43 | #define TFT_DC 16 //D2 44 | #define TFT_CS 5 //D1 45 | #define TFT_LED 15 //D8 46 | #define TFT_RST 17 //D8 47 | 48 | #endif 49 | 50 | #define TOUCH_CS 0 //D3 51 | #define TOUCH_IRQ 2 //D4 52 | 53 | 54 | // Wunderground Settings 55 | // To check your settings first try them out in your browser: 56 | // http://api.wunderground.com/api/WUNDERGROUND_API_KEY/conditions/q/WUNDERGROUND_COUNTTRY/WUNDERGROUND_CITY.json 57 | // e.g. http://api.wunderground.com/api/808ba87ed77c4511/conditions/q/CH/Zurich.json 58 | // e.g. http://api.wunderground.com/api/808ba87ed77c4511/conditions/q/CA/SAN_FRANCISCO.json <- note that in the US you use the state instead of country code 59 | 60 | const String DISPLAYED_CITY_NAME = "Yekaterinburg"; 61 | const String WUNDERGRROUND_API_KEY = "Your_API_Key"; 62 | const String WUNDERGRROUND_LANGUAGE = "RS"; 63 | const String WUNDERGROUND_COUNTRY = "Russia"; 64 | const String WUNDERGROUND_CITY = "Yekaterinburg"; 65 | 66 | #define UTC_OFFSET + 5 67 | struct dstRule StartRule = {"CEST", Last, Sun, Mar, 0, 0}; // Central European Summer Time = UTC/GMT +2 hours 68 | struct dstRule EndRule = {"CET", Last, Sun, Oct, 0, 0}; // Central European Time = UTC/GMT +1 hour 69 | 70 | // Settings for Boston 71 | // #define UTC_OFFSET -5 72 | // struct dstRule StartRule = {"EDT", Second, Sun, Mar, 2, 3600}; // Eastern Daylight time = UTC/GMT -4 hours 73 | // struct dstRule EndRule = {"EST", First, Sun, Nov, 1, 0}; // Eastern Standard time = UTC/GMT -5 hour 74 | 75 | // values in metric or imperial system? 76 | bool IS_METRIC = true; 77 | 78 | // Change for 12 Hour/ 24 hour style clock 79 | bool IS_STYLE_12HR = false; 80 | 81 | // change for different ntp (time servers) 82 | #define NTP_SERVERS "ru.pool.ntp.org", "1.ch.pool.ntp.org", "2.ch.pool.ntp.org" 83 | // #define NTP_SERVERS "us.pool.ntp.org", "time.nist.gov", "pool.ntp.org" 84 | 85 | /*************************** 86 | * End Settings 87 | **************************/ 88 | 89 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WundergroundForecastDemo/WundergroundForecastDemo.ino: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2017 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at https://blog.squix.org 24 | */ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include "WundergroundForecast.h" 31 | 32 | /** 33 | * Wunderground Settings 34 | */ 35 | const String WUNDERGRROUND_API_KEY = ""; 36 | const String WUNDERGR_UND_STATE_OR_COUNTRY = "CH"; 37 | const String WUNDERGR_UND_CITY = "ZURICH"; 38 | const String WUNDERGRROUND_LANGUAGE = "EN"; 39 | const boolean IS_METRIC = true; 40 | const boolean USE_PM = false; 41 | 42 | // initiate the WundergoundClient 43 | WundergroundForecast wunderground(IS_METRIC); 44 | 45 | 46 | /** 47 | * WiFi Settings 48 | */ 49 | const char* ESP_HOST_NAME = "esp-" + ESP.getFlashChipId(); 50 | const char* WIFI_SSID = "yourssid"; 51 | const char* WIFI_PASSWORD = "yourpassw0rd"; 52 | 53 | // initiate the WifiClient 54 | WiFiClient wifiClient; 55 | 56 | 57 | 58 | /** 59 | * Helping funtions 60 | */ 61 | void connectWifi() { 62 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 63 | Serial.print("Connecting to "); 64 | Serial.println(WIFI_SSID); 65 | while (WiFi.status() != WL_CONNECTED) { 66 | delay(500); 67 | Serial.print("."); 68 | } 69 | Serial.println(""); 70 | Serial.println("WiFi connected!"); 71 | Serial.println(WiFi.localIP()); 72 | Serial.println(); 73 | } 74 | 75 | 76 | /** 77 | * SETUP 78 | */ 79 | void setup() { 80 | Serial.begin(115200); 81 | delay(500); 82 | connectWifi(); 83 | 84 | Serial.println(); 85 | Serial.println("\n\nNext Loop-Step: " + String(millis()) + ":"); 86 | uint8_t maxForecasts = 10; 87 | WGForecast forecasts[maxForecasts]; 88 | wunderground.updateForecast(forecasts, maxForecasts, WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGR_UND_STATE_OR_COUNTRY, WUNDERGR_UND_CITY); 89 | 90 | for (int i = 0; i < maxForecasts; i++) { 91 | Serial.println("------------------------------------"); 92 | Serial.println("getForecastIcon: " + forecasts[i].forecastIcon); 93 | Serial.println("getForecastTitle: " + forecasts[i].forecastTitle); 94 | Serial.println("getForecastLowTemp: " + forecasts[i].forecastLowTemp); 95 | Serial.println("getForecastHighTemp: " + forecasts[i].forecastHighTemp); 96 | Serial.println("getForecastDay: " + forecasts[i].forecastDay); 97 | Serial.println("getForecastMonth: " + forecasts[i].forecastMonth); 98 | Serial.println("getForecastText: " + forecasts[i].forecastText); 99 | Serial.println("getPoP: " + forecasts[i].PoP); 100 | 101 | } 102 | 103 | 104 | Serial.println(); 105 | Serial.println("---------------------------------------------------/\n"); 106 | 107 | } 108 | 109 | 110 | /** 111 | * LOOP 112 | */ 113 | void loop() { 114 | 115 | } 116 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WundergroundAlertsDemo/WundergroundAlertsDemo.ino: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2017 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at https://blog.squix.org 24 | */ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include "WundergroundAlerts.h" 31 | 32 | /** 33 | * Wunderground Settings 34 | */ 35 | const String WUNDERGRROUND_API_KEY = ""; 36 | const String WUNDERGR_UND_STATE_OR_COUNTRY = "CH"; 37 | const String WUNDERGR_UND_CITY = "ZURICH"; 38 | const String WUNDERGRROUND_LANGUAGE = "EN"; 39 | const boolean IS_METRIC = true; 40 | const boolean USE_PM = false; 41 | 42 | // initiate the WundergoundClient 43 | WundergroundAlerts wunderground; 44 | 45 | 46 | /** 47 | * WiFi Settings 48 | */ 49 | const char* ESP_HOST_NAME = "esp-" + ESP.getFlashChipId(); 50 | const char* WIFI_SSID = "yourssid"; 51 | const char* WIFI_PASSWORD = "yourpassw0rd"; 52 | 53 | // initiate the WifiClient 54 | WiFiClient wifiClient; 55 | 56 | 57 | 58 | /** 59 | * Helping funtions 60 | */ 61 | void connectWifi() { 62 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 63 | Serial.print("Connecting to "); 64 | Serial.println(WIFI_SSID); 65 | while (WiFi.status() != WL_CONNECTED) { 66 | delay(500); 67 | Serial.print("."); 68 | } 69 | Serial.println(""); 70 | Serial.println("WiFi connected!"); 71 | Serial.println(WiFi.localIP()); 72 | Serial.println(); 73 | } 74 | 75 | 76 | /** 77 | * SETUP 78 | */ 79 | void setup() { 80 | Serial.begin(115200); 81 | delay(500); 82 | connectWifi(); 83 | 84 | Serial.println(); 85 | Serial.println("\n\nNext Loop-Step: " + String(millis()) + ":"); 86 | uint8_t maxAlerts = 3; 87 | WGAlert alerts[maxAlerts]; 88 | wunderground.updateAlerts(alerts, maxAlerts, WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGR_UND_STATE_OR_COUNTRY, WUNDERGR_UND_CITY); 89 | 90 | for (int i = 0; i < wunderground.getActiveAlertsCnt(); i++) { 91 | Serial.println("------------------------------------"); 92 | Serial.println("activeAlerts: " + alerts[i].activeAlerts); 93 | Serial.println("activeAlertsMessage: " + alerts[i].activeAlertsMessage); 94 | Serial.println("activeAlertsMessageTrunc: " + alerts[i].activeAlertsMessageTrunc); 95 | Serial.println("activeAlertsText: " + alerts[i].activeAlertsText); 96 | Serial.println("activeAlertsStart: " + alerts[i].activeAlertsStart); 97 | Serial.println("activeAlertsEnd: " + alerts[i].activeAlertsEnd); 98 | Serial.println("activeAlertsPhenomena: " + alerts[i].activeAlertsPhenomena); 99 | Serial.println("activeAlertsSignificance: " + alerts[i].activeAlertsSignificance); 100 | Serial.println("activeAlertsAttribution: " + alerts[i].activeAlertsAttribution); 101 | } 102 | 103 | 104 | Serial.println(); 105 | Serial.println("---------------------------------------------------/\n"); 106 | 107 | } 108 | 109 | 110 | /** 111 | * LOOP 112 | */ 113 | void loop() { 114 | 115 | } 116 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WundergroundHourlyDemo/WundergroundHourlyDemo.ino: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2017 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at https://blog.squix.org 24 | */ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include "WundergroundHourly.h" 31 | 32 | /** 33 | * Wunderground Settings 34 | */ 35 | const String WUNDERGRROUND_API_KEY = "API_KEY"; 36 | const String WUNDERGR_UND_STATE_OR_COUNTRY = "CH"; 37 | const String WUNDERGR_UND_CITY = "ZURICH"; 38 | const String WUNDERGRROUND_LANGUAGE = "EN"; 39 | const boolean IS_METRIC = true; 40 | const boolean IS_24HOURS = false; 41 | 42 | // initiate the WundergoundClient 43 | WundergroundHourly wunderground(IS_METRIC, IS_24HOURS); 44 | 45 | 46 | /** 47 | * WiFi Settings 48 | */ 49 | const char* ESP_HOST_NAME = "esp-" + ESP.getFlashChipId(); 50 | const char* WIFI_SSID = "yourssid"; 51 | const char* WIFI_PASSWORD = "yourpassw0rd"; 52 | 53 | // initiate the WifiClient 54 | WiFiClient wifiClient; 55 | 56 | 57 | 58 | /** 59 | * Helping funtions 60 | */ 61 | void connectWifi() { 62 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 63 | Serial.print("Connecting to "); 64 | Serial.println(WIFI_SSID); 65 | while (WiFi.status() != WL_CONNECTED) { 66 | delay(500); 67 | Serial.print("."); 68 | } 69 | Serial.println(""); 70 | Serial.println("WiFi connected!"); 71 | Serial.println(WiFi.localIP()); 72 | Serial.println(); 73 | } 74 | 75 | 76 | /** 77 | * SETUP 78 | */ 79 | void setup() { 80 | Serial.begin(115200); 81 | delay(500); 82 | connectWifi(); 83 | 84 | Serial.println(); 85 | Serial.println("\n\nNext Loop-Step: " + String(millis()) + ":"); 86 | 87 | WGHourly hourlies[24]; 88 | wunderground.setMetric(true); 89 | wunderground.set24Hours(true); 90 | wunderground.updateHourly(hourlies, WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGR_UND_STATE_OR_COUNTRY, WUNDERGR_UND_CITY); 91 | for (int i = 0; i < 24; i++) { 92 | Serial.println("------------------------------------"); 93 | Serial.println("icon: " + hourlies[i].icon); 94 | Serial.println("title: " + hourlies[i].title); 95 | Serial.println("temp: " + hourlies[i].temp); 96 | Serial.println("hour: " + hourlies[i].hour); 97 | Serial.println("PoP: " + hourlies[i].PoP); 98 | } 99 | wunderground.setMetric(false); 100 | wunderground.set24Hours(false); 101 | wunderground.updateHourly(hourlies, WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGR_UND_STATE_OR_COUNTRY, WUNDERGR_UND_CITY); 102 | for (int i = 0; i < 24; i++) { 103 | Serial.println("------------------------------------"); 104 | Serial.println("icon: " + hourlies[i].icon); 105 | Serial.println("title: " + hourlies[i].title); 106 | Serial.println("temp: " + hourlies[i].temp); 107 | Serial.println("hour: " + hourlies[i].hour); 108 | Serial.println("PoP: " + hourlies[i].PoP); 109 | } 110 | 111 | 112 | Serial.println(); 113 | Serial.println("---------------------------------------------------/\n"); 114 | 115 | } 116 | 117 | 118 | /** 119 | * LOOP 120 | */ 121 | void loop() { 122 | 123 | } 124 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WundergroundConditionsDemo/WundergroundConditionsDemo.ino: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2017 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at https://blog.squix.org 24 | */ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include "WundergroundConditions.h" 31 | 32 | /** 33 | * Wunderground Settings 34 | */ 35 | const String WUNDERGRROUND_API_KEY = ""; 36 | const boolean IS_METRIC = true; 37 | const boolean USE_PM = false; 38 | // to retrieve the ZMW-Code use 39 | // http://api.wunderground.com/api//conditions/q//.json 40 | // for example and grab for the zmw ... 41 | const String WUNDERGROUND_ZMW_CODE = "00000.215.10348"; // Braunschweig-Flughafen -> EDVE 42 | const String WUNDERGRROUND_LANGUAGE = "DE"; 43 | 44 | // initiate the WundergoundClient 45 | WundergroundConditions wunderground(IS_METRIC); 46 | 47 | 48 | /** 49 | * WiFi Settings 50 | */ 51 | const char* ESP_HOST_NAME = "esp-" + ESP.getFlashChipId(); 52 | const char* WIFI_SSID = "yourssid"; 53 | const char* WIFI_PASSWORD = "yourpassw0rd"; 54 | 55 | // initiate the WifiClient 56 | WiFiClient wifiClient; 57 | 58 | 59 | 60 | /** 61 | * Helping funtions 62 | */ 63 | void connectWifi() { 64 | WiFi.hostname(ESP_HOST_NAME); 65 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 66 | delay(20); 67 | Serial.print("Connecting to "); 68 | Serial.println(WIFI_SSID); 69 | while (WiFi.status() != WL_CONNECTED) { 70 | delay(500); 71 | Serial.print("."); 72 | } 73 | Serial.println(""); 74 | Serial.println("WiFi connected!"); 75 | Serial.println(WiFi.localIP()); 76 | Serial.println(); 77 | } 78 | 79 | 80 | /** 81 | * SETUP 82 | */ 83 | void setup() { 84 | 85 | Serial.begin(115200); 86 | 87 | connectWifi(); 88 | 89 | Serial.println(); 90 | Serial.println("\n\nNext Loop-Step: " + String(millis()) + ":"); 91 | WGConditions conditions; 92 | wunderground.updateConditions(&conditions, WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_ZMW_CODE); 93 | 94 | Serial.println("wundergroundDate: " + conditions.date); 95 | 96 | Serial.println("wundergroundWindSpeed: " + conditions.windSpeed); 97 | Serial.println("wundergroundWindDir: " + conditions.windDir); 98 | 99 | Serial.println("wundergroundCurrentTemp: " + conditions.currentTemp); 100 | Serial.println("wundergroundTodayIcon: " + conditions.weatherIcon); 101 | Serial.println("wundergroundTodayIconText: " + conditions.weatherText); 102 | Serial.println("wundergroundMeteoconIcon: " + wunderground.getMeteoconIcon(conditions.weatherIcon)); 103 | Serial.println("wundergroundWeatherText: " + conditions.weatherText); 104 | Serial.println("wundergroundHumidity: " + conditions.humidity); 105 | Serial.println("wundergroundPressure: " + conditions.pressure); 106 | Serial.println("wundergroundDewPoint: " + conditions.dewPoint); 107 | Serial.println("wundergroundPrecipitationToday: " + conditions.precipitationToday); 108 | 109 | Serial.println(); 110 | Serial.println("---------------------------------------------------/\n"); 111 | 112 | } 113 | 114 | 115 | /** 116 | * LOOP 117 | */ 118 | void loop() { 119 | 120 | } 121 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/TimeClient.cpp: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | #include "TimeClient.h" 27 | 28 | TimeClient::TimeClient(float utcOffset) { 29 | myUtcOffset = utcOffset; 30 | } 31 | 32 | void TimeClient::updateTime() { 33 | WiFiClient client; 34 | const int httpPort = 80; 35 | if (!client.connect("www.google.com", httpPort)) { 36 | Serial.println("connection failed"); 37 | return; 38 | } 39 | 40 | // This will send the request to the server 41 | client.print(String("GET / HTTP/1.1\r\n") + 42 | String("Host: www.google.com\r\n") + 43 | String("Connection: close\r\n\r\n")); 44 | int repeatCounter = 0; 45 | while(!client.available() && repeatCounter < 10) { 46 | delay(1000); 47 | Serial.println("."); 48 | repeatCounter++; 49 | } 50 | 51 | String line; 52 | 53 | int size = 0; 54 | client.setNoDelay(false); 55 | while(client.connected()) { 56 | while((size = client.available()) > 0) { 57 | line = client.readStringUntil('\n'); 58 | line.toUpperCase(); 59 | // example: 60 | // date: Thu, 19 Nov 2015 20:25:40 GMT 61 | if (line.startsWith("DATE: ")) { 62 | Serial.println(line.substring(23, 25) + ":" + line.substring(26, 28) + ":" +line.substring(29, 31)); 63 | int parsedHours = line.substring(23, 25).toInt(); 64 | int parsedMinutes = line.substring(26, 28).toInt(); 65 | int parsedSeconds = line.substring(29, 31).toInt(); 66 | Serial.println(String(parsedHours) + ":" + String(parsedMinutes) + ":" + String(parsedSeconds)); 67 | 68 | localEpoc = (parsedHours * 60 * 60 + parsedMinutes * 60 + parsedSeconds); 69 | Serial.println(localEpoc); 70 | localMillisAtUpdate = millis(); 71 | } 72 | } 73 | } 74 | 75 | } 76 | 77 | String TimeClient::getHours() { 78 | if (localEpoc == 0) { 79 | return "--"; 80 | } 81 | int hours = ((getCurrentEpochWithUtcOffset() % 86400L) / 3600) % 24; 82 | if (hours < 10) { 83 | return "0" + String(hours); 84 | } 85 | return String(hours); // print the hour (86400 equals secs per day) 86 | 87 | } 88 | String TimeClient::getMinutes() { 89 | if (localEpoc == 0) { 90 | return "--"; 91 | } 92 | int minutes = ((getCurrentEpochWithUtcOffset() % 3600) / 60); 93 | if (minutes < 10 ) { 94 | // In the first 10 minutes of each hour, we'll want a leading '0' 95 | return "0" + String(minutes); 96 | } 97 | return String(minutes); 98 | } 99 | String TimeClient::getSeconds() { 100 | if (localEpoc == 0) { 101 | return "--"; 102 | } 103 | int seconds = getCurrentEpochWithUtcOffset() % 60; 104 | if ( seconds < 10 ) { 105 | // In the first 10 seconds of each minute, we'll want a leading '0' 106 | return "0" + String(seconds); 107 | } 108 | return String(seconds); 109 | } 110 | 111 | String TimeClient::getFormattedTime() { 112 | return getHours() + ":" + getMinutes() + ":" + getSeconds(); 113 | } 114 | 115 | long TimeClient::getCurrentEpoch() { 116 | return localEpoc + ((millis() - localMillisAtUpdate) / 1000); 117 | } 118 | 119 | long TimeClient::getCurrentEpochWithUtcOffset() { 120 | return round(getCurrentEpoch() + 3600 * myUtcOffset + 86400L) % 86400L; 121 | } 122 | 123 | 124 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/README.md: -------------------------------------------------------------------------------- 1 | # WeatherStationDemoExtendedDST 2 | 3 | Daylight Saving Time and other customizations of the original ESP8266 OLED Weather Station. 4 | Uses SSD1306 128x64 OLED display with with either SPI or I2C interface 5 | 6 | | New Splash Screen | DHT22 Update | 7 | |:-----------------:|:------------:| 8 | | ![cover](https://github.com/neptune2/esp8266-weather-station-oled-DST/raw/master/resources/splash.jpg) | ![DHT22 Update](https://github.com/neptune2/esp8266-weather-station-oled-DST/raw/master/resources/DHT22_update.jpg) | 9 | 10 | | Zurich Standard Time | Boston Daylight Saving Time | Conditions Screen | 11 | |:--------------------:|:---------------------------:|:-----------------:| 12 | | ![Zurich CET](https://github.com/neptune2/esp8266-weather-station-oled-DST/raw/master/resources/Zurich_CET.jpg) | ![Boston EDT](https://github.com/neptune2/esp8266-weather-station-oled-DST/raw/master/resources/Boston_EDT.jpg) | ![Conditions](https://github.com/neptune2/esp8266-weather-station-oled-DST/raw/master/resources/conditions.jpg) | 13 | 14 | | DHT Sensor | Thingspeak Sensor | 1 to 3 Day Forecast | 4 to 6 Day Forecast | 15 | |:----------:|:-----------------:|:-------------------:|:-------------------:| 16 | | ![DHT Sensor](https://github.com/neptune2/esp8266-weather-station-oled-DST/raw/master/resources/DHT22_sensor.jpg) | ![ThingSpeak Sensor](https://github.com/neptune2/esp8266-weather-station-oled-DST/raw/master/resources/thingspeak.jpg) | ![DHT Sensor](https://github.com/neptune2/esp8266-weather-station-oled-DST/raw/master/resources/1-3_day_forecast.jpg) | ![ThingSpeak Sensor](https://github.com/neptune2/esp8266-weather-station-oled-DST/raw/master/resources/4-6_day_forecast.jpg) | 17 | 18 | ## Specific customizations include: 19 | 20 | * Added Wifi Splash screen and credit to Squix78 21 | * Modified progress bar to a thicker and symmetrical shape 22 | * Replaced TimeClient with built-in lwip sntp client (no need for external ntp client library) 23 | * Added Daylight Saving Time Auto adjuster with DST rules using simpleDSTadjust library 24 | * https://github.com/neptune2/simpleDSTadjust 25 | * Added Locale Setting examples for Boston, Zurich and Sydney 26 | * Selectable NTP servers for each locale 27 | * DST rules and timezone settings customizable for each locale 28 | * See https://www.timeanddate.com/time/change/ for DST rules 29 | * Added AM/PM or 24-hour option for each locale 30 | * Added metric settings for each locale 31 | * Changed Clock screen to 7-segment font from http://www.keshikan.net/fonts-e.html 32 | * Added Forecast screen for days 4-6 (requires 1.1.3 or later version of esp8266_Weather_Station library) 33 | * Added support for DHT22, DHT21 and DHT11 Indoor Temperature and Humidity Sensors 34 | * Fixed bug preventing display.flipScreenVertically() from working 35 | * Slight adjustments to overlay 36 | * Moved user settings into settings.h 37 | * Added #defines in settings.h to make it easier to select SPI or I2C interface for OLED in settings.h 38 | 39 | 40 | ## Hardware Requirements 41 | 42 | This code is made for an 128x64 SSD1603 OLED display with code running on an ESP8266. 43 | Either the SPI or I2C version can be used. 44 | You can buy the original Squix78 Weather Station Kit here: 45 | [Squix Shop](https://shop.squix.ch/index.php/esp8266.html) or here: [US Amazon store](https://www.amazon.com/gp/product/B01KE7BA3O) 46 | 47 | ## Software Requirements/ Libraries 48 | 49 | * [Arduino IDE with ESP8266 platform installed](https://github.com/esp8266/Arduino) 50 | * [Weather Station Library](https://github.com/squix78/esp8266-weather-station) or through Library Manager 51 | * [ESP8266 OLED SSD1306 Library](https://github.com/squix78/esp8266-oled-ssd1306) 52 | * [WifiManager Library](https://github.com/tzapu/WiFiManager) 53 | 54 | ### Additional required library for automatic Daylight Saving Time adjust 55 | * [simpleDSTadjust Library](https://github.com/neptune2/simpleDSTadjust) 56 | 57 | You also need to get an API key for the Wunderground data: https://www.wunderground.com/ 58 | 59 | ## Wemos D1R2 Wiring 60 | ![Wemos D1R2 and DHT22 sensor](https://github.com/neptune2/esp8266-weather-station-oled-DST/raw/master/resources/cover.jpg) 61 | 62 | See code for pin configurations 63 | 64 | | SSD1306 SPI | Wemos D1R2 | 65 | | ----------- |:----------:| 66 | | CS | D8 | 67 | | DC | D2 | 68 | | RST | D0 | 69 | | D1 | D7 | 70 | | D0 | D5 | 71 | | GND | GND | 72 | | VCC | 3V3 | 73 | 74 | | DHT22 | Wemos D1R2 | 75 | | ----- |:----------:| 76 | | DATA | D4 | 77 | | GND | GND | 78 | | VCC | 3V3 | 79 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/NTPClient.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * Copyright (c) 2015 by Fabrice Weinberg 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | #include "NTPClient.h" 23 | 24 | NTPClient::NTPClient(int timeOffset) { 25 | this->_timeOffset = timeOffset; 26 | } 27 | 28 | NTPClient::NTPClient(const char* poolServerName) { 29 | this->_poolServerName = poolServerName; 30 | } 31 | 32 | NTPClient::NTPClient(const char* poolServerName, int timeOffset) { 33 | this->_timeOffset = timeOffset; 34 | this->_poolServerName = poolServerName; 35 | } 36 | 37 | NTPClient::NTPClient(const char* poolServerName, int timeOffset, int updateInterval) { 38 | this->_timeOffset = timeOffset; 39 | this->_poolServerName = poolServerName; 40 | this->_updateInterval = updateInterval; 41 | } 42 | 43 | void NTPClient::begin() { 44 | #ifdef DEBUG_NTPClient 45 | Serial.println("Begin NTPClient"); 46 | Serial.print("Start udp connection on port: "); 47 | Serial.println(this->_port); 48 | #endif 49 | this->_udp.begin(this->_port); 50 | this->forceUpdate(); 51 | } 52 | 53 | void NTPClient::forceUpdate() { 54 | #ifdef DEBUG_NTPClient 55 | Serial.println("Update from NTP Server"); 56 | #endif 57 | 58 | IPAddress address; 59 | WiFi.hostByName(this->_poolServerName, address); 60 | 61 | this->sendNTPPacket(address); 62 | 63 | // Wait till data is there or timeout... 64 | byte timeout = 0; 65 | int cb = 0; 66 | do { 67 | delay ( 10 ); 68 | cb = this->_udp.parsePacket(); 69 | if (timeout > 100) return; // timeout after 1000 ms 70 | timeout++; 71 | } while (cb == 0); 72 | 73 | this->_lastUpdate = millis() - (10 * (timeout + 1)); // Account for delay in reading the time 74 | 75 | this->_udp.read(this->_packetBuffer, NTP_PACKET_SIZE); 76 | 77 | unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]); 78 | unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]); 79 | // combine the four bytes (two words) into a long integer 80 | // this is NTP time (seconds since Jan 1 1900): 81 | unsigned long secsSince1900 = highWord << 16 | lowWord; 82 | 83 | this->_currentEpoc = secsSince1900 - SEVENZYYEARS; 84 | } 85 | 86 | void NTPClient::update() { 87 | unsigned long runtime = millis(); 88 | if (runtime - this->_lastUpdate >= this->_updateInterval && this->_updateInterval != 0) { 89 | this->forceUpdate(); 90 | } 91 | } 92 | 93 | unsigned long NTPClient::getRawTime() { 94 | return this->_timeOffset + // User offset 95 | this->_currentEpoc + // Epoc returned by the NTP server 96 | ((millis() - this->_lastUpdate) / 1000); // Time since last update 97 | } 98 | 99 | String NTPClient::getHours() { 100 | return String((this->getRawTime() % 86400L) / 3600); 101 | } 102 | String NTPClient::getMinutes() { 103 | return String((this->getRawTime() % 3600) / 60); 104 | } 105 | 106 | String NTPClient::getSeconds() { 107 | return String(this->getRawTime() % 60); 108 | } 109 | 110 | String NTPClient::getFormattedTime() { 111 | unsigned long rawTime = this->getRawTime(); 112 | unsigned long hours = (rawTime % 86400L) / 3600; 113 | String hoursStr = hours < 10 ? "0" + String(hours) : String(hours); 114 | 115 | unsigned long minutes = (rawTime % 3600) / 60; 116 | String minuteStr = minutes < 10 ? "0" + String(minutes) : String(minutes); 117 | 118 | unsigned long seconds = rawTime % 60; 119 | String secondStr = seconds < 10 ? "0" + String(seconds) : String(seconds); 120 | 121 | return hoursStr + ":" + minuteStr + ":" + secondStr; 122 | } 123 | 124 | void NTPClient::sendNTPPacket(IPAddress ip) { 125 | // set all bytes in the buffer to 0 126 | memset(this->_packetBuffer, 0, NTP_PACKET_SIZE); 127 | // Initialize values needed to form NTP request 128 | // (see URL above for details on the packets) 129 | this->_packetBuffer[0] = 0b11100011; // LI, Version, Mode 130 | this->_packetBuffer[1] = 0; // Stratum, or type of clock 131 | this->_packetBuffer[2] = 6; // Polling Interval 132 | this->_packetBuffer[3] = 0xEC; // Peer Clock Precision 133 | // 8 bytes of zero for Root Delay & Root Dispersion 134 | this->_packetBuffer[12] = 49; 135 | this->_packetBuffer[13] = 0x4E; 136 | this->_packetBuffer[14] = 49; 137 | this->_packetBuffer[15] = 52; 138 | 139 | // all NTP fields have been given values, now 140 | // you can send a packet requesting a timestamp: 141 | this->_udp.beginPacket(ip, 123); //NTP requests are to port 123 142 | this->_udp.write(this->_packetBuffer, NTP_PACKET_SIZE); 143 | this->_udp.endPacket(); 144 | } 145 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/PlaneSpotterDemo/AdsbExchangeClient.cpp: -------------------------------------------------------------------------------- 1 | #include "AdsbExchangeClient.h" 2 | 3 | 4 | AdsbExchangeClient::AdsbExchangeClient() { 5 | 6 | } 7 | 8 | void AdsbExchangeClient::updateVisibleAircraft(String searchQuery) { 9 | JsonStreamingParser parser; 10 | parser.setListener(this); 11 | WiFiClient client; 12 | 13 | // http://global.adsbexchange.com/VirtualRadar/AircraftList.json?lat=47.437691&lng=8.568854&fDstL=0&fDstU=20&fAltL=0&fAltU=5000 14 | const char host[] = "global.adsbexchange.com"; 15 | String url = "/VirtualRadar/AircraftList.json?" + searchQuery; 16 | 17 | const int httpPort = 80; 18 | if (!client.connect(host, httpPort)) { 19 | Serial.println("connection failed"); 20 | return; 21 | } 22 | 23 | 24 | Serial.print("Requesting URL: "); 25 | Serial.println(url); 26 | 27 | // This will send the request to the server 28 | client.print(String("GET ") + url + " HTTP/1.1\r\n" + 29 | "Host: " + host + "\r\n" + 30 | "Connection: close\r\n\r\n"); 31 | 32 | int retryCounter = 0; 33 | while(!client.available()) { 34 | Serial.println("."); 35 | delay(1000); 36 | retryCounter++; 37 | if (retryCounter > 10) { 38 | return; 39 | } 40 | } 41 | 42 | int pos = 0; 43 | boolean isBody = false; 44 | char c; 45 | 46 | int size = 0; 47 | client.setNoDelay(false); 48 | while(client.connected()) { 49 | while((size = client.available()) > 0) { 50 | c = client.read(); 51 | if (c == '{' || c == '[') { 52 | isBody = true; 53 | } 54 | if (isBody) { 55 | parser.parse(c); 56 | } 57 | } 58 | } 59 | endDocument(); 60 | } 61 | 62 | String AdsbExchangeClient::getFrom() { 63 | if (from[CURRENT].length() >=4) { 64 | int firstComma = from[CURRENT].indexOf(","); 65 | return from[CURRENT].substring(5, firstComma); 66 | } 67 | return ""; 68 | } 69 | String AdsbExchangeClient::getFromIcao() { 70 | if (from[CURRENT].length() >=4) { 71 | return from[CURRENT].substring(0,4); 72 | } 73 | return ""; 74 | } 75 | String AdsbExchangeClient::getTo() { 76 | if (to[CURRENT].length() >=4) { 77 | int firstComma = to[CURRENT].indexOf(","); 78 | return to[CURRENT].substring(5, firstComma); 79 | } 80 | return ""; 81 | } 82 | 83 | String AdsbExchangeClient::getToIcao() { 84 | if (to[CURRENT].length() >=4) { 85 | return to[CURRENT].substring(0,4); 86 | } 87 | return ""; 88 | } 89 | String AdsbExchangeClient::getAltitude(){ 90 | return altitude[CURRENT]; 91 | } 92 | double AdsbExchangeClient::getDistance() { 93 | return distance[CURRENT]; 94 | 95 | } 96 | String AdsbExchangeClient::getAircraftType() { 97 | return aircraftType[CURRENT]; 98 | 99 | } 100 | String AdsbExchangeClient::getOperatorCode() { 101 | return operatorCode[CURRENT]; 102 | } 103 | 104 | double AdsbExchangeClient::getHeading() { 105 | return heading[CURRENT]; 106 | } 107 | 108 | void AdsbExchangeClient::whitespace(char c) { 109 | 110 | } 111 | 112 | void AdsbExchangeClient::startDocument() { 113 | counter = 0; 114 | currentMinDistance = 1000.0; 115 | } 116 | 117 | void AdsbExchangeClient::key(String key) { 118 | currentKey = key; 119 | } 120 | 121 | void AdsbExchangeClient::value(String value) { 122 | /*String from = ""; 123 | String to = ""; 124 | String altitude = ""; 125 | String aircraftType = ""; 126 | String currentKey = ""; 127 | String operator = ""; 128 | 129 | 130 | "Type": "A319", 131 | "Mdl": "Airbus A319 112", 132 | 133 | "From": "LSZH Z\u00c3\u00bcrich, Zurich, Switzerland", 134 | "To": "LEMD Madrid Barajas, Spain", 135 | "Op": "Swiss International Air Lines", 136 | "OpIcao": "SWR", 137 | "Dst": 6.23, 138 | "Year": "1996" 139 | */ 140 | if (currentKey == "Id") { 141 | counter++; 142 | } else if (currentKey == "From") { 143 | from[TEMP] = value; 144 | } else if (currentKey == "To") { 145 | to[TEMP] = value; 146 | } else if (currentKey == "OpIcao") { 147 | operatorCode[TEMP] = value; 148 | } else if (currentKey == "Dst") { 149 | distance[TEMP] = value.toFloat(); 150 | } else if (currentKey == "Mdl") { 151 | aircraftType[TEMP] = value; 152 | } else if (currentKey == "Trak") { 153 | heading[TEMP] = value.toFloat(); 154 | } else if (currentKey == "Alt") { 155 | altitude[TEMP] = value; 156 | } else if (currentKey == "Trt") { 157 | if (distance[TEMP] < currentMinDistance) { 158 | currentMinDistance = distance[TEMP]; 159 | Serial.println("Found a closer aircraft"); 160 | from[CURRENT] = from[TEMP]; 161 | to[CURRENT] = to[TEMP]; 162 | altitude[CURRENT] = altitude[TEMP]; 163 | distance[CURRENT] = distance[TEMP]; 164 | aircraftType[CURRENT] = aircraftType[TEMP]; 165 | operatorCode[CURRENT] = operatorCode[TEMP]; 166 | heading[CURRENT] = heading[TEMP]; 167 | } 168 | } 169 | Serial.println(currentKey + "=" + value); 170 | } 171 | 172 | int AdsbExchangeClient::getNumberOfVisibleAircrafts() { 173 | return counter; 174 | } 175 | 176 | void AdsbExchangeClient::endArray() { 177 | 178 | } 179 | 180 | void AdsbExchangeClient::endObject() { 181 | 182 | } 183 | 184 | void AdsbExchangeClient::endDocument() { 185 | Serial.println("Flights: " + String(counter)); 186 | if (counter == 0 && lastSightingMillis < millis() - MAX_AGE_MILLIS) { 187 | for (int i = 0; i < 2; i++) { 188 | from[i] = ""; 189 | to[i] = ""; 190 | altitude[i] = ""; 191 | distance[i] = 1000.0; 192 | aircraftType[i] = ""; 193 | operatorCode[i] = ""; 194 | heading[i] = 0.0; 195 | } 196 | } else if (counter > 0) { 197 | lastSightingMillis = millis(); 198 | } 199 | } 200 | 201 | boolean AdsbExchangeClient::isAircraftVisible() { 202 | return counter > 0 || lastSightingMillis > millis() - MAX_AGE_MILLIS; 203 | } 204 | 205 | void AdsbExchangeClient::startArray() { 206 | 207 | } 208 | 209 | void AdsbExchangeClient::startObject() { 210 | 211 | } 212 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WorldClockClient.cpp: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | 27 | #include "WorldClockClient.h" 28 | 29 | 30 | WorldClockClient::WorldClockClient(String language, String country, String dateFormat, int numberOfTimeZones, String* timeZoneIds) { 31 | myLanguage = language; 32 | myCountry = country; 33 | myDateFormat = dateFormat; 34 | myNumberOfTimeZoneIds = numberOfTimeZones; 35 | myTimeZoneIds = timeZoneIds; 36 | timeZoneOffsetToUtcMillis = (long*) malloc(numberOfTimeZones * sizeof(long)); 37 | } 38 | 39 | void WorldClockClient::updateTime() { 40 | JsonStreamingParser parser; 41 | parser.setListener(this); 42 | WiFiClient client; 43 | 44 | // http://api.thingspeak.com/channels/CHANNEL_ID/feeds.json?results=2&api_key=API_KEY 45 | const char host[] = "oleddisplay.squix.ch"; 46 | String url = "/rest/time"; 47 | 48 | const int httpPort = 80; 49 | if (!client.connect(host, httpPort)) { 50 | Serial.println("connection failed"); 51 | return; 52 | } 53 | 54 | 55 | Serial.print("Requesting URL: "); 56 | Serial.println(url); 57 | 58 | // {"language":"de","country":"CH","timeZoneIds":["Europe/Zurich", "Europe/London"],"dateFormat":"dd.MM.YYYY"} 59 | String timeZoneIdJson = "\"timeZoneIds\":["; 60 | for (int i = 0; i < myNumberOfTimeZoneIds; i++) { 61 | if (i > 0) { 62 | timeZoneIdJson +=","; 63 | } 64 | timeZoneIdJson += "\"" + myTimeZoneIds[i] + "\""; 65 | } 66 | timeZoneIdJson += "]"; 67 | String request = "{\"language\":\"" 68 | + myLanguage + "\",\"country\":\"" 69 | + myCountry + "\"," 70 | + timeZoneIdJson +",\"dateFormat\":\"" 71 | + myDateFormat +"\"}\r\n\r\n"; 72 | Serial.println("Request: " + request); 73 | // This will send the request to the server 74 | client.print("POST " + url + " HTTP/1.1\r\n" + 75 | "Host: " + host + "\r\n" + 76 | "Content-Length: " + String(request.length()) + "\r\n" + 77 | "Connection: close\r\n\r\n"); 78 | 79 | client.println(request); 80 | 81 | int retryCounter = 0; 82 | while(!client.available()) { 83 | Serial.println("."); 84 | delay(1000); 85 | retryCounter++; 86 | if (retryCounter > 10) { 87 | return; 88 | } 89 | } 90 | 91 | int pos = 0; 92 | boolean isBody = false; 93 | char c; 94 | 95 | int size = 0; 96 | client.setNoDelay(false); 97 | while(client.connected()) { 98 | while((size = client.available()) > 0) { 99 | c = client.read(); 100 | if (c == '{' || c == '[') { 101 | isBody = true; 102 | } 103 | if (isBody) { 104 | parser.parse(c); 105 | } 106 | } 107 | } 108 | } 109 | 110 | 111 | String WorldClockClient::getFormattedTime(int timeZoneIndex) { 112 | return getHours(timeZoneIndex) + ":" + getMinutes(timeZoneIndex) + ":" + getSeconds(timeZoneIndex); 113 | } 114 | 115 | String WorldClockClient::getHours(int timeZoneIndex) { 116 | if (millisOfDayAtUpdate == 0) { 117 | return "--"; 118 | } 119 | int hours = ((getSecondsOfDay(timeZoneIndex) % 86400L) / 3600) % 24; 120 | if (hours < 10) { 121 | return "0" + String(hours); 122 | } 123 | return String(hours); // print the hour (86400 equals secs per day) 124 | } 125 | 126 | String WorldClockClient::getMinutes(int timeZoneIndex) { 127 | if (millisOfDayAtUpdate == 0) { 128 | return "--"; 129 | } 130 | int minutes = ((getSecondsOfDay(timeZoneIndex) % 3600) / 60); 131 | if (minutes < 10 ) { 132 | // In the first 10 minutes of each hour, we'll want a leading '0' 133 | return "0" + String(minutes); 134 | } 135 | return String(minutes); 136 | } 137 | 138 | String WorldClockClient::getSeconds(int timeZoneIndex) { 139 | if (millisOfDayAtUpdate == 0) { 140 | return "--"; 141 | } 142 | int seconds = getSecondsOfDay(timeZoneIndex) % 60; 143 | if ( seconds < 10 ) { 144 | // In the first 10 seconds of each minute, we'll want a leading '0' 145 | return "0" + String(seconds); 146 | } 147 | return String(seconds); 148 | 149 | } 150 | 151 | long WorldClockClient::getSecondsOfDay(int timeZoneIndex) { 152 | return (millisOfDayAtUpdate + millis() - localMillisAtUpdate + timeZoneOffsetToUtcMillis[timeZoneIndex]) / 1000; 153 | } 154 | 155 | void WorldClockClient::whitespace(char c) { 156 | 157 | } 158 | 159 | void WorldClockClient::startDocument() { 160 | 161 | } 162 | 163 | void WorldClockClient::key(String key) { 164 | currentKey = key; 165 | } 166 | 167 | void WorldClockClient::value(String value) { 168 | Serial.println(currentKey + ": " + value); 169 | if (currentKey == "millisOfDayUtc") { 170 | millisOfDayAtUpdate = value.toInt(); 171 | localMillisAtUpdate = millis(); 172 | } else if (currentKey == "index") { 173 | currentTimeZoneIndex = value.toInt(); 174 | Serial.println("\n-->Current index: " + String(currentTimeZoneIndex)); 175 | } else if (currentKey == "timeZoneOffsetToUtcMillis") { 176 | Serial.println("\n-->Index: " + String(currentTimeZoneIndex)); 177 | Serial.println("\n-->value: " + value); 178 | timeZoneOffsetToUtcMillis[currentTimeZoneIndex] = value.toInt(); 179 | } 180 | } 181 | 182 | void WorldClockClient::endArray() { 183 | 184 | } 185 | 186 | void WorldClockClient::endObject() { 187 | 188 | } 189 | 190 | void WorldClockClient::endDocument() { 191 | 192 | } 193 | 194 | void WorldClockClient::startArray() { 195 | 196 | } 197 | 198 | void WorldClockClient::startObject() { 199 | 200 | } 201 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WorldClockDemo/WorldClockDemo.ino: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2017 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at https://blog.squix.org 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include "SSD1306Wire.h" 30 | #include "OLEDDisplayUi.h" 31 | #include "Wire.h" 32 | #include "WorldClockClient.h" 33 | #include "icons.h" 34 | #include "fonts.h" 35 | 36 | 37 | 38 | /*************************** 39 | * Begin Settings 40 | **************************/ 41 | // WIFI 42 | const char* WIFI_SSID = "yourssid"; 43 | const char* WIFI_PWD = "yourpassw0rd"; 44 | 45 | // Setup 46 | const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes 47 | 48 | // Display Settings 49 | const int I2C_DISPLAY_ADDRESS = 0x3c; 50 | const int SDA_PIN = D3; 51 | const int SDC_PIN = D4; 52 | 53 | // TimeClient settings 54 | 55 | 56 | // Initialize the oled display for address 0x3c 57 | // sda-pin=14 and sdc-pin=12 58 | 59 | SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN); 60 | OLEDDisplayUi ui ( &display ); 61 | 62 | /*************************** 63 | * End Settings 64 | **************************/ 65 | String timeZoneIds [] = {"America/New_York", "Europe/London", "Europe/Paris", "Australia/Sydney"}; 66 | WorldClockClient worldClockClient("de", "CH", "E, dd. MMMMM yyyy", 4, timeZoneIds); 67 | 68 | 69 | // flag changed in the ticker function every 10 minutes 70 | bool readyForUpdate = false; 71 | 72 | String lastUpdate = "--"; 73 | 74 | Ticker ticker; 75 | 76 | 77 | void updateData(OLEDDisplay *display) { 78 | drawProgress(display, 50, "Updating Time..."); 79 | worldClockClient.updateTime(); 80 | drawProgress(display, 100, "Done..."); 81 | readyForUpdate = false; 82 | delay(1000); 83 | } 84 | 85 | void drawProgress(OLEDDisplay *display, int percentage, String label) { 86 | display->clear(); 87 | display->setTextAlignment(TEXT_ALIGN_CENTER); 88 | display->setFont(ArialMT_Plain_10); 89 | display->drawString(64, 10, label); 90 | display->drawProgressBar(10, 28, 108, 12, percentage); 91 | display->display(); 92 | } 93 | 94 | void drawClock(OLEDDisplay *display, int x, int y, int timeZoneIndex, String city, const char* icon) { 95 | display->setTextAlignment(TEXT_ALIGN_LEFT); 96 | display->setFont(ArialMT_Plain_10); 97 | display->drawString(x + 60, y + 5, city); 98 | display->setFont(Crushed_Plain_36); 99 | display->drawXbm(x, y, 60, 60, icon); 100 | display->drawString(x + 60, y + 15, worldClockClient.getHours(timeZoneIndex) + ":" + worldClockClient.getMinutes(timeZoneIndex)); 101 | 102 | } 103 | 104 | void drawFrame1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { 105 | drawClock(display, x, y, 0, "New York", new_york_bits); 106 | } 107 | 108 | void drawFrame2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { 109 | drawClock(display, x, y, 1, "London", london_bits); 110 | } 111 | 112 | void drawFrame3(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { 113 | drawClock(display, x, y, 2, "Paris", paris_bits); 114 | } 115 | 116 | void drawFrame4(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { 117 | drawClock(display, x, y, 3, "Sydney", sydney_bits); 118 | } 119 | 120 | 121 | void setReadyForWeatherUpdate() { 122 | Serial.println("Setting readyForUpdate to true"); 123 | readyForUpdate = true; 124 | } 125 | 126 | // this array keeps function pointers to all frames 127 | // frames are the single views that slide from right to left 128 | FrameCallback frames[] = { drawFrame1, drawFrame2, drawFrame3, drawFrame4}; 129 | int numberOfFrames = 4; 130 | 131 | void setup() { 132 | Serial.begin(115200); 133 | Serial.println(); 134 | Serial.println(); 135 | 136 | // initialize dispaly 137 | display.init(); 138 | display.clear(); 139 | display.display(); 140 | 141 | //display.flipScreenVertically(); 142 | display.setFont(ArialMT_Plain_10); 143 | display.setTextAlignment(TEXT_ALIGN_CENTER); 144 | display.setContrast(255); 145 | 146 | WiFi.begin(WIFI_SSID, WIFI_PWD); 147 | 148 | int counter = 0; 149 | while (WiFi.status() != WL_CONNECTED) { 150 | delay(500); 151 | Serial.print("."); 152 | display.clear(); 153 | display.drawString(64, 10, "Connecting to WiFi"); 154 | display.drawXbm(46, 30, 8, 8, counter % 3 == 0 ? activeSymbol : inactiveSymbol); 155 | display.drawXbm(60, 30, 8, 8, counter % 3 == 1 ? activeSymbol : inactiveSymbol); 156 | display.drawXbm(74, 30, 8, 8, counter % 3 == 2 ? activeSymbol : inactiveSymbol); 157 | display.display(); 158 | 159 | counter++; 160 | } 161 | 162 | ui.setTargetFPS(30); 163 | 164 | // You can change this to 165 | // TOP, LEFT, BOTTOM, RIGHT 166 | ui.setIndicatorPosition(BOTTOM); 167 | 168 | // Defines where the first frame is located in the bar. 169 | ui.setIndicatorDirection(LEFT_RIGHT); 170 | 171 | // You can change the transition that is used 172 | // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN 173 | ui.setFrameAnimation(SLIDE_LEFT); 174 | 175 | // Add frames 176 | ui.setFrames(frames, numberOfFrames); 177 | 178 | // Inital UI takes care of initalising the display too. 179 | ui.init(); 180 | 181 | Serial.println(""); 182 | 183 | updateData(&display); 184 | 185 | ticker.attach(UPDATE_INTERVAL_SECS, setReadyForWeatherUpdate); 186 | 187 | } 188 | 189 | void loop() { 190 | 191 | if (readyForUpdate && ui.getUiState()->frameState == FIXED) { 192 | updateData(&display); 193 | } 194 | 195 | int remainingTimeBudget = ui.update(); 196 | 197 | if (remainingTimeBudget > 0) { 198 | // You can do some work here 199 | // Don't do stuff if you are below your 200 | // time budget. 201 | delay(remainingTimeBudget); 202 | } 203 | 204 | } 205 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WundergroundHourly.cpp: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | # if defined(ESP8266) 27 | #include 28 | #include 29 | #endif 30 | # if defined(ESP32) 31 | #include 32 | #include 33 | #endif 34 | 35 | #include 36 | #include "WundergroundHourly.h" 37 | 38 | WundergroundHourly::WundergroundHourly(boolean _isMetric, boolean _is24Hours) { 39 | isMetric = _isMetric; 40 | is24Hours = _is24Hours; 41 | } 42 | 43 | void WundergroundHourly::setMetric(bool isMetric) { 44 | this->isMetric = isMetric; 45 | } 46 | void WundergroundHourly::set24Hours(bool is24Hours) { 47 | this->is24Hours = is24Hours; 48 | } 49 | 50 | void WundergroundHourly::updateHourly(WGHourly *hourlies, String apiKey, String language, String country, String city) { 51 | doUpdate(hourlies, "http://api.wunderground.com/api/" + apiKey + "/hourly/lang:" + language + "/q/" + country + "/" + city + ".json"); 52 | } 53 | 54 | 55 | void WundergroundHourly::updateHourlyPWS(WGHourly *hourlies, String apiKey, String language, String pws) { 56 | doUpdate(hourlies, "http://api.wunderground.com/api/" + apiKey + "/hourly/lang:" + language + "/q/pws:" + pws + ".json"); 57 | } 58 | 59 | void WundergroundHourly::updateHourlyZMW(WGHourly *hourlies, String apiKey, String language, String zmwCode) { 60 | doUpdate(hourlies, "http://api.wunderground.com/api/" + apiKey + "/hourly/lang:" + language + "/q/zmw:" + zmwCode + ".json"); 61 | } 62 | 63 | void WundergroundHourly::doUpdate(WGHourly *hourlies, String url) { 64 | this->hourlies = hourlies; 65 | JsonStreamingParser parser; 66 | parser.setListener(this); 67 | 68 | HTTPClient http; 69 | 70 | http.begin(url); 71 | bool isBody = false; 72 | char c; 73 | int size; 74 | Serial.print("[HTTP] GET...\n"); 75 | // start connection and send HTTP header 76 | int httpCode = http.GET(); 77 | Serial.printf("[HTTP] GET... code: %d\n", httpCode); 78 | if(httpCode > 0) { 79 | 80 | 81 | 82 | WiFiClient * client = http.getStreamPtr(); 83 | 84 | while(client->connected()) { 85 | while((size = client->available()) > 0) { 86 | c = client->read(); 87 | if (c == '{' || c == '[') { 88 | 89 | isBody = true; 90 | } 91 | if (isBody) { 92 | parser.parse(c); 93 | } 94 | } 95 | } 96 | } 97 | this->hourlies = nullptr; 98 | } 99 | 100 | void WundergroundHourly::whitespace(char c) { 101 | Serial.println("whitespace"); 102 | } 103 | 104 | void WundergroundHourly::startDocument() { 105 | Serial.println("start document"); 106 | } 107 | 108 | void WundergroundHourly::key(String key) { 109 | currentKey = String(key); 110 | 111 | } 112 | 113 | void WundergroundHourly::value(String value) { 114 | if (currentKey == "hour") { 115 | currentHour = value.toInt(); 116 | } 117 | 118 | if (is24Hours && currentKey == "hour_padded") { 119 | hourlies[currentHour].hour = value + ":00"; 120 | } 121 | if (!is24Hours && currentKey == "civil") { 122 | hourlies[currentHour].hour = value; 123 | } 124 | 125 | if (currentKey == "icon") { 126 | hourlies[currentHour].icon = value; 127 | } 128 | if (currentKey == "condition") { 129 | hourlies[currentHour].title = value; 130 | } 131 | 132 | 133 | if (currentParent == "temp" && currentKey == "english" && !isMetric) { 134 | hourlies[currentHour].temp = value; 135 | } 136 | if (currentParent == "temp" && currentKey == "metric" && isMetric) { 137 | hourlies[currentHour].temp = value; 138 | } 139 | 140 | if (currentKey == "pop") { 141 | hourlies[currentHour].PoP = value; 142 | } 143 | 144 | } 145 | 146 | void WundergroundHourly::endArray() { 147 | 148 | } 149 | 150 | 151 | void WundergroundHourly::startObject() { 152 | currentParent = currentKey; 153 | } 154 | 155 | void WundergroundHourly::endObject() { 156 | currentParent = ""; 157 | } 158 | 159 | void WundergroundHourly::endDocument() { 160 | 161 | } 162 | 163 | void WundergroundHourly::startArray() { 164 | 165 | } 166 | 167 | 168 | 169 | String WundergroundHourly::getMeteoconIcon(String iconText) { 170 | if (iconText == "chanceflurries") return "F"; 171 | if (iconText == "chancerain") return "Q"; 172 | if (iconText == "chancesleet") return "W"; 173 | if (iconText == "chancesnow") return "V"; 174 | if (iconText == "chancetstorms") return "S"; 175 | if (iconText == "clear") return "B"; 176 | if (iconText == "cloudy") return "Y"; 177 | if (iconText == "flurries") return "F"; 178 | if (iconText == "fog") return "M"; 179 | if (iconText == "hazy") return "E"; 180 | if (iconText == "mostlycloudy") return "Y"; 181 | if (iconText == "mostlysunny") return "H"; 182 | if (iconText == "partlycloudy") return "H"; 183 | if (iconText == "partlysunny") return "J"; 184 | if (iconText == "sleet") return "W"; 185 | if (iconText == "rain") return "R"; 186 | if (iconText == "snow") return "W"; 187 | if (iconText == "sunny") return "B"; 188 | if (iconText == "tstorms") return "0"; 189 | 190 | if (iconText == "nt_chanceflurries") return "F"; 191 | if (iconText == "nt_chancerain") return "7"; 192 | if (iconText == "nt_chancesleet") return "#"; 193 | if (iconText == "nt_chancesnow") return "#"; 194 | if (iconText == "nt_chancetstorms") return "&"; 195 | if (iconText == "nt_clear") return "2"; 196 | if (iconText == "nt_cloudy") return "Y"; 197 | if (iconText == "nt_flurries") return "9"; 198 | if (iconText == "nt_fog") return "M"; 199 | if (iconText == "nt_hazy") return "E"; 200 | if (iconText == "nt_mostlycloudy") return "5"; 201 | if (iconText == "nt_mostlysunny") return "3"; 202 | if (iconText == "nt_partlycloudy") return "4"; 203 | if (iconText == "nt_partlysunny") return "4"; 204 | if (iconText == "nt_sleet") return "9"; 205 | if (iconText == "nt_rain") return "7"; 206 | if (iconText == "nt_snow") return "#"; 207 | if (iconText == "nt_sunny") return "4"; 208 | if (iconText == "nt_tstorms") return "&"; 209 | 210 | return ")"; 211 | } 212 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/settings.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2016 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | /* Customizations by Neptune (NeptuneEng on Twitter, Neptune2 on Github) 27 | * 28 | * Added Wifi Splash screen and credit to Squix78 29 | * Modified progress bar to a thicker and symmetrical shape 30 | * Replaced TimeClient with built-in lwip sntp client (no need for external ntp client library) 31 | * Added Daylight Saving Time Auto adjuster with DST rules using simpleDSTadjust library 32 | * https://github.com/neptune2/simpleDSTadjust 33 | * Added Setting examples for Boston, Zurich and Sydney 34 | * Selectable NTP servers for each locale 35 | * DST rules and timezone settings customizable for each locale 36 | * See https://www.timeanddate.com/time/change/ for DST rules 37 | * Added AM/PM or 24-hour option for each locale 38 | * Changed to 7-segment Clock font from http://www.keshikan.net/fonts-e.html 39 | * Added Forecast screen for days 4-6 (requires 1.1.3 or later version of esp8266_Weather_Station library) 40 | * Added support for DHT22, DHT21 and DHT11 Indoor Temperature and Humidity Sensors 41 | * Fixed bug preventing display.flipScreenVertically() from working 42 | * Slight adjustment to overlay 43 | */ 44 | 45 | #include 46 | #include "DHT.h" 47 | 48 | // >>> Uncomment one of the following 2 lines to define which OLED display interface type you are using 49 | //#define spiOLED 50 | #define i2cOLED 51 | 52 | #ifdef spiOLED 53 | #include "SSD1306Spi.h" 54 | #endif 55 | #ifdef i2cOLED 56 | #include "SSD1306Wire.h" 57 | #endif 58 | #include "OLEDDisplayUi.h" 59 | 60 | // Please read http://blog.squix.org/weatherstation-getting-code-adapting-it 61 | // for setup instructions 62 | 63 | #define HOSTNAME "ESP8266-OTA-" 64 | 65 | // Setup 66 | const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes 67 | 68 | #ifdef spiOLED 69 | // Pin definitions for SPI OLED 70 | #define OLED_CS D8 // Chip select 71 | #define OLED_DC D2 // Data/Command 72 | #define OLED_RESET D0 // RESET - If you get an error on this line, either change Tools->Board to the board you are using or change "D0" to the appropriate pin number for your board. 73 | #endif 74 | 75 | #ifdef i2cOLED 76 | // Pin definitions for I2C OLED 77 | const int I2C_DISPLAY_ADDRESS = 0x3c; 78 | // const int SDA_PIN = 0; 79 | // const int SDC_PIN = 2; 80 | const int SDA_PIN = D2; 81 | const int SDC_PIN = D3; 82 | #endif 83 | 84 | // DHT Settings 85 | // Uncomment whatever type you're using! 86 | 87 | // #define DHTPIN D2 // NodeMCU 88 | #define DHTPIN D4 // Wemos D1R2 Mini 89 | 90 | //#define DHTTYPE DHT11 // DHT 11 91 | #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 92 | //#define DHTTYPE DHT21 // DHT 21 (AM2301) 93 | 94 | #if DHTTYPE == DHT22 95 | #define DHTTEXT "DHT22" 96 | #elif DHTTYPE == DHT21 97 | #define DHTTEXT "DHT21" 98 | #elif DHTTYPE == DHT11 99 | #define DHTTEXT "DHT11" 100 | #endif 101 | char FormattedTemperature[10]; 102 | char FormattedHumidity[10]; 103 | 104 | // ----------------------------------- 105 | // Example Locales (uncomment only 1) 106 | #define Zurich 107 | //#define Boston 108 | //#define Sydney 109 | //------------------------------------ 110 | 111 | #ifdef Zurich 112 | //DST rules for Central European Time Zone 113 | #define UTC_OFFSET +1 114 | struct dstRule StartRule = {"CEST", Last, Sun, Mar, 2, 3600}; // Central European Summer Time = UTC/GMT +2 hours 115 | struct dstRule EndRule = {"CET", Last, Sun, Oct, 2, 0}; // Central European Time = UTC/GMT +1 hour 116 | 117 | // Uncomment for 24 Hour style clock 118 | #define STYLE_24HR 119 | 120 | #define NTP_SERVERS "0.ch.pool.ntp.org", "1.ch.pool.ntp.org", "2.ch.pool.ntp.org" 121 | 122 | // Wunderground Settings 123 | const boolean IS_METRIC = true; 124 | const String WUNDERGRROUND_API_KEY = ""; 125 | const String WUNDERGRROUND_LANGUAGE = "EN"; 126 | const String WUNDERGROUND_COUNTRY = "CH"; 127 | const String WUNDERGROUND_CITY = "Zurich"; 128 | #endif 129 | 130 | #ifdef Boston 131 | //DST rules for US Eastern Time Zone (New York, Boston) 132 | #define UTC_OFFSET -5 133 | struct dstRule StartRule = {"EDT", Second, Sun, Mar, 2, 3600}; // Eastern Daylight time = UTC/GMT -4 hours 134 | struct dstRule EndRule = {"EST", First, Sun, Nov, 1, 0}; // Eastern Standard time = UTC/GMT -5 hour 135 | 136 | // Uncomment for 24 Hour style clock 137 | //#define STYLE_24HR 138 | 139 | #define NTP_SERVERS "us.pool.ntp.org", "time.nist.gov", "pool.ntp.org" 140 | 141 | // Wunderground Settings 142 | const boolean IS_METRIC = false; 143 | const String WUNDERGRROUND_API_KEY = ""; 144 | const String WUNDERGRROUND_LANGUAGE = "EN"; 145 | const String WUNDERGROUND_COUNTRY = "MA"; 146 | const String WUNDERGROUND_CITY = "Boston"; 147 | #endif 148 | 149 | #ifdef Sydney 150 | //DST Rules for Australia Eastern Time Zone (Sydney) 151 | #define UTC_OFFSET +10 152 | struct dstRule StartRule = {"AEDT", First, Sun, Oct, 2, 3600}; // Australia Eastern Daylight time = UTC/GMT +11 hours 153 | struct dstRule EndRule = {"AEST", First, Sun, Apr, 2, 0}; // Australia Eastern Standard time = UTC/GMT +10 hour 154 | 155 | // Uncomment for 24 Hour style clock 156 | //#define STYLE_24HR 157 | 158 | #define NTP_SERVERS "0.au.pool.ntp.org", "1.au.pool.ntp.org", "2.au.pool.ntp.org" 159 | 160 | // Wunderground Settings 161 | const boolean IS_METRIC = true; 162 | const String WUNDERGRROUND_API_KEY = ""; 163 | const String WUNDERGRROUND_LANGUAGE = "EN"; 164 | const String WUNDERGROUND_COUNTRY = "AU"; 165 | const String WUNDERGROUND_CITY = "Sydney"; 166 | #endif 167 | 168 | //Thingspeak Settings 169 | const String THINGSPEAK_CHANNEL_ID = "67284"; 170 | const String THINGSPEAK_API_READ_KEY = "L2VIW20QVNZJBLAK"; 171 | 172 | #ifdef spiOLED 173 | SSD1306Spi display(OLED_RESET, OLED_DC, OLED_CS); // SPI OLED 174 | #endif 175 | #ifdef i2cOLED 176 | SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN); // I2C OLED 177 | #endif 178 | 179 | 180 | OLEDDisplayUi ui( &display ); 181 | 182 | // Setup simpleDSTadjust Library rules 183 | simpleDSTadjust dstAdjusted(StartRule, EndRule); 184 | 185 | /*************************** 186 | * End Settings 187 | **************************/ 188 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WundergroundAstronomy.cpp: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | # if defined(ESP8266) 27 | #include 28 | #include 29 | #endif 30 | # if defined(ESP32) 31 | #include 32 | #include 33 | #endif 34 | 35 | #include 36 | #include "WundergroundAstronomy.h" 37 | 38 | 39 | WundergroundAstronomy::WundergroundAstronomy(boolean _usePM) { 40 | usePM = _usePM; 41 | } 42 | void WundergroundAstronomy::setPM(boolean usePM) { 43 | this->usePM = usePM; 44 | } 45 | void WundergroundAstronomy::updateAstronomy(WGAstronomy *astronomy, String apiKey, String language, String country, String city) { 46 | doUpdate(astronomy, "http://api.wunderground.com/api/" + apiKey + "/astronomy/lang:" + language + "/q/" + country + "/" + city + ".json"); 47 | } 48 | 49 | void WundergroundAstronomy::updateAstronomyPWS(WGAstronomy *astronomy, String apiKey, String language, String pws) { 50 | doUpdate(astronomy, "http://api.wunderground.com/api/" + apiKey + "/astronomy/lang:" + language + "/q/pws:" + pws + ".json"); 51 | } 52 | 53 | void WundergroundAstronomy::doUpdate(WGAstronomy *astronomy, String url) { 54 | this->astronomy = astronomy; 55 | JsonStreamingParser parser; 56 | parser.setListener(this); 57 | 58 | HTTPClient http; 59 | 60 | http.begin(url); 61 | bool isBody = false; 62 | char c; 63 | int size; 64 | Serial.print("[HTTP] GET...\n"); 65 | // start connection and send HTTP header 66 | int httpCode = http.GET(); 67 | Serial.printf("[HTTP] GET... code: %d\n", httpCode); 68 | if(httpCode > 0) { 69 | 70 | 71 | 72 | WiFiClient * client = http.getStreamPtr(); 73 | 74 | while(client->connected()) { 75 | while((size = client->available()) > 0) { 76 | c = client->read(); 77 | if (c == '{' || c == '[') { 78 | 79 | isBody = true; 80 | } 81 | if (isBody) { 82 | parser.parse(c); 83 | } 84 | } 85 | } 86 | } 87 | this->astronomy = nullptr; 88 | } 89 | 90 | void WundergroundAstronomy::whitespace(char c) { 91 | Serial.println("whitespace"); 92 | } 93 | 94 | void WundergroundAstronomy::startDocument() { 95 | Serial.println("start document"); 96 | } 97 | 98 | void WundergroundAstronomy::key(String key) { 99 | currentKey = String(key); 100 | } 101 | 102 | void WundergroundAstronomy::value(String value) { 103 | 104 | if (currentKey == "ageOfMoon") { 105 | astronomy->moonAge = value; 106 | } 107 | 108 | if (currentKey == "phaseofMoon") { 109 | astronomy->moonPhase = value; 110 | } 111 | 112 | if (currentKey == "percentIlluminated") { 113 | astronomy->moonPctIlum = value; 114 | } 115 | 116 | 117 | if (currentParent == "sunrise") { // Has a Parent key and 2 sub-keys 118 | if (currentKey == "hour") { 119 | int tempHour = value.toInt(); // do this to concert to 12 hour time (make it a function!) 120 | if (usePM && tempHour > 12){ 121 | tempHour -= 12; 122 | isPM = true; 123 | } 124 | else { 125 | isPM = false; 126 | } 127 | char tempHourBuff[3] = ""; 128 | sprintf(tempHourBuff, "%02d", tempHour); 129 | astronomy->sunriseTime = String(tempHourBuff); 130 | } 131 | if (currentKey == "minute") { 132 | char tempMinBuff[4] = ""; 133 | if (usePM) { 134 | sprintf(tempMinBuff, "%02d%s", value.toInt(), isPM?"pm":"am"); 135 | } else { 136 | sprintf(tempMinBuff, "%02d", value.toInt()); 137 | } 138 | astronomy->sunriseTime += ":" + String(tempMinBuff); 139 | 140 | } 141 | this->sunriseTime.trim(); 142 | } 143 | 144 | 145 | if (currentParent == "sunset") { // Has a Parent key and 2 sub-keys 146 | if (currentKey == "hour") { 147 | int tempHour = value.toInt(); // do this to concert to 12 hour time (make it a function!) 148 | if (usePM && tempHour > 12) { 149 | tempHour -= 12; 150 | isPM = true; 151 | } else { 152 | isPM = false; 153 | } 154 | char tempHourBuff[3] = ""; 155 | sprintf(tempHourBuff, "%02d", tempHour); 156 | astronomy->sunsetTime = String(tempHourBuff); 157 | } 158 | if (currentKey == "minute") { 159 | char tempMinBuff[4] = ""; 160 | if (usePM) { 161 | sprintf(tempMinBuff, "%02d%s", value.toInt(), isPM?"pm":"am"); 162 | } else { 163 | sprintf(tempMinBuff, "%02d", value.toInt()); 164 | } 165 | astronomy->sunsetTime += ":" + String(tempMinBuff); 166 | } 167 | this->sunsetTime.trim(); 168 | } 169 | 170 | if (currentParent == "moonrise") { // Has a Parent key and 2 sub-keys 171 | if (currentKey == "hour") { 172 | int tempHour = value.toInt(); // do this to concert to 12 hour time (make it a function!) 173 | if (usePM && tempHour > 12){ 174 | tempHour -= 12; 175 | isPM = true; 176 | } 177 | else isPM = false; 178 | char tempHourBuff[3] = ""; 179 | sprintf(tempHourBuff, "%02d", tempHour); 180 | astronomy->moonriseTime = String(tempHourBuff); 181 | } 182 | if (currentKey == "minute") { 183 | char tempMinBuff[4] = ""; 184 | if (usePM) { 185 | sprintf(tempMinBuff, "%02d%s", value.toInt(), isPM?"pm":"am"); 186 | } else { 187 | sprintf(tempMinBuff, "%02d", value.toInt()); 188 | } 189 | astronomy->moonriseTime += ":" + String(tempMinBuff); 190 | } 191 | this->moonriseTime.trim(); 192 | } 193 | 194 | if (currentParent == "moonset") { // Has a Parent key and 2 sub-keys 195 | if (currentKey == "hour") { 196 | int tempHour = value.toInt(); // do this to concert to 12 hour time (make it a function!) 197 | if (usePM && tempHour > 12){ 198 | tempHour -= 12; 199 | isPM = true; 200 | } 201 | else isPM = false; 202 | char tempHourBuff[3] = ""; 203 | sprintf(tempHourBuff, "%02d", tempHour); 204 | astronomy->moonsetTime = String(tempHourBuff); 205 | } 206 | if (currentKey == "minute") { 207 | char tempMinBuff[4] = ""; 208 | if (usePM) { 209 | sprintf(tempMinBuff, "%02d%s", value.toInt(), isPM?"pm":"am"); 210 | } else { 211 | sprintf(tempMinBuff, "%02d", value.toInt()); 212 | } 213 | astronomy->moonsetTime += ":" + String(tempMinBuff); 214 | } 215 | astronomy->moonsetTime.trim(); 216 | } 217 | 218 | } 219 | 220 | void WundergroundAstronomy::endArray() { 221 | 222 | } 223 | 224 | 225 | void WundergroundAstronomy::startObject() { 226 | currentParent = currentKey; 227 | } 228 | 229 | void WundergroundAstronomy::endObject() { 230 | currentParent = ""; 231 | } 232 | 233 | void WundergroundAstronomy::endDocument() { 234 | 235 | } 236 | 237 | void WundergroundAstronomy::startArray() { 238 | 239 | } 240 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WundergroundClient.h: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | #define MAX_FORECAST_PERIODS 20 // Changed from 7 to 12 to support 6 day / 2 screen forecast (Neptune) 32 | // Changed to 20 to support max 10-day forecast returned from 'forecast10day' API (fowlerk) 33 | 34 | #define MAX_WEATHER_ALERTS 6 // The maximum number of concurrent weather alerts supported by the library 35 | 36 | class WundergroundClient: public JsonListener { 37 | private: 38 | String currentKey; 39 | String currentParent = ""; 40 | long localEpoc = 0; 41 | int gmtOffset = 1; 42 | long localMillisAtUpdate; 43 | String date = "-"; 44 | String observationDate = "-"; 45 | boolean isMetric = true; 46 | String currentTemp; 47 | // JJG added ... ////////////////////////////////// define returns ///////////////////////////////// 48 | String moonPctIlum; // not used 49 | String moonAge; // make this a long? 50 | String moonPhase; 51 | String sunriseTime; 52 | String sunsetTime; 53 | String moonriseTime; 54 | String moonsetTime; 55 | String windSpeed; 56 | String windDir; 57 | // end JJG add //////////////////////////////////////////////////////////////////////////////////// 58 | String weatherIcon; 59 | String weatherText; 60 | String humidity; 61 | String pressure; 62 | String dewPoint; 63 | String precipitationToday; 64 | // fowlerk added... 65 | String feelslike; 66 | String UV; 67 | String observationTime; // fowlerk add, 04-Dec-2016 68 | // end fowlerk add 69 | 70 | void doUpdate(String url); 71 | 72 | // forecast 73 | boolean isForecast = false; 74 | boolean isSimpleForecast = false; // true; fowlerk 75 | boolean isCurrentObservation = false; // Added by fowlerk 76 | boolean isAlerts = false; // Added by fowlerk 77 | boolean isAlertUS = false; // Added by fowlerk 78 | boolean isAlertEU = false; // Added by fowlerk 79 | int currentForecastPeriod; 80 | String forecastIcon [MAX_FORECAST_PERIODS]; 81 | String forecastTitle [MAX_FORECAST_PERIODS]; 82 | String forecastLowTemp [MAX_FORECAST_PERIODS]; 83 | String forecastHighTemp [MAX_FORECAST_PERIODS]; 84 | // fowlerk added... 85 | String forecastDay [MAX_FORECAST_PERIODS/2]; 86 | String forecastMonth [MAX_FORECAST_PERIODS/2]; 87 | String forecastText [MAX_FORECAST_PERIODS]; 88 | String PoP [MAX_FORECAST_PERIODS]; 89 | // Active alerts...added 18-Dec-2016 90 | String activeAlerts [MAX_WEATHER_ALERTS]; // For a max of 6 currently-active alerts 91 | String activeAlertsMessage [MAX_WEATHER_ALERTS]; // Alert full-text message 92 | bool activeAlertsMessageTrunc [MAX_WEATHER_ALERTS]; // Alert full-text message truncation flag 93 | String activeAlertsText [MAX_WEATHER_ALERTS]; // Alerts description text 94 | String activeAlertsStart [MAX_WEATHER_ALERTS]; // Start of alert date/time 95 | String activeAlertsEnd [MAX_WEATHER_ALERTS]; // Expiration of alert date/time 96 | String activeAlertsPhenomena [MAX_WEATHER_ALERTS]; // Alert phenomena code 97 | String activeAlertsSignificance [MAX_WEATHER_ALERTS]; // Alert significance code 98 | String activeAlertsAttribution [MAX_WEATHER_ALERTS]; // Alert significance code 99 | int activeAlertsCnt; // Number of active alerts 100 | int currentAlert; // For indexing the current active alert 101 | // end fowlerk add 102 | 103 | public: 104 | WundergroundClient(boolean isMetric); 105 | void updateConditions(String apiKey, String language, String country, String city); 106 | void updateConditions(String apiKey, String language, String zmwCode); 107 | void updateConditionsPWS(String apiKey, String language, String pws); 108 | void updateForecast(String apiKey, String language, String country, String city); 109 | void updateForecastPWS(String apiKey, String language, String pws); 110 | void updateForecastZMW(String apiKey, String language, String zmwCode); 111 | void updateAstronomy(String apiKey, String language, String country, String city); 112 | void updateAstronomyPWS(String apiKey, String language, String pws); 113 | void updateAlerts(String apiKey, String language, String country, String city); // Added by fowlerk, 18-Dec-2016 114 | void updateAlertsPWS(String apiKey, String language, String country, String pws); 115 | void initMetric(boolean isMetric); // Added by fowlerk, 12/22/16, as an option to change metric setting other than at instantiation 116 | // JJG added 117 | String getHours(); 118 | String getMinutes(); 119 | String getSeconds(); 120 | String getDate(); 121 | String getObservationDate(); 122 | // JJG added ... ///////////////////function name to string //////////////////////////// 123 | String getMoonPctIlum(); 124 | String getMoonAge(); 125 | String getMoonPhase(); 126 | String getSunriseTime(); 127 | String getSunsetTime(); 128 | String getMoonriseTime(); 129 | String getMoonsetTime(); 130 | String getWindSpeed(); 131 | String getWindDir(); 132 | // end JJG add /////////////////////////////////////////////////////////////////////// 133 | long getCurrentEpoch(); 134 | 135 | String getCurrentTemp(); 136 | 137 | String getTodayIcon(); 138 | 139 | String getTodayIconText(); 140 | 141 | String getMeteoconIcon(String iconText); 142 | 143 | String getWeatherText(); 144 | 145 | String getHumidity(); 146 | 147 | String getPressure(); 148 | 149 | String getDewPoint(); 150 | 151 | String getPrecipitationToday(); 152 | // fowlerk added... 153 | String getFeelsLike(); 154 | 155 | String getUV(); 156 | 157 | String getObservationTime(); // fowlerk add, 04-Dec-2016 158 | // end fowlerk add 159 | 160 | String getForecastIcon(int period); 161 | 162 | String getForecastTitle(int period); 163 | 164 | String getForecastLowTemp(int period); 165 | 166 | String getForecastHighTemp(int period); 167 | // fowlerk added... 168 | String getForecastDay(int period); 169 | 170 | String getForecastMonth(int period); 171 | 172 | String getForecastText(int period); 173 | 174 | String getPoP(int period); 175 | 176 | int getActiveAlertsCnt(); 177 | 178 | String getActiveAlerts(int alertIndex); 179 | 180 | String getActiveAlertsText(int alertIndex); 181 | 182 | String getActiveAlertsMessage(int alertIndex); 183 | 184 | bool getActiveAlertsMessageTrunc(int alertIndex); 185 | 186 | String getActiveAlertsStart(int alertIndex); 187 | 188 | String getActiveAlertsEnd(int alertIndex); 189 | 190 | String getActiveAlertsPhenomena(int alertIndex); 191 | 192 | String getActiveAlertsSignificance(int alertIndex); 193 | 194 | String getActiveAlertsAttribution(int alertIndex); 195 | 196 | // end fowlerk add 197 | 198 | virtual void whitespace(char c); 199 | 200 | virtual void startDocument(); 201 | 202 | virtual void key(String key); 203 | 204 | virtual void value(String value); 205 | 206 | virtual void endArray(); 207 | 208 | virtual void endObject(); 209 | 210 | virtual void endDocument(); 211 | 212 | virtual void startArray(); 213 | 214 | virtual void startObject(); 215 | }; 216 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WundergroundConditions.cpp: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | # if defined(ESP8266) 27 | #include 28 | #include 29 | #endif 30 | # if defined(ESP32) 31 | #include 32 | #include 33 | #endif 34 | 35 | #include 36 | #include "WundergroundConditions.h" 37 | 38 | WundergroundConditions::WundergroundConditions(boolean _isMetric) { 39 | isMetric = _isMetric; 40 | } 41 | 42 | void WundergroundConditions::setMetric(boolean isMetric) { 43 | this->isMetric = isMetric; 44 | } 45 | 46 | void WundergroundConditions::updateConditions(WGConditions *conditions, String apiKey, String language, String country, String city) { 47 | doUpdate(conditions, "http://api.wunderground.com/api/" + apiKey + "/conditions/lang:" + language + "/q/" + country + "/" + city + ".json"); 48 | } 49 | 50 | // wunderground change the API URL scheme: 51 | // http://api.wunderground.com/api//conditions/lang:de/q/zmw:00000.215.10348.json 52 | void WundergroundConditions::updateConditions(WGConditions *conditions, String apiKey, String language, String zmwCode) { 53 | doUpdate(conditions, "http://api.wunderground.com/api/" + apiKey + "/conditions/lang:" + language + "/q/zmw:" + zmwCode + ".json"); 54 | } 55 | 56 | void WundergroundConditions::updateConditionsPWS(WGConditions *conditions, String apiKey, String language, String pws) { 57 | doUpdate(conditions, "http://api.wunderground.com/api/" + apiKey + "/conditions/lang:" + language + "/q/pws:" + pws + ".json"); 58 | } 59 | 60 | void WundergroundConditions::doUpdate(WGConditions *conditions, String url) { 61 | this->conditions = conditions; 62 | JsonStreamingParser parser; 63 | parser.setListener(this); 64 | 65 | HTTPClient http; 66 | 67 | http.begin(url); 68 | bool isBody = false; 69 | char c; 70 | int size; 71 | Serial.print("[HTTP] GET...\n"); 72 | // start connection and send HTTP header 73 | int httpCode = http.GET(); 74 | Serial.printf("[HTTP] GET... code: %d\n", httpCode); 75 | if(httpCode > 0) { 76 | 77 | 78 | 79 | WiFiClient * client = http.getStreamPtr(); 80 | 81 | while(client->connected()) { 82 | while((size = client->available()) > 0) { 83 | c = client->read(); 84 | if (c == '{' || c == '[') { 85 | 86 | isBody = true; 87 | } 88 | if (isBody) { 89 | parser.parse(c); 90 | } 91 | } 92 | } 93 | } 94 | this->conditions = nullptr; 95 | } 96 | 97 | void WundergroundConditions::whitespace(char c) { 98 | Serial.println("whitespace"); 99 | } 100 | 101 | void WundergroundConditions::startDocument() { 102 | Serial.println("start document"); 103 | } 104 | 105 | void WundergroundConditions::key(String key) { 106 | currentKey = String(key); 107 | } 108 | 109 | void WundergroundConditions::value(String value) { 110 | 111 | if (currentKey == "wind_mph" && !isMetric) { 112 | conditions->windSpeed = value + "mph"; 113 | } 114 | 115 | if (currentKey == "wind_kph" && isMetric) { 116 | conditions->windSpeed = value + "km/h"; 117 | } 118 | 119 | if (currentKey == "wind_dir") { 120 | conditions->windDir = value; 121 | } 122 | 123 | if (currentKey == "local_time_rfc822") { 124 | conditions->date = value.substring(0, 16); 125 | } 126 | 127 | if (currentKey == "observation_time_rfc822") { 128 | conditions->observationDate = value.substring(0, 16); 129 | } 130 | 131 | if (currentKey == "observation_time") { 132 | conditions->observationTime = value; 133 | } 134 | 135 | 136 | if (currentKey == "temp_f" && !isMetric) { 137 | conditions->currentTemp = value; 138 | } 139 | if (currentKey == "temp_c" && isMetric) { 140 | conditions->currentTemp = value; 141 | } 142 | if (currentKey == "icon") { 143 | conditions->weatherIcon = value; 144 | } 145 | if (currentKey == "weather") { 146 | conditions->weatherText = value; 147 | } 148 | if (currentKey == "relative_humidity") { 149 | conditions->humidity = value; 150 | } 151 | if (currentKey == "pressure_mb" && isMetric) { 152 | conditions->pressure = value + "mb"; 153 | } 154 | if (currentKey == "pressure_in" && !isMetric) { 155 | conditions->pressure = value + "in"; 156 | } 157 | 158 | if (currentKey == "feelslike_f" && !isMetric) { 159 | conditions->feelslike = value; 160 | } 161 | 162 | if (currentKey == "feelslike_c" && isMetric) { 163 | conditions->feelslike = value; 164 | } 165 | 166 | if (currentKey == "UV") { 167 | conditions->UV = value; 168 | } 169 | 170 | if (currentKey == "dewpoint_f" && !isMetric) { 171 | conditions->dewPoint = value; 172 | } 173 | if (currentKey == "dewpoint_c" && isMetric) { 174 | conditions->dewPoint = value; 175 | } 176 | if (currentKey == "precip_today_metric" && isMetric) { 177 | conditions->precipitationToday = value + "mm"; 178 | } 179 | if (currentKey == "precip_today_in" && !isMetric) { 180 | conditions->precipitationToday = value + "in"; 181 | } 182 | 183 | } 184 | 185 | void WundergroundConditions::endArray() { 186 | 187 | } 188 | 189 | 190 | void WundergroundConditions::startObject() { 191 | currentParent = currentKey; 192 | } 193 | 194 | void WundergroundConditions::endObject() { 195 | currentParent = ""; 196 | } 197 | 198 | void WundergroundConditions::endDocument() { 199 | 200 | } 201 | 202 | void WundergroundConditions::startArray() { 203 | 204 | } 205 | 206 | 207 | String WundergroundConditions::getMeteoconIcon(String iconText) { 208 | if (iconText == "chanceflurries") return "F"; 209 | if (iconText == "chancerain") return "Q"; 210 | if (iconText == "chancesleet") return "W"; 211 | if (iconText == "chancesnow") return "V"; 212 | if (iconText == "chancetstorms") return "S"; 213 | if (iconText == "clear") return "B"; 214 | if (iconText == "cloudy") return "Y"; 215 | if (iconText == "flurries") return "F"; 216 | if (iconText == "fog") return "M"; 217 | if (iconText == "hazy") return "E"; 218 | if (iconText == "mostlycloudy") return "Y"; 219 | if (iconText == "mostlysunny") return "H"; 220 | if (iconText == "partlycloudy") return "H"; 221 | if (iconText == "partlysunny") return "J"; 222 | if (iconText == "sleet") return "W"; 223 | if (iconText == "rain") return "R"; 224 | if (iconText == "snow") return "W"; 225 | if (iconText == "sunny") return "B"; 226 | if (iconText == "tstorms") return "0"; 227 | 228 | if (iconText == "nt_chanceflurries") return "F"; 229 | if (iconText == "nt_chancerain") return "7"; 230 | if (iconText == "nt_chancesleet") return "#"; 231 | if (iconText == "nt_chancesnow") return "#"; 232 | if (iconText == "nt_chancetstorms") return "&"; 233 | if (iconText == "nt_clear") return "2"; 234 | if (iconText == "nt_cloudy") return "Y"; 235 | if (iconText == "nt_flurries") return "9"; 236 | if (iconText == "nt_fog") return "M"; 237 | if (iconText == "nt_hazy") return "E"; 238 | if (iconText == "nt_mostlycloudy") return "5"; 239 | if (iconText == "nt_mostlysunny") return "3"; 240 | if (iconText == "nt_partlycloudy") return "4"; 241 | if (iconText == "nt_partlysunny") return "4"; 242 | if (iconText == "nt_sleet") return "9"; 243 | if (iconText == "nt_rain") return "7"; 244 | if (iconText == "nt_snow") return "#"; 245 | if (iconText == "nt_sunny") return "4"; 246 | if (iconText == "nt_tstorms") return "&"; 247 | 248 | return ")"; 249 | } 250 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WundergroundAlerts.cpp: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | 27 | # if defined(ESP8266) 28 | #include 29 | #include 30 | #endif 31 | # if defined(ESP32) 32 | #include 33 | #include 34 | #endif 35 | 36 | #include 37 | #include "WundergroundAlerts.h" 38 | 39 | WundergroundAlerts::WundergroundAlerts() { 40 | 41 | } 42 | void WundergroundAlerts::updateAlerts(WGAlert *alerts, uint8_t maxAlerts, String apiKey, String language, String country, String city) { 43 | currentAlert = 0; 44 | activeAlertsCnt = 0; 45 | isAlerts = true; 46 | if (country == "US") { 47 | isAlertUS = true; 48 | isAlertEU = false; 49 | } else { 50 | isAlertUS = false; 51 | isAlertEU = true; 52 | } 53 | doUpdate(alerts, maxAlerts, "http://api.wunderground.com/api/" + apiKey + "/alerts/lang:" + language + "/q/" + country + "/" + city + ".json"); 54 | } 55 | // end fowlerk add 56 | 57 | void WundergroundAlerts::updateAlertsPWS(WGAlert *alert, uint8_t maxAlerts, String apiKey, String language, String country, String pws) { 58 | currentAlert = 0; 59 | activeAlertsCnt = 0; 60 | isAlerts = true; 61 | if (country == "US") { 62 | isAlertUS = true; 63 | isAlertEU = false; 64 | } else { 65 | isAlertUS = false; 66 | isAlertEU = true; 67 | } 68 | doUpdate(alerts, maxAlerts, "http://api.wunderground.com/api/" + apiKey + "/alerts/lang:" + language + "/q/pws:" + pws + ".json"); 69 | } 70 | 71 | void WundergroundAlerts::doUpdate(WGAlert *alerts, uint8_t maxAlerts, String url) { 72 | this->alerts = alerts; 73 | this->maxAlerts = maxAlerts; 74 | JsonStreamingParser parser; 75 | parser.setListener(this); 76 | 77 | HTTPClient http; 78 | 79 | http.begin(url); 80 | bool isBody = false; 81 | char c; 82 | int size; 83 | Serial.print("[HTTP] GET...\n"); 84 | // start connection and send HTTP header 85 | int httpCode = http.GET(); 86 | Serial.printf("[HTTP] GET... code: %d\n", httpCode); 87 | if(httpCode > 0) { 88 | 89 | 90 | 91 | WiFiClient * client = http.getStreamPtr(); 92 | 93 | while(client->connected()) { 94 | while((size = client->available()) > 0) { 95 | c = client->read(); 96 | if (c == '{' || c == '[') { 97 | 98 | isBody = true; 99 | } 100 | if (isBody) { 101 | parser.parse(c); 102 | } 103 | } 104 | } 105 | } 106 | this->alerts = nullptr; 107 | } 108 | 109 | void WundergroundAlerts::whitespace(char c) { 110 | Serial.println("whitespace"); 111 | } 112 | 113 | void WundergroundAlerts::startDocument() { 114 | Serial.println("start document"); 115 | } 116 | 117 | void WundergroundAlerts::key(String key) { 118 | currentKey = String(key); 119 | } 120 | 121 | void WundergroundAlerts::value(String value) { 122 | if (currentKey == "type" && isAlerts) { 123 | activeAlertsCnt++; 124 | currentAlert++; 125 | alerts[currentAlert-1].activeAlerts = value; 126 | Serial.print("Alert type processed, value: "); 127 | Serial.println(alerts[currentAlert-1].activeAlerts); 128 | } 129 | if (currentKey == "description" && isAlerts && isAlertUS) { 130 | alerts[currentAlert-1].activeAlertsText = value; 131 | Serial.print("Alert description processed, value: "); 132 | Serial.println(alerts[currentAlert-1].activeAlertsText); 133 | } 134 | if (currentKey == "wtype_meteoalarm_name" && isAlerts && isAlertEU) { 135 | alerts[currentAlert-1].activeAlertsText = value; 136 | Serial.print("Alert description processed, value: "); 137 | Serial.println(alerts[currentAlert-1].activeAlertsText); 138 | } 139 | if (currentKey == "message" && isAlerts) { 140 | alerts[currentAlert-1].activeAlertsMessage = value; 141 | Serial.print("Alert msg length: "); 142 | Serial.println(alerts[currentAlert-1].activeAlertsMessage.length()); 143 | if(alerts[currentAlert-1].activeAlertsMessage.length() >= 511) { 144 | alerts[currentAlert-1].activeAlertsMessageTrunc = true; 145 | } else { 146 | alerts[currentAlert-1].activeAlertsMessageTrunc = false; 147 | } 148 | Serial.print("Alert message processed, value: "); 149 | Serial.println(alerts[currentAlert-1].activeAlertsMessage); 150 | } 151 | if (currentKey == "date" && isAlerts) { 152 | alerts[currentAlert-1].activeAlertsStart = value; 153 | // Check last char for a "/"; the returned value sometimes includes this; if so, strip it (47 is a "/" char) 154 | if (alerts[currentAlert-1].activeAlertsStart.charAt(alerts[currentAlert-1].activeAlertsStart.length()-1) == 47) { 155 | Serial.println("...last char is a slash..."); 156 | alerts[currentAlert-1].activeAlertsStart = alerts[currentAlert-1].activeAlertsStart.substring(0,(alerts[currentAlert-1].activeAlertsStart.length()-1)); 157 | } 158 | // For meteoalarms, the start field is returned with the UTC=0 by default (not used?) 159 | if (isAlertEU && alerts[currentAlert-1].activeAlertsStart == "1970-01-01 00:00:00 GMT") { 160 | alerts[currentAlert-1].activeAlertsStart = ""; 161 | } 162 | Serial.print("Alert start processed, value: "); 163 | Serial.println(alerts[currentAlert-1].activeAlertsStart); 164 | } 165 | if (currentKey == "expires" && isAlerts) { 166 | alerts[currentAlert-1].activeAlertsEnd = value; 167 | Serial.print("Alert expiration processed, value: "); 168 | Serial.println(alerts[currentAlert-1].activeAlertsEnd); 169 | } 170 | if (currentKey == "phenomena" && isAlerts) { 171 | alerts[currentAlert-1].activeAlertsPhenomena = value; 172 | Serial.print("Alert phenomena processed, value: "); 173 | Serial.println(alerts[currentAlert-1].activeAlertsPhenomena); 174 | } 175 | if (currentKey == "significance" && isAlerts && isAlertUS) { 176 | alerts[currentAlert-1].activeAlertsSignificance = value; 177 | Serial.print("Alert significance processed, value: "); 178 | Serial.println(alerts[currentAlert-1].activeAlertsSignificance); 179 | } 180 | // Map meteoalarm level to the field for significance for consistency (used for European alerts) 181 | if (currentKey == "level_meteoalarm" && isAlerts && isAlertEU) { 182 | alerts[currentAlert-1].activeAlertsSignificance = value; 183 | Serial.print("Meteo alert significance processed, value: "); 184 | Serial.println(alerts[currentAlert-1].activeAlertsSignificance); 185 | } 186 | // For meteoalarms only (European alerts); attribution must be displayed according to the T&C's of use 187 | if (currentKey == "attribution" && isAlerts) { 188 | alerts[currentAlert-1].activeAlertsAttribution = value; 189 | // Remove some of the markup in the attribution 190 | alerts[currentAlert-1].activeAlertsAttribution.replace(" "," "); 193 | } 194 | 195 | } 196 | 197 | void WundergroundAlerts::endArray() { 198 | 199 | } 200 | 201 | 202 | void WundergroundAlerts::startObject() { 203 | currentParent = currentKey; 204 | } 205 | 206 | void WundergroundAlerts::endObject() { 207 | currentParent = ""; 208 | } 209 | 210 | void WundergroundAlerts::endDocument() { 211 | 212 | } 213 | 214 | void WundergroundAlerts::startArray() { 215 | 216 | } 217 | 218 | int WundergroundAlerts::getActiveAlertsCnt() { 219 | return activeAlertsCnt; 220 | } 221 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/src/WundergroundForecast.cpp: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2015 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | # if defined(ESP8266) 27 | #include 28 | #include 29 | #endif 30 | # if defined(ESP32) 31 | #include 32 | #include 33 | #endif 34 | 35 | #include 36 | #include "WundergroundForecast.h" 37 | 38 | WundergroundForecast::WundergroundForecast(boolean _isMetric) { 39 | isMetric = _isMetric; 40 | } 41 | 42 | void WundergroundForecast::setMetric(bool isMetric) { 43 | this->isMetric = isMetric; 44 | } 45 | 46 | void WundergroundForecast::updateForecast(WGForecast *forecasts, uint8_t maxForecasts, String apiKey, String language, String country, String city) { 47 | doUpdate(forecasts, maxForecasts, "http://api.wunderground.com/api/" + apiKey + "/forecast10day/lang:" + language + "/q/" + country + "/" + city + ".json"); 48 | } 49 | 50 | 51 | void WundergroundForecast::updateForecastPWS(WGForecast *forecasts, uint8_t maxForecasts, String apiKey, String language, String pws) { 52 | doUpdate(forecasts, maxForecasts, "http://api.wunderground.com/api/" + apiKey + "/forecast10day/lang:" + language + "/q/pws:" + pws + ".json"); 53 | } 54 | 55 | void WundergroundForecast::updateForecastZMW(WGForecast *forecasts, uint8_t maxForecasts, String apiKey, String language, String zmwCode) { 56 | doUpdate(forecasts, maxForecasts, "http://api.wunderground.com/api/" + apiKey + "/forecast10day/lang:" + language + "/q/zmw:" + zmwCode + ".json"); 57 | } 58 | 59 | void WundergroundForecast::doUpdate(WGForecast *forecasts, uint8_t maxForecasts, String url) { 60 | this->forecasts = forecasts; 61 | this->maxForecasts = maxForecasts; 62 | JsonStreamingParser parser; 63 | parser.setListener(this); 64 | 65 | HTTPClient http; 66 | 67 | http.begin(url); 68 | bool isBody = false; 69 | char c; 70 | int size; 71 | Serial.print("[HTTP] GET...\n"); 72 | // start connection and send HTTP header 73 | int httpCode = http.GET(); 74 | Serial.printf("[HTTP] GET... code: %d\n", httpCode); 75 | if(httpCode > 0) { 76 | 77 | 78 | 79 | WiFiClient * client = http.getStreamPtr(); 80 | 81 | while(client->connected()) { 82 | while((size = client->available()) > 0) { 83 | c = client->read(); 84 | if (c == '{' || c == '[') { 85 | 86 | isBody = true; 87 | } 88 | if (isBody) { 89 | parser.parse(c); 90 | } 91 | } 92 | } 93 | } 94 | this->forecasts = nullptr; 95 | } 96 | 97 | void WundergroundForecast::whitespace(char c) { 98 | Serial.println("whitespace"); 99 | } 100 | 101 | void WundergroundForecast::startDocument() { 102 | Serial.println("start document"); 103 | } 104 | 105 | void WundergroundForecast::key(String key) { 106 | currentKey = String(key); 107 | if (currentKey == "simpleforecast") { 108 | isSimpleForecast = true; 109 | } 110 | 111 | } 112 | 113 | void WundergroundForecast::value(String value) { 114 | if (currentKey == "local_epoch") { 115 | localEpoc = value.toInt(); 116 | localMillisAtUpdate = millis(); 117 | } 118 | 119 | if (currentKey == "period") { 120 | currentForecastPeriod = value.toInt(); 121 | } 122 | 123 | if (currentKey == "icon" && currentForecastPeriod < maxForecasts) { 124 | forecasts[currentForecastPeriod].forecastIcon = value; 125 | } 126 | if (currentKey == "title" && currentForecastPeriod < maxForecasts) { 127 | Serial.println(String(currentForecastPeriod) + ": " + value); 128 | forecasts[currentForecastPeriod].forecastTitle = value; 129 | } 130 | 131 | // Added forecastText key following...fowlerk, 12/3/16 132 | if (currentKey == "fcttext" && !isMetric && currentForecastPeriod < maxForecasts) { 133 | forecasts[currentForecastPeriod].forecastText = value; 134 | } 135 | // Added option for metric forecast following...fowlerk, 12/22/16 136 | if (currentKey == "fcttext_metric" && isMetric && currentForecastPeriod < maxForecasts) { 137 | forecasts[currentForecastPeriod].forecastText = value; 138 | } 139 | 140 | // Added PoP (probability of precipitation) key following...fowlerk, 12/22/16 141 | if (currentKey == "pop" && currentForecastPeriod < maxForecasts) { 142 | forecasts[currentForecastPeriod].PoP = value; 143 | } 144 | 145 | 146 | // The detailed forecast period has only one forecast per day with low/high for both 147 | // night and day, starting at index 1. 148 | int dailyForecastPeriod = (currentForecastPeriod - 1) * 2; 149 | 150 | if (currentKey == "fahrenheit" && !isMetric && dailyForecastPeriod < maxForecasts) { 151 | 152 | if (currentParent == "high") { 153 | forecasts[dailyForecastPeriod].forecastHighTemp = value; 154 | } 155 | if (currentParent == "low") { 156 | forecasts[dailyForecastPeriod].forecastLowTemp = value; 157 | } 158 | } 159 | if (currentKey == "celsius" && isMetric && dailyForecastPeriod < maxForecasts) { 160 | 161 | if (currentParent == "high") { 162 | Serial.println(String(currentForecastPeriod)+ ": " + value); 163 | forecasts[dailyForecastPeriod].forecastHighTemp = value; 164 | } 165 | if (currentParent == "low") { 166 | forecasts[dailyForecastPeriod].forecastLowTemp = value; 167 | } 168 | } 169 | 170 | if (currentKey == "month" && isSimpleForecast && currentForecastPeriod < maxForecasts) { 171 | // Handle transition from txtforecast to simpleforecast, as 172 | // the key "period" doesn't appear until after some of the key values needed and is 173 | // used as an array index. 174 | if (isSimpleForecast && currentForecastPeriod == 19) { 175 | currentForecastPeriod = 0; 176 | } 177 | forecasts[currentForecastPeriod].forecastMonth = value; 178 | } 179 | 180 | if (currentKey == "day" && isSimpleForecast && currentForecastPeriod < maxForecasts) { 181 | // Handle transition from txtforecast to simpleforecast, as 182 | // the key "period" doesn't appear until after some of the key values needed and is 183 | // used as an array index. 184 | if (isSimpleForecast && currentForecastPeriod == 19) { 185 | currentForecastPeriod = 0; 186 | } 187 | forecasts[currentForecastPeriod].forecastDay = value; 188 | } 189 | // end fowlerk add 190 | 191 | } 192 | 193 | void WundergroundForecast::endArray() { 194 | 195 | } 196 | 197 | 198 | void WundergroundForecast::startObject() { 199 | currentParent = currentKey; 200 | } 201 | 202 | void WundergroundForecast::endObject() { 203 | currentParent = ""; 204 | } 205 | 206 | void WundergroundForecast::endDocument() { 207 | 208 | } 209 | 210 | void WundergroundForecast::startArray() { 211 | 212 | } 213 | 214 | 215 | 216 | String WundergroundForecast::getMeteoconIcon(String iconText) { 217 | if (iconText == "chanceflurries") return "F"; 218 | if (iconText == "chancerain") return "Q"; 219 | if (iconText == "chancesleet") return "W"; 220 | if (iconText == "chancesnow") return "V"; 221 | if (iconText == "chancetstorms") return "S"; 222 | if (iconText == "clear") return "B"; 223 | if (iconText == "cloudy") return "Y"; 224 | if (iconText == "flurries") return "F"; 225 | if (iconText == "fog") return "M"; 226 | if (iconText == "hazy") return "E"; 227 | if (iconText == "mostlycloudy") return "Y"; 228 | if (iconText == "mostlysunny") return "H"; 229 | if (iconText == "partlycloudy") return "H"; 230 | if (iconText == "partlysunny") return "J"; 231 | if (iconText == "sleet") return "W"; 232 | if (iconText == "rain") return "R"; 233 | if (iconText == "snow") return "W"; 234 | if (iconText == "sunny") return "B"; 235 | if (iconText == "tstorms") return "0"; 236 | 237 | if (iconText == "nt_chanceflurries") return "F"; 238 | if (iconText == "nt_chancerain") return "7"; 239 | if (iconText == "nt_chancesleet") return "#"; 240 | if (iconText == "nt_chancesnow") return "#"; 241 | if (iconText == "nt_chancetstorms") return "&"; 242 | if (iconText == "nt_clear") return "2"; 243 | if (iconText == "nt_cloudy") return "Y"; 244 | if (iconText == "nt_flurries") return "9"; 245 | if (iconText == "nt_fog") return "M"; 246 | if (iconText == "nt_hazy") return "E"; 247 | if (iconText == "nt_mostlycloudy") return "5"; 248 | if (iconText == "nt_mostlysunny") return "3"; 249 | if (iconText == "nt_partlycloudy") return "4"; 250 | if (iconText == "nt_partlysunny") return "4"; 251 | if (iconText == "nt_sleet") return "9"; 252 | if (iconText == "nt_rain") return "7"; 253 | if (iconText == "nt_snow") return "#"; 254 | if (iconText == "nt_sunny") return "4"; 255 | if (iconText == "nt_tstorms") return "&"; 256 | 257 | return ")"; 258 | } 259 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemo/WeatherStationDemo.ino: -------------------------------------------------------------------------------- 1 | /**The MIT License (MIT) 2 | 3 | Copyright (c) 2016 by Daniel Eichhorn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | See more at http://blog.squix.ch 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include "SSD1306Wire.h" 30 | #include "OLEDDisplayUi.h" 31 | #include "Wire.h" 32 | #include "WundergroundClient.h" 33 | #include "WeatherStationFonts.h" 34 | #include "WeatherStationImages.h" 35 | #include "TimeClient.h" 36 | #include "ThingspeakClient.h" 37 | 38 | /*************************** 39 | * Begin Settings 40 | **************************/ 41 | // Please read http://blog.squix.org/weatherstation-getting-code-adapting-it 42 | // for setup instructions 43 | 44 | // WIFI 45 | const char* WIFI_SSID = "yourssid"; 46 | const char* WIFI_PWD = "yourpassw0rd"; 47 | 48 | 49 | // Setup 50 | const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes 51 | 52 | // Display Settings 53 | const int I2C_DISPLAY_ADDRESS = 0x3c; 54 | const int SDA_PIN = D3; 55 | const int SDC_PIN = D4; 56 | 57 | // TimeClient settings 58 | const float UTC_OFFSET = 2; 59 | 60 | // Wunderground Settings 61 | const boolean IS_METRIC = true; 62 | const String WUNDERGRROUND_API_KEY = "WUNDERGROUND_API_KEY"; 63 | const String WUNDERGRROUND_LANGUAGE = "DL"; 64 | const String WUNDERGROUND_COUNTRY = "CH"; 65 | const String WUNDERGROUND_CITY = "Zurich"; 66 | 67 | //Thingspeak Settings 68 | const String THINGSPEAK_CHANNEL_ID = "67284"; 69 | const String THINGSPEAK_API_READ_KEY = "L2VIW20QVNZJBLAK"; 70 | 71 | // Initialize the oled display for address 0x3c 72 | // sda-pin=14 and sdc-pin=12 73 | SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN); 74 | OLEDDisplayUi ui( &display ); 75 | 76 | /*************************** 77 | * End Settings 78 | **************************/ 79 | 80 | TimeClient timeClient(UTC_OFFSET); 81 | 82 | // Set to false, if you prefere imperial/inches, Fahrenheit 83 | WundergroundClient wunderground(IS_METRIC); 84 | 85 | ThingspeakClient thingspeak; 86 | 87 | // flag changed in the ticker function every 10 minutes 88 | bool readyForWeatherUpdate = false; 89 | 90 | String lastUpdate = "--"; 91 | 92 | Ticker ticker; 93 | 94 | //declaring prototypes 95 | void drawProgress(OLEDDisplay *display, int percentage, String label); 96 | void updateData(OLEDDisplay *display); 97 | void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); 98 | void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); 99 | void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); 100 | void drawThingspeak(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); 101 | void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex); 102 | void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state); 103 | void setReadyForWeatherUpdate(); 104 | 105 | 106 | // Add frames 107 | // this array keeps function pointers to all frames 108 | // frames are the single views that slide from right to left 109 | FrameCallback frames[] = { drawDateTime, drawCurrentWeather, drawForecast, drawThingspeak }; 110 | int numberOfFrames = 4; 111 | 112 | OverlayCallback overlays[] = { drawHeaderOverlay }; 113 | int numberOfOverlays = 1; 114 | 115 | void setup() { 116 | Serial.begin(115200); 117 | Serial.println(); 118 | Serial.println(); 119 | 120 | // initialize dispaly 121 | display.init(); 122 | display.clear(); 123 | display.display(); 124 | 125 | //display.flipScreenVertically(); 126 | display.setFont(ArialMT_Plain_10); 127 | display.setTextAlignment(TEXT_ALIGN_CENTER); 128 | display.setContrast(255); 129 | 130 | WiFi.begin(WIFI_SSID, WIFI_PWD); 131 | 132 | int counter = 0; 133 | while (WiFi.status() != WL_CONNECTED) { 134 | delay(500); 135 | Serial.print("."); 136 | display.clear(); 137 | display.drawString(64, 10, "Connecting to WiFi"); 138 | display.drawXbm(46, 30, 8, 8, counter % 3 == 0 ? activeSymbole : inactiveSymbole); 139 | display.drawXbm(60, 30, 8, 8, counter % 3 == 1 ? activeSymbole : inactiveSymbole); 140 | display.drawXbm(74, 30, 8, 8, counter % 3 == 2 ? activeSymbole : inactiveSymbole); 141 | display.display(); 142 | 143 | counter++; 144 | } 145 | 146 | ui.setTargetFPS(30); 147 | 148 | ui.setActiveSymbol(activeSymbole); 149 | ui.setInactiveSymbol(inactiveSymbole); 150 | 151 | // You can change this to 152 | // TOP, LEFT, BOTTOM, RIGHT 153 | ui.setIndicatorPosition(BOTTOM); 154 | 155 | // Defines where the first frame is located in the bar. 156 | ui.setIndicatorDirection(LEFT_RIGHT); 157 | 158 | // You can change the transition that is used 159 | // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN 160 | ui.setFrameAnimation(SLIDE_LEFT); 161 | 162 | ui.setFrames(frames, numberOfFrames); 163 | 164 | ui.setOverlays(overlays, numberOfOverlays); 165 | 166 | // Inital UI takes care of initalising the display too. 167 | ui.init(); 168 | 169 | Serial.println(""); 170 | 171 | updateData(&display); 172 | 173 | ticker.attach(UPDATE_INTERVAL_SECS, setReadyForWeatherUpdate); 174 | 175 | } 176 | 177 | void loop() { 178 | 179 | if (readyForWeatherUpdate && ui.getUiState()->frameState == FIXED) { 180 | updateData(&display); 181 | } 182 | 183 | int remainingTimeBudget = ui.update(); 184 | 185 | if (remainingTimeBudget > 0) { 186 | // You can do some work here 187 | // Don't do stuff if you are below your 188 | // time budget. 189 | delay(remainingTimeBudget); 190 | } 191 | 192 | 193 | } 194 | 195 | void drawProgress(OLEDDisplay *display, int percentage, String label) { 196 | display->clear(); 197 | display->setTextAlignment(TEXT_ALIGN_CENTER); 198 | display->setFont(ArialMT_Plain_10); 199 | display->drawString(64, 10, label); 200 | display->drawProgressBar(2, 28, 124, 10, percentage); 201 | display->display(); 202 | } 203 | 204 | void updateData(OLEDDisplay *display) { 205 | drawProgress(display, 10, "Updating time..."); 206 | timeClient.updateTime(); 207 | drawProgress(display, 30, "Updating conditions..."); 208 | wunderground.updateConditions(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY); 209 | drawProgress(display, 50, "Updating forecasts..."); 210 | wunderground.updateForecast(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY); 211 | drawProgress(display, 80, "Updating thingspeak..."); 212 | thingspeak.getLastChannelItem(THINGSPEAK_CHANNEL_ID, THINGSPEAK_API_READ_KEY); 213 | lastUpdate = timeClient.getFormattedTime(); 214 | readyForWeatherUpdate = false; 215 | drawProgress(display, 100, "Done..."); 216 | delay(1000); 217 | } 218 | 219 | 220 | 221 | void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { 222 | display->setTextAlignment(TEXT_ALIGN_CENTER); 223 | display->setFont(ArialMT_Plain_10); 224 | String date = wunderground.getDate(); 225 | int textWidth = display->getStringWidth(date); 226 | display->drawString(64 + x, 5 + y, date); 227 | display->setFont(ArialMT_Plain_24); 228 | String time = timeClient.getFormattedTime(); 229 | textWidth = display->getStringWidth(time); 230 | display->drawString(64 + x, 15 + y, time); 231 | display->setTextAlignment(TEXT_ALIGN_LEFT); 232 | } 233 | 234 | void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { 235 | display->setFont(ArialMT_Plain_10); 236 | display->setTextAlignment(TEXT_ALIGN_LEFT); 237 | display->drawString(60 + x, 5 + y, wunderground.getWeatherText()); 238 | 239 | display->setFont(ArialMT_Plain_24); 240 | String temp = wunderground.getCurrentTemp() + "°C"; 241 | display->drawString(60 + x, 15 + y, temp); 242 | int tempWidth = display->getStringWidth(temp); 243 | 244 | display->setFont(Meteocons_Plain_42); 245 | String weatherIcon = wunderground.getTodayIcon(); 246 | int weatherIconWidth = display->getStringWidth(weatherIcon); 247 | display->drawString(32 + x - weatherIconWidth / 2, 05 + y, weatherIcon); 248 | } 249 | 250 | 251 | void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { 252 | drawForecastDetails(display, x, y, 0); 253 | drawForecastDetails(display, x + 44, y, 2); 254 | drawForecastDetails(display, x + 88, y, 4); 255 | } 256 | 257 | void drawThingspeak(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { 258 | display->setTextAlignment(TEXT_ALIGN_CENTER); 259 | display->setFont(ArialMT_Plain_10); 260 | display->drawString(64 + x, 0 + y, "Outdoor"); 261 | display->setFont(ArialMT_Plain_16); 262 | display->drawString(64 + x, 10 + y, thingspeak.getFieldValue(0) + "°C"); 263 | display->drawString(64 + x, 30 + y, thingspeak.getFieldValue(1) + "%"); 264 | } 265 | 266 | void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex) { 267 | display->setTextAlignment(TEXT_ALIGN_CENTER); 268 | display->setFont(ArialMT_Plain_10); 269 | String day = wunderground.getForecastTitle(dayIndex).substring(0, 3); 270 | day.toUpperCase(); 271 | display->drawString(x + 20, y, day); 272 | 273 | display->setFont(Meteocons_Plain_21); 274 | display->drawString(x + 20, y + 12, wunderground.getForecastIcon(dayIndex)); 275 | 276 | display->setFont(ArialMT_Plain_10); 277 | display->drawString(x + 20, y + 34, wunderground.getForecastLowTemp(dayIndex) + "|" + wunderground.getForecastHighTemp(dayIndex)); 278 | display->setTextAlignment(TEXT_ALIGN_LEFT); 279 | } 280 | 281 | void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) { 282 | display->setColor(WHITE); 283 | display->setFont(ArialMT_Plain_10); 284 | String time = timeClient.getFormattedTime().substring(0, 5); 285 | display->setTextAlignment(TEXT_ALIGN_LEFT); 286 | display->drawString(0, 54, time); 287 | display->setTextAlignment(TEXT_ALIGN_RIGHT); 288 | String temp = wunderground.getCurrentTemp() + "°C"; 289 | display->drawString(128, 54, temp); 290 | display->drawHorizontalLine(0, 52, 128); 291 | } 292 | 293 | void setReadyForWeatherUpdate() { 294 | Serial.println("Setting readyForUpdate to true"); 295 | readyForWeatherUpdate = true; 296 | } 297 | -------------------------------------------------------------------------------- /esp8266-weather-station-master/examples/WeatherStationDemoExtendedDST/DSEG7Classic-BoldFont.h: -------------------------------------------------------------------------------- 1 | /****************************************************** 2 | [Name] 7-segment Font DSEG7 Family 3 | [Version] 0.30(2015.07.20) 4 | [File Type] Derived from TTF(True Type Font) 5 | [License] Free(See link for details) 6 | [Copyrights] Keshikan(http://www.keshikan.net/fonts-e.html) 7 | ******************************************************/ 8 | 9 | // Converted by FontConverterV3.java written by Squix78 http://oleddisplay.squix.ch/ Consider a donation 10 | // In case of problems make sure that you are using the font file with the correct version! 11 | const char DSEG7_Classic_Bold_21[] PROGMEM = { 12 | 0x11, // Width: 17 13 | 0x17, // Height: 23 14 | 0x20, // First Char: 32 15 | 0x1B, // Numbers of Chars: 27 16 | 17 | // Jump Table: 18 | 0xFF, 0xFF, 0x00, 0x04, // 32:65535 19 | 0x00, 0x00, 0x15, 0x08, // 33:0 20 | 0x00, 0x15, 0x15, 0x08, // 34:21 21 | 0x00, 0x2A, 0x15, 0x08, // 35:42 22 | 0x00, 0x3F, 0x15, 0x08, // 36:63 23 | 0x00, 0x54, 0x15, 0x08, // 37:84 24 | 0x00, 0x69, 0x15, 0x08, // 38:105 25 | 0x00, 0x7E, 0x15, 0x08, // 39:126 26 | 0x00, 0x93, 0x15, 0x08, // 40:147 27 | 0x00, 0xA8, 0x15, 0x08, // 41:168 28 | 0x00, 0xBD, 0x15, 0x08, // 42:189 29 | 0x00, 0xD2, 0x15, 0x08, // 43:210 30 | 0x00, 0xE7, 0x15, 0x08, // 44:231 31 | 0x00, 0xFC, 0x26, 0x11, // 45:252 32 | 0xFF, 0xFF, 0x00, 0x00, // 46:65535 33 | 0x01, 0x22, 0x15, 0x08, // 47:290 34 | 0x01, 0x37, 0x2D, 0x11, // 48:311 35 | 0x01, 0x64, 0x2D, 0x11, // 49:356 36 | 0x01, 0x91, 0x2C, 0x11, // 50:401 37 | 0x01, 0xBD, 0x2D, 0x11, // 51:445 38 | 0x01, 0xEA, 0x2D, 0x11, // 52:490 39 | 0x02, 0x17, 0x2D, 0x11, // 53:535 40 | 0x02, 0x44, 0x2D, 0x11, // 54:580 41 | 0x02, 0x71, 0x2D, 0x11, // 55:625 42 | 0x02, 0x9E, 0x2D, 0x11, // 56:670 43 | 0x02, 0xCB, 0x2D, 0x11, // 57:715 44 | 0x02, 0xF8, 0x09, 0x04, // 58:760 45 | 46 | // Font Data: 47 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 33 48 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 34 49 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 35 50 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 36 51 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 37 52 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 38 53 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 39 54 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 40 55 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 41 56 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 42 57 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 43 58 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 44 59 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x10, // 45 60 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 47 61 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xEF,0x3F,0xF4,0xEF,0x5F,0xEC,0xC7,0x6F,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0x1C,0x00,0x70,0xEC,0xC7,0x6F,0xF4,0xEF,0x5F,0xF8,0xEF,0x3F, // 48 62 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xC7,0x0F,0xF0,0xEF,0x1F,0xF8,0xEF,0x3F, // 49 63 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x3F,0x04,0xE0,0x5F,0x0C,0xD0,0x6F,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0xEC,0x17,0x60,0xF4,0x0F,0x40,0xF8,0x0F, // 50 64 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x40,0x0C,0x10,0x60,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0xEC,0xD7,0x6F,0xF4,0xEF,0x5F,0xF8,0xEF,0x3F, // 51 65 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x0F,0x00,0xF0,0x0F,0x00,0xE0,0x17,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0xE0,0xD7,0x0F,0xF0,0xEF,0x1F,0xF8,0xEF,0x3F, // 52 66 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x0F,0x00,0xF4,0x0F,0x40,0xEC,0x17,0x60,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x0C,0xD0,0x6F,0x04,0xE0,0x5F,0x00,0xE0,0x3F, // 53 67 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xEF,0x3F,0xF4,0xEF,0x5F,0xEC,0xD7,0x6F,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x0C,0xD0,0x6F,0x04,0xE0,0x5F,0x00,0xE0,0x3F, // 54 68 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x0F,0x00,0xF4,0x0F,0x00,0xEC,0x07,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0xEC,0xC7,0x0F,0xF4,0xEF,0x1F,0xF8,0xEF,0x3F, // 55 69 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xEF,0x3F,0xF4,0xEF,0x5F,0xEC,0xD7,0x6F,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0xEC,0xD7,0x6F,0xF4,0xEF,0x5F,0xF8,0xEF,0x3F, // 56 70 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x0F,0x00,0xF4,0x0F,0x40,0xEC,0x17,0x60,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0x1C,0x38,0x70,0xEC,0xD7,0x6F,0xF4,0xEF,0x5F,0xF8,0xEF,0x3F, // 57 71 | 0x00,0x00,0x00,0x80,0x03,0x03,0x80,0x03,0x03 // 58 72 | }; 73 | 74 | // Created by http://oleddisplay.squix.ch/ Consider a donation 75 | // In case of problems make sure that you are using the font file with the correct version! 76 | const char DSEG7_Classic_Regular_21[] PROGMEM = { 77 | 0x11, // Width: 17 78 | 0x17, // Height: 23 79 | 0x20, // First Char: 32 80 | 0x1B, // Numbers of Chars: 27 81 | 82 | // Jump Table: 83 | 0xFF, 0xFF, 0x00, 0x04, // 32:65535 84 | 0x00, 0x00, 0x15, 0x08, // 33:0 85 | 0x00, 0x15, 0x15, 0x08, // 34:21 86 | 0x00, 0x2A, 0x15, 0x08, // 35:42 87 | 0x00, 0x3F, 0x15, 0x08, // 36:63 88 | 0x00, 0x54, 0x15, 0x08, // 37:84 89 | 0x00, 0x69, 0x15, 0x08, // 38:105 90 | 0x00, 0x7E, 0x15, 0x08, // 39:126 91 | 0x00, 0x93, 0x15, 0x08, // 40:147 92 | 0x00, 0xA8, 0x15, 0x08, // 41:168 93 | 0x00, 0xBD, 0x15, 0x08, // 42:189 94 | 0x00, 0xD2, 0x15, 0x08, // 43:210 95 | 0x00, 0xE7, 0x15, 0x08, // 44:231 96 | 0x00, 0xFC, 0x29, 0x11, // 45:252 97 | 0xFF, 0xFF, 0x00, 0x00, // 46:65535 98 | 0x01, 0x25, 0x15, 0x08, // 47:293 99 | 0x01, 0x3A, 0x2D, 0x11, // 48:314 100 | 0x01, 0x67, 0x2D, 0x11, // 49:359 101 | 0x01, 0x94, 0x2C, 0x11, // 50:404 102 | 0x01, 0xC0, 0x2D, 0x11, // 51:448 103 | 0x01, 0xED, 0x2D, 0x11, // 52:493 104 | 0x02, 0x1A, 0x2D, 0x11, // 53:538 105 | 0x02, 0x47, 0x2D, 0x11, // 54:583 106 | 0x02, 0x74, 0x2D, 0x11, // 55:628 107 | 0x02, 0xA1, 0x2D, 0x11, // 56:673 108 | 0x02, 0xCE, 0x2D, 0x11, // 57:718 109 | 0x02, 0xFB, 0x09, 0x04, // 58:763 110 | 111 | // Font Data: 112 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 33 113 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 34 114 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 35 115 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 36 116 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 37 117 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 38 118 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 39 119 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 40 120 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 41 121 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 42 122 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 43 123 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 44 124 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10, // 45 125 | 0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0xFE,0x7F, // 47 126 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xEF,0x3F,0xF4,0xC7,0x5F,0x0C,0x00,0x60,0x0C,0x00,0x60,0x0C,0x00,0x60,0x0C,0x00,0x60,0x0C,0x00,0x60,0x0C,0x00,0x60,0x0C,0x00,0x60,0x0C,0x00,0x60,0x0C,0x00,0x60,0xF4,0xC7,0x5F,0xF8,0xEF,0x3F, // 48 127 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xC7,0x1F,0xF8,0xEF,0x3F, // 49 128 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x3F,0x04,0xD0,0x5F,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0xF4,0x17,0x40,0xF8,0x0F, // 50 129 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x40,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0xF4,0xD7,0x5F,0xF8,0xEF,0x3F, // 51 130 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x0F,0x00,0xF0,0x17,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0xF0,0xD7,0x1F,0xF8,0xEF,0x3F, // 52 131 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x0F,0x00,0xF4,0x17,0x40,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x04,0xD0,0x5F,0x00,0xE0,0x3F, // 53 132 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xEF,0x3F,0xF4,0xD7,0x5F,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x04,0xD0,0x5F,0x00,0xE0,0x3F, // 54 133 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x0F,0x00,0xF4,0x07,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0xF4,0xC7,0x1F,0xF8,0xEF,0x3F, // 55 134 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xEF,0x3F,0xF4,0xD7,0x5F,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0xF4,0xD7,0x5F,0xF8,0xEF,0x3F, // 56 135 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x0F,0x00,0xF4,0x17,0x40,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0x0C,0x10,0x60,0xF4,0xD7,0x5F,0xF8,0xEF,0x3F, // 57 136 | 0x00,0x00,0x00,0x80,0x03,0x03,0x80,0x03,0x03 // 58 137 | }; 138 | 139 | 140 | 141 | --------------------------------------------------------------------------------