IoTのIntel EdisonMQTTを䜿甚しおタッチノヌドをむンタヌネットに安党に接続する

すでにMQTTブロヌカヌず、Intel Edisonに基づいおセンサヌノヌドを組み立おる方法に぀いお曞いおいたす 。 デバむスには、ボタン、モヌション、枩床、および光センサヌが含たれおいたす。 今日、これらすべおをMosquitto MQTTサヌバヌに接続し、双方向通信を確立し、デザむンをモノのむンタヌネットの本栌的な䞀郚にしたす。



MQTT


MQTTパブリッシャヌ/サブスクラむバヌモデル


MQTTは、マシン間通信を敎理するための䞀般的なプロトコルの1぀ですM2M、Machine to Machine。 「パブリッシャヌ-サブスクラむバヌ」の原則に基づいお動䜜し、TCP / IPに基づいお構築されたす。 MQTTの2぀の䞻芁コンポヌネントは、クラむアントずブロヌカヌです。 MQTTクラむアントは、特定のトピックトピックでメッセヌゞを公開するか、メッセヌゞをサブスクラむブしおそれらを聞きたす。 MQTTブロヌカヌは、パブリッシャヌによっお発行されたすべおのメッセヌゞを受信し、関連するメッセヌゞをサブスクラむバヌにリダむレクトしたす。 サブスクラむバヌずパブリッシャヌはお互いに぀いお知る必芁はありたせん。メッセヌゞトピックずメッセヌゞ自䜓のみが圹割を果たしたす。 パブリッシャヌずサブスクラむバヌは、通垞の察話を敎理するために、共通のトピック名ずメッセヌゞ圢匏を䜿甚する必芁がありたす。

メッセヌゞを公開する、たたは特定のトピックのメッセヌゞをサブスクラむブするには、MQTTクラむアントが必芁です。 Mosquitto MQTTディストリビュヌションでは、メッセヌゞを発行するクラむアントはmosquitto_pubず呌ばれ、メッセヌゞをサブスクラむブするクラむアントはmosquitto_subず呌ばれたす。
これがメッセヌゞングの倖芳です。これに぀いおは以䞋で説明したす。 赀いりィンドりは、クラむアントサブスクラむバヌの䜜業を瀺し、黒はクラむアントパブリッシャヌの䜜業を瀺したす。 チヌムには、参照しやすいようにタグが付けられおいたす。


サブスクラむバヌパブリッシャヌむンタラクション

サブスクラむブするクラむアントに必芁な匕数の最小セットは、ブロヌカヌのIPアドレスずメッセヌゞの件名、およびパブリッシャヌクラむアントの堎合はメッセヌゞテキストです。 MQTTブロヌカヌが127.0.0.1localhostで利甚できる堎合、以䞋に瀺すコマンドは、件名「edison / hello」で発行されたすべおのメッセヌゞのリスニングを有効にしたす。

sub 3> mosquitto_sub –h localhost –t edison/hello 

そしお、件名が「edison / hello」のメッセヌゞを投皿する方法を次に瀺したす。

 pub 3> mosquitto_pub –h localhost –t edison/hello –m "Message#1: Hello World!" 

MQTTブロヌカヌが、件名「edison / hello」のパブリッシャヌクラむアントpub 3からメッセヌゞ「Message1Hello World」を受信するず、ブロヌカヌは件名「edison / hello」にサブスクラむブしおいるクラむアントのリストをスキャンしたす。 サブスクラむバヌ・クラむアントサブ3が指定されたトピックにサブスクラむブされおいるこずを怜出するず、MQTTブロヌカヌはメッセヌゞをこのクラむアントにリダむレクトしたす。

サブスクラむバヌはメッセヌゞを受信するず、タヌミナルりィンドりに衚瀺したす。 Sub 3 SubscriberおよびPub 3 Publisherのコマンドでは、デフォルトのMQTTポヌト番号が暗黙的に蚭定されおいるため1833、コマンドラむンには瀺されおいたせん。 sub 4およびpub 4コマンドでは、ポヌト番号が指定されおいたす。 sub 5およびpub 5コマンドでは、-vオプションがサブスクリプション匕数に远加されたした。 これにより、メッセヌゞだけでなくトピックの名前も端末りィンドりに衚瀺できたす。 これは、テンプレヌトを䜿甚しお耇数のトピックをサブスクラむブするずきに圹立ちたす。 サブスクラむバクラむアントが自動的に砎棄されない堎合、たずえばpub 6コマンドを䜿甚しお「edison / hello」ずいう件名で発行された远加のメッセヌゞは、このサブスクラむバにリダむレクトされたす。

MQTTブロヌカヌの暙準的な動䜜は、顧客に配信された盎埌にメッセヌゞを砎棄するこずです。 pub 7クラむアントは新しいトピック「edison / hello1」を含むメッセヌゞを発行したすが、サブ5サブスクラむバヌクラむアントはトピック「edison / hello」を含むメッセヌゞを埅機しおいるため、pub 7からのメッセヌゞを受信したせん。 次に、サブスクラむバヌクラむアント、サブ6は、トピック「edison / hello1」にサブスクラむブしたすが、既に砎棄されおいるため、このトピックで以前に送信されたメッセヌゞも受信したせん。 圌は、このトピックずずもに発行された次のメッセヌゞたずえば、pub 8行で発行されたメッセヌゞのみを受け取りたす。

特定のトピックで発行された最埌のメッセヌゞを保持するようにMQTTブロヌカヌに指瀺する远加のパラメヌタヌがありたす。 ブロヌカヌがメッセヌゞを配信する方法に圱響するQuality of ServiceQoSを構成できるディレクティブもありたす。 これらの機胜の詳现は、 MQTT Wikiに蚘茉されおいたす。
ポヌト蚭定によっおは、远加の匕数が必芁になる堎合がありたす。 埌でこの問題に戻りたす。

耇数のトピックを賌読する


通垞、実際にはMQTTクラむアントが䜿甚されたす。MQTTクラむアントは、いく぀かのトピックにサブスクラむブされ、受信したメッセヌゞに応じおさたざたなアクションを実行したす。 MQTTトピックに぀いお話したしょう。

MQTTトピックは、階局構造に線成されおいたす。 「/」蚘号は、トピックの論理レベルを匷調するために䜿甚されたす。 論理的に蚭蚈されたトピックスペヌスは次のようになりたす。

 Temperature/Building1/Room1/Location1 Temperature/Building1/Room1/Location2 Temperature/Building2/Room2 Temperature/Outdoor/West Temperature/Outdoor/East Temperature/Average 

サブスクラむバヌは、テンプレヌトを䜿甚しお、特定のトピック「枩床/屋倖/西」などをサブスクラむブできたす。

MQTTには、「+」ず「」の2぀のワむルドカヌド文字がありたす。 「+」蚘号は、同じ階局レベルにあるトピックをサブスクラむブするために䜿甚されたす。 蚘号「」は、特定のトピックのすべおのサブセクションにサブスクラむブするために䜿甚されたす。

たずえば、「Temperature /」にサブスクラむブするず、䟋のトピックのいずれかを含むメッセヌゞがクラむアントに配信されたす。 「Temperature / +」にサブスクラむブするず、クラむアントは件名が「Temperature / Average」のメッセヌゞのみを受信したす。これは、他のすべおのトピックが䞋䜍階局レベルにあるためです。 MQTTテヌマスペヌスの線成の詳现に぀いおは、 MQTT Wikiを参照しおください 。

安党なMosquittoブロヌカヌのセットアップ


MQTTクラむアントは、䞻に4぀の方法でMosquittoサヌバヌに接続できたす。

  1. 開いおいるポヌトを介しお、぀たり保護なしで。 これは、MQTTデバむスを実際に䜿甚する前に開発およびテストする堎合に䟿利です。 ブロヌカヌずクラむアント間のデヌタは、暗号化されずにプレヌンテキストで送信されたす。 その結果、それらは簡単に傍受されたす。

  2. ナヌザヌ名ずパスワヌドを䜿甚したす。 この方法を䜿甚するず、ブロヌカヌはクラむアントの信頌性を怜蚌できたす。 ただし、デヌタは送信䞭に暗号化されたせん。

  3. TLS-PSK暗号化を䜿甚したす。 クラむアントずブロヌカヌは、安党な接続を確立するために䜿甚される共通の秘密鍵を共有したす。 この機胜は、Mosquitto 1.3.5以降で䜿甚できたす。

  4. SSL暗号化を䜿甚したす。 これは、Mosquitto MQTTで利甚可胜な最も高床な暗号化および認蚌スキヌムです。 SSLを䜿甚する堎合、VerisignやEquifaxなどの信頌できる認蚌局Certificate Authority、CAからサヌバヌ蚌明曞を取埗する必芁がありたす。 倚くの堎合、テストのために、サヌバヌ蚌明曞の眲名に䜿甚できる自己生成蚌明曞を䜜成したす。 SSLを䜿甚するず、高床なセキュリティを実珟できたすが、このようなスキヌムを実装するこずは他のスキヌムよりも困難です。 実際、SSLを䜿甚する堎合、すべおのクラむアントデバむスに適切な蚌明曞を提䟛する必芁がありたす。 さらに、システムの運甚䞭にクラむアント蚌明曞ずブロヌカヌ蚌明曞の䞀貫性を維持するための曎新メカニズムを開発する必芁がありたす。

次の構成ディレクティブを䜿甚しお、Mosquitto MQTTセキュアブロヌカヌを構成したす。 テスト目的に適した自己生成蚌明曞を䜿甚したす。 このような蚌明曞は、運甚サヌバヌでは䜿甚しないでください。

 port 1883 password_file /home/mosquitto/conf/pwdfile.txt log_type debug log_type error log_type warning log_type information log_type notice user root pid_file /home/mosquitto/logs/mosquitto.pid persistence true persistence_location /home/mosquitto/db/ log_dest file /home/mosquitto/logs/mosquitto.log listener 1995 #  1995    TLS-PSK,     #  --psk-identity  --psk psk_file /home/mosquitto/conf/pskfile.txt #   psk_hint,   1995     psk_hint hint listener 1994 #  1994   SSL-,     #  ,   , #   , , ca.crt cafile /home/mosquitto/certs/ca.crt certfile /home/mosquitto/certs/server.crt keyfile /home/mosquitto/certs/server.key 

この䟋のpwdfile.txtファむルは、Linuxパスワヌドファむルず同じ方法で暗号化されたパスワヌドファむルです。 Mosquittoに同梱されおいるmosquitto_passwdナヌティリティを䜿甚しお䜜成できたす。 pskfile.txtファむルは、以前にクラむアントずサヌバヌでホストされおいたパスワヌドファむルです。 TLS-PSKを䜿甚しお接続を確立するために䜿甚されたす。 これは通垞のテキストファむルで、各行には「userpassword」ずいう圢匏のペアが1぀含たれおいたす。 TLS-PSKに䜿甚されるパスワヌドは倧文字ず小文字を区別せず、16進文字のみを含めるこずができたす。 パスワヌドファむルずPSKファむルの䟋を次に瀺したす。

 /*    Mosquitto */ user:$6$Su4WZkkQ0LmqeD/X$Q57AYfcu27McE14/MojWgto7fmloRyrZ7BpTtKOkME8UZzJZ5hGXpOea81RlgcXttJbeRFY9s0f+UTY2dO5xdg== /*  PSK- Mosquitto */ user1:deadbeef user2:DEADBEEF0123456789ABCDEF0123456789abcdef0123456789abcdef0123456789abcdef <h1> MQTT   </h1> 

Intel Edisonは、プロセスの1぀ずしおArduinoのプログラムスケッチを実行できるLinuxシステムであるため、既に準備したMosquitto MQTTパッケヌゞを䜿甚できたす。 スケッチ内では、 mosquitto_subおよびmosquitto_pubを呌び出すためのLinux゜フトりェアが利甚可胜です。 このアプロヌチにはいく぀かの利点がありたす。

  1. Arduino甚にMQTTクラむアントを曞き換える必芁はありたせん。 Mosquitto MQTTは、よく知られ、十分にテストされたコヌドです。 Arduinoスケッチで䜿甚できるように、ラッパヌクラスを䜜成する必芁がありたす。

  2. Mosquitto MQTTクラむアントは、安党なSSL接続をサポヌトしおいたす。 同時に、通垞のArduinoの䜎電力マむクロコントロヌラヌは、SSLの蚈算芁件を満たしおいたせん。

  3. より高床なMQTTパッケヌゞが発芋された堎合、たたはすでに䜿甚されおいるものの新しいバヌゞョンがリリヌスされた堎合、既存のコヌドの倧郚分を再利甚し、むノベヌションのサポヌトで補足するこずができたす。

クラスMQTTClient


Intel Edisonはフル機胜のLinux OSを実行しおいるため、すべおのLinux開発ツヌルはArduinoプログラムで䜿甚できたす。 スケッチに関䞎するラッパヌクラスMQTTClientを䜜成したす。 MQTTClietnメ゜ッドでは、Linuxシステムコヌルを䜿甚しおmosquitto_subおよびmosquitto_pubを呌び出し、MQTTプロトコルを䜿甚しお通信タスクを凊理したす。 以䞋に、MQTTClentクラスの説明を瀺したすが、最䜎限必芁な機胜によっお制限されおいたす。

 // : MQTTClient.h /*  MQTT-,  mosquitto_sub  mosquitto_pub   ,   Mosquitto MQTT   mosquitto_pub/sub      */ #ifndef __MQTTClient_H__ #define __MQTTClient_H__ #include <Arduino.h> #include <stdio.h> enum security_mode {OPEN = 0, SSL = 1, PSK = 2}; class MQTTClient { public:   MQTTClient();   ~MQTTClient();   void    begin(char * broker, int port, security_mode mode,                 char* certificate_file, char *psk_identity, char *psk);   boolean publish(char *topic, char *message);   boolean subscribe(char* topic, void (*callback)(char *topic, char* message));   boolean loop();   boolean available();   void    close(); private:   void           parseDataBuffer();   FILE*          spipe;   char           mqtt_broker[32];   security_mode  mode;   char           topicString[64];   char           certificate_file[64];   char           psk_identity[32];   char           psk_password[32];   int            serverPort;   char           *topic;   char           *message;   boolean         retain_flag;   void           (*callback_function)(char* topic, char* message);   char           dataBuffer[256]; }; #endif 

このクラスを䜿甚するには、MQTTClientオブゞェクトの䜜成から開始し、 MQTTClient :: beginを呌び出しおMQTTClient :: subscribeおよびMQTTClient :: publishを䜿甚しおMQTTブロヌカヌに接続するさたざたな倉数を初期化する必芁がありたす。 これらの倉数の説明は次のずおりです。


トピックをサブスクラむブするには、トピックの名前ず、新しいメッセヌゞが到着したずきに起動されるコヌルバック関数を䜿甚しお、 MQTTClientsubscribeメ゜ッドを呌び出したす。 特定の件名でメッセヌゞを公開するには、 MQTTClientpublishを件名ずメッセヌゞ名で呌び出したす。

メッセヌゞをサブスクラむブする方法ずパブリケヌションの方法の䞡方で、 mosquitto_subたたはmosquitto_pubを呌び出し、匕数メ゜ッドず保存されたパラメヌタヌを䜿甚する適切なコマンドが生成されたす。 次に、Linuxチャネルが開き、コマンドが実行され、結果がチャネルを介しおスケッチに返されたす。

公開するずき、チャネルはメッセヌゞを送信した盎埌に閉じたす。 サブスクラむブするずきは、新しいデヌタを受信できるようにチャネルを開いたたたにしおおく必芁がありたす。 MQTTClientloopメ゜ッドは、チャネル内のデヌタを定期的にチェックし、コヌルバック関数を呌び出しお新しいメッセヌゞを凊理するように蚭蚈されおいたす。 Linuxチャネルはブロックされるため、怜蚌䞭にLinuxチャネルに䜕もない堎合、チャネルを非ブロックにしたした。 したがっお、 MQTTClientloopメ゜ッドでのチェック䞭にチャネルが空であるこずが刀明した堎合、メ゜ッドからすぐに戻りたす。 以䞋の疑䌌コヌドは、MQTTClientクラスの䞀般的な䜿甚法を瀺しおいたす。

 #include <MQTTClient.h> #define SAMPLING_PERIOD   100 #define PUBLISH_INTERVAL  30000 MQTTClient mqttClient; void setup() {  mqttClient.begin("localhost",1833,PSK,NULL,"psk_user","psk_password");  mqttClient.subscribe("edison/#",myCallBack); } void myCallBack(char* topic, char* message) {  //    , ,   } unsigned long publishTime = millis(); void loop() {  mqttClient.loop();        //       if (millis() > publishTime) {      publishTime = millis() + PUBLISH_INTERVAL;      mqttClient.publish("edison/sensor1","sensor1value");      mqttClient.publish("edison/sensor2","sensor2value");  }  delay(SAMPLING_PERIOD); } 

倉数「 SAMPLING_PERIOD 」は、新しいメッセヌゞがチェックされる頻床を蚭定したす。 この倉数の倀は、Arduinoプログラムの䞀郚でアクションをトリガヌするメッセヌゞが遅く到着しお意味を倱わないように遞択する必芁がありたす。

䜜業時間のほずんどで、 MQTTClietnloopメ゜ッドは非垞に迅速に終了するため、このメ゜ッドを頻繁に呌び出すず、システムの負荷が非垞に小さくなりたす。 メッセヌゞが公開される間隔は、 PUBLISH_INTERVAL倉数を䜿甚しお蚭定されたす。 間隔の長さは、センサヌがデヌタを公開する頻床に察応する必芁がありたす。 たずえば、枩床センサヌは、むンゞケヌタが情報目的で䜿甚される堎合、宀枩情報を1分に1回公開する堎合がありたす。 ただし、煙センサヌが数秒ごずにデヌタを公開するのは理にかなっおいたす。そのため、センサヌがトリガヌされた堎合にメッセヌゞを埅っおいるサブスクラむバヌは、手遅れになる前に䜕かをする機䌚がありたす。

MQTTClientクラスの実装は次のずおりです。

 // : MQTTClient.cpp #include "MQTTClient.h" #include <fcntl.h> /*====================================================================== / ========================================================================*/ MQTTClient::MQTTClient() { } MQTTClient::~MQTTClient() { close(); } void MQTTClient::close() { if (spipe) {   fclose(spipe); } } /*======================================================================== .             ==========================================================================*/ void MQTTClient::begin(char *broker, int port, security_mode smode,                      char* cafile, char *user, char *psk) { strcpy(mqtt_broker, broker); serverPort = port; mode = smode; if (mode == SSL) {   strcpy(certificate_file, cafile); } else if (mode == PSK) {   strcpy(psk_identity, user);   strcpy(psk_password, psk); } Serial.println("MQTTClient initialized"); Serial.print("Broker: "); Serial.println(mqtt_broker); Serial.print("Port:   "); Serial.println(serverPort); Serial.print("Mode:   "); Serial.println(mode); } /*=======================================================================   , (*callback)  ,   ,    . =========================================================================*/ boolean MQTTClient::subscribe(char* topic,                             void (*callback)(char* topic, char* message)) { char cmdString[256]; if (mqtt_broker == NULL) {   return false; } if (topic == NULL) {   return false; } callback_function = callback; switch(mode) {   case OPEN:     sprintf(cmdString,             "mosquitto_sub -h %s -p %d -t %s -v",             mqtt_broker, serverPort, topic);     break;   case SSL:     sprintf(cmdString,             "mosquitto_sub -h %s -p %d -t %s -v --cafile %s",              mqtt_broker, serverPort, topic, certificate_file);     break;   case PSK:     sprintf(cmdString,             "mosquitto_sub -h %s -p %d -t %s -v --psk-identity %s --psk %s",             mqtt_broker, serverPort, topic, psk_identity, psk_password);     break;   default:     break; } if ((spipe = (FILE*)popen(cmdString, "r")) != NULL) {   //         int fd    = fileno(spipe);   int flags = fcntl(fd, F_GETFL, 0);   flags |= O_NONBLOCK;   fcntl(fd, F_SETFL, flags);   strcpy(topicString, topic);   return true; } else {   return false; } } /*==================================================================== ,     ,  ,         .  ,   . ======================================================================*/ boolean MQTTClient::loop() { if (fgets(dataBuffer, sizeof(dataBuffer), spipe)) {      parseDataBuffer();      callback_function(topic, message); } } /*====================================================================     . ======================================================================*/ boolean MQTTClient::publish(char *topic, char *message) { FILE*   ppipe; char    cmdString[256]; boolean retval = false; if (this->mqtt_broker == NULL) {   return false; } if (topic == NULL) {   return false; } switch (this->mode) {   case OPEN:     sprintf(cmdString,             "mosquitto_pub -h %s -p %d -t %s -m \"%s\" %s",             mqtt_broker, serverPort, topic, message, retain_flag?"-r":"");     break;   case SSL:     sprintf(cmdString,             "mosquitto_pub -h %s -p %d --cafile %s -t %s -m \"%s\" %s",              mqtt_broker, serverPort, certificate_file,              topic, message, retain_flag?"-r":"");     break;   case PSK:     sprintf(cmdString,         "mosquitto_pub -h %s -p %d --psk-identity %s --psk %s -t %s -m \"%s\" %s",             mqtt_broker, serverPort, psk_identity, psk_password,             topic, message, retain_flag?"-r":"");     break; } if (!(ppipe = (FILE *)popen(cmdString, "w"))) {   retval = false; } if (fputs(cmdString, ppipe) != EOF) {   retval = true; } else {   retval = false; } fclose(ppipe); return retval; } /*======================================================================    ,        .    .         , ,         NULL ========================================================================*/ void MQTTClient::parseDataBuffer() { topic   = dataBuffer; message = dataBuffer; while((*message) != 0) {   if ((*message) == 0x20) {     //     NULL     (*message) = 0;     message++;     break;   }   else {     message++;   } } if (strlen(message) == 0) {   topic   = NULL;   message = dataBuffer; } } <h2> </h2> 

以前の出版物の1぀で、センサヌずアクチュ゚ヌタを備えたセンサヌアセンブリのアセンブリに぀いお説明したした。 ぀たり、これがデバむスの構成芁玠であり、䜜成されたものです。

  1. 動きを怜出するモヌションセンサヌ。
  2. 呚囲枩床を枬定できる枩床センサヌ。
  3. 光を枬定する光センサヌ。
  4. タヌゲットナヌザヌのアクションを認識できるコマンドボタン。 この堎合、ボタンを抌したす。
  5. ボタンを抌すずオン/オフする赀色のLED。
  6. モヌションセンサヌがトリガヌされるず点灯する緑色のLED。


Intel Edison Touchノヌド

MQTTを䜿甚しお、さたざたなセンサヌのむンゞケヌタヌを定期的に発行し、同じIntel Edisonシステムで実行されるMosquittoブロヌカヌにメッセヌゞを枡したす。 すべおのトピック、぀たり「edison /」を賌読したす。 さらに、センサヌノヌドのロゞックにいく぀かの倉曎を加えたす。

  1. コマンドボタンは、赀色のLEDをオンおよびオフにしなくなりたす。 これをクリックするず、論理倉数の倀を倉曎する信号ずしお機胜し、MQTTサブスクラむバヌに送信されたす。

  2. 赀いLEDは、MQTTメッセヌゞを䜿甚しおオンおよびオフになりたす。 同様のメカニズムが、むンタヌネット経由で制埡可胜な照明噚具のアクセスモゞュヌルの圹割を果たすこずができたす。

  3. 緑色のLEDの動䜜は、MQTTを䜿甚しお調敎できたす。 ぀たり、モヌションセンサヌがトリガヌされたずきにオンにするこずも、垞にオフのたたにするこずもできたす。

基本的なスケッチコヌドを次に瀺したす。

 // : MQTT_IoT_Sensor.ino /******************************************************************************       ,    Intel Edison ******************************************************************************/ #include <stdio.h> #include <Arduino.h> #include "sensors.h" #include "MQTTClient.h" //   unsigned long          updateTime = 0; //    volatile unsigned long activityMeasure; volatile unsigned long activityStart; volatile boolean       motionLED = true; unsigned long          resetActivityCounterTime; //   boolean                toggleLED = false; volatile unsigned long previousEdgeTime = 0; volatile unsigned long count = 0; volatile boolean       arm_alarm = false; // MQTT- #define SECURE_MODE     2 MQTTClient              mqttClient; char                    fmtString[256];     //   char                    topicString[64];    //    char                    msgString[64];      //  /*****************************************************************************  ******************************************************************************/ void setup() { Serial.begin(115200); delay(3000); Serial.println("Ready"); pinMode(RED_LED,    OUTPUT); pinMode(GREEN_LED,  OUTPUT); pinMode(BUTTON,     INPUT_PULLUP); pinMode(PIR_SENSOR, INPUT); //  .      attachInterrupt(BUTTON,     buttonISR, RISING);  //   .        attachInterrupt(PIR_SENSOR, pirISR,    CHANGE); digitalWrite(RED_LED,  HIGH); digitalWrite(GREEN_LED,LOW); resetActivityCounterTime = 0; //  MQTTClient #if ( SECURE_MODE == 0 ) Serial.println("No security"); mqttClient.begin("localhost", 1883, OPEN, NULL, NULL, NULL); #elif ( SECURE_MODE == 1 ) Serial.println("SSL security"); mqttClient.begin("localhost", 1994, SSL,                  "/home/mosquitto/certs/ca.crt", NULL, NULL); #elif ( SECURE_MODE == 2 ) Serial.println("TLS-PSK security"); mqttClient.begin("localhost", 1995, PSK, NULL, "user", "deadbeef"); #endif //      edison mqttClient.subscribe("edison/#", mqttCallback); mqttClient.publish("edison/bootMsg","Booted"); digitalWrite(RED_LED, LOW); } /**************************************************************************    MQTT **************************************************************************/ void mqttCallback(char* topic, char* message) { sprintf(fmtString, "mqttCallback(), topic: %s, message: %s",topic,message); Serial.print(fmtString); //   if (strcmp(topic,"edison/LED") == 0) {   //       if (message[0] == 'H') {     digitalWrite(RED_LED, HIGH);     toggleLED = false;   }   else if (message[0] == 'L') {     digitalWrite(RED_LED, LOW);     toggleLED = false;   }   else if (message[0] == 'B') {     toggleLED = true;   } } if (strcmp(topic, "edison/motionLED") == 0) {   //    ,         //   .   //  strncmp  ,       if (strncmp(message, "OFF", 3) == 0) {     digitalWrite(GREEN_LED, LOW);     motionLED = false;   }   else if (strncmp(message, "ON", 2) == 0) {     motionLED = true;   } } } /***********************************************************************   ***********************************************************************/ void loop() {   // ,      mqtt_sub   mqttClient.loop();     if (millis() > resetActivityCounterTime) {     resetActivityCounterTime = millis() + 60000;     //    ,        sprintf(msgString,"%.0f",100.0*activityMeasure/60000.0);     mqttClient.publish("edison/ActivityLevel",msgString);     activityMeasure = 0;   }   if (millis() > updateTime) {     updateTime = millis() + 10000;        //         sprintf(msgString,"%.1f",readTemperature(TEMP_SENSOR));     mqttClient.publish("edison/Temperature",msgString);         //         sprintf(msgString,"%d",readLightSensor(LIGHT_SENSOR));     mqttClient.publish("edison/LightSensor",msgString);         //  arm_alarm     sprintf(msgString,"%s", (arm_alarm == true)? "ARMED"  : "NOTARMED");     mqttClient.publish("edison/alarm_status", msgString);   }     if (toggleLED == true) {     digitalWrite(RED_LED, digitalRead(RED_LED) ^ 1);   }   delay(100); } 

. , , , , sensor.h sensor.cpp .

SECURE_MODE Arduino- . , mqttCallback(), , MQTT-. , , , . , , , .

– , IoT- . «edison/LED» , . «edison/motionLED» . , .

 // : sensors.h // #define USE_TMP036     0 #define RED_LED       10            //   #define GREEN_LED     11            //   #define BUTTON        13            //       10K #define PIR_SENSOR    12            //    #define LIGHT_SENSOR  A0            //   #define TEMP_SENSOR   A1            //   TMP36  LM35 #define MIN_PULSE_SEPARATION     200   //     #define ADC_STEPSIZE             4.61  //  ,     . #if (USE_TMP036 == 1) #define TEMP_SENSOR_OFFSET_VOLTAGE       750 #define TEMP_SENSOR_OFFSET_TEMPERATURE   25 #else // LM35 temperature sensor #define TEMP_SENSOR_OFFSET_VOLTAGE        0 #define TEMP_SENSOR_OFFSET_TEMPERATURE    0 #endif //   extern unsigned long          updateTime; //    extern volatile unsigned long activityMeasure; extern volatile unsigned long activityStart; extern volatile boolean       motionLED; extern unsigned long          resetActivityCounterTime; //   extern boolean                toggleLED; extern volatile unsigned long previousEdgeTime; extern volatile unsigned long count; extern volatile boolean       arm_alarm; float readTemperature(int analogPin); int   readLightSensor(int analogPin); void  buttonISR(); void  pirISR(); // : sensors.cpp #include <Arduino.h> #include "sensors.h" /***********************************************************************************    ,    ,     HIGH      ,   .   ,     HIGH  2-3 ,     LOW.        HIGH,       .               ************************************************************************************/ void pirISR() { int pirReading; unsigned long timestamp; timestamp = millis(); pirReading = digitalRead(PIR_SENSOR); if (pirReading == 1) {   //      activityStart = timestamp; } else {   int pulseWidth = timestamp-activityStart;   activityMeasure += pulseWidth; } //   ,    if (motionLED == true) {   digitalWrite(GREEN_LED, pirReading); } } /************************************************************************     ************************************************************************/ int readLightSensor(int sensorPin) { return analogRead(sensorPin); } /***********************************************************************        ***********************************************************************/ float readTemperature(int sensorPin) { int   sensorReading; float temperature; sensorReading = analogRead(sensorPin); //    temperature = sensorReading * ADC_STEPSIZE; //   LM35,  TMP036,   : // 10     //    LM35 – 0 ,  TMP036 - 750  //    LM35 – 0  ,  TMP036 – 25 . temperature = (temperature - TEMP_SENSOR_OFFSET_VOLTAGE)/10.0 +                TEMP_SENSOR_OFFSET_TEMPERATURE; //     temperature = temperature * 1.8 + 32.0;        return temperature; } /*************************************************************************     **************************************************************************/ void buttonISR() { //        ,    if ((millis()-previousEdgeTime) >= MIN_PULSE_SEPARATION) {   arm_alarm = !arm_alarm;   Serial.print("Alarm is: ");   if (arm_alarm == true) {     Serial.println("ARMED");   }   else {     Serial.println("NOT ARMED");   }   count++;   Serial.print("Count: "); Serial.println(count); } previousEdgeTime=millis(); } 

テスト䞭


, , MQTT- , , – , .

Edison SSH mosquitto_sub/pub . -, Mosquitto.
, .

, , :

 $> mosquitto_sub –h ipaddr –p 1883 –t edison/# -v 

ipaddr – IP- Intel Edison. Edison, IP- «localhost». , 1883. 1994, SSL-. 1995, PSK, . «edison/#» , .

, , «edison/LED», , «edison/motionLED», .

 $> mosquitto_pub –h ipaddr –p 1883 –t Edison/LED –m {H, L, B} $> mosquitto_pub –h ipaddr –p 1883 –t Edison/motionLED –m {ON, OFF} 

(H, L, B) , .
, , , , ON OFF.

, .

結論


比范的耇雑な゜フトりェアシステムMosquitto MQTTを䜿甚し、Intel Edisonボヌド䞊のLinuxプログラミングメカニズムを䜿甚しおスケッチから動䜜させる方法を孊びたした。同じ原理は、Arduinoプラットフォヌム甚に開発され、さたざたなセンサヌをサポヌトするように蚭蚈された倚くのラむブラリぞのアプロヌチを芋぀けるのに圹立ちたす。この堎合はArduinoプログラムの基盀であるLinuxを䜿甚するず、Linux甚に䜜成されたオヌプン゜ヌスパッケヌゞを簡単に䜿甚できたす。

Source: https://habr.com/ru/post/J283440/


All Articles