/* Includes ------------------------------------------------------------------*/ #include "env.h" #include "src/epd/epd_cfg.h" #include "src/epd/epd_driver.h" #include "src/epd/epd_paint.h" #include "src/ntpt/ntp.h" #include "src/owm/owm.h" #include "src/sensor/sensor.h" #include "src/touch/gt1151.h" #include "src/influxdb/influx.h" #include #include #include #include #include #define PIN_SDA 18 #define PIN_SCL 23 /* Global Variables -----------------------------------------------------------*/ typedef enum { VIEW_MAIN = 0, VIEW_WEATHER_0, VIEW_WEATHER_1, VIEW_WEATHER_2, VIEW_WEATHER_3, VIEW_TEMP, VIEW_AIR, VIEW_CUSTOM, VIEW_COUNT } views_t; static const uint8_t view_count = 5; static uint8_t view_curr; static const views_t view_tab[view_count] = { VIEW_MAIN, VIEW_WEATHER_0,VIEW_WEATHER_1, VIEW_TEMP,VIEW_AIR }; static WiFiMulti wifiMulti; static TwoWire I2C = TwoWire(0); static strDateTime dateTime = {0}; static Sensor* sensor = new Sensor(&I2C); static GT1151* touch = new GT1151(&I2C); static OWM* owm[6] = {new OWM(LOCATION_0, OPENWEATHER_API), new OWM(LOCATION_1, OPENWEATHER_API), new OWM(LOCATION_2, OPENWEATHER_API), 0,0,0}; static Influx* iflx = new Influx(NULL, owm);//add sensor static NTPtime NTPch(NTP_URL); static bool time_update = false, ntp_update = true, weather_update = true, sensor_update = true, influx_w_update = true, influx_s_update = true, view_update = true, view_refresh = false; static bool shutdownt = false; static int shutdownc = 0; uint8_t *BlackImage; /* IRQ ------------------------------------------------------------------------*/ hw_timer_t * timer = NULL; void IRAM_ATTR onSecondTimer() { dateTime.second += 1; if (dateTime.second == 60) { dateTime.minute += 1; dateTime.second = 0; if (dateTime.minute == 60) { dateTime.hour += 1; dateTime.minute = 0; if (dateTime.hour == 24) { dateTime.hour = 0; dateTime.minute = 0; dateTime.second = 0; } ntp_update = true; } if(dateTime.minute % 5) weather_update = true; if(dateTime.minute % 5) sensor_update = true; if(dateTime.minute % 5) influx_w_update = true; if(dateTime.minute % 5) influx_s_update = true; view_update = true; time_update = true; } if(touch->dev.holding) shutdownc++; else shutdownc = 0; } void IRAM_ATTR onTouch(int8_t contacts, GTPoint *points) { if(touch->dev.holding) return; Serial.printf("Contacts: %d\n", contacts); for (uint8_t i = 0; i < contacts; i++) { Serial.printf("C%d: #%d %d,%d s:%d\n", i, points[i].id, points[i].x, points[i].y, points[i].a); yield(); } if(points[0].x < 125) view_curr = (++view_curr % view_count); else view_curr = (--view_curr % view_count); view_update = true; } //x = 250 to 0 //y = ???? /* Setup Functions -----------------------------------------------------------*/ void setup_EPD(){ //START EPD DEV_Module_Init(); EPD_2IN13_V2_Init(EPD_2IN13_V2_FULL); EPD_2IN13_V2_Clear(); delay(100); //EPD STORAGE uint16_t Imagesize = ((EPD_2IN13_V2_WIDTH % 8 == 0) ? (EPD_2IN13_V2_WIDTH / 8 ) : (EPD_2IN13_V2_WIDTH / 8 + 1)) * EPD_2IN13_V2_HEIGHT; if ((BlackImage = (uint8_t *)malloc(Imagesize)) == NULL) exit(1); Paint_NewImage(BlackImage, EPD_2IN13_V2_WIDTH, EPD_2IN13_V2_HEIGHT, 270, WHITE); Paint_SelectImage(BlackImage); Paint_SetMirroring(MIRROR_HORIZONTAL); Paint_Clear(WHITE); Paint_DrawIcon(89,54, ICON_LOGO, &FontIcon, BLACK, WHITE); Paint_DrawString_EN(29, 5, "Helcel", &Font45, WHITE, BLACK); Paint_SelectImage(BlackImage); EPD_2IN13_V2_Display(BlackImage); delay(100); } void setup_EPD_END(){ Paint_Clear(WHITE); EPD_2IN13_V2_Init(EPD_2IN13_V2_FULL); EPD_2IN13_V2_DisplayPartBaseImage(BlackImage); EPD_2IN13_V2_Init(EPD_2IN13_V2_PART); Paint_SelectImage(BlackImage); } void setup_TOUCH() { touch->setHandler(onTouch); touch->begin(); } void setup_WIFI(){ uint8_t tries = 3; WIFI_REGISTER_AP(wifiMulti); while(wifiMulti.run() != WL_CONNECTED && tries-- >0) delay(500); } void setup_TIMER(){ timer = timerBegin(0, 80, true); timerAttachInterrupt(timer, &onSecondTimer, true); timerAlarmWrite(timer, 1000000, true); timerAlarmEnable(timer); } /* Setup Functions --------------------------------------------------------------*/ void setup(){ Serial.begin(115200); I2C.begin(PIN_SDA, PIN_SCL, 100000); I2C.setPins(PIN_SDA,PIN_SCL); setup_EPD(); setup_TOUCH(); setup_WIFI(); setup_TIMER(); iflx->check(); setup_EPD_END(); } /* Update Functions-------------------------------------------------------------*/ void updateNTP(){ if (!ntp_update) return; if (wifiMulti.run() != WL_CONNECTED) return; strDateTime nDateTime = NTPch.getNTPtime(1.0, 1); if(nDateTime.valid){ dateTime = nDateTime; time_update = true; ntp_update = false; } } void updateWeather(){ if (!weather_update) return; if (wifiMulti.run() != WL_CONNECTED) return; uint8_t i = 0, success = true; while(owm && owm[i]){ success &= owm[i]-> update(); ++i; } if(success) weather_update = false; } void updateTime(){ if (!time_update) return; Paint_ClearWindows(170, EPD_2IN13_V2_WIDTH - Font24.Height, 170 + Font24.Width * 4.5, EPD_2IN13_V2_WIDTH, WHITE); if (!dateTime.valid) return; Paint_DrawTime(170, 98, &dateTime, &Font24, WHITE, BLACK); EPD_2IN13_V2_DisplayPart(BlackImage); time_update = false; } void updateSensor(){ if (!sensor_update) return; sensor->measure(); sensor_update = false; } ICON_tpe getWeatherIcon(int id){ if(id>=200 && id<300){ //Thunder return ICON_CLOUD_THUNDER; }else if(id>=300 && id<400){//Drizzle return ICON_CLOUD_RAIN; }else if(id>=500 && id<600){//Rain return ICON_CLOUD_RAIN; }else if(id>=600 && id<700){//Snow return ICON_CLOUD_SNOW; }else if(id>=700 && id<800){//Warning return ICON_WARN; }else if(id>=800 && id<900){//Clear & Cloudy if(id==800) return ICON_SUN; else if(id==801) return ICON_CLOUD_SUN; else return ICON_CLOUD; }else{ return ICON_WARN; } } void refreshDisplay(){ Paint_Clear(WHITE); EPD_2IN13_V2_Init(EPD_2IN13_V2_FULL); EPD_2IN13_V2_DisplayPartBaseImage(BlackImage); EPD_2IN13_V2_Init(EPD_2IN13_V2_PART); Paint_SelectImage(BlackImage); } OWM* viewToOWM(views_t view){ switch(view){ case VIEW_WEATHER_0: return owm[0]; case VIEW_WEATHER_1: return owm[1]; case VIEW_WEATHER_2: return owm[2]; case VIEW_WEATHER_3: return owm[3]; default: return NULL; } } void updateDisplay(){ if (!view_update) return; if (view_refresh) refreshDisplay(); Paint_ClearWindows(0, 0, EPD_2IN13_V2_HEIGHT, EPD_2IN13_V2_WIDTH - Font24.Height, WHITE); Paint_ClearWindows(0, EPD_2IN13_V2_WIDTH - Font24.Height, 170, EPD_2IN13_V2_WIDTH, WHITE); switch(view_tab[view_curr]){ case VIEW_MAIN: Paint_DrawIcon(0,0, ICON_LOGO,&FontIcon, BLACK, WHITE); Paint_DrawString_EN(60,0,"MAIN", &Font24, WHITE, BLACK); Paint_DrawIntUnit(0,30, 69,"", &Font24, BLACK, WHITE); break; case VIEW_WEATHER_0: case VIEW_WEATHER_1: case VIEW_WEATHER_2: case VIEW_WEATHER_3: { OWM* cowm = viewToOWM(view_tab[view_curr]); if(cowm == NULL || !cowm->valid_weather) break; JsonObject weather_0 = cowm->weather["weather"][0]; JsonObject weather_main = cowm->weather["main"]; JsonObject weather_wind = cowm->weather["wind"]; JsonObject weather_sys = cowm->weather["sys"]; if(!weather_0 || !weather_main || !weather_sys || !weather_wind) break; Paint_DrawIcon(0,8, getWeatherIcon(weather_0["id"]), &FontIcon, BLACK, WHITE); Paint_DrawString_EN(2,EPD_2IN13_V2_WIDTH - 4 - Font16.Height,weather_0["description"], &Font16, WHITE, BLACK); Paint_DrawFltUnit(76,0,weather_main["temp"], "C", &Font24, BLACK, WHITE); Paint_DrawFltUnit(186,6,weather_main["feels_like"], "C", &Font12, BLACK, WHITE); Paint_DrawIntUnit(76,24,weather_main["pressure"], "hPa", &Font24, BLACK, WHITE); Paint_DrawIntUnit(76,48,weather_main["humidity"], "%", &Font24, BLACK, WHITE); Paint_DrawFltUnit(76,72,weather_wind["speed"], "m/s", &Font24, BLACK, WHITE); strDateTime sunrisedt = NTPtime::ConvertUnixTimestamp(NTPtime::adjustTimeZone(weather_sys["sunrise"], 1.0, 1)); strDateTime sunsetdt = NTPtime::ConvertUnixTimestamp(NTPtime::adjustTimeZone(weather_sys["sunset"], 1.0, 1)); Paint_DrawTime(20, 6, &sunrisedt, &Font12, WHITE, BLACK); Paint_DrawTime(20, 76, &sunsetdt, &Font12, WHITE, BLACK); } break; case VIEW_TEMP: Paint_DrawIcon(0,Font24.Height, ICON_TEMPERATURE,&FontIcon, BLACK, WHITE); Paint_DrawString_EN(2,0,"Temp", &Font24, WHITE, BLACK); Paint_DrawFltUnit(76,0,sensor->heatidx, "C", &Font24, BLACK, WHITE); Paint_DrawFltUnit(76,36,sensor->temp, "C", &Font24, BLACK, WHITE); Paint_DrawFltUnit(160,36,sensor->hum, "%", &Font24, BLACK, WHITE); Paint_DrawFltUnit(76,64,sensor->pres, "hPa", &Font24, BLACK, WHITE); break; case VIEW_AIR: Paint_DrawIcon(0,Font24.Height, ICON_POLUTION,&FontIcon, BLACK, WHITE); Paint_DrawString_EN(2,0,"Air", &Font24, WHITE, BLACK); Paint_DrawIntUnit(150,10, 69,"", &Font24, BLACK, WHITE); break; case VIEW_CUSTOM: Paint_DrawString_EN(60,0,"CUSTOM", &Font24, WHITE, BLACK); break; default: break; } EPD_2IN13_V2_DisplayPart(BlackImage); view_update = false; } void updateInflux(){ if(wifiMulti.run() != WL_CONNECTED) return; iflx->record(influx_w_update, influx_s_update); influx_w_update = false; influx_s_update = false; } /* The main loop -------------------------------------------------------------*/ void loop(){ if(shutdownc >= 10){ refreshDisplay(); EPD_2IN13_V2_Sleep(); esp_deep_sleep_start(); } updateNTP(); updateWeather(); updateSensor(); updateInflux(); touch->update(); updateDisplay(); updateTime(); delay(50); if(!touch->dev.holding) shutdownc = 0; }