Arduino DLNA Server
Loading...
Searching...
No Matches
XMLDeviceParser.h
Go to the documentation of this file.
1#pragma once
2
3#include "Print.h"
4#include "XMLParserPrint.h"
5#include "assert.h"
6#include "basic/Icon.h"
7#include "basic/Logger.h"
8#include "basic/StrView.h"
10
11namespace tiny_dlna {
12
21 public:
23 resetState();
24 p_device = &result;
25 }
26
27 void begin() { start_time = millis(); }
28
31 void parse(const uint8_t* buffer, size_t len) {
32 DLNADeviceInfo& result = *p_device;
33 Str node;
34 Str text;
35 Str attr;
36 Vector<Str> path;
37
38 xml_parser.write(buffer, len);
39
40 // consume all parsed nodes available so far
41 while (xml_parser.parse(node, path, text, attr)) {
42 bool path_has_service = false;
43 bool path_has_icon = false;
44 for (int i = 0; i < path.size(); ++i) {
45 if (path[i] == "service") path_has_service = true;
46 if (path[i] == "icon") path_has_icon = true;
47 }
48
49 if (path_has_service) {
50 if (!in_service) {
51 in_service = true;
53 }
54 if (node.equals("serviceType")) {
55 const char* t = text.c_str();
56 if (t && *t) cur_service.service_type = t;
57 } else if (node.equals("serviceId")) {
58 const char* t = text.c_str();
59 if (t && *t) cur_service.service_id = t;
60 } else if (node.equals("SCPDURL")) {
61 const char* t = text.c_str();
62 if (t && *t) cur_service.scpd_url = t;
63 } else if (node.equals("controlURL")) {
64 const char* t = text.c_str();
65 if (t && *t) cur_service.control_url = t;
66 } else if (node.equals("eventSubURL")) {
67 const char* t = text.c_str();
68 if (t && *t) cur_service.event_sub_url = t;
69 }
70 } else if (path_has_icon) {
71 if (!in_icon) {
72 in_icon = true;
73 cur_icon = Icon();
74 }
75 if (node.equals("mimetype")) {
76 const char* t = text.c_str();
77 if (t && *t) cur_icon.mime = t;
78 } else if (node.equals("width")) {
79 const char* t = text.c_str();
80 cur_icon.width = t ? atoi(t) : 0;
81 } else if (node.equals("height")) {
82 const char* t = text.c_str();
83 cur_icon.height = t ? atoi(t) : 0;
84 } else if (node.equals("depth")) {
85 const char* t = text.c_str();
86 cur_icon.depth = t ? atoi(t) : 0;
87 } else if (node.equals("url")) {
88 const char* t = text.c_str();
89 if (t && *t) cur_icon.icon_url = t;
90 }
91 } else {
92 // device-level
93 if (node.equals("deviceType")) {
94 const char* t = text.c_str();
95 if (t && *t) result.device_type = t;
96 } else if (node.equals("friendlyName")) {
97 const char* t = text.c_str();
98 if (t && *t) result.friendly_name = t;
99 } else if (node.equals("manufacturer")) {
100 const char* t = text.c_str();
101 if (t && *t) result.manufacturer = t;
102 } else if (node.equals("manufacturerURL")) {
103 const char* t = text.c_str();
104 if (t && *t) result.manufacturer_url = t;
105 } else if (node.equals("modelDescription")) {
106 const char* t = text.c_str();
107 if (t && *t) result.model_description = t;
108 } else if (node.equals("modelName")) {
109 const char* t = text.c_str();
110 if (t && *t) result.model_name = t;
111 } else if (node.equals("modelNumber")) {
112 const char* t = text.c_str();
113 if (t && *t) result.model_number = t;
114 } else if (node.equals("modelURL")) {
115 const char* t = text.c_str();
116 if (t && *t) result.model_url = t;
117 } else if (node.equals("serialNumber")) {
118 const char* t = text.c_str();
119 if (t && *t) result.serial_number = t;
120 } else if (node.equals("UPC")) {
121 const char* t = text.c_str();
122 if (t && *t) result.universal_product_code = t;
123 } else if (node.equals("UDN")) {
124 const char* t = text.c_str();
125 if (t && *t) result.udn = t;
126 } else if (node.equals("URLBase")) {
127 const char* t = text.c_str();
128 if (t && *t) result.base_url = t;
129 }
130 }
131
132 // Detect leaving a service/icon block: xml_parser.parse returns nodes in
133 // document order; when the current node is outside service/icon but we
134 // had an open service/icon, the next non-service/icon node indicates
135 // the service/icon ended.
136 if (!path_has_service && in_service) {
137 // flush service
138 if (cur_service.service_id != nullptr ||
139 cur_service.service_type != nullptr) {
140 result.addService(cur_service);
141 }
143 in_service = false;
144 }
145 if (!path_has_icon && in_icon) {
146 result.addIcon(cur_icon);
147 cur_icon = Icon();
148 in_icon = false;
149 }
150 }
151 }
152
154 void end(DLNADeviceInfo& result) {
155 if (in_service) {
156 if (cur_service.service_id != nullptr ||
157 cur_service.service_type != nullptr) {
158 result.addService(cur_service);
159 }
160 in_service = false;
162 }
163 if (in_icon) {
164 result.addIcon(cur_icon);
165 in_icon = false;
166 cur_icon = Icon();
167 }
168
169 uint64_t elapsed = millis() - start_time;
170 DlnaLogger.log(DlnaLogLevel::Info, "XMLDeviceParser::parse took %d ms",
171 (int)elapsed);
172 }
173
174 protected:
178 uint64_t start_time = 0;
179 bool in_service = false;
180 bool in_icon = false;
182
183 void resetState() {
184 p_device = nullptr;
185 in_service = false;
187 in_icon = false;
188 cur_icon = Icon();
189 }
190};
191
192} // namespace tiny_dlna
Device Attributes and generation of XML using urn:schemas-upnp-org:device-1-0. We could just return a...
Definition: DLNADeviceInfo.h:25
Str udn
Definition: DLNADeviceInfo.h:259
Str model_number
Definition: DLNADeviceInfo.h:268
Str device_type
Definition: DLNADeviceInfo.h:261
Str universal_product_code
Definition: DLNADeviceInfo.h:270
void addService(DLNAServiceInfo s)
Adds a service definition.
Definition: DLNADeviceInfo.h:178
Str manufacturer_url
Definition: DLNADeviceInfo.h:264
void addIcon(Icon icon)
adds an icon
Definition: DLNADeviceInfo.h:225
Str base_url
Definition: DLNADeviceInfo.h:258
Str model_name
Definition: DLNADeviceInfo.h:266
Str manufacturer
Definition: DLNADeviceInfo.h:263
Str model_description
Definition: DLNADeviceInfo.h:265
Str serial_number
Definition: DLNADeviceInfo.h:269
Str model_url
Definition: DLNADeviceInfo.h:267
Str friendly_name
Definition: DLNADeviceInfo.h:262
Attributes needed for the DLNA Service Definition.
Definition: DLNAServiceInfo.h:18
Str event_sub_url
Definition: DLNAServiceInfo.h:41
Str service_id
Definition: DLNAServiceInfo.h:38
Str scpd_url
Definition: DLNAServiceInfo.h:39
Str service_type
Definition: DLNAServiceInfo.h:37
Str control_url
Definition: DLNAServiceInfo.h:40
Information about the icon.
Definition: Icon.h:10
const char * icon_url
Definition: Icon.h:16
int width
Definition: Icon.h:13
int height
Definition: Icon.h:14
const char * mime
Definition: Icon.h:12
int depth
Definition: Icon.h:15
Heap-backed string utility used throughout tiny_dlna.
Definition: Str.h:27
bool equals(const char *other) const
Exact string equality with C-string.
Definition: Str.h:167
const char * c_str() const
C-string pointer to internal buffer.
Definition: Str.h:88
Lightweight wrapper around std::vector with Arduino-friendly helpers and a pluggable allocator.
Definition: Vector.h:39
Incremental XML device parser using XMLParserPrint.
Definition: XMLDeviceParser.h:20
void end(DLNADeviceInfo &result)
Finalize parser state and flush any pending objects.
Definition: XMLDeviceParser.h:154
void resetState()
Definition: XMLDeviceParser.h:183
bool in_icon
Definition: XMLDeviceParser.h:180
Icon cur_icon
Definition: XMLDeviceParser.h:181
XMLParserPrint xml_parser
Definition: XMLDeviceParser.h:177
uint64_t start_time
Definition: XMLDeviceParser.h:178
XMLDeviceParser(DLNADeviceInfo &result)
Definition: XMLDeviceParser.h:22
bool in_service
Definition: XMLDeviceParser.h:179
void parse(const uint8_t *buffer, size_t len)
Definition: XMLDeviceParser.h:31
DLNAServiceInfo cur_service
Definition: XMLDeviceParser.h:175
void begin()
Definition: XMLDeviceParser.h:27
DLNADeviceInfo * p_device
Definition: XMLDeviceParser.h:176
Helper class that implements a Print interface to accumulate XML data and then parse it using XMLPars...
Definition: XMLParserPrint.h:16
size_t write(uint8_t ch) override
Writes a single byte to the buffer (Print interface)
Definition: XMLParserPrint.h:32
bool parse(Str &outNodeName, Vector< Str > &outPath, Str &outText, Str &outAttributes)
Parses the accumulated XML data and returns results via output parameters.
Definition: XMLParserPrint.h:59
Definition: Allocator.h:13