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.

312 lines
8.2KB

  1. #define PUYA_SUPPORT 1
  2. #define SPIFFS_NO_BLIND_WRITES
  3. #include <FS.h>
  4. #include <SPI_VFD.h>
  5. #include <Wire.h>
  6. #include <TimeLib.h>
  7. #include <NtpClientLib.h>
  8. #include <ESP8266WiFi.h>
  9. #include <ESP8266HTTPClient.h>
  10. #include <tinyxml2.h>
  11. #include <ArduinoJson.h>
  12. #include <DNSServer.h>
  13. #include <ESP8266WebServer.h>
  14. #include <WiFiManager.h>
  15. using namespace tinyxml2;
  16. #define ONBOARDLED 2 // Built in LED on ESP-12/ESP-07
  17. // set output pins
  18. //#define CLK D2 // ESP-12
  19. //#define STB D3 // ESP-12
  20. //#define DIO D4 // ESP-12
  21. #define CLK D9 // ESP-01 D9 RX
  22. #define STB D3 // ESP-01 IO0
  23. #define DIO D4 // ESP-01 IO2
  24. SPI_VFD vfd(DIO, CLK, STB);
  25. // wifi manager stuff
  26. bool wifi_connected = false;
  27. bool ntp_online = false;
  28. char ntp_server[40] = "ru.pool.ntp.org";
  29. char ntp_timezone[3] = "7";
  30. char wifi_hostname[40] = "clock-vfd";
  31. WiFiManagerParameter custom_ntp_server("server", "NTP server", ntp_server, 40);
  32. WiFiManagerParameter custom_timezone("timezone", "Timezone (default 7)", ntp_timezone, 3);
  33. WiFiManagerParameter custom_hostname("hostname", "Hostname (default clock-vfd)", wifi_hostname, 40);
  34. WiFiManager wifiManager;
  35. //flag for saving data, used after wifi manager configuration
  36. bool shouldSaveConfig = false;
  37. //callback config mode
  38. void configModeCallback (WiFiManager *myWiFiManager) {
  39. Serial.println("Entered config mode");
  40. Serial.println(WiFi.softAPIP());
  41. //if you used auto generated SSID, print it
  42. Serial.println(myWiFiManager->getConfigPortalSSID());
  43. }
  44. //callback notifying us of the need to save config
  45. void saveConfigCallback () {
  46. Serial.println("Should save config");
  47. shouldSaveConfig = true;
  48. }
  49. // set weather source
  50. static const char* yandexUrl = "http://blindage.org/weather";
  51. void processSyncEvent(NTPSyncEvent_t ntpEvent) {
  52. if (ntpEvent) {
  53. ntp_online = false;
  54. Serial.print("Time Sync error: ");
  55. if (ntpEvent == noResponse) {
  56. Serial.println("NTP server not reachable");
  57. }
  58. else if (ntpEvent == invalidAddress) {
  59. Serial.println("Invalid NTP server address");
  60. }
  61. }
  62. else {
  63. ntp_online = true;
  64. Serial.print("Got NTP time: ");
  65. Serial.println(NTP.getTimeDateString(NTP.getLastNTPSync()));
  66. HTTPClient http;
  67. http.begin(yandexUrl);
  68. Serial.println(yandexUrl);
  69. int httpCode = http.GET();
  70. if (httpCode > 0) {
  71. Serial.println(httpCode);
  72. if (httpCode == HTTP_CODE_OK) {
  73. String payload = http.getString();
  74. XMLDocument doc;
  75. doc.Parse( payload.c_str() );
  76. XMLElement* dayElement = doc.FirstChildElement( "info" )->FirstChildElement( "weather" )->FirstChildElement( "day" )->FirstChildElement( "day_part" );
  77. const char* temp = dayElement->FirstChildElement( "temperature" )->GetText();
  78. const char* pressure = dayElement->FirstChildElement( "pressure" )->GetText();
  79. const char* dampness = dayElement->FirstChildElement( "dampness" )->GetText();
  80. const char* wind = dayElement->FirstChildElement( "wind_speed" )->GetText();
  81. const char* wind_direction = dayElement->FirstChildElement( "wind_direction" )->Attribute("id");
  82. const char* weather_code = dayElement->FirstChildElement( "weather_code" )->GetText();
  83. vfd.setCursor(0, 1);
  84. vfd.print(" ");
  85. string line = "";
  86. line += temp;
  87. line += " ";
  88. line += wind;
  89. line += " km/h ";
  90. line += wind_direction;
  91. line += " ";
  92. line += dampness;
  93. line += "%";
  94. vfd.setCursor(0, 1);
  95. Serial.println(line.c_str());
  96. vfd.print(line.c_str());
  97. }
  98. }
  99. }
  100. }
  101. boolean syncEventTriggered = false;
  102. NTPSyncEvent_t ntpEvent;
  103. void reset_device() {
  104. // connection failed, reset
  105. Serial.println("Fatal error! Resetting device");
  106. vfd.clear();
  107. vfd.setCursor(0, 0);
  108. vfd.print("Fatal error!");
  109. vfd.setCursor(0, 1);
  110. vfd.print("Resetting device...");
  111. delay(3000);
  112. ESP.reset();
  113. delay(5000);
  114. }
  115. void setup()
  116. {
  117. Serial.begin(115200);
  118. pinMode(D9,OUTPUT);
  119. vfd.begin(20, 2);
  120. vfd.clear();
  121. vfd.setCursor(0, 0);
  122. vfd.print("CLOCK-VFD by");
  123. vfd.setCursor(0, 1);
  124. vfd.print("Vladimir Smagin");
  125. delay(2000);
  126. Serial.println("mounting FS...");
  127. // read wifi manager config
  128. if (SPIFFS.begin()) {
  129. Serial.println("mounted file system");
  130. if (SPIFFS.exists("/config.json")) {
  131. //file exists, reading and loading
  132. Serial.println("reading config file");
  133. File configFile = SPIFFS.open("/config.json", "r");
  134. if (configFile) {
  135. Serial.println("opened config file");
  136. size_t size = configFile.size();
  137. // Allocate a buffer to store contents of the file.
  138. std::unique_ptr<char[]> buf(new char[size]);
  139. configFile.readBytes(buf.get(), size);
  140. DynamicJsonBuffer jsonBuffer;
  141. JsonObject& json = jsonBuffer.parseObject(buf.get());
  142. json.printTo(Serial);
  143. if (json.success()) {
  144. Serial.println("\nparsed json");
  145. strcpy(ntp_server, json["ntp_server"]);
  146. strcpy(ntp_timezone, json["ntp_timezone"]);
  147. strcpy(wifi_hostname, json["wifi_hostname"]);
  148. } else {
  149. Serial.println("failed to load json config");
  150. }
  151. configFile.close();
  152. }
  153. }
  154. } else {
  155. Serial.println("failed to mount FS");
  156. }
  157. //end read
  158. vfd.clear();
  159. vfd.setCursor(0, 0);
  160. vfd.print("Connecting WIFI...");
  161. pinMode(ONBOARDLED, OUTPUT); // Onboard LED
  162. digitalWrite(ONBOARDLED, HIGH); // Switch off LED
  163. Serial.println("Wifi manager configuring...");
  164. // custom wifi parameters
  165. wifiManager.setSaveConfigCallback(saveConfigCallback); //set config save notify callback
  166. wifiManager.setAPCallback(configModeCallback);
  167. wifiManager.addParameter(&custom_ntp_server);
  168. wifiManager.addParameter(&custom_timezone);
  169. wifiManager.addParameter(&custom_hostname);
  170. Serial.println("Wifi connecting...");
  171. if (!wifiManager.autoConnect("clock-vfd-config")) {
  172. reset_device();
  173. }
  174. //if you get here you have connected to the WiFi
  175. Serial.println("Wifi connected");
  176. wifi_connected = true;
  177. //read updated parameters
  178. strcpy(ntp_server, custom_ntp_server.getValue());
  179. strcpy(ntp_timezone, custom_timezone.getValue());
  180. strcpy(wifi_hostname, custom_hostname.getValue());
  181. // check hostname, set if needed
  182. if (wifi_hostname != "clock-vfd") WiFi.hostname("clock-vfd");
  183. //save the custom parameters to FS
  184. if (shouldSaveConfig) {
  185. Serial.println("saving config");
  186. DynamicJsonBuffer jsonBuffer;
  187. JsonObject& json = jsonBuffer.createObject();
  188. json["ntp_server"] = ntp_server;
  189. json["ntp_timezone"] = ntp_timezone;
  190. json["wifi_hostname"] = wifi_hostname;
  191. File configFile = SPIFFS.open("/config.json", "w");
  192. if (!configFile) {
  193. Serial.println("failed to open config file for writing");
  194. }
  195. json.printTo(Serial);
  196. json.printTo(configFile);
  197. configFile.close();
  198. //end save
  199. }
  200. Serial.print("local ip ");
  201. Serial.println(WiFi.localIP());
  202. NTP.onNTPSyncEvent([](NTPSyncEvent_t event) {
  203. ntpEvent = event;
  204. syncEventTriggered = true;
  205. });
  206. }
  207. void starting() {
  208. NTP.begin(ntp_server, atoi(ntp_timezone), true);
  209. NTP.setInterval(10, 600);
  210. Serial.print("TZ: ");
  211. Serial.println(atoi(ntp_timezone));
  212. vfd.clear();
  213. while (ntp_online == false) {
  214. syncEventTriggered = true;
  215. if (syncEventTriggered) {
  216. processSyncEvent (ntpEvent);
  217. syncEventTriggered = true;
  218. }
  219. vfd.clear();
  220. vfd.print("Connecting NTP...");
  221. Serial.println("Connecting NTP...");
  222. delay(1000);
  223. }
  224. vfd.clear();
  225. }
  226. char timebuff[21];
  227. void loop()
  228. {
  229. if (WiFi.status() != WL_CONNECTED) {
  230. wifi_connected = false;
  231. }
  232. // if wifi suddenly disconnected do nothing
  233. if (wifi_connected == true) {
  234. // if ntp server is down try to reconnect
  235. if (ntp_online == false) {
  236. starting();
  237. } else {
  238. // all fine, working here
  239. if (syncEventTriggered) {
  240. processSyncEvent (ntpEvent);
  241. syncEventTriggered = false;
  242. }
  243. String timestamp = NTP.getTimeDateString();
  244. timestamp.toCharArray(timebuff, 21);
  245. delay(100);
  246. vfd.setCursor(0, 0);
  247. vfd.print(timestamp);
  248. }
  249. } else {
  250. vfd.clear();
  251. vfd.print("No wifi connection");
  252. NTP.stop();
  253. delay(10000);
  254. Serial.println("Wifi connecting...");
  255. if (wifiManager.autoConnect("clock-vfd-config")) {
  256. wifi_connected = true;
  257. starting();
  258. }
  259. }
  260. }