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"
extern "C" {
#include "osapi.h"
#include "ets_sys.h"
#include "user_interface.h"
#include "osapi.h"
#include "ets_sys.h"
#include "user_interface.h"
}
#include "lwip/opt.h"
@ -45,8 +45,7 @@ extern "C" {
#include "lwip/igmp.h"
#include "lwip/mem.h"
#include "include/UdpContext.h"
// #define DEBUG_SSDP Serial
//#define DEBUG_SSDP Serial
#define SSDP_INTERVAL 1200
#define SSDP_PORT 1900
@ -56,8 +55,6 @@ extern "C" {
#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";
@ -84,39 +81,39 @@ static const char _ssdp_schema_template[] PROGMEM =
"\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>"
"<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";
@ -126,15 +123,15 @@ struct SSDPTimer {
};
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)
_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';
@ -149,19 +146,20 @@ _notify_time(0)
sprintf(_schemaURL, "ssdp/schema.xml");
}
SSDPClass::~SSDPClass(){
SSDPClass::~SSDPClass() {
delete _timer;
}
bool SSDPClass::begin(){
bool SSDPClass::begin() {
_pending = false;
uint32_t chipId = ESP.getChipId();
sprintf(_uuid, "38323636-4558-4dda-9188-cda0e6%02x%02x%02x",
if (strcmp(_uuid,"") == 0) {
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 );
(uint16_t) ((chipId >> 8) & 0xff),
(uint16_t) chipId & 0xff );
}
#ifdef DEBUG_SSDP
DEBUG_SSDP.printf("SSDP UUID: %s\n", (char *)_uuid);
#endif
@ -199,29 +197,30 @@ bool SSDPClass::begin(){
return true;
}
void SSDPClass::_send(ssdp_method_t method){
void SSDPClass::_send(ssdp_method_t method) {
char buffer[1460];
IPAddress ip = WiFi.localIP();
char valueBuffer[strlen_P(_ssdp_notify_template)+1];
strcpy_P(valueBuffer, (method == NONE)?_ssdp_response_template:_ssdp_notify_template);
char valueBuffer[strlen_P(_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,
ip[0], ip[1], ip[2], ip[3], _port, _schemaURL
);
_ssdp_packet_template,
valueBuffer,
SSDP_INTERVAL,
_modelName,
_modelNumber,
_uuid,
(method == NONE) ? "ST" : "NT",
_deviceType,
ip[0], ip[1], ip[2], ip[3], _port, _schemaURL
);
_server->append(buffer, len);
ip_addr_t remoteAddr;
uint16_t remotePort;
if(method == NONE) {
if (method == NONE) {
remoteAddr.addr = _respondToAddr;
remotePort = _respondToPort;
#ifdef DEBUG_SSDP
@ -243,27 +242,27 @@ void SSDPClass::_send(ssdp_method_t method){
_server->send(&remoteAddr, remotePort);
}
void SSDPClass::schema(WiFiClient client){
void SSDPClass::schema(WiFiClient client) {
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);
client.printf(buffer,
ip[0], ip[1], ip[2], ip[3], _port,
_deviceType,
_friendlyName,
_presentationURL,
_serialNumber,
_modelName,
_modelNumber,
_modelURL,
_manufacturer,
_manufacturerURL,
_uuid
);
ip[0], ip[1], ip[2], ip[3], _port,
_deviceType,
_friendlyName,
_presentationURL,
_serialNumber,
_modelName,
_modelNumber,
_modelURL,
_manufacturer,
_manufacturerURL,
_uuid
);
}
void SSDPClass::_update(){
if(!_pending && _server->next()) {
void SSDPClass::_update() {
if (!_pending && _server->next()) {
ssdp_method_t method = NONE;
_respondToAddr = _server->getRemoteAddress();
@ -280,40 +279,58 @@ void SSDPClass::_update(){
char buffer[SSDP_BUFFER_SIZE] = {0};
while(_server->getSize() > 0){
while (_server->getSize() > 0) {
char c = _server->read();
(c == '\r' || c == '\n') ? cr++ : cr = 0;
switch(state){
switch (state) {
case METHOD:
if(c == ' '){
if(strcmp(buffer, "M-SEARCH") == 0) method = SEARCH;
if (c == ' ') {
if (strcmp(buffer, "M-SEARCH") == 0) method = SEARCH;
if(method == NONE) state = ABORT;
if (method == NONE) state = ABORT;
else state = URI;
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;
case URI:
if(c == ' '){
if(strcmp(buffer, "*")) state = ABORT;
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'; }
} else if (cursor < SSDP_URI_SIZE - 1) {
buffer[cursor++] = c;
buffer[cursor] = '\0';
}
break;
case PROTO:
if(cr == 2){ state = KEY; cursor = 0; }
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'; }
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){
if (cr == 2) {
switch (header) {
case START:
break;
case MAN:
@ -322,14 +339,14 @@ void SSDPClass::_update(){
#endif
break;
case ST:
if(strcmp(buffer, "ssdp:all")){
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(strcasecmp(buffer, _deviceType) == 0){
if (strcasecmp(buffer, _deviceType) == 0) {
_pending = true;
_process_time = millis();
state = KEY;
@ -340,15 +357,22 @@ void SSDPClass::_update(){
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 (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'; }
if (cursor < SSDP_BUFFER_SIZE - 1) {
buffer[cursor++] = c;
buffer[cursor] = '\0';
}
}
break;
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;
_send(NONE);
} 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));
}
void SSDPClass::setHTTPPort(uint16_t port){
void SSDPClass::setHTTPPort(uint16_t port) {
_port = port;
}
void SSDPClass::setDeviceType(const char *deviceType){
void SSDPClass::setDeviceType(const char *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));
}
void SSDPClass::setURL(const char *url){
void SSDPClass::setURL(const char *url) {
strlcpy(_presentationURL, url, sizeof(_presentationURL));
}
void SSDPClass::setSerialNumber(const char *serialNumber){
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::setSerialNumber(const uint32_t 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));
}
void SSDPClass::setModelNumber(const char *num){
void SSDPClass::setModelNumber(const char *num) {
strlcpy(_modelNumber, num, sizeof(_modelNumber));
}
void SSDPClass::setModelURL(const char *url){
void SSDPClass::setModelURL(const char *url) {
strlcpy(_modelURL, url, sizeof(_modelURL));
}
void SSDPClass::setManufacturer(const char *name){
void SSDPClass::setManufacturer(const char *name) {
strlcpy(_manufacturer, name, sizeof(_manufacturer));
}
void SSDPClass::setManufacturerURL(const char *url){
void SSDPClass::setManufacturerURL(const char *url) {
strlcpy(_manufacturerURL, url, sizeof(_manufacturerURL));
}
void SSDPClass::setTTL(const uint8_t ttl){
void SSDPClass::setTTL(const uint8_t ttl) {
_ttl = ttl;
}

View File

@ -39,7 +39,7 @@ class UdpContext;
#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_SERIAL_NUMBER_SIZE 37
#define SSDP_PRESENTATION_URL_SIZE 128
#define SSDP_MODEL_NAME_SIZE 64
#define SSDP_MODEL_URL_SIZE 128
@ -60,20 +60,22 @@ 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()); }
/*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 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 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()); }

View File

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