最終更新2018年9月20日
スケッチは以下の通りです
/* * 20180918 T.Wanibe 7 * Ajax Web Server のコードをKeyStudio0304 * Ajexの勉強をしている。なかなかうまくゆかない * 専用シールドを設置してデバッグ。 * 最大32256バイトのフラッシュメモリのうち、スケッチが16756バイト(51%)を使っています。 * 最大2048バイトのRAMのうち、グローバル変数が735バイト(35%)を使っていて、ローカル変数で1313バイト使うことができます。 * 最大32256バイトのフラッシュメモリのうち、スケッチが16874バイト(52%)を使っています。 * 最大2048バイトのRAMのうち、グローバル変数が735バイト(35%)を使っていて、ローカル変数で1313バイト使うことができます。 * 最大32256バイトのフラッシュメモリのうち、スケッチが17342バイト(53%)を使っています。 * 最大2048バイトのRAMのうち、グローバル変数が749バイト(36%)を使っていて、ローカル変数で1299バイト使うことができます。 * */ #include <SPI.h> #include <Ethernet3.h> #include <Wire.h> #include <RTClib.h> #define HttpPort 80 #define LED1 5 #define LED2 6 #define LED3 7 #define BTN1 2 #define BTN2 3 boolean gflag=false; String parm; // 0 で消灯 1で点灯 int dout[3] ={0,0,0}; long int outDateTime; // Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network: const byte mac[] = {0x00,0x50,0xC2,0x97,0x2C,0x3D}; const byte ip[] = {192,168,0,198}; const byte subnet[] = {255,255,255,0}; const byte gateway[] = {192,168,0,1}; // Initialize the Ethernet server library // with the IP address and port you want to use // (port 80 is default for HTTP): EthernetServer server(HttpPort); RTC_DS3231 RTC; DateTime now; //-------------------------------------------------------------- void setup() { Serial.begin(115200); Serial.println(F("Start")); pinMode(LED1,OUTPUT);digitalWrite(LED1,dout[0]); pinMode(LED2,OUTPUT);digitalWrite(LED2,dout[0]); pinMode(LED3,OUTPUT);digitalWrite(LED3,dout[0]); pinMode(BTN1,INPUT_PULLUP); pinMode(BTN2,INPUT_PULLUP); // start the Ethernet connection and the server: Ethernet.begin(mac, ip); Serial.print(F("Server is at ")); Serial.println(Ethernet.localIP()); server.begin(); Wire.begin(); RTC.begin(); now = RTC.now(); outDateTime = (long int)now.year() * 10000 + now.month() * 100 + now.day(); Serial.print(F("Date: "));Serial.println(outDateTime); outDateTime = (long int)now.hour() * 10000 + now.minute() * 100 + now.second(); Serial.print(F("Time: "));Serial.println(outDateTime); } //-------------------------------------------------------------- void loop() { // listen for incoming clients EthernetClient client = server.available(); if (client) { // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); // serch parameter from "HTTP GET" if(gflag){ if(c != ' '){ parm += c; }else{ gflag = false; } } if(c == '?' && parm == ""){ gflag = true; } //Serial.print(c); // 改行コードか空行を受けたら返信 if (c == '\n' && currentLineIsBlank) { // 標準のhttp応答ヘッダーを送信する Serial.print(F("PreCheck: "));Serial.println(parm); if(parm == ""){ // normal HTTP access normalHttpAccess(client); }else{ // using XMLhttpObject access XMLhttpObjectAccess(client,parm); parm = ""; } break; } if (c == '\n') { // you're starting a new line currentLineIsBlank = true; } else if (c != '\r') { // you've gotten a character on the current line currentLineIsBlank = false; } } } // give the web browser time to receive the data delay(1); // close the connection: client.stop(); } } //-------------------------------------------------------------------------------------------------------- // 200 OK means the resource was located on the server and the browser (or service consumer) should expect a happy response void sendHttpResponseOk(EthernetClient client) { Serial.println(F("200 OK")); Serial.println(); // send a standard http response header client.println(F("HTTP/1.1 200 OK")); client.println(F("Content-Type: text/html")); client.println(F("Connnection: close")); // do not reuse connection client.println(); } //-------------------------------------------------------------------------------------------------------- // 404 means it ain't here. quit asking. void sendHttp404(EthernetClient client) { Serial.println(F("404 Not Found")); Serial.println(); client.println(F("HTTP/1.1 404 Not Found")); client.println(F("Content-Type: text/html")); client.println(F("Connnection: close")); // do not reuse connection client.println(); } //-------------------------------------------------------------------------------------------------------- //normal HTTP access void normalHttpAccess(EthernetClient client) { sendHttpResponseOk; client.println(F("<html lang='ja'>\n\t<head>\n\t\t<title>Arduino Ajax TEST</title>\n")); client.println(F("\t\t<meta charset='UTF-8' name='viewport' content='width=240px' />\n")); client.println(F("\t\t<script type='text/javascript'>\n")); client.println(F("\t\tfunction createXMLHttpRequest(cbFunc){\n")); client.println(F("\t\t\tvar XObj = new XMLHttpRequest();\n")); client.println(F("\t\t\tif(XObj) XObj.onreadystatechange = cbFunc;return XObj;\n\t\t}\n")); client.println(F("\t\tfunction setData(val){\n\t\t\thtObj = createXMLHttpRequest(displayData);\n")); client.println(F("\t\t\tif(htObj){\n\t\t\t\thtObj.open('GET','/?btn='+val,true);htObj.send(null);\n\t\t\t}\n\t\t}\n")); client.println(F("\t\tfunction getData(){\n\t\t\thtObj = createXMLHttpRequest(displayData);\n")); client.println(F("\t\t\tif(htObj){\n\t\t\t\thtObj.open('GET','/?=',true);htObj.send(null);\n\t\t\t}\n\t\t}\n")); client.println(F("\t\tfunction displayData(){\n\t\t\tif((htObj.readyState == 4) && (htObj.status == 200)){\n")); client.println(F("\t\t\tdocument.getElementById('result').innerHTML = htObj.responseText;\n\t\t\t}\n\t\t}\n")); client.println(F("\t\tfunction strT(){\n\t\t\tgetData(); timerID=setTimeout('strT()',document.getElementById('tf1').value);\n")); client.println(F("\t\t\tdocument.getElementById('btn100').value = 'STARTING';\n\t\t}\n")); client.println(F("\t\tfunction clrT(){\n\t\t\tclearTimeout(timerID);\n")); client.println(F("\t\t\tdocument.getElementById('btn100').value = 'START';\n\t\t}\n")); client.println(F("\t\t</script>\n\t</head>\n\t<body onLoad='getData()'>\n\t\t<form action='/' method='GET'><br />\n")); client.println(F("\t\t<input id='btn5' type='button' value=' D5 ' onClick='setData(0)'>\n")); client.println(F("\t\t<input id='btn6' type='button' value=' D6 ' onClick='setData(1)'>\n")); client.println(F("\t\t<input id='btn7' type='button' value=' D7 ' onClick='setData(2)'><br /><br />\n")); client.println(F("\t\t</form><form>\t\t<input id='btn100' type='button' value=' START ' onClick='strT()'>\n")); client.println(F("\t\t<input id='btn200' type='button' value=' STOP ' onClick='clrT()'>\n")); client.println(F("\t\t<input id='tf1' type='text' size='6' value='1000'>\n")); client.println(F("\t\t</form><br />\n\t\t<div id='result'></div><br />\n")); client.println(F("\t</body>\n</html>")); } //-------------------------------------------------------------------------------------------------------- //using XMLhttpObject access void XMLhttpObjectAccess(EthernetClient client,String parm) { int check = parm.indexOf('='); if(check != -1){ //Set Digital Port int check2 = parm.indexOf('btn'); if(check2 != -1){ int port = (parm.substring(check+1)).toInt(); Serial.print(F("Port="));Serial.println(port); dout[port] = !dout[port]; digitalWrite(port+5, dout[port]); } //Write JSONP Data (Digital & Analog Ports Status, Callback function name is 'cb') client.print(F("cb({DO:[")); for(int i=0; i<3; i++ ){ client.print(dout[i]); if(i<2){ client.print(","); } } client.print("],DI:["); client.print(digitalRead(2)); client.print(","); client.print(digitalRead(3)); client.print("],AI:["); for(int i=0; i<4; i++ ){ client.print(analogRead(i)); if(i<3){ client.print(","); } } client.print("],TIME:["); now = RTC.now(); outDateTime = (long int)now.hour() * 10000 + now.minute() * 100 + now.second(); Serial.print(F("Time: "));Serial.println(outDateTime); client.print(outDateTime); client.print("]});"); } }上記スケッチにはブラウザに送るHTMLのコードが含まれています。実際にブラウザで読み込んでコードを確認すればいいのですが一応示します。
<html lang='ja'> <head> <title>Arduino Ajax TEST</title> <meta charset='UTF-8' name='viewport' content='width=240px' /> <script type='text/javascript'> function createXMLHttpRequest(cbFunc){ var XObj = new XMLHttpRequest(); if(XObj) XObj.onreadystatechange = cbFunc;return XObj; } function setData(val){ htObj = createXMLHttpRequest(displayData); if(htObj){ htObj.open('GET','/?btn='+val,true);htObj.send(null); } } function getData(){ htObj = createXMLHttpRequest(displayData); if(htObj){ htObj.open('GET','/?=',true);htObj.send(null); } } function displayData(){ if((htObj.readyState == 4) && (htObj.status == 200)){ document.getElementById('result').innerHTML = htObj.responseText; } } function strT(){ getData(); timerID=setTimeout('strT()',document.getElementById('tf1').value); document.getElementById('btn100').value = 'STARTING'; } function clrT(){ clearTimeout(timerID); document.getElementById('btn100').value = 'START'; } </script> </head> <body onLoad='getData()'> <form action='/' method='GET'><br /> <input id='btn5' type='button' value=' D5 ' onClick='setData(0)'> <input id='btn6' type='button' value=' D6 ' onClick='setData(1)'> <input id='btn7' type='button' value=' D7 ' onClick='setData(2)'><br /><br /> </form><form> <input id='btn100' type='button' value=' START ' onClick='strT()'> <input id='btn200' type='button' value=' STOP ' onClick='clrT()'> <input id='tf1' type='text' size='6' value='1000'> </form><br /> <div id='result'></div><br /> </body> </html>
このスケッチだとSTARTボタンを押す事で1秒毎にEventが起きます。また、D5/6/7のボタンを押すとRequestをサーバに送りLEDの点消灯が出来ます。ネットワーク間のデータ量は殆ど無い事も判ります。
SDカードにアクセスしない事もあり、UNOの実装にはまだ余裕がありそうです。
オリジナルのスケッチの問題点を幾つか手直ししています。
- STARTを押したのかどうか判らない点の対策として、表示名称の変更をしています。START->STARING、
STOPボタンを押すと STARING->STARTとします。- STARTを押したときに指定時間間隔が正しいか確認出来るようにRTCを毎回Callするようにしてみました。
Ajaxを使うとPage更新をせずに表示内容を更新出来るのはとても意味があります。
ただ、実現するには結構敷居が高いです。Ajaxと云う方法論は、必ずしも1本化されているモノではないため、いろいろな実現方法が提供されています。そのため、ちょっとレタッチしようとするにも参考情報が混ざってしまい、ドツボに嵌まります。
少なくともJavaScriptの構文は理解しておく必要がありそうです。ExampleをレタッチしてCH数の変更や表現方法の変更(ボタン色の変更等々)したくともなかなか難しいです。
免責事項
本ソフトウエアは、あなたに対して何も保証しません。本ソフトウエアの関係者(他の利用者も含む)は、あなたに対して一切責任を負いません。
あなたが、本ソフトウエアを利用(コンパイル後の再利用など全てを含む)する場合は、自己責任で行う必要があります。本ソフトウエアの著作権はToolsBoxに帰属します。
本ソフトウエアをご利用の結果生じた損害について、ToolsBoxは一切責任を負いません。
ToolsBoxはコンテンツとして提供する全ての文章、画像等について、内容の合法性・正確性・安全性等、において最善の注意をし、作成していますが、保証するものではありません。
ToolsBoxはリンクをしている外部サイトについては、何ら保証しません。
ToolsBoxは事前の予告無く、本ソフトウエアの開発・提供を中止する可能性があります。
商標・登録商標
Microsoft、Windows、WindowsNTは米国Microsoft Corporationの米国およびその他の国における登録商標です。
Windows Vista、Windows XPは、米国Microsoft Corporation.の商品名称です。
LabVIEW、National Instruments、NI、ni.comはNational Instrumentsの登録商標です。
I2Cは、NXP Semiconductors社の登録商標です。
その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
すべての商標および登録商標は、それぞれの所有者に帰属します。