iT邦幫忙

0

nodemcu和raspberry pi 的問題

  • 分享至 

  • xImage

我目前在做把nodemcu接感測器讀取值之後用AP的方式傳到raspberry pi資料庫儲存,之後顯示在raspberry pi 的網頁上(raspberry pi是網頁伺服器),目前我只能把資料庫的值列出來,我看大部分教學都是直接把網頁寫在nodemcu裡,感測器讀到值也能直接給程式用AP連接到他的網頁直接看到,可是我網頁是raspberry pi負責的,請問有甚麼方法可以把感測器的值透過nodemuc給raspberry pi後在網頁顯示嗎?
(我想的顯示大概是 溫度:"感測器值"度 )
程式碼差不多是這樣

nodemcu的程式

#include <ESP8266WiFi.h>
#include <DHT.h>
#define DHTPIN D3
//#define HOST "192.168.2.121"
//const char* ssid = "ASUSLAB";
//const char* password = "ASUSASUS";
#define HOST "192.168.0.13"
const char* ssid = "myssid";
const char* password = "mypassword";

DHT dht(DHTPIN, DHT11);
void setup() {
Serial.begin(115200);
delay(10);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Print the IP address
Serial.print("Your NodeMCU IP is : ");
Serial.print(WiFi.localIP());
}
void loop() {
float t;
float h;
t = dht.readTemperature();
h = dht.readHumidity();
while (isnan(h))
{
yield();
h = dht.readHumidity();
//return;
}
while (isnan(t))
{
yield();
t = dht.readTemperature();
//return;
}
Serial.println("-------------------");
Serial.print("溫度:");
Serial.println(t);
Serial.print("濕度:");
Serial.println(h);
WiFiClient client;
if (!client.connect(HOST,80)) {
Serial.println("connection failed");
Serial.println("wait 5 sec...");
delay(5000);
}
String dbserver = HOST;
String getStr = "GET /AddData.php?";
getStr +="Temp=";
getStr += String(t);
getStr +="&Humidity=";
getStr += String(h);
getStr += " HTTP/1.1\r\n";
getStr += "Host: " + String(dbserver) \
+ "\r\n"+ "Connection: close\r\n\r\n";
client.print(getStr);
delay(10);
client.stop();
delay(10000);
}

Sensor.html

<html>
<head>
<meta charset="utf-8">
<title>增加資料</title>
</head>
<body>
<form action="AddData.php" method="get">
溫度:<input type="text" name="Temp"><br>
濕度:<input type="text" name="Humidity"><br>
<input type="submit" value="送出資料">
</form>
<input type="button" value="查詢資料庫資料"
onclick="location.href='http://192.168.0.13/show.php'">
</body>
</html>

show.php

<html>
<head>
<meta charset="utf8">
</head>
<body>
<table border=3>
<tr>
<th>ID</th>
<th>溫度</th>
<th>濕度</th>
</tr>
<?php
date_default_timezone_set("asia/taipei");
$dsn='mysql:host=127.0.0.1;dbname=Sensors';
try {
$db=new PDO($dsn,'pi','raspberry');
$db->exec("set names utf8");
$sql="select * from DHT;";
foreach ($db->query($sql) as $row) {
echo "<tr>";
echo " <td>".$row["ID"]."</td>";
echo " <td>".$row["Temp"]."</td>";
echo " <td>".$row["Humidity"]."</td>";
echo "</tr>";
}
} catch (PDOException $e) {
printf("DATABASER_ERRMESG: %s",$e->getMessage());
}
?>
</table>
<input type="button" value="返回上一頁" onclick="location.href='http://192.168.0.13/Sensor.html'">
</body>
</html>

AddData.php

<?php
date_default_timezone_set("asia/taipei");
$dns="mysql:host=127.0.0.1;dbname=Sensors";
$Temp=$_GET['Temp'];
$Humidity=$_GET['Humidity'];
try{
$db=new PDO($dns,'pi','raspberry');
$db->exec("set names utf8");
$sql="insert into DHT(Temp,Humidity) values('$Temp','$Humidity');";
$result=$db->exec($sql);
if($result==1){
echo "新增成功";
}else{
echo "新增失敗";
}
}catch(PDOException $e){
printf("DATABASE_ERRMESG:%s",$e->getMessage());
}
?>

https://ithelp.ithome.com.tw/upload/images/20220510/20146916wEmWmWWvwC.png

CCCCC iT邦新手 4 級 ‧ 2022-05-10 22:51:33 檢舉
nodemcu接感測器讀取值>傳到raspberry pi資料庫儲存
>樹莓派裡的網頁讀自身的資料庫來顯示 不是這樣就好嗎?
sc05201 iT邦新手 5 級 ‧ 2022-05-10 23:18:11 檢舉
我想說只是要顯示值在網頁而已,可能之後跟其他東西互動後會有一組資料這時才要存,要是只是為了顯示把一堆不需要保存的資料丟到資料庫會不會爆?
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
淺水員
iT邦大師 6 級 ‧ 2022-05-10 22:56:18

請問有甚麼方法可以把感測器的值透過 nodemuc 給 raspberry pi 後在網頁顯示嗎?

看你程式碼,應該是 nodemuc 發 http request 給 raspberry pi
raspberry pi 收到後先存在資料庫
使用者要看的時候,是直接從 raspberry pi 取得網頁內容

目前看起來這種做法應該是沒問題的,不知道你有疑問的地方在哪?

看更多先前的回應...收起先前的回應...
淺水員 iT邦大師 6 級 ‧ 2022-05-10 23:49:03 檢舉

我想說只是要顯示值在網頁而已,可能之後跟其他東西互動後會有一組資料這時才要存,要是只是為了顯示把一堆不需要保存的資料丟到資料庫會不會爆?

如果說不需要歷史紀錄
那 raspberry pi 的資料表可以建立成

THETABLE

欄位名稱 型態 索引
key varchar(32) unique
value varchar(128)

預先填入

INSERT INTO THETABLE(`key`, `value`) VALUES('DHT', '')

AddData.php

//(前略)
$val = json_encode(['Temp'=>$Temp, 'Humidity'=>$Humidity]);
$sql = "UPDATE THETABLE SET `value` = '$val' WHERE `key` = 'DHT'";
//上面的 SQL 可能要再修改才能正確處理字串
//用prepare 是好選擇,也比較安全
//這邊只是方便解釋先這樣寫
//(後略)

show.php

//(前略)
$sql = "SELECT `value` FROM THETABLE WHERE `key` = 'DHT'";
//取出後,用 json_decode 轉換為 ['Temp'=>溫度, 'Humidity'=>濕度]
//(後略)
sc05201 iT邦新手 5 級 ‧ 2022-05-11 11:16:46 檢舉

請問AddData.php的
$sql = "UPDATE THETABLE SET value = '$val' WHERE key = 'DHT'"
意思是不是每次傳值進去後就更改原來的資料,所以不管傳多少次都只有一筆資料一直在更改?

obarisk iT邦研究生 2 級 ‧ 2022-05-11 11:18:36 檢舉

這個寫 db 是不是有點大浪費了?
何不考慮直接寫在 tmpfs

淺水員 iT邦大師 6 級 ‧ 2022-05-11 11:33:56 檢舉

sc05201 就是對同筆資料一直更新
obarisk 有想過要不要用文字檔存資料,不過為了避免寫入衝突要加鎖就是。tmpfs 等等我看一下是什麼,好像用 shared memory 也可以

淺水員 iT邦大師 6 級 ‧ 2022-05-11 13:42:55 檢舉

用 shared memory 的做法
(php.ini 的 shmop extension 要開啟)

MemCache.php

<?php
class MemCache
{
    private $shmId;
    private $doubleLength;

    public function __construct($mode = 'c')
    {
        $this->doubleLength = strlen(pack('d', 0));
        $key = ftok(__FILE__, 't');
        $this->shmId = shmop_open($key, $mode, 0644, $this->doubleLength * 2);
        if ($this->shmId === false) {
            throw new \Exception('cannot open shared memory');
        }
    }

    public function save($temperature, $humidity)
    {
        return shmop_write($this->shmId, pack('d2', $temperature, $humidity), 0);
    }

    public function read()
    {
        $data = shmop_read($this->shmId, 0, $this->doubleLength * 2);
        return unpack('dTemp/dHumidity', $data);
    }
}

AddData.php

<?php
require('MemCache.php');
$temp = filter_input(INPUT_GET, 'Temp', FILTER_VALIDATE_FLOAT);
$humidity = filter_input(INPUT_GET, 'Humidity', FILTER_VALIDATE_FLOAT);
if (
    $temp === false || $temp === null ||
    $humidity === false || $humidity === null
) {
    echo "新增失敗(參數錯誤)";
    exit();
}
if (
    ($memdb = new MemCache()) === false ||
    $memdb->save($temp, $humidity) === false
) {
    echo "新增失敗(寫入錯誤)";
    exit();
}
echo "新增成功";

show.php

<?php
require('MemCache.php');
$memdb = new MemCache('a');
$data = $memdb->read();
?>
<!DOCTYPE html>
<html lang="zh-Hant-TW">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <table>
        <thead>
            <tr>
                <th>溫度</th>
                <th>濕度</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td><?php echo $data['Temp'];?></td>
                <td><?php echo $data['Humidity'];?></td>
            </tr>
        </tbody>
    </table>
</body>
</html>
obarisk iT邦研究生 2 級 ‧ 2022-05-11 16:42:02 檢舉

tmpfs 是 linux 的虛擬硬碟。通常是 ramdisk

至於檔案的寫入衝突,應該 os 會處理才對

我要發表回答

立即登入回答