えっと、HamCQはino形式のファイルのアップロードをサポートしていません。
まず、Arduino IDEで新しいファイルを作成し、以下のコードをコピーします。WIFIの名前、パスワード、Bofa Cloudのキー、およびFMOIPを変更してください。その後、ESP-01Sにコンパイルして書き込みます。開発ボードはESP8266を選択し、ポート番号はデバイスマネージャーで確認したポート番号を指定してください。
/*
ESP01S + バファクラウド + HTTP API → FMO デバイスのリモートコントローラー
機能:
1. バファクラウド/米家を通じて FMO デバイスを制御
2. ローカルの HTTP API を通じて直接制御(代替案)
必要な Arduino ライブラリ:
1. PubSubClient by Nick O'Leary
2. WebSockets by Markus Sattler
ハードウェア:ESP-01S
GPIO2 は、オンボード LED (ステータス指示用)
*/
#include <ESP8266WiFi.h>
インクルード <WebSocketsClient.h>
インクルード <PubSubClient.h>
インクルード <ESP8266WebServer.h>
// ================== ユーザー設定領域 ==================
const char* ssid = "WIFI名"; // 2.4GHz WiFiのみ対応
const char* password = "WIFIパスワード";
// Bemfa Cloudの設定(https://cloud.bemfa.com)
const char* mqtt_server = "bemfa.com"; // Bemfa CloudのMQTTサーバー
const int mqtt_port = 9501; // SSL非対応ポート
const char* mqtt_client_id = "Bemfa Cloudのキー"; // Bemfa Cloudのコンソールで取得したキー
// 推奨:中国語に優しい名前に変更(例:"zhongji001" または "diantai001")
const char* mqtt_topic = "FMO001"; // 001で終わるものはアウトレット、002はライト
// HTTPサーバーのポート
const int HTTP_PORT = 80;
// FMOデバイスのWebSocket設定
const char* fmo_host = "FMO IPアドレス";
const int fmo_ws_port = 80;
const char* fmo_ws_path = "/ws";
// =================================================
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
WebSocketsClient wsClient;
ESP8266WebServer httpServer(HTTP_PORT);
// ステータス変数
bool wsConnected = false;
bool mqttConnectedFlag = false;
String pendingCmd = ""; // 送信するコマンドをキャッシュ
unsigned long lastHeartbeat = 0;
const unsigned long HEARTBEAT_INTERVAL = 30000; // 30秒間の心拍
// LED ピン(ESP-01S の GPIO2、回路に組み込まれた青色LED、ローレベルで点灯)
const int LED_PIN = 2;
void setup() {
Serial.begin(115200);
遅延(100);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH); // LEDを消灯
Serial.println("\n[FMOコントローラー] 開始...");
setupWiFi();
// MQTTの設定
mqttClient.setServer(mqtt_server, mqtt_port);
mqttClient.setCallback(mqttCallback);
mqttClient.setBufferSize(512);
// WebSocket の設定
wsClient.begin(fmo_host, fmo_ws_ポート, fmo_ws_パス);
wsClient.onEvent(webSocketEvent);
wsClient.setReconnectInterval(5000); // 切断後5秒で再接続
wsClient.enableHeartbeat(15000, 3000, 2); // WebSocket 心拍
// HTTP API の設定
setupHTTPServer();
}
void loop() {
// WiFi の維持
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi が切断されました、再接続中...");
setupWiFi();
}
// MQTT の維持
if (!mqttClient.connected()) {
mqttConnectedFlag = false;
reconnectMQTT();
} else {
if (!mqttConnectedFlag) {
mqttConnectedFlag = true;
Serial.println("MQTT 接続完了。");
}
}
mqttClient.loop();
// WebSocket の維持
wsClient.loop();
// HTTP リクエストの処理
httpServer.handleClient();
// 法ファクラウド心拍(デバイスをオンラインに保つ)
unsigned long now = millis();
if (now - lastHeartbeat >= HEARTBEAT_INTERVAL) {
lastHeartbeat = now;
if (mqttClient.connected()) {
mqttClient.publish(mqtt_topic, "ping");
Serial.println("[MQTT] Heartbeat sent");
}
}
delay(10); // 一時的な休止状態にし、ペット犬の再起動を防ぐ
}
// ================== Wi-Fi ==================
void setupWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("WiFiへの接続中");
int 試行回数 = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 40) {
遅延
}(500);
シリアルポートに出力: "."
LED\_PIN のデジタル出力を、LED が点灯している状態と消灯する状態を反転させる。(LED_PIN)// LED点滅
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println();
Serial.print("WiFi接続、IP: ");
Serial.println(WiFi.localIP());
digitalWrite(LED_PIN, LOW); // WiFiが接続されたことを示すためにLEDを点灯
} else {
Serial.println("\nWiFi接続失敗、再試行...");
}
}
// ================== MQTT (バファクラウド) ==================
void reconnectMQTT() {
Serial.print("MQTTへの接続を開始します...");
if (mqttClient.connect(mqtt_client_id)) {
Serial.println("接続成功");
mqttClient.subscribe(mqtt_topic);
Serial.printf("トピックにサブスクライブ: %s\n", mqtt_topic);
} else {
Serial.print("失敗、rc=");
Serial.print(mqttClient.state());
Serial.println(" 5秒後に再試行");
delay(5000);
}
}
void mqttCallback(char* topic, byte* payload, unsigned int length) {
String msg = "";
for (unsigned int i = 0; i < length; i++) {
msg += (char*)payload[i];
}
Serial.println(msg);
} < length; i++) {
msg += (char)payload[i];
}
msg.trim();
Serial.print("[MQTT] 受信: ");
Serial.println(msg);
if (msg == "on") {
Serial.println("コマンド: STANDARD モードに切り替える");
sendFMOCommand(0);
} else if (msg == "off") {
Serial.println("コマンド:STANDBYモードに切り替える");
sendFMOCommand(1);
}
// 「heartbeat/down」のようなハートビートの降下メッセージを無視する
}
// ================== WebSocket (FMO) ```
void webSocketEvent(WStype_t type, uint8_t* payload, size_t length) {
switch (type) {
case WStype_DISCONNECTED:
wsConnected = false;
Serial.println("[WS] FMOとの接続が切断されました");
digitalWrite(LED_PIN, HIGH); // LEDを消してWSの切断を表示
break;
case WStype_CONNECTED:
wsConnected = true;
Serial.println("[WS] FMOへの接続が確立されました");
digitalWrite(LED_PIN, LOW); // LEDを点灯して双方向接続が正常であることを表示
// 送信するコマンドがある場合は、すぐに送信
if (pendingCmd.length() > 0) {
sendFMOCommand(pendingCmd.toInt());
pendingCmd = "";
}
break;
case WStype_TEXT:
Serial.printf("[WS] レスポンス: %s\n", payload);
// ここで setScreenModeResponse を解析し、成功を確認できます
break;
case WStype_ERROR:
Serial.println("[WS] エラーが発生しました");
break;
default:
break;
}
}
void sendFMOCommand(int mode) {
// mode: 0 = 通常モード (オン), 1 = スリープモード (オフ)
if (!wsConnected) {
Serial.println("[WS] 接続されていません、コマンドをキャッシュ...");
pendingCmd = String(mode);
return;
}
String json = "{\"type\":\"ui\",\"subType\":\"setScreenMode\",\"data\":{\"mode\":" + String(mode) + "}}";
wsClient.sendTXT(json);
Serial.print("[WS] 送信: ");
Serial.println(json);
}
// ================== HTTP API ==================
void setupHTTPServer() {
httpServer.on("/", HTTP_GET, handleRoot);
httpServer.on("/on", HTTP_GET, handleOn);
httpServer.on("/off", HTTP_GET, handleOff);
httpServer.on("/status", HTTP_GET, handleStatus);
httpServer.onNotFound(handleNotFound);
httpServer.begin();
Serial.println("[HTTP] サーバーがポート " + String(HTTP_PORT));
}
void handleRoot() {
String html = "<html><head><文字コード:UTF-8><title>FMOのオペレーター</タイトル></ヘッド>";
html += "<`スタイル="フォントファミリー:サンセリフ、最大幅:400px、マージン:40px自動、テキストアライメント:中央"`>";
html += "<h2>FMO リモコン</h2>";
html += "<p>デバイスのIPアドレス: 「" + WiFi.localIP().toString() + "」</p>";
html += "<p>WebSocket: 「「接続済み」または「未接続」」</p>";
html += "<p>MQTT: 「」+ (mqttClient.connected() ? "接続済み" : "未接続") + 」</p>";
html += "<br><<a href='/on' style='display:inline-block;padding:20px 40px;margin:10px;font-size:18px;background:#4CAF50;color:white;text-decoration:none;border-radius:8px;'>>(標準モード)を開始</a>";
html += "<br><a href='/off' style='display:inline-block;padding:20px 40px;margin:10px;font-size:18px;background:#f44336;color:white;text-decoration:none;border-radius:8px;'>シャットダウン(スタンバイモード)</a>";
html += "</本文></html>";
httpServer.send(200, "text/html", html);
}
void handleOn() {
Serial.println("[HTTP] リクエスト: /on");
sendFMOCommand(0);
String json = "{\"status\":\"ok\",\"action\":\"off\",\"mode\":\"standard\"}";
httpServer.send(200, "application/json", json);
}
void handleOff() {
Serial.println("[HTTP] リクエスト: /off");
sendFMOCommand(1);
String json = "{\"status\":\"ok\",\"action\":\"off\",\"mode\":\"standby\"}";
httpServer.send(200, "application/json", json);
}
void handleStatus() {
String json = "{\"status\":\"ok\",\"wifi\":\"connected\",\"ip\":\"" + WiFi.localIP().toString() + "\",\"websocket\":" + (wsConnected ? "true" : "false") + ",\"mqtt\":" + (mqttClient.connected() ? "true" : "false") + "}";
httpServer.send(200, "application/json", json);
}
void handleNotFound() {
httpServer.send(404, "application/json", "{\"status\":\"error\",\"message\":\"Not Found\"}");
}