UNPKG

iobroker.oxxify-fan-control

Version:
1,383 lines 93 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var OxxifyProtocol_exports = {}; __export(OxxifyProtocol_exports, { OxxifyProtocol: () => OxxifyProtocol, ParameterType: () => ParameterType }); module.exports = __toCommonJS(OxxifyProtocol_exports); var import_ModelData = require("./ModelData"); var FunctionType = /* @__PURE__ */ ((FunctionType2) => { FunctionType2[FunctionType2["Undefined"] = 0] = "Undefined"; FunctionType2[FunctionType2["Read"] = 1] = "Read"; FunctionType2[FunctionType2["WriteRead"] = 3] = "WriteRead"; FunctionType2[FunctionType2["Response"] = 6] = "Response"; return FunctionType2; })(FunctionType || {}); var ParameterType = /* @__PURE__ */ ((ParameterType2) => { ParameterType2[ParameterType2["FanState"] = 1] = "FanState"; ParameterType2[ParameterType2["FanSpeedMode"] = 2] = "FanSpeedMode"; ParameterType2[ParameterType2["BoostState"] = 6] = "BoostState"; ParameterType2[ParameterType2["TimerMode"] = 7] = "TimerMode"; ParameterType2[ParameterType2["TimerCountdown"] = 11] = "TimerCountdown"; ParameterType2[ParameterType2["StateHumiditySensor"] = 15] = "StateHumiditySensor"; ParameterType2[ParameterType2["StateRelaisSensor"] = 20] = "StateRelaisSensor"; ParameterType2[ParameterType2["StateAnalogVoltageSensor"] = 22] = "StateAnalogVoltageSensor"; ParameterType2[ParameterType2["TargetHumidityValue"] = 25] = "TargetHumidityValue"; ParameterType2[ParameterType2["RtcBatteryVoltage"] = 36] = "RtcBatteryVoltage"; ParameterType2[ParameterType2["CurrentHumidityValue"] = 37] = "CurrentHumidityValue"; ParameterType2[ParameterType2["CurrentAnalogVoltageValue"] = 45] = "CurrentAnalogVoltageValue"; ParameterType2[ParameterType2["CurrentRelaisValue"] = 50] = "CurrentRelaisValue"; ParameterType2[ParameterType2["ManualFanSpeed"] = 68] = "ManualFanSpeed"; ParameterType2[ParameterType2["FanSpeedFan1Rpm"] = 74] = "FanSpeedFan1Rpm"; ParameterType2[ParameterType2["FanSpeedFan2Rpm"] = 75] = "FanSpeedFan2Rpm"; ParameterType2[ParameterType2["FilterExchangeCountdown"] = 100] = "FilterExchangeCountdown"; ParameterType2[ParameterType2["ResetFilterExchangeCountdown"] = 101] = "ResetFilterExchangeCountdown"; ParameterType2[ParameterType2["BoostModeFollowUpTime"] = 102] = "BoostModeFollowUpTime"; ParameterType2[ParameterType2["TriggerTimeSync"] = 256] = "TriggerTimeSync"; ParameterType2[ParameterType2["RtcTime"] = 111] = "RtcTime"; ParameterType2[ParameterType2["RtcDate"] = 112] = "RtcDate"; ParameterType2[ParameterType2["TimeControlledMode"] = 114] = "TimeControlledMode"; ParameterType2[ParameterType2["TimeControlSchedule"] = 119] = "TimeControlSchedule"; ParameterType2[ParameterType2["SearchFanId"] = 124] = "SearchFanId"; ParameterType2[ParameterType2["FanPassword"] = 125] = "FanPassword"; ParameterType2[ParameterType2["OperatingTime"] = 126] = "OperatingTime"; ParameterType2[ParameterType2["ResetAlarms"] = 128] = "ResetAlarms"; ParameterType2[ParameterType2["AlarmState"] = 131] = "AlarmState"; ParameterType2[ParameterType2["CloudServerEnabled"] = 133] = "CloudServerEnabled"; ParameterType2[ParameterType2["FirmwareVersionAndDate"] = 134] = "FirmwareVersionAndDate"; ParameterType2[ParameterType2["ResetFactoryDefaults"] = 135] = "ResetFactoryDefaults"; ParameterType2[ParameterType2["FilterExchangeNecessary"] = 136] = "FilterExchangeNecessary"; ParameterType2[ParameterType2["WifiOperatingMode"] = 148] = "WifiOperatingMode"; ParameterType2[ParameterType2["WifiName"] = 149] = "WifiName"; ParameterType2[ParameterType2["WifiPassword"] = 150] = "WifiPassword"; ParameterType2[ParameterType2["WifiEncryptionMode"] = 153] = "WifiEncryptionMode"; ParameterType2[ParameterType2["WifiChannel"] = 154] = "WifiChannel"; ParameterType2[ParameterType2["WifiIpMode"] = 155] = "WifiIpMode"; ParameterType2[ParameterType2["WifiIp"] = 156] = "WifiIp"; ParameterType2[ParameterType2["WifiSubnetMask"] = 157] = "WifiSubnetMask"; ParameterType2[ParameterType2["WifiGateway"] = 158] = "WifiGateway"; ParameterType2[ParameterType2["ExitWifiSetupAndSafe"] = 160] = "ExitWifiSetupAndSafe"; ParameterType2[ParameterType2["ExitWifiSetupAndDiscard"] = 162] = "ExitWifiSetupAndDiscard"; ParameterType2[ParameterType2["CurrentWifiIp"] = 163] = "CurrentWifiIp"; ParameterType2[ParameterType2["FanOperatingMode"] = 183] = "FanOperatingMode"; ParameterType2[ParameterType2["TargetAnalogVoltageValue"] = 184] = "TargetAnalogVoltageValue"; ParameterType2[ParameterType2["FanType"] = 185] = "FanType"; ParameterType2[ParameterType2["NightModeTimerSetpoint"] = 770] = "NightModeTimerSetpoint"; ParameterType2[ParameterType2["PartyModeTimerSetPoint"] = 771] = "PartyModeTimerSetPoint"; ParameterType2[ParameterType2["HumiditySensorOverSetPoint"] = 772] = "HumiditySensorOverSetPoint"; ParameterType2[ParameterType2["AnalogVoltageSensorOverSetPoint"] = 773] = "AnalogVoltageSensorOverSetPoint"; return ParameterType2; })(ParameterType || {}); class OxxifyProtocol { /** * Constructor of the class. */ constructor() { this.internalBuffer[0] = 253; this.internalBuffer[1] = 253; this.internalBuffer[2] = 2; this.internalBuffer[3] = 16; this.nWriteIndex = 4; this.FillstateDictionary(); } /** * Starts a new protocol frame by resetting internal variables and performing some input data checks. * * @param strFanId The unique fan id, for which the protocol frame is built. * @param strPassword The password of the fan, which is necessary for the frame to be processed. * @returns True if successful, otherwise false. */ StartNewFrame(strFanId, strPassword) { if (strFanId.length != 16) { return false; } if (strPassword.length <= 0) { return false; } this.nWriteIndex = 4; this.internalBuffer.write(strFanId, this.nWriteIndex); this.nWriteIndex += strFanId.length; this.internalBuffer[this.nWriteIndex] = strPassword.length; this.nWriteIndex++; this.internalBuffer.write(strPassword, this.nWriteIndex); this.nWriteIndex += strPassword.length; this.eCurrentFunction = 0 /* Undefined */; this.bIsFirstFunction = true; this.nCurrentWriteHighByte = 0; return true; } /** * Finishs the created protocol frame by calculating the checksum and appending it to the protocol data accoring to the protocol definition. * */ FinishFrame() { const checksum = this.CalculateChecksum(this.internalBuffer.subarray(2, this.nWriteIndex)); this.internalBuffer[this.nWriteIndex] = checksum & 255; this.nWriteIndex++; this.internalBuffer[this.nWriteIndex] = checksum >> 8; this.nWriteIndex++; } ////////////////////////////////////////////////////////////////////////////////////////////// /** * Adds a request to read the current fan on/off state. */ ReadFanState() { this.AddFunctionCode(1 /* Read */); this.AddParameter(1 /* FanState */); } /** * Add a request to write the fan on/off state. * * @param bEnabled true to turn the fan on, false to turn it off * @returns The ParameterType for FanState */ WriteFanState(bEnabled) { this.AddFunctionCode(3 /* WriteRead */); const data = Buffer.alloc(1); if (bEnabled) { data[0] = 1; } else { data[0] = 0; } this.AddParameter(1 /* FanState */, data); return 1 /* FanState */; } /** * Request the current fan speed mode value from the device. */ ReadFanSpeedMode() { this.AddFunctionCode(1 /* Read */); this.AddParameter(2 /* FanSpeedMode */); } /** * Add a request to write the fan speed mode. * * @param strValue String representation of the fan speed mode * @returns The ParameterType for FanSpeedMode */ WriteFanSpeedMode(strValue) { this.AddFunctionCode(3 /* WriteRead */); const data = Buffer.alloc(1); data[0] = this.ParseFanSpeedModeEnum(strValue); console.log(`Data in Buffer: ${data[0]}`); this.AddParameter(2 /* FanSpeedMode */, data); return 2 /* FanSpeedMode */; } /** * Request the current boost state from the device. */ ReadBoostState() { this.AddFunctionCode(1 /* Read */); this.AddParameter(6 /* BoostState */); } /** * Request both timer mode and its countdown from the device. */ ReadTimerModeValues() { this.AddFunctionCode(1 /* Read */); this.AddParameter(7 /* TimerMode */); this.AddParameter(11 /* TimerCountdown */); } /** * Add a request to set the timer mode. * * @param strValue Timer mode string (e.g., "off", "nightMode", "partyMode") * @returns The ParameterType for TimerMode */ WriteTimerMode(strValue) { this.AddFunctionCode(3 /* WriteRead */); const data = Buffer.alloc(1); data[0] = this.ParseTimerModeEnum(strValue); this.AddParameter(7 /* TimerMode */, data); return 7 /* TimerMode */; } /** * Request the current humidity sensor enabled/disabled state. */ ReadHumiditySensorState() { this.AddFunctionCode(1 /* Read */); this.AddParameter(15 /* StateHumiditySensor */); } /** * Add a request to enable/disable the humidity sensor on the fan. * * @param bEnabled true to enable, false to disable * @returns The ParameterType for StateHumiditySensor */ WriteHumiditySensorState(bEnabled) { this.AddFunctionCode(3 /* WriteRead */); const data = Buffer.alloc(1); if (bEnabled) { data[0] = 1; } else { data[0] = 0; } this.AddParameter(15 /* StateHumiditySensor */, data); return 15 /* StateHumiditySensor */; } /** * Request the current relay sensor state. */ ReadRelaisSensorState() { this.AddFunctionCode(1 /* Read */); this.AddParameter(20 /* StateRelaisSensor */); } /** * Add a request to enable/disable the relay sensor. * * @param bEnabled true to enable, false to disable * @returns The ParameterType for StateRelaisSensor */ WriteRelaisSensorState(bEnabled) { this.AddFunctionCode(3 /* WriteRead */); const data = Buffer.alloc(1); if (bEnabled) { data[0] = 1; } else { data[0] = 0; } this.AddParameter(20 /* StateRelaisSensor */, data); return 20 /* StateRelaisSensor */; } /** * Request the current analog voltage sensor enabled/disabled state. */ ReadAnalogVoltageSensorState() { this.AddFunctionCode(1 /* Read */); this.AddParameter(22 /* StateAnalogVoltageSensor */); } /** * Add a request to enable/disable the analog voltage sensor. * * @param bEnabled true to enable, false to disable * @returns The ParameterType for StateAnalogVoltageSensor */ WriteAnalogVoltageSensorState(bEnabled) { this.AddFunctionCode(3 /* WriteRead */); const data = Buffer.alloc(1); if (bEnabled) { data[0] = 1; } else { data[0] = 0; } this.AddParameter(22 /* StateAnalogVoltageSensor */, data); return 22 /* StateAnalogVoltageSensor */; } /** * Request the configured target humidity setpoint from the fan. */ ReadTargetHumidityValue() { this.AddFunctionCode(1 /* Read */); this.AddParameter(25 /* TargetHumidityValue */); } /** * Add a request to set the target humidity value. * * @param nValue Numeric humidity setpoint * @returns The ParameterType for TargetHumidityValue */ WriteTargetHumidityValue(nValue) { this.AddFunctionCode(3 /* WriteRead */); const data = Buffer.alloc(1); data[0] = nValue; this.AddParameter(25 /* TargetHumidityValue */, data); return 25 /* TargetHumidityValue */; } /** * Request the current RTC battery voltage from the fan. */ ReadRtcBattery() { this.AddFunctionCode(1 /* Read */); this.AddParameter(36 /* RtcBatteryVoltage */); } /** * Request the current humidity sensor reading from the fan. */ ReadCurrentHumidity() { this.AddFunctionCode(1 /* Read */); this.AddParameter(37 /* CurrentHumidityValue */); } /** * Request the current analog voltage reading from the fan. */ ReadCurrentAnalogVoltage() { this.AddFunctionCode(1 /* Read */); this.AddParameter(45 /* CurrentAnalogVoltageValue */); } /** * Request the current relay sensor reading from the fan. */ ReadCurrentRelaisState() { this.AddFunctionCode(1 /* Read */); this.AddParameter(50 /* CurrentRelaisValue */); } /** * Request the current manual fan speed setting. */ ReadManualFanSpeed() { this.AddFunctionCode(1 /* Read */); this.AddParameter(68 /* ManualFanSpeed */); } /** * Add a request to set the manual fan speed. * * @param nValue Numeric speed value * @returns The ParameterType for ManualFanSpeed */ WriteManualFanSpeed(nValue) { this.AddFunctionCode(3 /* WriteRead */); const data = Buffer.alloc(1); data[0] = nValue; this.AddParameter(68 /* ManualFanSpeed */, data); return 68 /* ManualFanSpeed */; } /** * Request fan #1 speed (RPM). */ ReadFan1Speed() { this.AddFunctionCode(1 /* Read */); this.AddParameter(74 /* FanSpeedFan1Rpm */); } /** * Request fan #2 speed (RPM). */ ReadFan2Speed() { this.AddFunctionCode(1 /* Read */); this.AddParameter(75 /* FanSpeedFan2Rpm */); } /** * Request the filter exchange countdown timer value. */ ReadFilterExchangeCountdown() { this.AddFunctionCode(1 /* Read */); this.AddParameter(100 /* FilterExchangeCountdown */); } /** * Add a request to reset the filter exchange countdown on the device. */ WriteResetFilterExchangeCountdown() { this.AddFunctionCode(3 /* WriteRead */); const resetByte = Buffer.alloc(1); resetByte[0] = 255; this.AddParameter(101 /* ResetFilterExchangeCountdown */, resetByte); } /** * Request the boost follow-up time value (in minutes). */ ReadBoostModeFollowUpTime() { this.AddFunctionCode(1 /* Read */); this.AddParameter(102 /* BoostModeFollowUpTime */); } /** * Add a request to set the boost follow-up time. * * @param nValue Number of minutes for boost follow-up * @returns The ParameterType for BoostModeFollowUpTime */ WriteBoostModeFollowUpTime(nValue) { this.AddFunctionCode(3 /* WriteRead */); const data = Buffer.alloc(1); data[0] = nValue; this.AddParameter(102 /* BoostModeFollowUpTime */, data); return 102 /* BoostModeFollowUpTime */; } /** * Request the current RTC date/time from the fan. */ ReadRtcDateTime() { this.AddFunctionCode(1 /* Read */); this.AddParameter(111 /* RtcTime */); this.AddParameter(112 /* RtcDate */); } /** * Add a request to write the RTC date/time to the fan. * * @param dateTime Date object to be written to the device * @returns True if the constructed frame was valid, otherwise false */ WriteRtcDateTime(dateTime) { this.AddFunctionCode(3 /* WriteRead */); const rtcTime = Buffer.alloc(3); rtcTime[0] = dateTime.getSeconds(); rtcTime[1] = dateTime.getMinutes(); rtcTime[2] = dateTime.getHours(); const rtcDate = Buffer.alloc(4); rtcDate[0] = dateTime.getDate(); rtcDate[1] = dateTime.getDay(); rtcDate[2] = dateTime.getMonth() + 1; rtcDate[3] = dateTime.getFullYear() % 100; this.AddParameter(111 /* RtcTime */, rtcTime); this.AddParameter(112 /* RtcDate */, rtcDate); return true; } /** * Request the current time-controlled mode setting from the fan. */ ReadTimeControlledMode() { this.AddFunctionCode(1 /* Read */); this.AddParameter(114 /* TimeControlledMode */); } /** * Add a request to enable/disable time-controlled mode. * * @param bEnabled true to enable, false to disable * @returns The ParameterType for TimeControlledMode */ WriteTimeControlledMode(bEnabled) { this.AddFunctionCode(3 /* WriteRead */); const data = Buffer.alloc(1); if (bEnabled) { data[0] = 1; } else { data[0] = 0; } this.AddParameter(114 /* TimeControlledMode */, data); return 114 /* TimeControlledMode */; } /** * Request the accumulated operating time from the fan. */ ReadOperatingTime() { this.AddFunctionCode(1 /* Read */); this.AddParameter(126 /* OperatingTime */); } /** * Request the current alarm/warning state from the device. */ ReadAlarmState() { this.AddFunctionCode(1 /* Read */); this.AddParameter(131 /* AlarmState */); } /** * Add a request to reset alarms on the fan. */ WriteResetAlarmState() { this.AddFunctionCode(3 /* WriteRead */); const resetAlarmByte = Buffer.alloc(1); resetAlarmByte[0] = 255; this.AddParameter(128 /* ResetAlarms */, resetAlarmByte); } /** * Request whether the cloud server functionality is enabled. */ ReadCloudServerEnabled() { this.AddFunctionCode(1 /* Read */); this.AddParameter(133 /* CloudServerEnabled */); } /** * Request the firmware version and build date from the fan. */ ReadFirmware() { this.AddFunctionCode(1 /* Read */); this.AddParameter(134 /* FirmwareVersionAndDate */); } /** * Request whether a filter exchange is necessary. */ ReadFilterExchangeNecessary() { this.AddFunctionCode(1 /* Read */); this.AddParameter(136 /* FilterExchangeNecessary */); } /** * Request the WiFi related configuration and status values from the fan. */ ReadWifiData() { this.AddFunctionCode(1 /* Read */); this.AddParameter(148 /* WifiOperatingMode */); this.AddParameter(149 /* WifiName */); this.AddParameter(150 /* WifiPassword */); this.AddParameter(153 /* WifiEncryptionMode */); this.AddParameter(154 /* WifiChannel */); this.AddParameter(155 /* WifiIpMode */); this.AddParameter(156 /* WifiIp */); this.AddParameter(157 /* WifiSubnetMask */); this.AddParameter(158 /* WifiGateway */); this.AddParameter(163 /* CurrentWifiIp */); } /** * Request the current operating mode of the fan (ventilation/heatRecovery/supplyAir). */ ReadOperatingMode() { this.AddFunctionCode(1 /* Read */); this.AddParameter(183 /* FanOperatingMode */); } /** * Add a request to set the fan's operating mode. * * @param strValue Operating mode string (e.g., "ventilation", "heatRecovery", "supplyAir") * @returns The ParameterType for FanOperatingMode */ WriteOperatingMode(strValue) { this.AddFunctionCode(3 /* WriteRead */); const data = Buffer.alloc(1); data[0] = this.ParseOperatingModeEnum(strValue); this.AddParameter(183 /* FanOperatingMode */, data); return 183 /* FanOperatingMode */; } /** * Request the configured target analog voltage setpoint. */ ReadTargetAnalogVoltageValue() { this.AddFunctionCode(1 /* Read */); this.AddParameter(184 /* TargetAnalogVoltageValue */); } /** * Add a request to set the target analog voltage value. * * @param nValue Numeric target voltage value * @returns The ParameterType for TargetAnalogVoltageValue */ WriteTargetAnalogVoltageValue(nValue) { this.AddFunctionCode(3 /* WriteRead */); const data = Buffer.alloc(1); data[0] = nValue; this.AddParameter(184 /* TargetAnalogVoltageValue */, data); return 184 /* TargetAnalogVoltageValue */; } /** * Request the fan hardware/type identifier. */ ReadFanType() { this.AddFunctionCode(1 /* Read */); this.AddParameter(185 /* FanType */); } /** * Request the night mode timer setpoint value. */ ReadNightModeTimerSetPoint() { this.AddFunctionCode(1 /* Read */); this.AddParameter(770 /* NightModeTimerSetpoint */); } /** * Add a request to set the night mode timer setpoint. * * @param strTimeValue Time string in format "HH:MM" * @returns The ParameterType for NightModeTimerSetpoint */ WriteNightModeTimerSetPoint(strTimeValue) { const [nHours, nMinutes] = strTimeValue.split(":").map(Number); const data = Buffer.alloc(2); data[0] = nMinutes; data[1] = nHours; this.AddFunctionCode(3 /* WriteRead */); this.AddParameter(770 /* NightModeTimerSetpoint */, data); return 770 /* NightModeTimerSetpoint */; } /** * Request the party mode timer setpoint value. */ ReadPartyModeTimerSetPoint() { this.AddFunctionCode(1 /* Read */); this.AddParameter(771 /* PartyModeTimerSetPoint */); } /** * Add a request to set the party mode timer setpoint. * * @param strTimeValue Time string in format "HH:MM" * @returns The ParameterType for PartyModeTimerSetPoint */ WritePartyModeTimerSetPoint(strTimeValue) { const [nHours, nMinutes] = strTimeValue.split(":").map(Number); const data = Buffer.alloc(2); data[0] = nMinutes; data[1] = nHours; this.AddFunctionCode(3 /* WriteRead */); this.AddParameter(771 /* PartyModeTimerSetPoint */, data); return 771 /* PartyModeTimerSetPoint */; } /** * Request the humidity sensor over-setpoint configuration value. */ ReadHumiditySensorOverSetPoint() { this.AddFunctionCode(1 /* Read */); this.AddParameter(772 /* HumiditySensorOverSetPoint */); } /** * Request the analog voltage sensor over-setpoint configuration value. */ ReadAnalogVoltageSensorOverSetPoint() { this.AddFunctionCode(1 /* Read */); this.AddParameter(773 /* AnalogVoltageSensorOverSetPoint */); } ////////////////////////////////////////////////////////////////////////////////////////////// /** * The currently constructed protocol packet buffer (only the written portion). * * @returns Buffer containing the frame ready to be sent */ get ProtocolPacket() { return Buffer.from(this.internalBuffer.subarray(0, this.nWriteIndex)); } /** * Parse a complete response frame from the fan and return structured parsed data. * * @param dataBytes Raw buffer bytes received from the fan * @returns ParsedData containing fan id, status and extracted datapoints */ ParseResponseData(dataBytes) { var _a; dataBytes = this.PreprocessData(dataBytes); const status = this.CheckProtocol(dataBytes); const result = new import_ModelData.ParsedData(); this.nCurrentReadHighByte = 0; if (dataBytes == void 0) { result.status = import_ModelData.ParsingStatus.Undefined; return result; } this.nReadIndex = 4; result.strFanId = dataBytes.subarray(this.nReadIndex, this.nReadIndex + 16).toString(); this.nReadIndex += 16; this.nReadIndex += (_a = dataBytes.at(this.nReadIndex)) != null ? _a : 0; this.nReadIndex++; let bIsDataToRead = false; if (dataBytes.at(this.nReadIndex) == 6 /* Response */) { bIsDataToRead = true; } result.bFrameIsResponse = bIsDataToRead; if (status != import_ModelData.ParsingStatus.Ok) { result.status = status; return result; } this.nReadIndex++; if (bIsDataToRead) { while (this.nReadIndex < dataBytes.length - 2) { this.nReadIndex += this.ParseData(dataBytes.subarray(this.nReadIndex), result.receivedData); } result.status = import_ModelData.ParsingStatus.Ok; return result; } result.status = import_ModelData.ParsingStatus.Undefined; return result; } /** * Preprocess raw incoming buffer to trim any preceding data before the second frame marker. * The protocol uses 0xFD 0xFD markers; this returns the buffer starting at the second marker. * * @param dataBytes Raw buffer received from the socket * @returns Trimmed buffer starting at the second marker or the original buffer if markers not found */ PreprocessData(dataBytes) { const marker = Buffer.from([253, 253]); const first = dataBytes.indexOf(marker); if (first === -1) { return dataBytes; } const second = dataBytes.indexOf(marker, first + 2); if (second === -1) { return dataBytes; } return dataBytes.subarray(0, second); } /** * Parse a single parameter block from a response frame and append any parsed datapoint to receivedData. * * @param data Buffer at the current read position (starts with parameter metadata) * @param receivedData Array to push parsed IoBrokerDataPoint instances into * @returns Number of bytes consumed for this parameter (to advance the read index) */ ParseData(data, receivedData) { var _a, _b, _c, _d, _e; let nIndex = 0; let nCurrentReadParameterSize = 1; if (data.at(nIndex) == 255) { nIndex++; this.nCurrentReadHighByte = (_a = data.at(nIndex)) != null ? _a : 0; nIndex++; } switch (data.at(nIndex)) { // Change response size case 254: nIndex++; nCurrentReadParameterSize = (_b = data.at(nIndex)) != null ? _b : 1; nIndex++; break; // Not supported low byte case 253: nIndex++; nIndex++; break; } const eParameter = ((_c = data.at(nIndex)) != null ? _c : 0) | this.nCurrentReadHighByte << 8; nIndex++; if (this.stateDictionary.has(eParameter)) { const fanData = this.stateDictionary.get(eParameter); if (fanData != void 0) { const parsedData = new import_ModelData.IoBrokerDataPoint(); parsedData.strIdentifer = (_d = fanData == null ? void 0 : fanData.strIdentifer) != null ? _d : "UNDEFINED"; parsedData.value = (_e = fanData == null ? void 0 : fanData.parseFunction(data.subarray(nIndex, nIndex + nCurrentReadParameterSize))) != null ? _e : null; receivedData.push(parsedData); } } const nReturnIndex = nIndex + nCurrentReadParameterSize; return nReturnIndex; } /** * Returns the parameter dictionary, which contains all available data endpoints with the necessary * meta-data to create the states within the object tree. */ get StateDictionary() { return this.stateDictionary; } static FanFolder = "fan"; static NetworkFolder = "network"; static SensorsFolder = "sensors"; static SystemFolder = "system"; //#region Protected data members internalBuffer = Buffer.alloc(256); nWriteIndex = 0; nReadIndex = 0; nCurrentReadHighByte = 0; nCurrentWriteHighByte = 0; bIsFirstFunction = false; eCurrentFunction = 0 /* Undefined */; // Dictionary with all available parametetrs and the index word as key (High and low byte) stateDictionary = /* @__PURE__ */ new Map(); //#endregion /** * Validate basic protocol structure of a received buffer (header, version, id size and checksum). * * @param dataBuffer The received buffer to validate * @returns ParsingStatus.Ok when valid or the specific error status otherwise */ CheckProtocol(dataBuffer) { if (dataBuffer.at(0) != 253 && dataBuffer.at(1) != 253) { return import_ModelData.ParsingStatus.WrongHeader; } if (dataBuffer.at(2) != 2) { return import_ModelData.ParsingStatus.WrongVersion; } if (dataBuffer.at(3) != 16) { return import_ModelData.ParsingStatus.WrongIdSize; } const nCalculatedChecksum = this.CalculateChecksum(dataBuffer.subarray(2, dataBuffer.length - 2)); const nReceivedChecksum = dataBuffer[dataBuffer.length - 2] + (dataBuffer[dataBuffer.length - 1] << 8); if (nCalculatedChecksum != nReceivedChecksum) { return import_ModelData.ParsingStatus.ChecksumError; } return import_ModelData.ParsingStatus.Ok; } /** * Add or switch the current function code in the outgoing frame. * The protocol expects a function code byte before parameters; when changing function type a separator (0xFC) * is written to the buffer. Duplicate insertion is avoided when the same function is already set. * * @param eNextFunction Next function type to set */ AddFunctionCode(eNextFunction) { if (this.bIsFirstFunction) { this.bIsFirstFunction = false; } else { if (eNextFunction == this.eCurrentFunction) { return; } this.internalBuffer[this.nWriteIndex] = 252; this.nWriteIndex++; } this.internalBuffer[this.nWriteIndex] = eNextFunction; this.nWriteIndex++; this.eCurrentFunction = eNextFunction; } /** * Adds an parameter for an read or an write request. * * @param eParameter The predefined enum value for the parameter, which is also teh relevant low-byte of the adressed data. * @param bytes The bytes to write in a Write / WriteRead request. Null in case of an read request. * @returns True if successful, otherwise false. */ AddParameter(eParameter, bytes = null) { var _a; const parameterData = this.stateDictionary.get(eParameter); if (parameterData == void 0) { return false; } const nHighByte = (Number(eParameter) & 65280) >> 8; const bChangeHighByte = nHighByte != this.nCurrentWriteHighByte; if (bChangeHighByte) { this.nCurrentWriteHighByte = nHighByte; this.internalBuffer[this.nWriteIndex] = 255; this.nWriteIndex++; this.internalBuffer[this.nWriteIndex] = nHighByte; this.nWriteIndex++; } if (parameterData.nSize != 1) { if (this.eCurrentFunction != 1 /* Read */) { this.internalBuffer[this.nWriteIndex] = 254; this.nWriteIndex++; this.internalBuffer[this.nWriteIndex] = parameterData.nSize; this.nWriteIndex++; } } this.internalBuffer[this.nWriteIndex] = eParameter; this.nWriteIndex++; if (this.eCurrentFunction == 3 /* WriteRead */) { if (bytes == null) { return false; } if (bytes.length == 1) { this.internalBuffer.writeUint8((_a = bytes.at(0)) != null ? _a : 0, this.nWriteIndex); } else { this.internalBuffer.write(bytes.toString(), this.nWriteIndex); } this.nWriteIndex += bytes.length; } return true; } /** * Calculate a 16-bit checksum by summing all bytes. * * @param bytes Array of bytes to include in the checksum * @returns 16-bit checksum value */ CalculateChecksum(bytes) { let checksum = 0; for (let i = 0; i < bytes.length; i++) { checksum += bytes[i]; } return checksum & 65535; } /** * Parse firmware version and date bytes into a readable string. * * @param bytes Buffer containing firmware/version bytes * @returns Formatted string like "v<major>.<minor> - <day>.<month>.<year>" */ ParseFirmware(bytes) { var _a, _b; const nYear = ((_a = bytes.at(4)) != null ? _a : 0) + (((_b = bytes.at(5)) != null ? _b : 0) << 8); return `v${bytes.at(0)}.${bytes.at(1)} - ${bytes.at(2)}.${bytes.at(3)}.${nYear}`; } /** * Parse a boolean value from a single byte. * * @param byte Buffer containing the boolean byte (0 = false, 1 = true) * @returns boolean or null if unknown */ ParseBool(byte) { var _a; switch ((_a = byte.at(0)) != null ? _a : 255) { case 0: return false; case 1: return true; default: break; } return null; } /** * Parse a single byte buffer into an ioBroker state value (number). * * @param byte Buffer containing a single byte * @returns The numeric value of the byte or null when not available */ ParseByteNumber(byte) { var _a; return (_a = byte.at(0)) != null ? _a : null; } /** * Parse a two-byte buffer (word) into an ioBroker state value (number). * * @param bytes Buffer containing two bytes (little-endian) * @returns The numeric value represented by the two bytes */ ParseWordNumber(bytes) { var _a, _b; return ((_a = bytes.at(0)) != null ? _a : 0) | ((_b = bytes.at(1)) != null ? _b : 0) << 8; } /** * Parse a timer mode byte into a string representation. * * @param byte Buffer containing the timer mode byte * @returns One of: "off", "nightMode", "partyMode" or null when unknown */ ParseTimerMode(byte) { var _a; switch ((_a = byte.at(0)) != null ? _a : 255) { case 0: return "off"; case 1: return "nightMode"; case 2: return "partyMode"; } return null; } /** * Convert a timer mode string to its numeric enum value. * * @param strEnum The timer mode string ("off", "nightMode", "partyMode") * @returns Numeric representation of the timer mode */ ParseTimerModeEnum(strEnum) { switch (strEnum) { case "off": return 0; case "nightMode": return 1; case "partyMode": return 2; } return 0; } /** * Parse the fan speed mode byte into a string representation. * * @param byte Buffer containing the fan speed mode byte * @returns A string like "ventilationLevel1".."ventilationLevel3" or "ventilationLevelManual" */ ParseFanSpeedMode(byte) { var _a; switch ((_a = byte.at(0)) != null ? _a : 255) { case 1: return "ventilationLevel1"; case 2: return "ventilationLevel2"; case 3: return "ventilationLevel3"; case 255: return "ventilationLevelManual"; } return null; } /** * Convert a fan speed mode string into its numeric enum value. * * @param strEnum One of the fan speed strings. * @returns Numeric value used by the protocol for the given speed mode */ ParseFanSpeedModeEnum(strEnum) { switch (strEnum) { case "ventilationLevel1": return 1; case "ventilationLevel2": return 2; case "ventilationLevel3": return 3; case "ventilationLevelManual": return 255; } return 1; } /** * Convert a small time buffer [sec, min, hour] into a HH:MM:SS string. * * @param bytes Buffer with at least 3 bytes representing seconds, minutes and hours * @returns Time formatted as "HH:MM:SS" */ ParseTimeSmallToLarge(bytes) { var _a, _b, _c; return `${(_a = bytes.at(2)) == null ? void 0 : _a.toString().padStart(2, "0")}:${(_b = bytes.at(1)) == null ? void 0 : _b.toString().padStart(2, "0")}:${(_c = bytes.at(0)) == null ? void 0 : _c.toString().padStart(2, "0")}`; } /** * Parse RTC date bytes into a human readable string. * Expected format in buffer: [day, weekday, month, year] * * @param bytes Buffer with date bytes * @returns Formatted date string like "DD.MM.YY (weekday)" */ ParseRtcDate(bytes) { var _a, _b, _c; return `${(_a = bytes.at(0)) == null ? void 0 : _a.toString().padStart(2, "0")}.${(_b = bytes.at(2)) == null ? void 0 : _b.toString().padStart(2, "0")}.${(_c = bytes.at(3)) == null ? void 0 : _c.toString().padStart(2, "0")} (${bytes.at(1)} day of the week)`; } /** * Parse operating time bytes into a formatted string. * * @param bytes Buffer where bytes represent [seconds, minutes, hours_low, hours_high] * @returns Formatted string like "HH:MM:SS" where hours may be >255 */ ParseOperatingTime(bytes) { var _a, _b, _c, _d; return `${((_a = bytes.at(2)) != null ? _a : 0) | ((_b = bytes.at(3)) != null ? _b : 0) << 8}:${(_c = bytes.at(1)) == null ? void 0 : _c.toString().padStart(2, "0")}:${(_d = bytes.at(0)) == null ? void 0 : _d.toString().padStart(2, "0")}`; } /** * Parse alarm/warning state from a byte and return a human readable string. * * @param byte Buffer containing the alarm state byte * @returns String describing the alarm state or null if unknown */ ParseAlarmWarningState(byte) { var _a; switch ((_a = byte.at(0)) != null ? _a : 255) { case 0: return "0 - Nothing"; case 1: return "1 - Alarm (highest priority)"; case 2: return "2 - Warning"; } return null; } /** * Parse the WiFi operating mode byte into a human readable string. * * @param byte Buffer containing the wifi mode byte * @returns "1 - Client" or "2 - Access Point" or null when unknown */ ParseWifiMode(byte) { var _a; switch ((_a = byte.at(0)) != null ? _a : 255) { case 1: return "1 - Client"; case 2: return "2 - Access Point"; } return null; } /** * Parse a text buffer into a string. * * @param bytes Buffer containing text data * @returns Decoded string */ ParseText(bytes) { return bytes.toString(); } /** * Parse WiFi encryption mode byte into a human readable description. * * @param byte Buffer containing the encryption mode byte * @returns Description string or null when unknown */ ParseWifiEncryptionMode(byte) { var _a; switch ((_a = byte.at(0)) != null ? _a : 255) { case 48: return "48 - Open/not encrypted"; case 50: return "50 - WPA PSK"; case 51: return "51 - WPA2 PSK"; case 52: return "52 - WPA/WPA2 PSK"; } return null; } /** * Parse WiFi IP mode byte into a human readable string. * * @param byte Buffer containing the IP mode byte * @returns "0 - Static IP" or "1 - DHCP" or null when unknown */ ParseWifiIpMode(byte) { var _a; switch ((_a = byte.at(0)) != null ? _a : 255) { case 0: return "0 - Static IP"; case 1: return "1 - DHCP"; } return null; } /** * Parse 4 bytes into an IPv4 dotted string. * * @param bytes Buffer with 4 bytes for IPv4 * @returns IPv4 address string */ ParseIpV4Value(bytes) { return `${bytes.at(0)}.${bytes.at(1)}.${bytes.at(2)}.${bytes.at(3)}`; } /** * Parse the operating mode byte into a descriptive string. * * @param byte Buffer containing the operating mode byte * @returns "ventilation", "heatRecovery", "supplyAir" or null when unknown */ ParseOperatingMode(byte) { var _a; switch ((_a = byte.at(0)) != null ? _a : 255) { case 0: return "ventilation"; case 1: return "heatRecovery"; case 2: return "supplyAir"; } return null; } /** * Convert an operating mode string into its numeric protocol value. * * @param strEnum One of the operating mode strings * @returns Numeric value used by the protocol */ ParseOperatingModeEnum(strEnum) { switch (strEnum) { case "ventilation": return 0; case "heatRecovery": return 1; case "supplyAir": return 2; } return 0; } /** * Parse the system type byte(s) to a readable description. * * @param bytes Buffer containing system type bytes * @returns Human readable description or null if unknown */ ParseSystemType(bytes) { var _a; switch ((_a = bytes.at(0)) != null ? _a : 255) { case 14: return "14 - Oxxify.smart 50"; } return null; } /** * Parse hour/minute timer bytes into a HH:MM string. * * @param bytes Buffer where bytes[1] = hours and bytes[0] = minutes * @returns Formatted string "HH:MM" */ ParseHourMinuteTimer(bytes) { var _a, _b; return `${(_a = bytes.at(1)) == null ? void 0 : _a.toString().padStart(2, "0")}:${(_b = bytes.at(0)) == null ? void 0 : _b.toString().padStart(2, "0")}`; } /** * Parser that intentionally returns no value (used for parameters without readable data). * * @param _ Ignored buffer * @returns Always null */ ParseNothing(_) { return null; } /** * Populate the internal state dictionary with metadata describing each parameter supported by the protocol. * Each entry maps a ParameterType to a FanData instance describing size, identifier, read/write flags, role, * type, localized names and a parser function. */ FillstateDictionary() { this.stateDictionary.set( 1 /* FanState */, new import_ModelData.FanData( 1, `${OxxifyProtocol.FanFolder}.fanState`, true, true, "switch", "boolean", { en: "Fan On/Off", de: "L\xFCfter ein/aus", ru: "\u0412\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435/\u0432\u044B\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435 \u0432\u0435\u043D\u0442\u0438\u043B\u044F\u0442\u043E\u0440\u0430", pt: "Ventilador ligado/desligado", nl: "Ventilator aan/uit", fr: "Ventilateur Marche/Arr\xEAt", it: "Ventola accesa/spenta", es: "Ventilador On/Off", pl: "Wentylator w\u0142.", uk: "\u0423\u0432\u0456\u043C\u043A\u043D\u0435\u043D\u043D\u044F/\u0432\u0438\u043C\u043A\u043D\u0435\u043D\u043D\u044F \u0432\u0435\u043D\u0442\u0438\u043B\u044F\u0442\u043E\u0440\u0430", "zh-cn": "Fan On/Off" }, this.ParseBool ) ); this.stateDictionary.set( 2 /* FanSpeedMode */, new import_ModelData.FanData( 1, `${OxxifyProtocol.FanFolder}.fanSpeedMode`, true, true, "state", "string", { en: "Number of the ventilation level", de: "Nummer der L\xFCftungsstufe", ru: "\u041D\u043E\u043C\u0435\u0440 \u0443\u0440\u043E\u0432\u043D\u044F \u0432\u0435\u043D\u0442\u0438\u043B\u044F\u0446\u0438\u0438", pt: "N\xFAmero do n\xEDvel de ventila\xE7\xE3o", nl: "Nummer van het ventilatieniveau", fr: "Num\xE9ro du niveau de ventilation", it: "Numero del livello di ventilazione", es: "N\xFAmero del nivel de ventilaci\xF3n", pl: "Numer poziomu wentylacji", uk: "\u041D\u043E\u043C\u0435\u0440 \u0440\u0456\u0432\u043D\u044F \u0432\u0435\u043D\u0442\u0438\u043B\u044F\u0446\u0456\u0457", "zh-cn": "Number of the ventilation level" }, this.ParseFanSpeedMode, void 0, void 0, void 0, { ventilationLevel1: "Ventilation Level 1", ventilationLevel2: "Ventilation Level 2", ventilationLevel3: "Ventilation Level 3", ventilationLevelManual: "Manual ventilation level" } ) ); this.stateDictionary.set( 6 /* BoostState */, new import_ModelData.FanData( 1, `${OxxifyProtocol.FanFolder}.boostState`, true, false, "sensor.switch", "boolean", { en: "Boost operating status on/off", de: "Boost-Betriebszustand ein/aus", ru: "\u0412\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435/\u0432\u044B\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435 \u0440\u0435\u0436\u0438\u043C\u0430 \u0440\u0430\u0431\u043E\u0442\u044B \u0431\u0443\u0441\u0442\u0430", pt: "Estado de funcionamento do Boost ligado/desligado", nl: "Bedrijfsstatus boost aan/uit", fr: "Activation/d\xE9sactivation de l'\xE9tat de fonctionnement de l'amplificateur", it: "Stato di funzionamento del boost on/off", es: "Estado de funcionamiento del Boost on/off", pl: "W\u0142\u0105czanie/wy\u0142\u0105czanie stanu pracy funkcji Boost", uk: "\u0423\u0432\u0456\u043C\u043A\u043D\u0435\u043D\u043D\u044F/\u0432\u0438\u043C\u043A\u043D\u0435\u043D\u043D\u044F \u0440\u043E\u0431\u043E\u0447\u043E\u0433\u043E \u0441\u0442\u0430\u043D\u0443 \u043F\u0456\u0434\u0441\u0438\u043B\u044E\u0432\u0430\u0447\u0430", "zh-cn": "Boost operating status on/off" }, this.ParseBool ) ); this.stateDictionary.set( 7 /* TimerMode */, new import_ModelData.FanData( 1, `${OxxifyProtocol.FanFolder}.timerMode`, true, true, "state", "mixed", { en: "Timer mode", de: "Timer-Modus", ru: "\u0420\u0435\u0436\u0438\u043C \u0442\u0430\u0439\u043C\u0435\u0440\u0430", pt: "Modo de temporizador", nl: "Timermodus", fr: "Mode minuterie", it: "Modalit\xE0 timer", es: "Modo temporizador", pl: "Tryb timera", uk: "\u0420\u0435\u0436\u0438\u043C \u0442\u0430\u0439\u043C\u0435\u0440\u0430", "zh-cn": "Timer mode" }, this.ParseTimerMode, void 0, void 0, void 0, { off: "Off", nightMode: "Night Mode", partyMode: "Party Mode" } ) ); this.stateDictionary.set( 11 /* TimerCountdown */, new import_ModelData.FanData( 3, `${OxxifyProtocol.FanFolder}.timerCountDown`, true, false, "state", "string", { en: "Current countdown of the timer operation", de: "Aktueller Countdown des Timerbetriebs", ru: "\u0422\u0435\u043A\u0443\u0449\u0438\u0439 \u043E\u0442\u0441\u0447\u0435\u0442 \u0432\u0440\u0435\u043C\u0435\u043D\u0438 \u0440\u0430\u0431\u043E\u0442\u044B \u0442\u0430\u0439\u043C\u0435\u0440\u0430", pt: "Contagem decrescente atual da opera\xE7\xE3o do temporizador", nl: "Huidig aftellen van de timer", fr: "Compte \xE0 rebours actuel de l'op\xE9ration de minuterie", it: "Conto alla rovescia corrente del funzionamento del timer", es: "Cuenta atr\xE1s actual de la operaci\xF3n del temporizador", pl: "Bie\u017C\u0105ce odliczanie operacji timera", uk: "\u041F\u043E\u0442\u043E\u0447\u043D\u0438\u0439 \u0432\u0456\u0434\u043B\u0456\u043A \u0440\u043E\u0431\u043E\u0442\u0438 \u0442\u0430\u0439\u043C\u0435\u0440\u0430", "zh-cn": "Current countdown of the timer operation" }, this.ParseTimeSmallToLarge, "hh:mm:ss" ) ); this.stateDictionary.set( 15 /* StateHumiditySensor */, new import_ModelData.FanData( 1, `${OxxifyProtocol.SensorsFolder}.stateHumiditySensor`, true, true, "switch", "boolean", { en: "Status of the humidity sensor on/off", de: "Status des Feuchtigkeitssensors ein/aus", ru: "\u0421\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0434\u0430\u0442\u0447\u0438\u043A\u0430 \u0432\u043B\u0430\u0436\u043D\u043E\u0441\u0442\u0438 \u0432\u043A\u043B/\u0432\u044B\u043A\u043B", pt: "Estado do sensor de humidade ligado/desligado", nl: "Status van de vochtigheidssensor aan/uit", fr: "\xC9tat du capteur d'humidit\xE9 activ\xE9/d\xE9sactiv\xE9", it: "Stato del sensore di umidit\xE0 on/off", es: "Estado del sensor de humedad on/off", pl: "Stan w\u0142\u0105czenia/wy\u0142\u0105czenia czujnika wilgotno\u015Bci", uk: "\u0421\u0442\u0430\u043D \u0443\u0432\u0456\u043C\u043A\u043D\u0435\u043D\u043D\u044F/\u0432\u0438\u043C\u043A\u043D\u0435\u043D\u043D\u044F \u0434\u0430\u0442\u0447\u0438\u043A\u0430 \u0432\u043E\u043B\u043E\u0433\u043E\u0441\u0442\u0456", "zh-cn": "Status of the humidity sensor on/off" }, this.ParseBool ) ); this.stateDictionary.set( 20 /* StateRelaisSensor */, new import_ModelData.FanData( 1, `${OxxifyProtocol.SensorsFolder}.stateRelaisSensor`, true, true, "switch", "boolean", { en: "Status of the relay sensor on/off", de: "Status des Relaissensors ein/aus", ru: "\u0421\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0434\u0430\u0442\u0447\u0438\u043A\u0430 \u0440\u0435\u043B\u0435 \u0432\u043A\u043B/\u0432\u044B\u043A\u043B", pt: "Estado do sensor de rel\xE9 ligado/desligado", nl: "Status van de relaissensor aan/uit", fr: "\xC9tat du capteur de relais activ\xE9/d\xE9sactiv\xE9", it: "Stato del sensore a rel\xE8 on/off", es: "Estado del rel\xE9 sensor on/off", pl: "Stan w\u0142\u0105czonego/wy\u0142\u0105czonego czujnika przeka\u017Anika", uk: "\u0421\u0442\u0430\u043D \u0443\u0432\u0456\u043C\u043A\u043D\u0435\u043D\u043E\u0433\u043E/\u0432\u0438\u043C\u043A\u043D\u0435\u043D\u043E\u0433\u043E \u0440\u0435\u043B\u0435\u0439\u043D\u043E\u0433\u043E \u0434\u0430\u0442\u0447\u0438\u043A\u0430", "zh-cn": "Status of the relay sensor on/off" }, this.ParseBool ) ); this.stateDictionary.set( 22 /* StateAnalogVoltageSensor */, new import_ModelData.FanData( 1, `${OxxifyProtocol.SensorsFolder}.stateAnalogVoltageSensor`, true, true, "switch", "boolean", { en: "Status of the analog voltage sensor on/off", de: "Status des analogen Spannungssensors ein/aus", ru: "\u0421\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0430\u043D\u0430\u043B\u043E\u0433\u043E\u0432\u043E\u0433\u043E \u0434\u0430\u0442\u0447\u0438\u043A\u0430 \u043D\u0430\u043F\u0440\u044F\u0436\u0435\u043D\u0438\u044F \u0432\u043A\u043B/\u0432\u044B\u043A\u043B", pt: "Estado do sensor de tens\xE3o anal\xF3gico ligado/desligado", nl: "Status van de analoge spanningssensor aan/uit", fr: "\xC9tat du capteur de tension analogique activ\xE9/d\xE9sactiv\xE9", it: "Stato del sensore di tensione analogico on/off", es: "Estado del sensor anal\xF3gico de tensi\xF3n on/off", pl: "Stan w\u0142\u0105czenia/wy\u0142\u0105czenia analogowego czujnika napi\u0119cia", uk: "\u0421\u0442\u0430\u043D \u0443\u0432\u0456\u043C\u043A\u043D\u0435\u043D