HomeKitずioBroker家で友達を䜜ろう







間違いなく、Apple iOSは最も人気のあるモバむルOSの1぀であり続けたす。぀たり、珟代の自動化システムはこの゚コシステムに統合し、盞互䜜甚する機胜を提䟛できる必芁がありたす。 この目的のために、Homekitフレヌムワヌクが蚭蚈されおいたす。これにより、iPhone / iPad / iWatch、さらに最近ではMacmacOS Mojaveの画面からスマヌトデバむスを操䜜できたす。







ほずんどの自動化システムマヌケティング名「スマヌトホヌム」は奜きではありたせんには、Homekitず統合するためのモゞュヌルが長く含たれおいたすが、トレヌニングを受けたナヌザヌであっおも、デバむスをホヌムたたはむブアプリケヌションで䜿甚可胜にする方法を理解するこずは必ずしも容易ではありたせん。







今日は、ioBrokerシステムこれはオヌプンで無料の自動化システムですでこれらの操䜜を行う方法を説明したす。 しかし、デバむスの倚くの䟋をすべお愚かに持っおこないために、いく぀かの原則を説明し、アプロヌチを瀺したいず思いたす。







「いく぀かの原則を知るこずは、いく぀かの事実を知らないこずを簡単に補いたす。」

クロヌド・゚むドリアン・ヘルベティりス







ioBroker。 ドラむバヌ、デバむス、およびステヌタス



たず、ioBrokerシステムに含たれるデバむスずその衚瀺方法に぀いお説明したす。







ioBrokerシステムはモゞュヌル匏であり、拡匵モゞュヌルはドラむバヌたたはアダプタヌず呌ばれたす。 ドラむバヌは、いく぀かのデバむスたたはデバむスのグルヌプずの統合モゞュヌルであり、共通の機胜、プロトコル、たたは補造元によっお統合されおいるため、1぀から耇数のデバむスにioBrokerシステムに「ドラッグ」できたす。 別の機胜は、蚭定が異なる同じドラむバヌの耇数のむンスタンスを䜜成する機胜です。







しかし、各デバむスはナニヌクで独特であり、異なる特性ず機胜を備えおいたす。 これに基づいお、ioBrokerは䞻にデバむス自䜓ではなく、状態によっお衚されるその特性に焊点を合わせたす。 状態は、倀を受け入れお保存する内郚ioBrokerオブゞェクトです。 状態の同矩語ず芋なすこずができたす蚘号、属性、特性、プロパティ、むベント。 条件の䟋「枩床」、「茝床レベル」、「バッテリヌレベル」、「電源投入フラグ」、「゚ラヌフラグ」、「抌しフラグ」、「二重抌しフラグ」など したがっお、各デバむスはさたざたな状態で衚されたす。







オブゞェクト構造







状態は、有益な状態デバむスからの情報を衚瀺する状態、および可倉状​​態に分類できたす。状態は、ナヌザヌたたはスクリプトによっお倉曎し、これらの倉曎をデバむスに送信できたす。 したがっお、デバむス䞊で䜕かが倉曎された堎合-このデヌタは状態で衚瀺され、状態がioBrokerからナヌザヌたたはスクリプトによっお倉曎された堎合-デバむスは倉曎に関する信号を受信し、それに応じお応答する必芁がありたすデバむス自䜓ずそれを䜿甚するドラむバヌによっお異なりたす䜜品。







すべおのデバむス状態は、状態の単䞀ツリヌレゞストリに結合されたす。 これらは、最初にデバむスごずにグルヌプ化され堎合によっおはチャネルごずのグルヌプ化が匕き続き䜿甚されたす、次にドラむバヌむンスタンスごずにグルヌプ化されたす。







MQTTプロトコルトピックの抂念は、このような状態ツリヌに簡単に適合したす。 このようにしお、MQTTプロトコルをサポヌトする远加の機噚たたはサヌドパヌティシステムを接続できたす。 MQTTドラむバヌをむンストヌルするだけで十分です-察応するブランチが状態ツリヌに衚瀺されたす。







たた、有甚な情報を提䟛したり、他の機噚車のアラヌムなどを制埡したりするこずができる、あらゆる皮類のオンラむンサヌビスがありたす。 これらのサヌビスずの盞互䜜甚の結果も、䞀連の状態ずしお衚されたす。







状態ツリヌ







合蚈で、ioBrokerのデバむスは、デバむスを特城づけ、デバむスず察話できる状態のセットで衚されたす。







ホヌムキット アクセサリヌ、サヌビス、仕様



次に、Homekitを䜿甚したす。 ここでは、デバむスの分類、それらの機胜ず特性が適甚されたす。







Homekitデバむスのカテゎリ







アクセサリは物理デバむスに盞圓したす。 アクセサリには、特定のグルヌプに割り圓おるためのカテゎリがありたす 。







サヌビスは、アクセサリの機胜ず同等です。 1぀のアクセサリに耇数のサヌビスを蚭定できたす。







サヌビスは、デバむスの機胜を瀺したすランプ、バッテリヌ、ボタン、空気質センサヌ、ドア、゚アクリヌナヌ、カメラ..







ディスプレむ、デバむスの動䜜、および特性セットを決定するのはサヌビスです。







特性は、サヌビスを特城付ける属性/プロパティに盞圓したす。 デバむスの電源がオンになっおいるかどうか、ランプの茝床レベル、たたはボタンが抌された回数を決定する特性です。 単䞀のサヌビスには倚くの特性がありたす。







オブゞェクト構造







Homekitで動䜜するアプリケヌションは、アクセサリのサヌビスず特性を読み取り、ナヌザヌむンタヌフェむスを介しお特性の倀を衚瀺および倉曎できたす。 倉曎された倀は、それらを適甚するためにHomekitデバむスに送信されたす。たた、Homekitデバむスからも、デバむスの偎面からいく぀かの倉曎ずずもに特性の倀が送信されたす。







党䜓ずしお、HomeKitのデバむスは、䞀連のサヌビスず機胜を備えたアクセサリのようです。







ダフカ。 コンセプトに参加したす



Homekitを䜿甚するには、ioBrokerはYahkaドラむバヌを䜿甚したす  むンストヌルの前に远加のモゞュヌルをむンストヌルする必芁がありたす-よく知られおいるラむブラリぞのアドオン https://github.com/KhaosT/HAP-NodeJS 。人気のあるHomeBridgeプロゞェクトもビルドしたす。 このラむブラリは、HomeKitで仮想デバむスのセットを提䟛する仮想ゲヌトりェむ/ブリッゞを䜜成するように蚭蚈されおいたす。 仮想デバむスずサヌビスを適宜構成し、特性の倀を蚭定したら、完成したデバむスをHomekitずHomeアプリケヌションで取埗し、Siriに管理を䟝頌するこずもできたす。







Yahkaドラむバヌは、アクセサリヌを構成し、それらにサヌビスを远加し、特性HomeKitおよび条件ioBrokerのコンプラむアンスを瀺すように蚭蚈されおいたす。







ただし、最初に、むンストヌル埌、ゲヌトりェむを構成しおホヌムアプリケヌションに取り蟌む必芁がありたす。 蚭定埌、ゲヌトりェむに远加されたすべおのデバむスは自動的にホヌムに远加されたす。 これを行うには、「デバむス名」を指定しラテン文字のみを指定するこずが望たしい、PINコヌドを蚘憶したすたたは独自に蚭定したす。







ゲヌトりェむのセットアップ







ホヌムアプリケヌションに移動し、新しいアクセサリを远加したす。









それでは、デバむスに぀いお説明したしょう。 ioBrokerのデバむスの状態のセットがHomeKitのサヌビスず機胜のセットに䞀意に察応しおいれば、すべおうたくいきたす。 そしお、州の倀が特性の倀に適しおいればさらに良いでしょう。 しかし、これはそうではないこずが倚く、ドッキングするための異垞な方法を考え出す必芁がありたす。 それらのいく぀かに぀いお以䞋で説明したすが、他のすべおのオプションを「むメヌゞず䌌姿で」自分で実装する必芁がありたす。







䟿宜䞊、サヌビスずタむプの倉換、および特性の可胜な倀を含むドキュメントを䜜成したした 。 䜿甚されるすべおのタむプずサヌビスは、 HAP-NodeJSラむブラリに察応しおいたす 。







枩床センサヌ



これは最も単玔な䟋です-必芁なのは、枩床の数倀を含む1぀の状態を持぀こずだけです。 センサヌたたはむンタヌネットサヌビス倩気から取埗できたす。

Sensorカテゎリのデバむスを远加し、TemperatureSensorサヌビスをデバむスに远加しお、このサヌビスに名前を付ける必芁がありたす。 このサヌビスには5぀の特性があり、そのうち最も重芁なのはCurrentTemperatureです。







アクセサリヌ枩床蚈







枩床センサヌサヌビス







CurrentTemperature特性で枩床に察応する状態の名前を瀺すだけで十分です。







ここにHumiditySensor湿床サヌビスを远加するず、Homekitに別のアクセサリヌアむコンが䜜成されたす。







HumiditySensorサヌビス







保存しお、完了です。 これでSiriに目を向け、枩床ず湿床に぀いお尋ねるこずができたす。













Siriずの䌚話









バッテリヌ



別のシンプルなサヌビス。 その秘trickは、ほがすべおのアクセサリに远加できるこずです。 BatteryServiceサヌビスを远加し、BatteryLevel特性でバッテリヌ充電の割合を含む状態を瀺したす。 その埌、充電デヌタがデバむスに関する远加デヌタに衚瀺されたす。







BatteryService







指定した状態の倀が1に等しい堎合、デバむスむメヌゞに察応するアむコンが衚瀺されたす、すぐに「䜎充電」のサむン特性StatusLowBatteryを蚭定できたす。







しかし、そのような状態ではなく、䜎充電アむコンを衚瀺したい堎合はどうでしょうか この状態を手動たたはスクリプトで䜜成し、䜜成した状態を特性で瀺す必芁がありたす。







珟圚は、この状態で倀を正しくtrueに蚭定するだけです。 これを行うには、スクリプトを䜿甚したす。バッテリヌが30に達するず、trueに蚭定されたす。







createState(""); on({id: "zigbee.0.00158d0001f41725.battery", change: "ne"}, function (obj) {   var value = obj.state.val; setState("javascript.0.", (value <= 30)); });
      
      





最初の実行埌、スクリプトは状態を䜜成し、特性で遞択できたす。













このサむンは、アクセサリヌの画像に衚瀺されたす













およびデバむスの詳现







ランプ



電球は異なりたす-明るく、暖かく、赀。 4぀のケヌスがありたす。









これらの各ケヌスに぀いお、Lightbulbサヌビスには察応する特性がありたす。









単玔なケヌスでは、「オン」特性で、オンずオフを切り替える責任がある状態を瀺したす。













ランプが調光可胜な堎合は、さらに茝床レベルでステヌタスを瀺したす。













正しい状態を割り圓おるこずに加えお、蚱容倀の間隔を芳察するこずが重芁です







䟋堎合によっおは、ランプの明るさの原因ずなる状態は0〜255の倀を取るこずができたすが、Homekitではこれらの倀は0〜100の間隔に制限されたす。この堎合、Yahkaドラむバヌ倉換関数を䜿甚できたす。 関数 "level255"は、倀0..255の間隔を間隔0..100に倉換したすおよびその逆。







ランプが色付けされおいる堎合、次の問題が発生する可胜性がありたすが、䜿甚される色はRGBです。 3぀の異なる状態、たたは1぀の番号たたは行のいずれかです。 この堎合、1぀のRGBカラヌスペヌスから別のXYBスペヌスこのスペヌスはHomeKitによっお䜿甚されたす、たたはXYプレヌンに倉換する必芁がありたす。







これを行うには、2぀の新しい状態色盞ず圩床を䜜成する必芁がありたす。この状態に倀をRGB状態から、たたはその逆に倉換したす。







結果の色のスクリプトは
 //       createState("Hue"); createState("Sat"); //      RGB- on({id: "Hue", ack: false, change: 'any'}, function (obj) {  var hue = parseInt(obj.state.val);  var sat = parseInt(getState('Sat').val);  var res = hsvToRgb(hue, sat, 100);  setRGB(parseInt(res[0]), parseInt(res[1]), parseInt(res[2])); }); //    RGB- function setRGB(r, g, b){  var val = ('00'+r.toString(16)).slice(-2)+('00'+g.toString(16)).slice(-2)+('00'+b.toString(16)).slice(-2);  // RGB-   setState('zigbee.0.00124b0014d016ab.color', val, false); } //   HSV   RGB function hsvToRgb(h, s, v) {  var r, g, b;  var i;  var f, p, q, t;   h = Math.max(0, Math.min(360, h));  s = Math.max(0, Math.min(100, s));  v = Math.max(0, Math.min(100, v));  s /= 100;  v /= 100;   if(s == 0) {      r = g = b = v;      return [          Math.round(r * 255),          Math.round(g * 255),          Math.round(b * 255)      ];  }   h /= 60;  i = Math.floor(h);  f = h - i;  p = v * (1 - s);  q = v * (1 - s * f);  t = v * (1 - s * (1 - f));   switch(i) {      case 0:          r = v;          g = t;          b = p;          break;       case 1:          r = q;          g = v;          b = p;          break;       case 2:          r = p;          g = v;          b = t;          break;       case 3:          r = p;          g = q;          b = v;          break;       case 4:          r = t;          g = p;          b = v;          break;       default: // case 5:          r = v;          g = p;          b = q;  }   return [      Math.round(r * 255),      Math.round(g * 255),      Math.round(b * 255)  ]; }
      
      





色枩床をより簡単に行うこずができたす-ランプで䜿甚可胜な倀の範囲がわかっおいる堎合、HomeKitで䜿甚可胜な間隔に倉換できたす scaleInt関数を䜿甚。







電球サヌビス













ランプの奥深く









サヌモスタット



サヌモスタット-蚭定枩床を維持するデバむスサヌモスタットサヌビス。 したがっお、サヌモスタットの䞻な特性は、目的の枩床TargetTemperatureです。 蚭定枩床に加えお、珟圚の枩床CurrentTemperatureを瀺すこずができたす。これは本質的に情報ですデバむスはセンサヌからのみ読み取るため。







ホヌムアプリケヌションから、サヌモスタットに目暙枩床が蚭定され、珟圚の枩床が監芖されたす。 私のサヌモスタットZontには、これら2぀の状態がありたした。これらは、サヌビスクラりドAPIを介しお利甚できたした。







HomeKitでデバむスを衚瀺するために、いく぀かの定数を远加する必芁がありたした。珟圚の加熱状態はアクティブ1、加熱の目暙状態は自動3です。







サヌモスタットサヌビス













枩床遞択







ゲむツ



ガレヌゞドアGarageDoorOpenerサヌビスを䜿甚するず、サヌモスタットを䜿甚するよりもすべおが耇雑になりたす。







䜿甚可胜な特性のうち、ゲヌトにはタヌゲット状態TargetDoorStateがありたす。これは、ゲヌトが「開いおいる」たたは「閉じおいる」こずを望んでいるこずを瀺しおいたす。 ただし、ゲヌトの珟圚の状態CurrentDoorStateを正しく衚瀺する必芁もありたす。これらは開いおいるか閉じおいるか、たたは開いおいるか閉じおいるのでしょうか。







私の堎合、ゲヌトはioBrokerのmqttを通じおいく぀かの情報状態で開かれたした。









ガレヌゞドア制埡状態







これらの状態のおかげで、ゲヌトの珟圚のステヌタスを蚈算できたす。









ゲヌトを開閉する信号を送信するには、mqttを介しおゲヌト制埡コントロヌラヌにメッセヌゞを送信する2぀の状態がありたす1぀の状態で察応できたすが、ここでは2぀ありたす。









信号を送信するには、「クリック」ボタンをシミュレヌトする必芁がありたす。倀をtrueに蚭定し、しばらくしおからfalseにリセットしたす。 この点で、HomeKitず統合するには、別の状態を䜜成する必芁がありたした-「タヌゲットゲヌト状態」、倉曎されるず、察応する信号が送信されたす。







ゲヌトの開攟性の兆候は、タヌゲット状態぀たり、目暙が目指すものに眮き換えるこずができたす。









たた、別の状態「珟圚のゲヌト状態」を䜜成し、サむンの倀ずタヌゲット状態に応じおスクリプトに入力したす。







ガレヌゞドアの状態倉曎スクリプト
 createState("gate_0.current"); //   createState("gate_0.target"); //   //    0,   300 on({id: "mqtt.0.gate.gpio.13", ack: false, val: 1}, function (obj) {  setStateDelayed("mqtt.0.gate.gpio.13", 0,  300); }); on({id: "mqtt.0.gate.gpio.12", ack: false, val: 1}, function (obj) {  setStateDelayed("mqtt.0.gate.gpio.12", 0,  300); }); //     on({id: "mqtt.0.gate.is_open", ack: false, val: 1}, function (obj) {  // ""  setState("javascript.0.gate_0.current", 0, true); }); on({id: "mqtt.0.gate.is_open", ack: false, val: 0}, function (obj) {  // ""  setState("javascript.0.gate_0.current", 1, true); }); //    - ,      on({id: "javascript.0.gate_0.target", ack: false, val: 0}, function (obj) {  setState("mqtt.0.gate.gpio.12", 1); }); //    - ,      on({id: "javascript.0.gate_0.target", ack: false, val: 1}, function (obj) {  setState("mqtt.0.gate.gpio.13", 1); }); on({id: "mqtt.0.gate.in_progress", ack: true, change: 'any'}, function (obj) {  //    " ",      if (obj.state.val === 1) {      //    "",         const target = getState("javascript.0.gate_0.target");      if (target.val === 0) {          // ""          setState("javascript.0.gate_0.current", 2, true);      } else {          // ""          setState("javascript.0.gate_0.current", 3, true);      }  }  //    " ",      if (obj.state.val === 0) {      //    "",         const target = getState("javascript.0.gate_0.target");      if (target.val === 0) {          // ""          setState("javascript.0.gate_0.current", 0, true);      } else {          // ""          setState("javascript.0.gate_0.current", 1, true);      }  } });
      
      





スクリプトを実行した埌、ガレヌゞドアサヌビスの特性を構成できたす。







GarageDoorOpenerサヌビス













カメラ



HomeKitにカメラを远加するには、「クラシック」メ゜ッドが䜿甚されたす。 ffmpegモゞュヌルを介しおカメラから画像をブロヌドキャストするこずができたす。 これにより、入力ストリヌムが゚ンコヌド、暗号化され、Homekitに枡されたす。







たず、ioBrokerが配眮されおいるサヌバヌにffmpegをむンストヌルする必芁がありたす。







プラットフォヌムごずに、さたざたな方法でむンストヌルされたす。゜ヌスからアセンブリするか、たずえば次のような既補のアセンブリを怜玢できたす。 https://www.johnvansickle.com/ffmpeg/ libx264゚ンコヌダヌが必芁です。 次のコマンドを䜿甚しお、ffmpegをむンストヌルした埌、゚ンコヌダヌを確認できたす。







 ffmpeg -codecs | grep 264
      
      





結果には、次の圢匏の行が含たれおいる必芁がありたす。







 DEV.LS h264                 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (decoders: h264 h264_v4l2m2m h264_vdpau ) (encoders: libx264 libx264rgb h264_v4l2m2m )
      
      





Raspberry Pi 3の堎合、GPUハヌドりェア゚ンコヌディングをサポヌトするコヌデックを備えた既補のアセンブリを䜿甚できたすh264_omx、消費リ゜ヌスが少ない。 次のように配眮したす。







 wget https://github.com/legotheboss/YouTube-files/raw/master/ffmpeg_3.1.4-1_armhf.deb sudo dpkg -i ffmpeg_3.1.4-1_armhf.deb
      
      





このアセンブリには䞡方のコヌデックが存圚したすlibx264およびh264_omx







次に、ブロヌドキャストする必芁のあるカメラストリヌムのアドレスを取埗する必芁がありたすこの手順はこの蚘事の範囲倖です。 たずえば、 既補のパブリックストリヌムを取埗できたす 。







カメラをYahkaに远加し、ストリヌムのアドレスを指定し、必芁に応じおコヌデック、画像サむズ、フレヌムレヌトのパラメヌタヌを倉曎したす。







重芁Homekitでカメラを正しく衚瀺するには、パラメヌタヌの組み合わせが非垞に重芁であり、カメラずストリヌムに䟝存したす。 たた、システムのパフォヌマンスにも圱響したす。 ffmpegの実行䞭のプロセスは倚くのリ゜ヌスを消費したす。







カメラを远加する







ストリヌム蚭定







カメラはゲヌトりェむの倖郚に個別のデバむスずしお远加され、ゲヌトりェむず同じ方法で远加する必芁がありたす







カメラのサムネむル







カメラからの攟送







ボヌナス



ボヌナスずしお、カメラブロヌドキャストの異垞な䜿甚に぀いお説明したす。







カメラの代わりに同じffmpegを䜿甚しお、画像や画像をブロヌドキャストできたす。 これらの写真は、ビデオストリヌムず組み合わせるこずができたす。 画像にテキスト、グラフィックス、およびその他の情報を衚瀺できたす。







テキストオヌバヌレむキャスト







その結果、興味深いダッシュボヌドを取埗できたす。 たた、定期的に画像を曎新するず、動的デヌタが埗られたす。







䟋ずしお、写真ディスク䞊のファむルの圢でいく぀かのむンゞケヌタヌの倉化のグラフを出したした。 このグラフは1分間に1回曎新され、ファむル内の画像を䞊曞きしたす。







関数createImage1、createImage2、グラフの圢成、および画像ぞのテキストの面付けは、この蚘事の範囲倖ですが、ヒントを瀺したす。

写真の圢でグラフを取埗する方法を説明したす。







IoBrokerには、グラフを䜜成する暙準的な方法であるFlotドラむバヌがありたす。 このドラむバヌはWebドラむバヌずペアになっおおり、ブラりザヌに結果を衚瀺したす。 ただし、䜜成されたグラフをサヌバヌ䞊スクリプト内で画像ずしお取埗するには、远加のPhantomJSドラむバヌが必芁です。このドラむバヌは、ペヌゞの「スクリヌンショット」Flotグラフを描画するを取埗したす。







ただし、スクリプトを䜿甚しおサヌバヌ䞊でグラフを䜜成する別の方法に぀いお説明したす。







そのようなChart.jsラむブラリhttp://www.chartjs.org/があり、これを䜿甚するず、ブラりザで芋栄えの良いグラフィックを描画できたす䟋http://www.chartjs.org/samples/latest/ 。







描画には、ブラりザの「キャンバス」キャンバスを䜿甚したす。 したがっお、サヌバヌでこのラむブラリを䜿甚しお描画するには、「サヌバヌ」バヌゞョンの「キャンバス」オブゞェクトずDOMオブゞェクトを䜿甚する必芁がありたす。 これがchartjs-nodeパッケヌゞの機胜です https://github.com/vmpowerio/chartjs-node 。







このパッケヌゞの䞻な䟝存関係は、キャンバスパッケヌゞ https://github.com/Automattic/node-canvas であり、グロヌバルたたはiobrokerフォルダヌにむンストヌルする必芁がありたす。 https://github.com/Automattic/node-canvas#compilingを配眮したプラットフォヌムのすべおの䟝存関係をむンストヌルするこずが重芁です。







その埌、chart.js、chartjs-nodeモゞュヌルをjavascriptドラむバヌ蚭定に远加できたす。 ゚ラヌなしで正しくむンストヌルされるはずです。 それ以倖の堎合は、゚ラヌを凊理しお解決したす。







そしお、スクリプトを曞くこずができたす。







以䞋は、䟋のスクリプトです。 これには、履歎ドラむバヌの䜿甚が含たれ、特定の状態名が䜿甚されたす。







泚意 スクリプトには、初心者向けの耇雑な構造がありたす-Promise これは、コヌルバックを䜿甚しお関数を䜜成するのではなく、ステップのチェヌンを䜜成する䟿利な方法です。 したがっお、たずえば、これを実行しお状態履歎からデヌタを取埗するず䟿利です。







 'use strict'; const ChartjsNode = require('chartjs-node'); /** *  sendTo  Promise,      */ function sendToPromise(adapter, cmd, params) { return new Promise((resolve, reject) => { sendTo(adapter, cmd, params, (result) => { resolve(result); }); }); } //    const chartColors = { black: 'rgb(0, 0, 0)', red: 'rgb(255, 99, 132)', orange: 'rgb(255, 159, 64)', yellow: 'rgb(255, 205, 86)', green: 'rgb(75, 192, 192)', blue: 'rgb(54, 162, 235)', purple: 'rgb(153, 102, 255)', grey: 'rgb(201, 203, 207)' }; /** *        * : * @param config -     * @param filename -     * : * @param Promise -    */ function doDraw(config, filename) { //     640x480  var chartNode = new ChartjsNode(640, 480); return chartNode.drawChart(config) .then(() => { //     return chartNode.writeImageToFile('image/png', filename); }); } /** *     ChartJS. * : * @param Promise -    */ function prepareDraw0(){ // ,    var ; //  Promise     return new Promise((resolve, reject)=>{resolve()}) //       ,      .then(()=>{ //  ,   ,      = [ {"val":3,"ack":1,"ts":1539063874301}, {"val":5,"ack":1,"ts":1539063884299}, {"val":5.3,"ack":1,"ts":1539063894299}, {"val":3.39,"ack":1,"ts":1539063904301}, {"val":5.6,"ack":1,"ts":1539063914300}, {"val":-1.3,"ack":1,"ts":1539063924300}, {"val":-6.3,"ack":1,"ts":1539063934302}, {"val":1.23,"ack":1,"ts":1539063944301}, ]; }) //   -    .then(()=>{ const chartJsOptions = { //   -  type: 'line', data: { //    datasets: [ { //   label: '', //  backgroundColor: chartColors.black, borderColor: chartColors.black, //   pointRadius: 3, //    borderWidth: 3, //     ''        data: .map((item) => { return {y: item.val, t: new Date(item.ts)} }), //   -  fill: false, } ] }, options: { //   legend: { labels: { //   fontSize: 20, }, }, //   scales: { //  X xAxes: [{ //  -   type: 'time', display: true, //   scaleLabel: { display: true, labelString: '' }, }], //  Y yAxes: [{ //  -  type: 'linear', display: true, //   scaleLabel: { display: true, labelString: '' }, }] } } }; return chartJsOptions; }); } /** *     ChartJS. *         , *     . * * : * @param hours -  ,     * : * @param Promise -    */ function prepareDraw1(hours){ //   ,      const end = new Date().getTime(), start = end - 3600000*(hours || 1); // 1 =   //  ,       //   var , 2, 1, 2, 2; //  Promise     return new Promise((resolve, reject)=>{resolve()}) //       'mqtt.0.ESP_Easy..Temperature' .then(() => { return sendToPromise('history.0', 'getHistory', { id: 'mqtt.0.ESP_Easy..Temperature', options: { start: start, end: end, aggregate: 'onchange' } } ).then((result) => { //     ''  = result.result; }); }) //       'sonoff.0.chicken2.DS18B20_Temperature' .then(() => { return sendToPromise('history.0', 'getHistory', { id: 'sonoff.0.chicken2.DS18B20_Temperature', options: { start: start, end: end, aggregate: 'onchange' } }).then((result)=>{ //     '2' 2 = result.result; }); }) .then(() => { return sendToPromise('history.0', 'getHistory', { id: 'sonoff.0.sonoff_chicken_vent.DS18B20_Temperature', options: { start: start, end: end, aggregate: 'onchange' } }).then((result)=>{ 1 = result.result; }); }) .then(() => { return sendToPromise('history.0', 'getHistory', { id: 'sonoff.0.chicken2.POWER1', options: { start: start, end: end, aggregate: 'onchange' } }).then((result)=>{ 2 = result.result; }); }) .then(() => { return sendToPromise('history.0', 'getHistory', { id: 'sonoff.0.chicken2.POWER2', options: { start: start, end: end, aggregate: 'onchange' } }).then((result)=>{ 2 = result.result; }); }) //   -    .then(()=>{ const chartJsOptions = { //   -  type: 'line', data: { //    datasets: [ { //           label: ' ('+[.length - 1].val+')', //  backgroundColor: chartColors.blue, borderColor: chartColors.blue, //  . 0 -   pointRadius: 0, //    borderWidth: 3, //     ''        data: .map((item) => { return {y: item.val, t: new Date(item.ts)} }), //   -  fill: false, //   Y yAxisID: 'y-axis-1', },{ label: ' 1 ('+1[1.length - 1].val+')', backgroundColor: chartColors.green, borderColor: chartColors.green, pointRadius: 0, borderWidth: 3, data: 1.map((item) => { return {y: item.val, t: new Date(item.ts)} }), fill: false, yAxisID: 'y-axis-1', },{ label: ' 2 ('+2[2.length - 1].val+')', backgroundColor: chartColors.red, borderColor: chartColors.red, pointRadius: 0, borderWidth: 3, data: 2.map((item) => { return {y: item.val, t: new Date(item.ts)} }), fill: false, yAxisID: 'y-axis-1', },{ label: ' 2  ('+2[2.length - 1].val+')', backgroundColor: chartColors.yellow, borderColor: chartColors.yellow, pointRadius: 0, borderWidth: 1, data: 2.map((item) => { return {y: (item.val) ? 1 : 0, t: new Date(item.ts)} }), fill: true, lineTension: 0, steppedLine: true, yAxisID: 'y-axis-2', },{ label: ' 2  ('+2[2.length - 1].val+')', backgroundColor: chartColors.grey, borderColor: chartColors.grey, pointRadius: 0, borderWidth: 1, data: 2.map((item) => { return {y: (item.val) ? -1 : 0, t: new Date(item.ts)} }), fill: true, lineTension: 0, steppedLine: true, yAxisID: 'y-axis-2', } ] }, options: { //   legend: { labels: { //   fontSize: 20, }, }, //   scales: { //  X xAxes: [{ //  -   type: 'time', display: true, //   scaleLabel: { display: true, labelString: '' }, //    () time: { unit: 'minute', displayFormats: { minute: 'HH:mm' } }, }], //  Y yAxes: [{ //  -  type: 'linear', display: true, //   scaleLabel: { display: true, labelString: '' }, //   -  position: 'left', //   id: 'y-axis-1', },{ type: 'linear', display: true, scaleLabel: { display: true, labelString: '  ' }, ticks: { min: -4, max: 2 }, //   -  position: 'right', id: 'y-axis-2', }] } } }; return chartJsOptions; }); } function createImage(filename, callback){ // filename -  ,       //    prepareDraw1(2) //     .then((result) => { //        return doDraw(result, filename); }) .then(()=>{ if (callback) callback(); }) .catch((err)=>{ console.error(err); }); }
      
      





ストリヌムの代わりに画像をブロヌドキャスト







サムネむル画像は玄1分に1回曎新されるため、10秒ごずに曎新されるように画像を蚭定したす。







 var fs = require('fs'); //  10    schedule("*/10 * * * * *", () => {  createImage1('/tmp/1_new.jpg', ()=> {      fs.renameSync('/tmp/1_new.jpg', '/tmp/1.jpg');  });  createImage2('/tmp/2_new.jpg', ()=> {      fs.renameSync('/tmp/2_new.jpg', '/tmp/2.jpg');  }); });
      
      





特殊な点は、画像をブロヌドキャストするプロセスで、ffmpegがクラッシュしないように画像を十分に迅速に眮き換える必芁があるこずです:)したがっお、画像は最初に1぀のファむルに圢成され、次にファむルは翻蚳に䜿甚されるファむルに名前が倉曎されたす。







ここで、カメラの蚭定で、ストリヌムアドレスの代わりに生成されたファむルの名前を指定し、画像が「曎新」される蚭定パラメヌタヌ「-loop 1」を远加したす。 これは、カメラの詳现プロパティで構成されたす。 これらのプロパティは、ffmpegを実行するためのコマンドラむンオプションにすぎたせん。 したがっお、ffmpegのドキュメントず䟋でパラメヌタヌの組み合わせを芋぀ける必芁がありたす。







プロパティは、「プレビュヌ」小さなカメラ画像を取埗するためずブロヌドキャストするための2皮類に分けられたす。 したがっお、たずえば異なる詳现で、異なる画像゜ヌスファむルを指定できたす。







Ffmpeg起動オプション







ラむブ攟送画像







おわりに



デバむスずサヌドパヌティのサヌビスをioBrokerシステムに統合するずいうトピックは非垞に深く、単玔ではありたせん。プラグむンの䜜成者は統合プロセスを簡玠化しようずしたすが、堎合によっおは远加のロゞックを蚘述する必芁がありたす。しかし、このような柔軟性のおかげで、ほがすべおのデバむスおよびサヌビスずの統合が可胜です。







Yahkaドラむバヌの開発者は、Materialドラむバヌで行われおいるように、努力しおデバむスの自動怜出を远加するこずが望たれたす。この堎合、状態の圹割ず機胜を瀺す必芁があり、ドラむバヌはHomeKitのゲヌトりェむ構成に適切なデバむスを远加するこずを提案する必芁がありたす。







Yahka, HomeKit — Ham, HomeBridge . しかし、これは別の蚘事のトピックです。








All Articles