Arduino core for the ESP32のWebServerライブラリでGETコマンドの引数を取得するには

最終修正日:2021/2/8

Arduino core for the ESP32 にて、WebServerライブラリを使用するケースは大変多いです。ただ、サンプルスケッチを見ても、明らかにArduinoUno+EthernetShieldを使っていた頃のスケッチとはコーディングスタイルが異なるかと思います。

ブラウザ側からSubmitでサーバに返信したパラメータをサーバ側でどう処理するか、サンプルスケッチを漁っても適当なモノがなかなか見つかりませんでした。
やっとそれなりの結果が出たのでそのソースを残しておきます。

IPアドレスやSSID等々をEEPROM領域に保存し、それを一覧してレタッチし、『submit』で情報更新したときの処理となります。

『submit』を押すとURLバーの文字列が以下のようになります。

https://192.168.0.17/setup?SBM=1&DT1=24&DT2=a&DT3=c4&DT4=61&DT5=1e&DT6=7c&DT1=36&DT2=10&DT3=196&DT4=97&DT5=30&DT6=124&DT7=192&DT8=168&DT9=0&DT10=33&DT11=255&DT12=255&DT13=255&DT14=0&DT15=192&DT16=168&DT17=0&DT18=1&DT19=Kingsland&DT20=password&DT21=24&DT22=a&DT23=c4&DT24=61&DT25=1e&DT26=7d&DT21=36&DT22=10&DT23=196&DT24=97&DT25=30&DT26=125&DT27=192&DT28=168&DT29=250&DT30=33&DT31=255&DT32=255&DT33=255&DT34=0&DT35=192&DT36=168&DT37=250&DT38=1&DT39=ESP_AP&DT40=password

WS.on(“/setup”, handleSetUp);
でEvent判断し、handleSetUp()の中で引数内に“SBM”が有るかどうかで『submit』が押されたかどうか判断出来る事が判りました。
String型を使うと容易にパラメータを取り出すことが出来ますね。

/*
 * 20201019 T.Wanibe
 * SPIFFSをサポートし,WebPageからJavaScriptの読込先を外部に依存しないように変更してみた
 * ChartJSに馴れてきたこともあり、もう少しグラフ表示を凝ったモノにして見る。
 * 24時間更新に関し、更新した次のデータ枠をNULLにするようにした。更新位置を明確にするため
 * /setup 頁を作成 EEPROMに必要な情報を書き込むように変更
 * 『Indoor environment monitor』としてプロジェクトを更新
 * Chart.jsを作り込み強化
 * フラッシュの使用量が多少増えているが、まだまだ大丈夫そう
 * 1日分のデータバッファをサイクリックに使うことにした。そのため初期値をキチンと定義することにした。
 * データが無い場合はNULLにすることでグラフプロットが無くなることが判っているので対応した。
 * RootのHTML表示スタイルを更新した。
 * 時刻表示を追加して見ました。起動時にNTPサーバにアクセスし、時刻取得。ESP32内部のRTCに登録してOLCDに時刻表示する
 * ESP32のGPIOの一部のpinにはArduinoに用意されているanalogWrite()がありません。DACが存在するからかもしれません。
 * その代わりなのかLED_PWMという機能が用意されているようです。https://garretlab.web.fc2.com/arduino/lab/ledc/
 * この機能が利用できるPinは16個のようです。今回PO3(GPIO4)、PO4(GPIO2)が対象pinのようですので、改造してみました。
 * PWMによるLEDの明るさ調整ですが、単純に直線的な輝度制御は難しいですね
 * LEDの配置等を変更
 * OTAを維持したまま、モードをST+APにして普段はPCとの間でトランシーバモード、一方、ファーム更新はSTモードで実現出来ないか確認する
 * Adafruit_BME280.hがESP32でうまく動作しないため、ライブラリを変更し、BME280I2C.hを採用した
 * WebServer  on()の扱いをリファレンスで確認する必要があります。
 * https://garretlab.web.fc2.com/arduino/esp32/reference/libraries/WebServer/WebServer_on.html
 * この関数の為、WiznetのWebServer関数との整合性がとれない。 ESP32とSTM32の共存は難しそう
 * この記述はESP8266/32のみ
 * ※HTMLの記述にてString型を駆使して記述するが、その手法も多岐にわたる。好みの方法を確立しておく必要がある
 * 最大1310720バイトのフラッシュメモリのうち、スケッチが883486バイト(67%)を使っています。
 * 最大327680バイトのRAMのうち、グローバル変数が44048バイト(13%)を使っていて、ローカル変数で283632バイト使うことができます。
 * バイナリファイルは787kBですので上記スケッチサイズに合致します。
 * ブラウザからの転送はあっという間に完了します。
 */
#include <WiFi.h>
#include <time.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>
#include <SPIFFS.h>
#include <FS.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//#include <Adafruit_Sensor.h>
//#include <Adafruit_BME280.h>
#include <BME280I2C.h>
#include "arduino_secrets.h"                                            //機密データを「Secret」タブ/arduino_secrets.hに入力してください
#include <EEPROM.h>
#include "esp_system.h"                                                 //MACマックアドレスを読み込む
#define HTTPport        80
#define SCREEN_WIDTH    128                                             // OLED display width, in pixels
#define SCREEN_HEIGHT   64                                              // OLED display height, in pixels
#define OLED_RESET      -1                                              // Reset pin # (or -1 if sharing Arduino reset pin)
#define NUMFLAKES       10                                              // アニメーション例の雪片の数
#define LOGO_HEIGHT     16
#define LOGO_WIDTH      16
#define OLCDAres        0x3C                                            //0x3Cか0x3D
#define LED             13                                              //ボード上のLEDは使えないのでGPIO13にLEDを接続
#define AIport          A0
#define PO1             17
#define PO2             16
#define PO3             4
#define PO4             2
#define PI1             39
#define PI2             34
#define PI3             35
#define PI4             33
//#define BMEID         0x58
#define LEDC_CHANNEL_0  0                                               // use first channel of 16 channels (started from zero)
#define LEDC_CHANNEL_1  1                                               // use first channel of 16 channels (started from zero)
const char*     host            = "esp32";
char            ssid[16]        = SECRET_SSID;                          //ネットワークSSID(名前)
char            pass[16]        = SECRET_PASS;                          //ネットワークパスワード(WPAの使用、またはWEPのキーとして使用)
String          myID            = "admin";
String          myPASS          = "password";
//variabls for blinking an LED with Millis
unsigned long   previousMillis  = 0;                                    //LEDが最後に更新されたときに保存されます
const long      interval        = 1000;                                 //点滅する間隔(ミリ秒)
int             ledState        = LOW;                                  //LEDの設定に使用されるledState
unsigned        status;
//Station用
byte            mac[]           = {0x24,0x0A,0xC4,0x61,0x1E,0x7C};      //Espressif Inc この企業は60個ほど保有している模様
byte            apMac[]         = {0x24,0x0A,0xC4,0x61,0x1E,0x7D};      //mac+1になっている模様 実際には本体に問い合わせ
byte            ip[]            = {192, 168, 0, 33};
byte            gateway[]       = {192, 168, 0, 1};
byte            netmask[]       = {255, 255, 255, 0};
//SoftAP用
byte            apIp[]          = {192, 168, 250, 33};
byte            apGateway[]     = {192, 168, 250, 1};
byte            apNetmask[]     = {255, 255, 255, 0};
char            apSsid[16]      = "ESP_AP";                             //このSSIDが公開される。
char            apPassword[16]  = "password";                           //
char            buf1[128];
char            buf2[128];
char            buf3[128];
String          buf11           = "ABC";
String          buf22           = "DEF";
float           gDataBuf[7];                                            //現在は3要素いずれ7要素
float           gDayBuf[24][7];                                         //24時間分3要素データ
float           temp(NAN),hum(NAN),pres(NAN);                           // hum(NAN)は無効
int             brightness      = 0;
int             fadeAmount      = 25;
//const char*     ntpServer     ="ntp.jst.mfeed.ad.jp";                 //日本のNTPサーバー選択
const char*     ntpServer       ="192.168.0.206";                       //LocalTimeServer
const long      gmtOffset_sec   = 9 * 3600;                             //9時間の時差を入れる
const int       daylightOffset_sec = 0;                                 //夏時間はないのでゼロ
struct tm       timeinfo;
WebServer       WS(HTTPport);
//I2C(SDA、SCLピン)に接続されたSSD1306ディスプレイの宣言
Adafruit_SSD1306 OLCD(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
BME280I2C       bmp;                                                    // Default : forced mode, standby time = 1000 ms
                                                                        // Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,
struct st_esp {                                                         // EEPROMで利用する構造体を宣言
        char id;
        char DT[47];
        char ssid[16];
        char pass[16];
        char apSsid[16];
        char apPass[16];
};
const byte      ID = 0xA2;
//-------------- Style
String style =
"<style>\n"
        "\t#file-input,input{width:100%;height:44px;border-radius:4px;margin:10px auto;font-size:15px}\n"
        "\tinput{background:#f1f1f1;border:0;padding:0 15px}body{background:#17A1A5;font-family:sans-serif;font-size:14px;color:#777}\n"
        "\t#file-input{padding:0;border:1px solid #ddd;line-height:44px;text-align:left;display:block;cursor:pointer}\n"
        "\t#bar,#prgbar{background-color:#f1f1f1;border-radius:10px}#bar{background-color:#17A1A5;width:0%;height:10px}\n"
        "\tform{background:#fff;max-width:258px;margin:75px auto;padding:30px;border-radius:5px;text-align:center}\n"
        "\t.btn{background:#17A1A5;color:#fff;cursor:pointer}\n"
"</style>\n";
//-------------- Login page
String loginIndex = 
"<form name=loginForm>\n"
        "\t<h1>ESP32 Login</h1>\n"
        "\t<input name=userid placeholder='User ID'>\n"
        "\t<input name=pwd placeholder=Password type=Password>\n"
"<input type=submit onclick=check(this.form) class=btn value=Login>\n</form>\n"
"<script>\n"
        "\tfunction check(form) {\n"
                "\t\tif(form.userid.value== '" + myID + "' && form.pwd.value== '" + myPASS +"' )\n"
                        "\t\t\t{window.open('/serverIndex')}\n"
                "\t\telse\n"
                        "\t\t\t{alert('Error Password or Username')}\n"
        "\t}\n"
"</script>\n" + style;
//-------------- Server Index Page
String serverIndex = 
"<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>\n"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>\n"
        "\t<input type='file' name='update' id='file' onchange='sub(this)' style=display:none>\n"
        "\t<label id='file-input' for='file'>   Choose file...</label>\n"
        "\t<input type='submit' class=btn value='Update'>\n"
        "\t<br><br>\n"
        "\t<div id='prg'></div>\n"
        "\t<br><div id='prgbar'><div id='bar'></div></div><br>\n"
"</form>\n"
"<script>\n"
        "\tfunction sub(obj){\n"
                "\t\tvar fileName = obj.value.split('\\\\');\n"
                "\t\tdocument.getElementById('file-input').innerHTML = '   '+ fileName[fileName.length-1];\n"
        "\t};\n"
        "\t$('form').submit(function(e){\n"
                "\t\te.preventDefault();\n"
                "\t\tvar form = $('#upload_form')[0];\n"
                "\t\tvar data = new FormData(form);\n"
                "\t\t$.ajax({\n"
                        "\t\t\turl: '/update',\n"
                        "\t\t\ttype: 'POST',\n"
                        "\t\t\tdata: data,\n"
                        "\t\t\tcontentType: false,\n"
                        "\t\t\tprocessData:false,\n"
                        "\t\t\txhr: function() {\n"
                                "\t\t\t\tvar xhr = new window.XMLHttpRequest();\n"
                                "\t\t\t\txhr.upload.addEventListener('progress', function(evt) {\n"
                                        "\t\t\t\t\tif (evt.lengthComputable) {\n"
                                                "\t\t\t\t\t\tvar per = evt.loaded / evt.total;\n"
                                                "\t\t\t\t\t\t$('#prg').html('progress: ' + Math.round(per*100) + '%');\n"
                                                "\t\t\t\t\t\t$('#bar').css('width',Math.round(per*100) + '%');\n"
                                        "\t\t\t\t\t}\n"
                                "\t\t\t\t}, false);\n"
                                "\t\t\t\treturn xhr;\n"
                        "\t\t\t},\n"
                        "\t\t\tsuccess:function(d, s) {\n"
                                "\t\t\t\tconsole.log('success!')\n"
                        "\t\t\t},\n"
                        "\t\t\terror: function (a, b, c) {\n"
                        "\t\t\t}\n"
                "\t\t});\n"
        "\t});\n"
"</script>\n" + style;
//------------ fileNotFound
String fileNotFound = 
"<html><head>\n"
        "\t<title>ESP32 : 404 Not Found</title>\n"
"</head><body>\n"
        "\t<center><h1>ESP32 404 : Not Found</h1></center>\n"
        "\t<p>The requested URL was not found on this server.</p>\n"
"</body></html>\n";
//------------
void handleGetData() {
        gDataBuf[6]     =       analogRead(A0);
        gDataBuf[1]     =       temp;
        gDataBuf[0]     =       pres;
        WS.send(200, "text/html", SendHTML(gDataBuf));         //Send ADC value only to client ajax request
}
//------------
void handleNotFound(){
        if (!handleFileRead(WS.uri())) {
                //  ファイルが見つかりません
                Serial.println(F("404 not found"));
                WS.send(404, "text/html",fileNotFound);
        }
}
//------------SPIFSS のファイルをクライアントに転送する
bool handleFileRead(String path) {
        Serial.println("handleFileRead: trying to read " + path);
        // パス指定されたファイルがあればクライアントに送信する
        if (path.endsWith("/")) path += "index.html";
                String contentType = getContentType(path);
                if (SPIFFS.exists(path)) {
                        Serial.println("handleFileRead: sending " + path);
                        File file = SPIFFS.open(path, "r");
                        WS.streamFile(file, contentType);
                        file.close();
                        Serial.println("handleFileRead: sent " + path);
                        return true;
        }else {
                Serial.println(F("handleFileRead: 404 not found"));
                WS.send(404, "text/html",fileNotFound);
                return false;
        }
}
//------------
void handleSetUp(){
        if(WS.hasArg("SBM")){                                           //引数に"SBM=1"が含まれていることを確認
                Serial.println(F("SetUp?"));
                int bufSize = sizeof(st_esp);
                EEPROM.begin(bufSize);                                  //構造体のサイズ設定
                st_esp  buf;
                String cmd1,cmd2,cmd3,cmd4,str1,str2;
                cmd1            = WS.arg("DT7");
                buf.DT[6]       = char(cmd1.toInt());
                cmd2            = WS.arg("DT8");
                buf.DT[7]       = char(cmd2.toInt());
                cmd3            = WS.arg("DT9");
                buf.DT[8]       = char(cmd3.toInt());
                cmd4            = WS.arg("DT10");
                buf.DT[9]       = char(cmd4.toInt());
                Serial.println("IP="+cmd1+"."+cmd2+"."+cmd3+"."+cmd4);
                cmd1            = WS.arg("DT11");
                buf.DT[10]      = char(cmd1.toInt());
                cmd2            = WS.arg("DT12");
                buf.DT[11]      = char(cmd2.toInt());
                cmd3            = WS.arg("DT13");
                buf.DT[12]      = char(cmd3.toInt());
                cmd4            = WS.arg("DT14");
                buf.DT[13]      = char(cmd4.toInt());
                Serial.println("MASK="+cmd1+"."+cmd2+"."+cmd3+"."+cmd4);
                cmd1            = WS.arg("DT15");
                buf.DT[14]      = char(cmd1.toInt());
                cmd2            = WS.arg("DT16");
                buf.DT[15]      = char(cmd2.toInt());
                cmd3            = WS.arg("DT17");
                buf.DT[16]      = char(cmd3.toInt());
                cmd4            = WS.arg("DT18");
                buf.DT[17]      = char(cmd4.toInt());
                Serial.println("GW="+cmd1+"."+cmd2+"."+cmd3+"."+cmd4);
                str1            = WS.arg("DT19");
                str1.toCharArray(buf.ssid, 16);
                Serial.println("SSID="+str1);
                str2            = WS.arg("DT20");
                str2.toCharArray(buf.pass, 16);
                Serial.println("PASSWORD="+str2);
                //
                cmd1            = WS.arg("DT27");
                buf.DT[26]      = char(cmd1.toInt());
                cmd2            = WS.arg("DT28");
                buf.DT[27]      = char(cmd2.toInt());
                cmd3            = WS.arg("DT29");
                buf.DT[28]      = char(cmd3.toInt());
                cmd4            = WS.arg("DT30");
                buf.DT[29]      = char(cmd4.toInt());
                Serial.println("AccessPoint IP="+cmd1+"."+cmd2+"."+cmd3+"."+cmd4);
                cmd1            = WS.arg("DT31");
                buf.DT[30]      = char(cmd1.toInt());
                cmd2            = WS.arg("DT32");
                buf.DT[31]      = char(cmd2.toInt());
                cmd3            = WS.arg("DT33");
                buf.DT[32]      = char(cmd3.toInt());
                cmd4            = WS.arg("DT34");
                buf.DT[33]      = char(cmd4.toInt());
                Serial.println("AccessPoint MASK="+cmd1+"."+cmd2+"."+cmd3+"."+cmd4);
                cmd1            = WS.arg("DT35");
                buf.DT[34]      = char(cmd1.toInt());
                cmd2            = WS.arg("DT36");
                buf.DT[35]      = char(cmd2.toInt());
                cmd3            = WS.arg("DT37");
                buf.DT[36]      = char(cmd3.toInt());
                cmd4            = WS.arg("DT38");
                buf.DT[37]      = char(cmd4.toInt());
                Serial.println("AccessPoint GW="+cmd1+"."+cmd2+"."+cmd3+"."+cmd4);
                str1            = WS.arg("DT39");
                str1.toCharArray(buf.apSsid, 16);
                Serial.println("AccessPoint SSID="+str1);
                str2            = WS.arg("DT40");
                str2.toCharArray(buf.apPass, 16);
                Serial.println("AccessPoint PASSWORD="+str2);                
                EEPROM.commit();
                for (int i = 0; i < 4; i++){
                        ip[i]           = buf.DT[i+6];
                }
                for (int i = 0; i < 4; i++){
                        netmask[i]      = buf.DT[i+10];
                }
                for (int i = 0; i < 4; i++){
                        gateway[i]      = buf.DT[i+14];
                }
                for (int i = 0; i < 4; i++){
                        apIp[i]         = buf.DT[i+26];
                }
                for (int i = 0; i < 4; i++){
                        apNetmask[i]      = buf.DT[i+30];
                }
                for (int i = 0; i < 4; i++){
                        apGateway[i]      = buf.DT[i+34];
                }
                WS.send(200, "text/html", SetupHTML());
        }else{
                Serial.println(F("SetUp"));
                WS.send(200, "text/html", SetupHTML());
        }
}
//------------
String SetupHTML(){
        String ptr =
        "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>\n"
        "<HTML>\n"
        "<HEAD>\n"
                "\t\t<META HTTP-EQUIV='Content-Type' charset='UTF-8'>\n"
                "\t\t<META HTTP-EQUIV='Content-Style-Type'>\n"
                "\t\t<TITLE>IndoorEnvironmentMonitor Setup Page</TITLE>\n"
        "</HEAD>\n"
        "<BODY MARGINWIDTH='0' MARGINHEIGHT='0' leftmargin='0' style='margin: 0; padding: 0;'>\n"
        "<FORM>\n"
        "\t<BLOCKQUOTE>\n"
                "\t\t<BLOCKQUOTE>\n"
                        "\t\t\t<TABLE BGCOLOR='#17A1A5' BORDER='0' WIDTH='100%' CELLPADDING='1' style='font-family:Verdana;color:#ffffff;font-size:12px;' CELLSPACING='2'>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD>IndoorEnvironmentMonitor Setup Page</TD>\n"
                        "\t\t\t</TR>\n"
                        "\t\t\t</TABLE><BR>\n"
                        "\t\t\t<script>\n"
                                "\t\t\t\tfunction hex2num (s_hex) {\n"
                                        "\t\t\t\t\teval(\"var n_num=0X\" + s_hex);\n"
                                        "\t\t\t\t\treturn n_num;\n"
                                "\t\t\t\t}\n"
                        "\t\t\t</script>\n"
                        "\t\t\t<tbody>\n"
                        "\t\t\t<INPUT TYPE='hidden' NAME='SBM' VALUE='1'>\n"
                        "\t\t\t<TABLE BORDER='0' CELLSPACING='1' CELLPADDING='0' WIDTH='100%' HEIGHT='450'>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD HEIGHT='24' WIDTH='175'>MAC:</TD> \n"
                                "\t\t\t\t<TD WIDTH='75%' NOWRAP HEIGHT='24'>\n"
                                        "\t\t\t\t\t<INPUT ID='T1'  TYPE='text' SIZE='3' MAXLENGTH='2' NAME='DT1' VALUE=" +String(mac[0],HEX) +" readonly>.\n"
                                        "\t\t\t\t\t<INPUT ID='T3'  TYPE='text' SIZE='3' MAXLENGTH='2' NAME='DT2' VALUE=" +String(mac[1],HEX) +" readonly>.\n"
                                        "\t\t\t\t\t<INPUT ID='T5'  TYPE='text' SIZE='3' MAXLENGTH='2' NAME='DT3' VALUE=" +String(mac[2],HEX) +" readonly>.\n"
                                        "\t\t\t\t\t<INPUT ID='T7'  TYPE='text' SIZE='3' MAXLENGTH='2' NAME='DT4' VALUE=" +String(mac[3],HEX) +" readonly>.\n"
                                        "\t\t\t\t\t<INPUT ID='T9'  TYPE='text' SIZE='3' MAXLENGTH='2' NAME='DT5' VALUE=" +String(mac[4],HEX) +" readonly>.\n"
                                        "\t\t\t\t\t<INPUT ID='T11' TYPE='text' SIZE='3' MAXLENGTH='2' NAME='DT6' VALUE=" +String(mac[5],HEX) +" readonly>(HEX FIXED)\n"
                                        "\t\t\t\t\t<INPUT ID='T2'  TYPE='hidden' NAME='DT1'>\n"
                                        "\t\t\t\t\t<INPUT ID='T4'  TYPE='hidden' NAME='DT2'>\n"
                                        "\t\t\t\t\t<INPUT ID='T6'  TYPE='hidden' NAME='DT3'>\n"
                                        "\t\t\t\t\t<INPUT ID='T8'  TYPE='hidden' NAME='DT4'>\n"
                                        "\t\t\t\t\t<INPUT ID='T10' TYPE='hidden' NAME='DT5'>\n"
                                        "\t\t\t\t\t<INPUT ID='T12' TYPE='hidden' NAME='DT6'>\n"
                                "\t\t\t\t</TD> \n"
                        "\t\t\t</TR>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD HEIGHT='32' WIDTH='175'>IP:</TD> \n"
                                "\t\t\t\t<TD WIDTH='75%'>\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT7'  VALUE=" +String(ip[0],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT8'  VALUE=" +String(ip[1],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT9'  VALUE=" +String(ip[2],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT10' VALUE=" +String(ip[3],DEC) +"\n"
                                "\t\t\t\t</TD>\n"
                        "\t\t\t</TR>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD HEIGHT='32' WIDTH='175'>MASK:</TD> \n"
                                "\t\t\t\t<TD WIDTH='75%'>\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT11' VALUE=" +String(netmask[0],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT12' VALUE=" +String(netmask[1],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT13' VALUE=" +String(netmask[2],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT14' VALUE=" +String(netmask[3],DEC) +">\n"
                                "\t\t\t\t</TD> \n"
                        "\t\t\t</TR>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD HEIGHT='32' WIDTH='175'>GW:</TD> \n"
                                "\t\t\t\t<TD WIDTH='75%'>\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT15' VALUE=" +String(gateway[0],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT16' VALUE=" +String(gateway[1],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT17' VALUE=" +String(gateway[2],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT18' VALUE=" +String(gateway[3],DEC) +">\n"
                                "\t\t\t\t</TD>\n"
                        "\t\t\t</TR>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD HEIGHT='24' WIDTH='175'>SSID:</TD>\n"
                                "\t\t\t\t<TD WIDTH='75%'>\n"
                                        "\t\t\t\t\t<INPUT NAME='DT19' TYPE='text' SIZE='25' maxlength='25' VALUE=" +String(ssid) +">(Up to 16 characters)\n"
                                "\t\t\t\t</TD>\n"
                        "\t\t\t</TR>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD HEIGHT='24' WIDTH='175' NOWRAP>PASSWORD:</TD> \n"
                                "\t\t\t\t<TD WIDTH='75%'>\n"
                                        "\t\t\t\t\t<INPUT NAME='DT20' TYPE='text' SIZE='25' maxlength='25' VALUE=" +String(pass) +">(Up to 16 characters)\n"
                                "\t\t\t\t</TD>\n"
                        "\t\t\t</TR>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD COLSPAN='2'><P><CENTER><HR></CENTER></TD>\n"
                        "\t\t\t</TR>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD HEIGHT='24' WIDTH='175'>AccessPoint MAC:</TD> \n"
                                "\t\t\t\t<TD WIDTH='75%' NOWRAP HEIGHT='24'>\n"
                                        "\t\t\t\t\t<INPUT ID='T21'  TYPE='text' SIZE='3' MAXLENGTH='2' NAME='DT21' VALUE=" +String(apMac[0],HEX) +" readonly>.\n"
                                        "\t\t\t\t\t<INPUT ID='T23'  TYPE='text' SIZE='3' MAXLENGTH='2' NAME='DT22' VALUE=" +String(apMac[1],HEX) +" readonly>.\n"
                                        "\t\t\t\t\t<INPUT ID='T25'  TYPE='text' SIZE='3' MAXLENGTH='2' NAME='DT23' VALUE=" +String(apMac[2],HEX) +" readonly>.\n"
                                        "\t\t\t\t\t<INPUT ID='T27'  TYPE='text' SIZE='3' MAXLENGTH='2' NAME='DT24' VALUE=" +String(apMac[3],HEX) +" readonly>.\n"
                                        "\t\t\t\t\t<INPUT ID='T29'  TYPE='text' SIZE='3' MAXLENGTH='2' NAME='DT25' VALUE=" +String(apMac[4],HEX) +" readonly>.\n"
                                        "\t\t\t\t\t<INPUT ID='T31'  TYPE='text' SIZE='3' MAXLENGTH='2' NAME='DT26' VALUE=" +String(apMac[5],HEX) +" readonly>(HEX FIXED)\n"
                                        "\t\t\t\t\t<INPUT ID='T22'  TYPE='hidden' NAME='DT21'>\n"
                                        "\t\t\t\t\t<INPUT ID='T24'  TYPE='hidden' NAME='DT22'>\n"
                                        "\t\t\t\t\t<INPUT ID='T26'  TYPE='hidden' NAME='DT23'>\n"
                                        "\t\t\t\t\t<INPUT ID='T28'  TYPE='hidden' NAME='DT24'>\n"
                                        "\t\t\t\t\t<INPUT ID='T30'  TYPE='hidden' NAME='DT25'>\n"
                                        "\t\t\t\t\t<INPUT ID='T32'  TYPE='hidden' NAME='DT26'>\n"
                                "\t\t\t\t</TD> \n"
                        "\t\t\t</TR>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD HEIGHT='32' WIDTH='175'>AccessPoint IP:</TD> \n"
                                "\t\t\t\t<TD WIDTH='75%'>\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT27' VALUE=" +String(apIp[0],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT28' VALUE=" +String(apIp[1],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT29' VALUE=" +String(apIp[2],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT30' VALUE=" +String(apIp[3],DEC) +"\n"
                                "\t\t\t\t</TD>\n"
                        "\t\t\t</TR>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD HEIGHT='32' WIDTH='175'>AccessPoint MASK:</TD> \n"
                                "\t\t\t\t<TD WIDTH='75%'>\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT31' VALUE=" +String(apNetmask[0],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT32' VALUE=" +String(apNetmask[1],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT33' VALUE=" +String(apNetmask[2],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT34' VALUE=" +String(apNetmask[3],DEC) +">\n"
                                "\t\t\t\t</TD> \n"
                        "\t\t\t</TR>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD HEIGHT='32' WIDTH='175'>AccessPoint GW:</TD> \n"
                                "\t\t\t\t<TD WIDTH='75%'>\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT35' VALUE=" +String(apGateway[0],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT36' VALUE=" +String(apGateway[1],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT37' VALUE=" +String(apGateway[2],DEC) +">.\n"
                                        "\t\t\t\t\t<INPUT TYPE='text' SIZE='3' MAXLENGTH='3' NAME='DT38' VALUE=" +String(apGateway[3],DEC) +">\n"
                                "\t\t\t\t</TD>\n"
                        "\t\t\t</TR>\n"
                        
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD HEIGHT='24' WIDTH='175'>AccessPoint SSID:</TD>\n"
                                "\t\t\t\t<TD WIDTH='75%'>\n"
                                        "\t\t\t\t\t<INPUT NAME='DT39' TYPE='text' SIZE='25' maxlength='25' VALUE=" +String(apSsid) +">(Up to 16 characters)\n"
                                "\t\t\t\t</TD>\n"
                        "\t\t\t</TR>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD HEIGHT='24' WIDTH='175' NOWRAP>AccessPoint PASSWORD:</TD> \n"
                                "\t\t\t\t<TD WIDTH='75%'>\n"
                                        "\t\t\t\t\t<INPUT NAME='DT40' TYPE='text' SIZE='25' maxlength='25' VALUE=" +String(apPassword) +">(Up to 16 characters)\n"
                                "\t\t\t\t</TD>\n"
                        "\t\t\t</TR>\n"
                        "\t\t\t<TR>\n"
                                "\t\t\t\t<TD COLSPAN='2' WIDTH='16%' HEIGHT='32'>\n"
                                        "\t\t\t\t\t<P ALIGN=RIGHT><INPUT ID='button1' TYPE='submit' VALUE='SUBMIT'\n"
                                        "\t\t\t\t\tOnclick=\"\n"
                                        "\t\t\t\t\t\tdocument.getElementById('T2').value  = hex2num(document.getElementById('T1').value);\n"
                                        "\t\t\t\t\t\tdocument.getElementById('T4').value  = hex2num(document.getElementById('T3').value);\n"
                                        "\t\t\t\t\t\tdocument.getElementById('T6').value  = hex2num(document.getElementById('T5').value);\n"
                                        "\t\t\t\t\t\tdocument.getElementById('T8').value  = hex2num(document.getElementById('T7').value);\n"
                                        "\t\t\t\t\t\tdocument.getElementById('T10').value = hex2num(document.getElementById('T9').value);\n"
                                        "\t\t\t\t\t\tdocument.getElementById('T12').value = hex2num(document.getElementById('T11').value);\n"
                                        "\t\t\t\t\t\tdocument.getElementById('T22').value = hex2num(document.getElementById('T21').value);\n"
                                        "\t\t\t\t\t\tdocument.getElementById('T24').value = hex2num(document.getElementById('T23').value);\n"
                                        "\t\t\t\t\t\tdocument.getElementById('T26').value = hex2num(document.getElementById('T25').value);\n"
                                        "\t\t\t\t\t\tdocument.getElementById('T28').value = hex2num(document.getElementById('T27').value);\n"
                                        "\t\t\t\t\t\tdocument.getElementById('T30').value = hex2num(document.getElementById('T29').value);\n"
                                        "\t\t\t\t\t\tdocument.getElementById('T32').value = hex2num(document.getElementById('T31').value);\">\n"
                                "\t\t\t\t</TD>\n"
                        "\t\t\t</TR></tbody> \n"
                "\t\t</TABLE></BLOCKQUOTE>\n"
        "\t</BLOCKQUOTE>\n"
        "</FORM>\n"
        "</BODY>\n"
        "</HTML>\n";
        return ptr;
}
//------------
//                "\t<script SRC='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.js'></script>\n"
//                "\t<script SRC='https://cdn.rawgit.com/chartjs/Chart.js/master/samples/utils.js'></script>\n"
String SendHTML(float *tempSensor){
        String ptr =
        "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>\n"
        "<html lang='ja'><head><META http-equiv='Content-Type' content='text/html; charset=utf-8'>\n"
        "<META http-equiv='Content-Style-Type' content='text/css'>\n"
                "\t<title>IndoorEnvironmentMonitor</title>\n"
                "\t<LINK REL='shortcut icon' HREF='favicon.ico'>\n"
                "\t<script type='application/javascript' SRC='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.js'></script>\n"
                "\t<script type='application/javascript' SRC='https://cdn.rawgit.com/chartjs/Chart.js/master/samples/utils.js'></script>\n"
                "\t<style>\n"
                        "\t\tcanvas{\n"
                        "\t\t\t-moz-user-select: none;\n"
                        "\t\t\t-webkit-user-select: none;\n"
                        "\t\t\t-ms-user-select: none;\n"
                        "\t\t}\n"
                        "\t\thtml { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n"
                        "\t\tbody{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n"
                        "\t\tp {font-size: 24px;color: #444444;margin-bottom: 10px;}\n"
                "\t</style>\n"
        "</head>\n"
        "<BODY BGCOLOR='#ffffff'>\n"
        "<CENTER><TABLE WIDTH='750' BORDER='0' CELLSPACING='0' CELLPADDING='0'>\n"
                "\t<TR>\n"
                        "\t\t<TD COLSPAN='3' VALIGN='TOP'>\n"
                        "\t\t<H2><CENTER>屋内環境モニタ</CENTER></H2>\n"
                        "\t\t</TD>\n"
                "\t</TR>\n"
                "\t<TR>\n"
                        "\t\t<TD WIDTH='33%'>\n"
                        "\t\t<BR CLEAR='ALL'></TD>\n"
                        "\t\t<TD WIDTH='33%'></TD>\n"
                        "\t\t<TD WIDTH='34%'></TD>\n"
                "\t</TR>\n"
                "\t<TR>\n"
                        "\t\t<TD WIDTH='33%'>\n"
                        "\t\t<BR CLEAR='ALL'></TD>\n"
                        "\t\t<TD WIDTH='33%'></TD>\n"
                        "\t\t<TD WIDTH='34%'></TD>\n"
                "\t</TR>\n"
                "\t<TR>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP' ALIGN='RIGHT'>データ取得時刻:</TD>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP' ALIGN='CENTER'>" +String(buf3) +"</TD>\n"
                        "\t\t<TD WIDTH='34%' VALIGN='TOP'></TD>\n"
                "\t</TR>\n"
                "\t<TR>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP' ALIGN='RIGHT'>気圧(BME280):</TD>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP' ALIGN='CENTER'>" +String(tempSensor[0],0)+"</TD>\n"
                        "\t\t<TD WIDTH='34%' VALIGN='TOP'>[Pa]</TD>\n"
                "\t</TR>\n"
                "\t<TR>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP' ALIGN='RIGHT'>気温(BME280):</TD>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP' ALIGN='CENTER'>" +String(tempSensor[1],1)+"</TD>\n"
                        "\t\t<TD WIDTH='34%' VALIGN='TOP'>[℃]</TD>\n"
                "\t</TR>\n"
                "\t<TR>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP' ALIGN='RIGHT'>湿度(BME280):</TD>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP'></TD>\n"
                        "\t\t<TD WIDTH='34%' VALIGN='TOP'>[%]</TD>\n"
                "\t</TR>\n"
                "\t<TR>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP' ALIGN='RIGHT'>浮遊粒子(GP2Y):</TD>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP'></TD>\n" 
                        "\t\t<TD WIDTH='34%' VALIGN='TOP'>[mg/m3]</TD>\n"
                "\t</TR>\n"
                "\t<TR>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP' ALIGN='RIGHT'>CO2濃度(CSS811):</TD>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP'></TD>\n"
                        "\t\t<TD WIDTH='34%' VALIGN='TOP'>[ppm]</TD>\n"
                "\t</TR>\n"
                "\t<TR>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP' ALIGN='RIGHT'>照度(TSL2561):</TD>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP'></TD>\n"
                        "\t\t<TD WIDTH='34%' VALIGN='TOP'>[lux]</TD>\n"
                "\t</TR>\n"
                "\t<TR>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP' ALIGN='RIGHT'>騒音(BOB-12758):</TD>\n"
                        "\t\t<TD WIDTH='33%' VALIGN='TOP' ALIGN='CENTER'>" +String(tempSensor[2],0) +"</TD>\n"
                        "\t\t<TD WIDTH='34%' VALIGN='TOP'>[dBm]</TD>\n"
                "\t</TR>\n"
        "</TABLE>\n"
        "<div style='width:75%;'><canvas id='canvas' width='750' height='400' style='display: block; width: 750px; height: 400px;'></canvas></div>\n"
        "</CENTER>\n"
        "\t<script>\n"
                "\t\tvar randomScalingFactor = function() {\n"
                        "\t\t\treturn 18 + Math.random() * 10;\n"
                "\t\t};\n"
                "\t\tvar data_00 = ["+  (gDayBuf[0][0] ==0.0 ? String('\0') : String(gDayBuf[0][0],0))+ ","+    (gDayBuf[1][0] ==0.0 ? String('\0') : String(gDayBuf[1][0],0))+ ","+
                                        (gDayBuf[2][0] ==0.0 ? String('\0') : String(gDayBuf[2][0],0))+ ","+    (gDayBuf[3][0] ==0.0 ? String('\0') : String(gDayBuf[3][0],0))+ ","+
                                        (gDayBuf[4][0] ==0.0 ? String('\0') : String(gDayBuf[4][0],0))+ ","+    (gDayBuf[5][0] ==0.0 ? String('\0') : String(gDayBuf[5][0],0))+ ","+
                                        (gDayBuf[6][0] ==0.0 ? String('\0') : String(gDayBuf[6][0],0))+ ","+    (gDayBuf[7][0] ==0.0 ? String('\0') : String(gDayBuf[7][0],0))+ ","+
                                        (gDayBuf[8][0] ==0.0 ? String('\0') : String(gDayBuf[8][0],0))+ ","+    (gDayBuf[9][0] ==0.0 ? String('\0') : String(gDayBuf[9][0],0))+ ","+
                                        (gDayBuf[10][0]==0.0 ? String('\0') : String(gDayBuf[10][0],0))+","+    (gDayBuf[11][0]==0.0 ? String('\0') : String(gDayBuf[11][0],0))+","+
                                        (gDayBuf[12][0]==0.0 ? String('\0') : String(gDayBuf[12][0],0))+","+    (gDayBuf[13][0]==0.0 ? String('\0') : String(gDayBuf[13][0],0))+","+
                                        (gDayBuf[14][0]==0.0 ? String('\0') : String(gDayBuf[14][0],0))+","+    (gDayBuf[15][0]==0.0 ? String('\0') : String(gDayBuf[15][0],0))+","+
                                        (gDayBuf[16][0]==0.0 ? String('\0') : String(gDayBuf[16][0],0))+","+    (gDayBuf[17][0]==0.0 ? String('\0') : String(gDayBuf[17][0],0))+","+
                                        (gDayBuf[18][0]==0.0 ? String('\0') : String(gDayBuf[18][0],0))+","+    (gDayBuf[19][0]==0.0 ? String('\0') : String(gDayBuf[19][0],0))+","+
                                        (gDayBuf[20][0]==0.0 ? String('\0') : String(gDayBuf[20][0],0))+","+    (gDayBuf[21][0]==0.0 ? String('\0') : String(gDayBuf[21][0],0))+","+
                                        (gDayBuf[22][0]==0.0 ? String('\0') : String(gDayBuf[22][0],0))+","+    (gDayBuf[23][0]==0.0 ? String('\0') : String(gDayBuf[23][0],0))+","+
                "];\n"
                "\t\tvar data_01 = ["+  (gDayBuf[0][1] ==0.0 ? String('\0') : String(gDayBuf[0][1],1))+ ","+    (gDayBuf[1][1] ==0.0 ? String('\0') : String(gDayBuf[1][1],1))+ ","+
                                        (gDayBuf[2][1] ==0.0 ? String('\0') : String(gDayBuf[2][1],1))+ ","+    (gDayBuf[3][1] ==0.0 ? String('\0') : String(gDayBuf[3][1],1))+ ","+
                                        (gDayBuf[4][1] ==0.0 ? String('\0') : String(gDayBuf[4][1],1))+ ","+    (gDayBuf[5][1] ==0.0 ? String('\0') : String(gDayBuf[5][1],1))+ ","+
                                        (gDayBuf[6][1] ==0.0 ? String('\0') : String(gDayBuf[6][1],1))+ ","+    (gDayBuf[7][1] ==0.0 ? String('\0') : String(gDayBuf[7][1],1))+ ","+
                                        (gDayBuf[8][1] ==0.0 ? String('\0') : String(gDayBuf[8][1],1))+ ","+    (gDayBuf[9][1] ==0.0 ? String('\0') : String(gDayBuf[9][1],1))+ ","+
                                        (gDayBuf[10][1]==0.0 ? String('\0') : String(gDayBuf[10][1],1))+","+    (gDayBuf[11][1]==0.0 ? String('\0') : String(gDayBuf[11][1],1))+","+
                                        (gDayBuf[12][1]==0.0 ? String('\0') : String(gDayBuf[12][1],1))+","+    (gDayBuf[13][1]==0.0 ? String('\0') : String(gDayBuf[13][1],1))+","+
                                        (gDayBuf[14][1]==0.0 ? String('\0') : String(gDayBuf[14][1],1))+","+    (gDayBuf[15][1]==0.0 ? String('\0') : String(gDayBuf[15][1],1))+","+
                                        (gDayBuf[16][1]==0.0 ? String('\0') : String(gDayBuf[16][1],1))+","+    (gDayBuf[17][1]==0.0 ? String('\0') : String(gDayBuf[17][1],1))+","+
                                        (gDayBuf[18][1]==0.0 ? String('\0') : String(gDayBuf[18][1],1))+","+    (gDayBuf[19][1]==0.0 ? String('\0') : String(gDayBuf[19][1],1))+","+
                                        (gDayBuf[20][1]==0.0 ? String('\0') : String(gDayBuf[20][1],1))+","+    (gDayBuf[21][1]==0.0 ? String('\0') : String(gDayBuf[21][1],1))+","+
                                        (gDayBuf[22][1]==0.0 ? String('\0') : String(gDayBuf[22][1],1))+","+    (gDayBuf[23][1]==0.0 ? String('\0') : String(gDayBuf[23][1],1))+","+
                "];\n"
                "\t\tvar data_02 = ["+  (gDayBuf[0][2] ==0.0 ? String('\0') : String(gDayBuf[0][2],0))+ ","+    (gDayBuf[1][2] ==0.0 ? String('\0') : String(gDayBuf[1][2],0))+ ","+
                                        (gDayBuf[2][2] ==0.0 ? String('\0') : String(gDayBuf[2][2],0))+ ","+    (gDayBuf[3][2] ==0.0 ? String('\0') : String(gDayBuf[3][2],0))+ ","+
                                        (gDayBuf[4][2] ==0.0 ? String('\0') : String(gDayBuf[4][2],0))+ ","+    (gDayBuf[5][2] ==0.0 ? String('\0') : String(gDayBuf[5][2],0))+ ","+
                                        (gDayBuf[6][2] ==0.0 ? String('\0') : String(gDayBuf[6][2],0))+ ","+    (gDayBuf[7][2] ==0.0 ? String('\0') : String(gDayBuf[7][2],0))+ ","+
                                        (gDayBuf[8][2] ==0.0 ? String('\0') : String(gDayBuf[8][2],0))+ ","+    (gDayBuf[9][2] ==0.0 ? String('\0') : String(gDayBuf[9][2],0))+ ","+
                                        (gDayBuf[10][2]==0.0 ? String('\0') : String(gDayBuf[10][2],0))+","+    (gDayBuf[11][2]==0.0 ? String('\0') : String(gDayBuf[11][2],0))+","+
                                        (gDayBuf[12][2]==0.0 ? String('\0') : String(gDayBuf[12][2],0))+","+    (gDayBuf[13][2]==0.0 ? String('\0') : String(gDayBuf[13][2],0))+","+
                                        (gDayBuf[14][2]==0.0 ? String('\0') : String(gDayBuf[14][2],0))+","+    (gDayBuf[15][2]==0.0 ? String('\0') : String(gDayBuf[15][2],0))+","+
                                        (gDayBuf[16][2]==0.0 ? String('\0') : String(gDayBuf[16][2],0))+","+    (gDayBuf[17][2]==0.0 ? String('\0') : String(gDayBuf[17][2],0))+","+
                                        (gDayBuf[18][2]==0.0 ? String('\0') : String(gDayBuf[18][2],0))+","+    (gDayBuf[19][2]==0.0 ? String('\0') : String(gDayBuf[19][2],0))+","+
                                        (gDayBuf[20][2]==0.0 ? String('\0') : String(gDayBuf[20][2],0))+","+    (gDayBuf[21][2]==0.0 ? String('\0') : String(gDayBuf[21][2],0))+","+
                                        (gDayBuf[22][2]==0.0 ? String('\0') : String(gDayBuf[22][2],0))+","+    (gDayBuf[23][2]==0.0 ? String('\0') : String(gDayBuf[23][2],0))+","+
                "];\n"
                "\t\tvar data_03 = ["+  (gDayBuf[0][3] ==0.0 ? String('\0') : String(gDayBuf[0][3],0))+ ","+    (gDayBuf[1][3] ==0.0 ? String('\0') : String(gDayBuf[1][3],0))+ ","+
                                        (gDayBuf[2][3] ==0.0 ? String('\0') : String(gDayBuf[2][3],0))+ ","+    (gDayBuf[3][3] ==0.0 ? String('\0') : String(gDayBuf[3][3],0))+ ","+
                                        (gDayBuf[4][3] ==0.0 ? String('\0') : String(gDayBuf[4][3],0))+ ","+    (gDayBuf[5][3] ==0.0 ? String('\0') : String(gDayBuf[5][3],0))+ ","+
                                        (gDayBuf[6][3] ==0.0 ? String('\0') : String(gDayBuf[6][3],0))+ ","+    (gDayBuf[7][3] ==0.0 ? String('\0') : String(gDayBuf[7][3],0))+ ","+
                                        (gDayBuf[8][3] ==0.0 ? String('\0') : String(gDayBuf[8][3],0))+ ","+    (gDayBuf[9][3] ==0.0 ? String('\0') : String(gDayBuf[9][3],0))+ ","+
                                        (gDayBuf[10][3]==0.0 ? String('\0') : String(gDayBuf[10][3],0))+","+    (gDayBuf[11][3]==0.0 ? String('\0') : String(gDayBuf[11][3],0))+","+
                                        (gDayBuf[12][3]==0.0 ? String('\0') : String(gDayBuf[12][3],0))+","+    (gDayBuf[13][3]==0.0 ? String('\0') : String(gDayBuf[13][3],0))+","+
                                        (gDayBuf[14][3]==0.0 ? String('\0') : String(gDayBuf[14][3],0))+","+    (gDayBuf[15][3]==0.0 ? String('\0') : String(gDayBuf[15][3],0))+","+
                                        (gDayBuf[16][3]==0.0 ? String('\0') : String(gDayBuf[16][3],0))+","+    (gDayBuf[17][3]==0.0 ? String('\0') : String(gDayBuf[17][3],0))+","+
                                        (gDayBuf[18][3]==0.0 ? String('\0') : String(gDayBuf[18][3],0))+","+    (gDayBuf[19][3]==0.0 ? String('\0') : String(gDayBuf[19][3],0))+","+
                                        (gDayBuf[20][3]==0.0 ? String('\0') : String(gDayBuf[20][3],0))+","+    (gDayBuf[21][3]==0.0 ? String('\0') : String(gDayBuf[21][3],0))+","+
                                        (gDayBuf[22][3]==0.0 ? String('\0') : String(gDayBuf[22][3],0))+","+    (gDayBuf[23][3]==0.0 ? String('\0') : String(gDayBuf[23][3],0))+","+
                "];\n"
                "\t\tvar data_04 = ["+  (gDayBuf[0][4] ==0.0 ? String('\0') : String(gDayBuf[0][4],0))+ ","+    (gDayBuf[1][4] ==0.0 ? String('\0') : String(gDayBuf[1][4],0))+ ","+
                                        (gDayBuf[2][4] ==0.0 ? String('\0') : String(gDayBuf[2][4],0))+ ","+    (gDayBuf[3][4] ==0.0 ? String('\0') : String(gDayBuf[3][4],0))+ ","+
                                        (gDayBuf[4][4] ==0.0 ? String('\0') : String(gDayBuf[4][4],0))+ ","+    (gDayBuf[5][4] ==0.0 ? String('\0') : String(gDayBuf[5][4],0))+ ","+
                                        (gDayBuf[6][4] ==0.0 ? String('\0') : String(gDayBuf[6][4],0))+ ","+    (gDayBuf[7][4] ==0.0 ? String('\0') : String(gDayBuf[7][4],0))+ ","+
                                        (gDayBuf[8][4] ==0.0 ? String('\0') : String(gDayBuf[8][4],0))+ ","+    (gDayBuf[9][4] ==0.0 ? String('\0') : String(gDayBuf[9][4],0))+ ","+
                                        (gDayBuf[10][4]==0.0 ? String('\0') : String(gDayBuf[10][4],0))+","+    (gDayBuf[11][4]==0.0 ? String('\0') : String(gDayBuf[11][4],0))+","+
                                        (gDayBuf[12][4]==0.0 ? String('\0') : String(gDayBuf[12][4],0))+","+    (gDayBuf[13][4]==0.0 ? String('\0') : String(gDayBuf[13][4],0))+","+
                                        (gDayBuf[14][4]==0.0 ? String('\0') : String(gDayBuf[14][4],0))+","+    (gDayBuf[15][4]==0.0 ? String('\0') : String(gDayBuf[15][4],0))+","+
                                        (gDayBuf[16][4]==0.0 ? String('\0') : String(gDayBuf[16][4],0))+","+    (gDayBuf[17][4]==0.0 ? String('\0') : String(gDayBuf[17][4],0))+","+
                                        (gDayBuf[18][4]==0.0 ? String('\0') : String(gDayBuf[18][4],0))+","+    (gDayBuf[19][4]==0.0 ? String('\0') : String(gDayBuf[19][4],0))+","+
                                        (gDayBuf[20][4]==0.0 ? String('\0') : String(gDayBuf[20][4],0))+","+    (gDayBuf[21][4]==0.0 ? String('\0') : String(gDayBuf[21][4],0))+","+
                                        (gDayBuf[22][4]==0.0 ? String('\0') : String(gDayBuf[22][4],0))+","+    (gDayBuf[23][4]==0.0 ? String('\0') : String(gDayBuf[23][4],0))+","+
                "];\n"
                "\t\tvar data_05 = ["+  (gDayBuf[0][5] ==0.0 ? String('\0') : String(gDayBuf[0][5],0))+ ","+    (gDayBuf[1][5] ==0.0 ? String('\0') : String(gDayBuf[1][5],0))+ ","+
                                        (gDayBuf[2][5] ==0.0 ? String('\0') : String(gDayBuf[2][5],0))+ ","+    (gDayBuf[3][5] ==0.0 ? String('\0') : String(gDayBuf[3][5],0))+ ","+
                                        (gDayBuf[4][5] ==0.0 ? String('\0') : String(gDayBuf[4][5],0))+ ","+    (gDayBuf[5][5] ==0.0 ? String('\0') : String(gDayBuf[5][5],0))+ ","+
                                        (gDayBuf[6][5] ==0.0 ? String('\0') : String(gDayBuf[6][5],0))+ ","+    (gDayBuf[7][5] ==0.0 ? String('\0') : String(gDayBuf[7][5],0))+ ","+
                                        (gDayBuf[8][5] ==0.0 ? String('\0') : String(gDayBuf[8][5],0))+ ","+    (gDayBuf[9][5] ==0.0 ? String('\0') : String(gDayBuf[9][5],0))+ ","+
                                        (gDayBuf[10][5]==0.0 ? String('\0') : String(gDayBuf[10][5],0))+","+    (gDayBuf[11][5]==0.0 ? String('\0') : String(gDayBuf[11][5],0))+","+
                                        (gDayBuf[12][5]==0.0 ? String('\0') : String(gDayBuf[12][5],0))+","+    (gDayBuf[13][5]==0.0 ? String('\0') : String(gDayBuf[13][5],0))+","+
                                        (gDayBuf[14][5]==0.0 ? String('\0') : String(gDayBuf[14][5],0))+","+    (gDayBuf[15][5]==0.0 ? String('\0') : String(gDayBuf[15][5],0))+","+
                                        (gDayBuf[16][5]==0.0 ? String('\0') : String(gDayBuf[16][5],0))+","+    (gDayBuf[17][5]==0.0 ? String('\0') : String(gDayBuf[17][5],0))+","+
                                        (gDayBuf[18][5]==0.0 ? String('\0') : String(gDayBuf[18][5],0))+","+    (gDayBuf[19][5]==0.0 ? String('\0') : String(gDayBuf[19][5],0))+","+
                                        (gDayBuf[20][5]==0.0 ? String('\0') : String(gDayBuf[20][5],0))+","+    (gDayBuf[21][5]==0.0 ? String('\0') : String(gDayBuf[21][5],0))+","+
                                        (gDayBuf[22][5]==0.0 ? String('\0') : String(gDayBuf[22][5],0))+","+    (gDayBuf[23][5]==0.0 ? String('\0') : String(gDayBuf[23][5],0))+","+
                "];\n"
                "\t\tvar data_06 = ["+  (gDayBuf[0][6] ==0.0 ? String('\0') : String(gDayBuf[0][6],0))+ ","+    (gDayBuf[1][6] ==0.0 ? String('\0') : String(gDayBuf[1][6],0))+ ","+
                                        (gDayBuf[2][6] ==0.0 ? String('\0') : String(gDayBuf[2][6],0))+ ","+    (gDayBuf[3][6] ==0.0 ? String('\0') : String(gDayBuf[3][6],0))+ ","+
                                        (gDayBuf[4][6] ==0.0 ? String('\0') : String(gDayBuf[4][6],0))+ ","+    (gDayBuf[5][6] ==0.0 ? String('\0') : String(gDayBuf[5][6],0))+ ","+
                                        (gDayBuf[6][6] ==0.0 ? String('\0') : String(gDayBuf[6][6],0))+ ","+    (gDayBuf[7][6] ==0.0 ? String('\0') : String(gDayBuf[7][6],0))+ ","+
                                        (gDayBuf[8][6] ==0.0 ? String('\0') : String(gDayBuf[8][6],0))+ ","+    (gDayBuf[9][6] ==0.0 ? String('\0') : String(gDayBuf[9][6],0))+ ","+
                                        (gDayBuf[10][6]==0.0 ? String('\0') : String(gDayBuf[10][6],0))+","+    (gDayBuf[11][6]==0.0 ? String('\0') : String(gDayBuf[11][6],0))+","+
                                        (gDayBuf[12][6]==0.0 ? String('\0') : String(gDayBuf[12][6],0))+","+    (gDayBuf[13][6]==0.0 ? String('\0') : String(gDayBuf[13][6],0))+","+
                                        (gDayBuf[14][6]==0.0 ? String('\0') : String(gDayBuf[14][6],0))+","+    (gDayBuf[15][6]==0.0 ? String('\0') : String(gDayBuf[15][6],0))+","+
                                        (gDayBuf[16][6]==0.0 ? String('\0') : String(gDayBuf[16][6],0))+","+    (gDayBuf[17][6]==0.0 ? String('\0') : String(gDayBuf[17][6],0))+","+
                                        (gDayBuf[18][6]==0.0 ? String('\0') : String(gDayBuf[18][6],0))+","+    (gDayBuf[19][6]==0.0 ? String('\0') : String(gDayBuf[19][6],0))+","+
                                        (gDayBuf[20][6]==0.0 ? String('\0') : String(gDayBuf[20][6],0))+","+    (gDayBuf[21][6]==0.0 ? String('\0') : String(gDayBuf[21][6],0))+","+
                                        (gDayBuf[22][6]==0.0 ? String('\0') : String(gDayBuf[22][6],0))+","+    (gDayBuf[23][6]==0.0 ? String('\0') : String(gDayBuf[23][6],0))+","+
                "];\n"
                "\t\tvar config = {\n"
                        "\t\t\ttype: 'line',\n"
                        "\t\t\tdata: {\n"
                                "\t\t\t\tlabels: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12' , '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'],\n"
                                "\t\t\t\tdatasets: [{\n"
                                        "\t\t\t\t\tlabel: '気圧[Pa]',\n"
                                        "\t\t\t\t\tdata: data_00,\n"
                                        "\t\t\t\t\tborderColor: window.chartColors.red,\n"
                                        "\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"
                                        "\t\t\t\t\tfill: false,\n"
                                        "\t\t\t\t\tcubicInterpolationMode: 'monotone',\n"
                                        "\t\t\t\t\tyAxisID: 'y1'\n"
                                "\t\t\t\t}, {\n"
                                        "\t\t\t\t\tlabel: '気温[℃]',\n"
                                        "\t\t\t\t\tdata: data_01,\n"
                                        "\t\t\t\t\tborderColor: window.chartColors.blue,\n"
                                        "\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"
                                        "\t\t\t\t\tfill: false,\n"
                                        "\t\t\t\t\tyAxisID: 'y2'\n"
                                "\t\t\t\t}, {\n"
                                        "\t\t\t\t\tlabel: '湿度[%]',\n"
                                        "\t\t\t\t\tdata: data_02,\n"
                                        "\t\t\t\t\tborderColor: window.chartColors.orange,\n"
                                        "\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"
                                        "\t\t\t\t\tfill: false,\n"
                                        "\t\t\t\t\tyAxisID: 'y3'\n"
                                "\t\t\t\t}, {\n"
                                        "\t\t\t\t\tlabel: '浮遊粒子[mg/m3]',\n"
                                        "\t\t\t\t\tdata: data_03,\n"
                                        "\t\t\t\t\tborderColor: window.chartColors.yellow,\n"
                                        "\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"
                                        "\t\t\t\t\tfill: false,\n"
                                        "\t\t\t\t\tyAxisID: 'y4'\n"
                                "\t\t\t\t}, {\n"
                                        "\t\t\t\t\tlabel: 'CO2濃度[ppm]',\n"
                                        "\t\t\t\t\tdata: data_04,\n"
                                        "\t\t\t\t\tborderColor: window.chartColors.purple,\n"
                                        "\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"
                                        "\t\t\t\t\tfill: false,\n"
                                        "\t\t\t\t\tyAxisID: 'y5'\n"
                                "\t\t\t\t}, {\n"
                                        "\t\t\t\t\tlabel: '照度[lux]',\n"
                                        "\t\t\t\t\tdata: data_05,\n"
                                        "\t\t\t\t\tborderColor: window.chartColors.grey,\n"
                                        "\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"
                                        "\t\t\t\t\tfill: false,\n"
                                        "\t\t\t\t\tyAxisID: 'y6'\n"
                                "\t\t\t\t}, {\n"
                                        "\t\t\t\t\tlabel: '騒音[dBm]',\n"
                                        "\t\t\t\t\tdata: data_06,\n"
                                        "\t\t\t\t\tborderColor: window.chartColors.green,\n"
                                        "\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"
                                        "\t\t\t\t\tfill: false,\n"
                                        "\t\t\t\t\tlineTension: 0,\n"
                                        "\t\t\t\t\tyAxisID: 'y7'\n"
                                "\t\t\t\t}]\n"
                        "\t\t\t},\n"
                        "\t\t\toptions: {\n"
                                "\t\t\t\tresponsive: true,\n"
                                "\t\t\t\ttitle: {\n"
                                        "\t\t\t\t\tdisplay: true,\n"
                                        "\t\t\t\t\ttext: '今日の測定結果'\n"
                                "\t\t\t\t},\n"
                                "\t\t\t\tlegend: {                               //凡例\n"
                                        "\t\t\t\t\tdisplay: true\n"
                                "\t\t\t\t},\n"
                                "\t\t\t\ttooltips: {                             //ツールチップ\n"
                                        "\t\t\t\t\tenabled: true,\n"
                                        "\t\t\t\t\tmode: 'index'\n"
                                "\t\t\t\t},\n"
                                "\t\t\t\tscales: {\n"
                                        "\t\t\t\t\txAxes: [{\n"
                                                "\t\t\t\t\t\tdisplay: true,\n"
                                                "\t\t\t\t\t\tscaleLabel: {\n"
                                                        "\t\t\t\t\t\t\tdisplay: true,\n"
                                                        "\t\t\t\t\t\t\tlabelString: '時刻 [時]'\n"
                                                "\t\t\t\t\t\t}\n"
                                        "\t\t\t\t\t}],\n"
                                        "\t\t\t\t\tyAxes: [{\n"
                                                "\t\t\t\t\t\tid:'y1',\n"
                                                "\t\t\t\t\t\tdisplay: true,\n"
                                                "\t\t\t\t\t\tscaleLabel: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n"
                                                        "\t\t\t\t\t\t\tdisplay: true,\n"
                                                        "\t\t\t\t\t\t\tlabelString: '圧力 [Pa]'\n"
                                                "\t\t\t\t\t\t},\n"
                                                "\t\t\t\t\t\tticks: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMin:  94000,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMax: 104000\n"
                                                "\t\t\t\t\t\t}\n"
                                        "\t\t\t\t\t},{\n"
                                                "\t\t\t\t\t\tid:'y2',\n"
                                                "\t\t\t\t\t\tscaleLabel: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n"
                                                        "\t\t\t\t\t\t\tdisplay: true,\n"
                                                        "\t\t\t\t\t\t\tlabelString: '温度 [℃]'\n"
                                                "\t\t\t\t\t\t},\n"
                                                "\t\t\t\t\t\tticks: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMin: 0,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMax: 50\n"
                                                "\t\t\t\t\t\t}\n"
                                        "\t\t\t\t\t},{\n"
                                                "\t\t\t\t\t\tid:'y3',\n"
                                                "\t\t\t\t\t\tscaleLabel: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n"
                                                        "\t\t\t\t\t\t\tdisplay: true,\n"
                                                        "\t\t\t\t\t\t\tlabelString: '湿度[%]'\n"
                                                "\t\t\t\t\t\t},\n"
                                                "\t\t\t\t\t\tticks: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMin: 0,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMax: 100\n"
                                                "\t\t\t\t\t\t}\n"
                                        "\t\t\t\t\t},{\n"
                                                "\t\t\t\t\t\tid:'y4',\n"
                                                "\t\t\t\t\t\tposition: 'right',\n"
                                                "\t\t\t\t\t\tscaleLabel: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n"
                                                        "\t\t\t\t\t\t\tdisplay: true,\n"
                                                        "\t\t\t\t\t\t\tlabelString: '浮遊粒子[mg/m3]'\n"
                                                "\t\t\t\t\t\t},\n"
                                                "\t\t\t\t\t\tticks: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMin: 0,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMax: 10000\n"
                                                "\t\t\t\t\t\t}\n"
                                        "\t\t\t\t\t},{\n"
                                                "\t\t\t\t\t\tid:'y5',\n"
                                                "\t\t\t\t\t\tposition: 'right',\n"
                                                "\t\t\t\t\t\tscaleLabel: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.purple,\n"
                                                        "\t\t\t\t\t\t\tdisplay: true,\n"
                                                        "\t\t\t\t\t\t\tlabelString: 'CO2濃度[ppm]'\n"
                                                "\t\t\t\t\t\t},\n"
                                                "\t\t\t\t\t\tticks: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.purple,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMin: 0,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMax: 10000\n"
                                                "\t\t\t\t\t\t}\n"
                                        "\t\t\t\t\t},{\n"
                                                "\t\t\t\t\t\tid:'y6',\n"
                                                "\t\t\t\t\t\tposition: 'right',\n"
                                                "\t\t\t\t\t\tscaleLabel: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.grey,\n"
                                                        "\t\t\t\t\t\t\tdisplay: true,\n"
                                                        "\t\t\t\t\t\t\tlabelString: '照度[lux]'\n"
                                                "\t\t\t\t\t\t},\n"
                                                "\t\t\t\t\t\tticks: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.grey,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMin: 0,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMax: 100000\n"
                                                "\t\t\t\t\t\t}\n"
                                        "\t\t\t\t\t},{\n"
                                                "\t\t\t\t\t\tid:'y7',\n"
                                                "\t\t\t\t\t\tposition: 'right',\n"
                                                "\t\t\t\t\t\tscaleLabel: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.green,\n"
                                                        "\t\t\t\t\t\t\tdisplay: true,\n"
                                                        "\t\t\t\t\t\t\tlabelString: '騒音[dBm]'\n"
                                                "\t\t\t\t\t\t},\n"
                                                "\t\t\t\t\t\tticks: {\n"
                                                        "\t\t\t\t\t\t\tfontColor: window.chartColors.green,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMin: 0,\n"
                                                        "\t\t\t\t\t\t\tsuggestedMax: 5000\n"
                                                "\t\t\t\t\t\t}\n"
                                        "\t\t\t\t\t}]\n"
                                "\t\t\t\t}\n"
                        "\t\t\t}\n"
                "\t\t};\n"
                "\t\twindow.onload = function() {\n"
                        "\t\t\tvar ctx = document.getElementById('canvas').getContext('2d');\n"
                        "\t\t\twindow.myLine = new Chart(ctx, config);\n"
                "\t\t};\n"
        "\t</script>\n</BODY>\n"
        "</html>\n";
        return ptr;
}
//------------      setup?SBM=1&DT1=24&DT2=a&DT3=c4&DT4=61&DT5=1e&DT6=7c&
//                              DT1=36&DT2=10&DT3=196&DT4=97&DT5=30&DT6=124&
//                              DT7=192&DT8=168&DT9=0&DT10=33&
//                              DT11=255&DT12=255&DT13=255&DT14=0&
//                              DT15=192&DT16=168&DT17=0&DT18=1&
//                              DT19=**********&DT20=**********&
//                              DT21=24&DT22=a&DT23=c4&DT24=61&DT25=1e&DT26=7d&
//                              DT21=36&DT22=10&DT23=196&DT24=97&DT25=30&DT26=125&
//                              DT27=192&DT28=168&DT29=250&DT30=33&
//                              DT31=255&DT32=255&DT33=255&DT34=0&
//                              DT35=192&DT36=168&DT37=250&DT38=1&
//                              DT39=ESP_AP&DT40=password
void handleUpdate() {
        Serial.println("SBM");
        digitalWrite(PO4, false);
        if(!WS.hasArg("SBM=1")){                                        //引数に"SBM=1"が含まれていることを確認
                handleNotFound();
                return;
        }
        String cmd = WS.arg("SBM=1");
        Serial.println(cmd);
        digitalWrite(PO4, true);
}
//------------ BMPprint
void printOLCDValues() {
        BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
        BME280::PresUnit presUnit(BME280::PresUnit_Pa);
        bmp.read(pres, temp, hum, tempUnit, presUnit);
        sprintf(buf1,"Temperature:%.2f%1s",temp,String(tempUnit == BME280::TempUnit_Celsius ? 'C' :'F'));
        sprintf(buf2,"Pressure: %.0f Pa",pres); 
        buf11   = String(buf1);
        buf22   = String(buf2);
        //Serial.println(buf1);
        //Serial.println(buf2);
        OLCD.setCursor(0, 40);
        OLCD.fillRect(0,40,128,16,SSD1306_BLACK);
        OLCD.setTextSize(1);OLCD.setTextColor(SSD1306_WHITE);OLCD.setCursor(0, 40);
        OLCD.println(buf1);
        OLCD.println(buf2);
        OLCD.display();
}
//------------ printTime
int printOLCDTime() {
        getLocalTime(&timeinfo);
        sprintf(buf3,"%04d/%02d/%02d %02d:%02d:%02d",timeinfo.tm_year+1900,timeinfo.tm_mon+1,timeinfo.tm_mday,timeinfo.tm_hour,timeinfo.tm_min,timeinfo.tm_sec);
        //Serial.println(buf3);
        OLCD.setCursor(0, 56);
        OLCD.fillRect(0,56,128,8,SSD1306_BLACK);
        OLCD.setTextSize(1);OLCD.setTextColor(SSD1306_WHITE);OLCD.setCursor(0, 56);
        OLCD.println(buf3);
        return timeinfo.tm_hour;
}
//------------ デバッグ用
void printLocalTime(){
        struct tm timeinfo;
        if (!getLocalTime(&timeinfo)) {
                Serial.println(F("Failed to obtain time"));
                return;
        }
        Serial.println(&timeinfo, "%Y %m %d %a %H:%M:%S");              //日本人にわかりやすい表記へ変更
}
//--------ContentTypeを拡張子で判断しているがこれでいいのか???
String getContentType(String filename){
        if(WS.hasArg("download"))               return "application/octet-stream";
        else if(filename.endsWith(".htm"))      return "text/html";
        else if(filename.endsWith(".html"))     return "text/html";
        else if(filename.endsWith(".css"))      return "text/css";
        else if(filename.endsWith(".js"))       return "application/javascript";
        else if(filename.endsWith(".png"))      return "image/png";
        else if(filename.endsWith(".gif"))      return "image/gif";
        else if(filename.endsWith(".jpg"))      return "image/jpeg";
        else if(filename.endsWith(".ico"))      return "image/x-icon";
        else if(filename.endsWith(".xml"))      return "text/xml";
        else if(filename.endsWith(".pdf"))      return "application/x-pdf";
        else if(filename.endsWith(".zip"))      return "application/x-zip";
        else if(filename.endsWith(".gz"))       return "application/x-gzip";
        return "text/plain";
}
//------------ setup function
void setup(void) {
        //
        Serial.begin(115200);
        //
        int bufSize = sizeof(st_esp);
        EEPROM.begin(bufSize);                                          //構造体のサイズ設定
        st_esp  buf;
        Serial.print(F("bufSize="));Serial.println(bufSize);
        EEPROM.get<st_esp>(0, buf);                                     //EEPROM読込
        Serial.print(F("bufID=0x"));Serial.println(buf.id,HEX);
        //MACアドレスの取得
        esp_read_mac(mac,       ESP_MAC_WIFI_STA);                      //StationModeのMacAddress
        esp_read_mac(apMac,     ESP_MAC_WIFI_SOFTAP);                   //APModeのMacAddress
        if(buf.id == ID){
                Serial.println(F("bufID:Match"));
                //既に情報がある場合は読込
                //for (int i = 0; i < 6; i++){
                //      mac[i]          = buf.DT[i];
                //}
                for (int i = 0; i < 4; i++){
                        ip[i]           = buf.DT[i+6];
                }
                for (int i = 0; i < 4; i++){
                        netmask[i]      = buf.DT[i+10];
                }
                for (int i = 0; i < 4; i++){
                        gateway[i]      = buf.DT[i+14];
                }
                for (int i = 0; i < 4; i++){
                        apIp[i]         = buf.DT[i+26];
                }
                for (int i = 0; i < 4; i++){
                        apNetmask[i]      = buf.DT[i+30];
                }
                for (int i = 0; i < 4; i++){
                        apGateway[i]      = buf.DT[i+34];
                }
                strcpy(ssid,buf.ssid);
                Serial.print(F("ssid ="));              Serial.println(ssid);
                strcpy(pass,buf.pass);
                Serial.print(F("ap_password ="));       Serial.println(apPassword);
                strcpy(apSsid,buf.apSsid);
                Serial.print(F("ap_ssid ="));           Serial.println(apSsid);
                strcpy(apPassword,buf.apPass);
                Serial.print(F("ap_password ="));       Serial.println(apPassword);
        }else{
                Serial.println(F("bufID:NotMatch"));
                //情報が書き込まれていないので初期値を書き込んでおく
                for (int i = 0; i < 6; i++){
                        buf.DT[i]     = mac[i];
                }
                for (int i = 0; i < 4; i++){
                        buf.DT[i+6]     = ip[i];
                }
                for (int i = 0; i < 4; i++){
                        buf.DT[i+10]    = netmask[i];
                }
                for (int i = 0; i < 4; i++){
                        buf.DT[i+14]    = gateway[i];
                }
                for (int i = 0; i < 6; i++){
                        buf.DT[i+20]    = apMac[i];
                }
                for (int i = 0; i < 4; i++){
                        buf.DT[i+26]    = apIp[i];
                }
                for (int i = 0; i < 4; i++){
                        buf.DT[i+30]    = apNetmask[i];
                }
                for (int i = 0; i < 4; i++){
                        buf.DT[i+34]    = apGateway[i];
                }
                strcpy(buf.ssid,ssid);
                strcpy(buf.pass,pass);
                strcpy(buf.apSsid,apSsid);
                strcpy(buf.apPass,apPassword);
                buf.id  = ID;
                EEPROM.put<st_esp>(0, buf);
                EEPROM.commit();                
        }
//        */
        pinMode(LED,OUTPUT);    digitalWrite(LED,LOW);                  //Onboard LED port Direction output
        pinMode(PO1,OUTPUT);    digitalWrite(PO1,LOW);
        pinMode(PO2,OUTPUT);    digitalWrite(PO2,LOW);
        pinMode(PO3,OUTPUT);    digitalWrite(PO3,LOW);
        //pinMode(PO4,OUTPUT);  digitalWrite(PO4,LOW);
        //ledcSetup(LEDC_CHANNEL_0,1000,8);                             //double ledcSetup(uint8_t chan, double freq, uint8_t bit_num);
        //ledcAttachPin(PO3, LEDC_CHANNEL_0);                           //void ledcAttachPin(uint8_t pin, uint8_t chan);
        ledcSetup(LEDC_CHANNEL_1,1000,8);
        ledcAttachPin(PO4, LEDC_CHANNEL_1);
        pinMode(PI1,INPUT);
        pinMode(PI2,INPUT);
        pinMode(PI3,INPUT);
        pinMode(PI4,INPUT);
        //SSD1306_SWITCHCAPVCC =内部で3.3Vから表示電圧を生成
        Wire.setClock(400000);                                          // クロック速度を最も速くなるように設定して、通信を改善します(高速モード)
        if(!OLCD.begin(SSD1306_SWITCHCAPVCC, OLCDAres)) {               // 128x64のスレーブアドレスオリジナル値は0x3Dでしたが手元の元は0x3Cでした。
                Serial.println(F("SSD1306 allocation failed"));
                for(;;);                                                // Don't proceed, loop forever
        }
        status = bmp.begin();
        if (!status) {
                Serial.println(F("Could not find BME280 sensor!"));
        }
        // bme.chipID(); // Deprecated. See chipModel().
        switch(bmp.chipModel()){
                case BME280::ChipModel_BME280:
                        Serial.println(F("Found BME280 sensor! Success."));
                        break;
                case BME280::ChipModel_BMP280:
                        Serial.println(F("Found BMP280 sensor! No Humidity available."));
                        break;
                default:
                        Serial.println(F("Found UNKNOWN sensor! Error!"));
        }
        // バッファをクリアします
        OLCD.clearDisplay();
        // SPIFFSのセットアップ  10.2で追加
        if(!SPIFFS.begin(true)){
                Serial.println("An Error has occurred while mounting SPIFFS");
                return;
        }
        // アクセスポイント(無線LAN親機) + ステーション(無線LAN子機)
        WiFi.mode(WIFI_AP_STA);
        // まず既存のアクセスポイント(ネットワーク)に接続する
        //WiFi.config(ip,gateway,netmask);                              //固定IPにする場合に使用
        WiFi.begin(ssid, pass);
        // Wait for connection
        Serial.println(F(""));
        while (WiFi.status() != WL_CONNECTED) {                         //接続するまでループするが、すごく電流を喰うようでchipが熱くなる。要対策。
                delay(1000);
                Serial.print(F("."));
        }
        Serial.println(F(""));
        Serial.print(F("Connected to "));Serial.println(ssid);
        IPAddress myIP =WiFi.localIP();
        Serial.print(F("IP address: "));Serial.println(myIP);
        OLCD.setTextSize(1);OLCD.setTextColor(SSD1306_WHITE);OLCD.setCursor(0, 0);
        OLCD.print(F("LoginID:"));OLCD.println(myID);
        OLCD.print(F("LoginPASS:"));OLCD.println(myPASS);
        OLCD.print(F("IP:"));OLCD.println(myIP);
        //OLCD.display();
        // SoftAPを開始する
        WiFi.softAPConfig(apIp,apGateway,apNetmask);
        WiFi.softAP(apSsid, apPassword);
        //IPAddress apIp = WiFi.softAPIP();
        OLCD.setTextSize(1);OLCD.setTextColor(SSD1306_WHITE);OLCD.setCursor(0, 40);
        OLCD.print(F("SSID:"));OLCD.println(apSsid);
        OLCD.print(F("PASS:"));OLCD.println(apPassword);
        OLCD.print(F("IP:"));OLCD.println(apIp[0]);OLCD.println(F("."));OLCD.println(apIp[1]);OLCD.println(F("."));OLCD.println(apIp[2]);OLCD.println(F("."));OLCD.println(apIp[3]);
        OLCD.display();
        Serial.print(F("SoftAPのIPアドレス(LAN側): "));Serial.println(myIP);
        //init and get the time
        configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);                       //void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char* server2, const char* server3);
        printLocalTime();
        //ホスト名解決にmdnsを使用する
        if (!MDNS.begin(host)) {                                //https://esp32.local
                Serial.println(F("Error setting up MDNS responder!"));
                OLCD.setCursor(0, 32);OLCD.print(F("Error setting up MDNS responder!"));
                while (1) {
                        delay(1000);
                }
        }
        Serial.println(F("mDNS responder started"));
        //serverIndexに格納されているインデックスページを返す
        WS.on("/login", HTTP_GET, []() {
                WS.sendHeader("Connection", "close");
                WS.send(200, "text/html", loginIndex);
                OLCD.fillRect(0,32,128,8,SSD1306_BLACK);
                OLCD.setCursor(0, 32);
                OLCD.setTextColor(SSD1306_WHITE);
                OLCD.print(F("Connection"));
                OLCD.display();
        });
        WS.on("/serverIndex", HTTP_GET, []() {
                WS.sendHeader("Connection", "close");
                WS.send(200, "text/html", serverIndex);
                OLCD.fillRect(0,32,128,8,SSD1306_BLACK);
                OLCD.setCursor(0, 32);
                OLCD.setTextColor(SSD1306_WHITE);
                OLCD.print(F("UpdateReady"));
                OLCD.display();
        });
        //ファームウェアファイルのアップロードの処理
        WS.on("/update", HTTP_POST, []() {
                WS.sendHeader("Connection", "close");
                OLCD.setCursor(0, 32);
                OLCD.drawRect(0,32,128,8,SSD1306_BLACK);
                OLCD.display();
                WS.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
                ESP.restart();
        }, []() {
                HTTPUpload& upload = WS.upload();
                if (upload.status == UPLOAD_FILE_START) {
                        Serial.printf("Update: %s\n", upload.filename.c_str());
                        OLCD.setCursor(0, 32);
                        OLCD.drawRect(0,32,128,8,SSD1306_BLACK);
                        OLCD.setTextColor(SSD1306_WHITE);
                        OLCD.print(F("Updating..."));
                        OLCD.display();
                        if (!Update.begin(UPDATE_SIZE_UNKNOWN)) {       //利用可能な最大サイズから始める
                                Update.printError(Serial);
                        }
                } else if (upload.status == UPLOAD_FILE_WRITE) {
                        //ESPへのファームウェアのフラッシュ
                        if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
                                Update.printError(Serial);
                        }
                } else if (upload.status == UPLOAD_FILE_END) {
                        if (Update.end(true)) {                         //サイズを現在の進行状況に設定する場合はtrue
                                Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
                        } else {
                                Update.printError(Serial);
                        }
                }
        });
        WS.on("/GetData", handleGetData);                               //To get update of ADC Value only
        WS.on("/setup?", handleUpdate);                                 //To SetUpPage
        WS.on("/setup", handleSetUp);                                   //To SetUpPage
        WS.on("/favicon.ico", handleNotFound);
        WS.on("/Chart.bundle.js", handleNotFound);
        WS.on("/utils.js", handleNotFound);
        WS.on("/", HTTP_GET, []() {                                     //ルートアクセス時の応答関数を設定
                WS.sendHeader("Connection", "close");
                gDataBuf[0]     =       pres;
                gDataBuf[1]     =       temp;
                gDataBuf[2]     =       analogRead(A0);
                WS.send(200, "text/html", SendHTML(gDataBuf));
                //OLCD.setCursor(0, 32);
                OLCD.fillRect(0,32,128,8,SSD1306_BLACK);
                OLCD.display();
        });
        WS.onNotFound(handleNotFound);                                  //不正アクセス時の応答関数を設定
        WS.begin();                                                     //ウェブサーバ開始
}
//------------
int count       = 0;
int preSet      = -1;
void loop(void) {
        WS.handleClient();                                              //クライアントからの要求を処理する
        //delay(100);
        printOLCDValues();                                              //OLCDにデータを更新表示
        int h = printOLCDTime();                                        //OLCDに時刻表示 返値0-23
        //ループして遅延なく点滅する
        unsigned long currentMillis = millis();
        if(preSet != h){
                //1時間おきに時刻を確認し、データをメモリに確保
                preSet  = h;
                gDayBuf[h][0]   =       pres;
                gDayBuf[h][1]   =       temp;
                gDayBuf[h][6]   =       analogRead(A0);
                digitalWrite(PO3, true);
                //次回分のデータをNULL化
                h = (h+1) % 24;
                gDayBuf[h][0]   =       0.0;
                gDayBuf[h][1]   =       0.0;
                gDayBuf[h][6]   =       0.0;
        }
        if (currentMillis - previousMillis >= interval) {
                //最後にLEDを点滅させた時間を保存します
                previousMillis = currentMillis;
                //LEDがオフの場合はオンにし、逆の場合も同様です。
                ledState = not(ledState);
                //変数のledStateでLEDを設定します。
                digitalWrite(LED, ledState);
                switch(count){
                        case 0:
                                digitalWrite(PO1, true);
                                digitalWrite(PO2, false);
                                //digitalWrite(PO3, false);
                                //digitalWrite(PO4, false);
                                break;
                        case 1:
                                digitalWrite(PO1, false);
                                digitalWrite(PO2, true);
                                //digitalWrite(PO3, false);
                                //digitalWrite(PO4, false);
                                break;
                        case 2:
                                digitalWrite(PO1, false);
                                digitalWrite(PO2, false);
                                //digitalWrite(PO3, true);
                                //digitalWrite(PO4, false);
                                break;
                        case 3:
                                digitalWrite(PO1, false);
                                digitalWrite(PO2, false);
                                //digitalWrite(PO3, false);
                                //digitalWrite(PO4, true);
                                break;
                        default:
                                digitalWrite(PO1, false);
                                digitalWrite(PO2, false);
                                //digitalWrite(PO3, false);
                                //digitalWrite(PO4, false);
                                break;
                }
                //ledcWrite(LEDC_CHANNEL_0, brightness);
                ledcWrite(LEDC_CHANNEL_1, 255 - brightness);
                brightness = brightness + fadeAmount;
                if (brightness <= 0){
                        brightness = 1;
                        fadeAmount = abs(fadeAmount);
                        digitalWrite(PO3, false);
                }else if(brightness >= 255){
                        brightness = 254;
                        fadeAmount = -abs(fadeAmount);
                }
                count = (count + 1) % 5;
                Serial.println(count);
        }
}

フォームに入力された情報をサーバに送る文字列は平文になっていることが判ります。悪意のある人がネットワークパケットを盗み見してしまうとサーバを乗っ取られる可能性があります。SSIDやパスワードが勝手に書き換えられる可能性が出てくるからです。これをどう対策するかですが、一般には通信部をSSL化(Secure Sockets Layer)する様ライブラリを変更する事になります。ESP32には先人の情報が情報が存在しますので吟味する必要がありそうです。-->ESP32 WebServerのSSL化検討


戯言(nonsense)に戻る


問い合わせ頁の表示


免責事項

本ソフトウエアは、あなたに対して何も保証しません。本ソフトウエアの関係者(他の利用者も含む)は、あなたに対して一切責任を負いません。
あなたが、本ソフトウエアを利用(コンパイル後の再利用など全てを含む)する場合は、自己責任で行う必要があります。

本ソフトウエアの著作権は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社の登録商標です。
その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
すべての商標および登録商標は、それぞれの所有者に帰属します。