设计的目的

大部分家用电器开关仍旧是传统的机械式按键开关,原因是传统式的电器开关开发周期短,制作成本低,方案成熟,但是传统的遥控家电开关已经不能满足人们对家电控制的要求,传统的遥控器具有单一性, 每种遥控器只能控制一种家用电器,随着家用电器的逐步增加,使得众多的遥控器很难去分辨。随着科学技术的快速发展,人们对生活品质的要求也不断提高,开始追求更好的生活方式。因此,为了适应物质生活的需求,智能家居小助手系统应运而生。例如:回到家时,饭已煮好,房间温度合适,热水器中的水也已经加热,既舒服又方便。另外,用户还能随时改变家用电器的工作状态,既节能又安全。

智能家居( Smart Home)小助手系统是以家为平台,兼备建筑、自动化,智能化于一体的高效、舒适、安全、便利的家居环境。采用智能手机APP、网页、小程序等进行家电的控制具有夸时代的进步,因为通过WiFi的方式不再受到遥控器型号的限制,传统的家用电器开关需要匹配的遥控器才能进行有效的操作,当有了WiFi技术,操作的便利性得到很大的提高。

简介

STM32单片机设计的智能家居小助手,结合单片机的外围电路实现对整个系统的控制,报警电路由蜂鸣器组成,单片机显示部分采用OLED显示,可以通过查看OLED或者按键设置温湿度、光照强度的阀值,利用通过STM32单片机采集温湿度、光照强度、雨滴模块等的数据通过连接WIFI使用ESP8266模块发送数据到服务端,然后通过网页、小程序、APP来显示和修改数据,从而可以相互通信。而且我们只需要增加或者减小在核心板的传感器,从而测量环境中的数据。

设计思路

采用STM32单片机作为主控芯片,ESP8266 WIFI 模块作为无线接收和发射模块,利用手机 APP 、网页、小程序对家用电器进行控制。研究手机终端作为信号的发出源,通过连接WIFI 信号,利用相应的控制软件以 WIFI 网络信号为载体发送相关数据信号,WiFi 模块主要的任务就是作为一个载体,将终端发送来的信号传递给单片机,以单片机为中心的控制模块就实时完成数据的处理,CPU处理之后将会输出相应的电平控制继电器,来实灯光的亮灭等一系列智能家居的功能。

硬件电路模块STC89C52DHT11(温湿度模块)BH1750(光照强度模块)蜂鸣器LEDESP8266步进电机土壤湿度模块等等。

软件设计APP小程序网页

  • (1)单片机采集数据,可以通过OLED的UI菜单可以显示对应的数据。
  • (2)单片机通过串口发送数据给ESP8266,然后ESP8266通过WIFI发送数据到MQTT服务端。
  • (3)通过查看OLED,可以通过按键设置温湿度、光照强度、土壤湿度等每一个模块对应的阀值,从而更好的控制。
  • (4)通过小程序、APP、网页,可以控制LED、风扇等设备。
  • (5)系统设计完成3路家电开关的开启与关闭控制,相互之间不能有干扰。
  • (6)显示时间,这样方便实用。

硬件设备

软件小程序

设计流程

硬件

  • 首先通过STM32主控器读取温湿度及光照模块的具体数值,然后通过计算转为实际单位数值;将得到的具体环境数值通过ESP8266-wifi模块发送至远程服务器端,在通过前端显示出来。前端的显示目前由微信小程序实现。
  • 蜂鸣器作为环境报警响应,有被动式及主动式。被动式因环境参数超过预定标准触发。主动式可通过实体按键或小程序进行通断。LED作为日光灯功能,有自动式及主动式。自动式通过判断环境亮度自行触发。主动式可通过实体按键或小程序进行灯的通断。

软件

小程序设计

小程序使用 MPVUE 构架开发,使用开发工具:VSCODE+微信开发工具。

基础使用

  • 1.安装全局vue-cli
npm install --global vue-cli@2.9
  • 2.创建一个mpvue-quickstart模板的新项目
vue init mpvue/mpvue-quickstart project

3.安装依赖

cd project

npm install

npm run dev

成功后可以看到以下文件夹:

主要介绍src目录和static 目录 ,static 目录主要放静态文件。

src目录下有:

pages 主要用于写view ,compontents 写template,utils写public js

pages下边写view ,一般的文件结构都是类似 index.vue main.js main.json 这样的三个文件,

index.vue 写我们的vue文件,mpvue 支持大多数的vue语法,例如具体支持什么不支持什么:http://mpvue.com/mpvue/#_9 请传送致官网main.js :暴露index.vue 文件

main.json 写配置文件

使用微信api

  • 1.首先导出wx

然后在需要的页面使用

main.js

接下来是indx.vue 文件

wx.getLocation是获取当前的地理位置、速度。

整个index.vue文件如下

查看天气

服务器设计

我们使用自己的云服务器安装开源的EMQ服务器,通过EMQ,我们可以通过MQTT可以让8266和小程序、网页和APP结合。EMQ服务器可以实现高并发,多用户在线访问,也不会网络出现问题。

EMQ下载

下载地址:https://www.emqx.io/downloads#broker

下载界面如下图所示:

我们此处选择了开原版。

  • 版本号为:v4.2.11
  • 系统和软件:Linux/centos7/zip
  • 下载后的文件为: emqx-centos7-4.2.11-x86_64.zip

解压缩包

具体命令如下:

unzip  emqx-centos7-4.2.11-x86_64.zip

emqttd目录结构如下图所示:

bin目录结构如下图所示:

启动EMQ服务器

具体命令如下:

./emqttd start

该命令在bin目录下。

启动状态查询确认

具体命令如下:

./emqttd_ctl status

该命令在bin目录下。

浏览器访问确认

访问地址:http://39.97.125.79:18083

这里的IP地址,是我本地虚拟机中CentOS系统的IP地址,服务器部署在那台主机上,应该把IP地址换成对应主机的真实地址。

访问后会出现登陆界面,如下图所示:

输入用户名和密码,尝试是否能正常登陆。

  • 用户名:admin
  • 密码:public

登陆后如果出现下图的界面,则表示EMQ服务器已正常运行。

MQTT服务器安装完成,MQTT使用EMQX,STM32通过WIFI模块把数据上传MQTT服务器,然后小程序订阅STM32设备的主题,就可以获取STM32设备的数据,同样STM32可以订阅小程序的主题。

Code

STM32

main.c

#include "led.h"
#include "key.h"
#include "beep.h"
#include "delay.h"
#include "sys.h"
#include "timer.h"
#include "usart.h"
#include "dht11.h"
#include "bh1750.h"
#include "oled.h"
#include "exti.h"
#include "stdio.h"

u8 alarmFlag = 0;//是否报警的标志
u8 alarm_is_free = 10;//报警器是否被手动操作,如果被手动操作即设置为0

u8 humidityH;      //湿度整数部分
u8 humidityL;      //湿度小数部分
u8 temperatureH;   //温度整数部分
u8 temperatureL;   //温度小数部分
extern char oledBuf[20];
float Light = 0; //光照度
u8 Led_Status = 0;

char PUB_BUF[256];//上传数据的buf
const char *devSubTopic[] = {"/mysmarthome/sub"};
const char devPubTopic[] = "/mysmarthome/pub";

 int main(void)
 {    
    unsigned short timeCount = 0;    //发送间隔变量

    delay_init();             //延时函数初始化     
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
    LED_Init();              //初始化与LED连接的硬件接口
    KEY_Init();              //初始化与按键连接的硬件接口
    EXTIX_Init();        //外部中断初始化
    BEEP_Init();
    DHT11_Init();
    BH1750_Init();
    Usart1_Init(115200);//debug串口
    Usart2_Init(115200);//stm32-8266通讯串口
    OLED_Init();
    OLED_ColorTurn(0);//0正常显示,1 反色显示
    OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
    OLED_Clear();
    TIM2_Int_Init(4999,7199);
    TIM3_Int_Init(2499,7199);
    UsartPrintf(USART_DEBUG, " Hardware init OK\r\n");


    BEEP = 0;//鸣叫提示接入成功
    delay_ms(250);
    BEEP = 1;


    while(1)
    {
        if(timeCount % 40 == 0)//1000ms / 25 = 40 一秒执行一次
        {
            /********** 温湿度传感器获取数据**************/
            DHT11_Read_Data(&humidityH,&humidityL,&temperatureH,&temperatureL);
            UsartPrintf(USART_DEBUG,"温度:%d.%d  湿度:%d.%d",humidityH,humidityL,temperatureH,temperatureL);
            /********** 光照度传感器获取数据**************/
            if (!i2c_CheckDevice(BH1750_Addr))
            {
                Light = LIght_Intensity();
                UsartPrintf(USART_DEBUG,"当前光照度为:%.1f lx\r\n", Light);
            }

            if(alarm_is_free == 10)//报警器控制权是否空闲 alarm_is_free == 10 初始值为10
            {
                if((humidityH < 80) && (temperatureH < 30) && (Light < 1000))alarmFlag = 0;
                else alarmFlag = 1;
            }
            if(alarm_is_free < 10)alarm_is_free++;
        }
        if(++timeCount >= 200)    // 5000ms / 25 = 200 发送间隔5000ms
        {
            Led_Status = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4);//读取LED0的状态
            UsartPrintf(USART_DEBUG, "OneNet_Publish\r\n");
            sprintf(PUB_BUF,"{\"Hum\":%d.%d,\"Temp\":%d.%d,\"Light\":%.1f,\"Lique\":1200,\"Natu\":1400,\"Smoke\":1250,\"Led\":%d,\"Beep\":%d}",
                humidityH,humidityL,temperatureH,temperatureL,Light,Led_Status?0:1,alarmFlag);
            UsartPrintf(USART2,PUB_BUF);
            timeCount = 0;

        }
        delay_ms(10);
    }
}

bh1750.c

#include "bh1750.h"
#include "sys.h"

/*
    应用说明:
    在访问I2C设备前,请先调用 i2c_CheckDevice() 检测I2C设备是否正常,该函数会配置GPIO
*/


static void I2C_BH1750_GPIOConfig(void);


/*
*********************************************************************************************************
*    函 数 名: i2c_Delay
*    功能说明: I2C总线位延迟,最快400KHz
*    形    参:无
*    返 回 值: 无
*********************************************************************************************************
*/
static void i2c_Delay(void)
{
    uint8_t i;

    /* 
         下面的时间是通过逻辑分析仪测试得到的。
    工作条件:CPU主频72MHz ,MDK编译环境,1级优化

        循环次数为10时,SCL频率 = 205KHz 
        循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 
         循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us 
    */
    for (i = 0; i < 10; i++);
}

/*
*********************************************************************************************************
*    函 数 名: i2c_Start
*    功能说明: CPU发起I2C总线启动信号
*    形    参:无
*    返 回 值: 无
*********************************************************************************************************
*/
void i2c_Start(void)
{
    /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
    BH1750_I2C_SDA_1();
    BH1750_I2C_SCL_1();
    i2c_Delay();
    BH1750_I2C_SDA_0();
    i2c_Delay();
    BH1750_I2C_SCL_0();
    i2c_Delay();
}

/*
*********************************************************************************************************
*    函 数 名: i2c_Start
*    功能说明: CPU发起I2C总线停止信号
*    形    参:无
*    返 回 值: 无
*********************************************************************************************************
*/
void i2c_Stop(void)
{
    /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
    BH1750_I2C_SDA_0();
    BH1750_I2C_SCL_1();
    i2c_Delay();
    BH1750_I2C_SDA_1();
}

/*
*********************************************************************************************************
*    函 数 名: i2c_SendByte
*    功能说明: CPU向I2C总线设备发送8bit数据
*    形    参:_ucByte : 等待发送的字节
*    返 回 值: 无
*********************************************************************************************************
*/
void i2c_SendByte(uint8_t _ucByte)
{
    uint8_t i;

    /* 先发送字节的高位bit7 */
    for (i = 0; i < 8; i++)
    {        
        if (_ucByte & 0x80)
        {
            BH1750_I2C_SDA_1();
        }
        else
        {
            BH1750_I2C_SDA_0();
        }
        i2c_Delay();
        BH1750_I2C_SCL_1();
        i2c_Delay();    
        BH1750_I2C_SCL_0();
        if (i == 7)
        {
             BH1750_I2C_SDA_1(); // 释放总线
        }
        _ucByte <<= 1;    /* 左移一个bit */
        i2c_Delay();
    }
}

/*
*********************************************************************************************************
*    函 数 名: i2c_ReadByte
*    功能说明: CPU从I2C总线设备读取8bit数据
*    形    参:无
*    返 回 值: 读到的数据
*********************************************************************************************************
*/
uint8_t i2c_ReadByte(void)
{
    uint8_t i;
    uint8_t value;

    /* 读到第1个bit为数据的bit7 */
    value = 0;
    for (i = 0; i < 8; i++)
    {
        value <<= 1;
        BH1750_I2C_SCL_1();
        i2c_Delay();
        if (BH1750_I2C_SDA_READ())
        {
            value++;
        }
        BH1750_I2C_SCL_0();
        i2c_Delay();
    }
    return value;
}

/*
*********************************************************************************************************
*    函 数 名: i2c_WaitAck
*    功能说明: CPU产生一个时钟,并读取器件的ACK应答信号
*    形    参:无
*    返 回 值: 返回0表示正确应答,1表示无器件响应
*********************************************************************************************************
*/
uint8_t i2c_WaitAck(void)
{
    uint8_t re;

    BH1750_I2C_SDA_1();    /* CPU释放SDA总线 */
    i2c_Delay();
    BH1750_I2C_SCL_1();    /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
    i2c_Delay();
    if (BH1750_I2C_SDA_READ())    /* CPU读取SDA口线状态 */
        re = 1;
    else
        re = 0;
    BH1750_I2C_SCL_0();
    i2c_Delay();
    return re;
}

/*
*********************************************************************************************************
*    函 数 名: i2c_Ack
*    功能说明: CPU产生一个ACK信号
*    形    参:无
*    返 回 值: 无
*********************************************************************************************************
*/
void i2c_Ack(void)
{
    BH1750_I2C_SDA_0();    /* CPU驱动SDA = 0 */
    i2c_Delay();
    BH1750_I2C_SCL_1();    /* CPU产生1个时钟 */
    i2c_Delay();
    BH1750_I2C_SCL_0();
    i2c_Delay();
    BH1750_I2C_SDA_1();    /* CPU释放SDA总线 */
}

/*
*********************************************************************************************************
*    函 数 名: i2c_NAck
*    功能说明: CPU产生1个NACK信号
*    形    参:无
*    返 回 值: 无
*********************************************************************************************************
*/
void i2c_NAck(void)
{
    BH1750_I2C_SDA_1();    /* CPU驱动SDA = 1 */
    i2c_Delay();
    BH1750_I2C_SCL_1();    /* CPU产生1个时钟 */
    i2c_Delay();
    BH1750_I2C_SCL_0();
    i2c_Delay();    
}

/*
*********************************************************************************************************
*    函 数 名: I2C_BH1750_GPIOConfig
*    功能说明: 配置I2C总线的GPIO,采用模拟IO的方式实现
*    形    参:无
*    返 回 值: 无
*********************************************************************************************************
*/
static void I2C_BH1750_GPIOConfig(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(BH1750_RCC_I2C_PORT, ENABLE);    /* 打开GPIO时钟 */

    GPIO_InitStructure.GPIO_Pin = BH1750_I2C_SCL_PIN | BH1750_I2C_SDA_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;      /* 开漏输出 */
    GPIO_Init(BH1750_GPIO_PORT_I2C, &GPIO_InitStructure);

    /* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
    i2c_Stop();
}

/*
*********************************************************************************************************
*    函 数 名: i2c_CheckDevice
*    功能说明: 检测I2C总线设备,CPU向发送设备地址,然后读取设备应答来判断该设备是否存在
*    形    参:_Address:设备的I2C总线地址
*    返 回 值: 返回值 0 表示正确, 返回1表示未探测到
*********************************************************************************************************
*/
uint8_t i2c_CheckDevice(uint8_t _Address)
{
    uint8_t ucAck;
    i2c_Start();        /* 发送启动信号 */
    /* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 */
    i2c_SendByte(_Address | BH1750_I2C_WR);
    ucAck = i2c_WaitAck();    /* 检测设备的ACK应答 */

    i2c_Stop();            /* 发送停止信号 */

    return ucAck;
}

//BH1750写一个字节
//返回值    成功:0        失败:非0 
uint8_t BH1750_Byte_Write(uint8_t data)
{
    i2c_Start();
    //发送写地址
    i2c_SendByte(BH1750_Addr|0);
    if(i2c_WaitAck()==1)
        return 1;
    //发送控制命令
    i2c_SendByte(data);
    if(i2c_WaitAck()==1)
        return 2;
    i2c_Stop();
    return 0;
}

//BH1750读取测量数据
//返回值 成功:返回光照强度     失败:返回0
uint16_t BH1750_Read_Measure(void)
{
    uint16_t receive_data=0; 
    i2c_Start();
    //发送读地址
    i2c_SendByte(BH1750_Addr|1);
    if(i2c_WaitAck()==1)
        return 0;
    //读取高八位
    receive_data=i2c_ReadByte();
    i2c_Ack();
    //读取低八位
    receive_data=(receive_data<<8)+i2c_ReadByte();
    i2c_NAck();
    i2c_Stop();
    return receive_data;    //返回读取到的数据
}


//BH1750s上电
void BH1750_Power_ON(void)
{
    BH1750_Byte_Write(POWER_ON);
}

//BH1750s断电
void BH1750_Power_OFF(void)
{
    BH1750_Byte_Write(POWER_OFF);
}

//BH1750复位    仅在上电时有效
void BH1750_RESET(void)
{
    BH1750_Byte_Write(MODULE_RESET);
}

//BH1750初始化
void BH1750_Init(void)
{
    I2C_BH1750_GPIOConfig();        /* 配置GPIO */

    BH1750_Power_ON();    //BH1750s上电
    //BH1750_RESET();            //BH1750复位
    BH1750_Byte_Write(Measure_Mode);
    //SysTick_Delay_ms(120);
}

//获取光照强度
float LIght_Intensity(void)
{
    return (float)(BH1750_Read_Measure()/1.1f*Resolurtion);
}

WIFI-ES8266 code

···#include <ESP8266WiFi.h>
#include <PubSubClient.h>

#include <NTPClient.h>
// change next line to use with another board/shield
#include <ESP8266WiFi.h>
//#include <WiFi.h> // for WiFi shield
//#include <WiFi101.h> // for WiFi 101 shield or MKR1000
#include <WiFiUdp.h>
WiFiUDP ntpUDP;

// You can specify the time server pool and the offset (in seconds, can be
// changed later with setTimeOffset() ). Additionaly you can specify the
// update interval (in milliseconds, can be changed using setUpdateInterval() ).
NTPClient timeClient(ntpUDP,"ntp1.aliyun.com",60*60*8,30*60*1000);

WiFiClient espClient;
PubSubClient client(espClient);

const char* wifissid = "iPhone xr"; //改成自己家wifi
const char* password = "qwertyuiop"; //改成自己家wifi

const char* mqtt_server = "wusiyuan.top";
const char* mqtt_id = "LYY_ESP";   //改成自己的QQ号+_ESP

//          订阅主题                                      
const char* Mqtt_sub_topic = "mysmarthome/sub1";   //订阅主题

//                 传感器发送的数据
const char* Mqtt_pub_topic = "mysmarthome/pub1";  //上报消息给手机APP的TOPIC 


long lastMsg = 0; //定时用的

String comdata = "";

void setup() {
  pinMode(2, OUTPUT);     
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void setup_wifi() {

  WiFi.begin(wifissid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

void callback(char* topic, byte* payload, unsigned int length) {
  String msg="";
  String LED_set = "";
  String BEEP_set = "";
    for (int i = 0; i < length; i++) {
    msg+= (char)payload[i];
    }
    Serial.println(msg);


}

void reconnect() {
  while (!client.connected()) {
    if (client.connect(mqtt_id)) {
      client.subscribe(Mqtt_sub_topic,1);
    } else {
      delay(5000);
    }
  }
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  long now = millis();
  if (now - lastMsg > 100) {
    lastMsg = now;
    char serialRead;
  while (Serial.available())
    {
        comdata += char(Serial.read());
        delay(2);

    }

     if (comdata.length() > 0)
    {
        String json = comdata;
        client.publish(Mqtt_pub_topic,json.c_str());
        comdata = "";
    }
  }
}

小程序Code

<template>
  <div class="wrapper">
    <div class="header-wrapper">
      <div class="header-title">
        <span>空气质量-{{airText}}</span>
        <span>设备一</span>
        <span>{{area}}-{{city}}</span>
      </div>
      <div class="header-text">
        <span>{{airValue}}</span>
        <span>{{weather}}</span>
      </div>
      <div class="weather-advice">{{weatherAdvice}}</div>
    </div>
    <div class="body-wrapper">
      <div class="body">

        <div class="data-wrapper">
          <div class="data">
            <img class="data-logo" src="/static/images/wendu.png" />
            <div class="data-text">
              <div class="data-title">温度</div>
              <div class="data-value">{{Temp}}℃</div>
            </div>
          </div>
          <div class="data">
            <img class="data-logo" src="/static/images/shidu.png" />
            <div class="data-text">
              <div class="data-title">湿度</div>
              <div class="data-value">{{Hum}}%</div>
            </div>
          </div>
        </div>

          <div class="data-wrapper">
             <div class="data">
             <img class="data-logo" src="/static/images/guangzhaodu.png" />
             <div class="data-text">
              <div class="data-title">光照度</div>
              <div class="data-value">{{Light}}Lx</div>
            </div>
          </div>
          <div class="data">
            <img class="data-logo" src="/static/images/yudu.png" />
            <div class="data-text">
              <div class="data-title">有毒气体</div>
              <div class="data-value">{{Lique}}p</div>
            </div>
          </div>
        </div>       

         <div class="data-wrapper">
          <div class="data">
            <img class="data-logo" src="/static/images/trq.png" />
            <div class="data-text">
              <div class="data-title">天然气</div>
              <div class="data-value">{{Natu}}p</div>
            </div>
          </div>
          <div class="data">
            <img class="data-logo" src="/static/images/yw.png" />
            <div class="data-text">
              <div class="data-title">烟雾</div>
              <div class="data-value">{{Smoke}}p</div>
            </div>
          </div>
        </div>

        <div class="data-wrapper">
          <div class="data">
            <img class="data-logo" src="/static/images/led.png" />
            <div class="data-text">
              <div class="data-title">客厅灯</div>
              <div class="data-value">
                <switch @change="onLedChange" :checked="Led" color="#3d7ef9" />
              </div>
            </div>
          </div>
          <div class="data">
            <img class="data-logo" src="/static/images/beep.png" />
            <div class="data-text">
              <div class="data-title">报警器</div>
              <div class="data-value">
                <switch @change="onBeepChange" :checked="Beep" color="#3d7ef9" />
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
      <div class="copyright-wrapper">
        <span class="copyright">Power By 行走的皮卡丘 © 2021</span>
    </div>
  </div>
</template>

<script>
import {connect } from '../../../node_modules/mqtt/dist/mqtt.js';

const mqttUrl = 'wxs://wusiyuan.top:8084/mqtt';

export default {
  data() {
    return {
      client: {},
      Temp: 0,   //温度
      Hum: 0,    //湿度
      Light: 0,  //光照
      Lique:0,   //有毒气体
      Natu:0,    //天然气
      Smoke:0,   //烟雾
      Led: false, //LED状态
      Beep: false,
      area: "请求中", //城区
      city: "请求中", //城市
      airText: "请求中", //空气优良
      airValue: 0, //空气指数
      weather: "请求中", //天气
      weatherAdvice: "请求中" //天气建议
    };
  },

  components: {},

  methods: {
    onLedChange(event) {
      var that = this;
      console.log(event.mp.detail);
      let sw = event.mp.detail.value;
      that.Led = sw;
      if (sw) {
        that.client.publish(
          "mysmarthome/sub",
          'A',
          function(err) {
            if (!err) {
              console.log("成功下发命令——开灯");
            }
          }
        );
      } else {
        that.client.publish(
          "mysmarthome/sub",
          'B',
          function(err) {
            if (!err) {
              console.log("成功下发命令——关灯");
            }
          }
        );
      }
    },
    onBeepChange(event) {
      var that = this;
      console.log(event.mp.detail);
      let sw = event.mp.detail.value;
      that.Beep = sw;
      if (sw) {
        that.client.publish(
          "mysmarthome/sub",
          'C',
          function(err) {
            if (!err) {
              console.log("成功下发命令——打开报警器");
            }
          }
        );
      } else {
        that.client.publish(
          "mysmarthome/sub",
          'D',
          function(err) {
            if (!err) {
              console.log("成功下发命令——关闭报警器");
            }
          }
        );
      }
    }
  },
  // created() {
  //   // let app = getApp()
  // },
  onShow() {
    var that = this;
    that.client = connect(mqttUrl);
    that.client.on("connect", function() {
      console.log("成功连接mqtt服务器!");
      that.client.subscribe("mysmarthome/pub", function(err) {
        if (!err) {
          console.log("成功订阅设备上行数据Topic!");
        }
      });
    });
    that.client.on("message", function(topic, message) {
      console.log(topic);
      // message是16进制的Buffer字节流
      let dataFromDev = {};
      dataFromDev = JSON.parse(message);
      console.log(dataFromDev);
      that.Temp = dataFromDev.Temp;
      that.Hum = dataFromDev.Hum;
      that.Light = dataFromDev.Light;
      that.Led = dataFromDev.Led;
      that.Beep = dataFromDev.Beep;
      that.Lique = dataFromDev.Lique;
      that.Natu = dataFromDev.Natu;
      that.Smoke = dataFromDev.Smoke;
    });
    wx.getLocation({
      type: "wgs84",
      success(res) {
        const latitude = res.latitude;
        const longitude = res.longitude;
        const key = "f7c21a960b0e47d1a97c13a91f7799c6";
        // console.log("LYY");
        wx.request({
          url: `https://free-api.heweather.net/s6/weather/now?location=${longitude},${latitude}&key=${key}`, //获取天气数据的api接口地址
          success(res) {
            //console.log(res.data);
            const { basic, now } = res.data.HeWeather6[0];
             console.log(basic);
            // console.log(now);
            that.area = basic.admin_area;
            that.city = basic.parent_city;
            that.weather = now.cond_txt;
            wx.request({
              url: `https://free-api.heweather.net/s6/air/now?location=${that.city}&key=${key}`, //获取空气数据的api接口地址
              success(res) {
                // console.log(res.data);
                const { air_now_city } = res.data.HeWeather6[0];
                // console.log(air_now_city);
                const { aqi, qlty } = air_now_city;
                that.airText = qlty;
                that.airValue = aqi;
              }
            });
          }
        });
        wx.request({
          url: `https://free-api.heweather.net/s6/weather/lifestyle?location=${longitude},${latitude}&key=${key}`, //获取空气数据的api接口地址
          success(res) {
            console.log(res.data);
            const { lifestyle} = res.data.HeWeather6[0];
            console.log(lifestyle)
            that.weatherAdvice = lifestyle[1].txt
          }
        });
      }
    });
  }
};
</script>

<style lang="scss" scoped>
.wrapper {
  padding: 15px;
  .header-wrapper {
    background-color: #3d7ef9;
    border-radius: 20px;
    color: #fff;
    box-shadow: #d6d6d6 0px 0px 5px;
    padding: 15px 30px;
    .header-title {
      display: flex;
      justify-content: space-between;
    }
    .header-text {
      font-size: 32px;
      font-weight: 400;
      display: flex;
      justify-content: space-between;
    }
    .weather-advice {
      margin-top: 20px;
      font-size: 12px;
    }
  }
   .copyright-wrapper {
    display: flex;
    justify-content: center;
    .copyright {
      color: #d6d6d6;
      position: fixed;
      bottom: 50px;
    }
  }
  .data-wrapper {
    margin-top: 20px;
    display: flex;
    justify-content: space-between;
    .data {
      background-color: #fff;
      width: 150px;
      height: 80px;
      border-radius: 20px;
      display: flex;
      justify-content: space-around;
      padding: 0 8px;
      box-shadow: #d6d6d6 0px 0px 5px;
      .data-logo {
        height: 36px;
        width: 36px;
        margin-top: 15px;
      }
      .data-text {
        margin-top: 15px;
        color: #7f7f7f;
        .data-title {
          text-align: right;
        }
        .data-value {
          font-size: 26px;
        }
      }
    }
  }
}
</style>