Browse Source

Merge branch 'dev_trial' of ssh://gitea.free-sun.vip:2022/free-sun/FS-IOT into dev_trial

release_0.0.2
wenlele 3 years ago
parent
commit
28e2133a7c
  1. 110
      code/VideoAccess-VCMP/api/app/lib/controllers/camera/create.js
  2. 32
      code/VideoAccess-VCMP/api/app/lib/controllers/camera/index.js
  3. 9
      code/VideoAccess-VCMP/api/app/lib/index.js
  4. 17
      code/VideoAccess-VCMP/api/app/lib/models/camera.js
  5. 61
      code/VideoAccess-VCMP/api/app/lib/models/secret_yingshi.js
  6. 14
      code/VideoAccess-VCMP/api/app/lib/routes/camera/index.js
  7. 4
      code/VideoAccess-VCMP/api/app/lib/service/socket.js
  8. 2
      code/VideoAccess-VCMP/api/app/lib/utils/index.js
  9. 15
      code/VideoAccess-VCMP/api/app/lib/utils/rtmp2others.js
  10. 49
      code/VideoAccess-VCMP/api/app/lib/utils/token4yingshi.js
  11. 9
      code/VideoAccess-VCMP/api/config.js
  12. 4
      code/VideoAccess-VCMP/api/sequelize-automate.config.js

110
code/VideoAccess-VCMP/api/app/lib/controllers/camera/create.js

@ -1,30 +1,129 @@
'use strict';
const moment = require('moment')
async function createYingshi (ctx) {
let errMsg = '添加萤石摄像头失败'
try {
const { models } = ctx.fs.dc
const { userId, token } = ctx.fs.api
const { utils: { token4yingshi } } = ctx.app.fs
const {
id, name, cloudControl, highDefinition, memoryCard,
voice, kindId, abilityId, rtmp, serialNo, longitude, latitude,
} = ctx.request.body;
const serialNo_ = String(serialNo).toUpperCase()
const secretRes = await models.SecretYingshi.findAll()
let cameraBeloneSecretId = null
for (let s of secretRes) {
const tokenYingshi = await token4yingshi(s.dataValues)
// 检测设备所属
const cameraState = await ctx.app.fs.yingshiRequest.post('lapp/device/info', {
query: {
accessToken: tokenYingshi,
deviceSerial: serialNo_
}
})
if (cameraState.code == 200) {
cameraBeloneSecretId = s.dataValues.id
break
}
}
const { id, name, cloudControl, highDefinition, memoryCard,
voice, kindId, abilityId, rtmp, } = ctx.request.body
if (!cameraBeloneSecretId) {
errMsg = '请联系管理员核验或新增萤石云权限'
throw errMsg
}
let storageData = {
type: 'yingshi', name, cloudControl, highDefinition, memoryCard,
voice, longitude, latitude, kindId, abilityId, rtmp,
yingshiSecretId: cameraBeloneSecretId
}
if (id) {
await models.Camera.update(storageData, {
where: {
id,
}
})
} else {
storageData.createTime = moment().format()
storageData.createUserId = userId
storageData.forbidden = false
await models.Camera.create(storageData)
}
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: errMsg
}
}
}
async function getNvrSteam (ctx) {
try {
const { models } = ctx.fs.dc
const { userId, token } = ctx.fs.api
ctx.status = 200;
ctx.body = {}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function createNvrCamera (ctx) {
try {
const { models } = ctx.fs.dc
const { userId, token } = ctx.fs.api
ctx.status = 200;
ctx.body = {}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function createIpcCamera (ctx) {
try {
const { models } = ctx.fs.dc
const { userId, token } = ctx.fs.api
const { utils: { token4yingshi } } = ctx.app.fs
const {
id, name, cloudControl, memoryCard,
voice, longitude, latitude, rtmp,
serialNo, kindId, abilityId,
} = ctx.request.body;
let storageData = {
type: 'ipc', name, cloudControl, memoryCard,
voice, longitude, latitude, rtmp,
serialNo, kindId, abilityId,
}
if (id) {
await models.Camera.update(storageData, {
where: {
id,
}
})
} else {
storageData.createTime = moment().format()
storageData.createUserId = userId
storageData.forbidden = false
await models.Camera.create(storageData)
}
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
@ -34,5 +133,8 @@ async function createYingshi (ctx) {
}
module.exports = {
createYingshi,
getNvrSteam,
createNvrCamera,
createIpcCamera,
};

32
code/VideoAccess-VCMP/api/app/lib/controllers/camera/index.js

@ -236,6 +236,36 @@ async function del (ctx) {
}
}
async function getAbility (ctx) {
try {
const { models } = ctx.fs.dc;
const abilityRes = await models.CameraAbility.findAll()
ctx.status = 200;
ctx.body = abilityRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
async function getKind (ctx) {
try {
const { models } = ctx.fs.dc;
const kindRes = await models.CameraKind.findAll()
ctx.status = 200;
ctx.body = kindRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {}
}
}
module.exports = {
getCameraProject,
getCamera,
@ -243,4 +273,6 @@ module.exports = {
detail,
banned,
del,
getAbility,
getKind,
};

9
code/VideoAccess-VCMP/api/app/lib/index.js

@ -1,7 +1,7 @@
'use strict';
const routes = require('./routes');
const utils = require('./utils')
const routes = require('./routes');
const redisConnect = require('./service/redis')
const socketConect = require('./service/socket')
const paasRequest = require('./service/paasRequest');
@ -16,9 +16,6 @@ module.exports.entry = function (app, router, opts) {
app.fs.api.authAttr = app.fs.api.authAttr || {};
app.fs.api.logAttr = app.fs.api.logAttr || {};
// 工具类函数
utils(app, opts)
// 顺序固定 ↓
redisConnect(app, opts)
socketConect(app, opts)
@ -26,6 +23,9 @@ module.exports.entry = function (app, router, opts) {
// 实例其他平台请求方法
paasRequest(app, opts)
// 工具类函数
utils(app, opts)
// 鉴权中间件
router.use(authenticator(app, opts));
@ -41,5 +41,6 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq
require('./models/camera')(dc);
require('./models/nvr')(dc);
require('./models/vender')(dc);
require('./models/secret_yingshi')(dc);
require('./models/ax_project')(dc);
};

17
code/VideoAccess-VCMP/api/app/lib/models/camera.js

@ -157,7 +157,7 @@ module.exports = dc => {
forbidden: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
defaultValue: false,
comment: "是否禁用",
primaryKey: false,
field: "forbidden",
@ -184,7 +184,7 @@ module.exports = dc => {
delete: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
defaultValue: false,
comment: "是否彻底删除",
primaryKey: false,
field: "delete",
@ -246,6 +246,19 @@ module.exports = dc => {
key: "id",
model: "cameraAbility"
}
},
yingshiSecretId: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "yingshi_secret_id",
autoIncrement: false,
references: {
key: "id",
model: "secretYingshi"
}
}
}, {
tableName: "camera",

61
code/VideoAccess-VCMP/api/app/lib/models/secret_yingshi.js

@ -0,0 +1,61 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const SecretYingshi = sequelize.define("secretYingshi", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "secret_yingshi_id_uindex"
},
key: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "key",
autoIncrement: false
},
secret: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "secret",
autoIncrement: false
},
token: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "token",
autoIncrement: false
},
expire: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "expire",
autoIncrement: false
}
}, {
tableName: "secret_yingshi",
comment: "",
indexes: []
});
dc.models.SecretYingshi = SecretYingshi;
return SecretYingshi;
};

14
code/VideoAccess-VCMP/api/app/lib/routes/camera/index.js

@ -1,8 +1,16 @@
'use strict';
const camera = require('../../controllers/camera');
const cameraCreate = require('../../controllers/camera/create')
module.exports = function (app, router, opts) {
// 摄像头创建
app.fs.api.logAttr['POST/camera/create/yingshi'] = { content: '创建萤石摄像头', visible: false };
router.post('/camera/create/yingshi', cameraCreate.createYingshi);
// 摄像头创建 END
app.fs.api.logAttr['GET/camera/project'] = { content: '获取摄像头列表及项目绑定信息', visible: false };
router.get('/camera/project', camera.getCameraProject);
@ -20,4 +28,10 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['DEL/camera'] = { content: '删除摄像头', visible: false };
router.delete('/camera', camera.del);
app.fs.api.logAttr['GET/camera/ability'] = { content: '获取摄像头能力列表', visible: false };
router.get('/camera/ability', camera.getAbility);
app.fs.api.logAttr['GET/camera/kind'] = { content: '获取摄像头种类列表', visible: false };
router.get('/camera/kind', camera.getKind);
};

4
code/VideoAccess-VCMP/api/app/lib/service/socket.js

@ -3,9 +3,9 @@
module.exports = async function factory (app, opts) {
app.socket.on('connection', async (socket) => {
console.info('WEB_SOCKET ' + socket.handshake.query.token + ' 已连接:' + socket.id);
// console.info('WEB_SOCKET ' + socket.handshake.query.token + ' 已连接:' + socket.id);
socket.on('disconnecting', async (reason) => {
console.info('WEB_SOCKET ' + socket.handshake.query.token + ' 已断开连接:' + reason);
// console.info('WEB_SOCKET ' + socket.handshake.query.token + ' 已断开连接:' + reason);
})
})

2
code/VideoAccess-VCMP/api/app/lib/utils/index.js

@ -6,7 +6,7 @@ const fs = require('fs');
module.exports = async function (app, opts) {
fs.readdirSync(__dirname).forEach((filename) => {
if (filename != 'index.js') {
const utils = require(`./${filename}`)
const utils = require(`./${filename}`)(app, opts)
app.fs.utils = {
...app.fs.utils,
...utils,

15
code/VideoAccess-VCMP/api/app/lib/utils/rtmp2others.js

@ -1,9 +1,11 @@
'use strict';
async function rtmp2others (rtmp) {
module.exports = function (app, opts) {
async function rtmp2others (rtmp) {
return {
liveUrl: {
liveUrl: {// 直播
hd: {// 高清
rtmp: 'xx',
hls: 'xx',
@ -19,13 +21,14 @@ async function rtmp2others (rtmp) {
onvif: 'xx',
}
},
replayUrl: {
replayUrl: {// 回放
cloud: 'xx',
local: 'xx',
}
}
}
}
module.exports = {
rtmp2others,
return {
rtmp2others
}
}

49
code/VideoAccess-VCMP/api/app/lib/utils/token4yingshi.js

@ -0,0 +1,49 @@
'use strict';
const moment = require('moment')
module.exports = function (app, opts) {
async function token4yingshi ({ key, secret, token, expire } = {}) {
const { models } = app.fs.dc
if (!key || !secret) {
throw '参数 { key, secret } 缺一不可'
}
if (token && expire && moment().isBefore(moment(expire))) {
return token
} else {
const secretRes = await models.SecretYingshi.findOne({
where: { key, secret }
})
if (secretRes && secretRes.expire && secretRes.token && moment().isBefore(moment(secretRes.expire))) {
return secretRes.token
}
}
// 也可以做基于 redis 的缓存
const tokenRes = await app.fs.yingshiRequest.post(`lapp/token/get`, {
query: {
appKey: key,
appSecret: secret
}
})
if (tokenRes.code == 200) {
const { accessToken, expireTime } = tokenRes.data
await models.SecretYingshi.update({
token: accessToken,
expire: expireTime
}, {
where: {
key, secret
}
})
return accessToken
} else {
throw tokenRes
}
}
return {
token4yingshi
}
}

9
code/VideoAccess-VCMP/api/config.js

@ -32,6 +32,7 @@ const IOT_AUTH_API = process.env.IOT_AUTH_API || flags.iotAuthApi;
const AXY_API_URL = process.env.AXY_API_URL || flags.axyApiUrl;
const GOD_URL = process.env.GOD_URL || flags.godUrl || 'https://restapi.amap.com/v3';
const GOD_KEY = process.env.GOD_KEY || flags.godKey;
const YINGSHI_URL = process.env.YINGSHI_URL || flags.yingshiUrl || 'https://open.ys7.com/api';
if (!IOT_VIDEO_ACCESS_DB || !IOTA_REDIS_SERVER_HOST || !IOTA_REDIS_SERVER_PORT || !GOD_KEY) {
console.log('缺少启动参数,异常退出');
@ -76,6 +77,14 @@ const product = {
key: GOD_KEY
}
}
}, {
name: 'yingshiRequest',
root: YINGSHI_URL,
params: {
query: {
key: GOD_KEY
}
}
},]
}
}

4
code/VideoAccess-VCMP/api/sequelize-automate.config.js

@ -25,8 +25,8 @@ module.exports = {
fileNameCamelCase: false, // Model 文件名是否使用驼峰法命名,默认文件名会使用表名,如 `user_post.js`;如果为 true,则文件名为 `userPost.js`
dir: './app/lib/models', // 指定输出 models 文件的目录
typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义
emptyDir: true, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir`
tables: null, // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir`
tables: ['secret_yingshi'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
skipTables: [], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性
tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中
ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面

Loading…
Cancel
Save