first commit
This commit is contained in:
280
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Domoticz.cpp
Normal file
280
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Domoticz.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
#include "Domoticz.h"
|
||||
|
||||
Domoticz::Domoticz(String domoticz, String port, const char* ssid, const char* pass)
|
||||
{
|
||||
_domoticz = domoticz;
|
||||
_port = port;
|
||||
_ssid = ssid;
|
||||
_pass = pass;
|
||||
|
||||
// // Domo
|
||||
// _domoc[_domoticz.length() + 1];
|
||||
// _domoticz.toCharArray(_domoc, _domoticz.length() + 1);
|
||||
//
|
||||
// // Port
|
||||
// char portc[_port.length() + 1];
|
||||
// _port.toCharArray(portc, _port.length() + 1);
|
||||
// _iport = atoi(portc);
|
||||
|
||||
}
|
||||
|
||||
boolean Domoticz::connect()
|
||||
{
|
||||
|
||||
// Domo
|
||||
char _domoc[_domoticz.length() + 1];
|
||||
_domoticz.toCharArray(_domoc, _domoticz.length() + 1);
|
||||
|
||||
// Port
|
||||
char portc[_port.length() + 1];
|
||||
_port.toCharArray(portc, _port.length() + 1);
|
||||
int _iport = atoi(portc);
|
||||
|
||||
boolean connected = _client.connect(_domoc, _iport);
|
||||
Serial.print(_domoc);
|
||||
Serial.print(" ");
|
||||
Serial.print(_iport);
|
||||
Serial.print(" ");
|
||||
Serial.print(" connected ");
|
||||
Serial.print(connected);
|
||||
Serial.print(" ");
|
||||
Serial.println(WiFi.localIP());
|
||||
return connected;
|
||||
}
|
||||
|
||||
void Domoticz::close()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Domoticz::initWifi()
|
||||
{
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.begin(_ssid, _pass); //Connect to local Wifi
|
||||
|
||||
Serial.println();
|
||||
Serial.print("Connecting to WiFi");
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(500);
|
||||
}
|
||||
Serial.println("WiFi Connected!");
|
||||
Serial.print("Connexion au reseau ");
|
||||
Serial.println(WiFi.localIP());
|
||||
}
|
||||
|
||||
String Domoticz::generateKey()
|
||||
{
|
||||
// WiFi.mode(WIFI_AP);
|
||||
|
||||
// Do a little work to get a unique-ish name. Append the
|
||||
// last two bytes of the MAC (HEX'd) to "Thing-":
|
||||
uint8_t mac[WL_MAC_ADDR_LENGTH];
|
||||
WiFi.softAPmacAddress(mac);
|
||||
String macID = String(mac[WL_MAC_ADDR_LENGTH - 2], HEX) + String(mac[WL_MAC_ADDR_LENGTH - 1], HEX);
|
||||
macID.toUpperCase();
|
||||
String AP_NameString = "ESP8266 Thing " + macID;
|
||||
|
||||
char AP_NameChar[AP_NameString.length() + 1];
|
||||
memset(AP_NameChar, 0, AP_NameString.length() + 1);
|
||||
|
||||
for (int i = 0; i < AP_NameString.length(); i++)
|
||||
{
|
||||
AP_NameChar[i] = AP_NameString.charAt(i);
|
||||
}
|
||||
|
||||
// WiFi.softAP(AP_NameChar, WiFiAPPSK);
|
||||
|
||||
Serial.println("macID=" + macID);
|
||||
_macID = macID;
|
||||
|
||||
return macID;
|
||||
}
|
||||
|
||||
void Domoticz::executeJson(String json, String svalue, String nvalue)
|
||||
{
|
||||
// Domo
|
||||
char _domoc[_domoticz.length() + 1];
|
||||
_domoticz.toCharArray(_domoc, _domoticz.length() + 1);
|
||||
|
||||
// Port
|
||||
char portc[_port.length() + 1];
|
||||
_port.toCharArray(portc, _port.length() + 1);
|
||||
int _iport = atoi(portc);
|
||||
|
||||
_client.print("GET " + json); //"GET /json.htm?type=command¶m=getuservariables");
|
||||
|
||||
if (svalue != "") {
|
||||
_client.print("&svalue=" + svalue);
|
||||
}
|
||||
if (nvalue != "") {
|
||||
_client.print("&nvalue=" + nvalue);
|
||||
}
|
||||
|
||||
_client.println(" HTTP/1.1");
|
||||
_client.print("Host: ");
|
||||
_client.print(_domoc);
|
||||
_client.print(":");
|
||||
_client.println(_iport);
|
||||
_client.println("User-Agent: Arduino-ethernet");
|
||||
_client.println("Connection: close");
|
||||
_client.println();
|
||||
|
||||
Serial.println("json=" + json);
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Read current supply voltage
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
String Domoticz::readVcc() {
|
||||
// most exact output
|
||||
uint16_t v = ESP.getVcc();
|
||||
float_t v_cal = ((float) v / 1024.0f);
|
||||
char v_str[10];
|
||||
dtostrf(v_cal, 5, 3, v_str);
|
||||
sprintf(v_str, "%s", v_str);
|
||||
Serial.print("Tension lue ");
|
||||
Serial.println(String(v_str));
|
||||
|
||||
return String(v_str); //ESP.getVcc() / 1024.0f; // Vcc in millivolts
|
||||
}
|
||||
|
||||
String Domoticz::getIndexOfString(String data, String separator, int index)
|
||||
{
|
||||
int found = 0;
|
||||
int strIndex[] = { 0, -1 };
|
||||
int maxIndex = data.length() - 1;
|
||||
|
||||
for (int i = 0; i <= maxIndex && found <= index; i++) {
|
||||
if (data.charAt(i) == separator.charAt(0) || i == maxIndex) {
|
||||
found++;
|
||||
strIndex[0] = strIndex[1] + 1;
|
||||
strIndex[1] = (i == maxIndex) ? i + 1 : i;
|
||||
}
|
||||
}
|
||||
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
|
||||
}
|
||||
|
||||
String Domoticz::readLine()
|
||||
{
|
||||
return _client.readStringUntil('\n');
|
||||
}
|
||||
|
||||
void Domoticz::readTempDayValues(String idx)
|
||||
{
|
||||
String json = "/json.htm?type=graph&sensor=temp&idx=" + idx + "&range=day";
|
||||
int nb = 0;
|
||||
int nbVal = 0;
|
||||
data = "";
|
||||
labels = "";
|
||||
String label = "";
|
||||
Serial.println("readTempDayValues " + idx);
|
||||
connect();
|
||||
executeJson(json, "", "");
|
||||
while (1)
|
||||
{
|
||||
// Avoid WDT reset during long process
|
||||
yield();
|
||||
String line = readLine();
|
||||
|
||||
if (line == "") {
|
||||
break;
|
||||
}
|
||||
|
||||
if (line.indexOf("\"d\"") != -1) {
|
||||
//Serial.println(line + " ");
|
||||
label = line.substring(line.indexOf(":") + 2, line.length());
|
||||
}
|
||||
if (line.indexOf("\"te\"") != -1) {
|
||||
// Serial.println(line + " ");
|
||||
nbVal++;
|
||||
if (nbVal % 10) {
|
||||
String val = line.substring(line.indexOf(":") + 2, line.indexOf(".") + 2);
|
||||
if (val != NULL) {
|
||||
//Serial.println(val);
|
||||
if (data == "") {
|
||||
data += val;
|
||||
labels = "\"0\"";
|
||||
} else {
|
||||
char charBuf[50];
|
||||
// val.toCharArray(charBuf, 50);
|
||||
data += "," + val; //printf("%2.1f", atof(charBuf));
|
||||
// data += "," + val;
|
||||
// Serial.println(printf("%2.1f", atof(charBuf)));
|
||||
labels = labels + label;
|
||||
}
|
||||
if (data.length() > 500) {
|
||||
data = data.substring(data.indexOf(",") + 1);
|
||||
labels = labels.substring(labels.indexOf(",") + 1);
|
||||
}
|
||||
yield();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
nb++;
|
||||
}
|
||||
// Avoid WDT reset during long process
|
||||
yield();
|
||||
// Serial.println(data);
|
||||
// Serial.println(labels);
|
||||
yield();
|
||||
Serial.print("Nombre de lignes ");
|
||||
Serial.println(nb);
|
||||
close();
|
||||
}
|
||||
|
||||
void Domoticz::getIdFromDomoticz(String macID, Params * params)
|
||||
{
|
||||
String separator = ",";
|
||||
int nb = 0;
|
||||
|
||||
Serial.println("Dans getIdFromDomoticz " + macID);
|
||||
|
||||
// -------------------
|
||||
// LECTURE PARAM
|
||||
// -------------------
|
||||
if (params->esp8266_id == "") {
|
||||
boolean connected = connect();
|
||||
|
||||
if (connected) {
|
||||
Serial.println("Connected to domoticz");
|
||||
executeJson("/json.htm?type=command¶m=getuservariables", "", "");
|
||||
// Read the first line of the request
|
||||
while (1) {
|
||||
String req = readLine();
|
||||
if (req.indexOf(macID) != -1) {
|
||||
Serial.println(req);
|
||||
req = readLine();
|
||||
req = readLine();
|
||||
String val = req.substring(req.indexOf(":") + 2, req.length() - 1);
|
||||
Serial.println(val);
|
||||
val.replace("\"", "");
|
||||
params->esp8266_id = getIndexOfString(val, separator, 0);
|
||||
String tmp = getIndexOfString(val, separator, 1);
|
||||
|
||||
char tmpc[tmp.length() + 1];
|
||||
tmp.toCharArray(tmpc, tmp.length() + 1);
|
||||
params->sleepTime = atoi(tmpc);
|
||||
if (params->sleepTime <= 0) {
|
||||
params->sleepTime = 60;
|
||||
}
|
||||
params->esp8266_id_Vcc = getIndexOfString(val, separator, 2);
|
||||
Serial.println("esp8266_id=" + params->esp8266_id);
|
||||
Serial.println("sleepTime=" + tmp);
|
||||
Serial.println("esp8266_id_Vcc=" + params->esp8266_id_Vcc);
|
||||
break;
|
||||
}
|
||||
if (req == "" || nb > 500) {
|
||||
break;
|
||||
}
|
||||
nb++;
|
||||
}
|
||||
_client.stop();
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
38
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Domoticz.h
Executable file
38
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Domoticz.h
Executable file
@@ -0,0 +1,38 @@
|
||||
#ifndef Domoticz_h
|
||||
#define Domoticz_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include "Params.h"
|
||||
|
||||
|
||||
class Domoticz
|
||||
{
|
||||
public:
|
||||
Domoticz(String domoticz, String port, const char* ssid, const char* pass);
|
||||
boolean connect();
|
||||
void close();
|
||||
void initWifi();
|
||||
void executeJson(String json, String svalue, String nvalue);
|
||||
//String getIdFromDomoticz();
|
||||
String generateKey();
|
||||
String readLine();
|
||||
String readVcc();
|
||||
void readTempDayValues(String idx);
|
||||
void getIdFromDomoticz(String macID, Params * params);
|
||||
static String getIndexOfString(String data, String separator, int index);
|
||||
private:
|
||||
public:
|
||||
const char* _pass;
|
||||
const char* _ssid;
|
||||
WiFiClient _client;
|
||||
char _domoc[];
|
||||
int _iport;
|
||||
String _domoticz;
|
||||
String _port;
|
||||
String _macID;
|
||||
String data = "";
|
||||
String labels = "";
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,142 @@
|
||||
//extern "C" {
|
||||
//#include "user_interface.h"
|
||||
//}
|
||||
|
||||
// Need for getVcc
|
||||
ADC_MODE(ADC_VCC);
|
||||
|
||||
|
||||
/////////////////////
|
||||
// Domoticz Classe
|
||||
/////////////////////
|
||||
#include "Domoticz.h"
|
||||
Domoticz domo("192.168.1.3", "81", "Livebox-37cc", "8A6060920A8A86896F770F2C47");
|
||||
#include "Modules.h"
|
||||
Modules modules;
|
||||
Params * params;
|
||||
#include "ServeurWeb.h"
|
||||
|
||||
ServeurWeb * serveurWeb;
|
||||
WiFiServer server(80);
|
||||
|
||||
#include "Octoprint.h"
|
||||
Octoprint octoprint("192.168.1.3", "5000", "B5746ACFF37140D0B5F6FEAAC4413B5C");
|
||||
|
||||
#include "Somfy.h"
|
||||
Somfy *somfy;
|
||||
// Ticker mqtt_error_timer(somfy.blink_function, 10, 11);
|
||||
// Ticker blink_timer(somfy.blink_function, 200, 21);
|
||||
// Ticker publish_timer(somfy.blink_function, 10, 11);
|
||||
|
||||
// Convert image to char array http://www.digole.com/tools/PicturetoC_Hex_converter.php
|
||||
|
||||
Params p;
|
||||
ServeurWeb sw;
|
||||
Somfy s;
|
||||
// domoticz
|
||||
String macID = "";
|
||||
unsigned long milli;
|
||||
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
// /* sda scl */
|
||||
// Wire.pins(SDA, SCL);
|
||||
// Wire.begin(SDA, SCL);
|
||||
|
||||
// Conversion d'objet en pointeur
|
||||
somfy = &s;
|
||||
params = &p;
|
||||
|
||||
somfy->init();
|
||||
|
||||
serveurWeb = &sw;
|
||||
serveurWeb->domoticz = &domo;
|
||||
serveurWeb->modules = &modules;
|
||||
serveurWeb->server = &server;
|
||||
serveurWeb->server->begin();
|
||||
|
||||
delay(100);
|
||||
domo.initWifi();
|
||||
macID = domo.generateKey();
|
||||
domo.getIdFromDomoticz(macID, params);
|
||||
|
||||
pinMode(RELAY_PIN, OUTPUT);
|
||||
digitalWrite(RELAY_PIN, HIGH);
|
||||
|
||||
// octoprint.connect();
|
||||
// octoprint.executeJson("/api/printer", "", "");
|
||||
// octoprint.executeJsonPost("/api/printer/command", "{\"command\": \"M503\"}");
|
||||
|
||||
milli = 0; millis();
|
||||
delay(100);
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//serveurWeb->loop();
|
||||
somfy->loop();
|
||||
|
||||
// yield();
|
||||
// files->ftpSrv.handleFTP(); //make sure in loop you call handleFTP()!!
|
||||
// yield();
|
||||
|
||||
// if (milli == 0 || milli + params->sleepTime * 1000 <= millis() ) {
|
||||
// // // Avoid WDT reset during long process
|
||||
// // yield();
|
||||
// milli = millis();
|
||||
// modules.readTemp();
|
||||
// printInfo();
|
||||
//
|
||||
// // Test Json
|
||||
// domo.readTempDayValues(params->esp8266_id);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
void printInfo()
|
||||
{
|
||||
|
||||
boolean connected = domo.connect();
|
||||
|
||||
Serial.println("Dans printInfo " + connected + ' ' + params->esp8266_id);
|
||||
yield();
|
||||
|
||||
// Domoticz format /json.htm?type=command¶m=udevice&idx=IDX&nvalue=0&svalue=TEMP;HUM;HUM_STAT
|
||||
|
||||
if (connected && params->esp8266_id != "") {
|
||||
Serial.println("Dans set temperature" + String(modules.temp));
|
||||
//domo.executeJson();
|
||||
if (modules.temp < 50 && modules.temp > 0) {
|
||||
String svalue = String(modules.temp) + ";" + String(modules.humidity) + ";0";
|
||||
|
||||
Serial.println(svalue);
|
||||
domo.executeJson("/json.htm?type=command¶m=udevice&idx=" + params->esp8266_id, svalue, "0");
|
||||
yield();
|
||||
|
||||
domo._client.stop();
|
||||
yield();
|
||||
}
|
||||
delay(200);
|
||||
}
|
||||
connected = domo.connect();
|
||||
if (connected && params->esp8266_id_Vcc != "") {
|
||||
Serial.print(" Envoi tension ");
|
||||
Serial.print(params->esp8266_id_Vcc);
|
||||
Serial.print(" ");
|
||||
yield();
|
||||
|
||||
String vcc = domo.readVcc();
|
||||
Serial.println(vcc);
|
||||
yield();
|
||||
|
||||
// domo._client.print("GET /json.htm?type=command¶m=udevice&idx=");
|
||||
domo.executeJson("/json.htm?type=command¶m=udevice&idx=" + params->esp8266_id_Vcc, vcc, "0");
|
||||
domo._client.stop();
|
||||
yield();
|
||||
|
||||
}
|
||||
}
|
||||
60
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Modules.cpp
Normal file
60
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Modules.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "Modules.h"
|
||||
|
||||
// int status = WL_IDLE_STATUS; // the Wifi radio's status
|
||||
//WiFiClient client;
|
||||
// Dallas
|
||||
|
||||
OneWire oneWire(ONE_WIRE_BUS);
|
||||
DallasTemperature DS18B20(&oneWire);
|
||||
|
||||
|
||||
Modules::Modules()
|
||||
{
|
||||
Serial.println("--------------------------------------");
|
||||
Serial.println("Init Module");
|
||||
pinMode(RELAY_PIN, OUTPUT);
|
||||
pinMode(RELAY_PIN_02, OUTPUT);
|
||||
pinMode(RELAY_PIN_03, OUTPUT);
|
||||
pinMode(RELAY_PIN_04, OUTPUT);
|
||||
delay(200);
|
||||
digitalWrite(RELAY_PIN, HIGH);
|
||||
digitalWrite(RELAY_PIN_02, HIGH);
|
||||
digitalWrite(RELAY_PIN_03, HIGH);
|
||||
digitalWrite(RELAY_PIN_04, HIGH);
|
||||
}
|
||||
|
||||
bool Modules::readTemp()
|
||||
{
|
||||
//DS18B20.begin();
|
||||
Serial.println("--------------------------------------");
|
||||
DS18B20.requestTemperatures();
|
||||
temp = DS18B20.getTempCByIndex(0);
|
||||
Serial.print("Température Dallas =");
|
||||
|
||||
Serial.println(temp);
|
||||
if (temp > 0 && temp < 70) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Modules::sleep(int sleepTime)
|
||||
{
|
||||
Serial.print("Go to sleep ");
|
||||
Serial.println(sleepTime);
|
||||
delay(20);
|
||||
|
||||
ESP.deepSleep(sleepTime * 1000000L); // Infini
|
||||
|
||||
//sleepWifi();
|
||||
delay(200);
|
||||
}
|
||||
|
||||
|
||||
void Modules::relay(int pin, int value)
|
||||
{
|
||||
delay(100);
|
||||
digitalWrite(pin, value);
|
||||
delay(100);
|
||||
}
|
||||
28
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Modules.h
Normal file
28
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Modules.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef Modules_h
|
||||
#define Modules_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <DallasTemperature.h>
|
||||
|
||||
#include "Pins.h"
|
||||
|
||||
// ################# Barometre ####
|
||||
#define ALTITUDE 19.0 // Altitude of SparkFun's HQ in Boulder, CO. in meters
|
||||
|
||||
//SFE_BMP180 pressure;
|
||||
// #####################
|
||||
|
||||
class Modules
|
||||
{
|
||||
public:
|
||||
Modules();
|
||||
bool readTemp();
|
||||
void sleep(int sleepTime);
|
||||
void relay(int pin, int value);
|
||||
private:
|
||||
public:
|
||||
double humidity = 0;
|
||||
double temp = 0;
|
||||
int end_filament = 0;
|
||||
};
|
||||
#endif
|
||||
178
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Octoprint.cpp
Normal file
178
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Octoprint.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
#include "Octoprint.h"
|
||||
|
||||
Octoprint::Octoprint(String octoprint, String port, String API)
|
||||
{
|
||||
_octoprint = octoprint;
|
||||
_port = port;
|
||||
_API = API;
|
||||
}
|
||||
|
||||
boolean Octoprint::connect()
|
||||
{
|
||||
|
||||
// Domo
|
||||
char _octo[_octoprint.length() + 1];
|
||||
_octoprint.toCharArray(_octo, _octoprint.length() + 1);
|
||||
|
||||
// Port
|
||||
char portc[_port.length() + 1];
|
||||
_port.toCharArray(portc, _port.length() + 1);
|
||||
int _iport = atoi(portc);
|
||||
|
||||
boolean connected = _client.connect(_octo, _iport);
|
||||
Serial.print(_octo);
|
||||
Serial.print(" ");
|
||||
Serial.print(_iport);
|
||||
Serial.print(" ");
|
||||
Serial.print(" connected ");
|
||||
Serial.print(connected);
|
||||
Serial.print(" ");
|
||||
Serial.println(WiFi.localIP());
|
||||
return connected;
|
||||
}
|
||||
|
||||
void Octoprint::close()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Octoprint::executeJson(String json, String svalue, String nvalue)
|
||||
{
|
||||
// Domo
|
||||
char _octo[_octoprint.length() + 1];
|
||||
_octoprint.toCharArray(_octo, _octoprint.length() + 1);
|
||||
|
||||
// Port
|
||||
char portc[_port.length() + 1];
|
||||
_port.toCharArray(portc, _port.length() + 1);
|
||||
int _iport = atoi(portc);
|
||||
|
||||
_client.print("GET " + json); //"GET /json.htm?type=command¶m=getuservariables");
|
||||
|
||||
if (svalue != "") {
|
||||
_client.print("&svalue=" + svalue);
|
||||
}
|
||||
if (nvalue != "") {
|
||||
_client.print("&nvalue=" + nvalue);
|
||||
}
|
||||
|
||||
_client.println(" HTTP/1.1");
|
||||
_client.print("Host: ");
|
||||
_client.print(_octo);
|
||||
_client.print(":");
|
||||
_client.println(_iport);
|
||||
_client.println("User-Agent: Arduino-ethernet");
|
||||
_client.println("X-Api-Key:" + _API);
|
||||
_client.println("Connection: close");
|
||||
_client.println();
|
||||
|
||||
Serial.println("json=" + json);
|
||||
|
||||
long interval = 2000;
|
||||
unsigned long currentMillis = millis(), previousMillis = millis();
|
||||
|
||||
while(!_client.available()){
|
||||
if( (currentMillis - previousMillis) > interval ){
|
||||
Serial.println("Timeout");
|
||||
_client.stop();
|
||||
return;
|
||||
}
|
||||
currentMillis = millis();
|
||||
}
|
||||
|
||||
// while (_client.connected())
|
||||
// {
|
||||
// if ( _client.available() )
|
||||
// {
|
||||
// char str=_client.read();
|
||||
// Serial.print(str);
|
||||
// }
|
||||
// }
|
||||
|
||||
while (1)
|
||||
{
|
||||
// Avoid WDT reset during long process
|
||||
yield();
|
||||
String line = readLine();
|
||||
|
||||
if (line == "") {
|
||||
break;
|
||||
}
|
||||
Serial.println(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Octoprint::executeJsonPost(String json, String postData)
|
||||
{
|
||||
if (connect()) {
|
||||
|
||||
_client.println("POST " +json + " HTTP/1.1");
|
||||
_client.println("Host: " + _octoprint + ":" + _port);
|
||||
_client.println("Cache-Control: no-cache");
|
||||
_client.println("X-Api-Key:" + _API);
|
||||
_client.println("Content-Type: application/json");
|
||||
_client.print("Content-Length: ");
|
||||
_client.println(postData.length());
|
||||
_client.println();
|
||||
_client.println(postData);
|
||||
|
||||
long interval = 2000;
|
||||
unsigned long currentMillis = millis(), previousMillis = millis();
|
||||
|
||||
while(!_client.available()){
|
||||
if( (currentMillis - previousMillis) > interval ){
|
||||
Serial.println("Timeout");
|
||||
_client.stop();
|
||||
return;
|
||||
}
|
||||
currentMillis = millis();
|
||||
}
|
||||
|
||||
// while (_client.connected())
|
||||
// {
|
||||
// if ( _client.available() )
|
||||
// {
|
||||
// char str=_client.read();
|
||||
// Serial.print(str);
|
||||
// }
|
||||
// }
|
||||
while (1)
|
||||
{
|
||||
// Avoid WDT reset during long process
|
||||
yield();
|
||||
String line = readLine();
|
||||
|
||||
if (line == "") {
|
||||
break;
|
||||
}
|
||||
Serial.println(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
String Octoprint::getIndexOfString(String data, String separator, int index)
|
||||
{
|
||||
int found = 0;
|
||||
int strIndex[] = { 0, -1 };
|
||||
int maxIndex = data.length() - 1;
|
||||
|
||||
for (int i = 0; i <= maxIndex && found <= index; i++) {
|
||||
if (data.charAt(i) == separator.charAt(0) || i == maxIndex) {
|
||||
found++;
|
||||
strIndex[0] = strIndex[1] + 1;
|
||||
strIndex[1] = (i == maxIndex) ? i + 1 : i;
|
||||
}
|
||||
}
|
||||
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
|
||||
}
|
||||
|
||||
String Octoprint::readLine()
|
||||
{
|
||||
return _client.readStringUntil('\n');
|
||||
}
|
||||
|
||||
|
||||
33
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Octoprint.h
Normal file
33
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Octoprint.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef Octoprint_h
|
||||
#define Octoprint_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include "Params.h"
|
||||
|
||||
|
||||
class Octoprint
|
||||
{
|
||||
public:
|
||||
Octoprint(String octoprint, String port, String API);
|
||||
boolean connect();
|
||||
void close();
|
||||
void executeJson(String json, String svalue, String nvalue);
|
||||
void executeJsonPost(String json, String postData);
|
||||
//String getIdFromOctoprint();
|
||||
String readLine();
|
||||
static String getIndexOfString(String data, String separator, int index);
|
||||
private:
|
||||
const char* _pass;
|
||||
public:
|
||||
const char* _ssid;
|
||||
WiFiClient _client;
|
||||
char _octo[];
|
||||
int _iport;
|
||||
String _octoprint;
|
||||
String _port;
|
||||
String _API;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
7
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Params.cpp
Executable file
7
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Params.cpp
Executable file
@@ -0,0 +1,7 @@
|
||||
#include "Params.h"
|
||||
|
||||
Params::Params()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
15
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Params.h
Executable file
15
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Params.h
Executable file
@@ -0,0 +1,15 @@
|
||||
#ifndef Params_h
|
||||
#define Params_h
|
||||
#include <Arduino.h>
|
||||
|
||||
|
||||
class Params {
|
||||
public :
|
||||
Params();
|
||||
public :
|
||||
String esp8266_id;
|
||||
String esp8266_id_Vcc;
|
||||
int sleepTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
29
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Pins.h
Executable file
29
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Pins.h
Executable file
@@ -0,0 +1,29 @@
|
||||
#ifndef Pins_h
|
||||
#define Pins_h
|
||||
#include <Arduino.h>
|
||||
|
||||
// #define SDA D1
|
||||
// #define SCL D2
|
||||
|
||||
#define ONE_WIRE_BUS D4 // DS18B20 pin
|
||||
#define RELAY_PIN D5
|
||||
#define RELAY_PIN_02 D6
|
||||
#define RELAY_PIN_03 D7
|
||||
#define RELAY_PIN_04 D0
|
||||
|
||||
#define FILAMENT_DETECTION 0
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// #define D0 16
|
||||
// #define D1 5 // I2C Bus SCL (clock)
|
||||
// #define D2 4 // I2C Bus SDA (data)
|
||||
// #define D3 0
|
||||
// #define D4 2 // Same as "LED_BUILTIN", but inverted logic
|
||||
// #define D5 14 // SPI Bus SCK (clock)
|
||||
// #define D6 12 // SPI Bus MISO
|
||||
// #define D7 13 // SPI Bus MOSI
|
||||
// #define D8 15 // SPI Bus SS (CS)
|
||||
// #define D9 3 // RX0 (Serial console)
|
||||
// #define D10 1 // TX0 (Serial console)
|
||||
657
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/PubSubClient.cpp
Normal file
657
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/PubSubClient.cpp
Normal file
@@ -0,0 +1,657 @@
|
||||
/*
|
||||
PubSubClient.cpp - A simple client for MQTT.
|
||||
Nick O'Leary
|
||||
http://knolleary.net
|
||||
*/
|
||||
|
||||
#include "PubSubClient.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
PubSubClient::PubSubClient() {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
this->_client = NULL;
|
||||
this->stream = NULL;
|
||||
setCallback(NULL);
|
||||
}
|
||||
|
||||
PubSubClient::PubSubClient(Client& client) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(addr, port);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(addr,port);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
}
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(addr, port);
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(addr,port);
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
}
|
||||
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(ip, port);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(ip,port);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
}
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(ip, port);
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(ip,port);
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
}
|
||||
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(domain,port);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(domain,port);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
}
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(domain,port);
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(domain,port);
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id) {
|
||||
return connect(id,NULL,NULL,0,0,0,0,1);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id, const char *user, const char *pass) {
|
||||
return connect(id,user,pass,0,0,0,0,1);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) {
|
||||
return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage,1);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) {
|
||||
return connect(id,user,pass,willTopic,willQos,willRetain,willMessage,1);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession) {
|
||||
if (!connected()) {
|
||||
int result = 0;
|
||||
Serial.print("client");
|
||||
if (domain != NULL) {
|
||||
result = _client->connect(this->domain, this->port);
|
||||
} else {
|
||||
result = _client->connect(this->ip, this->port);
|
||||
}
|
||||
Serial.println(result);
|
||||
|
||||
if (result == 1) {
|
||||
nextMsgId = 1;
|
||||
// Leave room in the buffer for header and variable length field
|
||||
uint16_t length = MQTT_MAX_HEADER_SIZE;
|
||||
unsigned int j;
|
||||
|
||||
#if MQTT_VERSION == MQTT_VERSION_3_1
|
||||
uint8_t d[9] = {0x00,0x06,'M','Q','I','s','d','p', MQTT_VERSION};
|
||||
#define MQTT_HEADER_VERSION_LENGTH 9
|
||||
#elif MQTT_VERSION == MQTT_VERSION_3_1_1
|
||||
uint8_t d[7] = {0x00,0x04,'M','Q','T','T',MQTT_VERSION};
|
||||
#define MQTT_HEADER_VERSION_LENGTH 7
|
||||
#endif
|
||||
for (j = 0;j<MQTT_HEADER_VERSION_LENGTH;j++) {
|
||||
buffer[length++] = d[j];
|
||||
}
|
||||
|
||||
uint8_t v;
|
||||
if (willTopic) {
|
||||
v = 0x04|(willQos<<3)|(willRetain<<5);
|
||||
} else {
|
||||
v = 0x00;
|
||||
}
|
||||
if (cleanSession) {
|
||||
v = v|0x02;
|
||||
}
|
||||
|
||||
if(user != NULL) {
|
||||
v = v|0x80;
|
||||
|
||||
if(pass != NULL) {
|
||||
v = v|(0x80>>1);
|
||||
}
|
||||
}
|
||||
|
||||
buffer[length++] = v;
|
||||
|
||||
buffer[length++] = ((MQTT_KEEPALIVE) >> 8);
|
||||
buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF);
|
||||
|
||||
CHECK_STRING_LENGTH(length,id)
|
||||
length = writeString(id,buffer,length);
|
||||
if (willTopic) {
|
||||
CHECK_STRING_LENGTH(length,willTopic)
|
||||
length = writeString(willTopic,buffer,length);
|
||||
CHECK_STRING_LENGTH(length,willMessage)
|
||||
length = writeString(willMessage,buffer,length);
|
||||
}
|
||||
|
||||
if(user != NULL) {
|
||||
CHECK_STRING_LENGTH(length,user)
|
||||
length = writeString(user,buffer,length);
|
||||
if(pass != NULL) {
|
||||
CHECK_STRING_LENGTH(length,pass)
|
||||
length = writeString(pass,buffer,length);
|
||||
}
|
||||
}
|
||||
|
||||
write(MQTTCONNECT,buffer,length-MQTT_MAX_HEADER_SIZE);
|
||||
|
||||
lastInActivity = lastOutActivity = millis();
|
||||
|
||||
while (!_client->available()) {
|
||||
unsigned long t = millis();
|
||||
if (t-lastInActivity >= ((int32_t) MQTT_SOCKET_TIMEOUT*1000UL)) {
|
||||
_state = MQTT_CONNECTION_TIMEOUT;
|
||||
_client->stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
uint8_t llen;
|
||||
uint16_t len = readPacket(&llen);
|
||||
|
||||
if (len == 4) {
|
||||
if (buffer[3] == 0) {
|
||||
lastInActivity = millis();
|
||||
pingOutstanding = false;
|
||||
_state = MQTT_CONNECTED;
|
||||
return true;
|
||||
} else {
|
||||
_state = buffer[3];
|
||||
}
|
||||
}
|
||||
_client->stop();
|
||||
} else {
|
||||
_state = MQTT_CONNECT_FAILED;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Serial.println("end connect");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// reads a byte into result
|
||||
boolean PubSubClient::readByte(uint8_t * result) {
|
||||
uint32_t previousMillis = millis();
|
||||
while(!_client->available()) {
|
||||
yield();
|
||||
uint32_t currentMillis = millis();
|
||||
if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*result = _client->read();
|
||||
return true;
|
||||
}
|
||||
|
||||
// reads a byte into result[*index] and increments index
|
||||
boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){
|
||||
uint16_t current_index = *index;
|
||||
uint8_t * write_address = &(result[current_index]);
|
||||
if(readByte(write_address)){
|
||||
*index = current_index + 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t PubSubClient::readPacket(uint8_t* lengthLength) {
|
||||
uint16_t len = 0;
|
||||
if(!readByte(buffer, &len)) return 0;
|
||||
bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH;
|
||||
uint32_t multiplier = 1;
|
||||
uint16_t length = 0;
|
||||
uint8_t digit = 0;
|
||||
uint16_t skip = 0;
|
||||
uint8_t start = 0;
|
||||
|
||||
do {
|
||||
if (len == 5) {
|
||||
// Invalid remaining length encoding - kill the connection
|
||||
_state = MQTT_DISCONNECTED;
|
||||
_client->stop();
|
||||
return 0;
|
||||
}
|
||||
if(!readByte(&digit)) return 0;
|
||||
buffer[len++] = digit;
|
||||
length += (digit & 127) * multiplier;
|
||||
multiplier *= 128;
|
||||
} while ((digit & 128) != 0);
|
||||
*lengthLength = len-1;
|
||||
|
||||
if (isPublish) {
|
||||
// Read in topic length to calculate bytes to skip over for Stream writing
|
||||
if(!readByte(buffer, &len)) return 0;
|
||||
if(!readByte(buffer, &len)) return 0;
|
||||
skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2];
|
||||
start = 2;
|
||||
if (buffer[0]&MQTTQOS1) {
|
||||
// skip message id
|
||||
skip += 2;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint16_t i = start;i<length;i++) {
|
||||
if(!readByte(&digit)) return 0;
|
||||
if (this->stream) {
|
||||
if (isPublish && len-*lengthLength-2>skip) {
|
||||
this->stream->write(digit);
|
||||
}
|
||||
}
|
||||
if (len < MQTT_MAX_PACKET_SIZE) {
|
||||
buffer[len] = digit;
|
||||
}
|
||||
len++;
|
||||
}
|
||||
|
||||
if (!this->stream && len > MQTT_MAX_PACKET_SIZE) {
|
||||
len = 0; // This will cause the packet to be ignored.
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
boolean PubSubClient::loop() {
|
||||
if (connected()) {
|
||||
unsigned long t = millis();
|
||||
if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) {
|
||||
if (pingOutstanding) {
|
||||
this->_state = MQTT_CONNECTION_TIMEOUT;
|
||||
_client->stop();
|
||||
return false;
|
||||
} else {
|
||||
buffer[0] = MQTTPINGREQ;
|
||||
buffer[1] = 0;
|
||||
_client->write(buffer,2);
|
||||
lastOutActivity = t;
|
||||
lastInActivity = t;
|
||||
pingOutstanding = true;
|
||||
}
|
||||
}
|
||||
if (_client->available()) {
|
||||
uint8_t llen;
|
||||
uint16_t len = readPacket(&llen);
|
||||
uint16_t msgId = 0;
|
||||
uint8_t *payload;
|
||||
if (len > 0) {
|
||||
lastInActivity = t;
|
||||
uint8_t type = buffer[0]&0xF0;
|
||||
if (type == MQTTPUBLISH) {
|
||||
if (callback) {
|
||||
uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; /* topic length in bytes */
|
||||
memmove(buffer+llen+2,buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */
|
||||
buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */
|
||||
char *topic = (char*) buffer+llen+2;
|
||||
// msgId only present for QOS>0
|
||||
if ((buffer[0]&0x06) == MQTTQOS1) {
|
||||
msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1];
|
||||
payload = buffer+llen+3+tl+2;
|
||||
callback(topic,payload,len-llen-3-tl-2);
|
||||
|
||||
buffer[0] = MQTTPUBACK;
|
||||
buffer[1] = 2;
|
||||
buffer[2] = (msgId >> 8);
|
||||
buffer[3] = (msgId & 0xFF);
|
||||
_client->write(buffer,4);
|
||||
lastOutActivity = t;
|
||||
|
||||
} else {
|
||||
payload = buffer+llen+3+tl;
|
||||
callback(topic,payload,len-llen-3-tl);
|
||||
}
|
||||
}
|
||||
} else if (type == MQTTPINGREQ) {
|
||||
buffer[0] = MQTTPINGRESP;
|
||||
buffer[1] = 0;
|
||||
_client->write(buffer,2);
|
||||
} else if (type == MQTTPINGRESP) {
|
||||
pingOutstanding = false;
|
||||
}
|
||||
} else if (!connected()) {
|
||||
// readPacket has closed the connection
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish(const char* topic, const char* payload) {
|
||||
return publish(topic,(const uint8_t*)payload,strlen(payload),false);
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) {
|
||||
return publish(topic,(const uint8_t*)payload,strlen(payload),retained);
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) {
|
||||
return publish(topic, payload, plength, false);
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) {
|
||||
if (connected()) {
|
||||
if (MQTT_MAX_PACKET_SIZE < MQTT_MAX_HEADER_SIZE + 2+strlen(topic) + plength) {
|
||||
// Too long
|
||||
return false;
|
||||
}
|
||||
// Leave room in the buffer for header and variable length field
|
||||
uint16_t length = MQTT_MAX_HEADER_SIZE;
|
||||
length = writeString(topic,buffer,length);
|
||||
uint16_t i;
|
||||
for (i=0;i<plength;i++) {
|
||||
buffer[length++] = payload[i];
|
||||
}
|
||||
uint8_t header = MQTTPUBLISH;
|
||||
if (retained) {
|
||||
header |= 1;
|
||||
}
|
||||
return write(header,buffer,length-MQTT_MAX_HEADER_SIZE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish_P(const char* topic, const char* payload, boolean retained) {
|
||||
return publish_P(topic, (const uint8_t*)payload, strlen(payload), retained);
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) {
|
||||
uint8_t llen = 0;
|
||||
uint8_t digit;
|
||||
unsigned int rc = 0;
|
||||
uint16_t tlen;
|
||||
unsigned int pos = 0;
|
||||
unsigned int i;
|
||||
uint8_t header;
|
||||
unsigned int len;
|
||||
|
||||
if (!connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tlen = strlen(topic);
|
||||
|
||||
header = MQTTPUBLISH;
|
||||
if (retained) {
|
||||
header |= 1;
|
||||
}
|
||||
buffer[pos++] = header;
|
||||
len = plength + 2 + tlen;
|
||||
do {
|
||||
digit = len % 128;
|
||||
len = len / 128;
|
||||
if (len > 0) {
|
||||
digit |= 0x80;
|
||||
}
|
||||
buffer[pos++] = digit;
|
||||
llen++;
|
||||
} while(len>0);
|
||||
|
||||
pos = writeString(topic,buffer,pos);
|
||||
|
||||
rc += _client->write(buffer,pos);
|
||||
|
||||
for (i=0;i<plength;i++) {
|
||||
rc += _client->write((char)pgm_read_byte_near(payload + i));
|
||||
}
|
||||
|
||||
lastOutActivity = millis();
|
||||
|
||||
return rc == tlen + 4 + plength;
|
||||
}
|
||||
|
||||
boolean PubSubClient::beginPublish(const char* topic, unsigned int plength, boolean retained) {
|
||||
if (connected()) {
|
||||
// Send the header and variable length field
|
||||
uint16_t length = MQTT_MAX_HEADER_SIZE;
|
||||
length = writeString(topic,buffer,length);
|
||||
uint16_t i;
|
||||
uint8_t header = MQTTPUBLISH;
|
||||
if (retained) {
|
||||
header |= 1;
|
||||
}
|
||||
size_t hlen = buildHeader(header, buffer, plength+length-MQTT_MAX_HEADER_SIZE);
|
||||
uint16_t rc = _client->write(buffer+(MQTT_MAX_HEADER_SIZE-hlen),length-(MQTT_MAX_HEADER_SIZE-hlen));
|
||||
lastOutActivity = millis();
|
||||
return (rc == (length-(MQTT_MAX_HEADER_SIZE-hlen)));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int PubSubClient::endPublish() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t PubSubClient::write(uint8_t data) {
|
||||
lastOutActivity = millis();
|
||||
return _client->write(data);
|
||||
}
|
||||
|
||||
size_t PubSubClient::write(const uint8_t *buffer, size_t size) {
|
||||
lastOutActivity = millis();
|
||||
return _client->write(buffer,size);
|
||||
}
|
||||
|
||||
size_t PubSubClient::buildHeader(uint8_t header, uint8_t* buf, uint16_t length) {
|
||||
uint8_t lenBuf[4];
|
||||
uint8_t llen = 0;
|
||||
uint8_t digit;
|
||||
uint8_t pos = 0;
|
||||
uint16_t len = length;
|
||||
do {
|
||||
digit = len % 128;
|
||||
len = len / 128;
|
||||
if (len > 0) {
|
||||
digit |= 0x80;
|
||||
}
|
||||
lenBuf[pos++] = digit;
|
||||
llen++;
|
||||
} while(len>0);
|
||||
|
||||
buf[4-llen] = header;
|
||||
for (int i=0;i<llen;i++) {
|
||||
buf[MQTT_MAX_HEADER_SIZE-llen+i] = lenBuf[i];
|
||||
}
|
||||
return llen+1; // Full header size is variable length bit plus the 1-byte fixed header
|
||||
}
|
||||
|
||||
boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) {
|
||||
uint16_t rc;
|
||||
uint8_t hlen = buildHeader(header, buf, length);
|
||||
|
||||
#ifdef MQTT_MAX_TRANSFER_SIZE
|
||||
uint8_t* writeBuf = buf+(MQTT_MAX_HEADER_SIZE-hlen);
|
||||
uint16_t bytesRemaining = length+hlen; //Match the length type
|
||||
uint8_t bytesToWrite;
|
||||
boolean result = true;
|
||||
while((bytesRemaining > 0) && result) {
|
||||
bytesToWrite = (bytesRemaining > MQTT_MAX_TRANSFER_SIZE)?MQTT_MAX_TRANSFER_SIZE:bytesRemaining;
|
||||
rc = _client->write(writeBuf,bytesToWrite);
|
||||
result = (rc == bytesToWrite);
|
||||
bytesRemaining -= rc;
|
||||
writeBuf += rc;
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
rc = _client->write(buf+(MQTT_MAX_HEADER_SIZE-hlen),length+hlen);
|
||||
lastOutActivity = millis();
|
||||
return (rc == hlen+length);
|
||||
#endif
|
||||
}
|
||||
|
||||
boolean PubSubClient::subscribe(const char* topic) {
|
||||
return subscribe(topic, 0);
|
||||
}
|
||||
|
||||
boolean PubSubClient::subscribe(const char* topic, uint8_t qos) {
|
||||
if (qos > 1) {
|
||||
return false;
|
||||
}
|
||||
if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
|
||||
// Too long
|
||||
return false;
|
||||
}
|
||||
if (connected()) {
|
||||
// Leave room in the buffer for header and variable length field
|
||||
uint16_t length = MQTT_MAX_HEADER_SIZE;
|
||||
nextMsgId++;
|
||||
if (nextMsgId == 0) {
|
||||
nextMsgId = 1;
|
||||
}
|
||||
buffer[length++] = (nextMsgId >> 8);
|
||||
buffer[length++] = (nextMsgId & 0xFF);
|
||||
length = writeString((char*)topic, buffer,length);
|
||||
buffer[length++] = qos;
|
||||
return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean PubSubClient::unsubscribe(const char* topic) {
|
||||
if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
|
||||
// Too long
|
||||
return false;
|
||||
}
|
||||
if (connected()) {
|
||||
uint16_t length = MQTT_MAX_HEADER_SIZE;
|
||||
nextMsgId++;
|
||||
if (nextMsgId == 0) {
|
||||
nextMsgId = 1;
|
||||
}
|
||||
buffer[length++] = (nextMsgId >> 8);
|
||||
buffer[length++] = (nextMsgId & 0xFF);
|
||||
length = writeString(topic, buffer,length);
|
||||
return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PubSubClient::disconnect() {
|
||||
buffer[0] = MQTTDISCONNECT;
|
||||
buffer[1] = 0;
|
||||
_client->write(buffer,2);
|
||||
_state = MQTT_DISCONNECTED;
|
||||
_client->flush();
|
||||
_client->stop();
|
||||
lastInActivity = lastOutActivity = millis();
|
||||
}
|
||||
|
||||
uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t pos) {
|
||||
const char* idp = string;
|
||||
uint16_t i = 0;
|
||||
pos += 2;
|
||||
while (*idp) {
|
||||
buf[pos++] = *idp++;
|
||||
i++;
|
||||
}
|
||||
buf[pos-i-2] = (i >> 8);
|
||||
buf[pos-i-1] = (i & 0xFF);
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
boolean PubSubClient::connected() {
|
||||
boolean rc;
|
||||
if (_client == NULL ) {
|
||||
rc = false;
|
||||
} else {
|
||||
rc = (int)_client->connected();
|
||||
if (!rc) {
|
||||
if (this->_state == MQTT_CONNECTED) {
|
||||
this->_state = MQTT_CONNECTION_LOST;
|
||||
_client->flush();
|
||||
_client->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) {
|
||||
IPAddress addr(ip[0],ip[1],ip[2],ip[3]);
|
||||
return setServer(addr,port);
|
||||
}
|
||||
|
||||
PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) {
|
||||
this->ip = ip;
|
||||
this->port = port;
|
||||
this->domain = NULL;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PubSubClient& PubSubClient::setServer(const char * domain, uint16_t port) {
|
||||
this->domain = domain;
|
||||
this->port = port;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PubSubClient& PubSubClient::setCallback(MQTT_CALLBACK_SIGNATURE) {
|
||||
this->callback = callback;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PubSubClient& PubSubClient::setClient(Client& client){
|
||||
this->_client = &client;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PubSubClient& PubSubClient::setStream(Stream& stream){
|
||||
this->stream = &stream;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int PubSubClient::state() {
|
||||
return this->_state;
|
||||
}
|
||||
173
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/PubSubClient.h
Normal file
173
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/PubSubClient.h
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
PubSubClient.h - A simple client for MQTT.
|
||||
Nick O'Leary
|
||||
http://knolleary.net
|
||||
*/
|
||||
|
||||
#ifndef PubSubClient_h
|
||||
#define PubSubClient_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "IPAddress.h"
|
||||
#include "Client.h"
|
||||
#include "Stream.h"
|
||||
|
||||
#define MQTT_VERSION_3_1 3
|
||||
#define MQTT_VERSION_3_1_1 4
|
||||
|
||||
// MQTT_VERSION : Pick the version
|
||||
//#define MQTT_VERSION MQTT_VERSION_3_1
|
||||
#ifndef MQTT_VERSION
|
||||
#define MQTT_VERSION MQTT_VERSION_3_1_1
|
||||
#endif
|
||||
|
||||
// MQTT_MAX_PACKET_SIZE : Maximum packet size
|
||||
#ifndef MQTT_MAX_PACKET_SIZE
|
||||
#define MQTT_MAX_PACKET_SIZE 128
|
||||
#endif
|
||||
|
||||
// MQTT_KEEPALIVE : keepAlive interval in Seconds
|
||||
#ifndef MQTT_KEEPALIVE
|
||||
#define MQTT_KEEPALIVE 15
|
||||
#endif
|
||||
|
||||
// MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds
|
||||
#ifndef MQTT_SOCKET_TIMEOUT
|
||||
#define MQTT_SOCKET_TIMEOUT 15
|
||||
#endif
|
||||
|
||||
// MQTT_MAX_TRANSFER_SIZE : limit how much data is passed to the network client
|
||||
// in each write call. Needed for the Arduino Wifi Shield. Leave undefined to
|
||||
// pass the entire MQTT packet in each write call.
|
||||
//#define MQTT_MAX_TRANSFER_SIZE 80
|
||||
|
||||
// Possible values for client.state()
|
||||
#define MQTT_CONNECTION_TIMEOUT -4
|
||||
#define MQTT_CONNECTION_LOST -3
|
||||
#define MQTT_CONNECT_FAILED -2
|
||||
#define MQTT_DISCONNECTED -1
|
||||
#define MQTT_CONNECTED 0
|
||||
#define MQTT_CONNECT_BAD_PROTOCOL 1
|
||||
#define MQTT_CONNECT_BAD_CLIENT_ID 2
|
||||
#define MQTT_CONNECT_UNAVAILABLE 3
|
||||
#define MQTT_CONNECT_BAD_CREDENTIALS 4
|
||||
#define MQTT_CONNECT_UNAUTHORIZED 5
|
||||
|
||||
#define MQTTCONNECT 1 << 4 // Client request to connect to Server
|
||||
#define MQTTCONNACK 2 << 4 // Connect Acknowledgment
|
||||
#define MQTTPUBLISH 3 << 4 // Publish message
|
||||
#define MQTTPUBACK 4 << 4 // Publish Acknowledgment
|
||||
#define MQTTPUBREC 5 << 4 // Publish Received (assured delivery part 1)
|
||||
#define MQTTPUBREL 6 << 4 // Publish Release (assured delivery part 2)
|
||||
#define MQTTPUBCOMP 7 << 4 // Publish Complete (assured delivery part 3)
|
||||
#define MQTTSUBSCRIBE 8 << 4 // Client Subscribe request
|
||||
#define MQTTSUBACK 9 << 4 // Subscribe Acknowledgment
|
||||
#define MQTTUNSUBSCRIBE 10 << 4 // Client Unsubscribe request
|
||||
#define MQTTUNSUBACK 11 << 4 // Unsubscribe Acknowledgment
|
||||
#define MQTTPINGREQ 12 << 4 // PING Request
|
||||
#define MQTTPINGRESP 13 << 4 // PING Response
|
||||
#define MQTTDISCONNECT 14 << 4 // Client is Disconnecting
|
||||
#define MQTTReserved 15 << 4 // Reserved
|
||||
|
||||
#define MQTTQOS0 (0 << 1)
|
||||
#define MQTTQOS1 (1 << 1)
|
||||
#define MQTTQOS2 (2 << 1)
|
||||
|
||||
// Maximum size of fixed header and variable length size header
|
||||
#define MQTT_MAX_HEADER_SIZE 5
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
#include <functional>
|
||||
#define MQTT_CALLBACK_SIGNATURE std::function<void(char*, uint8_t*, unsigned int)> callback
|
||||
#else
|
||||
#define MQTT_CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int)
|
||||
#endif
|
||||
|
||||
#define CHECK_STRING_LENGTH(l,s) if (l+2+strlen(s) > MQTT_MAX_PACKET_SIZE) {_client->stop();return false;}
|
||||
|
||||
class PubSubClient : public Print {
|
||||
private:
|
||||
Client* _client;
|
||||
uint8_t buffer[MQTT_MAX_PACKET_SIZE];
|
||||
uint16_t nextMsgId;
|
||||
unsigned long lastOutActivity;
|
||||
unsigned long lastInActivity;
|
||||
bool pingOutstanding;
|
||||
MQTT_CALLBACK_SIGNATURE;
|
||||
uint16_t readPacket(uint8_t*);
|
||||
boolean readByte(uint8_t * result);
|
||||
boolean readByte(uint8_t * result, uint16_t * index);
|
||||
boolean write(uint8_t header, uint8_t* buf, uint16_t length);
|
||||
uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos);
|
||||
// Build up the header ready to send
|
||||
// Returns the size of the header
|
||||
// Note: the header is built at the end of the first MQTT_MAX_HEADER_SIZE bytes, so will start
|
||||
// (MQTT_MAX_HEADER_SIZE - <returned size>) bytes into the buffer
|
||||
size_t buildHeader(uint8_t header, uint8_t* buf, uint16_t length);
|
||||
IPAddress ip;
|
||||
const char* domain;
|
||||
uint16_t port;
|
||||
Stream* stream;
|
||||
int _state;
|
||||
public:
|
||||
PubSubClient();
|
||||
PubSubClient(Client& client);
|
||||
PubSubClient(IPAddress, uint16_t, Client& client);
|
||||
PubSubClient(IPAddress, uint16_t, Client& client, Stream&);
|
||||
PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client);
|
||||
PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&);
|
||||
PubSubClient(uint8_t *, uint16_t, Client& client);
|
||||
PubSubClient(uint8_t *, uint16_t, Client& client, Stream&);
|
||||
PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client);
|
||||
PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&);
|
||||
PubSubClient(const char*, uint16_t, Client& client);
|
||||
PubSubClient(const char*, uint16_t, Client& client, Stream&);
|
||||
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client);
|
||||
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&);
|
||||
|
||||
PubSubClient& setServer(IPAddress ip, uint16_t port);
|
||||
PubSubClient& setServer(uint8_t * ip, uint16_t port);
|
||||
PubSubClient& setServer(const char * domain, uint16_t port);
|
||||
PubSubClient& setCallback(MQTT_CALLBACK_SIGNATURE);
|
||||
PubSubClient& setClient(Client& client);
|
||||
PubSubClient& setStream(Stream& stream);
|
||||
|
||||
boolean connect(const char* id);
|
||||
boolean connect(const char* id, const char* user, const char* pass);
|
||||
boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
|
||||
boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
|
||||
boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession);
|
||||
void disconnect();
|
||||
boolean publish(const char* topic, const char* payload);
|
||||
boolean publish(const char* topic, const char* payload, boolean retained);
|
||||
boolean publish(const char* topic, const uint8_t * payload, unsigned int plength);
|
||||
boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained);
|
||||
boolean publish_P(const char* topic, const char* payload, boolean retained);
|
||||
boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained);
|
||||
// Start to publish a message.
|
||||
// This API:
|
||||
// beginPublish(...)
|
||||
// one or more calls to write(...)
|
||||
// endPublish()
|
||||
// Allows for arbitrarily large payloads to be sent without them having to be copied into
|
||||
// a new buffer and held in memory at one time
|
||||
// Returns 1 if the message was started successfully, 0 if there was an error
|
||||
boolean beginPublish(const char* topic, unsigned int plength, boolean retained);
|
||||
// Finish off this publish message (started with beginPublish)
|
||||
// Returns 1 if the packet was sent successfully, 0 if there was an error
|
||||
int endPublish();
|
||||
// Write a single byte of payload (only to be used with beginPublish/endPublish)
|
||||
virtual size_t write(uint8_t);
|
||||
// Write size bytes from buffer into the payload (only to be used with beginPublish/endPublish)
|
||||
// Returns the number of bytes written
|
||||
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||
boolean subscribe(const char* topic);
|
||||
boolean subscribe(const char* topic, uint8_t qos);
|
||||
boolean unsubscribe(const char* topic);
|
||||
boolean loop();
|
||||
boolean connected();
|
||||
int state();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
890
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/ServeurWeb.cpp
Normal file
890
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/ServeurWeb.cpp
Normal file
@@ -0,0 +1,890 @@
|
||||
#include "ServeurWeb.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
#include "Pins.h"
|
||||
|
||||
ServeurWeb::ServeurWeb()
|
||||
{
|
||||
Serial.println("--------------------------------------");
|
||||
Serial.println("Init ServeurWeb");
|
||||
//domoticz = _domoticz;
|
||||
// WifiServer server(80);
|
||||
//server->begin();
|
||||
}
|
||||
|
||||
void ServeurWeb::loop()
|
||||
{
|
||||
//Serial.println("--------------------------------------");
|
||||
//Serial.println("Loop ServeurWeb");
|
||||
// read the state of the end button value:
|
||||
modules->end_filament = digitalRead(FILAMENT_DETECTION);
|
||||
//Serial.println('fin de filament ' + modules->end_filament);
|
||||
|
||||
if ((bcl % (refresh * 60)) == 0) { //DELAI_LECTURE == 0) {
|
||||
// infos();
|
||||
nbData += 1;
|
||||
nbData = nbData % 256;
|
||||
}
|
||||
|
||||
// Check if a client has connected
|
||||
client = server->available();
|
||||
if (!client) {
|
||||
// infos();
|
||||
// delay(1000);
|
||||
bcl++;
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the first line of the request
|
||||
String req = client.readStringUntil('\r');
|
||||
Serial.println(req);
|
||||
// client.flush();
|
||||
|
||||
// Match the request
|
||||
int val = -1; // We'll use 'val' to keep track of both the
|
||||
// request type (read/set) and value if set.
|
||||
if (req.indexOf("/admin") != -1) {
|
||||
val = -3;
|
||||
//int end = readPage(START_ADDRESS);
|
||||
//pageAdmin();
|
||||
pageMenu(PAGE_ADMIN);
|
||||
|
||||
} else if (req.indexOf("/graph") != -1) {
|
||||
pageMenu(PAGE_GRAPH);
|
||||
|
||||
} else if (req.indexOf("/reset") != -1) {
|
||||
client.println("Reset done. SSID, PASS, Domoticz, port & id cleaned.");
|
||||
delay(100);
|
||||
} else if (req.indexOf("/ident") != -1) {
|
||||
|
||||
ident(req);
|
||||
|
||||
} else if (req.indexOf("/status") != -1) {
|
||||
|
||||
//printWifiStatus();
|
||||
pageMenu(PAGE_STATUS);
|
||||
|
||||
} else if (req.indexOf("/infos") != -1) {
|
||||
pageMenu(PAGE_INFOS);
|
||||
} else if (req.indexOf("/relay_01") != -1) {
|
||||
client.print("relay_01=");
|
||||
client.print(val0); //digitalRead(0));
|
||||
delay(100);
|
||||
} else if (req.indexOf("/relay_02") != -1) {
|
||||
client.print("relay_02=");
|
||||
client.print(val2); //digitalRead(2));
|
||||
delay(100);
|
||||
} else if (req.indexOf("/action") != -1) {
|
||||
|
||||
// Affectation des variables aux sorties correspondantes
|
||||
if (req.indexOf("relay_01=false") != -1)
|
||||
{
|
||||
val0 = HIGH;
|
||||
modules->relay(RELAY_PIN, val0);
|
||||
}
|
||||
if (req.indexOf("relay_01=true") != -1)
|
||||
{
|
||||
val0 = LOW;
|
||||
modules->relay(RELAY_PIN, val0);
|
||||
}
|
||||
if (req.indexOf("relay_02=false") != -1)
|
||||
{
|
||||
val2 = HIGH;
|
||||
digitalWrite(RELAY_PIN_02, val2);
|
||||
}
|
||||
if (req.indexOf("relay_02=true") != -1)
|
||||
{
|
||||
val2 = LOW;
|
||||
digitalWrite(RELAY_PIN_02, val2);
|
||||
}
|
||||
if (req.indexOf("relay_03=false") != -1)
|
||||
{
|
||||
val3 = HIGH;
|
||||
digitalWrite(RELAY_PIN_03, val3);
|
||||
}
|
||||
if (req.indexOf("relay_03=true") != -1)
|
||||
{
|
||||
val3 = LOW;
|
||||
digitalWrite(RELAY_PIN_03, val3);
|
||||
}
|
||||
|
||||
if (req.indexOf("relay_04=false") != -1)
|
||||
{
|
||||
val4 = HIGH;
|
||||
digitalWrite(RELAY_PIN_04, val4);
|
||||
}
|
||||
if (req.indexOf("relay_04=true") != -1)
|
||||
{
|
||||
val4 = LOW;
|
||||
digitalWrite(RELAY_PIN_04, val4);
|
||||
}
|
||||
|
||||
Serial.println("Val0=" + String(val0) + " Val2=" + String(val2)
|
||||
+ " Val3=" + String(val3) + " Val4=" + String(val4));
|
||||
|
||||
pageMenu(PAGE_MENU);
|
||||
} else if (req.indexOf("/menu") != -1) {
|
||||
//pageMenu();
|
||||
pageMenu(PAGE_MENU);
|
||||
} else {
|
||||
pageMenu(PAGE_MENU);
|
||||
}
|
||||
|
||||
//client.stop();
|
||||
|
||||
// The client will actually be disconnected
|
||||
// when the function returns and 'client' object is detroyed
|
||||
}
|
||||
|
||||
String ServeurWeb::getValueFrom(String request, int deb, int fin) {
|
||||
|
||||
int bufLength = ((fin) - (deb + 5)); //the 5 is for the "name=" string
|
||||
|
||||
String tmp = request.substring((deb + 5), (fin - 1));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
char* ServeurWeb::convertToChar(String s, char* buf) {
|
||||
char c[s.length() + 1];
|
||||
s.toCharArray(c, s.length() + 1);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
void ServeurWeb::infos()
|
||||
{
|
||||
int nb = 0;
|
||||
|
||||
//WiFiClient client2; // = domoticz->_client;
|
||||
// Domoticz format /json.htm?type=command¶m=udevice&idx=IDX&nvalue=0&svalue=TEMP;HUM;HUM_STAT
|
||||
|
||||
// Type
|
||||
// 0 = Integer, e.g. -1, 1, 0, 2, 10
|
||||
//1 = Float, e.g. -1.1, 1.2, 3.1
|
||||
//2 = String
|
||||
//3 = Date in format DD/MM/YYYY
|
||||
//4 = Time in 24 hr format HH:MM
|
||||
//5 = DateTime (but the format is not checked)
|
||||
// SAve variable "json.htm?type=command¶m=saveuservariable&vname=" + domoticz->_macID + "uservariablename&vtype=2&vvalue=uservariablevalue"
|
||||
|
||||
// GEt Variables
|
||||
// http://192.168.0.10:8080/json.htm?type=command¶m=getuservariables&idx=4
|
||||
|
||||
|
||||
// // Domo
|
||||
// char domoticz->_domoc[domoticz.length() + 1];
|
||||
// domoticz.toCharArray(domoticz->_domoc, domoticz.length() + 1);
|
||||
|
||||
// // Port
|
||||
// char portc[port.length() + 1];
|
||||
// port.toCharArray(portc, port.length() + 1);
|
||||
// int domoticz->_iport = atoi(portc);
|
||||
|
||||
Serial.print(domoticz->_domoticz);
|
||||
Serial.print(" ");
|
||||
Serial.println(domoticz->_port);
|
||||
|
||||
Serial.print(" radiateur=");
|
||||
Serial.print(radiateur);
|
||||
Serial.print(" temperature=");
|
||||
Serial.print(temp);
|
||||
Serial.print(" consigne=");
|
||||
Serial.print(cons);
|
||||
Serial.println("");
|
||||
// Avoid WDT reset during long process
|
||||
yield();
|
||||
|
||||
// -------------------
|
||||
// LECTURE PARAM
|
||||
// -------------------
|
||||
if (radiateur == "") {
|
||||
Serial.println("Lecture parametre dans domoticz");
|
||||
if (domoticz->connect()) {
|
||||
Serial.println("Connected to domoticz");
|
||||
domoticz->executeJson("/json.htm?type=command¶m=getuservariables", "", "");
|
||||
|
||||
// Read the first line of the request
|
||||
while (1) {
|
||||
// Avoid WDT reset during long process
|
||||
yield();
|
||||
String req = domoticz->readLine();
|
||||
// Serial.println(req);
|
||||
|
||||
if (req.indexOf(domoticz->_macID) != -1) {
|
||||
Serial.println(req);
|
||||
|
||||
// Serial.println(req);
|
||||
req = domoticz->readLine();
|
||||
req = domoticz->readLine();
|
||||
String val = req.substring(req.indexOf(":") + 2, req.length() - 1);
|
||||
Serial.println(val);
|
||||
val.replace("\"", "");
|
||||
radiateur = domoticz->getIndexOfString(val, separator, 0);
|
||||
temp = domoticz->getIndexOfString(val, separator, 1);
|
||||
cons = domoticz->getIndexOfString(val, separator, 2);
|
||||
refresh = domoticz->getIndexOfString(val, separator, 3).toInt();
|
||||
nom = domoticz->getIndexOfString(val, separator, 4);
|
||||
|
||||
for (int cpt = 0; cpt < 5; cpt++ ) {
|
||||
Serial.print(domoticz->getIndexOfString(val, separator, cpt));
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("radiateur=" + radiateur);
|
||||
Serial.println("temp=" + temp);
|
||||
Serial.println("cons=" + cons);
|
||||
|
||||
break;
|
||||
}
|
||||
if (req == "" || nb > 500) {
|
||||
break;
|
||||
}
|
||||
nb++;
|
||||
}
|
||||
|
||||
//client2.stop();
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
if (radiateur != "") {
|
||||
if (domoticz->connect()) {
|
||||
Serial.println("Connected to domoticz lecteur statut radiateur" );
|
||||
domoticz->executeJson("/json.htm?type=devices&rid=" + radiateur, "", "");
|
||||
|
||||
// Read the first line of the request
|
||||
while (1) {
|
||||
// Avoid WDT reset during long process
|
||||
yield();
|
||||
String req = domoticz->readLine();
|
||||
|
||||
if (req.indexOf("\"Status\"") != -1) {
|
||||
Serial.println(req.substring(req.indexOf(":") + 2));
|
||||
break;
|
||||
}
|
||||
if (req == "" || nb > 500) {
|
||||
break;
|
||||
}
|
||||
nb++;
|
||||
}
|
||||
|
||||
//client2.stop();
|
||||
delay(100);
|
||||
}
|
||||
if (domoticz->connect()) {
|
||||
Serial.println("Connected to domoticz lecture donnée température" );
|
||||
domoticz->executeJson("/json.htm?type=devices&rid=723", "","");
|
||||
|
||||
// Read the first line of the request
|
||||
while (1) {
|
||||
// Avoid WDT reset during long process
|
||||
yield();
|
||||
String req = domoticz->readLine();
|
||||
Serial.println(req);
|
||||
if (req.indexOf("\"Temp\"") != -1) {
|
||||
String tmp = req.substring(req.indexOf(":") + 2);
|
||||
tmp = tmp.substring(0, tmp.indexOf(".") + 2);
|
||||
Serial.println(tmp);
|
||||
if (data == "") {
|
||||
data += tmp;
|
||||
labels = "\"0\"";
|
||||
} else {
|
||||
data += "," + tmp;
|
||||
if (nbData % 10 == 0) {
|
||||
labels = labels + "," + "\"" + nbData + "\"";
|
||||
} else {
|
||||
labels = labels + "," + "\"" + "\"";
|
||||
}
|
||||
|
||||
}
|
||||
if (data.length() > 500) {
|
||||
data = data.substring(data.indexOf(",") + 1);
|
||||
labels = labels.substring(labels.indexOf(",") + 1);
|
||||
}
|
||||
Serial.println(data);
|
||||
Serial.println(labels);
|
||||
break;
|
||||
}
|
||||
if (req == "" || nb > 500) {
|
||||
break;
|
||||
}
|
||||
nb++;
|
||||
}
|
||||
|
||||
//client2.stop();
|
||||
delay(100);
|
||||
}
|
||||
if (domoticz->connect()) {
|
||||
Serial.println("Connected to domoticz lecteur consigne" );
|
||||
|
||||
domoticz->executeJson("/json.htm?type=devices&rid=" + cons, "", "");
|
||||
|
||||
// Read the first line of the request
|
||||
while (1) {
|
||||
// Avoid WDT reset during long process
|
||||
yield();
|
||||
String req = domoticz->readLine();
|
||||
|
||||
if (req.indexOf("\"SetPoint\"") != -1) {
|
||||
String value = req.substring(req.indexOf(":") + 2);
|
||||
//value = .substring(req.indexOf(":") + 1);
|
||||
value.trim();
|
||||
|
||||
Serial.println(value);
|
||||
break;
|
||||
}
|
||||
if (req == "" || nb > 500) {
|
||||
break;
|
||||
}
|
||||
nb++;
|
||||
}
|
||||
|
||||
//client2.stop();
|
||||
delay(100);
|
||||
|
||||
}
|
||||
}
|
||||
// Avoid WDT reset during long process
|
||||
yield();
|
||||
Serial.println("Fin infos");
|
||||
// Avoid WDT reset during long process
|
||||
yield();
|
||||
}
|
||||
|
||||
|
||||
void ServeurWeb::printWifiStatus() {
|
||||
// print the SSID of the network you're attached to:
|
||||
Serial.print("SSID: ");
|
||||
Serial.println(WiFi.SSID());
|
||||
|
||||
// print your WiFi shield's IP address:
|
||||
IPAddress ip = WiFi.localIP();
|
||||
Serial.print("IP Address: ");
|
||||
Serial.println(ip);
|
||||
|
||||
// print the received signal strength:
|
||||
long rssi = WiFi.RSSI();
|
||||
Serial.print("signal strength (RSSI):");
|
||||
Serial.print(rssi);
|
||||
Serial.println(" dBm");
|
||||
|
||||
// PAge
|
||||
client.println("<p>Connected to ");
|
||||
client.println(WiFi.SSID());
|
||||
client.println("</p><p>Ip: ");
|
||||
client.println(ip);
|
||||
client.println("</p><p>Force du signal:");
|
||||
client.println(rssi);
|
||||
client.println(" dBm</p>");
|
||||
client.println("<p>Domoticz:");
|
||||
client.println(domoticz->_domoticz);
|
||||
client.println(":");
|
||||
client.println(domoticz->_port);
|
||||
client.println("</p>");
|
||||
//
|
||||
// client.println("<div class='c100 p25 dark orange'>");
|
||||
// client.println(" <span>25%</span>");
|
||||
// client.println(" <div class='slice'>");
|
||||
// client.println(" <div class='bar'></div>");
|
||||
// client.println(" <div class='fill'></div>");
|
||||
// client.println(" </div>");
|
||||
// client.println("</div>");
|
||||
client.println("<button class='boutonTemp' onclick='click()'>" + temp + "</button>");
|
||||
client.println("<button class='boutonCons' onclick='click()'>" + cons + "</button>");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
////// PAGE MENU
|
||||
////////////////////////////////////////////
|
||||
void ServeurWeb::pageMenu(int page) {
|
||||
client.println("<html>");
|
||||
client.println("<head>");
|
||||
client.println("<link rel=\"shortcut icon\" href=\"http://" + domoticz->_domoticz + ":" + domoticz->_port + "/favicon.ico\">");
|
||||
if (page == PAGE_GRAPH) {
|
||||
client.println("<meta http-equiv=\"refresh\" content=\"60\" >");
|
||||
}
|
||||
if (page == PAGE_MENU) {
|
||||
// // Look des champs de saisis
|
||||
// client.println("<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\"http://" + domoticz->_domoticz + "/ESP8266/css/styles.css\">");
|
||||
// // Look Bouton toggle
|
||||
// client.println("<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\"http://" + domoticz->_domoticz + "/ESP8266/css/toggles-soft.css\">");
|
||||
}
|
||||
|
||||
menuStyle(page);
|
||||
client.println("</head>");
|
||||
|
||||
menuBody(page);
|
||||
client.println("</html>\n\r");
|
||||
|
||||
}
|
||||
|
||||
void ServeurWeb::menuBody(int page) {
|
||||
client.println("<body>");
|
||||
client.println("<header role='banner'>");
|
||||
client.println("<div class='wrapper'>");
|
||||
client.print("<h1> ");
|
||||
client.print(nom + " " + domoticz->_macID);
|
||||
client.println("</h1>");
|
||||
client.println("<nav id='nav' role='navigation'>");
|
||||
client.println("<div class='show_menu_btn' data-target='#nav ul' data-shown-text='Hide menu' data-hidden-text='Show menu' >Show menu</div>");
|
||||
client.println("<ul>");
|
||||
client.println("<li><a href='/menu'>Menu</a></li>");
|
||||
client.println("<li><a href='/admin'>Admin</a></li>");
|
||||
//client.println("<li><a href='/infos'>Infos</a></li>");
|
||||
client.println("<li><a href='/status'>Status</a></li>");
|
||||
//client.println("<li><a href='/reset'>Reset</a></li>");
|
||||
client.println("<li><a href='/graph'>Graph</a></li>");
|
||||
//client.println("<li><a href='/aide'>Aide</a></li>");
|
||||
client.println("</ul>");
|
||||
client.println("</nav>");
|
||||
client.println("</div>");
|
||||
client.println("</header>");
|
||||
|
||||
client.println("<main role='main'>");
|
||||
client.println("<div class='wrapper'>");
|
||||
if (page == PAGE_MENU) {
|
||||
client.print("<form><div><input type=\"checkbox\" id=\"relay_01\" onclick=\"handleClick(this);\" ");
|
||||
if (val0 == 0) {
|
||||
client.print("unchecked");
|
||||
} else {
|
||||
client.print("checked");
|
||||
}
|
||||
client.println("><label for=\"relay_01\" onclick=\"relay_01();\">Relai 1</label></div></form>");
|
||||
client.println("<form><div><input type=\"checkbox\" id=\"relay_02\" onclick=\"handleClick(this);\" ");
|
||||
|
||||
if (val2 == 0) {
|
||||
client.print("unchecked");
|
||||
} else {
|
||||
client.print("checked");
|
||||
}
|
||||
client.println("><label for=\"relay_02\" onclick=\"relay_02();\">Relai 2</label></div></form>");
|
||||
client.println("<form><div><input type=\"checkbox\" id=\"relay_03\" onclick=\"handleClick(this);\" ");
|
||||
if (val3 == 0) {
|
||||
client.print("unchecked");
|
||||
} else {
|
||||
client.print("checked");
|
||||
}
|
||||
client.println("><label for=\"relay_03\" onclick=\"relay_03();\">Relai 3</label></div></form>");
|
||||
client.println("<form><div><input type=\"checkbox\" id=\"relay_04\" onclick=\"handleClick(this);\" ");
|
||||
if (val4 == 0) {
|
||||
client.print("unchecked");
|
||||
} else {
|
||||
client.print("checked");
|
||||
}
|
||||
client.println("><label for=\"relay_04\" onclick=\"relay_04();\">Relai 4</label></div></form>");
|
||||
|
||||
} else if (page == PAGE_ADMIN) {
|
||||
client.println( "<form action='/ident' method='get'>");
|
||||
client.println( "<script type='text/javascript'>\nfunction showValue(newValue)\n{\ndocument.getElementById('text').innerHTML=newValue;\n}\n</script>");
|
||||
client.println( "<div>");
|
||||
client.println( "<label for='name'>SSID:</label>");
|
||||
String ssid = String(domoticz->_ssid);
|
||||
// sprintf (domoticz->_ssid, "%18x", ssid);
|
||||
client.println( "<input type='text' id='name' name='name' value='" + ssid + "'/>");
|
||||
client.println( "</div>");
|
||||
client.println( "<div>");
|
||||
client.println( "<label for='pass'>Password:</label>");
|
||||
String pass = String(domoticz->_pass);
|
||||
client.println( "<input type='password' id='pass' name='pass' value='" + pass + "'/>");
|
||||
client.println( "</div>");
|
||||
client.println( "<div>");
|
||||
client.println( "<label for='domo'>Domoticz:</label>");
|
||||
client.println( "<input type='text' id='domo' name='domo' value='" + domoticz->_domoticz + "'/>"); // />");
|
||||
client.println( "</div>");
|
||||
client.println( "<div>");
|
||||
client.println( "<label for='port'>Port:</label>");
|
||||
client.println( "<input type='text' id='port' name='port' value='" + domoticz->_port + "'/>");
|
||||
client.println( "</div>");
|
||||
// client.println( "<div>");
|
||||
// client.println( "<label for='radi'>Id Radiateur:</label>");
|
||||
// client.println( "<input type='radi' id='radi' name='radi' value='" + radiateur + "'/>");
|
||||
// client.println( "</div>");
|
||||
// client.println( "<div>");
|
||||
// client.println( "<label for='temp'>Id Thermometre:</label>");
|
||||
// client.println( "<input type='temp' id='temp' name='temp' value='" + temp + "'/>");
|
||||
// client.println( "</div>");
|
||||
// client.println( "<div>");
|
||||
// client.println( "<label for='cons'>Id Consigne:</label>");
|
||||
// client.println( "<input type='cons' id='cons' name='cons' value='" + cons + "'/>");
|
||||
// client.println( "</div>");
|
||||
|
||||
client.println( "<div class='button'>");
|
||||
client.println( "<button name=H type='submit'>Ok</button>");
|
||||
client.println( "</div>");
|
||||
client.println( "</form>");
|
||||
} else if (page == PAGE_STATUS) {
|
||||
client.println("<article>");
|
||||
printWifiStatus();
|
||||
client.println("</article>");
|
||||
} else if (page == PAGE_GRAPH) {
|
||||
graph();
|
||||
} else if (page == PAGE_INFOS) {
|
||||
infos();
|
||||
}
|
||||
client.println(" </div>");
|
||||
client.println("</main>");
|
||||
|
||||
client.println("<script>");
|
||||
client.println("var show_menu=document.querySelector('.show_menu_btn'),viewport_width=document.documentElement.clientWidth,menu=document.querySelector('#nav ul');600>viewport_width&&(menu.style.display='none'),window.addEventListener('resize',function(){var e=document.documentElement.clientWidth;menu.style.display=e>599?'block':'none'}),show_menu.addEventListener('click',function(){var e=document.querySelector(show_menu.getAttribute('data-target'));'none'==e.style.display?(e.style.display='block',show_menu.innerHTML=show_menu.getAttribute('data-shown-text')):(e.style.display='none',show_menu.innerHTML=show_menu.getAttribute('data-hidden-text'))});");
|
||||
//menuJS();
|
||||
// Fonction pour les voutons
|
||||
//client.println("function click(){$(function() {$( '#dialog' ).dialog({width : 250, height: 180, modal : true }); }); }");
|
||||
client.println("</script>");
|
||||
|
||||
|
||||
if (page == PAGE_GRAPH) {
|
||||
// client.println("<script src=\"http://" + domoticz->_domoticz + "/" + jsPath + "/" + chartName + "\"></script>");
|
||||
client.println("<script src=\"https://www.chartjs.org/dist/2.9.3/Chart.min.js\"></script>");
|
||||
}
|
||||
else if (page == PAGE_MENU) {
|
||||
client.println("<script>");
|
||||
client.println("function relay_04() {document.getElementById(\"relay_04\").click();}");
|
||||
client.println("function relay_03() {document.getElementById(\"relay_03\").click();}");
|
||||
client.println("function relay_02() {document.getElementById(\"relay_02\").click();}");
|
||||
client.println("function relay_01() {document.getElementById(\"relay_01\").click();}");
|
||||
client.println("function handleClick(cb) {post_to_url(cb, \"/action\", { submit: \"submit\" });}");
|
||||
client.println("function post_to_url(x, path, params, method) {");
|
||||
client.println("method = \"get\"; var form = document.createElement(\"form\");");
|
||||
//1client.println("var x = document.getElementById(\"relay_01\");");
|
||||
// client.println("var x2 = document.getElementById(\"relay_02\");");
|
||||
client.println("form._submit_function_ = form.submit;");
|
||||
client.println("form.setAttribute(\"method\", method);");
|
||||
client.println("form.setAttribute(\"action\", path);");
|
||||
|
||||
client.println("var hiddenField = document.createElement(\"input\");");
|
||||
client.println("hiddenField.setAttribute(\"type\", \"hidden\");");
|
||||
client.println("hiddenField.setAttribute(\"name\", x.id);");
|
||||
client.println("hiddenField.setAttribute(\"value\", x.checked);");
|
||||
client.println("form.appendChild(hiddenField);");
|
||||
client.println("document.body.appendChild(form);");
|
||||
|
||||
// client.println("var hiddenField2 = document.createElement(\"input\");");
|
||||
// client.println("hiddenField2.setAttribute(\"type\", \"hidden\");");
|
||||
// client.println("hiddenField2.setAttribute(\"name\", x2.id);");
|
||||
// client.println("hiddenField2.setAttribute(\"value\", x2.checked);");
|
||||
// client.println("form.appendChild(hiddenField2);");
|
||||
// client.println("document.body.appendChild(form);");
|
||||
|
||||
client.println("form._submit_function_(); }</script>");
|
||||
}
|
||||
|
||||
client.println("</body>");
|
||||
|
||||
}
|
||||
|
||||
void ServeurWeb::menuStyle(int page) {
|
||||
// menuStyle.css
|
||||
client.println("<style>");
|
||||
client.println( "a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,");
|
||||
client.println( "figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,");
|
||||
client.println( "strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;font:inherit;vertical-align:baseline}");
|
||||
client.println( "article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}nav ul{list-style:none}blockquote,q{quotes:none}blockquote:");
|
||||
client.println( "after,blockquote:before,q:after,q:before{content:'';");
|
||||
client.println( "content:none}table{border-collapse:collapse;border-spacing:0}h1{font-size:1.5em;font-weight:700;padding:.5em 0;letter-spacing:1px}@media screen and ");
|
||||
client.println( "(max-width:599px){h1{text-align:center}}h2{font-size:1.25em;font-weight:700;line-height:1.2;padding:.5em 0}p{font-size:1em;padding:0 0 1em}a{color:#555;");
|
||||
client.println( "text-decoration:none;border-bottom:1px solid #555}a:hover{color:#88b47f;border-bottom:1px solid #88b47f}*{-moz-box-sizing:border-box;-webkit-box-sizing:");
|
||||
client.println( "border-box;box-sizing:border-box;-webkit-text-size-adjust:auto}body{font-family:sans-serif;font-size:100%;text-align:center;line-height:1.5;background:");
|
||||
client.println( "#f8f7f0;color:#555}.wrapper{width:90%;max-width:50em;margin:0 auto;text-align:left;overflow:hidden}");
|
||||
client.println( "header{margin-bottom:1em;padding-bottom:1em;background:#57575f;color:#fff}@media screen and (max-width:599px){.no-js .show_menu_btn{display:none}.js .show_menu_btn,.no-js #nav ul{display:block}.js #nav ul{display:none}}@media screen and (min-width:600px){.show_menu_btn{display:none}#nav ul{display:block}}.show_menu_btn{width:35%;margin:0 auto;padding:.3em;cursor:pointer;text-align:center;background:#88b47f}#nav ul{margin:1em 0}#nav ul li{padding:.5em}#nav ul li:hover{background:#88b47f}#nav ul a{display:block;font-size:1em;color:#eee;border-bottom:none}@media screen and (max-width:599px){#nav ul{display:block}#nav ul li{display:block;text-align:center;border-bottom:1px solid #6f6f7a}}@media screen and (min-width:600px){#nav{overflow:hidden}#nav ul li{width:7em;float:left;margin-right:1em}}");
|
||||
//Bouton
|
||||
client.println( ".boutonTemp {width:85px;height:85px;background:#fafafa;box-shadow:2px 2px 8px #aaa;font:bold 13px Arial;border-radius:50%;color:#555;}");
|
||||
client.println( ".boutonCons {width:85px;height:85px;background:#cc0000;font:bold 13px Arial;border-radius:50%;border:none;color:#fff;}");
|
||||
|
||||
// PAGE MENU
|
||||
client.println("input[type=\"checkbox\"] {display: none;}");
|
||||
client.println("input[type=\"checkbox\"] + label {display:inline-block; line-height:normal; cursor:pointer; padding: 3px 14px;");
|
||||
client.println("background-color: #EFEFEF;border-radius: 4px;border: 1px solid #D0D0D0;margin: 40px 100px 10px 40px;");
|
||||
client.println("}input[type=\"checkbox\"] + label:hover {border-color: #000;background-color: #911;color: #fff;}");
|
||||
client.println("input[type=\"checkbox\"]:checked + label {border-color: #000;background-color: #888;color: #fff;}");
|
||||
|
||||
|
||||
client.println("</style>");
|
||||
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// PAGE ADMIN
|
||||
///////////////////////////////////////////////////
|
||||
void ServeurWeb::pageAdmin() {
|
||||
|
||||
client.println("<html>");
|
||||
style();
|
||||
body();
|
||||
client.println("</html>\n\r");
|
||||
}
|
||||
|
||||
void ServeurWeb::body() {
|
||||
// body.html
|
||||
client.println( "<body>");
|
||||
client.println( "<form action='/ident' method='get'>");
|
||||
client.println( "<script type='text/javascript'>\nfunction showValue(newValue)\n{\ndocument.getElementById('text').innerHTML=newValue;\n}\n</script>");
|
||||
client.println( "<div>");
|
||||
client.println( "<label for='name'>SSID:</label>");
|
||||
client.println( "<input type='text' id='name' name='name' />");
|
||||
client.println( "</div>");
|
||||
client.println( "<div>");
|
||||
client.println( " <label for='pass'>Password:</label>");
|
||||
client.println( " <input type='password' id='pass' name='pass' />");
|
||||
client.println( "</div>");
|
||||
client.println( "<div>");
|
||||
client.println( " <label for='domo'>Domoticz:</label>");
|
||||
client.println( " <input type='text' id='domo' name='domo' />");
|
||||
client.println( " <label for='port'>Port:</label>");
|
||||
client.println( " <input type='text' id='port' name='port' />");
|
||||
client.println( "</div>");
|
||||
client.println( "<div>");
|
||||
client.println( " <label for='radi'>Id Radiateur:</label>");
|
||||
client.println( " <input type='radi' id='radi' name='radi' />");
|
||||
client.println( "</div>");
|
||||
client.println( "<div class='button'>");
|
||||
client.println( " <button name=H type='submit'>Ok</button>");
|
||||
client.println( "</div>");
|
||||
client.println( "</form>");
|
||||
client.println( "</body>");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ServeurWeb::style() {
|
||||
|
||||
// style.css
|
||||
client.println( "<style>");
|
||||
client.println( "form {");
|
||||
// client.println( " /* Just to center the form on the page */");
|
||||
client.println( " margin: 0 auto;");
|
||||
client.println( " width: 400px;");
|
||||
client.println( "");
|
||||
// client.println( " /* To see the limits of the form */");
|
||||
client.println( " padding: 1em;");
|
||||
client.println( " border: 1px solid #CCC;");
|
||||
client.println( " border-radius: 1em;");
|
||||
client.println( "}");
|
||||
client.println( "");
|
||||
client.println( "div + div {");
|
||||
client.println( " margin-top: 1em;");
|
||||
client.println( "}");
|
||||
client.println( "");
|
||||
client.println( "label {");
|
||||
// client.println( " /* To make sure that all label have the same size and are properly align */");
|
||||
client.println( " display: inline-block;");
|
||||
client.println( " width: 90px;");
|
||||
client.println( " text-align: right;");
|
||||
client.println( "}");
|
||||
client.println( "");
|
||||
client.println( "input, textarea {");
|
||||
// client.println( " /* To make sure that all text field have the same font settings");
|
||||
// client.println( " By default, textarea are set with a monospace font */");
|
||||
client.println( " font: 1em sans-serif;");
|
||||
client.println( "");
|
||||
// client.println( " /* To give the same size to all text field */");
|
||||
client.println( " width: 300px;");
|
||||
client.println( "");
|
||||
client.println( " -moz-box-sizing: border-box;");
|
||||
client.println( " box-sizing: border-box;");
|
||||
client.println( "");
|
||||
// client.println( " /* To harmonize the look & feel of text field border */");
|
||||
client.println( " border: 1px solid #999;");
|
||||
client.println( "}");
|
||||
client.println( "");
|
||||
client.println( "input:focus, textarea:focus {");
|
||||
// client.println( " /* To give a little highligh on active elements */");
|
||||
client.println( " border-color: #000;");
|
||||
client.println( "}");
|
||||
client.println( "");
|
||||
client.println( "textarea {");
|
||||
// client.println( " /* To properly align multiline text field with their label */");
|
||||
client.println( " vertical-align: top;");
|
||||
client.println( "");
|
||||
// client.println( " /* To give enough room to type some text */");
|
||||
client.println( " height: 5em;");
|
||||
client.println( "");
|
||||
// client.println( " /* To allow users to resize any textarea vertically");
|
||||
// client.println( " It works only on Chrome, Firefox and Safari */");
|
||||
client.println( " resize: vertical;");
|
||||
client.println( "}");
|
||||
client.println( "");
|
||||
client.println( ".button {");
|
||||
// client.println( " /* To position the buttons to the same position of the text fields */");
|
||||
// client.println( " padding-left: 90px; /* same size as the label elements */");
|
||||
client.println( "}");
|
||||
client.println( "");
|
||||
client.println( "button {");
|
||||
// client.println( " /* This extra magin represent the same space as the space between");
|
||||
// client.println( " the labels and their text fields */");
|
||||
client.println( " margin-left: .5em;");
|
||||
client.println( "}");
|
||||
|
||||
client.println(".toggle-slide {");
|
||||
client.println(" overflow: hidden;");
|
||||
client.println(" cursor: pointer;");
|
||||
client.println(" -webkit-touch-callout: none;");
|
||||
client.println(" -webkit-user-select: none;");
|
||||
client.println(" -khtml-user-select: none;");
|
||||
client.println(" -moz-user-select: none;");
|
||||
client.println(" -ms-user-select: none;");
|
||||
client.println(" user-select: none;");
|
||||
client.println(" direction: ltr;");
|
||||
client.println("}");
|
||||
client.println(".toggle-slide .toggle-on,.toggle-slide .toggle-off,.toggle-slide .toggle-blob {");
|
||||
client.println(" float: left;");
|
||||
client.println("}");
|
||||
client.println(".toggle-slide .toggle-blob {");
|
||||
client.println(" position: relative;");
|
||||
client.println(" z-index: 99;");
|
||||
client.println(" cursor: hand;");
|
||||
client.println(" cursor: grab;");
|
||||
client.println(" cursor: -moz-grab;");
|
||||
client.println(" cursor: -webkit-grab;");
|
||||
client.println("}");
|
||||
|
||||
|
||||
client.println( "</style>");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ServeurWeb::graph() {
|
||||
// infos();
|
||||
client.println( "<canvas id='canvas' ></canvas>");
|
||||
|
||||
client.println( "<script>");
|
||||
client.println( "var randomScalingFactor = function(){ return Math.round(Math.random()*100)};");
|
||||
|
||||
client.println( "var config = {");
|
||||
client.println( "type: 'line',");
|
||||
client.println( " data: {");
|
||||
|
||||
client.print( "labels : ["); //\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\"],");
|
||||
client.print(domoticz->labels);
|
||||
client.println("],");
|
||||
|
||||
client.println( "datasets : [");
|
||||
client.println( "{");
|
||||
client.println( "label: \"My First dataset\",");
|
||||
client.println( " fillColor : \"rgba(220,220,220,0.2)\",");
|
||||
client.println( " strokeColor : \"rgba(220,220,220,1)\",");
|
||||
client.println( " pointColor : \"rgba(220,220,220,1)\",");
|
||||
client.println( " pointStrokeColor : \"#fff\",");
|
||||
client.println( " pointHighlightFill : \"#fff\",");
|
||||
client.println( " pointHighlightStroke : \"rgba(220,220,220,1)\",");
|
||||
client.print( " data : [");
|
||||
|
||||
|
||||
// randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()
|
||||
client.print(domoticz->data);
|
||||
client.print("]}");
|
||||
|
||||
client.println( " ]}};");
|
||||
client.println( "window.onload = function(){");
|
||||
client.println( " var ctx = document.getElementById(\"canvas\").getContext(\"2d\");");
|
||||
client.println( " window.myLine = new Chart(ctx, config);");
|
||||
// client.println( " responsive: true, animation:true});");
|
||||
client.println( "}");
|
||||
client.println( "</script>");
|
||||
|
||||
}
|
||||
|
||||
//String domoticz->getIndexOfString(String data, String separator, int index)
|
||||
//{
|
||||
// int found = 0;
|
||||
// int strIndex[] = { 0, -1 };
|
||||
// int maxIndex = data.length() - 1;
|
||||
//
|
||||
// for (int i = 0; i <= maxIndex && found <= index; i++) {
|
||||
// if (data.charAt(i) == separator.charAt(0) || i == maxIndex) {
|
||||
// found++;
|
||||
// strIndex[0] = strIndex[1] + 1;
|
||||
// strIndex[1] = (i == maxIndex) ? i+1 : i;
|
||||
// }
|
||||
// }
|
||||
// return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
|
||||
//}
|
||||
|
||||
void ServeurWeb::ident(String req) {
|
||||
|
||||
// Return : ident?name=jjjjj&pass=kkkk&domo&H=
|
||||
int posName = req.indexOf("name");
|
||||
int posPass = req.indexOf("pass", posName);
|
||||
int posDomo = req.indexOf("domo", posPass);
|
||||
int posPort = req.indexOf("port", posDomo);
|
||||
// int posRadi = req.indexOf("radi", posPort);
|
||||
// int posTemp = req.indexOf("temp", posRadi);
|
||||
// int posCons = req.indexOf("cons", posTemp);
|
||||
// int End = req.indexOf("H", posCons);
|
||||
|
||||
//if (End < 0) {
|
||||
int End = req.length() + 1;
|
||||
//}
|
||||
//ssid
|
||||
String ssid = getValueFrom(req, posName, posPass);
|
||||
char ssidc[ssid.length() + 1];
|
||||
ssid.toCharArray(ssidc, ssid.length() + 1);
|
||||
|
||||
//Password
|
||||
String pass = getValueFrom(req, posPass, posDomo);
|
||||
char passc[pass.length() + 1];
|
||||
pass.toCharArray(passc, pass.length() + 1);
|
||||
|
||||
// Domo
|
||||
String domo = getValueFrom(req, posDomo, posPort);
|
||||
char domoc[domo.length() + 1];
|
||||
domo.toCharArray(domoc, domo.length() + 1);
|
||||
|
||||
// Port
|
||||
String port = getValueFrom(req, posPort, End); //posRadi);
|
||||
char portc[port.length() + 1];
|
||||
port.toCharArray(portc, port.length() + 1);
|
||||
|
||||
// // Radiateur
|
||||
// String radi = getValueFrom(req, posRadi, posTemp);
|
||||
// char radic[radi.length() + 1];
|
||||
// radi.toCharArray(radic, radi.length() + 1);
|
||||
|
||||
// // Thermometre
|
||||
// String temp = getValueFrom(req, posTemp, posCons);
|
||||
// char tempc[temp.length() + 1];
|
||||
// temp.toCharArray(tempc, temp.length() + 1);
|
||||
|
||||
// // Consigne
|
||||
// String cons = getValueFrom(req, posCons, End);
|
||||
// char consc[cons.length() + 1];
|
||||
// cons.toCharArray(consc, cons.length() + 1);
|
||||
|
||||
//Domoticz domo("192.168.1.3", "81", "Livebox-37cc", "8A6060920A8A86896F770F2C47");
|
||||
|
||||
|
||||
// boolean connected = connectToWifi(ssidc, passc);
|
||||
|
||||
// client.flush();
|
||||
// // Prepare the response. Start with the common header:
|
||||
|
||||
|
||||
String s = "HTTP/1.1 200 OK\r\n";
|
||||
s += "Content-Type: text/html\r\n\r\n";
|
||||
s += "<!DOCTYPE HTML>\r\n<html>\r\n";
|
||||
//s += "Connexion en-cours.";
|
||||
|
||||
if (true) {
|
||||
|
||||
s += "WiFi connected\n";
|
||||
|
||||
// Start the server
|
||||
// server.begin();
|
||||
|
||||
// s+="Server started\n";
|
||||
|
||||
// Print the IP address
|
||||
s += "Use this URL to connect: ";
|
||||
s += "http://";
|
||||
//s += WiFi.localIP();
|
||||
s += "/_n";
|
||||
|
||||
|
||||
} else {
|
||||
s += "Connexion impossible";
|
||||
}
|
||||
|
||||
s += "</html>\n";
|
||||
client.println(s);
|
||||
delay(200);
|
||||
|
||||
}
|
||||
82
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/ServeurWeb.h
Normal file
82
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/ServeurWeb.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#ifndef ServeurWeb_h
|
||||
#define ServeurWeb_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include "Domoticz.h"
|
||||
#include "Params.h"
|
||||
#include "Modules.h"
|
||||
#include "Pins.h"
|
||||
#define PAGE_MENU 0
|
||||
#define PAGE_ADMIN 1
|
||||
#define PAGE_STATUS 2
|
||||
#define PAGE_INFOS 3
|
||||
#define PAGE_GRAPH 4
|
||||
#define DELAI_LECTURE 120
|
||||
|
||||
|
||||
class ServeurWeb
|
||||
{
|
||||
public:
|
||||
ServeurWeb();
|
||||
//void setup();
|
||||
void loop();
|
||||
private:
|
||||
boolean connectToWifi();
|
||||
//void initHardware();
|
||||
char* convertToChar(String s, char* buf);
|
||||
void infos();
|
||||
void menuBody(int page);
|
||||
void pageAdmin();
|
||||
void pageMenu(int page);
|
||||
void printWifiStatus();
|
||||
//void setupWiFi();
|
||||
void body();
|
||||
String getValueFrom(String request, int deb, int fin);
|
||||
void menuStyle(int page);
|
||||
void style();
|
||||
void graph();
|
||||
void ident(String req);
|
||||
|
||||
public:
|
||||
Domoticz* domoticz;
|
||||
Modules* modules;
|
||||
// WiFiClient _client;
|
||||
String radiateur = ""; //"217";
|
||||
String temp = ""; //"281";
|
||||
String cons = ""; //"212";
|
||||
|
||||
String jsPath = "/ESP8266/js/";
|
||||
String jqueryName = "jquery.js";
|
||||
String chartName = "chart.js";
|
||||
String AP_NameString = "";
|
||||
int nbData = 0;
|
||||
String data = "22.3,22.3,22.3,22.3";
|
||||
String labels = "0,1,2,3";
|
||||
int bcl = 0;
|
||||
int val0;
|
||||
int val2;
|
||||
int val3;
|
||||
int val4;
|
||||
String separator = ",";
|
||||
String nom = "";
|
||||
int refresh = 2;
|
||||
WiFiClient client;
|
||||
WiFiServer* server;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// // Ordre dans Domoticz
|
||||
// // Radiateur Temp Consigne
|
||||
// //Manon 217 281 212
|
||||
// //Théo 219 335 211
|
||||
// //Chambre 218 254 213
|
||||
// //Bureau 163 260 214
|
||||
|
||||
|
||||
757
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Somfy.cpp
Normal file
757
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Somfy.cpp
Normal file
@@ -0,0 +1,757 @@
|
||||
// -------------------------------------------------------------
|
||||
//
|
||||
// Fichier principal de votre Box compatible Somfy RTS ou Chacon Dio
|
||||
// Version 1.1.0
|
||||
// Mise à jour par TOST Corp. le 02 janvier 2020
|
||||
// www.tostcorp.com/boxsomfyrts
|
||||
//
|
||||
// -------------------------------------------------------------
|
||||
|
||||
#include "config.h"
|
||||
// #include "Somfy.h"
|
||||
void blink_function();
|
||||
Ticker mqtt_error_timer(blink_function, 10, 11);
|
||||
Ticker blink_timer(blink_function, 200, 21);
|
||||
Ticker publish_timer(blink_function, 10, 11);
|
||||
void receivedCallback(char* topic, byte* payload, unsigned int length);
|
||||
|
||||
Somfy::Somfy()
|
||||
{
|
||||
}
|
||||
void Somfy::init()
|
||||
{
|
||||
// USB serial port
|
||||
delay(100);
|
||||
|
||||
while(! Serial);
|
||||
Serial.println(" ------------------------------------------------");
|
||||
Serial.println("| |");
|
||||
Serial.println("| TOST Corp. Box V1.0.2 - Copyright 2018-2020 |");
|
||||
Serial.println("| |");
|
||||
Serial.println(" ------------------------------------------------");
|
||||
Serial.println("");
|
||||
Serial.println("Available features:");
|
||||
Serial.println("1 SOMFY RTS");
|
||||
Serial.println("2 CHACON DiO 1.0");
|
||||
Serial.println("");
|
||||
Serial.println("Starting the Box...");
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
|
||||
// Open the output for 433.42MHz transmitter
|
||||
pinMode(PORT_TX, OUTPUT);
|
||||
// Open the output for 433.92MHz transmitter
|
||||
pinMode(PORT_DIO_TX, OUTPUT);
|
||||
SIG_LOW;
|
||||
digitalWrite(PORT_DIO_TX, LOW);
|
||||
|
||||
String device_id = WiFi.macAddress();
|
||||
|
||||
// Remove :
|
||||
while (device_id.indexOf(':') != -1)
|
||||
{
|
||||
int index_to_remove = device_id.indexOf(':');
|
||||
device_id.remove(index_to_remove, 1);
|
||||
}
|
||||
|
||||
Serial.print("Box ID: ");
|
||||
Serial.println(device_id);
|
||||
|
||||
// Connect to WiFi
|
||||
Serial.print("WiFi connection to ");
|
||||
Serial.print(wifi_ssid);
|
||||
Serial.print(" ");
|
||||
|
||||
WiFi.begin(wifi_ssid, wifi_password);
|
||||
WiFi.hostname("ESP8266-somfy");
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.print("Connected to WiFi | IP adress ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
// Configure MQTT
|
||||
|
||||
PubSubClient _mqtt(wifiClient);
|
||||
mqtt = _mqtt;
|
||||
mqtt.setServer(mqtt_server, mqtt_port);
|
||||
//mqtt.setCallback(receivedCallback);
|
||||
|
||||
mqtt.setCallback([this] (char* topic, byte* payload, unsigned int length) {
|
||||
this->receivedCallback(topic, payload, length);
|
||||
});
|
||||
|
||||
EEPROM.begin(1024);
|
||||
|
||||
// Print out all the configured remotes.
|
||||
// Also reset the rolling codes for ESP8266 if needed.
|
||||
|
||||
Serial.print("");
|
||||
Serial.println("Read the configuration...");
|
||||
|
||||
if (update_database)
|
||||
{
|
||||
clean_database(device_id);
|
||||
}
|
||||
|
||||
for ( REMOTE remote : remotes )
|
||||
{
|
||||
Serial.print("SOMFY RTS: ");
|
||||
Serial.print(remote.mqtt_topic);
|
||||
Serial.print(" | number: ");
|
||||
Serial.print(remote.id, HEX);
|
||||
Serial.print(" | rolling code: ");
|
||||
unsigned int current_code;
|
||||
|
||||
if ( reset_rolling_codes )
|
||||
{
|
||||
EEPROM.put( remote.eeprom_address, remote.default_rolling_code );
|
||||
EEPROM.commit();
|
||||
}
|
||||
EEPROM.get( remote.eeprom_address, current_code );
|
||||
Serial.print( current_code );
|
||||
Serial.print(" | description: ");
|
||||
Serial.println( remote.description );
|
||||
|
||||
// Add to database
|
||||
if (update_database)
|
||||
{
|
||||
add_to_database(device_id, remote.mqtt_topic, remote.description, "somfy_rts", remote.device_group);
|
||||
}
|
||||
}
|
||||
|
||||
for ( DIO_REMOTE dio_remote : dio_remotes )
|
||||
{
|
||||
Serial.print("CHACON DiO: ");
|
||||
Serial.print(dio_remote.mqtt_topic);
|
||||
Serial.print(" | number: ");
|
||||
Serial.print(dio_remote.id, HEX);
|
||||
Serial.print(" | description: ");
|
||||
Serial.println(dio_remote.description);
|
||||
|
||||
// Add to database
|
||||
if (update_database)
|
||||
{
|
||||
add_to_database(device_id, dio_remote.mqtt_topic, dio_remote.description, "chacon_dio_1.0", dio_remote.device_group);
|
||||
}
|
||||
|
||||
} // End of for
|
||||
|
||||
Serial.print("");
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
blink_timer.start();
|
||||
}
|
||||
|
||||
void Somfy::loop()
|
||||
{
|
||||
publish_timer.update();
|
||||
|
||||
// Reconnect MQTT if needed
|
||||
if ( !mqtt.connected() )
|
||||
{
|
||||
mqttconnect();
|
||||
// We are connected stop blinking to Wifi
|
||||
blink_timer.stop();
|
||||
Serial.println("The box is ready.\n");
|
||||
Serial.println("");
|
||||
}
|
||||
|
||||
mqtt.loop();
|
||||
loopSerial();
|
||||
delay(100);
|
||||
}
|
||||
|
||||
void Somfy::mqttconnect()
|
||||
{
|
||||
|
||||
// Loop until reconnected
|
||||
while ( !mqtt.connected() )
|
||||
{
|
||||
Serial.print("Connecting to MQTT ...");
|
||||
Serial.print(mqtt_id);
|
||||
Serial.print(mqtt_user);
|
||||
Serial.print(mqtt_password);
|
||||
Serial.print(status_topic);
|
||||
// Connect to MQTT, with retained last will message "offline"
|
||||
if (mqtt.connect(mqtt_id, mqtt_user, mqtt_password, status_topic, 1, 1, "offline")) {
|
||||
Serial.println(" Connected.");
|
||||
|
||||
Serial.print("Suscribe to MQTT .");
|
||||
// Subscribe to the topic of each remote with QoS 1
|
||||
for ( REMOTE remote : remotes ) {
|
||||
mqtt.subscribe(remote.mqtt_topic, 1);
|
||||
mqtt.subscribe(remote.device_group, 1);
|
||||
Serial.print(".");
|
||||
// Serial.print("\nLOG - Subscribed to SOMFY RTS topic: ");
|
||||
// Serial.println(remote.device_group);
|
||||
}
|
||||
|
||||
// Subscribe to the topic of each remote with QoS 1
|
||||
for ( DIO_REMOTE remote : dio_remotes ) {
|
||||
mqtt.subscribe(remote.mqtt_topic, 1);
|
||||
mqtt.subscribe(remote.device_group, 1);
|
||||
Serial.print(".");
|
||||
// Serial.print("\nLOG - Subscribed to DIO topic: ");
|
||||
// Serial.println(remote.mqtt_topic);
|
||||
}
|
||||
|
||||
// Update status, message is retained
|
||||
mqtt.publish(status_topic, "online", true);
|
||||
Serial.println("Done.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("ERR - Failed, status code = ");
|
||||
Serial.print(mqtt.state());
|
||||
Serial.println(" Try again in 5 seconds");
|
||||
// Wait 5 seconds before retrying
|
||||
blink_blue_light(5000, 200);
|
||||
}
|
||||
}
|
||||
blink_blue_light(500, 50);
|
||||
}
|
||||
|
||||
|
||||
void Somfy::receivedCallback(char* topic, byte* payload, unsigned int length) {
|
||||
char command = *payload; // 1st byte of payload
|
||||
bool commandIsValid = false;
|
||||
bool dioCommandIsValid = false;
|
||||
|
||||
String s_topic = String(topic);
|
||||
|
||||
REMOTE currentRemote;
|
||||
REMOTE remote;
|
||||
|
||||
// DIO_REMOTE dio_remote;
|
||||
DIO_REMOTE dio_currentRemote;
|
||||
|
||||
Serial.print("MQTT message received: ");
|
||||
digitalWrite(BUILTIN_LED, LOW);
|
||||
publish_timer.start();
|
||||
Serial.println(topic);
|
||||
|
||||
Serial.print("Payload: ");
|
||||
for (int i = 0; i < length; i++) {
|
||||
Serial.print((char)payload[i]);
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// Somfy command is valid if the payload contains one of the chars below AND the topic corresponds to one of the remotes
|
||||
if ( length == 1 && ( command == 'u' || command == 's' || command == 'd' || command == 'p' ) )
|
||||
{
|
||||
Serial.println("SOMFY RTS command received");
|
||||
int nb_remotes = sizeof remotes/sizeof remotes[0];
|
||||
for (int i=0; i<nb_remotes; i++)
|
||||
{
|
||||
remote = remotes[i];
|
||||
String s_mqtt_topic = String(remote.mqtt_topic);
|
||||
String s_device_group = String(remote.device_group);
|
||||
|
||||
// if ( strcmp(remote.mqtt_topic, s_topic) == 0 )
|
||||
if ( s_mqtt_topic.compareTo(s_topic) == 0 )
|
||||
{
|
||||
commandIsValid = true;
|
||||
send_somfy_command(command, remote, false);
|
||||
}
|
||||
// if ( strcmp(remote.device_group, s_topic) == 0 )
|
||||
else if ( s_device_group.compareTo(s_topic) == 0 )
|
||||
{
|
||||
Serial.print("SOMFY RTS command is grouped ");
|
||||
Serial.println(remote.mqtt_topic);
|
||||
commandIsValid = true;
|
||||
send_somfy_command(command, remote, true);
|
||||
}
|
||||
} // End of for
|
||||
}
|
||||
|
||||
// DIO command
|
||||
if ( length ==1 && ( command == '1' || command == '0' ) )
|
||||
{
|
||||
Serial.println("DiO command received");
|
||||
for ( DIO_REMOTE dio_remote : dio_remotes )
|
||||
{
|
||||
String s_mqtt_topic = String(dio_remote.mqtt_topic);
|
||||
String s_device_group = String(dio_remote.device_group);
|
||||
|
||||
// Single command
|
||||
// if ( strcmp(dio_remote.mqtt_topic, topic) == 0 )
|
||||
if ( s_mqtt_topic.compareTo(s_topic) == 0 )
|
||||
{
|
||||
dioCommandIsValid = true;
|
||||
send_dio_command(command, dio_remote, false);
|
||||
}
|
||||
// Multiple command
|
||||
// else if ( strcmp(dio_remote.device_group, topic) == 0 )
|
||||
else if ( s_device_group.compareTo(s_topic) == 0 )
|
||||
{
|
||||
Serial.println("DiO command is grouped");
|
||||
dioCommandIsValid = true;
|
||||
send_dio_command(command, dio_remote, true);
|
||||
}
|
||||
|
||||
} // End of for
|
||||
}
|
||||
}
|
||||
|
||||
void Somfy::send_somfy_command(char command, REMOTE currentRemote, bool group)
|
||||
{
|
||||
|
||||
if ( command == 'u' )
|
||||
{
|
||||
Serial.println("COMMAND - Up"); // Somfy is a French company, after all.
|
||||
BuildFrame(frame, HAUT, currentRemote);
|
||||
}
|
||||
else if ( command == 's' )
|
||||
{
|
||||
Serial.println("COMMAND - Stop");
|
||||
BuildFrame(frame, STOP, currentRemote);
|
||||
}
|
||||
else if ( command == 'd' )
|
||||
{
|
||||
Serial.println("COMMAND - Down");
|
||||
BuildFrame(frame, BAS, currentRemote);
|
||||
}
|
||||
else if ( command == 'p' )
|
||||
{
|
||||
Serial.println("COMMAND - Prog");
|
||||
BuildFrame(frame, PROG, currentRemote);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
|
||||
SendCommand(frame, 2);
|
||||
for ( int i = 0; i<2; i++ ) {
|
||||
SendCommand(frame, 7);
|
||||
}
|
||||
|
||||
// Send the MQTT ack message
|
||||
String ackString = "id: 0x";
|
||||
ackString.concat( String(currentRemote.id, HEX) );
|
||||
ackString.concat(", cmd: ");
|
||||
ackString.concat(command);
|
||||
mqtt.publish(ack_topic, ackString.c_str());
|
||||
if (group)
|
||||
{
|
||||
delay(delay_group_radio_signal);
|
||||
}
|
||||
}
|
||||
|
||||
void Somfy::send_dio_command(char command, DIO_REMOTE dio_currentRemote, bool group)
|
||||
{
|
||||
if ( command == '0' )
|
||||
{
|
||||
Serial.println("COMMAND - 0");
|
||||
// Serial.println(dio_currentRemote.sender);
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
transmit(dio_currentRemote.sender, dio_currentRemote.interruptor, 0);
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
else if ( command == '1' )
|
||||
{
|
||||
Serial.println("COMMAND - 1");
|
||||
// Serial.println(dio_currentRemote.sender);
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
transmit(dio_currentRemote.sender, dio_currentRemote.interruptor, 1);
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
|
||||
// Send the MQTT ack message
|
||||
String ackString = "id: 0x";
|
||||
ackString.concat( String(dio_currentRemote.id, HEX) );
|
||||
ackString.concat(", cmd: ");
|
||||
ackString.concat(command);
|
||||
mqtt.publish(ack_topic, ackString.c_str());
|
||||
if (group)
|
||||
{
|
||||
delay(delay_group_radio_signal);
|
||||
}
|
||||
}
|
||||
|
||||
void Somfy::BuildFrame(byte *frame, byte button, REMOTE remote) {
|
||||
unsigned int code;
|
||||
|
||||
EEPROM.get( remote.eeprom_address, code );
|
||||
|
||||
frame[0] = 0xA7; // Encryption key. Doesn't matter much
|
||||
frame[1] = button << 4; // Which button did you press? The 4 LSB will be the checksum
|
||||
frame[2] = code >> 8; // Rolling code (big endian)
|
||||
frame[3] = code; // Rolling code
|
||||
frame[4] = remote.id >> 16; // Remote address
|
||||
frame[5] = remote.id >> 8; // Remote address
|
||||
frame[6] = remote.id; // Remote address
|
||||
|
||||
Serial.print("Frame : ");
|
||||
for(byte i = 0; i < 7; i++) {
|
||||
if(frame[i] >> 4 == 0) { // Displays leading zero in case the most significant nibble is a 0.
|
||||
Serial.print("0");
|
||||
}
|
||||
Serial.print(frame[i],HEX); Serial.print(" ");
|
||||
}
|
||||
|
||||
// Checksum calculation: a XOR of all the nibbles
|
||||
byte checksum = 0;
|
||||
for(byte i = 0; i < 7; i++) {
|
||||
checksum = checksum ^ frame[i] ^ (frame[i] >> 4);
|
||||
}
|
||||
checksum &= 0b1111; // We keep the last 4 bits only
|
||||
|
||||
|
||||
// Checksum integration
|
||||
frame[1] |= checksum; // If a XOR of all the nibbles is equal to 0, the blinds will consider the checksum ok.
|
||||
|
||||
Serial.println(""); Serial.print("With checksum : ");
|
||||
for(byte i = 0; i < 7; i++) {
|
||||
if(frame[i] >> 4 == 0) {
|
||||
Serial.print("0");
|
||||
}
|
||||
Serial.print(frame[i],HEX); Serial.print(" ");
|
||||
}
|
||||
|
||||
|
||||
// Obfuscation: a XOR of all the bytes
|
||||
for(byte i = 1; i < 7; i++) {
|
||||
frame[i] ^= frame[i-1];
|
||||
}
|
||||
|
||||
Serial.println(""); Serial.print("Obfuscated : ");
|
||||
for(byte i = 0; i < 7; i++) {
|
||||
if(frame[i] >> 4 == 0) {
|
||||
Serial.print("0");
|
||||
}
|
||||
Serial.print(frame[i],HEX); Serial.print(" ");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.print("Rolling Code : ");
|
||||
Serial.println(code);
|
||||
|
||||
EEPROM.put( remote.eeprom_address, code + 1 );
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
void Somfy::SendCommand(byte *frame, byte sync) {
|
||||
if(sync == 2) { // Only with the first frame.
|
||||
//Wake-up pulse & Silence
|
||||
SIG_HIGH;
|
||||
delayMicroseconds(9415);
|
||||
SIG_LOW;
|
||||
delayMicroseconds(89565);
|
||||
}
|
||||
|
||||
// Hardware sync: two sync for the first frame, seven for the following ones.
|
||||
for (int i = 0; i < sync; i++) {
|
||||
SIG_HIGH;
|
||||
delayMicroseconds(4*SYMBOL);
|
||||
SIG_LOW;
|
||||
delayMicroseconds(4*SYMBOL);
|
||||
}
|
||||
|
||||
// Software sync
|
||||
SIG_HIGH;
|
||||
delayMicroseconds(4550);
|
||||
SIG_LOW;
|
||||
delayMicroseconds(SYMBOL);
|
||||
|
||||
//Data: bits are sent one by one, starting with the MSB.
|
||||
for(byte i = 0; i < 56; i++) {
|
||||
if(((frame[i/8] >> (7 - (i%8))) & 1) == 1) {
|
||||
SIG_LOW;
|
||||
delayMicroseconds(SYMBOL);
|
||||
SIG_HIGH;
|
||||
delayMicroseconds(SYMBOL);
|
||||
}
|
||||
else {
|
||||
SIG_HIGH;
|
||||
delayMicroseconds(SYMBOL);
|
||||
SIG_LOW;
|
||||
delayMicroseconds(SYMBOL);
|
||||
}
|
||||
}
|
||||
|
||||
SIG_LOW;
|
||||
delayMicroseconds(30415); // Inter-frame silence
|
||||
}
|
||||
|
||||
void blink_function()
|
||||
{
|
||||
//toggle state
|
||||
int state = digitalRead(BUILTIN_LED); // get the current state of GPIO1 pin
|
||||
digitalWrite(BUILTIN_LED, !state); // set pin to the opposite state
|
||||
// Serial.print("blink_function()");
|
||||
}
|
||||
|
||||
void Somfy::blink_blue_light(int time_ms, int delay_ms)
|
||||
{
|
||||
int total_time = 0;
|
||||
int light = 0;
|
||||
while (total_time < time_ms)
|
||||
{
|
||||
if (light == 0)
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
light = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
light = 0;
|
||||
}
|
||||
|
||||
delay(delay_ms);
|
||||
total_time = total_time + delay_ms;
|
||||
}
|
||||
|
||||
// force off
|
||||
digitalWrite(0, HIGH);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Somfy::sendBit(bool b)
|
||||
{
|
||||
if (b) {
|
||||
digitalWrite(PORT_DIO_TX, HIGH);
|
||||
delayMicroseconds(310); //275 originally, but tweaked.
|
||||
digitalWrite(PORT_DIO_TX, LOW);
|
||||
delayMicroseconds(1340); //1225 originally, but tweaked.
|
||||
} else {
|
||||
digitalWrite(PORT_DIO_TX, HIGH);
|
||||
delayMicroseconds(310); //275 originally, but tweaked.
|
||||
digitalWrite(PORT_DIO_TX, LOW);
|
||||
delayMicroseconds(310); //275 originally, but tweaked.
|
||||
}
|
||||
}
|
||||
|
||||
void Somfy::sendPair(bool b) {
|
||||
if (b) {
|
||||
sendBit(true);
|
||||
sendBit(false);
|
||||
} else {
|
||||
sendBit(false);
|
||||
sendBit(true);
|
||||
}
|
||||
}
|
||||
|
||||
void Somfy::transmit(unsigned long sender, int interruptor, int blnOn) {
|
||||
int i;
|
||||
|
||||
digitalWrite(PORT_DIO_TX, HIGH);
|
||||
delayMicroseconds(275);
|
||||
digitalWrite(PORT_DIO_TX, LOW);
|
||||
delayMicroseconds(9900); // first lock
|
||||
digitalWrite(PORT_DIO_TX, HIGH); // high again
|
||||
delayMicroseconds(275); // wait
|
||||
digitalWrite(PORT_DIO_TX, LOW); // second lock
|
||||
delayMicroseconds(2675);
|
||||
digitalWrite(PORT_DIO_TX, HIGH);
|
||||
|
||||
// Emiter ID
|
||||
for(i = 0; i < 26; i++) {
|
||||
sendPair( (sender >> (25 - i)) & 0b1);
|
||||
}
|
||||
|
||||
// 26th bit -- grouped command
|
||||
sendPair(false);
|
||||
|
||||
// 27th bit -- On or off
|
||||
sendPair(blnOn);
|
||||
|
||||
// 4 last bits -- reactor code 0000 -> 0 -- 0001 -> 1
|
||||
for (i = 0; i < 4; i++) {
|
||||
sendPair( (interruptor >> (3 - i)) & 1 );
|
||||
}
|
||||
|
||||
digitalWrite(PORT_DIO_TX, HIGH); // lock - end of data
|
||||
delayMicroseconds(275); // wait
|
||||
digitalWrite(PORT_DIO_TX, LOW); // lock - end of signal
|
||||
}
|
||||
|
||||
int Somfy::add_to_database(String device_id,const char* mqtt_topic, const char* description, const char* type, const char* device_group)
|
||||
{
|
||||
|
||||
if (wifiClient.connect(HOST, 80))
|
||||
{
|
||||
String url = "/somfy_rts/mqtt_web_hook_public.php?service=add_device&device_id=" + device_id +
|
||||
"&topic=" + urlencode(mqtt_topic) + "&description=" + urlencode(description) + "&type=" + type +
|
||||
"&device_group=" + urlencode(device_group)+ "&mqtt_info=" + urlencode(mqtt_password);
|
||||
|
||||
wifiClient.print(String("GET ") + url + " HTTP/1.1\r\n" +
|
||||
"Host: " + HOST + "\r\n" +
|
||||
"Connection: close\r\n\r\n");
|
||||
|
||||
String line = wifiClient.readStringUntil('\r');
|
||||
// Serial.println(line);
|
||||
|
||||
// Read all the lines of the reply from server and print them to Serial
|
||||
while(wifiClient.available())
|
||||
{
|
||||
line = wifiClient.readStringUntil('\r');
|
||||
// Serial.print(line);
|
||||
}
|
||||
|
||||
Serial.print("The device \"");
|
||||
Serial.print(description);
|
||||
Serial.println("\" was added/updated to the database.");
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("An error occurs while adding the device \"");
|
||||
Serial.print(description);
|
||||
Serial.print("\"");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int Somfy::clean_database(String device_id)
|
||||
{
|
||||
Serial.print("Clean the device ");
|
||||
Serial.println(device_id);
|
||||
|
||||
if (wifiClient.connect(HOST, 80))
|
||||
{
|
||||
String url = "/somfy_rts/mqtt_web_hook_public.php?service=clear_devices&device_id=" + device_id +
|
||||
"&mqtt_info=" + urlencode(mqtt_password);
|
||||
|
||||
wifiClient.print(String("GET ") + url + " HTTP/1.1\r\n" +
|
||||
"Host: " + HOST + "\r\n" +
|
||||
"Connection: close\r\n\r\n");
|
||||
|
||||
String line = wifiClient.readStringUntil('\r');
|
||||
// Serial.println(line);
|
||||
|
||||
// Read all the lines of the reply from server and print them to Serial
|
||||
while(wifiClient.available())
|
||||
{
|
||||
line = wifiClient.readStringUntil('\r');
|
||||
// Serial.print(line);
|
||||
}
|
||||
|
||||
Serial.print("The device \"");
|
||||
Serial.print(device_id);
|
||||
Serial.println("\" was deleted from the database.");
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("An error occurs while cleaning the device \"");
|
||||
Serial.print(device_id);
|
||||
Serial.print("\"");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
String Somfy::urlencode(String str)
|
||||
{
|
||||
String encodedString="";
|
||||
char c;
|
||||
char code0;
|
||||
char code1;
|
||||
char code2;
|
||||
for (int i =0; i < str.length(); i++){
|
||||
c=str.charAt(i);
|
||||
if (c == ' '){
|
||||
encodedString+= '+';
|
||||
} else if (isalnum(c)){
|
||||
encodedString+=c;
|
||||
} else{
|
||||
code1=(c & 0xf)+'0';
|
||||
if ((c & 0xf) >9){
|
||||
code1=(c & 0xf) - 10 + 'A';
|
||||
}
|
||||
c=(c>>4)&0xf;
|
||||
code0=c+'0';
|
||||
if (c > 9){
|
||||
code0=c - 10 + 'A';
|
||||
}
|
||||
code2='\0';
|
||||
encodedString+='%';
|
||||
encodedString+=code0;
|
||||
encodedString+=code1;
|
||||
//encodedString+=code2;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
return encodedString;
|
||||
|
||||
}
|
||||
|
||||
unsigned char Somfy::h2int(char c)
|
||||
{
|
||||
if (c >= '0' && c <='9'){
|
||||
return((unsigned char)c - '0');
|
||||
}
|
||||
if (c >= 'a' && c <='f'){
|
||||
return((unsigned char)c - 'a' + 10);
|
||||
}
|
||||
if (c >= 'A' && c <='F'){
|
||||
return((unsigned char)c - 'A' + 10);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void Somfy::loopSerial() {
|
||||
|
||||
// Send Remote Control Request by Serial
|
||||
if (Serial.available() > 0) {
|
||||
digitalWrite(BUILTIN_LED, LOW);
|
||||
publish_timer.start();
|
||||
REMOTE currentRemote;
|
||||
char inByte[2];
|
||||
Serial.readBytes(inByte, 2);
|
||||
byte idx = inByte[1]-48;
|
||||
Serial.print((char)inByte[0]);
|
||||
char command = (char)inByte[0];
|
||||
Serial.print(command);
|
||||
|
||||
int nb_remotes = sizeof remotes/sizeof remotes[0];
|
||||
for (int i=0; i<nb_remotes; i++) {
|
||||
if (i == idx) {
|
||||
currentRemote = remotes[idx];
|
||||
}
|
||||
}
|
||||
Serial.println(idx);
|
||||
|
||||
if ( command == 'u' ) {
|
||||
Serial.println("Monte"); // Somfy is a French company, after all.
|
||||
BuildFrame(frame, HAUT, currentRemote);
|
||||
}
|
||||
else if ( command == 's' ) {
|
||||
Serial.println("Stop");
|
||||
BuildFrame(frame, STOP, currentRemote);
|
||||
}
|
||||
else if ( command == 'd' ) {
|
||||
Serial.println("Descend");
|
||||
BuildFrame(frame, BAS, currentRemote);
|
||||
}
|
||||
else if ( command == 'p' ) {
|
||||
Serial.println("Prog");
|
||||
BuildFrame(frame, PROG, currentRemote);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
|
||||
SendCommand(frame, 2);
|
||||
for ( int i = 0; i<2; i++ ) {
|
||||
SendCommand(frame, 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
104
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Somfy.h
Normal file
104
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Somfy.h
Normal file
@@ -0,0 +1,104 @@
|
||||
// -------------------------------------------------------------
|
||||
//
|
||||
// Fichier principal de votre Box compatible Somfy RTS ou Chacon Dio
|
||||
// Version 1.1.0
|
||||
// Mise à jour par TOST Corp. le 02 janvier 2020
|
||||
// www.tostcorp.com/boxsomfyrts
|
||||
//
|
||||
// -------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef Somfy_h
|
||||
#define Somfy_h
|
||||
|
||||
// Librairies utilisées
|
||||
#include <Arduino.h>
|
||||
// #include "sql_database_helper.h"
|
||||
#include <EEPROM.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include "PubSubClient.h"
|
||||
#include "Ticker_v2.h"
|
||||
// #include "config.h"
|
||||
|
||||
struct REMOTE {
|
||||
unsigned int id;
|
||||
char const* mqtt_topic;
|
||||
unsigned int default_rolling_code;
|
||||
uint32_t eeprom_address;
|
||||
char const* description;
|
||||
char const* device_group;
|
||||
};
|
||||
|
||||
struct DIO_REMOTE {
|
||||
unsigned int id;
|
||||
char const* mqtt_topic;
|
||||
unsigned long sender;
|
||||
unsigned long interruptor;
|
||||
char const* description;
|
||||
char const* device_group;
|
||||
};
|
||||
|
||||
|
||||
/* Adapted to run on ESP32 from original code at https://github.com/Nickduino/Somfy_Remote
|
||||
This program allows you to emulate a Somfy RTS or Simu HZ remote.
|
||||
If you want to learn more about the Somfy RTS protocol, check out https://pushstack.wordpress.com/somfy-rts-protocol/
|
||||
The rolling code will be stored in non-volatile storage (Preferences), so that you can power the Arduino off.
|
||||
Serial communication of the original code is replaced by MQTT over WiFi.
|
||||
Modifications should only be needed in config.h.
|
||||
*/
|
||||
|
||||
#define SIG_HIGH GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1 << PORT_TX)
|
||||
#define SIG_LOW GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << PORT_TX)
|
||||
|
||||
|
||||
|
||||
// void blink_function();
|
||||
// Ticker mqtt_error_timer(blink_function, 10, 11);
|
||||
// Ticker blink_timer(blink_function, 200, 21);
|
||||
// Ticker publish_timer(blink_function, 10, 11);
|
||||
|
||||
// WiFiClient wifiClient;
|
||||
|
||||
// Buttons
|
||||
#define SYMBOL 640
|
||||
#define HAUT 0x2
|
||||
#define STOP 0x1
|
||||
#define BAS 0x4
|
||||
#define PROG 0x8
|
||||
|
||||
|
||||
class Somfy {
|
||||
public:
|
||||
Somfy();
|
||||
void init();
|
||||
void loop();
|
||||
//void blink_function();
|
||||
|
||||
void BuildFrame(byte *frame, byte button, REMOTE remote);
|
||||
void receivedCallback(char* topic, byte* payload, unsigned int length);
|
||||
void mqttconnect();
|
||||
void send_somfy_command(char command, REMOTE currentRemote, bool group);
|
||||
void send_dio_command(char command, DIO_REMOTE dio_currentRemote, bool group);
|
||||
void SendCommand(byte *frame, byte sync);
|
||||
void blink_blue_light(int time_ms, int delay_ms);
|
||||
void sendBit(bool b);
|
||||
void sendPair(bool b);
|
||||
void transmit(unsigned long sender, int interruptor, int blnOn);
|
||||
int add_to_database(String device_id,const char* mqtt_topic, const char* description, const char* type, const char* device_group);
|
||||
int clean_database(String device_id);
|
||||
String urlencode(String str);
|
||||
unsigned char h2int(char c);
|
||||
void loopSerial();
|
||||
void _receivedCallback(char* topic, byte* payload, unsigned int length);
|
||||
|
||||
public:
|
||||
const char* HOST = "bipbipavertisseur.alwaysdata.net";
|
||||
byte frame[7];
|
||||
PubSubClient mqtt;
|
||||
WiFiClient wifiClient;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
113
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Ticker_v2.cpp
Normal file
113
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Ticker_v2.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/* Ticker library code is placed under the MIT license
|
||||
* Copyright (c) 2018 Stefan Staub
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "Ticker_v2.h"
|
||||
|
||||
Ticker::Ticker(fptr callback, uint32_t timer, uint32_t repeat, resolution_t resolution) {
|
||||
this->resolution = resolution;
|
||||
if (resolution == MICROS) timer = timer * 1000;
|
||||
this->timer = timer;
|
||||
this->repeat = repeat;
|
||||
this->callback = callback;
|
||||
enabled = false;
|
||||
lastTime = 0;
|
||||
counts = 0;
|
||||
}
|
||||
|
||||
Ticker::~Ticker() {}
|
||||
|
||||
void Ticker::start() {
|
||||
if (callback == NULL) return;
|
||||
if (resolution == MILLIS) lastTime = millis();
|
||||
else lastTime = micros();
|
||||
enabled = true;
|
||||
counts = 0;
|
||||
status = RUNNING;
|
||||
}
|
||||
|
||||
void Ticker::resume() {
|
||||
if (callback == NULL) return;
|
||||
if (resolution == MILLIS) lastTime = millis() - diffTime;
|
||||
else lastTime = micros() - diffTime;
|
||||
if (status == STOPPED) counts = 0;
|
||||
enabled = true;
|
||||
status = RUNNING;
|
||||
}
|
||||
|
||||
void Ticker::stop() {
|
||||
enabled = false;
|
||||
counts = 0;
|
||||
status = STOPPED;
|
||||
}
|
||||
|
||||
void Ticker::pause() {
|
||||
if (resolution == MILLIS) diffTime = millis() - lastTime;
|
||||
else diffTime = micros() - lastTime;
|
||||
enabled = false;
|
||||
status = PAUSED;
|
||||
}
|
||||
|
||||
void Ticker::update()
|
||||
{
|
||||
if (tick()) callback();
|
||||
}
|
||||
|
||||
bool Ticker::tick() {
|
||||
if (!enabled) return false;
|
||||
if (resolution == MILLIS) {
|
||||
if ((millis() - lastTime) >= timer) {
|
||||
lastTime = millis();
|
||||
if (repeat - counts == 1) enabled = false;
|
||||
counts++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((micros() - lastTime) >= timer) {
|
||||
lastTime = micros();
|
||||
if (repeat - counts == 1) enabled = false;
|
||||
counts++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Ticker::interval(uint32_t timer) {
|
||||
if (resolution == MICROS) timer = timer * 1000;
|
||||
this->timer = timer;
|
||||
}
|
||||
|
||||
uint32_t Ticker::elapsed() {
|
||||
if (resolution == MILLIS) return millis() - lastTime;
|
||||
else return micros() - lastTime;
|
||||
}
|
||||
|
||||
status_t Ticker::state() {
|
||||
return status;
|
||||
}
|
||||
|
||||
uint32_t Ticker::counter() {
|
||||
return counts;
|
||||
}
|
||||
133
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Ticker_v2.h
Normal file
133
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/Ticker_v2.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/* Ticker library code is placed under the MIT license
|
||||
* Copyright (c) 2018 Stefan Staub
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TICKER_H
|
||||
#define TICKER_H
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
/** Ticker internal resolution
|
||||
*
|
||||
* @param MICROS default, the resoöution is in micro seconds, max is 70 minutes, the real resoltuion is 4 microseconds at 16MHz CPU cycle
|
||||
* @param MILLIS set the resolution to millis, for longer cycles over 70 minutes
|
||||
*
|
||||
*/
|
||||
enum resolution_t {MICROS, MILLIS, MICROS_MICROS};
|
||||
|
||||
/** Ticker status
|
||||
*
|
||||
* @param STOPPED default, ticker is stopped
|
||||
* @param RUNNIBG ticker is running
|
||||
* @param PAUSED ticker is paused
|
||||
*
|
||||
*/
|
||||
enum status_t {STOPPED, RUNNING, PAUSED};
|
||||
|
||||
typedef void (*fptr)();
|
||||
|
||||
class Ticker {
|
||||
|
||||
public:
|
||||
|
||||
/** create a Ticker object
|
||||
*
|
||||
* @param callback the name of the function to call
|
||||
* @param timer interval length in ms or us
|
||||
* @param repeat default 0 -> endless, repeat > 0 -> number of repeats
|
||||
* @param resolution default MICROS for tickers under 70min, use MILLIS for tickers over 70 min
|
||||
*
|
||||
*/
|
||||
Ticker(fptr callback, uint32_t timer, uint32_t repeat = 0, resolution_t resolution = MICROS);
|
||||
|
||||
/** destructor for the Ticker object
|
||||
*
|
||||
*/
|
||||
~Ticker();
|
||||
|
||||
/** start the ticker
|
||||
*
|
||||
*/
|
||||
void start();
|
||||
|
||||
/** resume the ticker. If not started, it will start it.
|
||||
*
|
||||
*/
|
||||
void resume();
|
||||
|
||||
/** pause the ticker
|
||||
*
|
||||
*/
|
||||
void pause();
|
||||
|
||||
/** stops the ticker
|
||||
*
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/** must to be called in the main loop(), it will check the Ticker, and if necessary, will run the callback
|
||||
*
|
||||
*/
|
||||
void update();
|
||||
|
||||
/**
|
||||
* @brief set the interval timer
|
||||
*
|
||||
* @param timer interval length in ms or us
|
||||
*/
|
||||
void interval(uint32_t timer);
|
||||
|
||||
/** actual ellapsed time
|
||||
*
|
||||
* @returns the elapsed time after the last tick
|
||||
*
|
||||
*/
|
||||
uint32_t elapsed();
|
||||
|
||||
/** get the state of the ticker
|
||||
*
|
||||
* @returns the state of the ticker: STOPPED, RUNNING or PAUSED
|
||||
*/
|
||||
status_t state();
|
||||
|
||||
/** get the numbers of executed repeats
|
||||
*
|
||||
* @returns the number of executed repeats
|
||||
*
|
||||
*/
|
||||
uint32_t counter();
|
||||
|
||||
private:
|
||||
bool tick();
|
||||
bool enabled;
|
||||
uint32_t timer;
|
||||
uint32_t repeat;
|
||||
resolution_t resolution = MICROS;
|
||||
uint32_t counts;
|
||||
status_t status;
|
||||
fptr callback;
|
||||
uint32_t lastTime;
|
||||
uint32_t diffTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
95
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/config.h
Normal file
95
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/config.h
Normal file
@@ -0,0 +1,95 @@
|
||||
// -------------------------------------------------------------
|
||||
//
|
||||
// Fichier de configuration de votre Box compatible Somfy RTS ou Chacon DiO
|
||||
// Mise à jour par TOST Corp. le 2 janvier 2020
|
||||
// 1.0.0 Initiale
|
||||
// 1.0.1 Suppression du vector pour remotes
|
||||
// 1.0.2 Ajout de la compatibilité CHACON DiO 1.0
|
||||
// 1.1.0 Ajoute d'information pour chaque équipement, notamment le groupe pour la commande groupée
|
||||
// et le delai entre deux commandes groupées
|
||||
// www.tostcorp.com/boxsomfyrts
|
||||
//
|
||||
// -------------------------------------------------------------
|
||||
|
||||
// Vous pouvez contrôler autant d'équipements (volets, prises, ...) que vous le souhaitez en ajoutant des éléments
|
||||
// à la list remotes ci-dessous
|
||||
// L'identifiant par exemple 0x123450 doit être unique, le code roulant par défaut peut rester à 1, incrémenter l'adresse
|
||||
// de l'EEPROM de 4 pour chaque équipement
|
||||
|
||||
// Après avoir téléchargé le code dans votre box
|
||||
// 1. Appuyer quelques secondes sur le bouton PROG de la télécommande d'un de vos équipements, le volet va faire un mouvement de va-et-vient haut/bas
|
||||
// 2. Envoyer un message "p" sur la messagerie MQTT avec le topic correspondant à l'équipement
|
||||
// 3. Envoyer un message "u", "d" ou "s" pour monter, descendre ou stopper le volet.
|
||||
|
||||
// Structure d'une télécommande
|
||||
// Ne pas toucher ces lignes
|
||||
|
||||
|
||||
#ifndef Config_h
|
||||
#define Config_h
|
||||
|
||||
// Librairies utilisées
|
||||
#include <Arduino.h>
|
||||
// #include "sql_database_helper.h"
|
||||
#include <EEPROM.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include "PubSubClient.h"
|
||||
#include "Ticker_v2.h"
|
||||
#include "Somfy.h"
|
||||
// ----------------
|
||||
// Etape 1
|
||||
// ----------------
|
||||
// Liste de vos équipements
|
||||
// L'id est un nombre en hexadécimal de votre choix, unique pour chaque équipement
|
||||
// id,"topic MQTT", code roulant par défaut, adresse EEPROM, "description", "nom de groupe"
|
||||
REMOTE remotes[] = {{0x100000, "jerome.delacotte@gmail.com/manon/volet", 1, 0, "cuisine", "jerome.delacotte@gmail.com/somfy/groupe_1" }
|
||||
,{0x120010, "jerome.delacotte@gmail.com/theo/volet", 1, 4, "chambre sullivan", "jerome.delacotte@gmail.com/somfy/groupe_1" }
|
||||
,{0x120020, "jerome.delacotte@gmail.com/chambre/volet", 1, 8, "room_3", "jerome.delacotte@gmail.com/somfy/groupe_2" }
|
||||
};
|
||||
|
||||
DIO_REMOTE dio_remotes[] = {{0x000000, "jerome.delacotte@gmail.com/dio/portail", 1000, 0 , "portail", "jerome.delacotte@gmail.com/dio/groupe_1"}
|
||||
,{0x000010, "jerome.delacotte@gmail.com/dio/inter_1", 2000, 1 , "inter_1", "jerome.delacotte@gmail.com/dio/groupe_2"}
|
||||
,{0x000030, "jerome.delacotte@gmail.com/dio/inter_2", 4000, 3 , "inter_2", "jerome.delacotte@gmail.com/dio/groupe_2"}
|
||||
};
|
||||
|
||||
// Laissez ce champ à false à moins de vouloir ré-initialiser le code roulant
|
||||
const bool reset_rolling_codes = false;
|
||||
// Mettre true pour mettre à jour la base de données avec les équipements
|
||||
// définis dans ce fichier (sinon à false pour gain de temps au reboot de la box).
|
||||
const bool update_database = false;
|
||||
const int delay_group_radio_signal = 500; // délai en millisecondes entre les ordres pour les commandes par groupe
|
||||
|
||||
// ----------------
|
||||
// Etape 2
|
||||
// ----------------
|
||||
// Configuration des identifiants Wifi de votre Box Internet (Free, SFR, Orange, Sosh, Bouygues...)
|
||||
const char* wifi_ssid = "Livebox-37cc";
|
||||
const char* wifi_password = "8A6060920A8A86896F770F2C47";
|
||||
|
||||
|
||||
// ----------------
|
||||
// Etape 3
|
||||
// ----------------
|
||||
// Configuration de votre serveur MQTT
|
||||
// Nom du serveur MQTT (à changer si nécessaire, par exemple tailor.cloudmqtt.com)
|
||||
// Sample: mosquitto_pub -h 192.168.1.3 -u souti -P setaou -t "jerome.delacotte@gmail.com/manon/volet" -m "u"
|
||||
|
||||
const char* mqtt_server = "192.168.1.3"; //"maqiatto.com";
|
||||
// Numéro de port
|
||||
const unsigned int mqtt_port = 1883;
|
||||
// Nom de l'utilisateur
|
||||
const char* mqtt_user = ""; //"souti"; //"jerome.delacotte@gmail.com";
|
||||
// Mot de passe de l'utilisateur
|
||||
const char* mqtt_password = ""; //"setaou";
|
||||
// Identifiant de l'utilisateur (à votre convenance mais sans espaces ni caractères spéciaux)
|
||||
const char* mqtt_id = ""; //"tost_corp_dio_jd_1969";
|
||||
|
||||
//
|
||||
// Ne pas changer les lignes qui suivent
|
||||
//
|
||||
const char* status_topic = "smartHome/somfy-remote/status"; // Online / offline
|
||||
const char* ack_topic = "smartHome/somfy-remote/ack"; // Commands ack "id: 0x184623, cmd: u"
|
||||
#define PORT_TX D1 // Output data on pin 23 (can range from 0 to 31). Check pin numbering on ESP8266.
|
||||
#define PORT_DIO_TX D1 // Output data on pin 23 (can range from 0 to 31). Check pin numbering on ESP8266.
|
||||
|
||||
#endif
|
||||
1
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/data/Test.txt
Normal file
1
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/data/Test.txt
Normal file
@@ -0,0 +1 @@
|
||||
TOTO
|
||||
27
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/data/body.html
Normal file
27
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/data/body.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<body>
|
||||
<form action='/ident' method='get'>
|
||||
<script type='text/javascript'>\nfunction showValue(newValue)\n{\ndocument.getElementById('text').innerHTML=newValue;\n}\n</script>
|
||||
<div>
|
||||
<label for='name'>SSID:</label>
|
||||
<input type='text' id='name' name='name' />
|
||||
</div>
|
||||
<div>
|
||||
<label for='pass'>Password:</label>
|
||||
<input type='password' id='pass' name='pass' />
|
||||
</div>
|
||||
<div>
|
||||
<label for='domo'>Domoticz:</label>
|
||||
<input type='text' id='domo' name='domo' />
|
||||
<label for='port'>Port:</label>
|
||||
<input type='text' id='port' name='port' />
|
||||
</div>
|
||||
<div>
|
||||
<label for='radi'>Id Radiateur:</label>
|
||||
<input type='radi' id='radi' name='radi' />
|
||||
</div>
|
||||
<div class='button'>
|
||||
<button name=H type='submit'>Ok</button>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
23
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/data/menuStyle.css
Normal file
23
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/data/menuStyle.css
Normal file
@@ -0,0 +1,23 @@
|
||||
<style>
|
||||
a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,
|
||||
figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,
|
||||
strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;font:inherit;vertical-align:baseline}
|
||||
article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}nav ul{list-style:none}blockquote,q{quotes:none}blockquote:
|
||||
after,blockquote:before,q:after,q:before{content:'';
|
||||
content:none}table{border-collapse:collapse;border-spacing:0}h1{font-size:1.5em;font-weight:700;padding:.5em 0;letter-spacing:1px}@media screen and
|
||||
(max-width:599px){h1{text-align:center}}h2{font-size:1.25em;font-weight:700;line-height:1.2;padding:.5em 0}p{font-size:1em;padding:0 0 1em}a{color:#555;
|
||||
text-decoration:none;border-bottom:1px solid #555}a:hover{color:#88b47f;border-bottom:1px solid #88b47f}*{-moz-box-sizing:border-box;-webkit-box-sizing:
|
||||
border-box;box-sizing:border-box;-webkit-text-size-adjust:auto}body{font-family:sans-serif;font-size:100%;text-align:center;line-height:1.5;background:
|
||||
#f8f7f0;color:#555}.wrapper{width:90%;max-width:50em;margin:0 auto;text-align:left;overflow:hidden}
|
||||
header{margin-bottom:1em;padding-bottom:1em;background:#57575f;color:#fff}@media screen and (max-width:599px){.no-js .show_menu_btn{display:none}.js .show_menu_btn,.no-js #nav ul{display:block}.js #nav ul{display:none}}@media screen and (min-width:600px){.show_menu_btn{display:none}#nav ul{display:block}}.show_menu_btn{width:35%;margin:0 auto;padding:.3em;cursor:pointer;text-align:center;background:#88b47f}#nav ul{margin:1em 0}#nav ul li{padding:.5em}#nav ul li:hover{background:#88b47f}#nav ul a{display:block;font-size:1em;color:#eee;border-bottom:none}@media screen and (max-width:599px){#nav ul{display:block}#nav ul li{display:block;text-align:center;border-bottom:1px solid #6f6f7a}}@media screen and (min-width:600px){#nav{overflow:hidden}#nav ul li{width:7em;float:left;margin-right:1em}}
|
||||
.boutonTemp {width:85px;height:85px;background:#fafafa;box-shadow:2px 2px 8px #aaa;font:bold 13px Arial;border-radius:50%;color:#555;}
|
||||
.boutonCons {width:85px;height:85px;background:#cc0000;font:bold 13px Arial;border-radius:50%;border:none;color:#fff;}
|
||||
|
||||
input[type="checkbox"] {display: none;}
|
||||
input[type="checkbox"] + label {display:inline-block; line-height:normal; cursor:pointer; padding: 3px 14px;
|
||||
background-color: #EFEFEF;border-radius: 4px;border: 1px solid #D0D0D0;margin: 40px 100px 10px 40px;
|
||||
}input[type="checkbox"] + label:hover {border-color: #000;background-color: #911;color: #fff;}
|
||||
input[type="checkbox"]:checked + label {border-color: #000;background-color: #888;color: #fff;}
|
||||
|
||||
|
||||
</style>
|
||||
91
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/data/style.css
Normal file
91
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/data/style.css
Normal file
@@ -0,0 +1,91 @@
|
||||
<style>
|
||||
form {
|
||||
/* Just to center the form on the page */
|
||||
margin: 0 auto;
|
||||
width: 400px;
|
||||
|
||||
/* To see the limits of the form */
|
||||
padding: 1em;
|
||||
border: 1px solid #CCC;
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
div + div {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
label {
|
||||
/* To make sure that all label have the same size and are properly align */
|
||||
display: inline-block;
|
||||
width: 90px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
/* To make sure that all text field have the same font settings
|
||||
By default, textarea are set with a monospace font */
|
||||
font: 1em sans-serif;
|
||||
|
||||
/* To give the same size to all text field */
|
||||
width: 300px;
|
||||
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
/* To harmonize the look & feel of text field border */
|
||||
border: 1px solid #999;
|
||||
}
|
||||
|
||||
input:focus, textarea:focus {
|
||||
/* To give a little highligh on active elements */
|
||||
border-color: #000;
|
||||
}
|
||||
|
||||
textarea {
|
||||
/* To properly align multiline text field with their label */
|
||||
vertical-align: top;
|
||||
|
||||
/* To give enough room to type some text */
|
||||
height: 5em;
|
||||
|
||||
/* To allow users to resize any textarea vertically
|
||||
It works only on Chrome, Firefox and Safari */
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.button {
|
||||
/* To position the buttons to the same position of the text fields */
|
||||
padding-left: 90px; /* same size as the label elements */
|
||||
}
|
||||
|
||||
button {
|
||||
/* This extra magin represent the same space as the space between
|
||||
the labels and their text fields */
|
||||
margin-left: .5em;
|
||||
}
|
||||
|
||||
.toggle-slide {
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
direction: ltr;
|
||||
}
|
||||
.toggle-slide .toggle-on,.toggle-slide .toggle-off,.toggle-slide .toggle-blob {
|
||||
float: left;
|
||||
}
|
||||
.toggle-slide .toggle-blob {
|
||||
position: relative;
|
||||
z-index: 99;
|
||||
cursor: hand;
|
||||
cursor: grab;
|
||||
cursor: -moz-grab;
|
||||
cursor: -webkit-grab;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
6
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/platformio.ini
Normal file
6
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/platformio.ini
Normal file
@@ -0,0 +1,6 @@
|
||||
[env:d1_mini_pro]
|
||||
platform = espressif8266
|
||||
board = d1_mini_pro
|
||||
framework = arduino
|
||||
lib_deps = PubSubClient
|
||||
board_build.f_cpu = 20000000L
|
||||
BIN
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/tool/esp8266fs.jar
Normal file
BIN
ESP8266_DOMOTICZ_OCTOPRINT_WEB_VOLETS/tool/esp8266fs.jar
Normal file
Binary file not shown.
Reference in New Issue
Block a user