Lemontree

[Internet of Things] Wireless switch based on Hi3861 mqtt protocol

 
Overview
# Wireless switch based on Hi3861 MQTT protocol## Existing design defects and solutions When IO8 is pulled up during power-on or reset, JTAG debugging will be turned on. However, JTAG IO multiplexing will cause UART IO to be occupied, causing the serial port log and download functions to be turned off. This phenomenon may also occur if only software is used to pull up IO8 before reset.

Therefore, when downloading, you need to press and hold KEY1 to pull IO8 low and then press RST to reset.

The fixing holes for size 86 may be M5? The fixing hole of the 86 box in my hand does not seem to be M3. ## Design idea Pressing the key controls the flipping of the virtual switch (Switch) in the program. The status of the virtual switch is synchronized with Home Assistant (hereinafter referred to as Hass) through MQTT. . Design automation in Hass to achieve linkage with other devices ## The hardware part of the hardware part refers to the size of the outer frame theme of the 86 box, which can be installed on the 86 box as a panel. At the same time, only buttons, Hi3861 modules and Type-C interfaces are reserved on the front. Guaranteed aesthetics. It is recommended to use solid copper to prevent cryptophobia ( ## Software part - the embedded software part mainly uses the Open Harmony (hereinafter referred to as ohos) routines provided by BearPi-HM Nano and the docker of the ohos development environment provided by Huawei Mirror. The program is developed based on the `D5_iot_mqtt` routine.

Automatically registering a device in Hass requires the device to actively send device information to the specified topic (Topic). I use the `cJSON` library to generate a json string. ```` int8_t RegisterHass(void ) { cJSON *device = cJSON_CreateObject(); cJSON_AddStringToObject(device, "identifiers", "abaaba"); cJSON_AddStringToObject(device, "manufacturer", "kaideDIY"); cJSON_AddStringToObject(device, "model", "Hi3861"); cJSON_AddStringToObject (device, "name", "ButtonBorad"); for (uint8_t i = 0; i < 4; i++) { char *pubtopic = regTopicList[i]; cJSON *payload_cjson = cJSON_CreateObject(); char temp_str[100]; sprintf (temp_str, "TestSwitchName%d", (int)i); cJSON_AddStringToObject(payload_cjson, "name", temp_str); sprintf(temp_str, "1234567890%02d", (int)i); cJSON_AddStringToObject(payload_cjson, "unique_id", temp_str); cJSON_AddStringToObject(payload_cjson, "command_topic", comTopicList[i]); cJSON_AddStringToObject(payload_cjson, "state_topic", stateTopicList[i]); cJSON_AddItemToObject(payload_cjson, "device", device); char *payload = cJSON_Print(payload_cjson) ; // clang-format off MQTTMessage message = { .qos = 2, .retained = 0, .payload = payload, .payloadlen = strlen(payload) }; // clang-format on int rc; if ((rc = MQTTPublish (&client, pubtopic, &message)) != 0) { printf("Return code from MQTT publish is %dn", rc); return WIFI_IOT_FAILURE; } delay_ms(500); } return WIFI_IOT_SUCCESS; } `` After registering the device Hass can issue instructions through the `command_topic` topic provided during registration, and will also subscribe to the `state_topic` topic to obtain status.

So we need to subscribe to the topic to receive the instructions from Hass, and after receiving them, we will parse the received instructions and change the virtual key state. ``` int8_t SubscribeSwitchTopic(void) {    int rc;    for (uint8_t i = 0; i < 4; i++) {        rc = MQTTSubscribe(&client, comTopicList[i], 0, Switch_CallBack);        if (rc != 0) {            printf("MQTTSubscribe: %dn", rc);            return WIFI_IOT_FAILURE;       }   }    return WIFI_IOT_SUCCESS; } void Switch_CallBack(MessageData *data) {    printf("Message arrived on topic %.*s: %.*sn",           data->topicName->lenstring.len, data->topicName->lenstring.data,           data->message->payloadlen, data->message->payload);    uint8_t switchID = 255;    char recTopic[50] = {0};    memcpy(recTopic, data->topicName->lenstring.data,           data->topicName->lenstring.len);    for (uint8_t i = 0; i < 4; i++) {        if (strcmp(recTopic, comTopicList[i]) == 0) {            switchID = i;            break;       }   }    if (switchID == 255) {        return;   }    char recString[4] = {0};    if (data->message->payloadlen > 4) {        return;   }    memcpy(recString, data->message->payload, data->message->payloadlen);    if (strcmp(recString, "ON")) {        switchState &= (~(1 << (3 - switchID))) & 0x0f;   } else {        switchState |= (1 << (3 - switchID));   }    // printf("SWID:%d,SWState:%dn", switchID, switchState);    SendSwitchState(); } ``` 同时定时发送虚拟按键状态来保持和Hass的同步 ``` int8_t SendSwitchState(void) {    int rc;    char state_to_send[4] = {0};    // clang-format off    MQTTMessage state_message = {       .qos = 2,       .retained = 0,       .payload = state_to_send   };    // clang-format on    uint8_t switchID = 1 << 3;    for (uint8_t i = 0; i < 4; i++) {        if (switchState & switchID) {            memcpy(state_to_send, "ON", 3);       } else {            memcpy(state_to_send, "OFF", 4);       }        state_message.payloadlen = strlen(state_to_send);        if ((rc = MQTTPublish(&client, stateTopicList[i], &state_message)) != 0) {            printf("Return code from MQTT publish is %dn", rc);            return WIFI_IOT_FAILURE;       }        switchID >>= 1;   }    return WIFI_IOT_SUCCESS; } ``` 在死循环中扫描按键改变虚拟开关的状态,同时心跳上传虚拟开关状态。 ```    uint8_t i = 0;    while (true) {        // 扫描到按键状态改变时发送按键状态        uint8_t keyState = Key_Scan();        if (keyState != 0) {            if (switchState & keyState) {                switchState &= ~keyState;           } else {                switchState |= keyState;           }            // printf("keyState:%d switchState:%dn", keyState, switchState);       }        // 1s心跳上报        if (++i == 10) {            i = 0;            if (SendSwitchState() != WIFI_IOT_SUCCESS) { printf("SendSwitchState failedn"); goto failure; } // printf("SWHeartBeat:%dn", switchState); } delay_ms(100); } '` Button scanning ``` uint8_t Key_Scan(void) { WifiIotIoName KeyList[] = {KEY0_Pin, KEY1_Pin, KEY2_Pin, KEY3_Pin}; WifiIotGpioValue keyState; uint8_t allKeysState = 0; for (uint8_t i = 0; i < 4; i++) { keyState = WIFI_IOT_GPIO_VALUE1; GpioGetInputVal(KeyList[i], &keyState); if (keyState == WIFI_IOT_GPIO_VALUE0) { allKeysState |= 1; while (keyState == WIFI_IOT_GPIO_VALUE0) { GpioGetInputVal(KeyList[i], &keyState); delay_ms(100); } } allKeysState < <= 1; } return allKeysState >> 1; } ``` Please see attachment ## for the specific code. Software part - Server-side MQTT has three identities, agent (that is, server), publisher and subscriber. So we are going to make a server to run the MQTT broker. I used docker to install mosquitto and installed it on the same machine as Hass. The MQTT plug-in must also be installed in Hass to connect to the broker.

![mqtt_plugin.png] Since we use the automatic configuration scheme, Hass will automatically add the devices registered in the embedded part ## The linkage to achieve synchronized switches and light switches mainly relies on four automations, and automatically activates another switch when the switch operates. It should be noted that the duration must be added for 1s, otherwise it may cause an infinite loop.

![auto_trigger.png] ![auto_action.png] ## For the mechanical part, due to factors such as being too lazy to buy M5 screws and the 86 box being difficult to install, I made a bracket (SW2020) suitable for installation. Above

![holder_sw.png] It is a fai4.5 hole. You can use a soldering iron to make a copper nut with an outer diameter of M5 and an inner diameter of M3, and then use M3 screws as set screws to fix it on the beam. Of course, in order not to leave marks on the beam, it is recommended to place a piece of useless PCB (


![holer.JPG]
参考设计图片
×
 
 
Search Datasheet?

Supported by EEWorld Datasheet

Forum More
Update:2025-07-01 16:54:06

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
community

Robot
development
community

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号