点击下方查看效果

Click Here

背景

不满足于在页面上显示单独的温湿度数据,我决定添加光线感应以及——每15分钟添加一次实时数据并更新页面。

资源准备

实现原理

服务端某进程每隔一段时间获取一次本地数据,并将数据添加到index.html

具体操作

本地端

首先,修改Arduino的部分代码,这个时候,我们就不需要返回一个html页面了,只需要一串表明物理量的数字即可。另外,顺便加上光敏数据,光敏模块使用3号数字引脚。

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
#include <SPI.h>
#include <Ethernet.h> //网络模块头文件
#include <dht11.h> //温湿度模块库文件

#define SENSORPIN 2 //定义传感器引脚
#define LIGHTSENSORPIN 3

//定义本机MAC地址和IP,IP子网必须与局域网一致
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xE8, 0xDE, 0xED };
IPAddress ip(192, 168, 1, 30);

dht11 sensor;

EthernetServer server(80);

void setup() {
Serial.begin(115200); //串口用于监控
Ethernet.begin(mac, ip);
server.begin();
}

void loop() {
EthernetClient client = server.available();

//当有连接传入,即开始传递数据
if (client) {
Serial.println("Incoming...\n");
if (client.connected()) {

//等待传入数据
int count = 0;
while (!client.available()) {
count++;
delay(100);
if (count >= 10) {
count = 0;
break;
}
}

//等待客户端请求结束
while (client.available()) {
char charget = client.read();
Serial.write(charget);
}

sensor.read(SENSORPIN); //读取温湿度数据
//这里就直接返回数值即可
client.println((float)sensor.humidity, 2);
client.println(sensor.temperature);
client.println(digitalRead(LIGHTSENSORPIN));
}
delay(1);

if (client.connected()) {
client.stop();
Serial.println("client disonnected");
}
}
}

frp客户端几乎不用动。

云端

我使用C++和shell,利用curl命令获取数据,然后把数据加到index.html头部。

比较懒,没注释。

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
//get_data.cpp

#include <iostream>
#include <fstream>
#include <unistd.h>
#include <ctime>
#include <string>

using namespace std;

string nowtime();
void getdata();
void work();
void deploy();

int main()
{
while (1)
{
work();
sleep(900);
}

return 0;
}

void getdata()
{
system("curl frp.vvzero.com:21321 > newdata.dat");
}

string nowtime()
{
string value("");

time_t now = time(0);
tm *ltm = localtime(&now);

value = to_string(ltm->tm_hour) + ':' + to_string(ltm->tm_min);
if (value.length()==4)
{
if (value[1] == ':') value.insert(0,1,'0');
else if (value[2] == ':') value.insert(3,1,'0');
}
else if (value.length()==3)
{
value.insert(0,1,'0');
value.insert(3,1,'0');
}
return value;
}

void work()
{
ofstream output;
ifstream index, data;

getdata();

output.open("tmp_data.dat",ios::out);
index.open("index.html",ios::in);
data.open("newdata.dat",ios::in);

string row;
for (int i=0;i<10;i++)
{
getline(index, row);
output << row << endl;
}
float humidity=0.0;
int temperature=0;
int light=0;
data >> humidity;
data >> temperature;
data >> light;

output << nowtime() << " " << (int)humidity << " " << temperature << " " << (light == 0 ? "Yes" : "No") << endl;

int count=0;
getline(index, row);
while (row[0]!='<' && count<99)
{
output << row << endl;
getline(index, row);
count++;
}

while (row[0]!='<') getline(index, row);
output << row << endl;
while (!index.eof())
{
getline(index, row);
if (row.length() >= 5) output << row << endl;
}

output.close();
index.close();
data.close();

deploy();
}

void deploy()
{
system("rm index.html");
system("rm newdata.dat");
system("mv tmp_data.dat index.html");
}

这里实现了每隔15分钟获取一次数据。

然后$g++ -o GET get_data.cpp -std=c++11

注意这里使用的是C++11标准,所以需要加上-std=c++11

在Nginx的根目录下,先新建一个如下格式的index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head>
<title>VVIOT</title>
</head>
<body>
Here is Villivateur Von's laboratory!</br>
<a href="https://www.vvzero.com">Click to enter my blog</a>
<pre>
Time Humidity(%) Temperature(C) Light_Detected
------------------------------------------------------------
</pre>
</body>
</html>

然后配置好合适的权限,在该目录下运行$sudo nohup ./GET &

大功告成!