自作スマートプラグをBlynk対応にしてみたのとWi-Fi後決め式にしてみた

頭がまとまらないからコードだけ貼っておくけど徐々に追記していこうかなと思う。

自作のスマートプラグを作った話は先日記事にしたし、動画でも公開したんだけどやっぱりSinric ProだとON/OFFがスマホ画面と逆転しているから微妙にストレスを感じていた。

それと次の願望としてパソコン切ったときにディスプレイ電源をオフにしたいっていうのを叶えるのにBlynkのほうが都合が良かったので変えてみた。

Wi-FiのSSIDとパスワードはハードコーディングしないでESP8266自身が最初ウェブサーバーになって決められるっていうのを導入してみたが、どこのサイトを参考にしたか忘れてしまった。とにかく自分で考えたのではないことは確か。

以下がそのコードだけどなぜかインデントが消えてしまう。


//#define DEBUG 1
#include <BlynkSimpleEsp8266.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>

#define BAUD_RATE 115200
// define the GPIO connected with Relays and switches
#define RelayPin5 5 //D1
#define SwitchPin5 14 //D5
#define wifiLed 16 //D0

#define VPIN_BUTTON_5 V5
int toggleState_5 = 1; //Define integer to remember the toggle state for relay 1
int wifiFlag = 0;
bool testWifi(void);
void launchWeb(void);
void setupAP(void);
void createWebServer();

//Variables
int i = 0;
int statusCode;
const char* ssid = "text";
const char* passphrase = "text";
String st;
String content;
//Establishing Local server at port 80 whenever required
ESP8266WebServer server(80);
// モード切り替えピン
const int MODE_PIN = 0; // GPIO0
#define AUTH "あなたのBlynkトークン" // You should get Auth Token in the Blynk App.
BlynkTimer timer;

void relayOnOff(int relay){
  switch(relay){
    case 1:
      if(toggleState_5 == 1){
        digitalWrite(RelayPin5, LOW); // turn on relay 1
        toggleState_5 = 0;
      }else{
        digitalWrite(RelayPin5, HIGH); // turn off relay 1
        toggleState_5 = 1;
      }
      delay(100);
      break;
    default : break;
  }
}

void with_internet(){
  //Manual Switch Control
  if (digitalRead(SwitchPin5) == LOW){
    delay(200);
    relayOnOff(1);
    Blynk.virtualWrite(VPIN_BUTTON_5, toggleState_5); // Update Button Widget
  }
}
void without_internet(){
  //Manual Switch Control
  if (digitalRead(SwitchPin5) == LOW){
    delay(200);
    relayOnOff(1);
  }
}

BLYNK_CONNECTED() {
  // Request the latest state from the server
  Blynk.syncVirtual(VPIN_BUTTON_5);
}

// When App button is pushed - switch the state
BLYNK_WRITE(VPIN_BUTTON_5) {
  toggleState_5 = param.asInt();
  digitalWrite(RelayPin5, toggleState_5);
  led_blink(100,100,1);
}

void checkBlynkStatus() { // called every 3 seconds by SimpleTimer
  bool isconnected = Blynk.connected();
  if (isconnected == false) {
    wifiFlag = 1;
    digitalWrite(wifiLed, HIGH); //Turn off WiFi LED
  }
  if (isconnected == true) {
    wifiFlag = 0;
    digitalWrite(wifiLed, LOW); //Turn on WiFi LED
  }
}
void setup(){
  Serial.begin(BAUD_RATE);
  pinMode(wifiLed, OUTPUT);
  pinMode(RelayPin5, OUTPUT);
  pinMode(SwitchPin5, INPUT_PULLUP);
  ////// Wi-Fi接続処理 //////
  WiFi.disconnect();
  EEPROM.begin(512); //Initialasing EEPROM
  delay(10);
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.println();
  Serial.println();
  Serial.println("Startup");
  Serial.println("Reading EEPROM ssid");

  String esid;
  for (int i = 0; i < 32; ++i){
    esid += char(EEPROM.read(i));
  }
  Serial.println();
  Serial.print("SSID: ");
  Serial.println(esid);
  Serial.println("Reading EEPROM pass");

  String epass = "";
  for (int i = 32; i < 96; ++i){
    epass += char(EEPROM.read(i));
  }
  Serial.print("PASS: ");
  Serial.println(epass);
  WiFi.begin(esid.c_str(), epass.c_str());
  if (testWifi()){
    Serial.println("Succesfully Connected!!!");
    timer.setInterval(3000L, checkBlynkStatus); // check if Blynk server is connected every 3 seconds
    Blynk.config(AUTH);
    led_blink(50,50,20);
    //During Starting all Relays should TURN OFF
    digitalWrite(RelayPin5, toggleState_5);
    Blynk.virtualWrite(VPIN_BUTTON_5, toggleState_5); // Update Button Widget
    return;
  } else {
    Serial.println("Turning the HotSpot On");
    launchWeb();
    setupAP();// Setup HotSpot
  }

  Serial.println();
  Serial.println("Waiting.");

  while ((WiFi.status() != WL_CONNECTED)){
    Serial.print(".");
    delay(2000);
    server.handleClient();
  }
}
void loop()
{
  if (digitalRead(MODE_PIN) == 0) {//フラッシュボタンが押されていたら
    delay(500);
    if (digitalRead(MODE_PIN) == 0) ESP.reset();
  }
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("WiFi Not Connected");
  } else {
    Blynk.run();
  }

  timer.run(); // Initiates SimpleTimer
  if (wifiFlag == 0)
    with_internet();
  else
    without_internet();
}

void led_blink(int OnSec,int OffSec,int n){
  for(int i=0;i<n;i++){
    digitalWrite(LED_BUILTIN, LOW); // turn the LED on (HIGH is the voltage level)
    delay(OnSec); // wait for a second
    digitalWrite(LED_BUILTIN, HIGH); // turn the LED off by making the voltage LOW
    delay(OffSec); // wait for a second
  }
}

//-------- Fuctions used for WiFi credentials saving and connecting to it which you do not need to change
bool testWifi(void)
{
  delay(1000); //1秒待機
  if (digitalRead(MODE_PIN) == 0) {//フラッシュボタンが押されていたらWi-Fi不通扱いで戻す
    return false;
  }
  int c = 0;
  Serial.println("Waiting for Wifi to connect");
  while ( c < 20 ) {
    if (WiFi.status() == WL_CONNECTED) {
      return true;
    }
    delay(500);
    Serial.print("*");
    c++;
  }
  Serial.println("");
  Serial.println("Connect timed out, opening AP");
  return false;
}

void launchWeb()
{
  Serial.println("");
  if (WiFi.status() == WL_CONNECTED)
    Serial.println("WiFi connected");
  Serial.print("Local IP: ");
  Serial.println(WiFi.localIP());
  Serial.print("SoftAP IP: ");
  Serial.println(WiFi.softAPIP());
  createWebServer();
  // Start the server
  server.begin();
  Serial.println("Server started");
}

void setupAP(void)
{
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  int n = WiFi.scanNetworks();
  Serial.println("scan done");
  if (n == 0)
    Serial.println("no networks found");
  else {
    Serial.print(n);
    Serial.println(" networks found");
    for (int i = 0; i < n; ++i) {
      // Print SSID and RSSI for each network found
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(")");
      Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");
      delay(10);
    }
  }
  Serial.println("");
  st = "<ol>";
  for (int i = 0; i < n; ++i) {
    // Print SSID and RSSI for each network found
    st += "<li>";
    st += WiFi.SSID(i);
    st += " (";
    st += WiFi.RSSI(i);
    st += ")";
    st += (WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*";
    st += "</li>";
  }
  st += "</ol>";
  delay(100);
  WiFi.softAP("ESP8266HOTSPOT", "");
  Serial.println("softap");
  launchWeb();
  Serial.println("over");
}

void createWebServer()
{
  {
    server.on("/", []() {
      IPAddress ip = WiFi.softAPIP();
      String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
      content = "<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 at ";
      content += "<form action=\"/scan\" method=\"POST\"><input type=\"submit\" value=\"scan\"></form>";
      content += ipStr;
      content += "<p>";
      content += st;
      content += "</p><form method='get' action='setting'><label>SSID: </label><input name='ssid' length=32><input name='pass' length=64><input type='submit'></form>";
      content += "</html>";
      server.send(200, "text/html", content);
    });
    server.on("/scan", []() {
      //setupAP();
      IPAddress ip = WiFi.softAPIP();
      String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);

      content = "<!DOCTYPE HTML>\r\n<html>go back";
      server.send(200, "text/html", content);
    });

    server.on("/setting", []() {
      String qsid = server.arg("ssid");
      String qpass = server.arg("pass");
      if (qsid.length() > 0 && qpass.length() > 0) {
        Serial.println("clearing eeprom");
        for (int i = 0; i < 96; ++i) {
          EEPROM.write(i, 0);
        }
        Serial.println(qsid);
        Serial.println("");
        Serial.println(qpass);
        Serial.println("");

        Serial.println("writing eeprom ssid:");
        for (int i = 0; i < qsid.length(); ++i) {
          EEPROM.write(i, qsid[i]);
          Serial.print("Wrote: ");
          Serial.println(qsid[i]);
        }
        Serial.println("writing eeprom pass:");
        for (int i = 0; i < qpass.length(); ++i) {
          EEPROM.write(32 + i, qpass[i]);
          Serial.print("Wrote: ");
          Serial.println(qpass[i]);
        }
        EEPROM.commit();

        content = "{\"Success\":\"saved to eeprom... reset to boot into new wifi\"}";
        statusCode = 200;
        ESP.reset();
      } else {
        content = "{\"Error\":\"404 not found\"}";
        statusCode = 404;
        Serial.println("Sending 404");
      }
      server.sendHeader("Access-Control-Allow-Origin", "*");
      server.send(statusCode, "application/json", content);
    });
  }
}

Blynkの使い方については以前の記事でも説明しているから省くけど、要するにBlynkのスマホアプリで1個ウィジェットを作って仮想ピンを設定してそれと一致するピンに対応したプロシージャを作ればいいだけ。

BLYNK_WRITE(V?) {}

の部分ね。

それとWi-Fiを固定しないでそこにあるWi-Fi一覧を取得して一旦NodeMCUがウェブサーバーになってWi-Fiを決めさせるっていう設定にした。

これは参考のサイトを見てもらったほうがいい。自分では真似てコーディングしただけで内容の理解はしていない。

あちこちから切り貼りして作ったコードだからどこのサイトを参考にしたかまったく忘れてしまっているが感謝している。

タイトルとURLをコピーしました