From b27355fe55abf32a32c744d68831643a0e6091e6 Mon Sep 17 00:00:00 2001
From: wangrong <wangrong@shsening.com>
Date: 星期一, 03 八月 2026 19:23:04 +0800
Subject: [PATCH] 更新页面标题和内容,优化萤石云接口处理逻辑,增加摄像头告警事件保存功能

---
 src/modules/push/controller/app/open.ts |  160 ++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 146 insertions(+), 14 deletions(-)

diff --git a/src/modules/push/controller/app/open.ts b/src/modules/push/controller/app/open.ts
index 3d70d84..67199aa 100644
--- a/src/modules/push/controller/app/open.ts
+++ b/src/modules/push/controller/app/open.ts
@@ -1,11 +1,10 @@
-import { Inject, Post, Body, Headers } from '@midwayjs/core';
+import { Inject, Post, Get, Body, Headers, Fields, Files } from '@midwayjs/core';
 import { CoolController, BaseController } from '@cool-midway/core';
 import { PushOpenService } from '../../service/open';
 import { WeightUploadDto } from '../../dto/weight.dto';
 import * as crypto from 'crypto';
 import { BaseSysParamService } from '../../../base/service/sys/param';
-
-
+import { Context } from '@midwayjs/koa'; //
 
 /**
  * 寮�鏀炬棤闇�楠岃瘉鐨勪笂鎶ユ暟鎹帴鍙�
@@ -14,6 +13,9 @@
   prefix: '/open/push',
 })
 export class AppPushOpenController extends BaseController {
+  @Inject()
+  ctx: Context;
+
   @Inject()
   pushOpenService: PushOpenService;
 
@@ -88,16 +90,146 @@
     }
   }
 
-
   @Post('/yingshiyun', { summary: '钀ょ煶浜慦ebhook涓婃姤鎺ュ彛' })
-  async saveYingshiyunMessage(
-    @Body() body: any
-  ) {
-
-    const result = await this.pushOpenService.saveYingshiyunMessage(body);
-    //return this.ok(result);
-
-    return { "messageId": result }
-
+  async saveYingshiyunMessage() {
+    const req = this.ctx.req;
+    const rawBody = await new Promise<string>((resolve, reject) => {
+      let data = '';
+      const timer = setTimeout(() => reject(new Error('璇诲彇娴佽秴鏃�')), 5000);
+      req.on('data', chunk => data += chunk);
+      req.on('end', () => {
+        clearTimeout(timer);
+        resolve(data);
+      });
+      req.on('error', err => {
+        clearTimeout(timer);
+        reject(err);
+      });
+    }).catch(err => {
+      console.error('璇诲彇stream寮傚父锛�', err);
+      this.ctx.status = 200;
+      this.ctx.body = { messageId: '' };
+      return '';
+    });
+    if (!rawBody) {
+      this.ctx.status = 200;
+      this.ctx.body = { messageId: '' };
+      return;
+    }
+    console.log('銆愯悿鐭充簯鍘熷鎶ユ枃銆�:', rawBody.slice(0, 500));
+    let msg: any;
+    try {
+      msg = JSON.parse(rawBody);
+    } catch (e) {
+      console.error('JSON瑙f瀽澶辫触:', e);
+      this.ctx.status = 200;
+      this.ctx.body = { messageId: '' };
+      return;
+    }
+    const messageId = msg?.header?.messageId;
+    const msgType = msg?.header?.type; // "ys.onoffline" / "ys.alarm" / ...
+    console.log('娑堟伅绫诲瀷:', msgType, '| messageId:', messageId);
+    if (msgType === 'ys.alarm') {
+      console.log('鍛婅绫诲瀷:', msg.body?.alarmType, '| 鎻忚堪:', msg.body?.describe);
+    } else if (msgType === 'ys.onoffline') {
+      console.log('璁惧涓婁笅绾�:', msg.body?.msgType, '| 璁惧:', msg.body?.deviceName);
+    }
+    try {
+      await this.pushOpenService.saveYingshiyunMessage(msg);
+    } catch (e) {
+      console.error('鏁版嵁澶勭悊澶辫触:', e);
+      // 鍗充娇瀛樺簱澶辫触锛屼篃瑕佸洖 200 + messageId锛岄伩鍏嶈悿鐭抽噸璇�
+    }
+    this.ctx.status = 200;
+    this.ctx.set('Content-Type', 'application/json');
+    this.ctx.body = { messageId: messageId || '' };
   }
-}
+
+
+  /**
+   * 鎽勫儚鏈轰富鍔ㄦ帹閫佸憡璀︿簨浠讹紙绉诲姩渚︽祴VMD銆佷汉浣撲睛娴嬶紝XML multipart鏍煎紡锛�
+   * 鍦板潃锛歅OST /open/push/cameraEvent
+   */
+  @Post('/cameraEvent', { summary: '鎽勫儚澶翠富鍔ㄤ笂鎶ュ憡璀︿簨浠�' })
+  async receiveCameraEvent() {
+    const req = this.ctx.req;
+    let rawBody = '';
+
+    try {
+      rawBody = await new Promise<string>((resolve, reject) => {
+        let data = '';
+        const timer = setTimeout(() => reject(new Error('璇诲彇娴佽秴鏃�')), 5000);
+        req.on('data', (chunk) => (data += chunk));
+        req.on('end', () => {
+          clearTimeout(timer);
+          resolve(data);
+        });
+        req.on('error', (err) => {
+          clearTimeout(timer);
+          reject(err);
+        });
+      });
+    } catch (err) {
+      console.error('銆愭憚鍍忓ご浜嬩欢銆戣鍙杝tream寮傚父锛�', err);
+      this.ctx.status = 200;
+      this.ctx.body = { code: -1, msg: 'read error' };
+      return;
+    }
+    if (!rawBody) {
+      this.ctx.status = 200;
+      this.ctx.body = { code: -1, msg: 'empty body' };
+      return;
+    }
+
+    // 鎴彇瀹屾暣XML鏂囨湰
+    const xmlReg = /<\?xml[\s\S]*?<\/EventNotificationAlert>/;
+    const xmlMatch = rawBody.match(xmlReg);
+    if (!xmlMatch) {
+      console.warn('銆愭憚鍍忓ご浜嬩欢銆戞湭鍖归厤鍒板憡璀ML鍐呭');
+      this.ctx.status = 200;
+      this.ctx.body = { code: -1 };
+      return;
+    }
+    const xmlStr = xmlMatch[0];
+
+    // 閫氱敤XML鑺傜偣鎻愬彇锛堟敮鎸佹爣绛惧墠鍚庢崲琛岀┖鏍硷級
+    const getVal = (xml: string, tag: string) => {
+      const reg = new RegExp(`<${tag}>\\s*([\\s\\S]*?)\\s*<\\/${tag}>`);
+      const res = xml.match(reg);
+      return res ? res[1].trim() : '';
+    };
+
+    // 缁勮鍛婅瀹炰綋
+    const cameraEvent = {
+      ipAddress: getVal(xmlStr, 'ipAddress'),
+      macAddress: getVal(xmlStr, 'macAddress'),
+      portNo: getVal(xmlStr, 'portNo'),
+      channelID: getVal(xmlStr, 'channelID'),
+      channelName: getVal(xmlStr, 'channelName'),
+      dateTime: getVal(xmlStr, 'dateTime'),
+      eventType: getVal(xmlStr, 'eventType'), // VMD=绉诲姩渚︽祴
+      eventState: getVal(xmlStr, 'eventState'),
+      eventDescription: getVal(xmlStr, 'eventDescription'),
+      targetType: getVal(xmlStr, 'targetType'), // human 浜轰綋
+      targetID: getVal(xmlStr, 'targetID'),
+      // 鐩爣鍧愭爣妗�
+      rectX: getVal(xmlStr, 'X'),
+      rectY: getVal(xmlStr, 'Y'),
+      rectWidth: getVal(xmlStr, 'width'),
+      rectHeight: getVal(xmlStr, 'height'),
+    };
+
+    try {
+      // 璋冪敤service澶勭悊鎽勫儚澶村憡璀︿簨浠讹紝寤鸿鏂板缓service鏂规硶
+      const result = await this.pushOpenService.saveCameraAlarmEvent(cameraEvent);
+
+      this.ctx.status = 200;
+      this.ctx.set('Content-Type', 'application/json');
+      this.ctx.body = { success: true, messageId: result };
+    } catch (serviceErr) {
+      console.error('銆愭憚鍍忓ご浜嬩欢銆戜笟鍔″鐞嗗け璐ワ細', serviceErr);
+      this.ctx.status = 200;
+      this.ctx.body = { code: -1, msg: 'handle fail' };
+    }
+  }
+}
\ No newline at end of file

--
Gitblit v1.9.1