Je me suis permis de mettre le script en français, de changer quelques icônes et de paramétrer pour l'ESP12E selon le câblage posté plus haut. J'ai aussi paramétré pour éteindre la LED de l'ESP pour ne pas trop consommer inutilement :
Code : Tout sélectionner
// Includes
#include <Time.h>
#include <TimeLib.h>
#include <ESP8266mDNS.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <SoftwareSerial.h>
#include <FS.h>
#include <MQTT.h>
#include <PubSubClient.h>
// webserver
ESP8266WebServer server(80);
MDNSResponder mdns;
WiFiClient client;
String roombotVersion = "0.7.2";
// WIFI
String ssid = "nom wifi"; // à changer
String password = "mot de passe wifi"; // à changer
String espName = "Roomboticz";
// AP mode when WIFI not available
const char *APssid = "Roombot";
const char *APpassword = "configesp";
String ClientIP;
// MQTT
const char* mqttServer = "IP du MQTT"; // à changer
const char* mqttUsername = NULL; // à changer
const char* mqttPassword = NULL; // à changer
const char* mqttClientId = "roomboticz"; // Must be unique on the MQTT network
PubSubClient mqttclient(client);
// MQTT Topics
const char* commandtopic = "roomba/commands";
const char* responsetopic = "roomba/response";
// Pimatic settings
long sendInterval = 600000; //in millis
long lastInterval = 0;
String WMode = "1";
#define SERIAL_RX 3 // pin for SoftwareSerial RX
#define SERIAL_TX 1 // pin for SoftwareSerial TX
#define Wake_Pin 14
SoftwareSerial mySerial(SERIAL_RX, SERIAL_TX); // (RX, TX. inverted, buffer)
// Div
File UploadFile;
String fileName;
String BSlocal = "0";
int FSTotal;
int FSUsed;
String state;
//-------------- FSBrowser application -----------
//format bytes
String formatBytes(size_t bytes) {
if (bytes < 1024) {
return String(bytes) + "B";
} else if (bytes < (1024 * 1024)) {
return String(bytes / 1024.0) + "KB";
} else if (bytes < (1024 * 1024 * 1024)) {
return String(bytes / 1024.0 / 1024.0) + "MB";
} else {
return String(bytes / 1024.0 / 1024.0 / 1024.0) + "GB";
}
}
// HTML
String header = "<html lang='en'><head><title>Panneau de contrôle de Roomboticz</title><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'><link rel='stylesheet' href='http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css'><script src='https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js'></script><script src='http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js'></script></head><body>";
String navbar = "<nav class='navbar navbar-default'><div class='container-fluid'><div class='navbar-header'><a class='navbar-brand' href='/'>Panneau de contrôle de Roomboticz</a></div><div><ul class='nav navbar-nav'><li><a href='/'><span class='glyphicon glyphicon-info-sign'></span> Etat</a></li><li class='dropdown'><a class='dropdown-toggle' data-toggle='dropdown' href='#'><span class='glyphicon glyphicon-cog'></span> Outils<span class='caret'></span></a><ul class='dropdown-menu'><li><a href='/updatefwm'><span class='glyphicon glyphicon-refresh'></span> Mise à jour</a></li><li><a href='/filemanager.html'><span class='glyphicon glyphicon-file'></span> Gestionnaire de fichier</a></li><li><a href='/fupload'><span class='glyphicon glyphicon-share-alt'></span> Importer fichier</a></li></ul></li><li><a href='https://github.com/incmve/roomba-eps8266/wiki' target='_blank'><span class='glyphicon glyphicon-question-sign'></span> Aide</a></li></ul></div></div></nav>";
String containerStart = "<div class='container'><div class='row'>";
String containerEnd = "<div class='clearfix visible-lg'></div></div></div>";
String siteEnd = "</body></html>";
String panelHeaderName = "<div class='col-md-4'><div class='page-header'><h1>";
String panelHeaderEnd = "</h1></div>";
String panelEnd = "</div>";
String panelBodySymbol = "<div class='panel panel-default'><div class='panel-body'><span class='glyphicon glyphicon-";
String panelBodyName = "'></span> ";
String panelBodyValue = "<span class='pull-right'>";
String panelcenter = "<div class='row'><div class='span6' style='text-align:center'>";
String panelBodyEnd = "</span></div></div>";
String inputBodyStart = "<form action='' method='POST'><div class='panel panel-default'><div class='panel-body'>";
String inputBodyName = "<div class='form-group'><div class='input-group'><span class='input-group-addon' id='basic-addon1'>";
String inputBodyPOST = "</span><input type='text' name='";
String inputBodyClose = "' class='form-control' aria-describedby='basic-addon1'></div></div>";
String roombacontrol = "<a href='/roombastart'<button type='button' class='btn btn-default'><span class='glyphicon glyphicon-play' aria-hidden='true'></span> Démarrage</button></a><a href='/roombamax'<button type='button' class='btn btn-default'><span class='glyphicon glyphicon-star-empty' aria-hidden='true'></span> Nettoyage maxi</button></a><a href='/roombastop'<button type='button' class='btn btn-default'><span class='glyphicon glyphicon-stop' aria-hidden='true'></span> Stop</button></a><a href='/roombaspot'<button type='button' class='btn btn-default'><span class='glyphicon glyphicon-record' aria-hidden='true'></span> Spot</button></a><a href='/roombadock'<button type='button' class='btn btn-default'><span class='glyphicon glyphicon-home' aria-hidden='true'></span> Base</button></a><a href='/roombasing'<button type='button' class='btn btn-default'><span class='glyphicon glyphicon-music' aria-hidden='true'></span> Star Wars</button></a></div>";
// ROOT page
void handle_root()
{
// get IP
IPAddress ip = WiFi.localIP();
ClientIP = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
delay(500);
String title1 = panelHeaderName + String("Paramètres") + panelHeaderEnd;
String IPAddClient = panelBodySymbol + String("globe") + panelBodyName + String("Adresse IP") + panelBodyValue + ClientIP + panelBodyEnd;
String ClientName = panelBodySymbol + String("tag") + panelBodyName + String("Nom du robot") + panelBodyValue + espName + panelBodyEnd;
String Version = panelBodySymbol + String("info-sign") + panelBodyName + String("Version Roomboticz") + panelBodyValue + roombotVersion + panelBodyEnd;
String Uptime = panelBodySymbol + String("time") + panelBodyName + String("Durée") + panelBodyValue + hour() + String(" h ") + minute() + String(" min ") + second() + String(" sec") + panelBodyEnd + panelEnd;
String title2 = panelHeaderName + String("Pimatic server") + panelHeaderEnd;
String IPAddServ = panelBodySymbol + String("globe") + panelBodyName + String("IP Address") + panelBodyValue + panelBodyEnd;
// String User = panelBodySymbol + String("user") + panelBodyName + String("Username") + panelBodyValue + Username + panelBodyEnd + panelEnd;
String title3 = panelHeaderName + String("Commandes") + panelHeaderEnd;
String commands = panelBodySymbol + panelBodyName + panelcenter + roombacontrol + panelBodyEnd;
server.send ( 200, "text/html", header + navbar + containerStart + title1 + IPAddClient + ClientName + Version + Uptime + title3 + commands + containerEnd + siteEnd);
}
// Setup
void setup(void)
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
mySerial.begin(115200);
pinMode(SERIAL_RX, INPUT);
pinMode(SERIAL_TX, OUTPUT);
pinMode(Wake_Pin, OUTPUT);
digitalWrite(Wake_Pin, LOW);
digitalWrite(LED_BUILTIN,HIGH); // mettre LOW pour maintenir la LED de l'ESP allumée
// Check if SPIFFS is OK
if (!SPIFFS.begin())
{
Serial.println("Défaut de SPIFFS, nécessite son formatage");
handleFormat();
delay(500);
ESP.restart();
}
else
{
FSInfo fs_info;
if (!SPIFFS.info(fs_info))
{
Serial.println("Echec fs_info");
}
else
{
FSTotal = fs_info.totalBytes;
FSUsed = fs_info.usedBytes;
}
}
WiFi.hostname(espName);
WiFi.begin(ssid.c_str(), password.c_str());
int i = 0;
while (WiFi.status() != WL_CONNECTED && i < 31)
{
delay(1000);
Serial.print(".");
++i;
}
if (WiFi.status() != WL_CONNECTED && i >= 30)
{
WiFi.disconnect();
delay(1000);
Serial.println("");
Serial.println("Je n'arrive pas à me connecter au réseau( ");
Serial.println("Définir le point d'accès:");
Serial.println("SSID: ");
Serial.println(APssid);
Serial.println("Mot de passe: ");
Serial.println(APpassword);
WiFi.mode(WIFI_AP);
WiFi.softAP(APssid, APpassword);
WMode = "AP";
Serial.print("Connecté à ");
Serial.println(APssid);
IPAddress myIP = WiFi.softAPIP();
Serial.print("Adresse IP: ");
Serial.println(myIP);
}
else
{
Serial.println("");
Serial.print("CConnecté à ");
Serial.println(ssid);
Serial.print("Adresse IP: ");
Serial.println(WiFi.localIP());
Serial.print("Nom de l'appareil : ");
Serial.println(espName);
}
server.on ( "/format", handleFormat );
server.on("/", handle_root);
server.on("/", handle_fupload_html);
server.on("/api", handle_api);
server.on("/updatefwm", handle_updatefwm_html);
server.on("/fupload", handle_fupload_html);
server.on("/roombastart", handle_roomba_start);
server.on("/roombamax", handle_roomba_max);
server.on("/roombastop", handle_roomba_stop);
server.on("/roombaspot", handle_roomba_spot);
server.on("/roombadock", handle_roomba_dock);
server.on("/roombasing", handle_roomba_sing);
server.on("/restart", handle_esp_restart);
// Upload firmware:
server.on("/updatefw2", HTTP_POST, []() {
server.sendHeader("Connection", "terminée");
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []()
{
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START)
{
fileName = upload.filename;
Serial.setDebugOutput(true);
Serial.printf("Update: %s\n", upload.filename.c_str());
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if (!Update.begin(maxSketchSpace)) { //start with max available size
Update.printError(Serial);
}
}
else if (upload.status == UPLOAD_FILE_WRITE)
{
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize)
{
Update.printError(Serial);
}
}
else if (upload.status == UPLOAD_FILE_END)
{
if (Update.end(true)) //true to set the size to the current progress
{
Serial.printf("Mise à jour terminée: %u\nredemarrage...\n", upload.totalSize);
}
else
{
Update.printError(Serial);
}
Serial.setDebugOutput(false);
}
yield();
});
// upload file to SPIFFS
server.on("/fupload2", HTTP_POST, []() {
server.sendHeader("Connection", "terminee");
server.sendHeader("Acces-Control-Allow-Origin", "*");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
}, []() {
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START)
{
fileName = upload.filename;
Serial.setDebugOutput(true);
//fileName = upload.filename;
Serial.println("Chargement fichier: " + fileName);
String path;
if (fileName.indexOf(".css") >= 0)
{
path = "/css/" + fileName;
}
else if (fileName.indexOf(".js") >= 0)
{
path = "/js/" + fileName;
}
else if (fileName.indexOf(".otf") >= 0 || fileName.indexOf(".eot") >= 0 || fileName.indexOf(".svg") >= 0 || fileName.indexOf(".ttf") >= 0 || fileName.indexOf(".woff") >= 0 || fileName.indexOf(".woff2") >= 0)
{
path = "/fonts/" + fileName;
}
else
{
path = "/" + fileName;
}
UploadFile = SPIFFS.open(path, "w");
// already existing file will be overwritten!
}
else if (upload.status == UPLOAD_FILE_WRITE)
{
if (UploadFile)
UploadFile.write(upload.buf, upload.currentSize);
Serial.println(fileName + " Taille: " + upload.currentSize);
}
else if (upload.status == UPLOAD_FILE_END)
{
Serial.print("Taille du chargement: ");
Serial.println(upload.totalSize); // need 2 commands to work!
if (UploadFile)
UploadFile.close();
}
yield();
});
if (!mdns.begin(espName.c_str(), WiFi.localIP())) {
Serial.println("Error setting up MDNS responder!");
while (1) {
delay(1000);
}
}
server.begin();
Serial.println("Serveur HTTP demarre");
//MQTT
mqttclient.setServer(mqttServer, 1883);
mqttclient.setCallback(callback);
}
// LOOP
void loop(void)
{
if (mySerial.available()) {
Serial.print(mySerial.read());
}
server.handleClient();
/*
if (millis() - lastInterval > sendInterval) //update pimatic
{
handle_charging_state();
handle_voltage();
handle_charging_sources();
lastInterval = millis();
}
*/
if (!mqttclient.connected()) {
reconnect();
}
mqttclient.loop();
}
// handles
// Define a song
// Data is 2 bytes per note
void sing(uint8_t songNumber, const uint8_t* data, int len)
{
mySerial.write(140);
mySerial.write(songNumber);
mySerial.write(len >> 1); // 2 bytes per note
mySerial.write(data, len);
}
void playSong(uint8_t songNumber)
{
mySerial.write(141);
mySerial.write(songNumber);
}
void handle_api()
{
// Get vars for all commands
String action = server.arg("action");
String value = server.arg("value");
String api = server.arg("api");
if (action == "clean" && value == "start")
{
handle_roomba_start();
}
if (action == "dock" && value == "home")
{
handle_roomba_dock();
}
if (action == "reset" && value == "true")
{
server.send ( 200, "text/html", "Redemarrage de l'ESP OK");
delay(500);
Serial.println("RESET");
ESP.restart();
}
if (action == "charge")
{
handle_charging_state();
}
if (action == "voltage")
{
handle_voltage();
}
if (action == "chargesource")
{
handle_charging_sources();
}
}
void handle_updatefwm_html()
{
server.send ( 200, "text/html", "<form method='POST' action='/updatefw2' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form><br<b>Fichier au format *.bin uniquement!!</b>");
}
void handle_fupload_html()
{
String HTML = "<br>Fichier a flasher :<br>";
Dir dir = SPIFFS.openDir("/");
while (dir.next())
{
fileName = dir.fileName();
size_t fileSize = dir.fileSize();
HTML += fileName.c_str();
HTML += " ";
HTML += formatBytes(fileSize).c_str();
HTML += " , ";
HTML += fileSize;
HTML += "<br>";
//Serial.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str());
}
server.send ( 200, "text/html", "<form method='POST' action='/fupload2' enctype='multipart/form-data'><input type='file' name='update' multiple><input type='submit' value='Update'></form><br<b>Pour fichiers web uniquement !!</b>possibilite d ajouter plusieurs fichiers<br>" + HTML);
}
void handle_update_upload()
{
if (server.uri() != "/update2") return;
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
Serial.setDebugOutput(true);
Serial.printf("Update: %s\n", upload.filename.c_str());
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if (!Update.begin(maxSketchSpace)) { //start with max available size
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
Update.printError(Serial);
}
Serial.setDebugOutput(false);
}
yield();
}
void handle_update_html2()
{
server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
handle_root();
}
void handleFormat()
{
server.send ( 200, "text/html", "OK");
Serial.println("Formatage du SPIFFS");
if (SPIFFS.format())
{
if (!SPIFFS.begin())
{
Serial.println("Echec formatage du SPIFFS");
}
}
else
{
Serial.println("Echec formatage du SPIFFS");
}
if (!SPIFFS.begin())
{
Serial.println("Defaut du SPIFFS, necessite son formatage");
}
else
{
Serial.println("SPIFFS monté");
}
}
void handle_roomba_wake() {
digitalWrite(Wake_Pin, HIGH);
delay(100);
digitalWrite(Wake_Pin, LOW);
delay(500);
digitalWrite(Wake_Pin, HIGH);
delay(200);
}
void handle_roomba_start()
{
handle_roomba_wake();
Serial.println("Mise en marche");
mySerial.write(128);
delay(500);
mySerial.write(131);
delay(500);
mySerial.write(135);
Serial.println("Je vais aspirer, mon maître");
handle_root();
mqttclient.publish(responsetopic, String("Je vais aspirer, mon maître").c_str());
}
void handle_roomba_sing()
{
handle_roomba_wake();
Serial.println("Mise en marche");
mySerial.write(128);
delay(500);
mySerial.write(131);
delay(500);
uint8_t song[] = {57, 30, 57, 30, 57, 30, 53, 20, 60, 10, 57, 30, 53, 20, 60, 10, 57, 45};
sing(1, song, sizeof(song));
uint8_t song2[] = {64, 30, 64, 30, 64, 30, 65, 20, 60, 10, 56, 30, 53, 20, 60, 10, 57, 45};
sing(2, song2, sizeof(song2));
playSong(1);
delay(3900);
playSong(2);
delay(4000);
Serial.println("Vous aimez ?");
handle_root();
mqttclient.publish(responsetopic, String("Vous aimez ?").c_str());
}
void handle_roomba_max()
{
handle_roomba_wake();
Serial.println("Mise en service");
mySerial.write(128);
delay(50);
mySerial.write(131);
delay(50);
mySerial.write(136);
Serial.println("Nettoyage maximum");
handle_root();
mqttclient.publish(responsetopic, String("Maximum cleaning").c_str());
}
void handle_roomba_spot()
{
handle_roomba_wake();
mySerial.write(128);
delay(50);
mySerial.write(131);
delay(50);
mySerial.write(134);
Serial.println("Nettoyage spot");
handle_root();
mqttclient.publish(responsetopic, String("Spot cleaning").c_str());
}
void handle_roomba_stop()
{
handle_roomba_wake();
mySerial.write(128);
delay(50);
mySerial.write(131);
delay(50);
mySerial.write(133);
Serial.println("STOP");
handle_root();
mqttclient.publish(responsetopic, String("STOP").c_str());
}
void handle_roomba_dock()
{
handle_roomba_wake();
mySerial.write(128);
delay(50);
mySerial.write(131);
delay(50);
mySerial.write(143);
Serial.println("Thank you for letting me rest, going home master");
handle_root();
mqttclient.publish(responsetopic, String("Merci de me laisser me reposer, je rentre à la base mon maître").c_str());
}
void handle_esp_restart() {
ESP.restart();
handle_root();
}
void handle_charging_state() {
//
int charge = 0;
// int data;
Serial.println("Start handle_charging_state");
mySerial.write(142);
delay(50);
mySerial.write(21);
delay(50);
if (mySerial.available()) {
charge = Serial.read();
Serial.println("..");
Serial.print(charge);
switch (charge) {
case 0: {
String data = "Not Charging";
mqttclient.publish(responsetopic, String(data).c_str());
break;
}
case 1: {
String data = "Reconditioning";
mqttclient.publish(responsetopic, String(data).c_str());
break;
}
case 2: {
String data = "Full Charging";
mqttclient.publish(responsetopic, String(data).c_str());
break;
}
case 3: {
String data = "Trickle Charging";
mqttclient.publish(responsetopic, String(data).c_str());
break;
}
case 4: {
String data = "Waiting";
mqttclient.publish(responsetopic, String(data).c_str());
break;
}
case 5: {
String data = "Charging Fault Condition";
String variable = String(charge);
mqttclient.publish(responsetopic, String(data).c_str());
break;
}
default:
// if nothing else matches, do the default
// default is optional
mqttclient.publish(responsetopic, String("no info").c_str());
break;
}
}
else {
mqttclient.publish(responsetopic, String("no info").c_str());
}
}
void handle_voltage() {
Serial.println("Tension");
String voltage = "0";
mySerial.write(142);
delay(50);
mySerial.write(22);
delay(50);
if (mySerial.available()) {
Serial.println("..");
Serial.print(Serial.read());
String data = String(Serial.read());
mqttclient.publish(responsetopic, String(data).c_str());
}
else {
mqttclient.publish(responsetopic, String("no info").c_str());
}
}
void handle_charging_sources() {
Serial.println("Charging source");
int source;
mySerial.write(142);
delay(50);
mySerial.write(34);
delay(50);
if (mySerial.available()) {
source = Serial.read();
Serial.println("..");
Serial.print(source);
switch (source) {
case 0: {
String data = "Not Charging";
mqttclient.publish(responsetopic, String(data).c_str());
break;
}
case 1: {
String data = "Reconditioning";
mqttclient.publish(responsetopic, String(data).c_str());
break;
}
default:
// if nothing else matches, do the default
// default is optional
mqttclient.publish(responsetopic, String("no info").c_str());
break;
}
}
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
Serial.println("payload");
payload[length] = '\0';
String strPayload = String((char*)payload);
Serial.println(strPayload);
if (strPayload == "clean") {
handle_roomba_start();
}
else if (strPayload == "max") {
handle_roomba_max();
}
else if (strPayload == "spot") {
handle_roomba_spot();
}
else if (strPayload == "stop") {
handle_roomba_stop();
}
else if (strPayload == "dock") {
handle_roomba_dock();
}
else if (strPayload == "wake") {
handle_roomba_wake();
}
else if (strPayload == "sing") {
handle_roomba_sing();
}
else if (strPayload == "charge") {
handle_charging_state();
}
else if (strPayload == "voltage") {
handle_voltage();
}
else if (strPayload == "chargesource") {
handle_charging_sources();
}
else if (strPayload == "reset") {
ESP.restart();
}
}
void reconnect() {
// Loop until we're reconnected
while (!mqttclient.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (mqttclient.connect(mqttClientId, mqttUsername, mqttPassword)) {
Serial.println("connected");
// subscribe
mqttclient.subscribe(commandtopic);
} else {
Serial.print("failed, rc=");
Serial.print(mqttclient.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}