タグ「M5StickC」を含む投稿[2件]
Tweet ⌚ 2023年7月17日(月) 08:43:28 情報 <19935文字>
M5StickC Plus の開発環境を構築する
elchika公式 @elchika_info さんがリツイートキャンペーンを行っていたのですが…
(ツイート埋め込み処理中...)Twitterで見る
それに応募したら大当選しちゃいました!!
そんな訳で M5StickC Plus を頂きました! 本当にありがとございます!!(>_<)w
こないだから Arduino Pro Micro をぼちぼちとイジり始めてマイコンへの興味が盛り上がってきた所なんで…さらに見識を深めることができそうで嬉しいです!(>_<)w
:
そんな M5StickC Plus の外観をざっくり見てみましょう
裏面には I/O の説明が所狭しと書かれています 何かとよく使う(と思われる)ボタンや LED のピン番号なんかも書かれているんで…ド忘れした時とかでも困らないと思います
USB は Type-C のようです
USB を挿して電源が供給されると起動するようです 何やらセンサーの状況が見れるようなものとかマイクのテストや赤外線の送信(?)のようなものを「M5」ボタンで切り替えながら楽しめるようです
ちなみに電源の ON/OFF は側面のボタンを長押しすることにより操作できるようです 電源を ON する場合には 2 秒位の長押しで電源を OFF にする場合は 6 秒くらい長押しするといいようです
:
そんな訳なんで動作チェックがてら開発環境を整えていきましょう M5StickC Plus (M5Stackシリーズ) の開発環境は Arduino IDE を使ってどうにかできるようなんで手軽っちゃぁ手軽ですよね
その辺の詳細な手順については 公式 に詳しく書かれていたんで…それを実際に試していきたいと思います
まずは Arduino IDE の「ファイル」→「環境設定」を開きます
その中の「追加ボードマネージャのURL」に https://m5stack.oss-cn-shenzhen.aliyuncs... を追加して「ok」します
お次に「ツール」→「ボード」→「ボードマネージャ」を開きます
検索欄に「m5stack」と入れて出てきた「M5Stack」をインストールする
これで「ツール」→「ボード」とした際に「M5Stick-C Plus」を選べるようになります
:
使用ボードの設定が済んだらライブラリをインストールします
「スケッチ」→「ライブラリをインクルード」→「ライブラリを管理」を開きます
検索欄に「m5stickcplus」と入れて出てきた「M5StickCPlus」をインストールします
なんか関連したライブラリ(?)も一緒にインストールするか聞かれるんだけど…よく判んなかったんで全部入れちゃいました(汗
ちなみに…もし間違ったライブラリを入れちゃった時にそれを消したい場合は「ファイル」→「環境設定」で確認できる「スケッチブックの保存場所」で確認できるフォルダを開いて libraries フォルダを開いて
該当するライブラリが入っているフォルダを削除して Arduino IDE を再起動すると消すことができるようです
まぁとにかくコレで M5StickC Plus のライブラリをインクルードできるようになりました
:
それじゃ実際にコードを書いてコンパイルして M5StickC Plus に書き込んでみましょう まぁ本来なら LED を点滅させる…いわゆる「Lチカ」を試すべきトコロなんですが液晶ディスプレイが搭載されているって事なんでそれに文字を出力させてみましょう
----------
# include <M5StickCPlus.h>
void setup(){
M5.begin(); // M5StickC Plus の初期化?
}
void loop() {
M5.Lcd.setTextSize(3); // フォントサイズ
M5.Lcd.setRotation(3); // 画面表示の向き
M5.Lcd.print("Hello World"); // お決まりのやつ
}
----------
ざっくりこんな感じですかね これをマイコンボードに書き込んでみましょう
無事に「Hello World」と表示されて大成功です!
:
ちなみにコンパイル時に…我が家の環境では以下のようなエラーが発生しました
Traceback (most recent call last):
File "/home/nekoyama/.arduino15/packages/m5stack/tools/esptool_py/3.1.0/esptool.py", line 38, in <module>
import serial
ModuleNotFoundError: No module named 'serial'
exit status 1
ボードM5Stick-C-Plusに対するコンパイル時にエラーが発生しました。
これは Python にシリアル通信するための pyserial モジュールが入ってない時に発生するらしいので…
pip install pyserial としてインストールしておけばいいようですメモ
:
さらにちなみに初回起動時に動いていたセンサーの状況が見れるようなものとかマイクのテストや赤外線の送信(?)のようなものは「ファイル」→「スケッチ例」→「M5StickCPlus」→「FactoryTest」で再び入れ直せるようです 他にも参考になりそうなものが用意されているんで…ざっと目を通しておくといいかもです
:
Arduino Pro Micro と M5StickC Plus を比べると…すぐに使える I/O が豊富でいろいろ興味を駆り立てられてしまいますね! 特に ESP32 ってやつですかね Wi-Fi でコネクションを確立したりその後に HTTP としてサーバからドキュメンをを取ってこれたりもできるようなんで Web サーバと連携させて M5StickC Plus をリモートで操作するようなものとか作れるかもしれんですね!
そんな感じで引き続きぼちぼちイジっていきたいと思います #Arduino #M5StickC
Tweet ⌚ 2022年3月26日(土) 15:07:18 情報 <2732文字>
(M5) ATOM Lite でまぁまぁスマートなリモコンを作ろう
今年の初めに…かれこれ 18 年くらい住んでたボロアパートをぶっ壊すってんで追い出されて今度は高級マンションの最上階に引っ越してきました!(>_<)w そんな高級マンションには…ご入居前リフォームで 2022 年製のエアコンに交換されていたのはいいんだけどちょっと使いづらいんですよね
何が使いづらいかっていうと…リモコンでのタイマーセットが不便なんですよ 以前のボロアパートで使ってたエアコンはリモコンに RTC(時計) が実装されていたのでタイマーセットも絶対時間で行うことができていたんですよ それがご新居のエアコンのリモコンには RTC(時計) が付いてないもんだでタイマーセットしようとすると「7時間後」って感じの相対時間での設定になるんですよ 不便ですよね(-_-;)
そんな訳なんでもちっとタイマーセットしやすいリモコンをどうにかするっていうか…せっかくなんでスマホちゃん等と連動させて絶対時間でエアコンの On/Off を制御できるリモコンを作ってみることにしました
昨年に「安いじゃん!」って思って買っておいた (M5) ATOM Lite が手元にあるんでそれを使うことにしました 今買うなら (M5) ATOMS3 Lite のほうがいいのかも知れないけど未確認です汗
それと CGI っていうか Perl が使える Web サーバが必要です 今回は Raspberry Pi OS にセットアップした Apache を使ってるけど…プロバイダなどで供されている CGI の使える Web サーバでも大丈夫だと思います
そうそう今回使う (M5) ATOM Lite には RTC が載っていません それ即ち時計が使えないって事なんでその辺をどうにかしなければなりません
そこで一定時間(今回は約30秒)ごとに Web サーバにアクセスして…アクセスされた Web サーバが現在時刻(とエアコン設定内容)を返しそれにより時刻の判定を行うようにしました
:
それでは最初に (M5) ATOM Lite の方から初めていきましょう 開発環境は Linux っていうか Snap 版の Arduino IDE を使いました まぁ Arduino IDE であれば Windows 版とかでも同じく使えるとは思いますが未確認です汗 そんな Arduino IDE の設定は M5StickC Plus の開発環境を構築する が参考になると思います ボードを追加した後に「M5Stack-ATOM」を設定すれば ok です
お次は (M5) ATOM Lite 向けのライブラリのインストールですかね これは「ツール」メニューから「ライブラリを管理…」を選んで検索窓に必要なキーワードを入れて出てきたものをインストールってする感じですかね
「m5atom」と入れて出てきた「M5Atom」をインストールする
「irremoteesp8266」と入れて出てきた「IRremoteEsp8266」をインストールする
「heatpumpir」と入れて出てきた「HeatpumpIR」をインストールする
これでライブラリ類の準備も完了ですかね それではコードを見ていきましょう…っていうか手探りの「どうにか動く」テスト的なものだったのが意外と問題なく動いてしまって「あーなんか書き直すのもめんどくさいなー」って気分が昂ぶってきたんでそんなテスト的なものをそのまま載せています 動作未保証なのはもちろんとして…諸々をきちっと書き直して使ってください それだけが私の望みです汗
:
----- Start of remcon.ino -----
#include <M5Atom.h> // Atom のヘッダファイルを準備
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <MitsubishiHeatpumpIR.h>
const char* url = "http://user:pass@hoge.orz/remocon/read.cgi"; // 現在時刻&設定内容の場所
const char* ssid = "WiFi_ssid"; // SSID
const char* password = "WiFi_pass"; // パスワード
const uint16_t kIrLed = 12; // 赤外線 LED 送信用のポート番号
IRSenderBitBang irSender(kIrLed); // 赤外線LEDが接続されているピン番号
HeatpumpIR *airCon = new MitsubishiFDHeatpumpIR(); // 三菱エアコンのインスタンス
// FastLED ライブラリの設定(CRGB構造体)
CRGB dispColor(uint8_t r, uint8_t g, uint8_t b) {
return (CRGB)((r << 16) | (g << 8) | b);
}
WiFiMulti WiFiMulti; // Wi-Fi を使いたい
void setup() {
Serial.begin(115200);
Serial.println("");
M5.begin(true, false, true); // 本体初期化(UART有効, I2C無効, LED有効)
M5.dis.drawpix(0, dispColor(0, 0, 0)); // LED全消灯(赤, 緑, 青)
WiFiMulti.addAP(ssid, password); // 「SSID」と「パスワード」を設定しておく
Serial.print("Fi-Fi Connecting.");
}
void loop() {
while (WiFiMulti.run() != WL_CONNECTED) {
Serial.print(".");
M5.dis.drawpix(0, dispColor(255, 0, 0)); //LED(赤)
delay(500);
}
Serial.print("ADDR: ");
Serial.println(WiFi.localIP());
M5.dis.drawpix(0, dispColor(20, 20, 20)); // LED(白)
HTTPClient http;
http.begin(url);
Serial.print("GET: ");
int httpCode = http.GET(); // GET メソッドでファイルを取得
Serial.println(httpCode);
// Serial.println(http.errorToString(httpCode));
if (httpCode > 0) {
String htdoc = http.getString(); // 取得したファイルの内容
Serial.println(htdoc);
// YYYY/MM/DD HH:YY:MM(WDAY)\ts?,HH:MM e?,HH:MM m?
// 現在年/月/日 時:分:秒(曜日)\t開始フラグ,時:分 終了フラグ,時:分 モード
String now_hour = htdoc.substring(11, 13); // 現在時を取得
String now_min = htdoc.substring(14, 16); // 現在分を取得
String st = htdoc.substring(25, 27); // 開始フラグを取得
String ed = htdoc.substring(34, 36); // 終了フラグを取得
String st_hour = htdoc.substring(28, 30); // 開始時
String st_min = htdoc.substring(31, 33); // 開始分
String ed_hour = htdoc.substring(37, 39); // 終了時
String ed_min = htdoc.substring(40, 42); // 終了分
String md = htdoc.substring(43, 45); // モードを取得
if (st == "s1" && now_hour == st_hour && now_min == st_min) {
if (md == "m1") {
Serial.println("Cool");
M5.dis.drawpix(0, dispColor(0, 0, 255)); //LED(青)
airCon->send(irSender, POWER_ON, MODE_COOL, FAN_1, 28, VDIR_DOWN, HDIR_AUTO); // 冷房
} else if (md == "m2") {
Serial.println("Hot");
M5.dis.drawpix(0, dispColor(255, 255, 0)); //LED(黄)
airCon->send(irSender, POWER_ON, MODE_HEAT, FAN_1, 16, VDIR_DOWN, HDIR_AUTO); // 暖房
} else {
Serial.println("Dry");
M5.dis.drawpix(0, dispColor(0, 255, 0)); //LED(緑)
airCon->send(irSender, POWER_ON, MODE_DRY, FAN_1, 28, VDIR_DOWN, HDIR_AUTO); // 除湿
}
}
if (ed == "e1" && now_hour == ed_hour && now_min == ed_min) {
Serial.println("--- Stop ---");
M5.dis.drawpix(0, dispColor(255, 0, 255)); //LED(紫)
airCon->send(irSender, POWER_OFF, MODE_COOL, FAN_1, 28, VDIR_DOWN, HDIR_AUTO); // 電源 Off
}
} else { // ファイルの取得に失敗している
Serial.println("Error");
}
delay(30000);
}
----- End of remcon.ino -----
※デバッグ用のシリアル通信のアレが残っているんで実稼働時には消したほうがいいかも知れないです
冒頭の #include <MitsubishiHeatpumpIR.h> は…まぁ見ての通り三菱社製のエアコン制御をする時に使うものです これが他社製であれば
#include <DaikinHeatpumpIR.h> // ダイキン社製
#include <FujitsuHeatpumpIR.h> // 富士通社製
#include <HitachiHeatpumpIR.h> // 日立社製
#include <PanasonicHeatpumpIR.h> // パナソニック社製
#include <ToshibaHeatpumpIR.h> // 東芝社製
こんな感じになるんじゃないかと思います(未確認) 詳しくは Aruduino IDE の関連フォルダ Arduino/libraries/HeatpumpIR/ を眺めてみるといいかと思います
:
データ(と時間)を取ってくる Web サーバの設定と… Wi-Fi 接続に関する設定を行います
const char* url = "http://user:pass@hoge.orz/remcon/read.cgi"; // 現在時刻&設定内容の場所
const char* ssid = "WiFi-ssid"; // SSID
const char* password = "WiFi-pass"; // パスワード
保安上っていうか恐らくベーシック認証なりをかけて運用すると思うのですが…その際に ID とパスワードの入力を自動化しておかねばなりません そんなときは http://user:pass@hoge.orz/remcon/read.cgi って感じで URL の前に「user:pass@」を付ければ自動で認証してくれます この書き方は一般的なブラウザでも(警告が出るかもだけど)使えます
その次に Wi-Fi の SSID とパスワードの設定を行います 上記のベーシック認証と併せて平文のパスワードを記すことになるので取り扱いには十分注意してください
:
HTTPClient http;
http.begin(url);
int httpCode = http.GET(); // GET メソッドでファイルを取得
Wi-Fi 接続が確立したら目的のサーバからデータを取ってきます 後でも説明しますが…ここで得られるデータは次のようになっています
YYYY/MM/DD HH:YY:MM(WDAY)[タブ(\t)]s?,HH:MM e?,HH:MM m?
[タブ(\t)] の前半がアクセスした時点での日時
[タブ(\t)] の後半がエアコンの開始/終了の時刻とモードを指しています
例えば 12 時 34 分に作動させたい場合は s1,12:34 となります その次が e1,23:45 だったら 23 時 45 分に電源を切る動作となります これが s0 もしくは e0 だった場合は何も動作しないようにしています
行末の m? は動作モードを指しています m1 が冷房 m2 が暖房 m3 が除湿です
http.GET(); した際のバッファサイズが不明だったんで…できるだけ切り詰めて必要最小限の内容にしました バッファに余裕があればもっと見やすい内容にするのもアリかもしれませんね
:
そして実際に赤外線で信号を送信する部分です
airCon->send(irSender, POWER_ON, MODE_COOL, FAN_1, 28, VDIR_DOWN, HDIR_AUTO); // 冷房
各パラメータの意味は以下のようになっています
// airCon->send( irSender, POWER_**, MODE_**, FAN1, 温度設定, VDIR_** , HDIR_** ); // 設定項目 ※温度設定は「整数値」で
// Arduino/libraries/HeatpumpIR/HeatpumpIR.h
//
// ・POWER (電源)
// POWER_ON (on)
// POWER_OFF (off)
// ・MODE (モード)
// MODE_AUTO (自動)
// MODE_COOL (冷房)
// MODE_HEAT (暖房)
// MODE_DRY (除湿)
// MODE_ON (不明)
// MODE_OFF (不明)
// ・FAN (風量)
// FAN_AUTO
// FAN_1 (弱)
// FAN_2
// FAN_3
// FAN_4
// FAN_5 (強)
// ・VDIR (風向高さ)
// VDIR_AUTO
// VDIR_UP
// VDIR_MUP
// VDIR_MIDDLE
// VDIR_MDOWN
// VDIR_DOWN
// ・HDIR (風向左右)
// HDIR_AUTO
// HDIR_LEFT
// HDIR_MLEFT
// HDIR_MIDDLE
// HDIR_MRIGHT
// HDIR_RIGHT
エアコンの設定温度は整数値で指定する必要があるようです 最近は 0.5℃ 間隔で設定できるエアコンが増えてる感じですが…そこまで細かい制御には対応できないっぽいです また今回のプログラムでは設定温度を即値の決め打ちしています 使い勝手を高めるのであればこの辺も外部から変更できるようにすべきですね
だいたいこんな感じですかね これを delay(30000); して約 30 秒間隔のループで回しています なにかの都合…例えば http.GET(); した際にサーバの返答が遅れたりするとループ間隔が長くなり指定された時間を通り越してしまうかも?って思ってこのくらいの間隔にしました まぁこの辺は各環境によりけりで程よい設定にしてもらえればなぁって思います
:
さて…お次は UI っていうか Web サーバ側の云々ですかね 用意するのは 4 つのファイル(index.html, index.css, index.cgi, read.cgi)とスクリプトが生成する 1 つのファイル(data.txt)です
----- Start of index.html -----
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<!-- ビューポートの設定 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- スタイルシートの読み込み -->
<link href="./index.css" rel="stylesheet">
<title>M5 Atom Lite タイマー予約</title>
</head>
<body>
<center><div class="red"></div></center>
<center><form action="./index.cgi" method="get">
<div>
<label for="name"><a href="./index.cgi">M5 Atom Lite タイマー予約</a></label>
</div>
<div><hr class="double" width=80% noshade></div>
<div>
<label><input class="st" type="checkbox" name="st" value="1">「入り」を使う</label>
</div>
<div>
<select name="st_hour">
<option class="st_hour" value="00">00</option>
<option class="st_hour" value="01">01</option>
<option class="st_hour" value="02">02</option>
<option class="st_hour" value="03">03</option>
<option class="st_hour" value="04">04</option>
<option class="st_hour" value="05">05</option>
<option class="st_hour" value="06">06</option>
<option class="st_hour" value="07">07</option>
<option class="st_hour" value="08">08</option>
<option class="st_hour" value="09">09</option>
<option class="st_hour" value="10">10</option>
<option class="st_hour" value="11">11</option>
<option class="st_hour" value="12">12</option>
<option class="st_hour" value="13">13</option>
<option class="st_hour" value="14">14</option>
<option class="st_hour" value="15">15</option>
<option class="st_hour" value="16">16</option>
<option class="st_hour" value="17">17</option>
<option class="st_hour" value="18">18</option>
<option class="st_hour" value="19">19</option>
<option class="st_hour" value="20">20</option>
<option class="st_hour" value="21">21</option>
<option class="st_hour" value="22">22</option>
<option class="st_hour" value="23">23</option>
</select>時
<select name="st_min">
<option class="st_min" value="00">00</option>
<option class="st_min" value="10">10</option>
<option class="st_min" value="20">20</option>
<option class="st_min" value="30">30</option>
<option class="st_min" value="40">40</option>
<option class="st_min" value="50">50</option>
</select> 分
</div>
<div><hr class="double" width=80% noshade></div>
<div>
<label><input class="ed" type="checkbox" name="ed" value="1">「切り」を使う</label>
</div>
<div>
<select name="ed_hour">
<option class="ed_hour" value="00">00</option>
<option class="ed_hour" value="01">01</option>
<option class="ed_hour" value="02">02</option>
<option class="ed_hour" value="03">03</option>
<option class="ed_hour" value="04">04</option>
<option class="ed_hour" value="05">05</option>
<option class="ed_hour" value="06">06</option>
<option class="ed_hour" value="07">07</option>
<option class="ed_hour" value="08">08</option>
<option class="ed_hour" value="09">09</option>
<option class="ed_hour" value="10">10</option>
<option class="ed_hour" value="11">11</option>
<option class="ed_hour" value="12">12</option>
<option class="ed_hour" value="13">13</option>
<option class="ed_hour" value="14">14</option>
<option class="ed_hour" value="15">15</option>
<option class="ed_hour" value="16">16</option>
<option class="ed_hour" value="17">17</option>
<option class="ed_hour" value="18">18</option>
<option class="ed_hour" value="19">19</option>
<option class="ed_hour" value="20">20</option>
<option class="ed_hour" value="21">21</option>
<option class="ed_hour" value="22">22</option>
<option class="ed_hour" value="23">23</option>
</select>時
<select name="ed_min">
<option class="ed_min" value="00">00</option>
<option class="ed_min" value="10">10</option>
<option class="ed_min" value="20">20</option>
<option class="ed_min" value="30">30</option>
<option class="ed_min" value="40">40</option>
<option class="ed_min" value="50">50</option>
</select>分
</div>
<div><hr class="double" width=80% noshade></div>
<div>
<input class="md" type="radio" name="md" value="1">冷房
<input class="md" type="radio" name="md" value="2">暖房
<input class="md" type="radio" name="md" value="3">除湿
</div>
<div><hr class="hrline" width=80% noshade></div>
<div>
<input class="submit" type="submit" value="予約">
</div>
</form></center>
</body>
</html>
----- End of index.html -----
index.html ってファイル名なんで…デフォルトで表示されるファイルっぽいですが実際にはそのような用途には使っていません デザインしやすいようにファイルを分割してあるだけで実際に表示は index.cgi が行います
----- Start of index.css -----
/* ボディ */
body { /* 一般的な表示部 */
margin: 0 ;
padding: 0 ;
font-size: 20px ;
line-height: 3 ;
}
input { /* チェックボックス */
width: 25px;
height: 25px;
-moz-transform: scale(1.4);
-webkit-transform: scale(1.4);
transform: scale(1.4);
}
select { /* プルダウンメニュー */
font-size: 30px ;
}
.hrline { /* 罫線(?) */
border: none;
background-color: #fff;
border-width: 1px 0 0 0;
border-top: double;
border-color: black;
}
.submit { /* 送信ボタン */
width: 100px;
height: 40px;
-moz-transform: scale(1.4);
-webkit-transform: scale(1.4);
transform: scale(1.4);
}
.red { /* 設定変更した */
font-size: 40px ;
color: #ff0000;
}
/* スマホだけに適用するCSS */
@media screen and ( max-width:479px ) {
body { /* 一般的な表示部 */
font-size: 20px ;
}
input { /* チェックボックス */
width: 25px;
height: 25px;
-moz-transform: scale(1.4);
-webkit-transform: scale(1.4);
transform: scale(1.4);
}
select { /* プルダウンメニュー */
font-size: 25px ;
}
.hrline { /* 罫線(?) */
border: none;
background-color: #fff;
border-width: 1px 0 0 0;
border-top: double;
border-color: black;
}
.submit { /* 送信ボタン */
width: 100px;
height: 40px;
-moz-transform: scale(1.4);
-webkit-transform: scale(1.4);
transform: scale(1.4);
}
.red { /* 設定変更した */
font-size: 40px ;
color: #ff0000;
}
}
----- End of index.css -----
でっか文字な表示にしたくて見様見真似で用意しました 見様見真似の即興ってことで CSS について何一つ理解していません汗 おかしな所しかないと思うけど…まぁその辺は生温かい目で見守って頂けると幸いに思います(瀧汗
----- Start of index.cgi -----
#!/usr/bin/perl
$datafile = "./data.txt"; # ATOM Lite が読みにくるファイル
$htmlfile = "./index.html"; # ベースとなる HTML ファイル
if ($ENV{'REQUEST_METHOD'} eq 'POST') { # POST メソッドで送られてきた場合
read(STDIN, $query, $ENV{'CONTENT_LENGTH'});
} else { # GET メソッドで送られてきた場合
$query = $ENV{'QUERY_STRING'};
}
#### ATOM Lite が読みにくるデータファイルを作成する ####
open (DATA, $datafile);
$data = <DATA>; # 既存のデータファイルを読み内容を取り出しておく
if ($data =~ /s(\d),(\d\d):(\d\d) e(\d),(\d\d):(\d\d) m(\d)/) {
$in{'st'} = $1;
$in{'st_hour'} = $2;
$in{'st_min'} = $3;
$in{'ed'} = $4;
$in{'ed_hour'} = $5;
$in{'ed_min'} = $6;
$in{'md'} = $7;
}
close (DATA);
if ($query) { # データを受信していた場合の処理
open (DATA, ">", $datafile);
foreach $data (split(/&/, $query)) { # 「&」で分割して全て処理する
($key, $value) = split(/=/, $data); # 「name=value」のそれぞれに分割して連想配列を作っていく
$value =~ s/\+/ /g; # 以下ざっくりとした URL デコードする
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack('C', hex($1))/eg;
$value =~ s/\t//g;
$in{"$key"} = $value; # value = $in{"$name"} の連想配列が出来上がる
}
# 送られてきた内容を適用してデータファイルを更新
if (!($query =~ /st=/)) { $in{'st'} = '0'; } # チェックボックスの挙動がアレなんで個別対応(汗
if (!($query =~ /ed=/)) { $in{'ed'} = '0'; } # チェックボックスの挙動がアレなんで個別対応(汗
if ($in{'st'}) { print DATA "s1,"; } else { print DATA "s0,"; }
if ($in{'st_hour'}) { printf DATA "%02d:", $in{'st_hour'}; } else { print DATA "00:"; }
if ($in{'st_min'}) { printf DATA "%02d ", $in{'st_min'}; } else { print DATA "00 "; }
if ($in{'ed'}) { print DATA "e1,"; } else { print DATA "e0,"; }
if ($in{'ed_hour'}) { printf DATA "%02d:", $in{'ed_hour'}; } else { print DATA "00:"; }
if ($in{'ed_min'}) { printf DATA "%02d ", $in{'ed_min'}; } else { print DATA "00 "; }
if ($in{'md'} eq "1") { print DATA "m1\n"; } elsif ($in{'md'} eq "2") { print DATA "m2\n"; } else { print DATA "m3\n"; }
close (DATA);
}
open (IN, $htmlfile); # 以下ベースとなる HTML ファイルを読み込み設定時間などを反映させる
print "Content-type: text/html; charset=UTF-8\n\n";
@lines = <IN>;
foreach (@lines) {
if ($query) { s/(<div class="red">)(<\/div>)/$1設定しました$2/; }
if ($in{'st'} eq "1") { s/(class="st")/$1 checked/; }
if ($in{'st_hour'}) { s/(class="st_hour" value=")($in{'st_hour'}")/$1$2 selected/; }
if ($in{'st_min'}) { s/(class="st_min" value=")($in{'st_min'}")/$1$2 selected/; }
if ($in{'ed'} eq "1") { s/(class="ed")/$1 checked/; }
if ($in{'ed_hour'}) { s/(class="ed_hour" value=")($in{'ed_hour'}")/$1$2 selected/; }
if ($in{'ed_min'}) { s/(class="ed_min" value=")($in{'ed_min'}")/$1$2 selected/; }
if ($in{'md'}) { s/(name="md" value=")($in{'md'}")/$1$2 checked="checked"/; }
print $_;
}
close (IN);
----- End of index.cgi -----
実際に表示を受け持つ index.cgi です 表示を受け持ちつつ…フォームで入力された値を解釈して data.txt を生成します そしてそのフォームで入力された値 index.html の内容を書き換えて表示するようになっています こうしておけば以前の設定内容を次回の設定に引き継げるようになるので便利かなーって思いまして
そんな訳なんで .htaccess で Web サーバの設定変更が可能な場合は DirectoryIndex index.cgi としてデフォルトで読み出されるファイルに設定しておくといいでしょう
あとこの index.cgi は GET メソッドでデータを受けれられるので…極端な話パラメータ付きの URL を直打ちすることでも設定が可能です 例えば 08 時 20 分 に 冷房 で作動させ 19 時 30 分 に電源を切る場合だと
http://user:pass@hoge.orz/remocon/index.cgi?st=1&st_hour=08&st_min=20&ed=1&ed_hour=19&ed_min=30&md=1
こんな感じの URL になります それ即ち wget や curl などのコマンドでアクセスすることが可能となり…さらに cron などを使えば毎日の動作や毎週の動作といった感じで自動化することも可能になります いや実際に試してはないですけどたぶん大丈夫だと思います汗
----- Start of read.cgi -----
#!/usr/bin/perl
print "Content-type: text/plain; charset=UTF-8\n\n";
# 現在日時の表示
@wdays = ( "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime(time());
printf "%04d/%02d/%02d %02d:%02d:%02d(%s)\t", $year + 1900, $mon + 1, $mday, $hour, $min, $sec, $wdays[$wday];
$datafile = "./data.txt"; # ブラウザで設定した内容のファイル
open (DATA, $datafile);
print <DATA>; # ファイルの 1 行目を読み取り表示する
close (DATA);
----- End of read.cgi -----
(M5) ATOM Lite がアクセスしてくるファイル(CGI)です 現在日時を整形して表示して…あとは index.cgi が生成した data.txt の内容をくっつけて送信してくれます
:
ごちゃごちゃ長くなったんで以下にまとめときます 「名前を付けてリンク先を保存」とかすれば手間がなくていいと思いますたぶん
remcon.ino (M5) ATOM Lite 用 Arduino Sketch ファイル
index.html 表示のベースとなる HTML ファイル
index.css でっか文字にするためのアレ
index.cgi ページ表示しつつデータファイルを作成する
read.cgi (M5) ATOM Lite が読みに来る先のやつ
data.txt index.cgi が作成するデータファイル
そして後はいい感じに設置して完了ですかね (M5) ATOM Lite の赤外線はかなり飛距離が短いんで…エアコンにへばりつけるような設置になっちゃうのかな
あーあと余談っていうか注意事項ですが (M5) ATOM Lite が読みに来る read.cgi は数十秒に 1 回のペースで 24 時間 365 日延々とアクセスがあります そのままの Web サーバだと…そのアクセス毎にログファイルが蓄積されることになります もし可能なら Web サーバの設定を変更して…このアクセスに対してのみログの書き込みを抑制するなどしたほうがいいと思います ざっくり SetEnvIf nolog なんて感じのキーワードでぐぐれば必要な情報に辿り着けるとイイナ!
:
そんな感じで最後までご覧いただきありがとございました汗 ざっくりテスト用に作ったのをイジくりまわした代物なのでいろいろおかしな部分はありますが…手っ取り早く動作を体感してみたい!って時には役立つかもです それにしても 1,000円 ちょっとで買える (M5) ATOM Lite はホントすごいですよね きちんと筐体に収められていつつ… Wi-fi で接続を確立して HTTP でデータを取ってくることができる 赤外線 LED でリモコンのような動作もさせられる 欲を云えば RTC(時計) が欲しかったかなって感じではあるけど…それもどっかのサーバに接続して時刻を取得すればそれほど問題にはならないんでまぁいいかな♪ なんかそんなかんじで #Arduino #M5StickC