First NodeMCU Project
说起物联网,最早接触的是Arduino。可是入手Arduino Mega后,一直没做出什么好玩的东西,以致Mega丢在角落里好几年。近来在部门经理的怂恿下,入手了NodeMCU,做了个检测盆栽的土壤湿度。本来想在Github开个项目,但是这第一版太简单了,就随便记录一下。
NodeMCU的特点,在于自带WiFi(还可以使用AP模式),而且价格便宜。当然,缺点也在WiFi,比较耗电。为了省电,可以设置网卡的硬件参数(wifi.setphymode()
),关闭WiFi(wifi.sleeptype()
),甚至是整块板进入深度睡眠模式(node.dsleep()
, rtctime.dsleep()
)。其开源、基于Lua的开发简单、尺寸迷你等优点,也是其好玩之处。
这个项目很简单,就是NodeMCU连个土壤湿度检测模块,定时(10分钟)获取一次数据,并上传到服务器。服务器是采用树梅派,用Python3,利用Flask框架,写了个HTTP服务,用于保存提交的数据,并做数据展示。数据都保存在MySQL数据库。
NodeMCU上的init.lua
print("\n")
print("ESP8266 Started")
dsleepTime = 630000000
ssid = "my-wifi"
password = "123456"
serverIp = "192.168.1.1"
serverPort = 8080
wifi.setphymode(wifi.PHYMODE_N)
wifi.setmode(wifi.STATION)
wifi.sta.config(ssid, password)
tmr.alarm(0,1000,1,function()
curIp = wifi.sta.getip()
if curIp ~= nil then
print("Current IP:"..curIp)
tmr.stop(0)
sendData(readValue(0, 5))
end
end)
--发送数据到服务器
function sendData(value)
print("sendData start")
conn = net.createConnection(net.TCP, false)
conn:on("receive", function(conn, pl)
print("Send data with value: "..value)
print("Result:\n"..pl)
conn:close()
conn = nil
wifi.sta.disconnect()
node.dsleep(dsleepTime)
end)
conn:connect(serverPort, serverIp)
conn:send("GET /gather/?key=123456&value="..value
.." HTTP/1.1\r\nHost: " + serverIp + "\r\n"
.."Connection: keep-alive\r\nAccept: */*\r\n\r\n")
--connect time out
tmr.alarm(1,5000,1,function()
print("[error]connet to server time out")
--conn:close()
--conn = nil
--wifi.sta.disconnect()
tmr.stop(1)
node.dsleep(dsleepTime)
end)
end
--读取土壤湿度数据
--一次有效的采样,最少取3次数据,去掉最大值和最小值,再计算平均值
function readValue(adcPin, readTimes)
if readTimes <= 2 then
readTimes = 3
end
local curValue = 0
local maxValue = 0
local minValue = 0
local sumValue = 0
for i = 0, readTimes - 1 do
curValue = adc.read(adcPin)
sumValue = sumValue + curValue
if maxValue < curValue then
maxValue = curValue
end
if (minValue == 0) or (minValue > curValue) then
minValue = curValue
end
end
sumValue = sumValue - maxValue - minValue
curValue = math.floor(sumValue / (readTimes - 2))
return curValue
end
服务器上的HTTP服务,文件site.ini
[uwsgi]
socket = 127.0.0.1:8080
processes = 2
threads = 1
plugins = python3
master = true
pythonpath = /opt/work/web_gather
chdir = /opt/work/web_gather
module = site
callable = app
chmod-socket = 777
memory-report = true
服务器上的HTTP服务,文件site.py
#!/bin/python3
from datetime import datetime
from flask import Flask, request, abort, render_template
from flask.ext.sqlalchemy import SQLAlchemy
from sqlalchemy import desc
app = Flask(__name__)
app.config['SECRET_KEY'] = '123456'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:123456@127.0.0.1/web_gather'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['HUMIDITY_MIN'] = 740
db = SQLAlchemy(app)
class Humidity(db.Model):
__tablename__ = 'humidity'
id = db.Column('id', db.Integer, primary_key=True)
createDate = db.Column('create_date', db.DateTime)
sourceValue = db.Column('source_value', db.Integer)
value = db.Column('value', db.Integer)
def __repr__(self):
return '<Humidity % r>' % self.id
@app.route('/', methods=['GET', 'POST'])
def index():
key = request.args.get('key', '')
if key == app.config['SECRET_KEY']:
sourceValue = request.args.get('value', '0')
value = (1024 - int(sourceValue)) / 1024 * 100
curTime = datetime.today()
humidity = Humidity(createDate=curTime, sourceValue=sourceValue, value=value)
db.session.add(humidity)
db.session.commit()
return 'true'
humidities = Humidity.query.order_by(desc(Humidity.createDate)).limit(500)
return render_template('humidity.html', humidities=humidities)
if __name__ == '__main__':
app.run(debug=False, host='127.0.0.1', port=8080)
#app.debug = False
#app.run()
MySQL的表定义
CREATE TABLE `humidity` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`create_date` datetime DEFAULT NULL,
`source_value` int(11) DEFAULT NULL,
`value` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2554 DEFAULT CHARSET=utf8