一、固定USB设备名
在做使用树莓派读取usb摄像头数据时,发现每次插拔usb,会导致设备号发生变化,读取失败。在网上找的方法,记录一下。
1、分别连接两个摄像头(每次只连一个),执行下面命令,记录返回结果中的idVendor 和idProduct
lsusb
2、配置固定名称
cd /etc/udev/rules.d
sudo touch camera.rules
sudo vi camera.rules
3、编辑文件,输入一下内容,注意idVendor 和idProduct使用第一步的数据
KERNEL=="video[0,2,4,6,8]*",ATTRS{idVendor}== "2993",ATTRS{idProduct}=="0858",GROUP="video",MODE="0777",SYMLINK+= "cameral_R"
KERNEL=="video[0,2,4,6,8]*",ATTRS{idVendor}== "1bcf",ATTRS{idProduct}=="28c4",GROUP="video",MODE="0777",SYMLINK+= "cameral_L"
4、重启设备服务
sudo udevadm control --reload
sudo service udev restart
5、不管后面怎样重新插拔usb,我们通cameral_R,cameral_L来获取usb摄像头数据
capR = cv2.VideoCapture("cameral_R", apiPreference=cv2.CAP_V4L2)
capL = cv2.VideoCapture("cameral_L", apiPreference=cv2.CAP_V4L2)
二、树莓派开机运行python
开机运行我用了两种方式,rc.local和service,最后发现还是service香。
rc.local 优点: 配置简单,修改灵活
rc.local 缺点: 开机运行后,如果有报错导致线程结束,当所有线程(包含主线程)结束后,服务就结束了,不会重新启动。
我的需求是,主线程启动后,启动两个子线程,主线程接收mqtt消息,就根据消息内容,启动、停止或更新配置文件后重启子线程。
但是因为我在主线程中没有删除input()
, rc.local启动主线程,主线程启动子线程,主线程停止子线程后,主线程也报错退出,导致整个服务结束,无法再接收mqtt消息。
service 优点: 配置稍微复杂一些,但是能解决服务退出的问题,可以设置Restart=always,当服务退出后,会自动启动服务。
1、配置service
cd /etc/systemd/system
sudo vi your_service.service
2、输入以下内容到文件your_service.service,并保存,ExecStart、WorkingDirectory和User根据自己的用户和python文件位置进行配置
[Unit]
Description=your service
After=network.target
[Service]
ExecStart=/usr/bin/python3 /home/user/your.py
WorkingDirectory=/home/user/
StandardOutput=inherit
StandardError=inherit
Restart=always
User=user
[Install]
WantedBy=multi-user.target
3、enable service配置,重启树莓派
sudo systemctl enable your_service.service
sudo reboot
4、可以查看进程确认python开机自启动情况
ps -ef | grep python