项目功能
手机浏览器,远程查看实时监控视频、按钮控制电机、获取环境温度。
难点:
1. 远程控制,两者之间需要外网服务器来中转控制消息和传输视频,这里使用得是阿里家的服务器。
2. 视频监控,常见的视频流有rtmp、rtsp、http-flv三种传输协议,其中rtmp需要靠 Flash 播放器插件播放,遗憾Flash 于 2020 年正式结束了(但是可以用来服务端的视频推流);而rtsp不兼容HTTP,不能应用在web端。即,移动端选择http-flv视频流协议拉流。
3. web端,需要和外网服务器进行消息收发,毫无疑问使用websocket最友好。
暂时用我身边的linux机子局域网实现,后期移植到阿里家
(以上有什么更好的方法,欢迎评论区或者私聊我讨论)
前端浏览
web移动端——加载状态
个人前端设计不好,丑了凑合着看,主要是先功能实现,后期在慢慢优化。下面献上js后端代码,简短了一下代码,主要是展现思路:
//兼容性通知
if ("WebSocket" in window){
}else{
alert("您的浏览器不支持 WebSocket!");
}
//创建websocket
var ws = new WebSocket("ws://192.168.10.100:8082");
//开启便发送“hello”
ws.onopen = function(){
ws.send("hello");
};
//websocket断开通知
ws.onclose = function()
{
alert("连接超时...请刷新");
};
//每200毫秒执行getstate函数,获取状态值
window.setInterval(function(){getstate()},200);
//获取状态值
function getstate(){
ws.send("getstate");
ws.onmessage = function (evt)
{
var received_msg = evt.data;
//led
led_id = document.getElementById("led");
if(received_msg.split(" ")[0] == '1'){
led_id.style.backgroundColor='green';
}else{
led_id.style.backgroundColor='red';
}
led_state = received_msg.split(" ")[0];
//motor
motor_id = document.getElementById("motor");
if(received_msg.split(" ")[1] == '1'){
motor_id.style.backgroundColor='green';
motor_id.innerHTML="运行中";
}else{
motor_id.style.backgroundColor='red';
motor_id.innerHTML="停";
}
//temp温度
document.getElementById("temp").innerHTML=received_msg.split(" ")[2]+'度';
};
}
var led_state;
//onclick事件,按钮触发,向服务器发送用户控制信息
function order(serial)
{
if(serial == "led"){
if(led_state == '0'){
ws.send("l1");
}else{
ws.send("l0");
}
}else if(serial == "motor"){
ws.send("m1");
}
}
每200毫秒获取状态值,200毫秒延时还是有一点感觉的,可以适当减少间隔时间,但时间过于小对移动端不是很友好。
两个后端
python后端
主要用的库有:
websockets ——联络web移动端
soocket ——联络ESP32端
cv2——处理图像
pipe——使用ffmpeg将处理好的图像推流给nginx-flv
threading ——线程(开始用的是 Process 进程库,可是遇到没法共享消息的问题,移动端进程和ESP32端进程之间交流不了,索性就用了线程)
nginx-flv+ffmpeg后端
nginx-flv的安装和配置不太友好,但按照github作者的用法做就可以。
ffmpeg视频推流的安装,我试过在官网下载压缩包make编译安装,但是还有依赖包等东西的安装。。。最后用apt install ffmpeg安装,一劳永逸。
这是实际运行的时候的网页状态,后面优化了一下,视频拉流的帧率不是很理想,够用。
硬件图片:
——2023.3.29