でんげき☆ Network Service

Raspberry Pi 4 で運用実験中 Connect checker

No.37, No.36, No.35, No.34, No.33, No.32, No.317件]

(M5) ATOM Lite でまぁまぁスマートなリモコンを作ろう

202307171653523-admin.png
 
今年の初めに…かれこれ 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 向けのライブラリのインストールですかね これは「ツール」メニューから「ライブラリを管理…」を選んで検索窓に必要なキーワードを入れて出てきたものをインストールってする感じですかね

20230717165352-admin.png
m5atom」と入れて出てきた「M5Atom」をインストールする

202307171653522-admin.png
irremoteesp8266」と入れて出てきた「IRremoteEsp8266」をインストールする

202307171653521-admin.png
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 が作成するデータファイル

20230717165352-admin.jpg
そして後はいい感じに設置して完了ですかね (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

情報 <19935文字>

IPv6 での接続について

2023032509192510-admin.png
 
2023年2月18日(土)に行った屋内電源及びネットワーク回線の工事の際に Firewall の設定を間違えてて WAN 側から IPv6 でのアクセスができない状態になってました
LAN 内では問題なくアクセスできたので設定ミスに気付くまで時間がかかってしまいました(汗 まぁ環境にもよるんだろうけど…意外と WAN 側からの諸々のテストは疎かになりがちなんで自戒メモ

20230325091925-admin.png 202303250919251-admin.png
そんな IPv6 での接続をざっくり判定して表示しています まぁ時既に世の多くが IPv6 での接続をサポートしてるっぽいんであ んまり意味ないかもだけど(滝汗

  :

ちなみにスマホちゃんの SIM でのデータ通信だと IPv4 と IPv6 を選択できるようです

---- Android の場合の設定例 ----
202303250919259-admin.png
「設定」画面から「ネットワークとインターネット」を選ぶ

202303250919258-admin.png
「ネットワークとインターネット」画面から「SIM」を選ぶ

202303250919257-admin.png
「SIM」画面から「対象のSIM」を選ぶ ※ここでは NTT DOCOMO を選択

202303250919256-admin.png
先ほど選択した「NTT DOCOMO」画面から「アクセスポイント名」を選ぶ

202303250919255-admin.png
「APN」画面から「現在使用中のAPN」を選ぶ ※ここでは DMM mobile を選択

202303250919254-admin.png
「アクセスポイントの編集」画面で「APNプロトコル」を選ぶ

202303250919253-admin.png
「APNプロトコル」ダイアログが出るので IPv4 か IPv6 を選択する

202303250919252-admin.png
右上の「︙」メニュー内の「保存」を選ぶ

--------

ご使用の OS のバージョンや SIM によって設定できたりできなかったりするらしいので…設定できたらラッキー☆って感じですかね つーかそもそも IPv6 の判定のやりかた自体が間違ってる可能性もアレですが(-_-;) #Android

メモ <784文字>

でんげき☆Network Service お部屋サーバの一時休止のお知らせ

2023年2月18日(土)に屋内電源及びネットワーク回線の工事を行うため午前8時頃から午後6時頃までサーバが停止してアクセスできなくなります
日程・時間などに変更が生じた場合には追ってご連絡いたします
ご不便をおかけしますがよろしくお願い致します

----- 追記 -----
無事に工事が終了しました ご協力ありがとございました

メモ <204文字>

かつや・牛バラ焼きとささみタレカツの合い盛り

20221120084016-admin.jpg
 
かつや の期間限定!「牛バラ焼きとささみタレカツの合い盛り」丼を食べてきました!
毎度ながらの丼からあふれんばかりの具だくさんすぎて思わずほっこりしちゃう盛り付けですね

どちらの具から頂こうか心もち悩みつつ…それじゃ鶏ささみタレカツからいってみましょう
しょーみ鶏ささみカツって「なんかパサパサしてそうだな」ってイメージだったんだけど…サックリ揚がったカツをタレにくぐらせることによりジューシーな仕上がりになってて先入観ぶっちぎりの美味しさでこれはイケます!

そして相方の牛バラ焼は…にんにくの香りを活かしたタレで焼かれているのでしょうか? 濃いめの味付けが脂ぎっしゅな牛バラ肉と相まってこれも美味い! 一緒に焼かれた玉ねぎと…付け合せの千切りキャベツによるアクセントが効いて飽きること無く楽しめます!

いやむしろ濃厚な具だくさんすぎて毎度ながらのご飯とのペース配分が乱されっぱなしな肉いメニューです 期間限定にしとくのは実に惜しい美味しさなんでまた早めにもっぺん楽しんでこなくっちゃですね!(>_<)w #外食記録

日記 <488文字>

吉野家・牛すき鍋膳

20221031163105-admin.jpg
 
寒くなってきたらコレに限るね!ってことで 吉野家牛すき鍋膳 を食べてきました
なんか「一食で半日分の野菜が摂れる」って辺りを推してる感じだけど…いやいや思ってたより脂ぎっしゅなお肉がたっぷりで食べ応えがありますぞ!
しかもお肉と野菜がたっぷりなだけでなく〆のうどんまで入ってるので満足感が大きいです

これが濃い目のタレでぐつぐつ煮込まれているってんだからご飯がどんだけあっても足りません!
定番通り小鉢の溶き卵にくぐらせながら食べるもよし…溶き卵を煮立った鍋に入れ玉子とじにしてご飯に載せて食べるのもイイネ!

圧倒的に価格以上の満足感を得られます これはまた近いうちに食べに行きたいです #外食記録

日記 <317文字>

MakeMKV の使い方…のもうちょっと前のメモ

20220925101846-admin.png
 
DVD や BD をアレするのに便利な MakeMKV ですが…そうそう毎日毎日頻繁に使うものじゃないんでイザ使おうと思うとなんかポップアップが出て使えない!ってことはありませんか? 私はあります でもまぁそうそう毎日毎日頻繁に使うものじゃないんでレアな出来事ではあるのですが(汗

202209251018461-admin.png
では頻繁にアップデートされる MakeMKV の更新方法からですかね なんか Windows 版とかではバイナリで供されているらしいんで…それを入れればいいらしい?って感じなんですが Linux 版はソースコードでの提供なんでその都度コンパイルしなくちゃいかんっぽいでうね

202209251018462-admin.png 202209251018463-admin.png
そんな訳で MakeMKV のページに行ってみて Downloadforum page. と進み…

202209251018464-admin.png
makemkv-oss-*.tar.gz makemkv-bin-*.tar.gz の 2 つをダウンロードしてそれぞれ適当なフォルダに解凍しておきます

202209251018465-admin.png
それでは makemkv-oss から処理していきましょう makemkv-oss を解凍したフォルダに移動して…

./configure
make
sudo make install


を順番に実行します 環境にもよるだろうけど…ちょっと時間がかかります
つーかまぁこの辺の何行かになってるのを一行づつコピペするのは面倒なんで…

./configure && make && sudo make install

こんな感じで「&&」でコマンドをつなげて実行するのもアリですかね

※なお MakeMKV の初回のインストールの際には sudo apt-get install build-essential pkg-config libc6-dev libssl-dev libexpat1-dev libavcodec-dev libgl1-mesa-dev qtbase5-dev zlib1g-dev を真っ先に実行しておいたほうがいいらしいです

  :

202209251018466-admin.png
お次は makemkv-bin を処理しましょう makemkv-bin を解凍したフォルダに移動して…

make
sudo make install


を順番に実行します これも先程と同じく「&&」でコマンドをつなげて実行していいと思います

make && sudo make install

202209251018467-admin.png 202209251018468-admin.png
途中で重要な注意事項的なものが表示されるので…カーソルキーの↑↓やスペースキーなどを使い読んだ後に「q」で抜けて了解した場合に「yes」を入力して次に進みます

  :

これで MakeMKV のアップデート(インストール)は完了です makemkv-*.tar.gz を展開しておいたフォルダは削除しても問題ないんで…まぁ邪魔くさいので消しておいたほうが無難でしょう

202209251018469-admin.png
そしてお次は「期限切れ」となってるこれをどうにかしましょう

2022092510184610-admin.png 2022092510184611-admin.png
News and Announcements 内の MakeMKV is free while in beta と進み「The current beta key is」の内容を…

2022092510184612-admin.png
MakeMKV を起動 → ヘルプ(H) → 公認(R) を選び…出てきた入力欄にコピペして「OK」すれば完了です

2022092510184613-admin.png
あとは MakeMKV を再起動すれば使用できるようになってます ありがたいですね(>_<)w

それほど面倒な手順ってほどでもないんだけど…リンク先とか忘れがちなんでその辺の対策メモってかんじでまとめておきました ご利用は自己判断でお願いします(汗 #Ubuntu

情報 <1542文字>

ラーメン山岡家・味噌ラーメン「背脂変更」

20220821070431-admin.jpg
 
栄光の 24 時間営業でお馴染み! 時差生活者にも嬉しいラーメン屋と云えば 山岡家 ですよね!
その山岡家の裏設定っていうか…何やら「背脂変更」なるものがあるって聞いたんでいっちょ試してきました

202208210704312-admin.jpg
試したのは「味噌ラーメン・背脂変更」です ほほう…なるほど確かに背脂のコクが広がって全体的に食べ応えが増した気がします!

そしてその食べ応えを更に楽しむっていうか…ライスにニンニクを載せて背脂をたっぷり吸った海苔で包んで食べるともう絶品!!
至福のひとときをお腹いっぱい堪能できて幸せです(>_<)w

202208210704311-admin.jpg
味噌ラーメン・塩ラーメン・醤油ラーメンで背脂の効果がいろいろ変化する感じでもあります この辺の好みの組み合わせを探求するのも楽しいですね! お試しあれ!! #外食記録

日記 <361文字>

DASHBOARD

■複合検索:

  • 投稿者名:
  • 投稿年月:
  • #タグ:
  • カテゴリ:
  • 出力順序:

■ハッシュタグ:

■カテゴリ:

■日付検索:

■機器状態:

Raspberry Pi 4 Status

編集

RSSフィード