From 4fdba1b635871611fcb13b6baf4908b80b7cb70c Mon Sep 17 00:00:00 2001 From: John Doe Date: Sat, 4 Jul 2015 22:55:48 +0300 Subject: [PATCH 01/11] Add SSDP Library and let Print::printf to handle longer strings --- cores/esp8266/Print.cpp | 4 +- libraries/ESP8266SSDP/ESP8266SSDP.cpp | 320 ++++++++++++++++++++++++ libraries/ESP8266SSDP/ESP8266SSDP.h | 100 ++++++++ libraries/ESP8266SSDP/README.md | 22 ++ libraries/ESP8266SSDP/examples/SSDP.ino | 57 +++++ libraries/ESP8266SSDP/keywords.txt | 53 ++++ 6 files changed, 554 insertions(+), 2 deletions(-) create mode 100644 libraries/ESP8266SSDP/ESP8266SSDP.cpp create mode 100644 libraries/ESP8266SSDP/ESP8266SSDP.h create mode 100644 libraries/ESP8266SSDP/README.md create mode 100644 libraries/ESP8266SSDP/examples/SSDP.ino create mode 100644 libraries/ESP8266SSDP/keywords.txt diff --git a/cores/esp8266/Print.cpp b/cores/esp8266/Print.cpp index efd6b9f174..06c51e0c1c 100644 --- a/cores/esp8266/Print.cpp +++ b/cores/esp8266/Print.cpp @@ -47,8 +47,8 @@ size_t ICACHE_FLASH_ATTR Print::write(const uint8_t *buffer, size_t size) { size_t Print::printf(const char *format, ...) { va_list arg; va_start(arg, format); - char temp[256]; - size_t len = ets_vsnprintf(temp, 256, format, arg); + char temp[1460]; + size_t len = ets_vsnprintf(temp, 1460, format, arg); len = print(temp); va_end(arg); return len; diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.cpp b/libraries/ESP8266SSDP/ESP8266SSDP.cpp new file mode 100644 index 0000000000..1077f66fb3 --- /dev/null +++ b/libraries/ESP8266SSDP/ESP8266SSDP.cpp @@ -0,0 +1,320 @@ +/* +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. + +*/ + +#include "ESP8266SSDP.h" + +extern "C" { + #include "ip_addr.h" + #include "user_interface.h" + #include "mem.h" +} +#include "lwip/igmp.h" + +#define SSDP_INTERVAL 1200 +#define SSDP_PORT 1900 +#define SSDP_METHOD_SIZE 10 +#define SSDP_URI_SIZE 2 +#define SSDP_BUFFER_SIZE 64 + +static const IPAddress SSDP_MULTICAST_ADDR(239, 255, 255, 250); + +const char* _ssdp_response_template = + "HTTP/1.1 200 OK\r\n" + "EXT:\r\n" + "ST: upnp:rootdevice\r\n"; + +const char* _ssdp_notify_template = + "NOTIFY * HTTP/1.1\r\n" + "HOST: 239.255.255.250:1900\r\n" + "NT: upnp:rootdevice\r\n" + "NTS: ssdp:alive\r\n"; + +const char* _ssdp_packet_template = + "%s" // _ssdp_response_template / _ssdp_notify_template + "CACHE-CONTROL: max-age=%u\r\n" // SSDP_INTERVAL + "SERVER: Arduino/1.0 UPNP/1.1 %s/%u.%u\r\n" // _modelName, _modelNumber->major, _modelNumber->minor + "USN: uuid:%s-%02X%02X%02X%02X%02X%02X\r\n" // _base, _mac[0], _mac[1], _mac[2], _mac[3], _mac[4], _mac[5] + "LOCATION: http://%u.%u.%u.%u/ssdp/schema.xml\r\n" // WiFi.localIP() + "\r\n"; + +const char* _ssdp_schema_template = + "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" + "" + "" + "" + "1" + "0" + "" + "" + "urn:schemas-upnp-org:device:Basic:1" + "%s" + "%s" + "%s" + "%s" + "%u.%u" + "%s" + "%s" + "%s" + "%s-%02X%02X%02X%02X%02X%02X" //uuid:UUID + "" + "\r\n" + "\r\n"; + +SSDPClass::SSDPClass(){ + _base = (char*)os_malloc(SSDP_BASE_SIZE); + _mac = (byte*)os_malloc(6); + _friendlyName = (char*)os_malloc(SSDP_FRIENDLY_NAME_SIZE); + _presentationURL = (char*)os_malloc(SSDP_PRESENTATION_URL_SIZE); + _serialNumber = (char*)os_malloc(SSDP_SERIAL_NUMBER_SIZE); + _modelName = (char*)os_malloc(SSDP_MODEL_NAME_SIZE); + _modelNumber = (ssdp_version_t*)os_malloc(SSDP_MODEL_VERSION_SIZE); + _modelURL = (char*)os_malloc(SSDP_MODEL_URL_SIZE); + _manufacturer = (char*)os_malloc(SSDP_MANUFACTURER_SIZE); + _manufacturerURL = (char*)os_malloc(SSDP_MANUFACTURER_URL_SIZE); + + _modelNumber->major = 0; + _modelNumber->minor = 0; + _friendlyName[0] = '\0'; + _presentationURL[0] = '\0'; + _serialNumber[0] = '\0'; + _modelName[0] = '\0'; + _modelURL[0] = '\0'; + _manufacturer[0] = '\0'; + _manufacturerURL[0] = '\0'; + _pending = false; +} + +SSDPClass::~SSDPClass(){ + os_free(_base); + os_free(_mac); + os_free(_friendlyName); + os_free(_presentationURL); + os_free(_serialNumber); + os_free(_modelName); + os_free(_modelNumber); + os_free(_modelURL); + os_free(_manufacturer); + os_free(_manufacturerURL); + _pending = false; +} + +void SSDPClass::begin(char *base){ + ip_addr_t ifaddr; + ip_addr_t multicast_addr; + + _pending = false; + strcpy(_base, base); + + WiFi.macAddress(_mac); + ifaddr.addr = WiFi.localIP(); + multicast_addr.addr = (uint32_t) SSDP_MULTICAST_ADDR; + igmp_joingroup(&ifaddr, &multicast_addr); + + _server.begin(SSDP_PORT); +} + +void SSDPClass::send(ssdp_method_t method){ +#ifdef DEBUG_SSDP + if(method == NONE){ + DEBUG_SSDP.print("Sending Response to "); + DEBUG_SSDP.print(_server.remoteIP()); + DEBUG_SSDP.print(":"); + DEBUG_SSDP.println(_server.remotePort()); + }else if(method == NOTIFY){ + DEBUG_SSDP.println("Sending Notify to 239.255.255.250:1900"); + } +#endif + + if(method == NONE){ + _server.beginPacket(_server.remoteIP(), _server.remotePort()); + } else { + _server.beginPacket(SSDP_MULTICAST_ADDR, SSDP_PORT); + } + + uint32_t ip = WiFi.localIP(); + + _server.printf(_ssdp_packet_template, + (method == NONE)?_ssdp_response_template:_ssdp_notify_template, + SSDP_INTERVAL, + _modelName, _modelNumber->major, _modelNumber->minor, + _base, _mac[0], _mac[1], _mac[2], _mac[3], _mac[4], _mac[5], + (uint8_t)(ip & 0xFF), (uint8_t)((ip >> 8) & 0xFF), (uint8_t)((ip >> 16) & 0xFF), (uint8_t)((ip >> 24) & 0xFF) + ); + + _server.endPacket(); +} + +void SSDPClass::schema(WiFiClient client){ + client.printf(_ssdp_schema_template, + _friendlyName, + _presentationURL, + _serialNumber, + _modelName, + _modelNumber->major, _modelNumber->minor, + _modelURL, + _manufacturer, + _manufacturerURL, + _base, _mac[0], _mac[1], _mac[2], _mac[3], _mac[4], _mac[5] + ); +} + +uint8_t SSDPClass::update(){ + if(!_pending && _server.parsePacket() > 0){ + ssdp_method_t method = NONE; + + 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.available() > 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 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 + } + 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; + } + } + + _server.flush(); + } + + 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); + } +} + +void SSDPClass::setName(char *name){ + strcpy(_friendlyName, name); +} + +void SSDPClass::setURL(char *url){ + strcpy(_presentationURL, url); +} + +void SSDPClass::setSerialNumber(char *serialNumber){ + strcpy(_serialNumber, serialNumber); +} + +void SSDPClass::setModelName(char *name){ + strcpy(_modelName, name); +} + +void SSDPClass::setModelNumber(uint8_t major, uint8_t minor){ + _modelNumber->major = major; + _modelNumber->minor = minor; +} + +void SSDPClass::setModelURL(char *url){ + strcpy(_modelURL, url); +} + +void SSDPClass::setManufacturer(char *name){ + strcpy(_manufacturer, name); +} + +void SSDPClass::setManufacturerURL(char *url){ + strcpy(_manufacturerURL, url); +} + +SSDPClass SSDP; diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.h b/libraries/ESP8266SSDP/ESP8266SSDP.h new file mode 100644 index 0000000000..7658091794 --- /dev/null +++ b/libraries/ESP8266SSDP/ESP8266SSDP.h @@ -0,0 +1,100 @@ +/* +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 +#include +#include + +#define DEBUG_SSDP Serial + +#define SSDP_BASE_SIZE 24 +#define SSDP_FRIENDLY_NAME_SIZE 32 +#define SSDP_SERIAL_NUMBER_SIZE 32 +#define SSDP_PRESENTATION_URL_SIZE 32 +#define SSDP_MODEL_NAME_SIZE 32 +#define SSDP_MODEL_URL_SIZE 32 +#define SSDP_MODEL_VERSION_SIZE 2 +#define SSDP_MANUFACTURER_SIZE 32 +#define SSDP_MANUFACTURER_URL_SIZE 32 + +typedef enum { + NONE, + SEARCH, + NOTIFY +} ssdp_method_t; + +typedef struct { + uint8_t major; + uint8_t minor; +} ssdp_version_t; + + +class SSDPClass{ + public: + SSDPClass(); + ~SSDPClass(); + + void begin(char *base); + uint8_t update(); + void send(ssdp_method_t method); + void schema(WiFiClient client); + + void setName(char *name); + void setURL(char *url); + void setSerialNumber(char *serialNumber); + void setModelName(char *name); + void setModelNumber(uint8_t major, uint8_t minor); + void setModelURL(char *url); + void setManufacturer(char *name); + void setManufacturerURL(char *url); + + private: + WiFiUDP _server; + bool _pending; + unsigned short _delay; + unsigned long _process_time; + unsigned long _notify_time; + + uint8_t *_mac; + char *_base; + char *_friendlyName; + char *_serialNumber; + char *_presentationURL; + char *_manufacturer; + char *_manufacturerURL; + char *_modelName; + char *_modelURL; + ssdp_version_t *_modelNumber; +}; + +extern SSDPClass SSDP; + +#endif diff --git a/libraries/ESP8266SSDP/README.md b/libraries/ESP8266SSDP/README.md new file mode 100644 index 0000000000..31d3530529 --- /dev/null +++ b/libraries/ESP8266SSDP/README.md @@ -0,0 +1,22 @@ +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 + +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. \ No newline at end of file diff --git a/libraries/ESP8266SSDP/examples/SSDP.ino b/libraries/ESP8266SSDP/examples/SSDP.ino new file mode 100644 index 0000000000..fa7753622d --- /dev/null +++ b/libraries/ESP8266SSDP/examples/SSDP.ino @@ -0,0 +1,57 @@ +#include +#include +#include +#include + +const char* ssid = "************"; +const char* password = "***********"; + +ESP8266WebServer HTTP(80); + +void setup() { + Serial.begin(115200); + Serial.println(); + Serial.println("Booting Sketch..."); + + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + if(WiFi.waitForConnectResult() == WL_CONNECTED){ + HTTP.on("/", HTTP_GET, [](){ + HTTP.sendHeader("Connection", "close"); + HTTP.sendHeader("Access-Control-Allow-Origin", "*"); + HTTP.send(200, "text/plain", "Hello World!"); + }); + HTTP.on("/ssdp/schema.xml", HTTP_GET, [](){ + SSDP.schema(HTTP.client()); + }); + HTTP.begin(); + + byte mac[6]; + char base[24]; + WiFi.macAddress(mac); + sprintf(base, "esp8266x-%02x%02x-%02x%02x-%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + Serial.printf("Starting SSDP: %s\n", base); + + SSDP.begin((char*)base); + SSDP.setName((char*)"ESP8266"); + SSDP.setSerialNumber((char*)"A0123456789"); + SSDP.setURL((char*)"/"); + SSDP.setModelName((char*)"ESP-12e"); + SSDP.setModelNumber(1, 0); + SSDP.setModelURL((char*)"http://12e.espressif.com"); + SSDP.setManufacturer((char*)"Espressif"); + SSDP.setManufacturerURL((char*)"http://espressif.com"); + + Serial.printf("Ready!\n"); + } else { + Serial.printf("WiFi Failed\n"); + while(1) delay(100); + } +} + +void loop() { + HTTP.handleClient(); + SSDP.update(); + delay(1); +} \ No newline at end of file diff --git a/libraries/ESP8266SSDP/keywords.txt b/libraries/ESP8266SSDP/keywords.txt new file mode 100644 index 0000000000..505ddf4dfe --- /dev/null +++ b/libraries/ESP8266SSDP/keywords.txt @@ -0,0 +1,53 @@ +####################################### +# Syntax Coloring Map For Ultrasound +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +ESP8266SSDP KEYWORD1 +SSDP KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +update KEYWORD2 +send KEYWORD2 +schema KEYWORD2 +setName KEYWORD2 +setURL KEYWORD2 +setSerialNumber KEYWORD2 +setModelName KEYWORD2 +setModelNumber KEYWORD2 +setModelURL KEYWORD2 +setManufacturer KEYWORD2 +setManufacturerURL KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### +SSDP_INTERVAL LITERAL1 +SSDP_PORT LITERAL1 +SSDP_METHOD_SIZE LITERAL1 +SSDP_URI_SIZE LITERAL1 +SSDP_BUFFER_SIZE LITERAL1 +SSDP_BASE_SIZE LITERAL1 +SSDP_FRIENDLY_NAME_SIZE LITERAL1 +SSDP_SERIAL_NUMBER_SIZE LITERAL1 +SSDP_PRESENTATION_URL_SIZE LITERAL1 +SSDP_MODEL_NAME_SIZE LITERAL1 +SSDP_MODEL_URL_SIZE LITERAL1 +SSDP_MODEL_VERSION_SIZE LITERAL1 +SSDP_MANUFACTURER_SIZE LITERAL1 +SSDP_MANUFACTURER_URL_SIZE LITERAL1 +SEARCH LITERAL1 +NOTIFY LITERAL1 +BASIC LITERAL1 +MANAGEABLE LITERAL1 +SOLARPROTECTIONBLIND LITERAL1 +DIGITALSECURITYCAMERA LITERAL1 +HVAC LITERAL1 +LIGHTINGCONTROL LITERAL1 From 9cb80528c71f5cf7902af31d93c9968f4f2fce3d Mon Sep 17 00:00:00 2001 From: John Doe Date: Sat, 4 Jul 2015 23:16:00 +0300 Subject: [PATCH 02/11] enable long model versions --- libraries/ESP8266SSDP/ESP8266SSDP.cpp | 18 ++++++++---------- libraries/ESP8266SSDP/ESP8266SSDP.h | 12 +++--------- libraries/ESP8266SSDP/examples/SSDP.ino | 4 ++-- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.cpp b/libraries/ESP8266SSDP/ESP8266SSDP.cpp index 1077f66fb3..60bde31edb 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.cpp +++ b/libraries/ESP8266SSDP/ESP8266SSDP.cpp @@ -57,7 +57,7 @@ const char* _ssdp_notify_template = const char* _ssdp_packet_template = "%s" // _ssdp_response_template / _ssdp_notify_template "CACHE-CONTROL: max-age=%u\r\n" // SSDP_INTERVAL - "SERVER: Arduino/1.0 UPNP/1.1 %s/%u.%u\r\n" // _modelName, _modelNumber->major, _modelNumber->minor + "SERVER: Arduino/1.0 UPNP/1.1 %s/%s\r\n" // _modelName, _modelNumber "USN: uuid:%s-%02X%02X%02X%02X%02X%02X\r\n" // _base, _mac[0], _mac[1], _mac[2], _mac[3], _mac[4], _mac[5] "LOCATION: http://%u.%u.%u.%u/ssdp/schema.xml\r\n" // WiFi.localIP() "\r\n"; @@ -80,7 +80,7 @@ const char* _ssdp_schema_template = "%s" "%s" "%s" - "%u.%u" + "%s" "%s" "%s" "%s" @@ -96,13 +96,12 @@ SSDPClass::SSDPClass(){ _presentationURL = (char*)os_malloc(SSDP_PRESENTATION_URL_SIZE); _serialNumber = (char*)os_malloc(SSDP_SERIAL_NUMBER_SIZE); _modelName = (char*)os_malloc(SSDP_MODEL_NAME_SIZE); - _modelNumber = (ssdp_version_t*)os_malloc(SSDP_MODEL_VERSION_SIZE); + _modelNumber = (char*)os_malloc(SSDP_MODEL_VERSION_SIZE); _modelURL = (char*)os_malloc(SSDP_MODEL_URL_SIZE); _manufacturer = (char*)os_malloc(SSDP_MANUFACTURER_SIZE); _manufacturerURL = (char*)os_malloc(SSDP_MANUFACTURER_URL_SIZE); - _modelNumber->major = 0; - _modelNumber->minor = 0; + _modelNumber[0] = '\0'; _friendlyName[0] = '\0'; _presentationURL[0] = '\0'; _serialNumber[0] = '\0'; @@ -165,7 +164,7 @@ void SSDPClass::send(ssdp_method_t method){ _server.printf(_ssdp_packet_template, (method == NONE)?_ssdp_response_template:_ssdp_notify_template, SSDP_INTERVAL, - _modelName, _modelNumber->major, _modelNumber->minor, + _modelName, _modelNumber, _base, _mac[0], _mac[1], _mac[2], _mac[3], _mac[4], _mac[5], (uint8_t)(ip & 0xFF), (uint8_t)((ip >> 8) & 0xFF), (uint8_t)((ip >> 16) & 0xFF), (uint8_t)((ip >> 24) & 0xFF) ); @@ -179,7 +178,7 @@ void SSDPClass::schema(WiFiClient client){ _presentationURL, _serialNumber, _modelName, - _modelNumber->major, _modelNumber->minor, + _modelNumber, _modelURL, _manufacturer, _manufacturerURL, @@ -300,9 +299,8 @@ void SSDPClass::setModelName(char *name){ strcpy(_modelName, name); } -void SSDPClass::setModelNumber(uint8_t major, uint8_t minor){ - _modelNumber->major = major; - _modelNumber->minor = minor; +void SSDPClass::setModelNumber(char *num){ + strcpy(_modelNumber, num); } void SSDPClass::setModelURL(char *url){ diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.h b/libraries/ESP8266SSDP/ESP8266SSDP.h index 7658091794..04fb41fab5 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.h +++ b/libraries/ESP8266SSDP/ESP8266SSDP.h @@ -41,7 +41,7 @@ License (MIT license): #define SSDP_PRESENTATION_URL_SIZE 32 #define SSDP_MODEL_NAME_SIZE 32 #define SSDP_MODEL_URL_SIZE 32 -#define SSDP_MODEL_VERSION_SIZE 2 +#define SSDP_MODEL_VERSION_SIZE 32 #define SSDP_MANUFACTURER_SIZE 32 #define SSDP_MANUFACTURER_URL_SIZE 32 @@ -51,12 +51,6 @@ typedef enum { NOTIFY } ssdp_method_t; -typedef struct { - uint8_t major; - uint8_t minor; -} ssdp_version_t; - - class SSDPClass{ public: SSDPClass(); @@ -71,7 +65,7 @@ class SSDPClass{ void setURL(char *url); void setSerialNumber(char *serialNumber); void setModelName(char *name); - void setModelNumber(uint8_t major, uint8_t minor); + void setModelNumber(char *num); void setModelURL(char *url); void setManufacturer(char *name); void setManufacturerURL(char *url); @@ -92,7 +86,7 @@ class SSDPClass{ char *_manufacturerURL; char *_modelName; char *_modelURL; - ssdp_version_t *_modelNumber; + char *_modelNumber; }; extern SSDPClass SSDP; diff --git a/libraries/ESP8266SSDP/examples/SSDP.ino b/libraries/ESP8266SSDP/examples/SSDP.ino index fa7753622d..236773abf7 100644 --- a/libraries/ESP8266SSDP/examples/SSDP.ino +++ b/libraries/ESP8266SSDP/examples/SSDP.ino @@ -38,7 +38,7 @@ void setup() { SSDP.setSerialNumber((char*)"A0123456789"); SSDP.setURL((char*)"/"); SSDP.setModelName((char*)"ESP-12e"); - SSDP.setModelNumber(1, 0); + SSDP.setModelNumber((char*)"1.0"); SSDP.setModelURL((char*)"http://12e.espressif.com"); SSDP.setManufacturer((char*)"Espressif"); SSDP.setManufacturerURL((char*)"http://espressif.com"); @@ -54,4 +54,4 @@ void loop() { HTTP.handleClient(); SSDP.update(); delay(1); -} \ No newline at end of file +} From 3c54cb0a26ca797db47a16c0517a4ae38f87642a Mon Sep 17 00:00:00 2001 From: John Doe Date: Sun, 5 Jul 2015 01:36:43 +0300 Subject: [PATCH 03/11] generate UUID automatically based on chip ID and MAC address --- libraries/ESP8266SSDP/ESP8266SSDP.cpp | 41 +++++++++++++++++-------- libraries/ESP8266SSDP/ESP8266SSDP.h | 14 ++------- libraries/ESP8266SSDP/examples/SSDP.ino | 16 +++------- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.cpp b/libraries/ESP8266SSDP/ESP8266SSDP.cpp index 60bde31edb..4ad6e191b1 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.cpp +++ b/libraries/ESP8266SSDP/ESP8266SSDP.cpp @@ -41,6 +41,16 @@ extern "C" { #define SSDP_URI_SIZE 2 #define SSDP_BUFFER_SIZE 64 +#define SSDP_UUID_SIZE 37 +#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 + static const IPAddress SSDP_MULTICAST_ADDR(239, 255, 255, 250); const char* _ssdp_response_template = @@ -58,7 +68,7 @@ const char* _ssdp_packet_template = "%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-%02X%02X%02X%02X%02X%02X\r\n" // _base, _mac[0], _mac[1], _mac[2], _mac[3], _mac[4], _mac[5] + "USN: uuid:%s\r\n" // _uuid "LOCATION: http://%u.%u.%u.%u/ssdp/schema.xml\r\n" // WiFi.localIP() "\r\n"; @@ -84,14 +94,13 @@ const char* _ssdp_schema_template = "%s" "%s" "%s" - "%s-%02X%02X%02X%02X%02X%02X" //uuid:UUID + "%s" "" "\r\n" "\r\n"; SSDPClass::SSDPClass(){ - _base = (char*)os_malloc(SSDP_BASE_SIZE); - _mac = (byte*)os_malloc(6); + _uuid = (char*)os_malloc(SSDP_UUID_SIZE); _friendlyName = (char*)os_malloc(SSDP_FRIENDLY_NAME_SIZE); _presentationURL = (char*)os_malloc(SSDP_PRESENTATION_URL_SIZE); _serialNumber = (char*)os_malloc(SSDP_SERIAL_NUMBER_SIZE); @@ -101,6 +110,7 @@ SSDPClass::SSDPClass(){ _manufacturer = (char*)os_malloc(SSDP_MANUFACTURER_SIZE); _manufacturerURL = (char*)os_malloc(SSDP_MANUFACTURER_URL_SIZE); + _uuid[0] = '\0'; _modelNumber[0] = '\0'; _friendlyName[0] = '\0'; _presentationURL[0] = '\0'; @@ -113,8 +123,7 @@ SSDPClass::SSDPClass(){ } SSDPClass::~SSDPClass(){ - os_free(_base); - os_free(_mac); + os_free(_uuid); os_free(_friendlyName); os_free(_presentationURL); os_free(_serialNumber); @@ -126,18 +135,26 @@ SSDPClass::~SSDPClass(){ _pending = false; } -void SSDPClass::begin(char *base){ +void SSDPClass::begin(){ ip_addr_t ifaddr; ip_addr_t multicast_addr; _pending = false; - strcpy(_base, base); - WiFi.macAddress(_mac); ifaddr.addr = WiFi.localIP(); multicast_addr.addr = (uint32_t) SSDP_MULTICAST_ADDR; igmp_joingroup(&ifaddr, &multicast_addr); - + + uint8_t mac[6]; + WiFi.macAddress(mac); + uint32_t chipId = ESP.getChipId(); + sprintf(_uuid, "38323636-4558-%04X-%04X-%02X%02X%02X%02X%02X%02X", + (chipId >> 16) & 0xFFFF, chipId & 0xFFFF, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] + ); +#ifdef DEBUG_SSDP + DEBUG_SSDP.printf("SSDP UUID: %s\n", (char *)_uuid); +#endif _server.begin(SSDP_PORT); } @@ -165,7 +182,7 @@ void SSDPClass::send(ssdp_method_t method){ (method == NONE)?_ssdp_response_template:_ssdp_notify_template, SSDP_INTERVAL, _modelName, _modelNumber, - _base, _mac[0], _mac[1], _mac[2], _mac[3], _mac[4], _mac[5], + _uuid, (uint8_t)(ip & 0xFF), (uint8_t)((ip >> 8) & 0xFF), (uint8_t)((ip >> 16) & 0xFF), (uint8_t)((ip >> 24) & 0xFF) ); @@ -182,7 +199,7 @@ void SSDPClass::schema(WiFiClient client){ _modelURL, _manufacturer, _manufacturerURL, - _base, _mac[0], _mac[1], _mac[2], _mac[3], _mac[4], _mac[5] + _uuid ); } diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.h b/libraries/ESP8266SSDP/ESP8266SSDP.h index 04fb41fab5..e2d8b3b971 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.h +++ b/libraries/ESP8266SSDP/ESP8266SSDP.h @@ -35,16 +35,6 @@ License (MIT license): #define DEBUG_SSDP Serial -#define SSDP_BASE_SIZE 24 -#define SSDP_FRIENDLY_NAME_SIZE 32 -#define SSDP_SERIAL_NUMBER_SIZE 32 -#define SSDP_PRESENTATION_URL_SIZE 32 -#define SSDP_MODEL_NAME_SIZE 32 -#define SSDP_MODEL_URL_SIZE 32 -#define SSDP_MODEL_VERSION_SIZE 32 -#define SSDP_MANUFACTURER_SIZE 32 -#define SSDP_MANUFACTURER_URL_SIZE 32 - typedef enum { NONE, SEARCH, @@ -56,7 +46,7 @@ class SSDPClass{ SSDPClass(); ~SSDPClass(); - void begin(char *base); + void begin(); uint8_t update(); void send(ssdp_method_t method); void schema(WiFiClient client); @@ -78,7 +68,7 @@ class SSDPClass{ unsigned long _notify_time; uint8_t *_mac; - char *_base; + char *_uuid; char *_friendlyName; char *_serialNumber; char *_presentationURL; diff --git a/libraries/ESP8266SSDP/examples/SSDP.ino b/libraries/ESP8266SSDP/examples/SSDP.ino index 236773abf7..6c94836e92 100644 --- a/libraries/ESP8266SSDP/examples/SSDP.ino +++ b/libraries/ESP8266SSDP/examples/SSDP.ino @@ -11,29 +11,23 @@ ESP8266WebServer HTTP(80); void setup() { Serial.begin(115200); Serial.println(); - Serial.println("Booting Sketch..."); + Serial.println("Starting WiFi..."); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); if(WiFi.waitForConnectResult() == WL_CONNECTED){ + + Serial.printf("Starting HTTP...\n"); HTTP.on("/", HTTP_GET, [](){ - HTTP.sendHeader("Connection", "close"); - HTTP.sendHeader("Access-Control-Allow-Origin", "*"); HTTP.send(200, "text/plain", "Hello World!"); }); HTTP.on("/ssdp/schema.xml", HTTP_GET, [](){ SSDP.schema(HTTP.client()); }); HTTP.begin(); - - byte mac[6]; - char base[24]; - WiFi.macAddress(mac); - sprintf(base, "esp8266x-%02x%02x-%02x%02x-%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - Serial.printf("Starting SSDP: %s\n", base); - - SSDP.begin((char*)base); + Serial.printf("Starting SSDP...\n"); + SSDP.begin(); SSDP.setName((char*)"ESP8266"); SSDP.setSerialNumber((char*)"A0123456789"); SSDP.setURL((char*)"/"); From bd6c4acfd87dc8844a0dac5360d130d2162a5c9d Mon Sep 17 00:00:00 2001 From: John Doe Date: Sun, 5 Jul 2015 12:40:59 +0300 Subject: [PATCH 04/11] Add ability to change schema url, http port and add base url --- libraries/ESP8266SSDP/ESP8266SSDP.cpp | 22 +++++++++++++++++++--- libraries/ESP8266SSDP/ESP8266SSDP.h | 5 ++++- libraries/ESP8266SSDP/examples/SSDP.ino | 22 ++++++++++++---------- libraries/ESP8266SSDP/keywords.txt | 2 ++ 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.cpp b/libraries/ESP8266SSDP/ESP8266SSDP.cpp index 4ad6e191b1..f118fe951d 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.cpp +++ b/libraries/ESP8266SSDP/ESP8266SSDP.cpp @@ -42,6 +42,7 @@ extern "C" { #define SSDP_BUFFER_SIZE 64 #define SSDP_UUID_SIZE 37 +#define SSDP_SCHEMA_URL_SIZE 64 #define SSDP_FRIENDLY_NAME_SIZE 64 #define SSDP_SERIAL_NUMBER_SIZE 32 #define SSDP_PRESENTATION_URL_SIZE 128 @@ -69,7 +70,7 @@ const char* _ssdp_packet_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 - "LOCATION: http://%u.%u.%u.%u/ssdp/schema.xml\r\n" // WiFi.localIP() + "LOCATION: http://%u.%u.%u.%u:%u/%s\r\n" // WiFi.localIP(), _port, _shemaURL "\r\n"; const char* _ssdp_schema_template = @@ -84,6 +85,7 @@ const char* _ssdp_schema_template = "1" "0" "" + "http://%u.%u.%u.%u:%u/" // WiFi.localIP(), _port "" "urn:schemas-upnp-org:device:Basic:1" "%s" @@ -94,13 +96,14 @@ const char* _ssdp_schema_template = "%s" "%s" "%s" - "%s" + "uuid:%s" "" "\r\n" "\r\n"; SSDPClass::SSDPClass(){ _uuid = (char*)os_malloc(SSDP_UUID_SIZE); + _schemaURL = (char*)os_malloc(SSDP_SCHEMA_URL_SIZE); _friendlyName = (char*)os_malloc(SSDP_FRIENDLY_NAME_SIZE); _presentationURL = (char*)os_malloc(SSDP_PRESENTATION_URL_SIZE); _serialNumber = (char*)os_malloc(SSDP_SERIAL_NUMBER_SIZE); @@ -119,11 +122,14 @@ SSDPClass::SSDPClass(){ _modelURL[0] = '\0'; _manufacturer[0] = '\0'; _manufacturerURL[0] = '\0'; + sprintf(_schemaURL, "ssdp/schema.xml"); + _port = 80; _pending = false; } SSDPClass::~SSDPClass(){ os_free(_uuid); + os_free(_schemaURL); os_free(_friendlyName); os_free(_presentationURL); os_free(_serialNumber); @@ -183,14 +189,16 @@ void SSDPClass::send(ssdp_method_t method){ SSDP_INTERVAL, _modelName, _modelNumber, _uuid, - (uint8_t)(ip & 0xFF), (uint8_t)((ip >> 8) & 0xFF), (uint8_t)((ip >> 16) & 0xFF), (uint8_t)((ip >> 24) & 0xFF) + (uint8_t)(ip & 0xFF), (uint8_t)((ip >> 8) & 0xFF), (uint8_t)((ip >> 16) & 0xFF), (uint8_t)((ip >> 24) & 0xFF), _port, _schemaURL ); _server.endPacket(); } void SSDPClass::schema(WiFiClient client){ + uint32_t ip = WiFi.localIP(); client.printf(_ssdp_schema_template, + (uint8_t)(ip & 0xFF), (uint8_t)((ip >> 8) & 0xFF), (uint8_t)((ip >> 16) & 0xFF), (uint8_t)((ip >> 24) & 0xFF), _port, _friendlyName, _presentationURL, _serialNumber, @@ -300,6 +308,14 @@ uint8_t SSDPClass::update(){ } } +void SSDPClass::setSchemaURL(char *url){ + strcpy(_schemaURL, url); +} + +void SSDPClass::setHTTPPort(uint16_t port){ + _port = port; +} + void SSDPClass::setName(char *name){ strcpy(_friendlyName, name); } diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.h b/libraries/ESP8266SSDP/ESP8266SSDP.h index e2d8b3b971..aa696953bb 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.h +++ b/libraries/ESP8266SSDP/ESP8266SSDP.h @@ -53,6 +53,8 @@ class SSDPClass{ void setName(char *name); void setURL(char *url); + void setSchemaURL(char *url); + void setHTTPPort(uint16_t port); void setSerialNumber(char *serialNumber); void setModelName(char *name); void setModelNumber(char *num); @@ -67,7 +69,8 @@ class SSDPClass{ unsigned long _process_time; unsigned long _notify_time; - uint8_t *_mac; + uint16_t _port; + char *_schemaURL; char *_uuid; char *_friendlyName; char *_serialNumber; diff --git a/libraries/ESP8266SSDP/examples/SSDP.ino b/libraries/ESP8266SSDP/examples/SSDP.ino index 6c94836e92..2f2d66ee70 100644 --- a/libraries/ESP8266SSDP/examples/SSDP.ino +++ b/libraries/ESP8266SSDP/examples/SSDP.ino @@ -18,24 +18,26 @@ void setup() { if(WiFi.waitForConnectResult() == WL_CONNECTED){ Serial.printf("Starting HTTP...\n"); - HTTP.on("/", HTTP_GET, [](){ + HTTP.on("/index.html", HTTP_GET, [](){ HTTP.send(200, "text/plain", "Hello World!"); }); - HTTP.on("/ssdp/schema.xml", HTTP_GET, [](){ + HTTP.on("/description.xml", HTTP_GET, [](){ SSDP.schema(HTTP.client()); }); HTTP.begin(); Serial.printf("Starting SSDP...\n"); SSDP.begin(); - SSDP.setName((char*)"ESP8266"); - SSDP.setSerialNumber((char*)"A0123456789"); - SSDP.setURL((char*)"/"); - SSDP.setModelName((char*)"ESP-12e"); - SSDP.setModelNumber((char*)"1.0"); - SSDP.setModelURL((char*)"http://12e.espressif.com"); - SSDP.setManufacturer((char*)"Espressif"); - SSDP.setManufacturerURL((char*)"http://espressif.com"); + SSDP.setSchemaURL((char*)"description.xml"); + SSDP.setHTTPPort(80); + SSDP.setName((char*)"Philips hue clone"); + SSDP.setSerialNumber((char*)"001788102201"); + SSDP.setURL((char*)"index.html"); + SSDP.setModelName((char*)"Philips hue bridge 2012"); + SSDP.setModelNumber((char*)"929000226503"); + SSDP.setModelURL((char*)"http://www.meethue.com"); + SSDP.setManufacturer((char*)"Royal Philips Electronics"); + SSDP.setManufacturerURL((char*)"http://www.philips.com"); Serial.printf("Ready!\n"); } else { diff --git a/libraries/ESP8266SSDP/keywords.txt b/libraries/ESP8266SSDP/keywords.txt index 505ddf4dfe..40070d672d 100644 --- a/libraries/ESP8266SSDP/keywords.txt +++ b/libraries/ESP8266SSDP/keywords.txt @@ -19,6 +19,8 @@ send KEYWORD2 schema KEYWORD2 setName KEYWORD2 setURL KEYWORD2 +setHTTPPort KEYWORD2 +setSchemaURL KEYWORD2 setSerialNumber KEYWORD2 setModelName KEYWORD2 setModelNumber KEYWORD2 From e34ae2d6f1820db63958cbc66b802c5043cbd299 Mon Sep 17 00:00:00 2001 From: John Doe Date: Sun, 5 Jul 2015 14:23:01 +0300 Subject: [PATCH 05/11] prep for icons --- libraries/ESP8266SSDP/ESP8266SSDP.cpp | 22 ++++++++++++++++++++-- libraries/ESP8266SSDP/ESP8266SSDP.h | 2 -- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.cpp b/libraries/ESP8266SSDP/ESP8266SSDP.cpp index f118fe951d..99ee9c761a 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.cpp +++ b/libraries/ESP8266SSDP/ESP8266SSDP.cpp @@ -35,6 +35,8 @@ extern "C" { } #include "lwip/igmp.h" +//#define DEBUG_SSDP Serial + #define SSDP_INTERVAL 1200 #define SSDP_PORT 1900 #define SSDP_METHOD_SIZE 10 @@ -70,7 +72,7 @@ const char* _ssdp_packet_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 - "LOCATION: http://%u.%u.%u.%u:%u/%s\r\n" // WiFi.localIP(), _port, _shemaURL + "LOCATION: http://%u.%u.%u.%u:%u/%s\r\n" // WiFi.localIP(), _port, _schemaURL "\r\n"; const char* _ssdp_schema_template = @@ -98,6 +100,22 @@ const char* _ssdp_schema_template = "%s" "uuid:%s" "" +// "" +// "" +// "image/png" +// "48" +// "48" +// "24" +// "icon48.png" +// "" +// "" +// "image/png" +// "120" +// "120" +// "24" +// "icon120.png" +// "" +// "" "\r\n" "\r\n"; @@ -154,7 +172,7 @@ void SSDPClass::begin(){ uint8_t mac[6]; WiFi.macAddress(mac); uint32_t chipId = ESP.getChipId(); - sprintf(_uuid, "38323636-4558-%04X-%04X-%02X%02X%02X%02X%02X%02X", + sprintf(_uuid, "38323636-4558-%04x-%04x-%02x%02x%02x%02x%02x%02x", (chipId >> 16) & 0xFFFF, chipId & 0xFFFF, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] ); diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.h b/libraries/ESP8266SSDP/ESP8266SSDP.h index aa696953bb..efaba1ac78 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.h +++ b/libraries/ESP8266SSDP/ESP8266SSDP.h @@ -33,8 +33,6 @@ License (MIT license): #include #include -#define DEBUG_SSDP Serial - typedef enum { NONE, SEARCH, From de70454a2a5eb275a0acf63763834c6bee1f0ee3 Mon Sep 17 00:00:00 2001 From: John Doe Date: Sun, 5 Jul 2015 19:15:13 +0300 Subject: [PATCH 06/11] send not needed to be public --- libraries/ESP8266SSDP/ESP8266SSDP.cpp | 6 +++--- libraries/ESP8266SSDP/ESP8266SSDP.h | 3 ++- libraries/ESP8266SSDP/keywords.txt | 1 - 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.cpp b/libraries/ESP8266SSDP/ESP8266SSDP.cpp index 99ee9c761a..081ca0419a 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.cpp +++ b/libraries/ESP8266SSDP/ESP8266SSDP.cpp @@ -182,7 +182,7 @@ void SSDPClass::begin(){ _server.begin(SSDP_PORT); } -void SSDPClass::send(ssdp_method_t method){ +void SSDPClass::_send(ssdp_method_t method){ #ifdef DEBUG_SSDP if(method == NONE){ DEBUG_SSDP.print("Sending Response to "); @@ -319,10 +319,10 @@ uint8_t SSDPClass::update(){ if(_pending && (millis() - _process_time) > _delay){ _pending = false; _delay = 0; - send(NONE); + _send(NONE); }else if(_notify_time == 0 || (millis() - _notify_time) > (SSDP_INTERVAL * 1000L)){ _notify_time = millis(); - send(NOTIFY); + _send(NOTIFY); } } diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.h b/libraries/ESP8266SSDP/ESP8266SSDP.h index efaba1ac78..1a25281513 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.h +++ b/libraries/ESP8266SSDP/ESP8266SSDP.h @@ -46,7 +46,6 @@ class SSDPClass{ void begin(); uint8_t update(); - void send(ssdp_method_t method); void schema(WiFiClient client); void setName(char *name); @@ -78,6 +77,8 @@ class SSDPClass{ char *_modelName; char *_modelURL; char *_modelNumber; + + void _send(ssdp_method_t method); }; extern SSDPClass SSDP; diff --git a/libraries/ESP8266SSDP/keywords.txt b/libraries/ESP8266SSDP/keywords.txt index 40070d672d..a01ce3dba4 100644 --- a/libraries/ESP8266SSDP/keywords.txt +++ b/libraries/ESP8266SSDP/keywords.txt @@ -15,7 +15,6 @@ SSDP KEYWORD1 begin KEYWORD2 update KEYWORD2 -send KEYWORD2 schema KEYWORD2 setName KEYWORD2 setURL KEYWORD2 From 49dc457fe54ad6a57cf4e20636c39956f72a9edc Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 7 Jul 2015 14:39:39 +0300 Subject: [PATCH 07/11] Add strlcpy implementation (#465) --- cores/esp8266/libc_replacements.c | 57 ++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/cores/esp8266/libc_replacements.c b/cores/esp8266/libc_replacements.c index e8e31afa4a..84ba411e0f 100644 --- a/cores/esp8266/libc_replacements.c +++ b/cores/esp8266/libc_replacements.c @@ -94,10 +94,6 @@ size_t ICACHE_FLASH_ATTR strnlen(const char *s, size_t len) { return (size_t)(cp - s); } -char* strstr(const char *haystack, const char *needle) { - return ets_strstr(haystack, needle); -} - char* ICACHE_FLASH_ATTR strchr(const char * str, int character) { while(1) { if(*str == 0x00) { @@ -443,3 +439,56 @@ int* ICACHE_FLASH_ATTR __errno(void) { return &errno_var; } + +/* + * begin newlib/string/strlcpy.c + * + * Copyright (c) 1998 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +size_t ICACHE_FLASH_ATTR strlcpy(char* dst, const char* src, size_t size) { + const char *s = src; + size_t n = size; + + if (n != 0 && --n != 0) { + do { + if ((*dst++ = *s++) == 0) + break; + } while (--n != 0); + } + + if (n == 0) { + if (size != 0) + *dst = 0; + while (*s++); + } + + return(s - src - 1); +} +/* + * end of newlib/string/strlcpy.c + */ + From 7fbb4831dad0f0bb07f4b09bf8c42a819c437f15 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 7 Jul 2015 14:42:20 +0300 Subject: [PATCH 08/11] Use static allocation, add convenience overloads which take String --- libraries/ESP8266SSDP/ESP8266SSDP.cpp | 93 +++++++++------------------ libraries/ESP8266SSDP/ESP8266SSDP.h | 58 +++++++++++------ 2 files changed, 69 insertions(+), 82 deletions(-) diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.cpp b/libraries/ESP8266SSDP/ESP8266SSDP.cpp index 081ca0419a..c381f7ff94 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.cpp +++ b/libraries/ESP8266SSDP/ESP8266SSDP.cpp @@ -25,14 +25,14 @@ License (MIT license): THE SOFTWARE. */ - +#define LWIP_OPEN_SRC #include "ESP8266SSDP.h" extern "C" { - #include "ip_addr.h" #include "user_interface.h" #include "mem.h" } +#include "lwip/ip_addr.h" #include "lwip/igmp.h" //#define DEBUG_SSDP Serial @@ -43,31 +43,20 @@ extern "C" { #define SSDP_URI_SIZE 2 #define SSDP_BUFFER_SIZE 64 -#define SSDP_UUID_SIZE 37 -#define SSDP_SCHEMA_URL_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 - static const IPAddress SSDP_MULTICAST_ADDR(239, 255, 255, 250); -const char* _ssdp_response_template = +static const char* _ssdp_response_template = "HTTP/1.1 200 OK\r\n" "EXT:\r\n" "ST: upnp:rootdevice\r\n"; -const char* _ssdp_notify_template = +static const char* _ssdp_notify_template = "NOTIFY * HTTP/1.1\r\n" "HOST: 239.255.255.250:1900\r\n" "NT: upnp:rootdevice\r\n" "NTS: ssdp:alive\r\n"; -const char* _ssdp_packet_template = +static const char* _ssdp_packet_template = "%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 @@ -75,7 +64,7 @@ const char* _ssdp_packet_template = "LOCATION: http://%u.%u.%u.%u:%u/%s\r\n" // WiFi.localIP(), _port, _schemaURL "\r\n"; -const char* _ssdp_schema_template = +static const char* _ssdp_schema_template = "HTTP/1.1 200 OK\r\n" "Content-Type: text/xml\r\n" "Connection: close\r\n" @@ -120,17 +109,6 @@ const char* _ssdp_schema_template = "\r\n"; SSDPClass::SSDPClass(){ - _uuid = (char*)os_malloc(SSDP_UUID_SIZE); - _schemaURL = (char*)os_malloc(SSDP_SCHEMA_URL_SIZE); - _friendlyName = (char*)os_malloc(SSDP_FRIENDLY_NAME_SIZE); - _presentationURL = (char*)os_malloc(SSDP_PRESENTATION_URL_SIZE); - _serialNumber = (char*)os_malloc(SSDP_SERIAL_NUMBER_SIZE); - _modelName = (char*)os_malloc(SSDP_MODEL_NAME_SIZE); - _modelNumber = (char*)os_malloc(SSDP_MODEL_VERSION_SIZE); - _modelURL = (char*)os_malloc(SSDP_MODEL_URL_SIZE); - _manufacturer = (char*)os_malloc(SSDP_MANUFACTURER_SIZE); - _manufacturerURL = (char*)os_malloc(SSDP_MANUFACTURER_URL_SIZE); - _uuid[0] = '\0'; _modelNumber[0] = '\0'; _friendlyName[0] = '\0'; @@ -146,17 +124,6 @@ SSDPClass::SSDPClass(){ } SSDPClass::~SSDPClass(){ - os_free(_uuid); - os_free(_schemaURL); - os_free(_friendlyName); - os_free(_presentationURL); - os_free(_serialNumber); - os_free(_modelName); - os_free(_modelNumber); - os_free(_modelURL); - os_free(_manufacturer); - os_free(_manufacturerURL); - _pending = false; } void SSDPClass::begin(){ @@ -207,7 +174,7 @@ void SSDPClass::_send(ssdp_method_t method){ SSDP_INTERVAL, _modelName, _modelNumber, _uuid, - (uint8_t)(ip & 0xFF), (uint8_t)((ip >> 8) & 0xFF), (uint8_t)((ip >> 16) & 0xFF), (uint8_t)((ip >> 24) & 0xFF), _port, _schemaURL + IP2STR(&ip), _port, _schemaURL ); _server.endPacket(); @@ -216,7 +183,7 @@ void SSDPClass::_send(ssdp_method_t method){ void SSDPClass::schema(WiFiClient client){ uint32_t ip = WiFi.localIP(); client.printf(_ssdp_schema_template, - (uint8_t)(ip & 0xFF), (uint8_t)((ip >> 8) & 0xFF), (uint8_t)((ip >> 16) & 0xFF), (uint8_t)((ip >> 24) & 0xFF), _port, + IP2STR(&ip), _port, _friendlyName, _presentationURL, _serialNumber, @@ -259,14 +226,14 @@ uint8_t SSDPClass::update(){ 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; 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; } @@ -298,7 +265,7 @@ uint8_t SSDPClass::update(){ } if(state != ABORT){ state = KEY; header = START; cursor = 0; } - }else if(c != '\r' && c != '\n'){ + } 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; @@ -320,50 +287,50 @@ uint8_t SSDPClass::update(){ if(_pending && (millis() - _process_time) > _delay){ _pending = false; _delay = 0; _send(NONE); - }else if(_notify_time == 0 || (millis() - _notify_time) > (SSDP_INTERVAL * 1000L)){ + } else if(_notify_time == 0 || (millis() - _notify_time) > (SSDP_INTERVAL * 1000L)){ _notify_time = millis(); _send(NOTIFY); } } -void SSDPClass::setSchemaURL(char *url){ - strcpy(_schemaURL, url); +void SSDPClass::setSchemaURL(const char *url){ + strlcpy(_schemaURL, url, sizeof(_schemaURL)); } void SSDPClass::setHTTPPort(uint16_t port){ _port = port; } -void SSDPClass::setName(char *name){ - strcpy(_friendlyName, name); +void SSDPClass::setName(const char *name){ + strlcpy(_friendlyName, name, sizeof(_friendlyName)); } -void SSDPClass::setURL(char *url){ - strcpy(_presentationURL, url); +void SSDPClass::setURL(const char *url){ + strlcpy(_presentationURL, url, sizeof(_presentationURL)); } -void SSDPClass::setSerialNumber(char *serialNumber){ - strcpy(_serialNumber, serialNumber); +void SSDPClass::setSerialNumber(const char *serialNumber){ + strlcpy(_serialNumber, serialNumber, sizeof(_serialNumber)); } -void SSDPClass::setModelName(char *name){ - strcpy(_modelName, name); +void SSDPClass::setModelName(const char *name){ + strlcpy(_modelName, name, sizeof(_modelName)); } -void SSDPClass::setModelNumber(char *num){ - strcpy(_modelNumber, num); +void SSDPClass::setModelNumber(const char *num){ + strlcpy(_modelNumber, num, sizeof(_modelNumber)); } -void SSDPClass::setModelURL(char *url){ - strcpy(_modelURL, url); +void SSDPClass::setModelURL(const char *url){ + strlcpy(_modelURL, url, sizeof(_modelURL)); } -void SSDPClass::setManufacturer(char *name){ - strcpy(_manufacturer, name); +void SSDPClass::setManufacturer(const char *name){ + strlcpy(_manufacturer, name, sizeof(_manufacturer)); } -void SSDPClass::setManufacturerURL(char *url){ - strcpy(_manufacturerURL, url); +void SSDPClass::setManufacturerURL(const char *url){ + strlcpy(_manufacturerURL, url, sizeof(_manufacturerURL)); } SSDPClass SSDP; diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.h b/libraries/ESP8266SSDP/ESP8266SSDP.h index 1a25281513..44e8b44235 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.h +++ b/libraries/ESP8266SSDP/ESP8266SSDP.h @@ -33,6 +33,17 @@ License (MIT license): #include #include +#define SSDP_UUID_SIZE 37 +#define SSDP_SCHEMA_URL_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, @@ -48,16 +59,25 @@ class SSDPClass{ uint8_t update(); void schema(WiFiClient client); - void setName(char *name); - void setURL(char *url); - void setSchemaURL(char *url); + 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 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 setSerialNumber(char *serialNumber); - void setModelName(char *name); - void setModelNumber(char *num); - void setModelURL(char *url); - void setManufacturer(char *name); - void setManufacturerURL(char *url); private: WiFiUDP _server; @@ -67,16 +87,16 @@ class SSDPClass{ unsigned long _notify_time; uint16_t _port; - char *_schemaURL; - char *_uuid; - char *_friendlyName; - char *_serialNumber; - char *_presentationURL; - char *_manufacturer; - char *_manufacturerURL; - char *_modelName; - char *_modelURL; - char *_modelNumber; + char _schemaURL[SSDP_SCHEMA_URL_SIZE]; + char _uuid[SSDP_UUID_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]; void _send(ssdp_method_t method); }; From 0c0892c54adf7cd56a9b5240ed186619853ab971 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 7 Jul 2015 14:43:19 +0300 Subject: [PATCH 09/11] Update example and move it to the right location --- .../ESP8266SSDP/examples/{ => SSDP}/SSDP.ino | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) rename libraries/ESP8266SSDP/examples/{ => SSDP}/SSDP.ino (66%) diff --git a/libraries/ESP8266SSDP/examples/SSDP.ino b/libraries/ESP8266SSDP/examples/SSDP/SSDP.ino similarity index 66% rename from libraries/ESP8266SSDP/examples/SSDP.ino rename to libraries/ESP8266SSDP/examples/SSDP/SSDP.ino index 2f2d66ee70..be4c0791ec 100644 --- a/libraries/ESP8266SSDP/examples/SSDP.ino +++ b/libraries/ESP8266SSDP/examples/SSDP/SSDP.ino @@ -27,17 +27,17 @@ void setup() { HTTP.begin(); Serial.printf("Starting SSDP...\n"); - SSDP.begin(); - SSDP.setSchemaURL((char*)"description.xml"); + SSDP.setSchemaURL("description.xml"); SSDP.setHTTPPort(80); - SSDP.setName((char*)"Philips hue clone"); - SSDP.setSerialNumber((char*)"001788102201"); - SSDP.setURL((char*)"index.html"); - SSDP.setModelName((char*)"Philips hue bridge 2012"); - SSDP.setModelNumber((char*)"929000226503"); - SSDP.setModelURL((char*)"http://www.meethue.com"); - SSDP.setManufacturer((char*)"Royal Philips Electronics"); - SSDP.setManufacturerURL((char*)"http://www.philips.com"); + SSDP.setName("Philips hue clone"); + SSDP.setSerialNumber("001788102201"); + SSDP.setURL("index.html"); + SSDP.setModelName("Philips hue bridge 2012"); + SSDP.setModelNumber("929000226503"); + SSDP.setModelURL("http://www.meethue.com"); + SSDP.setManufacturer("Royal Philips Electronics"); + SSDP.setManufacturerURL("http://www.philips.com"); + SSDP.begin(); Serial.printf("Ready!\n"); } else { From 1b27b6760cc7514c8760d45b7f691545f5a22202 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 7 Jul 2015 17:39:13 +0300 Subject: [PATCH 10/11] Make SSDP event-driven --- libraries/ESP8266SSDP/ESP8266SSDP.cpp | 164 +++++++++++++------ libraries/ESP8266SSDP/ESP8266SSDP.h | 27 ++- libraries/ESP8266SSDP/examples/SSDP/SSDP.ino | 1 - 3 files changed, 137 insertions(+), 55 deletions(-) diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.cpp b/libraries/ESP8266SSDP/ESP8266SSDP.cpp index c381f7ff94..24997eee84 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.cpp +++ b/libraries/ESP8266SSDP/ESP8266SSDP.cpp @@ -26,25 +26,36 @@ License (MIT license): */ #define LWIP_OPEN_SRC +#include #include "ESP8266SSDP.h" +#include "WiFiUdp.h" +#include "debug.h" extern "C" { + #include "osapi.h" + #include "ets_sys.h" #include "user_interface.h" - #include "mem.h" } -#include "lwip/ip_addr.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 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 1 static const IPAddress SSDP_MULTICAST_ADDR(239, 255, 255, 250); + + static const char* _ssdp_response_template = "HTTP/1.1 200 OK\r\n" "EXT:\r\n" @@ -108,7 +119,17 @@ static const char* _ssdp_schema_template = "\r\n" "\r\n"; -SSDPClass::SSDPClass(){ + +struct SSDPTimer { + ETSTimer timer; +}; + +SSDPClass::SSDPClass() : +_server(0), +_port(80), +_pending(false), +_timer(new SSDPTimer) +{ _uuid[0] = '\0'; _modelNumber[0] = '\0'; _friendlyName[0] = '\0'; @@ -119,65 +140,95 @@ SSDPClass::SSDPClass(){ _manufacturer[0] = '\0'; _manufacturerURL[0] = '\0'; sprintf(_schemaURL, "ssdp/schema.xml"); - _port = 80; - _pending = false; } SSDPClass::~SSDPClass(){ + delete _timer; } -void SSDPClass::begin(){ - ip_addr_t ifaddr; - ip_addr_t multicast_addr; - +bool SSDPClass::begin(){ _pending = false; - - ifaddr.addr = WiFi.localIP(); - multicast_addr.addr = (uint32_t) SSDP_MULTICAST_ADDR; - igmp_joingroup(&ifaddr, &multicast_addr); - - uint8_t mac[6]; - WiFi.macAddress(mac); + uint32_t chipId = ESP.getChipId(); - sprintf(_uuid, "38323636-4558-%04x-%04x-%02x%02x%02x%02x%02x%02x", - (chipId >> 16) & 0xFFFF, chipId & 0xFFFF, - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] - ); + 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 - _server.begin(SSDP_PORT); -} -void SSDPClass::_send(ssdp_method_t method){ -#ifdef DEBUG_SSDP - if(method == NONE){ - DEBUG_SSDP.print("Sending Response to "); - DEBUG_SSDP.print(_server.remoteIP()); - DEBUG_SSDP.print(":"); - DEBUG_SSDP.println(_server.remotePort()); - }else if(method == NOTIFY){ - DEBUG_SSDP.println("Sending Notify to 239.255.255.250:1900"); + 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; } -#endif - if(method == NONE){ - _server.beginPacket(_server.remoteIP(), _server.remotePort()); - } else { - _server.beginPacket(SSDP_MULTICAST_ADDR, SSDP_PORT); + if (!_server->listen(*IP_ADDR_ANY, SSDP_PORT)) { + return false; + } + + _server->setMulticastInterface(ifaddr); + _server->setMulticastTTL(SSDP_MULTICAST_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(); - _server.printf(_ssdp_packet_template, + int len = snprintf(buffer, sizeof(buffer), + _ssdp_packet_template, (method == NONE)?_ssdp_response_template:_ssdp_notify_template, SSDP_INTERVAL, _modelName, _modelNumber, _uuid, IP2STR(&ip), _port, _schemaURL ); - - _server.endPacket(); + + _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){ @@ -196,10 +247,13 @@ void SSDPClass::schema(WiFiClient client){ ); } -uint8_t SSDPClass::update(){ - if(!_pending && _server.parsePacket() > 0){ +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; @@ -211,8 +265,8 @@ uint8_t SSDPClass::update(){ char buffer[SSDP_BUFFER_SIZE] = {0}; - while(_server.available() > 0){ - char c = _server.read(); + while(_server->getSize() > 0){ + char c = _server->read(); (c == '\r' || c == '\n') ? cr++ : cr = 0; @@ -280,8 +334,6 @@ uint8_t SSDPClass::update(){ break; } } - - _server.flush(); } if(_pending && (millis() - _process_time) > _delay){ @@ -291,6 +343,12 @@ uint8_t SSDPClass::update(){ _notify_time = millis(); _send(NOTIFY); } + + if (_pending) { + while (_server->next()) + _server->flush(); + } + } void SSDPClass::setSchemaURL(const char *url){ @@ -333,4 +391,16 @@ void SSDPClass::setManufacturerURL(const char *url){ strlcpy(_manufacturerURL, url, sizeof(_manufacturerURL)); } +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(&SSDPClass::_onTimerStatic), reinterpret_cast(this)); + os_timer_arm(tm, interval, 1 /* repeat */); +} + SSDPClass SSDP; diff --git a/libraries/ESP8266SSDP/ESP8266SSDP.h b/libraries/ESP8266SSDP/ESP8266SSDP.h index 44e8b44235..8f6e280f3a 100644 --- a/libraries/ESP8266SSDP/ESP8266SSDP.h +++ b/libraries/ESP8266SSDP/ESP8266SSDP.h @@ -33,6 +33,8 @@ License (MIT license): #include #include +class UdpContext; + #define SSDP_UUID_SIZE 37 #define SSDP_SCHEMA_URL_SIZE 64 #define SSDP_FRIENDLY_NAME_SIZE 64 @@ -50,13 +52,16 @@ typedef enum { NOTIFY } ssdp_method_t; + +struct SSDPTimer; + class SSDPClass{ public: SSDPClass(); ~SSDPClass(); - void begin(); - uint8_t update(); + bool begin(); + void schema(WiFiClient client); void setName(const String& name) { setName(name.c_str()); } @@ -78,9 +83,19 @@ class SSDPClass{ void setManufacturerURL(const String& url) { setManufacturerURL(url.c_str()); } void setManufacturerURL(const char *url); void setHTTPPort(uint16_t port); - - private: - WiFiUDP _server; + + protected: + void _send(ssdp_method_t method); + void _update(); + void _startTimer(); + static void _onTimerStatic(SSDPClass* self); + + UdpContext* _server; + SSDPTimer* _timer; + + IPAddress _respondToAddr; + uint16_t _respondToPort; + bool _pending; unsigned short _delay; unsigned long _process_time; @@ -97,8 +112,6 @@ class SSDPClass{ char _modelName[SSDP_MODEL_NAME_SIZE]; char _modelURL[SSDP_MODEL_URL_SIZE]; char _modelNumber[SSDP_MODEL_VERSION_SIZE]; - - void _send(ssdp_method_t method); }; extern SSDPClass SSDP; diff --git a/libraries/ESP8266SSDP/examples/SSDP/SSDP.ino b/libraries/ESP8266SSDP/examples/SSDP/SSDP.ino index be4c0791ec..a1f55a8480 100644 --- a/libraries/ESP8266SSDP/examples/SSDP/SSDP.ino +++ b/libraries/ESP8266SSDP/examples/SSDP/SSDP.ino @@ -48,6 +48,5 @@ void setup() { void loop() { HTTP.handleClient(); - SSDP.update(); delay(1); } From 1be16c74c78054ca81811d58a993366a648ae247 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 7 Jul 2015 17:58:49 +0300 Subject: [PATCH 11/11] Remove update keyword --- libraries/ESP8266SSDP/keywords.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/ESP8266SSDP/keywords.txt b/libraries/ESP8266SSDP/keywords.txt index a01ce3dba4..241d341454 100644 --- a/libraries/ESP8266SSDP/keywords.txt +++ b/libraries/ESP8266SSDP/keywords.txt @@ -14,7 +14,6 @@ SSDP KEYWORD1 ####################################### begin KEYWORD2 -update KEYWORD2 schema KEYWORD2 setName KEYWORD2 setURL KEYWORD2