Blog | Phodal - A Growth Engineerhttp://www.phodal.com/blog/2015-04-16T04:58:28.543976+00:00BlogMQTT协议 Python Paho2015-01-11T12:41:11+00:002015-01-13T14:34:35.513818+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/python-paho-mqtt-mosquitto/之前看Mosquitto文档的时候,发现提供了一个Python的库,后来发现,他把这个库捐给了``Eclipse Paho``。
###Eclipse Paho 简介
> The Paho project provides scalable open-source client implementations of open and standard messaging protocols aimed at new, existing, and emerging applications for Machine‑to‑Machine (M2M) and Internet of Things (IoT).
是的,最近Eclipse在搞各种物联网。
##Python mosquitto
之前的代码是这样的
import mosquitto
mqttc = mosquitto.Mosquitto("python_pub")
mqttc.connect("mqtt.phodal.com", 1883, 60, True)
mqttc.publish("hello", "Hello, World!")
于是代码变成了这样
import paho.mqtt.client as mqtt
mqttc = mqtt.Client("python_pub")
mqttc.connect("mqtt.phodal.com", 1883, 60)
mqttc.publish("lettuce", "Hello, World baby!",2)
他们是要弄怎样!!
更详细代码如下面所示:
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe("lettuce")
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("mqtt.phodal.com", 1883, 60)
client.loop_forever()用code climate来clean code与重构2014-10-23T12:30:40+00:002014-10-23T15:28:53.656754+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/use-code-climate-clean-code-and-refactor/ - 当你写了一大堆代码,你没有意识到里面有一大堆重复。
- 当你写了一大堆测试,却不知道覆盖率有多少。
这就是个问题了,于是偶然间看到了一个叫code climate的网站。
##Code Climate
> Code Climate consolidates the results from a suite of static analysis tools into a single, real-time report, giving your team the information it needs to identify hotspots, evaluate new approaches, and improve code quality.
Code Climate整合一组静态分析工具的结果到一个单一的,实时的报告,让您的团队需要识别热点,探讨新的方法,提高代码质量的信息。
简单地来说:
- 对我们的代码评分
- 找出代码中的坏味道
于是,我们先来了个例子
Rating | Name | Complexity | Duplication | Churn | C/M | Coverage | Smells
--------|------|--------------|-------------|----------|---------|---------------------
A | lib/coap/coap_request_handler.js | 24 | 0 | 6 | 2.6 | 46.4% | 0
A | lib/coap/coap_result_helper.js | 14 | 0 | 2 | 3.4 | 80.0% | 0
A | lib/coap/coap_server.js | 16 | 0 | 5 | 5.2 | 44.0% | 0
A | lib/database/db_factory.js | 8 | 0 | 3 | 3.8 | 92.3% | 0
A | lib/database/iot_db.js | 7 | 0 | 6 | 1.0 | 58.8% | 0
A | lib/database/mongodb_helper.js | 63 | 0 | 11 | 4.5 | 35.0% | 0
C | lib/database/sqlite_helper.js | 32 | 86 | 10 | 4.5 | 35.0% | 2
B | lib/rest/rest_helper.js | 19 | 62 | 3 | 4.7 | 37.5% | 2
A | lib/rest/rest_server.js | 17 | 0 | 2 | 8.6 | 88.9% | 0
A | lib/url_handler.js | 9 | 0 | 5 | 2.2 | 94.1% | 0
分享得到的最后的结果是:
![Coverage][1]
##代码的坏味道
于是我们就打开``lib/database/sqlite_helper.js``,因为其中有两个坏味道
###Similar code found in two :expression_statement nodes (mass = 86)
在代码的 ``lib/database/sqlite_helper.js:58…61 < >``
SQLiteHelper.prototype.deleteData = function (url, callback) {
'use strict';
var sql_command = "DELETE FROM " + config.table_name + " where " + URLHandler.getKeyFromURL(url) + "=" + URLHandler.getValueFromURL(url);
SQLiteHelper.prototype.basic(sql_command, callback);
lib/database/sqlite_helper.js:64…67 < >
与
SQLiteHelper.prototype.getData = function (url, callback) {
'use strict';
var sql_command = "SELECT * FROM " + config.table_name + " where " + URLHandler.getKeyFromURL(url) + "=" + URLHandler.getValueFromURL(url);
SQLiteHelper.prototype.basic(sql_command, callback);
只是这是之前修改过的重复。。
原来的代码是这样的
SQLiteHelper.prototype.postData = function (block, callback) {
'use strict';
var db = new sqlite3.Database(config.db_name);
var str = this.parseData(config.keys);
var string = this.parseData(block);
var sql_command = "insert or replace into " + config.table_name + " (" + str + ") VALUES (" + string + ");";
db.all(sql_command, function (err) {
SQLiteHelper.prototype.errorHandler(err);
db.close();
callback();
});
};
SQLiteHelper.prototype.deleteData = function (url, callback) {
'use strict';
var db = new sqlite3.Database(config.db_name);
var sql_command = "DELETE FROM " + config.table_name + " where " + URLHandler.getKeyFromURL(url) + "=" + URLHandler.getValueFromURL(url);
db.all(sql_command, function (err) {
SQLiteHelper.prototype.errorHandler(err);
db.close();
callback();
});
};
SQLiteHelper.prototype.getData = function (url, callback) {
'use strict';
var db = new sqlite3.Database(config.db_name);
var sql_command = "SELECT * FROM " + config.table_name + " where " + URLHandler.getKeyFromURL(url) + "=" + URLHandler.getValueFromURL(url);
db.all(sql_command, function (err, rows) {
SQLiteHelper.prototype.errorHandler(err);
db.close();
callback(JSON.stringify(rows));
});
};
说的也是大量的重复,重构完的代码
SQLiteHelper.prototype.basic = function(sql, db_callback){
'use strict';
var db = new sqlite3.Database(config.db_name);
db.all(sql, function (err, rows) {
SQLiteHelper.prototype.errorHandler(err);
db.close();
db_callback(JSON.stringify(rows));
});
};
SQLiteHelper.prototype.postData = function (block, callback) {
'use strict';
var str = this.parseData(config.keys);
var string = this.parseData(block);
var sql_command = "insert or replace into " + config.table_name + " (" + str + ") VALUES (" + string + ");";
SQLiteHelper.prototype.basic(sql_command, callback);
};
SQLiteHelper.prototype.deleteData = function (url, callback) {
'use strict';
var sql_command = "DELETE FROM " + config.table_name + " where " + URLHandler.getKeyFromURL(url) + "=" + URLHandler.getValueFromURL(url);
SQLiteHelper.prototype.basic(sql_command, callback);
};
SQLiteHelper.prototype.getData = function (url, callback) {
'use strict';
var sql_command = "SELECT * FROM " + config.table_name + " where " + URLHandler.getKeyFromURL(url) + "=" + URLHandler.getValueFromURL(url);
SQLiteHelper.prototype.basic(sql_command, callback);
};
重构完后的代码比原来还长,这似乎是个问题~~
[1]: /static/media/uploads/screen_shot_2014-10-23_at_20.52.13.pngMongoDB Nodejs构建CoAP物联网(二)——简单工厂模式2014-10-17T14:32:07+00:002014-10-17T17:13:39.595915+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/use-nodejs-mongodb-build-coap-iot-with-simple-factory-pattern/设计模式是一些有意思的东西,只是这些东西,只有在我们觉得代码写得很烂的时候才有用。比如,当我发现我在代码中重复写了很多个if来判断选择那个数据库的时候。于是,我就想着似乎这就可以用这个简单工厂模式来实现SQLite3与MongoDB的选择。
##MongoDB Helper与SQLite Helper类重复
对于我们的类来说是下面这样子的:
function MongoDBHelper() {
'use strict';
return;
}
MongoDBHelper.deleteData = function (url, callback) {
'use strict';
...
};
MongoDBHelper.getData = function (url, callback) {
'use strict';
...
};
MongoDBHelper.postData = function (block, callback) {
'use strict';
...
};
MongoDBHelper.init = function () {
'use strict';
...
};
module.exports = MongoDBHelper;
然而,我们可以发现的是,对于我们的SQLiteHelper来说也是类似的
SQLiteHelper.init = function () {
'use strict';
...
};
SQLiteHelper.postData = function (block, callback) {
'use strict';
...
};
SQLiteHelper.deleteData = function (url, callback) {
'use strict';
...
};
SQLiteHelper.getData = function (url, db_callback) {
'use strict';
...
};
module.exports = SQLiteHelper;
想来想去觉得写一个父类似乎是没有多大意义的,于是用了简单工厂模式来解决这个问题。
##简单工厂模式
> 从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现,学习了此模式可以为后面的很多中模式打下基础。
总之,就是我们可以用简单工厂模式来做一个DB Factory,于是便有了
var MongoDBHelper = require("./mongodb_helper");
var SQLiteHelper = require("./sqlite_helper");
var config = require('../../iot').config;
function DB_Factory() {
'use strict';
return;
}
DB_Factory.prototype.DBClass = SQLiteHelper;
DB_Factory.prototype.selectDB = function () {
'use strict';
if (config.db === 'sqlite3') {
this.DBClass = SQLiteHelper;
} else if (config.db === "mongodb") {
this.DBClass = MongoDBHelper;
}
return this.DBClass;
};
module.exports = DB_Factory;
这样我们在使用的时候,便可以:
var DB_Factory = require("./lib/database/db_factory");
var db_factory = new DB_Factory();
var database = db_factory.selectDB();
database.init();
由于是直接由配置中读取进去的,这里的selectDB就不需要参数。
##其他
CoAP物联网系统代码: [https://github.com/gmszone/iot-coap](https://github.com/gmszone/iot-coap)
MongoDB Nodejs构建CoAP物联网系统2014-10-14T14:04:48+00:002014-10-14T16:45:01.039972+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/use-mongodb-nodejs-build-coap-iot/So,在还没适应印度TWU生活的时候,还是写写MongoDB与CoAP版物联网系统的那些事情吧。
##开始之前
你需要安装有MongoDB,并保证其能启动。
###MongoDB GUI
在Mac OS下面有一个叫Robomongo的工具可以方便我们来调试程序
##Node Mongodb
我们用的库是[https://github.com/mongodb/node-mongodb-native](https://github.com/mongodb/node-mongodb-native)。
``版本``用的是2.0。
###Node MongoDB 示例
在这里引用官方给的例子,于是就有了一次简单的连接测试
var MongoClient = require('mongodb').MongoClient
, assert = require('assert');
var url = 'mongodb://localhost:27017/myproject';
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
console.log("Connected correctly to server");
db.close();
});
这个测试是只是用于测试是否联上了数据库。
##MongoDB CoAP数据初始化
于是我们可以同[https://github.com/gmszone/iot-coap](https://github.com/gmszone/iot-coap)一样,配置一个简单的环境。
MongoClient.connect(mongodb_url, function (err, db) {
errorHandler(err);
var insertDocuments = function (db, callback) {
var collection = db.collection(config.mongodb_documents);
collection.insert(config.mongodb_init, function (err, docs) {
callback(docs);
});
};
var findDocuments = function (db, callback) {
var collection = db.collection(config.mongodb_documents);
collection.find(config.mongodb_init[0]).toArray(function (err, docs) {
if (_.isEmpty(docs)) {
insertDocuments(db, function () {
db.close();
});
}
callback(docs);
});
};
findDocuments(db, function () {
db.close();
});
});
接着我们就可以插入这些数据。上面的代码来得有些早,一个简单的插入Documents的代码,如下所示:
var insertDocuments = function(db, callback) {
var collection = db.collection('documents');
collection.insert([
{a : 1}, {a : 2}, {a : 3}
], function(err, result) {
callback(result);
});
}
而我们只是结合了插入和查询来完整一次简单的数据判断,以免一直插入数据。
Nodejs Mocha Chai为IoT CoAP进行测试2014-09-16T14:52:40+00:002014-12-17T16:49:02.769209+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/user-nodejs-mocha-chai-add-bdd-test-for-iot-coap/在上一篇——[为NodeJS项目添加语法检查](https://www.phodal.com/blog/nodejs-add-jslint-with-pre-commit/)我们简单地说了一下,在iot-coap要提交代码时会发生的事,接着我们来说说里面的测试是怎么进行的。。
##Mocha
官网是这么说的
> Mocha is a feature-rich JavaScript test framework running on node.js and the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases.
网上找到了一个翻译: Mocha是一个拥有非常多特征的javascript测试框架,除了能作为nodejs运行环境的测试框架外,它还支持在浏览器中做js测试框架。使用Mocha可以让javascript的异步代码测试变得简单。Mocha测试用例可以连续的执行,提供灵活和精确的测试报告,同时能在正确的测试用例中映射未捕获的异常。
##IoT CoAP Mocha
###安装mocha
1.直接安装
npm install -g mocha
2.通过package.json,在"devDependencies"字段中添加:
"mocha": "~1.21.4",
###官方示例
示例的测试文件
var assert = require("assert")
describe('Array', function(){
describe('#indexOf()', function(){
it('should return -1 when the value is not present', function(){
assert.equal(-1, [1,2,3].indexOf(5));
assert.equal(-1, [1,2,3].indexOf(0));
})
})
})
测试
mocha
##Chai
> Chai has several interfaces that allow the developer to choose the most comfortable. The chain-capable BDD styles provide an expressive language & readable style, while the TDD assert style provides a more classical feel.
Chai 是一个BDD/TDD模式的断言库.可以在node和浏览器环境下运行。添加到devDependencies中:
"devDependencies": {
"chai": "~1.9.1",
"mocha": "~1.21.4"
}
##Mocha Chai搭配
我们在test目录下配置了一个叫``mocha.opts``的文件,里面含有下面的内容,mocha会优先使用里面的参数
--reporter dot
--ui bdd
--growl
--check-leaks
--colors
--require test/common
这里的test/common是一个js文件,定义了一些全局变量
global.expect = require("chai").expect;
global.assert = require("chai").assert;
global.should = require('chai').should;
##IoT CoAP BDD
在IoT CoAP测试脚本这样子的
./node_modules/.bin/mocha --growl --colors --reporter spec 2>&1
于是,以其中的一个测试为例
var resultReturn = require('../lib/coap_result_helper.js');
describe('query data status code test', function() {
var res = function(){};
res.end = function(){};
it('should return 4.04 when result empty', function() {
var request = "[]";
resultReturn.jsonAndCode(request, res);
var result = res.code;
expect(result).to.eql("4.04");
});
});
在这里我们只用以判断返回结果的Status是不是预期的结果。
于是最后我们的结果跑出来是BDD风格的。
query data status code test
✓ should return 4.04 when result empty
✓ should return 2.05 when result empty
✓ should return 2.05 when delete result
✓ should return 2.05 when save result
CoAP与物联网系统之返回XML2014-08-28T14:14:14+00:002014-08-28T14:34:22.132476+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/use-jstoxml-convert-iot-coap-return-json/记得在一开始的时候给[IoT-CoAP](http://coap.phodal.com)添加了一个XML的支持,只是因为对于XML的了解似乎不是很深,又因此而挖了一个坑。
##jstoxml
这里用到了一个javascript转xml的库
他是这样用的
var jstoxml = require('jstoxml');
jstoxml.toXML({
a: '1',
foo: '',
b: '2'
});
// Output: <a>1</a><foo></foo><b>2</b>
看上去似乎很方便,一开始也不觉得有什么问题,便将这个库加到了package.json里面了。
##IoT CoAP xml
1.一个返回JSON的过程,便是我们需要接受application/xml这样的请求
request_helper.getHandler = function(req, res) {
switch (req.headers['Accept']) {
case "application/json":
qh.returnJSON(req, res);
break;
case "application/xml":
qh.returnXML(req, res);
break;
}
};
2.接着在查询完数据,回调
query_helper.returnXML = function(req, res) {
DBHelper.urlQueryData(req.url, function (result) {
returnResult.XMLAndCode(result, res);
});
};
3.我们便可以调用toXML返回XML
resultReturn.XMLAndCode = function (result, res) {
if (result.length == 2) {
res.code = '4.04';
res.end(jstoxml.toXML({
error: "Not Found"
}));
} else {
res.code = '2.05';
res.end(jstoxml.toXML(JSON.parse(result)));
}
};
##其他
最后返回的结果是
<id>1</id><value>is id 1</value><sensors1>19</sensors1><sensors2>20</sensors2>
只是这种结果似乎并不是真正意义上的XML,印象中XML的格式比这个复杂。
物联网相关web技术2014-08-27T12:54:14+00:002014-09-02T07:22:42.566232+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/internet-of-things-web-technology/找了一下一些常用的物联网相关的Web技术,整理如下。
##REST
REST不论是在HTTP协议中,还是在CoAP中都是常用的技术之一,虽然说不上是技术,但是常用是有的。
> REST从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的 应用通过URI来获取资源的表征。获得这些表征致使这些应用程序转变了其状态。随着不断获取资源的表征,客户端应用不断地在转变着其状态,所谓表征状态转移。
记得我在写毕业论文的时候这样写到:
> REST服务实际上是充当着网络与设备的传输介质,构建一个REST服务也就相当于 获取一个URL下的某个数据。
需要注意的是,这里最后关注的还是M2M的思想,写给机器的接口。
##CoAP
REST算是CoAP协议遵循的一个基本原则,除此之外他还是为受限制的设备而开始的协议。
> 受约束的应用协议(COAP)是一种软件协议旨在以非常简单的电子设备,使他们能够在互联网上进行交互式通信中使用。它特别针对小型低功率传感器,开关,阀门和需要被控制或监督远程,通过标准的Internet网络类似的组件。 COAP是一个应用层协议,该协议是用于在资源受限的网络连接设备,例如无线传感器网络节点使用。 COAP被设计为容易地转换为HTTP与Web简化集成,同时也能满足特殊的要求,例如多播支持,非常低的开销,和简单性。多播,低开销,以及简单性是因特网极其重要物联网(IOT)和机器对机器(M2M)设备,这往往是积重难返,有太多的内存和电源,比传统的互联网设备有。因此,效率是非常重要的。 COAP可以在支持UDP或UDP的模拟大多数设备上运行。
CoAP简化了HTTP协议,只提供了REST的四个方法。然而POST和PUT在我设计[IoT-CoAP](https://coap.phodal.com)的时候发现这两种行为是类似的,让人想起了patch方法。
##6LoWPAN
虽然还没有玩过这个东西,但是这个显然很受欢迎。
> Lowpan是IPv6 over Low-power wireless Personal Area Networks的首字母缩写,是IETF组织制定的物联网标准体系,它的物理层和MAC层采用802.15.4标准,网络层采用IPv6,并制定了专门的RPL组网路由协议,传输层采用UDP,应用层采用低开销的CoAP。简单讲,6Lowpan系统是一套完整的类似于Zigbee的网络技术,Zigbee能用的领域6Lowpan都可以使用,但是6Lowpan采用IPv6,具有许多优势,包括具有海量的地址空间,可与TCP/IP网络无缝集成,实现端到端的数据传输,并且很容易与HTTP转换,易于集成到互联网,开放的协议,无需专利费等。6Lowpan已经被ISA 100.11a、ETSI M2M、Zigbee SEP2.0等标准所采纳,很可能像TCP/IP成为互联网的事实标准那样,成为物联网领域的事实标准。Cisco、IBM、Honywell、TI、NXP等巨头以及Thingsqaure等众多初创企业都已经采用6Lowpan技术,研发相关芯片、协议栈、中间件以及应用系统,逐渐成为产业发展趋势。
有意思的是这是低功耗的网络,采用的是UDP。
##MQTT
在[IoT-CoAP](http://coap.phodal.com)的一个分支中就用到了这个协议。
> MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。MQTT协议是为大量计算能力有限,且工作在低带宽、不可靠的网络的远程传感器和控制设备通讯而设计的协议。
然而有意思的是MQTT采用的是使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。似乎从某种程度上来说这个会比CoAP的观察者好一点,因为是一对多。只是结果是推送功能的话,似乎还是是设备去获取状态。。
##XMPP
与JSON同样流行的还有XML,所以XMPP也会受到JAVA程序员的大爱。。
> XMPP是一种基于标准通用标记语言的子集XML的协议,它继承了在XML环境中灵活的发展性。因此,基于XMPP的应用具有超强的可扩展性。经过扩展以后的XMPP可以通过发送扩展的信息来处理用户的需求,以及在XMPP的顶端建立如内容发布系统和基于地址的服务等应用程 序。而且,XMPP包含了针对服务器端的软件协议,使之能与另一个进行通话,这使得开发者更容易建立客户应用程序或给一个配好系统添加功能。
##UDP
就设备来说UDP会比HTTP好一点。。
> UDP协议的全称是用户数据报协议 ,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。
##uIP
似乎这个和CoAP的目的是类似的,然而就目前而言还是没有CoAP来得有针对性。
> uIP 协议栈去掉了完整的 TCP/IP 中不常用的功能,简化了通讯流程,但保留了网络通信必须使用的协议,设计重点放在了 IP/TCP/ICMP/UDP/ARP 这些网络层和传输层协议上,保证了其代码的通用性和结构的稳定性。
IoT CoAP Content Format与application/json2014-08-25T14:09:10+00:002014-08-25T14:32:32.230963+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/coap-content-types-iot-coap-json-support/在做IoT-CoAP的过程中只支持JSON,查阅CoAP的草稿时发现支持了诸多的Content Types。
##CoAP Content Types
以下文字来自谷歌翻译:
> 互联网媒体类型是通过HTTP字符串标识,如“application/xml”。该字符串是由一个顶层的类型“applicaion”和子类型的“XML”。为了尽量减少使用这些类型的媒体类型来表示的开销消息有效载荷,COAP定义一个标识符编码方案互联网媒体类型的子集。预计这桌将可扩展标识符的值的IANA维护。内容类型选项被格式化为一个8位无符号整数。初始映射到一个合适的互联网媒体类型标识符表所示。复合型高层次类型(multipart和不支持消息)。标识符值是从201-255保留的特定于供应商的,应用程序特定的或实验使用和不由IANA。
下面是HTTP的标识符及类型
| Internet media type | Identifier |
|--------------------------------------------------|--------------|
| text/plain (UTF-8) | 0 |
| text/xml (UTF-8) | 1 |
| text/csv (UTF-8) | 2 |
| text/html (UTF-8) | 3 |
| image/gif | 21 |
| image/jpeg | 22 |
| image/png | 23 |
| image/tiff | 24 |
| audio/raw | 25 |
| video/raw | 26 |
| application/link-format [I-D.ietf-core-link-format] | 40 |
| application/xml | 41 |
| application/octet-stream | 42 |
| application/rdf+xml | 43 |
| application/soap+xml | 44 |
| application/atom+xml | 45 |
| application/xmpp+xml | 46 |
| application/exi | 47 |
| application/x-bxml | 48 |
| application/fastinfoset | 49 |
| application/soap+fastinfoset | 50 |
| application/json | 51 |
而在CoAP中只有简单地几个
| Media type | Encoding | Id. | Reference |
|------------------|----------|-------|-----------------------------|
| text/plain; | - | 0 | [RFC2046][RFC3676][RFC5147] |
| charset=utf-8 | | | |
| application/ | - | 40 | [RFC6690] |
| link-format | | | |
| application/xml | - | 41 | [RFC3023] |
| application/ | - | 42 | [RFC2045][RFC2046] |
| octet-stream | | | |
| application/exi | - | 47 | [EXIMIME] |
| application/json | - | 50 | [RFC4627] |
简单地说就是:
``诸如application/json的Content Types在CoAP中应该是50``。如上表所示的结果是其对应的结果,这样的话可以减少传递的信息量。
##IoT CoAP JSON
于是在一开始的时候首先支持的便是"application/json"这样的类型。
首先判断请求的header
request_helper.getHandler = function(req, res) {
switch (req.headers['Accept']) {
case "application/json":
qh.returnJSON(req, res);
break;
case "application/xml":
qh.returnXML(req, res);
break;
}
};
再转至相应的函数处理,而判断的依据则是Accept是不是"application/json"。
registerFormat('text/plain', 0)
registerFormat('application/link-format', 40)
registerFormat('application/xml', 41)
registerFormat('application/octet-stream', 42)
registerFormat('application/exi', 47)
registerFormat('application/json', 50)
对应地我们需要在一发出请求的时候设置好Accept,要不就没有办法返回我们需要的结果。
req.setHeader("Accept", "application/json");
IoT CoAP 块传输——使用Block传输数据2014-08-24T13:28:07+00:002014-08-24T14:22:07.009084+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/use-coap-block-send-data-on-iot-coap/在[IoT-CoAP](https://github.com/gmszone/iot-coap)中我们使用到了一个Block2的东西,于是便整理相关的一些资料,作一个简单的介绍,以及在代码中的使用。
##CoAP Block
简单地翻译了一下(谷歌 + 理解)
> CoAP是一个RESTful传输协议用于受限设备的节点和网络。基本的CoAP消息对于小型载荷——如温度传感器,光开关,和相似的楼宇自动化设备是相当不错的。然而,有时应用将需要传输更大的有效载荷,例如——更新固件。同HTTP,TCP做繁重工作将大型有效载荷分成多个数据包,并确保他们所有到达并以正确的顺序被处理。
CoAP是同UDP与DLTS一样是基于数据报传输的,这限制了资源表示(resource representation)的最大大小,使得传输不需要太多的分割。虽然UDP支持通过IP分片传输更大的有效载荷,且仅限于64KiB,更重要的是,并没有真正很好地约束应用和网络。
而不是依赖于IP分片,这种规范基本COAP了对“块”选项,用于传输信息从多个资源区块的请求 - 响应对。在许多重要的情况下,阻止使服务器能够真正无状态:服务器可以处理每块分开传输,而无需建立连接以前的数据块传输的其他服务器端内存。
综上所述,块(Block)选项提供了传送一个最小的在分块的方式更大的陈述。
##CoAP Post Block
看看在IoT CoAP中的post示例。
const coap = require('coap')
,request = coap.request
,bl = require('bl')
,req = request({hostname: 'localhost',port:5683,pathname: '',method: 'POST'});
req.setOption('Block2', [new Buffer('1'),new Buffer("'must'"), new Buffer('23'), new Buffer('12')]);
req.setHeader("Accept", "application/json");
req.on('response', function(res) {
res.pipe(bl(function(err, data) {
console.log(data);
process.exit(0);
}));
});
req.end();
Block2中一共有四个数据,相应的数据结果应该是
{ name: 'Block2', value: <buffer 31=""> }
{ name: 'Block2', value: <buffer 27="" 6d="" 73="" 74="" 75=""> }
{ name: 'Block2', value: <buffer 32="" 33=""> }
{ name: 'Block2', value: <buffer 31="" 32=""> }
这是没有解析的Block2,简单地可以用
_.values(e).toString()
将结果转换为
Block2,1
Block2,'must'
Block2,23
Block2,12
接着按","分开,
_.values(e).toString().split(',')[1]
就有
[ '1', '\'must\'', '23', '12' ]
便可以很愉快地将其post到数据库中了,</buffer></buffer></buffer></buffer>NodeJS New Relic安装指南2014-08-23T06:18:27.054274+00:002014-08-23T06:18:41.138227+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/use-new-relic-analytics-iot-coap-performace/在完成[iot-coap](https://github.com/gmszone/iot-coap)的node包之后,开始在服务器上部署,又想到了New Relic,于是开始了安装之旅。
##NodeJS New Relic安装指南
1.安装Node ``版本至少是0.8``
2.安装newrelic
npm install newrelic
3.从node_modules/newrelic复制newrelic.js到应用目录
4.设置newrelic.js
1). 起一个app_name
2). 复制license_key到这个js中
5.在应用中添加newrelic库
require('newrelic');
6.部署应用
tips: 数据应该可以在五分钟看到。
##其他
不知是不是因为是iot-coap包和new relic没有处理好,在后台基本上没有数据。
Nodejs RESTify RESTful创建2014-08-21T23:33:15+00:002014-08-21T23:42:24.851264+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/nodejs-restify-create-restful/回顾一下之前用RESTify创建API的过程,没有注意到官方给的示例和原来的不同,于是再次做个笔记。。
##RESTify GET
对于GET请求来说应该是比较简单的,也不会存在数据传不进来的问题,一个简单的GET示例
const restserver = restify.createServer();
restserver.get('id/:id', rest_helper.respond);
restserver.head('id/:id', rest_helper.respond);
restserver.listen(8848, function() {
console.log('%s listening at %s', restserver.name, restserver.url);
});
接着我们只需要创建一个简单的respond来响应就可以了
function respond (req, res, next) {
res.send({});
next();
};
这样便完成一个简单的GET请求,我们可以通过
curl http://localhost:8848/id/1
来传进ID值并返回一个结果。
##RESTify POST请求
一开始没有注意到官方的示例
var restify = require('restify');
var server = restify.createServer({});
server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());
server.get('/echo/:name', function (req, res, next) {
res.send(req.params);
return next();
});
server.listen(8080, function () {
console.log('%s listening at %s', server.name, server.url);
});
中用到了bodyParser用以接收参数,才能POST数据。我们才能用POST命令将数据POST进去,一个简单的curl示例如下所示
curl -H "Content-Type: application/json" -d '{"id":3, "value":"dream","sensors1":12,"sensors2":13}' http://localhost:8848
IoT CoAP 添加REST支持2014-08-21T14:35:36+00:002014-08-21T15:09:52.507851+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/use-coap-nodejs-sqlite-build-iot-create-restful-support/在完成第一阶段的CoAP功能之后,顺手把RESTful的HTTP版也添加了进去。
##CoAP REST 使用
创建一个简单的index.js
const iotcoap = require('iot-coap');
iotcoap.run();
iotcoap.rest.run(); //运行REST
这样我们就可以在不破坏原来功能的基本上添加新的特性了。只是我们还需要修改数据的配置
{
"db_name": "iot.db",
"table_name": "basic",
"key":[
"id",
"value",
"sensors1",
"sensors2"
],
"db_table": "id integer primary key, value text, sensors1 float, sensors2 float",
"init_table":[
"insert or replace into basic (id,value,sensors1,sensors2) VALUES (1, 'is id 1', 19, 20);",
"insert or replace into basic (id,value,sensors1,sensors2) VALUES (2, 'is id 2', 20, 21);"
],
"query_table":"select * from basic;",
"rest_url": "/id/:id",
"rest_post_url": "/",
"rest_port": 8848
}
添加了REST的端口配置,以及URL。
##CoAP REST 创建
有一个大前提是这里共用的是同一个数据库,自然而然的我们也可以用同一个db_helper。修改index.js
###添加rest
为了变成一个NodeJS的包提供给外部的函数使用,我们需要将其exports出去,于是修改index.js,添加下面的内容:
const rest = require('./server/rest');
module.exports.rest = rest;
###创建REST
代码如下所示,我们所做的便是创建一个RESTify 的基本资源管理
restserver.use(restify.gzipResponse());
restserver.use(restify.bodyParser());
restserver .use(restify.acceptParser(['json', 'application/json']));
restserver.get(config["rest_url"], rest_helper.get_respond);
restserver.put(config["rest_post_url"], rest_helper.post_respond);
restserver.del(config["rest_url"], rest_helper.del_respond);
restserver.post(config["rest_post_url"], rest_helper.post_respond);
restserver.head(config["rest_url"], rest_helper.respond);
restserver.listen(config["rest_port"], function() {
console.log('%s listening at %s', restserver.name, restserver.url);
});
详细代码可见
[https://github.com/gmszone/iot-coap](https://github.com/gmszone/iot-coap)
###REST GET/DELETE
再exports出这个rest,而rest_helper所做的便是一个与数据库的兼容。
rest_helper.respond = function(req, res, next) {
restdb_helper.urlQueryData(req.url, function(e){
res.send(JSON.parse(e));
next();
})
};
看看在query_helper.js中写的
query_helper.syncJSON = function(req, res, block) {
DBHelper.syncData(block, function (result) {
returnResult.saveAndCode(block, res);
});
};
两个看上去差不多,于是我们算是做了一个好的示例。而其他的大致也是类似的
rest_helper.get_respond = function (req, res, next) {
restdb_helper.urlQueryData(req.url, function(e){
res.send(JSON.parse(e));
next();
})
};
rest_helper.del_respond = function (req, res, next) {
restdb_helper.urlQueryData(req.url, function(e){
res.send(JSON.parse(e));
next();
})
};
###REST POST
除了里面的post_respond,因为CoAP用的是Buffer来发送数据的,而REST则用的JSON,于是我们需要将数据格式转换为简单的格式传递进去。
rest_helper.post_respond = function (req, res, next) {
var data=[];
_.each((req.params), function(key,value){
if(typeof key === "string"){
key = "'" + key + "'";
}
data.push(key);
});
restdb_helper.syncData(data, function(e){
res.send({});
next();
})
};
这里的做法与CoAP与数据之间的做法是一致的,POST和PUT用的是一样的写法。
IoT CoAP Node包创建与安装2014-08-20T14:25:18+00:002014-08-20T14:39:57.885519+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/create-iot-coap-node-pacakge-and-install/在经过几天的努力之后,终于可以支持用
npm install iot-coap
安装了。算是一个新的进步,然而虽然支持不是很完善,但是现在就先这样。。
##安装IoT CoAP
在上面的描述中,我们已经知道安装方法是
npm install iot-coap
接着我们创建一个简单的server.js
var iotcoap = require('iot-coap');
iotcoap.run();
同时我们还需要配置好我们的数据库,对于当前来说,数据库应该是这样子的
{
"db_name": "iot.db",
"table_name": "basic",
"key":[
"id",
"value",
"sensors1",
"sensors2"
],
"db_table": "id integer primary key, value text, sensors1 float, sensors2 float",
"init_table":[
"insert or replace into basic (id,value,sensors1,sensors2) VALUES (1, 'is id 1', 19, 20);",
"insert or replace into basic (id,value,sensors1,sensors2) VALUES (2, 'is id 2', 20, 21);"
],
"query_table":"select * from basic;"
}
##创建IoT CoAP
而在创建node包的时候,我们需要一个package.json,有一些基础的信息
{
"name": "iot-coap",
"version": "0.0.6",
"description": "Mini IoT CoAP Version",
"repository": {
"type": "git",
"url": "git@github.com:gmszone/iot-coap.git"
},
"dependencies": {
"coap": "0.8.0",
"bl": "~0.9.0",
"coap-cli": "0.3.0",
"sqlite3": "2.2.7",
"underscore": "1.6.0",
"jstoxml": "0.2.2"
},
"keywords": [
"coap",
"iot",
"internet of things"
],
"author": [
{
"name": "Fengda HUANG",
"url": "https://www.phodal.com/"
}
],
"license": "MIT",
"devDependencies": {
"pre-commit": "0.0.9",
"chai": "~1.9.1",
"mocha": "~1.21.4",
"timekeeper": "0.0.4",
"sinon": "~1.7.3"
},
"pre-commit": [
"test"
],
"scripts": {
"test": "./node_modules/.bin/mocha --bail --reporter spec 2>&1"
}
}
包含一些基本的信息如,包名,版本,依赖,作者等等,当然还包括了一个测试的脚本。而我们需要创建一个index.js,再export出iotcoap这个函数。最后我们就有了,一个简单的可以用的包,当然先包方法里面的内容给清了。
const coap = require('coap')
,server = coap.createServer({})
,fs = require('fs')
,file = './iot.json';
function iotcoap(){
}
iotcoap.run = function(){
};
module.exports = iotcoap;
我们便可以实现在步骤一的事情了。
构建基于CoAP SQLite Nodejs的物联网之查询数据2014-08-19T13:32:12+00:002014-08-19T14:06:19.068246+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/use-node-coap-sqlite-create-a-coap-server-get-response/简单地记录一下在IoT-CoAP中一次获取数据地过程。
##CoAP Get Client
我们先看看我们在示例中的Get.js的代码,这关乎在后面server端的代码。
const coap = require('coap')
,requestURI = 'coap://localhost/'
,url = require('url').parse(requestURI + 'id/1/')
,req = coap.request(url)
,bl = require('bl');
req.setHeader("Accept", "application/json");
req.on('response', function(res) {
res.pipe(bl(function(err, data) {
var json = JSON.parse(data);
console.log(json);
}));
});
req.end();
const定义数据的方法,和我们在其他语言中有点像。只是这的const主要是为了程序的健壮型,减少程序出错,当然这不是javascript的用法。
我们构建了一个请求的URL
coap://localhost/id/1/
我们对我们的请求添加了一个Header,内容是Accept,值是'application/json'也就是JSON格式。接着,便是等待请求回来,再处理返回的内容。
##IoT CoAP
###判断请求的方法
在这里先把一些无关的代码删除掉,并保证其能工作,so,下面就是简要的逻辑代码。
var coap = require('coap');
var server = coap.createServer({});
var request_handler = require('./request_handler.js');
server.on('request', function(req, res) {
switch(req.method){
case "GET": request_handler.getHandler(req, res);
break;
}
});
server.listen(function() {
console.log('server started');
});
创建一个CoAP服务,判断req.method,也就是请求的方法,如果是GET的话,就调用request_handler.getHandler(req, res)。而在getHandler里,判断了下请求的Accept
request_helper.getHandler = function(req, res) {
switch (req.headers['Accept']) {
case "application/json":
qh.returnJSON(req, res);
break;
case "application/xml":
qh.returnXML(req, res);
break;
}
};
如果是json刚调用returnJSON,
###Database与回调
而这里为了处理回调函数刚分为了两部分
query_helper.returnJSON = function(req, res) {
DBHelper.urlQueryData(req.url, function (result) {
QueryData.returnJSON(result, res);
});
};
而这里只是调用了
DBHelper.urlQueryData = function (url, callback) {
var db = new sqlite3.Database(config["db_name"]);
console.log("SELECT * FROM basic where " + url.split('/')[1] + "=" + url.split('/')[2]);
db.all("SELECT * FROM basic where " + url.split('/')[1] + "=" + url.split('/')[2], function(err, rows) {
db.close();
callback(JSON.stringify(rows));
});
};
这里调用了node sqlite3去查询对应id的数据,用回调处理了数据无法到外部的问题,而上面的returnJSON则只是返回最后的结果,code以及其他的内容。
QueryData.returnJSON = function(result, res) {
if (result.length == 2) {
res.code = '4.04';
res.end(JSON.stringify({
error: "Not Found"
}));
} else {
res.code = '2.05';
res.end(result);
}
};
当resulst的结果为空时,返回一个404,因为没有数据。这样我们就构成了整个的链,再一步步返回结果。构建基于CoAP SQLite Nodejs的物联网之数据库2014-08-18T12:45:02+00:002015-04-16T04:58:28.543976+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/use-coap-nodejs-sqlite-build-iot/在经历了几次重构之后,我们的IoT终于开始有个好的代码结构,再经过几次修正之后,我们就可以很愉快地发出第一个版本,v0.1或许将会是Nodejs的一个库。
##Node Module
这说里Module的意义是因为我们需要在别的地方引用到db_helper这个库,也就是下一小节要的讲的内容。
这样我们就可以在server.js类似于这样去引用这个js库。
var DBHelper = require('./db_helper.js');
DBHelper.initDB();
而这样调用的前提是我们需要去声明这样的module,为了方便地导出函数功能调用。
function DBHelper(){
}
DBHelper.initDB = function(){};
module.exports = DBHelper;
虽然这里的功能很简单,简单也能做我们想做的事情。
##Node Sqlite3
还是继续用到了SQLite3,只是这里用到的只是基本的查询和创建。
###一个简单的initDB函数
var db = new sqlite3.Database(config["db_name"]);
var create_table = 'create table if not exists basic (' + config["db_table"] + ');';
db.serialize(function() {
db.run(create_table);
_.each(config["init_table"], function(insert_data) {
db.run(insert_data);
});
});
db.close();
首先从配置中读取db_name,接着创建table,然后调用underscore的each方法,创建几个数据。配置如下所示
config = {
"db_name": "iot.db",
"db_table": "id integer primary key, value text, sensors1 float, sensors2 float",
"init_table":[
"insert or replace into basic (id,value,sensors1,sensors2) VALUES (1, 'is id 1', 19, 20);",
"insert or replace into basic (id,value,sensors1,sensors2) VALUES (2, 'is id 2', 20, 21);"
],
"query_table":"select * from basic;"
};
而我们在上一篇[CoAP与物联网系统之返回JSON](http://www.phodal.com/blog/use-coap-build-internet-of-things-return-json/)所提到的url查询所做的事情便是
DBHelper.urlQueryData = function (url, callback) {
var db = new sqlite3.Database("iot.db");
var result = [];
console.log("SELECT * FROM basic where " + url.split('/')[1] + "=" + url.split('/')[2]);
db.all("SELECT * FROM basic where " + url.split('/')[1] + "=" + url.split('/')[2], function(err, rows) {
db.close();
callback(JSON.stringify(rows));
});
};
将URL传进来,便解析这个参数,接着再放到数据库中查询,再回调回结果。
这样我们就可以构成之前所说的查询功能,而我们所谓的post功能似乎也可以用同样的方法加进去。CoAP与物联网系统之返回JSON2014-08-17T14:19:11+00:002014-09-10T08:07:37.915387+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/use-coap-build-internet-of-things-return-json/在给IoT CoAP添加了JSON支持之后,变得非常有意思,至少我们可以获得我们想要的结果。在上一篇中我们介绍了一些常用的工具——[CoAP 命令行工具集](http://www.phodal.com/blog/coap-command-line-tools-set/)。
##CoAP客户端代码示例
开始之前我们需要有一个客户端代码,以便我们的服务端可以返回正确的数据并解析
var coap = require('coap');
var requestURI = 'coap://localhost/';
var url = require('url').parse(requestURI + 'id/1/');
console.log("Request URL: " + url.href);
var req = coap.request(url);
var bl = require('bl');
req.setHeader("Accept", "application/json");
req.on('response', function(res) {
res.pipe(bl(function(err, data) {
var json = JSON.parse(data);
console.log(json);
}));
});
req.end();
代码有点长内容也有点多,但是核心是这句话:
req.setHeader("Accept", "application/json");
这样的话,我们只需要在我们的服务端一判断,
if(req.headers['Accept'] == 'application/json') {
//do something
};
这样就可以返回数据了
##CoAP Server端代码
Server端的代码比较简单,判断一下
if (req.headers['Accept'] == 'application/json') {
parse_url(req.url, function(result){
res.end(result);
});
res.code = '2.05';
}
请求的是否是JSON格式,再返回一个205,也就是Content,只是这时设计是请求一个URL返回对应的数据。如
coap://localhost/id/1/
这时应该请求的是ID为1的数据,即
[ { id: 1, value: 'is id 1', sensors1: 19, sensors2: 20 }]
而parse_url只是从数据库从读取相应的数据。
function parse_url(url ,callback) {
var db = new sqlite3.Database(config["db_name"]);
var result = [];
db.all("SELECT * FROM basic;", function(err, rows) {
callback(JSON.stringify(rows));
})
}
并且全部都显示出来,设计得真是有点不行,不过现在已经差不多了。
CoAP 请求、响应与状态码2014-08-15T13:07:16+00:002014-08-16T13:50:50.702536+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/coap-request-response-model-status-code/在写CoAP的物联网系统的时候,发出一个请求
coap get coap://localhost/id/2
结果返回的是
(4.06) [{"id":2,"value":"is id 2","sensors1":20,"sensors2":21}]
406不就是``Not Acceptable``么,于是才知道原来CoAP也有状态码
##CoAP请求/响应模式
下面是一个GET请求的示例,状态码是2.05
Client Server
| |
| CON [0xbc90] |
| GET /id/1 |
| (Token 0x71) |
+----------------->|
| |
| ACK [0xbc90] |
| 2.05 Content |
| (Token 0x71) |
| "22.5 C" |
|<-----------------+
| |
相应的对应于4.04也就有了
Client Server
| |
| CON [0xbc91] |
| GET /id/2 |
| (Token 0x72) |
+----------------->|
| |
| ACK [0xbc91] |
| 4.04 Not Found |
| (Token 0x72) |
| "Not found" |
|<-----------------+
| |
于是就去看看HTTP的状态码和CoAP的状态码,发现原来是相似的。
##CoAP状态码
一、 Success 2.xx
这一类型的状态码,代表请求已成功被服务器接收、理解、并接受。
- 2.01 Created
- 2.02 Deleted
- 2.03 Valid
- 2.04 Changed
- 2.05 Content
二、 Client Error 4.xx
这类的状态码代表了客户端看起来可能发生了错误,妨碍了服务器的处理。
- 4.00 Bad Request
- 4.01 Unauthorized
- 4.02 Bad Option
- 4.03 Forbidden
- 4.04 Not Found
- 4.05 Method Not Allowed
- 4.06 Not Acceptable
- 4.12 Precondition Failed
- 4.13 Request Entity Too Large
- 4.15 Unsupported Content-Format
三、 Server Error 5.xx
这类状态码代表了服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。
- 5.00 Internal Server Error
- 5.01 Not Implemented
- 5.02 Bad Gateway
- 5.03 Service Unavailable
##其他
物联网系统CoAP版进行时
[https://github.com/gmszone/iot-coap](https://github.com/gmszone/iot-coap)IoT CoAP 部署与测试2014-08-14T14:00:29+00:002014-10-30T05:10:01.275560+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/iot-coap-deploy-with-test/在开始写物联网系统的CoAP版的时候,在开始可以简单地运行之后,便开始试着部署工作,方便以后测试。
##IoT CoAP部署
1.Clone代码到PATH路径下
git clone git@github.com:phodal/iot-coap.git PATH
2.安装包
cd server
npm install
3.使用forever运行
sudo npm install -g forever
4.打开UDP端口
在iptables加一条
-A INPUT -p udp --dport 5683 -j ACCEPT
重启一下iptables
5.Nginx proxy配置
修改配置文件
listen 5683
...
proxy_pass http://localhost:5683
...
(但是这样有个问题就是会变成http代理,而不是纯CoAP??)
##IoT CoAP测试
一、 使用Copper测试
Copper是Firefox的一个插件
> The Copper (Cu) CoAP user-agent for Firefox installs a handler for the 'coap' URI scheme and allows users to browse and interact with Internet of Things devices.
可以用于测试CoAP,一个简单的示例就是 [coap://vs0.inf.ethz.ch/](coap://vs0.inf.ethz.ch/ )
在Firefox中可以直接打开这个URI,然而在其他浏览器的话,我们可以试试用CoAP-CLI
二、 CoAP-CLI
CoAP-CLI是一个基于Node-CoAP的命令行工具,在IoT-CoAP包中带有。
我们可以直接
coap get coap://localhost/Phodal
应该会返回一个
(2.05) GET Phodal
##其他
物联网系统CoAP版进行时
[https://github.com/phodal/iot-coap](https://github.com/phodal/iot-coap)