chenyc
2026-03-22 7885cede659f3255be56f77c1eef2ada7387d6f1
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
const fs = require("fs");
const path = require("path");
const logger = require("./logger");
 
class PropertyMapper {
  constructor() {
    this.map = new Map(); // identifier -> { identifier, name, ... }
    this.loadSchema();
  }
 
  loadSchema() {
    try {
      // 在普通 Node 环境下,schema.json 位于项目根目录;
      // 使用 pkg 打包后,优先从可执行文件同级目录读取 schema.json,便于现场替换。
      const appRoot = process.pkg
        ? path.dirname(process.execPath)
        : path.join(__dirname, "..");
      const schemaPath = path.join(appRoot, "schema.json");
      const raw = fs.readFileSync(schemaPath, "utf8");
      const json = JSON.parse(raw);
      if (Array.isArray(json.properties)) {
        for (const prop of json.properties) {
          if (prop.identifier) {
            this.map.set(prop.identifier, prop);
          }
        }
      }
      logger.info("Property schema loaded", { count: this.map.size });
    } catch (err) {
      logger.warn("Failed to load schema.json, using empty mapping", err.message || err);
    }
  }
 
  mapData(rawData) {
    const result = [];
    if (!rawData || typeof rawData !== "object") return result;
    for (const [key, value] of Object.entries(rawData)) {
      const def = this.map.get(key) || { identifier: key, name: key };
      result.push({
        identifier: def.identifier,
        name: def.name,
        value
      });
    }
    return result;
  }
 
  transformForHTTP(rawData, deviceNumber) {
    return {
      deviceNumber,
      properties: this.mapData(rawData)
    };
  }
 
  transformForMQTT(rawData, deviceNumber) {
    return {
      deviceNumber,
      timestamp: Date.now(),
      properties: this.mapData(rawData)
    };
  }
 
  transformForAliyun(rawData) {
    // 阿里云物模型上报通常直接使用 identifier -> value
    const result = {};
    if (!rawData || typeof rawData !== "object") return result;
    for (const [key, value] of Object.entries(rawData)) {
      result[key] = value;
    }
    return result;
  }
}
 
module.exports = PropertyMapper;