First booting version
This commit is contained in:
parent
5895e04366
commit
429e1ce61a
11
README.md
11
README.md
|
@ -1,3 +1,14 @@
|
||||||
|
# TODO's for ESP32
|
||||||
|
|
||||||
|
- Implement handleFirmwarePost() and handleFirmwareUpload() in MiLightHttpServer.cpp
|
||||||
|
- Erase config in MiLightHttpServer.cpp
|
||||||
|
- Wifi set hostname in main.cpp
|
||||||
|
- Set Wifi physical (setPhyMode) in main.cpp
|
||||||
|
- SSDP (Service discovery) support in main.cpp
|
||||||
|
- LED callback in WiFiManager loop in main.cpp
|
||||||
|
- Implement other TODO's in main.cpp
|
||||||
|
- Reset reason in AboutHelper.cpp
|
||||||
|
|
||||||
# esp8266_milight_hub [![Build Status](https://travis-ci.org/sidoh/esp8266_milight_hub.svg?branch=master)](https://travis-ci.org/sidoh/esp8266_milight_hub) [![License][shield-license]][info-license]
|
# esp8266_milight_hub [![Build Status](https://travis-ci.org/sidoh/esp8266_milight_hub.svg?branch=master)](https://travis-ci.org/sidoh/esp8266_milight_hub) [![License][shield-license]][info-license]
|
||||||
|
|
||||||
This is a replacement for a Milight/LimitlessLED remote/gateway hosted on an ESP8266. Leverages [Henryk Plötz's awesome reverse-engineering work](https://hackaday.io/project/5888-reverse-engineering-the-milight-on-air-protocol).
|
This is a replacement for a Milight/LimitlessLED remote/gateway hosted on an ESP8266. Leverages [Henryk Plötz's awesome reverse-engineering work](https://hackaday.io/project/5888-reverse-engineering-the-milight-on-air-protocol).
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include <ESPId.h>
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
uint32_t getESPId()
|
||||||
|
{
|
||||||
|
return ESP.getChipId();
|
||||||
|
}
|
||||||
|
#elif ESP32
|
||||||
|
uint32_t getESPId()
|
||||||
|
{
|
||||||
|
uint32_t id = 0;
|
||||||
|
for(int i=0; i<17; i=i+8) {
|
||||||
|
id |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef _ESPID_H
|
||||||
|
#define _ESPID_H
|
||||||
|
|
||||||
|
#include <Esp.h>
|
||||||
|
|
||||||
|
uint32_t getESPId();
|
||||||
|
|
||||||
|
#endif
|
|
@ -37,7 +37,7 @@ void HomeAssistantDiscoveryClient::addConfig(const char* alias, const BulbId& bu
|
||||||
DynamicJsonDocument config(1024);
|
DynamicJsonDocument config(1024);
|
||||||
|
|
||||||
char uniqidBuffer[30];
|
char uniqidBuffer[30];
|
||||||
//sprintf_P(uniqidBuffer, PSTR("%X-%s"), ESP.getChipId(), alias);
|
sprintf_P(uniqidBuffer, PSTR("%X-%s"), getESPId(), alias);
|
||||||
|
|
||||||
config[F("schema")] = F("json");
|
config[F("schema")] = F("json");
|
||||||
config[F("name")] = alias;
|
config[F("name")] = alias;
|
||||||
|
@ -50,7 +50,8 @@ void HomeAssistantDiscoveryClient::addConfig(const char* alias, const BulbId& bu
|
||||||
deviceMetadata[F("sw_version")] = QUOTE(MILIGHT_HUB_VERSION);
|
deviceMetadata[F("sw_version")] = QUOTE(MILIGHT_HUB_VERSION);
|
||||||
|
|
||||||
JsonArray identifiers = deviceMetadata.createNestedArray(F("identifiers"));
|
JsonArray identifiers = deviceMetadata.createNestedArray(F("identifiers"));
|
||||||
//identifiers.add(ESP.getChipId());
|
identifiers.add(getESPId());
|
||||||
|
|
||||||
bulbId.serialize(identifiers);
|
bulbId.serialize(identifiers);
|
||||||
|
|
||||||
// HomeAssistant only supports simple client availability
|
// HomeAssistant only supports simple client availability
|
||||||
|
@ -142,7 +143,7 @@ String HomeAssistantDiscoveryClient::buildTopic(const BulbId& bulbId) {
|
||||||
|
|
||||||
topic += "light/";
|
topic += "light/";
|
||||||
// Use a static ID that doesn't depend on configuration.
|
// Use a static ID that doesn't depend on configuration.
|
||||||
topic += "milight_hub_"; //+ String(ESP.getChipId());
|
topic += "milight_hub_" + String(getESPId());
|
||||||
|
|
||||||
// make the object ID based on the actual parameters rather than the alias.
|
// make the object ID based on the actual parameters rather than the alias.
|
||||||
topic += "/";
|
topic += "/";
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <BulbId.h>
|
#include <BulbId.h>
|
||||||
#include <MqttClient.h>
|
#include <MqttClient.h>
|
||||||
|
#include <ESPId.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
class HomeAssistantDiscoveryClient {
|
class HomeAssistantDiscoveryClient {
|
||||||
|
|
|
@ -56,7 +56,8 @@ void MqttClient::begin() {
|
||||||
|
|
||||||
bool MqttClient::connect() {
|
bool MqttClient::connect() {
|
||||||
char nameBuffer[30];
|
char nameBuffer[30];
|
||||||
sprintf_P(nameBuffer, "milight-hub-esp32"); //ESP.getChipId()
|
sprintf_P(nameBuffer, PSTR("milight-hub-%u"), getESPId());
|
||||||
|
|
||||||
|
|
||||||
#ifdef MQTT_DEBUG
|
#ifdef MQTT_DEBUG
|
||||||
Serial.println(F("MqttClient - connecting using name"));
|
Serial.println(F("MqttClient - connecting using name"));
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <PubSubClient.h>
|
#include <PubSubClient.h>
|
||||||
#include <WiFiClient.h>
|
#include <WiFiClient.h>
|
||||||
#include <MiLightRadioConfig.h>
|
#include <MiLightRadioConfig.h>
|
||||||
|
#include <ESPId.h>
|
||||||
|
|
||||||
#ifndef MQTT_CONNECTION_ATTEMPT_FREQUENCY
|
#ifndef MQTT_CONNECTION_ATTEMPT_FREQUENCY
|
||||||
#define MQTT_CONNECTION_ATTEMPT_FREQUENCY 5000
|
#define MQTT_CONNECTION_ATTEMPT_FREQUENCY 5000
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#include <GroupStatePersistence.h>
|
#include <GroupStatePersistence.h>
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include <SPIFFS.h>
|
|
||||||
|
#ifdef ESP32
|
||||||
|
#include <SPIFFS.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char FILE_PREFIX[] = "group_states/";
|
static const char FILE_PREFIX[] = "group_states/";
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ int PL1167_nRF24::internal_receive() {
|
||||||
|
|
||||||
// Currently, the syncword width is set to 5 in order to include the
|
// Currently, the syncword width is set to 5 in order to include the
|
||||||
// PL1167 trailer. The trailer is 4 bits, which pushes packet data
|
// PL1167 trailer. The trailer is 4 bits, which pushes packet data
|
||||||
// out of byte-alignment.
|
// out of byte-alignment.b
|
||||||
//
|
//
|
||||||
// The following code reads un-byte-aligned packet data.
|
// The following code reads un-byte-aligned packet data.
|
||||||
//
|
//
|
||||||
|
|
|
@ -0,0 +1,441 @@
|
||||||
|
/*
|
||||||
|
ESP8266 Simple Service Discovery
|
||||||
|
Copyright (c) 2015 Hristo Gochkov
|
||||||
|
|
||||||
|
Original (Arduino) version by Filippo Sallemi, July 23, 2014.
|
||||||
|
Can be found at: https://github.com/nomadnt/uSSDP
|
||||||
|
|
||||||
|
License (MIT license):
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#define LWIP_OPEN_SRC
|
||||||
|
#include <functional>
|
||||||
|
#include "New_ESP8266SSDP.h"
|
||||||
|
#include "WiFiUdp.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "osapi.h"
|
||||||
|
#include "ets_sys.h"
|
||||||
|
#include "user_interface.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/udp.h"
|
||||||
|
#include "lwip/inet.h"
|
||||||
|
#include "lwip/igmp.h"
|
||||||
|
#include "lwip/mem.h"
|
||||||
|
#include "include/UdpContext.h"
|
||||||
|
|
||||||
|
// #define DEBUG_SSDP Serial
|
||||||
|
|
||||||
|
#define SSDP_INTERVAL 1200
|
||||||
|
#define SSDP_PORT 1900
|
||||||
|
#define SSDP_METHOD_SIZE 10
|
||||||
|
#define SSDP_URI_SIZE 2
|
||||||
|
#define SSDP_BUFFER_SIZE 64
|
||||||
|
#define SSDP_MULTICAST_TTL 2
|
||||||
|
static const IPAddress SSDP_MULTICAST_ADDR(239, 255, 255, 250);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const char _ssdp_response_template[] PROGMEM =
|
||||||
|
"HTTP/1.1 200 OK\r\n"
|
||||||
|
"EXT:\r\n";
|
||||||
|
|
||||||
|
static const char _ssdp_notify_template[] PROGMEM =
|
||||||
|
"NOTIFY * HTTP/1.1\r\n"
|
||||||
|
"HOST: 239.255.255.250:1900\r\n"
|
||||||
|
"NTS: ssdp:alive\r\n";
|
||||||
|
|
||||||
|
static const char _ssdp_packet_template[] PROGMEM =
|
||||||
|
"%s" // _ssdp_response_template / _ssdp_notify_template
|
||||||
|
"CACHE-CONTROL: max-age=%u\r\n" // SSDP_INTERVAL
|
||||||
|
"SERVER: Arduino/1.0 UPNP/1.1 %s/%s\r\n" // _modelName, _modelNumber
|
||||||
|
"USN: uuid:%s\r\n" // _uuid
|
||||||
|
"%s: %s\r\n" // "NT" or "ST", _deviceType
|
||||||
|
"LOCATION: http://%u.%u.%u.%u:%u/%s\r\n" // WiFi.localIP(), _port, _schemaURL
|
||||||
|
"\r\n";
|
||||||
|
|
||||||
|
static const char _ssdp_schema_template[] PROGMEM =
|
||||||
|
"HTTP/1.1 200 OK\r\n"
|
||||||
|
"Content-Type: text/xml\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"Access-Control-Allow-Origin: *\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"<?xml version=\"1.0\"?>"
|
||||||
|
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
|
||||||
|
"<specVersion>"
|
||||||
|
"<major>1</major>"
|
||||||
|
"<minor>0</minor>"
|
||||||
|
"</specVersion>"
|
||||||
|
"<URLBase>http://%u.%u.%u.%u:%u/</URLBase>" // WiFi.localIP(), _port
|
||||||
|
"<device>"
|
||||||
|
"<deviceType>%s</deviceType>"
|
||||||
|
"<friendlyName>%s</friendlyName>"
|
||||||
|
"<presentationURL>%s</presentationURL>"
|
||||||
|
"<serialNumber>%s</serialNumber>"
|
||||||
|
"<modelName>%s</modelName>"
|
||||||
|
"<modelNumber>%s</modelNumber>"
|
||||||
|
"<modelURL>%s</modelURL>"
|
||||||
|
"<manufacturer>%s</manufacturer>"
|
||||||
|
"<manufacturerURL>%s</manufacturerURL>"
|
||||||
|
"<UDN>uuid:%s</UDN>"
|
||||||
|
"</device>"
|
||||||
|
// "<iconList>"
|
||||||
|
// "<icon>"
|
||||||
|
// "<mimetype>image/png</mimetype>"
|
||||||
|
// "<height>48</height>"
|
||||||
|
// "<width>48</width>"
|
||||||
|
// "<depth>24</depth>"
|
||||||
|
// "<url>icon48.png</url>"
|
||||||
|
// "</icon>"
|
||||||
|
// "<icon>"
|
||||||
|
// "<mimetype>image/png</mimetype>"
|
||||||
|
// "<height>120</height>"
|
||||||
|
// "<width>120</width>"
|
||||||
|
// "<depth>24</depth>"
|
||||||
|
// "<url>icon120.png</url>"
|
||||||
|
// "</icon>"
|
||||||
|
// "</iconList>"
|
||||||
|
"</root>\r\n"
|
||||||
|
"\r\n";
|
||||||
|
|
||||||
|
|
||||||
|
struct SSDPTimer {
|
||||||
|
ETSTimer timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
SSDPClass::SSDPClass() :
|
||||||
|
_server(0),
|
||||||
|
_timer(new SSDPTimer),
|
||||||
|
_port(80),
|
||||||
|
_ttl(SSDP_MULTICAST_TTL),
|
||||||
|
_respondToPort(0),
|
||||||
|
_pending(false),
|
||||||
|
_delay(0),
|
||||||
|
_process_time(0),
|
||||||
|
_notify_time(0)
|
||||||
|
{
|
||||||
|
_uuid[0] = '\0';
|
||||||
|
_modelNumber[0] = '\0';
|
||||||
|
sprintf(_deviceType, "urn:schemas-upnp-org:device:Basic:1");
|
||||||
|
_friendlyName[0] = '\0';
|
||||||
|
_presentationURL[0] = '\0';
|
||||||
|
_serialNumber[0] = '\0';
|
||||||
|
_modelName[0] = '\0';
|
||||||
|
_modelURL[0] = '\0';
|
||||||
|
_manufacturer[0] = '\0';
|
||||||
|
_manufacturerURL[0] = '\0';
|
||||||
|
sprintf(_schemaURL, "ssdp/schema.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
SSDPClass::~SSDPClass(){
|
||||||
|
delete _timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SSDPClass::begin(){
|
||||||
|
_pending = false;
|
||||||
|
|
||||||
|
uint32_t chipId = ESP.getChipId();
|
||||||
|
sprintf(_uuid, "38323636-4558-4dda-9188-cda0e6%02x%02x%02x",
|
||||||
|
(uint16_t) ((chipId >> 16) & 0xff),
|
||||||
|
(uint16_t) ((chipId >> 8) & 0xff),
|
||||||
|
(uint16_t) chipId & 0xff );
|
||||||
|
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.printf("SSDP UUID: %s\n", (char *)_uuid);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (_server) {
|
||||||
|
_server->unref();
|
||||||
|
_server = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_server = new UdpContext;
|
||||||
|
_server->ref();
|
||||||
|
|
||||||
|
ip_addr_t ifaddr;
|
||||||
|
ifaddr.addr = WiFi.localIP();
|
||||||
|
ip_addr_t multicast_addr;
|
||||||
|
multicast_addr.addr = (uint32_t) SSDP_MULTICAST_ADDR;
|
||||||
|
if (igmp_joingroup(&ifaddr, &multicast_addr) != ERR_OK ) {
|
||||||
|
DEBUGV("SSDP failed to join igmp group");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_server->listen(*IP_ADDR_ANY, SSDP_PORT)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_server->setMulticastInterface(ifaddr);
|
||||||
|
_server->setMulticastTTL(_ttl);
|
||||||
|
_server->onRx(std::bind(&SSDPClass::_update, this));
|
||||||
|
if (!_server->connect(multicast_addr, SSDP_PORT)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_startTimer();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::_send(ssdp_method_t method){
|
||||||
|
char buffer[1460];
|
||||||
|
uint32_t ip = WiFi.localIP();
|
||||||
|
|
||||||
|
char valueBuffer[strlen(_ssdp_notify_template)+1];
|
||||||
|
strcpy_P(valueBuffer, (method == NONE)?_ssdp_response_template:_ssdp_notify_template);
|
||||||
|
|
||||||
|
int len = snprintf_P(buffer, sizeof(buffer),
|
||||||
|
_ssdp_packet_template,
|
||||||
|
valueBuffer,
|
||||||
|
SSDP_INTERVAL,
|
||||||
|
_modelName, _modelNumber,
|
||||||
|
_uuid,
|
||||||
|
(method == NONE)?"ST":"NT",
|
||||||
|
_deviceType,
|
||||||
|
IP2STR(&ip), _port, _schemaURL
|
||||||
|
);
|
||||||
|
|
||||||
|
_server->append(buffer, len);
|
||||||
|
|
||||||
|
ip_addr_t remoteAddr;
|
||||||
|
uint16_t remotePort;
|
||||||
|
if(method == NONE) {
|
||||||
|
remoteAddr.addr = _respondToAddr;
|
||||||
|
remotePort = _respondToPort;
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.print("Sending Response to ");
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
remoteAddr.addr = SSDP_MULTICAST_ADDR;
|
||||||
|
remotePort = SSDP_PORT;
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.println("Sending Notify to ");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.print(IPAddress(remoteAddr.addr));
|
||||||
|
DEBUG_SSDP.print(":");
|
||||||
|
DEBUG_SSDP.println(remotePort);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_server->send(&remoteAddr, remotePort);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::schema(WiFiClient client){
|
||||||
|
uint32_t ip = WiFi.localIP();
|
||||||
|
char buffer[strlen(_ssdp_schema_template)+1];
|
||||||
|
strcpy_P(buffer, _ssdp_schema_template);
|
||||||
|
client.printf(buffer,
|
||||||
|
IP2STR(&ip), _port,
|
||||||
|
_deviceType,
|
||||||
|
_friendlyName,
|
||||||
|
_presentationURL,
|
||||||
|
_serialNumber,
|
||||||
|
_modelName,
|
||||||
|
_modelNumber,
|
||||||
|
_modelURL,
|
||||||
|
_manufacturer,
|
||||||
|
_manufacturerURL,
|
||||||
|
_uuid
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::_update(){
|
||||||
|
if(!_pending && _server->next()) {
|
||||||
|
ssdp_method_t method = NONE;
|
||||||
|
|
||||||
|
_respondToAddr = _server->getRemoteAddress();
|
||||||
|
_respondToPort = _server->getRemotePort();
|
||||||
|
|
||||||
|
typedef enum {METHOD, URI, PROTO, KEY, VALUE, ABORT} states;
|
||||||
|
states state = METHOD;
|
||||||
|
|
||||||
|
typedef enum {START, MAN, ST, MX} headers;
|
||||||
|
headers header = START;
|
||||||
|
|
||||||
|
uint8_t cursor = 0;
|
||||||
|
uint8_t cr = 0;
|
||||||
|
|
||||||
|
char buffer[SSDP_BUFFER_SIZE] = {0};
|
||||||
|
|
||||||
|
while(_server->getSize() > 0){
|
||||||
|
char c = _server->read();
|
||||||
|
|
||||||
|
(c == '\r' || c == '\n') ? cr++ : cr = 0;
|
||||||
|
|
||||||
|
switch(state){
|
||||||
|
case METHOD:
|
||||||
|
if(c == ' '){
|
||||||
|
if(strcmp(buffer, "M-SEARCH") == 0) method = SEARCH;
|
||||||
|
else if(strcmp(buffer, "NOTIFY") == 0) method = NOTIFY;
|
||||||
|
|
||||||
|
if(method == NONE) state = ABORT;
|
||||||
|
else state = URI;
|
||||||
|
cursor = 0;
|
||||||
|
|
||||||
|
} else if(cursor < SSDP_METHOD_SIZE - 1){ buffer[cursor++] = c; buffer[cursor] = '\0'; }
|
||||||
|
break;
|
||||||
|
case URI:
|
||||||
|
if(c == ' '){
|
||||||
|
if(strcmp(buffer, "*")) state = ABORT;
|
||||||
|
else state = PROTO;
|
||||||
|
cursor = 0;
|
||||||
|
} else if(cursor < SSDP_URI_SIZE - 1){ buffer[cursor++] = c; buffer[cursor] = '\0'; }
|
||||||
|
break;
|
||||||
|
case PROTO:
|
||||||
|
if(cr == 2){ state = KEY; cursor = 0; }
|
||||||
|
break;
|
||||||
|
case KEY:
|
||||||
|
if(cr == 4){ _pending = true; _process_time = millis(); }
|
||||||
|
else if(c == ' '){ cursor = 0; state = VALUE; }
|
||||||
|
else if(c != '\r' && c != '\n' && c != ':' && cursor < SSDP_BUFFER_SIZE - 1){ buffer[cursor++] = c; buffer[cursor] = '\0'; }
|
||||||
|
break;
|
||||||
|
case VALUE:
|
||||||
|
if(cr == 2){
|
||||||
|
switch(header){
|
||||||
|
case START:
|
||||||
|
break;
|
||||||
|
case MAN:
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.printf("MAN: %s\n", (char *)buffer);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case ST:
|
||||||
|
if(strcmp(buffer, "ssdp:all")){
|
||||||
|
state = ABORT;
|
||||||
|
#ifdef DEBUG_SSDP
|
||||||
|
DEBUG_SSDP.printf("REJECT: %s\n", (char *)buffer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// if the search type matches our type, we should respond instead of ABORT
|
||||||
|
if(strcmp(buffer, _deviceType) == 0){
|
||||||
|
_pending = true;
|
||||||
|
_process_time = millis();
|
||||||
|
state = KEY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MX:
|
||||||
|
_delay = random(0, atoi(buffer)) * 1000L;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state != ABORT){ state = KEY; header = START; cursor = 0; }
|
||||||
|
} else if(c != '\r' && c != '\n'){
|
||||||
|
if(header == START){
|
||||||
|
if(strncmp(buffer, "MA", 2) == 0) header = MAN;
|
||||||
|
else if(strcmp(buffer, "ST") == 0) header = ST;
|
||||||
|
else if(strcmp(buffer, "MX") == 0) header = MX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cursor < SSDP_BUFFER_SIZE - 1){ buffer[cursor++] = c; buffer[cursor] = '\0'; }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ABORT:
|
||||||
|
_pending = false; _delay = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_pending && (millis() - _process_time) > _delay){
|
||||||
|
_pending = false; _delay = 0;
|
||||||
|
_send(NONE);
|
||||||
|
} else if(_notify_time == 0 || (millis() - _notify_time) > (SSDP_INTERVAL * 1000L)){
|
||||||
|
_notify_time = millis();
|
||||||
|
_send(NOTIFY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pending) {
|
||||||
|
while (_server->next())
|
||||||
|
_server->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setSchemaURL(const char *url){
|
||||||
|
strlcpy(_schemaURL, url, sizeof(_schemaURL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setHTTPPort(uint16_t port){
|
||||||
|
_port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setDeviceType(const char *deviceType){
|
||||||
|
strlcpy(_deviceType, deviceType, sizeof(_deviceType));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setName(const char *name){
|
||||||
|
strlcpy(_friendlyName, name, sizeof(_friendlyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setURL(const char *url){
|
||||||
|
strlcpy(_presentationURL, url, sizeof(_presentationURL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setSerialNumber(const char *serialNumber){
|
||||||
|
strlcpy(_serialNumber, serialNumber, sizeof(_serialNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setSerialNumber(const uint32_t serialNumber){
|
||||||
|
snprintf(_serialNumber, sizeof(uint32_t)*2+1, "%08X", serialNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setModelName(const char *name){
|
||||||
|
strlcpy(_modelName, name, sizeof(_modelName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setModelNumber(const char *num){
|
||||||
|
strlcpy(_modelNumber, num, sizeof(_modelNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setModelURL(const char *url){
|
||||||
|
strlcpy(_modelURL, url, sizeof(_modelURL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setManufacturer(const char *name){
|
||||||
|
strlcpy(_manufacturer, name, sizeof(_manufacturer));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setManufacturerURL(const char *url){
|
||||||
|
strlcpy(_manufacturerURL, url, sizeof(_manufacturerURL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::setTTL(const uint8_t ttl){
|
||||||
|
_ttl = ttl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::_onTimerStatic(SSDPClass* self) {
|
||||||
|
self->_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSDPClass::_startTimer() {
|
||||||
|
ETSTimer* tm = &(_timer->timer);
|
||||||
|
const int interval = 1000;
|
||||||
|
os_timer_disarm(tm);
|
||||||
|
os_timer_setfn(tm, reinterpret_cast<ETSTimerFunc*>(&SSDPClass::_onTimerStatic), reinterpret_cast<void*>(this));
|
||||||
|
os_timer_arm(tm, interval, 1 /* repeat */);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SSDP)
|
||||||
|
SSDPClass SSDP;
|
||||||
|
#endif
|
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
ESP8266 Simple Service Discovery
|
||||||
|
Copyright (c) 2015 Hristo Gochkov
|
||||||
|
|
||||||
|
Original (Arduino) version by Filippo Sallemi, July 23, 2014.
|
||||||
|
Can be found at: https://github.com/nomadnt/uSSDP
|
||||||
|
|
||||||
|
License (MIT license):
|
||||||
|
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 ESP8266SSDP_H
|
||||||
|
#define ESP8266SSDP_H
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
|
||||||
|
class UdpContext;
|
||||||
|
|
||||||
|
#define SSDP_UUID_SIZE 37
|
||||||
|
#define SSDP_SCHEMA_URL_SIZE 64
|
||||||
|
#define SSDP_DEVICE_TYPE_SIZE 64
|
||||||
|
#define SSDP_FRIENDLY_NAME_SIZE 64
|
||||||
|
#define SSDP_SERIAL_NUMBER_SIZE 32
|
||||||
|
#define SSDP_PRESENTATION_URL_SIZE 128
|
||||||
|
#define SSDP_MODEL_NAME_SIZE 64
|
||||||
|
#define SSDP_MODEL_URL_SIZE 128
|
||||||
|
#define SSDP_MODEL_VERSION_SIZE 32
|
||||||
|
#define SSDP_MANUFACTURER_SIZE 64
|
||||||
|
#define SSDP_MANUFACTURER_URL_SIZE 128
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NONE,
|
||||||
|
SEARCH,
|
||||||
|
NOTIFY
|
||||||
|
} ssdp_method_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct SSDPTimer;
|
||||||
|
|
||||||
|
class SSDPClass{
|
||||||
|
public:
|
||||||
|
SSDPClass();
|
||||||
|
~SSDPClass();
|
||||||
|
|
||||||
|
bool begin();
|
||||||
|
|
||||||
|
void schema(WiFiClient client);
|
||||||
|
|
||||||
|
void setDeviceType(const String& deviceType) { setDeviceType(deviceType.c_str()); }
|
||||||
|
void setDeviceType(const char *deviceType);
|
||||||
|
void setName(const String& name) { setName(name.c_str()); }
|
||||||
|
void setName(const char *name);
|
||||||
|
void setURL(const String& url) { setURL(url.c_str()); }
|
||||||
|
void setURL(const char *url);
|
||||||
|
void setSchemaURL(const String& url) { setSchemaURL(url.c_str()); }
|
||||||
|
void setSchemaURL(const char *url);
|
||||||
|
void setSerialNumber(const String& serialNumber) { setSerialNumber(serialNumber.c_str()); }
|
||||||
|
void setSerialNumber(const char *serialNumber);
|
||||||
|
void setSerialNumber(const uint32_t serialNumber);
|
||||||
|
void setModelName(const String& name) { setModelName(name.c_str()); }
|
||||||
|
void setModelName(const char *name);
|
||||||
|
void setModelNumber(const String& num) { setModelNumber(num.c_str()); }
|
||||||
|
void setModelNumber(const char *num);
|
||||||
|
void setModelURL(const String& url) { setModelURL(url.c_str()); }
|
||||||
|
void setModelURL(const char *url);
|
||||||
|
void setManufacturer(const String& name) { setManufacturer(name.c_str()); }
|
||||||
|
void setManufacturer(const char *name);
|
||||||
|
void setManufacturerURL(const String& url) { setManufacturerURL(url.c_str()); }
|
||||||
|
void setManufacturerURL(const char *url);
|
||||||
|
void setHTTPPort(uint16_t port);
|
||||||
|
void setTTL(uint8_t ttl);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _send(ssdp_method_t method);
|
||||||
|
void _update();
|
||||||
|
void _startTimer();
|
||||||
|
static void _onTimerStatic(SSDPClass* self);
|
||||||
|
|
||||||
|
UdpContext* _server;
|
||||||
|
SSDPTimer* _timer;
|
||||||
|
uint16_t _port;
|
||||||
|
uint8_t _ttl;
|
||||||
|
|
||||||
|
IPAddress _respondToAddr;
|
||||||
|
uint16_t _respondToPort;
|
||||||
|
|
||||||
|
bool _pending;
|
||||||
|
unsigned short _delay;
|
||||||
|
unsigned long _process_time;
|
||||||
|
unsigned long _notify_time;
|
||||||
|
|
||||||
|
char _schemaURL[SSDP_SCHEMA_URL_SIZE];
|
||||||
|
char _uuid[SSDP_UUID_SIZE];
|
||||||
|
char _deviceType[SSDP_DEVICE_TYPE_SIZE];
|
||||||
|
char _friendlyName[SSDP_FRIENDLY_NAME_SIZE];
|
||||||
|
char _serialNumber[SSDP_SERIAL_NUMBER_SIZE];
|
||||||
|
char _presentationURL[SSDP_PRESENTATION_URL_SIZE];
|
||||||
|
char _manufacturer[SSDP_MANUFACTURER_SIZE];
|
||||||
|
char _manufacturerURL[SSDP_MANUFACTURER_URL_SIZE];
|
||||||
|
char _modelName[SSDP_MODEL_NAME_SIZE];
|
||||||
|
char _modelURL[SSDP_MODEL_URL_SIZE];
|
||||||
|
char _modelNumber[SSDP_MODEL_VERSION_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SSDP)
|
||||||
|
extern SSDPClass SSDP;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,7 +1,12 @@
|
||||||
#include <AboutHelper.h>
|
#include <AboutHelper.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <Settings.h>
|
#include <Settings.h>
|
||||||
#include <ETH.h>
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#elif ESP32
|
||||||
|
#include <WiFi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
String AboutHelper::generateAboutString(bool abbreviated) {
|
String AboutHelper::generateAboutString(bool abbreviated) {
|
||||||
DynamicJsonDocument buffer(1024);
|
DynamicJsonDocument buffer(1024);
|
||||||
|
@ -17,12 +22,20 @@ String AboutHelper::generateAboutString(bool abbreviated) {
|
||||||
void AboutHelper::generateAboutObject(JsonDocument& obj, bool abbreviated) {
|
void AboutHelper::generateAboutObject(JsonDocument& obj, bool abbreviated) {
|
||||||
obj["firmware"] = QUOTE(FIRMWARE_NAME);
|
obj["firmware"] = QUOTE(FIRMWARE_NAME);
|
||||||
obj["version"] = QUOTE(MILIGHT_HUB_VERSION);
|
obj["version"] = QUOTE(MILIGHT_HUB_VERSION);
|
||||||
obj["ip_address"] = ETH.localIP().toString();
|
obj["ip_address"] = WiFi.localIP().toString();
|
||||||
//obj["reset_reason"] = ESP.getResetReason();
|
#ifdef ESP8266
|
||||||
|
obj["reset_reason"] = ESP.getResetReason();
|
||||||
|
#elif ESP32
|
||||||
|
// TODO get reset reason
|
||||||
|
#endif
|
||||||
|
|
||||||
if (! abbreviated) {
|
if (! abbreviated) {
|
||||||
obj["variant"] = QUOTE(FIRMWARE_VARIANT);
|
obj["variant"] = QUOTE(FIRMWARE_VARIANT);
|
||||||
obj["free_heap"] = ESP.getFreeHeap();
|
obj["free_heap"] = ESP.getFreeHeap();
|
||||||
//obj["arduino_version"] = ESP.getCoreVersion();
|
#ifdef ESP8266
|
||||||
|
obj["arduino_version"] = ESP.getCoreVersion();
|
||||||
|
#elif ESP32
|
||||||
|
obj["arduino_version"] = ESP.getSdkVersion();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,14 @@
|
||||||
#include <Settings.h>
|
#include <Settings.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include <SPIFFS.h>
|
|
||||||
#include <IntParsing.h>
|
#include <IntParsing.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <JsonHelpers.h>
|
#include <JsonHelpers.h>
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
#include <SPIFFS.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PORT_POSITION(s) ( s.indexOf(':') )
|
#define PORT_POSITION(s) ( s.indexOf(':') )
|
||||||
|
|
||||||
GatewayConfig::GatewayConfig(uint16_t deviceId, uint16_t port, uint8_t protocolVersion)
|
GatewayConfig::GatewayConfig(uint16_t deviceId, uint16_t port, uint8_t protocolVersion)
|
||||||
|
@ -209,6 +212,7 @@ void Settings::dumpGroupIdAliases(JsonObject json) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::load(Settings& settings) {
|
void Settings::load(Settings& settings) {
|
||||||
|
|
||||||
if (SPIFFS.exists(SETTINGS_FILE)) {
|
if (SPIFFS.exists(SETTINGS_FILE)) {
|
||||||
// Clear in-memory settings
|
// Clear in-memory settings
|
||||||
settings = Settings();
|
settings = Settings();
|
||||||
|
|
|
@ -50,9 +50,9 @@
|
||||||
|
|
||||||
#define WEB_INDEX_FILENAME "/web/index.html"
|
#define WEB_INDEX_FILENAME "/web/index.html"
|
||||||
|
|
||||||
#define MILIGHT_GITHUB_USER "sidoh"
|
//#define MILIGHT_GITHUB_USER "sidoh"
|
||||||
#define MILIGHT_GITHUB_REPO "esp8266_milight_hub"
|
//#define MILIGHT_GITHUB_REPO "esp8266_milight_hub"
|
||||||
#define MILIGHT_REPO_WEB_PATH "/data/web/index.html"
|
//#define MILIGHT_REPO_WEB_PATH "/data/web/index.html"
|
||||||
|
|
||||||
#define MINIMUM_RESTART_PERIOD 1
|
#define MINIMUM_RESTART_PERIOD 1
|
||||||
#define DEFAULT_MQTT_PORT 1883
|
#define DEFAULT_MQTT_PORT 1883
|
||||||
|
@ -113,7 +113,7 @@ public:
|
||||||
ledModeOperating(LEDStatus::LEDMode::SlowBlip),
|
ledModeOperating(LEDStatus::LEDMode::SlowBlip),
|
||||||
ledModePacket(LEDStatus::LEDMode::Flicker),
|
ledModePacket(LEDStatus::LEDMode::Flicker),
|
||||||
ledModePacketCount(3),
|
ledModePacketCount(3),
|
||||||
hostname("milight-hub"),
|
hostname("esp32-milight-hub"),
|
||||||
rf24PowerLevel(RF24PowerLevelHelpers::defaultValue()),
|
rf24PowerLevel(RF24PowerLevelHelpers::defaultValue()),
|
||||||
rf24Channels(RF24ChannelHelpers::allValues()),
|
rf24Channels(RF24ChannelHelpers::allValues()),
|
||||||
groupStateFields(DEFAULT_GROUP_STATE_FIELDS),
|
groupStateFields(DEFAULT_GROUP_STATE_FIELDS),
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
#include <MiLightDiscoveryServer.h>
|
#include <MiLightDiscoveryServer.h>
|
||||||
#include <Size.h>
|
#include <Size.h>
|
||||||
#include <ETH.h>
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#elif ESP32
|
||||||
|
#include <WiFi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
const char V3_SEARCH_STRING[] = "Link_Wi-Fi";
|
const char V3_SEARCH_STRING[] = "Link_Wi-Fi";
|
||||||
const char V6_SEARCH_STRING[] = "HF-A11ASSISTHREAD";
|
const char V6_SEARCH_STRING[] = "HF-A11ASSISTHREAD";
|
||||||
|
@ -85,6 +90,10 @@ void MiLightDiscoveryServer::sendResponse(char* buffer) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
socket.beginPacket(socket.remoteIP(), socket.remotePort());
|
socket.beginPacket(socket.remoteIP(), socket.remotePort());
|
||||||
socket.write(int(buffer));
|
#ifdef ESP8266
|
||||||
|
socket.write(buffer);
|
||||||
|
#elif ESP32
|
||||||
|
socket.write(*buffer);
|
||||||
|
#endif
|
||||||
socket.endPacket();
|
socket.endPacket();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
#include <MiLightUdpServer.h>
|
#include <MiLightUdpServer.h>
|
||||||
#include <V5MiLightUdpServer.h>
|
#include <V5MiLightUdpServer.h>
|
||||||
#include <V6MiLightUdpServer.h>
|
#include <V6MiLightUdpServer.h>
|
||||||
#include <ETH.h>
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#elif ESP32
|
||||||
|
#include <WiFi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
MiLightUdpServer::MiLightUdpServer(MiLightClient*& client, uint16_t port, uint16_t deviceId)
|
MiLightUdpServer::MiLightUdpServer(MiLightClient*& client, uint16_t port, uint16_t deviceId)
|
||||||
: client(client),
|
: client(client),
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
#include <V6MiLightUdpServer.h>
|
#include <V6MiLightUdpServer.h>
|
||||||
#include <ETH.h>
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <Size.h>
|
#include <Size.h>
|
||||||
#include <V6CommandHandler.h>
|
#include <V6CommandHandler.h>
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#elif ESP32
|
||||||
|
#include <WiFi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MATCHES_PACKET(packet1) ( \
|
#define MATCHES_PACKET(packet1) ( \
|
||||||
matchesPacket(packet1, size(packet1), packet, packetSize) \
|
matchesPacket(packet1, size(packet1), packet, packetSize) \
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include <SPIFFS.h>
|
|
||||||
#include <Update.h>
|
|
||||||
#include <WiFiUdp.h>
|
#include <WiFiUdp.h>
|
||||||
#include <IntParsing.h>
|
#include <IntParsing.h>
|
||||||
#include <Settings.h>
|
#include <Settings.h>
|
||||||
|
@ -11,6 +9,10 @@
|
||||||
#include <AboutHelper.h>
|
#include <AboutHelper.h>
|
||||||
#include <index.html.gz.h>
|
#include <index.html.gz.h>
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
#include <SPIFFS.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
void MiLightHttpServer::begin() {
|
void MiLightHttpServer::begin() {
|
||||||
|
@ -103,7 +105,7 @@ WiFiClient MiLightHttpServer::client() {
|
||||||
return server.client();
|
return server.client();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiLightHttpServer::on(const char* path, HTTPMethod method, WebServer::THandlerFunction handler) {
|
void MiLightHttpServer::on(const char* path, HTTPMethod method, THandlerFunction handler) {
|
||||||
server.on(path, method, handler);
|
server.on(path, method, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +129,11 @@ void MiLightHttpServer::handleSystemPost(RequestContext& request) {
|
||||||
server.send_P(200, TEXT_PLAIN, PSTR("true"));
|
server.send_P(200, TEXT_PLAIN, PSTR("true"));
|
||||||
|
|
||||||
delay(100);
|
delay(100);
|
||||||
//ESP.eraseConfig();
|
#ifdef ESP8266
|
||||||
|
ESP.eraseConfig();
|
||||||
|
#elif ESP32
|
||||||
|
// TODO erase config
|
||||||
|
#endif
|
||||||
delay(100);
|
delay(100);
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
|
|
||||||
|
@ -227,6 +233,7 @@ void MiLightHttpServer::handleUpdateSettingsPost(RequestContext& request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiLightHttpServer::handleFirmwarePost() {
|
void MiLightHttpServer::handleFirmwarePost() {
|
||||||
|
#ifdef ESP8266
|
||||||
server.sendHeader("Connection", "close");
|
server.sendHeader("Connection", "close");
|
||||||
server.sendHeader("Access-Control-Allow-Origin", "*");
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
|
||||||
|
@ -247,12 +254,16 @@ void MiLightHttpServer::handleFirmwarePost() {
|
||||||
delay(1000);
|
delay(1000);
|
||||||
|
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
|
#elif ESP32
|
||||||
|
// TODO implement firmware post
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiLightHttpServer::handleFirmwareUpload() {
|
void MiLightHttpServer::handleFirmwareUpload() {
|
||||||
|
#ifdef ESP8266
|
||||||
HTTPUpload& upload = server.upload();
|
HTTPUpload& upload = server.upload();
|
||||||
if(upload.status == UPLOAD_FILE_START){
|
if(upload.status == UPLOAD_FILE_START){
|
||||||
//WiFiUDP::stopAll();
|
WiFiUDP::stopAll();
|
||||||
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
|
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
|
||||||
if(!Update.begin(maxSketchSpace)){//start with max available size
|
if(!Update.begin(maxSketchSpace)){//start with max available size
|
||||||
Update.printError(Serial);
|
Update.printError(Serial);
|
||||||
|
@ -268,6 +279,9 @@ void MiLightHttpServer::handleFirmwareUpload() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yield();
|
yield();
|
||||||
|
#elif ESP32
|
||||||
|
// TODO implement firmware upload
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -449,7 +463,7 @@ void MiLightHttpServer::handleUpdateGroupAlias(RequestContext& request) {
|
||||||
|
|
||||||
if (config == NULL) {
|
if (config == NULL) {
|
||||||
char buffer[40];
|
char buffer[40];
|
||||||
sprintf_P(buffer, PSTR("Unknown device type: %u"), bulbId.deviceType);
|
sprintf_P(buffer, PSTR("Unknown device type: %s"), bulbId.deviceType);
|
||||||
request.response.setCode(400);
|
request.response.setCode(400);
|
||||||
request.response.json["error"] = buffer;
|
request.response.json["error"] = buffer;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
typedef std::function<void(void)> SettingsSavedHandler;
|
typedef std::function<void(void)> SettingsSavedHandler;
|
||||||
typedef std::function<void(const BulbId& id)> GroupDeletedHandler;
|
typedef std::function<void(const BulbId& id)> GroupDeletedHandler;
|
||||||
|
typedef std::function<void(void)> THandlerFunction;
|
||||||
|
|
||||||
using RichHttpConfig = RichHttp::Generics::Configs::EspressifBuiltin;
|
using RichHttpConfig = RichHttp::Generics::Configs::EspressifBuiltin;
|
||||||
using RequestContext = RichHttpConfig::RequestContextType;
|
using RequestContext = RichHttpConfig::RequestContextType;
|
||||||
|
@ -47,7 +48,7 @@ public:
|
||||||
void handleClient();
|
void handleClient();
|
||||||
void onSettingsSaved(SettingsSavedHandler handler);
|
void onSettingsSaved(SettingsSavedHandler handler);
|
||||||
void onGroupDeleted(GroupDeletedHandler handler);
|
void onGroupDeleted(GroupDeletedHandler handler);
|
||||||
void on(const char* path, HTTPMethod method, WebServer::THandlerFunction handler);
|
void on(const char* path, HTTPMethod method, THandlerFunction handler);
|
||||||
void handlePacketSent(uint8_t* packet, const MiLightRemoteConfig& config);
|
void handlePacketSent(uint8_t* packet, const MiLightRemoteConfig& config);
|
||||||
WiFiClient client();
|
WiFiClient client();
|
||||||
|
|
||||||
|
@ -101,7 +102,7 @@ protected:
|
||||||
GroupStateStore*& stateStore;
|
GroupStateStore*& stateStore;
|
||||||
SettingsSavedHandler settingsSavedHandler;
|
SettingsSavedHandler settingsSavedHandler;
|
||||||
GroupDeletedHandler groupDeletedHandler;
|
GroupDeletedHandler groupDeletedHandler;
|
||||||
WebServer::THandlerFunction _handleRootPage;
|
THandlerFunction _handleRootPage;
|
||||||
PacketSender*& packetSender;
|
PacketSender*& packetSender;
|
||||||
RadioSwitchboard*& radios;
|
RadioSwitchboard*& radios;
|
||||||
TransitionController& transitions;
|
TransitionController& transitions;
|
||||||
|
|
|
@ -10,17 +10,16 @@
|
||||||
|
|
||||||
[common]
|
[common]
|
||||||
framework = arduino
|
framework = arduino
|
||||||
platform = espressif8266@~1.8
|
|
||||||
board_f_cpu = 160000000L
|
board_f_cpu = 160000000L
|
||||||
lib_deps_builtin =
|
lib_deps_builtin =
|
||||||
|
SPI
|
||||||
lib_deps_external =
|
lib_deps_external =
|
||||||
luc-github/ESP32SSDP@^1.1.1
|
|
||||||
RF24@~1.3.2
|
RF24@~1.3.2
|
||||||
ArduinoJson@~6.17.2
|
ArduinoJson@~6.10.1
|
||||||
PubSubClient@~2.8
|
PubSubClient@~2.7
|
||||||
https://github.com/ratkins/RGBConverter.git#07010f2
|
https://github.com/ratkins/RGBConverter.git#07010f2605d9f787c6c55e62df10fec14e5894e4
|
||||||
WebSockets@~2.3.3
|
WebSockets@~2.2.0
|
||||||
rlogiacco/CircularBuffer@~1.3.3
|
CircularBuffer@~1.2.0
|
||||||
PathVariableHandlers@~2.0.0
|
PathVariableHandlers@~2.0.0
|
||||||
RichHttpServer@~2.0.2
|
RichHttpServer@~2.0.2
|
||||||
extra_scripts =
|
extra_scripts =
|
||||||
|
@ -41,10 +40,12 @@ build_flags =
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
framework = ${common.framework}
|
framework = ${common.framework}
|
||||||
upload_speed = ${common.upload_speed}
|
upload_speed = ${common.upload_speed}
|
||||||
board = esp32-poe
|
|
||||||
build_flags = ${common.build_flags}
|
build_flags = ${common.build_flags}
|
||||||
extra_scripts = ${common.extra_scripts}
|
extra_scripts = ${common.extra_scripts}
|
||||||
|
test_ignore = ${common.test_ignore}
|
||||||
|
board = esp32-poe
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${common.lib_deps_builtin}
|
${common.lib_deps_builtin}
|
||||||
${common.lib_deps_external}
|
${common.lib_deps_external}
|
||||||
test_ignore = ${common.test_ignore}
|
https://github.com/tzapu/WiFiManager.git#2.0.3-alpha
|
||||||
|
monitor_speed = 115200
|
||||||
|
|
160
src/main.cpp
160
src/main.cpp
|
@ -1,13 +1,12 @@
|
||||||
#ifndef UNIT_TEST
|
#ifndef UNIT_TEST
|
||||||
|
#define DEBUG_PRINTF
|
||||||
|
#define DEBUG_SERIAL
|
||||||
|
|
||||||
#include <ETH.h>
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
//#include <WiFiManager.h>
|
#include <WiFiManager.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include "SPIFFS.h"
|
|
||||||
#include <WebServer.h>
|
|
||||||
#include <IntParsing.h>
|
#include <IntParsing.h>
|
||||||
#include <Size.h>
|
#include <Size.h>
|
||||||
#include <LinkedList.h>
|
#include <LinkedList.h>
|
||||||
|
@ -19,10 +18,6 @@
|
||||||
#include <MiLightRemoteType.h>
|
#include <MiLightRemoteType.h>
|
||||||
#include <Settings.h>
|
#include <Settings.h>
|
||||||
#include <MiLightUdpServer.h>
|
#include <MiLightUdpServer.h>
|
||||||
//#include <ESP8266SSDP.h>
|
|
||||||
#include "ESP32SSDP.h"
|
|
||||||
//#include <ESP8266mDNS.h>
|
|
||||||
#include "ESPmDNS.h"
|
|
||||||
#include <MqttClient.h>
|
#include <MqttClient.h>
|
||||||
#include <RGBConverter.h>
|
#include <RGBConverter.h>
|
||||||
#include <MiLightDiscoveryServer.h>
|
#include <MiLightDiscoveryServer.h>
|
||||||
|
@ -32,53 +27,24 @@
|
||||||
#include <PacketSender.h>
|
#include <PacketSender.h>
|
||||||
#include <HomeAssistantDiscoveryClient.h>
|
#include <HomeAssistantDiscoveryClient.h>
|
||||||
#include <TransitionController.h>
|
#include <TransitionController.h>
|
||||||
|
#include <ESPId.h>
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
#include <ESP8266mDNS.h>
|
||||||
|
#include <ESP8266SSDP.h>
|
||||||
|
#elif ESP32
|
||||||
|
#include <SPIFFS.h>
|
||||||
|
#include <ESPmDNS.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
//WiFiManager wifiManager;
|
WiFiManager wifiManager;
|
||||||
// because of callbacks, these need to be in the higher scope :(
|
// because of callbacks, these need to be in the higher scope :(
|
||||||
//WiFiManagerParameter* wifiStaticIP = NULL;
|
WiFiManagerParameter* wifiStaticIP = NULL;
|
||||||
//WiFiManagerParameter* wifiStaticIPNetmask = NULL;
|
WiFiManagerParameter* wifiStaticIPNetmask = NULL;
|
||||||
//WiFiManagerParameter* wifiStaticIPGateway = NULL;
|
WiFiManagerParameter* wifiStaticIPGateway = NULL;
|
||||||
|
|
||||||
static bool eth_connected = false;
|
|
||||||
void WiFiEvent(WiFiEvent_t event)
|
|
||||||
{
|
|
||||||
switch (event) {
|
|
||||||
case SYSTEM_EVENT_ETH_START:
|
|
||||||
Serial.println("ETH Started");
|
|
||||||
//set eth hostname here
|
|
||||||
ETH.setHostname("esp32-ethernet-milight-gateway");
|
|
||||||
break;
|
|
||||||
case SYSTEM_EVENT_ETH_CONNECTED:
|
|
||||||
Serial.println("ETH Connected");
|
|
||||||
break;
|
|
||||||
case SYSTEM_EVENT_ETH_GOT_IP:
|
|
||||||
Serial.print("ETH MAC: ");
|
|
||||||
Serial.print(ETH.macAddress());
|
|
||||||
Serial.print(", IPv4: ");
|
|
||||||
Serial.print(ETH.localIP());
|
|
||||||
if (ETH.fullDuplex()) {
|
|
||||||
Serial.print(", FULL_DUPLEX");
|
|
||||||
}
|
|
||||||
Serial.print(", ");
|
|
||||||
Serial.print(ETH.linkSpeed());
|
|
||||||
Serial.println("Mbps");
|
|
||||||
eth_connected = true;
|
|
||||||
break;
|
|
||||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
|
||||||
Serial.println("ETH Disconnected");
|
|
||||||
eth_connected = false;
|
|
||||||
break;
|
|
||||||
case SYSTEM_EVENT_ETH_STOP:
|
|
||||||
Serial.println("ETH Stopped");
|
|
||||||
eth_connected = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static LEDStatus *ledStatus;
|
static LEDStatus *ledStatus;
|
||||||
|
|
||||||
|
@ -310,6 +276,7 @@ void applySettings() {
|
||||||
if (settings.discoveryPort != 0) {
|
if (settings.discoveryPort != 0) {
|
||||||
discoveryServer = new MiLightDiscoveryServer(settings);
|
discoveryServer = new MiLightDiscoveryServer(settings);
|
||||||
discoveryServer->begin();
|
discoveryServer->begin();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update LED pin and operating mode
|
// update LED pin and operating mode
|
||||||
|
@ -317,24 +284,23 @@ void applySettings() {
|
||||||
ledStatus->changePin(settings.ledPin);
|
ledStatus->changePin(settings.ledPin);
|
||||||
ledStatus->continuous(settings.ledModeOperating);
|
ledStatus->continuous(settings.ledModeOperating);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
WiFi.hostname(settings.hostname);
|
|
||||||
|
|
||||||
WiFiPhyMode_t wifiMode;
|
// WiFi.hostname(settings.hostname);
|
||||||
switch (settings.wifiMode) {
|
|
||||||
case WifiMode::B:
|
// WiFiPhyMode_t wifiMode;
|
||||||
wifiMode = WIFI_PHY_MODE_11B;
|
// switch (settings.wifiMode) {
|
||||||
break;
|
// case WifiMode::B:
|
||||||
case WifiMode::G:
|
// wifiMode = WIFI_PHY_MODE_11B;
|
||||||
wifiMode = WIFI_PHY_MODE_11G;
|
// break;
|
||||||
break;
|
// case WifiMode::G:
|
||||||
default:
|
// wifiMode = WIFI_PHY_MODE_11G;
|
||||||
case WifiMode::N:
|
// break;
|
||||||
wifiMode = WIFI_PHY_MODE_11N;
|
// default:
|
||||||
break;
|
// case WifiMode::N:
|
||||||
}
|
// wifiMode = WIFI_PHY_MODE_11N;
|
||||||
WiFi.setPhyMode(wifiMode);
|
// break;
|
||||||
*/
|
// }
|
||||||
|
// WiFi.setPhyMode(wifiMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -352,14 +318,14 @@ bool shouldRestart() {
|
||||||
void handleLED() {
|
void handleLED() {
|
||||||
ledStatus->handle();
|
ledStatus->handle();
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
void wifiExtraSettingsChange() {
|
void wifiExtraSettingsChange() {
|
||||||
settings.wifiStaticIP = wifiStaticIP->getValue();
|
settings.wifiStaticIP = wifiStaticIP->getValue();
|
||||||
settings.wifiStaticIPNetmask = wifiStaticIPNetmask->getValue();
|
settings.wifiStaticIPNetmask = wifiStaticIPNetmask->getValue();
|
||||||
settings.wifiStaticIPGateway = wifiStaticIPGateway->getValue();
|
settings.wifiStaticIPGateway = wifiStaticIPGateway->getValue();
|
||||||
settings.save();
|
settings.save();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
// Called when a group is deleted via the REST API. Will publish an empty message to
|
// Called when a group is deleted via the REST API. Will publish an empty message to
|
||||||
// the MQTT topic to delete retained state
|
// the MQTT topic to delete retained state
|
||||||
void onGroupDeleted(const BulbId& id) {
|
void onGroupDeleted(const BulbId& id) {
|
||||||
|
@ -374,13 +340,23 @@ void onGroupDeleted(const BulbId& id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(38400);
|
Serial.begin(115200);
|
||||||
//String ssid = "ESP" + String(ESP.getChipId());
|
|
||||||
|
String ssid = "ESP" + String(getESPId());
|
||||||
|
|
||||||
// load up our persistent settings from the file system
|
// load up our persistent settings from the file system
|
||||||
|
#ifdef ESP8266
|
||||||
SPIFFS.begin();
|
SPIFFS.begin();
|
||||||
|
#elif ESP32
|
||||||
|
if(!SPIFFS.begin(true)){
|
||||||
|
Serial.println(F("Error while mounting SPIFFS"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Settings::load(settings);
|
Settings::load(settings);
|
||||||
|
#ifdef ESP8266
|
||||||
applySettings();
|
applySettings();
|
||||||
|
#endif
|
||||||
|
|
||||||
// set up the LED status for wifi configuration
|
// set up the LED status for wifi configuration
|
||||||
ledStatus = new LEDStatus(settings.ledPin);
|
ledStatus = new LEDStatus(settings.ledPin);
|
||||||
|
@ -395,11 +371,15 @@ void setup() {
|
||||||
// allows the "autoConnect" method to be non-blocking which can implement this same functionality. However,
|
// allows the "autoConnect" method to be non-blocking which can implement this same functionality. However,
|
||||||
// that change is only on the development branch so we are going to continue to use this fork until
|
// that change is only on the development branch so we are going to continue to use this fork until
|
||||||
// that is merged and ready.
|
// that is merged and ready.
|
||||||
//wifiManager.setSetupLoopCallback(handleLED);
|
#ifdef ESP8266
|
||||||
|
wifiManager.setSetupLoopCallback(handleLED);
|
||||||
|
#elif ESP32
|
||||||
|
// TODO check if the non-blocking implementation can be used or create a version with setSetupLoopCallback
|
||||||
|
#endif
|
||||||
|
|
||||||
// Allows us to have static IP config in the captive portal. Yucky pointers to pointers, just to have the settings carry through
|
// Allows us to have static IP config in the captive portal. Yucky pointers to pointers, just to have the settings carry through
|
||||||
//wifiManager.setSaveConfigCallback(wifiExtraSettingsChange);
|
wifiManager.setSaveConfigCallback(wifiExtraSettingsChange);
|
||||||
/*
|
|
||||||
wifiStaticIP = new WiFiManagerParameter(
|
wifiStaticIP = new WiFiManagerParameter(
|
||||||
"staticIP",
|
"staticIP",
|
||||||
"Static IP (Leave blank for dhcp)",
|
"Static IP (Leave blank for dhcp)",
|
||||||
|
@ -423,7 +403,7 @@ void setup() {
|
||||||
MAX_IP_ADDR_LEN
|
MAX_IP_ADDR_LEN
|
||||||
);
|
);
|
||||||
wifiManager.addParameter(wifiStaticIPGateway);
|
wifiManager.addParameter(wifiStaticIPGateway);
|
||||||
*/
|
|
||||||
// We have a saved static IP, let's try and use it.
|
// We have a saved static IP, let's try and use it.
|
||||||
if (settings.wifiStaticIP.length() > 0) {
|
if (settings.wifiStaticIP.length() > 0) {
|
||||||
Serial.printf_P(PSTR("We have a static IP: %s\n"), settings.wifiStaticIP.c_str());
|
Serial.printf_P(PSTR("We have a static IP: %s\n"), settings.wifiStaticIP.c_str());
|
||||||
|
@ -432,14 +412,10 @@ void setup() {
|
||||||
_ip.fromString(settings.wifiStaticIP);
|
_ip.fromString(settings.wifiStaticIP);
|
||||||
_subnet.fromString(settings.wifiStaticIPNetmask);
|
_subnet.fromString(settings.wifiStaticIPNetmask);
|
||||||
_gw.fromString(settings.wifiStaticIPGateway);
|
_gw.fromString(settings.wifiStaticIPGateway);
|
||||||
ETH.begin();
|
|
||||||
ETH.config(_ip, _gw, _subnet, _gw, _gw);
|
|
||||||
//wifiManager.setSTAStaticIPConfig(_ip,_gw,_subnet);
|
|
||||||
|
|
||||||
} else {
|
wifiManager.setSTAStaticIPConfig(_ip,_gw,_subnet);
|
||||||
ETH.begin();
|
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
wifiManager.setConfigPortalTimeout(180);
|
wifiManager.setConfigPortalTimeout(180);
|
||||||
|
|
||||||
if (wifiManager.autoConnect(ssid.c_str(), "milightHub")) {
|
if (wifiManager.autoConnect(ssid.c_str(), "milightHub")) {
|
||||||
|
@ -449,25 +425,42 @@ void setup() {
|
||||||
|
|
||||||
// if the config portal was started, make sure to turn off the config AP
|
// if the config portal was started, make sure to turn off the config AP
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
applySettings();
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// set LED mode for Wifi failed
|
// set LED mode for Wifi failed
|
||||||
ledStatus->continuous(settings.ledModeWifiFailed);
|
ledStatus->continuous(settings.ledModeWifiFailed);
|
||||||
Serial.println(F("Wifi failed. Restarting in 10 seconds.\n"));
|
Serial.println(F("Wifi failed. Restarting in 10 seconds.\n"));
|
||||||
*/
|
|
||||||
|
delay(10000);
|
||||||
|
ESP.restart();
|
||||||
|
}
|
||||||
|
|
||||||
MDNS.addService("http", "tcp", 80);
|
MDNS.addService("http", "tcp", 80);
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
SSDP.setSchemaURL("description.xml");
|
SSDP.setSchemaURL("description.xml");
|
||||||
SSDP.setHTTPPort(80);
|
SSDP.setHTTPPort(80);
|
||||||
SSDP.setName("ESP8266 MiLight Gateway");
|
SSDP.setName("ESP8266 MiLight Gateway");
|
||||||
//SSDP.setSerialNumber(ESP.getChipId());
|
SSDP.setSerialNumber(ESP.getChipId());
|
||||||
SSDP.setURL("/");
|
SSDP.setURL("/");
|
||||||
SSDP.setDeviceType("upnp:rootdevice");
|
SSDP.setDeviceType("upnp:rootdevice");
|
||||||
SSDP.begin();
|
SSDP.begin();
|
||||||
|
#elif ESP32
|
||||||
|
// TODO SSDP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
httpServer = new MiLightHttpServer(settings, milightClient, stateStore, packetSender, radios, transitions);
|
httpServer = new MiLightHttpServer(settings, milightClient, stateStore, packetSender, radios, transitions);
|
||||||
httpServer->onSettingsSaved(applySettings);
|
httpServer->onSettingsSaved(applySettings);
|
||||||
httpServer->onGroupDeleted(onGroupDeleted);
|
httpServer->onGroupDeleted(onGroupDeleted);
|
||||||
|
#ifdef ESP8266
|
||||||
httpServer->on("/description.xml", HTTP_GET, []() { SSDP.schema(httpServer->client()); });
|
httpServer->on("/description.xml", HTTP_GET, []() { SSDP.schema(httpServer->client()); });
|
||||||
|
#elif ESP32
|
||||||
|
// TODO SSDP
|
||||||
|
#endif
|
||||||
httpServer->begin();
|
httpServer->begin();
|
||||||
|
|
||||||
transitions.addListener(
|
transitions.addListener(
|
||||||
|
@ -486,6 +479,7 @@ void setup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|
||||||
httpServer->handleClient();
|
httpServer->handleClient();
|
||||||
|
|
||||||
if (mqttClient) {
|
if (mqttClient) {
|
||||||
|
|
Loading…
Reference in New Issue