2024年07月21日

【スマートホーム】Node-REDのバージョンアップでちょっと問題発生した話

こんにちは。

AmazonEchoとNode-REDをブリッジしてくれる「Node-RED Alexa Home Skill Bridge」というAlexaスキルがあります。
AmazonEchoから制御をNode-REDに渡すことで、自由自在にプログラムできるようになります。
私はこれを利用してAmzonEchoからの家電操作にひと工夫加えていました。

さて、Node-REDの新しいバージョンがリリースされました(v4.0.2)。
Raspberry PiにインストールしていたNode-REDをバージョンアップさせてみたら・・・
「Node-RED Alexa Home Skill Bridge」のサーバに繋がらなくなってしまいました(T_T)
接続を試みているようですが、ずっと下画像のまんまです。

スクリーンショット 2024-07-21 191025.png

難しいことは分かりませんが、Node-REDのバージョンアップに伴いNode.jsのバージョンも20 LTSに上げたのが原因のようです。
Node.jsのバージョンを18にダウングレードしたら無事に接続できました。

「Node-RED Alexa Home Skill Bridge」は有志による野良Alexaスキルであり、野良Node-REDノードです。
ローンチはもう8年前であり4年前を最後に更新もされていませんが、Node.js20に対応できていないからといって開発者の方に文句を言うわけにもいきません。
現在でもサーバを稼働させ続けてくれてるわけですし、むしろこれまでこのスキルのお陰でスマートライフを満喫できたことを感謝すべきでしょう。
もし将来のNode-REDがNode.js18を足切りするようなことがあればこのスキルはもう使えないということになりそうです。

ソースはGitHubで公開されているので、いっちょNode.js20対応やってみる???
すいません言ってみただけです。







.




posted by Huwy at 20:14 | Comment(0) | TrackBack(0) | スマートホーム | このブログの読者になる | 更新情報をチェックする

2023年11月10日

【スマートホーム】Switchbotボット(指ロボット)をリプレイス

こんにちは。

半年以上ぶりの更新となりました。
今回は、スマートホーム向けのさまざまなIoTデバイスを発売しているSwitchbot社の「ボット(指ロボット)」を置き換えた話題です。
通常の利用であれば、わざわざブログに書き起こすこともないくらい単純な置き換え作業です。
ですが私は指ロボットをシングルボードコンピュータ「Raspberry Pi」からコマンドを実行して利用しているため、少し躓くことになりました。



salastore_kk07b7nxv4r.jpg



■壊れ・・・てはいない → いや壊れた

置き換えに至った経緯は単純です。経年劣化です。
バッテリーは十分な電圧なのに、指ロボットの指の動きが極めて緩慢になってしまいました。
指の挙動はSwitchbot公式モバイルアプリである程度調整できるのですが、その設定もガン無視されます。
きっとモーターがもうダメなんでしょうね。 約4年ほどで寿命を迎えたようです。
2023/11/15追記:
ついに緩慢な動きさえ出来なくなり、モーターが悲鳴を上げるだけになりました。
分解してみると、モーターから伸びるシャフトを接続する指部品の穴が割れていました。
これではモーターのパワーが指部品に伝わるはずがありません。
強力な接着剤やパテで直したりすることも考えましたが、諦めて廃棄することにしました。


■新規購入そして置き換え・・・あれ?

ちょうどAmazonでSwitchbot社製品がセールとなっていましたが、メルカリで未使用品がもっと安く手に入りました。
先述のとおり私は指ロボットを公式アプリではなくRaspberry Piから実行する環境を構築しています。
指ロボットに対するコマンドラインのうち、Bluetooth MACアドレス部分だけを書き換えれば済む・・・そう思っていました。
ええ、エラーが出て動きません。え〜〜〜・・・・・


■MACアドレスだけじゃなかった

何しろ4年ぶり。当時Raspberry Piから実行できるようになるまでにどんな手順を踏んだかなんて覚えちゃいません。
いろいろ試行錯誤しているうちになんとか動かせるようになりました。
ポイントはコマンドパラメータに与えるハンドル値でした。
Raspberry Pi(Linux)からBluetoothで指ロボットに指示を出すコマンドは以下のとおりです。

# gatttool -i <hci#> -b <BLE MACアドレス> -t random --char-write-req -a <EndGrpハンドル> -n <動作モード>

今回躓いたのは、<EndGrpハンドル>の部分。
<BLE MACアドレス>だけでなく、<EndGrpハンドル>の値を変更する必要がありました。


■手順

いろいろ試行錯誤したのでもしかしたら以下の手順のうち必要ないものもあるかもしれません。
リセットして確認する気もないので、一応やったこと全部書いていきます。

 1. Raspberry Piに指ロボットを信頼させる。
 # sudo bluetoothctl
 [bluetooth]# connect <BLE MACアドレス>
 [bluetooth]# trust <BLE MACアドレス>
 [bluetooth]# exit
 # 
 2. EndGrpハンドル値を確認する。
 # gatttool -i <hci#> -b <BLE MACアドレス> -t random --primary
 attr handle = 0x0001, end grp handle = 0x0009 uuid: 00001800-0000-1000-8000-xxxxxxxxxxx
 attr handle = 0x000a, end grp handle = 0x000d uuid: 00001801-0000-1000-8000-xxxxxxxxxxx
 attr handle = 0x000e, end grp handle = 0x0013 uuid: cba20d00-224d-11e6-9fb8-xxxxxxxxxxx
 3. 上述の指ロボットに指示を出すコマンドの可変部分に適用する。
<hci#>
Raspberry Pi側のBluetoothモジュールの識別子です。私の環境では "hci0"と指定しています。

<BLE MACアドレス>
指ロボットのBluetooth MACアドレス。公式モバイルアプリに接続するとアプリから確認できます。

<EndGrpハンドル>
上述の手順で調べたハンドル値です。

<動作モード>
指ロボットの動作をコードで指定します。押す(570100), TurnON(570103), TurnOFF(570104) 

■最後に

劣化した旧指ロボットのファームウェアバージョンはv6.3、 新規購入した指ロボットはv6.6でした。
動かなくて困っているうちにこんな相違点を見つけてしまったものですから、もう従来のgatttoolコマンド自体が受け付けられない可能性を勝手に考えてしまい迷走してしまいました。
なにしろ最近のIoT業界はMatterという規格を標準化しようとしています。
きっと新しいファームウェアが当たっている指ロボットは、Matterのお作法に従ったコマンドしか受け付けないのだ・・・そう思い込んでしまいました。

そうではないということに気付いたのはコマンドのエラーメッセージに「Invalid handle」、ハンドル値が不正だよと表示されていたからです。
素直にハンドル値を探れば良かっただけでした。ちゃんとエラーメッセージ見ようぜ私よ。

余談ですが上記のような無駄な苦労することなく、MACアドレスを指定するだけで指ロボットを動かせるPythonスクリプトがネット上に出回っています。(っていうかSwitchbot公式です)
それを使ってもよかったのですが、旧指ロボット購入時に試してパフォーマンスが悪かったので今回も敬遠しました。







.


posted by Huwy at 14:58 | Comment(0) | TrackBack(0) | スマートホーム | このブログの読者になる | 更新情報をチェックする

2022年08月14日

【スマートホーム】SSL証明書更新処理の自動サイクル

こんにちは。

先日似たような記事を書きました。そちらはSSL証明書更新処理結果のメール通知についてです。
今回は更新処理のサイクルについて書きます。



■Let's Encryptクライアント「Lego」の罠

SSL証明書はLet's Encryptの無料のものを利用しています。
Let's Encrypt公式のクライアントもあるのですがどうも評判がよろしくないようで、安定してると評価の高いLegoを利用しています。

Let's Encryptの証明書は90日で期限切れとなることは前回記事にも書きました。
じゃあ毎日更新しとけば安心じゃんと考えがちになってしまいますが、あまりに頻繁にリクエストすると認証局からブロックされてしまうそうです。
認証局として負荷を抑えるという目的でしょうかね。Legoもそうした方針を尊重しているようで、デフォルトでは有効期限が残り30日にならないと認証局に更新リクエストを送信しない仕様となっているようです。

実はこれに素直に従うとけっこうややこしいことになります。
月ごとに日数が異なったり2月は短かったり閏年があったり・・・ということをしっかり考慮して更新処理をスケジュールしておかないと、更新可能な30日間を取りこぼして期限切れになる可能性があります(後述)。



■定期実行のスケジュールにはcrontabを使う

crontabは指定した「月日時分秒」のパターンで同じ処理を繰り返し実行するようスケジュールできます。
SSL証明書の定期更新というタスクにはまさにうってつけで、ネット上の多くの例でも取り上げられています。
しかし「月日時分秒」でしか指定できないという点がネックとなり、更新可能30日間をすっぽりとスキップしてしまう危険も含んでいます。
例:毎月01日に更新処理をスケジュール
・01月31日が有効期限=更新可能な30日間は01月02日から開始
・01月01日に実行→更新可能期間前なので更新スキップ
・02月01日に実行→有効期限切れ

◇月2回実行
毎月2回実行していれば更新可能な30日間を取りこぼすことは無いでしょう。
しかし実際に更新できるまで少なくとも60日間あるのに2週間足らずのインターバルで無駄撃ちを重ねるのもカッコ悪いなあと思ったり。
更新処理は大した負荷ではないので気にすることはないんでしょうけど、こういうとこ気にしちゃう性格なんとかしたい。

◇その他の方法@
crontabでも工夫すれば「月日時分秒」ではなく「30日ごと」等で更新処理を動かすことも可能だそうです。
crontabのスケジュール自体は「毎日1回」としておき「当日が基準日からの経過日数30日ごとにあたる」場合にのみ更新処理を実行するという条件付けをする方法です。
しかし月2回実行以上に無駄撃ちしまくりですし、crontabの書き方もトリッキーになります。
パッと見て何やってるのか理解しにくいのが難点です。

◇その他の方法A
crontab以外にもタスクをスケジュールできるコマンドがあります。atコマンドです。
しかしatコマンドは「POSIX準拠」なる仕様だそうで、bashを標準シェルとしている多くのLinuxディストリビューションでは扱いにくいとのこと。
Raspberry Pi OSも例に漏れず、atコマンドからbashで書いたスクリプトを実行できない可能性が高いです。
そもそもRaspberry Pi OSにはatコマンドが含まれておらずインストールする必要があります。
また、atコマンド→shを呼び出し→bashを呼び出しという手間が発生し、やはり後々のメンテナンスが面倒なことになりそうです。



■Legoの理解不足だった

先程「デフォルトでは有効期限が残り30日にならないと認証局に更新リクエストを送信しない仕様」と書きました。
そうです、あくまでデフォルトではそういう仕様だというだけでオプションで変更することが出来ます。
勉強不足でこの点を見落としていました。むしろ30日制限は認証局側の制約だと勝手に誤解していました。

「--days xx」とオプション指定すれば残りxx日であれば更新を認証局にリクエストします。
なので、crontabで2ヶ月毎の01日にスケジュールして更新処理で--days 90とオプション指定しておけば、約60日ごとに証明書が更新されるサイクルが組めます。

crontab:隔月01日の03時15分に更新処理を実行する例
15 3 1 */2 * /etc/renew_ssl.sh

/etc/renew_ssl.sh:有効期限の残日数に関わらず強制的に証明書更新する例
いろいろ準備
lego xxxxxxxxx renew --days 90
いろいろ後処理


■まとめ

Legoの利用例はネット上にたくさん情報があるのですが「更新は月1回やっとけばいいっしょ」という論調が多い気がします。
しかしそこに上述のような罠が潜んでいる点まで言及している情報はありませんでした。
まあ私が読み取れていなかっただけって話しですけど・・・。
「30日制限は認証局側の制約」ってどこで誤解したんだろ・・・(´・ω・`)







.
posted by Huwy at 08:12 | Comment(0) | TrackBack(0) | スマートホーム | このブログの読者になる | 更新情報をチェックする

2022年07月28日

【スマートホーム】SSL証明書更新処理結果をNode-REDでメール送信

こんにちは。

先日、Raspberry Pi 4Bで稼働中のNode-REDを外部公開しました。
外部公開と言っても私自身が外部からアクセスしたいだけなんですが、お勉強がてらリバースプロキシサーバを立てたりファイアウォールを設定したり・・・さらに無駄にもSSL証明書まで適用してみたりしました。

そんなSSL証明書は無料のLet's Encryptを利用しており、90日で有効期限が切れるため定期的に更新する必要があります。
更新処理はシェルスクリプトで自動化し定期実行しているのですが、もし失敗している場合にそれに気付かないままだと有効期限切れとなってしまいます。
そこで成功/失敗に関わらず処理結果をメールで自分に送ることを検討してみました。


■上手くいかん

さっそくLinux端末からメール送信するためのプログラムをインストールしてみたのですがどうにも上手くいきません。
先人のお知恵を拝借しながらsSMTP, Exim4を試してみたのですが、両方ともダメでした。

□sSMTP
謎のエラーが発生してメール送信に失敗します。
これは多くの方も上げられている問題で、設定ファイルにAuthLogin="YES"を追記すれば行ける!などの情報も試してみたのですが上手くいきませんでした。

□Exim4
こちらはSMTPサーバに拒否られます。何故なのかはさっぱり分かりません。
ネットにはGmailを利用した例が多く挙げられていましたが、諸々の事情で私はAOLメールを使う前提としました。
ファイアウォールのポート許可など万障お繰り合わせしたはずなんですが、GmailとAOLの差分を上手く設定に反映できていないっぽい?
どこをどうしていいのやら・・・。


■上手くいっている例がある

今回の「シェルスクリプトからメール送信」とは別件で実はメール送信出来ている例があります。
Node-REDのemailノードです。
Node-REDで操作している家電の稼働状況をAOLメールで送信していて、問題なく使えています。
じゃあSSL証明書更新の結果もNode-REDに送信させてしまえ!と思い立ちました。


■すげえ簡単じゃん

更新処理の標準出力/標準エラーはキャッシュファイルに出力するようスクリプトを組んでいます。
このキャッシュファイルをNode-REDで読み取ってそのままメール本文として送信してしまえばいいわけです。
そんなNode-REDフローを新規作成しHTTPでリクエストを受け付けるようにしました。
(シェルスクリプトからNode-REDフローを呼び出すもっとクレバーな方法があるのかもしれませんが)

シェルスクリプトには自ホストのNode-RED実行ポートに向けてHTTPリクエストを投げる一文を追加。
上述のキャッシュファイルのフルパスをパラメータとして渡すようにしました。以下のようなイメージ。
さて結果は・・・無事に成功!これでわざわざログファイルを見にいかなくても成否をプッシュで検出できます。
うーん、Node-REDのemailノードに出来てsSMTPやExim4では出来なかった理由はなんなんでしょう。
結果オーライなら深掘りしないという私の軽薄なポリシーに則り、sSMTPやExim4のことは忘れることにします。


■余談
シェルスクリプトの定期実行はcrontabで行っていますが、crontabにはスケジュールしたジョブの成否をメール送信する機能があるそうですね。
しかしRaspberry Pi OSに組み込まれたcrontabにはその機能が除外されいるようです。メール送信に関する設定項目がありません。
(crontabのコメントにはなんかゴニョゴニョ書いてあるんだけどな・・・)
そもそもメール送信コマンドも組み込まれていないようで、mailutilsをインストールする必要がありました。






.

posted by Huwy at 23:23 | Comment(0) | TrackBack(0) | スマートホーム | このブログの読者になる | 更新情報をチェックする

2022年05月19日

【スマートホーム】3年越しの夢

こんにちは。

以前の記事にも書きましたが、我が家で契約しているプロバイダは自宅サーバの設置を認めていませんでした。
当時サポートに問い合わせて言質も得ていました。

しかしこの度、制限付きながら晴れて設置OKという運びになりました。
プロバイダの説明ではなんでもコロナ禍でリモートワークが増えてどーのこーの・・・。
いまさらコロナを理由に解禁するのも解せませんが、そもそもそれと自宅サーバがどういう関係があるのいまいち分かりません。
でもまあ結果オーライ。
これによってスマートホーム構築でやりたくても出来なかったことが一気に進むことになりました。

スマートホーム構築を始めたのが約3年前、ようやく夢が叶います。ドリカム。


■Beebotte

BeebotteというMQTTブローカについて何回か記事にしてきました。
我が家のスマートホームの要であるNode-REDに外部からリクエストするための超苦肉の策として使っていました。
私にとってかなり重要な位置付けのサービスなのに、そこそこ不安定で出来れば使うのやめたかったんですよね。

今にして思えば、公開できないゆえに外部から何も受け付けられないはずのNode-REDが、ことMQTTだけは受信できていた理屈を理解できていません。
HTTPリクエストとレスポンスのように、最初に接続を確立した時点のルートを保持し続けてたんでしょうかね?
ネット上の情報を丸々パクって構築していたので理解が及んでいませんでした。

Beeboteは、例えばSesameスマートロックの解錠/施錠イベントをNode-REDに到達させ最終的には照明などの家電操作までを自動化するフローの、迂回路として使っていました。
IFTTTのSesameトリガ(解錠) → WebhookでBeebotteにPublish依頼 → Node-REDのMQTTノードで受信
その他にもさまざまなイベントをNode-REDに到達させるためにBeebotteに頼りっぱなしだったわけです。
サーバ公開が可能となったことで、Node-REDが外部から直接リクエストを受け付けらるようになります。
上記の例で言えば、SesameAPIがIFTTTもBeebotteも経由することなくNode-REDのエンドポイントに直接リクエストできます。
もうBeebotte要らない!


■IFTTT

既に上記にも書きましたが、Sesameのイベントを拾う手段はIFTTTしかありませんでした。
これもNode-REDが直接拾えるようになったので、わざわざ経由させる必要がなくなります。
もうIFTTTも要らない!
(うそ、IFTTTはいろいろ便利なのでこれからも使います。Proプランも契約してるしね)


Smart Home 20220507_抜粋.png




■それでも道は険し

こうして外部サービスの依存度が下がってハッピーなのですが、その代わり今度はセキュリティがばがばのNode-REDを保護してやらなくてはいけません。
ぶっちゃけセキュリティ設定についてはまだお勉強中で、がばがばのまま外部公開されてる極めてリスキーな状態。
まあ悪意ある第三者がNode-REDに侵入できたところで、私が家電操作に少し手間取るだけですけど。


■まとめと共有

今回の作業をNotionにまとめて近日公開予定です。
プロバイダや利用サービスの限られたかなりニッチの狭い内容になりますが、ビンゴで当てはまる方の参考になれば幸いです。

2022/05/20追記:
書きました。






.


posted by Huwy at 01:50 | Comment(0) | TrackBack(0) | スマートホーム | このブログの読者になる | 更新情報をチェックする