You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

297 lines
8.3 KiB

  1. #define PUYA_SUPPORT 1
  2. #define SPIFFS_NO_BLIND_WRITES
  3. // for display
  4. #include <SPI_VFD.h>
  5. // for NTP and time
  6. #include <NTPClient.h>
  7. #include <WiFiUdp.h>
  8. #include <TimeLib.h>
  9. // for wifi
  10. #include <Wire.h>
  11. #include <ESP8266WiFi.h>
  12. // for wifi manager
  13. #include <DNSServer.h>
  14. #include <ESP8266WebServer.h>
  15. #include <WiFiManager.h>
  16. // for weather
  17. #include <ESP8266HTTPClient.h>
  18. // need to parse config file
  19. #include <FS.h>
  20. #include <tinyxml2.h>
  21. #include <ArduinoJson.h>
  22. using namespace tinyxml2;
  23. // set output pins
  24. //#define CLK D2 // ESP-12
  25. //#define STB D3 // ESP-12
  26. //#define DIO D4 // ESP-12
  27. #define CLK 3 // ESP-01 D9 RX
  28. #define STB 0 // ESP-01 IO0
  29. #define DIO 2 // ESP-01 IO2
  30. SPI_VFD vfd(DIO, CLK, STB);
  31. // wifi manager stuff
  32. char ntp_server[40] = "ru.pool.ntp.org";
  33. char ntp_timezone[3] = "7";
  34. char wifi_hostname[40] = "clock-vfd";
  35. int updateInterval = 600;
  36. char yandex_url[256] = "http://blindage.org/weather"; // proxy from yandex
  37. WiFiManagerParameter custom_ntp_server("ntp_server", "NTP server", ntp_server, 40);
  38. WiFiManagerParameter custom_timezone("ntp_timezone", "Timezone", ntp_timezone, 3);
  39. WiFiManagerParameter custom_hostname("wifi_hostname", "Hostname", wifi_hostname, 40);
  40. WiFiManagerParameter custom_yandex_url("yandex_url", "Yandex http URL", yandex_url, 256);
  41. // NTP
  42. WiFiUDP ntpUDP;
  43. NTPClient timeClient(ntpUDP);
  44. char daysOfTheWeek[7][21] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
  45. // WIFI CONFIGURATOR
  46. WiFiManager wifiManager;
  47. //callback config mode
  48. void configModeCallback (WiFiManager *myWiFiManager) {
  49. Serial.println("Entered config mode");
  50. Serial.println(WiFi.softAPIP());
  51. //if you used auto generated SSID, print it
  52. Serial.println(myWiFiManager->getConfigPortalSSID());
  53. }
  54. //callback notifying us of the need to save config
  55. void saveConfigCallback () {
  56. Serial.println("Wifi manager want to save config");
  57. Serial.print("Mounting SPIFFS...");
  58. if (SPIFFS.begin()) {
  59. Serial.println("mounted");
  60. }
  61. strcpy(ntp_server, custom_ntp_server.getValue());
  62. strcpy(ntp_timezone, custom_timezone.getValue());
  63. strcpy(wifi_hostname, custom_hostname.getValue());
  64. strcpy(yandex_url, custom_yandex_url.getValue());
  65. saveWifiConfig();
  66. }
  67. void readWifiConfig() {
  68. Serial.print("Opening file...");
  69. if (SPIFFS.exists("/config.json")) {
  70. //file exists, reading and loading
  71. Serial.println("reading config file");
  72. File configFile = SPIFFS.open("/config.json", "r");
  73. if (configFile) {
  74. Serial.println("opened config file");
  75. size_t size = configFile.size();
  76. // Allocate a buffer to store contents of the file.
  77. std::unique_ptr<char[]> buf(new char[size]);
  78. configFile.readBytes(buf.get(), size);
  79. DynamicJsonBuffer jsonBuffer;
  80. JsonObject& json = jsonBuffer.parseObject(buf.get());
  81. json.printTo(Serial);
  82. if (json.success()) {
  83. Serial.println("\nparsed json");
  84. strcpy(ntp_server, json["ntp_server"]);
  85. strcpy(ntp_timezone, json["ntp_timezone"]);
  86. strcpy(wifi_hostname, json["wifi_hostname"]);
  87. strcpy(yandex_url, json["yandex_url"]);
  88. Serial.println("Loaded:");
  89. Serial.println(String("TZ: ") + ntp_timezone);
  90. Serial.println(String("NTP server: ") + ntp_server);
  91. Serial.println(String("Device name: ") + wifi_hostname);
  92. Serial.println(String("Yandex URL: ") + yandex_url);
  93. } else {
  94. Serial.println("error config parsing");
  95. }
  96. configFile.close();
  97. }
  98. } else {
  99. saveWifiConfig();
  100. reset_device();
  101. }
  102. }
  103. void saveWifiConfig() {
  104. //save the custom parameters to FS
  105. Serial.println("saving config");
  106. DynamicJsonBuffer jsonBuffer;
  107. JsonObject& json = jsonBuffer.createObject();
  108. json["ntp_server"] = ntp_server;
  109. json["ntp_timezone"] = ntp_timezone;
  110. json["wifi_hostname"] = wifi_hostname;
  111. json["yandex_url"] = yandex_url;
  112. File configFile = SPIFFS.open("/config.json", "w");
  113. if (!configFile) {
  114. Serial.println("failed to open config file for writing");
  115. }
  116. json.printTo(Serial);
  117. json.printTo(configFile);
  118. configFile.close();
  119. }
  120. // WEATHER
  121. void getWeatherForecast() {
  122. HTTPClient http;
  123. http.begin(yandex_url);
  124. Serial.println(String("Getting url ") + yandex_url);
  125. int httpCode = http.GET();
  126. if (httpCode > 0) {
  127. Serial.println(httpCode);
  128. if (httpCode == HTTP_CODE_OK) {
  129. String payload = http.getString();
  130. XMLDocument doc;
  131. doc.Parse( payload.c_str() );
  132. XMLElement* dayElement = doc.FirstChildElement( "info" )->FirstChildElement( "weather" )->FirstChildElement( "day" )->FirstChildElement( "day_part" );
  133. const char* temp = dayElement->FirstChildElement( "temperature" )->GetText();
  134. const char* pressure = dayElement->FirstChildElement( "pressure" )->GetText();
  135. const char* dampness = dayElement->FirstChildElement( "dampness" )->GetText();
  136. const char* wind = dayElement->FirstChildElement( "wind_speed" )->GetText();
  137. const char* wind_direction = dayElement->FirstChildElement( "wind_direction" )->Attribute("id");
  138. const char* weather_code = dayElement->FirstChildElement( "weather_code" )->GetText();
  139. vfd.setCursor(0, 1);
  140. vfd.print(" ");
  141. String line = "";
  142. line += temp;
  143. line += "\xDF ";
  144. line += wind;
  145. line += " km/h ";
  146. line += wind_direction;
  147. line += " ";
  148. line += dampness;
  149. line += "%";
  150. vfd.setCursor(0, 1);
  151. Serial.println(line.c_str());
  152. vfd.print(line.c_str());
  153. }
  154. }
  155. }
  156. void reset_device() {
  157. // connection failed, reset
  158. Serial.println("Fatal error! Resetting device");
  159. vfd.clear();
  160. vfd.setCursor(0, 0);
  161. vfd.print("Fatal error!");
  162. vfd.setCursor(0, 1);
  163. vfd.print("Resetting device...");
  164. delay(3000);
  165. ESP.reset();
  166. delay(5000);
  167. }
  168. void setup()
  169. {
  170. Serial.begin(115200);
  171. Serial.println("Starting...");
  172. pinMode(CLK, OUTPUT);
  173. vfd.begin(20, 2);
  174. delay(1000);
  175. vfd.clear();
  176. vfd.setCursor(0, 0);
  177. vfd.print("CLOCK-VFD by");
  178. vfd.setCursor(0, 1);
  179. vfd.print("Vladimir Smagin");
  180. vfd.setBrightness(VFD_BRIGHTNESS25);
  181. delay(200);
  182. vfd.setBrightness(VFD_BRIGHTNESS50);
  183. delay(200);
  184. vfd.setBrightness(VFD_BRIGHTNESS75);
  185. delay(200);
  186. vfd.setBrightness(VFD_BRIGHTNESS100);
  187. delay(200);
  188. delay(2000);
  189. vfd.setBrightness(VFD_BRIGHTNESS75);
  190. delay(200);
  191. vfd.setBrightness(VFD_BRIGHTNESS50);
  192. delay(2000);
  193. vfd.clear();
  194. vfd.setCursor(0, 0);
  195. vfd.print("Activating WIFI...");
  196. // custom wifi parameters
  197. wifiManager.setSaveConfigCallback(saveConfigCallback); //set config save notify callback
  198. wifiManager.setAPCallback(configModeCallback);
  199. wifiManager.addParameter(&custom_ntp_server);
  200. wifiManager.addParameter(&custom_timezone);
  201. wifiManager.addParameter(&custom_hostname);
  202. wifiManager.addParameter(&custom_yandex_url);
  203. Serial.println("Connecting WIFI...");
  204. vfd.clear();
  205. vfd.setCursor(0, 0);
  206. vfd.print("Connecting WIFI...");
  207. if (!wifiManager.autoConnect("clock-vfd-config")) {
  208. reset_device();
  209. }
  210. //if you get here you have connected to the WiFi
  211. Serial.println("Wifi connected");
  212. Serial.print("local ip ");
  213. Serial.println(WiFi.localIP());
  214. Serial.print("Mounting SPIFFS...");
  215. if (SPIFFS.begin()) {
  216. Serial.println("mounted");
  217. }
  218. Serial.println("Load config file");
  219. readWifiConfig();
  220. long TZ = atoi(ntp_timezone) * 3600;
  221. Serial.println(String("Timezone in seconds: ") + TZ);
  222. // start NTP client
  223. timeClient.setPoolServerName(ntp_server);
  224. timeClient.setTimeOffset(TZ);
  225. timeClient.begin();
  226. Serial.println("Updating NTP data at first time...");
  227. timeClient.update();
  228. getWeatherForecast();
  229. }
  230. int updateIntervalCounter = 0;
  231. void loop()
  232. {
  233. updateIntervalCounter++;
  234. if (updateIntervalCounter > updateInterval) {
  235. Serial.println("Updating NTP data");
  236. updateIntervalCounter = 0;
  237. timeClient.update();
  238. getWeatherForecast();
  239. }
  240. long epoch = timeClient.getEpochTime();
  241. char timestring[20];
  242. sprintf(timestring, "%02d:%02d:%02d %02d-%02d %s", hour(epoch), minute(epoch), second(epoch), day(epoch), month(epoch), daysOfTheWeek[timeClient.getDay()]);
  243. //Serial.println(hour(epoch) + String(":") + minute(epoch) +String(":")+ second(epoch) + String(" ") + day(epoch) +String("-")+ month(epoch) +String("-")+ year(epoch));
  244. Serial.println(timestring);
  245. delay(100);
  246. vfd.setCursor(0, 0);
  247. vfd.print(timestring);
  248. }