古いNationalエアコン用のスマートリモコンを作る

DIYする

古いNationalのエアコンのために、ESP32を使ったスマートリモコンをDIYしました。知られていない赤外線パターンだったので解析しました。また電源ボタンがトグル方式なので、近接センサでフラップの開閉を検出し、電源状態を取得しました。

古いエアコンのリモコン

National (今のパナソニック) の古いエアコンを、HomeKitからコントロールすることを考えました。古いのでエアコン自体を買い替えたほうが良いくらいなのですが、問題なく動作しているので活かしたいです。こんなリモコンです。

リモコンの裏側には、A75C219という型番がありました。古いので、いろいろ特殊です。ボタンは少ないですが、蓋が開けられるようになっていて、タイマー機能もあります。

電源がトグル動作

このリモコンをスマート化する際の1番の問題は、電源ボタンがトグル動作なことです。運転/停止ボタンが共通で、これを押すと交互にOnとOffになります。赤外線信号を解析したところ、OnとOffで信号内容は同じでした。同じ信号が送られて、その都度エアコンがOn/Offに切り替わります。なのでスマートリモコンをDIYする際には、プログラムの内部で現在の状態を保持しておき、例えばOnにする操作が続けて要求されたら、2回目以降は無視するような処理が必要です。

温度・風設定

Onの時も、Offの時も、どちらであっても、温度・風量・風向・運転モードの変更は可能です。Offの時にも、温度、風の設定は変更できて、次に電源ボタンを押した時に、その状態で動作します。

温度や風の設定方法自体は、今のエアコンと変わりません。風量切り替えボタンを押すと、自動、微風、弱風、強風と切り替わります。風向切り替えを押すと、フラップが1段階ずつ角度変化します。風向自動を押すと、フラップがスウィングします。

Natureを試すも無理

今のエアコンのリモコンと比べると、電源操作がトグルで特殊です。市販のスマートリモコンが使えるのか試してみました。国内向けエアコンを手厚くサポートしていることで定評のあるNature Remoで、このリモコンの登録を試みました。登録モードでリモコン信号を読み込ませると、パナソニックのエアコンであることは判定されました。しかし、On信号は効かず、Off信号にのみ反応し、その際にエアコンのOn/Offがトグルします。流石に古すぎて対応していないようです。

ということでこのリモコンのスマート化には、DIYが必須のようです。

赤外線信号パターンの解析

DIYにあたって、リモコンの赤外線信号パターンを解析しました。使ったツールは、以下でDIYしたESP32です。MQTT経由でコマンドを流すと、指定した秒数、赤外線を検出して、結果をMQTTメッセージで流してくれます。

赤外線記録機能をESP32スマートリモコンに追加する
ESP32でDIYしたスマートリモコンに、赤外線リモコン受信モジュールを組み込みました。これで各種リモコンの信号パターンを測定し、その結果をMQTTメッセージ経由で取得します。ESP32でDIYしたスマートリモコンESP32を使って、色々な...

これを使って、冷房、27度、風量自動、風向指定無しの設定で、On/Offボタンを押しました。得られたパターンは以下です。数値はマイクロ秒で、赤外線On/Offの長さを表してます。この例は、最初に3,400μs Onになり、次に3,600μs Off, 860μs On, 890μs Offというデータです。

[3400, 3600, 860, 890, 860, 890, 860, 2600, 860, 2600, 860, 2600, 860, 2600, 860, 2600, 860, 2600, 860, 890, 860, 890, 860, 2600, 860, 2600, 860, 2600, 860, 2600, 860, 2600, 860, 2600, 860, 890, 860, 2600, 860, 890, 860, 900, 860, 890, 860, 890, 860, 900, 860, 890, 860, 890, 860, 2600, 860, 890, 860, 890, 860, 900, 860, 890, 860, 890, 860, 890, 3400, 3600, 860, 890, 860, 900, 860, 2600, 860, 2600, 860, 2600, 860, 2600, 860, 2600, 860, 2600, 860, 890, 860, 890, 860, 2600, 860, 2600, 860, 2600, 860, 2600, 860, 2600, 860, 2600, 860, 900, 860, 2600, 860, 900, 850, 900, 860, 900, 850, 900, 860, 890, 860, 890, 860, 900, 860, 2600, 860, 900, 850, 900, 850, 900, 860, 900, 850, 900, 850, 900, 3400, 3600, 860, 14000, 3400, 3600, 850, 900, 850, 900, 850, 900, 850, 900, 860, 900, 850, 900, 850, 900, 860, 890, 860, 900, 860, 890, 860, 890, 860, 900, 860, 890, 860, 890, 860, 900, 860, 890, 860, 890, 860, 2600, 860, 2600, 860, 890, 860, 2600, 860, 2600, 860, 890, 860, 900, 860, 890, 860, 2600, 860, 2600, 860, 890, 860, 2600, 860, 2600, 860, 890, 860, 890, 3400, 3600, 860, 890, 860, 890, 860, 900, 860, 890, 850, 900, 860, 900, 850, 900, 860, 890, 860, 890, 860, 900, 860, 890, 860, 890, 850, 900, 850, 900, 860, 890, 860, 900, 850, 900, 860, 2600, 860, 2600, 860, 890, 860, 2600, 860, 2600, 860, 890, 860, 890, 850, 900, 850, 2600, 860, 2600, 860, 890, 860, 2600, 860, 2600, 860, 900, 860, 890, 3400, 3600, 860]

これをグラフにすると以下になります。横軸が時間で、縦軸が赤外線のOn/Offです。1が赤外線Onで、0がOffを表します。

中央に14msの休止を挟んで、前後にパターンがあります。前後どちらも、同じ内容を2回繰り返しています。一番短いパルスは860~890μsです。これをTとすると、赤外線がT秒OnでT秒Offの組と、T秒Onで3xT秒Offの組で、0, 1を表しているようです。前者を、{T, T}、後者を{T, 3T}と表すことにします。開始パターン、データの区切り、終了パターンが、{4T, 4T}になってます。前後のパターンの間に、{T, 16T}のパターンが挟まれてます。

他の業界標準の赤外線パターンと比較すると、開始パターンは、NECフォーマット、AEHAフォーマット、SONYフォーマットのいずれでも無いです。リモコンの型番でネットを検索しても、古すぎるのか、パターンを解析した情報は見つかりませんでした。

デコードする

{T, T}の組を0、{T, 3T}の組を1とし、LSBから送信されていると仮定して、デコードを試みます。その結果、

0xfc 0xfc 0x02 0x02
0xfc 0xfc 0x02 0x02

0x00 0x00 0x36 0x36
0x00 0x00 0x36 0x36

という情報が送出されていることがわかります。全部で4バイトの情報が、それぞれ4回繰り返されているようです。別のパターンを試してみます。今度は、暖房、22度、風量自動、風向設定なしパターンです。

0xf7 0xf7 0x04 0x04
0xf7 0xf7 0x04 0x04

0x00 0x00 0x36 0x36 
0x00 0x00 0x36 0x36

ということで、送信されているデータは4バイトで、それが{a,b,c,d}だった場合に、{a,a,b,b,a,a,b,b, 休止, c,c,d,d,c,c,d,d}というように繰り返されていることがわかりました。以下では、この{a,b,c,d}のデータを解析していきます。

データを解析する

運転モード、設定温度、風量、風向設定などを変えて、赤外線信号パターンを観察し、{a,b,c,d}に相当する4バイトのデータを解析しました。HomeKitで使うことを前提に、調査する項目を絞り、タイマー関係は調べてありません。結果、この4バイトデータは、以下であることがわかりました。

Byte

MSB <—> LSB

7 6 5 4 3 2 1 0
0

風量 (0xF:自動 0x6:強風 0x4:弱風 0x2:微風)

設定温度(設定温度 – 15)

1

0x00

電源維持*

2:冷房, 3:ドライ, 4:暖房, 6:自動

2

風向自動(swing)は0x04, 風向を自動にしない場合は0x00

3

0x36 (多分タイマー関係, デフォルトは0x36)

電源維持*  0:On/Offがトグルする 1:温度や風量風向の設定を変えるだけでOn/Offしない

2バイト目( Byte 1 )のLSBから4ビット目の、「電源維持」と名付けたビットが特色的です。「電源維持」ビットが0の場合は、電源がOn/Offとトグルします。リモコンの「電源ボタン」を押した時に0になります。一方「電源維持」ビットが1の場合は、電源はトグルしません。温度や風量を変更するボタンを押した場合に1になります。ビットが1の場合は、エアコンの電源状態は変化せず、温度や風の設定だけが変化します。

特殊な赤外パターン

「おやすみ」「風向自動」「風向切り替え」のボタンについては、上記の表とは全く関係のない、特別な赤外線パターンになってました。

  • 「おやすみ」0x01011010 を3回繰り返す
  • 「風向自動」0x80803030 を5回繰り返す
  • 「風向切り替え」0x02023030 を4回繰り返す

0x02023030 を4回繰り返す「風向切り替え」の赤外線パターンを以下に示します。

「おやすみ」機能は、HomeKitにはありませんので、DIYするスマートリモコン機能には含めないことにします。

「風向自動」はフラップがswingします。一方で「風向切り替え」はswing状態ならばswingを停止します。また引き続き「風向切り替え」を押すことで、風向を8段階に切り替えられます。そこで、「風向自動」はHomeKitのswing開始(首振り開始)に、「風向切り替え」はswing停止に割り当てることにしました。HomeKitから8段階の風向切り替えを行うUIはありませんが、swingを停止するタイミングで風向を決められます。

ESP32でハードウェアを作る

ESP32に赤外線LEDを接続してハードウェアを作成します。以下の記事で作ったプリント基板が、まだまだ余っているので、これを使ってハードウェアを作りました。

スマート赤外線リモコンのプリント基板を作る
ESP32を使った自作スマート赤外線リモコンのためにプリント基板を製造委託しました。基板の設計図を、基板屋さんのホームページにアップロードして発注したところ、基板が届き完成しました。こちらの記事の続きです。前回のあらすじ以前の記事では、ES...

よく見たら今回使用したESP32のシールドが凹んでました。AliExpressからの梱包が悪くて、複数購入した他のESP32のピンが当たって、凹んだようです。でもちゃんと動作してます。(追記:その後、WiFiの接続が不安定なためか、MQTTメッセージの応答が悪かったり、ESP32が再起動する現象に気づきました。シールドが凹んでいない、別のESP32に交換したら問題は解消しました。2024/07/29)

赤外線LEDを3個直列接続し、これをドライブするためにFET 2N7000を取り付けて、ESP32のデジタルピンに接続しました。温度測定のために、温度、湿度センサーDHT20も取り付けました。赤外線受信ユニットIRM0101は、今回は組み込みませんでした。その部分が空いてます。

電源トグル対策

先に述べたように、このリモコンの最大の問題は、電源ボタンがトグルな点です。電源ボタンを押すと、On/Offが切り替わりますが、実際の電源状態がOnなのかOffなのかリモコン側にはわかりません。OnとOffの信号が異なるリモコン方式ならば、赤外線送出直後のOn/Off状態を把握できます。しかしトグル動作するリモコンでは、On/Off状態が逆になっていても、システム側からそれを知ることができません。

そこで、エアコンのOn/Off状態を検出して、HomeKitの状態に反映する方法を考えました。エアコンの運転表示LEDを電気的に読み込むとか、消費電力を測定するとか、JEM-A端子があればそれを利用する(今回の機種にはありません)など方法は色々考えられます。今回はフラップの開閉を磁気接触センサーで検出することにしました。フラップに磁石を取り付けて、開閉を検出します。エレガントさの無い力技ですが、設置は簡単です。

使用したZigbee式接触センサーは、こちらで紹介したものです。

Zigbee磁気接触センサ (648円)をHomeKitで使う
Zigbeeを使った安価な磁気接触センサ(開閉センサー)を使いました。送料込みで648円です。Zigbee2MQTTで問題なく認識され、HomeKitから使用することができました。単4電池を2本使用するので、ボタン電池を使用する製品に比べる...

これをRaspberry Piで動作するZigbee2MQTTにペアリングしています。磁石の接触状態は、JSON形式でMQTTメッセージに流れるので、これをESP32で読み取ります。

接触センサのJSON方式MQTTメッセージを受け取る手順の詳細はこちらをご覧ください。

ESP32でJSONデータを使う
ESP32でJSONを扱うためメモ書きです。Arduino用のJSONライブラリを使うと、Web APIやMQTTメッセージで使われるJSONデータ利用が簡単になります。Zigbee2MQTTで動く開閉センサーのJSONデータを読み込み、L...

On/Off信号が独立しているリモコンでも、スマートホームシステムとは独立した物理リモコンで操作してしまうと、システムが把握している状態から乖離してしまう問題があります。この場合も、フラップ開閉を検出する接触センサで改善できると思います。

なお、接触センサーとして、ボタン電池使用の小型のZigbeeセンサーも検討しました。ただ、フラップと本体が同一平面になくて、接触時の磁気が弱いようで、小型センサーでは検出に失敗することがありました。大きくて少し目障りではありますが、大型のセンサーが適しているようです。

TuyaのZigbee磁気接触センサ(964円)
以前、格安のWiFi接触センサを紹介しました。今度はZigbee版です。WiFiに比べるとそこそこ高いです。こちらの商品です。IHSENOという会社の製品のようです。買った時は送料込み1200円くらいでした。今は1300円くらいでしょうか。...

全体構成

全体の構成を以下に示します。

接触センサは、Zigbee経由でZigbee2MQTTにペアリングされ、そのMQTTメッセージをESP32が読み取ります。ESP32は、MQTT経由でHomebridgeともメッセージ交換し、エアコンアクセサリの機能を実現します。

ESP32をプログラムする

ESP32のために作成したプログラムを、以下で公開しておきます。

GitHub - diysmartmatter/ir_NationalA75C219: ESP32 Smart IR remote for National A75C219 Air Conditioner
ESP32 Smart IR remote for National A75C219 Air Conditioner - GitHub - diysmartmatter/ir_NationalA75C219: ESP32 Smart IR ...

プログラムの冒頭では、以下のヘッダファイルをインクルードしています。

それぞれのライブラリは、以前の記事で紹介しました。詳しくはリンク先をご覧ください。

IRremoteESP8266を利用

今回も、こちらなどで使用した

エアコンリモコンのHomeKitアクセサリをDIYする (前編:赤外線送出)
エアコンリモコンに相当するアクセサリを作ろうと思いました。これでiPhone/Macの画面に上の図のようなコントローラが現れるはずです。最初のターゲットはパナソニックのエアコンです(他のメーカーでも同様に作れるはずです)。下図のように、(右...

IRremoteESP8266というライブラリを使いました。ESP8266 / ESP32用の赤外線リモコンライブラリです。

GitHub - crankyoldgit/IRremoteESP8266: Infrared remote library for ESP8266/ESP32: send and receive infrared signals with multiple protocols. Based on: https://github.com/shirriff/Arduino-IRremote/
Infrared remote library for ESP8266/ESP32: send and receive infrared signals with multiple protocols. Based on: - cranky...

このライブラリでは、各社エアコンの赤外線パターンをサポートしたクラスが多数提供されています。Nationalのリモコンが古くてクラスがありませんので、エアコンクラスは、次節で示すように自作しました。ただこのライブラリの基本的なクラスである、IRsendクラスだけを使わせてもらいました。このクラスで使用した主なメソッドは、sendGeneric()とsendRaw()です。sendGeneric()は、バイト列を赤外線信号として送出するメソッドです。ビット順は、LSBからです。ビット1と0を表す赤外線On/Off時間を設定します。また、バイト列の前後に、ヘッダーとフッターという識別パターンが付いています。これらが不要な場合は、それぞれの時間を0にすれば良いです。

void sendGeneric(
  const uint16_t headermark, //ヘッダーの赤外On時間
  const uint32_t headerspace, //ヘッダーの赤外Off時間
  const uint16_t onemark,  //データ1の赤外Off時間
  const uint32_t onespace, //データ1の赤外On時間
  const uint16_t zeromark, //データ0の赤外On時間
  const uint32_t zerospace,//データ0の赤外Off時間
  const uint16_t footermark, //フッターの赤外On時間
  const uint32_t gap,        //フッターの赤外Off時間
  const uint8_t *dataptr, const uint16_t nbytes, //送出するバイト列へのポインター
  const uint16_t frequency, const bool MSBfirst, //赤外線変調周波数。通常は38000 (38kHz)
  const uint16_t repeat, //全体をn+1回繰り返す。繰り返さなければ0
  const uint8_t dutycycle //デューティ比,通常は50
);

また、データの区切りなどで送出する特別なパターンは、sendRaw()メソッドを使って、On/Off時間(μs単位)の生データで指定します。

void sendRaw(
  const uint16_t buf[], //On/Off時間をμsで表す配列
  const uint16_t len,  //その長さ
  const uint16_t hz. //赤外線変調周波数。通常は38000 (38kHz)
);

この2つのメソッドを呼ぶだけで、適切な赤外線信号を送出できるので、プログラミングはと楽でした。

リモコンクラスの概要

このNationalのリモコンの動作を表すクラスとして、IRNationalという名前のクラスを作ることにしました。用意したメソッドの一部を以下に示します。内部で、エアコンのOn/Off状態を保持していて、on, offメソッドで指定した電源状態になるように、前述の「電源維持」ビットを設定します。

void send(void); //赤外線を送出. 電源維持ビットが0ならば電源状態を反転する
void begin(void); //初期化
void toggleOnOff(void); //エアコンをOnまたはOffする。トグルで動作する
bool updateState(const bool newState); //電源状態を設定する。変化があった場合はtrueが返る
void setTemp(const uint8_t temp); //温度を設定
uint8_t getTemp(void); //温度を取得
void setFan(const uint8_t fan); //風速を設定
void setMode(const uint8_t mode); //運転モードを設定
void setSwing(const bool enabled); //swing on/offのための赤外線を出す
char* toChars(void); //リモコン用の4バイトデータを文字列化(デバッグ用)

MQTTメッセージ対応プログラム

メインのプログラム、IR_airconMQTT_n.inoでは、2つのMQTTトピックス、

mqttthing/irNational/set/#
zigbee2mqtt/NationalFlap

をサブスクライブしてます。mqttthingトピックスは、HomeKitのmqttthingプラグインがパブリッシュするエアコン制御の情報です。一方で、zegbee2mqttトピックスは、エアコンのフラップに取り付けた接触センサーの情報です。

HomeKitからのメッセージ

HomeKitからのMQTTメッセージに従って、ESP32は赤外線信号を使ってエアコンを設定します。

エアコン制御のためにHomeKitから送られるメッセージは、6種類です。このメッセージを受け取った時に、onMessageReceivedH()関数が呼ばれます。onMessageReceivedH()関数の中では、

  • mqttthing/irNational/set/Active : HomeKitがpub. A/CをOn/Offする
  • mqttthing/irNational/set/TargetHeaterCoolerState : HomeKitがpub. 冷房暖房切替
  • mqttthing/irNational/set/CoolingThresholdTemperature : HomeKitがpub. 冷房温度
  • mqttthing/irNational/set/HeatingThresholdTemperature : HomeKitがpub. 暖房温度
  • mqttthing/irNational/set/RotationSpeed : HomeKitがpub. 風速
  • mqttthing/irNational/set/SwingMode : HomeKitがpub. 風向

のようにメッセージに対応します。onMessageReceivedH()関数のプログラムを以下に示します。ここでnationalはグローバル変数で、IRNationalクラスのインスタンスです。また、_CoolingThresholdTemperatureと_HeatingThresholdTemperatureもグローバル宣言されたuint_8型変数で、それぞれ冷房用、暖房用の設定温度です。

void onMessageReceivedH(const String& topic, const String& message) {
  String command = topic.substring(topic.lastIndexOf("/") + 1);
  
  if (command.equals("Active")) {
    bool newState=false; //default for JIC
    if(message.equalsIgnoreCase("true")) newState=true;
    if(message.equalsIgnoreCase("false")) newState=false;
    //if On/Off state is updated, toggle the AC power
    if(national.updateState(newState)) national.toggleOnOff();
  }else if(command.equals("TargetHeaterCoolerState")){
    if(message.equalsIgnoreCase("COOL")) {
      national.setTemp(_CoolingThresholdTemperature);//each mode has specific temp
      national.setMode(kNationalCool);
    }
    if(message.equalsIgnoreCase("HEAT")) {
      national.setTemp(_HeatingThresholdTemperature);//each mode has specific temp
      national.setMode(kNationalHeat);
    }
  }else if(command.equals("CoolingThresholdTemperature")){
    national.setTemp(message.toInt());
    _CoolingThresholdTemperature=national.getTemp(); //may be capped
    national.send();
  }else if(command.equals("HeatingThresholdTemperature")){
    national.setTemp(message.toInt());
    _HeatingThresholdTemperature=national.getTemp(); //may be capped
    national.send();
  }else if(command.equals("RotationSpeed")){
    int speed = message.toInt();
    if (speed < 25) national.setFan(kNationalFanAuto); //auto
    else if(speed < 50) national.setFan(kNationalFan1); //level-1
    else if(speed < 75) national.setFan(kNationalFan2); //level-2
    else national.setFan(kNationalFan3); //level-3
  }else if(command.equals("SwingMode")){
    if(message.equalsIgnoreCase("DISABLED")) national.setSwing(false);
    if(message.equalsIgnoreCase("ENABLED")) national.setSwing(true);
  }
}

Z2MQTTからのメッセージ

一方、エアコンのフラップに取り付けた接触センサーからは、フラップの開閉にともないZigbeeに情報が流れます。それをZigbee2MQTTが受け取り、以下のメッセージをMQTTに流します。

  • zigbee2mqtt/NationalFlap : 接触センサ値をZ2Mがpub. フラップ開閉

ESP32では、このメッセージを受け取り、フラップが開いた場合は(センサー値はfalse)エアコンの電源はOnになり、フラップが閉じた場合は(true)エアコンがOffになったと判断し、それぞれの状態をHomeKitにMQTT経由で知らせます。

ESP32のプログラムでは、Z2MQTTからのメッセージを受け取った場合のコールバック関数として、onMessageReceivedF()関数を用意しました。以下にこれを示します。

void onMessageReceivedF(const String& topic, const String& message) {
  DeserializationError error = deserializeJson(doc, message);
  if(error) {
    client->publish(DEBUG,"JSON deserialization error.");
  }
  else if(doc["contact"] == true) { //flap is closed (power off
    national.updateState( false );
    client->publish(PUBTOPICF,"false");
  }
  else if(doc["contact"] == false) { //flap is open (power on)
    national.updateState( true );
    client->publish(PUBTOPICF,"true");
  }
}

接触センサーからパブリッシュされるメッセージはJSON形式なので、JSONの読み取りをしています。フラップの開閉が検出された場合、エアコンクラスであるIRNationalのupdateState()メソッドを呼び出します。これで、IRNationalが内部的に保持している電源On/Off状態を書き換えます。さらに電源状態が変更された場合は、このことをHomeKitに知らせるべく、zigbee2mqtt/irNational/get/ActiveトピックスにtrueもしくはfalseのMQTTメッセージを送ります。

室温測定

メインのloop()では、publishDHT()という関数を呼び出してます。publishDHT()では、10秒ごとにDHT20のデータを読み、値が変化していたらMQTTに新しい気温・湿度の値をパブリッシュします。また変化がなくても、5分に1回は最新の気温・湿度の値をパブリッシュします。

//IR Remo and MQTT: read DHT20 and publish results
//check every 10 sec.
//if temp or humi change publish soon, otherwise publish every 5 min.
void publishDHT() {
  char buff[64];
  static int count10=0; //counts up in every 10 sec.
  float humi, temp;
  static int oldhumi=0, oldtemp=0; //previous value
  int newhumi, newtemp; //new value
  if(millis() - dht.lastRead() < 10000) return;//do nothing < 10 sec.
  count10++; //count up 10 s counter
  if(DHT20_OK != dht.read()){
    client->publish(DEBUG,"DHT20 Read Error.");
    return; //sensor error, do nothing.
  }
  //read the current temp and humi
  humi=dht.getHumidity();
  newhumi=round(humi);//int version
  temp=dht.getTemperature();
  newtemp=round(temp * 10);//int version (x10)
  //if measurement changes or 300 seconds passed
  if((oldtemp != newtemp) || (oldhumi != newhumi) || (count10 >= 30)){
    oldtemp=newtemp;
    oldhumi=newhumi;
    sprintf(buff, "{\"temperature\":%.1f,\"humidity\":%.0f}", temp, humi);
    client->publish(PUBTOPICT,buff);
    count10=0; //reset counter
  }
}

void loop() {
  ArduinoOTA.handle(); //loop for OTA
  client->loop(); //loop for MQTT
  publishDHT(); //publish temp and humi if needed
}

この結果、zigbee2mqtt/irNational/getトピックスに、{“temperature”:23.4,”humidity”:52}のようなメッセージが流れます。これをHomebridge, HomeKitが読み取り、エアコンアクセサリの室温表示に反映します。

Homebridgeの設定

これでESP32が、MQTTメッセージを受け取り、赤外線パターンを送出してくれるようになります。そのMQTTメッセージを、HomeKitに橋渡しするために、HomebridgeにMQTTThingプラグインを入れて、以下のように設定します。

{
    "type": "heaterCooler",
    "name": "NationalAC",
    "url": "mqtt://localhost:1883",
    "topics": {
        "setActive": "mqttthing/irNational/set/Active",
        "getActive": "mqttthing/irNational/get/Active",
        "setCoolingThresholdTemperature": "mqttthing/irNational/set/CoolingThresholdTemperature",
        "getCurrentTemperature": "mqttthing/irNational/get$.temperature",
        "setHeatingThresholdTemperature": "mqttthing/irNational/set/HeatingThresholdTemperature",
        "setRotationSpeed": "mqttthing/irNational/set/RotationSpeed",
        "setTargetHeaterCoolerState": "mqttthing/irNational/set/TargetHeaterCoolerState",
        "setSwingMode": "mqttthing/irNational/set/SwingMode"
    },
    "accessory": "mqttthing"
},

赤外パターンを確認する

このスマートリモコンで、実際に赤外線信号パターンを送出して、それをオリジナルのリモコンと比較しました。

オリジナルのリモコンが送出したパターンを読み取った結果を、再度以下に示します。冷房、27度、風量自動、風向指定無しの設定で、On/Offボタンを押した時のパターンです。

これに対して、同じ設定でESP32が生成したパターンを以下に示します。上のリモコンパターンと一致していますので、正しく生成できたようです。

Swing on/offの信号も比較しました。以下は、swing offに相当する「風向切り替え」の、オリジナルリモコンパターンとESP32の生成パターンです。0x02023030 を4回繰り返しています。

これも、オリジナルとESP32のパターンが一致していることを確認できました。

HomeKitから使う

以上のようにHomebridgeを設定し、ESP32を動作させると、HomeKitからエアコンアクセサリが見えるようになります。

これをクリックしてOn/Offできますし、温度設定、運転モード設定も可能です。

風量も設定できますし、風向のスウィングOn/Off(首振り)も動作しました。

また、例えば動作中に、本来のリモコンを使ってOffにすると、フラップが閉じ、それが接触センサが検出されるので、HomeKitにも反映されます。アクセサリの状態がOnからOffになります。

   

このリモコンは、前述のように電源On/Offがトグルする方式なので、正しいOn/Off動作がリモコン側からは不明です。でもフラップのセンサーにより本来のOn/Off状態を把握できるので、HomeKitアクセサリとして正しく動作します。

まとめ

古いナショナルのエアコンのために、スマートリモコンをESP32でDIYしました。電源がトグル方式で特殊なために、フラップの開閉を検出するZigbee接触センサを使い、電源On/Off状態を把握できるようにしました。HomeKitから正しく使えることを確認しました。

赤外線スマートリモコンは、コマンドが正しく機器に伝達されたことを確認できません。また、他のリモコンなどで操作されると、機器の状態を把握できなくなってしまいます。今回はフラップの開閉で電源On/Offを検出するようにしました。ただ、運転モード、温度、風の設定状態までは反映していません。SwitchBotのスマートリモコンでは他のリモコンからの赤外線信号を検出して、この問題に対応する予定らしいです。注目したいと思います。

コメント

タイトルとURLをコピーしました