Hi3861 OpenHarmony嵌入式应用入门--华为 IoTDA 设备接入

news2025/3/1 11:46:45

华为云物联网平台(IoT 设备接入云服务)提供海量设备的接入和管理能力,可以将自己的 IoT 设备 联接到华为云,支撑设备数据采集上云和云端下发命令给设备进行远程控制,配合华为云物联网平台的服 务实现设备与设备之间的控制,设备与物联网平台之间的数据信息交互。

在写代码之前先准备好华为云的环境。

注册华为云账号,这里就不介绍了,有手机就行,需要进行实名认证。

在控制台选择北京四,因为其他的可能需要企业才能使用,作为个人开发者就用北京四吧。

创建设备实例。

能看到设备实例的信息

我们要是用的接入方式-mqtt

通过接入地址查询IP。

记住这个IP地址。

创建新产品

注册设备

注意:生成好的设备 ID 和设备秘钥一定到妥善保管,只生成这一份。

创建产品模型

填写服务ID和服务类型

在此服务下“添加属性”,用于上传开发板上的数据,以风扇为例,其他的传感器也是类似的方法。

创建了两个

在此服务下“添加命令”,用于控制开发板上可以控制的设备,以风扇为例,其他的传感器也是类似的方法。

根据设备信息,生成用户名和密码

1.打开由华为云提供的生成用户名和密码的网址,进行生成

Huaweicloud IoTDA Mqtt ClientId Generator

2.填写生成好的设备ID和设备秘钥,点击按钮,生成用户名和密码

注意:下面的图片提供了方法。

这两个就是刚刚注册设备时候要求保存的,应该被保存在一个txt中了。

3.将生成好的信息(ClientD、Usemame、Password),修改文件“D:\DevEcoProjects\test\src\vendor\hqyj\fs_hi3861\demo\cloud_01_HuaWei_IoTDA\cloud_huawei_iotda_example.c”,下面内容直接替换。

ip用刚刚查询的mqtt地址。

数据结构参考设备属性上报_设备接入 IoTDA (huaweicloud.com)

向云端设置属性的数据格式如下所示:

{
    "services": [{
            "service_id": "attribute",
            "properties": {
                "status": "ON",
                "color": 60
            }
        }
    ]
}

代码编写

修改D:\DevEcoProjects\test\src\vendor\rtplay\rt_hi3861\demo\BUILD.gn文件

# Copyright (c) 2023 Beijing HuaQing YuanJian Education Technology Co., Ltd
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#    http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License. 

import("//build/lite/config/component/lite_component.gni")

lite_component("demo") {
  features = [
    #"base_00_helloworld:base_helloworld_example",
    #"base_01_led:base_led_example",
    #"base_02_loopkey:base_loopkey_example",
    #"base_03_irqkey:base_irqkey_example",
    #"base_04_adc:base_adc_example",
    #"base_05_pwm:base_pwm_example",
    #"base_06_ssd1306:base_ssd1306_example",
    #"kernel_01_task:kernel_task_example",
    #"kernel_02_timer:kernel_timer_example",
    #"kernel_03_event:kernel_event_example",
    #"kernel_04_mutex:kernel_mutex_example",
    #"kernel_05_semaphore_as_mutex:kernel_semaphore_as_mutex_example",
    #"kernel_06_semaphore_for_sync:kernel_semaphore_for_sync_example",
    #"kernel_07_semaphore_for_count:kernel_semaphore_for_count_example",
    #"kernel_08_message_queue:kernel_message_queue_example",
    #"wifi_09_hotspot:wifi_hotspot_example",
    #"wifi_10_sta:wifi_sta_example",
    #"tcp_11_server:tcp_server_example",
    #"tcp_12_client:tcp_client_example",
    #"udp_13_server:udp_server_example",
    #"udp_14_client:udp_client_example",
    #"network_15_mqtt:network_mqtt_example",
    #"network_16_sntp:network_sntp_example",
    #"network_17_httpd:network_httpd_example",
    "cloud_18_HuaWei_IoTDA:cloud_huawei_iotda_example",
  ]
}

创建D:\DevEcoProjects\test\src\vendor\rtplay\rt_hi3861\demo\cloud_18_HuaWei_IoTDA文件夹

文件夹中创建D:\DevEcoProjects\test\src\vendor\rtplay\rt_hi3861\demo\cloud_18_HuaWei_IoTDA\BUILD.gn文件

# Copyright (c) 2023 Beijing HuaQing YuanJian Education Technology Co., Ltd
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#    http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License. 

static_library("cloud_huawei_iotda_example") {
    sources = [
        "cloud_huawei_iotda_example.c",
        "network_mqtt.c",
        "wifi_connecter.c",

        "//third_party/paho.mqtt.embedded-c/MQTTPacket/src/MQTTConnectClient.c",
        "//third_party/paho.mqtt.embedded-c/MQTTPacket/src/MQTTConnectServer.c",
        "//third_party/paho.mqtt.embedded-c/MQTTPacket/src/MQTTDeserializePublish.c",
        "//third_party/paho.mqtt.embedded-c/MQTTPacket/src/MQTTFormat.c",
        "//third_party/paho.mqtt.embedded-c/MQTTPacket/src/MQTTPacket.c",
        "//third_party/paho.mqtt.embedded-c/MQTTPacket/src/MQTTSerializePublish.c",
        "//third_party/paho.mqtt.embedded-c/MQTTPacket/src/MQTTSubscribeClient.c",
        "//third_party/paho.mqtt.embedded-c/MQTTPacket/src/MQTTSubscribeServer.c",
        "//third_party/paho.mqtt.embedded-c/MQTTPacket/src/MQTTUnsubscribeServer.c",
        "//third_party/paho.mqtt.embedded-c/MQTTPacket/src/MQTTUnsubscribeClient.c",

    ]

    include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/kal/cmsis",
        "//base/iot_hardware/peripheral/interfaces/kits",
        "//foundation/communication/wifi_lite/interfaces/wifiservice",
        "//third_party/paho.mqtt.embedded-c/MQTTPacket/src",
        "//third_party/cJSON",
    ]
}

文件夹中创建D:\DevEcoProjects\test\src\vendor\rtplay\rt_hi3861\demo\cloud_18_HuaWei_IoTDA\wifi_connecter.h文件,该头文件包含wifi连接的宏。文件同network_16_sntp\wifi_connecter.h

文件夹中创建D:\DevEcoProjects\test\src\vendor\rtplay\rt_hi3861\demo\cloud_18_HuaWei_IoTDA\wifi_connecter.c文件,文件同network_16_sntp\wifi_connecter.c

文件夹中创建D:\DevEcoProjects\test\src\vendor\rtplay\rt_hi3861\demo\cloud_18_HuaWei_IoTDA\network_mqtt.h文件,文件同network_15_mqtt\network_mqtt.h文件,文件主要包含mqtt的函数。

文件夹中创建D:\DevEcoProjects\test\src\vendor\rtplay\rt_hi3861\demo\cloud_18_HuaWei_IoTDA\network_mqtt.c文件,文件同network_15_mqtt\network_mqtt.h文件,文件主要包含mqtt的函数实现。

文件夹中创建D:\DevEcoProjects\test\src\vendor\rtplay\rt_hi3861\demo\cloud_18_HuaWei_IoTDA\cloud_huawei_iotda_example.c文件

/*
 * Copyright (c) 2023 Beijing HuaQing YuanJian Education Technology Co., Ltd
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "cJSON.h"
#include "cmsis_os2.h"
#include "hi_gpio.h"
#include "hi_io.h"
#include "iot_errno.h"
#include "iot_gpio.h"
#include "iot_pwm.h"
#include "network_mqtt.h"
#include "ohos_init.h"
#include "wifi_connecter.h"

// 设备密码 fs12345678
// 设备ID
#define DEVICE_ID "668651baa559ef622666a845_hi3861"
// MQTT客户端ID
#define MQTT_CLIENT_ID "668651baa559ef622666a845_hi3861_0_0_2024070407"
// MQTT用户名
#define MQTT_USER_NAME "668651baa559ef622666a845_hi3861"
// MQTT密码
#define MQTT_PASS_WORD "d5b00ad95964f8016c9e6f79c8269265720d770acd7e97bf73cf30a339b04997"
// 华为云平台的IP地址
#define SERVER_IP_ADDR "117.78.5.125"
// 华为云平台的IP端口号
#define SERVER_IP_PORT 1883
// 订阅 接收控制命令的主题
#define MQTT_TOPIC_SUB_COMMANDS "$oc/devices/%s/sys/commands/#"
// 发布 成功接收到控制命令后的主题
#define MQTT_TOPIC_PUB_COMMANDS_REQ "$oc/devices/%s/sys/commands/response/request_id=%s"
#define MALLOC_MQTT_TOPIC_PUB_COMMANDS_REQ "$oc/devices//sys/commands/response/request_id="

// 发布 设备属性数据的主题
#define MQTT_TOPIC_PUB_PROPERTIES "$oc/devices/%s/sys/properties/report"
#define MALLOC_MQTT_TOPIC_PUB_PROPERTIES "$oc/devices//sys/properties/report"

#define TASK_STACK_SIZE (1024 * 10)
#define MsgQueueObjectNumber 16  // 定义消息队列对象的个数
typedef struct message_sensorData {
    uint8_t status;  // LED灯当前的状态
    uint8_t color;   // 颜色值
} msg_sensorData_t;
msg_sensorData_t sensorData = {0};   // 传感器的数据
osThreadId_t mqtt_send_task_id;      // mqtt 发布数据任务ID
osThreadId_t mqtt_recv_task_id;      // mqtt 接收数据任务ID
osThreadId_t key_detection_task_id;  // 按键检测任务ID
#define MQTT_SEND_TASK_TIME 10       // s
#define MQTT_RECV_TASK_TIME 1        // s
#define TASK_INIT_TIME 2             // s
#define DISPLAY_BUFF_MAX 64
#define MQTT_DATA_MAX 256

#define RED_LED_PIN_NAME HI_IO_NAME_GPIO_10
#define RED_LED_PIN_FUNCTION WIFI_IOT_IO_FUNC_GPIO_10_GPIO
#define GREEN_LED_PIN_NAME HI_IO_NAME_GPIO_2
#define GREEN_LED_PIN_FUNCTION WIFI_IOT_IO_FUNC_GPIO_2_GPIO
#define BLUE_LED_PIN_NAME HI_IO_NAME_GPIO_7
#define BLUE_LED_PIN_FUNCTION WIFI_IOT_IO_FUNC_GPIO_7_GPIO
#define PWM0_PORT_NUM (0)
#define PWM1_PORT_NUM (1)
#define PWM2_PORT_NUM (2)
#define PWM_FREQ_DIVITION 64000

#define KEY1 HI_IO_NAME_GPIO_6  // 对应按键key1
#define KEY2 HI_IO_NAME_GPIO_5  // 对应按键key2
#define TASK_DELAY_TIME (200 * 1000)

static int g_netId = -1;
uint8_t publish_topic[MQTT_DATA_MAX] = {0};
uint8_t mqtt_data[MQTT_DATA_MAX] = {0};

unsigned short duty0 = 0, duty1 = 0, duty2 = 0;  // pwm占空比记录变量
hi_gpio_value val1, val1_last, val2, val2_last;  // GPIO的状态值

/**
 * @brief 灯光开关
 */
void led_switch(uint8_t status)
{
    if (status == 1) {
        if (duty0 == 0) duty0 = 100;
        if (duty1 == 0) duty1 = 100;
        if (duty2 == 0) duty2 = 100;
        IoTPwmStart(PWM0_PORT_NUM, duty0, PWM_FREQ_DIVITION);
        IoTPwmStart(PWM1_PORT_NUM, duty1, PWM_FREQ_DIVITION);
        IoTPwmStart(PWM2_PORT_NUM, duty2, PWM_FREQ_DIVITION);
    } else {
        IoTPwmStart(PWM0_PORT_NUM, 0, PWM_FREQ_DIVITION);
        IoTPwmStart(PWM1_PORT_NUM, 0, PWM_FREQ_DIVITION);
        IoTPwmStart(PWM2_PORT_NUM, 0, PWM_FREQ_DIVITION);
    }
}

/**
 * @brief 设置灯光颜色
 */
void led_color(uint8_t r, uint8_t g, uint8_t b)
{
    printf("led_color: %d %d %d\r\n", r, g, b);
    IoTPwmStart(PWM0_PORT_NUM, b, PWM_FREQ_DIVITION);
    IoTPwmStart(PWM1_PORT_NUM, r, PWM_FREQ_DIVITION);
    IoTPwmStart(PWM2_PORT_NUM, g, PWM_FREQ_DIVITION);
}

/**
 * @brief 组JSON数据
 */
int Packaged_json_data(void)
{
    cJSON *root = NULL, *array = NULL, *services = NULL;
    cJSON *properties = NULL;
    int ret = 0;

    // 组JSON数据
    root = cJSON_CreateObject();  // 创建一个对象
    services = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "services", services);
    array = cJSON_CreateObject();
    cJSON_AddStringToObject(array, "service_id", "attribute");
    properties = cJSON_CreateObject();
    cJSON_AddItemToObject(array, "properties", properties);
    cJSON_AddStringToObject(properties, "status", sensorData.status ? "ON" : "OFF");
    cJSON_AddNumberToObject(properties, "color", (int)sensorData.color);
    cJSON_AddItemToArray(services, array);  // 将对象添加到数组中

    /* 格式化打印创建的带数组的JSON对象 */
    char *str_print = cJSON_PrintUnformatted(root);
    if (str_print != NULL) {
        // printf("%s\n", str_print);
        if (strcpy_s(mqtt_data, strlen(str_print) + 1, str_print) == 0) {
            ret = 0;
        } else {
            ret = -1;
        }
        cJSON_free(str_print);
    } else {
        ret = -1;
    }
    if (root != NULL) {
        cJSON_Delete(root);
    } else {
        ret = -1;
    }
    properties = str_print = root = array = services = NULL;

    return ret;
}

/**
 * @brief MQTT  上报消息
 */
void mqtt_client_pub(void)
{
    // 组Topic
    memset_s(publish_topic, MQTT_DATA_MAX, 0, MQTT_DATA_MAX);
    if (sprintf_s(publish_topic, MQTT_DATA_MAX, MQTT_TOPIC_PUB_PROPERTIES, DEVICE_ID) > 0) {
        // 组JSON数据
        Packaged_json_data();
        // 发布消息
        MQTTClient_pub(publish_topic, mqtt_data, strlen((char *)mqtt_data));
    }
}

/**
 * @brief MQTT  周期发布消息任务
 */
void mqtt_send_task(void)
{
    while (1) {
        mqtt_client_pub();
        sleep(MQTT_SEND_TASK_TIME);
    }
}

int get_jsonData_value(const cJSON *const object, uint8_t *value)
{
    cJSON *json_value = NULL;
    int ret = -1;
    json_value = cJSON_GetObjectItem(object, "value");
    if (json_value) {
        if (!strcmp(json_value->valuestring, "ON")) {
            *value = 1;
            json_value = NULL;
            ret = 0;  // 0为成功
        } else if (!strcmp(json_value->valuestring, "OFF")) {
            *value = 0;
            json_value = NULL;
            ret = 0;
        }
    }
    json_value = NULL;
    return ret;  // -1为失败
}

/**
 * @brief 解析JSON数据
 */
int Parsing_json_data(const char *payload)
{
    cJSON *root = NULL, *command_name = NULL, *paras = NULL, *value = NULL;
    cJSON *red = NULL, *green = NULL, *blue = NULL;
    int ret_code = 1;
    root = cJSON_Parse((const char *)payload);
    if (root) {
        // 解析JSON数据
        command_name = cJSON_GetObjectItem(root, "command_name");
        paras = cJSON_GetObjectItem(root, "paras");
        if (command_name) {
            if (!strcmp(command_name->valuestring, "led")) {
                ret_code = get_jsonData_value(paras, &sensorData.status);
                // 操作硬件
                led_switch(sensorData.status);
            } else if (!strcmp(command_name->valuestring, "RGB")) {
                red = cJSON_GetObjectItem(paras, "red");
                green = cJSON_GetObjectItem(paras, "green");
                blue = cJSON_GetObjectItem(paras, "blue");
                led_color(red->valueint, green->valueint, blue->valueint);
                ret_code = 0;  // 0为成功
            }
        }
    }
    cJSON_Delete(root);
    root = command_name = paras = value = red = green = blue = NULL;
    return ret_code;
}

// 向云端发送返回值
void send_cloud_request_code(const char *request_id, int ret_code, int request_len)
{
    char *request_topic =
        (char *)malloc(strlen(MALLOC_MQTT_TOPIC_PUB_COMMANDS_REQ) + strlen(DEVICE_ID) + request_len + 1);
    if (request_topic != NULL) {
        memset_s(request_topic, strlen(DEVICE_ID) + strlen(MALLOC_MQTT_TOPIC_PUB_COMMANDS_REQ) + request_len + 1, 0,
                 strlen(DEVICE_ID) + strlen(MALLOC_MQTT_TOPIC_PUB_COMMANDS_REQ) + request_len + 1);
        if (sprintf_s(request_topic, strlen(DEVICE_ID) + strlen(MALLOC_MQTT_TOPIC_PUB_COMMANDS_REQ) + request_len + 1,
                      MQTT_TOPIC_PUB_COMMANDS_REQ, DEVICE_ID, request_id) > 0) {
            if (ret_code == 0) {
                MQTTClient_pub(request_topic, "{\"result_code\":0}", strlen("{\"result_code\":0}"));
            } else if (ret_code == 1) {
                MQTTClient_pub(request_topic, "{\"result_code\":1}", strlen("{\"result_code\":1}"));
            }
        }
        free(request_topic);
        request_topic = NULL;
    }
}
/**
 * @brief MQTT接收数据的回调函数
 */
int8_t mqttClient_sub_callback(unsigned char *topic, unsigned char *payload)
{
    if ((topic == NULL) || (payload == NULL)) {
        return -1;
    } else {
        printf("topic: %s\r\n", topic);
        printf("payload: %s\r\n", payload);

        // 提取出topic中的request_id
        char request_id[50] = {0};
        int ret_code = 1;  // 1为失败
        if (0 == strcpy_s(request_id, sizeof(request_id),
                          topic + strlen(DEVICE_ID) + strlen("$oc/devices//sys/commands/request_id="))) {
            printf("request_id: %s\r\n", request_id);
            // 解析JSON数据
            ret_code = Parsing_json_data(payload);
            send_cloud_request_code(request_id, ret_code, sizeof(request_id));
        }
    }
    return 0;
}

/**
 * @brief MQTT  接收消息任务
 */
void mqtt_recv_task(void)
{
    while (1) {
        MQTTClient_sub();
        sleep(MQTT_RECV_TASK_TIME);
    }
}

/**
 * @brief 按键检测任务
 */
void key_detection_task(void)
{
    while (1) {
        hi_gpio_get_input_val(KEY1, &val1);  // 获取GPIO引脚的状态
        if (val1 != val1_last) {
            // 当GPIO状态改变的时候, 打印输出
            printf("key1Value: %s\r\n", val1 ? "HI_GPIO_VALUE_1" : "HI_GPIO_VALUE_0");
            val1_last = val1;
            if (!val1_last) {  // 按键被按下
                if (sensorData.status) {
                    sensorData.status = 0;
                    led_switch(sensorData.status);
                    mqtt_client_pub();
                } else {
                    sensorData.status = 1;
                    led_switch(sensorData.status);
                    mqtt_client_pub();
                }
            }
            printf("key1Value: end\r\n");
        }
        hi_gpio_get_input_val(KEY2, &val2);  // 获取GPIO引脚的状态
        if (val2 != val2_last) {
            // 当GPIO状态改变的时候, 打印输出
            printf("key2Value: %s\r\n", val2 ? "HI_GPIO_VALUE_1" : "HI_GPIO_VALUE_0");
            val2_last = val2;
        }

        // 200ms一检测
        usleep(TASK_DELAY_TIME);  // 200ms sleep
    }
}

static void network_wifi_mqtt_example(void)
{
    // 外设的初始化
    // 灯光pwm初始化
    hi_io_set_func(RED_LED_PIN_NAME, HI_IO_FUNC_GPIO_10_PWM1_OUT);
    hi_io_set_func(GREEN_LED_PIN_NAME, HI_IO_FUNC_GPIO_2_PWM2_OUT);
    hi_io_set_func(BLUE_LED_PIN_NAME, HI_IO_FUNC_GPIO_7_PWM0_OUT);
    IoTPwmInit(PWM0_PORT_NUM);
    IoTPwmInit(PWM1_PORT_NUM);
    IoTPwmInit(PWM2_PORT_NUM);

    // 按键初始化
    hi_gpio_init();                                // GPIO初始化
    hi_io_set_pull(KEY1, HI_IO_PULL_UP);           // 设置GPIO上拉
    hi_io_set_func(KEY1, HI_IO_FUNC_GPIO_6_GPIO);  // 设置IO16为GPIO功能
    hi_gpio_set_dir(KEY1, HI_GPIO_DIR_IN);         // 设置GPIO为输入模式
    hi_io_set_pull(KEY2, HI_IO_PULL_UP);           // 设置GPIO上拉
    hi_io_set_func(KEY2, HI_IO_FUNC_GPIO_5_GPIO);  // 设置IO15为GPIO功能
    hi_gpio_set_dir(KEY2, HI_GPIO_DIR_IN);         // 设置GPIO为输入模式

    p_MQTTClient_sub_callback = &mqttClient_sub_callback;

    // 连接WiFi
    WifiDeviceConfig config = {0};

    // 准备AP的配置参数
    // strcpy(config.ssid, PARAM_HOTSPOT_SSID);
    // strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK);
    strcpy_s(config.ssid, WIFI_MAX_SSID_LEN, PARAM_HOTSPOT_SSID);
    strcpy_s(config.preSharedKey, WIFI_MAX_KEY_LEN, PARAM_HOTSPOT_PSK);
    config.securityType = PARAM_HOTSPOT_TYPE;

    g_netId = ConnectToHotspot(&config);
    printf("netId = %d\r\n", g_netId);
    sleep(TASK_INIT_TIME);

    // 连接MQTT服务器
    if (MQTTClient_connectServer(SERVER_IP_ADDR, SERVER_IP_PORT) != WIFI_SUCCESS) {
        printf("[error] mqttClient_connectServer\r\n");
    }
    sleep(TASK_INIT_TIME);

    // 初始化MQTT客户端
    if (MQTTClient_init(MQTT_CLIENT_ID, MQTT_USER_NAME, MQTT_PASS_WORD) != WIFI_SUCCESS) {
        printf("[error] mqttClient_init\r\n");
    }
    sleep(TASK_INIT_TIME);

    // 订阅主题
    if (MQTTClient_subscribe(MQTT_TOPIC_SUB_COMMANDS) != WIFI_SUCCESS) {
        printf("[error] mqttClient_subscribe\r\n");
    }
    sleep(TASK_INIT_TIME);

    mqtt_client_pub();  // 连接后上报一次消息

    //  创建线程
    osThreadAttr_t options;
    options.name = "mqtt_send_task";
    options.attr_bits = 0;
    options.cb_mem = NULL;
    options.cb_size = 0;
    options.stack_mem = NULL;
    options.stack_size = TASK_STACK_SIZE;
    options.priority = osPriorityNormal;
    mqtt_send_task_id = osThreadNew((osThreadFunc_t)mqtt_send_task, NULL, &options);
    if (mqtt_send_task_id != NULL) {
        printf("ID = %d, Create mqtt_send_task_id is OK!\r\n", mqtt_send_task_id);
    }

    options.name = "mqtt_recv_task";
    options.stack_size = TASK_STACK_SIZE;
    mqtt_recv_task_id = osThreadNew((osThreadFunc_t)mqtt_recv_task, NULL, &options);
    if (mqtt_recv_task_id != NULL) {
        printf("ID = %d, Create mqtt_recv_task_id is OK!\r\n", mqtt_recv_task_id);
    }

    options.name = "key_detection_task";
    options.stack_size = TASK_STACK_SIZE;
    key_detection_task_id = osThreadNew((osThreadFunc_t)key_detection_task, NULL, &options);
    if (key_detection_task_id != NULL) {
        printf("ID = %d, Create key_detection_task is OK!\r\n", key_detection_task_id);
    }
}
SYS_RUN(network_wifi_mqtt_example);

其中有三个任务,分别是mqtt的周期上报,模拟温度计类的需要定时上报的功能,mqtt接收任务,用来处理服务器下发的控制命令,还有一个任务用来检测按键,当key1按下时切换灯的开关。

使用build,编译成功后,使用upload进行烧录。

这是可以从设备信息中看到设备在线,并且能看到设备上报的状态。

通过服务器下发设备控制命令,举例控制设备灯开关。

设备收到服务器发来的数据。

同时服务器也会更新设备上报的状态。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1917860.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL的约束键多表查询

约束 概念 概念&#xff1a;约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。目的&#xff1a;保证数据中数据的正确、有效性和完整性。 外键约束 概念 ​ 外键用来让两张表的数据之间建立连接&#xff0c;从而保证数据的一致性和完整性。 注意&#x…

钉钉扫码登录第三方

钉钉文档 实现登录第三方网站 - 钉钉开放平台 (dingtalk.com) html页面 将html放在 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>登录</title>// jquery<script src"http://code.jqu…

PHP趣味测评微信小程序开发搭建趣味测评流量主变现系统

趣味测评微信小程序&#xff1a;开发搭建&#xff0c;乐在其中&#x1f389; &#x1f31f;【开篇&#xff1a;探索趣味测评的魅力】&#x1f31f; 你是否厌倦了千篇一律的问卷调查&#xff1f;想要来点不一样的互动体验&#xff1f;那么&#xff0c;趣味测评微信小程序绝对是…

为什么大多数过来人还是建议你考一本HCIE

HCIE认证是华为推出的高级网络工程师认证。 然而&#xff0c;对于是否值得考取HCIE&#xff0c;许多人有不同的看法。 有些人质疑它的价值&#xff0c;但也有很多过来人强烈推荐。 今天探讨一番。为什么尽管有质疑声&#xff0c;许多经验丰富的老网工还是建议你考一本HCIE。 01…

自动清理群晖nas中的.TMP文件

公司某个部门需要使用群晖nas共享盘&#xff0c;对人员的相关权限有要求&#xff0c;部分人员对于某个文件夹&#xff0c;以及里面的文件不能有删除权限&#xff0c;在用户被剥夺了删除权限后&#xff0c;造成了一个问题&#xff0c;那就是这些没有删除权限的人员&#xff0c;在…

精益创业方法论在创业实践中的应用:以乔布斯视角探索创新与变革的艺术——张驰咨询

史蒂夫乔布斯以其非凡的愿景、不懈的迭代精神与对产品极致的追求&#xff0c;成为无数创业者心中的灯塔。本文将借鉴乔布斯的创新思维与精益创业方法论相结合&#xff0c;构建一套融合理论与实践的深度框架&#xff0c;旨在指导创业者在不确定的市场环境中高效探索、快速验证并…

jvm 07 GC算法,内存池,对象内存分配

01 垃圾判断算法 1.1引用计数算法 最简单的垃圾判断算法。在对象中添加一个属性用于标记对象被引用的次数&#xff0c;每多一个其他对象引用&#xff0c;计数1&#xff0c; 当引用失效时&#xff0c;计数-1&#xff0c;如果计数0&#xff0c;表示没有其他对象引用&#xff0c;…

Springboot 设置个性化banner

在 Spring Boot 中自定义 banner 的方法有几种&#xff0c;可以通过以下步骤来实现&#xff1a; 1、使用文本文件作为 banner 在 src/main/resources 目录下创建一个名为 banner.txt 的文件。 编辑这个文件&#xff0c;输入想要显示的文本。确保文本中包含换行符和空格…

【排序 - 插入排序 和 希尔排序】

插入排序&#xff08;Insertion Sort&#xff09;是一种简单直观的排序算法&#xff0c;它的工作原理是逐步构建有序序列。在排序过程中&#xff0c;它将未排序的元素逐个插入到已排序的部分中&#xff0c;从而在每次插入时扩展已排序序列的长度。 原理介绍 插入排序的基本思…

mindspore打卡20天之Shufflenet图像分类

ShuffleNet图像分类 当前案例不支持在GPU设备上静态图模式运行&#xff0c;其他模式运行皆支持。 ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一样主要应用在移动端&#xff0c;所以模型的设计目标就是利用有…

浅谈后置处理器之边界提取器

浅谈后置处理器之边界提取器 边界提取器&#xff08;Boundary Extractor&#xff09;作为一种常用的后置处理器&#xff0c;主要用于从服务器响应中提取特定内容&#xff0c;这些内容可以是文本、变量或cookies等&#xff0c;以便于后续请求中重用。本文档将详细介绍如何在JMe…

高阶面试-dubbo的学习

SPI机制 SPI&#xff0c;service provider interface&#xff0c;服务发现机制&#xff0c;其实就是把接口实现类的全限定名配置在文件里面&#xff0c;然后通过加载器ServiceLoader去读取配置加载实现类&#xff0c;比如说数据库驱动&#xff0c;我们把mysql的jar包放到项目的…

人员定位系统可以用在哪些方面?为什么这么受欢迎?

人员定位系统大家都不陌生&#xff0c;它也随着科技的发展变得越来越高端、功能也越来越完善了。从一开始的对讲机沟通到后来的蓝牙定位等等&#xff0c;定位系统的精准度越来越高不说&#xff0c;续航能力也越来也强&#xff0c;以往比较单一和迷你的汽车定位产品都能达到一年…

《故障复盘 · 记一次事务用法错误导致的大量锁表问题》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

VS2019使用C#写窗体程序技巧(1)

1、打开串口 private void button1_Click(object sender, EventArgs e){myPort cmb1.Text;mybaud Convert.ToInt32(cmb2.Text, 10);databit 8;parity Parity.None;stopBit StopBits.One;textBox9.Text "2";try{sp new SerialPort(myPort, mybaud, parity, dat…

蓝卓创始人褚健:工业互联网平台技术赋能中小企业数字化转型的实施路径

工业4.0是由工业软件驱动的工业革命&#xff0c;与传统厚重的工业软件不同&#xff0c;supOS就好比嵌入工厂的“安卓系统”。如果把一个工厂当作一台手机&#xff0c;因为有安卓或苹果开放的操作系统&#xff0c;吸引了全世界聪明的人开发了大量APP供人们使用&#xff0c;手机才…

java:将集合中的数据放到文件中

代码实现目标&#xff1a; 将集合中的数据写道文件中通过字符缓冲输出流实现 代码展示 public static void main(String[] args) throws IOException {//创建ArrayList集合ArrayList<Student> array new ArrayList<>();//创建学生对象Student s1 new Student(&…

昇思25天学习打卡营第14天|基于MindSpore的红酒分类实验

背景介绍 本文主要介绍使用MindSpore在部分wine数据集上进行KNN实验。 K近邻算法原理 K近邻算法&#xff08;K-Nearest-Neighbor, KNN&#xff09;是一种用于分类和回归的非参数统计方法&#xff0c;最初由 Cover和Hart于1968年提出(Cover等人,1967)&#xff0c;是机器学习最…

IPv4到IPv6的转换

为何要向IPv6过渡&#xff1a; 随着互联网的飞速发展&#xff0c;越来越多的设备接入网络&#xff0c;IPv4地址资源日益匮乏&#xff0c;已无法满足不断增长的需求。 IP地址定位&#xff1a;IP数据云 - 免费IP地址查询 - 全球IP地址定位平台 IPv6的出现为解决这一问题提供了…

基于OOB的NFTL设计

Nand flash设备存储结构示例 上图是一个1056Mb的存储设备。页面用户数据 空间是2KB&#xff0c;OOB是64字节&#xff0c;每个块 包含64个页面&#xff0c;一共 1024个块。用户数据 空间是128MB&#xff0c;OOB空间是4MB。 每个页面的OOB保留一个字节 用于坏块 标识 &#xff0c…