3Dプリンタの印刷終了をLINEにポストする機能をケースに組み込みました。
内部はこんな感じです。暗号化したWiFiのSSIDやパスワード、LINE notifyのトークン、およびポストするメッセージを格納したmicroSDはケースの蓋を開けないと取り外しできないようにしました。写真左側は、フォトリフレクタを収めたセンサ部です。
印刷を開始するとヒートベッドが最初何度が行き来するので、それが終わってヒートベッドがセンサ部を覆わなくなったらLINEダッシュボタンの電源を入れます。すると、監視開始のメッセージがポストされ、正常に監視を始めたことが分かります。
数時間後、印刷が終わるとヒートベッドが再びセンサ部を覆うので、それをトリガに印刷終了メッセージがポストされ、スマホが受け取ります。写真ではスマホを隣に並べていますが、LINEが繋がる場所ならどこにいても届きます。
回路図です。三端子レギュレータは1Aのものを使いましたが、500mA取れれば大丈夫なようです。
microSDに書き込むデータと暗号化処理は、昨日のWindows版暗号化、ESP32版暗号化 の記事を参照ください。
以下、ESP32のスケッチです。一応動いていますが、無保証です。
//--------------------------------------------------------------- // 2022.02.12 naka // LINE Dash Button(フォトリフレクタ版) // // ・WiFi ssid,password,LINE notify tokenは、暗号化してmicroSDに格納 // ファイル名:setup.txt // 暗号化したWiFi ssid, password, LINE notify tokenをそれぞれ1行ずつ // 順に記載し、4行目、5行目に送るメッセージを記載。 // (例) // &D/)%X/C04S+#T'?+USM // *%/O-J_F$##5)CK`(% // #VGN-Z_*-FCG+VK1/E;M<47E1UCJ.C/`-U(S#F?C06CV)%C_0$$E8W$89(0[5(U // 動作を開始しました。 // ボタンが押されました。 //--------------------------------------------------------------- #include <WiFi.h> #include <WiFiClientSecure.h> #include <SD.h> #define SD_CS 16 // SD card chip select #define SW GPIO_NUM_13 #define LED_G 25 #define LED_R 27 #define ON 1 #define OFF 0 #define FILENAME "/setup.txt" // ssid,pw,tokenを暗号化したときのキー char* crypt_key = "Open Sesame"; // LINE Notify const char* host = "notify-api.line.me"; char ssid[64],password[64],token[64],message1[128],message2[128]; int sw_newest; void setup() { pinMode(SW,INPUT_PULLUP); pinMode(LED_G,OUTPUT); pinMode(LED_R,OUTPUT); led_green(OFF); led_red(OFF); sw_newest = digitalRead(SW); if (read_setup_file(FILENAME)) { blink_red(10); esp_sleep_enable_ext0_wakeup(SW, LOW); esp_deep_sleep_start(); } // GPIO割り込みピン設定 gpio_wakeup_enable(SW, GPIO_INTR_LOW_LEVEL); // 動作確認のために動作開始メッセージを送る wifi_connect(); // WiFi接続 send_msg2line(message1); // LINE notifyに1行目のメッセージを送る wifi_disconnect(); // WiFi接続解除 led_green(ON); // GPIO割り込みでのsleep復帰を有効化 esp_sleep_enable_gpio_wakeup(); } void loop(){ // スリープ開始(復帰はこの後ろ) esp_light_sleep_start(); wifi_connect(); // WiFi接続 send_msg2line(message2); // LINE notifyに2行目のメッセージを送る wifi_disconnect(); // WiFi接続解除 led_green(ON); while(!digitalRead(SW)); delay(100); // チャタリング対策 } void led_green(int onoff) { if (onoff==ON) digitalWrite(LED_G,LOW); else digitalWrite(LED_G,HIGH); } void led_red(int onoff) { if (onoff==ON) digitalWrite(LED_R,LOW); else digitalWrite(LED_R,HIGH); } void wifi_connect() { WiFi.begin(ssid, password); int onoff = 0; while (WiFi.status() != WL_CONNECTED) { delay(500); if (onoff==0) led_green(ON); else led_green(OFF); onoff ^= 1; } // 以下5行は、普通は不要なハズ IPAddress gateway(192,168,0,1); IPAddress subnet(255,255,255,0); IPAddress dns1(8, 8, 8, 8); // Google DNS primery server IPAddress dns2(8, 8, 4, 4); // Google DNS secondary server WiFi.config(WiFi.localIP(),gateway,subnet,dns1,dns2); led_green(ON); } void wifi_disconnect() { WiFi.disconnect(true); led_green(OFF); } void send_msg2line(char* message) { WiFiClientSecure client; led_red(ON); client.setInsecure(); if (!client.connect(host, 443)) { blink_red(10); led_red(OFF); return; } String query = String("message=") + String(message); String request = String("") + "POST /api/notify HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Authorization: Bearer " + token + "\r\n" + "Content-Length: " + String(query.length()) + "\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n\r\n" + query + "\r\n"; client.print(request); while (client.connected()) { String line = client.readStringUntil('\n'); if (line == "\r") { break; } } String line = client.readStringUntil('\n'); led_red(OFF); } void blink_red(int no) { int onoff = 1; int i; for (i=0; i<no*2 ;i++) { delay(100); if (onoff==0) led_red(ON); else led_red(OFF); onoff ^= 1; } } int read_setup_file(char* fileName) { char buff[128]; if (!SD.begin(SD_CS, SPI, 24000000)) return 1; File setupFile = SD.open(fileName,FILE_READ); if (setupFile) { readLine(setupFile,buff); decrypt(ssid,buff,crypt_key); readLine(setupFile,buff); decrypt(password,buff,crypt_key); readLine(setupFile,buff); decrypt(token,buff,crypt_key); readLine(setupFile,message1); readLine(setupFile,message2); setupFile.close(); } return 0; } // microSDから1行読み取る int readLine(File fp, char *buff){ int i = 0; if(!fp.available()) { return -1; } while (fp.available()) { char c = fp.read(); if (c=='\r'); else if (c=='\n') break; else buff[i++] = c; } buff[i] = 0; return i; } void decrypt( char*a, char*b, char* key) { char x[128]; int i,j,k,m; // ascii文字をbinaryに戻す for(i=0; b[i]!=0; i++) { x[i] = b[i] - (int)'#'; } m = i - 1; // 6bit -> 8bit j = 0; for(i=0; j<m ; i++) { switch (i%3) { case 0: a[i] = (x[j]&0x3F)<<2 | (x[j+1]&0x30)>>4; j++; break; case 1: a[i] = (x[j]&0x0F)<<4 | (x[j+1]&0x3C)>>2; j++; break; case 2: a[i] = (x[j]&0x03)<<6 | x[j+1]&0x3F; j += 2; break; } } m = i; k = 0; int n = strlen(key); for (i=0; i<m; i++) { a[i] ^= key[k++]; k %= n; } a[i]= 0; } //--------------------------------------------------------------- // EOF //---------------------------------------------------------------
0 件のコメント:
コメントを投稿