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;
|