当前位置:   article > 正文

【STM32】基于MQTT协议实时监控项目

基于mqtt


一、MQTT与源码库

MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛,相关具体内容以及MQTT.fx软件的相关操作可见上一篇:MQTT协议与使用

MQTT是基于TCP/IP协议、与编程语言无关的标准物联网通信协议,正因为其在物联网系统中有非常广泛的应用,所以各种编程语言都有其开源实现,都可以找到。

由于我们用的单片机的Flash、内存容量有限,所以我们不能在上面跑很多其它开源的库,而应该采用适合单片机使用的MQTT库,这里选用Paho EmbeddedC库,Paho是 MOTT的官方开源库,其有很多版本,最新版Paho MQTT库项目地址: Paho MQTT,不过github访问不稳定,大家也可以搜索搜索其他资源进行下载。

二、Paho MQTT 移植

需要注意的是,这个官方的源码拿来并不能直接使用,我们需要将其针对ESP8266 WiFi模块做Paho MQTT的移植。

1.Paho源码分析

下载好Paho源码并解压缩后打开文件夹,可以看见三个主要源码文件夹:

  • MQTTClient,这里有arduino、linux、mbed等系统移植相关的c++参考代码;
  • MQTTClient-C,这里有cc3200、linux、FreeRTOS等系统移植相关的c参考代码;
  • MQTTPacket,这里面提供了MQTT协议数据报文打包、解析的相关代码。
    在这里插入图片描述

2.Paho源码移植

在我们单片机的项目路径的Core/Src文件夹下,新建一个mqtt文件夹:
在这里插入图片描述
然后,把Paho中MQTTPacket\Src文件夹中的所有.c和.h文件都拷贝到单片机的项目路径Core/Src/mqtt下,并刷新IDE:
在这里插入图片描述
然后在Core的属性中,添加mqtt的路径到include包含头文件的路径下:
在这里插入图片描述


三、MQTT发布实现温湿度实时上报

Paho MQTT库主要是提供了MQTT协议数据报文打包和报文解析的相关函数。因为不同的硬件和通信方式不一样,其底层的收发接口也不一样,这样底层的MQTT消息发送的代码和上层MQTT订阅、发布功能代码都需要用户在移植的时候自己实现。

1.MQTT的底层源文件transport.c/h

在之前基础上代码如下:
之前相关文件可见:ESP8266 WiFi模块实时上报温湿度及控制LED灯项目笔记或私信作者

/*
 * transport.h
 *
 *  Created on: 2023年2月28日
 *      Author: ASUS
 */

#ifndef SRC_MQTT_TRANSPORT_H_
#define SRC_MQTT_TRANSPORT_H_

/*使用ESP8266创建socket连接到MQTT服务器的函数*/
extern int transport_open(char * host, int port);

/*ESP8266关闭socket连接的函数*/
extern int transport_sendPacketBuffer(unsigned char* buf, int buflen);

/*使用ESP8266发送一个MQTT数据报文的函数*/
extern int transport_sendPacketBuffer(unsigned char* buf, int buflen);

/*使用ESP8266接收MQTT数据报文的函数*/
extern int transport_getdata(unsigned char* buf, int count);

/*清除ESP8266接收MQTT数据的socket buffer的函数*/
extern int transport_clearBuf(void);

#endif /* SRC_MQTT_TRANSPORT_H_ */

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
/*
 * transport.c
 *
 *  Created on: 2023年2月28日
 *      Author: ASUS
 */
#include <string.h>
#include "transport.h"
#include "esp8266.h"

static unsigned char			s_sock_buf[256];
static int						s_rx_bytes;

int transport_open(char * addr, int port)
{
	return esp8266_sock_connect(addr, port) ? -1 : 0 ;
}

int transport_close(void)
{
	return esp8266_sock_disconnect();
}

int transport_sendPacketBuffer(unsigned char* buf, int buflen)
{
	return esp8266_sock_send(buf, buflen);
}

int transport_getdata(unsigned char* buf, int count)
{
	int							rv = 0;

	if( !s_rx_bytes )
	{
		rv = esp8266_sock_recv(s_sock_buf, sizeof(s_sock_buf));
		if(!rv)
		{
			return 0;
		}
		s_rx_bytes = rv;
	}

	rv = count>s_rx_bytes ? s_rx_bytes : count;

	memcpy(buf, s_sock_buf, rv);
	s_rx_bytes -= rv;

	if(s_rx_bytes > 0)
	{
		memmove(s_sock_buf, &s_sock_buf[rv], s_rx_bytes);
	}

	return rv;
}

void transport_clearbuf(void)
{
	memset(s_sock_buf, 0, sizeof(s_sock_buf));
	s_rx_bytes = 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

2.MQTT上层调用功能函数

core_mqtt.c/h代码如下:

/*
 * core_mqtt.h
 *
 *  Created on: 2023年2月28日
 *      Author: ASUS
 */

#ifndef SRC_MQTT_CORE_MQTT_H_
#define SRC_MQTT_CORE_MQTT_H_

#include "MQTTPacket.h"
#include "transport.h"

#define MQTT_KEEP_ALIVE_TIMEOUT_SECONDS		( 60U )

enum
{
	Qos0=0,
	Qos1,
	Qos2,
};

/*MQTT连接Broker的函数*/
extern int mqtt_connect(char*host, int port, char *clentid, char *username, char *passwd);

/*MQTT断开Broker连接的函数*/
extern int mqtt_disconnect(void);

/*MQTT订阅主体函数*/
extern int mqtt_subscribe_topic(char *topic, int qos, int msgid);

/*MQTT取消主体订阅函数*/
extern int mqtt_unsubscribe_topic(char *topic, int msgid);

/*MQTT发布消息函数*/
extern int mqtt_publish(char *topic, int qos, char *payload);

/*MQTT保持连接心跳包函数*/
extern int mqtt_pingreq(void);

#endif /* SRC_MQTT_CORE_MQTT_H_ */

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
/*
 * core_mqtt.c
 *
 *  Created on: 2023年2月28日
 *      Author: ASUS
 */
#include <stdio.h>
#include <string.h>

#include "stm32l4xx_hal.h"
#include "core_mqtt.h"

int mqtt_connect(char *host, int port, char *clientid, char *username, char *passwd)
{
	MQTTPacket_connectData			data = MQTTPacket_connectData_initializer;
	int								rv;
	unsigned char					buf[256];
	unsigned char					sessionPresent;
	unsigned char					connack_rc;

	if( !host || port<=0 || !clientid )
	{
		printf("ERROR:Invalid input arguments\r\n");
		return -1;
	}

	if( (rv=transport_open( host, port)) < 0 )
	{
		printf( "socket connect[%s:%d] failure, rv=%d\r\n", host, port, rv);
		return rv;
	}
	printf("socket connect [ %s:%d ] ok\r\n", host,  port);

	data.clientID.cstring = clientid;
	data.keepAliveInterval = MQTT_KEEP_ALIVE_TIMEOUT_SECONDS;
	data.cleansession = 1;

	if( username && passwd )
	{
		data.username.cstring = username;
		data.password.cstring = passwd;
	}

	rv=MQTTSerialize_connect(buf, sizeof(buf), &data);

	if(rv != transport_sendPacketBuffer(buf,rv))
	{
		printf("transport_sendPacketBuffer for mqtt_connect failure, rv=%d\n", rv);
	}

	HAL_Delay(800);

	memset(buf, 0, sizeof(buf));
	rv = MQTTPacket_read(buf, sizeof(buf), transport_getdata);
	if( CONNACK != rv )
	{
		printf( "MQTTPacket_read for MQTT CONNACK failure, rv=%d\n", rv);
		return -3;
	}

	if((rv=MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, sizeof(buf)))!= 1 || connack_rc!=0)
	{
		printf("MQTTDeserialize_connack failure, rv=%d\n", rv);
		return -4;
	}

	return 0;
}

int mqtt_disconnect(void)
{
	int								rv;
	unsigned char					buf[256];

	rv = MQTTSerialize_disconnect( buf, sizeof(buf) );
	if( rv < 0 )
	{
		printf("MQTTSerialize_disconnect failure, rv=%d\n", rv);
		return -1;
	}

	if ( rv != transport_sendPacketBuffer(buf,rv) )
	{
		printf( "transport_sendPacketBuffer for mqtt_disconnect failure, rv=%d\n", rv);
		return -2;
	}

	return 0;
}

int mqtt_subscribe_topic(char *topic, int qos, int msgid)
{
	MQTTString						topicString = MQTTString_initializer;
	unsigned short					submsgid;
	int								subcount, granted_qos;
	int								rv;
	unsigned char					buf[256];

	topicString.cstring = topic;

	rv = MQTTSerialize_subscribe(buf, sizeof(buf), 0, msgid, 1,&topicString, &qos);
	if( rv < 0 )
	{
		printf("MQTTSerialize_subscribe failure, rv=%d\n", rv);
		return -1;
	}

	if ( rv != transport_sendPacketBuffer(buf,rv) )
	{
		printf( "transport_sendPacketBuffer for mqtt_subscribe_topic failure, rv=%d\n", rv);
		return -2;
	}

	HAL_Delay(800);

	memset(buf, 0, sizeof(buf));
	rv = MQTTPacket_read(buf, sizeof(buf), transport_getdata);
	if(SUBACK != rv)
	{
		printf("MQTTPacket_read for MQTT SUBACK failure, rv=%d\n", rv);
		return -3;
	}

	rv = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, buf, sizeof(buf));
	if( !rv || submsgid!=msgid || granted_qos==0x80)
	{
		printf( "MQTTDeserialize_suback failure, rv=%d\n", rv);
		return -4;
	}

	return 0;
}

int mqtt__unsubscribe_topic(char *topic, int msgid)
{
		MQTTString						topicString = MQTTString_initializer;
		unsigned short					submsgid;
		int								rv;
		unsigned char					buf[256];

		topicString.cstring = topic;
		rv = MQTTSerialize_unsubscribe(buf, sizeof(buf), 0, msgid, 1, &topicString);
		if( rv < 0 )
		{
			printf("MQTTSerialize_subscribe failure,rv=%d\n", rv);
			return -1;
		}

		if ( rv != transport_sendPacketBuffer(buf, rv) )
		{
			printf("transport_sendPacketBuffer for mqtt_unsubscribe_topic failure, rv=%d\n", rv);
			return -2;
		}

		HAL_Delay(800);

		memset(buf, 0, sizeof(buf));
		rv = MQTTPacket_read(buf, sizeof(buf), transport_getdata);
		if( UNSUBACK != rv )
		{
			printf("MQTTPacket_read for MQTT UNSUBACK failure, rv=%d\n", rv);
			return -3;
		}

		rv = MQTTDeserialize_unsuback(&submsgid, buf, sizeof(buf));
		if( !rv || submsgid!=msgid )
		{
			printf("MQTTDeserialize_unsuback failure,rv=%d\n", rv);
			return -4;
		}

		return 0;
}

int mqtt_publish(char *topic, int qos, char *payload)
{
		MQTTString						topicString = MQTTString_initializer;
		int								rv;
		unsigned char					buf[256];
		unsigned char					dup = 0;
		unsigned char					retained = 0;
		unsigned short					packetid = 0;

		topicString.cstring = topic;

		rv =MQTTSerialize_publish(buf, sizeof(buf), dup, qos, retained, packetid, topicString, (unsigned char*)payload, strlen(payload));
		if( rv < 0 )
		{
			printf( "MQTTSerialize_publish failure, rv=%d \n", rv);
			return -1;
		}

		if ( rv != transport_sendPacketBuffer(buf, rv) )
		{
			printf("transport_sendPacketBuffer for MQTTSerialize_publish failure,rv=%d \n", rv);
			return -2;
		}

		HAL_Delay(800);

		memset(buf, 0, sizeof(buf));
		rv = MQTTPacket_read(buf, sizeof(buf), transport_getdata);
		if( PUBLISH!=rv && -1!=rv )
		{
			printf("MQTTPacket_read for MQTT PUBLISH failure,rv=%d\n", rv);
			return -3;
		}

		return 0;
}

int mqtt_pingreq(void)
{
	int								rv;
	unsigned char					buf[256];

	rv = MQTTSerialize_pingreq(buf, sizeof(buf));
	if( rv < 0 )
	{
		printf("MQTTSerialize_pingreq failure, rv=%d\n", rv);
		return -1;
	}

	if (rv != transport_sendPacketBuffer(buf, rv) )
	{
		printf("transport_sendPacketBuffer for MQTTSerialize_pingreq failure,rv=%d\n", rv);
		return -2;
	}

	HAL_Delay(800);

	memset(buf, 0, sizeof(buf));
	rv = MQTTPacket_read(buf, sizeof(buf), transport_getdata);
	if(PINGRESP != rv)
	{
		printf("MQTTPacket_read for MQTT PINGRESP failure,rv=%d\n", rv);
		return -3;
	}

	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242

3.MQTT实现温湿度实时上报与LED灯远程控制

main.c代码如下:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
#include "dht11.h"
#include "sht30.h"
#include "core_json.h"
#include "oled.h"
#include "esp8266.h"
#include "core_mqtt.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
#define FLAG_WIFI_CONNECTED		(1<<0)	/* WiFi连接路由器标志位*/
#define FLAG_SOCK_CONNECTED 	(1<<1)  /* Socket连接服务器标志位*/

#define DEF_ROUTER_SSID			"***"//填入自己WiFi的SSID
#define	DEF_ROUTER_PWD			"***"//填入密码

#define MQTT_BROKER_HOSTNAME	"***"		//设置对应的MQTT Broker服务器
#define MQTT_BROKER_PORT		****				//设置MQTT Broker监听发端口

//Broker没有用户名和密码则不用设置
#define MQTT_BROKER_USERNAME	"***"//填入用户名
#define MQTT_BROKER_PASSWORD	"***"//填入密码

#define	MQTT_CLIENT_ID			"BearKE-dengyonghao" 		//设置客户端ID
#define	MQTT_PUB_TOPIC			"$Sys/studio/Uplink/"MQTT_CLIENT_ID
#define	MQTT_SUB_TOPIC			"$Sys/studio/Downlink/"MQTT_CLIENT_ID

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
static int report_tempRH_json(void);
static int parser_led_json(char *json_string, int bytes);
//static void proc_uart1_recv(void);
void	mqtt_subscribe_proc(void);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

//  uint32_t		lux,noisy;
//  uint32_t		start = 0;
//  uint32_t		light_status = 0;
//  float temperature, humidity;

	uint32_t		last_time = 0; /*每隔3s上报一次,上一次上报的时间*/
//	unsigned char	buf[256]; /*WiFi模块socket接收的buffer MQTT中没有用到*/
	int				rv;

	char			ipaddr[16];
	char			gateway[16];
	unsigned char	wifi_flag = 0;

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM6_Init();
  MX_USART1_UART_Init();
  MX_ADC1_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

  //sysled_hearbeat();
  //beep_start(3,300);
  printf("Start BearKE1 5G NB_IoT Board Example Program v1.0\r\n");
  printf("Welcome Mr.deng!\r\n");

  OLED_Init();
  OLED_ShowBanner(TIME_1S*2);

  esp8266_module_init();

  while(1)
  {
	  /*wiFi没有连接上无线路由器的话,开始连接无线路由器并ping测试*/
	  if(!(wifi_flag&FLAG_WIFI_CONNECTED))
	  {
		  if(esp8266_join_network(DEF_ROUTER_SSID, DEF_ROUTER_PWD))
		  {
			  esp8266_module_init();
			  HAL_Delay(2000);
			  continue;
		  }
		  if(esp8266_get_ipaddr(ipaddr, gateway, sizeof(ipaddr)))
		  {
			  HAL_Delay(1000);
			  continue;
		  }
		  if(esp8266_ping_test(gateway))
		  {
			  HAL_Delay(1000);
			  continue;
		  }
		  wifi_flag |= FLAG_WIFI_CONNECTED; /* set wifi connected flag */
	  }

	  /*网络socket没有连接上Socket服务器的话就开始连接Socket服务器 */
//	  if(!(wifi_flag&FLAG_SOCK_CONNECTED))
//	  {
//		  if(esp8266_sock_connect("192.168.0.120", 12345))
//		  {
//			  HAL_Delay(1000);
//			  continue;
//		  }
//		  wifi_flag |= FLAG_SOCK_CONNECTED; /* set wifi connected flag */
//	  }

	  /*这里使用MQTT Broker服务器所以判断没有连接的时候就开始连接对应MQTT Broker服务器*/
	  if(!(wifi_flag&FLAG_SOCK_CONNECTED))
	  {
		  rv = mqtt_connect(MQTT_BROKER_HOSTNAME, MQTT_BROKER_PORT, MQTT_CLIENT_ID, MQTT_BROKER_USERNAME, MQTT_BROKER_PASSWORD);
		  if( rv )
		  {
			  HAL_Delay(1000);
			  continue;
		  }

		  /* 连上MQTT Broker后订阅下发三色Led控制命令的主题*/
		  mqtt_subscribe_topic(MQTT_SUB_TOPIC, Qos0, 1);

		  wifi_flag |= FLAG_SOCK_CONNECTED; /* set wifi connected flag */
	  }

	  /*处理MQTT订阅收到的消息*/
	  mqtt_subscribe_proc();

	  /*接收并且打印Socket服务器发送过来的数据*/
//	  rv = esp8266_sock_recv(buf, sizeof(buf));
//	  printf(("%d\n"), rv);
//	  if( (rv=esp8266_sock_recv(buf, sizeof(buf))) > 0 )
//	  {
//		  parser_led_json((char *)buf, rv);
//		  printf("ESP8266 socket receive %d bytes data: %s\n", rv, buf);
//	  }

	  /*定时发数据到Socket服务器*/
//	  if(time_after(HAL_GetTick(), last_time+3000))
//	  {
//		  rv = report_tempRH_json();
//		  if( rv == 0 )
//		  {
//			  printf("ESP8266 socket send message ok\n");
//		  }
//		  else
//		  {
//			  printf("ESP8266 socket send message failure, rv=%d\n", rv);
//			  wifi_flag &= ~FLAG_SOCK_CONNECTED;/* clear socket connected flag */
//
//			  if(esp8266_ping_test(gateway))
//			  {
//				  wifi_flag &= ~FLAG_WIFI_CONNECTED;/* clear wifi connected flag */
//			  }
//		  }
//
//		  last_time = HAL_GetTick();/*update last report time */
//	  }

	  /*定时发布采样温度值到MQTT Broker,修改为30s上报一次*/
	  if(time_after(HAL_GetTick(), last_time+30000))
	  {
		  rv = report_tempRH_json();
		  if( rv == 0 )
		  {
			  printf("ESP8266 MQTT publish message ok\n");
		  }
		  else
		  {
			  printf("ESP8266 MQTT publish message failure, rv=%d\n", rv);
			  wifi_flag &= ~FLAG_SOCK_CONNECTED;/* clear socket connected flag */

			  if(esp8266_ping_test(gateway))
			  {
				  wifi_flag &= ~FLAG_WIFI_CONNECTED;/* clear wifi connected flag */
			  }
		  }

		  last_time = HAL_GetTick();/*update last report time */
	  }

//	  uart_forward();//后面使用无线通讯时只需要用Socket通信,不在需要此转发程序,如果没有注释掉会报错,并不会执行PC发的JOSN指令
#if 0
	  /*sht30*/
	  report_tempRH_json();
	  HAL_Delay(3000);

	  /*json上报*/
	  proc_uart1_recv();
	  if( report_tempRH_json() < 0 )
	  {
		  printf("ERROR: UART report temperature and relative humidity failure\r\n");
	  }
	  HAL_Delay(3000);

//	  if( DHT11_SampleData(&temperature, &humidity) < 0 )
//	  {
//		  printf("ERROR: DHT11 Sample Data failure\r\n");
//	  }
//	  else
//	  {
//		  printf("DHT11 Sample Temperature: %.3f Relative Humidity: %.3f\r\n", temperature, humidity);
//	  }
//
//
//	  HAL_Delay(1000);

//Tag:灯光
//	if( OFF == light_status )
//	{
//		adc_sample_lux_noisy(&lux, &noisy);
//		printf("Lux[%lu] Noisy[%lu]\r\n", lux, noisy);
//		if( lux<400 && noisy>800 )
//		{
//			printf("Turn Light on\r\n");
//			turn_relay(Relay2,ON);
//			turn_led(GreenLed,ON);//还得写turn_Led()
//			light_status = ON;
//
//			start = HAL_GetTick();
//		}
			HAL_Delay(5000);
//	}
//
//	else
//	{
//		if( time_after(HAL_GetTick(), start+15000) )
//		{
//			printf("Turn Light off\r\n");
//			turn_relay(Relay2,OFF);
//			turn_led(GreenLed,OFF);
//			turn_led(RedLed,ON);
//
//			HAL_Delay(1000);
//			turn_led(RedLed,OFF);
//
//			light_status = OFF;
//		}
//
//	}
//
//	HAL_Delay(10);
#endif
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 1;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_USART2
                              |RCC_PERIPHCLK_ADC;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
  PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1;
  PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE;
  PeriphClkInit.PLLSAI1.PLLSAI1M = 1;
  PeriphClkInit.PLLSAI1.PLLSAI1N = 9;
  PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;
  PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
  PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV6;
  PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_ADC1CLK;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure the main internal regulator output voltage
  */
  if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
/*处理单片机通过ESP8266和MQTT订阅收到的消息*/
void mqtt_subscribe_proc(void)
{
	unsigned char					buf[256];
	int								packet_type;
	MQTTString						topicName;
	unsigned char					dup;
	int								qos;
	unsigned char					retained;
	unsigned short					msgid;
	unsigned char					*payload = NULL;;
	int								payloadlen = 0;
	int								rv;

	memset(buf, 0, sizeof(buf));

	packet_type = MQTTPacket_read(buf, sizeof(buf), transport_getdata);
	if( packet_type < 0 )
	{
		return ;
	}

	switch( packet_type )
	{
		case 0:
		break;

		case PUBLISH:
		{
			rv = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &topicName, &payload, &payloadlen, buf, sizeof(buf));
			if( rv==1 )
			{
				printf("MQTT Payload: %s\n", payload);
				parser_led_json((char *)payload, payloadlen);
			}
			else
			{
				printf("ERROR: MQTTDeserialize_publish() failure, rv=%d\r\n", rv);
			}
			break;
		}
		case CONNACK:
		case PUBACK:
		case SUBACK:
		case UNSUBACK:
		case PUBREC:
		case PUBREL:
		case PUBCOMP:
			break;
	}
}

int parser_led_json(char *json_string, int bytes)
{
	JSONStatus_t result;
	char save;
	char *value;
	size_t valen;
	int i;

	printf("DBUG: Start parser JSON string: %s\r\n", json_string);
	result = JSON_Validate(json_string, bytes);
	/* JSON document is valid so far but incomplete */
	if( JSONPartial == result )
	{
		printf("WARN: JSON document is valid so far but incomplete!\r\n");
		return 0;
	}

	/* JSON document is not valid JSON */
	if( JSONSuccess != result )
	{
		printf("ERROR: JSON document is not valid JSON!\r\n");
		return -1;
	}
	/* Parser and set LED status */
	for(i=0; i<LedMax; i++)
	{
		result = JSON_Search( json_string, bytes, leds[i].name, strlen(leds[i].name), &value, &valen);
		if( JSONSuccess == result )
		{
			save = value[valen];
			value[valen] = '\0';

			if( !strncasecmp(value, "on", 2) )
			{
				printf("DBUG: turn %s on\r\n", leds[i].name);
				turn_led(i, ON);
			}
			else if( !strncasecmp(value, "off", 3) )
			{
				printf("DBUG: turn %s off\r\n", leds[i].name);
				turn_led(i, OFF);
			}

			value[valen] = save;
		}
	}
	return 1;
}

//void proc_uart1_recv(void)
//{
//	if( g_uart1_bytes > 0 )
//	{
//		HAL_Delay(200);
//		if( 0 != parser_led_json(g_uart1_rxbuf, g_uart1_bytes) )
//		{
//			clear_uart1_rxbuf();
//		}
//	}
//}

/*json上报*/
//int report_tempRH_json(void)
//{
//	char buf[128];
//	float temperature, humidity;
//
//
//	if ( DHT11_SampleData(&temperature, &humidity) < 0 )
//	{
//		printf("ERROR: DHT11 Sample data failure\n");
//		return -1;
//	}
//
//
//	memset(buf, 0, sizeof(buf));
//	snprintf(buf, sizeof(buf), "{\"Temperature\":\"%.2f\", \"Humidity\":\"%.2f\"}", temperature, humidity);
//
//	HAL_UART_Transmit(&huart1 , (uint8_t *)buf, strlen(buf), 0xFFFF);
//
//	return 0;
//}

/*sht30采样*/
int report_tempRH_json(void)
{
	char buf[128];
	float temperature, humidity;
	uint32_t temp, humd;
	int	rv;

	if ( SHT30_SampleData(&temperature, &humidity) < 0 )
	{
		printf("ERROR: SHT30 Sample data failure\n");
		return -1;
	}


	memset(buf, 0, sizeof(buf));
	snprintf(buf, sizeof(buf), "{\"Temperature\":\"%.2f\", \"Humidity\":\"%.2f\"}", temperature, humidity);

	temp = (int)(temperature*100);
	humd = (int)(humidity*100);
	OLED_ShowTempHumdity(temp, humd, TIME_1S*2);

	rv = mqtt_publish(MQTT_PUB_TOPIC, Qos0, buf);
	printf("MQTT publish topic[%s] with msg '%s' %s, rv=%d\r\n", MQTT_PUB_TOPIC, buf, rv ? "failure":"ok", rv);

	return rv;

	/*esp8266测试*/
//	rv = esp8266_sock_send((uint8_t *)buf, strlen(buf));
//	HAL_UART_Transmit(&huart1 , (uint8_t *)buf, strlen(buf), 0xFFFF);
//	return rv>0 ? 0 : -2;
}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508
  • 509
  • 510
  • 511
  • 512
  • 513
  • 514
  • 515
  • 516
  • 517
  • 518
  • 519
  • 520
  • 521
  • 522
  • 523
  • 524
  • 525
  • 526
  • 527
  • 528
  • 529
  • 530
  • 531
  • 532
  • 533
  • 534
  • 535
  • 536
  • 537
  • 538
  • 539
  • 540
  • 541
  • 542
  • 543
  • 544
  • 545
  • 546
  • 547
  • 548
  • 549
  • 550
  • 551
  • 552
  • 553
  • 554
  • 555
  • 556
  • 557
  • 558
  • 559
  • 560
  • 561
  • 562
  • 563
  • 564
  • 565
  • 566
  • 567
  • 568
  • 569
  • 570
  • 571
  • 572
  • 573
  • 574
  • 575
  • 576
  • 577
  • 578
  • 579
  • 580
  • 581
  • 582
  • 583
  • 584
  • 585
  • 586
  • 587
  • 588
  • 589
  • 590
  • 591
  • 592
  • 593

在这里插入图片描述

测试结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、总结

本文是基于MQTT协议的实时监控项目,通过MQTT协议结合无线通讯模块实现了对温湿度的无线监控和LED灯的远程控制。

别忘了点赞 关注 收藏呀!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/176302
推荐阅读
相关标签
  

闽ICP备14008679号