zigbee-herdsman-converters
Version:
Collection of device converters to be used with zigbee-herdsman
773 lines (771 loc) • 29.6 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateDefinition = generateDefinition;
exports.generateGreenPowerDefinition = generateGreenPowerDefinition;
const zigbee_herdsman_1 = require("zigbee-herdsman");
const logger_1 = require("./logger");
const m = __importStar(require("./modernExtend"));
const philips = __importStar(require("./philips"));
const utils_1 = require("./utils");
const NS = "zhc:gendef";
// Generator allows to define instances of GeneratedExtend that have typed arguments to extender.
class ExtendGenerator {
extend;
args;
source;
lib;
constructor(args) {
this.extend = args.extend;
this.args = args.args;
this.source = args.source;
this.lib = args.lib;
}
getExtend() {
return this.extend(this.args);
}
getSource() {
let jsonArgs = JSON.stringify(this.args);
if (!this.args || jsonArgs === "{}") {
jsonArgs = "";
}
return `${this.source}(${jsonArgs})`;
}
}
// If generator will have endpoint argument - generator implementation
// should not provide it if only the first device endpoint is passed in.
// If multiple endpoints provided(maybe including the first device endpoint) -
// they all should be passed as an argument, where possible, to be explicit.
const INPUT_EXTENDERS = [
[
["msTemperatureMeasurement"],
async (d, eps) => [new ExtendGenerator({ extend: m.temperature, args: maybeEndpointArgs(d, eps), source: "temperature" })],
],
[["msPressureMeasurement"], async (d, eps) => [new ExtendGenerator({ extend: m.pressure, args: maybeEndpointArgs(d, eps), source: "pressure" })]],
[["msRelativeHumidity"], async (d, eps) => [new ExtendGenerator({ extend: m.humidity, args: maybeEndpointArgs(d, eps), source: "humidity" })]],
[["msCO2"], async (d, eps) => [new ExtendGenerator({ extend: m.co2, args: maybeEndpointArgs(d, eps), source: "co2" })]],
[["genPowerCfg"], async (d, eps) => [new ExtendGenerator({ extend: m.battery, source: "battery" })]],
[["genOnOff", "genLevelCtrl", "lightingColorCtrl"], extenderOnOffLight],
[["seMetering", "haElectricalMeasurement"], extenderElectricityMeter],
[["closuresDoorLock"], extenderLock],
[
["msIlluminanceMeasurement"],
async (d, eps) => [new ExtendGenerator({ extend: m.illuminance, args: maybeEndpointArgs(d, eps), source: "illuminance" })],
],
[["msOccupancySensing"], async (d, eps) => [new ExtendGenerator({ extend: m.occupancy, source: "occupancy" })]],
[
["ssIasZone"],
async (d, eps) => [
new ExtendGenerator({
extend: m.iasZoneAlarm,
args: {
zoneType: "generic",
zoneAttributes: ["alarm_1", "alarm_2", "tamper", "battery_low"],
},
source: "iasZoneAlarm",
}),
],
],
[["ssIasWd"], async (d, eps) => [new ExtendGenerator({ extend: m.iasWarning, source: "iasWarning" })]],
[
["genDeviceTempCfg"],
async (d, eps) => [new ExtendGenerator({ extend: m.deviceTemperature, args: maybeEndpointArgs(d, eps), source: "deviceTemperature" })],
],
[["pm25Measurement"], async (d, eps) => [new ExtendGenerator({ extend: m.pm25, args: maybeEndpointArgs(d, eps), source: "pm25" })]],
[["msFlowMeasurement"], async (d, eps) => [new ExtendGenerator({ extend: m.flow, args: maybeEndpointArgs(d, eps), source: "flow" })]],
[["msSoilMoisture"], async (d, eps) => [new ExtendGenerator({ extend: m.soilMoisture, args: maybeEndpointArgs(d, eps), source: "soilMoisture" })]],
[
["closuresWindowCovering"],
async (d, eps) => [new ExtendGenerator({ extend: m.windowCovering, args: { controls: ["lift", "tilt"] }, source: "windowCovering" })],
],
[["genBinaryInput"], extenderBinaryInput],
[["genBinaryOutput"], extenderBinaryOutput],
[["genAnalogInput"], extenderAnalogInput],
[["genAnalogOutput"], extenderAnalogOutput],
];
const OUTPUT_EXTENDERS = [
[["genOnOff"], async (d, eps) => [new ExtendGenerator({ extend: m.commandsOnOff, args: maybeEndpointArgs(d, eps), source: "commandsOnOff" })]],
[
["genLevelCtrl"],
async (d, eps) => [new ExtendGenerator({ extend: m.commandsLevelCtrl, args: maybeEndpointArgs(d, eps), source: "commandsLevelCtrl" })],
],
[
["lightingColorCtrl"],
async (d, eps) => [new ExtendGenerator({ extend: m.commandsColorCtrl, args: maybeEndpointArgs(d, eps), source: "commandsColorCtrl" })],
],
[
["closuresWindowCovering"],
async (d, eps) => [
new ExtendGenerator({ extend: m.commandsWindowCovering, args: maybeEndpointArgs(d, eps), source: "commandsWindowCovering" }),
],
],
];
function generateSource(definition, generatedExtend) {
const imports = [...new Set(generatedExtend.map((e) => e.lib ?? "modernExtend"))];
const importsStr = imports.map((e) => `import * as ${e === "modernExtend" ? "m" : e} from 'zigbee-herdsman-converters/lib/${e}';`).join("\n");
const meta = definition.meta ? `\n meta: ${JSON.stringify(definition.meta)},` : "";
return `${importsStr}
export default {
zigbeeModel: ['${definition.zigbeeModel}'],
model: '${definition.model}',
vendor: '${definition.vendor}',
description: 'Automatically generated definition',
extend: [${generatedExtend.map((e) => `${e.lib ?? "m"}.${e.getSource()}`).join(", ")}],${meta}
};
`;
}
function generateGreenPowerSource(definition, ieeeAddr) {
return `import {genericGreenPower} from 'zigbee-herdsman-converters/lib/modernExtend';
export default {
fingerprint: [{modelID: '${definition.model}', ieeeAddr: new RegExp('^${ieeeAddr}$')}],
model: '${definition.model}',
vendor: '${definition.vendor}',
description: 'Automatically generated definition for Green Power',
extend: [genericGreenPower()],
};`;
}
async function generateDefinition(device) {
if (device.type === "GreenPower") {
return generateGreenPowerDefinition(device);
}
// Map cluster to all endpoints that have this cluster.
const mapClusters = (endpoint, clusters, clusterMap) => {
for (const cluster of clusters) {
if (!clusterMap.has(cluster.name)) {
clusterMap.set(cluster.name, []);
}
const endpointsWithCluster = clusterMap.get(cluster.name);
endpointsWithCluster.push(endpoint);
}
};
const knownInputClusters = INPUT_EXTENDERS.flatMap((ext) => ext[0]);
const knownOutputClusters = OUTPUT_EXTENDERS.flatMap((ext) => ext[0]);
const inputClusterMap = new Map();
const outputClusterMap = new Map();
for (const endpoint of device.endpoints) {
// Filter clusters to leave only the ones that we can generate extenders for.
const inputClusters = endpoint.getInputClusters().filter((c) => knownInputClusters.find((known) => known === c.name));
const outputClusters = endpoint.getOutputClusters().filter((c) => knownOutputClusters.find((known) => known === c.name));
mapClusters(endpoint, inputClusters, inputClusterMap);
mapClusters(endpoint, outputClusters, outputClusterMap);
}
// Generate extenders
const usedExtenders = [];
const generatedExtend = [];
const addGenerators = async (clusterName, endpoints, extenders) => {
const extender = extenders.find((e) => e[0].includes(clusterName));
if (!extender || usedExtenders.includes(extender)) {
return;
}
usedExtenders.push(extender);
generatedExtend.push(...(await extender[1](device, endpoints)));
};
for (const [cluster, endpoints] of inputClusterMap) {
await addGenerators(cluster, endpoints, INPUT_EXTENDERS);
}
for (const [cluster, endpoints] of outputClusterMap) {
await addGenerators(cluster, endpoints, OUTPUT_EXTENDERS);
}
const extenders = generatedExtend.map((e) => e.getExtend());
// Generated definition below will provide this.
for (const extender of extenders) {
extender.endpoint = undefined;
}
// Currently multiEndpoint is enabled if device has more then 1 endpoint.
// It is possible to better check if device should be considered multiEndpoint
// based, for example, on generator arguments(i.e. presence of "endpointNames"),
// but this will be enough for now.
const endpointsWithoutGreenPower = device.endpoints.filter((e) => e.ID !== 242);
const multiEndpoint = endpointsWithoutGreenPower.length > 1;
if (multiEndpoint) {
const endpoints = {};
for (const endpoint of endpointsWithoutGreenPower) {
endpoints[endpoint.ID.toString()] = endpoint.ID;
}
// Add to beginning for better visibility.
generatedExtend.unshift(new ExtendGenerator({ extend: m.deviceEndpoints, args: { endpoints }, source: "deviceEndpoints" }));
extenders.unshift(generatedExtend[0].getExtend());
}
const definition = {
zigbeeModel: [device.modelID],
model: device.modelID ?? "",
vendor: device.manufacturerName ?? "",
description: "Automatically generated definition",
extend: extenders,
generated: true,
};
const externalDefinitionSource = generateSource(definition, generatedExtend);
return { externalDefinitionSource, definition };
}
function generateGreenPowerDefinition(device) {
const definition = {
fingerprint: [{ modelID: device.modelID, ieeeAddr: new RegExp(`^${device.ieeeAddr}$`) }],
model: device.modelID ?? "",
vendor: device.manufacturerName ?? "",
description: "Automatically generated definition for Green Power",
extend: [m.genericGreenPower()],
generated: true,
};
const externalDefinitionSource = generateGreenPowerSource(definition, device.ieeeAddr);
return { externalDefinitionSource, definition };
}
function stringifyEps(endpoints) {
return endpoints.map((e) => e.ID.toString());
}
// This function checks if provided array of endpoints contain
// only first device endpoint, which is passed in as `firstEndpoint`.
function onlyFirstDeviceEnpoint(device, endpoints) {
return endpoints.length === 1 && endpoints[0].ID === device.endpoints[0].ID;
}
// maybeEndpoints returns either `toExtend` if only first device endpoint is provided
// as `endpoints`, or `endpointNames` with `toExtend`.
// This allows to drop unnecessary `endpointNames` argument if it is not needed.
function maybeEndpointArgs(device, endpoints, toExtend) {
if (onlyFirstDeviceEnpoint(device, endpoints)) {
return toExtend;
}
return { endpointNames: stringifyEps(endpoints), ...toExtend };
}
async function extenderLock(device, endpoints) {
// TODO: Support multiple endpoints
if (endpoints.length > 1) {
logger_1.logger.warning("extenderLock can accept only one endpoint", NS);
}
const endpoint = endpoints[0];
const pinCodeCount = await (0, utils_1.getClusterAttributeValue)(endpoint, "closuresDoorLock", "numOfPinUsersSupported", 50);
return [new ExtendGenerator({ extend: m.lock, args: { pinCodeCount }, source: "lock" })];
}
async function extenderOnOffLight(device, endpoints) {
const generated = [];
const lightEndpoints = endpoints.filter((e) => e.supportsInputCluster("lightingColorCtrl") || e.supportsInputCluster("genLevelCtrl"));
const onOffEndpoints = endpoints.filter((e) => lightEndpoints.findIndex((ep) => e.ID === ep.ID) === -1);
if (onOffEndpoints.length !== 0) {
let endpointNames;
if (!onlyFirstDeviceEnpoint(device, onOffEndpoints)) {
endpointNames = onOffEndpoints.map((e) => e.ID.toString());
}
generated.push(new ExtendGenerator({ extend: m.onOff, args: { powerOnBehavior: false, endpointNames }, source: "onOff" }));
}
for (const endpoint of lightEndpoints) {
let endpointNames;
if (!onlyFirstDeviceEnpoint(device, lightEndpoints)) {
endpointNames = lightEndpoints.map((e) => e.ID.toString());
}
// In case read fails, support all features with 31
let colorCapabilities = 0;
if (endpoint.supportsInputCluster("lightingColorCtrl")) {
colorCapabilities = await (0, utils_1.getClusterAttributeValue)(endpoint, "lightingColorCtrl", "colorCapabilities", 31);
}
const supportsHueSaturation = (colorCapabilities & (1 << 0)) > 0;
const supportsEnhancedHueSaturation = (colorCapabilities & (1 << 1)) > 0;
const supportsColorXY = (colorCapabilities & (1 << 3)) > 0;
const supportsColorTemperature = (colorCapabilities & (1 << 4)) > 0;
const args = {};
args.endpointNames = endpointNames;
if (supportsColorTemperature) {
const minColorTemp = await (0, utils_1.getClusterAttributeValue)(endpoint, "lightingColorCtrl", "colorTempPhysicalMin", 150);
const maxColorTemp = await (0, utils_1.getClusterAttributeValue)(endpoint, "lightingColorCtrl", "colorTempPhysicalMax", 500);
args.colorTemp = { range: [minColorTemp, maxColorTemp] };
}
if (supportsColorXY) {
args.color = true;
if (supportsHueSaturation || supportsEnhancedHueSaturation) {
args.color = {};
if (supportsHueSaturation)
args.color.modes = ["xy", "hs"];
if (supportsEnhancedHueSaturation)
args.color.enhancedHue = true;
}
}
if (endpoint.getDevice().manufacturerID === zigbee_herdsman_1.Zcl.ManufacturerCode.SIGNIFY_NETHERLANDS_B_V) {
generated.push(new ExtendGenerator({ extend: philips.m.light, args, source: "m.light", lib: "philips" }));
}
else {
generated.push(new ExtendGenerator({ extend: m.light, args, source: "light" }));
}
}
return generated;
}
async function extenderElectricityMeter(device, endpoints) {
// TODO: Support multiple endpoints
if (endpoints.length > 1) {
logger_1.logger.warning("extenderElectricityMeter can accept only one endpoint", NS);
}
const endpoint = endpoints[0];
const metering = endpoint.supportsInputCluster("seMetering");
const electricalMeasurements = endpoint.supportsInputCluster("haElectricalMeasurement");
const args = {};
if (!metering || !electricalMeasurements) {
args.cluster = metering ? "metering" : "electrical";
}
if (args.cluster === "electrical") {
// If this value will be 0 then the value of 'args.electricalMeasurementType' will not be changed.
const measurementType = await (0, utils_1.getClusterAttributeValue)(endpoint, "haElectricalMeasurement", "measurementType", 0);
// MeasurementType will have bit on index 6 set for DC measurement.
const isDCMeasureType = ((measurementType >> 6) & 1) === 1;
args.electricalMeasurementType = "ac";
if (isDCMeasureType) {
args.electricalMeasurementType = "dc";
}
}
if (endpoint.ID !== 1) {
args.endpointNames = stringifyEps([endpoint]);
}
return [new ExtendGenerator({ extend: m.electricityMeter, args, source: "electricityMeter" })];
}
async function extenderBinaryInput(device, endpoints) {
const generated = [];
let endpointName;
for (const endpoint of endpoints) {
if (!onlyFirstDeviceEnpoint(device, endpoints)) {
endpointName = endpoint.ID.toString();
}
const name = await (0, utils_1.getClusterAttributeValue)(endpoint, "genBinaryInput", "description", endpointName ? "binary_input" : `binary_input_${endpoint.ID}`);
let label;
if (name !== "binary_input" && name !== `binary_input_${endpoint.ID}`) {
label = name;
}
const description = `Binary Input ${name} on endpoint ${endpoint.ID}`;
const args = {
name: name.replace(/\s+/g, "_").toLowerCase(),
label,
cluster: "genBinaryInput",
attribute: "presentValue",
reporting: { min: "MIN", max: "MAX", change: 1 },
valueOn: ["ON", 1],
valueOff: ["OFF", 0],
description: description,
access: "STATE_GET",
endpointName,
};
generated.push(new ExtendGenerator({ extend: m.binary, args, source: "binary" }));
}
return generated;
}
async function extenderBinaryOutput(device, endpoints) {
const generated = [];
let endpointName;
for (const endpoint of endpoints) {
if (!onlyFirstDeviceEnpoint(device, endpoints)) {
endpointName = endpoint.ID.toString();
}
const name = await (0, utils_1.getClusterAttributeValue)(endpoint, "genBinaryOutput", "description", endpointName ? "binary_output" : `binary_output_${endpoint.ID}`);
let label;
if (name !== "binary_output" && name !== `binary_output_${endpoint.ID}`) {
label = name;
}
const description = `Binary Output ${name} on endpoint ${endpoint.ID}`;
const args = {
name: name.replace(/\s+/g, "_").toLowerCase(),
label,
cluster: "genBinaryOutput",
attribute: "presentValue",
reporting: { min: "MIN", max: "MAX", change: 1 },
valueOn: ["ON", 1],
valueOff: ["OFF", 0],
description: description,
access: "ALL",
endpointName,
};
generated.push(new ExtendGenerator({ extend: m.binary, args, source: "binary" }));
}
return generated;
}
function getUnitfromApplicationType(applicationType) {
// Map of applicationType to unit strings. Only take type ( Bits 16 to 23 ) into account.
const type = (applicationType >> 16) & 0xff;
const applicationTypeMap = {
0: "°C", // Temp_Degrees_C
1: "%", // Relative_Humidity_Percent
2: "Pa", // Pressure_Pascal
3: "L/s", // Flow_Liters_Per_Sec
4: "%", // Percentage
5: "ppm", // Parts_Per_Million
6: "rpm", // Rotational_Speed_RPM
7: "A", // Current_Amps
8: "Hz", // Frequency_Hz
9: "W", // Power_Watts
10: "kW", // Power_Kilo_Watts
11: "kWh", // Energy_Kilo_Watt_Hours
12: undefined, // Count
13: "kJ/kg", // Enthalpy_KJoules_Per_Kg
14: "s", // Time_Seconds
};
return applicationTypeMap[type];
}
function getUnitfromBACnetUnit(bacnetUnit) {
const bacnetUnitMap = {
0: "m²",
1: "ft²",
2: "mA",
3: "A",
4: "Ω",
5: "V",
6: "kV",
7: "MV",
8: "VA",
9: "kVA",
10: "MVA",
11: "var",
12: "kvar",
13: "Mvar",
14: "°phase",
15: "pf",
16: "J",
17: "kJ",
18: "Wh",
19: "kWh",
20: "Btu",
21: "therm",
22: "ton·h",
23: "J/kg",
24: "Btu/lb",
25: "cycles/h",
26: "cycles/min",
27: "Hz",
28: "g/kg",
29: "%",
30: "mm",
31: "m",
32: "in",
33: "ft",
34: "W/ft²",
35: "W/m²",
36: "lm",
37: "lx",
38: "fc",
39: "kg",
40: "lb",
41: "tons",
42: "kg/s",
43: "kg/min",
44: "kg/h",
45: "lb/min",
46: "lb/h",
47: "W",
48: "kW",
49: "MW",
50: "Btu/h",
51: "hp",
52: "ton",
53: "Pa",
54: "kPa",
55: "bar",
56: "psi",
57: "cm H₂O",
58: "in H₂O",
59: "mmHg",
60: "cm Hg",
61: "in Hg",
62: "°C",
63: "K",
64: "°F",
65: "°C·d",
66: "°F·d",
67: "years",
68: "months",
69: "weeks",
70: "days",
71: "hours",
72: "minutes",
73: "seconds",
74: "m/s",
75: "km/h",
76: "ft/s",
77: "ft/min",
78: "mph",
79: "ft³",
80: "m³",
81: "imp gal",
82: "L",
83: "gal",
84: "ft³/min",
85: "m³/s",
86: "imp gal/min",
87: "L/s",
88: "L/min",
89: "gal/min",
90: "°",
91: "°C/h",
92: "°C/min",
93: "°F/h",
94: "°F/min",
95: undefined,
96: "ppm",
97: "ppb",
98: "%",
99: "%/s",
100: "1/min",
101: "1/s",
102: "psi/°F",
103: "rad",
104: "rpm",
105: "currency",
106: "currency",
107: "currency",
108: "currency",
109: "currency",
110: "currency",
111: "currency",
112: "currency",
113: "currency",
114: "currency",
115: "in²",
116: "cm²",
117: "Btu/lb",
118: "cm",
119: "lb/s",
120: "Δ°F",
121: "ΔK",
122: "kΩ",
123: "MΩ",
124: "mV",
125: "kJ/kg",
126: "MJ",
127: "J/K",
128: "J/(kg·K)",
129: "kHz",
130: "MHz",
131: "1/h",
132: "mW",
133: "hPa",
134: "mbar",
135: "m³/h",
136: "L/h",
137: "kWh/m²",
138: "kWh/ft²",
139: "MJ/m²",
140: "MJ/ft²",
141: "W/(m²·K)",
142: "ft³/s",
143: "% obscuration/ft",
144: "% obscuration/m",
145: "mΩ",
146: "MWh",
147: "kBtu",
148: "MBtu",
149: "kJ/kg_dry",
150: "MJ/kg_dry",
151: "kJ/K",
152: "MJ/K",
153: "N",
154: "g/s",
155: "g/min",
156: "tons/h",
157: "kBtu/h",
158: "1/100 s",
159: "ms",
160: "N·m",
161: "mm/s",
162: "mm/min",
163: "m/min",
164: "m/h",
165: "m³/min",
166: "m/s²",
167: "A/m",
168: "A/m²",
169: "A·m²",
170: "F",
171: "H",
172: "Ω·m",
174: "S/m",
175: "T",
176: "V/K",
177: "V/m",
178: "Wb",
179: "cd",
180: "cd/m²",
181: "K/h",
182: "K/min",
183: "J·s",
184: "rad/s",
185: "m²/N",
186: "kg/m³",
187: "N·s",
188: "N/m",
189: "W/(m·K)",
190: "µS/cm",
191: "ft³/h",
192: "gal/h",
193: "km",
194: "µm",
195: "g",
196: "mg",
197: "mL",
198: "mL/s",
199: "dB",
200: "dBm",
201: "dBV",
202: "mS/cm",
203: "var·h",
204: "kvar·h",
205: "Mvar·h",
206: "mm H₂O",
207: "‰",
208: "g/g",
209: "kg/kg",
210: "g/kg",
211: "mg/g",
212: "mg/kg",
213: "g/mL",
214: "g/L",
215: "mg/L",
216: "µg/L",
217: "g/m³",
218: "mg/m³",
219: "µg/m³",
220: "ng/m³",
221: "g/cm³",
222: "Bq",
223: "kBq",
224: "MBq",
225: "Gy",
226: "mGy",
227: "µGy",
228: "Sv",
229: "mSv",
230: "µSv",
231: "µSv/h",
232: "dBA",
233: "NTU",
234: "pH",
235: "g/m²",
236: "min/K",
237: "Ω·m²/m",
238: "A·s",
239: "VA·h",
240: "kVA·h",
241: "MVA·h",
242: "var·h",
243: "kvar·h",
244: "Mvar·h",
245: "V²·h",
246: "A²·h",
247: "J/h",
248: "ft³/d",
249: "m³/d",
250: "Wh/m³",
251: "J/m³",
252: "mol%",
253: "Pa·s",
254: "MMSCFM",
};
return bacnetUnitMap[bacnetUnit];
}
async function extenderAnalogInput(device, endpoints) {
const generated = [];
let endpointNames;
for (const endpoint of endpoints) {
if (!onlyFirstDeviceEnpoint(device, endpoints)) {
endpointNames = [endpoint.ID.toString()];
}
const name = await (0, utils_1.getClusterAttributeValue)(endpoint, "genAnalogInput", "description", endpointNames ? "analog_input" : `analog_input_${endpoint.ID}`);
let label;
if (name !== "analog_input" && name !== `analog_input_${endpoint.ID}`) {
label = name;
}
const description = `Analog Input ${name} on endpoint ${endpoint.ID}`;
const applicationType = await (0, utils_1.getClusterAttributeValue)(endpoint, "genAnalogInput", "applicationType", undefined);
let unit;
if (applicationType !== undefined) {
unit = getUnitfromApplicationType(applicationType);
}
if (unit === undefined) {
const bacnet_unit = await (0, utils_1.getClusterAttributeValue)(endpoint, "genAnalogInput", "engineeringUnits", undefined);
if (bacnet_unit !== undefined) {
unit = getUnitfromBACnetUnit(bacnet_unit);
}
}
const args = {
name: name.replace(/\s+/g, "_").toLowerCase(),
label,
valueMin: await (0, utils_1.getClusterAttributeValue)(endpoint, "genAnalogInput", "minPresentValue", undefined),
valueMax: await (0, utils_1.getClusterAttributeValue)(endpoint, "genAnalogInput", "maxPresentValue", undefined),
valueStep: await (0, utils_1.getClusterAttributeValue)(endpoint, "genAnalogInput", "resolution", undefined),
cluster: "genAnalogInput",
attribute: "presentValue",
reporting: { min: "MIN", max: "MAX", change: 1 },
description: description,
access: "STATE_GET",
endpointNames,
unit,
};
generated.push(new ExtendGenerator({ extend: m.numeric, args, source: "numeric" }));
}
return generated;
}
async function extenderAnalogOutput(device, endpoints) {
const generated = [];
let endpointNames;
for (const endpoint of endpoints) {
if (!onlyFirstDeviceEnpoint(device, endpoints)) {
endpointNames = [endpoint.ID.toString()];
}
const name = await (0, utils_1.getClusterAttributeValue)(endpoint, "genAnalogOutput", "description", endpointNames ? "analog_output" : `analog_output_${endpoint.ID}`);
let label;
if (name !== "analog_output" && name !== `analog_output_${endpoint.ID}`) {
label = name;
}
const description = `Analog Output ${name} on endpoint ${endpoint.ID}`;
const applicationType = await (0, utils_1.getClusterAttributeValue)(endpoint, "genAnalogOutput", "applicationType", undefined);
let unit;
if (applicationType !== undefined) {
unit = getUnitfromApplicationType(applicationType);
}
if (unit === undefined) {
const bacnet_unit = await (0, utils_1.getClusterAttributeValue)(endpoint, "genAnalogOutput", "engineeringUnits", undefined);
if (bacnet_unit !== undefined) {
unit = getUnitfromBACnetUnit(bacnet_unit);
}
}
const args = {
name: name.replace(/\s+/g, "_").toLowerCase(),
label,
valueMin: await (0, utils_1.getClusterAttributeValue)(endpoint, "genAnalogOutput", "minPresentValue", undefined),
valueMax: await (0, utils_1.getClusterAttributeValue)(endpoint, "genAnalogOutput", "maxPresentValue", undefined),
valueStep: await (0, utils_1.getClusterAttributeValue)(endpoint, "genAnalogOutput", "resolution", undefined),
cluster: "genAnalogOutput",
attribute: "presentValue",
reporting: { min: "MIN", max: "MAX", change: 1 },
description: description,
access: "ALL",
endpointNames,
unit,
};
generated.push(new ExtendGenerator({ extend: m.numeric, args, source: "numeric" }));
}
return generated;
}
//# sourceMappingURL=generateDefinition.js.map