├── .gitattributes ├── .gitignore ├── README.md ├── esp8266 └── esp8266.ino └── screenshots ├── screencapture_big.png └── screencapture_small.png /.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 on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # esp8266-pimatic-Arduino 2 | ESP8266 Pimatic Client to send Data (e.g. DHT22) to pimatic server. WebUI included. 3 | 4 | #Features: 5 | - mDNS Support: device will be found in network as http://.local (Bonjour Service needed) 6 | - supported devices: DHT22 7 | - WebUI based on Bootstrap 8 | 9 | # ToDo: 10 | - Configuration Page WIP, as of now DHT22 needs to be on GPIO2 11 | 12 | #Screenshots: 13 | Normal Layout: 14 | ![WebUI](https://github.com/Okadesde/esp8266-pimatic-Arduino/blob/master/screenshots/screencapture_big.png "WebUI") 15 | 16 | Adaptive Layout: 17 | ![WebUI](https://github.com/Okadesde/esp8266-pimatic-Arduino/blob/master/screenshots/screencapture_small.png "WebUI") 18 | 19 | -------------------------------------------------------------------------------- /esp8266/esp8266.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// !!PLEASE CHANGE THESE!! 11 | String ssid = "WiFi SSID"; 12 | String password = "WiFi Password"; 13 | 14 | String espName = "esp01"; 15 | 16 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// NETWORK 17 | ESP8266WebServer server(80); 18 | MDNSResponder mdns; 19 | 20 | const char* APssid = "ESPap"; 21 | const char* APpassword = "123456789"; 22 | 23 | 24 | 25 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// GLOBAL VARIABLES 26 | long lastInterval = 0; 27 | const int httpPort = 80; 28 | float temperature = 0.0; 29 | float humidity = 0.0; 30 | 31 | String deviceType = "DHT22"; 32 | long sendInterval = 10000; //in millis 33 | 34 | String Username = "sensors"; 35 | String Password = "iamasensor"; 36 | 37 | char authVal[40]; 38 | char authValEncoded[40]; 39 | 40 | String host = "192.168.0.100"; 41 | 42 | String ClientIP; 43 | // send data 44 | WiFiClient client; 45 | 46 | 47 | //uint8_t DHTPIN = 2; //data pin, GPIO2 48 | //uint8_t DHTTYPE = DHT22; 49 | 50 | DHT dht(2, DHT22, 20); 51 | 52 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HTML SNIPPLETS 53 | String header = "ESP8266 Pimatic Client"; 54 | String navbar = " "; 55 | String navbarNonActive = " "; 56 | String containerStart = "
"; 57 | String containerEnd = "
"; 58 | String siteEnd = ""; 59 | 60 | String panelHeaderName = "
"; 62 | String panelEnd = "
"; 63 | 64 | String panelBodySymbol = "
"; 66 | String panelBodyValue = ""; 67 | String panelBodyEnd = "
"; 68 | 69 | String inputBodyStart = "
"; 70 | String inputBodyName = "
"; 71 | String inputBodyPOST = "
"; 73 | String inputBodyEnd = "
"; 74 | 75 | 76 | //String landingNav = "


"; 77 | //String landingStartPartA = "
Please login to your WiFi Network
Wifi Name
"; 78 | //String landingStartPartB = "
WiFi Pass
Device Name "; 79 | //String landingStartPartC = "
"; 80 | //String landingEnd = "
"; 81 | 82 | 83 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ROOT 84 | void handle_root() { 85 | 86 | Serial.println(server.args()); 87 | 88 | // get IP 89 | IPAddress ip = WiFi.localIP(); 90 | ClientIP = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]); 91 | delay(500); 92 | 93 | String title1 = panelHeaderName + String("Sensor Data") + panelHeaderEnd; 94 | String Humidity = panelBodySymbol + String("tint") + panelBodyName + String("Humidity") + panelBodyValue + humidity + String("%") + panelBodyEnd; 95 | String Temperature = panelBodySymbol + String("fire") + panelBodyName + String("Temperature") + panelBodyValue + temperature + String("°C") + panelBodyEnd + panelEnd; 96 | 97 | String title2 = panelHeaderName + String("Client Settings") + panelHeaderEnd; 98 | String IPAddClient = panelBodySymbol + String("globe") + panelBodyName + String("IP Address") + panelBodyValue + ClientIP + panelBodyEnd; 99 | String DeviceType = panelBodySymbol + String("scale") + panelBodyName + String("Device Type") + panelBodyValue + deviceType + panelBodyEnd; 100 | String ClientName = panelBodySymbol + String("tag") + panelBodyName + String("Client Name") + panelBodyValue + espName + panelBodyEnd; 101 | String Interval = panelBodySymbol + String("hourglass") + panelBodyName + String("Interval") + panelBodyValue + sendInterval + String(" millis") + panelBodyEnd; 102 | String Uptime = panelBodySymbol + String("time") + panelBodyName + String("Uptime") + panelBodyValue + hour() + String(" h ") + minute() + String(" min ") + second() + String(" sec") + panelBodyEnd + panelEnd; 103 | 104 | String title3 = panelHeaderName + String("Server Settings") + panelHeaderEnd; 105 | String IPAddServ = panelBodySymbol + String("globe") + panelBodyName + String("IP Address") + panelBodyValue + host + panelBodyEnd; 106 | String User = panelBodySymbol + String("user") + panelBodyName + String("Username") + panelBodyValue + Username + panelBodyEnd + panelEnd; 107 | 108 | 109 | //String data = title1 + Humidity + Temperature + title2 + IPAddClient + DeviceType + ClientName + Interval + Uptime + title3 + IPAddServ + User; 110 | //server.send ( 200, "text/html", header + navbar + containerStart + data + containerEnd + siteEnd ); 111 | server.send ( 200, "text/html", header + navbar + containerStart + title1 + Humidity + Temperature + title2 + IPAddClient + DeviceType + ClientName + Interval + Uptime + title3 + IPAddServ + User + containerEnd + siteEnd); 112 | } 113 | 114 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CONFIG - Client 115 | void handle_cliconf() { 116 | 117 | String payload=server.arg("name"); 118 | if (payload.length() > 0 ) { 119 | espName = payload; 120 | } 121 | Serial.println(payload); 122 | 123 | payload=server.arg("type"); 124 | if (payload.length() > 0 ) { 125 | deviceType = payload; 126 | } 127 | Serial.println(payload); 128 | 129 | payload=server.arg("interval"); 130 | if (payload.length() > 0 ) { 131 | sendInterval = payload.toInt(); 132 | } 133 | Serial.println(payload); 134 | 135 | String title1 = panelHeaderName + String("Client Configuration") + panelHeaderEnd; 136 | 137 | String data = title1 + inputBodyStart + inputBodyName + String("Name") + inputBodyPOST + String("name") + inputBodyClose + inputBodyName + String("Device Type") + inputBodyPOST + String("type") + inputBodyClose + inputBodyName + String("Interval in seconds") + inputBodyPOST + String("interval") + inputBodyClose + inputBodyEnd; 138 | server.send ( 200, "text/html", header + navbarNonActive + containerStart + data + containerEnd + siteEnd ); 139 | } 140 | 141 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CONFIG - Server 142 | void handle_serconf() { 143 | 144 | String payload=server.arg("server"); 145 | if (payload.length() > 0 ) { 146 | host = payload; 147 | } 148 | Serial.println(payload); 149 | 150 | payload=server.arg("user"); 151 | if (payload.length() > 0 ) { 152 | Username = payload; 153 | } 154 | Serial.println(payload); 155 | 156 | payload=server.arg("password"); 157 | if (payload.length() > 0 ) { 158 | Password = payload; 159 | } 160 | Serial.println(payload); 161 | 162 | String title1 = panelHeaderName + String("Server Configuration") + panelHeaderEnd; 163 | 164 | String data = title1 + inputBodyStart + inputBodyName + String("Pimatic Server") + inputBodyPOST + String("server") + inputBodyClose + inputBodyName + String("Username") + inputBodyPOST + String("user") + inputBodyClose + inputBodyName + String("Password") + inputBodyPOST + String("password") + inputBodyClose + inputBodyEnd; 165 | 166 | server.send ( 200, "text/html", header + navbarNonActive + containerStart + data + containerEnd + siteEnd); 167 | 168 | 169 | } 170 | 171 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// LANDING 172 | /* 173 | void landing() { 174 | 175 | String payload=server.arg("wifiname"); 176 | if (payload.length() > 0 ) { 177 | ssid = payload; 178 | } 179 | Serial.println(payload); 180 | payload=server.arg("wifipass"); 181 | if (payload.length() > 0 ) { 182 | password = payload; 183 | } 184 | Serial.println(payload); 185 | 186 | payload=server.arg("devicename"); 187 | if (payload.length() > 0 ) { 188 | espName = payload; 189 | } 190 | Serial.println(payload); 191 | 192 | String landing = header + landingNav + landingStartPartA + landingStartPartB + landingStartPartC + landingEnd; 193 | server.send ( 200, "text/html", landing); 194 | } 195 | */ 196 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// SEND DATA 197 | void send_data() { 198 | 199 | String yourdata; 200 | 201 | // get data 202 | float h = dht.readHumidity(); 203 | float t = dht.readTemperature(); 204 | 205 | //check erros 206 | if (isnan(h) || isnan(t)) { 207 | Serial.println("Failed to read from DHT sensor!"); 208 | return; 209 | } 210 | 211 | temperature = t; 212 | humidity = h; 213 | 214 | char host_char_array[host.length()+1]; 215 | host.toCharArray(host_char_array,host.length()+1); 216 | 217 | if (!client.connect(host_char_array, httpPort)) { 218 | Serial.println("connection failed"); 219 | return; 220 | } 221 | 222 | // calculate Base64Login 223 | memset(authVal,0,40); 224 | (Username + String(":") + Password).toCharArray(authVal, 40); 225 | memset(authValEncoded,0,40); 226 | base64_encode(authValEncoded, authVal, (Username + String(":") + Password).length()); 227 | 228 | // char base64login[40]; 229 | 230 | // (Username + String(":") + Password).toCharArray(base64login, 40); 231 | 232 | //Send Humidity 233 | yourdata = "{\"type\": \"value\", \"valueOrExpression\": \"" + String(humidity) + "\"}"; 234 | 235 | 236 | client.print("PATCH /api/variables/"); 237 | client.print(espName); 238 | client.print("-hum HTTP/1.1\r\n"); 239 | client.print("Authorization: Basic "); 240 | client.print(authValEncoded); 241 | client.print("\r\n"); 242 | client.print("Host: " + host +"\r\n"); 243 | client.print("Content-Type:application/json\r\n"); 244 | client.print("Content-Length: "); 245 | client.print(yourdata.length()); 246 | client.print("\r\n\r\n"); 247 | client.print(yourdata); 248 | 249 | delay(500); 250 | 251 | //Send Temperature 252 | yourdata = "{\"type\": \"value\", \"valueOrExpression\": \"" + String(temperature) + "\"}"; 253 | 254 | client.print("PATCH /api/variables/"); 255 | client.print(espName); 256 | client.print("-tem HTTP/1.1\r\n"); 257 | client.print("Authorization: Basic "); 258 | client.print(authValEncoded); 259 | client.print("\r\n"); 260 | client.print("Host: " + host +"\r\n"); 261 | client.print("Content-Type:application/json\r\n"); 262 | client.print("Content-Length: "); 263 | client.print(yourdata.length()); 264 | client.print("\r\n\r\n"); 265 | client.print(yourdata); 266 | 267 | 268 | } 269 | 270 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AP 271 | void setupAP(void) { 272 | delay(100); 273 | WiFi.softAP(APssid,APpassword,6); 274 | } 275 | 276 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// SETUP 277 | void setup(void) 278 | { 279 | Serial.begin(115200); 280 | 281 | 282 | WiFi.begin(ssid.c_str(), password.c_str()); 283 | while (WiFi.status() != WL_CONNECTED) { 284 | delay(500); 285 | Serial.print("."); 286 | } 287 | Serial.println(""); 288 | Serial.print("Connected to "); 289 | Serial.println(ssid); 290 | Serial.print("IP address: "); 291 | Serial.println(WiFi.localIP()); 292 | 293 | server.on("/", handle_root); 294 | 295 | server.on("/cliconf", handle_cliconf); 296 | 297 | server.on("/serconf", handle_serconf); 298 | 299 | //server.on("/landing", landing); 300 | 301 | if (!mdns.begin(espName.c_str(), WiFi.localIP())) { 302 | Serial.println("Error setting up MDNS responder!"); 303 | while(1) { 304 | delay(1000); 305 | } 306 | } 307 | server.begin(); 308 | Serial.println("HTTP server started"); 309 | dht.begin(); 310 | } 311 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// MAIN 312 | void loop(void) 313 | { 314 | 315 | if (millis() - lastInterval > sendInterval) { 316 | send_data(); 317 | lastInterval = millis(); 318 | } 319 | 320 | server.handleClient(); 321 | 322 | } 323 | 324 | -------------------------------------------------------------------------------- /screenshots/screencapture_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Okadesde/esp8266-pimatic-Arduino/c6dfa36e3888b5da887159646bc238803fb0ee14/screenshots/screencapture_big.png -------------------------------------------------------------------------------- /screenshots/screencapture_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Okadesde/esp8266-pimatic-Arduino/c6dfa36e3888b5da887159646bc238803fb0ee14/screenshots/screencapture_small.png --------------------------------------------------------------------------------