【intel程序猿笔记】英特尔® Edison编程环境间的数据分享
2015-07-289679
AI 快速预览详细
本文介绍了如何在英特尔® Edison平台上实现不同编程环境(如NodeJS、Arduino、C++)之间的数据共享。通过发布-订阅模式,利用中断事件触发数据流,避免了轮询和复杂的绑定开发。示例代码展示了如何在Arduino和NodeJS之间进行通信。这种方案适用于需要跨语言协同工作的开发者,提升了开发效率。
|
周二福利帖又来了!首先,我们来揭晓上周【intel程序猿笔记】使用英特尔® Edison探索空气质量监测 的获奖情况。
上周有奖问答题目是:下列哪个选项不是该系统函数所涉及到的功能的 ?

奖品将在系列活动结束后统一寄出,奖品实行累积制,各位,再接再厉!没有获奖的小伙伴,今天机会又来了喔!
现在,进入科学时间:我是原文链接喔~
在许多情况下,我们希望使用多种编程环境开发(比如)物联网应用。
- 相比于 NodeJS 或 Arduino,我们更喜欢使用 OpenCV* 以 C++ 语言进行图像处理。 主要是因为以 C++ 编写的 OpenCV 能够提供许多示例。
- 譬如,我们用 Arduino 编写的应用需要读取摄像镜头中的面部编号。 为此,我们需要使用 OpenCV 处理摄像头图像,然后将检测到的面部编号传给 Arduino。
- 我们喜欢使用 NodeJS 创建基于开发板的 web 服务器,因为相比于采用其他语言,这种方法更加简单。
有许多这种类似的示例。 然而,我们希望在这些示例中找到一种简单的机制实现不同编程环境的数据共享。
Han, Matthias 写了一篇关于 Arduino 与 C++ 共享内存的好文章。 这种方法可行,因为C++ 和 Arduino 的运行方式类似于 Linux 中的进程。 但是,对于 C++ 的初学者来说,这种进程相对比较复杂。 而且,如果您希望将该进程扩展至 NodeJS,需要编写 C++ 代码,并编写原生绑定,以访问 NodeJS 中的变量。
还有一种方法是创建可从所有程序读取的通用可共享文件。 所有程序均可轮询文件中的数据变化。 在这种情况下,将会有线程或循环负责查找文件中的数据变化。 读取数据时,如有数据变化,您将读取和处理该数据。 这种想法看似简单,但在软件领域,轮询并不太受欢迎。
在本文中,我将探讨发布程序-订阅程序模式,这种模式可使运行于 Linux 的不同程序之间实现数据共享。 在软件开发过程中,这种模式的适应性非常强。 但在嵌入式领域,结合使用软硬件才能实现这种模式。
架构:
消息流可分为两部分。 一部分是变化通知,另一部分是数据读取。 在软件领域,这是一种已确定的老方法。 一些数据仓储应用(硬件)运用这种方法协同数据。 在这类硬件中,首先将小型通知文件拖放至目录。 该通知文件将包含数据信息和数据变化时间,并参考实际数据文件的位置,最后通常会变成大型文件。 精灵程序将读取该通知文件,并触发 appreciate 程序读取这一大型文件。 在此,我尝试引入相同的概念。 不过在这一示例中,我将触发中断事件,而非通知文件:
通知流:

消息流:

我们来了解一下通知流和信息流:
每种编程环境都有自己的输出数据容器和针脚来触发通知。 如果需要发送数据,该环境首先将内容推送至容器文件。 然后向通知针脚发送信号 HIGH。 我们来看看下面一种奇怪的线路图。 令人惊讶的是,这些针脚都被缩短了。 我们来举例说明这种情况。
线路:

我们来看看 Arduino 程序与 NodeJS 之间如何通信。

数据和通知流从 NodeJS 前往 Arduino。
假设您有一个 Arduino 程序,用来读取距离传感器的数据。 该距离传感器数据需发送至 NodeJS 做进一步处理。
在这种情况下,Arduino 需要一个通知针脚,即 GPIO 针脚。 根据上述线路图,用于 Arduino 的针脚为 #3。 如果出现任何新数据,Arduino 把该数据写入根目录(参考消息流示意图)中的通知容器文件,即 /arduino_notification_out.txt。
成功写入内容后,Arduino 向针脚 #3 发送信号 HIGH。 现在,请看上述线路图。 #3 缩短成了 #1。 这意味着,如果针脚 #3 变成 HIGH,该信号 HIGH 将发送至针脚 #1。
Arduino 代码:
- int notifier_pin = 3;
- int js_subscriber_pin = 6;
-
- FILE *fromarduino, *toarduino;
- int i = 0;
- int c;
-
- // the setup routine runs once when you press reset:
- void setup() {
- pinMode(notifier_pin, OUTPUT); //Notification pin
- pinMode(js_subscriber_pin, INPUT_PULLUP); //interrupt pin for reading message from JS
- attachInterrupt(js_subscriber_pin, subscriberEvent, RISING); //Subscribe to interrupt notifications from JavaScript
- Serial.begin(9600);
- }
-
- //Read message from js notification file
- void subscriberEvent() {
-
- toarduino = fopen("/js_notification_out.txt","r"); //Opening message from JS
- if (toarduino)
- {
- while ((c = getc(toarduino)) != EOF)
- {
- if(c != 10)//new line
- {
- Serial.print((char)c);
- }
- }
- Serial.println("");
- Serial.println("----------------");
- fclose(toarduino);
- }
- }
-
- // the loop routine runs over and over again forever:
- void loop() {
- if(i < 50)
- {
- i = i + 1;
- }
- else
- {
- i = 0;
- }
-
- publishData();
- notifyWorld();
- delay(1000); // wait for a second
- }
-
- void publishData()
- {
- fromarduino = fopen ("/arduino_notification_out.txt", "w+");
- fprintf(fromarduino, "[%d]", i);
- fclose(fromarduino);
- }
-
- //Nofity any body connected to this interrupt (C++ program and NodeJS) program
- void notifyWorld()
- {
- digitalWrite(notifier_pin, HIGH);
- delay(200);
- digitalWrite(notifier_pin, LOW);
- }
复制代码在 NodeJS 程序中,我们为针脚 #1 附加一个中断事件。 如果针脚升高,说明 Arduino 通知容器文件中出现新数据。 现在,NodeJS 读取该文件并处理数据。 请参考 “数据和事件流从 Arduino 前往 NodeJS” 示意图,以更加清晰地了解这一过程。
NodeJS 代码:
- var mraa = require("mraa");
- var fs = require('fs');
-
-
- /**********Read notification from arduino*************/
- var subscriber_pin = new mraa.Gpio(1);
- subscriber_pin.dir(mraa.DIR_IN);
- subscriber_pin.isr(mraa.EDGE_RISING, subscriberEvent); //Subscribe to interrupt notifications from Arduino
-
- function subscriberEvent() {
- var contents = fs.readFileSync('/arduino_notification_out.txt').toString();
- console.log("Message from Arduino:" + contents);
- }
-
- /********** Trigger message sending interrupt every 20 seconds *************/
- var counter = 0;
- var notifier_pin = new mraa.Gpio(5);
- notifier_pin.dir(mraa.DIR_OUT);
-
- setInterval(function(){
- counter++;
- fs.writeFileSync("/js_notification_out.txt", "NodeJS: [" + counter + "]\n");
- notifyWorld();
- counter = 0;
- },20000);
-
-
- function notifyWorld()
- {
- notifier_pin.write(1);
- setTimeout(function(){
- notifier_pin.write(0);
- },200);
- }
复制代码您可以通过类似的方法将数据从 NodeJS 发送至 Arduino。 请参考 “数据和事件流从 NodeJS 前往 Arduino” 示意图,以更加清晰地了解这一过程。
我们可将该方法扩展至任何支持中断事件的编程环境。
这种方法的优势:
运用这种方法,可以避免不必要的文件变化轮询,也无需开发 C++ 绑定以与 NodeJS 共享数据。 其编程也非常简单。
运用这种方法,可以避免不必要的文件变化轮询,也无需开发 C++ 绑定以与 NodeJS 共享数据。 其编程也非常简单。
这种方法的劣势:
这种方法存在一种劣势, 即所有方向的数据流都需要一对 GPIO 针脚。 如果需要与多种编程环境交换数据,可能会耗尽 GPIO。 不过,我们可采用类似的架构达到相同的效果,而且只需消耗一对 GPIO。 但这之后您需要用带有 eventsource、事件数据等相应属性的单一 JSON 文件管理逻辑。 还需注意文件锁定情况。 尽管如此,这种方法依然可行。
这种方法存在一种劣势, 即所有方向的数据流都需要一对 GPIO 针脚。 如果需要与多种编程环境交换数据,可能会耗尽 GPIO。 不过,我们可采用类似的架构达到相同的效果,而且只需消耗一对 GPIO。 但这之后您需要用带有 eventsource、事件数据等相应属性的单一 JSON 文件管理逻辑。 还需注意文件锁定情况。 尽管如此,这种方法依然可行。
更多Edison信息请点击右边链接直接登录 >>>> 英特尔开发人员专区
广告,请广而告知——
每周二【intel 程序猿笔记】帖子下会设计一个与帖子内容相关的问答投票,你只要在留言区参与投票,选出正确的答案,社区小管家会挑选每周前10名回答正确的幸运互动者随机赠送小礼品,礼品可以实行累积制喔。也奏是说——只要你脑洞够大、热情够给力,你就可以横扫所有奖品实现大满贯喔!当然,对于大满贯获得者,我们还有神秘大礼包让你喜上加喜、锦上添花。奏这么任性,没办法!
现在,抢福利时间又到——
下面哪个选是消息流内容所包含的选项()?(答案单选)





不过还有些疑问
1.多个程序见访问相同资源的冲突要如何避免,比如我在arduino里面初始化某个端口,可能不小心在js里面也初始化了。这种冲突是程序设计时候自己去避免吗?
2.c++和js的数据共享是不是可以达到更快的传输速度?不过看原文貌似非常麻烦。
作良心老板——3D打印在向我招手~~