コンテンツにスキップ

ネットワークプロトコルソフトウェアマニュアル

1.HTTP/HTTPS

1.1. HTTP/HTTPSの概要

HTTP(Hyper Text Transfer Protocol、ハイパーテキスト転送プロトコル)は、インターネット上で最も広く使われているネットワークプロトコルです。クライアントとサーバー間のリクエストおよびレスポンスの標準であり、WWWサーバーからローカルへハイパーテキストを転送するための通信プロトコルです。

一方、HTTPS(Hyper Text Transfer Protocol over SecureSocket Layer)は、セキュリティを目的としたHTTPチャネルであり、従来のHTTPをベースに通信の暗号化と身元認証(SSL/TLSセキュリティプロトコルの追加)を行うことで、通信プロセスにおける安全性を保証します。

1.1.1 HTTPとHTTPSの違い

HTTPとHTTPSの違いは以下の表の通りです。

プロトコルHTTPHTTPS
CA証明書不要必要
通信の暗号化方式平文通信、暗号化なしSSL/TLS暗号化通信
接続方式ポート番号 80 を使用ポート番号 443 を使用
接続状態ステートレス(無状態)SSL+HTTPプロトコルで構築された、暗号化通信および身元認証が可能なネットワークプロトコル

1.1.2 リクエストとレスポンス

典型的なHTTP/HTTPS通信は、ブラウザとWebサーバー間で行われます。ブラウザは「クライアント」として機能し、リクエストの送信、メッセージの受信、そして表示のレンダリングを担当します。Webサーバーは「サーバー」として機能し、リクエストへの応答、サーバーファイルの管理、具体的な業務処理を担当します。特定の状況下では、HTTPは情報交換のための通信ルールとして機能することもあります。

クライアントがリソースを必要とする際に送信するものが「リクエストメッセージ(Request)」であり、サーバーがリクエストを受信した後にクライアントへ返すものが「レスポンスメッセージ(Response)」です。HTTPでは、これらリクエストメッセージとレスポンスメッセージのフォーマットが規定されています。

リクエストメッセージフォーマット

リクエストメッセージフォーマット

リクエストメッセージのフォーマットは以下の通りです。

メッセージ要素説明
リクエスト行 (Request Line)リクエストメソッド: 一般的なメソッドは以下の通りです。

・GET: サーバーのリソースを検索・取得するために使用します。リクエスト内容はURL上に表示されます。

・POST: サーバー上にコンテンツを作成または更新するために使用します。リクエスト内容はURL上には表示されず、メッセージボディ(主体)内に含まれます。

URL: サーバーの仮想ファイルパスです。詳細は次のセクションで説明します。

レスポンスメッセージの主な構成要素は以下の通りです。

  • ステータス行: プロトコルバージョン、ステータスコード、ステータスフレーズを含みます。

  • レスポンスヘッダー: キーバリューペア(キーと値のペア)の形式で存在します(例:日時、データ型、データ長など)。

  • 空行: ヘッダーとボディを区別するための空行です。

  • レスポンスボディ (本文): Webページの場合は通常HTMLコードですが、音声・動画ファイルや画像の場合もあります。通常、ヘッダーの Content-Type で指定されます。

レスポンスメッセージフォーマット

レスポンスメッセージフォーマット

1.1.3 URL

ある環境モニタリングサーバーシステムを構築し、市内各観測点の環境データを収集・記録すると仮定します。パブリックネットワーク上のドメイン名を www.huanjin.com とし、サーバー内に2つのデバイスがあり、各デバイスに異なる日付の気温データが保存されているとします。クライアントが特定のデバイスの特定のデータを呼び出す際、サーバーに検索させるための一意のパスを送信する必要があります。この一意のパスが URL です。

環境モニタリングサーバーのURL構成例

環境モニタリングサーバーのURL構成例

URL(Uniform Resource Locator、統一資源位置指定子)は、リクエストメッセージのリクエスト行に配置され、道しるべの役割を果たします。Webページを閲覧して様々なコンポーネントをクリックすると、ブラウザは自動的に異なるURLを補完してくれます。完全なURLは、プロトコル部分URL(ドメイン)部分ファイルアドレスで構成されます。

URL構成要素の例

URL構成要素の例

具体的な内容は以下の通りです。

構成部分説明
プロトコル// で区切られます。一般的なものに http と https があります。
URL (ドメイン)パブリックネットワーク上で唯一無二のドメイン名です。
ファイルアドレスドメイン名の後の最初の / から、最後の / の前までの内容は「仮想ディレクトリ」と呼ばれます。

最後の / の後から # の前までが「ファイル名」となります。

例えば、環境モニタリングサーバーにある「デバイス1」の「12月25日」のデータを取得したい場合、GETリクエストを使用し、URLは http://www.huanjin.com/Device-1/日付データ/20211225 のようになります。

URLには変数情報(URLクエリストリング)を含めることも可能です。形式は以下の通りです。

Terminal window
https://www.Adblock.com/s?a=123&b=234

変数はURLの末尾に配置され、? で始まり、パラメータ名=値 のキーバリューペア形式で格納されます。複数のパラメータは & で区切られます。

1.1.4 HTTPS使用の要点

上記の説明から、HTTPSを使用する際は以下の点を常に意識する必要があります。

  • CA証明書: HTTPSプロトコルはSSL/TLSを使用します。

  • データ送信: POSTリクエストを使用し、サーバーアドレスはURL形式で表現します。

  • データ・ファイルの受信: GETリクエストを使用し、サーバーアドレスはURL形式で表現します。

当社の easyeai-api ソフトウェア・オープンソースライブラリは、複雑なメッセージフォーマットや送受信操作を統一的にカプセル化しており、お客様がシンプルで便利な呼び出し方法でHTTP/HTTPS通信機能を実現できるようにしています。

1.2. クイックスタート

1.2.1 開発環境の準備

このドキュメントを初めて読む場合は、『スタートガイド/開発環境の準備/Easy-Eaiコンパイル環境の準備と更新』を一読し、その手順に従ってコンパイル環境の構築を行ってください。

PC上のUbuntuシステムで run スクリプトを実行し、EASY-EAIコンパイル環境に入ります。詳細は以下の通りです。

Terminal window
cd ~/develop_environment
./run.sh 2204

1.2.2 ソースコードのダウンロードとサンプルのコンパイル

EASY-EAIコンパイル環境下で、ソースコードリポジトリを管理するディレクトリを作成します。

Terminal window
cd /opt
mkdir EASY-EAI-Toolkit
cd EASY-EAI-Toolkit

Demos.zip 上記のリンクから Demos.zip 圧縮ファイルをダウンロードし、仮想マシンの /opt/EASY-EAI-Toolkit ディレクトリにアップロードして解凍します。 対応するサンプルのディレクトリに移動し、コンパイル操作を実行します。具体的なコマンドは以下の通りです。

Terminal window
cd EASY-EAI-Toolkit-1126B/Demos/netProtocol-http/
./build.sh

💡 注意 : 依存ライブラリがボード上に配置されているため、クロスコンパイル中は必ず /mnt のマウントを維持してください。

HTTPサンプルのビルド結果

HTTPサンプルのビルド結果

1.2.3 サンプルの実行

シリアルデバッグまたはSSHデバッグを通じてボードのバックグラウンドに入り、サンプルが配置されている場所に移動します。以下の通りです。

Terminal window
cd /userdata/Demo/netProtocol-http

HTTPサンプルディレクトリ

HTTPサンプルディレクトリ

サンプルの実行コマンドは以下の通りです。

Terminal window
./test-http_server & ./test-http_client

1.2.4 実行結果

実行結果は以下のようになります。

HTTPサンプル実行結果

HTTPサンプル実行結果

1.3. HTTPSライブラリ関数の説明

本章では、EASY EAIのHTTPSライブラリ関数の使用方法について説明します。

1.3.1 インクルード/参照方法

EASY EAI api ライブラリは、本リポジトリの easyeai-api ディレクトリにあります。お客様がローカルプロジェクトで EASY EAI api ライブラリを直接呼び出せるように、プロジェクト内でリンクする必要があるライブラリやヘッダーファイル等を以下にリストアップしています。

説明CMakeでの記述Makefileでの記述
api.cmake${netProtocol_root}/http/api.cmake無し
ヘッダーファイルディレクトリ${HTTP_INCLUDE_DIRS}-I ../../easyeai-api/netProtocol/http
ソースファイルディレクトリ${HTTP_SOURCE_DIRS}../../easyeai-api/netProtocol/http
ライブラリファイルディレクトリ無し無し
ライブラリリンクパラメータ${HTTP_LIBS}無し

APIソースコードのパスは EASY-EAI-Toolkit-1126B/easyeai-api/netProtocol/http/ です。ユーザーはソースコードを通じてインターフェースの実装を確認でき、ソースコードを直接変更することも可能です。

1.3.2 証明書の設定

証明書を設定する関数のプロトタイプは以下の通りです。

Terminal window
void set_customer_crt(const char \*crt_file);

具体的な説明は以下の通りです。

関数名:set_customer_crt()詳細
ヘッダーファイルeasyeai-api/netProtocol/http/https_request.h
入力パラメータcrt_file:証明書のパス
戻り値無し
注意事項無し

1.3.3 HTTP/HTTPSサーバーへのform-dataデータの送信

1.3.3.1 form_dataキャッシュのクリア

キャッシュをクリアする関数のプロトタイプは以下の通りです。

Terminal window
void clear_multipart();

具体的な説明は以下の通りです。

関数名:clear_multipart()詳細
ヘッダーファイルeasyeai-api/netProtocol/http/https_request.h
入力パラメータ無し
戻り値無し
注意事項form-dataのキャッシュは1つしか存在しないため、どこで実行してもform-dataキャッシュは空になります。複数スレッドでこの関数を実行する場合は、スレッドの同期問題に注意してください。
1.3.3.2 form_dataキャッシュの追加 (パディング)

キャッシュを追加する関数のプロトタイプは以下の通りです。送信するデータはキーバリューペア形式で追加します。

Terminal window
void add_multipart_form_data(const char \*key, const char \*value);

具体的な説明は以下の通りです。

関数名:add_multipart_form_data()詳細
ヘッダーファイルeasyeai-api/netProtocol/http/https_request.h
入力パラメータkey: form-dataデータのキー名

value: form-dataデータの内容
戻り値無し
注意事項form-dataのキャッシュは1つしか存在しません。clear_multipart() を実行すると、それまでキャッシュに追加されたform-dataデータはすべてクリアされます。複数スレッドで実行する場合は、スレッドの同期問題に注意してください。
1.3.3.3 form-dataデータの送信

HTTPとHTTPSでは暗号化方式が異なるため、パラメータは同じですが2つの関数が定義されています。関数のプロトタイプは以下の通りです。

Terminal window
int32_t send_data_to_Http(const char *server, const char *func, char *result, uint32_t result_lenth);
int32_t send_data_to_Https(const char *server, const char *func, char *result, uint32_t result_lenth);

具体的な説明は以下の通りです。

HTTP送信関数:send_data_to_Http()
HTTPS送信関数:send_data_to_Https()
詳細
ヘッダーファイルeasyeai-api/netProtocol/https/https_request.h (※原文のまま記載)
入力パラメータserver: サーバーのURL

func: メソッド(パス/API名)

result: HTTP/HTTPSからの返答ボディデータを保存するバッファ

result_lenth: ボディデータ用にユーザーが割り当てたバッファの最大サイズ
戻り値-1: 失敗

0: 成功。関数内部で自動的に clear_multipart() が呼び出され、キャッシュがクリアされます。
注意事項このインターフェースはHTTP/HTTPS POSTリクエストをカプセル化したもので、form-dataのキャッシュを送信します。呼び出し成功後にキャッシュをクリアします。マルチスレッド環境では同期に注意してください。

1.3.4 HTTP/HTTPSサーバーへのJSONデータの送信

HTTPとHTTPSで暗号化方式が異なるため、それぞれ関数が定義されています(パラメータは同一です)。

Terminal window
int32_t send_json_to_Http(const char *server, const char *func, const char *json, char *result, uint32_t result_length);
int32_t send_json_to_Https(const char *server, const char *func, const char *json, char *result, uint32_t result_length);

具体的な説明は以下の通りです。

HTTP送信関数:send_json_to_Http()
HTTPS送信関数:send_json_to_Https()
詳細
ヘッダーファイルeasyeai-api/netProtocol/https/https_request.h
入力パラメータserver: サーバーのURL

func: メソッド(パス/API名)

json: 送信するJSON文字列

result: 返答ボディデータを保存するバッファ

result_lenth: ボディデータ用にユーザーが割り当てたバッファの最大サイズ
戻り値-1: 失敗

0: 成功
注意事項無し

1.3.5 HTTP/HTTPSサーバーからのファイル取得

HTTPとHTTPSで暗号化方式が異なるため、それぞれ関数が定義されています(パラメータは同一です)。

Terminal window
int32_t get_file_from_https(const char *url, const char *func, const char *filePath);
int32_t get_file_from_http(const char *url, const char *func, const char *filePath);

具体的な説明は以下の通りです。

HTTPファイル取得関数:get_file_from_https() (※原文のまま記載)
HTTPSファイル取得関数:get_file_from_http() (※原文のまま記載)
詳細
ヘッダーファイルeasyeai-api/netProtocol/https/https_request.h
入力パラメータurl: サーバーのURLパス

func: メソッド(パス)

filePath: 取得したファイルを保存するローカルパス
戻り値Success, Unknown, Connection, BindIPAddress, ReadWrite, ExceedRedirectCount, Canceled, SSLConnection, SSLLoadingCerts, SSLServerVerification, UnsupportedMultipartBoundaryChars, Compression など
注意事項このインターフェースはHTTP/HTTPS GETリクエストをカプセル化したものです。

1.4. 使用例

サンプルコードのパスは EASY-EAI-Toolkit-1126B/Demos/netProtocol-http/test-http_client.c です。

1.4.1 CRTキーファイル(証明書)の設定

キーファイルの設定操作は以下の通りです。

Terminal window
set_customer_crt("/userdata/customer.crt");

1.4.2 form_dataデータの送信

1.4.2.1 データの追加

form_dataデータバッファをクリアし、その後form_dataバッファにデータを追加します。

Terminal window
clear_multipart();
add_multipart_form_data("name", "gzlmo");
add_multipart_form_data("id", "888888");
add_multipart_form_data("pwd", "123456");
1.4.2.2 データの送信

送信操作は以下の通りです。

Terminal window
send_data_to_Http("192.168.3.191:50000", "/add", res, sizeof(res));

1.4.3 JSONデータの送信

JSONデータの送信操作は以下の通りです。

Terminal window
send_json_to_Http("192.168.3.191:50000", "/add", "{name : \\gzlmo\\}", res, sizeof(res));

2.MQTT

2.1. MQTTの概要

MQTT(Message Queuing Telemetry Transport)は、パブリッシュ/サブスクライブ(publish/subscribe)モデルに基づく「軽量」な通信プロトコルです。MQTTの最大の利点は、極めて少ないコードと限られた帯域幅で、リモートデバイスの接続に対してリアルタイムかつ信頼性の高いメッセージサービスを提供できることです。オーバーヘッドや帯域幅の消費が少ないインスタント通信プロトコルとして、IoT(モノのインターネット)、小型デバイス、モバイルアプリなどで広く応用されています。

2.1.1 パブリッシュとサブスクライブ

MQTTが採用しているパブリッシュ/サブスクライブのメッセージモデルは、1対多のメッセージ配信メカニズムを提供し、アプリケーション間の疎結合を実現します。これは、メッセージが送信側から受信側へ直接(ピアツーピアで)送信されるのではなく、MQTTサーバー(別名:MQTTブローカー)を介して配信されるメッセージ伝達モデルです。

  • MQTTの通信プロセスには、パブリッシャー(Publisher:発行者)ブローカー(Broker:仲介者)、サブスクライバー(Subscriber:購読者)の3つの役割が存在します。

  • MQTTで転送されるメッセージは、トピック(Topic)ペイロード(Payload)の2つの部分に分かれます。

MQTTパブリッシュ・サブスクライブモデル

MQTTパブリッシュ・サブスクライブモデル

パブリッシャーはブローカー(MQTT Broker)に対して特定のトピックのメッセージを発行し、ブローカーはそのトピックを購読しているすべてのサブスクライバーにメッセージをプッシュします。

  • メッセージを発行するクライアントがパブリッシャーであり、トピックのメッセージを購読するクライアントがサブスクライバーです。

2.1.2 サービス品質 (QoS: Quality of Service levels)

サービス品質はMQTTの重要な特性の一つです。TCP/IPを使用する場合、接続はある程度保護されています。しかし、ワイヤレスネットワークでは切断や干渉が頻繁に発生するため、MQTTのQoSレベルが情報の損失を防ぐのに役立ちます。

2.1.2.1 QoS 0

「最大1回(At most once)」。メッセージの配信は基盤となるTCP/IPネットワークに完全に依存します。メッセージの損失や重複が発生する可能性があります。このレベルは、環境センサーのデータなど、すぐに次のデータが送信されるため1回程度の記録漏れが問題にならない状況で使用されます。

MQTT QoS 0 通信フロー

MQTT QoS 0 通信フロー

2.1.2.2 QoS 1

「少なくとも1回(At least once)」。メッセージの到達を保証しますが、メッセージが重複して到達する可能性があります。

MQTT QoS 1 通信フロー

MQTT QoS 1 通信フロー

2.1.2.3 QoS 2

「正確に1回(Exactly once)」。メッセージが確実に1回だけ到達することを保証します。このレベルは、課金システムなど、メッセージの重複や損失が誤った結果を招く状況で使用されます。

MQTT QoS 2 通信フロー

MQTT QoS 2 通信フロー

  • 一意のメッセージIDを持つメッセージは、送信側と受信側の両方で保存されます。QoSレベル2は、送信側と受信側で2つのフローを必要とするため、ネットワーク上のオーバーヘッドが最も高くなります。

2.1.3 オープンソースプロジェクトの紹介

広く使用されておりコミュニティも活発なものとして、Eclipse Paho Cライブラリが現在最も一般的で人気のあるC言語用MQTTクライアントのオープンソースライブラリです。Windows、MAC、Linux、FreeRTOS、ESP32などのプラットフォームに適用可能です。

Ubuntuシステムでは、GitHubリポジトリを直接コンパイルして必要なライブラリやヘッダーファイルを取得することもできますが、以下のコマンドで直接インストールすることも可能です(この手順は省略可能です):

Terminal window
sudo apt-get update
sudo apt-get install libpaho-mqtt-dev

Paho Cはサポートするプラットフォームが充実しており互換性が高いという利点がありますが、【APIが低レイヤー寄り】であり、使い勝手が悪く、さらに独自のラップ処理(カプセル化)が必要になるという制限もあります。

そのため、本ドキュメントではEclipse傘下のもう一つのMQTTプロジェクトである mosquitto を採用します。このプロジェクトはリソースが限られた組み込みデバイスにより適しており、Paho Cほど網羅的ではありませんが基本要件を満たし、かつ非常に使いやすいのが特徴です。

Ubuntuシステムでは、以下のコマンドで関連する開発ライブラリを直接インストールできます:

Terminal window
sudo apt-get update
sudo apt-get install libmosquitto-dev

2.1.4 一般的な通信モデル

一般的な使用方法として、MQTT Server(ブローカー)プログラムをクラウドに展開し、ボード(開発ボード)がパブリッシャーおよびサブスクライバーとしてデータの送受信通信を行うモデルがあります。

MQTT通信モデル

MQTT通信モデル

ローカルネットワーク(LAN)内で使用したい場合は、PCプラットフォーム(Windows/Linux)上にMQTT Serverを展開し、ボードがパブリッシャーおよびサブスクライバーとして通信を行うこともできます。

例えば、Ubuntuシステムで以下のコマンドを実行し、MQTT Serverを展開できます:

Terminal window
sudo apt-get update
sudo apt-get install mosquitto
sudo systemctl start mosquitto

MQTT ServerをUbuntuの起動時に自動起動させたい場合は、以下のコマンドを追加で実行します:

Terminal window
sudo systemctl enable mosquitto

2.1.5 デモの説明

本ドキュメントでは、デモの解説を簡単にするため、【ブローカー】、【サブスクライバー】、【パブリッシャー】のすべてを【同一のボードデバイス上】に展開します。

まず、ボードの電源を入れ、ネットワークに接続します。次に、シリアルポートまたはSSHを通じてボードのバックグラウンドに入り、MQTT関連のリソースをインストールします:

Terminal window
sudo apt-get update
sudo apt-get install libmosquitto-dev mosquitto
sudo systemctl enable mosquitto && sudo systemctl start mosquitto

2.2. クイックスタート

2.2.1 開発環境の準備

このドキュメントを初めて読む場合は、『スタートガイド/開発環境の準備/Easy-Eaiコンパイル環境の準備と更新』を一読し、その手順に従ってコンパイル環境の構築を行ってください。

PC上のUbuntuシステムで run スクリプトを実行し、EASY-EAIコンパイル環境に入ります。

Terminal window
cd ~/develop_environment
./run.sh 2204

2.2.2 ソースコードのダウンロードとサンプルのコンパイル

EASY-EAIコンパイル環境下で、ソースコードリポジトリを管理するディレクトリを作成します。

Terminal window
cd /opt
mkdir EASY-EAI-Toolkit
cd EASY-EAI-Toolkit

Demos.zip 上記のリンクから Demos.zip 圧縮ファイルをダウンロードし、仮想マシンの /opt/EASY-EAI-Toolkit ディレクトリにアップロードして解凍します。 該当するサンプルのディレクトリに移動し、コンパイル操作を実行します。

Terminal window
cd EASY-EAI-Toolkit-1126B/Demos/netProtocol-mqtt/
./build.sh

MQTTサンプルのビルド結果

MQTTサンプルのビルド結果

💡 注意 : 依存ライブラリがボード上に配置されているため、クロスコンパイル中は必ず /mnt のマウントを維持してください。コンパイルに失敗し mosquitto.h が見つからないというエラーが出た場合は、1.5 デモの説明 の項を確認してください。

2.2.3 サンプルの実行

シリアルデバッグまたはSSHを通じてボードのバックグラウンドに入り、サンプルプログラムの場所に移動します。

Terminal window
cd /userdata/Demo/netProtocol-mqtt

MQTTサンプルディレクトリ

MQTTサンプルディレクトリ

まず、【サブスクライバー】プログラムを実行します:

Terminal window
./test-mqtt_subscription &

MQTTサブスクライバー起動結果

MQTTサブスクライバー起動結果

💡 注意 :実行に失敗し「Connection refused (接続拒否)」と表示された場合は、1.5 デモの説明 の項を確認してください。サブスクライバーはバックグラウンドで動作するため、再実行する場合は事前に kill コマンドでプロセスを終了させてください。

続いて、【パブリッシャー】プログラムを実行します:

Terminal window
./test-mqtt_publish

2.2.4 実行結果

実行結果として、パブリッシャーが送信したメッセージをサブスクライバーが正常に受信して出力する様子が確認できます

MQTT送受信実行結果

MQTT送受信実行結果

2.3. Mosquittoライブラリ関数の説明

本章では、本サンプルで使用する mosquitto ライブラリのインターフェースについて説明します。より詳細なAPIの説明については、公式サイトのAPIドキュメント (https://mosquitto.org/api/files/mosquitto-h.html) を参照してください。

2.3.1 参照方法

EASY EAI api ライブラリは、本リポジトリの easyeai-api ディレクトリにあります。プロジェクト内でリンクする必要があるライブラリやヘッダーファイル等は以下の通りです。

説明CMakeでの記述Makefileでの記述
api.cmake${netProtocol_root}/mqtt/api.cmake無し
ヘッダーファイルディレクトリ${MQTT_INCLUDE_DIRS}$SYSROOT/usr/include/
ソースファイルディレクトリ${MQTT_SOURCE_DIRS}無し
ライブラリファイルディレクトリ無し$SYSROOT/usr/lib/aarch64-linux-gnu/
ライブラリリンクパラメータ${MQTT_LIBS}-lmosquitto -lcrypto -lssl -lstdc++

APIソースコードのパスは EASY-EAI-Toolkit-1126B/easyeai-api/netProtocol/mqtt/ です。

2.3.2 Mosquittoライブラリの初期化

Terminal window
int mosquitto_lib_init(void);
項目詳細
関数名mosquitto_lib_init()
ヘッダーファイル$SYSROOT/usr/include/mosquitto.h
入力パラメータ無し
戻り値MOSQ_ERR_SUCCESS (0): 初期化成功

2.3.3 Mosquittoクライアントインスタンスの新規作成

Terminal window
struct mosquitto \*mosquitto_new(const char \*id, bool clean_session, void \*userdata);
項目詳細
関数名mosquitto_new(const char *id, bool clean_session, void *userdata)
ヘッダーファイル$SYSROOT/usr/include/mosquitto.h
入力パラメータid: クライアントの識別子(文字列)

clean_session: true の場合、切断時にセッション情報をクリアします。false の場合、セッション情報を保持します。

userdata: ユーザー定義データへのポインタ
戻り値struct mosquitto * (インスタンスへのポインタ)

2.3.4 接続コールバック関数の設定

ブローカーとの接続状態の変化を処理します。

Terminal window
void mosquitto_connect_callback_set(struct mosquitto \*mosq, void (\*on_connect)(struct mosquitto \*, void \*,int));
項目詳細
関数名mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int))
ヘッダーファイル$SYSROOT/usr/include/mosquitto.h
入力パラメータmosq: クライアントインスタンス

on_connect: 接続コールバック関数へのポインタ(戻り値 void、引数:クライアントインスタンス、ユーザーデータ、接続戻り値コード)

2.3.5 切断コールバック関数の設定

ブローカーとの切断イベントを処理します。

Terminal window
void mosquitto_disconnect_callback_set(struct mosquitto \*mosq, void (\*on_disconnect)(struct mosquitto \*, void \*, int));
項目詳細
関数名mosquitto_disconnect_callback_set(struct mosquitto *mosq, void (*on_disconnect)(struct mosquitto *, void *, int))
ヘッダーファイル$SYSROOT/usr/include/mosquitto.h
入力パラメータmosq: クライアントインスタンス

on_disconnect: 切断コールバック関数へのポインタ(戻り値 void、引数:クライアントインスタンス、ユーザーデータ、切断戻り値コード)

2.3.6 メッセージ発行コールバック関数の設定

メッセージがブローカーに正常に送信された際のイベントを処理します。

Terminal window
void mosquitto_publish_callback_set(struct mosquitto \*mosq, void (\*on_publish)(struct mosquitto \*, void \*, int));
項目詳細
関数名mosquitto_publish_callback_set(struct mosquitto *mosq, void (*on_publish)(struct mosquitto *, void *, int))
ヘッダーファイルnetProtocol-mqtt/include/mosquitto.h
入力パラメータmosq: クライアントインスタンス

on_publish: メッセージ発行コールバック関数へのポインタ(引数:クライアントインスタンス、ユーザーデータ、メッセージID)

2.3.7 購読(サブスクライブ)コールバック関数の設定

トピックの購読が成功した際のイベントを処理します。

Terminal window
void mosquitto_subscribe_callback_set(struct mosquitto \*mosq, void (\*on_subscribe)(struct mosquitto \*, void \*, int, int, const int \*));
項目詳細
関数名mosquitto_subscribe_callback_set(struct mosquitto *mosq, void (*on_subscribe)(struct mosquitto *, void *, int, int, const int *))
ヘッダーファイル$SYSROOT/usr/include/mosquitto.h
入力パラメータmosq: クライアントインスタンス

on_subscribe: コールバック関数ポインタ。引数は順に:クライアントインスタンス、ユーザーデータポインタ、メッセージID、成功したトピック数、QoSレベル配列。

2.3.8 指定したブローカーへの接続

Terminal window
int mosquitto_connect(struct mosquitto \*mosq, const char \*host, int port, int keepalive);
項目詳細
関数名mosquitto_connect(struct mosquitto *mosq, const char *host, int port, int keepalive)
ヘッダーファイル$SYSROOT/usr/include/mosquitto.h
入力パラメータmosq: クライアントインスタンス

host: ブローカーのアドレス

port: ブローカーのポート番号

keepalive: キープアライブ時間(秒)

2.3.9 トピックの購読 (サブスクライブ)

Terminal window
int mosquitto_subscribe(struct mosquitto \*mosq, int \*mid, const char \*sub, int qos);
項目詳細
関数名mosquitto_subscribe(struct mosquitto *mosq, int *mid, const char *sub, int qos)
ヘッダーファイル$SYSROOT/usr/include/mosquitto.h
入力パラメータmosq: クライアントインスタンス

mid: メッセージIDを格納する変数へのポインタ(NULL も可)

sub: 購読するトピック文字列

qos: 購読のQoSレベル
戻り値MOSQ_ERR_SUCCESS で成功、それ以外は失敗

2.3.10 指定トピックへのメッセージ発行 (パブリッシュ)

Terminal window
int mosquitto_publish(struct mosquitto \*mosq, int \*mid, const char \*topic, int payloadlen, const void \*payload, int qos, bool retain);
項目詳細
関数名mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain)
ヘッダーファイル$SYSROOT/usr/include/mosquitto.h
入力パラメータmosq: クライアントインスタンス

mid: メッセージID格納用ポインタ(NULL も可)

topic: 発行先トピック文字列

payloadlen: メッセージペイロードの長さ

payload: メッセージペイロードデータへのポインタ

qos: QoSレベル

retain: true の場合、メッセージを保持 (Retain) する
戻り値MOSQ_ERR_SUCCESS で成功、それ以外は失敗

2.3.11 ブローカーからの切断

Terminal window
void mosquitto_destroy(struct mosquitto \*mosq);
項目詳細
関数名mosquitto_disconnect(struct mosquitto *mosq)
ヘッダーファイル$SYSROOT/usr/include/mosquitto.h
入力パラメータmosq: クライアントインスタンス

2.3.12 Mosquittoクライアントインスタンスの破棄

Terminal window
void mosquitto_destroy(struct mosquitto \*mosq);
項目詳細
関数名mosquitto_destroy(struct mosquitto *mosq)
ヘッダーファイル$SYSROOT/usr/include/mosquitto.h
入力パラメータmosq: クライアントインスタンス

2.3.13 Mosquittoライブラリ使用リソースのクリーンアップ

Terminal window
void mosquitto_lib_cleanup(void);
項目詳細
関数名mosquitto_lib_cleanup(void)
ヘッダーファイル$SYSROOT/usr/include/mosquitto.h
入力パラメータ無し

2.4. 使用例

  • 送信 (パブリッシュ) サンプルコードのパス:

EASY-EAI-Toolkit-1126B/Demos/netProtocol-mqtt/test-mqtt_publish.c

  • 購読 (サブスクライブ) サンプルコードのパス:

EASY-EAI-Toolkit-1126B/Demos/netProtocol-mqtt/test-mqtt_subscription.c

3.MODBUS

3.1. MODBUSの概要

MODBUSは、異なる種類のバスやネットワークを介して接続されたデバイス間でクライアント/サーバー通信を行うためのアプリケーション層メッセージ転送プロトコルです。Modbusが他の通信プロトコルよりも広く使用されている主な理由は、公に発表されており著作権の要求がないこと、展開と保守が容易であること、そしてベンダーにとってローカルなビットやバイトの移動を変更する際の制限が少ないためです。

3.1.1 プロトコルバージョンと内容

現在、Modbusプロトコルには、シリアルポート、イーサネット、およびその他のインターネットプロトコルをサポートするネットワーク用のバージョンが存在します。

ほとんどのModbusデバイスは、シリアルEIA-485物理層を介して通信します。シリアル接続には2つのバリエーションがあり、数値データの表現方法とプロトコルの詳細がわずかに異なります。MODBUSモードは3つのカテゴリに分けられます。1つはRTU(リモート端末装置)モード、もう1つはASCII(米国情報交換標準暗号)モード、そして3つ目はTCP(イーサネット上で動作するプロトコル)モードです。

  • Modbus RTU:バイナリでデータを表現するコンパクトな方式です(Modbusプロトコルで規定されており、デフォルトモードはRTUでなければならず、ASCIIはオプションです)。

  • Modbus ASCII:人間が読める冗長な表現方式です。

これら2つのバリエーションはどちらもシリアル通信(serial communication)を使用します。TCP/IP(イーサネットなど)を介した接続には、複数のModbus/TCPのバリエーションが存在し、この方式ではチェックサムの計算は必要ありません。これら3つの通信プロトコルはすべて、データモデルと関数呼び出しにおいて同一であり、カプセル化の方法のみが異なります。

3.1.2 通信とデバイス

Modbusプロトコルはマスター/スレーブ(master/slave)アーキテクチャのプロトコルです。1つのノードがマスターノードであり、Modbusプロトコルを使用して通信に参加する他のノードはスレーブノードです。各スレーブデバイスは一意のアドレスを持ちます。シリアルネットワークおよびMB+ネットワークでは、マスターノードとして指定されたノードのみがコマンドを開始できます(イーサネット上では、どのデバイスもModbusコマンドを送信できますが、通常は1つのマスターノードデバイスのみがコマンドを開始します)。

Modbusコマンドには、実行対象となるデバイスのModbusアドレスが含まれます。すべてのデバイスがコマンドを受信しますが、指定されたアドレスのデバイスのみがコマンドを実行し、応答します(アドレス0は例外であり、アドレス0を指定したコマンドはブロードキャストコマンドです。コマンドを受信したすべてのデバイスが実行しますが、応答はしません)。すべてのModbusコマンドには、到達したコマンドが破損していないことを確認するためのチェックコードが含まれています。基本的なModbusコマンドは、RTUにそのレジスタの特定の値を変更させたり、I/Oポートを制御または読み取ったり、デバイスにそのレジスタ内の1つまたは複数のデータを送り返すように指示することができます。

3.1.3 MODBUS使用の要点

以上の説明から、Modbusを使用する際は常に以下の点に注意する必要があります。

  • Modbusはマスター・スレーブ方式の通信であり、非同期に通信することはできません。

  • マスターが送信しなければ、バス上にデータ通信は発生しません。

  • デバイスはRTUプロトコルをサポートしている必要があります(これはModbusプロトコル上の規定です)。

  • 基本的なフローは以下の通りです。

    • 送信:スレーブアドレス + ファンクションコード + レジスタアドレス + レジスタアドレスの数 + チェックコード

    • 応答:スレーブアドレス + ファンクションコード + マスターに送信するデータのバイト数 + データ + チェックコード

当社のeasyeai-apiソフトウェアオープンソースライブラリは、複雑なメッセージフォーマットや送受信操作を統合的にカプセル化し、お客様がシンプルで便利な呼び出し方法でModbus通信機能を実現できるようにしています。

3.2. クイックスタート

3.2.1 開発環境の準備

PC側のUbuntuシステムでrunスクリプトを実行し、EASY-EAIコンパイル環境に入ります。具体的な手順は以下の通りです。

Terminal window
cd ~/develop_environment
./run.sh 2204

3.2.2 ソースコードのダウンロードとサンプルプログラムのコンパイル

EASY-EAIコンパイル環境で、ソースコードリポジトリを保存する管理ディレクトリを作成します。

Terminal window
cd /opt
mkdir EASY-EAI-Toolkit
cd EASY-EAI-Toolkit

Demos.zip 上記のリンクから Demos.zip 圧縮ファイルをダウンロードし、仮想マシンの /opt/EASY-EAI-Toolkit ディレクトリにアップロードして解凍します。

対応するサンプルプログラムのディレクトリに移動し、コンパイル操作を実行します。具体的なコマンドは以下の通りです。

Terminal window
cd EASY-EAI-Toolkit-1126B/Demos/netProtocol-modbus/
./build.sh

💡 注意 : 依存ライブラリがボード上に配置されているため、クロスコンパイルのプロセス中は必ず /mnt マウントを保持してください。

MODBUSサンプルのビルド結果

MODBUSサンプルのビルド結果

3.2.3 サンプルプログラムの実行

シリアルデバッグまたはsshデバッグを通じてボードのバックグラウンドに入り、サンプルプログラムが展開されている場所に移動します。以下の通りです。

Terminal window
cd /userdata/Demo/netProtocol-modbus

MODBUSサンプルディレクトリ

MODBUSサンプルディレクトリ

サンプルプログラムを実行するコマンドは以下の通りです。

Terminal window
./test-modbus_tcp_master & ./test-modbus_tcp_slave

3.2.4 実行結果

TCPモードの実行結果は以下のようになります。

MODBUS TCP実行結果

MODBUS TCP実行結果

RTUモードに変更する必要がある場合は、コードを自身で変更できます。

  • コードパス:EASY-EAI-Toolkit-1126B/Demos/netProtocol-modbus/test-modbus_tcp_slave.c

MODBUS RTUコード変更箇所

MODBUS RTUコード変更箇所

APIの詳細な説明およびAPIの呼び出し(このサンプルプログラムのソースコード)については、以下の説明を参照してください。

3.3. MODBUSライブラリ関数の説明

本章では、EASY EAIのMODBUSライブラリ関数の使用方法を紹介します。

3.3.1 引用(インクルード)方法

EASY EAI apiライブラリは、本リポジトリの easyeai-api ディレクトリにあります。お客様がローカルプロジェクトで当社のEASY EAI apiライブラリを直接呼び出せるように、プロジェクトでリンクする必要のあるライブラリやヘッダーファイル等を以下にリストアップします。

説明CMakeでの記述Makefileでの記述
api.cmake${netProtocol_root}/modbus/api.cmake無し
ヘッダーディレクトリ${MODBUS_INCLUDE_DIRS}-I ../../easyeai-api/netProtocol/modbus
ソースディレクトリ${MODBUS_SOURCE_DIRS}../../easyeai-api/netProtocol/modbus
ライブラリディレクトリ無し無し
リンクパラメータ${MODBUS_LIBS}無し

APIのソースコードパスは EASY-EAI-Toolkit-1126B/easyeai-api/netProtocol/modbus/ です。ソースコードを通じてインターフェースの実装を確認したり、ソースコードを変更したりすることも可能です。

3.3.2 インスタンスの作成

TCP方式でModbusインスタンスを作成し、初期化します。

Terminal window
modbus_t\* modbus_new_tcp(const char \*ip, int port);
関数名:modbus_new_tcp()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータip:IPアドレス

port:ポート番号
戻り値成功:Modbusインスタンス

失敗:NULL
注意事項無し

3.3.3 スレーブIDの設定

スレーブIDを設定する関数のプロトタイプは以下の通りです。

Terminal window
void modbus_set_slave(modbus_t \*ctx, int slave);
関数名:modbus_set_slave()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータctx:Modbusインスタンス

slave:スレーブID
戻り値成功:0

失敗:-1
注意事項無し

3.4 スレーブとの接続

スレーブと接続を確立する関数のプロトタイプは以下の通りです。

Terminal window
void modbus_connect(modbus_t \*ctx);
関数名:modbus_connect()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータctx:Modbusインスタンス
戻り値成功:0

失敗:-1
注意事項無し

3.4.1 レジスタ操作(ファンクションコード対応関数)

3.4.1.1 コイル状態の読み取り(ファンクションコード:0x01)

連続する複数のコイル状態を読み取ることができます。

Terminal window
int modbus_read_bits(modbus_t \*ctx, int addr, int nb, uint8_t \*dest);
関数名:modbus_read_bits()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータctx:Modbusインスタンス

addr:レジスタ開始アドレス

nb:レジスタ数

dest:取得した状態値
戻り値読み取ったレジスタ数(失敗時は-1)
注意事項無し
3.4.1.2 入力状態の読み取り(ファンクションコード:0x02)

連続する複数の入力状態を読み取ることができます。

Terminal window
int modbus_read_input_bits(modbus_t \*ctx, int addr, int nb, uint8_t \*dest);
関数名:modbus_read_input_bits()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータctx:Modbusインスタンス

addr:レジスタ開始アドレス

nb:レジスタ数

dest:取得した状態値
戻り値成功:nb の値を返す(失敗時は-1)
注意事項無し
3.4.1.3 保持レジスタの読み取り(ファンクションコード:0x03)

連続する複数の保持レジスタの値を読み取ることができます。

Terminal window
int modbus_read_registers(modbus_t \*ctx, int addr, int nb, uint16_t \*dest);
関数名:modbus_read_registers()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータctx:Modbusインスタンス

addr:レジスタ開始アドレス

nb:レジスタ数

dest:取得したレジスタの値
戻り値成功:読み取ったレジスタの数

失敗:-1
注意事項無し
3.4.1.4 入力レジスタの読み取り(ファンクションコード:0x04)

連続する複数の入力レジスタの値を読み取ることができます。

Terminal window
int modbus_read_input_registers(modbus_t \*ctx, int addr, int nb, uint16_t \*dest);
関数名:modbus_read_input_registers()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータctx:Modbusインスタンス

addr:レジスタ開始アドレス

nb:レジスタ数

dest:取得したレジスタの値
戻り値成功:読み取ったレジスタの数

失敗:-1
注意事項無し
3.4.1.5 単一コイル状態の書き込み(ファンクションコード:0x05)
Terminal window
int modbus_write_bit(modbus_t \*ctx, int addr, int status);
関数名:modbus_write_bit()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータctx:Modbusインスタンス

addr:コイルアドレス

status:コイル状態
戻り値成功:0

失敗:-1
注意事項無し
3.4.1.6 複数の連続コイル状態の書き込み(ファンクションコード:15)
Terminal window
int modbus_write_bits(modbus_t \*ctx, int addr, int nb, const uint8_t \*src);
関数名:modbus_write_bits()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータctx:Modbusインスタンス

addr:コイル開始アドレス

nb:コイル数

src:書き込む複数のコイル状態
戻り値成功:0

失敗:-1
注意事項無し
3.4.1.7 単一レジスタの書き込み(ファンクションコード:0x06)
Terminal window
int modbus_write_register(modbus_t \*ctx, int addr, int value);
関数名:modbus_write_register()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータctx:Modbusインスタンス

addr:レジスタアドレス

value:レジスタの値
戻り値成功:0

失敗:-1
注意事項無し
3.4.1.8 複数の連続レジスタの書き込み(ファンクションコード:16)
Terminal window
int modbus_write_registers(modbus_t \*ctx, int addr, int nb, const uint16_t \*src);
関数名:modbus_write_registers()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータctx:Modbusインスタンス

addr:レジスタ開始アドレス

nb:レジスタ数

src:書き込む複数のレジスタの値
戻り値成功:0

失敗:-1
注意事項無し

3.4.2 ソケットのクローズ

ソケットを閉じる関数のプロトタイプは以下の通りです。

Terminal window
void modbus_close(modbus_t \*ctx);
関数名:modbus_close()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータctx:Modbusインスタンス
戻り値無し
注意事項無し

3.4.3 インスタンスの解放

インスタンスを解放する関数のプロトタイプは以下の通りです。

Terminal window
void modbus_free(modbus_t \*ctx);
関数名:modbus_free()詳細
ヘッダーファイルeasyeai-api/netProtocol/modbus/modbus.h
入力パラメータctx:Modbusインスタンス
戻り値無し
注意事項無し