ものづくり基礎工学IoT編（マイコン）・Webサーバ（簡易バージョン）

ここのプログラムは，インターネットの仕組みについてある程度詳しくないと，理解が難しいと思います。一応，技術的な説明はしてありますが，おそらく1年生ですと分からないことが多いと思います。読んで理解するのは大変ですので，指示に従ってください。

サンプルプログラム実行にあたり，「ツール」から「シリアルモニタ」を選択して，シリアルモニタを開いておいてください。LCDでは表示しきれないので，マイコンからパソコンのシリアルモニタに色々表示します。

#Webサーバ
マイコンをWebサーバにしてしまい，スマホからアクセスして，マイコンのLEDを制御してみます。スマホから見るとマイコンはアクセスポイントとしても動作しています。マイコンがインターネットに接続するには，別途3Gモジュールを接続し，通信会社と契約する必要がありますが，スマートフォンと1対1で接続する分には問題なくできます。つまりWi-Fiを使ってスマートフォンからマイコンを制御することが可能になります。

説明は，インターネットに関する知識が必要になるので，ここではソフトウェアを動かしてみるだけにします。

##Wi-Fiでマイコンを制御するサンプルプログラム
マイコンボード上にあるLEDをWi-Fi経由で光らせるプログラムです。「ON」ボタンを押すとそのLEDが点灯すると同時に，ボタンが「OFF」に変化します。

![Wi-Fi_LED.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146927/b9d08075-a317-dbec-267e-3dd2249bada9.jpeg)

このプログラムは，次のように動作させてください。
◎スマホのモバイルデータをオフにしてください。
◎自分のスマホでテザリングする場合の，SSIDとパスワードを次の部分にセットしてください。
const char SSID[] = "ESP32-LearningBoard"; // "4Jxx-Yamada"の様に各自の出席番号と名字に必ず変更
const char PASS[] = "mokemoke";
◎マイコンのLCDに表示されるIPアドレスが，アクセスポイントになりますので，スマホのブラウザのアドレス欄に，そのIPを入力して接続します。

以上の作業で，上の写真のように，「ESP32 LED Blinker」が表示されればokです。タップするとマイコンのLEDが制御できるのが分かると思います。同様にすれば，サーボを回転させることもできますし，そのサーボにドアノブのロックするツマミを接続しておけば，開錠・施錠も可能になります。

```c:HttpServer3Wi-Fi_LED
#include <esp32-nittc210131.h>

void initAll(){                 // 全部初期化，不要なものはリマークにするが，表示するデバイスの初期化は残すこと
  showInitProcess(false);       // true: 初期化の様子をLCDとシリアルモニタに表示，false: 表示しない
  initLcd();                    // LCDの初期化
  initSerialMonitor(115200);    // 引数は通信速度
  initPushSwitch();             // プッシュスイッチ（プッシュボタン）の初期化
  initTouchSensor(30);          // 引数はタッチの有無による閾値
  initLed();                    // LEDの初期化
  initI2C();                    // I2Cの初期化
  initDidtanceSensor(LongToF);  // Longモード，他に，MediumToF, ShortToF，通常はLongモードで良い
  initAudioAmp(10,200);          // スピーカーアンプの初期化，使用するタイマーのチャンネル（他とぶつからないよう注意，0,2,4,6,8,10,12,14のどれか），1音を継続する長さms
//  initGSensor(1000);            // ボタン1が押されていると補正係数測定実行，押されてなければEEPROMから補正係数を読む，引数は補正係数測定のための平均回数
  initRcServo(14, 500, 2400, 180, 50); // RCサーボの初期化，引数は使用するタイマーチャンネル（他とぶつからないよう注意），PWMのHパルス幅最小値us，最大値us，全回転角度，PWM周波数
//  initWifi("Pixel 4a 5G","mokemoke"); // 無線LAN接続，引数は，SSIDとパスワード
//  waitTouchAndReleasePad();     // LCDでIPを見て接続確認しない場合この行をリマーク文にする
//  initRTC(9*3600,0,"ntp.nict.jp");     // RTCをNICTのNTPサーバで初期化，UTCとの時差秒，サマータイムがある場合の時差秒，URL
//  waitTouchAndReleasePad();     // LCDでIPを見て接続確認しない場合この行をリマーク文にする
//  initSD();                     // SDカード関係の初期化，現在espressif/arduino-esp32ライブラリが対応していないが，initWifiとInitRTCが成功後，initSDを実行するとファイルのタイムスタンプが可能にできる
//  uint8_t yourBtMacAdr[6]= {0xA4, 0xCF, 0x12, 0x8C, 0x21, 0x62};  // BT Mac Address，自分がマスター時のスレーブ側のMac，自分がスレーブの時はリマークして構わない
//  initBluetooth("esp32",true,yourBtMacAdr);  // BT接続，引数：BTデバイス名，マスターtrue・スレーブfalse，スレーブBT（相手）のMac=6個の16進数
}


/* 接続情報の設定 */
const char SSID[] = "ESP32-LearningBoard"; // "4Jxx-Yamada"の様に各自の出席番号と名字に必ず変更
const char PASS[] = "mokemoke";

/* HTMLのヘッダーとフッター */
const String HTML_HEAD = "<!DOCTYPE html><html>\n<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<link rel=\"icon\" href=\"data:,\">\n <style>html { display: inline-block; margin: 0px auto; text-align: center;}\n .button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;\ntext-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}\n.button2 {background-color: #555555;}</style></head>\n<body><h1>ESP32 LED Blinker</h1>\n";
const String HTML_FOOT = "</body></html>";

/* LEDの状態保存用の変数 */
String LED1_STATUS = "OFF";
String LED2_STATUS = "OFF";

WebServer server(80);

void handleRoot(){
  server.send(200, "text/html", createHTMLByStatus());
}

void handleLED1ON(){
  turnOnLed(Led1);
  lcd.setCursor(0,0); lcd.printf("LED1 ON!        "); beep(1000,1);
  LED1_STATUS = "ON";
  server.send(200, "text/html", createHTMLByStatus());
}

void handleLED1OFF(){
  turnOffLed(Led1);
  lcd.setCursor(0,0); lcd.printf("LED1 OFF!       "); beep(250,1);
  LED1_STATUS = "OFF";
  server.send(200, "text/html", createHTMLByStatus());
}

void handleLED2ON(){
  turnOnLed(Led2);
  lcd.setCursor(0,1); lcd.printf("LED2 ON!        "); beep(1000,1);
  LED2_STATUS = "ON";
  server.send(200, "text/html", createHTMLByStatus());
}

void handleLED2OFF(){
  turnOffLed(Led2);
  lcd.setCursor(0,1); lcd.printf("LED2 OFF!       "); beep(250,1);
  LED2_STATUS = "OFF";
  server.send(200, "text/html", createHTMLByStatus());
}

String createHTMLByStatus(){
  String html = HTML_HEAD;
  html += "<p>LED1 State : ";
  html += LED1_STATUS;
  html += "</p>\n";
  if(LED1_STATUS == "OFF"){
    html += "<p><a href=\"/LED1/ON\"><button class=\"button\">ON</button></a></p>\n";
  }else{
    html += "<p><a href=\"/LED1/OFF\"><button class=\"button button2\">OFF</button></a></p>\n";
  }
  html += "<p>LED2 State : ";
  html += LED2_STATUS;
  html += "</p>\n";
  if(LED2_STATUS == "OFF"){
    html += "<p><a href=\"/LED2/ON\"><button class=\"button\">ON</button></a></p>\n";
  }else{
    html += "<p><a href=\"/LED2/OFF\"><button class=\"button button2\">OFF</button></a></p>\n";
  }
  html += HTML_FOOT;
  return html;
}

void setup(){
  initAll();
  char *version="HttpServerVer3.0";
  Serial.printf("ESP32 %s\n",version);  // \nは\r\nと書いてもよい
  lcd.clear();
  lcd.setCursor(0,0);  lcd.printf("ESP32");
  lcd.setCursor(0,1);  lcd.printf(version);     // 起動時にバージョンの表示などを行う
  delay(1000);  // バージョンを少しの間見せる

  WiFi.softAP(SSID, PASS);  // Wi-Fi起動
//  delay(100);

  // 接続情報をシリアルモニタに出力
  IPAddress ip=WiFi.softAPIP();
  Serial.println("Wi-Fi start.");
  Serial.printf("SSID: ");
  Serial.println(SSID);
  Serial.printf("PASS: ");
  Serial.println(PASS);
  Serial.printf("IPAddress: ");
  Serial.println(ip);
    
  /* サーバの設定 */
  server.on("/", handleRoot);
  server.on("/LED1/ON", handleLED1ON);
  server.on("/LED1/OFF", handleLED1OFF);
  server.on("/LED2/ON", handleLED2ON);
  server.on("/LED2/OFF", handleLED2OFF);
  server.begin();             // サーバを開始
    
  Serial.println("http Server Setup Complete.");
  lcd.clear();
  lcd.setCursor(0,0); lcd.printf("Http Server");
  lcd.setCursor(0,1); lcd.printf("%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
  beep(1000,1);
}

void loop(){
    server.handleClient();      // クライアントのリクエストを処理する関数
}
```

___課題13：上のサンプルプログラムを動作させ，動画を撮影するなどして，マイコンのLEDをスマホから操作する様子をkadai13.mp4としてアップロードせよ。___