├── .gitattributes ├── .gitignore ├── ESPSensorHourly.ino ├── Mail.ino ├── README.md ├── Sparkfun.ino └── ubidots.ino /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /ESPSensorHourly.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | ADC_MODE(ADC_VCC); //vcc read-mode 4 | 5 | // Include API-Headers 6 | extern "C" { 7 | #include "ets_sys.h" 8 | #include "os_type.h" 9 | #include "osapi.h" 10 | #include "mem.h" 11 | #include "user_interface.h" 12 | #include "cont.h" 13 | } 14 | 15 | #include ; 16 | 17 | 18 | // state definietions 19 | #define STATE_COLDSTART 0 20 | #define STATE_SLEEP_WAKE 1 21 | #define STATE_ALARM 2 22 | #define STATE_CONNECT_WIFI 4 23 | 24 | #define ALARM_PIN 14 // pin to test for alarm condition 25 | #define ALARM_POLARITY 1 // signal representing alarm 26 | #define SLEEP_TIME 60*1*1000000 // sleep intervalls in us 27 | #define SLEEP_COUNTS_FOR_LIVE_MAIL 24*2*7 // send live mail every 7 days 28 | #define SLEEP_COUNTS_FOR_BATT_CHECK 2*24 // send low-Batt mail once a day 29 | #define BATT_WARNING_VOLTAGE 2.4 // Voltage for Low-Bat warning 30 | #define WIFI_CONNECT_TIMEOUT_S 20 // max time for wifi connect to router, if exceeded restart 31 | 32 | 33 | // RTC-MEM Adresses 34 | #define RTC_BASE 65 35 | #define RTC_STATE 66 36 | #define RTC_WAKE_COUNT 67 37 | #define RTC_MAIL_TYPE 68 38 | 39 | // mail Types 40 | #define MAIL_NO_MAIL 0 41 | #define MAIL_WELCOME 1 // mail at startup 42 | #define MAIL_LIVE_SIGNAL 2 43 | #define MAIL_ALARM 3 44 | #define MAIL_LOW_BAT 4 45 | 46 | #define SPARKFUN_BATTERY 1 47 | 48 | #define VCC_ADJ 1.096 49 | 50 | #define SERIAL_DEBUG 51 | //#define DEBUG_NO_SEND 52 | 53 | // global variables 54 | byte buf[10]; 55 | byte state; // state variable 56 | byte event = 0; 57 | uint32_t sleepCount; 58 | uint32_t time1, time2; 59 | 60 | // Temporary buffer 61 | uint32_t b = 0; 62 | 63 | int i; 64 | 65 | WiFiClient client; 66 | 67 | void setup() { 68 | WiFi.forceSleepBegin(); // send wifi to sleep to reduce power consumption 69 | yield(); 70 | system_rtc_mem_read(RTC_BASE, buf, 2); // read 2 bytes from RTC-MEMORY 71 | 72 | // if serial is not initialized all following calls to serial end dead. 73 | #ifdef SERIAL_DEBUG 74 | Serial.begin(115200); 75 | delay(10); 76 | Serial.println(); 77 | Serial.println(); 78 | Serial.println(F("Started from reset")); 79 | #endif 80 | 81 | if ((buf[0] != 0x55) || (buf[1] != 0xaa)) // cold start, magic number is nor present 82 | { state = STATE_COLDSTART; 83 | buf[0] = 0x55; buf[1] = 0xaa; 84 | system_rtc_mem_write(RTC_BASE, buf, 2); 85 | } 86 | else // reset was due to sleep-wake or external event 87 | { system_rtc_mem_read(RTC_STATE, buf, 1); 88 | state = buf[0]; 89 | if (state == STATE_SLEEP_WAKE) // could be a sleep wake or an alarm 90 | { pinMode(ALARM_PIN, INPUT); 91 | bool pinState = digitalRead(ALARM_PIN); // read the alarm pin to find out whether an alarm is teh reset cause 92 | Serial.printf("GPIO %d read: %d\r\n", ALARM_PIN, pinState); 93 | if (pinState == ALARM_POLARITY) 94 | { // this is an alarm! 95 | state = STATE_ALARM; 96 | } 97 | } 98 | } 99 | 100 | // now the restart cause is clear, handle the different states 101 | Serial.printf("State: %d\r\n", state); 102 | 103 | switch (state) 104 | { case STATE_COLDSTART: // first run after power on - initializes 105 | sleepCount = 0; 106 | system_rtc_mem_write(RTC_WAKE_COUNT, &sleepCount, 4); // initialize counter 107 | buf[0] = MAIL_WELCOME; 108 | system_rtc_mem_write(RTC_MAIL_TYPE, buf, 1); // set a welcome-mail when wifi is on 109 | // prepare to activate wifi 110 | buf[0] = STATE_CONNECT_WIFI; // one more sleep required to to wake with wifi on 111 | WiFi.forceSleepWake(); 112 | WiFi.mode(WIFI_STA); 113 | system_rtc_mem_write(RTC_STATE, buf, 1); // set state for next wakeUp 114 | ESP.deepSleep(10, WAKE_RFCAL); 115 | yield(); 116 | 117 | break; 118 | case STATE_SLEEP_WAKE: 119 | system_rtc_mem_read(RTC_WAKE_COUNT, &sleepCount, 4); // read counter 120 | sleepCount++; 121 | if (sleepCount > SLEEP_COUNTS_FOR_LIVE_MAIL) 122 | { // its time to send mail as live signal 123 | buf[0] = MAIL_LIVE_SIGNAL; 124 | system_rtc_mem_write(RTC_MAIL_TYPE, buf, 1); // set mail type to send 125 | // prepare to activate wifi 126 | buf[0] = STATE_CONNECT_WIFI; // one more sleep required to to wake with wifi on 127 | WiFi.forceSleepWake(); 128 | WiFi.mode(WIFI_STA); 129 | system_rtc_mem_write(RTC_STATE, buf, 1); // set state for next wakeUp 130 | ESP.deepSleep(10, WAKE_RFCAL); 131 | yield(); 132 | } 133 | // check battery 134 | if (sleepCount > SLEEP_COUNTS_FOR_BATT_CHECK) 135 | { if ((float)ESP.getVcc()* VCC_ADJ < BATT_WARNING_VOLTAGE) 136 | { sleepCount = 0; // start from beginning so batt-warning is not sent every wakeup 137 | buf[0] = MAIL_LOW_BAT; 138 | system_rtc_mem_write(RTC_MAIL_TYPE, buf, 1); // set mail type to send 139 | system_rtc_mem_write(RTC_WAKE_COUNT, &sleepCount, 4); // write counter 140 | // prepare to activate wifi 141 | buf[0] = STATE_CONNECT_WIFI; // one more sleep required to to wake with wifi on 142 | WiFi.forceSleepWake(); 143 | WiFi.mode(WIFI_STA); 144 | system_rtc_mem_write(RTC_STATE, buf, 1); // set state for next wakeUp 145 | ESP.deepSleep(10, WAKE_RFCAL); 146 | yield(); 147 | } 148 | } 149 | 150 | // no special event, go to sleep again 151 | system_rtc_mem_write(RTC_WAKE_COUNT, &sleepCount, 4); // write counter 152 | buf[0] = STATE_SLEEP_WAKE; 153 | system_rtc_mem_write(RTC_STATE, buf, 1); // set state for next wakeUp 154 | ESP.deepSleep(SLEEP_TIME, WAKE_RF_DISABLED); 155 | yield(); // pass control back to background processes to prepate sleep 156 | break; 157 | 158 | case STATE_ALARM: 159 | buf[0] = MAIL_ALARM; 160 | system_rtc_mem_write(RTC_MAIL_TYPE, buf, 1); // set mail type to send 161 | // prepare to activate wifi 162 | buf[0] = STATE_CONNECT_WIFI; // one more sleep required to to wake with wifi on 163 | WiFi.forceSleepWake(); 164 | WiFi.mode(WIFI_STA); 165 | system_rtc_mem_write(RTC_STATE, buf, 1); // set state for next wakeUp 166 | ESP.deepSleep(10, WAKE_RFCAL); 167 | yield(); 168 | break; 169 | case STATE_CONNECT_WIFI: 170 | WiFi.forceSleepWake(); 171 | delay(500); 172 | wifi_set_sleep_type(MODEM_SLEEP_T); 173 | WiFi.mode(WIFI_STA); 174 | yield(); 175 | 176 | time1 = system_get_time(); 177 | 178 | // Connect to WiFi network 179 | Serial.println(); 180 | Serial.println(); 181 | Serial.print("Connecting to "); 182 | Serial.println(ASP_ssid); 183 | WiFi.begin(ASP_ssid, ASP_password); 184 | while (WiFi.status() != WL_CONNECTED) { 185 | delay(500); 186 | Serial.print("."); 187 | time2 = system_get_time(); 188 | if (((time2 - time1) / 1000000) > WIFI_CONNECT_TIMEOUT_S) // wifi connection lasts too ling, retry 189 | { ESP.deepSleep(10, WAKE_RFCAL); 190 | yield(); 191 | } 192 | } 193 | Serial.println(""); 194 | Serial.println("WiFi connected"); 195 | 196 | system_rtc_mem_read(RTC_MAIL_TYPE, buf, 1); 197 | 198 | if (buf[0] == MAIL_ALARM) { 199 | Serial.printf("Post to Sparkfun %d\r\n", buf[0]); 200 | //sendSparkfun(SPARKFUN_BATTERY); 201 | sendubidots(SPARKFUN_BATTERY); 202 | } 203 | else { 204 | Serial.printf("Send email %d\r\n", buf[0]); 205 | sendEmail(buf[0]); 206 | } 207 | // now re-initialize 208 | sleepCount = 0; 209 | system_rtc_mem_write(RTC_WAKE_COUNT, &sleepCount, 4); // initialize counter 210 | buf[0] = MAIL_NO_MAIL; 211 | system_rtc_mem_write(RTC_MAIL_TYPE, buf, 1); // no mail pending 212 | buf[0] = STATE_SLEEP_WAKE; 213 | system_rtc_mem_write(RTC_STATE, buf, 1); // set state for next wakeUp 214 | ESP.deepSleep(SLEEP_TIME, WAKE_RF_DISABLED); 215 | yield(); // pass control back to background processes to prepate sleep 216 | 217 | break; 218 | 219 | } 220 | delay(1000); 221 | // 222 | 223 | } 224 | 225 | 226 | void loop() 227 | { 228 | delay(10); 229 | 230 | 231 | } 232 | -------------------------------------------------------------------------------- /Mail.ino: -------------------------------------------------------------------------------- 1 | 2 | char server[] = "mail.smtpcorp.com"; 3 | 4 | #define HEADER_WELCOME "ESP8266 System powered on" 5 | #define HEADER_ALARM "ESP8266 ALARM!" 6 | #define HEADER_LIVE "ESP8266 System is working ok" 7 | #define HEADER_LOW_BAT "ESP8266 System has low battery" 8 | 9 | #define MAIL_FROM "sensorsiot@gmail.com" 10 | #define MAIL_TO "andreas.spiess@arumba.com" 11 | 12 | 13 | // my Chip IDs to give it a cleartype name 14 | #define WA1 14117293 15 | #define WA2 12612352 16 | 17 | 18 | bool sendEmail(byte MailType) 19 | { 20 | byte thisByte = 0; 21 | byte respCode; 22 | 23 | #ifdef DEBUG_NO_SEND 24 | if (MailType == MAIL_WELCOME) 25 | Serial.println(F(HEADER_WELCOME)); 26 | if (MailType == MAIL_ALARM) 27 | Serial.println(F(HEADER_ALARM)); 28 | if (MailType == MAIL_LIVE_SIGNAL) 29 | Serial.println(F(HEADER_LIVE)); 30 | if (MailType == MAIL_LOW_BAT) 31 | Serial.println(F(HEADER_LOW_BAT)); 32 | 33 | return true; 34 | #endif 35 | 36 | if (client.connect(server, 2525) == 1) { 37 | Serial.println(F("connected")); 38 | } else { 39 | Serial.println(F("connection failed")); 40 | return false; 41 | } 42 | if (!eRcv()) return false; 43 | 44 | Serial.println(F("Sending EHLO")); 45 | client.println("EHLO www.example.com"); 46 | if (!eRcv()) return false; 47 | Serial.println(F("Sending auth login")); 48 | client.println("auth login"); 49 | if (!eRcv()) return false; 50 | Serial.println(F("Sending User")); 51 | // Change to your base64, ASCII encoded user 52 | // client.println(MAIL_USER); 53 | client.println(SMTP2goUSER); //<---------User in base64 54 | if (!eRcv()) return false; 55 | Serial.println(F("Sending Password")); 56 | // change to your base64, ASCII encoded password 57 | // client.println(MAIL_PASS); 58 | client.println(SMTP2goPW);//<---------Password in base64 59 | if (!eRcv()) return false; 60 | Serial.println(F("Sending From")); 61 | // change to your email address (sender) 62 | client.print(F("MAIL From: ")); 63 | client.println(F(MAIL_FROM)); 64 | if (!eRcv()) return false; 65 | // change to recipient address 66 | Serial.println(F("Sending To")); 67 | client.print(F("RCPT To: ")); 68 | client.println(F(MAIL_TO)); 69 | if (!eRcv()) return false; 70 | Serial.println(F("Sending DATA")); 71 | client.println(F("DATA")); 72 | if (!eRcv()) return false; 73 | Serial.println(F("Sending email")); 74 | // change to recipient address 75 | client.print(F("To: ")); 76 | client.println(F(MAIL_TO)); 77 | // change to your address 78 | client.print(F("From: ")); 79 | client.println(F(MAIL_FROM)); 80 | client.print(F("Subject: ")); 81 | if (MailType == MAIL_WELCOME) 82 | client.println(F(HEADER_WELCOME)); 83 | if (MailType == MAIL_ALARM) 84 | client.println(F(HEADER_ALARM)); 85 | if (MailType == MAIL_LIVE_SIGNAL) 86 | client.println(F(HEADER_LIVE)); 87 | if (MailType == MAIL_LOW_BAT) 88 | client.println(F(HEADER_LOW_BAT)); 89 | 90 | client.println(F("This is from my ESP8266\n")); 91 | client.print(F("Power is: ")); 92 | client.print(float(ESP.getVcc() * VCC_ADJ)); 93 | client.println(F("mV")); 94 | int32 ChipID = ESP.getChipId(); 95 | if (ChipID == WA1) 96 | client.println("Device: Water-Alarm 1"); 97 | else if (ChipID == WA2) 98 | client.println("Device: Water-Alarm 2"); 99 | else 100 | { client.print(F("Device Chip ID: ")); 101 | client.println(ChipID); 102 | } 103 | 104 | 105 | client.println(F(".")); 106 | if (!eRcv()) return false; 107 | Serial.println(F("Sending QUIT")); 108 | client.println(F("QUIT")); 109 | if (!eRcv()) return false; 110 | client.stop(); 111 | Serial.println(F("disconnected")); 112 | return true; 113 | } 114 | 115 | byte eRcv() 116 | { 117 | byte respCode; 118 | byte thisByte; 119 | int loopCount = 0; 120 | 121 | while (!client.available()) { 122 | delay(1); 123 | loopCount++; 124 | // if nothing received for 10 seconds, timeout 125 | if (loopCount > 10000) { 126 | client.stop(); 127 | Serial.println(F("\r\nTimeout")); 128 | return false; 129 | } 130 | } 131 | 132 | respCode = client.peek(); 133 | while (client.available()) 134 | { 135 | thisByte = client.read(); 136 | Serial.write(thisByte); 137 | } 138 | 139 | if (respCode >= '4') 140 | { 141 | // efail(); 142 | return false; 143 | } 144 | return true; 145 | } 146 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP8266-Longterm-Sensor-Hourly 2 | ESP8266-Longterm Sensor Hourly 3 | 4 | This code belongs to a Youtube video: https://youtu.be/IYuYTfO6iOs 5 | -------------------------------------------------------------------------------- /Sparkfun.ino: -------------------------------------------------------------------------------- 1 | 2 | // my Chip IDs to give it a cleartype name 3 | #define WA1 14117293 4 | #define WA2 12612352 5 | 6 | 7 | bool sendSparkfun(byte sparkfunType) { 8 | 9 | // Use Sparkfun testing stream 10 | const char* host = "data.sparkfun.com"; 11 | const char* streamId = "q5Jpbl9jmpFYgLMr8zQv"; 12 | const char* privateKey = "BVBnz5ywgnSJpz68ek7r"; 13 | 14 | Serial.print("Connecting to "); Serial.print(host); 15 | 16 | WiFiClient client; 17 | int retries = 5; 18 | while (!client.connect(host, 80) && (retries-- > 0)) { 19 | Serial.print("."); 20 | } 21 | Serial.println(); 22 | if (!client.connected()) { 23 | Serial.println("Failed to connect, going back to sleep"); 24 | return false; 25 | } 26 | 27 | String url = "/input/"; 28 | url += streamId; 29 | url += "?private_key="; 30 | url += privateKey; 31 | url += "&battery="; 32 | url += float(ESP.getVcc() * VCC_ADJ); // Could be any string 33 | 34 | Serial.println(); 35 | Serial.println("sparkfun: "); 36 | Serial.println(); 37 | 38 | Serial.print("Request URL: "); Serial.println(url); 39 | 40 | client.print(String("GET ") + url + 41 | " HTTP/1.1\r\n" + 42 | "Host: " + host + "\r\n" + 43 | "Connection: close\r\n\r\n"); 44 | 45 | int timeout = 5 * 10; // 5 seconds 46 | while (!client.available() && (timeout-- > 0)) { 47 | delay(100); 48 | } 49 | 50 | if (!client.available()) { 51 | Serial.println("No response, going back to sleep"); 52 | return false; 53 | } 54 | Serial.println(F("disconnected")); 55 | return true; 56 | } 57 | -------------------------------------------------------------------------------- /ubidots.ino: -------------------------------------------------------------------------------- 1 | 2 | // Use Sparkfun testing stream 3 | 4 | 5 | 6 | // my Chip IDs to give it a cleartype name 7 | #define WA1 14117293 8 | #define WA2 12612352 9 | 10 | 11 | bool sendubidots(byte ubidotsType) { 12 | const char* host = "things.ubidots.com"; 13 | const char* streamId = ubidotsStreamId; 14 | const char* token = ubidotsToken; 15 | Serial.print("Connecting to "); Serial.print(host); 16 | 17 | WiFiClient client; 18 | int retries = 5; 19 | while (!client.connect(host, 80) && (retries-- > 0)) { 20 | Serial.print("."); 21 | } 22 | Serial.println(); 23 | if (!client.connected()) { 24 | Serial.println("Failed to connect, going back to sleep"); 25 | return false; 26 | } 27 | 28 | String url = "/api/v1.6/variables/"; 29 | url += streamId; 30 | 31 | 32 | Serial.println(); 33 | Serial.println("UBIDOTS: "); 34 | Serial.println(); 35 | 36 | String value = String(float(ESP.getVcc() * VCC_ADJ)); 37 | String valueStr = "{\"value\":" + value + '}'; 38 | 39 | String urlLoad = String("POST ") + url + 40 | "/values HTTP/1.1\r\n" + 41 | "X-Auth-Token: " + token + "\r\n" + 42 | "Host: " + host + "\r\n" + 43 | "Connection: close\r\n" + 44 | "Content-Type: application/json\r\n" + 45 | "Content-Length: " + valueStr.length() + "\r\n\r\n" + 46 | valueStr + "\r\n\r\n"; 47 | 48 | Serial.print(urlLoad); 49 | client.print(urlLoad); 50 | 51 | int timeout = 5 * 10; // 5 seconds 52 | while (!client.available() && (timeout-- > 0)) { 53 | delay(100); 54 | } 55 | 56 | if (!client.available()) { 57 | Serial.println("No response, going back to sleep"); 58 | return false; 59 | } 60 | Serial.println(F("disconnected")); 61 | return true; 62 | } 63 | --------------------------------------------------------------------------------