首页 前端知识 【花雕学编程】Arduino JSON 之带序列号的心跳包发送

【花雕学编程】Arduino JSON 之带序列号的心跳包发送

2025-03-04 11:03:34 前端知识 前端哥 689 325 我要收藏

在这里插入图片描述

Arduino是一个开放源码的电子原型平台,它可以让你用简单的硬件和软件来创建各种互动的项目。Arduino的核心是一个微控制器板,它可以通过一系列的引脚来连接各种传感器、执行器、显示器等外部设备。Arduino的编程是基于C/C++语言的,你可以使用Arduino IDE(集成开发环境)来编写、编译和上传代码到Arduino板上。Arduino还有一个丰富的库和社区,你可以利用它们来扩展Arduino的功能和学习Arduino的知识。

Arduino的特点是:
1、开放源码:Arduino的硬件和软件都是开放源码的,你可以自由地修改、复制和分享它们。
2、易用:Arduino的硬件和软件都是为初学者和非专业人士设计的,你可以轻松地上手和使用它们。
3、便宜:Arduino的硬件和软件都是非常经济的,你可以用很低的成本来实现你的想法。
4、多样:Arduino有多种型号和版本,你可以根据你的需要和喜好来选择合适的Arduino板。
5、创新:Arduino可以让你用电子的方式来表达你的创意和想象,你可以用Arduino来制作各种有趣和有用的项目,如机器人、智能家居、艺术装置等。

在这里插入图片描述
Arduino JSON 的全面详细科学解释

  1. Arduino 概述
    Arduino 是一个开源的电子原型平台,基于易用的硬件和软件。它由硬件(各种型号的 Arduino 板)和软件(Arduino IDE)组成,主要用于快速开发交互式项目。

  2. JSON 概述
    JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于 JavaScript 的一个子集,但独立于语言,广泛用于 Web 应用和 IoT 设备之间的数据交换。

  3. Arduino JSON 的定义
    Arduino JSON 是指在 Arduino 平台上使用 JSON 格式进行数据交换和处理。通过 Arduino JSON 库,开发者可以轻松地在 Arduino 项目中解析和生成 JSON 数据。Arduino JSON是一个用于处理JSON数据的Arduino库,适用于嵌入式C++项目。它支持JSON的序列化和反序列化,能够在有限的内存环境中高效地解析和生成JSON数据。

  4. 关键特点:
    简单的API:Arduino JSON提供了直观的语法,使开发者能够轻松地处理对象和数组。
    序列化和反序列化:支持将JSON数据转换为字符串(序列化)和将字符串转换为JSON数据(反序列化)。
    输入过滤:可以过滤大型输入,只保留与应用程序相关的字段,从而节省内存。
    流式处理:支持从输入流(如串行端口、以太网连接等)中解析JSON数据。
    缩进输出:可以生成紧凑的JSON文档或美化的JSON文档。
    闪存字符串:可以直接使用存储在程序内存中的字符串(PROGMEM)。
    字符串去重:去重JSON文档中的字符串,减少内存消耗。
    隐式或显式转换:支持两种编码风格,可以选择隐式或显式转换。

  5. 主要功能
    数据解析: 从 JSON 字符串中提取数据。
    数据生成: 将数据转换为 JSON 格式的字符串。
    数据交换: 通过 JSON 格式与外部服务进行数据交换。

  6. 技术实现
    库支持: 使用 Arduino JSON 库(如 ArduinoJson)来解析和生成 JSON 数据。
    数据格式: JSON 数据格式包括对象(用花括号 {} 表示)和数组(用方括号 [] 表示),键值对用冒号 : 分隔。
    数据处理: 在 Arduino 上处理 JSON 数据,执行相应操作。

  7. 应用场景
    物联网(IoT): 与云平台进行数据交换。
    Web 服务: 与 Web API 进行数据交互。
    传感器数据: 处理和传输传感器数据。
    配置文件: 存储和读取配置信息。

  8. 开发工具
    Arduino IDE: 编写和上传代码到 Arduino 板。
    ArduinoJson 库: 提供 JSON 解析和生成的库。
    网络模块: 如 ESP8266、ESP32,用于连接互联网。

  9. 优势与挑战
    优势:
    轻量级: JSON 格式简洁,易于解析和生成。
    跨平台: 独立于语言,适用于多种开发环境。
    灵活性: 支持复杂的数据结构。
    挑战:
    内存限制: Arduino 内存有限,处理大 JSON 数据需优化。
    性能限制: 解析和生成 JSON 数据可能占用较多资源。
    数据安全: 需要确保数据完整性和安全性。

  10. 未来发展方向
    优化性能: 提高 JSON 解析和生成的效率。
    扩展功能: 支持更多的 JSON 特性(如 JSON Schema)。
    增强安全性: 提供数据加密和验证机制。

在这里插入图片描述
主要特点

  1. 序列号管理
    唯一性标识:在心跳包中加入序列号是为了给每个心跳包赋予一个唯一的标识。在 Arduino 系统里,通过递增序列号(如从 1 开始,每次发送心跳包时序列号加 1),接收方可以根据序列号准确识别心跳包的先后顺序。例如,服务器端接收到心跳包后,能依据序列号判断是否有心跳包丢失,若序列号不连续,就表明可能存在丢包情况。
    状态追踪:序列号有助于追踪设备的状态和通信历史。对于设备而言,它可以记录自己发送的心跳包序列号;对于接收方,通过对比序列号能了解设备是否正常工作以及通信是否稳定。
  2. JSON 格式封装
    数据结构化:采用 JSON 格式封装心跳包,使得心跳包的数据具有良好的结构化特点。JSON 以键 - 值对的形式组织数据,易于阅读和解析。例如,一个带序列号的心跳包 JSON 数据可能如下:{“sequence_number”: 5, “status”: “normal”, “timestamp”: 1632432000},清晰地展示了序列号、设备状态和时间戳等信息。
    扩展性强:JSON 的灵活性允许在心跳包中方便地添加更多的数据字段。如果后续需要添加设备的温度、电量等信息,只需在 JSON 数据中增加相应的键 - 值对即可,而不需要对整体的通信协议进行大规模修改。
  3. 心跳机制保障
    连接监测:心跳包的主要作用是监测设备与服务器之间的连接状态。Arduino 定时发送心跳包,若服务器在一定时间内未收到心跳包,就可以判断连接可能中断;反之,若能正常接收心跳包,则表明连接正常。序列号的存在进一步增强了这种监测的可靠性,通过序列号的连续性判断通信是否顺畅。
    设备存活检测:对于服务器端来说,持续接收到带序列号的心跳包意味着设备处于存活状态。这对于需要实时掌握设备状态的应用场景非常重要,例如在物联网系统中,确保每个设备都正常运行。

应用场景

  1. 物联网设备管理
    设备监控:在大规模的物联网系统中,有大量的 Arduino 设备分布在不同的位置。服务器需要实时监控这些设备的状态和连接情况。通过接收带序列号的 JSON 心跳包,服务器可以及时发现设备是否离线、通信是否中断等问题,便于及时采取措施进行维护和修复。
    设备调度:根据心跳包中的信息(如设备状态、负载情况等),服务器可以对设备进行合理的调度。例如,当某个设备的负载过高时,服务器可以将部分任务分配给其他设备,以保证整个系统的稳定运行。
  2. 工业自动化
    生产设备监控:在工业生产线上,Arduino 设备可能用于控制和监测各种生产设备。通过发送带序列号的心跳包,生产监控中心可以实时了解设备的运行状态,及时发现设备故障或异常情况,避免生产事故的发生。
    数据同步:心跳包还可以用于设备之间的数据同步。在工业自动化系统中,多个设备需要协同工作,通过心跳包中的序列号和其他信息,设备之间可以保持数据的一致性和同步性。
  3. 智能家居系统
    设备状态反馈:在智能家居系统中,各种智能设备(如智能灯具、智能门锁等)可以通过 Arduino 发送带序列号的心跳包给家庭网关或服务器。用户可以通过手机应用等方式实时了解设备的状态,如设备是否在线、是否正常工作等。
    节能管理:根据心跳包中的信息,智能家居系统可以对设备进行节能管理。例如,当检测到某个设备长时间处于空闲状态时,可以自动调整其工作模式,降低能耗。

需要注意的事项

  1. 序列号管理
    溢出问题:由于序列号通常是一个整数,当发送的心跳包数量足够多时,序列号可能会发生溢出。在设计时,需要考虑序列号的范围和溢出处理机制。例如,可以采用循环序列号,当序列号达到最大值后,重新从最小值开始计数,但需要确保接收方能够正确处理这种循环。
    序列号重置:在某些情况下,如设备重启、通信中断恢复等,可能需要重置序列号。此时,需要确保接收方能够正确识别序列号的重置,并进行相应的处理,避免因序列号重置导致的通信混乱。
  2. JSON 解析与生成
    资源消耗:Arduino 的资源相对有限,JSON 数据的解析和生成会消耗一定的内存和 CPU 资源。在设计时,需要优化 JSON 数据的结构,减少不必要的数据字段,同时选择高效的 JSON 解析和生成库,以降低资源消耗。
    格式错误处理:在发送和接收 JSON 心跳包时,可能会出现格式错误的情况。例如,网络传输错误可能导致 JSON 数据损坏。因此,需要在代码中添加错误处理机制,当解析 JSON 数据出错时,能够进行相应的处理,如记录错误信息、尝试重新解析等。
  3. 心跳包发送频率
    通信带宽:心跳包的发送频率过高会增加通信带宽的消耗,特别是在网络资源有限的情况下,可能会影响其他数据的传输。因此,需要根据实际情况合理设置心跳包的发送频率,在保证连接监测可靠性的前提下,尽量减少通信带宽的占用。
    设备功耗:对于一些电池供电的 Arduino 设备,心跳包的发送频率过高会增加设备的功耗,缩短电池的使用寿命。在设计时,需要综合考虑设备的功耗和通信需求,选择合适的心跳包发送频率。

在这里插入图片描述
1、基本心跳包发送

#include <ESP8266WiFi.h>
#include <ArduinoJson.h>

const char* ssid = "your_SSID"; // WiFi SSID
const char* password = "your_PASSWORD"; // WiFi 密码
const char* serverName = "http://your-server.com/heartbeat"; // 服务器地址

WiFiClient client;
unsigned long previousMillis = 0; // 上次发送时间
const long interval = 5000; // 每5秒发送一次
int sequenceNumber = 0; // 心跳包序列号

void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, password); // 连接 WiFi
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi...");
    }
    Serial.println("Connected to WiFi");
}

void loop() {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;

        // 创建 JSON 对象
        StaticJsonDocument<200> doc;
        doc["sequence"] = sequenceNumber++;
        doc["status"] = "online";
        doc["timestamp"] = millis(); // 发送时间戳

        // 序列化 JSON 对象
        String jsonString;
        serializeJson(doc, jsonString);

        // 发送 HTTP POST 请求
        if (client.connect(serverName, 80)) {
            client.println("POST /heartbeat HTTP/1.1");
            client.println("Host: your-server.com");
            client.println("Content-Type: application/json");
            client.print("Content-Length: ");
            client.println(jsonString.length());
            client.println();
            client.println(jsonString);
            Serial.println("Heartbeat sent: " + jsonString);
        } else {
            Serial.println("Connection failed");
        }
    }
}

2、心跳包带温度数据

#include <ESP8266WiFi.h>
#include <ArduinoJson.h>

const char* ssid = "your_SSID"; // WiFi SSID
const char* password = "your_PASSWORD"; // WiFi 密码
const char* serverName = "http://your-server.com/heartbeat"; // 服务器地址

WiFiClient client;
unsigned long previousMillis = 0; // 上次发送时间
const long interval = 5000; // 每5秒发送一次
int sequenceNumber = 0; // 心跳包序列号

void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, password); // 连接 WiFi
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi...");
    }
    Serial.println("Connected to WiFi");
}

void loop() {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;

        // 模拟温度数据
        float temperature = random(20, 30); // 生成20到30之间的随机温度

        // 创建 JSON 对象
        StaticJsonDocument<200> doc;
        doc["sequence"] = sequenceNumber++;
        doc["status"] = "online";
        doc["temperature"] = temperature;
        doc["timestamp"] = millis(); // 发送时间戳

        // 序列化 JSON 对象
        String jsonString;
        serializeJson(doc, jsonString);

        // 发送 HTTP POST 请求
        if (client.connect(serverName, 80)) {
            client.println("POST /heartbeat HTTP/1.1");
            client.println("Host: your-server.com");
            client.println("Content-Type: application/json");
            client.print("Content-Length: ");
            client.println(jsonString.length());
            client.println();
            client.println(jsonString);
            Serial.println("Heartbeat sent: " + jsonString);
        } else {
            Serial.println("Connection failed");
        }
    }
}

3、心跳包带电量和状态信息

#include <ESP8266WiFi.h>
#include <ArduinoJson.h>

const char* ssid = "your_SSID"; // WiFi SSID
const char* password = "your_PASSWORD"; // WiFi 密码
const char* serverName = "http://your-server.com/heartbeat"; // 服务器地址

WiFiClient client;
unsigned long previousMillis = 0; // 上次发送时间
const long interval = 5000; // 每5秒发送一次
int sequenceNumber = 0; // 心跳包序列号

void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, password); // 连接 WiFi
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi...");
    }
    Serial.println("Connected to WiFi");
}

void loop() {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;

        // 模拟电量数据
        int batteryLevel = random(50, 100); // 生成50到100之间的随机电量

        // 创建 JSON 对象
        StaticJsonDocument<200> doc;
        doc["sequence"] = sequenceNumber++;
        doc["status"] = "online";
        doc["battery"] = batteryLevel;
        doc["timestamp"] = millis(); // 发送时间戳

        // 序列化 JSON 对象
        String jsonString;
        serializeJson(doc, jsonString);

        // 发送 HTTP POST 请求
        if (client.connect(serverName, 80)) {
            client.println("POST /heartbeat HTTP/1.1");
            client.println("Host: your-server.com");
            client.println("Content-Type: application/json");
            client.print("Content-Length: ");
            client.println(jsonString.length());
            client.println();
            client.println(jsonString);
            Serial.println("Heartbeat sent: " + jsonString);
        } else {
            Serial.println("Connection failed");
        }
    }
}

要点解读
心跳包的基本概念:
心跳包是 IoT 设备定时发送到服务器的消息,用于报告其状态和健康状况。在这些示例中,每个设备每隔 5 秒发送一次心跳包。
序列号的使用:
每个心跳包都包含一个序列号 (sequence),用于标识心跳包的发送顺序。这有助于服务器跟踪和检查丢失的心跳包。
JSON 数据格式:
使用 Arduino JSON 库构建 JSON 对象,包含设备状态、温度、电池电量和时间戳等信息。通过 serializeJson() 方法将其转换为字符串,方便发送。
WiFi 连接和 HTTP 请求:
示例中使用 ESP8266 连接到 WiFi 网络,并通过 HTTP POST 请求将心跳包发送到服务器。连接错误会被处理并输出到串口。
模拟数据生成:
示例 2 和示例 3 中生成了随机的温度和电池电量数据。这样的模拟数据通常用于测试,实际应用中可替换为真实的传感器数据。

在这里插入图片描述

4、基础心跳包发送

#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

WiFiUDP udp;
const char* ssid = "YourSSID";
const char* password = "YourPassword";
const char* udpAddress = "192.168.1.100"; // 目标IP地址
const int udpPort = 1234; // 目标端口
unsigned long heartbeatInterval = 5000; // 心跳包发送间隔
unsigned long lastSendTime = 0;
int sequenceNumber = 0; // 心跳包序列号

void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, password); // 连接Wi-Fi
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi...");
    }
    Serial.println("Connected to WiFi");
    udp.begin(udpPort); // 启动UDP
}

void loop() {
    unsigned long currentMillis = millis();
    if (currentMillis - lastSendTime >= heartbeatInterval) {
        lastSendTime = currentMillis;
        sendHeartbeat(); // 发送心跳包
    }
}

void sendHeartbeat() {
    StaticJsonDocument<200> doc;
    doc["sequence"] = sequenceNumber++; // 设置序列号
    doc["status"] = "alive"; // 心跳状态

    String message;
    serializeJson(doc, message); // 序列化为字符串

    udp.beginPacket(udpAddress, udpPort);
    udp.print(message); // 发送心跳包
    udp.endPacket();

    Serial.print("Sent heartbeat: ");
    Serial.println(message); // 打印发送的心跳包
}

要点解读:
Wi-Fi和UDP设置:通过ESP8266连接Wi-Fi并设置UDP通信,确保设备可以发送数据。
心跳包发送机制:使用millis()函数控制心跳包的发送间隔,确保定时发送。
JSON构建:使用Arduino JSON库构建心跳包,包含序列号和状态信息,便于监控。
数据发送:通过UDP发送序列化的JSON字符串,适合低延迟的网络通信场景。
简单易懂:代码结构清晰,适合初学者理解如何发送心跳包。

5、附加传感器数据的心跳包

#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

WiFiUDP udp;
const char* ssid = "YourSSID";
const char* password = "YourPassword";
const char* udpAddress = "192.168.1.100"; // 目标IP地址
const int udpPort = 1234; // 目标端口
unsigned long heartbeatInterval = 5000; // 心跳包发送间隔
unsigned long lastSendTime = 0;
int sequenceNumber = 0; // 心跳包序列号

// 模拟传感器数据
float temperature = 22.5;
float humidity = 60.0;

void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, password); // 连接Wi-Fi
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi...");
    }
    Serial.println("Connected to WiFi");
    udp.begin(udpPort); // 启动UDP
}

void loop() {
    unsigned long currentMillis = millis();
    if (currentMillis - lastSendTime >= heartbeatInterval) {
        lastSendTime = currentMillis;
        sendHeartbeat(); // 发送心跳包
    }
}

void sendHeartbeat() {
    StaticJsonDocument<300> doc;
    doc["sequence"] = sequenceNumber++; // 设置序列号
    doc["status"] = "alive"; // 心跳状态
    doc["temperature"] = temperature; // 传感器数据
    doc["humidity"] = humidity; // 传感器数据

    String message;
    serializeJson(doc, message); // 序列化为字符串

    udp.beginPacket(udpAddress, udpPort);
    udp.print(message); // 发送心跳包
    udp.endPacket();

    Serial.print("Sent heartbeat: ");
    Serial.println(message); // 打印发送的心跳包
}

要点解读:
传感器数据集成:在心跳包中添加温度和湿度数据,增强监控信息的丰富性。
JSON扩展:通过Arduino JSON库轻松扩展心跳包的内容,适应不同的传感器数据需求。
UDP通信:依然使用UDP进行数据发送,适合快速传输和低延迟的场景。
定时发送:使用millis()函数实现定时机制,确保每隔一定时间发送一次心跳包。
易于理解:代码结构清晰,适合对传感器数据发送有基本了解的开发者。

6、接收和解析心跳包

#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

WiFiUDP udp;
const char* ssid = "YourSSID";
const char* password = "YourPassword";
const int udpPort = 1234; // 本地端口
unsigned long lastReceiveTime = 0;

void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, password); // 连接Wi-Fi
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi...");
    }
    Serial.println("Connected to WiFi");
    udp.begin(udpPort); // 启动UDP
}

void loop() {
    int packetSize = udp.parsePacket();
    if (packetSize) {
        char buffer[255];
        int n = udp.read(buffer, 255); // 读取数据
        buffer[n] = 0; // 添加字符串结束符
        Serial.print("Received packet: ");
        Serial.println(buffer); // 打印接收到的心跳包

        parseHeartbeat(buffer); // 解析心跳包
        lastReceiveTime = millis(); // 更新接收时间
    }
}

void parseHeartbeat(const char* message) {
    StaticJsonDocument<300> doc;
    DeserializationError error = deserializeJson(doc, message); // 解析JSON

    if (error) {
        Serial.print("deserializeJson() failed: ");
        Serial.println(error.f_str());
        return;
    }

    // 提取数据
    int sequence = doc["sequence"];
    const char* status = doc["status"];
    float temperature = doc["temperature"];
    float humidity = doc["humidity"];

    Serial.print("Sequence: ");
    Serial.println(sequence);
    Serial.print("Status: ");
    Serial.println(status);
    Serial.print("Temperature: ");
    Serial.println(temperature);
    Serial.print("Humidity: ");
    Serial.println(humidity);
}

要点解读:
接收UDP数据:通过UDP协议接收心跳包,展示如何处理网络数据。
JSON解析:使用deserializeJson()解析收到的心跳包,提取序列号、状态和传感器数据。
有效的错误处理:在解析过程中检查错误,确保系统的健壮性,避免崩溃。
信息输出:将解析出的数据打印到串口,方便开发者监测和调试。
结构清晰:代码结构简洁,适合学习如何接收和解析UDP数据包。

总结
以上示例展示了如何使用Arduino JSON库发送和接收带序列号的心跳包。关键要点包括:
Wi-Fi和UDP设置:通过ESP8266连接Wi-Fi并设置UDP通信,确保设备可以发送和接收数据。
心跳包机制:使用定时机制控制心跳包的发送频率,确保实时监控。
JSON构建和解析:使用Arduino JSON库构建和解析心跳包内容,灵活扩展数据格式。
错误处理和输出:通过有效的错误处理和串口输出,增强用户体验和调试能力。
易于扩展:代码结构清晰,便于根据实际需求添加更多功能或数据字段。

注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。

在这里插入图片描述

转载请注明出处或者链接地址:https://www.qianduange.cn//article/22610.html
标签
评论
发布的文章

图论-腐烂的橘子

2025-03-04 11:03:06

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!