树莓派云浇水--上层搭建自研版 :P
这个是个人的实际需求。如果出差,家中个别宝贝植物如何看护?
翻文章的话,经常看到的一套是什么检测土壤湿度,判断完数据后浇水的。个人觉得,植物浇水嘛,大部分的普通植物,看到它叶子耷拉了,那就一定要浇水了。鬼个土壤湿度检测模块。我需要的是远程监控模块(让我远程检查植物生存状态),和浇水装置。
当然说白了,就买个家庭监控活动摄像头,再淘个远程浇水是最快解决问题的。
但如果要搞一体化(说白了就是作),应该怎么动手?本文记录一套打法。
BOM表如下,
1. 能联网的树莓派(我后面要用土豆派降低成本,树莓派已经贵的不像话)。240元朝上
2. 网购5vDC输入的usb小水泵,对,就是给鱼缸抽水那玩意儿。15元
👆🏻这玩意儿剪断usb头,把正负极抽出来。
3. 面包板,杜邦线。算10元
4.1路继电器一个。3元
5.树莓派那个csi摄像头。18元
以上成本逃不开。3-5或者至少3和4,可以一起买,包邮。
实现思路就是内网穿透导致公网可以访问到树莓派,查看美丽的花草,然后浇水。
我看现成用motion的也不少,我觉得不需要,其实有实时图片就够了,不用这么大一套框架。接下来介绍散装手法,以及里面最重要的细节。
首先一套cpolar,让树莓派可以公网访问,可以从公网ssh树莓派开始。hmmm cpolar的穿透谈不上什么难度吧,可能就https那里(至少买了基本套餐保留二级域名),有个坑。我采用了去sslforfree网站生成完证书上传树莓派,再配置cpolar和nginx这种方式。另外如果只是自己用,最好上来就用个http auth。具体nginx方面的写法,展示在后面代码部分。
接下来我用的是nginx+php-fpm+mysql这个后台引擎组合拳,前端搭了个wordpress,选择了blank的专题。
按两个钮,看图和浇水。
这个已经是公网访问的成品了。
这俩钮也许在服务器终端是好控制的,但是做到php脚本里真是苦煞老奴(嗯,主要还是因为很多东西不懂)首先其实libcamera和raspi-gpio的控制权都在root手里,或者是因为/dev/media*的控制权在root手里。个人觉得比较保险的一个做法是给运行nginx的user一个sudo免密码权限,具体就是 sudo visudo,然后给对应用户搞两个sudo免密权限。
接下来是写php、js、html和css的痛苦。尤其是这帮混蛋要都在一个php文件里。专业的看这个估计是看笑话,但是对于本人是千辛万苦的代码搬运啊。主要是在专题的index.php里面改,以及创建一个叫execute-shell-command.php。 直接上关键代码,留以日后嘲笑。
index.php
<?php
/**
* The base (and only) template
*
* @package WordPress
* @subpackage intentionally-blank
*/
?><!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>><?php wp_body_open(); ?><div id="page">
<div class="site-title"><div class="site-title-bg">
<h1><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1>
<?php
$blank_description = get_bloginfo( 'description', 'display' );
if ( $blank_description || is_customize_preview() ) :
?>
<p class="site-description"><?php echo esc_html( $blank_description ); ?></p>
<?php endif; ?>
</div></div>
<?php the_custom_logo(); ?>
<div class="pic_button">
<button id="pic_taking">实时图片</button>
</div>
<p></p>
<div class="water_button">
<button id="water_pouring" onclick="alert('点击确定,开始工作。将浇水10秒');" >浇水</button>
</div>
<script>
const pic = document.getElementById("pic_taking");
const water = document.getElementById("water_pouring");
pic.addEventListener("click", ()=>{executeCommand('taking')});
water.addEventListener("click", ()=>{executeCommand('pouring')});
async function executeCommand(action) {
try {
const res = await fetch(`https://hahahahhaha.com/interesting_scripts/execute-shell-command.php?action=${action}`);
console.log(res.json());
} catch (error) {
console.error(new Error(error));
}
}
</script>
</div>
<p></p>
<div style="text-align: center;">
<?php
$fileList = glob("wp-content/uploads/plant_pic/*");
foreach($fileList as $filename){
if (is_file($filename)){
echo "<img src=".$filename." />";
break;
}
}
if (count($fileList)==0)
echo "<img src=wp-content/uploads/Untargeted/FileNotFound.jpg />";
?>
</div>
<footer id="colophon" class="site-footer">
<?php if ( get_theme_mod( 'blank_show_copyright', true ) ) : ?>
<div class="site-info">
<?php echo wp_kses_post( get_theme_mod( 'blank_copyright', __( 'Intentionally Blank - Proudly powered by WordPress', 'intentionally-blank' ) ) ); ?>
</div>
<?php endif; ?>
</footer>
</div><!-- #page -->
<?php wp_footer(); ?></body></html>
execute-shell-command.php
<?php
// Get the query params
$action = $_GET["action"];
if (isset($action)) {
if ($action === "taking") {
shell_exec('rm -rf /your/forlder/*');
$now = time();
shell_exec('sudo libcamera-still -o /you/flder/'.$now.'cool.jpg --width 720 --height 640 --mode 720:640 --vflip');
}
if ($action === "pouring") {
shell_exec('sudo raspi-gpio set 17 op'); //设定gpio17为输出
shell_exec('sudo raspi-gpio set 17 dh'); //我的逻辑是高电平时水泵工作
shell_exec('sleep 10'); //工作了10秒
shell_exec('sudo raspi-gpio set 17 dl'); //将gpio17弄回低电平
shell_exec('sudo raspi-gpio set 17 ip pd'); //将gpio恢复成最初的未选择状态
}
}
// Anything echo'd will be the response to the request
// and will get console.logged in the browser
echo json_encode(array("requested action"=>$action));
nginx配置文件:
##
# Default server configuration
#
upstream php {
server unix:/run/php/php7.3-fpm.sock;
server 127.0.0.1:9000;
}
server {
listen 80;
listen [::]:80;
auth_basic "请输入口令!";
auth_basic_user_file /your/folder/path/.htpasswd;
root /your/folder/path;
index index.html index.htm index.php;
server_name nameyourserver.com;
add_header Content-Security-Policy upgrade-insecure-requests; #加上,不然报https混入http内容的错误
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ~ /\. {
deny all;
}
location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
location /wordpress {
try_files $uri $uri/ /wordpress/index.php?$args;
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
fastcgi_index index.php;
fastcgi_pass unix:/run/php/php7.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
整体板子布局:
水泵与继电器的连接方式,抄了个灯泡的图,反正也就电源正负,一个意思啦。
借鉴了很多提问回答,大佬思路。太多了,实在点不了鸣谢。只能说,都是站在高手们肩膀上瞎折腾。感谢!