-
Notifications
You must be signed in to change notification settings - Fork 584
/
3.1.coap.md.html
601 lines (585 loc) · 52.7 KB
/
3.1.coap.md.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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title></title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
<link rel="stylesheet" href="css/vendor.css" type="text/css" />
</head>
<body>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wb="http://open.weibo.com/wb" >
<head>
<title>一步步搭建物联网系统(教你设计物联网系统)</title>
<meta name="keywords" content="设计物联网系统,物联网系统设计">
<meta name="description" content="一份关于如何设计物联网系统的文档">
<link rel="stylesheet" href="../css/vendor.css" />
</head>
<body class="container inner wrap">
<h1>一步步搭建物联网系统(教你设计物联网系统)</h1>
</body>
</html>
<div id="TOC">
<ul>
<li><a href="#restful的coap协议"><span class="toc-section-number">1</span> RESTful的CoAP协议</a><ul>
<li><a href="#coap-嵌入式系统的rest"><span class="toc-section-number">1.1</span> CoAP: 嵌入式系统的REST</a></li>
<li><a href="#coap-命令行工具"><span class="toc-section-number">1.2</span> CoAP 命令行工具</a><ul>
<li><a href="#node-coap-cli"><span class="toc-section-number">1.2.1</span> Node CoAP CLI</a></li>
<li><a href="#libcoap"><span class="toc-section-number">1.2.2</span> libcoap</a></li>
<li><a href="#firefox-copper"><span class="toc-section-number">1.2.3</span> Firefox Copper</a></li>
</ul></li>
<li><a href="#coap-helloworld"><span class="toc-section-number">1.3</span> CoAP Hello,World</a></li>
<li><a href="#coap-数据库查询"><span class="toc-section-number">1.4</span> CoAP 数据库查询</a><ul>
<li><a href="#node-module"><span class="toc-section-number">1.4.1</span> Node Module</a></li>
<li><a href="#node-sqlite3"><span class="toc-section-number">1.4.2</span> Node-Sqlite3</a></li>
<li><a href="#查询数据"><span class="toc-section-number">1.4.3</span> 查询数据</a></li>
</ul></li>
<li><a href="#coap-block"><span class="toc-section-number">1.5</span> CoAP Block</a><ul>
<li><a href="#coap-post"><span class="toc-section-number">1.5.1</span> CoAP POST</a></li>
<li><a href="#coap-content-types"><span class="toc-section-number">1.5.2</span> CoAP Content Types</a></li>
</ul></li>
<li><a href="#coap-json"><span class="toc-section-number">1.6</span> CoAP JSON</a></li>
</ul></li>
</ul>
</div>
<h1 id="restful的coap协议"><span class="header-section-number">1</span> RESTful的CoAP协议</h1>
<h2 id="coap-嵌入式系统的rest"><span class="header-section-number">1.1</span> CoAP: 嵌入式系统的REST</h2>
<p>引自维基百科上的介绍,用的是谷歌翻译。。。</p>
<blockquote>
<p>受约束的应用协议(COAP)是一种软件协议旨在以非常简单的电子设备,使他们能够在互联网上进行交互式通信中使用。它特别针对小型低功率传感器,开关,阀门和需要被控制或监督远程,通过标准的Internet网络类似的组件。 COAP是一个应用层协议,该协议是用于在资源受限的网络连接设备,例如无线传感器网络节点使用。 COAP被设计为容易地转换为HTTP与Web简化集成,同时也能满足特殊的要求,例如多播支持,非常低的开销,和简单性。多播,低开销,以及简单性是因特网极其重要物联网(IOT)和机器对机器(M2M)设备,这往往是积重难返,有太多的内存和电源,比传统的互联网设备有。因此,效率是非常重要的。 COAP可以在支持UDP或UDP的模拟大多数设备上运行。</p>
</blockquote>
<p>简单地来说,CoAP是简化了HTTP协议的RESTful API,因而也只提供了REST的四个方法,即PUT,GET,POST和DELETE。对于微小的资源受限,在资源受限的通信的IP的网络,HTTP不是一种可行的选择。它占用了太多的资源和太多的带宽。而对于物联网这种嵌入式设备来说,关于资源与带宽,是我们需要优先考虑的内容。</p>
<ul>
<li>CoAP采用了二进制报头,而不是文本报头(text header)</li>
<li>CoAP降低了头的可用选项的数量。</li>
<li>CoAP减少了一些HTTP的方法</li>
<li>CoAP可以支持检测装置</li>
</ul>
<h2 id="coap-命令行工具"><span class="header-section-number">1.2</span> CoAP 命令行工具</h2>
<p>为了测试测试我们的代码是否是正确工作,我们需要一个CoAP的命令行工具。目前有两个不错的工具可以使用。</p>
<ul>
<li>CoAP-cli,一个基于NodeJS的CoAP命令行工具,其核心是基于Node-CoAP库。</li>
<li>libcooap,一个用C写的CoAP命令行工具。</li>
<li>FireFox Copper, 一个Firefox的插件。</li>
</ul>
<h3 id="node-coap-cli"><span class="header-section-number">1.2.1</span> Node CoAP CLI</h3>
<p>安装命令如下</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"> <span class="kw">npm</span> install coap-cli -g </code></pre></div>
<h4 id="coap命令行"><span class="header-section-number">1.2.1.1</span> CoAP命令行</h4>
<p>在coap-cli中,一共有四个方法。分别表示REST的四种不同的方式:</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">Commands</span>:
<span class="kw">get</span> performs a GET request
<span class="kw">put</span> performs a PUT request
<span class="kw">post</span> performs a POST request
<span class="kw">delete</span> performs a DELETE request</code></pre></div>
<p>在这里,我们用<a href="coap://vs0.inf.ethz.ch/" class="uri">coap://vs0.inf.ethz.ch/</a>来作一个简单的测试</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">coap</span> get coap://vs0.inf.ethz.ch/
<span class="kw">(2.05)</span> <span class="kw">************************************************************</span>
<span class="kw">I-D</span></code></pre></div>
<p>测试一下现在的最小的物联网系统CoAP版</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">coap</span> get coap://iot-coap.phodal.com/id/1
<span class="kw">(2.05)</span> [{<span class="st">"id"</span>:<span class="kw">1</span>,<span class="st">"value"</span>:<span class="st">"is id 1"</span>,<span class="st">"sensors1"</span>:19,<span class="st">"sensors2"</span>:20}]</code></pre></div>
<h3 id="libcoap"><span class="header-section-number">1.2.2</span> libcoap</h3>
<h4 id="mac-os-libcoap安装"><span class="header-section-number">1.2.2.1</span> mac os libcoap安装</h4>
<p>Mac OS下可以直接用</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">brew</span> install libcoap</code></pre></div>
<h4 id="ubuntu-libcoap安装"><span class="header-section-number">1.2.2.2</span> Ubuntu libcoap安装</h4>
<p>Ubuntu GNU/Linux下</p>
<h4 id="windows-libcoap安装"><span class="header-section-number">1.2.2.3</span> Windows libcoap安装</h4>
<p>Windows 下</p>
<p>安装完libcoap,我们可以直接用自带的两个命令</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">coap-client</span>
<span class="kw">coap-server</span></code></pre></div>
<p>1.用coap-server启一个CoAP服务</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">coap-server</span></code></pre></div>
<p>2.客户端获取数据</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">coap-client</span> -m get coap://localhost</code></pre></div>
<p>返回结果</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">v</span>:1 t:0 tkl:0 c:1 id:37109
<span class="kw">This</span> is a test server made with libcoap (see http://libcoap.sf.net)
<span class="kw">Copyright</span> (C) <span class="kw">2010--2013</span> Olaf Bergmann <span class="kw"><</span>[email protected]<span class="kw">></span></code></pre></div>
<h3 id="firefox-copper"><span class="header-section-number">1.2.3</span> Firefox Copper</h3>
<p>为了能访问<a href="coap://localhost/" class="uri">coap://localhost/</a>,于是我们便需要安装一个Firefox并安装一个名为Copper的插件。</p>
<ol style="list-style-type: decimal">
<li><p>下载地址: <a href="https://addons.mozilla.org/en-US/firefox/addon/copper-270430/" class="uri">https://addons.mozilla.org/en-US/firefox/addon/copper-270430/</a></p></li>
<li><p>作为测试我们同样可以访问 <a href="coap://vs0.inf.ethz.ch:5683/" class="uri">coap://vs0.inf.ethz.ch:5683/</a></p></li>
</ol>
<h2 id="coap-helloworld"><span class="header-section-number">1.3</span> CoAP Hello,World</h2>
<p>接着我们便开始试试做一个简单的CoAP协议的应用:</p>
<p>这里用到的是一个Nodejs的扩展Node-CoAP</p>
<blockquote>
<p>node-coap is a client and server library for CoAP modelled after the http module.</p>
</blockquote>
<p>Node-CoAP是一个客户端和服务端的库用于CoAP的模块建模。创建一个package.json文件,添加这个库</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="op">{</span>
<span class="st">"dependencies"</span><span class="op">:{</span>
<span class="st">"coap"</span><span class="op">:</span> <span class="st">"0.7.2"</span>
<span class="op">}</span>
<span class="op">}</span></code></pre></div>
<p>接着执行</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">npm</span> install</code></pre></div>
<p>就可以安装好这个库。如果遇到权限问题,请用</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">sudo</span> npm install</code></pre></div>
<p>接着,创建这样一个app.js</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">const</span> coap <span class="op">=</span> <span class="at">require</span>(<span class="st">'coap'</span>)
<span class="op">,</span> server <span class="op">=</span> <span class="va">coap</span>.<span class="at">createServer</span>()
<span class="va">server</span>.<span class="at">on</span>(<span class="st">'request'</span><span class="op">,</span> <span class="kw">function</span>(req<span class="op">,</span> res) <span class="op">{</span>
<span class="va">res</span>.<span class="at">end</span>(<span class="st">'Hello '</span> <span class="op">+</span> <span class="va">req</span>.<span class="va">url</span>.<span class="at">split</span>(<span class="st">'/'</span>)[<span class="dv">1</span>] <span class="op">+</span> <span class="st">'</span><span class="sc">\n</span><span class="st">'</span>)
<span class="op">}</span>)
<span class="va">server</span>.<span class="at">listen</span>(<span class="kw">function</span>() <span class="op">{</span>
<span class="va">console</span>.<span class="at">log</span>(<span class="st">'server started'</span>)
<span class="op">}</span>) </code></pre></div>
<p>执行</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">node</span> app.js</code></pre></div>
<p>便可以在浏览器上访问了,因为现在什么也没有,所以什么也不会返回。</p>
<p>接着下来再创建一个client端的js,并运行之</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">const</span> coap <span class="op">=</span> <span class="at">require</span>(<span class="st">'coap'</span>)
<span class="op">,</span> req <span class="op">=</span> <span class="va">coap</span>.<span class="at">request</span>(<span class="st">'coap://localhost/World'</span>)
<span class="va">req</span>.<span class="at">on</span>(<span class="st">'response'</span><span class="op">,</span> <span class="kw">function</span>(res) <span class="op">{</span>
<span class="va">res</span>.<span class="at">pipe</span>(<span class="va">process</span>.<span class="at">stdout</span>)
<span class="op">}</span>)
<span class="va">req</span>.<span class="at">end</span>()</code></pre></div>
<p>就可以在console上输出</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">Hello</span> World </code></pre></div>
<p>也就达到了我们的目的,用CoAP协议创建一个服务,接着我们应该用它创建更多的东西,如产生JSON数据,以及RESTful。和HTTP版的最小物联网系统一样,CoAP版的最小物联网系统也是要返回JSON的。</p>
<h2 id="coap-数据库查询"><span class="header-section-number">1.4</span> CoAP 数据库查询</h2>
<h3 id="node-module"><span class="header-section-number">1.4.1</span> Node Module</h3>
<p>这说里NodeJS Module的意义是因为我们需要在别的地方引用到db_helper这个库,也就是下一小节要的讲的内容。</p>
<p>这样我们就可以在server.js类似于这样去引用这个js库。</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> DBHelper <span class="op">=</span> <span class="at">require</span>(<span class="st">'./db_helper.js'</span>)<span class="op">;</span>
<span class="va">DBHelper</span>.<span class="at">initDB</span>()<span class="op">;</span></code></pre></div>
<p>而这样调用的前提是我们需要去声明这样的module,为了方便地导出函数功能调用。</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">function</span> <span class="at">DBHelper</span>()<span class="op">{</span>
<span class="op">}</span>
<span class="va">DBHelper</span>.<span class="at">initDB</span> <span class="op">=</span> <span class="kw">function</span>()<span class="op">{};</span>
<span class="va">module</span>.<span class="at">exports</span> <span class="op">=</span> DBHelper<span class="op">;</span></code></pre></div>
<h3 id="node-sqlite3"><span class="header-section-number">1.4.2</span> Node-Sqlite3</h3>
<p>这次我们用的是SQLite3(你可以用MySQL,出于安全考虑用SQLite3,SQLite3产生的是一个文件)。一个简单的initDB函数</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> db <span class="op">=</span> <span class="kw">new</span> <span class="va">sqlite3</span>.<span class="at">Database</span>(config[<span class="st">"db_name"</span>])<span class="op">;</span>
<span class="kw">var</span> create_table <span class="op">=</span> <span class="st">'create table if not exists basic ('</span> <span class="op">+</span> config[<span class="st">"db_table"</span>] <span class="op">+</span> <span class="st">');'</span><span class="op">;</span>
<span class="va">db</span>.<span class="at">serialize</span>(<span class="kw">function</span>() <span class="op">{</span>
<span class="va">db</span>.<span class="at">run</span>(create_table)<span class="op">;</span>
<span class="va">_</span>.<span class="at">each</span>(config[<span class="st">"init_table"</span>]<span class="op">,</span> <span class="kw">function</span>(insert_data) <span class="op">{</span>
<span class="va">db</span>.<span class="at">run</span>(insert_data)<span class="op">;</span>
<span class="op">}</span>)<span class="op">;</span>
<span class="op">}</span>)<span class="op">;</span>
<span class="va">db</span>.<span class="at">close</span>()<span class="op">;</span></code></pre></div>
<p>首先从配置中读取db_name,接着创建table,然后调用underscore的each方法,创建几个数据。配置如下所示</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript">config <span class="op">=</span> <span class="op">{</span>
<span class="st">"db_name"</span><span class="op">:</span> <span class="st">"iot.db"</span><span class="op">,</span>
<span class="st">"db_table"</span><span class="op">:</span> <span class="st">"id integer primary key, value text, sensors1 float, sensors2 float"</span><span class="op">,</span>
<span class="st">"init_table"</span><span class="op">:</span>[
<span class="st">"insert or replace into basic (id,value,sensors1,sensors2) VALUES (1, 'is id 1', 19, 20);"</span><span class="op">,</span>
<span class="st">"insert or replace into basic (id,value,sensors1,sensors2) VALUES (2, 'is id 2', 20, 21);"</span>
]<span class="op">,</span>
<span class="st">"query_table"</span><span class="op">:</span><span class="st">"select * from basic;"</span>
<span class="op">};</span></code></pre></div>
<p>而之前所提到的url查询所做的事情便是</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="va">DBHelper</span>.<span class="at">urlQueryData</span> <span class="op">=</span> <span class="kw">function</span> (url<span class="op">,</span> callback) <span class="op">{</span>
<span class="kw">var</span> db <span class="op">=</span> <span class="kw">new</span> <span class="va">sqlite3</span>.<span class="at">Database</span>(<span class="st">"iot.db"</span>)<span class="op">;</span>
<span class="kw">var</span> result <span class="op">=</span> []<span class="op">;</span>
<span class="va">console</span>.<span class="at">log</span>(<span class="st">"SELECT * FROM basic where "</span> <span class="op">+</span> <span class="va">url</span>.<span class="at">split</span>(<span class="st">'/'</span>)[<span class="dv">1</span>] <span class="op">+</span> <span class="st">"="</span> <span class="op">+</span> <span class="va">url</span>.<span class="at">split</span>(<span class="st">'/'</span>)[<span class="dv">2</span>])<span class="op">;</span>
<span class="va">db</span>.<span class="at">all</span>(<span class="st">"SELECT * FROM basic where "</span> <span class="op">+</span> <span class="va">url</span>.<span class="at">split</span>(<span class="st">'/'</span>)[<span class="dv">1</span>] <span class="op">+</span> <span class="st">"="</span> <span class="op">+</span> <span class="va">url</span>.<span class="at">split</span>(<span class="st">'/'</span>)[<span class="dv">2</span>]<span class="op">,</span> <span class="kw">function</span>(err<span class="op">,</span> rows) <span class="op">{</span>
<span class="va">db</span>.<span class="at">close</span>()<span class="op">;</span>
<span class="at">callback</span>(<span class="va">JSON</span>.<span class="at">stringify</span>(rows))<span class="op">;</span>
<span class="op">}</span>)<span class="op">;</span>
<span class="op">};</span></code></pre></div>
<p>将URL传进来,便解析这个参数,接着再放到数据库中查询,再回调回结果。这样我们就可以构成之前所说的查询功能,而我们所谓的post功能似乎也可以用同样的方法加进去。</p>
<h3 id="查询数据"><span class="header-section-number">1.4.3</span> 查询数据</h3>
<p>简单地记录一下在IoT-CoAP中一次获取数据地过程。</p>
<p>先看看在示例中的Get.js的代码,这关乎在后面server端的代码。</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">const</span> coap <span class="op">=</span> <span class="at">require</span>(<span class="st">'coap'</span>)
<span class="op">,</span>requestURI <span class="op">=</span> <span class="st">'coap://localhost/'</span>
<span class="op">,</span>url <span class="op">=</span> <span class="at">require</span>(<span class="st">'url'</span>).<span class="at">parse</span>(requestURI <span class="op">+</span> <span class="st">'id/1/'</span>)
<span class="op">,</span>req <span class="op">=</span> <span class="va">coap</span>.<span class="at">request</span>(url)
<span class="op">,</span>bl <span class="op">=</span> <span class="at">require</span>(<span class="st">'bl'</span>)<span class="op">;</span>
<span class="va">req</span>.<span class="at">setHeader</span>(<span class="st">"Accept"</span><span class="op">,</span> <span class="st">"application/json"</span>)<span class="op">;</span>
<span class="va">req</span>.<span class="at">on</span>(<span class="st">'response'</span><span class="op">,</span> <span class="kw">function</span>(res) <span class="op">{</span>
<span class="va">res</span>.<span class="at">pipe</span>(<span class="at">bl</span>(<span class="kw">function</span>(err<span class="op">,</span> data) <span class="op">{</span>
<span class="kw">var</span> json <span class="op">=</span> <span class="va">JSON</span>.<span class="at">parse</span>(data)<span class="op">;</span>
<span class="va">console</span>.<span class="at">log</span>(json)<span class="op">;</span>
<span class="op">}</span>))<span class="op">;</span>
<span class="op">}</span>)<span class="op">;</span>
<span class="va">req</span>.<span class="at">end</span>()<span class="op">;</span></code></pre></div>
<p>const定义数据的方法,和我们在其他语言中有点像。只是这的const主要是为了程序的健壮型,减少程序出错,当然这不是javascript的用法。</p>
<p>我们构建了一个请求的URL</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">coap</span>://localhost/id/1/</code></pre></div>
<p>我们对我们的请求添加了一个Header,内容是Accept,值是’application/json’也就是JSON格式。接着,便是等待请求回来,再处理返回的内容。</p>
<p><strong>判断请求的方法</strong></p>
<p>在这里先把一些无关的代码删除掉,并保证其能工作,so,下面就是简要的逻辑代码。</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> coap <span class="op">=</span> <span class="at">require</span>(<span class="st">'coap'</span>)<span class="op">;</span>
<span class="kw">var</span> server <span class="op">=</span> <span class="va">coap</span>.<span class="at">createServer</span>(<span class="op">{}</span>)<span class="op">;</span>
<span class="kw">var</span> request_handler <span class="op">=</span> <span class="at">require</span>(<span class="st">'./request_handler.js'</span>)<span class="op">;</span>
<span class="va">server</span>.<span class="at">on</span>(<span class="st">'request'</span><span class="op">,</span> <span class="kw">function</span>(req<span class="op">,</span> res) <span class="op">{</span>
<span class="cf">switch</span>(<span class="va">req</span>.<span class="at">method</span>)<span class="op">{</span>
<span class="cf">case</span> <span class="st">"GET"</span><span class="op">:</span> <span class="va">request_handler</span>.<span class="at">getHandler</span>(req<span class="op">,</span> res)<span class="op">;</span>
<span class="cf">break</span><span class="op">;</span>
<span class="op">}</span>
<span class="op">}</span>)<span class="op">;</span>
<span class="va">server</span>.<span class="at">listen</span>(<span class="kw">function</span>() <span class="op">{</span>
<span class="va">console</span>.<span class="at">log</span>(<span class="st">'server started'</span>)<span class="op">;</span>
<span class="op">}</span>)<span class="op">;</span></code></pre></div>
<p>创建一个CoAP服务,判断req.method,也就是请求的方法,如果是GET的话,就调用request_handler.getHandler(req, res)。而在getHandler里,判断了下请求的Accept</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="va">request_helper</span>.<span class="at">getHandler</span> <span class="op">=</span> <span class="kw">function</span>(req<span class="op">,</span> res) <span class="op">{</span>
<span class="cf">switch</span> (<span class="va">req</span>.<span class="at">headers</span>[<span class="st">'Accept'</span>]) <span class="op">{</span>
<span class="cf">case</span> <span class="st">"application/json"</span><span class="op">:</span>
<span class="va">qh</span>.<span class="at">returnJSON</span>(req<span class="op">,</span> res)<span class="op">;</span>
<span class="cf">break</span><span class="op">;</span>
<span class="cf">case</span> <span class="st">"application/xml"</span><span class="op">:</span>
<span class="va">qh</span>.<span class="at">returnXML</span>(req<span class="op">,</span> res)<span class="op">;</span>
<span class="cf">break</span><span class="op">;</span>
<span class="op">}</span>
<span class="op">};</span></code></pre></div>
<p>如果是json刚调用returnJSON,</p>
<p><strong>Database与回调</strong></p>
<p>而这里为了处理回调函数刚分为了两部分</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="va">query_helper</span>.<span class="at">returnJSON</span> <span class="op">=</span> <span class="kw">function</span>(req<span class="op">,</span> res) <span class="op">{</span>
<span class="va">DBHelper</span>.<span class="at">urlQueryData</span>(<span class="va">req</span>.<span class="at">url</span><span class="op">,</span> <span class="kw">function</span> (result) <span class="op">{</span>
<span class="va">QueryData</span>.<span class="at">returnJSON</span>(result<span class="op">,</span> res)<span class="op">;</span>
<span class="op">}</span>)<span class="op">;</span>
<span class="op">};</span></code></pre></div>
<p>而这里只是调用了</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="va">DBHelper</span>.<span class="at">urlQueryData</span> <span class="op">=</span> <span class="kw">function</span> (url<span class="op">,</span> callback) <span class="op">{</span>
<span class="kw">var</span> db <span class="op">=</span> <span class="kw">new</span> <span class="va">sqlite3</span>.<span class="at">Database</span>(config[<span class="st">"db_name"</span>])<span class="op">;</span>
<span class="va">console</span>.<span class="at">log</span>(<span class="st">"SELECT * FROM basic where "</span> <span class="op">+</span> <span class="va">url</span>.<span class="at">split</span>(<span class="st">'/'</span>)[<span class="dv">1</span>] <span class="op">+</span> <span class="st">"="</span> <span class="op">+</span> <span class="va">url</span>.<span class="at">split</span>(<span class="st">'/'</span>)[<span class="dv">2</span>])<span class="op">;</span>
<span class="va">db</span>.<span class="at">all</span>(<span class="st">"SELECT * FROM basic where "</span> <span class="op">+</span> <span class="va">url</span>.<span class="at">split</span>(<span class="st">'/'</span>)[<span class="dv">1</span>] <span class="op">+</span> <span class="st">"="</span> <span class="op">+</span> <span class="va">url</span>.<span class="at">split</span>(<span class="st">'/'</span>)[<span class="dv">2</span>]<span class="op">,</span> <span class="kw">function</span>(err<span class="op">,</span> rows) <span class="op">{</span>
<span class="va">db</span>.<span class="at">close</span>()<span class="op">;</span>
<span class="at">callback</span>(<span class="va">JSON</span>.<span class="at">stringify</span>(rows))<span class="op">;</span>
<span class="op">}</span>)<span class="op">;</span>
<span class="op">};</span></code></pre></div>
<p>这里调用了node sqlite3去查询对应id的数据,用回调处理了数据无法到外部的问题,而上面的returnJSON则只是返回最后的结果,code以及其他的内容。</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="va">QueryData</span>.<span class="at">returnJSON</span> <span class="op">=</span> <span class="kw">function</span>(result<span class="op">,</span> res) <span class="op">{</span>
<span class="cf">if</span> (<span class="va">result</span>.<span class="at">length</span> <span class="op">==</span> <span class="dv">2</span>) <span class="op">{</span>
<span class="va">res</span>.<span class="at">code</span> <span class="op">=</span> <span class="st">'4.04'</span><span class="op">;</span>
<span class="va">res</span>.<span class="at">end</span>(<span class="va">JSON</span>.<span class="at">stringify</span>(<span class="op">{</span>
<span class="dt">error</span><span class="op">:</span> <span class="st">"Not Found"</span>
<span class="op">}</span>))<span class="op">;</span>
<span class="op">}</span> <span class="cf">else</span> <span class="op">{</span>
<span class="va">res</span>.<span class="at">code</span> <span class="op">=</span> <span class="st">'2.05'</span><span class="op">;</span>
<span class="va">res</span>.<span class="at">end</span>(result)<span class="op">;</span>
<span class="op">}</span>
<span class="op">};</span></code></pre></div>
<p>当resulst的结果为空时,返回一个404,因为没有数据。这样我们就构成了整个的链,再一步步返回结果。</p>
<p>在<a href="https://github.com/phodal/iot-coap">IoT-CoAP</a>中我们使用到了一个Block2的东西,于是便整理相关的一些资料,作一个简单的介绍,以及在代码中的使用。</p>
<h2 id="coap-block"><span class="header-section-number">1.5</span> CoAP Block</h2>
<p>CoAP是一个RESTful传输协议用于受限设备的节点和网络。基本的CoAP消息是一个不错的选择对于小型载荷如</p>
<ul>
<li>温度传感器</li>
<li>灯光开关</li>
<li>楼宇自动化设备</li>
</ul>
<p>然而,有时我们的应用需要传输更大的有效载荷,如——更新固件。与HTTP,TCP做繁重工作将大型有效载荷分成多个数据包,并确保他们所有到达并以正确的顺序被处理。</p>
<p>CoAP是同UDP与DLTS一样是基于数据报传输的,这限制了资源表示(resource representation)的最大大小,使得传输不需要太多的分割。虽然UDP支持通过IP分片传输更大的有效载荷,且仅限于64KiB,更重要的是,并没有真正很好地约束应用和网络。</p>
<p>而不是依赖于IP分片,这种规范基本COAP了对“块”选项,用于传输信息从多个资源区块的请求 - 响应对。在许多重要的情况下,阻止使服务器能够真正无状态:服务器可以处理每块分开传输,而无需建立连接以前的数据块传输的其他服务器端内存。</p>
<p>综上所述,块(Block)选项提供了传送一个最小的在分块的方式更大的陈述。</p>
<h3 id="coap-post"><span class="header-section-number">1.5.1</span> CoAP POST</h3>
<p>看看在IoT CoAP中的post示例。</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">const</span> coap <span class="op">=</span> <span class="at">require</span>(<span class="st">'coap'</span>)
<span class="op">,</span>request <span class="op">=</span> <span class="va">coap</span>.<span class="at">request</span>
<span class="op">,</span>bl <span class="op">=</span> <span class="at">require</span>(<span class="st">'bl'</span>)
<span class="op">,</span>req <span class="op">=</span> <span class="at">request</span>(<span class="op">{</span><span class="dt">hostname</span><span class="op">:</span> <span class="st">'localhost'</span><span class="op">,</span><span class="dt">port</span><span class="op">:</span><span class="dv">5683</span><span class="op">,</span><span class="dt">pathname</span><span class="op">:</span> <span class="st">''</span><span class="op">,</span><span class="dt">method</span><span class="op">:</span> <span class="st">'POST'</span><span class="op">}</span>)<span class="op">;</span>
<span class="va">req</span>.<span class="at">setOption</span>(<span class="st">'Block2'</span><span class="op">,</span> [<span class="kw">new</span> <span class="at">Buffer</span>(<span class="st">'1'</span>)<span class="op">,</span><span class="kw">new</span> <span class="at">Buffer</span>(<span class="st">"'must'"</span>)<span class="op">,</span> <span class="kw">new</span> <span class="at">Buffer</span>(<span class="st">'23'</span>)<span class="op">,</span> <span class="kw">new</span> <span class="at">Buffer</span>(<span class="st">'12'</span>)])<span class="op">;</span>
<span class="va">req</span>.<span class="at">setHeader</span>(<span class="st">"Accept"</span><span class="op">,</span> <span class="st">"application/json"</span>)<span class="op">;</span>
<span class="va">req</span>.<span class="at">on</span>(<span class="st">'response'</span><span class="op">,</span> <span class="kw">function</span>(res) <span class="op">{</span>
<span class="va">res</span>.<span class="at">pipe</span>(<span class="at">bl</span>(<span class="kw">function</span>(err<span class="op">,</span> data) <span class="op">{</span>
<span class="va">console</span>.<span class="at">log</span>(data)<span class="op">;</span>
<span class="va">process</span>.<span class="at">exit</span>(<span class="dv">0</span>)<span class="op">;</span>
<span class="op">}</span>))<span class="op">;</span>
<span class="op">}</span>)<span class="op">;</span>
<span class="va">req</span>.<span class="at">end</span>()<span class="op">;</span></code></pre></div>
<p>Block2中一共有四个数据,相应的数据结果应该是</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="op">{</span> <span class="dt">name</span><span class="op">:</span> <span class="st">'Block2'</span><span class="op">,</span> <span class="dt">value</span><span class="op">:</span> <span class="op"><</span>Buffer <span class="dv">31</span><span class="op">></span> <span class="op">}</span>
<span class="op">{</span> <span class="dt">name</span><span class="op">:</span> <span class="st">'Block2'</span><span class="op">,</span> <span class="dt">value</span><span class="op">:</span> <span class="op"><</span>Buffer <span class="dv">27</span> 6d <span class="dv">75</span> <span class="dv">73</span> <span class="dv">74</span> <span class="dv">27</span><span class="op">></span> <span class="op">}</span>
<span class="op">{</span> <span class="dt">name</span><span class="op">:</span> <span class="st">'Block2'</span><span class="op">,</span> <span class="dt">value</span><span class="op">:</span> <span class="op"><</span>Buffer <span class="dv">32</span> <span class="dv">33</span><span class="op">></span> <span class="op">}</span>
<span class="op">{</span> <span class="dt">name</span><span class="op">:</span> <span class="st">'Block2'</span><span class="op">,</span> <span class="dt">value</span><span class="op">:</span> <span class="op"><</span>Buffer <span class="dv">31</span> <span class="dv">32</span><span class="op">></span> <span class="op">}</span></code></pre></div>
<p>这是没有解析的Block2,简单地可以用</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="va">_</span>.<span class="at">values</span>(e).<span class="at">toString</span>()</code></pre></div>
<p>将结果转换为</p>
<p>Block2,1 Block2,‘must’ Block2,23 Block2,12</p>
<p>接着按“,”分开,</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="va">_</span>.<span class="at">values</span>(e).<span class="at">toString</span>().<span class="at">split</span>(<span class="st">','</span>)[<span class="dv">1</span>]</code></pre></div>
<p>就有</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">[</span> <span class="st">'1'</span>, <span class="st">'\'</span>must<span class="dt">\'</span><span class="st">', '</span>23<span class="st">', '</span>12<span class="st">' ]</span></code></pre></div>
<p>便可以很愉快地将其post到数据库中了,</p>
<p>在做IoT-CoAP的过程中只支持JSON,查阅CoAP的草稿时发现支持了诸多的Content Types。</p>
<h3 id="coap-content-types"><span class="header-section-number">1.5.2</span> CoAP Content Types</h3>
<p>以下文字来自谷歌翻译:</p>
<blockquote>
<p>互联网媒体类型是通过HTTP字符串标识,如“application/xml”。该字符串是由一个顶层的类型“applicaion”和子类型的“XML”。为了尽量减少使用这些类型的媒体类型来表示的开销消息有效载荷,COAP定义一个标识符编码方案互联网媒体类型的子集。预计这桌将可扩展标识符的值的IANA维护。内容类型选项被格式化为一个8位无符号整数。初始映射到一个合适的互联网媒体类型标识符表所示。复合型高层次类型(multipart和不支持消息)。标识符值是从201-255保留的特定于供应商的,应用程序特定的或实验使用和不由IANA。</p>
</blockquote>
<p>下面是HTTP的标识符及类型</p>
<table>
<thead>
<tr class="header">
<th align="left">Internet media type</th>
<th align="left">Identifier</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="left">text/plain (UTF-8)</td>
<td align="left">0</td>
</tr>
<tr class="even">
<td align="left">text/xml (UTF-8)</td>
<td align="left">1</td>
</tr>
<tr class="odd">
<td align="left">text/csv (UTF-8)</td>
<td align="left">2</td>
</tr>
<tr class="even">
<td align="left">text/html (UTF-8)</td>
<td align="left">3</td>
</tr>
<tr class="odd">
<td align="left">image/gif</td>
<td align="left">21</td>
</tr>
<tr class="even">
<td align="left">image/jpeg</td>
<td align="left">22</td>
</tr>
<tr class="odd">
<td align="left">image/png</td>
<td align="left">23</td>
</tr>
<tr class="even">
<td align="left">image/tiff</td>
<td align="left">24</td>
</tr>
<tr class="odd">
<td align="left">audio/raw</td>
<td align="left">25</td>
</tr>
<tr class="even">
<td align="left">video/raw</td>
<td align="left">26</td>
</tr>
<tr class="odd">
<td align="left">application/link-format [I-D.ietf-core-link-format]</td>
<td align="left">40</td>
</tr>
<tr class="even">
<td align="left">application/xml</td>
<td align="left">41</td>
</tr>
<tr class="odd">
<td align="left">application/octet-stream</td>
<td align="left">42</td>
</tr>
<tr class="even">
<td align="left">application/rdf+xml</td>
<td align="left">43</td>
</tr>
<tr class="odd">
<td align="left">application/soap+xml</td>
<td align="left">44</td>
</tr>
<tr class="even">
<td align="left">application/atom+xml</td>
<td align="left">45</td>
</tr>
<tr class="odd">
<td align="left">application/xmpp+xml</td>
<td align="left">46</td>
</tr>
<tr class="even">
<td align="left">application/exi</td>
<td align="left">47</td>
</tr>
<tr class="odd">
<td align="left">application/x-bxml</td>
<td align="left">48</td>
</tr>
<tr class="even">
<td align="left">application/fastinfoset</td>
<td align="left">49</td>
</tr>
<tr class="odd">
<td align="left">application/soap+fastinfoset</td>
<td align="left">50</td>
</tr>
<tr class="even">
<td align="left">application/json</td>
<td align="left">51</td>
</tr>
</tbody>
</table>
<p>而在CoAP中只有简单地几个</p>
<table>
<thead>
<tr class="header">
<th align="left">Media type</th>
<th align="left">Encoding</th>
<th align="left">Id.</th>
<th align="left">Reference</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="left">text/plain;</td>
<td align="left">-</td>
<td align="left">0</td>
<td align="left">[RFC2046][RFC3676][RFC5147]</td>
</tr>
<tr class="even">
<td align="left">charset=utf-8</td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
</tr>
<tr class="odd">
<td align="left">application/</td>
<td align="left">-</td>
<td align="left">40</td>
<td align="left">[RFC6690]</td>
</tr>
<tr class="even">
<td align="left">link-format</td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
</tr>
<tr class="odd">
<td align="left">application/xml</td>
<td align="left">-</td>
<td align="left">41</td>
<td align="left">[RFC3023]</td>
</tr>
<tr class="even">
<td align="left">application/</td>
<td align="left">-</td>
<td align="left">42</td>
<td align="left">[RFC2045][RFC2046]</td>
</tr>
<tr class="odd">
<td align="left">octet-stream</td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
</tr>
<tr class="even">
<td align="left">application/exi</td>
<td align="left">-</td>
<td align="left">47</td>
<td align="left">[EXIMIME]</td>
</tr>
<tr class="odd">
<td align="left">application/json</td>
<td align="left">-</td>
<td align="left">50</td>
<td align="left">[RFC4627]</td>
</tr>
</tbody>
</table>
<p>简单地说就是:</p>
<p><code>诸如application/json的Content Types在CoAP中应该是50</code>。如上表所示的结果是其对应的结果,这样的话可以减少传递的信息量。</p>
<h2 id="coap-json"><span class="header-section-number">1.6</span> CoAP JSON</h2>
<p>于是在一开始的时候首先支持的便是“application/json”这样的类型。</p>
<p>首先判断请求的header</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="va">request_helper</span>.<span class="at">getHandler</span> <span class="op">=</span> <span class="kw">function</span>(req<span class="op">,</span> res) <span class="op">{</span>
<span class="cf">switch</span> (<span class="va">req</span>.<span class="at">headers</span>[<span class="st">'Accept'</span>]) <span class="op">{</span>
<span class="cf">case</span> <span class="st">"application/json"</span><span class="op">:</span>
<span class="va">qh</span>.<span class="at">returnJSON</span>(req<span class="op">,</span> res)<span class="op">;</span>
<span class="cf">break</span><span class="op">;</span>
<span class="cf">case</span> <span class="st">"application/xml"</span><span class="op">:</span>
<span class="va">qh</span>.<span class="at">returnXML</span>(req<span class="op">,</span> res)<span class="op">;</span>
<span class="cf">break</span><span class="op">;</span>
<span class="op">}</span>
<span class="op">};</span></code></pre></div>
<p>再转至相应的函数处理,而判断的依据则是Accept是不是“application/json”。</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="at">registerFormat</span>(<span class="st">'text/plain'</span><span class="op">,</span> <span class="dv">0</span>)
<span class="at">registerFormat</span>(<span class="st">'application/link-format'</span><span class="op">,</span> <span class="dv">40</span>)
<span class="at">registerFormat</span>(<span class="st">'application/xml'</span><span class="op">,</span> <span class="dv">41</span>)
<span class="at">registerFormat</span>(<span class="st">'application/octet-stream'</span><span class="op">,</span> <span class="dv">42</span>)
<span class="at">registerFormat</span>(<span class="st">'application/exi'</span><span class="op">,</span> <span class="dv">47</span>)
<span class="at">registerFormat</span>(<span class="st">'application/json'</span><span class="op">,</span> <span class="dv">50</span>)</code></pre></div>
<p>对应地我们需要在一发出请求的时候设置好Accept,要不就没有办法返回我们需要的结果。</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="va">req</span>.<span class="at">setHeader</span>(<span class="st">"Accept"</span><span class="op">,</span> <span class="st">"application/json"</span>)<span class="op">;</span></code></pre></div>
<p><strong>返回JSON</strong></p>
<p>在给IoT CoAP添加了JSON支持之后,变得非常有意思,至少我们可以获得我们想要的结果。在上一篇中我们介绍了一些常用的工具——<a href="http://www.phodal.com/blog/coap-command-line-tools-set/">CoAP 命令行工具集</a>。</p>
<p><strong>CoAP客户端代码</strong></p>
<p>开始之前我们需要有一个客户端代码,以便我们的服务端可以返回正确的数据并解析</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">var</span> coap <span class="op">=</span> <span class="at">require</span>(<span class="st">'coap'</span>)<span class="op">;</span>
<span class="kw">var</span> requestURI <span class="op">=</span> <span class="st">'coap://localhost/'</span><span class="op">;</span>
<span class="kw">var</span> url <span class="op">=</span> <span class="at">require</span>(<span class="st">'url'</span>).<span class="at">parse</span>(requestURI <span class="op">+</span> <span class="st">'id/1/'</span>)<span class="op">;</span>
<span class="va">console</span>.<span class="at">log</span>(<span class="st">"Request URL: "</span> <span class="op">+</span> <span class="va">url</span>.<span class="at">href</span>)<span class="op">;</span>
<span class="kw">var</span> req <span class="op">=</span> <span class="va">coap</span>.<span class="at">request</span>(url)<span class="op">;</span>
<span class="kw">var</span> bl <span class="op">=</span> <span class="at">require</span>(<span class="st">'bl'</span>)<span class="op">;</span>
<span class="va">req</span>.<span class="at">setHeader</span>(<span class="st">"Accept"</span><span class="op">,</span> <span class="st">"application/json"</span>)<span class="op">;</span>
<span class="va">req</span>.<span class="at">on</span>(<span class="st">'response'</span><span class="op">,</span> <span class="kw">function</span>(res) <span class="op">{</span>
<span class="va">res</span>.<span class="at">pipe</span>(<span class="at">bl</span>(<span class="kw">function</span>(err<span class="op">,</span> data) <span class="op">{</span>
<span class="kw">var</span> json <span class="op">=</span> <span class="va">JSON</span>.<span class="at">parse</span>(data)<span class="op">;</span>
<span class="va">console</span>.<span class="at">log</span>(json)<span class="op">;</span>
<span class="op">}</span>))<span class="op">;</span>
<span class="op">}</span>)<span class="op">;</span>
<span class="va">req</span>.<span class="at">end</span>()<span class="op">;</span></code></pre></div>
<p>代码有点长内容也有点多,但是核心是这句话:</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="va">req</span>.<span class="at">setHeader</span>(<span class="st">"Accept"</span><span class="op">,</span> <span class="st">"application/json"</span>)<span class="op">;</span></code></pre></div>
<p>这样的话,我们只需要在我们的服务端一判断,</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="cf">if</span>(<span class="va">req</span>.<span class="at">headers</span>[<span class="st">'Accept'</span>] <span class="op">==</span> <span class="st">'application/json'</span>) <span class="op">{</span>
<span class="co">//do something</span>
<span class="op">};</span></code></pre></div>
<p>这样就可以返回数据了</p>
<p><strong>CoAP Server端代码</strong></p>
<p>Server端的代码比较简单,判断一下</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="cf">if</span> (<span class="va">req</span>.<span class="at">headers</span>[<span class="st">'Accept'</span>] <span class="op">==</span> <span class="st">'application/json'</span>) <span class="op">{</span>
<span class="at">parse_url</span>(<span class="va">req</span>.<span class="at">url</span><span class="op">,</span> <span class="kw">function</span>(result)<span class="op">{</span>
<span class="va">res</span>.<span class="at">end</span>(result)<span class="op">;</span>
<span class="op">}</span>)<span class="op">;</span>
<span class="va">res</span>.<span class="at">code</span> <span class="op">=</span> <span class="st">'2.05'</span><span class="op">;</span>
<span class="op">}</span></code></pre></div>
<p>请求的是否是JSON格式,再返回一个205,也就是Content,只是这时设计是请求一个URL返回对应的数据。如</p>
<div class="sourceCode"><pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">coap</span>://localhost/id/1/</code></pre></div>
<p>这时应该请求的是ID为1的数据,即</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript">[ <span class="op">{</span> <span class="dt">id</span><span class="op">:</span> <span class="dv">1</span><span class="op">,</span> <span class="dt">value</span><span class="op">:</span> <span class="st">'is id 1'</span><span class="op">,</span> <span class="dt">sensors1</span><span class="op">:</span> <span class="dv">19</span><span class="op">,</span> <span class="dt">sensors2</span><span class="op">:</span> <span class="dv">20</span> <span class="op">}</span>]</code></pre></div>
<p>而parse_url只是从数据库从读取相应的数据。</p>
<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="kw">function</span> <span class="at">parse_url</span>(url <span class="op">,</span>callback) <span class="op">{</span>
<span class="kw">var</span> db <span class="op">=</span> <span class="kw">new</span> <span class="va">sqlite3</span>.<span class="at">Database</span>(config[<span class="st">"db_name"</span>])<span class="op">;</span>
<span class="kw">var</span> result <span class="op">=</span> []<span class="op">;</span>
<span class="va">db</span>.<span class="at">all</span>(<span class="st">"SELECT * FROM basic;"</span><span class="op">,</span> <span class="kw">function</span>(err<span class="op">,</span> rows) <span class="op">{</span>
<span class="at">callback</span>(<span class="va">JSON</span>.<span class="at">stringify</span>(rows))<span class="op">;</span>
<span class="op">}</span>)
<span class="op">}</span></code></pre></div>
<p>并且全部都显示出来,设计得真是有点不行,不过现在已经差不多了。</p>
</body>
</html>