├── .gitattributes
├── .gitignore
├── README.md
├── SSDPDevice.cpp
├── SSDPDevice.h
├── SSDPinNetwork.PNG
├── esp32SSDP.ino
├── update_server.h
├── update_server.ino
├── wifi_ss.h
└── wifi_ss.ino
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.bin
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # esp32SSDP
2 | SSDP for ESP32, including http updater without JQuery
3 | based on https://github.com/esp8266/Arduino/issues/2283
4 | https://github.com/esp8266/Arduino/files/980894/SSDPDevice.zip
5 | by Pawel Dino
6 |
7 | Shows the ESP32 in Windows Network tab under Home Automation.
8 |
9 |
10 |
11 | The example needs a ssid and password defined for the WiFi credentials see
12 | wifi_ss.h
13 |
14 | Included httpupdater code that is independent of JQuery, and lacks
15 | the overload of braces that confuse me.
16 |
17 |
--------------------------------------------------------------------------------
/SSDPDevice.cpp:
--------------------------------------------------------------------------------
1 | // based on https://github.com/esp8266/Arduino/issues/2283
2 | // https://github.com/esp8266/Arduino/files/980894/SSDPDevice.zip
3 | // by Pawel Dino
4 |
5 |
6 | #include "SSDPDevice.h"
7 | #include "lwip/igmp.h"
8 |
9 | SSDPDeviceClass::SSDPDeviceClass() :
10 | m_server(0),
11 | m_port(80),
12 | m_ttl(SSDP_MULTICAST_TTL)
13 | {
14 | m_uuid[0] = '\0';
15 | m_modelNumber[0] = '\0';
16 | sprintf(m_deviceType, "urn:schemas-upnp-org:device:Basic:1");
17 | m_friendlyName[0] = '\0';
18 | m_presentationURL[0] = '\0';
19 | m_serialNumber[0] = '\0';
20 | m_modelName[0] = '\0';
21 | m_modelURL[0] = '\0';
22 | m_manufacturer[0] = '\0';
23 | m_manufacturerURL[0] = '\0';
24 | sprintf(m_schemaURL, "ssdp/schema.xml");
25 |
26 | #ifdef ESP8266
27 | uint32_t chipId = ESP.getChipId();
28 | #endif
29 | #ifdef ESP32
30 | uint32_t chipId = ESP.getEfuseMac();
31 | #endif
32 |
33 | sprintf(m_uuid, "38323636-4558-4dda-9188-cda0e6%02x%02x%02x",
34 | (uint16_t)((chipId >> 16) & 0xff),
35 | (uint16_t)((chipId >> 8) & 0xff),
36 | (uint16_t)chipId & 0xff);
37 |
38 | for (int i = 0; i < SSDP_QUEUE_SIZE; i++) {
39 | m_queue[i].time = 0;
40 | }
41 | }
42 |
43 | void SSDPDeviceClass::update() {
44 | postNotifyUpdate();
45 | }
46 |
47 | bool SSDPDeviceClass::readLine(String &value) {
48 | char buffer[65];
49 | int bufferPos = 0;
50 |
51 | while (1) {
52 | int c = m_server->read();
53 |
54 | if (c < 0) {
55 | buffer[bufferPos] = '\0';
56 |
57 | break;
58 | }
59 | if (c == '\r' && m_server->peek() == '\n') {
60 | m_server->read();
61 |
62 | buffer[bufferPos] = '\0';
63 |
64 | break;
65 | }
66 | if (bufferPos < 64) {
67 | buffer[bufferPos++] = c;
68 | }
69 | }
70 |
71 | value = String(buffer);
72 |
73 | return bufferPos > 0;
74 | }
75 |
76 | bool SSDPDeviceClass::readKeyValue(String &key, String &value) {
77 | char buffer[65];
78 | int bufferPos = 0;
79 |
80 | while (1) {
81 | int c = m_server->read();
82 |
83 | if (c < 0) {
84 | if (bufferPos == 0) return false;
85 |
86 | buffer[bufferPos] = '\0';
87 |
88 | break;
89 | }
90 | if (c == ':') {
91 | buffer[bufferPos] = '\0';
92 |
93 | while (m_server->peek() == ' ') m_server->read();
94 |
95 | break;
96 | }
97 | else if (c == '\r' && m_server->peek() == '\n') {
98 | m_server->read();
99 |
100 | if (bufferPos == 0) return false;
101 |
102 | buffer[bufferPos] = '\0';
103 |
104 | key = String();
105 | value = String(buffer);
106 |
107 | return true;
108 | }
109 | if (bufferPos < 64) {
110 | buffer[bufferPos++] = c;
111 | }
112 | }
113 |
114 | key = String(buffer);
115 |
116 | readLine(value);
117 |
118 | return true;
119 | }
120 |
121 | void SSDPDeviceClass::postNotifyALive() {
122 | unsigned long time = millis();
123 |
124 | post(NOTIFY_ALIVE_INIT, ROOT_FOR_ALL, SSDP_MULTICAST_ADDR, SSDP_PORT, time + 10);
125 | post(NOTIFY_ALIVE_INIT, ROOT_BY_UUID, SSDP_MULTICAST_ADDR, SSDP_PORT, time + 55);
126 | post(NOTIFY_ALIVE_INIT, ROOT_BY_TYPE, SSDP_MULTICAST_ADDR, SSDP_PORT, time + 80);
127 |
128 | post(NOTIFY_ALIVE_INIT, ROOT_FOR_ALL, SSDP_MULTICAST_ADDR, SSDP_PORT, time + 210);
129 | post(NOTIFY_ALIVE_INIT, ROOT_BY_UUID, SSDP_MULTICAST_ADDR, SSDP_PORT, time + 255);
130 | post(NOTIFY_ALIVE_INIT, ROOT_BY_TYPE, SSDP_MULTICAST_ADDR, SSDP_PORT, time + 280);
131 |
132 | post(NOTIFY_ALIVE, ROOT_FOR_ALL, SSDP_MULTICAST_ADDR, SSDP_PORT, time + 610);
133 | post(NOTIFY_ALIVE, ROOT_BY_UUID, SSDP_MULTICAST_ADDR, SSDP_PORT, time + 655);
134 | post(NOTIFY_ALIVE, ROOT_BY_TYPE, SSDP_MULTICAST_ADDR, SSDP_PORT, time + 680);
135 | }
136 |
137 | void SSDPDeviceClass::postNotifyUpdate() {
138 | unsigned long time = millis();
139 |
140 | post(NOTIFY_UPDATE, ROOT_FOR_ALL, SSDP_MULTICAST_ADDR, SSDP_PORT, time + 10);
141 | post(NOTIFY_UPDATE, ROOT_BY_UUID, SSDP_MULTICAST_ADDR, SSDP_PORT, time + 55);
142 | post(NOTIFY_UPDATE, ROOT_BY_TYPE, SSDP_MULTICAST_ADDR, SSDP_PORT, time + 80);
143 | }
144 |
145 | void SSDPDeviceClass::postResponse(long mx) {
146 | unsigned long time = millis();
147 | unsigned long delay = random(0, mx) * 900L; // 1000 ms - 100 ms
148 |
149 | IPAddress address = m_server->remoteIP();
150 | uint16_t port = m_server->remotePort();
151 |
152 | post(RESPONSE, ROOT_FOR_ALL, address, port, time + delay / 3);
153 | post(RESPONSE, ROOT_BY_UUID, address, port, time + delay / 3 * 2);
154 | post(RESPONSE, ROOT_BY_TYPE, address, port, time + delay);
155 | }
156 |
157 | void SSDPDeviceClass::postResponse(ssdp_udn_t udn, long mx) {
158 | post(RESPONSE, udn, m_server->remoteIP(), m_server->remotePort(), millis() + random(0, mx) * 900L); // 1000 ms - 100 ms
159 | }
160 |
161 | void SSDPDeviceClass::post(ssdp_message_t type, ssdp_udn_t udn, IPAddress address, uint16_t port, unsigned long time) {
162 | for (int i = 0; i < SSDP_QUEUE_SIZE; i++) {
163 | if (m_queue[i].time == 0) {
164 | m_queue[i].type = type;
165 | m_queue[i].udn = udn;
166 | m_queue[i].address = address;
167 | m_queue[i].port = port;
168 | m_queue[i].time = time;
169 |
170 | break;
171 | }
172 | }
173 | }
174 |
175 | void SSDPDeviceClass::send(ssdp_send_parameters_t *parameters) {
176 | uint8_t buffer[1460];
177 | unsigned int ip = WiFi.localIP();
178 |
179 | const char *typeTemplate;
180 | const char *uri, *usn1, *usn2, *usn3;
181 |
182 | switch (parameters->type) {
183 | case NOTIFY_ALIVE_INIT:
184 | case NOTIFY_ALIVE:
185 | typeTemplate = SSDP_NOTIFY_ALIVE_TEMPLATE;
186 | break;
187 | case NOTIFY_UPDATE:
188 | typeTemplate = SSDP_NOTIFY_UPDATE_TEMPLATE;
189 | break;
190 | default: // RESPONSE
191 | typeTemplate = SSDP_RESPONSE_TEMPLATE;
192 | break;
193 | }
194 |
195 | String uuid = "uuid:" + String(m_uuid);
196 |
197 | switch (parameters->udn) {
198 | case ROOT_FOR_ALL:
199 | uri = "upnp:rootdevice";
200 | usn1 = uuid.c_str();
201 | usn2 = "::";
202 | usn3 = "upnp:rootdevice";
203 | break;
204 | case ROOT_BY_UUID:
205 | uri = uuid.c_str();
206 | usn1 = uuid.c_str();
207 | usn2 = "";
208 | usn3 = "";
209 | break;
210 | case ROOT_BY_TYPE:
211 | uri = m_deviceType;
212 | usn1 = uuid.c_str();
213 | usn2 = "::";
214 | usn3 = m_deviceType;
215 | break;
216 | }
217 |
218 | int len = snprintf_P((char *)buffer, sizeof(buffer),
219 | SSDP_PACKET_TEMPLATE, typeTemplate,
220 | SSDP_INTERVAL, m_modelName, m_modelNumber, usn1, usn2, usn3, parameters->type == RESPONSE ? "ST" : "NT", uri,
221 | LIP2STR(&ip), m_port, m_schemaURL
222 | );
223 |
224 | if (parameters->address == (uint32_t) SSDP_MULTICAST_ADDR) {
225 | #ifdef ESP8266
226 | m_server->beginPacketMulticast(parameters->address, parameters->port, m_ttl);
227 | #endif
228 | #ifdef ESP32
229 | m_server->beginMulticast(parameters->address, parameters->port);
230 | m_server->beginMulticastPacket();
231 | #endif
232 | } else {
233 | m_server->beginPacket(parameters->address, parameters->port);
234 | }
235 |
236 | m_server->write(buffer, len);
237 | m_server->endPacket();
238 |
239 | parameters->time = parameters->type == NOTIFY_ALIVE ? parameters->time + SSDP_INTERVAL * 900L : 0; // 1000 ms - 100 ms
240 | }
241 |
242 | void SSDPDeviceClass::schema(WiFiClient client) {
243 | uint32_t ip = WiFi.localIP();
244 | client.printf(SSDP_SCHEMA_TEMPLATE,
245 | LIP2STR(&ip), m_port, m_schemaURL,
246 | m_deviceType,
247 | m_friendlyName,
248 | m_presentationURL,
249 | m_serialNumber,
250 | m_modelName,
251 | m_modelNumber,
252 | m_modelURL,
253 | m_manufacturer,
254 | m_manufacturerURL,
255 | m_uuid
256 | );
257 | }
258 |
259 | void SSDPDeviceClass::handleClient() {
260 | IPAddress current = WiFi.localIP();
261 |
262 | if (m_last != current) {
263 | m_last = current;
264 |
265 | for (int i = 0; i < SSDP_QUEUE_SIZE; i++) {
266 | m_queue[i].time = 0;
267 | }
268 |
269 | if (current != INADDR_NONE) {
270 | if (!m_server) m_server = new WiFiUDP();
271 |
272 | #ifdef ESP8266
273 | m_server->beginMulticast(current, SSDP_MULTICAST_ADDR, SSDP_PORT);
274 | #endif
275 | #ifdef ESP32
276 | m_server->beginMulticast(SSDP_MULTICAST_ADDR, SSDP_PORT);
277 | m_server->beginMulticastPacket();
278 | #endif
279 | postNotifyALive();
280 | }
281 | else if (m_server) {
282 | m_server->stop();
283 | }
284 | }
285 |
286 | if (m_server && m_server->parsePacket()) {
287 | String value;
288 |
289 | if (readLine(value) && value.equalsIgnoreCase("M-SEARCH * HTTP/1.1")) {
290 | String key, st;
291 | bool host = false, man = false;
292 | long mx = 0;
293 |
294 | while (readKeyValue(key, value)) {
295 | if (key.equalsIgnoreCase("HOST") && value.equals("239.255.255.250:1900")) {
296 | host = true;
297 | }
298 | else if (key.equalsIgnoreCase("MAN") && value.equals("\"ssdp:discover\"")) {
299 | man = true;
300 | }
301 | else if (key.equalsIgnoreCase("ST")) {
302 | st = value;
303 | }
304 | else if (key.equalsIgnoreCase("MX")) {
305 | mx = value.toInt();
306 | }
307 | }
308 |
309 | if (host && man && mx > 0) {
310 | if (st.equals("ssdp:all")) {
311 | postResponse(mx);
312 | }
313 | else if (st.equals("upnp:rootdevice")) {
314 | postResponse(ROOT_FOR_ALL, mx);
315 | }
316 | else if (st.equals("uuid:" + String(m_uuid))) {
317 | postResponse(ROOT_BY_UUID, mx);
318 | }
319 | else if (st.equals(m_deviceType)) {
320 | postResponse(ROOT_BY_TYPE, mx);
321 | }
322 | }
323 | }
324 |
325 | m_server->flush();
326 | }
327 | else {
328 | unsigned long time = millis();
329 |
330 | for (int i = 0; i < SSDP_QUEUE_SIZE; i++) {
331 | if (m_queue[i].time > 0 && m_queue[i].time < time) {
332 | send(&m_queue[i]);
333 | }
334 | }
335 | }
336 | }
337 |
338 | void SSDPDeviceClass::setSchemaURL(const char *url) {
339 | strlcpy(m_schemaURL, url, sizeof(m_schemaURL));
340 | }
341 |
342 | void SSDPDeviceClass::setHTTPPort(uint16_t port) {
343 | m_port = port;
344 | }
345 |
346 | void SSDPDeviceClass::setDeviceType(const char *deviceType) {
347 | strlcpy(m_deviceType, deviceType, sizeof(m_deviceType));
348 | }
349 |
350 | void SSDPDeviceClass::setName(const char *name) {
351 | strlcpy(m_friendlyName, name, sizeof(m_friendlyName));
352 | }
353 |
354 | void SSDPDeviceClass::setURL(const char *url) {
355 | strlcpy(m_presentationURL, url, sizeof(m_presentationURL));
356 | }
357 |
358 | void SSDPDeviceClass::setSerialNumber(const char *serialNumber) {
359 | strlcpy(m_serialNumber, serialNumber, sizeof(m_serialNumber));
360 | }
361 |
362 | void SSDPDeviceClass::setSerialNumber(const uint32_t serialNumber) {
363 | snprintf(m_serialNumber, sizeof(uint32_t) * 2 + 1, "%08X", serialNumber);
364 | }
365 |
366 | void SSDPDeviceClass::setModelName(const char *name) {
367 | strlcpy(m_modelName, name, sizeof(m_modelName));
368 | }
369 |
370 | void SSDPDeviceClass::setModelNumber(const char *num) {
371 | strlcpy(m_modelNumber, num, sizeof(m_modelNumber));
372 | }
373 |
374 | void SSDPDeviceClass::setModelURL(const char *url) {
375 | strlcpy(m_modelURL, url, sizeof(m_modelURL));
376 | }
377 |
378 | void SSDPDeviceClass::setManufacturer(const char *name) {
379 | strlcpy(m_manufacturer, name, sizeof(m_manufacturer));
380 | }
381 |
382 | void SSDPDeviceClass::setManufacturerURL(const char *url) {
383 | strlcpy(m_manufacturerURL, url, sizeof(m_manufacturerURL));
384 | }
385 |
386 | void SSDPDeviceClass::setTTL(const uint8_t ttl) {
387 | m_ttl = ttl;
388 | }
389 |
390 | SSDPDeviceClass SSDPDevice;
391 |
--------------------------------------------------------------------------------
/SSDPDevice.h:
--------------------------------------------------------------------------------
1 | // SSDPDevice.h
2 | // based on https://github.com/esp8266/Arduino/issues/2283
3 | // https://github.com/esp8266/Arduino/files/980894/SSDPDevice.zip
4 | // by Pawel Dino
5 |
6 | #ifndef _SSDPDEVICE_h
7 | #define _SSDPDEVICE_h
8 |
9 |
10 | #ifdef ESP8266
11 | #include
12 | #include
13 | #endif
14 |
15 | #ifdef ESP32
16 | #include
17 | #include
18 | #endif
19 |
20 | #define pip41(ipaddr) ((u16_t)(((u8_t*)(ipaddr))[0]))
21 | #define pip42(ipaddr) ((u16_t)(((u8_t*)(ipaddr))[1]))
22 | #define pip43(ipaddr) ((u16_t)(((u8_t*)(ipaddr))[2]))
23 | #define pip44(ipaddr) ((u16_t)(((u8_t*)(ipaddr))[3]))
24 |
25 |
26 | #define LIP2STR(ipaddr) pip41(ipaddr), \
27 | pip42(ipaddr), \
28 | pip43(ipaddr), \
29 | pip44(ipaddr)
30 |
31 |
32 | #define SSDP_INTERVAL 1200
33 | #define SSDP_PORT 1900
34 | //#define SSDP_METHOD_SIZE 10
35 | //#define SSDP_URI_SIZE 2
36 | //#define SSDP_BUFFER_SIZE 64
37 | #define SSDP_MULTICAST_TTL 2
38 |
39 | #define SSDP_QUEUE_SIZE 21
40 |
41 | static const IPAddress SSDP_MULTICAST_ADDR(239, 255, 255, 250);
42 |
43 | #define SSDP_UUID_SIZE 37
44 | #define SSDP_SCHEMA_URL_SIZE 64
45 | #define SSDP_DEVICE_TYPE_SIZE 64
46 | #define SSDP_FRIENDLY_NAME_SIZE 64
47 | #define SSDP_SERIAL_NUMBER_SIZE 32
48 | #define SSDP_PRESENTATION_URL_SIZE 128
49 | #define SSDP_MODEL_NAME_SIZE 64
50 | #define SSDP_MODEL_URL_SIZE 128
51 | #define SSDP_MODEL_VERSION_SIZE 32
52 | #define SSDP_MANUFACTURER_SIZE 64
53 | #define SSDP_MANUFACTURER_URL_SIZE 128
54 |
55 | static const char* PROGMEM SSDP_RESPONSE_TEMPLATE =
56 | "HTTP/1.1 200 OK\r\n"
57 | "EXT:\r\n";
58 |
59 | static const char* PROGMEM SSDP_NOTIFY_ALIVE_TEMPLATE =
60 | "NOTIFY * HTTP/1.1\r\n"
61 | "HOST: 239.255.255.250:1900\r\n"
62 | "NTS: ssdp:alive\r\n";
63 |
64 | static const char* PROGMEM SSDP_NOTIFY_UPDATE_TEMPLATE =
65 | "NOTIFY * HTTP/1.1\r\n"
66 | "HOST: 239.255.255.250:1900\r\n"
67 | "NTS: ssdp:update\r\n";
68 |
69 | static const char* PROGMEM SSDP_PACKET_TEMPLATE =
70 | "%s" // _ssdp_response_template / _ssdp_notify_template
71 | "CACHE-CONTROL: max-age=%u\r\n" // SSDP_INTERVAL
72 | "SERVER: UPNP/1.1 %s/%s\r\n" // m_modelName, m_modelNumber
73 | "USN: %s%s%s\r\n" // m_uuid
74 | "%s: %s\r\n" // "NT" or "ST", m_deviceType
75 | "LOCATION: http://%u.%u.%u.%u:%u/%s\r\n" // WiFi.localIP(), m_port, m_schemaURL
76 | "\r\n";
77 |
78 | static const char* PROGMEM SSDP_SCHEMA_TEMPLATE =
79 | "HTTP/1.1 200 OK\r\n"
80 | "Content-Type: text/xml\r\n"
81 | "Connection: close\r\n"
82 | "Access-Control-Allow-Origin: *\r\n"
83 | "\r\n"
84 | ""
85 | ""
86 | ""
87 | "1"
88 | "0"
89 | ""
90 | "http://%u.%u.%u.%u:%u/%s" // WiFi.localIP(), _port
91 | ""
92 | "%s"
93 | "%s"
94 | "%s"
95 | "%s"
96 | "%s"
97 | "%s"
98 | "%s"
99 | "%s"
100 | "%s"
101 | "uuid:%s"
102 | ""
103 | // ""
104 | // ""
105 | // "image/png"
106 | // "48"
107 | // "48"
108 | // "24"
109 | // "icon48.png"
110 | // ""
111 | // ""
112 | // "image/png"
113 | // "120"
114 | // "120"
115 | // "24"
116 | // "icon120.png"
117 | // ""
118 | // ""
119 | "\r\n"
120 | "\r\n";
121 |
122 | typedef enum {
123 | NOTIFY_ALIVE_INIT,
124 | NOTIFY_ALIVE,
125 | NOTIFY_UPDATE,
126 | RESPONSE
127 | } ssdp_message_t;
128 |
129 | typedef enum {
130 | ROOT_FOR_ALL,
131 | ROOT_BY_UUID,
132 | ROOT_BY_TYPE
133 | } ssdp_udn_t;
134 |
135 | typedef struct {
136 | unsigned long time;
137 |
138 | ssdp_message_t type;
139 | ssdp_udn_t udn;
140 | uint32_t address;
141 | uint16_t port;
142 | } ssdp_send_parameters_t;
143 |
144 | class SSDPDeviceClass {
145 | private:
146 | WiFiUDP *m_server;
147 |
148 | IPAddress m_last;
149 |
150 | char m_schemaURL[SSDP_SCHEMA_URL_SIZE];
151 | char m_uuid[SSDP_UUID_SIZE];
152 | char m_deviceType[SSDP_DEVICE_TYPE_SIZE];
153 | char m_friendlyName[SSDP_FRIENDLY_NAME_SIZE];
154 | char m_serialNumber[SSDP_SERIAL_NUMBER_SIZE];
155 | char m_presentationURL[SSDP_PRESENTATION_URL_SIZE];
156 | char m_manufacturer[SSDP_MANUFACTURER_SIZE];
157 | char m_manufacturerURL[SSDP_MANUFACTURER_URL_SIZE];
158 | char m_modelName[SSDP_MODEL_NAME_SIZE];
159 | char m_modelURL[SSDP_MODEL_URL_SIZE];
160 | char m_modelNumber[SSDP_MODEL_VERSION_SIZE];
161 |
162 | uint16_t m_port;
163 | uint8_t m_ttl;
164 |
165 | ssdp_send_parameters_t m_queue[SSDP_QUEUE_SIZE];
166 | protected:
167 | bool readLine(String &value);
168 | bool readKeyValue(String &key, String &value);
169 |
170 | void postNotifyALive();
171 | void postNotifyUpdate();
172 | void postResponse(long mx);
173 | void postResponse(ssdp_udn_t udn, long mx);
174 | void post(ssdp_message_t type, ssdp_udn_t udn, IPAddress address, uint16_t port, unsigned long time);
175 |
176 | void send(ssdp_send_parameters_t *parameters);
177 | public:
178 | SSDPDeviceClass();
179 |
180 | void update();
181 |
182 | void schema(WiFiClient client);
183 |
184 | void handleClient();
185 |
186 | void setDeviceType(const String& deviceType) { setDeviceType(deviceType.c_str()); }
187 | void setDeviceType(const char *deviceType);
188 | void setName(const String& name) { setName(name.c_str()); }
189 | void setName(const char *name);
190 | void setURL(const String& url) { setURL(url.c_str()); }
191 | void setURL(const char *url);
192 | void setSchemaURL(const String& url) { setSchemaURL(url.c_str()); }
193 | void setSchemaURL(const char *url);
194 | void setSerialNumber(const String& serialNumber) { setSerialNumber(serialNumber.c_str()); }
195 | void setSerialNumber(const char *serialNumber);
196 | void setSerialNumber(const uint32_t serialNumber);
197 | void setModelName(const String& name) { setModelName(name.c_str()); }
198 | void setModelName(const char *name);
199 | void setModelNumber(const String& num) { setModelNumber(num.c_str()); }
200 | void setModelNumber(const char *num);
201 | void setModelURL(const String& url) { setModelURL(url.c_str()); }
202 | void setModelURL(const char *url);
203 | void setManufacturer(const String& name) { setManufacturer(name.c_str()); }
204 | void setManufacturer(const char *name);
205 | void setManufacturerURL(const String& url) { setManufacturerURL(url.c_str()); }
206 | void setManufacturerURL(const char *url);
207 | void setHTTPPort(uint16_t port);
208 | void setTTL(uint8_t ttl);
209 | };
210 |
211 | extern SSDPDeviceClass SSDPDevice;
212 |
213 | #endif
214 |
--------------------------------------------------------------------------------
/SSDPinNetwork.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitpeut/esp32SSDP/ff63b12dc8aed30899d74b32d5e9f69b1f2f4539/SSDPinNetwork.PNG
--------------------------------------------------------------------------------
/esp32SSDP.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "update_server.h"
5 | #include "wifi_ss.h"
6 | #include "SSDPDevice.h"
7 |
8 | const char* host = "esesdepe";
9 |
10 | WebServer server(80);
11 |
12 |
13 | /*-----------------------------------------------------------------------------------*/
14 | /*
15 | * setup function
16 | */
17 |
18 | char *nothing = "Hello, SSDP test. updater test is here";
19 |
20 | void setup(void) {
21 | Serial.begin(115200);
22 |
23 | wifi_begin();
24 |
25 | update_begin( &server);
26 |
27 | server.on("/", HTTP_GET, []() {
28 | server.send(200, "text/html", nothing);
29 | });
30 |
31 | server.on("/reset", HTTP_GET, []() {
32 | server.send(200, "text/plain", "Resetting...");
33 | delay(3000);
34 | ESP.restart();
35 | });
36 |
37 | server.on("/description.xml", HTTP_GET, [](){
38 | SSDPDevice.schema( server.client());
39 | });
40 |
41 | SSDPDevice.setName( host );
42 | SSDPDevice.setDeviceType("urn:schemas-upnp-org:device:BinaryLight:1");
43 | SSDPDevice.setSchemaURL("description.xml");
44 | SSDPDevice.setSerialNumber(ESP.getEfuseMac());
45 | SSDPDevice.setURL("/");
46 | SSDPDevice.setModelName(host);
47 | SSDPDevice.setModelNumber("1");
48 | SSDPDevice.setManufacturer("Peut");
49 | SSDPDevice.setManufacturerURL("http://www.peut.org/");
50 |
51 |
52 |
53 | server.begin();
54 | }
55 |
56 | void loop(void) {
57 | server.handleClient();
58 | SSDPDevice.handleClient();
59 |
60 | delay(1);
61 | }
62 |
--------------------------------------------------------------------------------
/update_server.h:
--------------------------------------------------------------------------------
1 | #ifndef UPDATE_SERVER_H
2 | #define UPDATE_SERVER_H
3 |
4 | #include
5 | #include
6 |
7 | void update_begin(WebServer *server);
8 | void update_ask();
9 | void update_progress();
10 | void update_end();
11 |
12 | #endif
13 |
--------------------------------------------------------------------------------
/update_server.ino:
--------------------------------------------------------------------------------
1 | #include "update_server.h"
2 |
3 | /*-----------------------------------------------------------------------------------*/
4 |
5 | const char* updatepage =
6 | "\n\\
29 | \n\\
33 | \n";
34 |
35 | /*-----------------------------------------------------------------------------------*/
36 | WebServer *update_server;
37 |
38 | void update_begin(WebServer *server){
39 | update_server = server;
40 | update_server->on("/update", HTTP_GET, update_ask );
41 | update_server->on("/update", HTTP_POST, update_end, update_progress );
42 |
43 | }
44 |
45 | /*-----------------------------------------------------------------------------------*/
46 |
47 | void update_ask(){
48 | update_server->sendHeader("Connection", "close");
49 | update_server->send(200, "text/html", updatepage );
50 | }
51 |
52 | /*-----------------------------------------------------------------------------------*/
53 |
54 | void update_progress(){
55 | static int written_size=0;
56 |
57 | HTTPUpload& upload = update_server->upload();
58 |
59 | if (upload.status == UPLOAD_FILE_START) {
60 | Serial.printf("Update: %s\n", upload.filename.c_str());
61 | if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
62 | Update.printError(Serial);
63 | }
64 | } else if (upload.status == UPLOAD_FILE_WRITE ) {
65 | /* flashing firmware to ESP*/
66 | //written_size += upload.currentSize;
67 | //Serial.printf("Writing %d bytes, %d/%d\n", upload.currentSize, upload.totalSize, written_size );
68 | if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
69 | Update.printError(Serial);
70 | }
71 | } else if (upload.status == UPLOAD_FILE_END) {
72 | if (Update.end(true)) { //true to set the size to the current progress
73 | Serial.printf("\nUpdate Success: %u\nRebooting...\n", upload.totalSize);
74 | update_server->sendHeader("Connection", "close");
75 | update_server->send(200, "text/plain", "Upload successful, rebooting");
76 | } else {
77 | Update.printError(Serial);
78 | update_server->send(200, "text/plain", "Upload failed");
79 | }
80 | }
81 | }
82 |
83 | void update_end(){
84 | update_server->sendHeader("Connection", "close");
85 | update_server->send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
86 | Serial.printf("---Update %s\n", Update.hasError() ? "FAIL" : "OK");
87 | Serial.flush();
88 | ESP.restart();
89 | }
90 |
--------------------------------------------------------------------------------
/wifi_ss.h:
--------------------------------------------------------------------------------
1 | #ifndef WIFI_SS_H
2 | #define WIFI_SS_H
3 |
4 | #include
5 | // made a directory wificredentials in libraries and define ssid and password in wificredentials.h
6 | #include
7 |
8 | void wifi_begin();
9 | void wifi_event ( WiFiEvent_t event );
10 |
11 |
12 | #endif
13 |
--------------------------------------------------------------------------------
/wifi_ss.ino:
--------------------------------------------------------------------------------
1 |
2 |
3 | #include "wifi_ss.h"
4 |
5 |
6 |
7 | bool wifi_disconnecting = false;
8 |
9 | /*--------------------------------------------------*/
10 |
11 | void wifi_begin(){
12 |
13 | WiFi.mode(WIFI_STA);
14 | WiFi.onEvent( wifi_event );
15 | // Wait for connection
16 | for ( int i=3, kill = 0; WiFi.status() != WL_CONNECTED; ++i, ++kill ) {
17 | if ( i > 2 ) {
18 | WiFi.begin(ssid, password);
19 | i = 0;
20 | }
21 | delay(500);
22 | Serial.print(".");
23 | if ( kill > 20){
24 | Serial.flush();
25 | ESP.restart();
26 | }
27 | }
28 | wifi_disconnecting = false;
29 |
30 | Serial.print("Connected to ");
31 | Serial.println(ssid);
32 | Serial.print("IP address: ");
33 | Serial.println(WiFi.localIP());
34 |
35 | }
36 |
37 | /*--------------------------------------------------*/
38 |
39 | void wifi_event ( WiFiEvent_t event ){
40 |
41 | int do_reconnect = 1;
42 |
43 | switch( event ){
44 | case SYSTEM_EVENT_STA_DISCONNECTED:
45 | Serial.println("Disconnected from WiFi access point");
46 | break;
47 | case SYSTEM_EVENT_STA_LOST_IP:
48 | Serial.println("Lost IP address and IP address is reset to 0");
49 | break;
50 | case 200:
51 | Serial.println("Beacon time out");
52 | break;
53 | case 202:
54 | Serial.println("WiFi Auth fail");
55 | break;
56 | default:
57 | do_reconnect = 0;
58 | }
59 |
60 | if ( do_reconnect && ! wifi_disconnecting ){
61 | wifi_disconnecting = true;
62 | WiFi.disconnect();
63 |
64 | wifi_begin();
65 | }
66 |
67 | }
68 |
69 | /*--------------------------------------------------*/
70 |
--------------------------------------------------------------------------------