Contributed by sujingliang, organized by Ai-Thinker
[Ai-WB2 Review] Bafa Cloud MQTT
1. Platform Preparation
**1. Log in to https://bemfa.com/注册个用户**

The system assigns a private key.
2. Select the MQTT device cloud

3. Create a topic
Topic name: AIWB2002; the last 3 digits, 002, indicate the device is a light
| Last three digits | Description |
|---|---|
| 001 | Socket device |
| 002 | Light bulb device |
| 003 | Fan device |
| 004 | Sensor |
| 005 | Air conditioner device |
| 006 | Switch device |
| 009 | Curtain device |
| 010 | Thermostat |
| 011 | Water heater |
| 012 | TV |
| 013 | Air purifier |


2. Modify the Program
Use applications/protocols/mqtt/tcp as the template
1. main.c
Click to expand full code
java
#define ROUTER_SSID
"SSID"
#define ROUTER_PWD
"PWD"Modify the Wi-Fi login SSID and password
- demo.c
Click to expand full code
java
void
mqtt_start
(
void
)
{
pwm_led_init();
//pwm 初始化
axk_mqtt_client_config_t
mqtt_cfg
=
{
.uri =
"mqtt://bemfa.com"
,
//巴法云地址
.port =
9501
,
//巴法云端口9501,不是1883
.client_id =
"平台提供的私钥"
,
.event_handle = event_cb,
//回调
};
axk_mqtt_client_handle_t
client
=
axk_mqtt_client_init(&mqtt_cfg);
axk_mqtt_client_start(client);
}The event_cb function
Click to expand full code
java
static
axk_err_t
event_cb
(axk_mqtt_event_handle_t event)
{
...
case
MQTT_EVENT_CONNECTED:
//MQTT建立连接事件
blog_info(
"MQTT_EVENT_CONNECTED"
);
// 订阅主题(如 light001)
axk_mqtt_client_subscribe(client,
"AIWB2002"
,
0
);
//订阅前面注册的AIWB2002主题
break
;
case
MQTT_EVENT_DATA:
//MQTT接收数据事件
blog_info(
"MQTT_EVENT_DATA"
);
printf(
"TOPIC=%.*s\r\n"
, event->topic_len, event->topic);
printf(
"DATA=%.*s\r\n"
, event->data_len, event->data);
// 判断指令并控制 GPIO
if
(strncmp(event->data,
"on#"
,
3
) ==
0
) {
//收到on#44,设置LED亮度为44
// 2. 提取亮度值(如 "44")
char
brightness_str[
4
] = {
0
};
int
brightness
=
0
;
strncpy(brightness_str, event->data +
3
, event->data_len -
3
);
brightness = atoi(brightness_str);
// 字符串转整数
// 3. 限制亮度范围(0~255)
if
(brightness <
0
) brightness =
0
;
if
(brightness >
255
) brightness =
255
;
rgb_control(
255
,
255
,
255
,brightness);
}
else
if
(strncmp(event->data,
"on"
, event->data_len) ==
0
) {
//收到on,设置LED亮度为255
blog_info(
"Turn ON LED"
);
rgb_control(
255
,
255
,
255
,
255
);
}
// 处理关闭指令(如 "off")
else
if
(strncmp(event->data,
"off"
, event->data_len) ==
0
) {
//收到off,设置LED亮度为0
rgb_control(
255
,
255
,
255
,
0
);
blog_info(
"Turn OFF LED"
);
}
break
;
...
}pwmled.c
Click to expand full code
java
#include <FreeRTOS.h>
#include <task.h>
#include <blog.h>
#include <bl602.h>
#include <bl602_gpio.h>
#include <bl602_glb.h>
#include <bl_pwm.h>
#include
"pwmled.h"
#define
PWM_Get_Channel_Reg
(ch)
(PWM_BASE+PWM_CHANNEL_OFFSET+(ch)*
0x20
)
#define
PWM_STOP_TIMEOUT_COUNT
(
160
*
1000
)
GLB_GPIO_Cfg_Type cfg[
3
] = {
{
.drive =
0
,
.smtCtrl =
1
,
.gpioMode = GPIO_MODE_OUTPUT,
.pullType = GPIO_PULL_DOWN,
.gpioPin =
14
,
/// red
.gpioFun =
8
,
},
{
.drive =
0
,
.smtCtrl =
1
,
.gpioMode = GPIO_MODE_OUTPUT,
.pullType = GPIO_PULL_DOWN,
.gpioPin =
17
,
/// green
.gpioFun =
8
,
},
{
.drive =
0
,
.smtCtrl =
1
,
.gpioMode = GPIO_MODE_OUTPUT,
.pullType = GPIO_PULL_DOWN,
.gpioPin =
3
,
/// blue
.gpioFun =
8
,
},
};
/// @brief Copy from PWM_Smart_Configure. Use Bus Clock instead of External Crystal Clock for PWM Timer
/// @param ch PWM Channel
/// @param clkDiv PWM clock divider
/// @param period PWM period
/// @param threshold2
/// @return
BL_Err_Type
PWM_Smart_Configure2
(PWM_CH_ID_Type ch, uint16_t clkDiv, uint16_t period,uint16_t threshold2)
{
uint32_t tmpVal;
uint32_t
timeoutCnt
=
PWM_STOP_TIMEOUT_COUNT;
/* Get channel register */
uint32_t
PWMx
=
PWM_Get_Channel_Reg(ch);
tmpVal = BL_RD_REG(PWMx, PWM_CONFIG);
// if(BL_GET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL) != PWM_CLK_XCLK){
if
(BL_GET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL) != PWM_CLK_BCLK){
BL_WR_REG(PWMx, PWM_CONFIG, BL_SET_REG_BIT(tmpVal, PWM_STOP_EN));
while
(!BL_IS_REG_BIT_SET(BL_RD_REG(PWMx, PWM_CONFIG), PWM_STS_TOP)){
timeoutCnt--;
if
(timeoutCnt ==
0
){
return
TIMEOUT;
}
}
// tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL, PWM_CLK_XCLK);
tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL, PWM_CLK_BCLK);
}
tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_OUT_INV, PWM_POL_NORMAL);
tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_STOP_MODE, PWM_STOP_GRACEFUL);
BL_WR_REG(PWMx, PWM_CONFIG, tmpVal);
/* Config pwm division */
BL_WR_REG(PWMx, PWM_CLKDIV, clkDiv);
/* Config pwm period and duty */
BL_WR_REG(PWMx, PWM_PERIOD, period);
BL_WR_REG(PWMx, PWM_THRE1,
0
);
BL_WR_REG(PWMx, PWM_THRE2, threshold2);
return
SUCCESS;
}
void
pwm_led_init
(
void
)
{
for
(
int
i
=
0
; i <
3
; i++) {
GLB_GPIO_Init(cfg + i);
PWM_CH_ID_Type
ch
=
cfg[i].gpioPin % PWM_CH_MAX;
PWM_Channel_Disable(ch);
}
}
void
pwm_led_set
(uint8_t red,uint8_t green,uint8_t blue)
{
PWM_Smart_Configure2(
2
,
80
,
255
, green);
PWM_Channel_Enable(
2
);
PWM_Smart_Configure2(
3
,
80
,
255
, blue);
PWM_Channel_Enable(
3
);
PWM_Smart_Configure2(
4
,
80
,
255
, red);
PWM_Channel_Enable(
4
);
}
void
rgb_control
(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
{
uint8_t t_red,t_green,t_blue;
// 应用透明度/亮度
t_red = red*alpha/
255
;
t_green = green*alpha/
255
;
t_blue = blue*alpha/
255
;
pwm_led_set(t_red,t_green,t_blue);
}3. Running
Bafa Cloud mini program



MQTTX debugging


4. XiaoDu Speaker + Bafa
The order of the pictures below is mixed up. The flow is: XiaoDu APP on the phone -> My -> Go to My Home -> + Add Device -> search for "Bafa" -> tap the created device "Light"
Then you can use the XiaoDu speaker to control the light by voice.
For example: "XiaoDu XiaoDu, turn on the light."









