wangzhibo
2026-07-28 920cec41cedfde27f89d7c19b78e03147b926ab5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
import { InjectClient, Provide, Inject } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { PushWeightEntity } from '../entity/weight';
import { PushSiteweightEntity } from '../entity/siteweight';
import { PushAuditlogEntity } from '../entity/auditlog';
import { PushCameraGpsEntity } from '../entity/cameragps';
import { PushVehicleGpsEntity } from '../entity/vehiclegps';
import { PushDeviceOnoffEntity } from '../entity/deviceonoff';
import { PushDevicealarmEntity } from '../entity/devicealarm';
import { PluginService } from '../../plugin/service/info';
import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager';
 
/**
 * 开放接口业务逻辑服务
 */
@Provide()
export class PushOpenService extends BaseService {
  @InjectEntityModel(PushWeightEntity)
  pushWeightEntity: Repository<PushWeightEntity>;
 
  @InjectEntityModel(PushSiteweightEntity)
  pushSiteweightEntity: Repository<PushSiteweightEntity>;
 
  @InjectEntityModel(PushCameraGpsEntity)
  pushCameraGpsEntity: Repository<PushCameraGpsEntity>;
 
  @InjectEntityModel(PushVehicleGpsEntity)
  pushVehicleGpsEntity: Repository<PushVehicleGpsEntity>;
 
  @InjectEntityModel(PushDeviceOnoffEntity)
  pushDeviceOnoffEntity: Repository<PushDeviceOnoffEntity>;
 
  @InjectEntityModel(PushDevicealarmEntity)
  pushDevicealarmEntity: Repository<PushDevicealarmEntity>;
 
  @InjectEntityModel(PushAuditlogEntity)
  pushAuditlogEntity: Repository<PushAuditlogEntity>;
 
  @Inject()
  pluginService: PluginService;
 
  @InjectClient(CachingFactory, 'default')
  midwayCache: MidwayCache;
 
  /**
   * 上报称重数据核心业务
   */
  async reportWeight(data: any) {
    const logTime = new Date();
 
    try {
      // 1. 保存原始称重数据
      const rawWeight = new PushWeightEntity();
      rawWeight.deviceNo = data.deviceNo;
      rawWeight.uploadTime = data.uploadTime
        ? new Date(data.uploadTime)
        : new Date();
      rawWeight.garbageType = data.garbageType;
      rawWeight.weight = data.garbageWeight || 0;
      rawWeight.extraData =
        typeof data.extraData === 'object'
          ? JSON.stringify(data.extraData)
          : data.extraData;
      await this.pushWeightEntity.save(rawWeight);
 
      // 2. 模拟关联基础数据模块查询获取商户信息并写入业务称重表
      const siteWeight = new PushSiteweightEntity();
      siteWeight.deviceNo = data.deviceNo;
      siteWeight.uploadTime = rawWeight.uploadTime;
      siteWeight.garbageType = data.garbageType;
      siteWeight.weight = data.garbageWeight || 0;
      siteWeight.extraData = rawWeight.extraData;
 
      // 动态查询设备基础数据关联信息
      const iotDevices = await this.nativeQuery(
        'SELECT businessId, departmentId FROM t_basicdata_iot WHERE iotCode = ? LIMIT 1',
        [data.deviceNo],
      );
 
      if (iotDevices && iotDevices.length > 0) {
        siteWeight.businessId = iotDevices[0].businessId;
        siteWeight.departmentId = iotDevices[0].departmentId;
        await this.pushSiteweightEntity.save(siteWeight);
 
      } else {
        siteWeight.businessId = 'UNKNOWN';
        siteWeight.departmentId = -1;
        await this.writePushAuditLog("weight", { "deviceNo": data.deviceNo, "requestContent": data, "errorMessage": "电子秤还未分配到垃圾收集点." });
      }
 
    } catch (err) {
      await this.writePushAuditLog("weight", { "deviceNo": data.deviceNo || "UNKNOW", "requestContent": data, "errorMessage": 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 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': {
          // 图片下载并上传到本地/对象存储  pictureList: Array<{ url: string; id: string }>;
          const localUrls: Record<string, string>[] = [];
          if (body.pictureList && Array.isArray(body.pictureList)) {
            const filePlugin = await this.pluginService.getInstance('upload');
            for (const item of body.pictureList) {
              try {
                const result = await filePlugin.downAndUpload(item.url);
                localUrls.push({url: result, id: item.id});
              } catch (err) {
                console.error(`图片下载失败: ${item.url}`, err);
              }
            }
          }
          await this.pushDevicealarmEntity.save({
            devSerial: body.devSerial,
            channelNo: body.channelNo || String(body.channel),
            alarmId: body.alarmId,
            alarmTime: body.alarmTime,
            alarmType: body.alarmType,
            channelName: body.channelName,
            channelType: body.channelType ? Number(body.channelType) : 1,
            checksum: body.checksum,
            crypt: body.crypt ? Number(body.crypt) : 0,
            customInfo: body.customInfo,
            customType: body.customType,
            describe: body.describe,
            location: body.location,
            relationId: body.relationId,
            status: body.status ? Number(body.status) : 1,
            pictureList: localUrls || []
          });
          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 = '';
      if (body.sn) {
 
        const gpsData = body.data || {};
        const statusVal = gpsData.status === 'A' ? 'A' : 'B';
 
        await this.pushCameraGpsEntity.save({
          sn: body.sn,
          msgSeq: body.msgSeq,
          createDate: body.createDate && !isNaN(Number(body.createDate))
            ? new Date(Number(body.createDate))
            : new Date(),
          gpsTime: gpsData.gpsTime
            ? new Date(gpsData.gpsTime.replace(' ', 'T'))
            : new Date(),
          longitude: gpsData.longitude,
          latitude: gpsData.latitude,
          speed: gpsData.speed,
          direction: gpsData.direction,
          elevation: gpsData.elevation,
          status: statusVal,
        });
 
        const iotDevice: any[] = await this.nativeQuery(
          'SELECT businessId FROM t_basicdata_iot WHERE iotCode = ? LIMIT 1',
          [body.sn]
        );
        if (iotDevice && iotDevice.length > 0 && iotDevice[0].businessId) {
          vehicleNo = `vehicle_${iotDevice[0].businessId}`;
 
          await this.pushVehicleGpsEntity.save({
            sn: body.sn,
            msgSeq: body.msgSeq,
            createDate: body.createDate && !isNaN(Number(body.createDate))
              ? new Date(Number(body.createDate))
              : new Date(),
            vehicleNo,
            gpsTime: gpsData.gpsTime
              ? new Date(gpsData.gpsTime.replace(' ', 'T'))
              : new Date(),
            longitude: gpsData.longitude,
            latitude: gpsData.latitude,
            speed: gpsData.speed,
            direction: gpsData.direction,
            elevation: gpsData.elevation,
            status: statusVal,
          });
 
        } else {
          await this.writePushAuditLog("camera_gps", { "deviceNo": body.sn, "requestContent": body, "errorMessage": "车载监控还未分配到车辆" });
        }
      } else {
        await this.writePushAuditLog("camera_gps", { "deviceNo": "UNKOWN", "requestContent": body, "errorMessage": "未包含设备号SN" });
      }
 
    } catch (err: any) {
 
      await this.writePushAuditLog("camera_gps", { "deviceNo": body.sn || "UNKNOW", "requestContent": body, "errorMessage": err });
 
    }
  }
 
  async writePushAuditLog(pushType: string, data: any) {
    let isSuccess = true;
    let errorMsg = '';
    try {
      const auditLog = new PushAuditlogEntity();
      auditLog.logTime = new Date();
      auditLog.pushType = pushType;
      auditLog.deviceNo = data.deviceNo || 'unknown-device';
      auditLog.requestContent = JSON.stringify(data.requestContent);
      auditLog.errorMessage = data.errorMessage || 'unknown-erroe';
      await this.pushAuditlogEntity.save(auditLog);
 
    } catch (err) {
      isSuccess = false;
    }
 
  }
 
 
 
 
 
}