| src/modules/push/controller/admin/deviceonoff.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/push/controller/app/open.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/push/entity/deviceonoff.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/push/service/deviceonoff.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/modules/push/service/open.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/modules/push/controller/admin/deviceonoff.ts
New file @@ -0,0 +1,36 @@ import { Inject } from '@midwayjs/core'; import { CoolController, BaseController } from '@cool-midway/core'; import { PushDeviceOnoffEntity } from '../../entity/deviceonoff'; import { PushDeviceOnoffService } from '../../service/deviceonoff'; /** * 设备对象管理 */ @CoolController({ api: ['add', 'delete', 'update', 'info', 'list', 'page'], entity: PushDeviceOnoffEntity, service: PushDeviceOnoffService, pageQueryOp: { keyWordLikeFields: ['a.deviceId', 'a.subSerial', 'a.deviceName'], fieldEq: [ { column: 'a.status', requestParam: 'status' }, { column: 'a.msgType', requestParam: 'msgType' }, { column: 'a.devType', requestParam: 'devType' } ], where: async (ctx) => { const { startTime, endTime } = ctx.request.body; const condition = []; if (startTime && endTime) { condition.push([ 'a.occurTime BETWEEN :startTime AND :endTime', { startTime, endTime } ]); } return condition; } } }) export class AdminPushDeviceOnoffController extends BaseController { @Inject() pushDeviceOnoffService: PushDeviceOnoffService; } src/modules/push/controller/app/open.ts
@@ -89,12 +89,12 @@ } @Post('/cameragps', { summary: '原始车载监控上报接口' }) async uploadCameraGps( @Post('/yingshiyun', { summary: '萤石云Webhook上报接口' }) async saveYingshiyunMessage( @Body() body: any ) { const result = await this.pushOpenService.receiveCameraGpsMessage(body); const result = await this.pushOpenService.saveYingshiyunMessage(body); //return this.ok(result); return { "messageId": result } src/modules/push/entity/deviceonoff.ts
New file @@ -0,0 +1,45 @@ import { BaseEntity } from '../../base/entity/base'; import { Column, Entity, Index } from 'typeorm'; /** * 终端设备的上线/下线数据 */ @Entity('t_push_device_onoff') export class PushDeviceOnoffEntity extends BaseEntity { @Index() @Column({ comment: '设备ID' }) deviceId: string; @Column({ comment: '通道号', type: 'int' , nullable: true,default:0 }) channelNo: number; @Column({ comment: '消息唯一ID' }) messageId: string; @Column({ comment: '消息时间' }) messageTime: Date; @Column({ comment: '消息类型', dict: ['ONLINE', 'OFFLINE'], default: 'ONLINE' }) msgType: string; @Column({ comment: '设备类型' , nullable: true }) devType: string; @Column({ comment: '设备名称', nullable: true }) deviceName: string; @Column({ comment: '子序列号' , nullable: true }) subSerial: string; @Column({ comment: '源端ID', nullable: true }) dasId: string; @Column({ comment: 'NAT的IP', nullable: true }) natIp: string; @Column({ comment: '事件发生时间', nullable: true }) occurTime: Date; @Column({ comment: '注册时间', nullable: true }) regTime: Date; } src/modules/push/service/deviceonoff.ts
New file @@ -0,0 +1,14 @@ import { Provide } from '@midwayjs/core'; import { BaseService } from '@cool-midway/core'; import { InjectEntityModel } from '@midwayjs/typeorm'; import { Repository } from 'typeorm'; import { PushDeviceOnoffEntity } from '../entity/deviceonoff'; /** * 监控设备的上线/下线消息服务 */ @Provide() export class PushDeviceOnoffService extends BaseService { @InjectEntityModel(PushDeviceOnoffEntity) pushDeviceOnoffEntity: Repository<PushDeviceOnoffEntity>; } src/modules/push/service/open.ts
@@ -7,6 +7,7 @@ import { PushAuditlogEntity } from '../entity/auditlog'; import { PushCameraGpsEntity } from '../entity/cameragps'; import { PushVehicleGpsEntity } from '../entity/vehiclegps'; import { PushDeviceOnoffEntity } from '../entity/deviceonoff'; import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager'; /** @@ -25,6 +26,10 @@ @InjectEntityModel(PushVehicleGpsEntity) pushVehicleGpsEntity: Repository<PushVehicleGpsEntity>; @InjectEntityModel(PushDeviceOnoffEntity) pushDeviceOnoffEntity: Repository<PushDeviceOnoffEntity>; @InjectEntityModel(PushAuditlogEntity) pushAuditlogEntity: Repository<PushAuditlogEntity>; @@ -86,24 +91,95 @@ } /** * 接收GPS消息并缓存 * 接收萤石云 消息并缓存 */ async receiveCameraGpsMessage(body: any) { const messageId = body.msgSeq || Math.random().toString(36).substring(2); await this.midwayCache.set(`push:cameragps:queue:${messageId}`, JSON.stringify(body), 24 * 3600); this.processCameraGpsAsync(messageId).catch(err => { async saveYingshiyunMessage(body: any) { const messageId = body?.header?.messageId || Math.random().toString(36).substring(2); await this.midwayCache.set(`push:yingshiyun:queue:${messageId}`, JSON.stringify(body), 24 * 3600); this.processYingshiyunAsync(messageId).catch(err => { console.error('异步处理GPS消息失败:', err); }); return messageId ; } /** * 异步解析车载监控视频的位置数据并入库 * 异步解析萤石云消息,按照消息类型 入库 */ async processCameraGpsAsync(messageId: string) { const dataStr = await this.midwayCache.get(`push:cameragps:queue:${messageId}`) as string | null; async processYingshiyunAsync(messageId: string) { const dataStr = await this.midwayCache.get(`push:yingshiyun:queue:${messageId}`) as string | null; if (!dataStr) return; const body = JSON.parse(dataStr); const type = body?.header?.type; try { switch (type) { // 设备上下线 case 'ys.onoffline': { await this.pushDeviceOnoffEntity.save({ deviceId:body.header.deviceId, channelNo: body.header.channelNo, messageId: body.header.messageId, messageTime: new Date(body.header.messageTime), msgType: body.body.msgType, devType: body.body.devType, deviceName: body.body.deviceName, subSerial: body.body.subSerial, dasId: body.body.dasId, natIp: body.body.natIp, occurTime: body.body.occurTime, regTime: body.body.regTime }); break; } // 萤石告警 /* case 'ys.alarm': { await this.pushAlarmRepo.save({ messageId, raw: JSON.stringify(body), createTime: new Date(), }); break; } */ // 海康 ISAPI //case 'ys.open.isapi': { //processCameraGpsAsync(body) //await this.pushIsapiRepo.save({ // messageId, // raw: JSON.stringify(body), // createTime: new Date(), //}); //break; //} default: console.warn('Unknown yingshi webhook type:', type); } } catch (err) { await this.writePushAuditLog(type || 'unknown', { deviceNo: body?.sn || 'UNKNOWN', requestContent: body, errorMessage: err, }); } // 不管成功与否,删除缓存中的任务队列 await this.midwayCache.del(`push:yingshiyun:queue:${messageId}`); } /** * 异步解析车载监控的GPS数据,存储并添加业务表 */ async processCameraGpsAsync(body: any) { try { let vehicleNo = ''; @@ -161,9 +237,8 @@ await this.writePushAuditLog("camera_gps",{ "deviceNo": "UNKOWN", "requestContent": body, "errorMessage": "未包含设备号SN" }); } await this.midwayCache.del(`push:gps:queue:${messageId}`); } catch (err: any) { await this.writePushAuditLog("camera_gps",{ "deviceNo": body.sn || "UNKNOW", "requestContent": body, "errorMessage": err }); }