HTTPプロトコルで構成したWEBサーバーを搭載したマイコンシステム【STM32Nucleo】

マイコンにTCPサーバーが搭載されていればHTTPプロトコルで構成したWEBサーバーに発展させることは容易です。WEBサーバーを搭載したシステムの利点は、ブラウザからアクセスできるためにPC、スマホ等どの端末からも専用アプリをインストールしなくても通信でき遠隔操作管理等のIoT化を容易に実現できることです。

今回はNUCLEO-F103RBのようなメモリの小さいマイコンに最低限の機能をもったWEBサーバーを搭載してみます。

WiFiモジュールESP32のときもWEBサーバーを扱ったのですが、メーカー提供のHTTPドライバフォーマットに従っただけのため、プロトコル内容は意識せずともブラウザからアクセスできました。今回は一般的なHTTPプロトコルの知識をもってより自由度の高い簡易的なサーバーを構築したいと思います。

HTTPプロトコルとは

めかのとろ

これに関しては解説記事が世に溢れているため、詳細解説はここではあえてしません。マイコンでWEBサーバーを構成するにあたってつまずきやすいポイントにしぼって最低限必要な知識の要点をまとめるように努めています。

めかのとろ

HTTPはTCPの上位にあるプロトコルでHTTPリクエストHTTPレスポンスと呼ばれるHTTPメッセージでやり取りしているのですが、目に見えない水面下ではTCPによるデータ通信を行っています

ポイント

HTTPはブラウザなどのクライアントからリクエストをうけてサーバーがレスポンスを返すプロトコです。すなわち、サーバーはデータが定期的に更新されてもクライアントからのリクエストがない限りデータを返すことはありません

マイコンに搭載するWEBサーバー

めかのとろ

通常、WEBサーバーファイルシステムをもっているコンピュータシステムにHTMLで記述したページ、CGIプログラム、さらに画像ファイル等を保存しておき、クライアントからの指示に従ってページを渡したり、プログラムを実行したりブラウザへ応答するものです。

ファイルシステムをもつWEBサーバー
めかのとろ

対して、ファイルシステムを持たないマイコンの場合はサーバーは個々のファイルが作成できないために、かわりにすべてのデータを静的な文字列にコード化(ハードコーディング)して配列に格納して文字列の送信でブラウザに表示させます。 

めかのとろ

ファイルシステムがないサーバーは画像ファイルが扱えないために、見た目のシンプルな簡易的なものに限られますが、最低限の機能でもブラウザからマイコンにアクセスできてリモート管理等できることは大きな意義があります。

ファイルシステムがないマイコンのWEBサーバー
ポイント

マイコンはブラウザへHTMLファイルをハードコーディングして配列に格納したものを送信します。HTMLファイルは基本的には静的なファイルなのですが、動的な数値などを結合したり、スクリプトファイルを埋め込んで実行することもできます。

HTTPフォーマット

めかのとろ

HTTPWEB専用ブラウザとサーバの間でやりとりするプロトコルです。クライアントであるブラウザがリクエストメッセージ(要求メッセージ)をだしてWEBサーバーはレスポンスメッセージ(応答メッセージ)を返します。

めかのとろ

HTTPプロトコルテキストで記述したヘッダーを送受信したいデータに加えたフォーマットになっています。

 ① HTTPリクエスト 

HTTPリクエストの一行目はリクエストラインメソッドを含んだコマンドラインのような情報を含んでいます。
メッセージヘッダが続いてブラウザの種類やデータのタイプ等情報を伝えています。
空行を入れることでヘッダの終了を伝え、続いてメッセージボディに伝えたいデータを格納します。空の場合もあります。

めかのとろ

下のコードはアクセスしたいWEBサーバーのURLをブラウザから入力したときのリクエストメッセージです。一行目はリクエストラインでメソッドGETから始まりアクセスしたいURL等が続きます。

めかのとろ

ついでメッセージヘッダでブラウザの情報を伝えています。このリクエストにはデータはありませんのでボディーは空です。

HTTPリクエスト
めかのとろ

上記コードはGETメソッドでURLが192.168.3.100:50000へのアクセスリクエストです。 URLにはアクセスしたいファイルのパス名まで入れることもありますが、省略したときはトップページのHTMLを要求していることになります。

めかのとろ

HTTPプロトコルの規定ポート番号80以外の場合にはポート番号を明記します。

 ② HTTPレスポンス 

HTTPレスポンスの一行目はステータスラインWEBサーバーの処理の結果を伝えます。
メッセージヘッダが続いてサーバーのソフトウェア情報や返信データタイプ、圧縮方法、渡すデータの長さなどを伝えます。
空行を経てメッセージボディにHTMLなどのデータを格納します。

めかのとろ

HTTPレスポンスにはWEBサーバーの情報を記述します。ヘッダ項目でHTMLで記述したページを送りたい場合はContent-Typetext/htmlとします。次のContent-Lengthはメッセージボディのデータ長を指定します。これらの設定はブラウザに内容を正しく表示する上で重要です。

HTTPレスポンス
めかのとろ

メッセージボディはHTMLで記述したページ等の内容です。上記のコードはマイコンからブラウザへHTMLをコード化(ハードコーディング)した文字列を送信した内容ファイルシステムでのHTMLファイルを送るのと同じものになります。

めかのとろ

ブラウザからの入力フォームで送信ボタンにGETメソッドを指定(method="get")しています。

HTTPメソッド

めかのとろ

HTTPメソッドとはクライアントがWEBサーバーに要求する処理のことで、数種類ありますがブラウザとマイコンとのやり取りでは主にGETメソッドPOSTメソッドの2種類を扱います。

めかのとろ

ブラウザがサーバーからHTMLファイルなどを取得する場合にはGETメソッドを、ブラウザからサーバーにデータを送信する場合はPOSTメソッドを使います。GETメソッドはPOSTメソッドのようにデータ送信にも使えますが、その場合はURLの後ろにデータを付けて送信します。

 ① GETメソッドによるWEBページアクセス 

めかのとろ

標準的なGETメソッドの用法です。ブラウザ(クライアント)はWEBページのURLを入力するとまずはじめにサーバーへTCP接続を要求します。

めかのとろ

サーバー側がクライアント側からのTCP接続要求を受け入れて接続(コネクション)が確立するとHTTPプロトコルでのやり取りがはじまります。

めかのとろ

ブラウザGETメソッドリクエストラインから始まるリクエストメッセージをサーバーに送信します。

WEBページアクセス時のリクエスト
めかのとろ

サーバーはGETリクエストを受けて次のレスポンスを返します

HTTP/1.1 200 OK

めかのとろ

ブラウザはGETリクエストの内容によりHTMLページを開いたり、指定されたファイルにアクセスします。

 ② GETメソッドによるデータ送信 

めかのとろ

GETメソッドを使ったデータ送信フォーマットです。ブラウザのアドレス欄にURL末尾に「?」をつけて「データ=xxx」を送ります。

GETメソッドによるデータ送信
めかのとろ

サーバーは下記のようなフォーマットでリクエストメッセージを受信データとして取得できますのでメソッド「GET」データ「ABC」処理して抽出すればよいだけです。

めかのとろ

GETメソッドによるデータの送信はとても簡単な方法ですが、URL欄に履歴が残るために機密データを送信するには問題があります。

GETメソッド送信リクエスト

 ③ POSTメソッドによるデータ送信 

めかのとろ

基本的にデータの送信にはPOSTメソッドを使います。GETメソッドとは違いブラウザの履歴は残りません。

めかのとろ

サーバーは下記のようなフォーマットでリクエストメッセージを受信データとして取得できます。データはリクエストヘッダが終了した空行のあとボディにあります。

めかのとろ

リクエストすべてを受信してからのメソッド「POST」ボディ内のデータ「ABC」処理して抽出することになるため、「GET」のときに比べて受信データ量は大きなものになります。

POSTメソッド送信リクエスト

マイコンへの実装

マイコンシステムにWEBサーバーを実装するときに重要なポイントをまとめました。

WEBサーバー搭載プログラム

めかのとろ

WEBサーバーを搭載してもプログラムの基本的な流れはTCPサーバーの時とあまり変わりません。送受信データにHTTPプロトコル特有の多少の尾ひれがつくのでその処理が追加になります。

めかのとろ

STM32マイコンにWEBサーバーを搭載したプログラム概要です。HTTPプロトコル特有の内容はモジュールhttp_server.cに記述しておき、ヘッダファイル http_server.h を読み込んでおきます。

めかのとろ

ここではサーバー内でのデータをブラウザで表示するデモ用プログラムとしてRTOSのタスクprvTask_monitorを一つ追加してその中でデータ値を1秒間に1カウントアップしています。

main HTTP server
ポイント

マイコンにWEBサーバーを実装するうえで重要なポイントはいくつかあるのですがとりわけ重要なものがメモリの扱いです。TCPサーバーとの違いは扱う文字列が長いことです。FreeRTOSを使用しているときは長い文字列を扱うタスクのスタック容量を大きめ(384ワード程度:最低1kバイト)に設定しておくことが重要です。

FreeRTOS【STM32学習向け】

WEBサーバーモジュール

めかのとろ

下のWEBサーバーモジュールは今回のデモ用WEBサーバーの中核となる部分です。ブラウザでURLを入力して起動するトップページは配列top_document[]の内容です。GETメソッドリクエストにデータが含まれない場合のページです。

めかのとろ

送信した文字列があらかじめ設定した文字列"ABC"と一致したときと不一致のときのメッセージを表示する別ページは配列top_document2[]の内容です。GETメソッドリクエストにデータが含まれる場合のページです。

WEBサーバーモジュール http_server.c
めかのとろ

HTMLファイルをコード化して配列に格納するにあたって最も重要なポイントは変化のない静的なコードと内容により異なるコード長データ"len_top_document"など動的なコードsprintf関数で結合しているところです。これを利用すると静的なファイルであるはずのHTMLが動的な要素を含んだページになります。

ポイント

ブラウザからのリクエストに対するレスポンスはここでは簡略化のため"HTTP/ 1.1 200 OK"に固定しています。厳密にはHTTPプロトコルではブラウザからのリクエストバージョンに整合したり、ステータスコードを状態に応じて割り当てたものを返します。

コラム

日本語の表示させるとブラウザで文字化けする場合はサーバー側で対処しておきます。上のコードでは文字コードをUTF-8からにUTF-8Nにしただけで解決できたのですが対処療法的なのでより根本的な解決方法を適用してください。

受信文字処理

めかのとろ

ブラウザからのリクエストメッセージにはGETやPOSTなどのメッセージおよびデータが含まれていますので、それらをまず正確に抽出する処理が必要です。これらはタスクprvTask_TCP内で処理を行っています。

めかのとろ

今回のデモプログラムではデータ送信にGETメソッドを使用しているために「GET」をコマンドとして受信した場合にリクエストデータなしデータ付きかで処理を分岐しています。

受信データ処理 cmd_string関数
ポイント

Nucleo-F103RBはメモリがあまり大きくないので、FreeRTOSにWEBサーバーを搭載する場合はFreeRTOSの設定ファイルFreeRTOSConfig.hのメモリ割り当てに関する部分は見直したほうがよいです。特にヒープサイズを指定するconfigTOTAL_HEAP_SIZEは使用するタスク数が少なければ小さく設定しても大丈夫です。動作する範囲で調整してください。

ブラウザとマイコンとの通信

めかのとろ

Nucleo-F103RBにWEBサーバーを搭載したところで実際にブラウザにURLのIPアドレスとポートを入力してアクセスしてみます。

めかのとろ

URLを入力するとサーバーとのコネクションが確立して以下のページに切替わります。配列top_document[]にコード化した内容です。 左下の数値はマイコン内で1秒毎にカウントアップしているデータを表示したものです。現在値を確認するにはブラウザを手動で更新します。

めかのとろ

以下のフォーム画面で文字を入力してGETメソッドでサーバーに送ります。文字"ABC"を入力して送信ボタン(Send)を押します。このボタンはGETメソッドに設定しています。

WEBサーバーTOPページ
コラム

入力文字を履歴にも残さない伏せ字にするにはHTMLの入力タグを<input type="text">から<input type="password">に変更するだけです。これを利用すると簡易にパスワード要求画面が作成できます。ただし、送信メソッドはPOSTにする必要がありますが。

めかのとろ

送信ボタンを押すとブラウザのアドレス欄にURL/?cmd=ABCが自動的に入り、ページが配列top_document2[]に格納したHTMLページに切替わります。入力した文字が“ABC”と一致すると下記のメッセージが表示されます。

入力文字列一致
めかのとろ

今度は"abc"を入力して送信ボタンを押すとブラウザのアドレス欄にURL/?cmd=abcが自動的に入り、ページが切替わります。入力した文字が“ABC”と不一致であると下記のメッセージが表示されます。

入力文字不一致
めかのとろ

以上、ブラウザからマイコンにアクセスして文字列を送信する様子とマイコンからのデータを表示することを確認しました。このデモプログラムは、機能は単純ですがこれらを自由自在に扱いこなせるとマイコンをブラウザからリモート管理することができる重要な要素を納めていますので是非実践してみてください。C言語で文字列を扱うトレーニングにもなります。

ポイント

サーバーからブラウザへ送られる数値は手動で更新していますが、HTMLのmeta refreshタグで自動更新することもできます。HTTPプロトコルは基本的にクライアントからリクエストしなければデータは更新できないのですが、リアルタイムで表示する方法として、server sent events(SSE)別のプロトコルであるWebSocketなどがあります。ファイルシステムを持たないマイコン搭載のWEBサーバーには敷居が高いので当面は自動更新で十分かと思います。

コラム

HTTPプロトコルを扱うためにはクライアントとサーバー間で実際にやりとりされている生のデータ(パケット)を確認しながら行うことが重要です。
"Fiddler"というフリーソフトはツールの一つでブラウザとマイコン間でやり取りするパケットをモニターできますのでプログラム開発やトラブルシュートに役に立ちます

コラム

ここまでくるとマイコンにファイルシステム搭載してWEBサーバーでプログラムを搭載した高度なものを実現したくなります。ファイルシステムさえあれば一般的なWEBサーバーの方法が採用できるのでかえって楽に高度なことができるので機会があれば挑戦したいと思います。