-
Notifications
You must be signed in to change notification settings - Fork 6
/
micurest-tutorial.html
172 lines (161 loc) · 36.9 KB
/
micurest-tutorial.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<title>μcuREST Tutorial</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" media="screen,projection" href="http://hutorny.in.ua/wp-content/themes/veryplaintxt/style.css" title="veryplaintxt" />
<link rel="stylesheet" type="text/css" media="print" href="http://hutorny.in.ua/wp-content/themes/veryplaintxt/print.css" />
<script type="text/javascript">
var loading_url = "http://hutorny.in.ua/wp-content/plugins/thumbnail-viewer/images/loadingImage.gif";
</script>
<style type="text/css" media="all">
body{font-family:'trebuchet ms',helvetica,sans-serif;font-size:90%;}
body div#container { float: left; margin: 0 -200px 2em 0; } body div#content { margin: 3em 200px 0 0; } body div.sidebar { float: right; }
body div#content div.hentry{text-align:justify;}
body div#content h2,div#content h3,div#content h4,div#content h5,div#content h6{font-family:verdana,geneva,sans-serif;}
body div#wrapper{max-width:65em;min-width:35em;width:80%;}
body div.sidebar{text-align:left;}
</style>
<style type="text/css" id="syntaxhighlighteranchor"></style>
<style>.term { font-family: "courier new",courier,monospace; }
span.code { font-family: "courier new",courier,monospace; font-style: italic;}
</style>
</head>
<body class="wordpress single">
<div id="wrapper">
<div id="container">
<div id="content" class="hfeed">
<div id="post-860" class="hentry p1 post publish author-Eugene category-micurest y2017 m04 d17 h12">
<h2 class="entry-title">μcuREST Tutorial</h2>
<div class="entry-content">
<h2>Getting Started</h2>
<p>With <span class="term">μcuREST</span> you can implement REST services and/or a web application for communication with your embedded application. First you’ll need to decide which resources (variables or functions of your application) you wish to expose via HTTP and assign URI to those resources. Then define a <span class="term">μcuREST</span>resource map, binding URI names to the resources. Use this map to instantiate a <code>micurest::application</code> and start a network stack for that application.</p>
<p><span id="more-860"></span></p>
<h3>Defining a Resource Map</h3>
<p>The easiest way to start is to take an example and adjust/replace the resource map according to your application needs. The resource map is a variadic template function parametrized with the resource entries. The following code sample lists five simplest resource entries of different types.</p>
<div><div id="highlighter_207832" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp comments">/* declaration of application resources */</code></div><div class="line number2 index1 alt1"><code class="cpp keyword bold">extern</code> <code class="cpp plain">cstring hello_html ();</code></div><div class="line number3 index2 alt2"><code class="cpp keyword bold">extern</code> <code class="cpp color1 bold">char</code> <code class="cpp plain">hello_text[32];</code></div><div class="line number4 index3 alt1"><code class="cpp keyword bold">extern</code> <code class="cpp color1 bold">bool</code> <code class="cpp plain">getLed();</code></div><div class="line number5 index4 alt2"><code class="cpp keyword bold">extern</code> <code class="cpp keyword bold">void</code> <code class="cpp plain">setLed(</code><code class="cpp color1 bold">bool</code><code class="cpp plain">);</code></div><div class="line number6 index5 alt1"><code class="cpp keyword bold">extern</code> <code class="cpp plain">unsigned data;</code></div><div class="line number7 index6 alt2"><code class="cpp keyword bold">extern</code> <code class="cpp plain">unsigned </code><code class="cpp color1 bold">char</code> <code class="cpp plain">blob[1024];</code></div><div class="line number8 index7 alt1"><code class="cpp keyword bold">extern</code> <code class="cpp color1 bold">size_t</code> <code class="cpp plain">blob_size;</code></div><div class="line number9 index8 alt2"> </div><div class="line number10 index9 alt1"><code class="cpp comments">/* definition of resource names */</code></div><div class="line number11 index10 alt2"><code class="cpp keyword bold">namespace</code> <code class="cpp plain">name {</code></div><div class="line number12 index11 alt1"><code class="cpp spaces"> </code><code class="cpp plain">NAME(hello_html)</code></div><div class="line number13 index12 alt2"><code class="cpp spaces"> </code><code class="cpp plain">NAME(led)</code></div><div class="line number14 index13 alt1"><code class="cpp spaces"> </code><code class="cpp plain">NAME(hello)</code></div><div class="line number15 index14 alt2"><code class="cpp spaces"> </code><code class="cpp plain">NAME(data)</code></div><div class="line number16 index15 alt1"><code class="cpp spaces"> </code><code class="cpp plain">NAME(blob)</code></div><div class="line number17 index16 alt2"><code class="cpp plain">}</code></div><div class="line number18 index17 alt1"> </div><div class="line number19 index18 alt2"><code class="cpp comments">/* map of URIs to application resources */</code></div><div class="line number20 index19 alt1"><code class="cpp keyword bold">const</code> <code class="cpp plain">directory& resourceMap(){</code></div><div class="line number21 index20 alt2"><code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">Root<</code></div><div class="line number22 index21 alt1"><code class="cpp spaces"> </code><code class="cpp plain">resource::FileConstString<name::hello_html, hello_html, media::html>,</code></div><div class="line number23 index22 alt2"><code class="cpp spaces"> </code><code class="cpp plain">resource::FileText<name::hello, </code><code class="cpp keyword bold">sizeof</code><code class="cpp plain">(hello_text), hello_text>,</code></div><div class="line number24 index23 alt1"><code class="cpp spaces"> </code><code class="cpp plain">resource::FileFunctions<name::led, </code><code class="cpp color1 bold">bool</code><code class="cpp plain">, getLed, setLed>,</code></div><div class="line number25 index24 alt2"><code class="cpp spaces"> </code><code class="cpp plain">resource::FileVariable<name::data, unsigned, &data>,</code></div><div class="line number26 index25 alt1"><code class="cpp spaces"> </code><code class="cpp plain">resource::FileBinary<name::blob, &blob_size, </code><code class="cpp keyword bold">sizeof</code><code class="cpp plain">(blob), blob></code></div><div class="line number27 index26 alt2"><code class="cpp spaces"> </code><code class="cpp plain">>();</code></div><div class="line number28 index27 alt1"><code class="cpp plain">}</code></div></div></td></tr></tbody></table></div></div>
<p>Once you get familiar with <code>resource::File*</code> templates, you may switch to their short codes <code>F:</code></p>
<div><div id="highlighter_991663" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp comments">/* map of URIs to application resources (same as above) */</code></div><div class="line number2 index1 alt1"><code class="cpp keyword bold">const</code> <code class="cpp plain">directory& resourceMap(){</code></div><div class="line number3 index2 alt2"><code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">Root<</code></div><div class="line number4 index3 alt1"><code class="cpp spaces"> </code><code class="cpp plain">F<name::hello_html, hello_html, media::html>,</code></div><div class="line number5 index4 alt2"><code class="cpp spaces"> </code><code class="cpp plain">F<name::hello, </code><code class="cpp keyword bold">sizeof</code><code class="cpp plain">(hello_text), hello_text>,</code></div><div class="line number6 index5 alt1"><code class="cpp spaces"> </code><code class="cpp plain">F<name::led, </code><code class="cpp color1 bold">bool</code><code class="cpp plain">, getLed, setLed>,</code></div><div class="line number7 index6 alt2"><code class="cpp spaces"> </code><code class="cpp plain">F<name::data, unsigned, &data>,</code></div><div class="line number8 index7 alt1"><code class="cpp spaces"> </code><code class="cpp plain">F<name::blob, &blob_size, </code><code class="cpp keyword bold">sizeof</code><code class="cpp plain">(blob), blob></code></div><div class="line number9 index8 alt2"><code class="cpp spaces"> </code><code class="cpp plain">>();</code></div></div></td></tr></tbody></table></div></div>
<h3>Instantiating and Running an Application</h3>
<p>Interaction with the network stack depends on the underlying stack implementation. In a poll-style stack, such as Wiznet’s for Arduino, main application instantiates application, initializes the server and runs the server in the loop:</p>
<div><div id="highlighter_543200" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp plain">micurest::application MyApp(resourceMap);</code></div><div class="line number2 index1 alt1"><code class="cpp plain">tcp::server server(MyApp);</code></div><div class="line number3 index2 alt2"><code class="cpp keyword bold">void</code> <code class="cpp plain">setup() {</code></div><div class="line number4 index3 alt1"><code class="cpp spaces"> </code><code class="cpp plain">server.listen(80);</code></div><div class="line number5 index4 alt2"><code class="cpp plain">}</code></div><div class="line number6 index5 alt1"><code class="cpp keyword bold">void</code> <code class="cpp plain">loop() {</code></div><div class="line number7 index6 alt2"><code class="cpp spaces"> </code><code class="cpp plain">server.run();</code></div><div class="line number8 index7 alt1"><code class="cpp comments">// ...</code></div><div class="line number9 index8 alt2"><code class="cpp plain">}</code></div></div></td></tr></tbody></table></div></div>
<p>In an event driven network stack, such as lwIP, the server is driven by events coming from the network stack, so it is sufficient to instantiate the application and initializes the server:</p>
<div><div id="highlighter_728407" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp plain">micurest::application MyApp(resourceMap);</code></div><div class="line number2 index1 alt1"><code class="cpp plain">tcp::server server(MyApp);</code></div><div class="line number3 index2 alt2"><code class="cpp keyword bold">void</code> <code class="cpp plain">setup() {</code></div><div class="line number4 index3 alt1"><code class="cpp spaces"> </code><code class="cpp plain">server.listen(80);</code></div><div class="line number5 index4 alt2"><code class="cpp plain">}</code></div></div></td></tr></tbody></table></div></div>
<h2>Resource Map Elements</h2>
<h3>Root</h3>
<p>A Resource Map root is a <code>directory</code> reference returned by the <code>Root</code> variadic template function, parametrized with top-level entries. There is no limitation on number of entries or number of resource maps (except, of course, those exposed by compiler or target platform capabilities).</p>
<div><div id="highlighter_214824" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">const</code> <code class="cpp plain">directory& resourceMap(){</code></div><div class="line number2 index1 alt1"><code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">Root<…>();</code></div><div class="line number3 index2 alt2"><code class="cpp plain">}</code></div></div></td></tr></tbody></table></div></div>
<h3>Entries</h3>
<p>In the examples on top of this tutorial <the code="">resource::File… templates combine resource name and its content. In a more generic case, resource name and its content are introduced with different templates – <code>resource::Entry…</code> and <code>resource::Node…</code> . The first one is responsible for matching resource name and the latter – for providing the content.</the></p>
<div><div id="highlighter_488423" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp plain">resource::EntryGenericResource<name::anything, resource::NodeJSON<MyClass::json>></code></div></div></td></tr></tbody></table></div></div>
<p>or in short codes:</p>
<div><div id="highlighter_324844" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp plain">E<name::anything, N<MyClass::json>></code></div></div></td></tr></tbody></table></div></div>
<p><span class="term">μcuREST</span> provides several templates for defining entries:</p>
<ul>
<li><code>resource::EntryGenericResource</code> – a generic named entry</li>
<li><code>resource::EntryIndexedResource</code> – indexed homogeneous entries (see below)</li>
<li><code>resource::EntryDynamicResource</code> – indexed heterogeneous entries</li>
</ul>
<h3>Resource Names</h3>
<p>Direct use of string literals as templates parameters is not supported by C++11. Therefore <span class="term">μcuREST</span> defines names as functions returning <code>cstring</code><sup title="cstring is a typedef to const char* on all platforms, except avr, where names are allocated on progmem and cstring is defined as progmem<char> instead"><a href="#fn1">1</a></sup>. This workaround does not allow inline name definitions, e.g. a name should be declared before its use. As a good practice, names are placed in <code>namespace name</code>.</p>
<h3>Indexed Entries</h3>
<p>Described so far use cases operate with on static resource names. But what if your application needs to expose a set of similar resources, such as array of values or number of GPIO pins? To address this use case <span class="term">μcuREST</span> offers indexed entries with vectorized nodes. When matching the URI part to an indexed entry, <span class="term">μcuREST</span> calls an identity parser, associated with the entry. The parser processes the URI part and stores the identity in the message. Then <span class="term">μcuREST</span> accesses the array or calls the functions using the identity as the index. In latter case you need to provide three functions: a getter, a setter and a detector. The following examples illustrate use of an indexed entry with functions and with an array.</p>
<div><div id="highlighter_77532" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">extern</code> <code class="cpp color1 bold">bool</code> <code class="cpp plain">digital_has(</code><code class="cpp color1 bold">size_t</code> <code class="cpp plain">index);</code></div><div class="line number2 index1 alt1"><code class="cpp keyword bold">extern</code> <code class="cpp plain">byte digital_read(</code><code class="cpp color1 bold">size_t</code> <code class="cpp plain">index);</code></div><div class="line number3 index2 alt2"><code class="cpp keyword bold">extern</code> <code class="cpp keyword bold">void</code> <code class="cpp plain">digital_write(</code><code class="cpp color1 bold">size_t</code> <code class="cpp plain">index, byte val);</code></div><div class="line number4 index3 alt1"> </div><div class="line number5 index4 alt2"><code class="cpp keyword bold">const</code> <code class="cpp plain">directory& resourceMap(){</code></div><div class="line number6 index5 alt1"><code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">Root<</code></div><div class="line number7 index6 alt2"><code class="cpp spaces"> </code><code class="cpp plain">resource::EntryIndexedResource<identity::numeric,</code></div><div class="line number8 index7 alt1"><code class="cpp spaces"> </code><code class="cpp plain">resource::NodeIndexedVector<</code></div><div class="line number9 index8 alt2"><code class="cpp spaces"> </code><code class="cpp plain">accessor::vector<byte,</code></div><div class="line number10 index9 alt1"><code class="cpp spaces"> </code><code class="cpp plain">digital_read, digital_write, digital_has>>></code></div><div class="line number11 index10 alt2"><code class="cpp spaces"> </code><code class="cpp plain">>();</code></div><div class="line number12 index11 alt1"><code class="cpp plain">}</code></div><div class="line number13 index12 alt2"> </div><div class="line number14 index13 alt1"><code class="cpp keyword bold">extern</code> <code class="cpp plain">unsigned array[12];</code></div><div class="line number15 index14 alt2"> </div><div class="line number16 index15 alt1"><code class="cpp keyword bold">const</code> <code class="cpp plain">directory& resourceMap(){</code></div><div class="line number17 index16 alt2"><code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">Root<</code></div><div class="line number18 index17 alt1"><code class="cpp spaces"> </code><code class="cpp plain">resource::EntryIndexedResource<identity::numeric,</code></div><div class="line number19 index18 alt2"><code class="cpp spaces"> </code><code class="cpp plain">resource::NodeIndexedVector<</code></div><div class="line number20 index19 alt1"><code class="cpp spaces"> </code><code class="cpp plain">accessor::array<unsigned, details::countof(array), array>>></code></div><div class="line number21 index20 alt2"><code class="cpp spaces"> </code><code class="cpp plain">>();</code></div><div class="line number22 index21 alt1"><code class="cpp plain">}</code></div></div></td></tr></tbody></table></div></div>
<p>In the example above all entries are of the same nature – elements of unsigned array. In a more advanced cases an entry may index elements of various nature. This is achieved with <code>resource::EntryDynamicResource</code> template that accepts an identity parser and a function returning entry reference for the identity passed as a parameter:</p>
<div><div id="highlighter_855028" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">const</code> <code class="cpp plain">details::node& mynodes(</code><code class="cpp keyword bold">const</code> <code class="cpp plain">identity::type& id) {</code></div><div class="line number2 index1 alt1"><code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">(id&1) ? resource::NodeJSON<Male::json>() : resource::NodeJSON<Female::json>(); </code></div><div class="line number3 index2 alt2"><code class="cpp plain">}</code></div><div class="line number4 index3 alt1"> </div><div class="line number5 index4 alt2"><code class="cpp keyword bold">const</code> <code class="cpp plain">directory& resourceMap() </code><code class="cpp keyword bold">noexcept</code> <code class="cpp plain">{</code></div><div class="line number6 index5 alt1"><code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">Root<resource::EntryDynamicResource<identity::numeric, mynodes>>();</code></div><div class="line number7 index6 alt2"><code class="cpp plain">}</code></div></div></td></tr></tbody></table></div></div>
<h3>Identity Parser</h3>
<p>Currently μcuREST implements only one identity parser – numeric. If your application needs another kind of index, you may use your own parser instead. It is a function with rather simple signature:</p>
<div><div id="highlighter_92691" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp color1 bold">bool</code> <code class="cpp plain">parser(</code><code class="cpp keyword bold">const</code> <code class="cpp plain">char_t* str, identity::type& identity); </code><code class="cpp comments">// on success fill identity and return true.</code></div></div></td></tr></tbody></table></div></div>
<h3>Nodes</h3>
<p><span class="term">μcuREST</span> provides several templates for defining nodes:</p>
<ul>
<li><code>resource::NodeTextFuction<M,V></code> – text content of media type M returned by function V</li>
<li><code>resource::NodeProvider<M,P></code> – text content of media type M written by function P</li>
<li><code>resource::NodeAction<F,L></code> – function F called on PUT with a payload string of max length L</li>
<li><code>resource::NodeJSON<V></code> – a JSON value, provided via COJSON structure V</li>
<li><code>resource::NodeJSONRpc<V,M></code> – a JSON value with alternate media type M</li>
<li><code>resource::NodeIndexedVector</code> – an indexable node bound to a vector via accessor X (<code>accessor::vector</code> or <code>accessor::bunch</code> </li>
</ul>
<h3>Files</h3>
<p><span class="term">μcuREST</span> provides several templates for defining “files” (combination of entry and node):</p>
<ul>
<li><code>resource::FileAccessor<id,X></code> – an application resource accessible via accessor X (<code>cojson::accessor::*</code>)</li>
<li><code>resource::FileVariable<id,T,V></code> – a static variable type T accessible via its pointer V</li>
<li><code>resource::FileFunctions<id,T,G,P></code> – a pair of functions G/P called on GET/PUT and returing/accepting value of type T</li>
<li><code>resource::FileConstString<id,F,M></code> – GET-only string content of type M provided by function F</li>
<li><code>resource::FileText<id,N,V></code> – plain text zero-terminated char buffer V of maximal length N</li>
<li><code>resource::FileBinary<id,L,N,V></code> – An r/w octet-stream stored in char buffer V of of maximal length N and its current length stored in L</li>
</ul>
<h3>Directories</h3>
<p><span class="term">μcuREST</span> allows hierarchical structuring of the resource map by organizing entries in directories with template <code>resource::Dir</code></p>
<ul>
<li><code>resource::Dir<id,...L></code> – directory with name id nesting a set of entries L…</li>
</ul>
<h3>Short Codes</h3>
<p><span class="term">μcuREST</span> provides optional short names for all Resource Map elements:</p>
<ul>
<li><code>resource::File…</code> – <code>F</code></li>
<li><code>resource::Entry…</code> – <code>E</code></li>
<li><code>resource::Node…</code> – <code>N</code></li>
<li><code>resource::Dir</code> – <code>D</code></li>
</ul>
<h3>Custom Nodes</h3>
<p>If none of the listed above templates suite needs of your application, you may define your own Node. A Node is a function returning const reference to an instance of resource::node implementing get and put methods as needed:</p>
<div><div id="highlighter_895949" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">const</code> <code class="cpp plain">resource::node& MyNode() </code><code class="cpp keyword bold">noexcept</code> <code class="cpp plain">{</code></div><div class="line number2 index1 alt1"><code class="cpp spaces"> </code><code class="cpp keyword bold">static</code> <code class="cpp keyword bold">const</code> <code class="cpp keyword bold">struct</code> <code class="cpp plain">local : resource::node {</code></div><div class="line number3 index2 alt2"><code class="cpp spaces"> </code><code class="cpp keyword bold">void</code> <code class="cpp plain">get(details::message& msg) </code><code class="cpp keyword bold">const</code> <code class="cpp keyword bold">noexcept</code> <code class="cpp plain">{</code></div><div class="line number4 index3 alt1"><code class="cpp spaces"> </code><code class="cpp plain">msg.status(status_t::OK);</code></div><div class="line number5 index4 alt2"><code class="cpp spaces"> </code><code class="cpp plain">ostream& out(msg.obody());</code></div><div class="line number6 index5 alt1"><code class="cpp spaces"> </code><code class="cpp comments">//...</code></div><div class="line number7 index6 alt2"><code class="cpp spaces"> </code><code class="cpp plain">}</code></div><div class="line number8 index7 alt1"><code class="cpp spaces"> </code><code class="cpp keyword bold">void</code> <code class="cpp plain">put(details::message& msg) </code><code class="cpp keyword bold">const</code> <code class="cpp keyword bold">noexcept</code> <code class="cpp plain">{</code></div><div class="line number9 index8 alt2"><code class="cpp spaces"> </code><code class="cpp plain">istream& in(msg.ibody());</code></div><div class="line number10 index9 alt1"><code class="cpp spaces"> </code><code class="cpp comments">//...</code></div><div class="line number11 index10 alt2"><code class="cpp spaces"> </code><code class="cpp plain">msg.status(status_t::No_Content);</code></div><div class="line number12 index11 alt1"><code class="cpp spaces"> </code><code class="cpp plain">}</code></div><div class="line number13 index12 alt2"> </div><div class="line number14 index13 alt1"><code class="cpp spaces"> </code><code class="cpp plain">} l;</code></div><div class="line number15 index14 alt2"><code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">l;</code></div><div class="line number16 index15 alt1"><code class="cpp plain">}</code></div></div></td></tr></tbody></table></div></div>
<h2>Configuration</h2>
<p><span class="term">μcuREST</span> deploys <a href="http://hutorny.in.ua/research/cascaded-configuration-sets-for-c1y" target="_blank">Cascaded Configuration Sets</a>. Each module that uses configurable options has a <code>.ccs</code> file with a default configuration. To change some of the configurable options, you need to specialize <code>Configuration</code> template with a target, a build or both, override options in the body of that template, specialize configuration selector and place all these in the <code>configuration.h</code> file. For example:</p>
<div><div id="highlighter_882155" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp preprocessor">#include "micurest/network_spark_socket.ccs"</code></div><div class="line number2 index1 alt1"><code class="cpp keyword bold">namespace</code> <code class="cpp plain">configuration {</code></div><div class="line number3 index2 alt2"><code class="cpp keyword bold">struct</code> <code class="cpp plain">Current : Is<target::Photon, build::Default> {};</code></div><div class="line number4 index3 alt1"><code class="cpp keyword bold">template</code><code class="cpp plain"><</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">build></code></div><div class="line number5 index4 alt2"><code class="cpp keyword bold">struct</code> <code class="cpp plain">Configuration<micurest::network_spark_socket::proto::tcp,target::Photon,build></code></div><div class="line number6 index5 alt1"><code class="cpp spaces"> </code><code class="cpp plain">: Configuration<micurest::network_spark_socket::proto::tcp,target::All,build> {</code></div><div class="line number7 index6 alt2"><code class="cpp spaces"> </code><code class="cpp keyword bold">static</code> <code class="cpp keyword bold">constexpr</code> <code class="cpp color1 bold">short</code> <code class="cpp plain">inactivity_timeout = 5000;</code></div><div class="line number8 index7 alt1"><code class="cpp plain">};</code></div><div class="line number9 index8 alt2"><code class="cpp plain">}</code></div></div></td></tr></tbody></table></div></div>
<h2>Modularization</h2>
<p>In a large or complex project, the application’s Resource Map may not be fitting/suiting a single compilation unit. Since every entry and every node in the resource map is eventually a function, the standard C/C++ modularization approach works for <span class="term">μcuREST</span> as well:</p>
<div><div id="highlighter_558087" class="syntaxhighlighter nogutter cpp"><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp comments">/* definition of resource names */</code></div><div class="line number2 index1 alt1"><code class="cpp keyword bold">namespace</code> <code class="cpp plain">name {</code></div><div class="line number3 index2 alt2"><code class="cpp spaces"> </code><code class="cpp plain">NAME(mynode1)</code></div><div class="line number4 index3 alt1"><code class="cpp spaces"> </code><code class="cpp plain">NAME(mynode2)</code></div><div class="line number5 index4 alt2"><code class="cpp plain">}</code></div><div class="line number6 index5 alt1"> </div><div class="line number7 index6 alt2"><code class="cpp comments">/* declaration of resource map nodes and entries, implemented in other source files */</code></div><div class="line number8 index7 alt1"><code class="cpp keyword bold">extern</code> <code class="cpp keyword bold">const</code> <code class="cpp plain">resource::node& mynode1();</code></div><div class="line number9 index8 alt2"><code class="cpp keyword bold">extern</code> <code class="cpp keyword bold">const</code> <code class="cpp plain">resource::node& mynode2();</code></div><div class="line number10 index9 alt1"><code class="cpp keyword bold">extern</code> <code class="cpp keyword bold">const</code> <code class="cpp plain">resource::entry& myentry();</code></div><div class="line number11 index10 alt2"> </div><div class="line number12 index11 alt1"><code class="cpp keyword bold">const</code> <code class="cpp plain">directory& resourceMap5() </code><code class="cpp keyword bold">noexcept</code> <code class="cpp plain">{</code></div><div class="line number13 index12 alt2"><code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">Root<</code></div><div class="line number14 index13 alt1"><code class="cpp spaces"> </code><code class="cpp plain">E<name::mynode1, mynode1>,</code></div><div class="line number15 index14 alt2"><code class="cpp spaces"> </code><code class="cpp plain">E<name::mynode2, mynode2>,</code></div><div class="line number16 index15 alt1"><code class="cpp spaces"> </code><code class="cpp plain">myentry</code></div><div class="line number17 index16 alt2"><code class="cpp spaces"> </code><code class="cpp plain">>();</code></div><div class="line number18 index17 alt1"><code class="cpp plain">}</code></div></div></td></tr></tbody></table></div></div>
<h3>Cross Origin Resource Sharing</h3>
<p>MCU is a constrained device – it has very limited storage and computation power. You should take into account these limitations in your application design. A reasonable limitation for every HTTP response is one MTU (~1400) – it does not bring network latency into MCU’s loop, makes the timings predictable and does not much distract MCU’s from its primary tasks. On the other hand, a rich web UI may require large file volumes overwhelming 1.4K limit. To solve this problem, your application may use resources hosted on a cloud server – scripts, stylesheets, images, HTML pages etc.</p>
<p>Using shared scripts, stylesheets, images from a cloud server is easy – once the server is configured for CORS, you just link shared resources in the application’s HTML pages. With the HTML pages itself, (which also may easily exceed 1.4K in size), simple linking hits browser’s security restrictions – JS from such page is not allowed to access MCU because of same origin policy. To workaround this restriction, your application may link a bootstrap script from the cloud, and the script then constructs HTML page on the fly, as many JS frameworks normally do single-pager apps. μcuREST examples also use this approach and load shared HTML pages into an inner iframe.</p>
<hr>
<sup><a id="fn1">1</a></sup><code>cstring </code>is a <code>typedef</code> to <code>const char*</code> on all platforms, except avr, where names are allocated on <code>progmem</code> and <code>cstring</code> is defined as <code>progmem<char></code> instead.<p></p>
</div>
</div><!-- post-860 -->
</div><!-- #content .hfeed -->
</div><!-- #container -->
<script type='text/javascript' src='http://hutorny.in.ua/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shCore.js?ver=3.0.9b'></script>
<script type='text/javascript' src='http://hutorny.in.ua/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushCpp.js?ver=3.0.9b'></script>
<script type='text/javascript' src='http://hutorny.in.ua/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushJScript.js?ver=3.0.9b'></script>
<script type='text/javascript' src='http://hutorny.in.ua/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/scripts/shBrushPlain.js?ver=3.0.9b'></script>
<script type='text/javascript'>
(function(){
var corecss = document.createElement('link');
var themecss = document.createElement('link');
var corecssurl = "http://hutorny.in.ua/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/styles/shCore.css?ver=3.0.9b";
if ( corecss.setAttribute ) {
corecss.setAttribute( "rel", "stylesheet" );
corecss.setAttribute( "type", "text/css" );
corecss.setAttribute( "href", corecssurl );
} else {
corecss.rel = "stylesheet";
corecss.href = corecssurl;
}
document.getElementsByTagName("head")[0].insertBefore( corecss, document.getElementById("syntaxhighlighteranchor") );
var themecssurl = "http://hutorny.in.ua/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/styles/shThemeEclipse.css?ver=3.0.9b";
if ( themecss.setAttribute ) {
themecss.setAttribute( "rel", "stylesheet" );
themecss.setAttribute( "type", "text/css" );
themecss.setAttribute( "href", themecssurl );
} else {
themecss.rel = "stylesheet";
themecss.href = themecssurl;
}
//document.getElementById("syntaxhighlighteranchor").appendChild(themecss);
document.getElementsByTagName("head")[0].insertBefore( themecss, document.getElementById("syntaxhighlighteranchor") );
})();
SyntaxHighlighter.config.strings.expandSource = '+ expand source';
SyntaxHighlighter.config.strings.help = '?';
SyntaxHighlighter.config.strings.alert = 'SyntaxHighlighter\n\n';
SyntaxHighlighter.config.strings.noBrush = 'Can\'t find brush for: ';
SyntaxHighlighter.config.strings.brushNotHtmlScript = 'Brush wasn\'t configured for html-script option: ';
SyntaxHighlighter.defaults['light'] = true;
SyntaxHighlighter.defaults['pad-line-numbers'] = true;
SyntaxHighlighter.all();
</script>
</div><!-- #wrapper -->
</body><!-- end trasmission -->
</html>