preface

The project is a project of the embedded courses last design, do not very good (bosses don’t spray ~), especially the STM32 data processing section, because just learning STM32, and the use of C language pointer, etc and some unfamiliar (although learned, but forget most), did not dare to use casually, so some code design is not good, Only a few simple functions can be performed. ESP8266 uses the NodeMCU development board, developed with ArduinoIDE (because there are so many libraries and data). The APP was developed by Android Studio. I referred to many people’s codes from the Internet and finally modified them into my own. It took about 2 weeks (mainly because there were classes in the middle and some knowledge had to be learned), but in the end the function was basically implemented and I learned a lot.

The specific functions include the following three aspects:

  1. TFTLCD can display the temperature (accuracy ±2°C), humidity (±5%RH), light (0~100, darkest 0, brightest 100) information collected by STM32 through DHT11 module and photosensitive resistor module. And display the set alarm temperature, the lowest light; In addition, ESP8266WIFI module can obtain the time (year-month-day hour: minute: second) and weather information (temperature, humidity, weather, wind) of the local city through the network.

  2. STM32 can drive the buzzer to emit sound when the indoor temperature is too high (exceeding the alarm temperature), and drive the LED to light up when the indoor brightness is low (below the set minimum light).

  3. In any place that can be connected to the network, the self-designed mobile APP can display the indoor environment information (temperature, humidity, light intensity), and can set the alarm temperature (0~100°C) and the lowest light (0~100).

STM32 end program design

Function is introduced

  1. The STM32 MCU collects temperature and humidity using the DHT11 temperature and humidity sensor

  2. The voltage of the photosensitive resistor after voltage division is collected by an ANALOG-to-digital converter (ADC), and then converted into light intensity

  3. The serial port receives ESP8266 information and extracts time, weather information, alarm temperature and minimum light information (from APP, used to control the opening and closing of buzzer and LED)

  4. When the indoor temperature exceeds the alarm temperature, the buzzer starts; When the indoor light is low (below the set minimum light), the LED lights up

The overall block diagram is as follows:

The specific implementation

The following will mainly introduce some functions, the complete code please see:

Complete code open source address -Gitee

Complete code open source address -Github

Temperature and humidity collection

Example Initialize the DHT11 module

/ / DHT11 initialization
// Returns 0: initialization succeeded, 1: failed
u8 DHT11_Init(a)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);

	GPIO_InitStructure.GPIO_Pin=DHT11;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIO_DHT11,&GPIO_InitStructure);
	GPIO_SetBits(GPIO_DHT11,DHT11);	   / / up

	DHT11_Rst();	  
	return DHT11_Check();	
}

/ / reset DHT11
void DHT11_Rst(a)	   
{                 
	DHT11_IO_OUT(); 	//SET OUTPUT
    DHT11_DQ_OUT=0; 	/ / low DQ
    delay_ms(20);    	// Pull down at least 18ms
    DHT11_DQ_OUT=1; 	//DQ=1 
	delay_us(30);     	// raise the host by 20 to 40us
}
// Wait for DHT11 to respond
// Return 1: the presence of DHT11 is not detected
// Returns 0: exists
u8 DHT11_Check(a) 	   
{   
	u8 retry=0;
	DHT11_IO_IN();//SET INPUT	 
    while (DHT11_DQ_IN&&retry<100)//DHT11 will drop 40~50us
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)return 1;
	else retry=0;
    while(! DHT11_DQ_IN&&retry<100)//DHT11 will be raised again by 40~50us
	{
		retry++;
		delay_us(1);
	};
	if(retry>=100)return 1;	    
	return 0;
}

Copy the code

Read the data

// Read a bit from DHT11
// Return value: 1/0
u8 DHT11_Read_Bit(void) 			 
{
    u8 retry=0;
    while(DHT11_DQ_IN&&retry<100)// Wait to turn low 12-14us start
    {
        retry++;
        delay_us(1);
    }
    retry=0;
    while(! DHT11_DQ_IN&&retry<100)// Wait to change high level 26-28us indicates 0,116-118us indicates 1
    {
        retry++;
        delay_us(1);
    }
    delay_us(40);/ / wait 40 us
    if(DHT11_DQ_IN)return 1;
    else return 0;		   
}

// Read a byte from DHT11
// Return value: read data
u8 DHT11_Read_Byte(void)    
{        
    u8 i,dat;
    dat=0;
    for (i=0; i<8; i++) { dat<<=1; 
       dat|=DHT11_Read_Bit();
    }						    
    return dat;
}

 // Read the data from DHT11 and store it in the parameter variables temp and humi
 // Temp: temperature value (range :0~50°)
 // HUMI: humidity value (range: 20%-90%)
 // Return value: 0, normal; 1. The read fails
 u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
 {        
     u8 buf[5];
     u8 i;
     DHT11_Rst();
     if(DHT11_Check()==0)
     {
         for(i=0; i<5; i++)// Read 40 bits of data
         {
             buf[i]=DHT11_Read_Byte();
         }
         if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
         {
             *humi=buf[0];
             *temp=buf[2]; }}else return 1;
     return 0;       
 }
Copy the code

Light gathering

The partial pressure of the photoresistor is collected using an ADC3 analog-to-digital converter, which is then converted to light intensity (the conversion process takes the brightest as 100 and the darkest as 0 as the final result).

First, initialize ADC3

// Initialize the photosensor
void Lsens_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef ADC_InitStructure; 

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE);// Enable the PORTF clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE );	  // Enable the ADC3 channel clock
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3, ENABLE);/ / ADC reset
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3, DISABLE);// The reset is complete

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;/ / PF8 anolog input
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		// Simulate input pin
    GPIO_Init(GPIOF, &GPIO_InitStructure);	

    ADC_DeInit(ADC3);  // Set all the registers of ADC3 to default values

    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC working mode: independent mode
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;	// Analog-to-digital conversion works in single-channel mode
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	// Analog-to-digital conversion works in single conversion mode
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	// Transformations are initiated by software rather than external triggers
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	// Align ADC data right
    ADC_InitStructure.ADC_NbrOfChannel = 1;	// Number of ADC channels that perform sequential rule conversions
    ADC_Init(ADC3, &ADC_InitStructure);	// Initialize the register of the peripheral ADCx with the parameter specified in ADC_InitStruct

    ADC_Cmd(ADC3, ENABLE);	// Enable the specified ADC3

    ADC_ResetCalibration(ADC3);	// Enable reset calibration

    while(ADC_GetResetCalibrationStatus(ADC3));	// Wait for the reset calibration to finish

    ADC_StartCalibration(ADC3);	 // Enable AD calibration

    while(ADC_GetCalibrationStatus(ADC3));	 // Wait for the calibration to finish
}

Copy the code

And then collect the data

// Get the value of a channel ADC3
//ch: the channel value ranges from 0 to 16
// Return value: conversion result
u16 Get_ADC3(u8 ch)   
{
    // Sets the specified ADC rule group channel, a sequence, and sampling time
    ADC_RegularChannelConfig(ADC3, ch, 1, ADC_SampleTime_239Cycles5 );	//ADC3,ADC channel, sampling time is 239.5 cycles

    ADC_SoftwareStartConvCmd(ADC3, ENABLE);		// Enable the software conversion startup function of the specified ADC3

    while(! ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC ));// Wait for the conversion to finish

    return ADC_GetConversionValue(ADC3);	// Returns the result of the last ADC3 rule group conversion
} 


// Read the Light Sens value
/ / 0 ~ 100:0, the dark; 100, the brightest
u8 Lsens_Get_Val(void)
{
    u32 temp_val=0;
    u8 t;
    for(t=0; t<LSENS_READ_TIMES; t++) { temp_val+=Get_ADC3(ADC_Channel_6);// Read the ADC value
            delay_ms(5);
    }
    temp_val/=LSENS_READ_TIMES;// get the average value
    if(temp_val>4000)temp_val=4000;
    return (u8)(100-(temp_val/40));
}

Copy the code

Receives and processes data from serial port USART2

USART2 was initialized. Procedure

void usart2_init( void )
{	
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA2
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	// reuse push-pull output
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;// Float input
    GPIO_Init(GPIOA, &GPIO_InitStructure);// Initialize GPIOA

    //USART2 initializes the setting
    USART_InitStructure.USART_BaudRate = 115200;// Serial port baud rate
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;// The character length is in 8-bit data format
    USART_InitStructure.USART_StopBits = USART_StopBits_1;// a stop bit
    USART_InitStructure.USART_Parity = USART_Parity_No;// None Parity bit
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;// No hardware data flow control
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	// Send/receive mode
    USART_Init(USART2, &USART_InitStructure); // Initialize serial port 2

    USART_ClearFlag(USART2, USART_FLAG_TC);

    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);// Enable serial port acceptance and bus idle interrupt
    //USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);

    USART_Cmd(USART2, ENABLE);                    // Enable serial port 2

    / / USART2 NVIC configuration
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;// Preempt priority 3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		// Subpriority 3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			// The IRQ channel is enabled
    NVIC_Init(&NVIC_InitStructure);	// Initialize the VIC register with the specified parameters
}


Copy the code

Receive USART2 data

char USART2_RX_BUF[RX_BUF_MAX_LEN];
u16 USART2_RX_STA = 0;     

void USART2_IRQHandler(void)
{
    u8 r;
    if(USART_GetITStatus(USART2, USART_IT_RXNE) ! = RESET)// Receive is interrupted
    {
        r = USART_ReceiveData(USART2);//(USART2->DR); // Read the received data
        if((USART2_RX_STA&0x8000) = =0)// The reception is not complete
        {
            if(USART2_RX_STA&0x4000)// receive 0x0d(i.e. '\r')
            {
                if(r! =0x0a)USART2_RX_STA=0;// Receive error (that is, '\n' was not received), restart

                else {
                    //USART2_RX_STA|=0x8000; // Receive completed ('\r' received after '\n' received)
                    USART2_RX_STA = 0;  // Receive \n and wait for the next receive}}else // Not yet received 0X0D(i.e. '\r')
            {	
                if(r==0x0d)USART2_RX_STA|=0x4000; // If \r is received, place USART2_RX_STA at position 14 1
                else
                {
                    USART2_RX_BUF[USART2_RX_STA&0X3FFF]=r;
                    USART2_RX_STA++;
                    if(USART2_RX_STA>(RX_BUF_MAX_LEN- 1))USART2_RX_STA=0;// Failed to receive data
                }		 
            }
        } 		
    } 

}
Copy the code

Process the data received by USART2

Extracting time and weather information; For convenience, the data ESP8266 sends to STM32 are separated by commas, such as time, weather, temperature, humidity…

Weather data is stored in the structure

struct WeatherData{
    char datetime[20];
    char city[10];
    char weather[10];  // It was 10
    char temp[10];
    char humi[10];
    char windpower[10];  // Wind level
};
Copy the code

Process the data received by USART2

struct WeatherData processWdata(char data[]){
    / / char data [] = "2022-22-22 so when it comes: 33, Yin, 47, 13 < = 7";
    u8 i=0, j=0, i0=0, k=0;
	u8 ind=0, jnd=0;
	
    int slen = strlen(data);
    struct WeatherData weather;
	
    / / initialization
    for(ind=0; ind<8; ind++){
        switch(ind){
            case 0: {
                    for(jnd=0; jnd<20; jnd++){
                            weather.datetime[jnd]='\ 0'; }};break;
            case 1: {
                    for(jnd=0; jnd<10; jnd++){
                            weather.city[jnd]='\ 0'; }};break;
            case 2: {
                    for(jnd=0; jnd<10; jnd++){
                            weather.humi[jnd]='\ 0'; }};break;

            case 3: {
                    for(jnd=0; jnd<10; jnd++){
                            weather.temp[jnd]='\ 0'; }};break;
            case 4: {
                    for(jnd=0; jnd<10; jnd++){
                            weather.weather[jnd]='\ 0'; }};break;
            case 5: {
                    for(jnd=0; jnd<10; jnd++){
                            weather.windpower[jnd]='\ 0'; }};break;
            case 6: {
                    for(jnd=0; jnd<10; jnd++){
                            minLsens_str[jnd]='\ 0'; }};break;
            case 7: {
                    for(jnd=0; jnd<10; jnd++){
                            alarmTemp_str[jnd]='\ 0'; }};break; }}strcpy(weather.city, "Xi 'an");
    for(i=0; i<slen; i++){
        if(data[i]==', ') {
            i0++;
            for(j=k; j<i; j++){

                if(i0==1) weather.datetime[j-k]=data[j];
                else if(i0==2) weather.weather[j-k]=data[j];
                else if(i0==3) weather.temp[j-k]=data[j];
                else if(i0==4) weather.humi[j-k]=data[j];
                else if(i0==5) weather.windpower[j-k]=data[j];
                else if(i0==6) alarmTemp_str[j-k]=data[j];
                else if(i0==7) minLsens_str[j-k]=data[j];
            }
            k=i+1; }}return weather;
}
Copy the code

A string number is converted to an integer number

u8 str2int(char s[]){
    u8 n=0, i=0, len, sum=0;
    len = strlen(s);
    for(i=0; i<len; i++){
        if(47<s[i]<58){
            n = s[i] - 48;   // Get a digit
            sum += (n * pow(10, len- 1-i)); }}return sum;	
}
Copy the code

To send data

Sends data (in JSON string format) to ESP8266 by TIM2 timer 1s

Example Initialize TIM2

// Initialize TIM2
void TIM2_init(u16 arr, u16 psc){
    TIM_TimeBaseInitTypeDef TIM_Structure;
    NVIC_InitTypeDef NVIC_Structure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // Delay time (unit :s) : ARR /(72000000/ PSC)
    TIM_Structure.TIM_Period = arr - 1;  / / load values
    TIM_Structure.TIM_Prescaler = psc- 1;  // The frequency division coefficient
    TIM_Structure.TIM_ClockDivision = 0;
    TIM_Structure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_Structure);

    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // Start timer TIM2 interrupt
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    NVIC_Structure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_Structure.NVIC_IRQChannelPreemptionPriority = 6; // Preempt priority
    NVIC_Structure.NVIC_IRQChannelSubPriority = 4;  // Subpriority
    NVIC_Structure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_Structure);

    TIM_ClearFlag(TIM2, TIM_FLAG_Update);
    TIM_Cmd(TIM2, ENABLE);
}

Copy the code

Timer interrupt occurs when the timer time (1s is used in the project) reaches, and then enter the interrupt function to send data

void TIM2_IRQHandler(void){
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) ! = RESET){ ESP8266_Usart("{\"temp\":\"%d\",\"humi\":\"%d\",\"light\":\"%d\",\"ledsta\":\"%d\",\"beepsta\":\"%d\"}\r\n", dhtData.temp, dhtData.humi, lsens, ledSta, beepSta);// Output [light, temperature, humidity, LED, BEEP status] to ESP8266, and then send to mobile phoneTIM_ClearITPendingBit(TIM2, TIM_IT_Update); }}Copy the code

Control LED and buzzer

void ledBeepOnOrNot(u8 lsens, u8 mlsens, u8 t, u8 alarmT){  // Whether to enable LED and BEEP
    if(lsens < mlsens){
        LED1 = 0;  / / light
        ledSta = 1;  
    }

    else{
        LED1 = 1;  / / put out
        ledSta = 0;
    }

    if(t>alarmT){
        BEEP=1;         / / call
        beepSta = 1;
    }
    else{
        BEEP=0;			/ / don't call
        beepSta = 0; }}Copy the code

ESP8266 end program design

The ESP8266WIFI module connects to the server through MQTT protocol. After the data is published to the server, the Android client can subscribe to the topic of the server to get the message and then display it. The ESP8266 client can also obtain the messages published by the Android client by subscribing.

Function is introduced

  1. Connect the WiFi
  2. The LED lights up after startup, blinks when connected to MQTT server, and is not connected to steady on
  3. Obtain the following information from the network
    • Time: Use [Suning API]http://quan.suning.com/getSysTime.do
    • Weather: Use [Autonavi Weather API]http://restapi.amap.com/v3/weather/weatherInfo?key=xxxxx&city=610100)(Parameter key should be obtained by yourself, city is the city code)
  4. Data communication with STM32 through serial port
  5. Establish a connection to the MQTT server
  6. Publishes and receives messages to the topic specified by the server
  7. Json data processing

The specific implementation

ESP8266 is developed using the NodeMCU module, ArduinoIDE

Some global variables

/ / wifi configuration
const char* ssid = "xxxxxx";
const char* password = "xxxxxxxx";

// MQTT server connection configuration
const char *mqttBroker = "xxxxxx.iotcloud.tencentdevices.com";
const char *mqttUsername = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char *mqttPassword = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char *mqttClientId = "xxxxxxxxxxxesp8266";
const char *pubTopic = "xxxxxx/esp8266/data";
const char *subTopic = "xxxxxx/esp8266/data";
const int mqttPort = 1883;

/ / time API
const String timeUrl = "http://quan.suning.com/getSysTime.do";
// Autonavi API (get the key, city is the city code)
const String gaoDeUrl = "http://restapi.amap.com/v3/weather/weatherInfo?key=xxxxx&city=610100";

Copy the code

Connect the WiFi

void connectWifi(a){
  WiFi.mode(WIFI_STA);  WIFI_STA, WIFI_AP, WIFI_AP_STA
  WiFi.begin(ssid, password);

  while(WiFi.status() ! = WL_CONNECTED) { delay(500); }}Copy the code

Sending an HTTP request

String callHttp(String httpUrl) { 
  HTTPClient hClient;
  String message;
  hClient.begin(httpUrl); 
  
  int httpCode = hClient.GET();
  if (httpCode > 0) {
    if(httpCode == HTTP_CODE_OK) { String payload = hClient.getString(); message = payload; }}else {
    message = "[1-HTTP]failed, error:" + String(hClient.errorToString(httpCode).c_str());
  }
  hClient.end();
  return message;
}
Copy the code

Connect to the MQTT server

void connectMqttServer(a){
  while(! mqttClient.connected()) {if (mqttClient.connect(mqttClientId, mqttUsername, mqttPassword)) {
        subscribeTopic(subTopic);  // Subscribe to the topic
    } else {
        delay(2000);
// serial. println(" connection failed ");}}}Copy the code

Publishes information to the specified topic

void publishTopic(const char* topic, char* jsonMsg){
  mqttClient.publish(topic, jsonMsg, false);
}

Copy the code

Subscribe to the topic

// Subscribe to the specified topic
void subscribeTopic(const char* topic){
  if(mqttClient.subscribe(topic)){

  } else{}}Copy the code

Callback function (called when a message from the server is received)

void receiveCallback(char* topic, byte* payload, unsigned int length) {
  serverMsg = "";   // Clear the data at the next call
  for (int i = 0; i < length; i++) {
// Serial.print((char)payload[i]);
    serverMsg += (char)payload[i];
  }
// Serial.println("\n");
// Serial.println(serverMsg);
}

Copy the code

The complete code

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <ESP8266HTTPClient.h>
#include <WiFiManager.h>  

/ / wifi configuration
const char* ssid = "xxxxxx";
const char* password = "xxxxxxxx";

// MQTT server connection configuration
const char *mqttBroker = "xxxxxx.iotcloud.tencentdevices.com";
const char *mqttUsername = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char *mqttPassword = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char *mqttClientId = "xxxxxxxxxxxesp8266";
const char *pubTopic = "xxxxxx/esp8266/data";
const char *subTopic = "xxxxxx/esp8266/data";
const int mqttPort = 1883;

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

struct Weather{
  String wea="";
  String temp="";
  String windpower="";  // Wind force, unit: level
  String humi="";
};

struct ServerMsg{
  String alarmTemp="";
  String minLight="";
};

/ / time API
const String timeUrl = "http://quan.suning.com/getSysTime.do";
// Autonavi API (get the key, city is the city code)
const String gaoDeUrl = "http://restapi.amap.com/v3/weather/weatherInfo?key=xxxxx&city=610100";
String timeMsg="";
String weatherMsg="";
String timeAfterParse="";
struct Weather weatherAfterParse;
String data2stm="";   // Message sent to STM32 after packaging
String data2server="";  // Publish information to the MQTT server

String callHttp(String httpUrl);
String parseJsonTime(String tjson);
struct Weather parseJsonWeather(String wjson);
void ledOnOff(a);
String tqzh2py(String zhtq);    // The weather changes to pinyin
String windpowerFormat(String wp);

void connectWifi(a);
void setLedOnOff(a);
void publishTopic(const char* topic, char* jsonMsg);
void subscribeTopic(const char* topic);
struct ServerMsg parseServerMsg(String jsonMsg);
void getSerialDataAndProcess(a);

void setup(a) {
  pinMode(LED_BUILTIN, OUTPUT);     // Set the LED pin on the board to output mode
  digitalWrite(LED_BUILTIN, LOW);  // Turn on the LED on the board
  Serial.begin(115200);               // Start serial communication

  connectWifi();
  mqttInit();
  connectMqttServer();

  timeMsg = callHttp(timeUrl);
  weatherMsg = callHttp(gaoDeUrl);
}

struct ServerMsg serverMsgAfterParse;
String serverMsg="";
String stm32Msg="";
int n = 0;

void loop(a) {

  delay(500);
  n++;
    
  // Get network data (time, weather)
  
  if(n % 2= =0){
    ledOnOff();
    timeMsg = callHttp(timeUrl);
    if(n >= 20) {// get the weather every 10s
      weatherMsg = callHttp(gaoDeUrl);
      n=0; }}// Get stM32 data and send it to MQTT server
  getSerialDataAndProcess();

  // Process the data from the network
  if(timeMsg! =""){
    timeAfterParse = parseJsonTime(timeMsg);
  }
  if(weatherMsg! =""){
    weatherAfterParse = parseJsonWeather(weatherMsg);
  }
  if(serverMsg! =""){
    serverMsgAfterParse = parseServerMsg(serverMsg);
  }
  
  // Package and send to STm32
  if(timeMsg! =""&& weatherMsg! =""){
      data2stm = (timeAfterParse + "," + tqzh2py(weatherAfterParse.wea) + "," + weatherAfterParse.temp + "," +weatherAfterParse.humi +"," + windpowerFormat(weatherAfterParse.windpower) + "," + serverMsgAfterParse.alarmTemp + "," + serverMsgAfterParse.minLight + "," + "\r\n"); // Date, weather, temperature, humidity, wind level, alarm temperature, lowest light
      Serial.print(data2stm);
  }
  
  if (mqttClient.connected()) { // If the development board successfully connects to the server
    mqttClient.loop();          // Process information and heartbeat
  } else {                      // If the development board fails to connect to the server
    connectMqttServer();        // Attempts to connect to the server}}void mqttInit(a){
  mqttClient.setServer(mqttBroker, mqttPort);
  // Set the MQTT subscription callback function
  mqttClient.setCallback(receiveCallback);
}

// Connect to the MQTT server and subscribe to the information
void connectMqttServer(a){
  while(! mqttClient.connected()) {if (mqttClient.connect(mqttClientId, mqttUsername, mqttPassword)) {
        subscribeTopic(subTopic);  // Subscribe to the topic
    } else {
        delay(2000);
// serial. println(" connection failed ");}}}// Subscribe to the specified topic
void subscribeTopic(const char* topic){
  if(mqttClient.subscribe(topic)){

  } else{}}// The callback function after receiving the message
void receiveCallback(char* topic, byte* payload, unsigned int length) {
  serverMsg = "";   // Clear the data at the next call
  for (int i = 0; i < length; i++) {
// Serial.print((char)payload[i]);
    serverMsg += (char)payload[i];
  }
// Serial.println("\n");
// Serial.println(serverMsg);
}

struct ServerMsg parseServerMsg(String jsonMsg){
  struct ServerMsg smsg;
  const size_t capacity = 96;
  DynamicJsonDocument sdoc(capacity);
 
  // deserialize data
  deserializeJson(sdoc, jsonMsg);
  smsg.alarmTemp = sdoc["atemp"].as<String>();
  smsg.minLight = sdoc["mlight"].as<String>();
  return smsg;
}

void publishTopic(const char* topic, char* jsonMsg){
  mqttClient.publish(topic, jsonMsg, false);
}

void ledOnOff(a){
  static bool LEDState=0;
  if(mqttClient.connected()){ LEDState = ! LEDState;// Connect, LED flashing
  }
  else{
    LEDState = 0;   // Not connected, led is on
  }
  digitalWrite(LED_BUILTIN, LEDState);
}

String callHttp(String httpUrl) { 
  HTTPClient hClient;
  String message;
  hClient.begin(httpUrl); 
  
  int httpCode = hClient.GET();
  if (httpCode > 0) {
    if(httpCode == HTTP_CODE_OK) { String payload = hClient.getString(); message = payload; }}else {
    message = "[1-HTTP]failed, error:" + String(hClient.errorToString(httpCode).c_str());
  }
  hClient.end();
  return message;
}

void getTimeMsg(a){
  timeMsg = callHttp(timeUrl);
}

void getWeatherMsg(a){
  weatherMsg = callHttp(gaoDeUrl);  
}

String parseJsonTime(String tjson){

  const size_t capacity = 96;
  DynamicJsonDocument tdoc(capacity);
 
  // deserialize data
  deserializeJson(tdoc, tjson);
 
  // Get parsed data
  String datetime = tdoc["sysTime2"].as<String>();

  return datetime;
}


/ / {" status ":" 1 ", "count" : "1", "info" : "OK", "infocode" : "10000", "mattress" : [{" province ", "shanxi", "city" : "xi", "adcode" : "610100", "wea Ther, ":" clear ", "temperature", "13", "winddirection" : "north", "windpower" : "3", "or less humidity" : "88", "reporttime" : "the 2021-10-29 21:03:10"}}]
struct Weather parseJsonWeather(String wjson){
  
  struct Weather weather;

  const size_t capacity = 512;
  DynamicJsonDocument wdoc(capacity);
 
  // deserialize data
  deserializeJson(wdoc, wjson);

  JsonObject lives_0 = wdoc["lives"] [0];
  
  weather.wea = lives_0["weather"].as<String>(); / / "fine"
  weather.temp = lives_0["temperature"].as<String>(); 13 "/ /"
  weather.humi = lives_0["humidity"].as<String>(); / / "88"
  weather.windpower = lives_0["windpower"].as<String>(); / / "3" or less
  return weather;
}


String tqzh2py(String zhtq){  

  String zh_cn[68] = {"Fine"."Little cloud"."Sunny and cloudy"."Cloudy"."Yin"."The wind"."Calm"."The wind"."Wind"."The wind"."Strong wind"."Blast"."The wind"."Gale"."The storm".Blast of wind."Hurricane"."Tropical storm"."Haze"."Moderate haze"."Heavy haze"."Heavy haze"."Shower"."Thunder shower"."Thundershower with hail."."Rain"."Rain"."Rain"."Rain"."Heavy rain"."Heavy rain"."Heavy showers"."Severe thunderstorm"."Extreme rainfall"."Drizzle/drizzle"."Rain"."Light rain - Moderate rain"."Moderate rain - heavy rain"."Heavy rain. - Heavy rain."."Torrential rain." - Torrential rain.."Heavy rain." - Heavy rain.."Rain and snow"."Sleet"."Sleet"."Rain"."Snow"."Snow"."Light snow"."Moderate snow."."Snow"."Blizzard"."Light snow to moderate snow"."Moderate snow - heavy snow"."Heavy snow."."Dust"."Flying sand"."Sandstorm"."Strong sandstorm".Tornado."Fog"."Fog"."Heavy fog"."Mist"."The fog"."Extremely dense fog"."Hot"."Cold"."Unknown"}; String py[68] = {"qing"."shaoyun"."qingjianduoyun"."duoyun"."yin"."youfeng"."pingjing"."weifeng"."hefeng"."qingfeng"."qiangfeng/jinfeng"."jifeng"."dafeng"."liefeng"."fengbao"."kuangbaofeng"."jufeng"."redaifengbao"."mai"."zhongdumai"."zhongdumai"."yanzhongmai"."zhenyu"."leizhenyu"."leizhenyubingbanyoubingbao"."xiaoyu"."zhongyu"."dayu"."baoyu"."dabaoyu"."tedabaoyu"."qiangzhenyu"."qiangleizhenyu"."jiduanjiangyu"."maomaoyu/xiyu"."yu"."xiaoyu-zhongyu"."zhongyu-dayu"."dayu-baoyu"."baoyu-dabaoyu"."dabaoyu-tedabaoyu"."yuxuetianqi"."yujiaxue"."zhenyujiaxue"."dongyu"."xue"."zhenxue"."xiaoxue"."zhongxue"."daxue"."baoxue"."xiaoxue-zhongxue"."zhongxue-daxue"."daxue-baoxue"."fuchen"."yangsha"."shachenbao"."qiangshachenbao"."longjuanfeng"."wu"."nongwu"."qiangnongwu"."qingwu"."dawu"."teqiangnongwu"."re"."leng"."weizhi"};
  
  for(int i=0; i<68; i++){
    
   // if(strstr())
    if(zh_cn[i] == zhtq)
      return py[i];
    }
    
  return zhtq;  // Return Chinese if no
}
 
String windpowerFormat(String wp){
  
  if(wp=="3" or less) {return "< = 3";
  }
  return wp;
}

// To get the post-processing of the data, treat it as a serial interrupt function
void getSerialDataAndProcess(a){
  if (Serial.available()) {    // The data read by the serial port is forwarded to wifi, because the serial port is sent bit by bit, so it is cached here and then sent
    size_t countBytes = Serial.available();
    char sbuf[countBytes];
    Serial.readBytes(sbuf, countBytes);

// Serial.write(sbuf, countBytes);publishTopic(pubTopic, sbuf); Serial.flush(); }}void connectWifi(a){
  
// WiFiManager wifiManager;
//    
// Automatically connect to WiFi. The following statement takes the name of the WiFi when the ESP8266 is connected
// wifiManager.autoConnect("IamESP8266");

  WiFi.mode(WIFI_STA);  WIFI_STA, WIFI_AP, WIFI_AP_STA
  WiFi.begin(ssid, password);

  while(WiFi.status() ! = WL_CONNECTED) { delay(500); }}Copy the code

Android terminal program design

Function is introduced

Mainly through MQTT server, to obtain ESP8266 published information, and then processing display; At the same time, the APP can also publish messages to modify the alarm temperature and the lowest light value.

The specific implementation

Use Android Studio for development (please refer to Baidu for specific installation, download and environment configuration)

The project code is open source. Please go to GitHub and Gitee

Add MQTT dependencies

  1. Under its own [project]build.gradleAdd the following code
 repositories {
         google()
         mavenCentral()
         // Add the following code
         maven {
             url "https://repo.eclipse.org/content/repositories/paho-releases/"}}Copy the code
  1. Under the [project] / appbuild.gradleAdd the following code
 dependencies {
     compile 'org. Eclipse. Paho: org. Eclipse paho. Android. Service: 1.1.1'
     compile 'org. Eclipse. Paho: org. Eclipse paho. Client. Mqttv3:1.1.1'
 }
Copy the code

Then select the Sync Now message that pops up at the top

Access configuration

Modify androidmanifest.xml to add permissions

<! -- Allows applications to open network sockets -->
<uses-permission android:name="android.permission.INTERNET" />
<! Allow applications to obtain network status
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Copy the code

As follows:

display

Modify the activity_main. XML file to display the following information

The specific code is as follows:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <TextView
        android:layout_marginTop="20dp"
        android:layout_marginLeft="20dp"
        android:layout_marginBottom="10dp"
        android:id="@+id/house_env"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Indoor environment"
        android:textStyle="bold"
        android:textSize="20dp" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/show_temp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="20dp"
            android:layout_marginBottom="10dp"

            android:text="Temperature (° C)"
            android:textSize="20dp" />

        <TextView
            android:id="@+id/temp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="20dp"
            android:layout_marginBottom="10dp"
            android:text="0"
            android:textSize="20dp" />

        <TextView
            android:id="@+id/show_humi"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_marginTop="10dp"
            android:layout_marginLeft="20dp"
            android:layout_marginBottom="10dp"
            android:text="The humidity (RH %)"
            android:textSize="20dp" />
        <TextView
            android:id="@+id/humi"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_marginTop="10dp"
            android:layout_marginLeft="20dp"
            android:layout_marginBottom="10dp"
            android:text="0"
            android:textSize="20dp" />

    </LinearLayout>

    <LinearLayout android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
        <TextView
            android:id="@+id/show_light"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:text="Light intensity"
            android:textSize="20dp" />
        <TextView
            android:id="@+id/light"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:text="0"
            android:textSize="20dp" />

    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/ledsta1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:text="State of the LED"
            android:textSize="20dp" />
        <TextView
            android:id="@+id/ledsta2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:text="Closed"
            android:textSize="20dp" />

        <TextView
            android:id="@+id/beepsta1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:text="Buzzer status"
            android:textSize="20dp" />
        <TextView
            android:id="@+id/beepsta2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:text="Closed"
            android:textSize="20dp" />
    </LinearLayout>
    <TextView
        android:id="@+id/sets"
        android:layout_column="1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:layout_marginLeft="20dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:text="Settings"
        android:textStyle="bold"
        android:textSize="20dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/set_temp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:text="Alarm temperature (buzzer will alarm if current temperature exceeds this value)"
            android:textSize="15dp" />

        <TextView
            android:id="@+id/seekbarval1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="10dp"
            android:text="40"/>
    </LinearLayout>
    <SeekBar
        android:id="@+id/seekBar1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:layout_gravity="center"
        android:max="100"
        android:progress="40"/>
<! -- android:progressDrawable="@drawable/seekbar_progress" />-->

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/set_tlight"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:layout_marginLeft="20dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:text="Minimum light (current light below this value will light up the LED)"
            android:textSize="15dp" />

        <TextView
            android:id="@+id/seekbarval2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="20dp"
            android:text="12"/>
    </LinearLayout>
    <SeekBar
        android:id="@+id/seekBar2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:layout_gravity="center"
        android:max="100"
        android:progress="12"/>
<! -- android:progressDrawable="@drawable/seekbar_progress2" />-->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">


    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        >
        <Button
            android:layout_marginLeft="100dp"
            android:layout_marginTop="20dp"
            android:id="@+id/connectbtn"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:textColor="@color/white"
            android:text="Connection"/>

        <Button
            android:layout_marginTop="20dp"
            android:layout_marginRight="20dp"
            android:layout_marginLeft="20dp"
            android:id="@+id/exitbtn"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:textColor="@color/white"
            android:text="Quit"/>

    </LinearLayout>
    <TextView
        android:layout_margin="5dp"
        android:id="@+id/msgTxt"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:scrollbars="vertical"
        android:text=""/>
</LinearLayout>
Copy the code

Interface control

Next, modify mainActivity.java to add control actions so that the data can be displayed via TextView and a button can be pressed to react. Above, just create a static interface

package com.ajream.mqttdemo4;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class MainActivity extends AppCompatActivity {

    // Define a member
    private Button connectbtn;
    private Button exitbtn;

    private TextView temptv;
    private TextView humitv;
    private TextView lighttv;
    private TextView ledtv;
    private TextView beeptv;
    private TextView bar1tv;
    private TextView bar2tv;
    private TextView showmsgtv;

    private SeekBar tempbar;
    private SeekBar lightbar;

    // Information required for MQTT client configuration
    private String host = "tcp://xxxxxxx.iotcloud.tencentdevices.com:1883";  // Address and port of MQTT server (Tencent Cloud)
    private String userName = "xxxxxxxxxx";       // User name (check your device information in Tencent Cloud)
    private String passWord = "xxxxxxxxxx";			// Password (check your device information in Tencent Cloud)
    private String mqtt_id = "xxxxxxxxxxxxxxxxxxx";
    private String mqtt_sub_topic = "xxxxxxxxxx/AndroidClient/data";
    private String mqtt_pub_topic = "xxxxxxxxxx/AndroidClient/data";

    private ScheduledExecutorService scheduler;
    private MqttClient mqttClient;
    private MqttConnectOptions options;
    private Handler handler;

    private String msgToPublish = "";  // A message to publish
    private String alarmTempMsg = "";
    private String minLightMsg = "";
    JSONObject msgGet;

    @SuppressLint("HandlerLeak")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Associate the control
        connectbtn = findViewById(R.id.connectbtn);
        exitbtn = findViewById(R.id.exitbtn);
        temptv = findViewById(R.id.temp);
        humitv = findViewById(R.id.humi);
        lighttv = findViewById(R.id.light);
        ledtv = findViewById(R.id.ledsta2);
        beeptv = findViewById(R.id.beepsta2);
        bar1tv = findViewById(R.id.seekbarval1);
        bar2tv = findViewById(R.id.seekbarval2);
        showmsgtv = findViewById(R.id.msgTxt);

        tempbar = findViewById(R.id.seekBar1);
        lightbar = findViewById(R.id.seekBar2);

        alarmTempMsg = String.valueOf(tempbar.getProgress());
        minLightMsg = String.valueOf(lightbar.getProgress());

        /* Click the button to connect */
        connectbtn.setOnClickListener(view -> {
            Mqtt_init();
            startReconnect();
        });

        exitbtn.setOnClickListener(view -> {
            android.os.Process.killProcess(android.os.Process.myPid());
        });


        tempbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                Toast.makeText(MainActivity.this."Set alarm temperature to:" + progress, Toast.LENGTH_LONG).show();
                bar1tv.setText(check(progress));
                alarmTempMsg = check(progress);
            }


            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}@Override
            public void onStopTrackingTouch(SeekBar seekBar) {
// msgToPublish = alarmTempMsg + "," + minLightMsg;
                msgToPublish = "{\"atemp\":\"" + alarmTempMsg + "\",\"mlight\":\"" + minLightMsg+"\"}"; publishMsg(mqtt_pub_topic, msgToPublish); }}); lightbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                Toast.makeText(MainActivity.this."Set the lowest light to:" + i, Toast.LENGTH_LONG).show();
                bar2tv.setText(check(i));
                minLightMsg = check(i);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}@Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                msgToPublish = "{\"atemp\":\"" + alarmTempMsg + "\",\"mlight\":\"" + minLightMsg+"\"}"; publishMsg(mqtt_pub_topic, msgToPublish); }}); handler =new Handler() {
            @SuppressLint("SetTextI18n")

            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case 1: // Check updates are sent back after startup
                        break;
                    case 2:  // Feedback is sent back
                        break;
                    case 3: UTF8Buffer MSG =newUTF8Buffer(object.tostring ()));
// Toast.makeText(MainActivity.this,msg.obj.toString(),Toast.LENGTH_SHORT).show();
                        showmsgtv.setText(msg.obj.toString());
                        JSONObject msgGet = null;
                        try {
                            msgGet = new JSONObject(msg.obj.toString());
                            temptv.setText(msgGet.get("temp").toString());
                            humitv.setText(msgGet.get("humi").toString());
                            lighttv.setText(msgGet.get("light").toString());
                            if(Integer.parseInt(msgGet.get("ledsta").toString())==0) ledtv.setText("Closed");
                            else ledtv.setText("Open");
                            if(msgGet.get("beepsta").toString().charAt(0) = ='0') beeptv.setText("Closed");
                            else beeptv.setText("Open");
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        break;

                    case 30:  // Connection failed
                        Toast.makeText(MainActivity.this."Connection failed" ,Toast.LENGTH_SHORT).show();
                        break;
                    case 31:   // The connection succeeded
                        Toast.makeText(MainActivity.this."Connection successful" ,Toast.LENGTH_SHORT).show();
                        try {
                            mqttClient.subscribe(mqtt_sub_topic,1);
                        }
                        catch (MqttException e) {
                            e.printStackTrace();
                        }
                        break;
                    default:
                        break; }}}; }private String check(int progress) {
        int curValue = 100 * progress/Math.abs(100);
        return String.valueOf(curValue);
    }

    private void publishMsg(String topic, String message2) {
        if (mqttClient == null| |! mqttClient.isConnected()) {return;
        }
        MqttMessage message = new MqttMessage();
        message.setPayload(message2.getBytes());
        try {
            mqttClient.publish(topic, message);
        } catch(MqttException e) { e.printStackTrace(); }}private void Mqtt_init(a) {
        try {
            // Host is the host name, and test is clientid, which is the ID of the client connected to MQTT. Generally, it is represented by the unique identifier of the client. MemoryPersistence sets the storage mode of CLIentid, which is stored in memory by default
            mqttClient = new MqttClient(host, mqtt_id, new MemoryPersistence());

            // Connection Settings for MQTT
            options = new MqttConnectOptions();

            If the value is set to false, the server keeps the connection record of the client. If the value is set to true, the server uses a new identity for each connection to the server
            options.setCleanSession(false);

            options.setUserName(userName); // Set the connection user name

            options.setPassword(passWord.toCharArray()); // Set the connection password

            // Set the timeout period to seconds
            options.setConnectionTimeout(10);
            // Set the heartbeat time in seconds. The server sends a message to the client every 1.5 x 20 seconds to check whether the client is online. However, this method does not provide a reconnection mechanism
            options.setKeepAliveInterval(20);

            // Set the callback function
            mqttClient.setCallback(new MqttCallback() {
                @Override
                public void connectionLost(Throwable cause) {
                    // When a connection is lost, it is usually reconnected in this area
// System.out.println("connectionLost----------");
// startReconnect();
                }
                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {
                    //publish will execute here
                    System.out.println("deliveryComplete---------"
                            + token.isComplete());
                }
                @Override
                public void messageArrived(String topicName, MqttMessage message)
                        throws Exception {
                    //subscribe the message is executed here
                    System.out.println("getMsg: ");
                    Message msg = new Message();
                    msg.what = 3;   // Received message flag bit
                    msg.obj = message.toString();
                    handler.sendMessage(msg);    / / hander comes back}}); }catch(Exception e) { e.printStackTrace(); }}private void Mqtt_connect(a) {
        new Thread(new Runnable() {
            @Override
            public void run(a) {
                try {
                    if(! (mqttClient.isConnected())) { mqttClient.connect(options); Message msg =new Message();
                        msg.what = 31; handler.sendMessage(msg); }}catch (Exception e) {
                    e.printStackTrace();
                    Message msg = new Message();
                    msg.what = 30;
                    handler.sendMessage(msg);
                }
            }
        }).start();
    }
    private void startReconnect(a) {
        scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run(a) {
                if(! mqttClient.isConnected()) { Mqtt_connect(); }}},0 * 1000.10 * 1000, TimeUnit.MILLISECONDS); }}Copy the code

Note: THE configuration of MQTT server is not introduced here, you can use some public MQTT servers (you can go to Baidu to search), or you can build one by yourself. I use the MQTT service configured by myself through Tencent cloud here, and you can check my blog or official documents for the specific construction

Results the preview

TFTLCD display

The Android APP interface