课程设计|物联网实验-温湿度实时监测系统
前言: 这是大四上学期做的物联网实验,总共4个实验,这是第4个,也是最难的一个,当然大部分程序是我的老师编写的,我只是跟着实验指导书做出来的,希望可以帮到大家。
1. 系统工作原理 温湿度感知节点(Client),实时采集温湿度数据,然后通过WiFi模块,以TCP协议
将采集数据实时无线传输给服务端(Server);服务端将接收到的温湿度数据存于数据库
中;用户终端(User)从服务端获取实时采集和历史数据,用以监测、分析、查询等应
用。
2. 系统 设计 用户应用程序界面如图所示。
文章图片
服务器界面:
文章图片
使用串口助手看数据:
如果不写服务器程序和用户应用程序,也可以使用串口助手来观察数据
操作方法如下:
- 打开串口调试工具SSCOM,如下图所示。
- 实验以开发板作为客户端(Client),以电脑作为服务器端(Server)。所以,在SSCOM中,端口号选择TCPServer,服务器IP(本地IP)、端口设置与main函数中的一致。
- 按下SSCOM“侦听”按钮,若系统显示“已连接”,表明开发板已经建立了与服务器端的TCP连接,则可以看到温湿度的实时监测数据,。
文章图片
主要用到的元器件有:
STM32F103C8T6、ESP8266、DHT11、DS18B20、ST-LINK下载器、方口数据线
3. 程序编写 STM32部分源码:
这部分代码太多了,只给出主函数的代码。
#include "filelib.h"int main(void)
{ char *sendtxt = (char*)malloc(48);
strcpy(P_data.wifi_ssid,"XIAOCHUN");
//设置连接WiFi名称
strcpy(P_data.wifi_psd,"3118003167");
//设置连接WiFi密码
strcpy(P_data.wifi_ip,"192.168.43.217");
//设置连接服务器IP
strcpy(P_data.wifi_port,"12345");
//设置连接服务器端口
ESP8266_Init ();
//初始化ESP8266
DHT11_GPIO_Config();
DS18B20_Init();
macESP8266_CH_ENABLE();
//使能ESP8266
ESP8266_AT_Test();
//检测ESP8266的AT是否启动(若10次测试失败,则结束程序运行)
ESP8266_Net_Mode_Choose(STA);
//设置wifi模块为STA模式
//连接wifi
while (!ESP8266_JoinAP(P_data.wifi_ssid, P_data.wifi_psd))
{ //连接wifi失败,重连
}
ESP8266_Enable_MultipleId(DISABLE);
//关闭WiFi多连接
//连接到远程服务器
while (!ESP8266_Link_Server(enumTCP, P_data.wifi_ip, P_data.wifi_port, Single_ID_0))
{ //连接服务器失败,重连}
while (!ESP8266_UnvarnishSend()) ;
//开启穿透模式 while(1)
{Delay_ms(1500);
//每隔1500ms获取一次温湿度
//Dev_data.temp = readtemp();
//获取温度
Dev_data.temp =DS18B20_GetTemperture();
sprintf(sendtxt,"%s%.2f%s","温度:",Dev_data.temp,"℃");
ESP8266_SendString ( ENABLE,sendtxt,0, Single_ID_0 );
//发送温度值到服务器Dev_data.humi = Get_Humi_Value();
//获取湿度
sprintf(sendtxt,"%s%u%s","湿度:",Dev_data.humi,"%RH");
ESP8266_SendString ( ENABLE,sendtxt,0, Single_ID_0 );
//发送温度值到服务器
//ESP8266_SendString ( ENABLE, "Welcome!\r\n", 0, Single_ID_0 );
//发送湿度值到服务器
}
}
服务器源码:
#define _CRT_SECURE_NO_WARNINGS#if defined(_WIN32) || defined(_WIN64)//为了支持windows平台上的编译
#include
#endif#include
#include
#include
#include
#include
#include "mysql.h"//该文件在…\mysql-8.0.18-winx64\include下#pragma comment(lib,"ws2_32.lib")using namespace std;
void initialization();
int main() { //以下是MySQL数据库操作程序
MYSQL mysql, * sock;
//声明MySQL的句柄
const char* host = "localhost";
//数据库服务器IP
const char* user = "root";
//连接MySQL的用户名
const char* passwd = "123456";
//连接MySQL的用户密码
const char* db = "iotdatabase";
//连接数据库的名字
unsigned int port = 3306;
//这是MySQL的服务器的端口,如果没有修改过的话就是3306
const char* unix_socket = NULL;
//unix_socket这是unix下的,在Windows下把它设置为NULL
unsigned long client_flag = 0;
//这个参数一般为0
char query_str[200];
//MySQL命令字符串
mysql_init(&mysql);
//连接数据库之前必须使用初始化函数进行初始化 //连接MySQL
if ((sock = mysql_real_connect(&mysql, host, user, passwd, db, port, NULL,0 )) == NULL)//unix_socketclient_flag
{cout << "连接mysql失败" << endl;
exit(1);
//exit(0);
正常的关闭所有程序;
exit(1):有错误的关闭所有程序
} //以下是Socket通信服务端程序
int recv_len = 0;
//定义长度变量
int len = 0;
//定义服务端套接字,接受请求套接字
SOCKET s_server;
SOCKET s_accept;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
SOCKADDR_IN accept_addr;
//initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
//协议簇类型:TCP/IP–IPv4
server_addr.sin_addr.S_un.S_addr = inet_addr("192.168.43.217");
//服务器IP 192.168.43.217
server_addr.sin_port = htons(12345);
//服务器端口 //初始化套接字
WORD w_req = MAKEWORD(2, 2);
//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
//初始化套接字
if (err != 0) {WSACleanup();
//中止套接字
} //创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
//SOCK_STREAM—TCP流
//SOCK_DGRAM—UDP数据报;SOCK_RAW—原始套接字
if (bind(s_server, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {WSACleanup();
cout << "失败" << endl;
}
else {cout << "套接字绑定成功!" << endl;
cout << "IP:192.168.43.217" << endl;
cout << "端口:12345" << endl;
} //设置套接字为监听状态
if (listen(s_server, SOMAXCONN) < 0) {cout << "设置监听状态失败!" << endl;
WSACleanup();
}
else {cout << "设置监听状态成功!" << endl;
}
cout << "服务端正在监听连接,请稍候...." << endl;
//接受连接请求
len = sizeof(SOCKADDR);
s_accept = accept(s_server, (SOCKADDR*)&accept_addr, &len);
if (s_accept == SOCKET_ERROR) {cout << "连接失败!" << endl;
WSACleanup();
//释放DLL资源
return 0;
}
cout << "连接建立,准备接受数据" << endl;
//接收数据
while (1) {char recv_buf[100] = {
"\0" };
//定义接受缓冲区,并赋初值Null
recv_len = recv(s_accept, recv_buf, 100, 0);
//接收数据长度
if (recv_len < 0) {cout << "接受失败!" << endl;
break;
}
else {//获取温湿度数据 数据格式:温度数据 + 湿度数据 #
char* p1 = NULL;
char* p2 = NULL;
char* p3 = NULL;
//分割字符串安全函数,这个函数将剩余的字符串存储在buf变量中,而不是静态变量中,从而保证了安全性。
//char *strtok_s( char *strToken, const char *strDelimit, char **buf);
string tempData = https://www.it610.com/article/strtok_s(recv_buf,"+", &p2);
string humiData = https://www.it610.com/article/strtok_s(p2,"#", &p3);
//获取采集时间
char str[50];
SYSTEMTIME st;
//系统时间变量
GetLocalTime(&st);
//获得系统时间
sprintf(str, "%u-%u-%u %u:%u:%u",st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
string datetimeDA = str;
//将采集时间转换为字符串 //拼接MYSQL查询命令字符串
string sql = "insert into acquisitiondata(tempData,humiData,datetimeDA) values ('" + tempData + "','" + humiData + "','" + datetimeDA + "')";
strcpy_s(query_str, sql.c_str());
//将采集的温湿度插入MySQL数据表acquisitiondata
mysql_real_query(&mysql, query_str, strlen(query_str));
//执行由query_str指向的SQL查询
cout << "将采集的温湿度插入MySQL数据表acquisitiondata" << endl;
}
} //关闭服务端套接字
closesocket(s_server);
closesocket(s_accept);
//释放DLL资源
WSACleanup();
return 0;
}void initialization() { //初始化套接字库
WORD w_req = MAKEWORD(2, 2);
//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0) {cout << "初始化套接字库失败!" << endl;
}
else {cout << "初始化套接字库成功!" << endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {cout << "套接字库版本号不符!" << endl;
WSACleanup();
}
else {cout << "套接字库版本正确!" << endl;
}
}
【课程设计|物联网实验-温湿度实时监测系统】用户程序源码:
using System.Windows;
using MySql.Data.MySqlClient;
using System.Data;
using System.Linq;
using System.Threading;
namespace UserApp
{///
/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : Window
{public MainWindow()
{InitializeComponent();
//窗体界面定义初始化
string connectionString = "server=localhost;
port=3306;
database=iotdatabase;
charset=utf8;
user id=root;
password=123456;
pooling=false;
";
//MySQL数据库连接字符串
MySqlConnection conn = new MySqlConnection(connectionString);
//连接MySQL数据库
conn.Open();
//打开连接
DataTable dt = new DataTable();
//定义数据表
string sqlstring = "SELECT * from acquisitiondata where numRecord = (SELECT max(numRecord)FROM acquisitiondata)";
//查询实时数据命令字符串
MySqlCommand cmd = new MySqlCommand //定义MySQLCommand对象
{Connection = conn,
CommandText = sqlstring,
CommandType = CommandType.Text
};
SynchronizationContext _syncContext = SynchronizationContext.Current;
Thread LogThread = new Thread(new ThreadStart(DoService));
//定义线程
LogThread.IsBackground = true;
//设置线程为后台线程
LogThread.Start();
//开启线程void DoService()
{while (true)
{MySqlDataAdapter da = new MySqlDataAdapter(cmd);
//获取实时数据
da.Fill(dt);
//将数据填充到数据表dtDataRow dr_last = dt.AsEnumerable().Last();
_syncContext.Post(SetTextBox1, dr_last[1].ToString());
//通过线程更新txBoxTemp
_syncContext.Post(SetTextBox2, dr_last[2].ToString());
//通过线程更新txBoxHumi
_syncContext.Post(SetTextBox3, dr_last[3].ToString());
//通过线程更新txBoxTime
Thread.Sleep(1000);
}
}
void SetTextBox1(object text)
{txBoxTemp.Text = text.ToString();
//更新txBoxTemp
}
void SetTextBox2(object text)
{txBoxHumi.Text = text.ToString();
//更新txBoxHumi
}
void SetTextBox3(object text)
{txBoxTime.Text = text.ToString();
//更新txBoxTime
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{//查询按钮
string connectionString = "server=localhost;
port=3306;
database=iotdatabase;
charset=utf8;
user id = root;
password = 123456;
pooling = false;
";
MySqlConnection conn = new MySqlConnection(connectionString);
//连接MySQL数据库
conn.Open();
//打开连接
DataTable dt = new DataTable();
//定义数据表
string sqlstring = "SELECT * FROM acquisitiondata;
";
//查询所有记录命令字符串
MySqlCommand cmd = new MySqlCommand();
//定义MySQLCommand对象
cmd.Connection = conn;
cmd.CommandText = sqlstring;
cmd.CommandType = CommandType.Text;
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
da.Fill(dt);
//将数据填充到数据表dt
dataGridViewTH.ItemsSource = dt.DefaultView;
//dataGridViewTH绑定数据表dt
conn.Close();
//关闭数据库连接
}
private void BtnClear_Click_1(object sender, RoutedEventArgs e)
{//清空按钮
string connectionString = "server=localhost;
port=3306;
database=iotdatabase;
charset=utf8;
user id = root;
password = 123456;
pooling = false;
";
MySqlConnection conn = new MySqlConnection(connectionString);
//连接MySQL数据库
conn.Open();
//打开连接
DataTable dt = new DataTable();
//定义数据表
string sqlstring = "TRUNCATE acquisitiondata;
";
//TRUNCATE TABLE 删除表中的所有行,而不记录单个行删除操作
MySqlCommand cmd = new MySqlCommand();
//定义MySQLCommand对象
cmd.Connection = conn;
cmd.CommandText = sqlstring;
cmd.CommandType = CommandType.Text;
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
da.Fill(dt);
//将数据填充到数据表dt
dataGridViewTH.ItemsSource = dt.DefaultView;
//dataGridViewTH绑定数据表dt
conn.Close();
//关闭数据库连接
}
private void txBoxTime_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{//采集时间框
}
private void TextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{//温度数据框
}
private void txBoxHumi_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{//湿度数据款框
}
}
}
推荐阅读
- PMSJ寻平面设计师之现代(Hyundai)
- 跌跌撞撞奔向你|跌跌撞撞奔向你 第四章(你补英语,我补物理)
- 做一件事情的基本原理是什么()
- 基于微信小程序带后端ssm接口小区物业管理平台设计
- 螃蟹和这些食物同吃,轻则腹泻、重则中毒!要小心哦~
- 做个俗物有什么不好
- 爱琐搭配(喜欢复古、冷淡,像这种双环设计的气质耳环)
- 有句话忍很久了,女生要求买房怎么就物质了()
- 球松
- 六一礼物