From aadb8b01f4d1dad6ad6f10da7cdfa3dcd2749353 Mon Sep 17 00:00:00 2001 From: Luc <8822552+luc-github@users.noreply.github.com> Date: Thu, 18 Jun 2020 12:44:36 +0200 Subject: [PATCH] Update SSDP library with latest --- libraries/ESP32SSDP-1.0.1/ESP32SSDP.cpp | 479 ------------ .../ESP32SSDP-1.0.1/examples/SSDP/SSDP.ino | 52 -- libraries/ESP32SSDP-1.1.0/.astylerc | 1 + libraries/ESP32SSDP-1.1.0/.travis.yml | 64 ++ libraries/ESP32SSDP-1.1.0/ESP32SSDP.cpp | 710 ++++++++++++++++++ .../ESP32SSDP.h | 112 ++- .../README.rst => ESP32SSDP-1.1.0/README.md} | 6 +- libraries/ESP32SSDP-1.1.0/command.sh | 19 + .../ESP32SSDP-1.1.0/examples/SSDP/SSDP.ino | 105 +++ .../keywords.txt | 0 .../library.properties | 2 +- libraries/ESP32SSDP-1.1.0/set_style.bat | 4 + .../ESP32SSDP-1.1.0/test/install_astyle.sh | 16 + libraries/ESP32SSDP-1.1.0/test/platformio.ini | 30 + 14 files changed, 1047 insertions(+), 553 deletions(-) delete mode 100644 libraries/ESP32SSDP-1.0.1/ESP32SSDP.cpp delete mode 100644 libraries/ESP32SSDP-1.0.1/examples/SSDP/SSDP.ino create mode 100644 libraries/ESP32SSDP-1.1.0/.astylerc create mode 100644 libraries/ESP32SSDP-1.1.0/.travis.yml create mode 100644 libraries/ESP32SSDP-1.1.0/ESP32SSDP.cpp rename libraries/{ESP32SSDP-1.0.1 => ESP32SSDP-1.1.0}/ESP32SSDP.h (60%) rename libraries/{ESP32SSDP-1.0.1/README.rst => ESP32SSDP-1.1.0/README.md} (56%) create mode 100644 libraries/ESP32SSDP-1.1.0/command.sh create mode 100644 libraries/ESP32SSDP-1.1.0/examples/SSDP/SSDP.ino rename libraries/{ESP32SSDP-1.0.1 => ESP32SSDP-1.1.0}/keywords.txt (100%) rename libraries/{ESP32SSDP-1.0.1 => ESP32SSDP-1.1.0}/library.properties (93%) create mode 100644 libraries/ESP32SSDP-1.1.0/set_style.bat create mode 100644 libraries/ESP32SSDP-1.1.0/test/install_astyle.sh create mode 100644 libraries/ESP32SSDP-1.1.0/test/platformio.ini diff --git a/libraries/ESP32SSDP-1.0.1/ESP32SSDP.cpp b/libraries/ESP32SSDP-1.0.1/ESP32SSDP.cpp deleted file mode 100644 index bbe03dce..00000000 --- a/libraries/ESP32SSDP-1.0.1/ESP32SSDP.cpp +++ /dev/null @@ -1,479 +0,0 @@ -/* -ESP32 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. - -*/ -#ifdef ARDUINO_ARCH_ESP32 -#include -#include "ESP32SSDP.h" -#include "WiFiUdp.h" -#include - -//#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" - "" - "" - "" - "1" - "0" - "" - "http://%u.%u.%u.%u:%u/" // WiFi.localIP(), _port - "" - "%s" - "%s" - "%s" - "%s" - "%s" - "%s" - "%s" - "%s" - "%s" - "uuid:%s" - "" -// "" -// "" -// "image/png" -// "48" -// "48" -// "24" -// "icon48.png" -// "" -// "" -// "image/png" -// "120" -// "120" -// "24" -// "icon120.png" -// "" -// "" - "\r\n" - "\r\n"; - -struct SSDPTimer { - ETSTimer timer; -}; - -SSDPClass::SSDPClass() : -_server(0), -_timer(0), -_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(){ - end(); -} - -void SSDPClass::end(){ - if(!_server) { - return; - } -#ifdef DEBUG_SSDP - DEBUG_SSDP.printf_P(PSTR("SSDP end ... ")); -#endif - // undo all initializations done in begin(), in reverse order - _stopTimer(); - _server->stop(); - delete (_server); - _server = 0; -} - -IPAddress SSDPClass::localIP(){ - tcpip_adapter_ip_info_t ip; - if (WiFi.getMode() == WIFI_STA) { - if (tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip)) { - return IPAddress(); - } - } else if (WiFi.getMode() == WIFI_OFF) { - if (tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)) { - return IPAddress(); - } - } - return IPAddress(ip.ip.addr); -} - -bool SSDPClass::begin(){ - _pending = false; - end(); - uint32_t chipId = ((uint16_t) (ESP.getEfuseMac() >> 32)); - sprintf(_uuid, "38323636-4558-4dda-9188-cda0e6%02x%02x%02x", - (uint16_t) ((chipId >> 16) & 0xff), - (uint16_t) ((chipId >> 8) & 0xff), - (uint16_t) chipId & 0xff ); - assert(nullptr == _server); - _server = new WiFiUDP; -#ifdef DEBUG_SSDP - DEBUG_SSDP.printf("SSDP UUID: %s\n", (char *)_uuid); -#endif - - - _server = new WiFiUDP; - if (!(_server->beginMulticast(IPAddress(SSDP_MULTICAST_ADDR), SSDP_PORT))) { -#ifdef DEBUG_SSDP - DEBUG_SSDP.println("Error begin"); -#endif - return false; - } - - _startTimer(); - - return true; -} - -void SSDPClass::_send(ssdp_method_t method){ - char buffer[1460]; - IPAddress ip = localIP(); - - 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 - ); - if(len < 0) return; - IPAddress remoteAddr; - uint16_t remotePort; - if(method == NONE) { - remoteAddr = _respondToAddr; - remotePort = _respondToPort; -#ifdef DEBUG_SSDP - DEBUG_SSDP.print("Sending Response to "); -#endif - } else { - remoteAddr = IPAddress(SSDP_MULTICAST_ADDR); - remotePort = SSDP_PORT; -#ifdef DEBUG_SSDP - DEBUG_SSDP.println("Sending Notify to "); -#endif - } -#ifdef DEBUG_SSDP - DEBUG_SSDP.print(remoteAddr); - DEBUG_SSDP.print(":"); - DEBUG_SSDP.println(remotePort); -#endif - _server->beginPacket(remoteAddr, remotePort); - _server->println(buffer); - _server->endPacket(); -} - -void SSDPClass::schema(WiFiClient client){ - IPAddress ip = localIP(); - 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 - ); -} - -void SSDPClass::_update(){ - int nbBytes =0; - char * packetBuffer = nullptr; - - if(!_pending && _server) { - ssdp_method_t method = NONE; - nbBytes= _server->parsePacket(); - 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}; - packetBuffer = new char[nbBytes +1]; - int message_size=_server->read(packetBuffer,nbBytes); - int process_pos = 0; - packetBuffer[message_size]='\0'; - _respondToAddr = _server->remoteIP(); - _respondToPort = _server->remotePort(); -#ifdef DEBUG_SSDP - if (message_size) { - DEBUG_SSDP.println("****************************************************"); - DEBUG_SSDP.println(_server->remoteIP()); - DEBUG_SSDP.println(packetBuffer); - DEBUG_SSDP.println("****************************************************"); - } -#endif - while(process_pos < message_size){ - - char c = packetBuffer[process_pos]; - process_pos++; - (c == '\r' || c == '\n') ? cr++ : cr = 0; -#ifdef DEBUG_SSDP - if ((c == '\r' || c == '\n') && (cr < 2)) DEBUG_SSDP.println(buffer); -#endif - switch(state){ - case METHOD: - if(c == ' '){ - if(strcmp(buffer, "M-SEARCH") == 0) method = SEARCH; - - 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(strcasecmp(buffer, _deviceType) == 0){ - _pending = true; - _process_time = 0; -#ifdef DEBUG_SSDP - DEBUG_SSDP.println("the search type matches our type"); -#endif - 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(packetBuffer) delete packetBuffer; - if(_pending && (millis() - _process_time) > _delay){ - _pending = false; _delay = 0; -#ifdef DEBUG_SSDP - DEBUG_SSDP.println("Send None"); -#endif - _send(NONE); - } else if(_notify_time == 0 || (millis() - _notify_time) > (SSDP_INTERVAL * 1000L)){ - _notify_time = millis(); - #ifdef DEBUG_SSDP - DEBUG_SSDP.println("Send Notify"); -#endif - _send(NOTIFY); - } else { -#ifdef DEBUG_SSDP - DEBUG_SSDP.println("Do not sent"); -#endif - } - - if (_pending) { - _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) { -#ifdef DEBUG_SSDP - DEBUG_SSDP.println("Update"); -#endif - self->_update(); -} - -void SSDPClass::_startTimer() { - _stopTimer(); - _timer= new SSDPTimer(); - ETSTimer* tm = &(_timer->timer); - const int interval = 1000; - ets_timer_disarm(tm); - ets_timer_setfn(tm, reinterpret_cast(&SSDPClass::_onTimerStatic), reinterpret_cast(this)); - ets_timer_arm(tm, interval, 1 /* repeat */); -} - -void SSDPClass::_stopTimer() { - if(!_timer){ - return; - } - ETSTimer* tm = &(_timer->timer); - ets_timer_disarm(tm); - delete _timer; - _timer = nullptr; -} - -#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SSDP) -SSDPClass SSDP; -#endif - -#endif \ No newline at end of file diff --git a/libraries/ESP32SSDP-1.0.1/examples/SSDP/SSDP.ino b/libraries/ESP32SSDP-1.0.1/examples/SSDP/SSDP.ino deleted file mode 100644 index 46f02438..00000000 --- a/libraries/ESP32SSDP-1.0.1/examples/SSDP/SSDP.ino +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include - -const char* ssid = "********"; -const char* password = "********"; - -WebServer HTTP(80); - -void setup() { - Serial.begin(115200); - Serial.println(); - Serial.println("Starting WiFi..."); - - WiFi.mode(WIFI_STA); - WiFi.begin(ssid, password); - if(WiFi.waitForConnectResult() == WL_CONNECTED){ - - Serial.printf("Starting HTTP...\n"); - HTTP.on("/index.html", HTTP_GET, [](){ - HTTP.send(200, "text/plain", "Hello World!"); - }); - HTTP.on("/description.xml", HTTP_GET, [](){ - SSDP.schema(HTTP.client()); - }); - HTTP.begin(); - - Serial.printf("Starting SSDP...\n"); - SSDP.setSchemaURL("description.xml"); - SSDP.setHTTPPort(80); - 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.setDeviceType("upnp:rootdevice"); //to appear as root device - SSDP.begin(); - - Serial.printf("Ready!\n"); - } else { - Serial.printf("WiFi Failed\n"); - while(1) delay(100); - } -} - -void loop() { - HTTP.handleClient(); - delay(1); -} diff --git a/libraries/ESP32SSDP-1.1.0/.astylerc b/libraries/ESP32SSDP-1.1.0/.astylerc new file mode 100644 index 00000000..a5ed8f51 --- /dev/null +++ b/libraries/ESP32SSDP-1.1.0/.astylerc @@ -0,0 +1 @@ +style=otbs diff --git a/libraries/ESP32SSDP-1.1.0/.travis.yml b/libraries/ESP32SSDP-1.1.0/.travis.yml new file mode 100644 index 00000000..3a87e753 --- /dev/null +++ b/libraries/ESP32SSDP-1.1.0/.travis.yml @@ -0,0 +1,64 @@ +dist: xenial +sudo: require + +language: python + +python: + - "3.7" + +os: + - linux + +cache: + pip: true + directories: + - "~/.platformio" + - $HOME/astyle + +install: + - pip install -U platformio + +before_script: + - platformio update + - wget http://downloads.arduino.cc/arduino-1.8.5-linux64.tar.xz + - tar xf arduino-1.8.5-linux64.tar.xz + - mv arduino-1.8.5 $HOME/arduino_ide + - cd $HOME/arduino_ide/hardware + - mkdir esp32 + - cd esp32 + - git clone https://github.com/espressif/arduino-esp32.git esp32 + - cd esp32 + - git submodule update --init --recursive + - cd tools + - python get.py + - cd $TRAVIS_BUILD_DIR + - cp -r $TRAVIS_BUILD_DIR $HOME/arduino_ide/libraries/ + - sh test/install_astyle.sh + +script: + - cd $TRAVIS_BUILD_DIR + - export ARTISTIC_STYLE_OPTIONS=".astylerc" + - astyle -Q `find . -name *.cpp -o -name *.ino -o -name *.h` > astyle.out + - TEST=$(cat astyle.out | wc -l) + - | + if [[ $TEST -ne 0 ]]; then + cat astyle.out + git --no-pager diff + echo "Please fix style issues as shown above" + exit 1 + fi + - source command.sh + - export PATH="$HOME/arduino_ide:$PATH" + - rm -f $HOME/.arduino15/preferences.txt + - arduino --board esp32:esp32:esp32:PartitionScheme=min_spiffs,FlashFreq=80,PSRAM=disabled,CPUFreq=240,FlashMode=qio,FlashSize=4M,DebugLevel=none --pref compiler.warning_level=all --save-prefs + - build_sketch $TRAVIS_BUILD_DIR/examples/SSDP/SSDP.ino + - rm -fr $HOME/arduino_ide + - rm -fr $HOME/.arduino15 + - cp $TRAVIS_BUILD_DIR/test/platformio.ini $TRAVIS_BUILD_DIR/examples/SSDP/ + - cd $TRAVIS_BUILD_DIR/examples/SSDP/ + - platformio run + +notifications: + email: + on_success: change + on_failure: change diff --git a/libraries/ESP32SSDP-1.1.0/ESP32SSDP.cpp b/libraries/ESP32SSDP-1.1.0/ESP32SSDP.cpp new file mode 100644 index 00000000..c0dce245 --- /dev/null +++ b/libraries/ESP32SSDP-1.1.0/ESP32SSDP.cpp @@ -0,0 +1,710 @@ +/* +ESP32 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. + +*/ +#ifdef ARDUINO_ARCH_ESP32 +#include +#include "ESP32SSDP.h" +#include "WiFiUdp.h" +#include + +//#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); +#define SSDP_UUID_ROOT "38323636-4558-4dda-9188-cda0e6" + + +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" // _interval + "SERVER: %s UPNP/1.1 %s/%s\r\n" // _servername, _modelName, _modelNumber + "USN: uuid:%s%s\r\n" // _uuid, _usn_suffix + "%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" + "" + "" + "" + "1" + "0" + "" + "http://%u.%u.%u.%u:%u/" // WiFi.localIP(), _port + "" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "uuid:%s" + "%s" + "" + "%s" + "\r\n" + "\r\n"; + +struct SSDPTimer { + ETSTimer timer; +}; + +SSDPClass::SSDPClass() : + _server(0), + _timer(0), + _port(80), + _ttl(SSDP_MULTICAST_TTL), + _interval(SSDP_INTERVAL), + _replySlots{NULL}, + _respondToAddr{0,0,0,0}, + _respondToPort(0), + _pending(false), + _stmatch(false), + _delay(0), + _process_time(0), + _notify_time(0) +{ + _uuid[0] = '\0'; + _usn_suffix[0] = '\0'; + _respondType[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'; + _servername = "Arduino/1.0"; + sprintf(_schemaURL, "ssdp/schema.xml"); + _schema = nullptr; +} + +SSDPClass::~SSDPClass() +{ + end(); +} + +void SSDPClass::end() +{ + if (_schema) { + free(_schema); + _schema = nullptr; + } + if(!_server) { + return; + } +#ifdef DEBUG_SSDP + DEBUG_SSDP.printf_P(PSTR("SSDP end ... ")); +#endif + // undo all initializations done in begin(), in reverse order + _stopTimer(); + _server->stop(); + delete (_server); + _server = 0; +} + +IPAddress SSDPClass::localIP() +{ + tcpip_adapter_ip_info_t ip; + if (WiFi.getMode() == WIFI_STA) { + if (tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip)) { + return IPAddress(); + } + } else if (WiFi.getMode() == WIFI_OFF) { + if (tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)) { + return IPAddress(); + } + } + return IPAddress(ip.ip.addr); +} + +void SSDPClass::setUUID(const char *uuid, bool rootonly) +{ + //no sanity check is done - TBD + if (rootonly) { + uint32_t chipId = ((uint16_t) (ESP.getEfuseMac() >> 32)); + sprintf(_uuid, "%s%02x%02x%02x", + uuid, + (uint16_t) ((chipId >> 16) & 0xff), + (uint16_t) ((chipId >> 8) & 0xff), + (uint16_t) chipId & 0xff ); + } else { + strlcpy(_uuid, uuid,sizeof(_uuid)); + } +} + +bool SSDPClass::begin() +{ + _pending = false; + _stmatch = false; + end(); + if (strlen(_uuid) == 0) { + setUUID(SSDP_UUID_ROOT); + } +#ifdef DEBUG_SSDP + DEBUG_SSDP.printf("SSDP UUID: %s\n", (char *)_uuid); +#endif + assert(nullptr == _server); + _server = new WiFiUDP; + if (!(_server->beginMulticast(IPAddress(SSDP_MULTICAST_ADDR), SSDP_PORT))) { +#ifdef DEBUG_SSDP + DEBUG_SSDP.println("Error begin"); +#endif + return false; + } + + _startTimer(); + + return true; +} + +void SSDPClass::_send(ssdp_method_t method) +{ + char buffer[1460]; + IPAddress ip = localIP(); + + 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, + _interval, + _servername.c_str(), + _modelName, _modelNumber, + _uuid, _usn_suffix, + (method == NONE)?"ST":"NT", + _respondType, + ip[0], ip[1], ip[2], ip[3], _port, _schemaURL + ); + if(len < 0) { + return; + } + IPAddress remoteAddr; + uint16_t remotePort; + if(method == NONE) { + remoteAddr = _respondToAddr; + remotePort = _respondToPort; +#ifdef DEBUG_SSDP + DEBUG_SSDP.print("Sending Response to "); +#endif + } else { + remoteAddr = IPAddress(SSDP_MULTICAST_ADDR); + remotePort = SSDP_PORT; +#ifdef DEBUG_SSDP + DEBUG_SSDP.print("Sending Notify to "); +#endif + } +#ifdef DEBUG_SSDP + DEBUG_SSDP.print(remoteAddr); + DEBUG_SSDP.print(":"); + DEBUG_SSDP.println(remotePort); +#endif + _server->beginPacket(remoteAddr, remotePort); + _server->println(buffer); +#ifdef DEBUG_SSDP + DEBUG_SSDP.println("*************************TX*************************"); + DEBUG_SSDP.println(buffer); + DEBUG_SSDP.println("****************************************************"); +#endif + _server->endPacket(); +} + +const char * SSDPClass::schema() +{ + uint len = strlen(_ssdp_schema_template) + + 21 //(IP = 15) + 1 (:) + 5 (port) + + SSDP_DEVICE_TYPE_SIZE + + SSDP_FRIENDLY_NAME_SIZE + + SSDP_SCHEMA_URL_SIZE + + SSDP_SERIAL_NUMBER_SIZE + + SSDP_MODEL_NAME_SIZE + + _modelDescription.length() + + SSDP_MODEL_VERSION_SIZE + + SSDP_MODEL_URL_SIZE + + SSDP_MANUFACTURER_SIZE + + SSDP_MANUFACTURER_URL_SIZE + + SSDP_UUID_SIZE + + _services.length() + + _icons.length(); + if (_schema) { + free (_schema); + _schema = nullptr; + } + _schema = (char *)malloc(len+1); + if (_schema) { + IPAddress ip = localIP(); + sprintf(_schema, _ssdp_schema_template, + ip[0], ip[1], ip[2], ip[3], _port, + _deviceType, + _friendlyName, + _presentationURL, + _serialNumber, + _modelName, + _modelDescription.c_str(), + _modelNumber, + _modelURL, + _manufacturer, + _manufacturerURL, + _uuid, + _services.c_str(), + _icons.c_str() + ); + } else { +#ifdef DEBUG_SSDP + DEBUG_SSDP.println("not enough memory for schema"); +#endif + } + return _schema; +} + +void SSDPClass::schema(WiFiClient client) +{ + client.print(schema()); +} + +void SSDPClass::_update() +{ + int nbBytes =0; + char * packetBuffer = nullptr; + + if(!_pending && _server) { + ssdp_method_t method = NONE; + nbBytes= _server->parsePacket(); + typedef enum {METHOD, URI, PROTO, KEY, VALUE, ABORT} states; + states state = METHOD; + typedef enum {STRIP, START, SKIP, MAN, ST, MX} headers; + headers header = STRIP; + + uint8_t cursor = 0; + uint8_t cr = 0; + + char buffer[SSDP_BUFFER_SIZE] = {0}; + packetBuffer = new char[nbBytes +1]; + int message_size=_server->read(packetBuffer,nbBytes); + int process_pos = 0; + packetBuffer[message_size]='\0'; + _respondToAddr = _server->remoteIP(); + _respondToPort = _server->remotePort(); +#ifdef DEBUG_SSDP + if (message_size) { + DEBUG_SSDP.println("*************************RX*************************"); + DEBUG_SSDP.print(_server->remoteIP()); + DEBUG_SSDP.print(":"); + DEBUG_SSDP.println(_server->remotePort()); + DEBUG_SSDP.println(packetBuffer); + DEBUG_SSDP.println("****************************************************"); + } +#endif + while(process_pos < message_size) { + + char c = packetBuffer[process_pos]; + process_pos++; + (c == '\r' || c == '\n') ? cr++ : cr = 0; + switch(state) { + case METHOD: + if(c == ' ') { + if(strcmp(buffer, "M-SEARCH") == 0) { + method = SEARCH; + } + + 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: + // end of HTTP request parsing. If we find a match start reply delay. + if(cr == 4) { + if (_stmatch) { + _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: + case STRIP: + case SKIP: + break; + case MAN: +#ifdef DEBUG_SSDP + DEBUG_SSDP.printf("MAN: %s\n", (char *)buffer); +#endif + break; + case ST: + // save the search term for the reply and clear usn suffix. + strlcpy(_respondType, buffer, sizeof(_respondType)); + _usn_suffix[0] = '\0'; +#ifdef DEBUG_SSDP + DEBUG_SSDP.printf("ST: '%s'\n",buffer); +#endif + // if looking for all or root reply with upnp:rootdevice + if(strcmp(buffer, "ssdp:all")==0 || strcmp(buffer, "upnp:rootdevice")==0) { + _stmatch = true; + // set USN suffix + strlcpy(_usn_suffix, "::upnp:rootdevice", sizeof(_usn_suffix)); +#ifdef DEBUG_SSDP + DEBUG_SSDP.println("the search type matches all and root"); +#endif + state = KEY; + } else + // if the search type matches our type, we should respond instead of ABORT + if(strcasecmp(buffer, _deviceType) == 0) { + _stmatch = true; + // set USN suffix to the device type + strlcpy(_usn_suffix, "::", sizeof(_usn_suffix)); + strlcat(_usn_suffix, _deviceType, sizeof(_usn_suffix)); +#ifdef DEBUG_SSDP + DEBUG_SSDP.println("the search type matches our type"); +#endif + state = KEY; + } else { + state = ABORT; +#ifdef DEBUG_SSDP + DEBUG_SSDP.println("REJECT. The search type does not match our type"); +#endif + } + break; + case MX: + // delay in ms from 0 to MX*1000 where MX is in seconds with limits. + _delay = (short)random(0, atoi(buffer) * 1000L); + if (_delay > SSDP_MAX_DELAY) { + _delay = SSDP_MAX_DELAY; + } + break; + } + + if(state != ABORT) { + state = KEY; + header = STRIP; + cursor = 0; + } + } else if(c != '\r' && c != '\n') { + if(header == STRIP) { + if(c == ' ') { + break; + } else { + header = START; + } + } + 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; + } else { + header = SKIP; + } + } + + if(cursor < SSDP_BUFFER_SIZE - 1) { + buffer[cursor++] = c; + buffer[cursor] = '\0'; + } + } + break; + case ABORT: + _pending = false; + _delay = 0; + break; + } + } + } + if(packetBuffer) { + delete packetBuffer; + } + // save reply in reply queue if one is pending + if(_pending) { + int i; + // Many UPNP hosts send out mulitple M-SEARCH packets at the same time to mitigate + // packet loss. Just reply to one for a given host:port. + for (i = 0; i < SSDP_MAX_REPLY_SLOTS; i++) { + if (_replySlots[i]) { + if (_replySlots[i]->_respondToPort == _respondToPort && + _replySlots[i]->_respondToAddr == _respondToAddr + ) { + // keep original delay + _delay = _replySlots[i]->_delay; + _process_time = _replySlots[i]->_process_time; +#ifdef DEBUG_SSDP + DEBUG_SSDP.printf("Remove dupe SSDP reply in slot %i.\n", i); +#endif + delete _replySlots[i]; + _replySlots[i] = 0; + } + } + } + // save packet to available reply queue slot + for (i = 0; i < SSDP_MAX_REPLY_SLOTS; i++) { + if (!_replySlots[i]) { +#ifdef DEBUG_SSDP + DEBUG_SSDP.printf("Saving deferred SSDP reply to queue slot %i.\n", i); +#endif + _replySlots[i] = new ssdp_reply_slot_item_t; + _replySlots[i]->_process_time = _process_time; + _replySlots[i]->_delay = _delay; + _replySlots[i]->_respondToAddr = _respondToAddr; + _replySlots[i]->_respondToPort = _respondToPort; + strlcpy(_replySlots[i]->_respondType, _respondType, sizeof(_replySlots[i]->_respondType)); + strlcpy(_replySlots[i]->_usn_suffix, _usn_suffix, sizeof(_replySlots[i]->_usn_suffix)); + break; + } + } +#ifdef DEBUG_SSDP + if (i == SSDP_MAX_REPLY_SLOTS) { + DEBUG_SSDP.println("SSDP reply queue is full dropping packet."); + } +#endif + _pending = false; + _delay = 0; + } + // send any packets that are pending and overdue. + unsigned long t = millis(); + bool sent = false; + for (int i = 0; i < SSDP_MAX_REPLY_SLOTS; i++) { + if (_replySlots[i]) { + // millis delay with overflow protection. + if (t - _replySlots[i]->_process_time > _replySlots[i]->_delay) { + // reply ready. restore and send. + _respondToAddr = _replySlots[i]->_respondToAddr; + _respondToPort = _replySlots[i]->_respondToPort; + strlcpy(_respondType, _replySlots[i]->_respondType, sizeof(_respondType)); + strlcpy(_usn_suffix, _replySlots[i]->_usn_suffix, sizeof(_usn_suffix)); +#ifdef DEBUG_SSDP + DEBUG_SSDP.println("Send None"); +#endif + _send(NONE); + sent = true; + delete _replySlots[i]; + _replySlots[i] = 0; + } + } + } +#ifdef DEBUG_SSDP + uint8_t rcount = 0; + DEBUG_SSDP.print("SSDP reply queue status: ["); + for (int i = 0; i < SSDP_MAX_REPLY_SLOTS; i++) { + DEBUG_SSDP.print(_replySlots[i] ? "X" : "-" ); + } + DEBUG_SSDP.println("]"); +#endif + if(_notify_time == 0 || (millis() - _notify_time) > (_interval * 1000L)) { + _notify_time = millis(); + // send notify with our root device type + strlcpy(_respondType, "upnp:rootdevice", sizeof(_respondType)); + strlcpy(_usn_suffix, "::upnp:rootdevice", sizeof(_usn_suffix)); +#ifdef DEBUG_SSDP + DEBUG_SSDP.println("Send Notify"); +#endif + _send(NOTIFY); + sent = true; + } + if (!sent) { +#ifdef DEBUG_SSDP + DEBUG_SSDP.println("Do not sent"); +#endif + } else { + _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::setModelDescription(const char *desc) +{ + _modelDescription = desc; +} +void SSDPClass::setServerName(const char *name) +{ + _servername = name; +} + +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::setInterval(uint32_t interval) +{ + _interval = interval; +} + +void SSDPClass::_onTimerStatic(SSDPClass* self) +{ +#ifdef DEBUG_SSDP + DEBUG_SSDP.println("Update"); +#endif + self->_update(); +} + +void SSDPClass::_startTimer() +{ + _stopTimer(); + _timer= new SSDPTimer(); + ETSTimer* tm = &(_timer->timer); + const int interval = 1000; + ets_timer_disarm(tm); + ets_timer_setfn(tm, reinterpret_cast(&SSDPClass::_onTimerStatic), reinterpret_cast(this)); + ets_timer_arm(tm, interval, 1 /* repeat */); +} + +void SSDPClass::_stopTimer() +{ + if(!_timer) { + return; + } + ETSTimer* tm = &(_timer->timer); + ets_timer_disarm(tm); + delete _timer; + _timer = nullptr; +} + +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SSDP) +SSDPClass SSDP; +#endif + +#endif diff --git a/libraries/ESP32SSDP-1.0.1/ESP32SSDP.h b/libraries/ESP32SSDP-1.1.0/ESP32SSDP.h similarity index 60% rename from libraries/ESP32SSDP-1.0.1/ESP32SSDP.h rename to libraries/ESP32SSDP-1.1.0/ESP32SSDP.h index 545e3d09..1ef6b485 100644 --- a/libraries/ESP32SSDP-1.0.1/ESP32SSDP.h +++ b/libraries/ESP32SSDP-1.1.0/ESP32SSDP.h @@ -44,18 +44,29 @@ License (MIT license): #define SSDP_MODEL_VERSION_SIZE 32 #define SSDP_MANUFACTURER_SIZE 64 #define SSDP_MANUFACTURER_URL_SIZE 128 +#define SSDP_MAX_REPLY_SLOTS 5 +#define SSDP_MAX_DELAY 10000 typedef enum { - NONE, - SEARCH, - NOTIFY + NONE, + SEARCH, + NOTIFY } ssdp_method_t; +typedef struct { + unsigned long _process_time; + short _delay; + IPAddress _respondToAddr; + uint16_t _respondToPort; + char _respondType[SSDP_DEVICE_TYPE_SIZE]; + char _usn_suffix[SSDP_DEVICE_TYPE_SIZE]; +} ssdp_reply_slot_item_t; struct SSDPTimer; -class SSDPClass{ - public: +class SSDPClass +{ +public: SSDPClass(); ~SSDPClass(); @@ -63,53 +74,109 @@ class SSDPClass{ void end(); void schema(WiFiClient client); + const char * schema(); - void setDeviceType(const String& deviceType) { setDeviceType(deviceType.c_str()); } + 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 String& name) + { + setName(name.c_str()); + } 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 setSchemaURL(const String& url) { setSchemaURL(url.c_str()); } + 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()); } + 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 String& num) + { + setModelNumber(num.c_str()); + } void setModelNumber(const char *num); - void setModelURL(const String& url) { setModelURL(url.c_str()); } + void setModelURL(const String& url) + { + setModelURL(url.c_str()); + } + void setModelDescription(const String& desc) + { + setModelDescription(desc.c_str()); + } + void setModelDescription(const char *desc); + void setServerName(const String& name) + { + setServerName(name.c_str()); + } + void setServerName(const char *name); void setModelURL(const char *url); - void setManufacturer(const String& name) { setManufacturer(name.c_str()); } + 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 String& url) + { + setManufacturerURL(url.c_str()); + } void setManufacturerURL(const char *url); void setHTTPPort(uint16_t port); void setTTL(uint8_t ttl); + void setInterval(uint32_t interval); + void setUUID(const char * uuid, bool rootonly = true); + void setServices(const char * services) + { + _services = services; + } + void setIcons(const char * icons) + { + _icons = icons; + } - protected: +protected: void _send(ssdp_method_t method); void _update(); void _startTimer(); void _stopTimer(); static void _onTimerStatic(SSDPClass* self); IPAddress localIP(); - WiFiUDP *_server; - SSDPTimer* _timer; + WiFiUDP *_server; + SSDPTimer* _timer; uint16_t _port; uint8_t _ttl; + uint8_t _interval; + ssdp_reply_slot_item_t *_replySlots[SSDP_MAX_REPLY_SLOTS]; IPAddress _respondToAddr; uint16_t _respondToPort; bool _pending; - unsigned short _delay; + bool _stmatch; + short _delay; unsigned long _process_time; unsigned long _notify_time; + char _respondType[SSDP_DEVICE_TYPE_SIZE]; char _schemaURL[SSDP_SCHEMA_URL_SIZE]; char _uuid[SSDP_UUID_SIZE]; + char _usn_suffix[SSDP_DEVICE_TYPE_SIZE]; char _deviceType[SSDP_DEVICE_TYPE_SIZE]; char _friendlyName[SSDP_FRIENDLY_NAME_SIZE]; char _serialNumber[SSDP_SERIAL_NUMBER_SIZE]; @@ -119,6 +186,11 @@ class SSDPClass{ char _modelName[SSDP_MODEL_NAME_SIZE]; char _modelURL[SSDP_MODEL_URL_SIZE]; char _modelNumber[SSDP_MODEL_VERSION_SIZE]; + String _modelDescription; + String _servername; + char * _schema; + String _services; + String _icons; }; #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SSDP) @@ -126,4 +198,4 @@ extern SSDPClass SSDP; #endif #endif -#endif \ No newline at end of file +#endif diff --git a/libraries/ESP32SSDP-1.0.1/README.rst b/libraries/ESP32SSDP-1.1.0/README.md similarity index 56% rename from libraries/ESP32SSDP-1.0.1/README.rst rename to libraries/ESP32SSDP-1.1.0/README.md index b2c92c75..7b27990a 100644 --- a/libraries/ESP32SSDP-1.0.1/README.rst +++ b/libraries/ESP32SSDP-1.1.0/README.md @@ -1,6 +1,10 @@ ESP32 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 +found at: https://github.com/nomadnt/uSSDP + +[Latest stable release ![Release Version](https://img.shields.io/github/release/luc-github/ESP32SSDP.svg?style=plastic) ![Release Date](https://img.shields.io/github/release-date/luc-github/ESP32SSDP.svg?style=plastic)](https://github.com/luc-github/ESP32SSDP/releases/latest/) [![Travis (.org) branch](https://img.shields.io/travis/luc-github/ESP32SSDP/master?style=plastic)](https://travis-ci.org/luc-github/ESP32SSDP) + +[Latest development version ![Development Version](https://img.shields.io/badge/devt-yellow?style=plastic) ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/luc-github/ESP32SSDP/devt?style=plastic)](https://github.com/luc-github/ESP32SSDP/tree/devt) [![Travis (.org) branch](https://img.shields.io/travis/luc-github/ESP32SSDP/devt?style=plastic)](https://travis-ci.org/luc-github/ESP32SSDP) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/libraries/ESP32SSDP-1.1.0/command.sh b/libraries/ESP32SSDP-1.1.0/command.sh new file mode 100644 index 00000000..e366f20e --- /dev/null +++ b/libraries/ESP32SSDP-1.1.0/command.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +function build_sketch() +{ + local sketch=$1 + + # buld sketch with arudino ide + echo -e "\n Build $sketch \n" + arduino --verbose --verify $sketch + + # get build result from arduino + local re=$? + + # check result + if [ $re -ne 0 ]; then + echo "Failed to build $sketch" + return $re + fi +} diff --git a/libraries/ESP32SSDP-1.1.0/examples/SSDP/SSDP.ino b/libraries/ESP32SSDP-1.1.0/examples/SSDP/SSDP.ino new file mode 100644 index 00000000..21f3a219 --- /dev/null +++ b/libraries/ESP32SSDP-1.1.0/examples/SSDP/SSDP.ino @@ -0,0 +1,105 @@ +#include +#include +#include + +const char* ssid = "********"; +const char* password = "********"; + +WebServer HTTP(80); + +void setup() +{ + Serial.begin(115200); + Serial.println(); + Serial.println("Starting WiFi..."); + + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + if(WiFi.waitForConnectResult() == WL_CONNECTED) { + + Serial.printf("Starting HTTP...\n"); + HTTP.on("/index.html", HTTP_GET, []() { + HTTP.send(200, "text/plain", "Hello World!"); + }); + HTTP.on("/description.xml", HTTP_GET, []() { + SSDP.schema(HTTP.client()); + }); + HTTP.begin(); + + //set schema xml url, nees to match http handler + //"ssdp/schema.xml" if not set + SSDP.setSchemaURL("description.xml"); + //set port + //80 if not set + SSDP.setHTTPPort(80); + //set device name + //Null string if not set + SSDP.setName("Philips hue clone"); + //set Serial Number + //Null string if not set + SSDP.setSerialNumber("001788102201"); + //set device url + //Null string if not set + SSDP.setURL("index.html"); + //set model name + //Null string if not set + SSDP.setModelName("Philips hue bridge 2012"); + //set model description + //Null string if not set + SSDP.setModelDescription("This device can be controled by WiFi"); + //set model number + //Null string if not set + SSDP.setModelNumber("929000226503"); + //set model url + //Null string if not set + SSDP.setModelURL("http://www.meethue.com"); + //set model manufacturer name + //Null string if not set + SSDP.setManufacturer("Royal Philips Electronics"); + //set model manufacturer url + //Null string if not set + SSDP.setManufacturerURL("http://www.philips.com"); + //set device type + //"urn:schemas-upnp-org:device:Basic:1" if not set + SSDP.setDeviceType("upnp:rootdevice"); //to appear as root device + //set server name + //"Arduino/1.0" if not set + SSDP.setServerName("SSDPServer/1.0"); + //set UUID, you can use https://www.uuidgenerator.net/ + //use 38323636-4558-4dda-9188-cda0e6 + 4 last bytes of mac address if not set + //use SSDP.setUUID("daa26fa3-d2d4-4072-bc7a-a1b88ab4234a", false); for full UUID + SSDP.setUUID("daa26fa3-d2d4-4072-bc7a"); + //Set icons list, NB: optional, this is ignored under windows + SSDP.setIcons( "" + "image/png" + "48" + "48" + "24" + "icon48.png" + ""); + //Set service list, NB: optional for simple device + SSDP.setServices( "" + "urn:schemas-upnp-org:service:SwitchPower:1" + "urn:upnp-org:serviceId:SwitchPower:1" + "/SwitchPower1.xml" + "/SwitchPower/Control" + "/SwitchPower/Event" + ""); + + Serial.printf("Starting SSDP...\n"); + SSDP.begin(); + + Serial.printf("Ready!\n"); + } else { + Serial.printf("WiFi Failed\n"); + while(1) { + delay(100); + } + } +} + +void loop() +{ + HTTP.handleClient(); + delay(1); +} diff --git a/libraries/ESP32SSDP-1.0.1/keywords.txt b/libraries/ESP32SSDP-1.1.0/keywords.txt similarity index 100% rename from libraries/ESP32SSDP-1.0.1/keywords.txt rename to libraries/ESP32SSDP-1.1.0/keywords.txt diff --git a/libraries/ESP32SSDP-1.0.1/library.properties b/libraries/ESP32SSDP-1.1.0/library.properties similarity index 93% rename from libraries/ESP32SSDP-1.0.1/library.properties rename to libraries/ESP32SSDP-1.1.0/library.properties index 85620f8b..e80c8f94 100644 --- a/libraries/ESP32SSDP-1.0.1/library.properties +++ b/libraries/ESP32SSDP-1.1.0/library.properties @@ -1,5 +1,5 @@ name=ESP32SSPD -version=1.0.1 +version=1.1.0 author=Me-No-Dev maintainer=luc-github sentence=Simple SSDP library for ESP32 diff --git a/libraries/ESP32SSDP-1.1.0/set_style.bat b/libraries/ESP32SSDP-1.1.0/set_style.bat new file mode 100644 index 00000000..a9ca89ad --- /dev/null +++ b/libraries/ESP32SSDP-1.1.0/set_style.bat @@ -0,0 +1,4 @@ +cd %~dp0 +astyle --recursive --style=otbs *.h *.cpp *.ino +del /S *.ori +pause diff --git a/libraries/ESP32SSDP-1.1.0/test/install_astyle.sh b/libraries/ESP32SSDP-1.1.0/test/install_astyle.sh new file mode 100644 index 00000000..32c2f5ef --- /dev/null +++ b/libraries/ESP32SSDP-1.1.0/test/install_astyle.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# +# $HOME/astyle directory is cached on Travis. +# If cached build is not present, download astyle and build it. +# Install built astyle binary into the home directory. +# + +set -e + +if [ ! -f $HOME/astyle/build/gcc/bin/astyle ]; then + wget -O astyle_3.1_linux.tar.gz https://sourceforge.net/projects/astyle/files/astyle/astyle%203.1/astyle_3.1_linux.tar.gz/download + tar -xf astyle_3.1_linux.tar.gz -C $HOME + make -C $HOME/astyle/build/gcc +fi + +make -C $HOME/astyle/build/gcc prefix=$HOME install diff --git a/libraries/ESP32SSDP-1.1.0/test/platformio.ini b/libraries/ESP32SSDP-1.1.0/test/platformio.ini new file mode 100644 index 00000000..f2bc0f5c --- /dev/null +++ b/libraries/ESP32SSDP-1.1.0/test/platformio.ini @@ -0,0 +1,30 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +src_dir = . +build_dir = .pioenvs +libdeps_dir = .piolibdeps +lib_dir = ../../.. +[env:esp32dev] +platform = https://github.com/platformio/platform-espressif32.git +;theboard +board = esp32dev +framework = arduino +monitor_speed = 115200 +; set frequency to 240MHz +board_build.f_cpu = 240000000L +; set frequency to 80MHz +board_build.f_flash = 80000000L +board_build.flash_mode = qio +; No debug +build_flags = -DCORE_DEBUG_LEVEL=0 +board_build.partitions = min_spiffs.csv +upload_speed = 921600