微信小程序控制硬件-从软件到硬件搭建一个微信小程序控制esp8266的项目,自定义通讯协议,为面试职位和比赛项目加分
目录
【微信小程序控制硬件③】 从软件到硬件搭建一个微信小程序控制esp8266的项目,自定义通讯协议,为面试职位和比赛项目加分!
微信物联网生态主要分在 微信硬件开发平台 与 腾讯物联开发平台 ,前者已经停止维护,但依然有着很大的学习价值,而后者作为主推的平台,集成很多功能,包括从微信小程序实现配网到控制;
为了兼顾更多的朋友和自己的学习笔记,我将会一直更新此专题笔记,欢迎关注 ,带你走进前沿领域,学习前沿技术!
自搭微信服务器&&微信硬件开发平台
腾讯物联开发平台
文章目录
一、前言;
- 网上留言抨击从来不是一天两天的事情,为此霍建华退出微博是情有可原的,因为水军太多了!男人大丈夫,不拘小节,做自己的事情,让别人说去吧。好了,从去年自学前端知识
H5+css+js
,从上个星期给大家带来的服务器搭建,今天有幸给大家带来我的小项目, 对于学习微信小程序控制智能硬件(包括esp8266
)的原理与过程,我觉得对你有一定的启发! - 再次声明: 到目前(2018/11/28)为止,微信小程序不支持给智能设备配网! 微信仅仅支持微信公众号给智能设备配网!
二、准备材料;
- ①:智能硬件
esp8266
最小系统一个,LED一个,2
个轻触开关,杜邦线若干; - ②:在 注册个人微信小程序 , 下载开发者工具 。
- ③:服务器要求支持
wss
即websocket+ssl
, 而且该端口必须是443
,为了大家方便,我这里教大家怎么接入 ,因为百度天工已经支持微信小程序了!当然了,你可以看我第一篇怎么搭建属于自己域名的微信小程序MQTT
服务器,用自己的服务器作为桥梁也行!看业务需要!
三、通讯原理以及如何拟定通讯协议;
- 注意角色: (设备 –> esp8266,设备商云 –> 服务器,微信客户端 –> 微信小程序):
- 先上图,也请认真观看上图,这是我本篇实现的控制过程,也是我想到的控制过程,哈哈!
- 概述
:
- ①:服务器我们不用
微信硬件云
,而是我们自己的服务器,上位机就是微信客户端,我们是在微信的环境下开发的,也就避免不了和微信打交道,避免不了要遵循微信开发的规范!所以要有一定的前端开发知识哦!也就是
H5+css+javaSrcipt
,微信的小程序开发和这个非常相似!如果想入门微信小程序开发,自己可以去琢磨! - ②:设备商云也就是我们的服务器,仅仅做一个中转信号处理,不做任何的消息存储和分析哈!
- ③:通讯过程是 esp8266上报消息到服务器,服务器转发消息到微信小程序!反过来,微信小程序控制下发,先发送消息到服务器,然后到esp8266!
- ④:既然服务器仅仅是一个中转信号处理,那么我们的微信小程序和esp8266的通讯协议,自己拟定就好,下面是我拟定的,也是本文项目的协议!
- ①:服务器我们不用
微信硬件云
,而是我们自己的服务器,上位机就是微信客户端,我们是在微信的环境下开发的,也就避免不了和微信打交道,避免不了要遵循微信开发的规范!所以要有一定的前端开发知识哦!也就是
- 微信小程序下发控制的通讯协议 :
主题 | 发送端 | 接收端 | 消息(JSON格式) | 消息含义 |
---|---|---|---|---|
/light/deviceOut | 微信小程序 | esp8266 | “{“change”:“power”,“value”:true}” | 开灯 |
“{“change”:“power”,“value”:“false”}” | 关灯 | |||
“{“change”:“pwm”,“value”:50}” | 调节亮度:value为亮度值 ,范围 [0,100] | |||
“{“change”:“query”,“value”:0}” | 微信小程序主动请求最新状态 |
- esp8266上报同步的通讯协议 :
主题 | 发送端 | 接收端 | 消息(JSON格式) | 消息含义 |
---|---|---|---|---|
/light/deviceIn | esp8266 | 微信小程序 | “{“power”:“false”,“brightNess”:50}” | power为灯的状态,brightNess是亮度值,范围 [0,100] |
四、开始服务器准备;
- 对于服务器的搭建,一直都是我们嵌入式开发攻城狮的弊病,因为我们确实不懂怎么弄服务器开发!呵呵!好,那么我带大家用百度天工服务器去搭建我们的微信小程序
MQTT
硬件服务器!还是啰嗦一句,如果您有自己的服务器,那么这个章节可以不看!
第一步:在百度云:https://console.bce.baidu.com 注册账号,找到 物接入 loT Hub 。
第二步:这个 物接入 loT Hub 接入也不是完全免费的,是按照流量收费的,我选择为1元一个月的流量然后付款一年才十元,足够自己一个人用了!之后选择创建项目,按照如下步骤:
第三步:在认真观看了上面协议的通讯协议之后,我们按照上面的协议来创建策略。
第四步:之后我们要去创建身份,拿到
MQTT
连接的密码和账号!吐槽下,真麻烦,还要说什么是身份列表,呵呵。
第五步:创建策略后,我们还需要创建用户!过程中的身份、策略选择都是上几个步骤创建的即可!然后,我们点击设备测试下;
第六步:一样的步骤,我们一共要创建2个用户,一个是设备
esp8266
,一个是微信小程序连接客户端;
五 、微信小程序代码部分详解;
5.1 配置获取;
- 作为客户端,连接的域名和端口号以及
MQTT
的账号密码肯定需要的!那么上面已经拿到了账号和密码,那么域名和端口号在哪呢?看下图:
- 微信小程序开发的第一步,就是必须要在微信小程序后台配置下域名和地址,这个有必要去配置下,下面的服务器域名就填上面这个!
- 之后我们用微信小程序开发工具打开我提供的微信小程序工程,配置详情:
5.2 代码讲解;
- 连接核心代码,主要看注释:
- 第一步:先配置好服务器连接的参数,之后开始连接;
- 第二步:设置服务器下发回调函数,并在里面解析数据做我们的
UI
同步工作。 - 第三步:特别注意,我们在异常回调函数检测到异常断开服务器之后,要重连服务器哦!
connect: function() {
var that = this;
//获取全局变量,server_domain是MQTT服务器的域名
var client = new Client(app.globalData.server_domain, "DeviceId-7zne322b0g");
client.connect({
useSSL: true, //使用SSL
cleanSession: true, //清理会话为true
keepAliveInterval: 60, //心跳
userName: '7qfp623/wechatapp', //用户名
password: '5bXUJ3FfTJdK95sdh9', //用户密码
onSuccess: function() {
wx.showToast({
title: '连接成功'
})
that.data.client = client
// 服务器下发消息回调匿名回调处理
client.onMessageArrived = function(msg) {
if (typeof that.data.onMessageArrived === 'function') {
return that.data.onMessageArrived(msg)
}
console.log("收到消息:" + msg.payloadString);
var jsonObj = JSON.parse(msg.payloadString);
if (typeof jsonObj.power == "boolean")
console.log("解析 power :" + jsonObj.power);
if (typeof jsonObj.brightNess == "number")
console.log("解析 brightNess :" + jsonObj.brightNess);
//根据esp8266发过来的 power字段内容做不同的图片显示
var temp;
if (jsonObj.power == true) {
temp = '../pic/light_on.jpg'; //开灯图片加载显示
} else
temp = '../pic/light_off.jpg'; //关灯图片加载显示
//开始同步界面显示处理
that.setData({
valueSlier: jsonObj.brightNess,
lightValue: jsonObj.brightNess,
isOpen: jsonObj.power,
valuePic:temp,
})
}
//开始订阅主题
that.subscribe(app.globalData.subTopic, {
qos: 1
})
//连接异常断开,我们要做重连服务器的逻辑
client.onConnectionLost = function(responseObject) {
if (typeof that.data.onConnectionLost === 'function') {
return that.data.onConnectionLost(responseObject)
}
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:" + responseObject.errorMessage);
//检测到与服务器断开连接,设置定时函数一秒后重新连接服务器
setTimeout(function() {
_self.connect();
}, 1000)
}
}
//每次连接服务器都要主动查询设备的最新状态,保证界面是最新状态!
var obj = new Object();
obj.change = "query";
obj.value = 0;
that.publish(app.globalData.pubTopic, JSON.stringify(obj), 1, false)
}
});
}
- 我们的控制界面的代码非常简答,也就是绑定几个变量罢了!
<view class="container">
<view>
<image src="{{valuePic}}" class='imgLight'></image>
</view>
<view class='item-power'>
<text class='ele_text'>电源:</text>
<switch bindchange="onSwitch" checked="{{isOpen}}" class='ele_switch' />
</view>
<view class='line'></view>
<view class='item_adjust_light'>
<text class="section_title">当前亮度:{{lightValue}}</text>
<slider value="{{valueSlier}}"class='slider' block-size="20" activeColor="#00BFFF" bindchange="eventSlider"/>
</view>
</view>
- 看起来还是蛮整洁的!hh –em!
- 下面是按钮和拖动条的点击回调函数处理发送消息到设备代码,至于
CSS
样式代码,我就不贴了!
//拖动条点击下发
eventSlider: function(e) {
console.log("发生 change 事件,携带值为:" + e.detail.value);
this.setData({
lightValue: e.detail.value
})
//开始构造json数据
var obj = new Object();
obj.change = "pwm";
obj.value = e.detail.value;
//开始发布消息
this.publish(app.globalData.pubTopic, JSON.stringify(obj), 1, false)
},
//按键触发
onSwitch: function(e) {
console.log("onSwitch success :" + e.detail.value);
//开始构造json数据
var jsonObj = new Object();
jsonObj.change = "power";
jsonObj.value = "" + e.detail.value + "";
//开始发布消息
this.publish(app.globalData.pubTopic, JSON.stringify(jsonObj), 1, false)
},
六 、 esp8266
工程代码部分详解;
- 首先说明的是,这份代码是基于
Rtos 2.2
的 ,不是3.0
版本的哈!而且MQTT
连接库是我提供的,在我的GitHub
有,稳定性不得说很好哈!- ①:按键长按触发一键配网模式
smartConfig
,短按就是调节亮度的明暗,很好! - ②:短按调节明暗,也要上报到服务器以此同步上位机的控制面板!
- ③:因为我们的
pwm
调节方法输入的参数duty
是0到1023,但是我们的微信小程序发来的是0到100,所以要转换一下,这样就可以了:pwm_set_duty(1023 * apkPwm / 100, 0);
,其中apkPwm
是微信小程序发来的数值!
- ①:按键长按触发一键配网模式
- 按键回调代码:
//按键一短按的回调逻辑处理
static void key_13_short_press(void) {
INFO("short press..");
//每次pwm百分比输出加10,如果大于100强制为最大值100!
apkPwm += 10;
if (apkPwm > 100) {
apkPwm = 100;
}
pwm_set_duty(1023 * apkPwm / 100, 0); //因为微信发来的是 0到100,我们取百分比之后再相乘 1023
pwm_start();
//上报当前状态服务器
post_data_to_clouds();
}
//按键一长按3秒的回调逻辑处理
static void key_13_long_press(void) {
INFO("long press.. into smartConfig..");
//标志位设置为5,下次开机读取标志位,如果为5就进去配网模式
u8 saveNumber[4];
saveNumber[0] = 5;
spi_flash_erase_sector(520);
spi_flash_write(520 * 4096, (uint32 *) &saveNumber, 4);
//重启
system_restart();
}
//按键二短按的回调逻辑处理
static void key_sw2_short_press(void) {
INFO("short press..");
//每次减去百分比10的亮度,当小于0强制为0;
apkPwm -= 10;
if (apkPwm < 0) {
apkPwm = 0;
}
pwm_set_duty(1023 * apkPwm / 100, 0); //因为微信发来的是 0到100,我们取百分比之后再相乘 1023
pwm_start();
//上报当前状态服务器
post_data_to_clouds();
}
//按键二长按3秒的回调逻辑处理
static void key_sw2_long_press(void) {
INFO("long press.. into smartConfig..");
//标志位设置为5,下次开机读取标志位,如果为5就进去配网模式
u8 saveNumber[4];
saveNumber[0] = 5;
spi_flash_erase_sector(520);
spi_flash_write(520 * 4096, (uint32 *) &saveNumber, 4);
//重启
system_restart();
}
- 服务器配置:从下面可以看到,我们硬件是走
TCP
的,所以端口号是1883
,以此同时,订阅的主题发布的主题和微信小程序刚刚是相反的!
//MQTT服务器设置
//MQTT ip地址或域名
#define MQTT_BROKER_HOST "7qfp6898.mqtt.iot.gz.baidubce.com"
//端口号
#define MQTT_BROKER_PORT 1883
//userName
#define MQTT_USER_NAME "7qfp6898/esp8266"
//userPassword
#define MQTT_USER_PASSWORD "5bXUJ3FfTJdKs8h9"
- 下面是收到服务器下发的消息的逻辑处理:
//收到消息
INFO("topic:\"%s\"", rMsg.topic);
INFO("payload(%3d)---> %s", rMsg.payloadlen, rMsg.payload);
/**
* 解析 "{"change":"power","value":true}"
*/
cJSON *pRoot = cJSON_Parse(rMsg.payload);
if (NULL == pRoot) {
INFO("arrive Error get Json : [%s] ",
cJSON_GetErrorPtr());
cJSON_Delete(pRoot);
break;
}
INFO("-----------arrive ok get Json-------------");
cJSON *pJSON_change = cJSON_GetObjectItem(pRoot, "change");
if (!pJSON_change) {
cJSON_Delete(pRoot);
INFO("- error parse Json : pJSON_change --");
break;;
}
cJSON *pJSON_value = cJSON_GetObjectItem(pRoot, "value");
//判断是否开关按钮
if (strcmp(pJSON_change->valuestring, "power") == 0) {
INFO("--arrive ok get Json --> power-------------");
if (strcmp(pJSON_value->valuestring, "true") == 0) {
pwm_set_duty(512, 0); //开灯
pwm_start();
apkPwm = 50;
} else {
apkPwm = 0;
pwm_set_duty(0, 0); //关灯
pwm_start();
}
post_data_to_clouds();//同步上报服务器
//判断是否调节亮度
} else if (strcmp(pJSON_change->valuestring, "pwm") == 0) {
INFO("---arrive ok get Json --> pwm-------------");
u8 value = pJSON_value->valueint;
apkPwm = value;
pwm_set_duty(1023 * value / 100, 0); //因为微信发来的是 0到100,我们取百分比之后再相乘 1023
pwm_start();
post_data_to_clouds();//同步上报服务器
} else if (strcmp(pJSON_change->valuestring, "query")
== 0) {
post_data_to_clouds(); //同步上报服务器
}
cJSON_Delete(pRoot);
- 下面是程序入口部分:
//按键初始化
TaskKeyInit();
//station模式开启
wifi_set_opmode(STATION_MODE);
u8 tempSaveData[4];
spi_flash_read(520 * 4096, (uint32 *) &tempSaveData, 4);
//如果标志位读取失败
if (tempSaveData[0] == -1) {
tempSaveData[0] = 1;
spi_flash_erase_sector(520);
spi_flash_write(520 * 4096, (uint32 *) &tempSaveData, 4);
}
printf("spi_flash_read tempSaveData--> %d \n" ,tempSaveData[0]);
if (tempSaveData[0] == 5 ) {
//进去配网模式
xTaskCreate(TaskSmartConfig, "TaskSmartConfig", 512, NULL, 2, NULL);
//记得恢复标志为0
u8 saveNumber[4];
saveNumber[0]=0;
spi_flash_erase_sector(520);
spi_flash_write(520 * 4096, (uint32 *) &saveNumber, 4);
} else {
//否则则自动连接上次过的路由器
wifi_set_event_handler_cb(wifi_event_handler_cb);
//设置自动连接
wifi_station_connect();
}
uint32 pwm_duty_init[1] = { 0 };
uint32 io_info[][3] = { { PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12, 12 } }; //GPIO12作为pwm输出脚位
pwm_init(1000, pwm_duty_init, 1, io_info); //初始化 PWM
pwm_set_duty(1023, 0); //最大亮度
pwm_start();
七 、电路原理图以及开发过程的睬坑记录;
- 原理图非常简单:
- ①:
gpio0
和gpio2
都要上拉,虽然内部已经上拉。 - ②:按键的另一端都是接地,我们代码是下降沿触发中断!
- 效果图:
八 、后记;
- 微信小程序是本人周末一天开发的,而且协议和服务器搭建是花费蛮多时间的,最重要的是,这博文是花费几乎五个小时排版和编写,哈哈!需要的私聊我!