Last active
February 26, 2021 02:08
-
-
Save NaotoKumagai/263cb73d7c7d6eb7680abf61c0cbfc04 to your computer and use it in GitHub Desktop.
シェアハウスのお風呂利用状況監視君
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Arduino.h> | |
#include <Hash.h> | |
#include <ESP8266WiFi.h> | |
#include <ESP8266WebServer.h> | |
#include <ESP8266HTTPClient.h> | |
#include <WebSocketsClient.h> | |
#include <ArduinoJson.h> | |
extern "C" { | |
#include "user_interface.h" | |
} | |
#define WIFI_SSID "接続したいSSID" | |
#define WIFI_PWD "SSIDのパスワード" | |
#define SLACK_SSL_FINGERPRINT "AB F0 5B A9 1A E0 AE 5F CE 32 2E 7C 66 67 49 EC DD 6D 6A 38" | |
#define SLACK_BOT_TOKEN "SlackBotのトークン" | |
#define SLACK_DEFAULT_CHANNEL "投稿するデフォルトのチャンネル" //この辺りどうするかは運用に合わせて | |
#define SLACK_BOT_USER_ID "BOTのUserID" //自分の投稿を読み取らない様にハードコードで回避(rtm.startから取得したほうがカッコイイかも) | |
#define HTML_HEADER "<!doctype html>"\ | |
"<html><head><meta charset=\"UTF-8\"/>"\ | |
"<meta name=\"viewport\" content=\"width=device-width\"/>"\ | |
"</head><body>" | |
#define HTML_FOOTER "</body></html>" | |
bool connected = false; | |
bool helloSaid = false; | |
unsigned long lastAccess =0; | |
WebSocketsClient webSocket; | |
ESP8266WebServer server(80); | |
// 光センサの値取得 | |
int getToutValue() { | |
int res = system_adc_read(); // アナログ値の読み取り | |
return res; | |
} | |
String getToutString() { | |
if (getToutValue() < 150) { //手持ちのセンサではしきい値150位で良い塩梅だった。 | |
return "お風呂空いてます"; | |
} | |
return "お風呂利用中です"; | |
} | |
String getImageHTML() { | |
if (getToutValue() < 150) { | |
return "<br><img src=\"http://01.gatag.net/img/201506/11l/gatag-00006874.jpg\"><br>"; | |
} | |
return "<br><img src=\"http://01.gatag.net/img/201507/12l/gatag-00010490.jpg\"><br>"; | |
} | |
// グローバルIPの取得(外から利用する予定は無いけどなんとなく) | |
String findPublicIP() { | |
WiFiClient client; | |
if (client.connect("api.ipify.org", 80)) { | |
client.println("GET /?format=txt HTTP/1.0"); | |
client.println("Host: api.ipify.org"); | |
client.println(); | |
} else { | |
Serial.println("connection failed"); | |
} | |
delay(50); | |
int a = 1; | |
while (client.connected()) { | |
a = a + 1; | |
String line = client.readStringUntil('\n'); | |
if (a == 10) { | |
Serial.println(line); | |
return line; | |
} | |
} | |
return ""; | |
} | |
void sendPing() { | |
DynamicJsonBuffer jsonBuffer; | |
JsonObject& root = jsonBuffer.createObject(); | |
root["type"] = "ping"; | |
String json; | |
root.printTo(json); | |
webSocket.sendTXT(json); | |
} | |
bool connectToSlack() { | |
HTTPClient http; | |
http.begin("https://slack.com/api/rtm.start?token=" SLACK_BOT_TOKEN, SLACK_SSL_FINGERPRINT); | |
int httpCode = http.GET(); | |
if (httpCode != HTTP_CODE_OK) { | |
Serial.printf("HTTP GET failed with code %d\n", httpCode); | |
return false; | |
} | |
WiFiClient *client = http.getStreamPtr(); | |
client->find("wss:\\/\\/"); | |
String host = client->readStringUntil('\\'); | |
String path = client->readStringUntil('"'); | |
path.replace("\\/", "/"); | |
Serial.println("WebSocket Host=" + host + " Path=" + path); | |
webSocket.beginSSL(host, 443, path, "", ""); | |
webSocket.onEvent(webSocketEvent); | |
return true; | |
} | |
void webSocketEvent(WStype_t type, uint8_t *payload, size_t len) { | |
switch (type) { | |
case WStype_DISCONNECTED: | |
Serial.printf("[WebSocket] Disconnected :-( \n"); | |
connected = false; | |
break; | |
case WStype_CONNECTED: | |
Serial.printf("[WebSocket] Connected to: %s\n", payload); | |
break; | |
case WStype_TEXT: | |
Serial.printf("[WebSocket] Message: %s\n", payload); | |
processSlackMessage((char*)payload); | |
break; | |
} | |
} | |
void processSlackMessage(char *payload) { | |
StaticJsonBuffer<1000> jsonBuffer; | |
JsonObject& root = jsonBuffer.parseObject(payload); | |
if (!root.success()) { | |
Serial.println("[Json] Parse failed"); | |
return; | |
} | |
if (root.containsKey("type")) { | |
if (strcmp("hello", root["type"]) == 0) { | |
helloSaid = true; | |
} else if (strcmp("message", root["type"]) == 0 ) { | |
if (!root.containsKey("user") || strcmp(SLACK_BOT_USER_ID, root["user"]) != 0) { | |
if (root.containsKey("text")) { | |
if (((String)(root["text"].asString())).substring(0, 12) == "<@" SLACK_BOT_USER_ID ">") { | |
DynamicJsonBuffer jsonBuffer; | |
JsonObject& root = jsonBuffer.createObject(); | |
root["type"] = "message"; | |
root["channel"] = SLACK_DEFAULT_CHANNEL; | |
root["text"] = getToutString() + ":bathtub:"; | |
sendMessage(root); | |
} | |
} | |
} | |
} | |
} | |
} | |
void sendMessage() { | |
DynamicJsonBuffer jsonBuffer; | |
JsonObject& root = jsonBuffer.createObject(); | |
root["type"] = "message"; | |
root["channel"] = SLACK_DEFAULT_CHANNEL; | |
root["text"] = "hoge"; | |
String json; | |
root.printTo(json); | |
webSocket.sendTXT(json); | |
} | |
void sendMessage(JsonObject& root) { | |
String json; | |
root.printTo(json); | |
webSocket.sendTXT(json); | |
} | |
void setupWebServer() { | |
server.on("/", []() { | |
lastAccess = millis(); | |
String html = HTML_HEADER "<h1>" + getToutString() + "</h1>" + getImageHTML() + HTML_FOOTER; | |
server.send(200, "text/html", html); | |
}); | |
server.on("/sensor", []() { | |
String accessSec = String((millis() - lastAccess)/1000); | |
String html = HTML_HEADER; | |
html+="<h1> 光センサの値 : "; | |
html+=getToutValue(); | |
html+="</h1><br><h1>最後のアクセスから"; | |
html+=accessSec; | |
html+="sec</h1>"; | |
html+= HTML_FOOTER; | |
server.send(200, "text/html", html); | |
}); | |
server.begin(); | |
} | |
unsigned long lastPing = 0; | |
void slackBotLoop() { | |
webSocket.loop(); | |
if (connected) { | |
if (millis() - lastPing > 5000) { | |
if (helloSaid) { | |
sendPing(); | |
} | |
lastPing = millis(); | |
} | |
} else { | |
connected = connectToSlack(); | |
lastPing = millis(); | |
} | |
} | |
void setup() { | |
Serial.begin(9600); | |
Serial.setDebugOutput(true); | |
WiFi.begin(WIFI_SSID, WIFI_PWD); | |
Serial.println(""); | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(1000); | |
Serial.print("."); | |
} | |
Serial.println("Grobal IP = " + findPublicIP()); | |
Serial.println("Local IP = " + WiFi.localIP()); | |
setupWebServer(); | |
} | |
void loop() { | |
server.handleClient(); | |
slackBotLoop(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment