前回の続き
スタックチャンがしゃべれるようになったので、次は外部からしゃべる指令を出す端末のバージョンアップ。呼び出しは予約確認のための自宅用通知マシンと兼用。
エッジ検出処理&疑似的な並列処理はこちらに大体まとめた感じ。
メインのループ(Arduinoのloop関数)は並行処理するループ(yoyakuCheckLoop,yobidashiCheckLoop)をそれぞれ呼び出しyobidashiCheckLoopの中でボタンが押されている判定をして押されていたらネットワーク越しにスタックチャンがしゃべるURLをたたいてしゃべらせる。
最初はPOSTで叩こうとしたけどPOSTの引数違うぞみたいなエラーメッセージが出たのでとりいそぎGETメソッド(5秒も調べていない)
メインのループの中でyobidashiCheckLoopを呼び出し。下に張った中のyobidashiCheckLoopでやっていることはこちらに大体まとめた感じ。で、execYobidashi(開発環境ならexecDevYobidashi)で、httpsのリクエストを投げているだけ。セキュリティ的なものはつけていないのでそのまま叩ける。
一応全体
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <CertStoreBearSSL.h>
#include <time.h>
#include <FS.h>
#include <LittleFS.h>
#include <WiFiClient.h>
#define DEVELOP
#ifdef DEVELOP
// 見えているけど店の公開wifiなので気にしない
#ifndef STASSID
#define STASSID "rocher_guest";
#define STAPSK "sd5ks86vn5nti";
#endif
const char *ssid = STASSID;
const char *pass = STAPSK;
#endif // DEVELOP
#define INPUT_PIN 12
#define LED_PIN 13
BearSSL::CertStore certStore;
volatile bool pushed = false;
unsigned long lastTimeYoyakuCheck;
unsigned long lastTimeYobidashiCheck;
#ifdef DEVELOP
void connectDevWifi() {
// We start by connecting to a WiFi network
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
#else // not develop
void connectWifi() {
Serial.print("Connecting");
WiFi.begin();
int i = 1;
while (WiFi.status() != WL_CONNECTED) {
if (i++ > 20) { // 10 seconds
Serial.println("Smart Config Start!");
WiFi.mode(WIFI_STA);
WiFi.beginSmartConfig();
while (!WiFi.smartConfigDone()) {
delay(500);
Serial.print(".");
}
Serial.println("Smart Config Done!");
}
delay(500);
Serial.print(".");
}
}
#endif // DEVELOP
// Set time via NTP, as required for x.509 validation
void setClock() {
configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");
Serial.print("Waiting for NTP time sync: ");
time_t now = time(nullptr);
while (now < 8 * 3600 * 2) {
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println("");
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
Serial.print("Current time: ");
Serial.print(asctime(&timeinfo));
}
void IRAM_ATTR shopYobidashiCallback() {
pushed = true;
}
void setup() {
Serial.begin(115200);
Serial.println();
LittleFS.begin();
#ifdef DEVELOP
connectDevWifi();
#else
connectWifi();
#endif // DEVELOP
setClock(); // Required for X.509 validation
int numCerts = certStore.initCertStore(LittleFS, PSTR("/certs.idx"), PSTR("/certs.ar"));
Serial.printf("Number of CA certs read: %d\n", numCerts);
if (numCerts == 0) {
Serial.printf("No certs found. Did you run certs-from-mozilla.py and upload the LittleFS directory before running?\n");
return;
}
pinMode(INPUT_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(INPUT_PIN), shopYobidashiCallback, FALLING);
pinMode(LED_PIN, OUTPUT);
lastTimeYoyakuCheck = millis();
lastTimeYobidashiCheck = millis();
}
const unsigned long yoyakuCheckInterval = 10000;
void yoyakuCheckLoop() {
if ((millis() - lastTimeYoyakuCheck) < yoyakuCheckInterval) {
return;
}
lastTimeYoyakuCheck = millis();
BearSSL::WiFiClientSecure *bear = new BearSSL::WiFiClientSecure();
bear->setCertStore(&certStore);
HTTPClient https;
if (https.begin(*bear, "https://mail.epea.co.jp/api/reserve_count")) {
int httpCode = https.GET();
Serial.print("httpCode:");
Serial.println(httpCode);
String payload = https.getString();
Serial.print("payload:");
Serial.println(payload);
String zero = "0";
if (zero.equals(payload)) {
Serial.println("0件だよ");
digitalWrite(LED_PIN, LOW);
} else {
// 0以外だと点灯。エラー等で変な値が返ってきたときもこっち(ステータス見る処理等はないので大体)
Serial.println("0件じゃないよ");
digitalWrite(LED_PIN, HIGH);
}
}
delete bear;
}
#ifdef DEVELOP
void execDevYobidashi() {
WiFiClient client;
HTTPClient http;
if (http.begin(client, "http://192.168.11.26/yobidashi")) {
int httpCode = http.GET();
Serial.print("httpCode:");
Serial.println(httpCode);
String payload = http.getString();
Serial.print("payload:");
Serial.println(payload);
}
}
#else
void execDevYobidashi() {
BearSSL::WiFiClientSecure *bear = new BearSSL::WiFiClientSecure();
bear->setCertStore(&certStore);
HTTPClient https;
if (https.begin(client, "http://momoyama.epea.co.jp/yobidashi")) {
int httpCode = https.GET();
Serial.print("httpCode:");
Serial.println(httpCode);
String payload = https.getString();
Serial.print("payload:");
Serial.println(payload);
}
delete bear;
}
#endif // DEVELOP
const unsigned long yobidashiCheckInterval = 100;
void yobidashiCheckLoop() {
// チェック間隔以内なら
if ((millis() - lastTimeYobidashiCheck) < yobidashiCheckInterval) {
return;
}
lastTimeYobidashiCheck = millis();
// ボタン押されていなかったら戻る
if (!pushed) {
return;
}
// チャタリング安定待ち(待ち時間は大体)
delay(200);
// LOWが100ms間隔で3回続くか
for (int count = 0; count < 3; count++) {
if (digitalRead(INPUT_PIN)) {
pushed = false;
return;
}
delay(100);
}
// 実処理
#ifdef DEVELOP
execDevYobidashi();
#else
execYobidashi();
#endif // DEVELOP
pushed = false;
}
void loop() {
yoyakuCheckLoop();
yobidashiCheckLoop();
}
続けてネットワーク回り