Skip to content

Instantly share code, notes, and snippets.

@moyashipan
Created November 23, 2020 07:54
Show Gist options
  • Save moyashipan/9440c3c02659d0b1e986c900a2f803be to your computer and use it in GitHub Desktop.
Save moyashipan/9440c3c02659d0b1e986c900a2f803be to your computer and use it in GitHub Desktop.
測距センサーをつないだM5ATOM MatrixからAlexaのChangeReportを送る
String regenerateAccessToken() {
String payload = "";
payload += "grant_type=refresh_token";
payload += "&refresh_token=" + REFRESH_TOKEN;
payload += "&client_id=amzn1.application-...";
payload += "&client_secret=...";
HTTPClient client;
client.begin("https://api.amazon.com/auth/o2/token");
client.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpCode = client.POST(payload);
Serial.printf("[HTTPS] POST... code: %d\n", httpCode);
String response_body = client.getString();
Serial.println(response_body);
int str_start = response_body.indexOf("Atza|");
int str_end = response_body.indexOf("\"", str_start);
String access_token = response_body.substring(str_start, str_end);
client.end();
return access_token;
}
void postChangeRequst(String access_token, bool state) {
String value = state ? "NOT_DETECTED" : "DETECTED";
String payload = "";
payload += "{";
payload += "\"context\": {},";
payload += "\"event\": {";
payload += "\"header\": {";
payload += "\"messageId\": \"abc-123-def-456\",";
payload += "\"namespace\": \"Alexa\",";
payload += "\"name\": \"ChangeReport\",";
payload += "\"payloadVersion\": \"3\"";
payload += "},";
payload += "\"endpoint\": {";
payload += "\"scope\": {";
payload += "\"type\": \"BearerToken\",";
payload += "\"token\": \"" + access_token +"\"";
payload += "},";
payload += "\"endpointId\": \"sensor-001\"";
payload += "},";
payload += "\"payload\": {";
payload += "\"change\": {";
payload += "\"cause\": {";
payload += "\"type\": \"PHYSICAL_INTERACTION\"";
payload += "},";
payload += "\"properties\": [";
payload += "{";
payload += "\"namespace\": \"Alexa.ContactSensor\",";
payload += "\"name\": \"detectionState\",";
payload += "\"value\": \"" + value + "\",";
payload += "\"timeOfSample\": \"" + DateTime.format("%FT%T.00Z") + "\",";
payload += "\"uncertaintyInMilliseconds\": 0";
payload += "}";
payload += "]";
payload += "}";
payload += "}";
payload += "}";
payload += "}";
Serial.println(payload);
HTTPClient client;
client.begin("https://api.fe.amazonalexa.com/v3/events");
client.addHeader("Content-Type", "application/json");
client.addHeader("Authorization", "Bearer " + access_token);
client.addHeader("User-Agent", "M5Stack ATOM Matrix");
client.addHeader("Accept", "*/*");
client.addHeader("Accept-Encoding", "gzip, deflate, br");
int httpCode = client.POST(payload);
Serial.printf("[HTTPS] POST... code: %d\n", httpCode);
client.end();
}
#include <M5Atom.h>
#include <HTTPClient.h>
#include <DateTime.h>
const char SSID[] = "";
const char PASSWORD[] = "";
const String REFRESH_TOKEN = "Atzr|...";
const int RECV_PIN = 33;
const int AVE_LENGTH = 100;
int MIN_CAT_DISTANCE = 1000; // この値以上なら猫がいる
bool last_has_cat = false; // ひとつ前の検出結果
bool stabled_has_cat = false; // チャタリングを無視した現在の状態
int stable_count = 0;
const int MAX_STABLE_COUNT = 3;
int timer = 0;
bool show_led = true;
void setup() {
M5.begin(true, false, true);
delay(50);
pinMode(RECV_PIN, INPUT);
M5.dis.drawpix(0, 0xf00000);
WiFi.mode(WIFI_STA);
wifiDisconnect(true);
while (!wifiConnect());
DateTime.setTimeZone(0);
DateTime.begin();
}
void loop() {
delay(50);
M5.update();
showDistance();
if (M5.Btn.wasPressed()) {
show_led = !show_led;
}
timer++;
if (timer >= 20) {
timer = 0;
} else {
return;
}
int total = 0;
for (int i = 0; i < AVE_LENGTH; i++) {
total += receiveDistance();
}
float ave = (float)total / AVE_LENGTH;
Serial.println(ave);
bool has_cat = ave >= MIN_CAT_DISTANCE;
bool stabled_changed = false;
if (has_cat == last_has_cat) {
if (stable_count < MAX_STABLE_COUNT) {
stable_count++;
bool stabled = (stable_count == MAX_STABLE_COUNT);
stabled_changed = stabled && (has_cat != stabled_has_cat);
}
} else {
stable_count = 0;
}
last_has_cat = has_cat;
// 安定状態が変化した
if (stabled_changed) {
Serial.println("Cat state changed");
// 送信する
post(has_cat);
Serial.println("Completed");
stabled_has_cat = has_cat;
}
}
void showDistance() {
M5.dis.clear();
if (!show_led) {
return;
}
int reading = analogRead(RECV_PIN);
int m = reading * 25 / 4095;
CRGB color = (reading >= MIN_CAT_DISTANCE) ? 0x00ff00 : 0x0000ff;
for (int i = 0; i < m; i++) {
M5.dis.drawpix(i, color);
}
}
int receiveDistance() {
int reading = analogRead(RECV_PIN);
return reading;
}
void led(bool v) {
M5.dis.clear();
if (v) {
M5.dis.drawpix(0, 0xff0000);
}
}
void post(bool state) {
while (!wifiConnect());
String access_token = regenerateAccessToken();
if (access_token.length() > 0) {
postChangeRequst(access_token, state);
}
}
bool wifiConnect() {
wifiDisconnect(true);
WiFi.begin(SSID, PASSWORD);
Serial.print("WiFi connecting");
int count = 0;
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
led(true);
delay(10);
led(false);
delay(90);
if (++count > 100) {
wifiDisconnect(true);
WiFi.begin(SSID, PASSWORD);
Serial.println("");
Serial.print("reconnecting");
count = 0;
}
}
Serial.println(" connected");
return true;
}
bool wifiDisconnect(bool val) {
WiFi.disconnect(val);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment