风云再起 · 2022年02月13日

XR806开发板MQTT电源智能控制器

非常感谢这次极术社区,借助对Xr806开发板的试用,接触到了鸿蒙harmonyos,使用一定过程历时较长,也是一点点摸索,得到了很好学习机会。
社区里很多文章,感谢各位大佬的文章指点,本次试用主要是参考了两位大佬的, 【XR806开发板试用】儿童遥控挖掘机无线化升级改造【XR806开发板试用】基于MQTT与Cjson库的花式点灯,其他大佬的文章也有翻阅学习。

环境搭建

使用Ubuntu20.04的虚拟机,尝试了很久,最后只要能运行Hellworld示例说明环境就算是正常了。

外部硬件

一个5V的4路继电器
QQ截图20220213231454.png

接线方式

0002.png

代码部分

建文件夹mymqttrelay
下面建文件BUILD.gn

import("//device/xradio/xr806/liteos_m/config.gni")

static_library("app_mymqttrelay") {
   configs = []

   sources = [
      "src/main.c",
   ]

   cflags = board_cflags

   include_dirs = board_include_dirs
   include_dirs += [
      "//kernel/liteos_m/kernel/arch/include",
      "//base/iot_hardware/peripheral/interfaces/kits",
      "include",

      ".",
      "//utils/native/lite/include",
      "//foundation/communication/wifi_lite/interfaces/wifiservice",
      "//device/xradio/xr806/xr_skylark/project"
   ]
}

建src/main.cs核心代码

#include <stdio.h>
#include <string.h>
#include "ohos_init.h"
#include "kernel/os/os.h"

#include "iot_gpio.h"
#include "wifi_device.h"
#include "common/framework/net_ctrl.h"
#include "net/mqtt/MQTTClient-C/MQTTClient.h"
#include "driver/chip/hal_pwm.h"

static OS_Thread_t g_main_thread;
static OS_Thread_t g_mqtt_thread;


#define PWM_OUTPUT_CHL        PWM_GROUP1_CH2
#define PWM_OUTPUT_MODE       PWM_CYCLE_MODE

#define WIFI_DEVICE_CONNECT_AP_SSID "Xiaomi"//路由器的SSID
#define WIFI_DEVICE_CONNECT_AP_PSK "123456789"//路由器的PWD


#define MQTT_DEMO_CLIENT_ID "mqtt_xr806"
#define MQTT_DEMO_HOST_NAME "broker-cn.emqx.io"//这个是免费调试用的MQTT服务器地址
#define MQTT_DEMO_PORT      "1883"
#define MQTT_DEMO_USERNAME  "xr806_0001"
#define MQTT_DEMO_PASSWORD  "12345678"
#define MQTT_RESP_TOPIC "/test/relay" 
#define MQTT_RECV_TOPIC  "/show/relay" // TOPIC
#define MQTT_DEMO_BUF_SIZE (2*1024)

static MQTTPacket_connectData mqtt_demo_connectData = MQTTPacket_connectData_initializer;
static Client mqtt_demo_client;
static Network mqtt_demo_network;
static int max_duty_ratio = 0;

static int mqtt_demo_publish(char *topic, char *msg) ;

static int mqtt_demo_init(void) {
    char *send_buf;
    char *recv_buf;

    mqtt_demo_connectData.clientID.cstring = MQTT_DEMO_CLIENT_ID;
    mqtt_demo_connectData.keepAliveInterval = 30; // 30s
    mqtt_demo_connectData.cleansession = 0;
    mqtt_demo_connectData.MQTTVersion = 4; //Version of MQTT 3.1.1

    send_buf = malloc(MQTT_DEMO_BUF_SIZE);
    if (send_buf == NULL) {
        printf("no memory\n");
        return -1;
    }
    recv_buf = malloc(MQTT_DEMO_BUF_SIZE);
    if (recv_buf == NULL) {
        free(send_buf);
        printf("no memory\n");
        return -1;
    }

    /* init network */
    NewNetwork(&mqtt_demo_network);
    /* init mqtt client object */
    MQTTClient(&mqtt_demo_client, &mqtt_demo_network, 6000,
               (unsigned char *)send_buf, MQTT_DEMO_BUF_SIZE,
               (unsigned char *)recv_buf, MQTT_DEMO_BUF_SIZE);

    /* set username and password */
    mqtt_demo_connectData.username.cstring = MQTT_DEMO_USERNAME;
    mqtt_demo_connectData.password.cstring = MQTT_DEMO_PASSWORD;
    return 0;
}

static int mqtt_demo_connect(char *host_name, char *host_port) {
    int ret = -1;

    ret = ConnectNetwork(&mqtt_demo_network, host_name, atoi(host_port));
    if (ret != 0) {
        printf("mqtt connect faild, ret:%d, host:%s, port:%s\n", ret, host_name, host_port);
        goto exit;
    }

    ret = MQTTConnect(&mqtt_demo_client, &mqtt_demo_connectData);
    if (ret != 0) {
        printf("mqtt connect faild, ret:%d\n", ret);
        mqtt_demo_network.disconnect(&mqtt_demo_network);
        goto exit;
    }
    printf("mqtt connected\n");
exit:
    return ret;
}

static void mqtt_demo_msg_cb(MessageData *data) {
    printf("get a message, topic: %.*s, msg: %.*s\n", data->topicName->lenstring.len,
           data->topicName->lenstring.data, data->message->payloadlen,
           (char *)data->message->payload);
    char *temptest = (char *)data->message->payload;
    if(!strncmp(data->topicName->lenstring.data, "/show/relay", 11) && data->message->payloadlen) {
        if(!strcmp(data->message->payload,"relay01")){
            IoTGpioSetOutputVal(GPIO_ID_PA23, 0);
            IoTGpioSetOutputVal(GPIO_ID_PA22, 0);
            IoTGpioSetOutputVal(GPIO_ID_PA21, 0);
            IoTGpioSetOutputVal(GPIO_ID_PA20, 1);
            printf("mqtt------relay01");
        }else if(!strcmp(data->message->payload,"relay02")){
            IoTGpioSetOutputVal(GPIO_ID_PA23, 0);
            IoTGpioSetOutputVal(GPIO_ID_PA22, 0);
            IoTGpioSetOutputVal(GPIO_ID_PA21, 1);
            IoTGpioSetOutputVal(GPIO_ID_PA20, 0);
            printf("mqtt------relay02");
        }else if(!strcmp(data->message->payload,"relay03")){
            IoTGpioSetOutputVal(GPIO_ID_PA23, 0);
            IoTGpioSetOutputVal(GPIO_ID_PA22, 1);
            IoTGpioSetOutputVal(GPIO_ID_PA21, 0);
            IoTGpioSetOutputVal(GPIO_ID_PA20, 0);
            printf("mqtt------relay03");
        }else if(!strcmp(data->message->payload,"relay04")){
            IoTGpioSetOutputVal(GPIO_ID_PA23, 1);
            IoTGpioSetOutputVal(GPIO_ID_PA22, 0);
            IoTGpioSetOutputVal(GPIO_ID_PA21, 0);
            IoTGpioSetOutputVal(GPIO_ID_PA20, 0);
            printf("mqtt------relay04");
        }else {
            IoTGpioSetOutputVal(GPIO_ID_PA23, 0);
            IoTGpioSetOutputVal(GPIO_ID_PA22, 0);
            IoTGpioSetOutputVal(GPIO_ID_PA21, 0);
            IoTGpioSetOutputVal(GPIO_ID_PA20, 0);
        }


        char *payload = data->message->payload;
        char str[8] = "";
        int max_len = data->message->payloadlen > 3 ? 3 : data->message->payloadlen;
        strncpy(str, payload, max_len);
        int duty = atoi(str);
        HAL_Status status = HAL_PWM_ChSetDutyRatio(PWM_OUTPUT_CHL, duty * max_duty_ratio / 100);
        if (status != HAL_OK)
            printf("%s(): %d, PWM set duty ratio error\n", __func__, __LINE__);
        
        if(duty) {
            mqtt_demo_publish(MQTT_RESP_TOPIC, "light on");
        } else {
            mqtt_demo_publish(MQTT_RESP_TOPIC, "light off");
        }
    } 
}

static int mqtt_demo_subscribe(char *topic) {
    int ret = -1;
    if (mqtt_demo_client.isconnected) {
        ret = MQTTSubscribe(&mqtt_demo_client, topic, 0, mqtt_demo_msg_cb);
        if (ret != 0)
            printf("mqtt subscribe faild ret:%d\n", ret);
    }
    return ret;
}

static int mqtt_demo_unsubscribe(char *topic) {
    int ret = -1;
    if (mqtt_demo_client.isconnected) {
        ret = MQTTUnsubscribe(&mqtt_demo_client, topic);
        if (ret != 0)
            printf("mqtt unsubscribe faild, ret:%d\n", ret);
    }
    return ret;
}

static int mqtt_demo_publish(char *topic, char *msg) {
    int ret = -1;

    MQTTMessage message;
    memset(&message, 0, sizeof(message));
    message.qos = 0;
    message.retained = 0; /* disable retain the message in server */
    message.payload = msg;
    message.payloadlen = strlen(msg);
    ret = MQTTPublish(&mqtt_demo_client, topic, &message);
    if (ret != 0)
        printf("mqtt publish faild, ret:%d\n", ret);
    return ret;
}

static int mqtt_demo_disconnect(void) {
    int ret = -1;

    if (mqtt_demo_client.isconnected) {
        ret = MQTTDisconnect(&mqtt_demo_client);
        if (ret != 0)
            printf("mqtt disconnect fail, ret:%d\n", ret);
        mqtt_demo_network.disconnect(&mqtt_demo_network);
    }
    return ret;
}

static void mqtt_demo_deinit(void) {
    if (mqtt_demo_client.buf) {
        free(mqtt_demo_client.buf);
        mqtt_demo_client.buf = NULL;
    }
    if (mqtt_demo_client.readbuf) {
        free(mqtt_demo_client.readbuf);
        mqtt_demo_client.readbuf = NULL;
    }
}

static void mqtt_task(void *arg)   {
    int ret;
    int reconnect_times = 0;

    mqtt_demo_init();

    ret = mqtt_demo_connect(MQTT_DEMO_HOST_NAME, MQTT_DEMO_PORT);
    if (ret != 0)
        goto exit;

    ret = mqtt_demo_subscribe(MQTT_RECV_TOPIC);
    if (ret != 0)
        goto exit;

    mqtt_demo_publish(MQTT_RESP_TOPIC, "light ready");

    while (1) {
        ret = MQTTYield(&mqtt_demo_client, 300);
        if (ret != 0) {
            printf("mqtt yield err, ret:%d\n", ret);
reconnect:
            printf("mqtt reconnect\n");
            mqtt_demo_disconnect();
            ret = mqtt_demo_connect(MQTT_DEMO_HOST_NAME, MQTT_DEMO_PORT);
            if (ret != 0) {
                reconnect_times++;
                if (reconnect_times > 5)
                    goto exit;
                OS_MSleep(5000); //5s
                goto reconnect;
            }
        }
    }

exit:
    mqtt_demo_unsubscribe(MQTT_RECV_TOPIC);
    mqtt_demo_disconnect();
    mqtt_demo_deinit();
    OS_ThreadDelete(&g_mqtt_thread);
}

static void net_cb(uint32_t event, uint32_t data, void *arg) {
    uint16_t type = EVENT_SUBTYPE(event);
    switch (type) {
    case NET_CTRL_MSG_NETWORK_UP:
        printf("NET_CTRL_MSG_NETWORK_UP\n");
        if (!OS_ThreadIsValid(&g_mqtt_thread)) {
            OS_ThreadCreate(&g_mqtt_thread, "connect_to_server_task",
                                mqtt_task, (void *)NULL,  OS_THREAD_PRIO_APP, (8 * 1024));
        }
        break;
    case NET_CTRL_MSG_NETWORK_DOWN:
        break;
    default:
        break;
    }
}

static void MainThread(void *arg)   {
    printf("MainThread start\r\n");

    /*Config GPIO*/
    IoTGpioInit(GPIO_ID_PA23);
    IoTGpioSetDir(GPIO_ID_PA23, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(GPIO_ID_PA23, 0);

    IoTGpioInit(GPIO_ID_PA22);
    IoTGpioSetDir(GPIO_ID_PA22, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(GPIO_ID_PA22, 0);

    IoTGpioInit(GPIO_ID_PA21);
    IoTGpioSetDir(GPIO_ID_PA21, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(GPIO_ID_PA21, 0);

    IoTGpioInit(GPIO_ID_PA20);
    IoTGpioSetDir(GPIO_ID_PA20, IOT_GPIO_DIR_OUT);
    IoTGpioSetOutputVal(GPIO_ID_PA20, 0);


    HAL_Status status = HAL_ERROR;
    PWM_ClkParam clk_param;
    PWM_ChInitParam ch_param;

    clk_param.clk = PWM_CLK_HOSC;
    clk_param.div = PWM_SRC_CLK_DIV_1;

    status = HAL_PWM_GroupClkCfg(PWM_OUTPUT_CHL, &clk_param);
    if (status != HAL_OK)
        printf("%s(): %d, PWM group clk config error\n", __func__, __LINE__);

    ch_param.hz = 1000;
    ch_param.mode = PWM_OUTPUT_MODE;
    ch_param.polarity = PWM_HIGHLEVE;
    max_duty_ratio = HAL_PWM_ChInit(PWM_OUTPUT_CHL, &ch_param);
    if (max_duty_ratio == -1)
        printf("%s(): %d, PWM ch init error\n", __func__, __LINE__);

    printf("max_duty_ratio=%d\n", max_duty_ratio);
    status = HAL_PWM_ChSetDutyRatio(PWM_OUTPUT_CHL, 0);
    if (status != HAL_OK)
        printf("%s(): %d, PWM set duty ratio error\n", __func__, __LINE__);

    status = HAL_PWM_EnableCh(PWM_OUTPUT_CHL, PWM_OUTPUT_MODE, 1);
    if (status != HAL_OK)
        printf("%s(): %d, PWM ch enable error\n", __func__, __LINE__);

    if (WIFI_SUCCESS != EnableWifi()) {
        printf("Error: EnableWifi fail\n");
        return;
    }

    OS_Sleep(1);

    if (WIFI_SUCCESS != Scan()) {
        printf("Error: Scan fail.\n");
        return;
    }

    OS_Sleep(3);//这里为了方便用延时,实际用回调更好,否则3秒可能不够

    const char ssid_want_connect[] = WIFI_DEVICE_CONNECT_AP_SSID;
    const char psk[] = WIFI_DEVICE_CONNECT_AP_PSK;
    WifiScanInfo scan_results[30];
    unsigned int scan_num = 30;

    if (WIFI_SUCCESS != GetScanInfoList(scan_results, &scan_num)) {
        printf("Error: GetScanInfoList fail.\n");
        return;
    }

    WifiDeviceConfig config = { 0 };
    int netId = 0;

    int i;
    for (i = 0; i < scan_num; i++) {
        printf("ssid: %s    ", scan_results[i].ssid);
        printf("securityType: %d\n", scan_results[i].securityType);
        if (0 == strcmp(scan_results[i].ssid, ssid_want_connect)) {
            memcpy(config.ssid, scan_results[i].ssid,
                   WIFI_MAX_SSID_LEN);
            memcpy(config.bssid, scan_results[i].bssid,
                   WIFI_MAC_LEN);
            strcpy(config.preSharedKey, psk);
            config.securityType = scan_results[i].securityType;
            config.wapiPskType = WIFI_PSK_TYPE_ASCII;
            config.freq = scan_results[i].frequency;
            break;
        }
    }

    if (i >= scan_num) {
        printf("Error: No found ssid in scan_results\n");
        return;
    }

    if (WIFI_SUCCESS != AddDeviceConfig(&config, &netId)) {
        printf("Error: AddDeviceConfig Fail\n");
        return;
    }
    printf("Config Success\n");

    if (WIFI_SUCCESS != ConnectTo(netId)) {
        printf("Error: ConnectTo Fail\n");
        return;
    }
    
    observer_base *net_ob;
    net_ob = sys_callback_observer_create(CTRL_MSG_TYPE_NETWORK, NET_CTRL_MSG_ALL, net_cb, NULL);
    if (net_ob == NULL)
        return;

    if (sys_ctrl_attach(net_ob) != 0)
        return;

    while (1) {
        OS_MSleep(500);
    }
}

void MqttMain(void) {
    if (OS_ThreadCreate(&g_main_thread, "MainThread", MainThread, NULL, OS_THREAD_PRIO_APP, 4 * 1024) != OS_OK) {
        printf("[ERR] Create MainThread Failed\n");
    }
}

SYS_RUN(MqttMain);

视频

https://www.bilibili.com/vide...

推荐阅读
关注数
13820
内容数
140
全志XR806开发板相关的知识介绍以及应用专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息