前言:這篇是「威玲旺卡Aileen」和「阿狗A-Go」的原創物聯網邊造邊寫系列筆記。沒有告知時請不要轉載吶,謝謝。另外我要感謝Marcel Ochsendorf(馬賽)同學對我的指導。
0. 本集問題情景:
阿狗想在何時何地都可以知道他生命中最重要的地方——狗窩的溫度和濕度。這樣他可以決定是不是需要打開暖氣和加濕器以保持他狗毛的蓬松和柔軟,同時也可以知道供暖系統和加濕器的真正效果。目前他能在一個網頁上看到實時數據就滿意了,阿狗對web框架一無所知,手邊也只有一塊樹莓派,他打算用很老很成熟的LAMP(Linux-Apache-MySQL-PHP)來實現它。
0. 這個邊造邊寫的筆記將會涵蓋:
- 部署一個aws虛擬主機,打造服務器+web構架+域名
- 創建aws Linux AMI主機
- 通過yum安裝LAMP
- 為主機申請靜態IP,修改域名DNS到主機
- 用樹莓派讀取溫度濕度傳感器數值并上傳數據庫(通過requests)
- 硬件連接DHT傳感器
- 安裝Adafruit Sensor Library,測試讀取傳感器數據
- 這里狗要思考一下在哪里登錄數據庫,所以狗先去了第三部分,然后回到這個點繼續
- 安裝requests,通過它進行數據交流
- 創建數據庫表結構,用php與MySQL對話,最終顯示傳感器實時數據至頁面
- 通過phpMyAdmin界面設計表結構
- 寫用來登錄數據庫的db.php
- 寫用來執行插入操作的insert.php(回到2.4,在樹莓派上requests它,測試數值是否插入數據庫成功)
- 寫顯示頁面
我們開始動手啦。
1. 部署一個aws虛擬主機,打造服務器+web構架+域名
1.1裝一個aws實例
按照非常好的官方文檔,
Amazon EC2 Linux 實例入門
新手教程-如何在 Amazon AWS 上搭建和部署網站
使用 SSH 連接到 Linux 實例
這一步的目標是:
ssh鏈接實例成功!
我當下的安全組設置,感覺非常不安全,后面一定要改改。
說到要熟悉aws最快最好的方式,我不得不提qwiklabs,真實環境lab,非常棒。
1.2安裝Web構架
教程走一個
教程:在 Amazon Linux 上安裝 LAMP Web 服務器
這一部的完成的鑒定是,登錄主機DNS可以看到它:
登錄主機DNS/phpinfo.php可以看到裝的php版本,
登錄主機DNS/phpMyAdmin可以看到數據庫登錄入口,
我安裝的過程中原來用
sudo yum install -y http php php-mysql mysql mysql-server
后來折騰了好久也弄不好phpMyAdmin,后來只能全卸載,確定版本,這才搞定
sudo yum install -y httpd24 php70 mysql56-server php70-mysqlnd
創建index.php或者index.html就可以替換掉默認主頁了。
這些都是在主機里弄的,沒有用到亞馬遜的RDS(Relational Database Service)也沒有掛載EFS(Elastic File System)留給之后探索。
1.3為主機申請靜態IP,修改域名DNS到主機
官方文檔 彈性 IP 地址
獲得IP后一定要關聯運行著的主機,否則沒有關聯實例的IP會被扣費,此外,如果申請了靜態IP并且關聯后,把主機給關掉了,那么這個IP也會被扣費。
阿狗買了一個叫wolfiethedog.de的域名,在DNS中將A地址指向靜態IP就完成了。但當我用CNAME將www指向主機地IPv4地址(ec2-xxxxxxxx.eu-central-1.compute.amazonaws.com)卻一直失敗,現在也沒搞定,我把subdomain的“www”設置成域名跳轉到主頁作為臨時的辦法。
至此,我們的aws+LAMP搞定了,用時沒超過2小時。
2. 用樹莓派讀取溫度濕度傳感器數值并上傳數據庫(通過requests)
2.1 硬件連接DHT傳感器
樹莓派針腳的布局(派3至少是這樣的)
淘寶來的溫度濕度傳感器,一定要找找模塊名字,找到了叫DHT11,三個針腳VCC,DATA和GND
分別接到01(3.3v電壓),07(GPIO04)和06(GOUND)
okay,希望成功吧,啟動派,準備讀取數值了。
2.2 安裝Adafruit Sensor Library,測試讀取傳感器數據
我原來一直以為我需要讀出二進制raw data再換算成可讀數據,還琢磨著我該怎么查看它的輸出結構呢?
但其實庫類已經把這個問題給handle了。移步 https://github.com/adafruit/Adafruit_Python_DHT
安裝完之后,因為我的傳感器是DHT11,所以需要修改一下它的simpletest.py
import Adafruit_DHT
sensor = Adafruit_DHT.DHT11
pin = 4
humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)
if humidity is not None and temperature is not None:
print('Temp={0:0.1f}*C Humidity={1:0.1f}%'.format(temperature, humidity))
else:
print('Failed to get reading. Try again!')
成功啦!
2.3 要思考一下在哪里登錄數據庫
我們差一點就要在樹莓派連接數據庫了,因為當時我一直在想用php連接數據庫該怎么碼,后來Marek說用python連接MySQL不就好了,我那個時候思維被偏向了,我在派上安了MySQLdb,打算遠程登錄數據庫,然后再插入數據,用root的身份和密碼竟然被拒絕,這時我發現root是默認沒有遠程登錄權限的,我要通過mysql script去賦予權限,
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;
FLUSH PRIVILEGES;
隨后還經歷了mysql需要升級,卻一直失敗,最后要--force才通過
mysql_upgrade --force -uroot -p
直到都折騰完了,我才頓悟,我為什么要在派上登錄呢?這情況派只要構建一個 Request 對象,其他事情都該交給服務器。所以接下來我們要開始在服務器上寫php。
3. 創建數據庫表結構,用php與MySQL對話,最終顯示傳感器實時數據至頁面
3.1 通過phpMyAdmin界面設計表結構
本科知識復習,建表,我們在數據庫DHT下,建立了一個叫Pi_reader的表,其中有鍵:
- ID索引(作為主鍵同時自動加A_I)
- 溫度
- 濕度
- 時間戳
Pi_reader表結構.png
期間還溫習了一下 char、varchar和text的區別
3.2 寫用來登錄數據庫的db.php
Apache的web文件默認地址是 /var/www/html
其實root根本不需要遠程登錄權限。
db.php代碼
<?php
DEFINE('DB_USERNAME','root');
DEFINE('DB_PASSWORD','password');
DEFINE('DB_HOST','xx.xx.xxx.xxx');
DEFINE('DB_DATABASE','DHT');
$mysqli = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
if (mysqli_connect_error()){
die('Connect Error('.mysqli_connect_error().')'.mysqli_connect_error());
}
echo '<i>數據庫已成功連接。</i>';
?>
3.3 寫用來執行插入操作的insert.php
我們需要將收到的請求,如果是合理的,就添加進數據庫。
合理是指符合這樣的格式
http://xx.xx.xxx.xxx.xxx/insert.php?temp=aa&hum=bb&token=0000
那么溫度aa,濕度bb和timestamp都會被加入到數據庫。
其中token是充當一個密碼保護的功能。
如果數據項目很多的話,可以傳輸一個xml或者json
insert.php代碼
<?php
include 'db.php';
if(!isset($_GET["token"]) || $_GET["token"] != "0000"){
echo "wrong_token";
exit();
}
$temp = $_GET["temp"];
$hum = $_GET["hum"];
echo $temp;
$sql = "INSERT INTO Pi_reader (id,temperature,humidity,timestamp) VALUES (NULL, '". $temp ."','". $hum ."', CURRENT_TIMESTAMP);";
$result = mysqli_query($mysqli, $sql);
?>
3.4 寫顯示頁面
在第一集中,我只寫了白板。
連接數據庫后,讀取一個表的所有記錄,循環輸出三個鍵值,溫度,濕度,時間戳。
index.php
<?php
echo "<h1>阿狗狗窩的溫度濕度實時監視器</h1>";
include 'db.php';
$query = "SELECT * FROM Pi_reader";
$result = mysqli_query($mysqli, $query);
echo "<table>";
echo "<tr><td>" . "<b>溫度</b>" . "</td><td>" . "<b>濕度</b>" . "</td><td>". "<b>時間</b>". "</td></tr>";
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC))
{
echo "<tr><td>" . $row[temperature] . "°C </td><td>" . $row[humidity] . "% </td><td>". $row[timestamp]. "</td></tr>";
}
echo "</table>";
mysql_close();
?>
2.4 回到樹莓派,完成最后的對服務器的請求
現在只剩下最后一步了,在派每次讀取數據后,我們想要它發送一個請求到服務器,這個請求說,“我請求把xx溫度xx濕度加入數據庫。”
而且我們希望1分鐘可以更新一次數據。
我們安裝了 Requests
直接在剛才讀取數據的腳本上粗暴地改動:
#!/usr/bin/python
import Adafruit_DHT
import requests
import time
sensor = Adafruit_DHT.DHT11
pin = 4
#humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)
temp_temp = 0
temp_hum = 0
while(1):
humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)
if humidity is not None and temperature is not None:
if str(humidity) is not str(temp_hum) or str(temperature) is not str(temp_temp):
r = requests.get("http://xx.xx.xxx.xxx/insert.php?token=0000&temp="+ str(temperature) +"&hum=" +str( humidity))
print(r.status_code)
print('Temp={0:0.1f}*C Humidity={1:0.1f}%'.format(temperature, humidity))
temp_temp = temperature
temp_hum = humidity
else:
print('Failed to get reading. Try again!')
time.sleep(60)
測試!
好,我們現在登錄 http://wolfiethedog.de/woofaniot/s01e01/ 看看效果
頁面出現了樹莓派中獲取的當下溫度和濕度,細細研究,時間間距并不是準時的1分鐘。request給服務器的過程中還是出現了些短小的延時的。
沒有css的html終究是難看的,但是我們的毛坯房已經有了。下一集我和阿狗會專門研究顯示的儀表盤,dashboard。
這個實驗的額外收獲就是,那個小小的加濕器在整個房間的效果上還是有功效的。
至此,《嚎出一個極簡物聯網》第一集《美味的云端LAMP派》就完成了。
耶!