Last active
January 29, 2019 17:51
-
-
Save libbymiller/e3511c16d1590467171d9e157c6218b1 to your computer and use it in GitHub Desktop.
Slackwobbler - anywhere - updated to new ArduinoJson and improved by Tim
This file contains 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
/** | |
Arduino Real-Time Slack Bot | |
Copyright (C) 2016, Uri Shaked. | |
Licensed under the MIT License | |
https://github.com/urish/arduino-slack-bot | |
Bodged to use WiFiManager and a servo by libby. | |
Instructions: | |
* Install CH340G Driver (no need for Linux) https://wiki.wemos.cc/downloads | |
* set up Arduino environment for ESP 8266: https://chewett.co.uk/blog/937/configuring-wemos-d1-mini-pro-esp8266-arduino-ide/ | |
* add this library: https://github.com/tzapu/WiFiManager | |
* add latest ArduinJson - 6.7.0 | |
* update line 39 with SLACK_BOT_TOKEN | |
WiFiManager gives you a wifi portal to connect to (called 'wobbler') if it doesn't find its last wifi network. | |
You connect to it, a browser captive portal window should launch, and you can add your wifi details there. | |
*/ | |
#include <Arduino.h> | |
#include <WiFiManager.h> | |
//https://github.com/tzapu/WiFiManager | |
#include <ESP8266WiFi.h> | |
#include <ESP8266WiFiMulti.h> | |
#include <ESP8266HTTPClient.h> | |
#include <WebSocketsClient.h> | |
#include <ArduinoJson.h> | |
#define NAME "wobbler" | |
#define SLACK_SSL_FINGERPRINT "C1 0D 53 49 D2 3E E5 2B A2 61 D5 9E 6F 99 0D 3D FD 8B B2 B3" // If Slack changes their SSL fingerprint, you would need to update this | |
#define SLACK_BOT_TOKEN "xxxxx" // Get token by creating new bot integration at https://my.slack.com/services/new/bot | |
#define LEDS_PIN D2 | |
#define LEDS_NUMPIXELS 24 | |
#define WORD_SEPERATORS "., \"'()[]<>;:-+&?!\n\t" | |
ESP8266WiFiMulti WiFiMulti; | |
WebSocketsClient webSocket; | |
long nextCmdId = 1; | |
bool connected = false; | |
#include <Servo.h> | |
Servo myservo; // create servo object to control a servo | |
int pos = 0; // variable to store the servo position | |
/** | |
Sends a ping message to Slack. Call this function immediately after establishing | |
the WebSocket connection, and then every 5 seconds to keep the connection alive. | |
*/ | |
void sendPing() { | |
DynamicJsonDocument jsonBuffer; | |
JsonObject root = jsonBuffer.to<JsonObject>(); | |
root["type"] = "ping"; | |
root["id"] = nextCmdId++; | |
String json = ""; | |
serializeJson(jsonBuffer, json); | |
webSocket.sendTXT(json); | |
} | |
/** | |
Looks for names in the incoming slack messages | |
*/ | |
void processSlackMessage(char *payload) { | |
StaticJsonDocument<200> doc; | |
deserializeJson(doc, payload); | |
JsonObject root = doc.as<JsonObject>(); | |
if(root["type"] == "message") { | |
const char *message = root["text"]; | |
char *nextWord = NULL; | |
for (nextWord = strtok((char *) message, WORD_SEPERATORS); nextWord; nextWord = strtok(NULL, WORD_SEPERATORS)) { | |
//Serial.println(nextWord); | |
if (strcasecmp(nextWord, "wordtomatch") == 0 || | |
strcasecmp(nextWord, "@here") == 0) { | |
Serial.println("match!!!"); | |
myservo.write(0); | |
delay(200); | |
myservo.write(180); | |
delay(200); | |
myservo.write(0); | |
delay(200); | |
myservo.write(180); | |
delay(200); | |
myservo.write(0); | |
} | |
} | |
} | |
} | |
/** | |
Called on each web socket event. Handles disconnection, and also | |
incoming messages from slack. | |
*/ | |
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); | |
sendPing(); | |
break; | |
case WStype_TEXT: | |
Serial.printf("[WebSocket] Message: %s\n", payload); | |
processSlackMessage((char*)payload); | |
break; | |
} | |
} | |
/** | |
Establishes a bot connection to Slack: | |
1. Performs a REST call to get the WebSocket URL | |
2. Conencts the WebSocket | |
Returns true if the connection was established successfully. | |
*/ | |
bool connectToSlack() { | |
// Step 1: Find WebSocket address via RTM API (https://api.slack.com/methods/rtm.connect) | |
HTTPClient http; | |
http.begin("https://slack.com/api/rtm.connect?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("\\/", "/"); | |
// Step 2: Open WebSocket connection and register event handler | |
Serial.println("WebSocket Host=" + host + " Path=" + path); | |
webSocket.beginSSL(host, 443, path, "", ""); | |
webSocket.onEvent(webSocketEvent); | |
return true; | |
} | |
void setup() { | |
Serial.begin(115200); | |
Serial.setDebugOutput(true); | |
//wemos D1 pinout: https://escapequotes.net/esp8266-wemos-d1-mini-pins-and-diagram/ | |
// we are using IO5 -> D1 | |
myservo.attach(5); | |
WiFiManager wifiManager; | |
// Try to connnect to the previously configured wifi network - or project a | |
// configuration portal temporarily. | |
// | |
wifiManager.autoConnect(NAME); | |
Serial.println("connected"); | |
configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov"); | |
} | |
unsigned long lastPing = 0; | |
/** | |
Sends a ping every 5 seconds, and handles reconnections | |
*/ | |
void loop() { | |
webSocket.loop(); | |
if (connected) { | |
// Send ping every 5 seconds, to keep the connection alive | |
if (millis() - lastPing > 5000) { | |
sendPing(); | |
lastPing = millis(); | |
} | |
} else { | |
// Try to connect / reconnect to slack | |
connected = connectToSlack(); | |
if (!connected) { | |
delay(500); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment