導語 本文基于contiki3.0系統梅忌,翻譯自iot in five days规婆,使用的節(jié)點是avr-atmega128rfa1
Copper是一個基于CoAP的IOT通用瀏覽器,它可以和當前存在的CoAP設備直觀的交互和調試傲茄。More Information
- 2.在本次試驗中使用兩個節(jié)點:一個Border Router和一個CoAP server
注:要確保節(jié)點在之前的sessions已經寫入了Node ID,以便產生MAC/IPv6地址
注:在atmega128rfa1平臺上EUI即IEEE地址位于platform/avr-atmega128rfa1/params.h捐康,在本次試驗中畦幢,我將border-router的IEEE地址設置為{0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x02},CoAP server節(jié)點設為{0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01}
另潮孽,發(fā)現以下錯誤揪荣,修改examples/er-rest-example/project-conf.h中的UIP_CONF_BUFFER_SIZE為240,同時為了使LED可用,在該文件中添加以下代碼:
#define PLATFORM_HAS_LEDS 1
3.在Makefile(examples/er-rest-example/)中有兩件事要注意:
-
1.resource文件夾被包含作為項目文件夾往史,所有的resource文件都被加入編譯
-
2.包含了er-coap和rest-engine應用
注:如果我們想盡可能避免沖突变逃,移除下面代碼:
#undef NETSTACK_CONF_MAC #define NETSTACK_CONF_MAC nullmac_driver
* 4.接下來檢查**project-conf.h**中的相關配置,首先確保TCP被禁用怠堪,因為CoAP是基于UDP的
![](http://upload-images.jianshu.io/upload_images/1245901-aec86e78e6cf255d.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 5.**REST_MAX_CHUNK_SIZE**是提供給資源響應的最大緩沖區(qū)大小,更大的數據要通過resource處理并被發(fā)送給CoAP blocks.**COAP_MAX_OPEN_TRANSACTION**是節(jié)點能夠處理的最大開放傳輸數量
![](http://upload-images.jianshu.io/upload_images/1245901-d57dfc2fa23f6e32.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#CoAP Server
通過測試er-example-server.c(examples/er-rest-example)這個例子理解它的實現名眉。首先要注意一個叫resources的文件夾:各種resources被不同的文件實現粟矿,易于調試。
在CoAP中要被包含的resources定義如下:
/*
* Resources to be activated need to be imported through the extern keyword.
* The build system automatically compiles the resources in the corresponding sub-directory.
*/
extern resource_t
res_hello,
res_mirror,
res_chunks,
res_separate,
res_push,
res_event,
res_sub,
res_b1_sep_b2;
#if PLATFORM_HAS_LEDS
extern resource_t res_leds, res_toggle;
#endif
#if PLATFORM_HAS_LIGHT
#include "dev/light-sensor.h"
extern resource_t res_light;
#endif
/*
#if PLATFORM_HAS_BATTERY
#include "dev/battery-sensor.h"
extern resource_t res_battery;
#endif
#if PLATFORM_HAS_RADIO
#include "dev/radio-sensor.h"
extern resource_t res_radio;
#endif
#if PLATFORM_HAS_SHT11
#include "dev/sht11/sht11-sensor.h"
extern resource_t res_sht11;
#endif
*/
包含在**PLATFORM_HAS_X**的resources宏定義是獨立于目標平臺的损拢,如果平臺被選定陌粹,資源也就確定了。
REST engine通過調用*rest_init_engine()*初始化福压,這樣開啟的resources就被綁定了掏秩。
rest_init_engine();
/*
* Bind the resources to their Uri-Path.
* WARNING: Activating twice only means alternate path, not two instances!
* All static variables are the same for each URI path.
*/
rest_activate_resource(&res_hello, "test/hello");
/* rest_activate_resource(&res_mirror, "debug/mirror"); */
/* rest_activate_resource(&res_chunks, "test/chunks"); */
/* rest_activate_resource(&res_separate, "test/separate"); */
rest_activate_resource(&res_push, "test/push");
/* rest_activate_resource(&res_event, "sensors/button"); */
/* rest_activate_resource(&res_sub, "test/sub"); */
/* rest_activate_resource(&res_b1_sep_b2, "test/b1sepb2"); */
#if PLATFORM_HAS_LEDS
/* rest_activate_resource(&res_leds, "actuators/leds"); */
rest_activate_resource(&res_toggle, "actuators/toggle");
#endif
#if PLATFORM_HAS_LIGHT
rest_activate_resource(&res_light, "sensors/light");
SENSORS_ACTIVATE(light_sensor);
#endif
現在看看res-hello.c荆姆,它實現了一個“hello world” resource 用于測試
如前所示資源已經在**RESOURCE**宏中定義了蒙幻,對于這個特定的實現,我們規(guī)定資源名為res-hello,也規(guī)定了link-formatted屬性和**GET**回調handler胆筒。**POST,PUT,DELETE**方法在本resource中不被支持邮破,就傳入**NULL**作為參數。
![](http://upload-images.jianshu.io/upload_images/1245901-8975a78e8b536c35.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**res_get_handler**是**GET** request的回調函數仆救,其實現:
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
const char *len = NULL;
/* Some data that has the length up to REST_MAX_CHUNK_SIZE. For more, see the chunk resource. */
char const *const message = "Hello World! ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy";
int length = 12; /* |<-------->| */ //默認
長度的回復抒和,在本例中整個字符串只有Hello World!會被發(fā)送
/* The query string can be retrieved by rest_get_query() or parsed for its key-value pairs. */
if(REST.get_query_variable(request, "len", &len)) {//如果len被設定了就發(fā)送len長度字節(jié)的信息
length = atoi(len);
if(length < 0) {//如果為負,發(fā)送空字符串
length = 0;
}
if(length > REST_MAX_CHUNK_SIZE) {//如果len比最大允許值還大就值發(fā)送最大允許值的字符串
length = REST_MAX_CHUNK_SIZE;
}
memcpy(buffer, message, length); //copy the default
} else {
memcpy(buffer, message, length);
}
//設置response內容類型為 Content-Type:text/plain
REST.set_header_content_type(response, REST.type.TEXT_PLAIN); /* text/plain is the default, hence this option could be omitted. */
REST.set_header_etag(response, (uint8_t *)&length, 1);//在response前加入header,設置負荷長度字段
REST.set_response_payload(response, buffer, length);//把負荷加入response
}
![](http://upload-images.jianshu.io/upload_images/1245901-4e4b9ba76ef75c36.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
在**project-conf.h**中加入以下代碼用于測試
#undef NETSTACK_CONF_RDC
#define NETSTACK_CONF_RDC nullrdc_driver
然后編譯并上載(這里為了方便就直接借書上的圖了彤蔽,具體操作可以看我的這篇博客[Contiki邊界路由](http://www.reibang.com/p/8d54bc801271):
![](http://upload-images.jianshu.io/upload_images/1245901-a732a8a8676815a8.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
在串口打印中也可以看到IPv6服務器地址摧莽,斷開節(jié)點連上另一個作為客戶端
#Border-Router:
######此部分和我的[Contiki邊界路由](http://www.reibang.com/p/8d54bc801271)博客差不多。顿痪。镊辕。不好意思這篇博客是先寫的
![](http://upload-images.jianshu.io/upload_images/1245901-164137d73e763599.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
不要關閉窗口,讓節(jié)點連接员魏,就可以看見類似于如下的信息:
![
![](http://upload-images.jianshu.io/upload_images/1245901-6cb368f954af8b69.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
](http://upload-images.jianshu.io/upload_images/1245901-84d37dc1158c1c59.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可以ping border-router:
![](http://upload-images.jianshu.io/upload_images/1245901-9b5a1edb4fc94d6a.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
連接上服務器節(jié)點,也可以ping:
![](http://upload-images.jianshu.io/upload_images/1245901-52925ff581c938b7.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
這樣就可以發(fā)現服務器資源了丑蛤。打開firfox,輸入服務器地址:
coap://[aaaa::c30c:0000:0000:0001]:5683/
![](http://upload-images.jianshu.io/upload_images/1245901-9c63b98fdf3bbf89.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
點擊**DISCOVER**撕阎,在左側網頁你就可以:
如果你選擇**toggle**資源受裹,使用**POST**你可以看見服務器節(jié)點的紅燈會翻轉;
如果選擇**Hello**資源,服務器會回應你一個Hello World!
如果你通過選擇并點擊**OBSERVE**棉饶,觀察**Sensors->BUTTON**事件厦章,每當你按一次用戶按鈕,一個事件就會被觸發(fā)并被回報照藻。
最后袜啃,如果你去**er-example-server.c**文件,并打開下面的宏定義幸缕,可以看到更多可用的宏定義群发。
![](http://upload-images.jianshu.io/upload_images/1245901-265dfef0468f3684.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
獲得當前收發(fā)器的RSSI值:
![](http://upload-images.jianshu.io/upload_images/1245901-8e9eaa3e873609ce.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
獲取電池電量:
![](http://upload-images.jianshu.io/upload_images/1245901-9e6fb0c09ca9e19e.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
當節(jié)點連接到USB,獲取ADC單元的值发乔,實際值將為:
v[mV]=(units*5000)/4096
如果想讓綠燈亮:
![](http://upload-images.jianshu.io/upload_images/1245901-21bec7552c85bee7.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
然后在payload(the ongoing tab)上寫:
mode="on"
并按下**POST**或**PUT**