【电子DIY作品】+ M61+VC02语音控制HA设备

[复制链接]
查看1081 | 回复13 | 2024-7-15 17:54:38 | 显示全部楼层 |阅读模式

本帖最后由 WT_0213 于 2024-7-16 11:14 编辑

智能家居的话,如果只能手动控制会觉得不太智能,如果能用说的或者自动的话体验可能会更好一些。

才发现作品提交日期已经到了,慌得一批希望还来得及。

第二期 | 有奖征集智能家居电子DIY作品 https://bbs.ai-thinker.com/forum.php?mod=viewthread&tid=44894&fromuid=15918 (出处: 物联网开发者社区-安信可论坛)

智能家居其实就是为了给生活添加一些便利,懒人推送科技发展是没错的。

对于个人而言接入智能家居无非有以下几个原因:

1、动动手动动嘴不动腿就是懒恨不能意念控制

2、开关对小朋友不友好,个头不够摸不到开关

3、全屋联动回家模式离家模式等等

基于以上几个原因

通过尝试。实现了语音控制HA设备的基本功能。

主要思路如图:

流程.png

开始想着增加机械开关手动去操作,后来想了以下都语音控制了还要物理开关干嘛呢。

小朋友和老人,直接语音控制开关设备。就很舒服呢。

对于红外设备,还没研究透彻怎么去获取遥控器的红外编码,然后发射出来。这样就可以实现更多的功能。

可以语音控制空调、电视等红外设备。

[智能家居]MQTT控制HomeAssistant设备 https://bbs.ai-thinker.com/forum.php?mod=viewthread&tid=44644&fromuid=15918 (出处: 物联网开发者社区-安信可论坛)

这里主要还是用到了HomeAssistant的自动化功能,这种设置不需要对HomeAssistant有很深的了解,简单配置即可。

对于小白用户体验更好一些,上手就用。对于大佬的话,可以延伸出更多的功能。

下面介绍一下主要功能模块

一、离线语音模组系列

 VC系列模组是我司开发的一款AI离线语音识别的产品,主芯片是云知声推出的离线语音识别芯片锋鸟M(US516P6),具有高可靠性,通用性强的特点。在语音识别技术上实现了高可靠的唤醒识别率、更远距离的唤醒、更低误唤醒率、更强的抗噪音能力、更快的响应识别时间,免联网的纯离线识别。

  VC系列模组采用了32bit RISC 架构内核,并加入了专门针对信号处理和语音识别所需要的 DSP 指令集,支持浮点运算的 FPU 运算单元,以及 FFT 加速器。支持最高150 条本地指令离线识别,支持 RTOS 轻量级系统,以及简单友好的客制化工具。

  VC系列模组具有丰富的外围接口,包括UART/I2C/PWM/SPI,以及简单友好的二次开发工具,方便客户实现单模组的语音控制应用场景方案。

VC-02 模组

捕获.PNG

扬声器功率尽量不要太大,如果用M61-32S供电扬声器功率过高会导致掉电。

扬声器:

SPK-8Ω2W SPK+8Ω2W

官方资料

VC-02 模组规格书:中文 EN

VC-02原理图:点我下载

VC-02封装: 点击下载

串口烧录工具

定制语音

安信可语音开放平台:http://voice.ai-thinker.com/

在安信可语音开放平台创建产品,选择VC系列模组。

c.PNG

然后修改唤醒词

w.PNG

设置Pin引脚功能

P.PNG

波特率设置115200,引脚B6设置为UART1_RX 引脚B7设置为UART1_TX,用来发送接收数据。注意不要配置多个UART1,否则不生效。

添加语音指令

cmd.PNG

然后添加控制详情

cmd1.PNG

这里主要用到的就是串口数据,这里发送指令 第一位是指令开头默认A1,第二位定义的是设备位置,第三位定义的是设备类型,第四位定义的是开关状态,第五位结束位默认FF。根据自己的需要设置解析即可。

还有免唤醒命令,不用唤醒词直接就可以用,比如开灯、关灯等等。

mcmd.PNG

免唤醒命令词最多10个选择自己需要的添加,添多了也是默认取前10条。

二、Ai-M61-32S WIFI模组

Ai-M61 系列模组(下称模组)是由深圳市安信可科技有限公司开发的 Wi-Fi6 & 蓝牙双模模组,搭载BL618芯片作为处理器,支持Wi-Fi 802.11b/g/n/ax协议和BLE 5.3协议。BL618芯片内置低功耗的32位RISC-V CPU,最高主频可达320M. 丰富的外围接口,包括DVP、MJPEG、Dispaly、Audio Codec、USB2.0、SDU、以太网(EMAC)、SD/MMC(SDH)、SPI、UART、I2C、I2S、PWM、GPDAC、GPADC、ACOMP和GPIO等。可广泛应用于音视频多媒体、物联网(IoT)、移动设备、可穿戴电子设备、智能家居等领域。

M61-32S模组

092423xvffcw0wc8f8gvzo.png

官方资料

Ai-M61-32S-Kit开发板规格书:中文 EN

Ai-M61-32S开发板原理图:中文

Ai-M61-32S模组规格书:中文 EN

Ai-M61-32S推荐封装:点击下载

Ai-M61系列出厂固件

固件下载工具:点击下载

固件烧录指南:M61/M62系列烧录指导(包含模组&开发板)

三、代码部分

主要用wifi、mqtt、uart、flash

uart代码主要参考

【完全开源】智能桌面助手——AiPi-DSL_Dashboard https://bbs.ai-thinker.com/forum.php?mod=viewthread&tid=42026&fromuid=15918

主程序代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include "log.h"
#include "board.h"
#include "mem.h"

//easy flash
#include "easyflash.h"
#include "bflb_mtd.h"
#include "bl_fw_api.h"
#include "wifi_mgmr_ext.h"
#include "wifi_mgmr.h"
#include "ha_task.h"
#include "wifi_event.h"
#include "voice_uart.h"

int main(void)
{
    board_init();
    wifi_start_firmware_task();
    //init easyflash
    bflb_mtd_init();
    easyflash_init();
    xTaskCreate(voice_uart_task, "uart task", 1024, NULL, 10, NULL);
    xTaskCreate(queue_receive_task, "queue_receive_task", 1024*3, NULL, 3, NULL);

    vTaskStartScheduler();
}

VC02模组交互代码

5#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <FreeRTOS.h>
#include <queue.h>
#include <timers.h>
#include <task.h>
#include "ha_task.h"
#include "bflb_uart.h"
#include "bflb_gpio.h"
#include "voice_uart.h"
#include "user_mqtt.h"
#include "log.h"

#define GBD_TAG "UART"

static void uart_init(void);


extern xQueueHandle queue;
uart_rx_cmd_t uart_cmd;
static struct bflb_device_s* uart1;
static char uart_buff[5] = { 0 };

static const uart_data_t g_uart_buf[] = {
  {{0xA1, 0x00, 0x01, 0x00, 0xFF}, 5}, //wakeup_uni
  {{0xA1, 0x00, 0x01, 0x01, 0xFF}, 5}, //openL
  {{0xA1, 0x00, 0x01, 0x00, 0xFF}, 5}, //closeL
};

void voice_uart_task(void* arg)
{

    uart_init();
    while (1) {
        vTaskDelay(1000/portTICK_PERIOD_MS);
    }
}

static int voice_cmd_check(char* buff, int len)
{

    int data_cnt = 0, j = 0;
    // char* uart_txbuf = pvPortMalloc(4);
    // memset(uart_txbuf, 0, 4);
    while (1) {
        for (size_t i = 0; i < 5; i++)
        {
            if (buff[i]==g_uart_buf[j].data[i]) data_cnt++;
            else break;
        }
        if (data_cnt==g_uart_buf->len) break;
        data_cnt = 0;
        j++;
        if (j>23) return -1;
    }
    LOG_I("check uart cmd=%d", j);
    return j;
}

static void uart_isr(int irq, void* arg)
{
    uint32_t intstatus = bflb_uart_get_intstatus(uart1);
    uint32_t rx_data_len = 0;
    char data_type[1] = { 0 };
    if (intstatus & UART_INTSTS_RX_FIFO) {
        int index = 0;
        memset(uart_buff, 0, 5);
        LOG_I("rx fifo\r\n");
        while (bflb_uart_rxavailable(uart1)) {
            uart_buff[index++] = bflb_uart_getchar(uart1);
        }
        LOG_I("uart recv:%02X %02X %02X %02X %02X", uart_buff[0], uart_buff[1], uart_buff[2], uart_buff[3], uart_buff[4]);
    }
}
/**
 * @brief
 *
*/
static void uart_init(void)
{
    struct bflb_device_s* gpio;
    struct bflb_uart_config_s cfg = {
        .baudrate = 115200,
        .data_bits = UART_DATA_BITS_8,
        .stop_bits = UART_STOP_BITS_1,
        .parity = UART_PARITY_NONE,
        .flow_ctrl = 0,
        .tx_fifo_threshold = 4,
        .rx_fifo_threshold = 4,
    };

    gpio = bflb_device_get_by_name("gpio");
    uart1 = bflb_device_get_by_name("uart1");

    bflb_gpio_uart_init(gpio, GPIO_PIN_25, GPIO_UART_FUNC_UART1_TX);
    bflb_gpio_uart_init(gpio, GPIO_PIN_26, GPIO_UART_FUNC_UART1_RX);

    bflb_uart_init(uart1, &cfg);

    bflb_uart_txint_mask(uart1, false);
    bflb_uart_rxint_mask(uart1, false);
    bflb_irq_attach(uart1->irq_num, uart_isr, NULL);
    bflb_irq_enable(uart1->irq_num);
}

MQTT与WIFI

wifi

#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"

#include <lwip/tcpip.h>
#include <lwip/sockets.h>
#include <lwip/netdb.h>

#include "bl_fw_api.h"
#include "wifi_mgmr_ext.h"
#include "wifi_mgmr.h"
#include "bflb_irq.h"
#include "bflb_uart.h"
#include "bflb_l1c.h"
#include "bflb_mtimer.h"

#include "bl616_glb.h"
#include "rfparam_adapter.h"

#include "board.h"
#include "log.h"
#include "ha_task.h"
#include "config.h"

#define DBG_TAG "WIFI EVENT"

#define WIFI_STACK_SIZE     (1024*4)
#define TASK_PRIORITY_FW    (16)

static wifi_conf_t conf =
{
    .country_code = "CN",
};
static TaskHandle_t wifi_fw_task;
static uint32_t sta_ConnectStatus = 0;

extern TaskHandle_t https_Handle;
/**
 * @brief WiFi 任务
 *
 * @return int
*/
int wifi_start_firmware_task(void)
{
    LOG_I("Starting wifi ...");

    /* enable wifi clock */

    GLB_PER_Clock_UnGate(GLB_AHB_CLOCK_IP_WIFI_PHY | GLB_AHB_CLOCK_IP_WIFI_MAC_PHY | GLB_AHB_CLOCK_IP_WIFI_PLATFORM);
    GLB_AHB_MCU_Software_Reset(GLB_AHB_MCU_SW_WIFI);

    /* set ble controller EM Size */

    GLB_Set_EM_Sel(GLB_WRAM160KB_EM0KB);

    if (0 != rfparam_init(0, NULL, 0)) {
        LOG_I("PHY RF init failed!");
        return 0;
    }

    LOG_I("PHY RF init success!");

    /* Enable wifi irq */

    extern void interrupt0_handler(void);
    bflb_irq_attach(WIFI_IRQn, (irq_callback)interrupt0_handler, NULL);
    bflb_irq_enable(WIFI_IRQn);

    xTaskCreate(wifi_main, (char*)"fw", WIFI_STACK_SIZE, NULL, TASK_PRIORITY_FW, &wifi_fw_task);

    return 0;
}
/**
 * @brief wifi event handler
 *      WiFi 事件回调
 *
 * @param code
*/


void wifi_event_handler(uint32_t code)
{

    sta_ConnectStatus = code;

    switch (code) {
        case CODE_WIFI_ON_INIT_DONE:
        {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_INIT_DONE", __func__);
            wifi_mgmr_init(&conf);
        }
        break;
        case CODE_WIFI_ON_MGMR_DONE:
        {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_MGMR_DONE", __func__);

        }
        break;
        case CODE_WIFI_ON_SCAN_DONE:
        {
            char* scan_msg = pvPortMalloc(128);
            wifi_mgmr_sta_scanlist();
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_SCAN_DONE SSID numbles:%d", __func__, wifi_mgmr_sta_scanlist_nums_get());
            sprintf(scan_msg, "{\"wifi_scan\":{\"status\":0}}");
            vPortFree(scan_msg);
        }
        break;
        case CODE_WIFI_ON_CONNECTED:
        {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_CONNECTED", __func__);
            void mm_sec_keydump();
            mm_sec_keydump();
        }
        break;
        case CODE_WIFI_ON_GOT_IP:
        {

            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_GOT_IP", __func__);
            mqtt_client_init(MQTT_HOST, MQTT_PORT);
            mqtt_client_register_event();
            vTaskDelay(500/portTICK_PERIOD_MS);
            mqtt_start_connect(MQTT_HOST, MQTT_PORT, MQTT_USERNAME, MQTT_PASSWORD);
            mqtt_app_subscribe("sub", 0);
        }
        break;
        case CODE_WIFI_ON_DISCONNECT:
        {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_DISCONNECT", __func__);

        }
        break;
        case CODE_WIFI_ON_AP_STARTED:
        {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_AP_STARTED", __func__);
        }
        break;
        case CODE_WIFI_ON_AP_STOPPED:
        {
            LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_AP_STOPPED", __func__);
        }
        break;
        case CODE_WIFI_ON_AP_STA_ADD:
        {
            LOG_I("[APP] [EVT] [AP] [ADD] %lld", xTaskGetTickCount());
        }
        break;
        case CODE_WIFI_ON_AP_STA_DEL:
        {
            LOG_I("[APP] [EVT] [AP] [DEL] %lld", xTaskGetTickCount());
        }
        break;
        default:
        {
            LOG_I("[APP] [EVT] Unknown code %u ", code);
        }
    }
}

uint8_t wifi_connect(char* ssid, char* passwd)
{
    int ret = 255;
    // struct fhost_vif_ip_addr_cfg ip_cfg = { 0 };
    uint32_t ipv4_addr = 0;
    char* queue_buff = pvPortMalloc(128);
    memset(queue_buff, 0, 128);
    if (NULL==ssid || 0==strlen(ssid)) {
        return 1;
    }
    //先断开WiFi
    if (wifi_mgmr_sta_state_get() == 1) {
        wifi_sta_disconnect();
    }
    LOG_I("WiFi STA connect .....");
    if (wifi_sta_connect(ssid, passwd, NULL, NULL, 0, 0, 0, 1)<0) {
        vPortFree(queue_buff);
        return 4;
    }
    LOG_I("Wating wifi connet");
    //等待连接成功
    sta_ConnectStatus = 0;
    for (int i = 0;i<10*30;i++) {

        vTaskDelay(100/portTICK_PERIOD_MS);
        switch (sta_ConnectStatus) {
            case CODE_WIFI_ON_MGMR_DONE:
                // vTaskDelay(2000);
                // LOG_I("wifi_mgmr_sta_scan:%d", wifi_mgmr_sta_scan(wifi_scan_config));
                vPortFree(queue_buff);
                return 3;
            case CODE_WIFI_ON_SCAN_DONE:

                // LOG_I("WIFI STA SCAN DONE %s", wifi_scan_config[0].ssid_array);

                vPortFree(queue_buff);
                return 2;
            case CODE_WIFI_ON_DISCONNECT:   //连接失败(超过了重连次数还没有连接成功的状态)

                // wifi_sta_disconnect();
                // vPortFree(queue_buff);
                return 4;
            case CODE_WIFI_ON_CONNECTED:    //连接成功(表示wifi sta状态的时候表示同时获取IP(DHCP)成功,或者使用静态IP)
                // LOG_I("Wating wifi connet OK");
                break;
            case CODE_WIFI_ON_GOT_IP:
                wifi_sta_ip4_addr_get(&ipv4_addr, NULL, NULL, NULL);
                LOG_I("wifi connened %s,IP:%s", ssid, inet_ntoa(ipv4_addr));
                sprintf(queue_buff, "{\"ip\":{\"IP\":\"%s\"}}", inet_ntoa(ipv4_addr));
                flash_erase_set(SSID_KEY, ssid);
                flash_erase_set(PASS_KEY, passwd);
                LOG_I("Wating wifi connet OK and get ip OK");
                vPortFree(queue_buff);
                return 0;
            default:
                //等待连接成功
                break;
        }

    }
    vPortFree(queue_buff);
    return 14; //连接超时
}

mqtt

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "FreeRTOS.h"
#include "log.h"
#include <mqtt.h>

#include "user_mqtt.h"
#include "ha_task.h"
#include <lwip/inet.h>
#include "bflb_uart.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <lwip/errno.h>
#include <netdb.h>
#include "bflb_uart.h"
#include "voice_uart.h"
#include "utils_getopt.h"
#include "config.h"
#define DBG_TAG "MQTT"


// #define USER_MQTT
int test_sockfd;
struct mqtt_client client;
static mqtt_event_t event;
uint8_t sendbuf[2048]; /* sendbuf should be large enough to hold multiple whole mqtt messages */
uint8_t recvbuf[1024]; /* recvbuf should be large enough any whole mqtt message expected to be received */

static TaskHandle_t client_daemon;
static int open_socket(const char* host, const char* port);

static int open_socket(const char* host, const char* port)
{
    struct addrinfo hints = { 0 };
    hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6 */
    hints.ai_socktype = SOCK_STREAM; /* Must be TCP */
    int sockfd = -1;
    int rv;
    struct addrinfo* p, * servinfo;

    /* get address information */
    LOG_I("host:%s, port=%s", host, port);
    rv = getaddrinfo(host, port, &hints, &servinfo);
    if (rv != 0) {
        LOG_E("Failed to open socket (getaddrinfo): %d", rv);
        return -1;
    }

    /* open the first possible socket */
    for (p = servinfo; p != NULL; p = p->ai_next) {
        sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
        if (sockfd == -1) continue;

        /* connect to server */
        rv = connect(sockfd, p->ai_addr, p->ai_addrlen);
        if (rv == -1) {
            close(sockfd);
            sockfd = -1;
            continue;
        }
        break;
    }

    /* free servinfo */
    freeaddrinfo(servinfo);

    /* make non-blocking */
    if (sockfd != -1) {
        int iMode = 1;
        ioctlsocket(sockfd, FIONBIO, &iMode);
    }

    return sockfd;
}
/**
 * @brief
 *
 * @param sig
*/
static void test_close(void)
{
    if (test_sockfd)
    {
        close(test_sockfd);
    }
    vTaskDelete(client_daemon);

}
/**
 * @brief
 *
 * @param unused
 * @param published
*/
static void publish_callback_1(void** unused, struct mqtt_response_publish* published)
{
    /* not used in this example */

    char* topic_name = (char*)malloc(published->topic_name_size + 1);
    memcpy(topic_name, published->topic_name, published->topic_name_size);
    topic_name[published->topic_name_size] = '\0';

    char* topic_msg = (char*)malloc(published->application_message_size + 1);
    memcpy(topic_msg, published->application_message, published->application_message_size);
    topic_msg[published->application_message_size] = '\0';
    printf("%s:[%s]\r\n", topic_name, topic_msg);
    char* queue_buff = pvPortMalloc(512);
    memset(queue_buff, 0, 512);
    sprintf(queue_buff, "{\"mqtt_msg\":{\"topic\":\"%s\",\"data\":%.*s}}", topic_name, published->application_message_size, topic_msg);
    vPortFree(queue_buff);
    free(topic_name);
    free(topic_msg);
}
/**
 * @brief  _inspector_callback
 *
 * @param client_arg
 * @return enum MQTTErrors
*/
enum MQTTErrors _inspector_callback(struct mqtt_client* client_arg)
{
    if (client_arg->mq.queue_tail->state!=MQTT_QUEUED_UNSENT) return MQTT_OK; //识别消息状态是否有更新,没有更新就返回

    event = client_arg->mq.queue_tail->control_type;
    static struct bflb_device_s* uartx;
    uartx = bflb_device_get_by_name("uart1");
    switch (event) {
        case MQTT_EVENT_CONNECT:
        {
            LOG_I("MQTT_EVENT_CONNECT");
        }
        break;
        case MQTT_EVENT_CONNACK:
        {
            LOG_I("MQTT_EVENT_CONNACK");
        }
        break;
        case MQTT_EVENT_PUBLISH:
        {
            LOG_I("MQTT_EVENT_PUBLISH");
        }
        break;
        case MQTT_EVENT_PUBACK:
        {
            LOG_I("MQTT_EVENT_PUBACK");
        }
        break;
        case MQTT_EVENT_PUBREC:
        {
            LOG_I("MQTT_EVENT_PUBREC");
        }
        break;
        case MQTT_EVENT_PUBREL:
        {
            LOG_I("MQTT_EVENT_PUBREL");
        }
        break;
        case MQTT_EVENT_PUBCOMP:
        {
            LOG_I("MQTT_EVENT_PUBCOMP");
        }
        break;
        case MQTT_EVENT_SUBSCRIBE:
        {
            LOG_I("MQTT_EVENT_SUBSCRIBE");
        }
        break;
        case MQTT_EVENT_SUBACK:
        {
            LOG_I("MQTT_EVENT_SUBACK");
        }
        break;
        case MQTT_EVENT_UNSUBSCRIBE:
        {
            LOG_I("MQTT_EVENT_UNSUBSCRIBE");
        }
        break;
        case MQTT_EVENT_UNSUBACK:
        {
            LOG_I("MQTT_EVENT_UNSUBACK");
        }
        break;
        case MQTT_EVENT_PINGREQ:
        {
            LOG_I("MQTT_EVENT_PINGREQ");
        }
        break;
        case MQTT_EVENT_PINGRESP:
        {
            LOG_I("MQTT_EVENT_PINGRESP");
        }
        break;
        case MQTT_EVENT_DISCONNECT:
        {
            LOG_I("MQTT_EVENT_DISCONNECT");
        }
        break;
        default:
            break;
    }
    return MQTT_OK;
}

/**
 * @brief
 *
 * @param host
 * @param port
*/
void  mqtt_client_init(const char* host, int port)
{
    LOG_I("MQTT init start");
    test_sockfd = open_socket(host, "1883");
    if (test_sockfd < 0) {
        LOG_E("Failed to open socket: %d", test_sockfd);
        test_close();
        return;
    }
    LOG_I(" test_sockfd  crater OK id=%d", test_sockfd);

    mqtt_init(&client, test_sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), publish_callback_1);

}
/**
 * @brief
 *
 * @param client
*/
static void client_refresher(void* arg)
{
    struct mqtt_client* client = (struct mqtt_client*)arg;
    while (1)
    {
        mqtt_sync(client);
        vTaskDelay(200/portTICK_PERIOD_MS);
    }
}
/**
 * @brief mqtt_start_connect
 *  MQTT启动连接
 * @param host
 * @param port
 * @param user_name
 * @param pass
 * @return int
*/
int mqtt_start_connect(char* host, uint16_t port, char* user_name, char* pass)
{
    int ret = 0;

    /* Ensure we have a clean session */
    uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION;
    /* Send connection request to the broker. */
    ret = mqtt_connect(&client, MQTT_CLIENT_ID, NULL, NULL, 0, user_name, pass, connect_flags, 400);
    if (ret != MQTT_OK)
    {
        LOG_E("MQTT init fail");
    }
    /* check that we don't have any errors */
    if (client.error != MQTT_OK) {
        LOG_E("error: %s", mqtt_error_str(client.error));
        test_close();
    }
    xTaskCreate(client_refresher, (char*)"client_ref", 1024, &client, 10, &client_daemon);
    return 0;
}

void mqtt_app_diconnect(void)
{
    test_close();
}
/**
 * @brief  mqtt_app_publish
 *
 * @param topic
 * @param payload
 * @param qos
 * @return int
*/
int mqtt_app_publish(const char* topic, const char* payload, int qos)
{
    static enum MQTTPublishFlags qos_flags;
    if (qos==0)qos_flags = MQTT_PUBLISH_QOS_0;
    else if (qos==1)qos_flags = MQTT_PUBLISH_QOS_1;
    else qos_flags = MQTT_PUBLISH_QOS_2;

    mqtt_publish(&client, topic, payload, strlen(payload), qos_flags);
    if (client.error != MQTT_OK) {
        LOG_E("error: %s", mqtt_error_str(client.error));
        test_close();
        return -1;
    }
    return 0;
}

/**
 * @brief mqtt_app_subscribe
 *
 * @param topic
 * @param qos
 * @return int
*/
int mqtt_app_subscribe(char* topic, int qos)
{
    mqtt_subscribe(&client, topic, 0);
    return 0;
}


void mqtt_client_register_event(void)
{
    client.inspector_callback = _inspector_callback;
}

配置文件

#define SSID_KEY "SSID"
#define PASS_KEY "PASS"
#define USER_SSID               "******"
#define USER_PASSWORD               "******"
#define MQTT_HOST               "192.168.5*.*"
#define MQTT_PORT                1883
#define MQTT_USERNAME                "******"
#define MQTT_PASSWORD                "******"
#define MQTT_TOPIC                               "/HA/Ai/topic"
#define MQTT_MSG_OPEN_L                          "{status:true}"
#define MQTT_MSG_CLOSE_L                         "{status:false}"

如果感兴趣的话可以看下

[智能家居]小安派 DSL 通过MQTT 控制Home Assistant灯 https://bbs.ai-thinker.com/forum.php?mod=viewthread&tid=44671&fromuid=15918 (出处: 物联网开发者社区-安信可论坛)

【完全开源】智能桌面助手——AiPi-DSL_Dashboard https://bbs.ai-thinker.com/forum.php?mod=viewthread&tid=42026&fromuid=15918

自动化方案低配置,低代码。操作简单。

【【电子DIY作品】+ M61+VC02语音控制HA设备】 https://www.bilibili.com/video/BV1wvbdebEZY/?share_source=copy_web&vd_source=95f092a8edb82d1fb04a2d285b5f28a7

现在手里只有M61开发板,不知道有没有小一些功耗低一些的模组。希望一块小电池能坚持一个月那种。

😄 求推荐。外壳的话,因为这个属于方案验证,暂时没有设计。还有一些想法没有执行。从想到做还有很长的一段距离。

感觉发展方向符合我的预期,现在唯一不敢搞的就是市电。不敢乱搞怕把屋子点了。不然全屋定制就都可以自己改造了。乐趣就在于折腾。但一定注意安全。

回复

使用道具 举报

WT_0213 | 2024-8-21 09:03:22 | 显示全部楼层
【电子DIY作品】+ M61+VC02语音控制HA设备v1.1版
https://bbs.ai-thinker.com/forum ... 9&fromuid=15918
回复 支持 反对

使用道具 举报

WT_0213 | 2024-7-15 17:59:00 | 显示全部楼层

视频……

外壳……

想找个低功耗的模组做个完整的开关

200ma的小电池,没多久就没电了。

回复 支持 反对

使用道具 举报

爱笑 | 2024-7-15 17:59:01 | 显示全部楼层
我还在纳闷幸福哥怎么还没出手!迟来的爱啊
用心做好保姆工作
回复 支持 反对

使用道具 举报

WT_0213 | 2024-7-15 18:01:24 | 显示全部楼层
本帖最后由 WT_0213 于 2024-7-17 12:05 编辑
爱笑 发表于 2024-7-15 17:59
我还在纳闷幸福哥怎么还没出手!迟来的爱啊


回复 支持 反对

使用道具 举报

molun | 2024-7-16 00:14:58 | 显示全部楼层
等风,等雨,也等你!
回复

使用道具 举报

1084504793 | 2024-7-16 08:10:38 | 显示全部楼层
回复

使用道具 举报

jkernet | 2024-7-16 10:43:47 | 显示全部楼层
感谢分享!厉害!
回复 支持 反对

使用道具 举报

lazy | 2024-7-16 11:34:58 | 显示全部楼层
回复

使用道具 举报

djy876 | 2024-7-16 13:42:25 | 显示全部楼层
用的什么排版的,挺漂亮!
回复 支持 反对

使用道具 举报

USN | 2024-7-22 10:14:11 | 显示全部楼层
感谢分享!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则