2011年9月16日金曜日

Arduino Ajax Web Server

MASHUP AWARDS 7 というコンテストが開催されています。
先日、その関連イベントの一つ(Mashup Camp in Tokyo)に参加しました。

Web のAPI はあまり馴染みがなかったのですが、なかなか面白そうです。
この技術をArduino のWeb サーバーに使えば、iPhone とArduino の連携手段として、有力なのではないでしょうか?

次のような手順で作成していきました。

1) GET (HTTP のGET) でArduino Server に値を渡せるようにする
2) XMLHttpRequest でページ遷移なしに値を取得できるようにする
3) JSON 形式で値を返すようにする
4) JSONP 形式で値を返すようにする

Arduino のプログラムは、IDE 標準サンプルの WebServer に少し手を加えただけです。
URL の末尾に付けるオプションに対応するのと、返すHTML データ(の中のJavaScript) に仕掛けがあります。



Arduino のプログラムはこちらです。
<新>http://djgj.sub.jp/TETRASTYLE/arduino/ajax_slim.txt
<旧>http://djgj.sub.jp/TETRASTYLE/arduino/Ajax_WebServer.txt

変更点(2015.10.21):
- Arduino.cc のIDE 1.6.5 に合わせた修正
- メモリ使いすぎだったので変数や関数名、値を短く変更
- "Access-Control-Allow-Origin: *" を追加
- JSONP からJSON に変更
- 外部ホストから操作するhtml のサンプルも追加→(サンプル)
  (Arduino サーバーのIP アドレスは 1) ページ埋め込み 2) ?host=xxx.xxx.xxx.xxx で渡す 3) ページ内のフォームで書き換える の3通り用意しました。

<説明は旧のまま>
Web ブラウザ(IE 未確認) からアクセスします。
サーバーのIPアドレス (標準では http://192.168.1.177/) にアクセスすると、動画のような画面になります。

JSON(P) でデータのみを取得する場合は
<-- data-blogger-escaped-br="" data-blogger-escaped-http:="">
返ってくる値
--> cb({"D":[D0,D1,D2,D3,D4,D5,D6,D7],"A":[A0,A1,A2,A3,A4,A5]});

デジタルポート(D0 - D7) のトグル(ON/OFF) は、各ポート毎、個別に送ります。(On と Off の指定はなく、現在の状態を反転します)
<-- data-blogger-escaped-btn="0<br" data-blogger-escaped-http:=""> <-- data-blogger-escaped-btn="1<br" data-blogger-escaped-http:=""> ...
<-- data-blogger-escaped-btn="7<br" data-blogger-escaped-http:="">

5 件のコメント:

  1. TETRASTYLEさん はじめまして
    とても分かりやすいブログで今更ながらいろいろ読ませていただいています。

    ところで、同じことをやりたくてArduinoをサーバーにしてデータの取得をするためajaxから呼び出しているのですがどうしてもエラーが出ます。

    理由が分からないで悪戦苦闘していて、このページに行きあたり、早速入れてみましたがやはり同じエラーが出てデーターの取り出しができません。
    そのエラーはいかのメッセージです。
    jQuery1113045079727947027537_1444402173200 was not called
    ajax側のリストを見せていただくことはできませんか。

    すっかり困り果てているのでよろしくお願いします。

    返信削除
  2. とうはんさん はじめまして。だいぶ古い記事なので、いろいろと状況が変わっている様です。とりあえず、古いバージョンの 0023 ではコンパイル、実行できました。Mac のChrome では表示できるものの、Safari ではできず。iPhone (iOS9)もSafari はNG、Chrome はOKでした。 Arduino Version 1.x 系では多少の修正でビルドはできたものの、ブラウザからの表示はできませんでした。  やりたいことや機器の構成など、詳細を書いていただければ、アドバイスできることもあるかもしれませんが、、あまり早い返信ができないので、その点はご了承ください。

    返信削除
  3. TETRASTYLEさん、ご返事ありがとうございます。
    ご親切な申し出感謝します。

    状況をご説明します。
    Arduinoは純正Unoです。それにSunFounder(サンファウンダー) イーサネットシールド W5100を乗せています。MACアドレスは{0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xE0}でIPアドレスは192.168.0.80としました。

    Windows8.1のパソコンからUSBで接続しています。
    ArduinoのIDEは1.7.7です。
    パソコンからArduinoへは正常に書き込めました。

    おなじWindowsパソコンからhtmlでajaxを使ってネット経由でdataコマンドを送ると正常に動作します。
    なお同じajaxを他のパソコンのPHPファイルに送ると返ってきます。
    またブラウザのURLでhttp://192.168.0.80を開くとarduinoから返ってきます。

    今度はarduinoからの情報をパソコンに
    req = $.ajax({
    type:"GET",
    dataType:"json",
    url:url,
    data:"aaaa=bbbbb",
    async: true,
    timeout: 10000
    }).done(function(request,textStatus) {
    $("#done").val(textStatus+ " > " + request);
    }).fail(function(xhr, textStatus, errorThrown){
    $("#done").val(textStatus+ " > " + errorThrown);
    })
    として取り込もうとしましたが、全くデータが送られてきません。

    プレークポイントを設定して見ても全く何も送られて来てないようです。

    もしかするとクロスドメインの問題かと思ってajaxに
    headers: {
    'Access-Control-Allow-Origin': '*'
    },
    を入れてみましたが、関係ないようでした。

    datatypeはjson,jsonp,text,htmlなどやってみましたが、どれも反応なしです。
    asyncはfalseでもtrueでも返ってこないのは同じです。
    送られたdataはarduinoで認識しています。

    資料を見ても、ネットで検索してもこの部分に問題があると言う話は見あたらないので、私のプログラムかハードのどちらかに問題があると思っています。

    必要であればソースをお送りしますので、私にメールをいただければ返信でソースをお送りします。

    mythreelittlekittens@gmail.com
    ※@を半角にしてください。

    大変お手数をおかけしますが、何かお分かりのことがあれば教えてください。
    とうはん

    返信削除
    返信
    1. とうはんさん
      プログラム修正しました。
      根本的にArduino Uno(Atmega328p) で動かすにはRAM 不足だった様で、IDE のバージョンを新しくしたら、エラーがでていました。
      プログラムをスリムアップし、IDE1.6.5 (Arduino.cc版)で動作確認したものを記事中に掲載しました。

      また、Access-Control-Allow-Origin: *
      をヘッダで返すように変更し、戻り値もJSONP をやめJSON にし、外部HTML のサンプルも掲載しました。

      基本的にArduino 内のHTML だけで動作できるプログラムなので、外部HTMLの動作だけでよい場合は、
      if文の半分(normal HTTP access と書いてある側)が不要になるので、これより大幅に使用メモリを減らすことができます。

      ひとまず上記プログラム をご確認ください。

      不明点、コメントでは記載しづらい点がありましたら こちらにメールをお願いします。 m@djgj.jp

      削除
  4. TETRASTYLEさん、
    ありがとうございます。
    私にはちょっとレベルが高くて、理解するのにてこずっています。^ ^;;
    何度も読み返して、どうしてもわからないところを整理して
    またお聞きしたいと思います。

    でも、少しわかってきました。ありがとうございます。

    返信削除