【微信小程序控制硬件③】 从软件到硬件搭建一个微信小程序控制esp8266的项目,自定义通信协议,为面试职位和比赛项目加分!

微信小程序控制硬件第1篇 】 全网首发,借助 emq 消息服务器带你如何搭建微信小程序的mqtt服务器,轻松控制智能硬件!
微信小程序控制硬件第2篇 】 开始微信小程序之旅,导入小程序Mqtt客户端源码,实现简单的验证和通信于服务器!
微信小程序控制硬件第3篇 】 从软件到硬件搭建一个微信小程序控制esp8266的项目,自定义通信协议,为面试职位和比赛项目加分!
微信小程序控制硬件第4篇 】 深度剖析微信公众号配网 Airkiss 原理与过程,esp8266如何自定义回调参数给微信,实现绑定设备第一步!
微信小程序控制硬件第5篇 】理清接下来必须走的架构思想,学习下 JavaScript 的观察者模式,在微信小程序多页面同时接收到设备推送事件!
微信小程序控制硬件第6篇 】服务器如何集成七牛云存储SDK,把用户自定义设备图片存储在第三方服务器!
微信小程序控制硬件第7篇 】动起来作一个微信小程序Mqtt协议控制智能硬件的框架,为本身内心全栈工程师梦想浇水!!
微信小程序控制硬件第8篇 】微信小程序以 websocket 链接阿里云IOT物联网平台mqtt服务器,封装起来使用就是这么简单!
微信小程序控制硬件第9篇 】巧借阿里云物联网平台的免费链接,从微信小程序颜色采集控制 esp8266 输出七彩灯效果,中秋节来个直播如何?!
微信公众号控制硬件 第10篇 】如何在微信公众号网页实现链接mqtt服务器教程!!
微信小程序控制硬件 第11篇 】全网首发,微信小程序ble蓝牙控制esp32,实现无需网络也能够控制亮度开关。css


1、前言;

  • 网上留言抨击历来不是一天两天的事情,为此霍建华退出微博是情有可原的,由于水军太多了!男人大丈夫,不拘小节,作本身的事情,让别人说去吧。好了,从去年自学前端知识H5+css+js,从上个星期给你们带来的服务器搭建,今天有幸给你们带来个人小项目,对于学习微信小程序控制智能硬件(包括esp8266)的原理与过程,我以为对你有必定的启发!
  • 再次声明:到目前(2018/11/28)为止,微信小程序不支持给智能设备配网! 微信仅仅支持微信公众号给智能设备配网!

2、准备材料;

  • ①:智能硬件esp8266最小系统一个,LED一个,2个轻触开关,杜邦线若干;
  • ②:在微信公众平台:https://mp.weixin.qq.com 注册我的微信小程序 , 下载开发者工具点我下载
  • ③:服务器要求支持wsswebsocket+ssl并且该端口必须是443,为了你们方便,我这里教你们怎么接入百度天工服务器,由于百度天工已经支持微信小程序了!固然了,你能够看我第一篇怎么搭建属于本身域名的微信小程序MQTT服务器,用本身的服务器做为桥梁也行!看业务须要!

3、通信原理以及如何拟定通信协议;

  • 注意角色:(设备 --> 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]

4、开始服务器准备;


  • 对于服务器的搭建,一直都是咱们嵌入式开发攻城狮的弊病,由于咱们确实不懂怎么弄服务器开发!呵呵!好,那么我带你们用百度天工服务器去搭建咱们的微信小程序MQTT硬件服务器!仍是啰嗦一句,若是您有本身的服务器,那么这个章节能够不看!

第一步:在百度云:https://console.bce.baidu.com 注册帐号,找到 物接入 loT Hubhtml

在这里插入图片描述

第二步:这个 物接入 loT Hub接入也不是彻底免费的,是按照流量收费的,我选择为1元一个月的流量而后付款一年才十元,足够本身一我的用了!以后选择建立项目,按照以下步骤:前端

在这里插入图片描述


第三步:在认真观看了上面协议的通信协议以后,咱们按照上面的协议来建立策略。java

在这里插入图片描述


第四步:以后咱们要去建立身份,拿到MQTT链接的密码和帐号!吐槽下,真麻烦,还要说什么是身份列表,呵呵。web

在这里插入图片描述


第五步:建立策略后,咱们还须要建立用户!过程当中的身份、策略选择都是上几个步骤建立的便可!而后,咱们点击设备测试下;面试

在这里插入图片描述


第六步:同样的步骤,咱们一共要建立2个用户,一个是设备esp8266,一个是微信小程序链接客户端;json


五 、微信小程序代码部分详解;


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();

七 、电路原理图以及开发过程的睬坑记录;


在这里插入图片描述

  • 原理图很是简单:小程序

  • ①:gpio0gpio2都要上拉,虽然内部已经上拉。微信小程序

  • ②:按键的另外一端都是接地,咱们代码是降低沿触发中断!七牛云存储

  • 效果图:

在这里插入图片描述


八 、后记;


  • 微信小程序是本人周末一天开发的,并且协议和服务器搭建是花费蛮多时间的,最重要的是,这博文是花费几乎五个小时排版和编写,哈哈!各位能力强的朋友就参考我思路能够了,群里有些人要Bug个人代码,因此,我小费出售,下面是联系方式!
  • 只求真诚交易!本工程包括微信小程序源码、8266源码。咸鱼APP扫描联系我!

在这里插入图片描述