RTCの時刻表示がいつの間にか30分遅れる問題(備忘録)

最終更新日:2023年7月18日

STM32miniShieldをベースに安価な温度センサである18B20を2個連結して温度計測するガジェットを作りました。
使いながら気になる点を修正してきましたが、内部時計表示がいつの間にか30分遅れるという問題が発生し、この問題がなかなか解決出来ません。備忘録として記録に残すことにしました。

センサは18B20です。1-WireRインタフェースという珍しいデバイスです。現在ではアナログデバイス社が扱っています。(もともとMAXIM社の製品です。)カタログでは、「プログラマブル分解能1-Wireデジタルサーモメータ」と謳ってあります。

Arduino用に作成されたライブラリのままSTM32dioでコンパイル実行が可能でした。また、複数購入しても内部にユニークなシリアルが振ってあるようで、複数台を一つのバスに乗せて計測が可能です。

このガジェットでは、

といった機能を有しているのですが、ちょっと気になることが見つかると、スケッチを修正して使用している次第です。
室温を複数の位置で同時計測し、表示出来るのは意味があると思っており、もっと測定ポイントを増やしたいとも思っています。

ただ、最近の修正で時刻表示がちょっとおかしくなりました。起動時はNTPdから取得した時刻をきちんと表示しているのですが、いつの間にか正確に30分遅れた時刻表示をするのです。
このスケッチでは1時間に一回NTPを実行しています。そのタイミングで発生するのだと思うのですが、確信が持てません。また、ソースにバグがあるのだとも思ったのですが、怪しいところが見つかりません。
問題のあるコードは以下の通りです。

.ino

/*
 * 2023/07/14 T.Wanibe
 * 1.6.5 修正点:
 *      1.6.4で時刻表示が-30分という意味不明のバグがあったので、もう一度時刻表示コードを見直す
 *      ブラウザ表示で[Return]ボタンを追加
 *      lED&kEYのコールがMainLoopと割込Loopでバッティングしているので割込Loopのみに見直す
 * 1.6.4 修正点:
 *      時刻表示の改善が無かったので別の手段を試みた
 *      やはりタイマ割込を導入して1秒毎の更新となるように変更 ※温度計測はタイマ割込にすると処理時間の問題が出るのでメインループで実行する。
 * 1.6.3 修正点:
        時刻表示が1時間ずれるときがある。演算方法に問題があるようなので、他のコードからこの機能分を移植し直す
 * 1.6.2 修正点:
 *      経過時間表示がオーバフローしてしまう問題を修正
 *      IP設定画面の入力枠内を右寄せ表示に修正
 * 1.6.0 修正点:
 *      毎分の温度変化をグラフ表示出来る様に修正したいと考えました。setup3
 * 1.5.1 修正点:
 *      コードに無駄があったので修正した。接続デバイス数はsetup()内で自動判別するのが良いと思い変更
 * 1.5.0 修正点:
 *      ダミー計測をすることで値が0.0になることはなくなったが、2つのDS18B20を取り違えて計測してしまう事があり、連続性に問題がある。
 *      コードを変更してsetup()時に接続されているDS18B20のindexListを取得し、計測時にIDが合致するデータ列を意識するように変更した 
 * 1.4.2 修正点:
 *      計測前にdelayは効果無し 結果を見る限り定期的に三時間毎に0.0になっているので、ダミー計測を試すことにした。
 * 1.4.1 修正点:
 *      ch1のDS18B20のデータ取得に失敗するケースの対策が不十分 よく判らないが、計測前にdelayを入れてみる
 * 1.4.0 修正点:
 *      一時間毎のデータで0と云う値が出ている。これはおかしい。データ取得に失敗している。
 *      2ch目では発生していないことから、データ取得時待ち時間を置いてからデータ取得するように修正 
 *コメント
 *      DS18B20をブラウザ表示するソフトウエアコードを書いているのですが、03までのスケッチは期待通りに動作しません。
 *      時刻同期がなぜか失敗することが問題です。
 *      そこでベースとなるコードを変更して、機能追加し実現してみることにしました。
 *      以下はオリジナルコードのコメントです。
 *      このコードはEthernet3のExample“Udp NTP Client”をSTM32MINIShieldで動く様にレタッチしました。.
 *      BluePillにはRTCが搭載されていますが、精度が悪くバックアップ電源もありません。※接続は可能です
 *      そこで起動時にNTPで時刻所得して登録し、LED&KEYに時刻表示します。
 *      以後毎秒時刻更新します。
 *      1時間毎にNTPにアクセスして時刻調整します。
 *      Michael Margolis氏が2010年9月4日に作成したモノをレタッチしています。
 * 最大131072バイトのフラッシュメモリのうち、スケッチが56656バイト(43%)を使っています。
 * 最大20480バイトのRAMのうち、グローバル変数が4568バイト(22%)を使っていて、ローカル変数で15912バイト使うことができます。
 */
#include <libmaple/iwdg.h>
#include <SPI.h>
#include <Ethernet3.h>
#include <EthernetUdp3.h>
#include <TM1638.h>
#include <RTClock.h>
#include <EEPROM.h>
#include <avr/pgmspace.h>
#include <TextFinder.h>                                                 //WebSetting
#include <OneWire.h>                                                    //DS18B20通信用ライブラリ
//#include <DallasTemperature.h>
//PIN
#define W550io_Rst      PA8                                             //NIC_Reset
#define SPI1_NSS_PIN    PA4                                             //NIC_ChipSelec
#define UpdateInterval  86400                                           //更新間隔
#define dataPin         PB4
#define clockPin        PB3
#define strobePin       PA15
#define BUILTIN_LED     PC13
#define DS18B20Port     PA10
#define LED1            PB8
#define LED2            PB9
#define HttpPort        80                                              //HTTP
#define debug           1
#define iwdg_init_ms(N) iwdg_init(IWDG_PRE_256,((N)/8))                 //設定時間をmsecとするためにマクロを用意する。
#define vers            "STM32miniShield DS18B20 1.6"
#define NTP_PACKET_SIZE 48
#define SECS_PER_HOUR   3600
#define maxDevices      10
//コントローラのMACアドレスを以下に入力してください。
//新しいイーサネットシールドには、シールドのステッカーにMACアドレスが印刷されています
const char      FVirsion[]      = "1.6.5";
byte            mac[]           = {0x00,0x08,0xDC,0x54,0x4D,0xD1};      //Wiznet
byte            ip[]            = {192, 168, 0, 205};
byte            dns_server[]    = {192, 168, 0, 1};
byte            gateway[]       = {0, 0, 0, 0};
byte            subnet[]        = {255, 255, 255, 0};
byte            timeServer[]    = {192,168,0,199}; 
byte            packetBuffer[ NTP_PACKET_SIZE];                         //着信および発信パケットを保持するバッファ
byte            keys,lastKey;
//
unsigned int    localPort       = 8888;                                 //UDPパケットをリッスンするローカルポート
char            STRBUF[32];
char            buffer[128];
int             timeZone        = 9;                                    // change to your timezone
//オブジェクトコンストラクタ
EthernetServer  webServer(HttpPort);
EthernetClient  client;
RTClock rtclock (RTCSEL_LSE);                                           //RTC初期化
EthernetUDP     Udp;                                                    //UDPを介してパケットを送受信できるようにするUDPインスタンス
tm_t            tmm,tmm1;
TM1638          LedAndKey(dataPin, clockPin, strobePin);                //データピンPB4、クロックピンPB3、およびストローブピンPA15でモジュールを定義する
const byte      ID = 0x9B;
char            buf1[32];
char            buf2[32];
char            MacAddressStr[20];
char            IPAddressStr[20];
char            SubnetMaskStr[20];
char            GatewayStr[20];
char            NTPserverStr[20];
char            DateTimeStr[20];
String          DateStr;
String          TimeStr;
float           gDayBuf[24][4];                                         //24時間分4要素データ確保
float           gHourBuf[60][4];                                        //24時間分4要素データ確保
unsigned long   OperatingTime   = 0;                                    //稼働時間 Count2で1秒
OneWire         ds(PA10);                                               // on pin 10 (a 4.7K resistor is necessary)
boolean         fDoneTime       = false;
int             wdgTime         = 40000;
int             devNum          = maxDevices;                           //DS18B20の接続数 初期値は2としておきます。 メモリ確保のため
byte            gDS[maxDevices][8];
byte            h;                                                      //返値0-23
byte            m;                                                      //返値0-59
byte            dot             = 0;
unsigned long   DispTime;
int             preSet          = -1;
int             preMSet         = -1;
int             Temp1,Temp2;
//----------------------------------
void LANSetup(){
        int idcheck = EEPROM.read(0);
        if (idcheck != ID){
                //idがIDの値ではない場合、
                //このスケッチがシールドを設定する前に使用されていなかったことを意味します
                //スケッチの始めに書かれた値を使用するだけです
        }
        if (idcheck == ID){
                //idがIDと同じ値の場合、
                //これは、このスケッチがシールドを設定するために使用されたことを意味します。
                //EERPOMの値を読み取ってシールドを設定します。
                for (int i = 0; i < 6; i++){
                        mac[i] = EEPROM.read(i+1);
                }
                for (int i = 0; i < 4; i++){
                        ip[i] = EEPROM.read(i+7);
                }
                for (int i = 0; i < 4; i++){
                        subnet[i] = EEPROM.read(i+11);
                }
                for (int i = 0; i < 4; i++){
                        gateway[i] = EEPROM.read(i+15);
                }
                //アクセスNTPサーバー
                for (int i = 0; i < 4; i++){
                        timeServer[i] = EEPROM.read(i+19);
                }
        }
        sprintf(MacAddressStr,"%02x.%02x.%02x.%02x.%02x.%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
        sprintf(IPAddressStr,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
        sprintf(SubnetMaskStr,"%d.%d.%d.%d",subnet[0],subnet[1],subnet[2],subnet[3]);
        sprintf(GatewayStr,"%d.%d.%d.%d",gateway[0],gateway[1],gateway[2],gateway[3]);
        sprintf(NTPserverStr,"%d.%d.%d.%d",timeServer[0],timeServer[1],timeServer[2],timeServer[3]);
        Ethernet.begin(mac, ip);
}
//--------------------------
void SetWebPage( EthernetClient client){
        client.println(F("HTTP/1.1 200 OK"));
        client.println(F("Content-Type: text/html"));
        client.println();
        //
        client.print(F("<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=UTF-8\">\n"));
        client.print(F("\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>"));
        client.print(vers);
        client.print(F(" Setup Page</TITLE>\n"));
        client.print(F("\t<SCRIPT>\n\t\tfunction HP(w1){parent.window.open(w1,'_top')}\n\t</SCRIPT>\n"));
        client.print(F("\t<style type=\"text/css\">\n\t\t.tbox-style{\n\t\t\tpadding-top   : 4px;\n\t\t\tpadding-right : 4px;\n\t\t\tpadding-bottom: 2px;\n\t\t\ttext-align    : right;\n\t\t}\n\t</style>\n</HEAD>\n"));
        client.print(F("<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\">\n<BLOCKQUOTE><BLOCKQUOTE>\n"));
        client.print(F("<table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\">\n"));
        client.print(F("<tr><td>"));
        client.print(vers);
        client.print(F(" Setup Page</td></tr></table><br>\n"));
        //
        client.print(F("<script>\n\tfunction hex2num (s_hex) {\n\t\teval(\"var n_num=0X\" + s_hex);\n\t\treturn n_num;\n\t}\n</script>\n"));
        client.print(F("<tbody>\n<FORM><input type=\"hidden\" name=\"SBM\" value=\"1\">\n<table>\n<tr><td>MAC:</td><td>"));
        client.print(F("<input id=\"T1\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT1\" value=\""));
        client.print(mac[0],HEX);
        client.print(F("\" class=\"tbox-style\">.<input id=\"T3\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT2\" value=\""));
        client.print(mac[1],HEX);
        client.print(F("\" class=\"tbox-style\">.<input id=\"T5\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT3\" value=\""));
        client.print(mac[2],HEX);
        client.print(F("\" class=\"tbox-style\">.<input id=\"T7\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT4\" value=\""));
        client.print(mac[3],HEX);
        client.print(F("\" class=\"tbox-style\">.<input id=\"T9\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT5\" value=\""));
        client.print(mac[4],HEX);
        client.print(F("\" class=\"tbox-style\">.<input id=\"T11\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT6\" value=\""));
        client.print(mac[5],HEX);
        //
        client.print(F("\" class=\"tbox-style\"><input id=\"T2\" type=\"hidden\" name=\"DT1\"><input id=\"T4\" type=\"hidden\" name=\"DT2"));
        client.print(F("\"><input id=\"T6\" type=\"hidden\" name=\"DT3\"><input id=\"T8\" type=\"hidden\" name=\"DT4"));
        client.print(F("\"><input id=\"T10\" type=\"hidden\" name=\"DT5\"><input id=\"T12\" type=\"hidden\" name=\"DT6"));
        client.print(F("\"></td></tr>\n<tr><td>IP:</td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT7\" value=\""));
        client.print(ip[0],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT8\" value=\""));
        client.print(ip[1],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT9\" value=\""));
        client.print(ip[2],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT10\" value=\""));
        client.print(ip[3],DEC);
        //
        client.print(F("\" class=\"tbox-style\"></td></tr>\n<tr><td>MASK: </td><td><input type= \"text\" size=\"3\" maxlength=\"3\" name=\"DT11\" value=\""));
        client.print(subnet[0],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT12\" value=\""));
        client.print(subnet[1],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT13\" value=\""));
        client.print(subnet[2],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT14\" value=\""));
        client.print(subnet[3],DEC);
        //
        client.print(F("\" class=\"tbox-style\"></td></tr>\n<tr><td>GW: </td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT15\" value=\""));
        client.print(gateway[0],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT16\" value=\""));
        client.print(gateway[1],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT17\" value=\""));
        client.print(gateway[2],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT18\" value=\""));
        client.print(gateway[3],DEC);
        //
        //client.print(F("\"></td></tr>\n<tr><td><br></td COLSPAN='2'>\n<HR ALIGN=LEFT>"));
        client.print(F("\" class=\"tbox-style\"></td></tr><tr><td COLSPAN='2'>\n<HR ALIGN=CENTER></td><td>"));                      //1行空けたい
        //
        client.print(F("</td></tr><tr><td>NTPd: </td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT19\" value=\""));
        client.print(timeServer[0],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT20\" value=\""));
        client.print(timeServer[1],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT21\" value=\""));
        client.print(timeServer[2],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT22\" value=\""));
        client.print(timeServer[3],DEC);
        client.print(F("\" class=\"tbox-style\"></td></tr>\n<tr><td><br></td></tr><tr><td COLSPAN='2'><P ALIGN=RIGHT><INPUT TYPE=\"button\" VALUE=\"RETURN\" onClick=\"HP('http://"));
        client.print(IPAddressStr);
        client.print(F("/setup9')\"/><input id=\"button1\"type=\"submit\" value=\"SUBMIT\" "));
        //
        client.print(F("Onclick=\""));
        client.print(F("document.getElementById('T2').value      = hex2num(document.getElementById('T1').value);\n"));
        client.print(F("\t\tdocument.getElementById('T4').value  = hex2num(document.getElementById('T3').value);\n"));
        client.print(F("\t\tdocument.getElementById('T6').value  = hex2num(document.getElementById('T5').value);\n"));
        client.print(F("\t\tdocument.getElementById('T8').value  = hex2num(document.getElementById('T7').value);\n"));
        client.print(F("\t\tdocument.getElementById('T10').value = hex2num(document.getElementById('T9').value);\n"));
        client.print(F("\t\tdocument.getElementById('T12').value = hex2num(document.getElementById('T11').value);\""));
        //
        client.print(F("></td></tr></tbody>\n</table>\n</BLOCKQUOTE></BLOCKQUOTE>\n</form>\n</BODY>\n</html>\n"));
}
//-------------------------- 2021/8/12
void SetPage1Day( EthernetClient client){
        client.println("HTTP/1.1 200 OK");
        client.println("Content-Type: text/html");
        client.println();
        //
        client.print(F("<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=\"UTF-8\">\n"));
        client.print(F("\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>"));
        client.print(vers);
        client.print(F(" Utility Page</TITLE>\n"));
        client.print(F("\t<script type='application/javascript' SRC='http://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.js'></script>\n"));
        client.print(F("\t<script type='application/javascript' SRC='./setup3'></script>\n"));
        client.print(F("\t<SCRIPT>\n\t\tfunction HP(w1){parent.window.open(w1,'_top')}\n\t</SCRIPT>\n"));
        client.print(F("\t<style>\n\t\tcanvas{\n"));
        client.print(F("\t\t\t-moz-user-select: none;\n"));
        client.print(F("\t\t\t-webkit-user-select: none;\n"));
        client.print(F("\t\t\t-ms-user-select: none;\n\t\t}\n"));
        client.print(F("\t\thtml { font-family: Helvetica; display: inline-block; margin: 0px auto;}\n"));
        client.print(F("\t\tbody{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n"));
        client.print(F("\t\tp {font-size: 24px;color: #444444;margin-bottom: 10px;}\n"));
        client.print(F("\t</style>\n</HEAD>\n"));
        client.print(F("<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\" BGCOLOR=\"#ffffff\">\n"));
        client.print(F("<FORM>\n<BLOCKQUOTE><BLOCKQUOTE>\n"));
        client.print(F("<P><table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\" CELLSPACING=\"2\">\n"));
        client.print(F("<tr><td>"));
        client.print(vers);
        client.print(F(" Utility Page</td></tr></table><br>\n"));
        //
        client.print(F("<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\" style=\"table-layout: fixed\">"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">&nbsp;</TD><TD WIDTH=\"20%\">&nbsp;</TD><TD WIDTH=\"55%\"><P ALIGN=CENTER><INPUT TYPE=\"button\" VALUE=\"RETURN\" onClick=\"HP('http://"));
        client.print(IPAddressStr);
        client.print(F("/setup9')\"/></TD>\n<TR>\n\t<TD WIDTH=\"25%\">FirmwareVirsion:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(FVirsion);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">MacAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(MacAddressStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">IPAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(IPAddressStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">SubnetMask:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(SubnetMaskStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Data acquisition time(Local):</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(DateTimeStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Num of connected sensors:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(devNum);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Operating Time:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        sprintf(buf2,"%ld[sec]",OperatingTime);
        client.print(buf2);
        client.print(F("</TD>\n</TR></TABLE></P>\n"));
        client.print(F("\t<div style='width:75%;'><canvas id='canvas' width='750' height='400' style='display: block; width: 750px; height: 400px;'></canvas></div>\n"));
        client.print(F("</CENTER></BLOCKQUOTE></BLOCKQUOTE>\n</form>\n"));
        client.print(F("<script>\n"));
        client.print(F("\t\tvar randomScalingFactor = function() {\n\t\t\treturn 18 + Math.random() * 10;\n\t\t};\n"));
        client.print(F("\t\tvar data_00 = ["));
        for(int i = 0; i<24 ;i++){
                client.print(isnan(gDayBuf[i][0]) ? String('\0') : String(gDayBuf[i][0],6));
                client.print(F(","));
        }
        client.print(F("];\n"));
        client.print(F("\t\tvar data_01 = ["));
        for(int i = 0; i<24 ;i++){
                client.print(isnan(gDayBuf[i][1]) ? String('\0') : String(gDayBuf[i][1],6));
                client.print(F(","));
        }
        client.print(F("];\n"));
        client.print(F("\t\tvar data_02 = ["));
        for(int i = 0; i<24 ;i++){
                client.print(isnan(gDayBuf[i][2]) ? String('\0') : String(gDayBuf[i][2],2));
                client.print(F(","));
        }
        client.print(F("];\n"));
        client.print(F("\t\tvar data_03 = ["));
        for(int i = 0; i<24 ;i++){
                client.print(isnan(gDayBuf[i][3]) ? String('\0') : String(gDayBuf[i][3],2));
                client.print(F(","));
        }
        client.print(F("];\n"));        
        client.print(F("\t\tvar config = {"));
        client.print(F("\t\t\ttype: 'line',\n\t\t\tdata: {\n"));
        client.print(F("\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"));
        client.print(F("\t\t\t\tdatasets: [{\n"));
        client.print(F("\t\t\t\t\tlabel: '温度1[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_00,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.red,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tcubicInterpolationMode: 'monotone',\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y1'\n"));
        client.print(F("\t\t\t\t}, {\n"));
        client.print(F("\t\t\t\t\tlabel: '温度2[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_01,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.blue,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y2'\n"));
        client.print(F("\t\t\t\t}, {\n"));
        client.print(F("\t\t\t\t\tlabel: '温度3[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_02,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.orange,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y3'\n"));
        client.print(F("\t\t\t\t}, {\n"));
        client.print(F("\t\t\t\t\tlabel: '温度4[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_03,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.yellow,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y4'\n"));
        client.print(F("\t\t\t\t}]\n\t\t\t},\n"));
        client.print(F("\t\t\toptions: {\n\t\t\t\tresponsive: true,\n"));
        client.print(F("\t\t\t\ttitle: {\n\t\t\t\t\tdisplay: true,\n\t\t\t\t\ttext: '温度取得履歴'\n\t\t\t\t},\n"));
        client.print(F("\t\t\t\tlegend: {\n\t\t\t\t\tdisplay: true\n\t\t\t\t},\n"));
        client.print(F("\t\t\t\ttooltips: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tmode: 'index'\n\t\t\t\t},\n"));
        client.print(F("\t\t\t\tscales: {\n\t\t\t\t\txAxes: [{\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\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"));
        client.print(F("\t\t\t\t\tyAxes: [{\n\t\t\t\t\t\tid:'y1',\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度1[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t}\n"));
        client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y2',\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度2[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t}\n"));
        client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y3',\n\t\t\t\t\t\tposition: 'right',\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度3[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t\t}\n"));
        client.print(F("\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\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度4[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}],\n"));
        client.print(F("\t\t\t\t}\n\t\t\t}\n\t\t};\n")); 
        client.print(F("\t\twindow.onload = function() {\n\t\t\tvar ctx = document.getElementById('canvas').getContext('2d');\n"));
        client.print(F("\t\t\twindow.myLine = new Chart(ctx, config);\n\t\t};\n"));
        client.print(F("</script>\n"));
        client.print(F("</BODY></html>"));
}
//-------------------------- 2022/2/18
void SetPage1Hour( EthernetClient client){
        client.println("HTTP/1.1 200 OK\nContent-Type: text/html\n\n");
        //client.println("Content-Type: text/html");
        //client.println();
        //
        client.print(F("<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=\"UTF-8\">\n\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>"));
        //client.print(F("\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>"));
        client.print(vers);
        client.print(F(" Utility Page</TITLE>\n\t<script type='application/javascript' SRC='http://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.js'></script>\n\t<script type='application/javascript' SRC='./setup3'></script>\n"));
        client.print(F("\t<SCRIPT>\n\t\tfunction HP(w1){parent.window.open(w1,'_top')}\n\t</SCRIPT>\n"));
        //client.print(F("\t<script type='application/javascript' SRC='http://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.js'></script>\n"));
        //client.print(F("\t<script type='application/javascript' SRC='./setup3'></script>\n"));
        client.print(F("\t<style>\n\t\tcanvas{\n"));
        client.print(F("\t\t\t-moz-user-select: none;\n"));
        client.print(F("\t\t\t-webkit-user-select: none;\n"));
        client.print(F("\t\t\t-ms-user-select: none;\n\t\t}\n"));
        client.print(F("\t\thtml { font-family: Helvetica; display: inline-block; margin: 0px auto;}\n"));
        client.print(F("\t\tbody{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n"));
        client.print(F("\t\tp {font-size: 24px;color: #444444;margin-bottom: 10px;}\n"));
        client.print(F("\t</style>\n</HEAD>\n"));
        client.print(F("<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\" BGCOLOR=\"#ffffff\">\n"));
        client.print(F("<FORM>\n<BLOCKQUOTE><BLOCKQUOTE>\n"));
        client.print(F("<P><table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\" CELLSPACING=\"2\">\n"));
        client.print(F("<tr><td>"));
        client.print(vers);
        client.print(F(" Utility Page</td></tr></table><br>\n"));
        //
        client.print(F("<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\" style=\"table-layout: fixed\">"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">&nbsp;</TD><TD WIDTH=\"20%\">&nbsp;</TD><TD WIDTH=\"55%\"><P ALIGN=CENTER><INPUT TYPE=\"button\" VALUE=\"RETURN\" onClick=\"HP('http://"));
        client.print(IPAddressStr);
        client.print(F("/setup9')\"/></TD>\n<TR>\n\t<TD WIDTH=\"25%\">FirmwareVirsion:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(FVirsion);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">MacAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(MacAddressStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">IPAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(IPAddressStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">SubnetMask:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(SubnetMaskStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Data acquisition time(Local):</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(DateTimeStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Num of connected sensors:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(devNum);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Operating Time:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        sprintf(buf2,"%ld[sec]",OperatingTime);
        client.print(buf2);
        client.print(F("</TD>\n</TR></TABLE></P>\n"));
        client.print(F("\t<div style='width:75%;'><canvas id='canvas' width='750' height='400' style='display: block; width: 750px; height: 400px;'></canvas></div>\n"));
        client.print(F("</CENTER></BLOCKQUOTE></BLOCKQUOTE>\n</form>\n"));
        client.print(F("<script>\n"));
        client.print(F("\t\tvar randomScalingFactor = function() {\n\t\t\treturn 18 + Math.random() * 10;\n\t\t};\n"));
        client.print(F("\t\tvar data_00 = ["));
        for(int i = 0; i<60 ;i++){
                client.print(isnan(gHourBuf[i][0]) ? String('\0') : String(gHourBuf[i][0],6));
                client.print(F(","));
        }
        client.print(F("];\n"));
        client.print(F("\t\tvar data_01 = ["));
        for(int i = 0; i<60 ;i++){
                client.print(isnan(gHourBuf[i][1]) ? String('\0') : String(gHourBuf[i][1],6));
                client.print(F(","));
        }
        client.print(F("];\n"));
        client.print(F("\t\tvar data_02 = ["));
        for(int i = 0; i<60 ;i++){
                client.print(isnan(gHourBuf[i][2]) ? String('\0') : String(gHourBuf[i][2],2));
                client.print(F(","));
        }
        client.print(F("];\n"));
        client.print(F("\t\tvar data_03 = ["));
        for(int i = 0; i<60 ;i++){
                client.print(isnan(gHourBuf[i][3]) ? String('\0') : String(gHourBuf[i][3],2));
                client.print(F(","));
        }
        client.print(F("];\n"));        
        client.print(F("\t\tvar config = {"));
        client.print(F("\t\t\ttype: 'line',\n\t\t\tdata: {\n"));
        client.print(F("\t\t\t\tlabels: ['0', '', '2', '', '4', '', '6', '', '8', '', '10', '', '12' , '', '14', '', '16', '', '18', '', '20', '', '22', '', '24', '', '26', '', '28', '', '30', '', '32' , '', '34', '', '36', '', '38', '', '40', '', '42', '', '44', '', '46', '', '48', '', '50', '', '52' , '', '54', '', '56', '', '', '59'],\n"));
        client.print(F("\t\t\t\tdatasets: [{\n"));
        client.print(F("\t\t\t\t\tlabel: '温度1[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_00,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.red,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tcubicInterpolationMode: 'monotone',\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y1'\n"));
        client.print(F("\t\t\t\t}, {\n"));
        client.print(F("\t\t\t\t\tlabel: '温度2[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_01,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.blue,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y2'\n"));
        client.print(F("\t\t\t\t}, {\n"));
        client.print(F("\t\t\t\t\tlabel: '温度3[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_02,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.orange,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y3'\n"));
        client.print(F("\t\t\t\t}, {\n"));
        client.print(F("\t\t\t\t\tlabel: '温度4[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_03,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.yellow,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y4'\n"));
        client.print(F("\t\t\t\t}]\n\t\t\t},\n"));
        client.print(F("\t\t\toptions: {\n\t\t\t\tresponsive: true,\n"));
        client.print(F("\t\t\t\ttitle: {\n\t\t\t\t\tdisplay: true,\n\t\t\t\t\ttext: '温度取得履歴'\n\t\t\t\t},\n"));
        client.print(F("\t\t\t\tlegend: {\n\t\t\t\t\tdisplay: true\n\t\t\t\t},\n"));
        client.print(F("\t\t\t\ttooltips: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tmode: 'index'\n\t\t\t\t},\n"));
        client.print(F("\t\t\t\tscales: {\n\t\t\t\t\txAxes: [{\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\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"));
        client.print(F("\t\t\t\t\tyAxes: [{\n\t\t\t\t\t\tid:'y1',\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度1[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t}\n"));
        client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y2',\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度2[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t}\n"));
        client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y3',\n\t\t\t\t\t\tposition: 'right',\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度3[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t\t}\n"));
        client.print(F("\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\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度4[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}],\n"));
        client.print(F("\t\t\t\t}\n\t\t\t}\n\t\t};\n")); 
        client.print(F("\t\twindow.onload = function() {\n\t\t\tvar ctx = document.getElementById('canvas').getContext('2d');\n"));
        client.print(F("\t\t\twindow.myLine = new Chart(ctx, config);\n\t\t};\n"));
        client.print(F("</script>\n"));
        client.print(F("</BODY></html>"));
}
//--------------------------
void checkWebPage( EthernetClient client)
{
        Serial.println(F("new webClient"));
        boolean restart = false;
        if (client) {
                TextFinder  finder(client );
                while (client.connected()) {
                        //digitalWrite(LED, HIGH);
                        if (client.available()) {
                                //この部分はすべてのテキスト検索を行います。
                                if( finder.find("GET /") ) {
                                        // 「setup」とい語が見つかった場合は、さらに探してください。
                                        // その単語が見つからない場合は、検索を停止して先に進みます。
                                        // これにより、後でスケッチに独自のWebページを配置できます。
                                        if (finder.findUntil("setup", "\n\r")){
                                                long cord = finder.getValue();
                                                sprintf(buf1,"setupIn=%d",cord);
                                                Serial.println(buf1);
                                                switch(cord){
                                                        case 1:
                                                                // 「SBM」という単語が見つかった場合は、さらに探し続けます。
                                                                // その言葉が見つからない場合は、探して停止します。
                                                                // SUBMITボタンが押されていない、何も押されていないことを意味します
                                                                // セットアップページが構築されている場所に移動し、クライアントのブラウザに表示します。
                                                                if (finder.findUntil("SBM", "\n\r")){
                                                                        byte SET = finder.getValue();
                                                                        // これで、「DT」という文字を探している間に、「DT」の後ろにあるすべての数字を覚えて、
                                                                        // 値を一致させて、mac、ip、subnet、およびgatewayに入れる必要があります。
                                                                        while(finder.findUntil("DT", "\n\r")){
                                                                                int val = finder.getValue();
                                                                                // 「DT」のvalが1?6の場合、対応する値はMAC値でなければなりません。
                                                                                if(val >= 1 && val <= 6) {
                                                                                        mac[val - 1] = finder.getValue();
                                                                                }
                                                                                // 「DT」のvalが7?10の場合、対応する値はIP値でなければなりません。
                                                                                if(val >= 7 && val <= 10) {
                                                                                        ip[val - 7] = finder.getValue();
                                                                                }
                                                                                // 「DT」のvalが11?14の場合、対応する値はMASK値でなければなりません。
                                                                                if(val >= 11 && val <= 14) {
                                                                                        subnet[val - 11] = finder.getValue();
                                                                                }
                                                                                // 「DT」のvalが15?18の場合、対応する値はGW値でなければなりません。
                                                                                if(val >= 15 && val <= 18) {
                                                                                        gateway[val - 15] = finder.getValue();
                                                                                }  
                                                                                // 「DT」のvalが19?22の場合、対応する値はTimeServer値でなければなりません。
                                                                                if(val >= 19 && val <= 22) {
                                                                                        timeServer[val - 19] = finder.getValue();
                                                                                }
                                                                        }
                                                                        // すべてのデータを取得したので、EEPROMに保存できます
                                                                        for (int i = 0 ; i < 6; i++){
                                                                                EEPROM.write(i + 1,mac[i]);
                                                                        }
                                                                        for (int i = 0 ; i < 4; i++){
                                                                                EEPROM.write(i + 7, ip[i]);
                                                                        }
                                                                        for (int i = 0 ; i < 4; i++){
                                                                                EEPROM.write(i + 11, subnet[i]);
                                                                        }
                                                                        for (int i = 0 ; i < 4; i++){
                                                                                EEPROM.write(i + 15, gateway[i]);
                                                                        }
                                                                        for (int i = 0 ; i < 4; i++){
                                                                                EEPROM.write(i + 19, timeServer[i]);
                                                                        }
                                                                        // IDを既知のビットに設定します。したがって、Arduinoをリセットすると、EEPROM値が使用されます。
                                                                        EEPROM.write(0, ID);
                                                                        sprintf(MacAddressStr,"%02x.%02x.%02x.%02x.%02x.%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
                                                                        sprintf(IPAddressStr,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
                                                                        sprintf(SubnetMaskStr,"%d.%d.%d.%d",subnet[0],subnet[1],subnet[2],subnet[3]);
                                                                        sprintf(GatewayStr,"%d.%d.%d.%d",gateway[0],gateway[1],gateway[2],gateway[3]);
                                                                        // すべてのデータがEEPROMに書き込まれている場合、arduinoをリセットする必要があります。
                                                                        //ハードウェアリセットボタンを使用する必要があります。
                                                                        restart = true;
                                                                }else{
                                                                        
                                                                }
                                                                // この時点から、セットアップページの構築を開始し、クライアントのブラウザーに表示できます。
                                                                SetWebPage(client);
                                                                break;
                                                        case 2:
                                                                // 新規にユーティリティ頁を作りました。
                                                                Serial.println(F("SetPage1Day"));
                                                                rtclock.getTime(tmm);
                                                                sprintf(DateTimeStr,"%04u/%02u/%02u %02u:%02u:%02u",tmm.year+1970, tmm.month, tmm.day,tmm.hour, tmm.minute, tmm.second);
                                                                SetPage1Day(client);
                                                                break;
                                                        case 3:
                                                                //utils.jsが要求された。
                                                                Serial.println(F("utils.js"));
                                                                LoadUtilsJS(client);
                                                                break;
                                                        case 4:
                                                                //新規に一時間分の分単位グラフ表示を作りました
                                                                Serial.println(F("SetPage1Hour"));
                                                                rtclock.getTime(tmm);
                                                                sprintf(DateTimeStr,"%04u/%02u/%02u %02u:%02u:%02u",tmm.year+1970, tmm.month, tmm.day,tmm.hour, tmm.minute, tmm.second);
                                                                SetPage1Hour(client);
                                                                break;
                                                       case 9:
                                                                //トップページに戻る方法として追加しました。
                                                                Serial.println(F("Home"));
                                                                pageIntroduction(client);
                                                                break;
                                                        default:
                                                                PrintResponse404(client );
                                                                break;   
                                                }
                                        }else{
                                              pageIntroduction(client);  
                                        }
                                }
                                break;
                        }
                        PrintResponse404(client );
                }
                delay(1);
                client.stop();
                if(restart)     nvic_sys_reset();
        }     
}
//----------------------------2022年2月18日メニュー追加 2023年7月11日レタッチ
void pageIntroduction( EthernetClient client){
        client.println(F("HTTP/1.1 200 OK\nContent-Type: text/html\n\n"));
        //client.println(F("Content-Type: text/html"));
        //client.println();
        // put your own html from here on
        sprintf(buf1,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
        client.println(F("<HTML>\n<HEAD>\n\t<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;CHARSET=UTF-8\">\n</HEAD>\n<BODY BGCOLOR='#ffffff'>\n<H2><CENTER><FONT COLOR='#00ff00'>DS18B20 SetUp Menu</FONT></CENTER></H2>\n<P><CENTER><TABLE WIDTH='500' BORDER='0' CELLSPACING='0' CELLPADDING='0'>\n\t<TR>\n\t\t<TD WIDTH='100%'>\n\t\t<OL>\n"));
        //client.println(F("<BODY BGCOLOR='#ffffff'>\n<H2><CENTER><FONT COLOR='#00ff00'>DS18B20 SetUp Menu</FONT></CENTER></H2>\n"));
        //client.println(F("<P><CENTER><TABLE WIDTH='500' BORDER='0' CELLSPACING='0' CELLPADDING='0'>\n\t<TR>\n\t\t<TD WIDTH='100%'>\n\t\t<OL>\n"));
        sprintf(buffer,"\t\t\t<LI><FONT SIZE='+1'><A HREF=\"http://%s/setup1\">設定メニュー</A>\n",buf1);
        client.println(buffer);
        sprintf(buffer,"\t\t\t<LI><A HREF=\"http://%s/setup2\">温度履歴表示 時単位(最近一日)</A>\n",buf1);
        client.println(buffer);
        sprintf(buffer,"\t\t\t<LI><A HREF=\"http://%s/setup4\">温度履歴表示 分単位(最近一時間)</A></FONT>\n",buf1);
        client.println(buffer);
        client.print(F("\t\t</OL>\n\t\t</TD>\n\t</TR>\n</TABLE></CENTER>\n</BODY>\n</HTML>\n"));
        client.stop();
}
//--------------------------
void PrintResponse404( EthernetClient client )
{
        client.println(F("HTTP/1.1 404 Not Found\nContent-Type: text/html\nConnnection: close\n\n"));
        //client.println(F("Content-Type: text/html"));
        //client.println(F("Connnection: close")); 
        //client.println();
        client.stop();
}
//--------------------------
void LoadUtilsJS( EthernetClient client ){                              //2023/07/11 少しでも纏めてみた。
        client.println("HTTP/1.1 200 OK\nContent-Type: text/html\n\n");
        //client.println("Content-Type: text");
        //client.println();
        //
        client.println("'use strict';\nwindow.chartColors = {\n\tred: 'rgb(255, 99, 132)',\n\torange: 'rgb(255, 159, 64)',\n\tyellow: 'rgb(255, 205, 86)',\n\tgreen: 'rgb(75, 192, 192)',\n\tblue: 'rgb(54, 162, 235)',\npurple: 'rgb(153, 102, 255)',\n\tgrey: 'rgb(201, 203, 207)'\n};\n");
        //
        //client.println("window.chartColors = {");
        //client.println("\tred: 'rgb(255, 99, 132)',");
        //client.println("\torange: 'rgb(255, 159, 64)',");
        //client.println("\tyellow: 'rgb(255, 205, 86)',");
        //client.println("\tgreen: 'rgb(75, 192, 192)',");
        //client.println("\tblue: 'rgb(54, 162, 235)',");
        //client.println("\tpurple: 'rgb(153, 102, 255)',");
        //client.println("\tgrey: 'rgb(201, 203, 207)'");
        //client.println("};\n");
        //
        client.println("(function(global) {\n\tvar MONTHS = [\n\t\t'January',\n\t\t'February',\n\t\t'March',\n\t\t'April',\n\t\t'May',\n\t\t'June',\n\t\t'July',\n\t\t'August',\n\t\t'September',\n\t\t'October',\n\t\t'November',\n\t\t'December'\n\t];\n");
        //client.println("\tvar MONTHS = [");
        //client.println("\t\t'January',");
        //client.println("\t\t'February',");
        //client.println("\t\t'March',");
        //client.println("\t\t'April',");
        //client.println("\t\t'May',");
        //client.println("\t\t'June',");
        //client.println("\t\t'July',");
        //client.println("\t\t'August',");
        //client.println("\t\t'September',");
        //client.println("\t\t'October',");
        //client.println("\t\t'November',");
        //client.println("\t\t'December'");
        //client.println("\t];\n");
        //
        client.println("\tvar COLORS = [\n\t\t'#4dc9f6',\n\t\t'#f67019',\n\t\t'#f53794',\n\t\t'#537bc4',\n\t\t'#acc236',\n\t\t'#166a8f',\n\t\t'#00a950',\n\t\t'#58595b',\n\t\t'#8549ba'\n\t];\n");
        //client.println("\t\t'#4dc9f6',");
        //client.println("\t\t'#f67019',");
        //client.println("\t\t'#f53794',");
        //client.println("\t\t'#537bc4',");
        //client.println("\t\t'#acc236',");
        //client.println("\t\t'#166a8f',");
        //client.println("\t\t'#00a950',");
        //client.println("\t\t'#58595b',");
        //client.println("\t\t'#8549ba'");
        //client.println("\t];\n");
        //
        client.println("\tvar Samples = global.Samples || (global.Samples = {});\n\tvar Color = Chart.helpers.color;\n");
        //client.println("\tvar Color = Chart.helpers.color;\n");
        //
        client.println("\tfunction applyDefaultNumbers(config) {\n\t\tvar cfg = config || {};\n\t\tcfg.min = cfg.min || 0;\n\t\tcfg.max = cfg.max || 1;\n\t\tcfg.from = cfg.from || [];\n\t\tcfg.count = cfg.count || 8;\n\t\tcfg.decimals = cfg.decimals || 8;\n\t\tcfg.continuity = cfg.continuity || 1;\n");
        //client.println("\t\tvar cfg = config || {};");
        //client.println("\t\tcfg.min = cfg.min || 0;");
        //client.println("\t\tcfg.max = cfg.max || 1;");
        //client.println("\t\tcfg.from = cfg.from || [];");
        //client.println("\t\tcfg.count = cfg.count || 8;");
        //client.println("\t\tcfg.decimals = cfg.decimals || 8;");
        //client.println("\t\tcfg.continuity = cfg.continuity || 1;\n");
        //
        client.println("\t\treturn cfg;\n\t}\n");
        //client.println("\t}\n");
        //
        client.println("\tSamples.utils = {\n\t\t// Adapted from http://indiegamr.com/generate-repeatable-random-numbers-in-js/\n\t\tsrand: function(seed) {\n\t\t\tthis._seed = seed;\n\t\t},\n");
        //client.println("\t\t// Adapted from http://indiegamr.com/generate-repeatable-random-numbers-in-js/");
        //client.println("\t\tsrand: function(seed) {");
        //client.println("\t\t\tthis._seed = seed;");
        //client.println("\t\t},\n");
        //
        client.println("\t\trand: function(min, max) {\n\t\t\tvar seed = this._seed;\n\t\t\tmin = min === undefined ? 0 : min;\n\t\t\tmax = max === undefined ? 1 : max;\n\t\t\tthis._seed = (seed * 9301 + 49297) % 233280;\n\t\t\treturn min + (this._seed / 233280) * (max - min);\n\t\t},\n");
        //client.println("\t\t\tvar seed = this._seed;");
        //client.println("\t\t\tmin = min === undefined ? 0 : min;");
        //client.println("\t\t\tmax = max === undefined ? 1 : max;");
        //client.println("\t\t\tthis._seed = (seed * 9301 + 49297) % 233280;");
        //client.println("\t\t\treturn min + (this._seed / 233280) * (max - min);");
        //client.println("\t\t},\n");
        //
        client.println("\t\tnumbers: function(config) {\n\t\t\tvar cfg = applyDefaultNumbers(config);\n\t\t\tvar dfactor = Math.pow(10, cfg.decimals) || 0;\n\t\t\tvar data = [];\n\t\t\tvar i, value;\n");
        //client.println("\t\t\tvar cfg = applyDefaultNumbers(config);");
        //client.println("\t\t\tvar dfactor = Math.pow(10, cfg.decimals) || 0;");
        //client.println("\t\t\tvar data = [];");
        //client.println("\t\t\tvar i, value;\n");
        //
        client.println("\t\t\tfor (i = 0; i < cfg.count; ++i) {\n\t\t\t\tvalue = (cfg.from[i] || 0) + this.rand(cfg.min, cfg.max);\n\t\t\t\tif (this.rand() <= cfg.continuity) {\n\t\t\t\t\tdata.push(Math.round(dfactor * value) / dfactor);\n\t\t\t\t} else {\n\t\t\t\t\tdata.push(null);\n\t\t\t\t}\n\t\t\t}\n");
        //client.println("\t\t\t\tvalue = (cfg.from[i] || 0) + this.rand(cfg.min, cfg.max);");
        //client.println("\t\t\t\tif (this.rand() <= cfg.continuity) {");
        //client.println("\t\t\t\t\tdata.push(Math.round(dfactor * value) / dfactor);");
        //client.println("\t\t\t\t} else {");
        //client.println("\t\t\t\t\tdata.push(null);");
        //client.println("\t\t\t\t}");
        //client.println("\t\t\t}\n");
        //
        client.println("\t\t\treturn data;\n\t\t},\n");
        //client.println("\t\t},\n");
        //
        client.println("\t\tlabels: function(config) {\n\t\t\tvar cfg = config || {};\n\t\t\tvar min = cfg.min || 0;\n\t\t\tvar max = cfg.max || 100;\n\t\t\tvar count = cfg.count || 8;\n\t\t\tvar step = (max - min) / count;\n\t\t\tvar decimals = cfg.decimals || 8;\n\t\t\tvar dfactor = Math.pow(10, decimals) || 0;\n\t\t\tvar prefix = cfg.prefix || '';\n\t\t\tvar values = [];\n\t\t\tvar i;\n");
        //client.println("\t\t\tvar cfg = config || {};");
        //client.println("\t\t\tvar min = cfg.min || 0;");
        //client.println("\t\t\tvar max = cfg.max || 100;");
        //client.println("\t\t\tvar count = cfg.count || 8;");
        //client.println("\t\t\tvar step = (max - min) / count;");
        //client.println("\t\t\tvar decimals = cfg.decimals || 8;");
        //client.println("\t\t\tvar dfactor = Math.pow(10, decimals) || 0;");
        //client.println("\t\t\tvar prefix = cfg.prefix || '';");
        //client.println("\t\t\tvar values = [];");
        //client.println("\t\t\tvar i;\n");
        //
        client.println("\t\t\tfor (i = min; i < max; i += step) {\n\t\t\t\tvalues.push(prefix + Math.round(dfactor * i) / dfactor);\n\t\t\t}\n");
        //client.println("\t\t\t\tvalues.push(prefix + Math.round(dfactor * i) / dfactor);");
        //client.println("\t\t\t}\n");
        //
        client.println("\t\t\treturn values;\n\t\t},\n");
        //client.println("\t\t},\n");
        //
        client.println("\t\tmonths: function(config) {\n\t\t\tvar cfg = config || {};\n\t\t\tvar count = cfg.count || 12;\n\t\t\tvar section = cfg.section;\n\t\t\tvar values = [];\n\t\t\tvar i, value;\n");
        //client.println("\t\t\tvar cfg = config || {};");
        //client.println("\t\t\tvar count = cfg.count || 12;");
        //client.println("\t\t\tvar section = cfg.section;");
        //client.println("\t\t\tvar values = [];");
        //client.println("\t\t\tvar i, value;\n");
        //
        client.println("\t\t\tfor (i = 0; i < count; ++i) {\n\t\t\t\tvalue = MONTHS[Math.ceil(i) % 12];\n\t\t\t\tvalues.push(value.substring(0, section));\n\t\t\t}\n");
        //client.println("\t\t\t\tvalue = MONTHS[Math.ceil(i) % 12];");
        //client.println("\t\t\t\tvalues.push(value.substring(0, section));");
        //client.println("\t\t\t}\n");
        //
        client.println("\t\t\treturn values;\n\t\t},\n");
        //client.println("\t\t},\n");
        //
        client.println("\t\tcolor: function(index) {\n\t\t\treturn COLORS[index % COLORS.length];\n\t\t},\n");
        //client.println("\t\t\treturn COLORS[index % COLORS.length];");
        //client.println("\t\t},\n");
        //
        client.println("\t\ttransparentize: function(color, opacity) {\n\t\t\tvar alpha = opacity === undefined ? 0.5 : 1 - opacity;\n\t\t\treturn Color(color).alpha(alpha).rgbString();\n\t\t}\n\t};\n");
        //client.println("\t\t\tvar alpha = opacity === undefined ? 0.5 : 1 - opacity;");
        //client.println("\t\t\treturn Color(color).alpha(alpha).rgbString();");
        //client.println("\t\t}");
        //client.println("\t};\n");
        //
        client.println("\t// DEPRECATED\n\twindow.randomScalingFactor = function() {\n\t\treturn Math.round(Samples.utils.rand(-100, 100));\n\t};\n");
        //client.println("\twindow.randomScalingFactor = function() {");
        //client.println("\t\treturn Math.round(Samples.utils.rand(-100, 100));");
        //client.println("\t};\n");
        //
        client.println("\t// INITIALIZATION\n\n\tSamples.utils.srand(Date.now());\n");
        //
        //client.println("\tSamples.utils.srand(Date.now());\n");
        //
        client.println("\t// Google Analytics\n\t/* eslint-disable */\n\tif (document.location.hostname.match(/^(www\\.)?chartjs\\.org$/)) {\n\t\t(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n\t\t(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n\t\tm=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n\t\t})(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\t\tga('create', 'UA-28909194-3', 'auto')\n\t\tga('send', 'pageview');\n\t}\n\t/* eslint-enable */\n");
        //client.println("\t/* eslint-disable */");
        //client.println("\tif (document.location.hostname.match(/^(www\\.)?chartjs\\.org$/)) {");
        //client.println("\t\t(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){");
        //client.println("\t\t(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),");
        //client.println("\t\tm=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)");
        //client.println("\t\t})(window,document,'script','//www.google-analytics.com/analytics.js','ga');");
        //client.println("\t\tga('create', 'UA-28909194-3', 'auto');");
        //client.println("\t\tga('send', 'pageview');");
        //client.println("\t}");
        //client.println("\t/* eslint-enable */\n");
        //
        client.println("}(this));");
}
//-------指定されたアドレスのタイムサーバーにNTP要求を送信します
void    sendNTPpacket(byte address[]){
        memset(packetBuffer, 0, NTP_PACKET_SIZE);               //バッファ内のすべてのバイトを0に設定します
        //NTP要求を形成するために必要な値を初期化する
        packetBuffer[0]         = 0b11100011;                   // LI, Version, Mode
        packetBuffer[1]         = 0;                            //階層、またはクロックのタイプ
        packetBuffer[2]         = 6;                            //ポーリング間隔
        packetBuffer[3]         = 0xEC;                         //ピアクロックの精度
        //ルート遅延およびルート分散用のゼロの8バイト
        packetBuffer[12]        = 49;
        packetBuffer[13]        = 0x4E;
        packetBuffer[14]        = 49;
        packetBuffer[15]        = 52;
        //すべてのNTPフィールドに値が与えられました。
        //タイムスタンプを要求するパケットを送信できます:
        Udp.beginPacket(address, 123);                          //NTPリクエストはポート123へ
        Udp.write(packetBuffer, NTP_PACKET_SIZE);
        Udp.endPacket();
}
//-----------------     割込CallBack      修正2023/07/12 500msec毎に呼び出され、表示更新する様にした。
void TimeUpdate(void){
        //500msec毎に呼ばれる
        OperatingTime++;
        if(OperatingTime%2)     dot     =       0b00010000;
        else                    dot     =       0b00000100;
        //時刻チェック
        rtclock.getTime(tmm);
        h = tmm.hour;                           //返値0-23
        m = tmm.minute;                         //返値0-59
        //
        if(lastKey != 0){
                switch(lastKey){
                        case 0x01:                                      //温度1を表示
                                //sprintf(STRBUF,"%06d",int(gHourBuf[preMSet][0]  * 100.0));
                                //LedAndKey.setDisplayToString(STRBUF,0b00000100,4);
                                Temp1 = int(gHourBuf[preMSet][0]  * 100.0);
                                LedAndKey.setDisplayToDecNumber(Temp1,0b00000100,false);
                                break;
                        case 0x02:                                      //温度2を表示
                                //sprintf(STRBUF,"%06d",int(gHourBuf[preMSet][1]  * 100.0));
                                //LedAndKey.setDisplayToString(STRBUF,0b00000100,4);
                                Temp2 = int(gHourBuf[preMSet][1]  * 100.0);
                                LedAndKey.setDisplayToDecNumber(Temp2,0b00000100,false);
                                break;
                        default:                                        //時刻表示
                                //
                                DispTime    =       h*10000 + m*100 + tmm.second;
                                //sprintf(STRBUF,"%02u%02u%02u",h,m,tmm.second);
                                //LedAndKey.setDisplayToString(STRBUF,0,2);
                                LedAndKey.setDisplayToDecNumber(DispTime,dot,false);
                                break;
                }
        }
        if(preSet != h){
                //1時間おきに時刻を確認し、データをメモリに確保
                preSet  = h;
                float   celsius;
                //本計測
                for (int i = 0;i<devNum;i++){
                        GetDSTemp(celsius,i);
                        if(celsius != 0.0){
                              gDayBuf[h][i]   =       celsius;  
                        }
                }
                //次回分のデータをNULL化
                h = (h+1) % 24;
                for (int i = 0;i<devNum;i++){
                         gDayBuf[h][i]   =       NAN;
                }
        }else if(preMSet != m){
                //1分おきにデータ取込
                preMSet  = m;
                float   celsius;
                //本計測
                for (int i = 0;i<devNum;i++){
                        GetDSTemp(celsius,i);
                        if(celsius != 0.0){
                              gHourBuf[m][i]    =       celsius;  
                        }
                }
                //次回分のデータをNULL化
                m = (m+1) % 60;
                for (int i = 0;i<devNum;i++){
                         gHourBuf[m][i]         =       NAN;
                }
                if(!fDoneTime){
                        fDoneTime               = checkNTP();
                }
        }else{
                //計測しない
        }
        keys    = LedAndKey.getButtons();
        if(keys != 0){
                lastKey = keys;
                LedAndKey.setLEDs(lastKey);
        }
}
//------------------
bool SetDSDevice(int index) {
        byte i;
        byte present = 0;
        byte type_s;
        byte data[12];
        byte addr[8];
        //float celsius;
        if ( !ds.search(addr)) {
                Serial.println(F("No more addresses."));
                ds.reset_search();
                delay(100);
                return false;
        }else{
                memcpy(gDS[index], addr, sizeof(addr));
                return true;
        }
}
//------------------
void GetDSTemp(float &celsius,int index) {
        byte i;
        byte present = 0;
        byte type_s;
        byte data[12];
        byte addr[8];
        //float celsius;
        /* 検索不要
        for (int i;i<devNum;i++){
                ds.search(addr);
                if(memcmp(addr, gDS[i], sizeof(addr)) == 0)     break;
        }
        ds.reset_search();
        */
        if (OneWire::crc8(gDS[index], 7) != gDS[index][7]) {
                Serial.println(F("CRC is not valid!"));
                return;
        }
        // 最初のROMバイトはチップ種を示します
        switch (gDS[index][0]) {
                case 0x10:
                        Serial.println(F("  Chip = DS18S20"));          // or old DS1820
                        type_s = 1;
                        break;
                case 0x28:
                        Serial.println(F("  Chip = DS18B20"));
                        type_s = 0;
                        break;
                case 0x22:
                        Serial.println(F("  Chip = DS1822"));
                        type_s = 0;
                        break;
                default:
                        Serial.println(F("Device is not a DS18x20 family device."));
                        return;
        }
        ds.reset();
        ds.select(gDS[index]);
        ds.write(0x44, 1);                              // 最後に寄生物の電源を入れて、変換を開始します
        delay(750);                                     // 多分750msで十分かもしれません12bit分解能の場合
        // ここでds.depower()を実行する場合がありますが、リセットによって処理されます。
        present = ds.reset();
        ds.select(gDS[index]);    
        ds.write(0xBE);                                 // スクラッチパッドを読む
        //Serial.print(F("  Data = "));
        //Serial.print(present, HEX);
        //Serial.print(F(" "));
        for ( i = 0; i < 9; i++) {                      // we need 9 bytes
                data[i] = ds.read();
                //Serial.print(data[i], HEX);
                //Serial.print(F(" "));
        }
        //Serial.print(F(" CRC="));
        //Serial.print(OneWire::crc8(data, 8), HEX);
        //Serial.println();
        //結果は16ビットの符号付き整数であるため、データを実際の温度に変換します。
        //データは「int16_t」タイプに格納する必要があります。
        //これは、32ビットプロセッサでコンパイルした場合でも常に16ビットです。
        int16_t raw = (data[1] << 8) | data[0];
        if (type_s) {
                raw = raw << 3;                         // デフォルトの9ビット解像度
                if (data[7] == 0x10) {                  // 「残り数」は完全な12ビットの解像度を提供します
                        raw = (raw & 0xFFF0) + 12 - data[6];
                }
        } else {
                byte cfg = (data[4] & 0x60);
                // 低解像度では、下位ビットは未定義なので、ゼロにしましょう
                if (cfg == 0x00) raw = raw & ~7;        // 9ビットの解像度、93.75ミリ秒
                else if (cfg == 0x20) raw = raw & ~3;   // 10ビットの解像度、187.5ミリ秒
                else if (cfg == 0x40) raw = raw & ~1;   // 11ビットの解像度、375ミリ秒
                // デフォルトは12ビットの解像度、750ミリ秒の変換時間です
        }
        celsius = (float)raw / 16.0;
        //fahrenheit = celsius * 1.8 + 32.0;
        Serial.print(F("  Temperature = "));    Serial.println(celsius);
        return;
}
//-----------------
int     getHourTime(void){
        rtclock.getTime(tmm1);
        return tmm1.hour;
}
//-----------------
int     getMinuteTime(void){
        rtclock.getTime(tmm1);
        return tmm1.minute;
}
//----------------
bool checkNTP(){
        sendNTPpacket(timeServer);                              //NTPパケットをタイムサーバーに送信する
        delay(300);                                            //返信が利用可能かどうかを確認するのを待ちます
        if ( Udp.parsePacket() ) {
                //パケットを受信し、そこからデータを読み取ります
                Udp.read(packetBuffer, NTP_PACKET_SIZE);        //パケットをバッファに読み込みます
                //タイムスタンプは、受信したパケットのバイト40から始まり、4バイト、つまり2ワードの長さです。
                unsigned long secsSince1900;
                // convert four bytes starting at location 40 to a long integer
                secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
                secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
                secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
                secsSince1900 |= (unsigned long)packetBuffer[43];
                unsigned long epoch   = secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
                rtclock.setTime(time_t(epoch));                 //JSTを内部時計にセット
                Serial.print((epoch  % 86400L) / 3600);         //時間を印刷します(86400は1日あたりの秒数に相当)
                Serial.print(':');
                int min = (epoch % 3600) / 60;
                if ( min < 10 ) {
                        Serial.print('0');                      //各時間の最初の10分では、先頭に「0」が必要です。
                }
                Serial.print(min);                              //分を印刷する(3600は1分あたりの秒数に等しい)
                Serial.print(':');
                int sec = epoch % 60;
                if ( sec < 10 ) {
                        Serial.print('0');                      //各分の最初の10秒で、先頭に「0」が必要になります
                }
                Serial.println(sec);                            //秒を印刷
                return true;
        }else{
                return false;
        }
}
//----------------
void setup()
{
        // Open serial communications and wait for port to open:
        Serial.begin(115200);                                   //シリアル通信を開ます。
        pinMode(BUILTIN_LED,OUTPUT);    digitalWrite(BUILTIN_LED,LOW);
        pinMode(LED1,OUTPUT);           digitalWrite(LED1, HIGH);
        pinMode(LED2,OUTPUT);           digitalWrite(LED2, LOW);
        //Ethernet3API
        Ethernet.setCsPin(SPI1_NSS_PIN);
        Ethernet.setRstPin(W550io_Rst);
        pinMode(W550io_Rst, OUTPUT);
        digitalWrite(W550io_Rst, LOW);
        delay(10);
        digitalWrite(W550io_Rst, HIGH);
        Serial.print(F("NIC_Reset\n"));
        LANSetup();
        //イーサネットとUDPを開始します
        Udp.begin(localPort);
        Serial.print(F("server is at "));Serial.println(Ethernet.localIP());
        fDoneTime       = checkNTP();
        rtclock.getTime(tmm);
        sprintf(STRBUF,"%02u%02u%02u",tmm.hour,tmm.minute,tmm.second);
        LedAndKey.setDisplayToString(STRBUF,0b00010100,2);
        //LedAndKey.setDisplayToString("000000",0,2);
        Serial.print(F("server is at "));Serial.println(Ethernet.localIP());
        webServer.begin();
        //データバッファクリア
        for(int i = 0;i<24;i++){
                for(int j = 0;j<4;j++){
                        gDayBuf[i][j] = NAN;
                }
        }
        for(int i = 0;i<60;i++){
                for(int j = 0;j<4;j++){
                        gHourBuf[i][j] = NAN;
                }
        }
        //DS18B20の初期化
        for(int i = 0;i<10;i++){
                if(!SetDSDevice(i)){
                        devNum = i;
                        break;
                }
        }
        //タイマ割込設定
        Timer1.pause();                                                 //
        Timer1.setPrescaleFactor(7200);                                 // 72MHz100uSEC
        Timer1.setOverflow(5000);                                      // 500mSEC
        Timer1.attachInterrupt(TIMER_UPDATE_INTERRUPT,TimeUpdate);      // 割り込みサーブルーチンの宣言:TimeUpdate
        Timer1.setCount(0);                                             // 0
        Timer1.refresh();
        Timer1.resume(); 
        //
        iwdg_init_ms(wdgTime);                                         //ウォッチドッグをオンにして、オーバーフロー時間を設定します。
        Serial.println(F("EndSetUp"));
}
//----------------
void loop()
{
        //このLoopはscantime=1秒程度です。そのため5秒経っても戻らなかったらリセットすることにします。
        iwdg_feed();                                                    //ウォッチドッグタイマーをリセットするには、ドッグ操作をフィードします
        //
        if(!(OperatingTime % 3600)){                                    //1時間に一回
                fDoneTime       = checkNTP();     
        }
        if(!(OperatingTime % 60))       Serial.println(F("."));
        else                            Serial.print(F("."));
        //digitalWrite(BUILTIN_LED,OperatingTime % 2);
        client          = webServer.available();                        //HTTP要求確認
        if(client)      checkWebPage(client);
        client.stop();                                                  // コネクションを閉じる。
        if(OperatingTime % 2){
                digitalWrite(LED1, LOW);
                digitalWrite(LED2, HIGH);
        }else{
                digitalWrite(LED1, HIGH);
                digitalWrite(LED2, LOW);
        }
        delay(200);
}

よく判らないまま怪しいところを見つけました。MainLoop内で、NTP同期を定期的に実行しているのですが、これが30分に一回実行されていました。どうもこれが原因なのでは無いかと云うことで修正しました。

        if(!(OperatingTime % 3600)){                                    //1時間に一回
                fDoneTime       = checkNTP();     
        }

以下のように変更しました。

        if(!(OperatingTime % 7200)){                                    //1時間に一回
                fDoneTime       = checkNTP();     
        }

.ino

/*
 * 2023/07/18 T.Wanibe
 * 1.6.6 修正点:
 *      時刻表示が-30分という意味不明のバグがまだ改善しない。もう一度時刻表示コードを見直す
 *      checkNTP()の実行タイミングに確かに問題があった タイマ割込のインターバルを500msecに変更した点を反映していなかった
 * 1.6.5 修正点:
 *      1.6.4で時刻表示が-30分という意味不明のバグがあったので、もう一度時刻表示コードを見直す
 *      ブラウザ表示で[Return]ボタンを追加
 *      lED&kEYのコールがMainLoopと割込Loopでバッティングしているので割込Loopのみに見直す
 * 1.6.4 修正点:
 *      時刻表示の改善が無かったので別の手段を試みた
 *      やはりタイマ割込を導入して1秒毎の更新となるように変更 ※温度計測はタイマ割込にすると処理時間の問題が出るのでメインループで実行する。
 * 1.6.3 修正点:
        時刻表示が1時間ずれるときがある。演算方法に問題があるようなので、他のコードからこの機能分を移植し直す
 * 1.6.2 修正点:
 *      経過時間表示がオーバフローしてしまう問題を修正
 *      IP設定画面の入力枠内を右寄せ表示に修正
 * 1.6.0 修正点:
 *      毎分の温度変化をグラフ表示出来る様に修正したいと考えました。setup3
 * 1.5.1 修正点:
 *      コードに無駄があったので修正した。接続デバイス数はsetup()内で自動判別するのが良いと思い変更
 * 1.5.0 修正点:
 *      ダミー計測をすることで値が0.0になることはなくなったが、2つのDS18B20を取り違えて計測してしまう事があり、連続性に問題がある。
 *      コードを変更してsetup()時に接続されているDS18B20のindexListを取得し、計測時にIDが合致するデータ列を意識するように変更した 
 * 1.4.2 修正点:
 *      計測前にdelayは効果無し 結果を見る限り定期的に三時間毎に0.0になっているので、ダミー計測を試すことにした。
 * 1.4.1 修正点:
 *      ch1のDS18B20のデータ取得に失敗するケースの対策が不十分 よく判らないが、計測前にdelayを入れてみる
 * 1.4.0 修正点:
 *      一時間毎のデータで0と云う値が出ている。これはおかしい。データ取得に失敗している。
 *      2ch目では発生していないことから、データ取得時待ち時間を置いてからデータ取得するように修正 
 *コメント
 *      DS18B20をブラウザ表示するソフトウエアコードを書いているのですが、03までのスケッチは期待通りに動作しません。
 *      時刻同期がなぜか失敗することが問題です。
 *      そこでベースとなるコードを変更して、機能追加し実現してみることにしました。
 *      以下はオリジナルコードのコメントです。
 *      このコードはEthernet3のExample“Udp NTP Client”をSTM32MINIShieldで動く様にレタッチしました。.
 *      BluePillにはRTCが搭載されていますが、精度が悪くバックアップ電源もありません。※接続は可能です
 *      そこで起動時にNTPで時刻所得して登録し、LED&KEYに時刻表示します。
 *      以後毎秒時刻更新します。
 *      1時間毎にNTPにアクセスして時刻調整します。
 *      Michael Margolis氏が2010年9月4日に作成したモノをレタッチしています。
 * 最大131072バイトのフラッシュメモリのうち、スケッチが56552バイト(43%)を使っています。
 * 最大20480バイトのRAMのうち、グローバル変数が4576バイト(22%)を使っていて、ローカル変数で15904バイト使うことができます。
 */
#include <libmaple/iwdg.h>
#include <SPI.h>
#include <Ethernet3.h>
#include <EthernetUdp3.h>
#include <TM1638.h>
#include <RTClock.h>
#include <EEPROM.h>
#include <avr/pgmspace.h>
#include <TextFinder.h>                                                 //WebSetting
#include <OneWire.h>                                                    //DS18B20通信用ライブラリ
//#include <DallasTemperature.h>
//PIN
#define W550io_Rst      PA8                                             //NIC_Reset
#define SPI1_NSS_PIN    PA4                                             //NIC_ChipSelec
#define UpdateInterval  86400                                           //更新間隔
#define dataPin         PB4
#define clockPin        PB3
#define strobePin       PA15
#define BUILTIN_LED     PC13
#define DS18B20Port     PA10
#define LED1            PB8
#define LED2            PB9
#define HttpPort        80                                              //HTTP
#define debug           1
#define iwdg_init_ms(N) iwdg_init(IWDG_PRE_256,((N)/8))                 //設定時間をmsecとするためにマクロを用意する。
#define vers            "STM32miniShield DS18B20 1.6"
#define NTP_PACKET_SIZE 48
#define SECS_PER_HOUR   3600
#define maxDevices      10
//コントローラのMACアドレスを以下に入力してください。
//新しいイーサネットシールドには、シールドのステッカーにMACアドレスが印刷されています
const char      FVirsion[]      = "1.6.6";
byte            mac[]           = {0x00,0x08,0xDC,0x54,0x4D,0xD1};      //Wiznet
byte            ip[]            = {192, 168, 0, 205};
byte            dns_server[]    = {192, 168, 0, 1};
byte            gateway[]       = {0, 0, 0, 0};
byte            subnet[]        = {255, 255, 255, 0};
byte            timeServer[]    = {192,168,0,199}; 
byte            packetBuffer[ NTP_PACKET_SIZE];                         //着信および発信パケットを保持するバッファ
byte            keys,lastKey;
//
unsigned int    localPort       = 8888;                                 //UDPパケットをリッスンするローカルポート
char            STRBUF[32];
char            buffer[128];
int             timeZone        = 9;                                    // change to your timezone
//オブジェクトコンストラクタ
EthernetServer  webServer(HttpPort);
EthernetClient  client;
RTClock rtclock (RTCSEL_LSE);                                           //RTC初期化
EthernetUDP     Udp;                                                    //UDPを介してパケットを送受信できるようにするUDPインスタンス
tm_t            tmm,tmm1;
TM1638          LedAndKey(dataPin, clockPin, strobePin);                //データピンPB4、クロックピンPB3、およびストローブピンPA15でモジュールを定義する
const byte      ID = 0x9B;
char            buf1[32];
char            buf2[32];
char            MacAddressStr[20];
char            IPAddressStr[20];
char            SubnetMaskStr[20];
char            GatewayStr[20];
char            NTPserverStr[20];
char            DateTimeStr[20];
String          DateStr;
String          TimeStr;
float           gDayBuf[24][4];                                         //24時間分4要素データ確保
float           gHourBuf[60][4];                                        //24時間分4要素データ確保
unsigned long   OperatingTime   = 0;                                    //稼働時間 Count2で1秒
OneWire         ds(PA10);                                               // on pin 10 (a 4.7K resistor is necessary)
boolean         fDoneTime       = false;
int             wdgTime         = 40000;
int             devNum          = maxDevices;                           //DS18B20の接続数 初期値は2としておきます。 メモリ確保のため
byte            gDS[maxDevices][8];
byte            h;                                                      //返値0-23
byte            m;                                                      //返値0-59
byte            dot             = 0;
unsigned long   DispTime;
int             preSet          = -1;
int             preMSet         = -1;
int             Temp1,Temp2;
//----------------------------------
void LANSetup(){
        int idcheck = EEPROM.read(0);
        if (idcheck != ID){
                //idがIDの値ではない場合、
                //このスケッチがシールドを設定する前に使用されていなかったことを意味します
                //スケッチの始めに書かれた値を使用するだけです
        }
        if (idcheck == ID){
                //idがIDと同じ値の場合、
                //これは、このスケッチがシールドを設定するために使用されたことを意味します。
                //EERPOMの値を読み取ってシールドを設定します。
                for (int i = 0; i < 6; i++){
                        mac[i] = EEPROM.read(i+1);
                }
                for (int i = 0; i < 4; i++){
                        ip[i] = EEPROM.read(i+7);
                }
                for (int i = 0; i < 4; i++){
                        subnet[i] = EEPROM.read(i+11);
                }
                for (int i = 0; i < 4; i++){
                        gateway[i] = EEPROM.read(i+15);
                }
                //アクセスNTPサーバー
                for (int i = 0; i < 4; i++){
                        timeServer[i] = EEPROM.read(i+19);
                }
        }
        sprintf(MacAddressStr,"%02x.%02x.%02x.%02x.%02x.%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
        sprintf(IPAddressStr,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
        sprintf(SubnetMaskStr,"%d.%d.%d.%d",subnet[0],subnet[1],subnet[2],subnet[3]);
        sprintf(GatewayStr,"%d.%d.%d.%d",gateway[0],gateway[1],gateway[2],gateway[3]);
        sprintf(NTPserverStr,"%d.%d.%d.%d",timeServer[0],timeServer[1],timeServer[2],timeServer[3]);
        Ethernet.begin(mac, ip);
}
//--------------------------
void SetWebPage( EthernetClient client){
        client.println(F("HTTP/1.1 200 OK"));
        client.println(F("Content-Type: text/html"));
        client.println();
        //
        client.print(F("<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=UTF-8\">\n"));
        client.print(F("\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>"));
        client.print(vers);
        client.print(F(" Setup Page</TITLE>\n"));
        client.print(F("\t<SCRIPT>\n\t\tfunction HP(w1){parent.window.open(w1,'_top')}\n\t</SCRIPT>\n"));
        client.print(F("\t<style type=\"text/css\">\n\t\t.tbox-style{\n\t\t\tpadding-top   : 4px;\n\t\t\tpadding-right : 4px;\n\t\t\tpadding-bottom: 2px;\n\t\t\ttext-align    : right;\n\t\t}\n\t</style>\n</HEAD>\n"));
        client.print(F("<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\">\n<BLOCKQUOTE><BLOCKQUOTE>\n"));
        client.print(F("<table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\">\n"));
        client.print(F("<tr><td>"));
        client.print(vers);
        client.print(F(" Setup Page</td></tr></table><br>\n"));
        //
        client.print(F("<script>\n\tfunction hex2num (s_hex) {\n\t\teval(\"var n_num=0X\" + s_hex);\n\t\treturn n_num;\n\t}\n</script>\n"));
        client.print(F("<tbody>\n<FORM><input type=\"hidden\" name=\"SBM\" value=\"1\">\n<table>\n<tr><td>MAC:</td><td>"));
        client.print(F("<input id=\"T1\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT1\" value=\""));
        client.print(mac[0],HEX);
        client.print(F("\" class=\"tbox-style\">.<input id=\"T3\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT2\" value=\""));
        client.print(mac[1],HEX);
        client.print(F("\" class=\"tbox-style\">.<input id=\"T5\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT3\" value=\""));
        client.print(mac[2],HEX);
        client.print(F("\" class=\"tbox-style\">.<input id=\"T7\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT4\" value=\""));
        client.print(mac[3],HEX);
        client.print(F("\" class=\"tbox-style\">.<input id=\"T9\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT5\" value=\""));
        client.print(mac[4],HEX);
        client.print(F("\" class=\"tbox-style\">.<input id=\"T11\" type=\"text\" size=\"3\" maxlength=\"2\" name=\"DT6\" value=\""));
        client.print(mac[5],HEX);
        //
        client.print(F("\" class=\"tbox-style\"><input id=\"T2\" type=\"hidden\" name=\"DT1\"><input id=\"T4\" type=\"hidden\" name=\"DT2"));
        client.print(F("\"><input id=\"T6\" type=\"hidden\" name=\"DT3\"><input id=\"T8\" type=\"hidden\" name=\"DT4"));
        client.print(F("\"><input id=\"T10\" type=\"hidden\" name=\"DT5\"><input id=\"T12\" type=\"hidden\" name=\"DT6"));
        client.print(F("\"></td></tr>\n<tr><td>IP:</td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT7\" value=\""));
        client.print(ip[0],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT8\" value=\""));
        client.print(ip[1],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT9\" value=\""));
        client.print(ip[2],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT10\" value=\""));
        client.print(ip[3],DEC);
        //
        client.print(F("\" class=\"tbox-style\"></td></tr>\n<tr><td>MASK: </td><td><input type= \"text\" size=\"3\" maxlength=\"3\" name=\"DT11\" value=\""));
        client.print(subnet[0],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT12\" value=\""));
        client.print(subnet[1],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT13\" value=\""));
        client.print(subnet[2],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT14\" value=\""));
        client.print(subnet[3],DEC);
        //
        client.print(F("\" class=\"tbox-style\"></td></tr>\n<tr><td>GW: </td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT15\" value=\""));
        client.print(gateway[0],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT16\" value=\""));
        client.print(gateway[1],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT17\" value=\""));
        client.print(gateway[2],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT18\" value=\""));
        client.print(gateway[3],DEC);
        //
        //client.print(F("\"></td></tr>\n<tr><td><br></td COLSPAN='2'>\n<HR ALIGN=LEFT>"));
        client.print(F("\" class=\"tbox-style\"></td></tr><tr><td COLSPAN='2'>\n<HR ALIGN=CENTER></td><td>"));                      //1行空けたい
        //
        client.print(F("</td></tr><tr><td>NTPd: </td><td><input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT19\" value=\""));
        client.print(timeServer[0],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT20\" value=\""));
        client.print(timeServer[1],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT21\" value=\""));
        client.print(timeServer[2],DEC);
        client.print(F("\" class=\"tbox-style\">.<input type=\"text\" size=\"3\" maxlength=\"3\" name=\"DT22\" value=\""));
        client.print(timeServer[3],DEC);
        client.print(F("\" class=\"tbox-style\"></td></tr>\n<tr><td><br></td></tr><tr><td COLSPAN='2'><P ALIGN=RIGHT><INPUT TYPE=\"button\" VALUE=\"RETURN\" onClick=\"HP('http://"));
        client.print(IPAddressStr);
        client.print(F("/setup9')\"/><input id=\"button1\"type=\"submit\" value=\"SUBMIT\" "));
        //
        client.print(F("Onclick=\""));
        client.print(F("document.getElementById('T2').value      = hex2num(document.getElementById('T1').value);\n"));
        client.print(F("\t\tdocument.getElementById('T4').value  = hex2num(document.getElementById('T3').value);\n"));
        client.print(F("\t\tdocument.getElementById('T6').value  = hex2num(document.getElementById('T5').value);\n"));
        client.print(F("\t\tdocument.getElementById('T8').value  = hex2num(document.getElementById('T7').value);\n"));
        client.print(F("\t\tdocument.getElementById('T10').value = hex2num(document.getElementById('T9').value);\n"));
        client.print(F("\t\tdocument.getElementById('T12').value = hex2num(document.getElementById('T11').value);\""));
        //
        client.print(F("></td></tr></tbody>\n</table>\n</BLOCKQUOTE></BLOCKQUOTE>\n</form>\n</BODY>\n</html>\n"));
}
//-------------------------- 2021/8/12
void SetPage1Day( EthernetClient client){
        client.println("HTTP/1.1 200 OK");
        client.println("Content-Type: text/html");
        client.println();
        //
        client.print(F("<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=\"UTF-8\">\n"));
        client.print(F("\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>"));
        client.print(vers);
        client.print(F(" Utility Page</TITLE>\n"));
        client.print(F("\t<script type='application/javascript' SRC='http://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.js'></script>\n"));
        client.print(F("\t<script type='application/javascript' SRC='./setup3'></script>\n"));
        client.print(F("\t<SCRIPT>\n\t\tfunction HP(w1){parent.window.open(w1,'_top')}\n\t</SCRIPT>\n"));
        client.print(F("\t<style>\n\t\tcanvas{\n"));
        client.print(F("\t\t\t-moz-user-select: none;\n"));
        client.print(F("\t\t\t-webkit-user-select: none;\n"));
        client.print(F("\t\t\t-ms-user-select: none;\n\t\t}\n"));
        client.print(F("\t\thtml { font-family: Helvetica; display: inline-block; margin: 0px auto;}\n"));
        client.print(F("\t\tbody{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n"));
        client.print(F("\t\tp {font-size: 24px;color: #444444;margin-bottom: 10px;}\n"));
        client.print(F("\t</style>\n</HEAD>\n"));
        client.print(F("<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\" BGCOLOR=\"#ffffff\">\n"));
        client.print(F("<FORM>\n<BLOCKQUOTE><BLOCKQUOTE>\n"));
        client.print(F("<P><table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\" CELLSPACING=\"2\">\n"));
        client.print(F("<tr><td>"));
        client.print(vers);
        client.print(F(" Utility Page</td></tr></table><br>\n"));
        //
        client.print(F("<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\" style=\"table-layout: fixed\">"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">&nbsp;</TD><TD WIDTH=\"20%\">&nbsp;</TD><TD WIDTH=\"55%\"><P ALIGN=CENTER><INPUT TYPE=\"button\" VALUE=\"RETURN\" onClick=\"HP('http://"));
        client.print(IPAddressStr);
        client.print(F("/setup9')\"/></TD>\n<TR>\n\t<TD WIDTH=\"25%\">FirmwareVirsion:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(FVirsion);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">MacAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(MacAddressStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">IPAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(IPAddressStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">SubnetMask:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(SubnetMaskStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Data acquisition time(Local):</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(DateTimeStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Num of connected sensors:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(devNum);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Operating Time:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        sprintf(buf2,"%ld[sec]",OperatingTime);
        client.print(buf2);
        client.print(F("</TD>\n</TR></TABLE></P>\n"));
        client.print(F("\t<div style='width:75%;'><canvas id='canvas' width='750' height='400' style='display: block; width: 750px; height: 400px;'></canvas></div>\n"));
        client.print(F("</CENTER></BLOCKQUOTE></BLOCKQUOTE>\n</form>\n"));
        client.print(F("<script>\n"));
        client.print(F("\t\tvar randomScalingFactor = function() {\n\t\t\treturn 18 + Math.random() * 10;\n\t\t};\n"));
        client.print(F("\t\tvar data_00 = ["));
        for(int i = 0; i<24 ;i++){
                client.print(isnan(gDayBuf[i][0]) ? String('\0') : String(gDayBuf[i][0],6));
                client.print(F(","));
        }
        client.print(F("];\n"));
        client.print(F("\t\tvar data_01 = ["));
        for(int i = 0; i<24 ;i++){
                client.print(isnan(gDayBuf[i][1]) ? String('\0') : String(gDayBuf[i][1],6));
                client.print(F(","));
        }
        client.print(F("];\n"));
        client.print(F("\t\tvar data_02 = ["));
        for(int i = 0; i<24 ;i++){
                client.print(isnan(gDayBuf[i][2]) ? String('\0') : String(gDayBuf[i][2],2));
                client.print(F(","));
        }
        client.print(F("];\n"));
        client.print(F("\t\tvar data_03 = ["));
        for(int i = 0; i<24 ;i++){
                client.print(isnan(gDayBuf[i][3]) ? String('\0') : String(gDayBuf[i][3],2));
                client.print(F(","));
        }
        client.print(F("];\n"));        
        client.print(F("\t\tvar config = {"));
        client.print(F("\t\t\ttype: 'line',\n\t\t\tdata: {\n"));
        client.print(F("\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"));
        client.print(F("\t\t\t\tdatasets: [{\n"));
        client.print(F("\t\t\t\t\tlabel: '温度1[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_00,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.red,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tcubicInterpolationMode: 'monotone',\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y1'\n"));
        client.print(F("\t\t\t\t}, {\n"));
        client.print(F("\t\t\t\t\tlabel: '温度2[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_01,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.blue,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y2'\n"));
        client.print(F("\t\t\t\t}, {\n"));
        client.print(F("\t\t\t\t\tlabel: '温度3[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_02,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.orange,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y3'\n"));
        client.print(F("\t\t\t\t}, {\n"));
        client.print(F("\t\t\t\t\tlabel: '温度4[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_03,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.yellow,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y4'\n"));
        client.print(F("\t\t\t\t}]\n\t\t\t},\n"));
        client.print(F("\t\t\toptions: {\n\t\t\t\tresponsive: true,\n"));
        client.print(F("\t\t\t\ttitle: {\n\t\t\t\t\tdisplay: true,\n\t\t\t\t\ttext: '温度取得履歴'\n\t\t\t\t},\n"));
        client.print(F("\t\t\t\tlegend: {\n\t\t\t\t\tdisplay: true\n\t\t\t\t},\n"));
        client.print(F("\t\t\t\ttooltips: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tmode: 'index'\n\t\t\t\t},\n"));
        client.print(F("\t\t\t\tscales: {\n\t\t\t\t\txAxes: [{\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\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"));
        client.print(F("\t\t\t\t\tyAxes: [{\n\t\t\t\t\t\tid:'y1',\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度1[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t}\n"));
        client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y2',\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度2[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t}\n"));
        client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y3',\n\t\t\t\t\t\tposition: 'right',\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度3[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t\t}\n"));
        client.print(F("\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\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度4[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}],\n"));
        client.print(F("\t\t\t\t}\n\t\t\t}\n\t\t};\n")); 
        client.print(F("\t\twindow.onload = function() {\n\t\t\tvar ctx = document.getElementById('canvas').getContext('2d');\n"));
        client.print(F("\t\t\twindow.myLine = new Chart(ctx, config);\n\t\t};\n"));
        client.print(F("</script>\n"));
        client.print(F("</BODY></html>"));
}
//-------------------------- 2022/2/18
void SetPage1Hour( EthernetClient client){
        client.println("HTTP/1.1 200 OK\nContent-Type: text/html\n\n");
        //client.println("Content-Type: text/html");
        //client.println();
        //
        client.print(F("<!DOCTYPE HTML PUBLIC \"\">\n<html>\n<HEAD>\n\t<META http-equiv=\"Content-Type\" charset=\"UTF-8\">\n\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>"));
        //client.print(F("\t<META http-equiv=\"Content-Style-Type\">\n\t<TITLE>"));
        client.print(vers);
        client.print(F(" Utility Page</TITLE>\n\t<script type='application/javascript' SRC='http://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.js'></script>\n\t<script type='application/javascript' SRC='./setup3'></script>\n"));
        client.print(F("\t<SCRIPT>\n\t\tfunction HP(w1){parent.window.open(w1,'_top')}\n\t</SCRIPT>\n"));
        //client.print(F("\t<script type='application/javascript' SRC='http://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.js'></script>\n"));
        //client.print(F("\t<script type='application/javascript' SRC='./setup3'></script>\n"));
        client.print(F("\t<style>\n\t\tcanvas{\n"));
        client.print(F("\t\t\t-moz-user-select: none;\n"));
        client.print(F("\t\t\t-webkit-user-select: none;\n"));
        client.print(F("\t\t\t-ms-user-select: none;\n\t\t}\n"));
        client.print(F("\t\thtml { font-family: Helvetica; display: inline-block; margin: 0px auto;}\n"));
        client.print(F("\t\tbody{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n"));
        client.print(F("\t\tp {font-size: 24px;color: #444444;margin-bottom: 10px;}\n"));
        client.print(F("\t</style>\n</HEAD>\n"));
        client.print(F("<BODY marginwidth=\"0\" marginheight=\"0\" leftmargin=\"0\" style=\"margin: 0; padding: 0;\" BGCOLOR=\"#ffffff\">\n"));
        client.print(F("<FORM>\n<BLOCKQUOTE><BLOCKQUOTE>\n"));
        client.print(F("<P><table bgcolor=\"#17A1A5\" border=\"0\" width=\"100%\" cellpadding=\"1\" style=\"font-family:Verdana;color:#ffffff;font-size:12px;\" CELLSPACING=\"2\">\n"));
        client.print(F("<tr><td>"));
        client.print(vers);
        client.print(F(" Utility Page</td></tr></table><br>\n"));
        //
        client.print(F("<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\" style=\"table-layout: fixed\">"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">&nbsp;</TD><TD WIDTH=\"20%\">&nbsp;</TD><TD WIDTH=\"55%\"><P ALIGN=CENTER><INPUT TYPE=\"button\" VALUE=\"RETURN\" onClick=\"HP('http://"));
        client.print(IPAddressStr);
        client.print(F("/setup9')\"/></TD>\n<TR>\n\t<TD WIDTH=\"25%\">FirmwareVirsion:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(FVirsion);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">MacAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(MacAddressStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">IPAddress:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(IPAddressStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\">SubnetMask:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(SubnetMaskStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Data acquisition time(Local):</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(DateTimeStr);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Num of connected sensors:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        client.print(devNum);
        client.print(F("</TD>\n</TR>"));
        client.print(F("<TR>\n\t<TD WIDTH=\"25%\" NOWRAP>Operating Time:</TD>\n\t<TD WIDTH=\"20%\"></TD>\n\t<TD WIDTH=\"55%\">"));
        sprintf(buf2,"%ld[sec]",OperatingTime);
        client.print(buf2);
        client.print(F("</TD>\n</TR></TABLE></P>\n"));
        client.print(F("\t<div style='width:75%;'><canvas id='canvas' width='750' height='400' style='display: block; width: 750px; height: 400px;'></canvas></div>\n"));
        client.print(F("</CENTER></BLOCKQUOTE></BLOCKQUOTE>\n</form>\n"));
        client.print(F("<script>\n"));
        client.print(F("\t\tvar randomScalingFactor = function() {\n\t\t\treturn 18 + Math.random() * 10;\n\t\t};\n"));
        client.print(F("\t\tvar data_00 = ["));
        for(int i = 0; i<60 ;i++){
                client.print(isnan(gHourBuf[i][0]) ? String('\0') : String(gHourBuf[i][0],6));
                client.print(F(","));
        }
        client.print(F("];\n"));
        client.print(F("\t\tvar data_01 = ["));
        for(int i = 0; i<60 ;i++){
                client.print(isnan(gHourBuf[i][1]) ? String('\0') : String(gHourBuf[i][1],6));
                client.print(F(","));
        }
        client.print(F("];\n"));
        client.print(F("\t\tvar data_02 = ["));
        for(int i = 0; i<60 ;i++){
                client.print(isnan(gHourBuf[i][2]) ? String('\0') : String(gHourBuf[i][2],2));
                client.print(F(","));
        }
        client.print(F("];\n"));
        client.print(F("\t\tvar data_03 = ["));
        for(int i = 0; i<60 ;i++){
                client.print(isnan(gHourBuf[i][3]) ? String('\0') : String(gHourBuf[i][3],2));
                client.print(F(","));
        }
        client.print(F("];\n"));        
        client.print(F("\t\tvar config = {"));
        client.print(F("\t\t\ttype: 'line',\n\t\t\tdata: {\n"));
        client.print(F("\t\t\t\tlabels: ['0', '', '2', '', '4', '', '6', '', '8', '', '10', '', '12' , '', '14', '', '16', '', '18', '', '20', '', '22', '', '24', '', '26', '', '28', '', '30', '', '32' , '', '34', '', '36', '', '38', '', '40', '', '42', '', '44', '', '46', '', '48', '', '50', '', '52' , '', '54', '', '56', '', '', '59'],\n"));
        client.print(F("\t\t\t\tdatasets: [{\n"));
        client.print(F("\t\t\t\t\tlabel: '温度1[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_00,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.red,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tcubicInterpolationMode: 'monotone',\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y1'\n"));
        client.print(F("\t\t\t\t}, {\n"));
        client.print(F("\t\t\t\t\tlabel: '温度2[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_01,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.blue,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y2'\n"));
        client.print(F("\t\t\t\t}, {\n"));
        client.print(F("\t\t\t\t\tlabel: '温度3[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_02,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.orange,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y3'\n"));
        client.print(F("\t\t\t\t}, {\n"));
        client.print(F("\t\t\t\t\tlabel: '温度4[℃]',\n"));
        client.print(F("\t\t\t\t\tdata: data_03,\n"));
        client.print(F("\t\t\t\t\tborderColor: window.chartColors.yellow,\n"));
        client.print(F("\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0)',\n"));
        client.print(F("\t\t\t\t\tfill: false,\n"));
        client.print(F("\t\t\t\t\tyAxisID: 'y4'\n"));
        client.print(F("\t\t\t\t}]\n\t\t\t},\n"));
        client.print(F("\t\t\toptions: {\n\t\t\t\tresponsive: true,\n"));
        client.print(F("\t\t\t\ttitle: {\n\t\t\t\t\tdisplay: true,\n\t\t\t\t\ttext: '温度取得履歴'\n\t\t\t\t},\n"));
        client.print(F("\t\t\t\tlegend: {\n\t\t\t\t\tdisplay: true\n\t\t\t\t},\n"));
        client.print(F("\t\t\t\ttooltips: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tmode: 'index'\n\t\t\t\t},\n"));
        client.print(F("\t\t\t\tscales: {\n\t\t\t\t\txAxes: [{\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\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"));
        client.print(F("\t\t\t\t\tyAxes: [{\n\t\t\t\t\t\tid:'y1',\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度1[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.red,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t}\n"));
        client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y2',\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度2[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.blue,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t}\n"));
        client.print(F("\t\t\t\t\t},{\n\t\t\t\t\t\tid:'y3',\n\t\t\t\t\t\tposition: 'right',\n\t\t\t\t\t\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度3[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.orange,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t\t}\n"));
        client.print(F("\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\tdisplay: true,\n"));
        client.print(F("\t\t\t\t\t\tscaleLabel: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n"));
        client.print(F("\t\t\t\t\t\t\tdisplay: true,\n\t\t\t\t\t\t\tlabelString: '温度4[℃]'\n\t\t\t\t\t\t},\n"));
        client.print(F("\t\t\t\t\t\tticks: {\n\t\t\t\t\t\t\tfontColor: window.chartColors.yellow,\n"));
        client.print(F("\t\t\t\t\t\t\tsuggestedMin: 10,\n\t\t\t\t\t\t\tsuggestedMax:  50\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}],\n"));
        client.print(F("\t\t\t\t}\n\t\t\t}\n\t\t};\n")); 
        client.print(F("\t\twindow.onload = function() {\n\t\t\tvar ctx = document.getElementById('canvas').getContext('2d');\n"));
        client.print(F("\t\t\twindow.myLine = new Chart(ctx, config);\n\t\t};\n"));
        client.print(F("</script>\n"));
        client.print(F("</BODY></html>"));
}
//--------------------------
void checkWebPage( EthernetClient client)
{
        Serial.println(F("new webClient"));
        boolean restart = false;
        if (client) {
                TextFinder  finder(client );
                while (client.connected()) {
                        //digitalWrite(LED, HIGH);
                        if (client.available()) {
                                //この部分はすべてのテキスト検索を行います。
                                if( finder.find("GET /") ) {
                                        // 「setup」とい語が見つかった場合は、さらに探してください。
                                        // その単語が見つからない場合は、検索を停止して先に進みます。
                                        // これにより、後でスケッチに独自のWebページを配置できます。
                                        if (finder.findUntil("setup", "\n\r")){
                                                long cord = finder.getValue();
                                                sprintf(buf1,"setupIn=%d",cord);
                                                Serial.println(buf1);
                                                switch(cord){
                                                        case 1:
                                                                // 「SBM」という単語が見つかった場合は、さらに探し続けます。
                                                                // その言葉が見つからない場合は、探して停止します。
                                                                // SUBMITボタンが押されていない、何も押されていないことを意味します
                                                                // セットアップページが構築されている場所に移動し、クライアントのブラウザに表示します。
                                                                if (finder.findUntil("SBM", "\n\r")){
                                                                        byte SET = finder.getValue();
                                                                        // これで、「DT」という文字を探している間に、「DT」の後ろにあるすべての数字を覚えて、
                                                                        // 値を一致させて、mac、ip、subnet、およびgatewayに入れる必要があります。
                                                                        while(finder.findUntil("DT", "\n\r")){
                                                                                int val = finder.getValue();
                                                                                // 「DT」のvalが1?6の場合、対応する値はMAC値でなければなりません。
                                                                                if(val >= 1 && val <= 6) {
                                                                                        mac[val - 1] = finder.getValue();
                                                                                }
                                                                                // 「DT」のvalが7?10の場合、対応する値はIP値でなければなりません。
                                                                                if(val >= 7 && val <= 10) {
                                                                                        ip[val - 7] = finder.getValue();
                                                                                }
                                                                                // 「DT」のvalが11?14の場合、対応する値はMASK値でなければなりません。
                                                                                if(val >= 11 && val <= 14) {
                                                                                        subnet[val - 11] = finder.getValue();
                                                                                }
                                                                                // 「DT」のvalが15?18の場合、対応する値はGW値でなければなりません。
                                                                                if(val >= 15 && val <= 18) {
                                                                                        gateway[val - 15] = finder.getValue();
                                                                                }  
                                                                                // 「DT」のvalが19?22の場合、対応する値はTimeServer値でなければなりません。
                                                                                if(val >= 19 && val <= 22) {
                                                                                        timeServer[val - 19] = finder.getValue();
                                                                                }
                                                                        }
                                                                        // すべてのデータを取得したので、EEPROMに保存できます
                                                                        for (int i = 0 ; i < 6; i++){
                                                                                EEPROM.write(i + 1,mac[i]);
                                                                        }
                                                                        for (int i = 0 ; i < 4; i++){
                                                                                EEPROM.write(i + 7, ip[i]);
                                                                        }
                                                                        for (int i = 0 ; i < 4; i++){
                                                                                EEPROM.write(i + 11, subnet[i]);
                                                                        }
                                                                        for (int i = 0 ; i < 4; i++){
                                                                                EEPROM.write(i + 15, gateway[i]);
                                                                        }
                                                                        for (int i = 0 ; i < 4; i++){
                                                                                EEPROM.write(i + 19, timeServer[i]);
                                                                        }
                                                                        // IDを既知のビットに設定します。したがって、Arduinoをリセットすると、EEPROM値が使用されます。
                                                                        EEPROM.write(0, ID);
                                                                        sprintf(MacAddressStr,"%02x.%02x.%02x.%02x.%02x.%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
                                                                        sprintf(IPAddressStr,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
                                                                        sprintf(SubnetMaskStr,"%d.%d.%d.%d",subnet[0],subnet[1],subnet[2],subnet[3]);
                                                                        sprintf(GatewayStr,"%d.%d.%d.%d",gateway[0],gateway[1],gateway[2],gateway[3]);
                                                                        // すべてのデータがEEPROMに書き込まれている場合、arduinoをリセットする必要があります。
                                                                        //ハードウェアリセットボタンを使用する必要があります。
                                                                        restart = true;
                                                                }else{
                                                                        
                                                                }
                                                                // この時点から、セットアップページの構築を開始し、クライアントのブラウザーに表示できます。
                                                                SetWebPage(client);
                                                                break;
                                                        case 2:
                                                                // 新規にユーティリティ頁を作りました。
                                                                Serial.println(F("SetPage1Day"));
                                                                rtclock.getTime(tmm);
                                                                sprintf(DateTimeStr,"%04u/%02u/%02u %02u:%02u:%02u",tmm.year+1970, tmm.month, tmm.day,tmm.hour, tmm.minute, tmm.second);
                                                                SetPage1Day(client);
                                                                break;
                                                        case 3:
                                                                //utils.jsが要求された。
                                                                Serial.println(F("utils.js"));
                                                                LoadUtilsJS(client);
                                                                break;
                                                        case 4:
                                                                //新規に一時間分の分単位グラフ表示を作りました
                                                                Serial.println(F("SetPage1Hour"));
                                                                rtclock.getTime(tmm);
                                                                sprintf(DateTimeStr,"%04u/%02u/%02u %02u:%02u:%02u",tmm.year+1970, tmm.month, tmm.day,tmm.hour, tmm.minute, tmm.second);
                                                                SetPage1Hour(client);
                                                                break;
                                                       case 9:
                                                                //トップページに戻る方法として追加しました。
                                                                Serial.println(F("Home"));
                                                                pageIntroduction(client);
                                                                break;
                                                        default:
                                                                PrintResponse404(client );
                                                                break;   
                                                }
                                        }else{
                                              pageIntroduction(client);  
                                        }
                                }
                                break;
                        }
                        PrintResponse404(client );
                }
                delay(1);
                client.stop();
                if(restart)     nvic_sys_reset();
        }     
}
//----------------------------2022年2月18日メニュー追加 2023年7月11日レタッチ
void pageIntroduction( EthernetClient client){
        client.println(F("HTTP/1.1 200 OK\nContent-Type: text/html\n\n"));
        //client.println(F("Content-Type: text/html"));
        //client.println();
        // put your own html from here on
        sprintf(buf1,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
        client.println(F("<HTML>\n<HEAD>\n\t<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;CHARSET=UTF-8\">\n</HEAD>\n<BODY BGCOLOR='#ffffff'>\n<H2><CENTER><FONT COLOR='#00ff00'>DS18B20 SetUp Menu</FONT></CENTER></H2>\n<P><CENTER><TABLE WIDTH='500' BORDER='0' CELLSPACING='0' CELLPADDING='0'>\n\t<TR>\n\t\t<TD WIDTH='100%'>\n\t\t<OL>\n"));
        //client.println(F("<BODY BGCOLOR='#ffffff'>\n<H2><CENTER><FONT COLOR='#00ff00'>DS18B20 SetUp Menu</FONT></CENTER></H2>\n"));
        //client.println(F("<P><CENTER><TABLE WIDTH='500' BORDER='0' CELLSPACING='0' CELLPADDING='0'>\n\t<TR>\n\t\t<TD WIDTH='100%'>\n\t\t<OL>\n"));
        sprintf(buffer,"\t\t\t<LI><FONT SIZE='+1'><A HREF=\"http://%s/setup1\">設定メニュー</A>\n",buf1);
        client.println(buffer);
        sprintf(buffer,"\t\t\t<LI><A HREF=\"http://%s/setup2\">温度履歴表示 時単位(最近一日)</A>\n",buf1);
        client.println(buffer);
        sprintf(buffer,"\t\t\t<LI><A HREF=\"http://%s/setup4\">温度履歴表示 分単位(最近一時間)</A></FONT>\n",buf1);
        client.println(buffer);
        client.print(F("\t\t</OL>\n\t\t</TD>\n\t</TR>\n</TABLE></CENTER>\n</BODY>\n</HTML>\n"));
        client.stop();
}
//--------------------------
void PrintResponse404( EthernetClient client )
{
        client.println(F("HTTP/1.1 404 Not Found\nContent-Type: text/html\nConnnection: close\n\n"));
        //client.println(F("Content-Type: text/html"));
        //client.println(F("Connnection: close")); 
        //client.println();
        client.stop();
}
//--------------------------
void LoadUtilsJS( EthernetClient client ){                              //2023/07/11 少しでも纏めてみた。
        client.println("HTTP/1.1 200 OK\nContent-Type: text/html\n\n");
        //client.println("Content-Type: text");
        //client.println();
        //
        client.println("'use strict';\nwindow.chartColors = {\n\tred: 'rgb(255, 99, 132)',\n\torange: 'rgb(255, 159, 64)',\n\tyellow: 'rgb(255, 205, 86)',\n\tgreen: 'rgb(75, 192, 192)',\n\tblue: 'rgb(54, 162, 235)',\npurple: 'rgb(153, 102, 255)',\n\tgrey: 'rgb(201, 203, 207)'\n};\n");
        //
        //client.println("window.chartColors = {");
        //client.println("\tred: 'rgb(255, 99, 132)',");
        //client.println("\torange: 'rgb(255, 159, 64)',");
        //client.println("\tyellow: 'rgb(255, 205, 86)',");
        //client.println("\tgreen: 'rgb(75, 192, 192)',");
        //client.println("\tblue: 'rgb(54, 162, 235)',");
        //client.println("\tpurple: 'rgb(153, 102, 255)',");
        //client.println("\tgrey: 'rgb(201, 203, 207)'");
        //client.println("};\n");
        //
        client.println("(function(global) {\n\tvar MONTHS = [\n\t\t'January',\n\t\t'February',\n\t\t'March',\n\t\t'April',\n\t\t'May',\n\t\t'June',\n\t\t'July',\n\t\t'August',\n\t\t'September',\n\t\t'October',\n\t\t'November',\n\t\t'December'\n\t];\n");
        //client.println("\tvar MONTHS = [");
        //client.println("\t\t'January',");
        //client.println("\t\t'February',");
        //client.println("\t\t'March',");
        //client.println("\t\t'April',");
        //client.println("\t\t'May',");
        //client.println("\t\t'June',");
        //client.println("\t\t'July',");
        //client.println("\t\t'August',");
        //client.println("\t\t'September',");
        //client.println("\t\t'October',");
        //client.println("\t\t'November',");
        //client.println("\t\t'December'");
        //client.println("\t];\n");
        //
        client.println("\tvar COLORS = [\n\t\t'#4dc9f6',\n\t\t'#f67019',\n\t\t'#f53794',\n\t\t'#537bc4',\n\t\t'#acc236',\n\t\t'#166a8f',\n\t\t'#00a950',\n\t\t'#58595b',\n\t\t'#8549ba'\n\t];\n");
        //client.println("\t\t'#4dc9f6',");
        //client.println("\t\t'#f67019',");
        //client.println("\t\t'#f53794',");
        //client.println("\t\t'#537bc4',");
        //client.println("\t\t'#acc236',");
        //client.println("\t\t'#166a8f',");
        //client.println("\t\t'#00a950',");
        //client.println("\t\t'#58595b',");
        //client.println("\t\t'#8549ba'");
        //client.println("\t];\n");
        //
        client.println("\tvar Samples = global.Samples || (global.Samples = {});\n\tvar Color = Chart.helpers.color;\n");
        //client.println("\tvar Color = Chart.helpers.color;\n");
        //
        client.println("\tfunction applyDefaultNumbers(config) {\n\t\tvar cfg = config || {};\n\t\tcfg.min = cfg.min || 0;\n\t\tcfg.max = cfg.max || 1;\n\t\tcfg.from = cfg.from || [];\n\t\tcfg.count = cfg.count || 8;\n\t\tcfg.decimals = cfg.decimals || 8;\n\t\tcfg.continuity = cfg.continuity || 1;\n");
        //client.println("\t\tvar cfg = config || {};");
        //client.println("\t\tcfg.min = cfg.min || 0;");
        //client.println("\t\tcfg.max = cfg.max || 1;");
        //client.println("\t\tcfg.from = cfg.from || [];");
        //client.println("\t\tcfg.count = cfg.count || 8;");
        //client.println("\t\tcfg.decimals = cfg.decimals || 8;");
        //client.println("\t\tcfg.continuity = cfg.continuity || 1;\n");
        //
        client.println("\t\treturn cfg;\n\t}\n");
        //client.println("\t}\n");
        //
        client.println("\tSamples.utils = {\n\t\t// Adapted from http://indiegamr.com/generate-repeatable-random-numbers-in-js/\n\t\tsrand: function(seed) {\n\t\t\tthis._seed = seed;\n\t\t},\n");
        //client.println("\t\t// Adapted from http://indiegamr.com/generate-repeatable-random-numbers-in-js/");
        //client.println("\t\tsrand: function(seed) {");
        //client.println("\t\t\tthis._seed = seed;");
        //client.println("\t\t},\n");
        //
        client.println("\t\trand: function(min, max) {\n\t\t\tvar seed = this._seed;\n\t\t\tmin = min === undefined ? 0 : min;\n\t\t\tmax = max === undefined ? 1 : max;\n\t\t\tthis._seed = (seed * 9301 + 49297) % 233280;\n\t\t\treturn min + (this._seed / 233280) * (max - min);\n\t\t},\n");
        //client.println("\t\t\tvar seed = this._seed;");
        //client.println("\t\t\tmin = min === undefined ? 0 : min;");
        //client.println("\t\t\tmax = max === undefined ? 1 : max;");
        //client.println("\t\t\tthis._seed = (seed * 9301 + 49297) % 233280;");
        //client.println("\t\t\treturn min + (this._seed / 233280) * (max - min);");
        //client.println("\t\t},\n");
        //
        client.println("\t\tnumbers: function(config) {\n\t\t\tvar cfg = applyDefaultNumbers(config);\n\t\t\tvar dfactor = Math.pow(10, cfg.decimals) || 0;\n\t\t\tvar data = [];\n\t\t\tvar i, value;\n");
        //client.println("\t\t\tvar cfg = applyDefaultNumbers(config);");
        //client.println("\t\t\tvar dfactor = Math.pow(10, cfg.decimals) || 0;");
        //client.println("\t\t\tvar data = [];");
        //client.println("\t\t\tvar i, value;\n");
        //
        client.println("\t\t\tfor (i = 0; i < cfg.count; ++i) {\n\t\t\t\tvalue = (cfg.from[i] || 0) + this.rand(cfg.min, cfg.max);\n\t\t\t\tif (this.rand() <= cfg.continuity) {\n\t\t\t\t\tdata.push(Math.round(dfactor * value) / dfactor);\n\t\t\t\t} else {\n\t\t\t\t\tdata.push(null);\n\t\t\t\t}\n\t\t\t}\n");
        //client.println("\t\t\t\tvalue = (cfg.from[i] || 0) + this.rand(cfg.min, cfg.max);");
        //client.println("\t\t\t\tif (this.rand() <= cfg.continuity) {");
        //client.println("\t\t\t\t\tdata.push(Math.round(dfactor * value) / dfactor);");
        //client.println("\t\t\t\t} else {");
        //client.println("\t\t\t\t\tdata.push(null);");
        //client.println("\t\t\t\t}");
        //client.println("\t\t\t}\n");
        //
        client.println("\t\t\treturn data;\n\t\t},\n");
        //client.println("\t\t},\n");
        //
        client.println("\t\tlabels: function(config) {\n\t\t\tvar cfg = config || {};\n\t\t\tvar min = cfg.min || 0;\n\t\t\tvar max = cfg.max || 100;\n\t\t\tvar count = cfg.count || 8;\n\t\t\tvar step = (max - min) / count;\n\t\t\tvar decimals = cfg.decimals || 8;\n\t\t\tvar dfactor = Math.pow(10, decimals) || 0;\n\t\t\tvar prefix = cfg.prefix || '';\n\t\t\tvar values = [];\n\t\t\tvar i;\n");
        //client.println("\t\t\tvar cfg = config || {};");
        //client.println("\t\t\tvar min = cfg.min || 0;");
        //client.println("\t\t\tvar max = cfg.max || 100;");
        //client.println("\t\t\tvar count = cfg.count || 8;");
        //client.println("\t\t\tvar step = (max - min) / count;");
        //client.println("\t\t\tvar decimals = cfg.decimals || 8;");
        //client.println("\t\t\tvar dfactor = Math.pow(10, decimals) || 0;");
        //client.println("\t\t\tvar prefix = cfg.prefix || '';");
        //client.println("\t\t\tvar values = [];");
        //client.println("\t\t\tvar i;\n");
        //
        client.println("\t\t\tfor (i = min; i < max; i += step) {\n\t\t\t\tvalues.push(prefix + Math.round(dfactor * i) / dfactor);\n\t\t\t}\n");
        //client.println("\t\t\t\tvalues.push(prefix + Math.round(dfactor * i) / dfactor);");
        //client.println("\t\t\t}\n");
        //
        client.println("\t\t\treturn values;\n\t\t},\n");
        //client.println("\t\t},\n");
        //
        client.println("\t\tmonths: function(config) {\n\t\t\tvar cfg = config || {};\n\t\t\tvar count = cfg.count || 12;\n\t\t\tvar section = cfg.section;\n\t\t\tvar values = [];\n\t\t\tvar i, value;\n");
        //client.println("\t\t\tvar cfg = config || {};");
        //client.println("\t\t\tvar count = cfg.count || 12;");
        //client.println("\t\t\tvar section = cfg.section;");
        //client.println("\t\t\tvar values = [];");
        //client.println("\t\t\tvar i, value;\n");
        //
        client.println("\t\t\tfor (i = 0; i < count; ++i) {\n\t\t\t\tvalue = MONTHS[Math.ceil(i) % 12];\n\t\t\t\tvalues.push(value.substring(0, section));\n\t\t\t}\n");
        //client.println("\t\t\t\tvalue = MONTHS[Math.ceil(i) % 12];");
        //client.println("\t\t\t\tvalues.push(value.substring(0, section));");
        //client.println("\t\t\t}\n");
        //
        client.println("\t\t\treturn values;\n\t\t},\n");
        //client.println("\t\t},\n");
        //
        client.println("\t\tcolor: function(index) {\n\t\t\treturn COLORS[index % COLORS.length];\n\t\t},\n");
        //client.println("\t\t\treturn COLORS[index % COLORS.length];");
        //client.println("\t\t},\n");
        //
        client.println("\t\ttransparentize: function(color, opacity) {\n\t\t\tvar alpha = opacity === undefined ? 0.5 : 1 - opacity;\n\t\t\treturn Color(color).alpha(alpha).rgbString();\n\t\t}\n\t};\n");
        //client.println("\t\t\tvar alpha = opacity === undefined ? 0.5 : 1 - opacity;");
        //client.println("\t\t\treturn Color(color).alpha(alpha).rgbString();");
        //client.println("\t\t}");
        //client.println("\t};\n");
        //
        client.println("\t// DEPRECATED\n\twindow.randomScalingFactor = function() {\n\t\treturn Math.round(Samples.utils.rand(-100, 100));\n\t};\n");
        //client.println("\twindow.randomScalingFactor = function() {");
        //client.println("\t\treturn Math.round(Samples.utils.rand(-100, 100));");
        //client.println("\t};\n");
        //
        client.println("\t// INITIALIZATION\n\n\tSamples.utils.srand(Date.now());\n");
        //
        //client.println("\tSamples.utils.srand(Date.now());\n");
        //
        client.println("\t// Google Analytics\n\t/* eslint-disable */\n\tif (document.location.hostname.match(/^(www\\.)?chartjs\\.org$/)) {\n\t\t(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n\t\t(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n\t\tm=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n\t\t})(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\t\tga('create', 'UA-28909194-3', 'auto')\n\t\tga('send', 'pageview');\n\t}\n\t/* eslint-enable */\n");
        //client.println("\t/* eslint-disable */");
        //client.println("\tif (document.location.hostname.match(/^(www\\.)?chartjs\\.org$/)) {");
        //client.println("\t\t(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){");
        //client.println("\t\t(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),");
        //client.println("\t\tm=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)");
        //client.println("\t\t})(window,document,'script','//www.google-analytics.com/analytics.js','ga');");
        //client.println("\t\tga('create', 'UA-28909194-3', 'auto');");
        //client.println("\t\tga('send', 'pageview');");
        //client.println("\t}");
        //client.println("\t/* eslint-enable */\n");
        //
        client.println("}(this));");
}
//-------指定されたアドレスのタイムサーバーにNTP要求を送信します
void    sendNTPpacket(byte address[]){
        memset(packetBuffer, 0, NTP_PACKET_SIZE);               //バッファ内のすべてのバイトを0に設定します
        //NTP要求を形成するために必要な値を初期化する
        packetBuffer[0]         = 0b11100011;                   // LI, Version, Mode
        packetBuffer[1]         = 0;                            //階層、またはクロックのタイプ
        packetBuffer[2]         = 6;                            //ポーリング間隔
        packetBuffer[3]         = 0xEC;                         //ピアクロックの精度
        //ルート遅延およびルート分散用のゼロの8バイト
        packetBuffer[12]        = 49;
        packetBuffer[13]        = 0x4E;
        packetBuffer[14]        = 49;
        packetBuffer[15]        = 52;
        //すべてのNTPフィールドに値が与えられました。
        //タイムスタンプを要求するパケットを送信できます:
        Udp.beginPacket(address, 123);                          //NTPリクエストはポート123へ
        Udp.write(packetBuffer, NTP_PACKET_SIZE);
        Udp.endPacket();
}
//-----------------     割込CallBack      修正2023/07/12 500msec毎に呼び出され、表示更新する様にした。
void TimeUpdate(void){
        //500msec毎に呼ばれる
        OperatingTime++;
        if(OperatingTime%2)     dot     =       0b00010000;
        else                    dot     =       0b00000100;
        //時刻チェック
        rtclock.getTime(tmm);
        h = tmm.hour;                           //返値0-23
        m = tmm.minute;                         //返値0-59
        //
        if(lastKey != 0){
                switch(lastKey){
                        case 0x01:                                      //温度1を表示
                                Temp1 = int(gHourBuf[preMSet][0]  * 100.0);
                                LedAndKey.setDisplayToDecNumber(Temp1,0b00000100,false);
                                break;
                        case 0x02:                                      //温度2を表示
                                Temp2 = int(gHourBuf[preMSet][1]  * 100.0);
                                LedAndKey.setDisplayToDecNumber(Temp2,0b00000100,false);
                                break;
                        default:                                        //時刻表示
                                //
                                DispTime    =       h*10000 + m*100 + tmm.second;
                                LedAndKey.setDisplayToDecNumber(DispTime,dot,false);
                                break;
                }
        }
        if(preSet != h){
                //1時間おきに時刻を確認し、データをメモリに確保
                preSet  = h;
                float   celsius;
                //本計測
                for (int i = 0;i<devNum;i++){
                        GetDSTemp(celsius,i);
                        if(celsius != 0.0){
                              gDayBuf[h][i]   =       celsius;  
                        }
                }
                //次回分のデータをNULL化
                h = (h+1) % 24;
                for (int i = 0;i<devNum;i++){
                         gDayBuf[h][i]   =       NAN;
                }
        }else if(preMSet != m){
                //1分おきにデータ取込
                preMSet  = m;
                float   celsius;
                //本計測
                for (int i = 0;i<devNum;i++){
                        GetDSTemp(celsius,i);
                        if(celsius != 0.0){
                              gHourBuf[m][i]    =       celsius;  
                        }
                }
                //次回分のデータをNULL化
                m = (m+1) % 60;
                for (int i = 0;i<devNum;i++){
                         gHourBuf[m][i]         =       NAN;
                }
                if(!fDoneTime){
                        fDoneTime               = checkNTP();
                }
        }else{
                //計測しない
        }
        keys    = LedAndKey.getButtons();
        if(keys != 0){
                lastKey = keys;
                LedAndKey.setLEDs(lastKey);
        }
}
//------------------
bool SetDSDevice(int index) {
        byte i;
        byte present = 0;
        byte type_s;
        byte data[12];
        byte addr[8];
        //float celsius;
        if ( !ds.search(addr)) {
                Serial.println(F("No more addresses."));
                ds.reset_search();
                delay(100);
                return false;
        }else{
                memcpy(gDS[index], addr, sizeof(addr));
                return true;
        }
}
//------------------
void GetDSTemp(float &celsius,int index) {
        byte i;
        byte present = 0;
        byte type_s;
        byte data[12];
        byte addr[8];
        //float celsius;
        /* 検索不要
        for (int i;i<devNum;i++){
                ds.search(addr);
                if(memcmp(addr, gDS[i], sizeof(addr)) == 0)     break;
        }
        ds.reset_search();
        */
        if (OneWire::crc8(gDS[index], 7) != gDS[index][7]) {
                Serial.println(F("CRC is not valid!"));
                return;
        }
        // 最初のROMバイトはチップ種を示します
        switch (gDS[index][0]) {
                case 0x10:
                        Serial.println(F("  Chip = DS18S20"));          // or old DS1820
                        type_s = 1;
                        break;
                case 0x28:
                        Serial.println(F("  Chip = DS18B20"));
                        type_s = 0;
                        break;
                case 0x22:
                        Serial.println(F("  Chip = DS1822"));
                        type_s = 0;
                        break;
                default:
                        Serial.println(F("Device is not a DS18x20 family device."));
                        return;
        }
        ds.reset();
        ds.select(gDS[index]);
        ds.write(0x44, 1);                              // 最後に寄生物の電源を入れて、変換を開始します
        delay(750);                                     // 多分750msで十分かもしれません12bit分解能の場合
        // ここでds.depower()を実行する場合がありますが、リセットによって処理されます。
        present = ds.reset();
        ds.select(gDS[index]);    
        ds.write(0xBE);                                 // スクラッチパッドを読む
        //Serial.print(F("  Data = "));
        //Serial.print(present, HEX);
        //Serial.print(F(" "));
        for ( i = 0; i < 9; i++) {                      // we need 9 bytes
                data[i] = ds.read();
                //Serial.print(data[i], HEX);
                //Serial.print(F(" "));
        }
        //Serial.print(F(" CRC="));
        //Serial.print(OneWire::crc8(data, 8), HEX);
        //Serial.println();
        //結果は16ビットの符号付き整数であるため、データを実際の温度に変換します。
        //データは「int16_t」タイプに格納する必要があります。
        //これは、32ビットプロセッサでコンパイルした場合でも常に16ビットです。
        int16_t raw = (data[1] << 8) | data[0];
        if (type_s) {
                raw = raw << 3;                         // デフォルトの9ビット解像度
                if (data[7] == 0x10) {                  // 「残り数」は完全な12ビットの解像度を提供します
                        raw = (raw & 0xFFF0) + 12 - data[6];
                }
        } else {
                byte cfg = (data[4] & 0x60);
                // 低解像度では、下位ビットは未定義なので、ゼロにしましょう
                if (cfg == 0x00) raw = raw & ~7;        // 9ビットの解像度、93.75ミリ秒
                else if (cfg == 0x20) raw = raw & ~3;   // 10ビットの解像度、187.5ミリ秒
                else if (cfg == 0x40) raw = raw & ~1;   // 11ビットの解像度、375ミリ秒
                // デフォルトは12ビットの解像度、750ミリ秒の変換時間です
        }
        celsius = (float)raw / 16.0;
        //fahrenheit = celsius * 1.8 + 32.0;
        Serial.print(F("  Temperature = "));    Serial.println(celsius);
        return;
}
//-----------------
int     getHourTime(void){
        rtclock.getTime(tmm1);
        return tmm1.hour;
}
//-----------------
int     getMinuteTime(void){
        rtclock.getTime(tmm1);
        return tmm1.minute;
}
//----------------
bool checkNTP(){
        sendNTPpacket(timeServer);                              //NTPパケットをタイムサーバーに送信する
        delay(300);                                            //返信が利用可能かどうかを確認するのを待ちます
        if ( Udp.parsePacket() ) {
                //パケットを受信し、そこからデータを読み取ります
                Udp.read(packetBuffer, NTP_PACKET_SIZE);        //パケットをバッファに読み込みます
                //タイムスタンプは、受信したパケットのバイト40から始まり、4バイト、つまり2ワードの長さです。
                unsigned long secsSince1900;
                // convert four bytes starting at location 40 to a long integer
                secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
                secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
                secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
                secsSince1900 |= (unsigned long)packetBuffer[43];
                unsigned long epoch   = secsSince1900 - 2208988800UL + (timeZone * SECS_PER_HOUR);
                rtclock.setTime(time_t(epoch));                 //JSTを内部時計にセット
                rtclock.getTime(tmm1);
                /*
                Serial.print((epoch  % 86400L) / 3600);         //時間を印刷します(86400は1日あたりの秒数に相当)
                Serial.print(':');
                int min = (epoch % 3600) / 60;
                if ( min < 10 ) {
                        Serial.print('0');                      //各時間の最初の10分では、先頭に「0」が必要です。
                }
                Serial.print(min);                              //分を印刷する(3600は1分あたりの秒数に等しい)
                Serial.print(':');
                int sec = epoch % 60;
                if ( sec < 10 ) {
                        Serial.print('0');                      //各分の最初の10秒で、先頭に「0」が必要になります
                }
                Serial.println(sec);                            //秒を印刷
                */
                return true;
        }else{
                return false;
        }
}
//----------------
void setup()
{
        // Open serial communications and wait for port to open:
        Serial.begin(115200);                                   //シリアル通信を開ます。
        pinMode(BUILTIN_LED,OUTPUT);    digitalWrite(BUILTIN_LED,LOW);
        pinMode(LED1,OUTPUT);           digitalWrite(LED1, HIGH);
        pinMode(LED2,OUTPUT);           digitalWrite(LED2, LOW);
        //Ethernet3API
        Ethernet.setCsPin(SPI1_NSS_PIN);
        Ethernet.setRstPin(W550io_Rst);
        pinMode(W550io_Rst, OUTPUT);
        digitalWrite(W550io_Rst, LOW);
        delay(10);
        digitalWrite(W550io_Rst, HIGH);
        Serial.print(F("NIC_Reset\n"));
        LANSetup();
        //イーサネットとUDPを開始します
        Udp.begin(localPort);
        Serial.print(F("server is at "));Serial.println(Ethernet.localIP());
        fDoneTime       = checkNTP();
        rtclock.getTime(tmm);
        sprintf(STRBUF,"%02u%02u%02u",tmm.hour,tmm.minute,tmm.second);
        LedAndKey.setDisplayToString(STRBUF,0b00010100,2);
        //LedAndKey.setDisplayToString("000000",0,2);
        Serial.print(F("server is at "));Serial.println(Ethernet.localIP());
        webServer.begin();
        //データバッファクリア
        for(int i = 0;i<24;i++){
                for(int j = 0;j<4;j++){
                        gDayBuf[i][j] = NAN;
                }
        }
        for(int i = 0;i<60;i++){
                for(int j = 0;j<4;j++){
                        gHourBuf[i][j] = NAN;
                }
        }
        //DS18B20の初期化
        for(int i = 0;i<10;i++){
                delay(1);
                if(!SetDSDevice(i)){
                        devNum = i;
                        break;
                }
        }
        //タイマ割込設定
        Timer1.pause();                                                 //
        Timer1.setPrescaleFactor(7200);                                 // 72MHz100uSEC
        Timer1.setOverflow(5000);                                       // 500mSEC
        Timer1.attachInterrupt(TIMER_UPDATE_INTERRUPT,TimeUpdate);      // 割り込みサーブルーチンの宣言:TimeUpdate
        Timer1.setCount(0);                                             // 0
        Timer1.refresh();
        Timer1.resume(); 
        //
        iwdg_init_ms(wdgTime);                                         //ウォッチドッグをオンにして、オーバーフロー時間を設定します。
        Serial.println(F("EndSetUp"));
}
//----------------
void loop()
{
        //このLoopはscantime=1秒程度です。そのため5秒経っても戻らなかったらリセットすることにします。
        iwdg_feed();                                                    //ウォッチドッグタイマーをリセットするには、ドッグ操作をフィードします
        //
        if(!(OperatingTime % 7200)){                                    //1時間に一回
                fDoneTime       = checkNTP();     
        }
        if(Serial){
                if(!(OperatingTime % 60))       Serial.println(F("."));
                else                            Serial.print(F("."));
        }
        //digitalWrite(BUILTIN_LED,OperatingTime % 2);
        client          = webServer.available();                        //HTTP要求確認
        if(client)      checkWebPage(client);
        client.stop();                                                  // コネクションを閉じる。
        if(OperatingTime % 2){
                digitalWrite(LED1, LOW);
                digitalWrite(LED2, HIGH);
        }else{
                digitalWrite(LED1, HIGH);
                digitalWrite(LED2, LOW);
        }
        delay(200);
}

よくNTP同期を掛けると1時間ずれるという現象はよく見かけます。原因はTimeZoneが台湾時刻GMT+8になっていたと云う事が多々あります。
M/BやPLCの生産地が台湾だからと云う事もよく有る理由です。アセンブリも台湾で行ってしまうと、見直しが掛からないままユーザの手元に届いてしまいますね。
AliExpressでSTBを購入したときも1時間ずれていました。メーカ所在地の中国・深センもGMT+8のタイムゾーンなのですね。


戯言(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社の登録商標です。
その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
すべての商標および登録商標は、それぞれの所有者に帰属します。