From f72a28c30b915ffb6f643b2917715c8d7121a1a2 Mon Sep 17 00:00:00 2001 From: "gao.zhiyuan" Date: Fri, 1 Jul 2022 11:31:08 +0800 Subject: [PATCH] =?UTF-8?q?mqtt=20=E8=A7=86=E9=A2=91=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=8E=A8=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/VideoAccess-VCMP/api/.vscode/launch.json | 2 +- .../api/app/lib/schedule/freshYingshiMsg.js | 72 ++++++++++--------- .../api/app/lib/service/mqttVideoServer.js | 23 +++++- .../api/app/lib/utils/camera.js | 42 +++++++++++ .../src/components/videoPlayer/videoPlay.jsx | 27 ++++--- .../web/client/src/utils/webapi.js | 17 +++-- code/VideoAccess-VCMP/web/config.js | 10 ++- code/VideoAccess-VCMP/web/package.json | 2 +- 8 files changed, 140 insertions(+), 55 deletions(-) diff --git a/code/VideoAccess-VCMP/api/.vscode/launch.json b/code/VideoAccess-VCMP/api/.vscode/launch.json index 70913c0..bfa084a 100644 --- a/code/VideoAccess-VCMP/api/.vscode/launch.json +++ b/code/VideoAccess-VCMP/api/.vscode/launch.json @@ -23,7 +23,7 @@ "--iotVideoServerUrl http://221.230.55.27:8081", "--godUrl https://restapi.amap.com/v3", "--godKey 21c2d970e1646bb9a795900dd00093ce", - "--mqttVideoServer tcp://tee2b1be.cn.emqx.cloud:12847", + "--mqttVideoServer mqtt://10.8.30.71:30883", "--cameraPlayWsHost ws://221.230.55.27:8081", "--cameraPlayHttpFlvHost http://221.230.55.27:2020", "--cameraPlayHlsHost http://221.230.55.27:8081", diff --git a/code/VideoAccess-VCMP/api/app/lib/schedule/freshYingshiMsg.js b/code/VideoAccess-VCMP/api/app/lib/schedule/freshYingshiMsg.js index e96a5f3..bcc7143 100644 --- a/code/VideoAccess-VCMP/api/app/lib/schedule/freshYingshiMsg.js +++ b/code/VideoAccess-VCMP/api/app/lib/schedule/freshYingshiMsg.js @@ -4,13 +4,12 @@ const moment = require('moment') module.exports = function (app, opts) { const freshYingshiState = schedule.scheduleJob( // '* * 4 * * *', - // '*/10 * * * *', - '0 27 4 * * *', + '*/10 * * * *', async () => { try { const startTime = moment() const { models } = app.fs.dc - const { token4yingshi, getYingshiPlayUrl } = app.fs.utils + const { token4yingshi, getYingshiPlayUrl, cameraStatePush } = app.fs.utils const secretRes = await models.SecretYingshi.findAll() let deviceList = [] for (let s of secretRes) { @@ -57,38 +56,43 @@ module.exports = function (app, opts) { // 状态更新 END // 状态推送 - const { connected } = app.socket.sockets - const roomId = 'ROOM_' + Math.random() + '_' + d.deviceSerial - let cameraName = '' - if (connected) { - for (let c in connected) { - const { client: { conn: { request: { _query } } } } = connected[c] - if (_query && _query.token) { - let userInfo = await app.redis.hget(_query.token, 'userInfo'); - if (userInfo) { - userInfo = JSON.parse(userInfo) - const corCameraRes = await models.Camera.findOne({ - where: { - gbId: existD.id, - createUserId: userInfo.id - } - }) - // TODO 管理员判断 - if (corCameraRes) { - cameraName = corCameraRes.name - connected[c].join(roomId) - } - } - } - } + cameraStatePush({ + gbId: existD.id, + online: storageD.online, + ipctype: storageD.ipctype, + }) + // const { connected } = app.socket.sockets + // const roomId = 'ROOM_' + Math.random() + '_' + d.deviceSerial + // let cameraName = '' + // if (connected) { + // for (let c in connected) { + // const { client: { conn: { request: { _query } } } } = connected[c] + // if (_query && _query.token) { + // let userInfo = await app.redis.hget(_query.token, 'userInfo'); + // if (userInfo) { + // userInfo = JSON.parse(userInfo) + // const corCameraRes = await models.Camera.findOne({ + // where: { + // gbId: existD.id, + // createUserId: userInfo.id + // } + // }) + // // TODO 管理员判断 + // if (corCameraRes) { + // cameraName = corCameraRes.name + // connected[c].join(roomId) + // } + // } + // } + // } - app.socket.to(roomId).emit('CAMERA_ONLINE', { - ipctype: 'yingshi', - online: storageD.online, - gbId: existD.id, - name: cameraName - }) - } + // app.socket.to(roomId).emit('CAMERA_ONLINE', { + // ipctype: 'yingshi', + // online: storageD.online, + // gbId: existD.id, + // name: cameraName + // }) + // } } } else { const yingshiRes = await models.GbCamera.create(storageD) diff --git a/code/VideoAccess-VCMP/api/app/lib/service/mqttVideoServer.js b/code/VideoAccess-VCMP/api/app/lib/service/mqttVideoServer.js index 6e468e8..69b4046 100644 --- a/code/VideoAccess-VCMP/api/app/lib/service/mqttVideoServer.js +++ b/code/VideoAccess-VCMP/api/app/lib/service/mqttVideoServer.js @@ -8,15 +8,32 @@ module.exports = async function factory (app, opts) { client.on('connect', function () { console.info(`mqtt connect success ${opts.mqtt.mqttVideoServer}`); - client.subscribe('test', { qos: 2 });//订阅主题为test的消息 + client.subscribe('topic/test', { qos: 0 });//订阅主题为test的消息 }) client.on('error', function (e) { console.error(`mqtt connect failed ${opts.mqtt.mqttVideoServer}`); app.fs.logger.error('info', '[FS-AUTH-MQTT]', `mqtt connect failed ${opts.mqtt.mqttVideoServer}`); }) - client.on('message', function (top, message) { - console.log(message.toString()); + client.on('message', async (top, message) => { + let msgStr = message.toString(); + let msg = JSON.parse(msgStr.replace(/\\/g, '')); + if (msg.id && msg.online) { + const { cameraStatePush } = app.fs.utils + const { models } = app.fs.dc + const gbCameraRes = await models.GbCamera.findOne({ + where: { + id: msg.id + } + }) + if (gbCameraRes) { + cameraStatePush({ + gbId: msg.id, + online: msg.online, + ipctype: gbCameraRes.ipctype, + }) + } + } }); app.mqttVideoServer = client diff --git a/code/VideoAccess-VCMP/api/app/lib/utils/camera.js b/code/VideoAccess-VCMP/api/app/lib/utils/camera.js index 530d47d..d010902 100644 --- a/code/VideoAccess-VCMP/api/app/lib/utils/camera.js +++ b/code/VideoAccess-VCMP/api/app/lib/utils/camera.js @@ -118,6 +118,47 @@ module.exports = function (app, opts) { } } + async function cameraStatePush ({ gbId, online, ipctype }) { + try { + const { models } = app.fs.dc + const { connected } = app.socket.sockets + const roomId = 'ROOM_' + Math.random() + '_' + gbId + let cameraName = '' + if (connected) { + // TODO 摄像头绑定关系查询 + for (let c in connected) { + const { client: { conn: { request: { _query } } } } = connected[c] + if (_query && _query.token) { + let userInfo = await app.redis.hget(_query.token, 'userInfo'); + if (userInfo) { + userInfo = JSON.parse(userInfo) + const corCameraRes = await models.Camera.findOne({ + where: { + gbId: gbId, + createUserId: userInfo.id + } + }) + // TODO 管理员判断 + if (corCameraRes) { + cameraName = corCameraRes.name + connected[c].join(roomId) + } + } + } + } + + app.socket.to(roomId).emit('CAMERA_ONLINE', { + ipctype: ipctype, + online: online, + gbId: gbId, + name: cameraName + }) + } + } catch (error) { + app.fs.logger.error(`utils: cameraStatePush, error: ${error}`); + } + } + return { getGbCameraLevel1ByStreamId, getGbCameraLevel3ByStreamId, @@ -125,5 +166,6 @@ module.exports = function (app, opts) { verifyIpcInfo, verifyCascadeInfo, getPlayUrl, + cameraStatePush, } } \ No newline at end of file diff --git a/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlay.jsx b/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlay.jsx index 1cf1348..c5530c4 100644 --- a/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlay.jsx +++ b/code/VideoAccess-VCMP/web/client/src/components/videoPlayer/videoPlay.jsx @@ -15,19 +15,29 @@ const VideoPlay = ({ height, width, containerId = 'myPlayer', // playUrl, name, + // videoObj, + // videoObj = { + // type: 'yingshi', + // audio: false, + // serialNo: 'G75922040', // 设备序列号 必须 + // channelNo: 1, // + // yingshiToken: 'at.3j6eyqbn0g5xvcut73v0rzdu1nh0gnxx-4ua03m82o9-12u1t9g-rtzndpyds', // 萤石必须 + // playUrlSd: 'ezopen://open.ys7.com/G75922040/1.live', // 必须 + // // playUrl: 'ws://221.230.55.27:8081/jessica/34020000001110000077/34020000001310000003', + // playUrlHd: 'ezopen://open.ys7.com/G75922040/1.hd.live', + // // replayUrl: 'ezopen://open.ys7.com/G75922040/1.rec', + // }, videoObj = { - type: 'yingshi', + type: 'cascade', audio: false, serialNo: 'G75922040', // 设备序列号 必须 - channelNo: 1, // - yingshiToken: 'at.3j6eyqbn0g5xvcut73v0rzdu1nh0gnxx-4ua03m82o9-12u1t9g-rtzndpyds', // 萤石必须 - playUrlSd: 'ezopen://open.ys7.com/G75922040/1.live', // 必须 - // playUrl: 'ws://221.230.55.27:8081/jessica/34020000001110000077/34020000001310000003', - playUrlHd: 'ezopen://open.ys7.com/G75922040/1.hd.live', + topSerialNo: 'G75922040', // 设备顶级序列号 必须 + playUrlSd: 'ws://221.230.55.27:8081/jessica/34020000001110000077/34020000001310000003', // 必须 + // playUrlHd: 'ezopen://open.ys7.com/G75922040/1.hd.live', // replayUrl: 'ezopen://open.ys7.com/G75922040/1.rec', }, }) => { - console.log(videoObj); + console.log(videoObj); const [jessibuca, setjessibuca] = useState(null) const [isPlaying, setIsPlaying] = useState(false) const [operationState, setoperationState] = useState() @@ -199,8 +209,9 @@ const VideoPlay = ({ } }, [processDisX]) - const createJessibuca = () => { + const createJessibuca = async () => { if (videoObj.type != 'yingshi') { + let $container = document.getElementById('container'); const jessibuca = new window.Jessibuca({ container: $container, diff --git a/code/VideoAccess-VCMP/web/client/src/utils/webapi.js b/code/VideoAccess-VCMP/web/client/src/utils/webapi.js index 93c0992..68d3e73 100644 --- a/code/VideoAccess-VCMP/web/client/src/utils/webapi.js +++ b/code/VideoAccess-VCMP/web/client/src/utils/webapi.js @@ -3,6 +3,7 @@ import { ProxyRequest } from "@peace/utils"; export const AuthRequest = new ProxyRequest("_auth"); export const AxyRequest = new ProxyRequest("_axy"); +export const IotVideoServerRequest = new ProxyRequest("_vs"); export const ApiTable = { login: "login", @@ -30,15 +31,17 @@ export const ApiTable = { postCameraNvr: "camera/create/nvr", //记录NVR摄像头 getCascadeSIP: "camera/sip_list/cascade", //获取级联摄像头sip列表 postAddCascade: "camera/create/cascade", //添加级联摄像头 - getParentCamera:"camera/cascade_device", //获取级联摄像头父级设备 - postVerifyYingshi:"camera/verify/yingshi", //验证萤石摄像头信息 - postVerifyIpc:"camera/verify/ipc", //验证IPC摄像头信息 - postVerifyCascade:"camera/verify/cascade", //验证级联摄像头信息 - getCascadeStream:"/camera/cascade_stream", //获取级联视频流 - - + getParentCamera: "camera/cascade_device", //获取级联摄像头父级设备 + postVerifyYingshi: "camera/verify/yingshi", //验证萤石摄像头信息 + postVerifyIpc: "camera/verify/ipc", //验证IPC摄像头信息 + postVerifyCascade: "camera/verify/cascade", //验证级联摄像头信息 + getCascadeStream: "/camera/cascade_stream", //获取级联视频流 }; +export const VideoServeApi = { + invite: 'api/gb28181/invite' +} + export const RouteTable = { apiRoot: "/api/root", fileUpload: "/_upload/new", diff --git a/code/VideoAccess-VCMP/web/config.js b/code/VideoAccess-VCMP/web/config.js index ccef0de..251909a 100644 --- a/code/VideoAccess-VCMP/web/config.js +++ b/code/VideoAccess-VCMP/web/config.js @@ -15,6 +15,7 @@ args.option(['u', 'api-url'], 'webapi的URL'); args.option('apiAuthUrl', 'IOT 鉴权 api'); args.option('apiAnxinyunUrl', '安心云 api'); args.option('iotAuthWeb', 'IOT 鉴权 web'); +args.option('iotVideoServer', 'IOT 后端视频服务鉴权'); const flags = args.parse(process.argv); @@ -22,8 +23,9 @@ const API_URL = process.env.API_URL || flags.apiUrl; const API_AUTH_URL = process.env.API_AUTH_URL || flags.apiAuthUrl; const IOT_AUTH_WEB = process.env.IOT_AUTH_WEB || flags.iotAuthWeb; const API_ANXINYUN_URL = process.env.API_ANXINYUN_URL || flags.apiAnxinyunUrl; +const IOT_VIDEO_SERVER = process.env.IOT_VIDEO_SERVER || flags.iotVideoServer; -if (!API_URL || !API_ANXINYUN_URL || !API_AUTH_URL || !IOT_AUTH_WEB) { +if (!API_URL || !API_ANXINYUN_URL || !API_AUTH_URL || !IOT_AUTH_WEB || !IOT_VIDEO_SERVER) { console.log('缺少启动参数,异常退出'); args.showHelp(); process.exit(-1); @@ -50,6 +52,12 @@ const product = { host: API_ANXINYUN_URL, match: /^\/_axy\//, } + }, { + entry: require('./middlewares/proxy').entry, + opts: { + host: IOT_VIDEO_SERVER, + match: /^\/_vs\//, + } }, { entry: require('./routes').entry, opts: { diff --git a/code/VideoAccess-VCMP/web/package.json b/code/VideoAccess-VCMP/web/package.json index 51afb0e..56a30b1 100644 --- a/code/VideoAccess-VCMP/web/package.json +++ b/code/VideoAccess-VCMP/web/package.json @@ -7,7 +7,7 @@ "test": "mocha", "start-vite": "cross-env NODE_ENV=developmentVite npm run start-params", "start": "cross-env NODE_ENV=development npm run start-params", - "start-params": "node server -p 5000 -u http://10.8.30.7:4000 --apiAuthUrl http://10.8.30.7:4200 --apiAnxinyunUrl http://10.8.30.7:4100 --iotAuthWeb http://localhost:5200", + "start-params": "node server -p 5000 -u http://10.8.30.7:4000 --apiAuthUrl http://10.8.30.7:4200 --apiAnxinyunUrl http://10.8.30.7:4100 --iotAuthWeb http://localhost:5200 --iotVideoServer http://221.230.55.27:8081", "deploy": "export NODE_ENV=production&& npm run build && node server", "build-dev": "cross-env NODE_ENV=development&&webpack --config webpack.config.js", "build": "export NODE_ENV=production&&webpack --config webpack.config.prod.js"