物联网应用中的跨编程环境数据共享

物联网(IoT)应用开发中,经常需要在多种编程环境中工作。例如,可能会选择使用C++和OpenCV库进行图像处理,因为C++中有许多OpenCV的示例。另一方面,可能会选择Node.js来创建一个网络服务器,因为它相对容易实现。在这些情况下,总是希望有一个简单的机制来在不同的编程环境中共享数据。

英特尔开发者

英特尔开发者区为物联网提供了丰富的资源,包括知识、工具、开发套件和专家社区,以帮助快速轻松地将创新想法转化为物联网解决方案。

数据共享的挑战

在不同的编程环境中共享数据可能会遇到一些挑战。例如,Arduino程序可能需要读取摄像头图像中的人脸数量,这需要使用OpenCV进行图像处理,然后将检测到的人脸数量传递给Arduino。或者,可能需要在Node.js中创建一个网络服务器,并且希望它能够与Arduino程序通信。

共享内存的方法

Han, Matthias写了一篇关于如何在Arduino和C++之间共享内存的好文章。这种方法是可行的,因为C++和Arduino就像Linux中的进程一样运行。然而,对于C++初学者来说,这个过程看起来有点复杂。此外,如果想将此扩展到Node.js,那么将不得不编写C++代码并编写原生绑定以在Node.js中访问这些变量。

使用共享文件的方法

另一种方法是创建一个可以被所有程序读取的公共共享文件。每个程序将轮询文件中的数据变化。在这种情况下,会有一个线程或循环寻找文件中的变化。如果在读取时有变化,那么将读取并处理数据。这个想法看起来简单,但轮询并不是软件世界中特别受欢迎的方法。

发布-订阅模型

今天,博客将讨论在Linux上运行的各种程序之间共享数据的发布-订阅模型。这种模型在软件开发中非常适应。然而,在嵌入式领域,通过结合硬件和软件来实现这种模型。

消息流有两个部分:一个是通知变化,另一个是读取数据。这是一种相当成熟的、古老的软件方法。这种方法在一些数据仓库应用程序(DW)中用于数据联合。在这种情况下,首先在目录中放置一个微小的通知文件。这个通知文件将包含有关更改的日期和时间的信息,以及实际数据文件的位置引用,该文件通常非常大。一个守护进程将读取这个通知文件并触发适当的进程来读取大文件。在这里,试图引入相同的概念。但在这种情况下,将触发一个中断,而不是通知文件。

让理解通知和消息流:

    // 每个编程环境都有自己的输出数据容器和一个触发通知的引脚。
    // 每当需要发送数据时,该环境首先将内容推送到容器文件中。
    // 然后该环境将发送一个高信号到其通知引脚。
    

让看看Arduino程序如何与Node.js通信,反之亦然。

    // 假设有一个Arduino程序,它从距离传感器读取数据。
    // 这个距离传感器数据需要发送到Node.js进行进一步处理。
    

假设有一个Arduino程序,它从距离传感器读取数据。这个距离传感器数据需要发送到Node.js进行进一步处理。在这种情况下,Arduino需要一个通知引脚,这只不过是一个GPIO引脚。根据电路图,假设Arduino的这个引脚是#3。每当有新数据时,Arduino将把这个数据写入其自己的通知容器文件到根目录中,例如:

    /arduino_notification_out.txt
    
    int notifier_pin = 3;
    int js_subscriber_pin = 6;

    FILE *fromarduino, *toarduino;
    int i = 0;
    int c;

    void setup() {                
        pinMode(notifier_pin, OUTPUT);
        pinMode(js_subscriber_pin, INPUT_PULLUP);
        attachInterrupt(js_subscriber_pin, subscriberEvent, RISING);
        Serial.begin(9600);
    }

    void subscriberEvent() {
        toarduino = fopen("/js_notification_out.txt", "r");
        if (toarduino) {
            while ((c = getc(toarduino)) != EOF) {
                if (c != 10) {
                    Serial.print((char)c);
                }
            }
            Serial.println();
            Serial.println("----------------");
            fclose(toarduino);
        }  
    }

    void loop() {
        if (i < 50) {
            i = i + 1;
        } else {
            i = 0;   
        }
        
        publishData();
        notifyWorld();  
        delay(1000);
    }

    void publishData() {
        fromarduino = fopen("/arduino_notification_out.txt", "w+");
        fprintf(fromarduino, "[%d]", i);
        fclose(fromarduino);  
    }

    void notifyWorld() {
        digitalWrite(notifier_pin, HIGH);
        delay(200);
        digitalWrite(notifier_pin, LOW);
    }
    
    var mraa = require("mraa");
    var fs = require('fs');

    var subscriber_pin = new mraa.Gpio(1);
    subscriber_pin.dir(mraa.DIR_IN);
    subscriber_pin.isr(mraa.EDGE_RISING, subscriberEvent);

    function subscriberEvent() {
        var contents = fs.readFileSync('/arduino_notification_out.txt').toString();
        console.log("Message from Arduino:" + contents);        
    }

    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);
    }
    

优势与劣势

这种方法避免了不必要的文件变化轮询,也不需要为Node.js开发任何C++绑定来共享数据。编程相对简单。然而,这种方法的一个缺点是,每个数据流方向都需要一对GPIO引脚。如果需要与多个编程环境交换数据,那么可能会用完GPIO。然而,可以通过只使用一对GPIO来实现相同的结果,但将需要管理一个带有适当属性的单个JSON文件,例如事件源、事件数据等。还需要处理文件锁定情况。然而,这是可行的。

英特尔物联网开发者计划

立即开始发明,使用英特尔物联网开发者计划,它提供了知识、工具、开发套件和专家社区,以帮助快速轻松地将创新想法转化为物联网解决方案。

英特尔物联网开发者套件

使用英特尔Edison和Galileo平台的英特尔物联网开发者套件开始构建。这些套件是多功能的、性能优化的和完全集成的端到端物联网解决方案,支持多种编程环境、工具、安全性、云连接和硬件。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485