From: BuildTools Date: Mon, 13 Mar 2017 16:16:40 +0000 (+0000) Subject: Remote DC power control with a WeMos D1 mini X-Git-Url: http://stoneship.org.uk/projects/git/?a=commitdiff_plain;ds=inline;p=remote_power Remote DC power control with a WeMos D1 mini --- c7f2bb87028576e5ac47db34311e39161344c809 diff --git a/remote_power.fzz b/remote_power.fzz new file mode 100644 index 0000000..4b0871a Binary files /dev/null and b/remote_power.fzz differ diff --git a/remote_power.ino b/remote_power.ino new file mode 100644 index 0000000..04a4039 --- /dev/null +++ b/remote_power.ino @@ -0,0 +1,339 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// prototytpes +String getDate(time_t when); +String getTime(time_t when); + +// The MOSFET that switches the appliance +#define MOSFET D1 + +#define MANAGER_AP "RemotePower" +#define CONFIG_PORT 80 +#define NTP_SERVER "1.uk.pool.ntp.org" + +#define DEVICE_ON HIGH +#define DEVICE_OFF LOW +#define DEFAULT_DELAY 10000 // 10 seconds + + +#define www_username "admin" +#define www_password "wibble" + +ESP8266WebServer server(CONFIG_PORT); + +unsigned long trigtime = 0; +unsigned long trighold = 0; + +// track the status of our output pin +bool mosfet_status = false; + +const unsigned int localPort = 2390; +IPAddress ntpServerIP; + +const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message + +byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets + +WiFiUDP udp; + +unsigned long ntp_lastset = 0; +unsigned long ntp_lasttry = 0; + + + +void output_set(bool on) +{ + digitalWrite(MOSFET, on?DEVICE_ON:DEVICE_OFF); + mosfet_status = on; +} + +/* compose and send an NTP time request packet */ +void ntp_send() +{ + if (ntpServerIP == INADDR_NONE) { + if (WiFi.hostByName(NTP_SERVER, ntpServerIP) == 1) { + if (ntpServerIP == IPAddress(1,0,0,0)) { + Serial.println("DNS lookup failed for " NTP_SERVER " try again later."); + ntpServerIP = INADDR_NONE; + return; + } + Serial.print("Got NTP server " NTP_SERVER " address "); + Serial.println(ntpServerIP); + } else { + Serial.println("DNS lookup of " NTP_SERVER " failed."); + return; + } + } + + ntp_lasttry = millis(); + memset(packetBuffer, 0, NTP_PACKET_SIZE); + // Initialize values needed to form NTP request + // (see URL above for details on the packets) + packetBuffer[0] = 0b11100011; // LI, Version, Mode + packetBuffer[1] = 0; // Stratum, or type of clock + packetBuffer[2] = 6; // Polling Interval + packetBuffer[3] = 0xEC; // Peer Clock Precision + // 8 bytes of zero for Root Delay & Root Dispersion + packetBuffer[12] = 49; + packetBuffer[13] = 0x4E; + packetBuffer[14] = 49; + packetBuffer[15] = 52; + + // all NTP fields have been given values, now + // you can send a packet requesting a timestamp: + udp.beginPacket(ntpServerIP, 123); //NTP requests are to port 123 + udp.write(packetBuffer, NTP_PACKET_SIZE); + udp.endPacket(); + + Serial.println("Sending NTP request"); +} + +/* request a time update from NTP and parse the result */ +time_t ntp_fetch() +{ + while (udp.parsePacket() > 0); // discard old udp packets + ntp_send(); + + uint32_t beginWait = millis(); + + while (millis() - beginWait < 2500) { + int size = udp.parsePacket(); + if (size >= NTP_PACKET_SIZE) { + udp.read(packetBuffer, NTP_PACKET_SIZE); + + // this is NTP time (seconds since Jan 1 1900): + unsigned long secsSince1900 = packetBuffer[40] << 24 | packetBuffer[41] << 16 | packetBuffer[42] << 8 | packetBuffer[43]; + const unsigned long seventyYears = 2208988800UL; + time_t unixtime = secsSince1900 - seventyYears; + + ntp_lastset = millis(); + Serial.print("NTP update unixtime="); + Serial.println(unixtime); + return unixtime; + } + } + Serial.println("No NTP response"); + return 0; +} + + +String one_button_form(String target, String action, String blurb) +{ + String out = ""; + out += "
"; + out += ""; + out += ""; + out += "
\n"; + + return out; +} + + +/* HTTP page request for / */ +void handleRoot() +{ + char mtime[16]; + int sec = millis() / 1000; + int mi = sec / 60; + int hr = mi / 60; + int day = hr / 24; + + snprintf(mtime, 16, "%dd %02d:%02d:%02d", day, hr % 24, mi % 60, sec % 60); + + if (server.hasArg("action")) { + String action = server.arg("action"); + + if (action == "on") { + output_set(DEVICE_ON); + trigtime = 0; + } else + if (action == "off") { + output_set(DEVICE_OFF); + trigtime = 0; + } else + if (action == "toggle") { + output_set(!mosfet_status); + trigtime = 0; + } else + if (action == "pulse") { + if (server.hasArg("dur")) { + trighold = server.arg("dur").toInt(); + } else { + trighold = 0; + } + if (trighold == 0) trighold = DEFAULT_DELAY; + trigtime = millis(); + output_set(DEVICE_OFF); + } + } + + String out = "\ + \ + Remote Power\ + \ + \ + \ +

Remote Power

\ +

Uptime: " + (String)mtime + "

\n"; + + if (timeStatus() == timeSet) { + time_t when = now(); + out += "

Time now: " + getDate(when) + " " + getTime(when) + "

\n"; + } + + FSInfo fs_info; + if (SPIFFS.info(fs_info)) { + out += "

Onboard Flash disk: - Size:"+String(fs_info.totalBytes)+" Used:"+String(fs_info.usedBytes)+"

\n"; + } + + out += "

Powered device is "; + out += mosfet_status?"ON":"OFF"; + out += "("; + out += digitalRead(MOSFET) == HIGH?"HIGH":"LOW"; + out += ")"; + + if (!mosfet_status && trigtime != 0) { + out += " and is due to turn back ON in "; + out += (trigtime + trighold - millis() )/ 1000; + out += " seconds."; + } + + out += "

\n"; + + out += "
    \n"; + out += "
  • Reset Configuration\n"; + out += "
  • " + one_button_form("/", "on", "Turn Device ON"); + out += "
  • " + one_button_form("/", "off", "Turn Device OFF"); + out += "
  • " + one_button_form("/", "toggle", "Toggle Device Status"); + out += "
  • " + one_button_form("/", "pulse", (String)"Turn Device OFF for " + (int)(DEFAULT_DELAY/1000) + (String)" seconds"); + + + out += "
\n"; + out += "\n\n"; + + server.send( 200, "text/html", out); +} + +void handleNotFound() { + String out = "File Not found\n\n"; + server.send(404, "text/plain", out); +} + +// User wants to reset config +void handleReset() { + if (!server.authenticate(www_username, www_password)) + return server.requestAuthentication(); + + server.send(200, "text/plain", "Rebooting to config manager...\n\n"); + + WiFiManager wfm; + wfm.resetSettings(); + WiFi.disconnect(); + ESP.reset(); + delay(5000); +} + +void returnOK() { + server.send(200, "text/plain", ""); +} + +String getTime(time_t when) +{ + String ans; + int h = hour(when); + int m = minute(when); + int s = second(when); + + if (h<10) ans += "0"; + ans += String(h) + ":"; + if (m<10) ans += "0"; + ans += String(m) + ":"; + if (s<10) ans += "0"; + ans += String(s); + + return ans; +} + +String getDate(time_t when) +{ + String ans; + + ans += String(year(when)) + "-" + String(month(when)) + "-" + String(day(when)); + return ans; +} + + +void setup() { + // some serial, for debug + Serial.begin(115200); + + // The lock mechanism + pinMode(MOSFET, OUTPUT); + output_set(DEVICE_ON); + + Serial.println("Remote Power switcher"); + Serial.println("Test WiFi and enter manager mode."); + + WiFiManager wfm; + // Only wait in config mode for 3 minutes max + wfm.setConfigPortalTimeout(180); + // Try to connect to the old Ap for this long + wfm.setConnectTimeout(60); + // okay, lets try and connect... + wfm.autoConnect(MANAGER_AP); + + Serial.println("Entering normal operation mode."); + + // we have config and are running normally, setup web server + server.on( "/", handleRoot ); + server.on( "/reset", handleReset ); + server.onNotFound( handleNotFound ); + server.begin(); + + // advertise we exist via MDNS + if (!MDNS.begin("remotepower")) { + Serial.println("Error setting up MDNS responder."); + } else { + MDNS.addService("http", "tcp", 80); + } + + // enable internal flash + SPIFFS.begin(); + + Serial.println("Requesting time from network"); + udp.begin(localPort); + setSyncProvider(ntp_fetch); + + Serial.println("Remote power switch. Ready"); +} + +void loop() { + // put your main code here, to run repeatedly: + server.handleClient(); + + // a timed off state in progress + if (trigtime != 0) { + if (trigtime + trighold < millis()) { + trigtime = 0; + output_set(DEVICE_ON); + } + } + + // has ntp failed. do we need to try again? + if (ntp_lastset == 0 && ntp_lasttry + 300000 < millis()) { + Serial.println("Ask Time service to try again"); + setSyncProvider(ntp_fetch); + } + +}