Skip to content

Instantly share code, notes, and snippets.

@TakuroFukamizu
Created August 25, 2019 05:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TakuroFukamizu/37e932c302ff3a46814fd50e8314155c to your computer and use it in GitHub Desktop.
Save TakuroFukamizu/37e932c302ff3a46814fd50e8314155c to your computer and use it in GitHub Desktop.
Control SESAME mini by M5Stack
#include <M5Stack.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#define WIFI_SSID "YOUR WIFI SSID"
#define WIFI_PASS "YOUR WIFI PASS"
#define SESAME_TOKEN "YOUR API KEY"
#define SESAME_DEVICE_ID "YOUR SESAME ID"
enum SESAME_COMMAND
{
LOCK,
UNLOCK,
};
typedef struct {
bool locked;
uint8_t battery;
bool responsive;
} SESAME_STATUS;
typedef struct {
const char* status;
bool successful;
} ACTION_STATUS;
void setup() {
M5.begin();
wifi_connect();
M5.Lcd.clear();
M5.Lcd.setCursor(0, 3);
M5.Lcd.println("M5Sesame");
M5.Lcd.println(" A: LOCK");
M5.Lcd.println(" B: UNLOCK");
M5.Lcd.println(" C: STATUS");
M5.Lcd.drawLine(0, 40, 320, 40, TFT_BLUE);
M5.Lcd.setCursor(0, 50);
}
void loop() {
M5.update();
try {
if (M5.BtnA.wasPressed()) {
Serial.println("M5.BtnA.wasPressed()");
M5.Lcd.print("LOCK > ");
String taskId = sendCommand(LOCK);
M5.Lcd.println(taskId);
M5.Lcd.print(" > ");
while(true) {
ACTION_STATUS res = getActionResult(taskId);
if (res.successful) {
M5.Lcd.println(" complete");
break;
}
M5.Lcd.print(".");
delay(500);
}
}
if (M5.BtnB.wasPressed()) {
Serial.println("M5.BtnB.wasPressed()");
M5.Lcd.print("UNLOCK > ");
String taskId = sendCommand(UNLOCK);
M5.Lcd.println(taskId);
M5.Lcd.print(" > ");
while(true) {
ACTION_STATUS res = getActionResult(taskId);
if (res.successful) {
M5.Lcd.println(" complete");
break;
}
M5.Lcd.print(".");
delay(500);
}
}
if (M5.BtnC.wasPressed()) {
Serial.println("M5.BtnC.wasPressed()");
M5.Lcd.print("STATUS > ");
SESAME_STATUS status = getStatus();
if (status.locked) {
M5.Lcd.print("LOCK");
} else {
M5.Lcd.print("OPEN");
}
M5.Lcd.print(", battery:" + String(status.battery));
M5.Lcd.println(", responsive:" + String(status.responsive));
}
} catch (char *e) {
Serial.println(e);
}
}
// ----------------
void wifi_connect() {
const char* ssid = WIFI_SSID;
const char* pass = WIFI_PASS;
M5.Lcd.print("Connect to ");
M5.Lcd.println(ssid);
WiFi.disconnect(true);
M5.Lcd.printf(".");
delay(1000);
M5.Lcd.printf(".");
WiFiMulti wifiMulti;
wifiMulti.addAP(ssid, pass);
while (wifiMulti.run() != WL_CONNECTED) {
delay(500);
M5.Lcd.printf(".");
}
M5.Lcd.println("wifi connect ok");
}
SESAME_STATUS getStatus() {
String url = "https://api.candyhouse.co/public/sesame/" + String(SESAME_DEVICE_ID);
Serial.println(url);
HTTPClient http;
http.begin(url);
http.addHeader("Authorization", String(SESAME_TOKEN));
int httpResponseCode = http.GET();
Serial.println("http status code: "+String(httpResponseCode));
if (httpResponseCode < 0) {
Serial.println(http.errorToString(httpResponseCode));
throw http.errorToString(httpResponseCode);
} else if (httpResponseCode != 200) {
throw "other errors: " + String(httpResponseCode);
} else if (http.getSize() < 0) {
throw "size is invalid";
}
SESAME_STATUS res;
Stream* resp = http.getStreamPtr();
StaticJsonDocument<255> resDoc;
deserializeJson(resDoc, *resp);
JsonObject object = resDoc.as<JsonObject>();
bool locked = object["locked"];
uint8_t battery = object["battery"];
bool responsive = object["responsive"];
Serial.print("locked:" + String(locked));
Serial.print("battery:" + String(battery));
Serial.println("responsive:" + String(responsive));
res = { locked, battery, responsive };
http.end();
return res;
}
String sendCommand(SESAME_COMMAND command) {
StaticJsonDocument<200> doc;
switch(command) {
case LOCK : doc["command"] = "lock"; break;
case UNLOCK: doc["command"] = "unlock"; break;
}
String jsonString;
serializeJson(doc, jsonString);
const char* taskId;
HTTPClient http;
http.begin("https://api.candyhouse.co/public/sesame/" + String(SESAME_DEVICE_ID));
http.addHeader("Authorization", String(SESAME_TOKEN));
int httpResponseCode = http.POST(jsonString);
if (httpResponseCode < 0) {
Serial.println(http.errorToString(httpResponseCode));
throw http.errorToString(httpResponseCode);
} else if (httpResponseCode != 200) {
throw "other errors: " + String(httpResponseCode);
} else if (http.getSize() < 0) {
throw "size is invalid";
}
Stream* resp = http.getStreamPtr();
StaticJsonDocument<255> resDoc;
deserializeJson(resDoc, *resp);
JsonObject object = resDoc.as<JsonObject>();
taskId = object["task_id"];
Serial.println("taskId:" + String(taskId));
http.end();
return taskId;
}
ACTION_STATUS getActionResult(String taskId) {
String url = "https://api.candyhouse.co/public/action-result?task_id=" + String(taskId);
Serial.println(url);
HTTPClient http;
http.begin(url);
http.addHeader("Authorization", String(SESAME_TOKEN));
int httpResponseCode = http.GET();
Serial.println("http status code: "+String(httpResponseCode));
if (httpResponseCode < 0) {
Serial.println(http.errorToString(httpResponseCode));
throw http.errorToString(httpResponseCode);
} else if (httpResponseCode != 200) {
throw "other errors: " + String(httpResponseCode);
} else if (http.getSize() < 0) {
throw "size is invalid";
}
ACTION_STATUS res;
Stream* resp = http.getStreamPtr();
StaticJsonDocument<255> resDoc;
deserializeJson(resDoc, *resp);
JsonObject object = resDoc.as<JsonObject>();
const char* status = object["status"];
bool successful = object["successful"];
Serial.println("status:" + String(status) + ", successful:" + String(successful));
res = { status, successful };
http.end();
return res;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment