基于 Node-red 的 IoT 软件构建工具

本项目的目的是想基于 Node-red 这一开源的图形化程序设计工具,开发一套针对 IoT 设备的软件构建工具。通过简单的 drug&drop 操作,可以使没有编程基础的人,很容易的构建出 IoT 设备上运行的软件。

 

最新更新

  • 2015/03/25 04:18:59

    light_sensor 运行状态图

    上图可以看到,光感的指数在 400-500 之间。

    手指遮住传感器之后,指数降到了 100 以下。


2015/03/25 04:13:18

light_sensor node 编写完成

light_sensor node 的编译方法跟上一个 face_detection 的编译方法一样。

这里主要讲一下代码的编写方式。

我们在编写 node-red 的 node 的时候,尽量采用异步的方式,这样在处理 iot msg 的同时,还会接收新的 msg。

因此,我们采用了 node.js 上比较流行的 libuv。

libuv 是 Node 的新跨平台抽象层,用于抽象 Windows 的 IOCP 及 Unix 的 libev。作者打算在这个库的包含所有平台的差异性。

libuv 采用了 异步 (asynchronous), 事件驱动 (event-driven) 的编程风格, 其主要任务是为开人员提供了一套事件循环和基于 I/O(或其他活动) 通知的回调函数, libuv 提供了一套核心的工具集, 例如定时器, 非阻塞网络编程的支持, 异步访问文件系统, 子进程以及其他功能.

以上信息摘自百度。

简单来说,libuv 就是一个大的循环,他可以监控一堆的事件,例如文件操作,socket IO,等等。它的优势在于异步,并且响应迅速。

在本项目中的 light_sensor node 中,要如何使用 libuv 呢?我们先来描述一下 light_sensor 的工作原理。

这个 sensor 非常的简单,就是从模拟口中读出当前的模拟量,大于 400,则认为当前环境有光,小于 400 则认为当前环境较暗。

我们现在要做的就是在 libuv 的循环中,挂一个定时器,定时器每次到时,会触发 libuv 通知一个自定义的回调函数,这个函数中触发 mraa 读取一次 light_sensor 的模拟值。下面是简单的函数实现

#include

#include

#include

#include

#include

#include

#include “mraa/aio.h”

#include “senser.h”

 

using namespace std;

 

bool init_light_senser = false;

 

typedef struct _ls_result_t {

int aNum; /*analog value output by the light senser*/

} ls_result_t;

 

// for libuv

static uv_loop_t *ls_loop = NULL;

static req_ls_t req_ls;

static uv_timer_t ls_timer;

mraa_aio_context adc_a0;

uint16_t adc_value = 0;

 

void LS_release_all()

{

mraa_aio_close(adc_a0);

init_light_senser = false;

return;

}

bool LS_init(int ls_io_pin)

{

adc_a0 = mraa_aio_init(ls_io_pin);

return true;

}

 

int LS_read_value(int ls_io_pin, ls_result_t *result)

{

if(!init_light_senser) {

LS_init(ls_io_pin);

init_light_senser = true;

}

 

if(adc_a0 == NULL)

{

return -1;

}

 

result->aNum = mraa_aio_read(adc_a0);

return 0;

 

}

 

void run_ls_timer(uv_timer_t *req)

{

static int last_num = 0;

req_ls_t *ls = (req_ls_t*)(req->data);

 

// run fd

ls_result_t result;

LS_read_value(ls->ls_io_pin,&result);

char str[120] = {0};

 

if(result.aNum > 400)

{

sprintf(str, “And God said, Let there be light; and there was light. [ %d ]”, result.aNum);

}

else

{

sprintf(str, “The light shines in the darkness, and the darkness did not overcome it. [ %d ]”, result.aNum);

}

 

ls->ls_cb(result.aNum, str);

}

int light_senser(int interval, int ls_io_pin, light_senser_cb_t cb)

{

uv_timer_stop(&ls_timer);

 

req_ls.ls_cb = cb;

req_ls.ls_io_pin = ls_io_pin;

ls_timer.data = (void*)&req_ls;

if(ls_loop == NULL)

ls_loop = uv_default_loop();

uv_timer_init(ls_loop, &ls_timer);

uv_timer_start(&ls_timer, run_ls_timer, 0, interval);

}

void light_senser_run()

{

uv_run(ls_loop, UV_RUN_DEFAULT);

}

需要简单解释一下这个 libuv 的用法,如上面的函数 light_sensor 中,创建了一个名为 ls_loop 的 libuv 大循环( ls_loop = uv_default_loop();),并且初始化了一个名为 ls_timer 的定时器事件,将 run_ls_timer 函数作为 ls_timer 定时器到时后的回调函数。而 light_sensor_run,这个函数中则将 ls_loop 的 libuv 循环运行起来。这样每次定时器到时,就会触发 run_ls_timer 函数,然后读取传感器的值。


2015/03/24 11:37:59

face_detection Node 编写完成

第一个自定义 node。实现了从摄像头读取数据,并且在检测到人脸的情况下,在浏览器界面上显示一张照片。

进入 io-js/utils/autogen 并且打开 config.py. 修改如下变量:INPUT_DIR, INPUT_DECL_PATHS, INPUT_LIB_PATH, NODERED_PATH, EXTRA_LIB. 注意下面有一句话,##### DO NOT CHANGE BELOW VAR ######,下面的就都不要改了。

INPUT_DIR 里面如果有多个需要暴露给外面的 h 文件,建议把里面的东西都合成一个,目前 INPUT_DIR 里面只支持写一个头文件。

新版本的 io-js,支持指定 config.py 文件,需要使用-c 参数。

然后,在 io-js/utils/autogen 目录下运行 run.py,脚本会自动将 c 代码转换成 js 脚本,并且存放在在 Atlas/iot/sample/xxx 目录下,xxx 为你在 config.py 中制定的文件夹。

然后进入 Atlas/iot/sample/xxx/addon 目录下,这里是 face_detection/addon 目录,然后直接 make。

成功之后,编译过程就结束了。

然后就能在 node-red 的界面上看到 face_detection 的 node 了。


2015/03/24 11:28:23

工具主框架完成

通过在 msg 中增加 iot 字段,使得在标准的 node-red 中可以处理 iot 相关的信息。所有的我们开发的 iot node,都支持从 msg 的 iot 字段中获取 iot 设备需要的 input、output 参数

如上图,msg.iot 字段中包含了 buzzarnode 需要的参数信息。

 

发布者:Cara,转载请注明出处:http://www.makercollider.com/project/5632

发表评论

登录后才能评论
QR code