ESP8266で家電(テレビ)を制御してみる

ESP8266で家電(テレビ)を制御してみる

ESP8266という小型WIFIモジュールを使って、家電の電源制御ができたのでまとめて書いてみる。

国内で購入すると、割高なのでAliexpressで中国から購入。
amazon.co.jpでも取り扱いがありますが国際便なので同じかも)

リレーモジュールはUSB電源5Vで動作するのであえて3.3Vに変換しなくても良い。
書き込みにはESP-01用のライターを使用しています。

 


今回はarduinoという開発ソフトを使用して、ESP8266に書き込むプログラムを作成。
littleFSにて、HTMLファイルをESP8266のファイル領域に書き込む。

Arduinoのセットアップについては、別記事を参照して下さい。

書き込み後にESP8266をリレーモジュールに挿して、USBで電源供給すると、WIFIの一覧にesp-xxxxxxが表示されるので、そのSSIDに接続します。

http://192.168.10.1を入力すると、ON/OFFの切替画面が表示される。
http://192.168.10.1/config/を入力すると、設定画面が表示されます。

WIFIクライアントとして接続する場合、接続先のSSID/パスワードを設定します。
DHCPでなく、固定IPで設定するほうが、直接IPアドレスを入力して制御できるので、おすすめです。

初回ログイン時は 認証が必要です。
 ユーザ = root  パスワード = root になっています
 不要な場合は143-145行をコメントアウトしてください。

 

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h> //ESP Web Server Library
#include <LittleFS.h>
#include <Ticker.h>

#define SETTING_INI  "/SETTING.txt"
#define RELAY_PIN  0 // GPIO0
#define RELAY_ON  LOW
#define RELAY_OFF HIGH

//#define DEBUG_RELAY

#define SSBAUD          115200  // logger on console

ESP8266WebServer server( 80 );
Ticker           ticker;
WiFiEventHandler NewClient;
// RELAY OUT STATUS
//bool IO_STATUS = RELAY_OFF;

// AP_MODE Use
String SOFTAP_SSID = "ESP-" + String(ESP.getChipId(), HEX);
String SOFTAP_PASS = "password"; // default

const String DEF_IP = "192.168.10.1"; //default
const String DEF_SN = "255.255.255.0";

// Basic authenticate
String www_username = "root";
String www_password = "root";

String XSSID = SOFTAP_SSID;
String XPASS = SOFTAP_PASS;
bool   UseIP = true;
String ConIP = DEF_IP; //default
String ConSN = DEF_SN;
String ConGW = DEF_IP;
String CName = "Controller";
bool   BotOf = false;

bool   APMode = false;
String MDNSName = "ESP-";

void setup() {
  IPAddress _ip, _gw, _sn;
  int       reConnect;
  delay(100);
  // Serial Port Open
  Serial.begin(SSBAUD);
  Serial.flush();

  Serial.println("***BOOT-UP***");
  pinMode(RELAY_PIN, OUTPUT);
  // initialize file System
  LittleFS.begin();
  Serial.println("FileList-----------");
  listDir( "/");
  Serial.println("------------Done.");

  bool FoundSetting = LoadConfig();
  if (!FoundSetting || (FoundSetting && XSSID == SOFTAP_SSID)) {
    APMode = true;
  }

  // Client Mode ---------------------------------
  if (!APMode) {
    WiFi.mode(WIFI_STA);
    DebugInfo();
    if (UseIP) {
      _ip.fromString(ConIP);
      _gw.fromString(ConGW);
      _sn.fromString(ConSN);
      WiFi.config(_ip, _gw, _sn);
    }
    delay(100);
    Serial.println("Will be Connecting to WIFI..");
    WiFi.begin(XSSID.c_str(), XPASS.c_str());
    for (reConnect = 1; reConnect < 120 ; reConnect++) {
      if (WiFi.status() == WL_CONNECTED) {
        break;
      }
      delay(500); // 0.5s
      Serial.println(".");
    }
    // 60 second time out
    if (reConnect < 120) {
      if (!UseIP) {
        Serial.println("");
        Serial.print("IP  Address: ");
        Serial.println(WiFi.localIP());
        Serial.print("Mac Address: ");
        Serial.println(WiFi.macAddress());
        Serial.print("Subnet Mask: ");
        Serial.println(WiFi.subnetMask());
        Serial.print("Gateway IP : ");
        Serial.println(WiFi.gatewayIP());
        Serial.print("DNS     IP : ");
        Serial.println(WiFi.dnsIP()); 
      }
      Serial.println("WiFi connected!");
      RelayControl((BotOf ? RELAY_OFF : RELAY_ON)); // boot on power-on
    } else {
      wifi_disconnect();
      Serial.println("Client Not Connect! Go AP Mode");
      APMode = true;
    }
  }
  // APMode --------------------------------------
  if (APMode) {
    WiFi.mode(WIFI_AP_STA);
    XSSID = SOFTAP_SSID;
    XPASS = SOFTAP_PASS;
    ConIP = DEF_IP;
    ConSN = DEF_SN;
    ConGW = DEF_IP;
    DebugInfo();
    WiFi.softAP(SOFTAP_SSID.c_str(), SOFTAP_PASS.c_str());
    _ip.fromString(ConIP);
    _sn.fromString(ConSN);
    WiFi.softAPConfig(_ip, _ip, _sn);
    NewClient = WiFi.onSoftAPModeStationConnected(&WiFiStationConnected);
    //  IO_STATUS = RELAY_ON;
  }
  // URL Request --------------------------------
  server.on("/config/", HTTP_POST, []() {
    SaveConfig();
    StreamWebSend("/config/");
    ticker.attach(3, RestartReady);
  });
  server.on("/", HTTP_POST, []() {
    PinOutControl();
  });
  server.on("/resetconfig", HTTP_GET, []() {
    configReset();
  });

  server.onNotFound([]() {
    if (server.hasArg("pin")) {
      PinOutControlWithApp();
    } else {
      // BASIC authenticate
      if (!server.authenticate(www_username.c_str(), www_password.c_str())) {
        return server.requestAuthentication();
      }
      StreamWebSend(server.uri());
    }
  });
  server.begin();
}
// Manage incoming device connection on ESP access point
void WiFiStationConnected(const WiFiEventSoftAPModeStationConnected& sta_info) {
  Serial.println("New Client is " + macToString(sta_info.mac));
}
String macToString(const unsigned char* mac) {
  char buf[20];
  snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  return String(buf);
}

// Serial Out Config
void DebugInfo() {
  if (APMode) {
    Serial.println("[AP SETTING MODE]");
  } else {
    if (UseIP) {
      Serial.println("[DYNAMIC IP MODE]");
    } else {
      Serial.println("[STATIC IP MODE]");
    }
  }
  Serial.println("SSID: " + XSSID);
  Serial.println("PASS: " + XPASS);
  Serial.println("MAC : " + WiFi.macAddress());
  if (UseIP) {
    Serial.println("IP  : " + ConIP);
    Serial.println("MASK: " + ConSN);
    Serial.println("GW  : " + ConGW);
  }
}

// load config file
bool LoadConfig() {
  File f = LittleFS.open(SETTING_INI, "r");
  delay(100);
  if (f) {
    String BWork;
    XSSID = f.readStringUntil('\n'); XSSID.trim(); // SSID
    XPASS = f.readStringUntil('\n'); XPASS.trim(); // PASS
    BWork = f.readStringUntil('\n'); BWork.trim(); // IP-MODE(true=static/false=DHCP)
    UseIP = ( BWork == "true" ? true : false);
    ConIP = f.readStringUntil('\n'); ConIP.trim(); // IP-ADRS
    ConSN = f.readStringUntil('\n'); ConSN.trim(); // IP-MASK
    ConGW = f.readStringUntil('\n'); ConGW.trim(); // IP-GWAY
    CName = f.readStringUntil('\n'); CName.trim(); // Control name
    if (CName.length() == 0) {
      CName = "Controler";
    }
    BWork = f.readStringUntil('\n'); BWork.trim(); // Booting On Power On Relay
    BotOf = ( BWork == "true" ? true : false);
    f.close();
    Serial.println("Config Loaded!");
    return true;
  }
  return false;
}
// save config file
void SaveConfig() {
  Serial.println("SaveConfig");
  XSSID = server.arg("ssid");
  XPASS = server.arg("pass");
  UseIP = (server.arg("useip") == "true" ? true : false);
  ConIP = server.arg("ip");
  ConSN = server.arg("mask");
  ConGW = server.arg("gway");
  CName = server.arg("cnam");
  BotOf = (server.arg("btof") == "true" ? true : false);
  File f = LittleFS.open(SETTING_INI, "w");
  delay(100);
  f.println(XSSID);
  f.println(XPASS);
  f.println(UseIP ? "true" : "false");
  f.println(ConIP);
  f.println(ConSN);
  f.println(ConGW);
  f.println(CName);
  f.println(BotOf ? "true" : "false");
  f.close();
}

void PinOutControl() {
  // PIO control
  if (server.hasArg(CName)) {
    if (server.arg(CName) == "1") {
      Serial.println(CName + ":ON");
      RelayControl(RELAY_ON);
    } else {
      Serial.println(CName + ":OFF");
      RelayControl(RELAY_OFF);
    }
  }
  StreamWebSend("/");
}

void PinOutControlWithApp() {
  // PIO control
  if (server.hasArg("pin")) {
    if (server.arg("pin") == "ON") {
      Serial.println(CName + ":ON");
      RelayControl(RELAY_ON);
    } else if (server.arg("pin") == "OFF") {
      Serial.println(CName + ":OFF");
      RelayControl(RELAY_OFF);
    }
    String RELAY_STATUS = (digitalRead(RELAY_PIN) == RELAY_ON) ? "ON" : "OFF";
    server.send(200, "text/plain", RELAY_STATUS );
  } else {


  }
}
void listDir(const char *dirname) {
  Dir root = LittleFS.openDir(dirname);
  while (root.next()) {
    String TargetPath = String(dirname) + '/' + String(root.fileName());
    if (root.isDirectory()) {
      listDir(TargetPath.c_str());
    }else{
      File file = root.openFile("r");
      Serial.print("  FILE: ");
      Serial.print(TargetPath);
      Serial.print("  SIZE: ");
      Serial.print(file.size());
      time_t t = file.getLastWrite();
      struct tm * tmstruct = localtime(&t);
      file.close();        
      Serial.printf("  LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec);
    }
  }
}


void RelayControl(int sw) {
#ifdef DEBUG_RELAY
  SerialOut("GPIO(" + String(RELAY_PIN) + ") is " + ((sw ==  RELAY_ON) ? "on" : "off"));
#else
  digitalWrite(RELAY_PIN, sw);
#endif
  // IO_STATUS = sw;
}

//  MIMEtype
String getContentType(String filename) {
  if (filename.endsWith(".html") || filename.endsWith(".htm")) return "text/html";
  else if (filename.endsWith(".css")) return "text/css";
  else if (filename.endsWith(".js" )) return "application/javascript";
  else if (filename.endsWith(".png")) return "image/png";
  else if (filename.endsWith(".gif")) return "image/gif";
  else if (filename.endsWith(".jpg")) return "image/jpeg";
  else return "text/plain";
}
//  open and send LittleFS file( and parameter)
bool StreamWebSend(String path) {
  // settings
  if (path == "/config/setting.js") {
    String SettingInfo, UIP, BTOF;
    UIP  = UseIP ? "true" : "false";
    BTOF = BotOf ? "true" : "false";
    SettingInfo  = "var Setting = {SSID:'" + XSSID + "',PASS:'" + XPASS + "',UseIP:" + UIP + ",ConIP:'" + ConIP + "',ConSN:'" + ConSN + "',ConGW:'" + ConGW + "',CName:'" + CName + "',BtOf:" + BTOF + "};";
    server.send(200, "application/javascript", SettingInfo);
    return true;
  }
  // port info
  if (path == "/status.js") {
    String PortInfo, PTS;
    PTS = ( digitalRead(RELAY_PIN) == RELAY_ON) ? "1" : "0";
    //  PTS = (IO_STATUS == RELAY_ON) ? "1" : "0";
    PortInfo  = "var Ports = " + PTS + ";" + "var CName = '" + CName + "';";
    server.send(200, "application/javascript", PortInfo);
    return true;
  }
  // load add path
  if (path.endsWith("/")) {
    path += "index.html";
  }
  // send file
  if (LittleFS.exists(path)) {
    String contentType = getContentType(path);
    Serial.println("Sending..[" + path + "]");
    File file = LittleFS.open(path, "r");
    size_t send = server.streamFile(file, contentType);
    file.close();
    return true;
  }
  // not found
  Serial.println("404 not found " + path);
  server.send(404, "text/plain", "404 Page Not Found");
}

void configReset() {
  LittleFS.remove(SETTING_INI);
  delay(200);
  Serial.println("remove Setting File");
  RestartReady();
}

// restart Hooker
void RestartReady() {
  wifi_disconnect();
  LittleFS.end();
  delay(100);
  server.close();
  delay(100);
  ESP.reset();
  ESP.restart();
}

void wifi_disconnect() {
  while (WiFi.status() == WL_CONNECTED ) {
    WiFi.disconnect();
    delay(1000);
  }
}
void loop() {
  server.handleClient();
}

■arduino のソースコード ESPCONTROLER_src esp8266_src

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA