1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

Include SetUUID for SSDP (#4981)

* Include SetUUID for SSDP

Inclusion of the SetUUID Method for Custom UUID

* Ajusts PR

* Include IconList Object on XML
This commit is contained in:
Laercio Mendonça 2018-07-30 02:52:16 -03:00 committed by Develo
parent 0899ae9d3e
commit 75a6a3f073
3 changed files with 164 additions and 131 deletions

View File

@ -34,9 +34,9 @@ License (MIT license):
#include "debug.h" #include "debug.h"
extern "C" { extern "C" {
#include "osapi.h" #include "osapi.h"
#include "ets_sys.h" #include "ets_sys.h"
#include "user_interface.h" #include "user_interface.h"
} }
#include "lwip/opt.h" #include "lwip/opt.h"
@ -45,8 +45,7 @@ extern "C" {
#include "lwip/igmp.h" #include "lwip/igmp.h"
#include "lwip/mem.h" #include "lwip/mem.h"
#include "include/UdpContext.h" #include "include/UdpContext.h"
//#define DEBUG_SSDP Serial
// #define DEBUG_SSDP Serial
#define SSDP_INTERVAL 1200 #define SSDP_INTERVAL 1200
#define SSDP_PORT 1900 #define SSDP_PORT 1900
@ -56,8 +55,6 @@ extern "C" {
#define SSDP_MULTICAST_TTL 2 #define SSDP_MULTICAST_TTL 2
static const IPAddress SSDP_MULTICAST_ADDR(239, 255, 255, 250); static const IPAddress SSDP_MULTICAST_ADDR(239, 255, 255, 250);
static const char _ssdp_response_template[] PROGMEM = static const char _ssdp_response_template[] PROGMEM =
"HTTP/1.1 200 OK\r\n" "HTTP/1.1 200 OK\r\n"
"EXT:\r\n"; "EXT:\r\n";
@ -84,39 +81,39 @@ static const char _ssdp_schema_template[] PROGMEM =
"\r\n" "\r\n"
"<?xml version=\"1.0\"?>" "<?xml version=\"1.0\"?>"
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">" "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
"<specVersion>" "<specVersion>"
"<major>1</major>" "<major>1</major>"
"<minor>0</minor>" "<minor>0</minor>"
"</specVersion>" "</specVersion>"
"<URLBase>http://%u.%u.%u.%u:%u/</URLBase>" // WiFi.localIP(), _port "<URLBase>http://%u.%u.%u.%u:%u/</URLBase>" // WiFi.localIP(), _port
"<device>" "<device>"
"<deviceType>%s</deviceType>" "<deviceType>%s</deviceType>"
"<friendlyName>%s</friendlyName>" "<friendlyName>%s</friendlyName>"
"<presentationURL>%s</presentationURL>" "<presentationURL>%s</presentationURL>"
"<serialNumber>%s</serialNumber>" "<serialNumber>%s</serialNumber>"
"<modelName>%s</modelName>" "<modelName>%s</modelName>"
"<modelNumber>%s</modelNumber>" "<modelNumber>%s</modelNumber>"
"<modelURL>%s</modelURL>" "<modelURL>%s</modelURL>"
"<manufacturer>%s</manufacturer>" "<manufacturer>%s</manufacturer>"
"<manufacturerURL>%s</manufacturerURL>" "<manufacturerURL>%s</manufacturerURL>"
"<UDN>uuid:%s</UDN>" "<UDN>UUID: %s</UDN>"
"</device>" "</device>"
// "<iconList>" //"<iconList>"
// "<icon>" //"<icon>"
// "<mimetype>image/png</mimetype>" //"<mimetype>image/png</mimetype>"
// "<height>48</height>" //"<height>48</height>"
// "<width>48</width>" //"<width>48</width>"
// "<depth>24</depth>" //"<depth>24</depth>"
// "<url>icon48.png</url>" //"<url>icon48.png</url>"
// "</icon>" //"</icon>"
// "<icon>" //"<icon>"
// "<mimetype>image/png</mimetype>" //"<mimetype>image/png</mimetype>"
// "<height>120</height>" //"<height>120</height>"
// "<width>120</width>" //"<width>120</width>"
// "<depth>24</depth>" //"<depth>24</depth>"
// "<url>icon120.png</url>" //"<url>icon120.png</url>"
// "</icon>" //"</icon>"
// "</iconList>" //"</iconList>"
"</root>\r\n" "</root>\r\n"
"\r\n"; "\r\n";
@ -126,15 +123,15 @@ struct SSDPTimer {
}; };
SSDPClass::SSDPClass() : SSDPClass::SSDPClass() :
_server(0), _server(0),
_timer(new SSDPTimer), _timer(new SSDPTimer),
_port(80), _port(80),
_ttl(SSDP_MULTICAST_TTL), _ttl(SSDP_MULTICAST_TTL),
_respondToPort(0), _respondToPort(0),
_pending(false), _pending(false),
_delay(0), _delay(0),
_process_time(0), _process_time(0),
_notify_time(0) _notify_time(0)
{ {
_uuid[0] = '\0'; _uuid[0] = '\0';
_modelNumber[0] = '\0'; _modelNumber[0] = '\0';
@ -149,19 +146,20 @@ _notify_time(0)
sprintf(_schemaURL, "ssdp/schema.xml"); sprintf(_schemaURL, "ssdp/schema.xml");
} }
SSDPClass::~SSDPClass(){ SSDPClass::~SSDPClass() {
delete _timer; delete _timer;
} }
bool SSDPClass::begin(){ bool SSDPClass::begin() {
_pending = false; _pending = false;
if (strcmp(_uuid,"") == 0) {
uint32_t chipId = ESP.getChipId(); uint32_t chipId = ESP.getChipId();
sprintf(_uuid, "38323636-4558-4dda-9188-cda0e6%02x%02x%02x", sprintf(_uuid, "38323636-4558-4dda-9188-cda0e6%02x%02x%02x",
(uint16_t) ((chipId >> 16) & 0xff), (uint16_t) ((chipId >> 16) & 0xff),
(uint16_t) ((chipId >> 8) & 0xff), (uint16_t) ((chipId >> 8) & 0xff),
(uint16_t) chipId & 0xff ); (uint16_t) chipId & 0xff );
}
#ifdef DEBUG_SSDP #ifdef DEBUG_SSDP
DEBUG_SSDP.printf("SSDP UUID: %s\n", (char *)_uuid); DEBUG_SSDP.printf("SSDP UUID: %s\n", (char *)_uuid);
#endif #endif
@ -199,29 +197,30 @@ bool SSDPClass::begin(){
return true; return true;
} }
void SSDPClass::_send(ssdp_method_t method){ void SSDPClass::_send(ssdp_method_t method) {
char buffer[1460]; char buffer[1460];
IPAddress ip = WiFi.localIP(); IPAddress ip = WiFi.localIP();
char valueBuffer[strlen_P(_ssdp_notify_template)+1]; char valueBuffer[strlen_P(_ssdp_notify_template) + 1];
strcpy_P(valueBuffer, (method == NONE)?_ssdp_response_template:_ssdp_notify_template); strcpy_P(valueBuffer, (method == NONE) ? _ssdp_response_template : _ssdp_notify_template);
int len = snprintf_P(buffer, sizeof(buffer), int len = snprintf_P(buffer, sizeof(buffer),
_ssdp_packet_template, _ssdp_packet_template,
valueBuffer, valueBuffer,
SSDP_INTERVAL, SSDP_INTERVAL,
_modelName, _modelNumber, _modelName,
_uuid, _modelNumber,
(method == NONE)?"ST":"NT", _uuid,
_deviceType, (method == NONE) ? "ST" : "NT",
ip[0], ip[1], ip[2], ip[3], _port, _schemaURL _deviceType,
); ip[0], ip[1], ip[2], ip[3], _port, _schemaURL
);
_server->append(buffer, len); _server->append(buffer, len);
ip_addr_t remoteAddr; ip_addr_t remoteAddr;
uint16_t remotePort; uint16_t remotePort;
if(method == NONE) { if (method == NONE) {
remoteAddr.addr = _respondToAddr; remoteAddr.addr = _respondToAddr;
remotePort = _respondToPort; remotePort = _respondToPort;
#ifdef DEBUG_SSDP #ifdef DEBUG_SSDP
@ -243,27 +242,27 @@ void SSDPClass::_send(ssdp_method_t method){
_server->send(&remoteAddr, remotePort); _server->send(&remoteAddr, remotePort);
} }
void SSDPClass::schema(WiFiClient client){ void SSDPClass::schema(WiFiClient client) {
IPAddress ip = WiFi.localIP(); IPAddress ip = WiFi.localIP();
char buffer[strlen_P(_ssdp_schema_template)+1]; char buffer[strlen_P(_ssdp_schema_template) + 1];
strcpy_P(buffer, _ssdp_schema_template); strcpy_P(buffer, _ssdp_schema_template);
client.printf(buffer, client.printf(buffer,
ip[0], ip[1], ip[2], ip[3], _port, ip[0], ip[1], ip[2], ip[3], _port,
_deviceType, _deviceType,
_friendlyName, _friendlyName,
_presentationURL, _presentationURL,
_serialNumber, _serialNumber,
_modelName, _modelName,
_modelNumber, _modelNumber,
_modelURL, _modelURL,
_manufacturer, _manufacturer,
_manufacturerURL, _manufacturerURL,
_uuid _uuid
); );
} }
void SSDPClass::_update(){ void SSDPClass::_update() {
if(!_pending && _server->next()) { if (!_pending && _server->next()) {
ssdp_method_t method = NONE; ssdp_method_t method = NONE;
_respondToAddr = _server->getRemoteAddress(); _respondToAddr = _server->getRemoteAddress();
@ -280,40 +279,58 @@ void SSDPClass::_update(){
char buffer[SSDP_BUFFER_SIZE] = {0}; char buffer[SSDP_BUFFER_SIZE] = {0};
while(_server->getSize() > 0){ while (_server->getSize() > 0) {
char c = _server->read(); char c = _server->read();
(c == '\r' || c == '\n') ? cr++ : cr = 0; (c == '\r' || c == '\n') ? cr++ : cr = 0;
switch(state){ switch (state) {
case METHOD: case METHOD:
if(c == ' '){ if (c == ' ') {
if(strcmp(buffer, "M-SEARCH") == 0) method = SEARCH; if (strcmp(buffer, "M-SEARCH") == 0) method = SEARCH;
if(method == NONE) state = ABORT; if (method == NONE) state = ABORT;
else state = URI; else state = URI;
cursor = 0; cursor = 0;
} else if(cursor < SSDP_METHOD_SIZE - 1){ buffer[cursor++] = c; buffer[cursor] = '\0'; } } else if (cursor < SSDP_METHOD_SIZE - 1) {
buffer[cursor++] = c;
buffer[cursor] = '\0';
}
break; break;
case URI: case URI:
if(c == ' '){ if (c == ' ') {
if(strcmp(buffer, "*")) state = ABORT; if (strcmp(buffer, "*")) state = ABORT;
else state = PROTO; else state = PROTO;
cursor = 0; cursor = 0;
} else if(cursor < SSDP_URI_SIZE - 1){ buffer[cursor++] = c; buffer[cursor] = '\0'; } } else if (cursor < SSDP_URI_SIZE - 1) {
buffer[cursor++] = c;
buffer[cursor] = '\0';
}
break; break;
case PROTO: case PROTO:
if(cr == 2){ state = KEY; cursor = 0; } if (cr == 2) {
state = KEY;
cursor = 0;
}
break; break;
case KEY: case KEY:
if(cr == 4){ _pending = true; _process_time = millis(); } if (cr == 4) {
else if(c == ' '){ cursor = 0; state = VALUE; } _pending = true;
else if(c != '\r' && c != '\n' && c != ':' && cursor < SSDP_BUFFER_SIZE - 1){ buffer[cursor++] = c; buffer[cursor] = '\0'; } _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; break;
case VALUE: case VALUE:
if(cr == 2){ if (cr == 2) {
switch(header){ switch (header) {
case START: case START:
break; break;
case MAN: case MAN:
@ -322,14 +339,14 @@ void SSDPClass::_update(){
#endif #endif
break; break;
case ST: case ST:
if(strcmp(buffer, "ssdp:all")){ if (strcmp(buffer, "ssdp:all")) {
state = ABORT; state = ABORT;
#ifdef DEBUG_SSDP #ifdef DEBUG_SSDP
DEBUG_SSDP.printf("REJECT: %s\n", (char *)buffer); DEBUG_SSDP.printf("REJECT: %s\n", (char *)buffer);
#endif #endif
} }
// if the search type matches our type, we should respond instead of ABORT // if the search type matches our type, we should respond instead of ABORT
if(strcasecmp(buffer, _deviceType) == 0){ if (strcasecmp(buffer, _deviceType) == 0) {
_pending = true; _pending = true;
_process_time = millis(); _process_time = millis();
state = KEY; state = KEY;
@ -340,15 +357,22 @@ void SSDPClass::_update(){
break; break;
} }
if(state != ABORT){ state = KEY; header = START; cursor = 0; } if (state != ABORT) {
} else if(c != '\r' && c != '\n'){ state = KEY;
if(header == START){ header = START;
if(strncmp(buffer, "MA", 2) == 0) header = MAN; cursor = 0;
else if(strcmp(buffer, "ST") == 0) header = ST; }
else if(strcmp(buffer, "MX") == 0) header = MX; } 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'; } if (cursor < SSDP_BUFFER_SIZE - 1) {
buffer[cursor++] = c;
buffer[cursor] = '\0';
}
} }
break; break;
case ABORT: case ABORT:
@ -358,7 +382,7 @@ void SSDPClass::_update(){
} }
} }
if(_pending && (millis() - _process_time) > _delay){ if (_pending && (millis() - _process_time) > _delay) {
_pending = false; _delay = 0; _pending = false; _delay = 0;
_send(NONE); _send(NONE);
} else if(_notify_time == 0 || (millis() - _notify_time) > (SSDP_INTERVAL * 1000L)){ } else if(_notify_time == 0 || (millis() - _notify_time) > (SSDP_INTERVAL * 1000L)){
@ -373,55 +397,60 @@ void SSDPClass::_update(){
} }
void SSDPClass::setSchemaURL(const char *url){ void SSDPClass::setSchemaURL(const char *url) {
strlcpy(_schemaURL, url, sizeof(_schemaURL)); strlcpy(_schemaURL, url, sizeof(_schemaURL));
} }
void SSDPClass::setHTTPPort(uint16_t port){ void SSDPClass::setHTTPPort(uint16_t port) {
_port = port; _port = port;
} }
void SSDPClass::setDeviceType(const char *deviceType){ void SSDPClass::setDeviceType(const char *deviceType) {
strlcpy(_deviceType, deviceType, sizeof(_deviceType)); strlcpy(_deviceType, deviceType, sizeof(_deviceType));
} }
void SSDPClass::setName(const char *name){ void SSDPClass::setUUID(const char *uuid) {
strlcpy(_uuid, uuid, sizeof(_uuid));
}
void SSDPClass::setName(const char *name) {
strlcpy(_friendlyName, name, sizeof(_friendlyName)); strlcpy(_friendlyName, name, sizeof(_friendlyName));
} }
void SSDPClass::setURL(const char *url){ void SSDPClass::setURL(const char *url) {
strlcpy(_presentationURL, url, sizeof(_presentationURL)); strlcpy(_presentationURL, url, sizeof(_presentationURL));
} }
void SSDPClass::setSerialNumber(const char *serialNumber){ void SSDPClass::setSerialNumber(const char *serialNumber) {
strlcpy(_serialNumber, serialNumber, sizeof(_serialNumber)); strlcpy(_serialNumber, serialNumber, sizeof(_serialNumber));
} }
void SSDPClass::setSerialNumber(const uint32_t serialNumber){ void SSDPClass::setSerialNumber(const uint32_t serialNumber) {
snprintf(_serialNumber, sizeof(uint32_t)*2+1, "%08X", serialNumber); snprintf(_serialNumber, sizeof(uint32_t) * 2 + 1, "%08X", serialNumber);
} }
void SSDPClass::setModelName(const char *name){ void SSDPClass::setModelName(const char *name) {
strlcpy(_modelName, name, sizeof(_modelName)); strlcpy(_modelName, name, sizeof(_modelName));
} }
void SSDPClass::setModelNumber(const char *num){ void SSDPClass::setModelNumber(const char *num) {
strlcpy(_modelNumber, num, sizeof(_modelNumber)); strlcpy(_modelNumber, num, sizeof(_modelNumber));
} }
void SSDPClass::setModelURL(const char *url){ void SSDPClass::setModelURL(const char *url) {
strlcpy(_modelURL, url, sizeof(_modelURL)); strlcpy(_modelURL, url, sizeof(_modelURL));
} }
void SSDPClass::setManufacturer(const char *name){ void SSDPClass::setManufacturer(const char *name) {
strlcpy(_manufacturer, name, sizeof(_manufacturer)); strlcpy(_manufacturer, name, sizeof(_manufacturer));
} }
void SSDPClass::setManufacturerURL(const char *url){ void SSDPClass::setManufacturerURL(const char *url) {
strlcpy(_manufacturerURL, url, sizeof(_manufacturerURL)); strlcpy(_manufacturerURL, url, sizeof(_manufacturerURL));
} }
void SSDPClass::setTTL(const uint8_t ttl){
void SSDPClass::setTTL(const uint8_t ttl) {
_ttl = ttl; _ttl = ttl;
} }

View File

@ -39,7 +39,7 @@ class UdpContext;
#define SSDP_SCHEMA_URL_SIZE 64 #define SSDP_SCHEMA_URL_SIZE 64
#define SSDP_DEVICE_TYPE_SIZE 64 #define SSDP_DEVICE_TYPE_SIZE 64
#define SSDP_FRIENDLY_NAME_SIZE 64 #define SSDP_FRIENDLY_NAME_SIZE 64
#define SSDP_SERIAL_NUMBER_SIZE 32 #define SSDP_SERIAL_NUMBER_SIZE 37
#define SSDP_PRESENTATION_URL_SIZE 128 #define SSDP_PRESENTATION_URL_SIZE 128
#define SSDP_MODEL_NAME_SIZE 64 #define SSDP_MODEL_NAME_SIZE 64
#define SSDP_MODEL_URL_SIZE 128 #define SSDP_MODEL_URL_SIZE 128
@ -60,20 +60,22 @@ class SSDPClass{
public: public:
SSDPClass(); SSDPClass();
~SSDPClass(); ~SSDPClass();
bool begin(); bool begin();
void schema(WiFiClient client); void schema(WiFiClient client);
void setDeviceType(const String& deviceType) { setDeviceType(deviceType.c_str()); } void setDeviceType(const String& deviceType) { setDeviceType(deviceType.c_str()); }
void setDeviceType(const char *deviceType); void setDeviceType(const char *deviceType);
void setName(const String& name) { setName(name.c_str()); }
/*To define a custom UUID, you must call the method before begin(). Otherwise an automatic UUID based on CHIPID will be generated.*/
void setUUID(const String& uuid) { setUUID(uuid.c_str()); }
void setUUID(const char *uuid);
void setName(const String& name) { setName(name.c_str()); }
void setName(const char *name); void setName(const char *name);
void setURL(const String& url) { setURL(url.c_str()); } void setURL(const String& url) { setURL(url.c_str()); }
void setURL(const char *url); void setURL(const char *url);
void setSchemaURL(const String& url) { setSchemaURL(url.c_str()); } void setSchemaURL(const String& url) { setSchemaURL(url.c_str()); }
void setSchemaURL(const char *url); void setSchemaURL(const char *url);
void setSerialNumber(const String& serialNumber) { setSerialNumber(serialNumber.c_str()); } void setSerialNumber(const String& serialNumber) { setSerialNumber(serialNumber.c_str()); }
void setSerialNumber(const char *serialNumber); void setSerialNumber(const char *serialNumber);
void setSerialNumber(const uint32_t serialNumber); void setSerialNumber(const uint32_t serialNumber);
void setModelName(const String& name) { setModelName(name.c_str()); } void setModelName(const String& name) { setModelName(name.c_str()); }

View File

@ -15,6 +15,7 @@ SSDP KEYWORD1
begin KEYWORD2 begin KEYWORD2
schema KEYWORD2 schema KEYWORD2
setUUID KEYWORD2
setName KEYWORD2 setName KEYWORD2
setURL KEYWORD2 setURL KEYWORD2
setHTTPPort KEYWORD2 setHTTPPort KEYWORD2
@ -30,6 +31,7 @@ setManufacturerURL KEYWORD2
# Constants (LITERAL1) # Constants (LITERAL1)
####################################### #######################################
SSDP_INTERVAL LITERAL1 SSDP_INTERVAL LITERAL1
SSDP_UUID LITERAL1
SSDP_PORT LITERAL1 SSDP_PORT LITERAL1
SSDP_METHOD_SIZE LITERAL1 SSDP_METHOD_SIZE LITERAL1
SSDP_URI_SIZE LITERAL1 SSDP_URI_SIZE LITERAL1