From 0bdbeb9cf74b36411aff007bc6e9fc12d032fb3d Mon Sep 17 00:00:00 2001 From: xyj <10908227994@qq.com> Date: Mon, 22 Jan 2024 18:01:03 +0800 Subject: [PATCH] first --- .idea/inspectionProfiles/Project_Default.xml | 33 +++ .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 7 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .idea/workspace.xml | 237 ++++++++++++++++++ .idea/xumu_iot.iml | 12 + MQTT.py | 86 +++++++ bash/start_push_stream.sh | 2 + bash/stop_push_stream.sh | 2 + bash/stream.sh | 3 + conf/common/mqtt.conf | 10 + conf/common/push_stream.conf | 9 + conf/device/device.conf | 10 + conf/example/supervisord.conf | 40 +++ conf/tmp/device_name | 1 + config.py | 44 ++++ git_push.sh | 5 + git_update.sh | 9 + requirements.txt | 2 + tool.py | 92 +++++++ 21 files changed, 624 insertions(+) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 .idea/xumu_iot.iml create mode 100644 MQTT.py create mode 100755 bash/start_push_stream.sh create mode 100755 bash/stop_push_stream.sh create mode 100644 bash/stream.sh create mode 100644 conf/common/mqtt.conf create mode 100644 conf/common/push_stream.conf create mode 100644 conf/device/device.conf create mode 100644 conf/example/supervisord.conf create mode 100644 conf/tmp/device_name create mode 100644 config.py create mode 100755 git_push.sh create mode 100755 git_update.sh create mode 100644 requirements.txt create mode 100755 tool.py diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..53670f4 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,33 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..b9b36bf --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..90821fa --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..257c4a7 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + "associatedIndex": 3 +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1702028845497 + + + + + + \ No newline at end of file diff --git a/.idea/xumu_iot.iml b/.idea/xumu_iot.iml new file mode 100644 index 0000000..9e256bc --- /dev/null +++ b/.idea/xumu_iot.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/MQTT.py b/MQTT.py new file mode 100644 index 0000000..b28ea7a --- /dev/null +++ b/MQTT.py @@ -0,0 +1,86 @@ +import time + +import paho.mqtt.client as mqtt + +from tool import * + +from config import broker, port, subscribe_topic, username, password, info_topic + + +def valid(msg, client): + origin_data = json.loads(msg.payload.decode('utf-8')) + if 'msg' not in origin_data: + client.publish(info_topic, payload=publish_payload(code=404, msg="msg must be supplied"), qos=0) + return False + return True + + +class MQTTClient: + def __init__(self, broker, port, topic, username, password): + self.broker = broker + self.port = port + self.topic = topic + self.username = username + self.password = password + # 千万不要指定client_id 不然死翘翘 + self.client = mqtt.Client(client_id=subscribe_topic) + self.client.username_pw_set(self.username, self.password) + self.client.on_connect = self.on_connect + self.client.on_message = self.on_message + + def on_connect(self, client, userdata, flags, rc): + if rc == 0: + self.client.subscribe(self.topic) + client.publish(info_topic, payload=publish_payload(code=200, msg='成功订阅' + self.topic), + qos=0) + # 关闭摄像机电 + subprocess.Popen(['sudo /usr/bin/python close_led.py'], shell=True) + # 关闭LED灯 + subprocess.Popen(['sudo /usr/bin/python close_blue_led.py'], shell=True) + + def on_message(self, client, userdata, msg): + if not valid(msg, client): + return + try: + origin_data = json.loads(msg.payload.decode('utf-8')) + data = origin_data["msg"] + if data == "push_stream": + # 启动推流视频 + push_stream(client) + elif data == "close_stream": + # 关闭推流视频 + close_stream(client) + elif data == "exec": + # 执行命令 + exec_sh(msg, client) + elif data == "update": + # git更新项目和配置文件 + update(client) + elif data == "reload": + # 重启配置 + reload(client) + elif data == "status": + # 查看运行状态 + get_status(client) + else: + # 错误类型 + client.publish(info_topic, payload=publish_payload(code=404, msg='No Such Msg Type'), qos=0) + except Exception as e: + pass + + def start(self): + self.client.connect(self.broker, self.port) + + +if __name__ == '__main__': + # MQTT客户端 + MQTT = MQTTClient(broker, port, subscribe_topic, username, password) + # 循环连接 + while True: + try: + MQTT.start() + # 阻塞监听 + MQTT.client.loop_forever() + except Exception as e: + # 异常等待时间在进行连接 + time.sleep(30) diff --git a/bash/start_push_stream.sh b/bash/start_push_stream.sh new file mode 100755 index 0000000..6b949e7 --- /dev/null +++ b/bash/start_push_stream.sh @@ -0,0 +1,2 @@ +#!/bin/bash +supervisorctl start push_stream diff --git a/bash/stop_push_stream.sh b/bash/stop_push_stream.sh new file mode 100755 index 0000000..855eaeb --- /dev/null +++ b/bash/stop_push_stream.sh @@ -0,0 +1,2 @@ +#!/bin/bash +supervisorctl stop push_stream diff --git a/bash/stream.sh b/bash/stream.sh new file mode 100644 index 0000000..d39990b --- /dev/null +++ b/bash/stream.sh @@ -0,0 +1,3 @@ +#!/bin/bash +device_name=`cat /home/pi/device_name` +/usr/bin/ffmpeg -rtsp_transport tcp -re -i "rtsp://admin:lihai123@192.168.0.123:554/cam/realmonitor?channel=1&subtype=0" -c copy -f rtsp -rtsp_transport tcp rtsp://47.108.186.87:554/live/$device_name \ No newline at end of file diff --git a/conf/common/mqtt.conf b/conf/common/mqtt.conf new file mode 100644 index 0000000..29c3fb0 --- /dev/null +++ b/conf/common/mqtt.conf @@ -0,0 +1,10 @@ +[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 diff --git a/conf/common/push_stream.conf b/conf/common/push_stream.conf new file mode 100644 index 0000000..78c3fb2 --- /dev/null +++ b/conf/common/push_stream.conf @@ -0,0 +1,9 @@ +[program:push_stream] +directory=/home/pi/lot_manager/bash +command=/usr/bin/bash stream.sh +user=pi +autostart=true +autorestart=true +redirect_stderr=true +stopsignal=TERM +stopasgroup=True \ No newline at end of file diff --git a/conf/device/device.conf b/conf/device/device.conf new file mode 100644 index 0000000..ba4a17a --- /dev/null +++ b/conf/device/device.conf @@ -0,0 +1,10 @@ +# 设备1-32G +# 编号 +[xumu_camera_1] +# 订阅的控制主题,必须和系统设置的相同 +subscribe_topic=xumu_camera_1 +# 发布消息的主题 +publish_topic=camera_1 +info_topic=info_xumu_camera_1 +username=lihai_lot_land1 +password=lihai_lot_land1 \ No newline at end of file diff --git a/conf/example/supervisord.conf b/conf/example/supervisord.conf new file mode 100644 index 0000000..71e1528 --- /dev/null +++ b/conf/example/supervisord.conf @@ -0,0 +1,40 @@ +; 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 diff --git a/conf/tmp/device_name b/conf/tmp/device_name new file mode 100644 index 0000000..97bae99 --- /dev/null +++ b/conf/tmp/device_name @@ -0,0 +1 @@ +xumu_camera_1 \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 0000000..bc77ef9 --- /dev/null +++ b/config.py @@ -0,0 +1,44 @@ +import configparser + +import subprocess + +try: + p = subprocess.Popen(['cat /home/pi/device_name'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + # 设备名称,必须要有 + device_name = out.decode('utf-8').strip() + + # 读取配置 + config = configparser.ConfigParser() + # 读取公共配置 + config.read('conf/main/common.conf') + # 域名 + broker = config.get("broker", "host") + # 端口,这里必须是int类型 + port = config.getint("broker", "port") + # 录像地址 + post_record_list_url = config.get("record", "post_record_list_url") + post_record_url = config.get("record", "post_record_url") + + # 读取设备配置 + config.read('conf/device/device.conf') + # 订阅的主题 + subscribe_topic = config.get(device_name, "subscribe_topic") + # 发布数据的主题 + publish_topic = config.get(device_name, "publish_topic") + # 发布信息的主题 + info_topic = config.get(device_name, "info_topic") + # 用户 + username = config.get(device_name, "username") + # 密码 + password = config.get(device_name, "password") + + # 特殊配置 + config.read('conf/zhanguan/topic.conf') + zhanguan_device_name = config.get("device", "name") + + # tool配置 + mp4_path = '/home/pi/mp4' +except Exception as e: + # print(e) + pass diff --git a/git_push.sh b/git_push.sh new file mode 100755 index 0000000..0799741 --- /dev/null +++ b/git_push.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e +git add . +git commit -m 'update' +git push -f origin master diff --git a/git_update.sh b/git_update.sh new file mode 100755 index 0000000..762d4da --- /dev/null +++ b/git_update.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e +# git更新 +git pull origin master --force +# 配置文件复制到supervisor管理 +# cp -r conf/common/*.conf /etc/supervisor/conf.d/ +# 更新配置文件 +supervisorctl reread +supervisorctl update diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e185e44 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +paho-mqtt~=1.6.1 +requests~=2.31.0 \ No newline at end of file diff --git a/tool.py b/tool.py new file mode 100755 index 0000000..85a9476 --- /dev/null +++ b/tool.py @@ -0,0 +1,92 @@ +import json +import os +import subprocess +import threading + +import requests + +from config import mp4_path, post_record_list_url, post_record_url, info_topic + + +# 统一返回 +def publish_payload(code, msg): + return json.dumps({ + "code": code, + "msg": msg + }, ensure_ascii=False) + + +def exception_handler(func): + def wrapper(*args, **kwargs): + try: + return func(*args, **kwargs) + except Exception as e: + print(f"函数{func.__name__}中发生了异常:{e}") + + return wrapper + + +def push_stream(client): + p = subprocess.Popen(['/bin/bash /home/pi/lot_manager/bash/start_push_stream.sh'], + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = p.communicate() + output = out.decode('utf-8').strip() + client.publish(info_topic, payload=publish_payload(200, output), qos=0) + + +def close_stream(client): + p = subprocess.Popen(['/bin/bash /home/pi/lot_manager/bash/stop_push_stream.sh'], + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = p.communicate() + output = out.decode('utf-8').strip() + client.publish(info_topic, payload=publish_payload(code=200, msg=output), qos=0) + + +def exec_sh(msg, client): + origin_data = json.loads(msg.payload.decode('utf-8')) + if 'data' not in origin_data: + client.publish(info_topic, payload=publish_payload(code=404, msg='data must be supplied'), qos=0) + return + cmd = origin_data["data"] + if cmd in ["supervisorctl stop __mqtt__", + "supervisorctl restart __mqtt__", + "supervisorctl stop all"]: + return + if cmd == "supervisorctl reload": + client.publish(info_topic, payload=publish_payload(code=200, msg='reloading'), qos=0) + subprocess.Popen([cmd], shell=True) + return + p = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + output = out.decode('utf-8').strip() + client.publish(info_topic, payload=publish_payload(code=200, msg=output), qos=0) + + +def get_status(client): + p = subprocess.Popen(['supervisorctl status'], + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = p.communicate() + output = out.decode('utf-8').strip() + client.publish(info_topic, payload=publish_payload(code=200, msg=output), qos=0) + + +def update(client): + p = subprocess.Popen(['/bin/bash /home/pi/lot_manager/git_update.sh'], + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = p.communicate() + output = out.decode('utf-8').strip() + client.publish(info_topic, payload=publish_payload(code=200, msg=output), + qos=0) + + +def reload(client): + client.publish(info_topic, payload=publish_payload(200, "reloading"), qos=0) + subprocess.Popen(['supervisorctl reload'], shell=True)