lot_manager/README.md

673 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 1. 项目简介
# 2. 开发环境部署
## 软件要求
#### 已经测试过的系统
- Debian GNU/Linux 12(bookworm) Linux version 5.16.17+
## 环境安装
```
# 首先,确信你的机器安装了python 3.11.2
$ python --version
Python 3.11.2
# 同步本地软件包列表与远程软件源中的最新软件包
$ sudo apt update
# 安装supervisor进程管理
$ sudo apt install supervisor
$ supervisord -v
4.2.5
# 安装FFmpeg推流管理
$ sudo apt install ffmpeg -y
$ ffmpeg -version
ffmpeg version 5.1.4-0+deb12u1 Copyright (c) 2000-2023 the FFmpeg developers
built with gcc 12 (Debian 12.2.0-14)
# 安装git
$ sudo apt install git
# 设置时区为上海
$ sudo timedatectl set-timezone Asia/Shanghai
$ date
Thu Dec 14 15:13:45 CST 2023
# 更新py库
$ pip3 install --upgrade pip
```
## 配置wifi
```
# 使用arp协议查看以太网接口的摄像机地址需要将摄像机连接以太网
$ sudo arp -a
# 系统设置静态IP
# 使用nmcli radio wifi查看wifi开启状态
$ nmcli radio wifi
enabled
# 连接wifi
$ sudo nmcli dev wifi connect <SSID> password <PASSWORD>
```
## 配置系统静态IP
### 使用nmtui网络界面管理
`$ sudo nmtui`
- 设置的静态IP地址网段需要和摄像机在同一个网段
- 无需设置网关即为空。此项解决wifi上网和以太网上网冲突的问题。
- DNS设置为8.8.8.8
- 勾选始终不使用此网络于默认路由
## 配置git和pip
```
# 设置git的usrenmae
$ git config --global user.name xxx
# 设置git的email
$ git config --global user.email xxx
# 设置git拉取代码时用户名和密码的存储
$ git config --global credential.helper store
$ git clone https://gitea.lihaink.cn/xyj/lot_manager.git
$ cd lot_manager
# 安装项目依赖
$ pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
```
## 创建设备名称(系统唯一标识名称)
```
# lihai_lot_walnutpi_dev_1代表1号设备可以自行设置
$ cd ~
$ echo 'lihai_lot_walnutpi_dev_1' | tee device_name
lihai_lot_walnutpi_dev_1
```
## 创建mp4文件目录
```
$ mkdir /home/pi/mp4
```
## 配置定时任务
```
$ sudo crontab -e
# 公共定时任务
# 每小时0分执行
0 * * * * /usr/bin/bash /home/pi/lot_manager/bash/cron_delete_mp4.sh
# 每天00分执行
0 0 * * * /usr/bin/python /home/pi/lot_manager/delete_lot_data_3_days.py
# 针对32G内存卡的定时额外加这个
# 每隔15分钟进行
*/15 * * * * /usr/bin/python /home/pi/lot_manager/delete_than20G.py
```
## 初始化本地数据库
```
$ python /home/pi/lot_manager/create_db.py
```
## 配置supervisor文件
1. 安装完supervisor后会在/etc/supervisor目录下存在supervisord.conf文件和conf.d目录。
```
$ cd /etc/supervisor/
$ ls
conf.d supervisord.conf supervisord.conf.bak
```
2. 需要对supervisord.conf文件进行配置
```
$ sudo cp supervisord.conf supervisord.conf.bak
$ sudo vim supervisord.conf
```
3. 配置信息:
```
; supervisor config file
[unix_http_server]
file=/var/run/supervisor.sock ; (the path to the socket file)
chmod=0777 ; sockef file mode (default 0700)
[supervisord]
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP)
user=root
; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket
user=pi
; The [include] section can just contain the "files" setting. This
; setting can list multiple files (separated by whitespace or
; newlines). It can also contain wildcards. The filenames are
; interpreted as relative to this file. Included files *cannot*
; include files themselves.
[inet_http_server]
host = 127.0.0.1
port = 9001
[program:__mqtt__]
directory=/home/pi/lot_manager
command=/usr/bin/python MQTT.py
user=pi
autostart=true
autorestart=true
redirect_stderr=true
stopsignal=TERM
stopasgroup=True
priority=1
[include]
files = /home/pi/lot_manager/conf/common/*.conf
```
上面是已经修改好的配置文件,修改了其中几项:
- [unix_http_server]
chmod改为0777使得普通用户得以执行。
- [include]
files = /etc/supervisor/conf.d/*.conffiles是用户定义的配置文件。
- [supervisorctl]
添加user=pi使得普通用户得以执行。
- [program:\_\_mqtt\_\_]
添加mqtt配置信息
- 修改/etc/supervisor/conf.d的权限sudo chmod 777 /etc/supervisor/conf.d
4. 设置开启启动supervisor
```
$ sudo systemctl enable supervisor
```
5. 启动supervisor
```
sudo systemctl start supervisor
```
# 3. 项目结构
- lot_manager
- bash
- cron_delete_mp4.sh 定时删除录像脚本
- modify_device_name.sh 修改设备唯一名称脚本
- record.sh 录像脚本
- start_data_upload.sh 开启数据上传脚本
- start_push_stream.sh 启动推流脚本
- stop_data_upload.sh 停止数据上传脚本
- stop_push_stream.sh 停止推流脚本
- stream.sh 推流命令脚本
- conf
- common
- data_upload.conf 数据上传配置
- mqtt.conf mqtt配置
- push_stream.conf 推流配置
- record.conf 录像配置
- sensor_to_local.conf 数据保存在本地
- sensor_to_server.conf 数据发布到mq服务器
- device
- device.conf 不同设备的配置
- example
- cron_for_32G.conf 对于32G卡的定时任务配置
- cron_for_64G.conf 对于64G卡的定时任务配置
- supervisord.conf 配置supervisor文件
- main
- common.conf 公共配置
- tmp
- device_name 需要修改的设备名称
- zhanguan
- topic.conf 展馆的特殊设备
- db/ 本地数据库管理
- MQTT.py
- data_upload.py 数据上传程序
- api.py 本地数据库api
- config.py 读取各种配置文件
- create_db.py 创建数据库程序
- delete_lot_3_days.py 删除数据库中早于3天的数据
- delete_than20G.py 当录像超过20G直接删除直到小于20G
- sensor_to_local.py 数据保存在本地
- sensor_to_server.py 数据发布到服务器
- tool.py 工具
- git_push.sh 推送git脚本
- git_update.sh 更新git脚本
- install.sh 安装依赖脚本
# 4.supervisor参数配置
配置文件都在conf文件夹下。主要是common、main和device文件夹。
- conf
- common 表示supervisor管理的进程配置文件
- device 设置不同device的配置包括订阅主题、发布主题、用户名和密码等
- main 公共配置,包括域名设置、录像上传地址等
### MQTT的supervisor配置文件
directory表示执行命令时首先进入这个文件夹
command表示要执行的命令
user必须是pi
autostart表示随开机或supervisor重启时跟着启动
autorestart表示启动失败自动重启3次
```
[program:__mqtt__]
directory=/home/pi/lot_manager
command=/usr/bin/python MQTT.py
user=pi
autostart=true
autorestart=true
redirect_stderr=true
stopsignal=TERM
stopasgroup=True
priority=1
```
### 数据上传的supervisor配置文件
```
[program:data_upload]
directory=/home/pi/lot_manager
command=/usr/bin/python data_upload.py
user=pi
;是否随开机自启 或者reload自启动
autostart=true
;失败重启
autorestart=true
;重启次数
restart_times=3
redirect_stderr=true
stopsignal=TERM
stopasgroup=True
```
### 推流的supervisor配置文件
注意不要跟随开机或supervisor重启启动
```
[program:push_stream]
directory=/home/pi/lot_manager/bash
command=/usr/bin/bash stream.sh
user=pi
autostart=false
autorestart=true
redirect_stderr=true
stopsignal=TERM
stopasgroup=True
```
### 录像的supervisor配置文件
```
[program:record]
directory=/home/pi/lot_manager/bash
command=/usr/bin/bash record.sh
user=pi
;是否随开机自启 或者reload自启动
autostart=true
;失败重启
autorestart=true
;重启次数
restart_times=3
redirect_stderr=true
stopsignal=TERM
stopasgroup=True
```
### 数据保存在本地的supervisor配置文件
```
[program:sensor_to_local]
directory=/home/pi/lot_manager
command=/usr/bin/python sensor_to_local.py
user=pi
;是否随开机自启 或者reload自启动
autostart=false
;失败重启
autorestart=true
;重启次数
restart_times=3
redirect_stderr=true
stopsignal=TERM
stopasgroup=True
```
### 数据保存在mq服务器的supervisor配置文件
```
[program:sensor_to_server]
directory=/home/pi/lot_manager
command=/usr/bin/python sensor_to_server.py
user=pi
;是否随开机自启 或者reload自启动
autostart=false
;失败重启
autorestart=true
;重启次数
restart_times=3
redirect_stderr=true
stopsignal=TERM
stopasgroup=True
```
## 不同设备的配置
```
# 设备1-32G
# 编号
[lihai_lot_walnutpi_dev_1]
# 订阅的控制主题,必须和系统设置的相同
subscribe_topic=lihai_lot_walnutpi_dev_1
# 发布消息的主题
publish_topic=camera_1
username=lihai_lot_land_1
password=123456
####################################
# 设备2-32G
[lihai_lot_walnutpi_dev_2]
# 订阅的控制主题,必须和系统设置的相同
subscribe_topic=lihai_lot_walnutpi_dev_2
# 发布消息的主题
publish_topic=camera_2
username=lihai_lot_land_1
password=123456
####################################
# 设备3-64G
[lihai_lot_walnutpi_dev_3]
# 订阅的控制主题,必须和系统设置的相同
subscribe_topic=lihai_lot_walnutpi_dev_3
# 发布消息的主题
publish_topic=camera_3
username=lihai_lot_land_1
password=123456
####################################
# 设备4-64G
[lihai_lot_walnutpi_dev_4]
# 订阅的控制主题,必须和系统设置的相同
subscribe_topic=lihai_lot_walnutpi_dev_4
# 发布消息的主题
publish_topic=camera_4
username=lihai_lot_land_1
password=123456
####################################
# 设备5-64G
[lihai_lot_walnutpi_dev_5]
# 订阅的控制主题,必须和系统设置的相同
subscribe_topic=lihai_lot_walnutpi_dev_5
# 发布消息的主题
publish_topic=camera_5
username=lihai_lot_land_1
password=123456
####################################
# 设备6-64G
[lihai_lot_walnutpi_dev_6]
# 订阅的控制主题,必须和系统设置的相同
subscribe_topic=lihai_lot_walnutpi_dev_6
# 发布消息的主题
publish_topic=camera_6
username=lihai_lot_land_1
password=123456
```
### 公共配置
```
# 域名地址
[broker]
host=mqtt.lihaink.cn
port=1883
[record]
post_record_list_url=https://ceshi-iot.lihaink.cn/api/index/file_list
post_record_url=https://ceshi-iot.lihaink.cn/api/index/upload
[publish_pwd]
value=123456
```
# 5. ffmpeg推流设置
推流的脚本为stream.sh内容如下
```
#!/bin/bash
device_name=`cat /home/pi/device_name`
/usr/bin/ffmpeg -rtsp_transport tcp -re -i rtsp://admin:123456@192.168.0.123:554/mpeg4 -c copy -preset fast -r 20 -flvflags no_duration_filesize -f rtsp -rtsp_transport tcp rtsp://47.108.186.87:554/live/$device_name
```
对于ffmpeg的参数设置如下
- -rtsp_transport_tcp tcp 表示以tcp进行获取流保证数据完整性
- -re 表示推流设置
- -i 表示输入流,这里是摄像机地址
- -c 表示直接复制源流对象,不进行编码
- -preset fast表示快速传输
- -r 20表示以帧率20传输
- flvflags no_duration_filesize表示其他一些错误排除
- -f rtsp -rtsp_transport tcp 表示输出的文件格式输出为rtsp流也是tcp传输
- rtsp://47.108.186.87:554/live/$device_name表示推流地址
# 6.录像保存设置
录像的脚本为record.sh内容如下
```
#!/bin/bash
RTSP_URL="rtsp://admin:123456@192.168.0.123:554/mpeg4" # RTSP流的URL
OUTPUT_DIR="/home/pi/mp4" # 录像文件保存的目录
RECORD_DURATION=900 # 录像时长(秒)
# 获取当前时间
CURRENT_TIME=$(date +"%Y-%m-%d_%H-%M-%S")
# 构建录像文件名
OUTPUT_FILE="${OUTPUT_DIR}/${CURRENT_TIME}.mp4"
# 开始录制RTSP流
/usr/bin/ffmpeg -rtsp_transport tcp -i "${RTSP_URL}" -c copy -c:a aac -s 1920x1080 -r 15 -crf 35 -t "${RECORD_DURATION}" -f mp4 "${OUTPUT_FILE}"
```
参数设置如下:
- -rtsp_transport_tcp tcp 表示以tcp进行获取流保证数据完整性
- -i 表示输入流,这里是摄像机地址
- -c 表示直接复制源流对象,不进行编码
- -c:a aac表示音频编码格式为aac
- -s 1920x1080是分辨率裁剪
- -r 15是帧率改为15
- -crf 35是改变恒定传输速率值越大压缩越好但质量越差默认值是28
- -t 表示900秒一次保存一次
- -f mp4是保存为mp4文件
# MQTT程序控制配置发布消息和订阅消息
### 设备的编号配置信息
设备的配置为:
```
[lihai_lot_walnutpi_dev_1]
# 订阅的控制主题,必须和系统设置的相同
subscribe_topic=lihai_lot_walnutpi_dev_1
# 发布消息的主题
publish_topic=camera_1
username=lihai_lot_land_1
password=123456
```
其中,
- subscribe_topic 表示订阅的主题,只有订阅后才能进行控制
- publish_topic 表示数据发布的主题
- username 表示客户端进行连接的用户名
- password 表示客户端进行连接的密码
### 控制设备(推流、数据上传、录像等)
1. 发布的主题
```
lihai_lot_walnutpi_dev_1
```
2. 发送的消息体payload
example:
```
{
"msg":"exec",
"data":"sudo ifconfig",
"pwd":"123456"
}
```
### msg类型
msg表示消息类型包括
- push_stream 设备启动推流
```
发布主题lihai_lot_walnutpi_dev_1
{
"msg":"exec",
"pwd":"123456"
}
```
- close_stream 设备关闭推流
```
发布主题lihai_lot_walnutpi_dev_1
{
"msg":"close_stream",
"pwd":"123456"
}
```
- record_list 录像文件列表
```
发布主题lihai_lot_walnutpi_dev_1
{
"msg":"record_list",
"pwd":"123456"
}
```
- record 上传选定文件
```
发布主题lihai_lot_walnutpi_dev_1
{
"msg":"record_list",
"data":"2023-12-13_11-11-11.mp4"
"pwd":"123456"
}
```
- status 查看supervisor运行状态
```
发布主题lihai_lot_walnutpi_dev_1
订阅success
{
"msg":"status",
"pwd":"123456"
}
```
- reload 重启supervisor
```
发布主题lihai_lot_walnutpi_dev_1
订阅success,error
{
"msg":"reload",
"pwd":"123456"
}
```
- update 更新git
```
发布主题lihai_lot_walnutpi_dev_1
订阅success,error
{
"msg":"update",
"pwd":"123456"
}
```
- exec 执行linux命令
```
发布主题lihai_lot_walnutpi_dev_1
订阅success,error
{
"msg":"exec",
"data":"supervisorctl tail record"
"pwd":"123456"
}
```
### data
- data在执行linux命令和获取录像时必须设置。
- 在执行命令时data则是需要执行的命令获取录像时需要指定需要的录像名称
- 订阅success和error主题可以查看错误消息和命令执行结果
# 本地数据库字段设置
```
class LOT_DATA(BaseModel):
create_time: int = Field(None, description='创建时间(时间戳) ')
wind_speed: float = Field(None, description='风速:(0到30)m/s ')
wind_direction: float = Field(None, description='风向:0360°')
ambient_temperature: float = Field(None, description='环境温度:℃')
ambient_humidity: float = Field(None, description='环境湿度:%RH')
carbon_dioxide: float = Field(None, description='二氧化碳0~5000ppm')
ambient_air_pressure: float = Field(None, description='环境气压0~120KPa')
rainfall: float = Field(None, description='雨量mm')
ambient_lighting: float = Field(None, description='环境光照0-65535Lux0-20万Lux')
soil_temperature: float = Field(None, description='土壤温度:-40~80℃')
soil_moisture: float = Field(None, description='土壤湿度0-100%RH')
soil_conductivity: float = Field(None, description='土壤电导率0-20000μS/cm')
soil_PH: float = Field(None, description='土壤PH:3~9PH')
soil_potassium_phosphate_nitrogen: float = Field(None, description='土壤磷酸钾氮的标准值在140-225mg/kg')
soil_potassium_phosphate_phosphorus: float = Field(None, description='土壤磷酸钾磷的标准值在57-100mg/kg,')
soil_potassium_phosphate_potassium: float = Field(None, description='土壤磷酸钾钾的标准值在106-150mg/kg')
```
### 本地数据库存放位置
```
# 存放的路径
KB_ROOT_PATH = "/home/pi/"
# 数据库名称
DB_ROOT_PATH = os.path.join(KB_ROOT_PATH, "lot_data.db")
# 连接URI
SQLALCHEMY_DATABASE_URI = f"sqlite:///{DB_ROOT_PATH}"
```
# 技术路线图
- [x] 数据上传
- [x] 摄像机推流
- [ ] MQTT程序控制的返回结果设置统一的返回状态码