本文參考 NodeMCU 官網 API : http://nodemcu.readthedocs.org/en/dev/,將 DHT22 的感測資料透過 http 呼叫傳送給SQL server,為了支援浮點運算,須使用韌體版本為支援浮點數運算之nodemcu_float_0.9.6-dev_20150704.bin,與先前使用的整數版本不同,請先自行更新韌體。
1. DHT模組 API 測試
NodeMCU DHT API:
http://nodemcu.readthedocs.org/en/dev/en/modules/dht/ ,
DHT 模組 API 可以自行判斷 DHT11 (整數)與其他 DHT (浮點數) 之結果
函數
|
功能
|
讀取以下型號之DHT感測器: DHT11, 21, 22,
33, 44
|
|
讀取DHT11感測器
|
|
讀取DHT11以外之感測器
|
回應結果:dht.OK (0),dht.ERROR_CHECKSUM (1),dht.ERROR_TIMEOUT (2)
Lua程式測試範例:
pin = 2
status, temp, humi, temp_dec,
humi_dec = dht.read(pin)
if status == dht.OK then
-- Integer firmware using this example
print(string.format("DHT
Temperature:%d.%03d;Humidity:%d.%03d\r\n",
math.floor(temp),
temp_dec,
math.floor(humi),
humi_dec
))
-- Float firmware using this example
print("DHT
Temperature:"..temp..";".."Humidity:"..humi)
elseif status == dht.ERROR_CHECKSUM
then
print( "DHT Checksum error." )
elseif status == dht.ERROR_TIMEOUT
then
print( "DHT timed out." )
end
|
2. 將 DHT 感測資料上傳至 MySQL 伺服器
這部分有 init.lua、user.lua、dht22_report.lua 三個模組。 init.lua 於開機時會自動執行,程式碼如下:
local timerID=0 -- LED閃滅用的 timer編號
local pinLED=4
local lighton=0
--
-- flashLED()
--
function flashLED()
if (wifi.sta.getip()==nil) then
gpio.write(pinLED,gpio.LOW)
else
if (lighton==1) then
gpio.write(pinLED,gpio.HIGH)
lighton = 0
else
gpio.write(pinLED,gpio.LOW)
lighton = 1
end
end
end
--
-- checkWifi()
--
function checkWifi()
local ip = wifi.sta.getip()
if(ip==nil) then
print("Connecting...")
else
tmr.stop(timerID)
print("Connected to AP!")
print(ip)
tmr.alarm(timerID, 500,
tmr.ALARM_AUTO, flashLED)
end
end
--
-- main()
--
-- init LED status
gpio.mode(pinLED, gpio.OUTPUT)
gpio.write(pinLED,gpio.LOW)
-- connect Wifi
wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","PASSWORD") -- 這裡要替換成自己 AP 的 SSID 與密碼
wifi.sta.autoconnect(1)
tmr.stop(timerID) -- stop previous
timer
tmr.unregister(timerID)
tmr.register(timerID, 2000,
tmr.ALARM_AUTO,checkWifi)
if not tmr.start(timerID) then
print("tmr.start("..timerID..") failed!")
end
-- start user file
dofile("user.lua")
|
user.lua負責啟動所有服務,程式碼如下:
dofile("dht22_report.lua");
|
dht22_report.lua 每隔 10 秒讀取 DHT 的感測值,並用 POST 方式上傳至 MySQL 伺服器:
--
--
DHT22_report
--
--
Note: this module needs the float version firmware :
-- nodemcu_float_0.9.6-dev_20150704.bin
--
local timerID=1 -- 讀取 DHT22用的計時器編號
local pinDHT=2
local
sqlServer="XXX.XXX.XXX.XXX" --這裡要替換成伺服器的 IP
local Location="NodeMCU"
--
-- sendDHT(temp, humi)
--
function postDHT(temp, humi)
local conn = nil
-- receive()
function receive(conn, payloadout)
if (string.find(payloadout,
"Status: 200 OK") ~= nil) then
print("Posted OK");
end
end
--connection()
function connection(conn, payloadout)
local params =
"loc="..Location.."&temp="..temp.."&hum="..humi --post paramaters
-- Post
local httpString = "POST /SensorReport.php
HTTP/1.1\n"
.. "Host:
"..sqlServer.."\n"
.. "Content-Type:
application/x-www-form-urlencoded\n"
.. "Content-Length:
"..string.len(params).."\n\n"
.. params
print("***postDHT:\n"..httpString.."\n")
conn:send(httpString)
end
--
function disconnection(conn, payloadout)
conn:close();
collectgarbage();
end
-- create connection and register callback funciton
conn = net.createConnection(net.TCP, 0)
conn:on("receive", receive)
conn:on("connection", connection)
conn:on("disconnection", disconnection)
-- connect to server
conn:connect(80,sqlServer)
end
--
-- readDHT()
--
function readDHT()
status, temp, humi, temp_dec, humi_dec = dht.read(pinDHT)
if status == dht.OK then
local t = temp + temp_dec/1000
local h = humi + humi_dec/1000
print(string.format("***DHT:
Temperature : %.1f Humidity :
%.1f",t,h)) --debug
if(wifi.sta.getip()==nil) then
print("***DHT: Wifi is not
connected")
else
postDHT(t,h)
end
elseif status == dht.ERROR_CHECKSUM then
print( "***DHT: Checksum
error." )
elseif status == dht.ERROR_TIMEOUT then
print( "***DHT: timed out."
)
end
end
--
-- main()
--
tmr.stop(timerID) -- stop previous
timer
tmr.unregister(timerID)
tmr.register(timerID, 10000,
tmr.ALARM_AUTO, readDHT)
if not tmr.start(timerID) then
print("tmr.start("..timerID..") failed!")
end
--- start message
print("start DHT report
service")
|
3. MySQL 伺服器的 http API
最後是 SensorReport.php,雖然是只用 POST 傳資料,但仍將 GET 放進來,網頁單獨測試時,可以直接在瀏覽器網址輸入測試資料, root 與 password 要替換成 mysql 的帳密 :
<?php
//The 'root' and 'password' is required to be setup according to your own
mysql installation
$db = mysql_pconnect("localhost","root","password") or
die('[{"Msg":"'.mysql_error().'"}]');
mysql_query("SET CHARACTER SET 'UTF8';");
mysql_query('SET NAMES UTF8;');
mysql_query('SET CHARACTER_SET_CLIENT=UTF8;');
mysql_query('SET CHARACTER_SET_RESULTS=UTF8;');
mysql_select_db("HomeDB");
date_default_timezone_set('Asia/Taipei');
$loc="";
$temp=-999;
$hum=-999;
if (isset($_GET['loc'])) {
$loc= $_GET['loc'];
}
if (isset($_GET['temp'])) {
$temp =
$_GET['temp'];
}
if (isset($_GET['hum'])) {
$hum = $_GET['hum'];
}
if (isset($_POST['loc'])) {
$loc = $_POST['loc'];
}
if (isset($_POST['temp'])) {
$temp=
$_POST['temp'];
}
if (isset($_POST['hum'])) {
$hum= $_POST['hum'];
}
if ($loc=="") { //
invalid location
die(
'[{"Msg":"loc is null"}]'); //result code
}
$query = 'INSERT INTO `HomeDB`.`sensor` '.
'(`Date`, `Time`, `Location`, `Temperature`,
`Humidity`)'.
' VALUES '.
'(CURDATE(), CURTIME(),"'.$loc.
'","' .$temp. '","' .$hum.'");';
if(mysql_query($query)>0) {
//create successfully
print '{"Msg":"OK"},';
} else {
print '{"Msg":"FAIL"},';
}
mysql_close();
?>
|
參考資料
[1] “NodeMCU
Documentation”, http://nodemcu.readthedocs.org/en/dev/
沒有留言:
張貼留言