"use strict";
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 (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const exposes = __importStar(require("../lib/exposes"));
const fromZigbee_1 = __importDefault(require("../converters/fromZigbee"));
const toZigbee_1 = __importDefault(require("../converters/toZigbee"));
const reporting = __importStar(require("../lib/reporting"));
const constants = __importStar(require("../lib/constants"));
const e = exposes.presets;
const ea = exposes.access;
const utils_1 = require("../lib/utils");
const modernExtend = __importStar(require("../lib/modernExtend"));
const { forcePowerSource, temperature, humidity, co2, deviceEndpoints, onOff, illuminance, occupancy, ota, } = modernExtend;
const sprutCode = 0x6666;
const manufacturerOptions = { manufacturerCode: sprutCode };
const switchActionValues = ['OFF', 'ON'];
const co2Lookup = {
    co2_autocalibration: 'sprutCO2AutoCalibration',
    co2_manual_calibration: 'sprutCO2Calibration',
};
const fzLocal = {
    temperature: {
        cluster: 'msTemperatureMeasurement',
        type: ['attributeReport', 'readResponse'],
        convert: (model, msg, publish, options, meta) => {
            const temperature = parseFloat(msg.data['measuredValue']) / 100.0;
            return { temperature };
        },
    },
    occupancy_level: {
        cluster: 'msOccupancySensing',
        type: ['readResponse', 'attributeReport'],
        convert: (model, msg, publish, options, meta) => {
            if (msg.data.hasOwnProperty('sprutOccupancyLevel')) {
                return { occupancy_level: msg.data['sprutOccupancyLevel'] };
            }
        },
    },
    voc: {
        cluster: 'sprutVoc',
        type: ['readResponse', 'attributeReport'],
        convert: (model, msg, publish, options, meta) => {
            if (msg.data.hasOwnProperty('voc')) {
                return { voc: msg.data['voc'] };
            }
        },
    },
    noise: {
        cluster: 'sprutNoise',
        type: ['readResponse', 'attributeReport'],
        convert: (model, msg, publish, options, meta) => {
            if (msg.data.hasOwnProperty('noise')) {
                return { noise: msg.data['noise'].toFixed(2) };
            }
        },
    },
    noise_detected: {
        cluster: 'sprutNoise',
        type: ['readResponse', 'attributeReport'],
        convert: (model, msg, publish, options, meta) => {
            if (msg.data.hasOwnProperty('noiseDetected')) {
                return { noise_detected: msg.data['noiseDetected'] === 1 };
            }
        },
    },
    occupancy_timeout: {
        cluster: 'msOccupancySensing',
        type: ['readResponse', 'attributeReport'],
        convert: (model, msg, publish, options, meta) => {
            return { occupancy_timeout: msg.data['pirOToUDelay'] };
        },
    },
    noise_timeout: {
        cluster: 'sprutNoise',
        type: ['readResponse', 'attributeReport'],
        convert: (model, msg, publish, options, meta) => {
            return { noise_timeout: msg.data['noiseAfterDetectDelay'] };
        },
    },
    occupancy_sensitivity: {
        cluster: 'msOccupancySensing',
        type: ['readResponse', 'attributeReport'],
        convert: (model, msg, publish, options, meta) => {
            return { occupancy_sensitivity: msg.data['sprutOccupancySensitivity'] };
        },
    },
    noise_detect_level: {
        cluster: 'sprutNoise',
        type: ['readResponse', 'attributeReport'],
        convert: (model, msg, publish, options, meta) => {
            return { noise_detect_level: msg.data['noiseDetectLevel'] };
        },
    },
    co2_mh_z19b_config: {
        cluster: 'msCO2',
        type: ['attributeReport', 'readResponse'],
        convert: (model, msg, publish, options, meta) => {
            if (msg.data.hasOwnProperty('sprutCO2AutoCalibration')) {
                return { co2_autocalibration: switchActionValues[msg.data['sprutCO2AutoCalibration']] };
            }
            if (msg.data.hasOwnProperty('sprutCO2Calibration')) {
                return { co2_manual_calibration: switchActionValues[msg.data['sprutCO2Calibration']] };
            }
        },
    },
    th_heater: {
        cluster: 'msRelativeHumidity',
        type: ['attributeReport', 'readResponse'],
        convert: (model, msg, publish, options, meta) => {
            if (msg.data.hasOwnProperty('sprutHeater')) {
                return { th_heater: switchActionValues[msg.data['sprutHeater']] };
            }
        },
    },
};
const tzLocal = {
    sprut_ir_remote: {
        key: ['play_store', 'learn_start', 'learn_stop', 'clear_store', 'play_ram', 'learn_ram_start', 'learn_ram_stop'],
        convertSet: async (entity, key, value, meta) => {
            const options = {
                frameType: 0, manufacturerCode: sprutCode, disableDefaultResponse: true,
                disableResponse: true, reservedBits: 0, direction: 0, writeUndiv: false,
                // @ts-expect-error
                transactionSequenceNumber: null,
            };
            switch (key) {
                case 'play_store':
                    await entity.command('sprutIrBlaster', 'playStore', { param: value['rom'] }, options);
                    break;
                case 'learn_start':
                    await entity.command('sprutIrBlaster', 'learnStart', { value: value['rom'] }, options);
                    break;
                case 'learn_stop':
                    await entity.command('sprutIrBlaster', 'learnStop', { value: value['rom'] }, options);
                    break;
                case 'clear_store':
                    await entity.command('sprutIrBlaster', 'clearStore', {}, options);
                    break;
                case 'play_ram':
                    await entity.command('sprutIrBlaster', 'playRam', {}, options);
                    break;
                case 'learn_ram_start':
                    await entity.command('sprutIrBlaster', 'learnRamStart', {}, options);
                    break;
                case 'learn_ram_stop':
                    await entity.command('sprutIrBlaster', 'learnRamStop', {}, options);
                    break;
            }
        },
    },
    occupancy_timeout: {
        key: ['occupancy_timeout'],
        convertSet: async (entity, key, value, meta) => {
            const number = (0, utils_1.toNumber)(value, 'occupancy_timeout');
            await entity.write('msOccupancySensing', { pirOToUDelay: number }, (0, utils_1.getOptions)(meta.mapped, entity));
            return { state: { [key]: number } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read('msOccupancySensing', ['pirOToUDelay']);
        },
    },
    noise_timeout: {
        key: ['noise_timeout'],
        convertSet: async (entity, key, value, meta) => {
            let number = (0, utils_1.toNumber)(value, 'noise_timeout');
            number *= 1;
            await entity.write('sprutNoise', { noiseAfterDetectDelay: number }, (0, utils_1.getOptions)(meta.mapped, entity));
            return { state: { [key]: number } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read('sprutNoise', ['noiseAfterDetectDelay']);
        },
    },
    occupancy_sensitivity: {
        key: ['occupancy_sensitivity'],
        convertSet: async (entity, key, value, meta) => {
            let number = (0, utils_1.toNumber)(value, 'occupancy_sensitivity');
            number *= 1;
            const options = (0, utils_1.getOptions)(meta.mapped, entity, manufacturerOptions);
            await entity.write('msOccupancySensing', { 'sprutOccupancySensitivity': number }, options);
            return { state: { [key]: number } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read('msOccupancySensing', ['sprutOccupancySensitivity'], manufacturerOptions);
        },
    },
    noise_detect_level: {
        key: ['noise_detect_level'],
        convertSet: async (entity, key, value, meta) => {
            let number = (0, utils_1.toNumber)(value, 'noise_detect_level');
            number *= 1;
            const options = (0, utils_1.getOptions)(meta.mapped, entity, manufacturerOptions);
            await entity.write('sprutNoise', { 'noiseDetectLevel': number }, options);
            return { state: { [key]: number } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read('sprutNoise', ['noiseDetectLevel'], manufacturerOptions);
        },
    },
    temperature_offset: {
        key: ['temperature_offset'],
        convertSet: async (entity, key, value, meta) => {
            let number = (0, utils_1.toNumber)(value, 'temperature_offset');
            number *= 1;
            const newValue = number * 100.0;
            const options = (0, utils_1.getOptions)(meta.mapped, entity, manufacturerOptions);
            await entity.write('msTemperatureMeasurement', { 'sprutTemperatureOffset': newValue }, options);
            return { state: { [key]: number } };
        },
    },
    co2_mh_z19b_config: {
        key: ['co2_autocalibration', 'co2_manual_calibration'],
        convertSet: async (entity, key, value, meta) => {
            let newValue = value;
            (0, utils_1.assertString)(value, 'co2_autocalibration/co2_manual_calibration');
            newValue = switchActionValues.indexOf(value);
            const options = (0, utils_1.getOptions)(meta.mapped, entity, manufacturerOptions);
            await entity.write('msCO2', { [(0, utils_1.getFromLookup)(key, co2Lookup)]: newValue }, options);
            return { state: { [key]: value } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read('msCO2', [(0, utils_1.getFromLookup)(key, co2Lookup)], manufacturerOptions);
        },
    },
    th_heater: {
        key: ['th_heater'],
        convertSet: async (entity, key, value, meta) => {
            let newValue = value;
            (0, utils_1.assertString)(value, 'th_heater');
            newValue = switchActionValues.indexOf(value);
            const options = (0, utils_1.getOptions)(meta.mapped, entity, manufacturerOptions);
            await entity.write('msRelativeHumidity', { 'sprutHeater': newValue }, options);
            return { state: { [key]: value } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read('msRelativeHumidity', ['sprutHeater'], manufacturerOptions);
        },
    },
};
const sprutModernExtend = {
    sprutActivityIndicator: (args) => modernExtend.binary({
        name: 'activity_led',
        cluster: 'genBinaryOutput',
        attribute: 'presentValue',
        description: 'Controls green activity LED',
        reporting: { attribute: 'presentValue', min: 'MIN', max: 'MAX', change: 1 },
        valueOn: [true, 1],
        valueOff: [false, 0],
        access: 'ALL',
        entityCategory: 'config',
        ...args,
    }),
    sprutTemperatureOffset: (args) => modernExtend.numeric({
        name: 'temperature_offset',
        cluster: 'msTemperatureMeasurement',
        attribute: 'sprutTemperatureOffset',
        description: 'Self-heating compensation. The compensation value is subtracted from the measured temperature (default: 0)',
        valueMin: -10,
        valueMax: 10,
        unit: '°C',
        scale: 100,
        access: 'ALL',
        entityCategory: 'config',
        zigbeeCommandOptions: manufacturerOptions,
        ...args,
    }),
    sprutThHeater: (args) => modernExtend.binary({
        name: 'th_heater',
        cluster: 'msRelativeHumidity',
        attribute: 'sprutHeater',
        description: 'Turn on when working in conditions of high humidity (more than 70 %, RH) or condensation, ' +
            'if the sensor shows 0 or 100 %.',
        valueOn: [true, 1],
        valueOff: [false, 0],
        access: 'ALL',
        entityCategory: 'config',
        zigbeeCommandOptions: manufacturerOptions,
        ...args,
    }),
    sprutOccupancyLevel: (args) => modernExtend.numeric({
        name: 'occupancy_level',
        cluster: 'msOccupancySensing',
        attribute: 'sprutOccupancyLevel',
        reporting: { min: '10_SECONDS', max: '1_MINUTE', change: 5 },
        description: 'Measured occupancy level',
        access: 'STATE_GET',
        entityCategory: 'diagnostic',
        ...args,
    }),
    sprutOccupancyTimeout: (args) => modernExtend.numeric({
        name: 'occupancy_timeout',
        cluster: 'msOccupancySensing',
        attribute: 'pirOToUDelay',
        description: 'Time in seconds after which occupancy is cleared after detecting it (default: 60)',
        valueMin: 0,
        valueMax: 2000,
        unit: 's',
        access: 'ALL',
        entityCategory: 'config',
        ...args,
    }),
    sprutOccupancySensitivity: (args) => modernExtend.numeric({
        name: 'occupancy_sensitivity',
        cluster: 'msOccupancySensing',
        attribute: 'sprutOccupancySensitivity',
        description: 'If the sensor is triggered by the slightest movement, reduce the sensitivity, ' +
            'otherwise increase it (default: 50)',
        valueMin: 0,
        valueMax: 2000,
        access: 'ALL',
        entityCategory: 'config',
        zigbeeCommandOptions: manufacturerOptions,
        ...args,
    }),
    sprutNoise: (args) => modernExtend.numeric({
        name: 'noise',
        cluster: 'sprutNoise',
        attribute: 'noise',
        reporting: { min: '10_SECONDS', max: '1_MINUTE', change: 5 },
        description: 'Measured noise level',
        unit: 'dBA',
        precision: 2,
        access: 'STATE_GET',
        entityCategory: 'diagnostic',
        ...args,
    }),
    sprutNoiseDetectLevel: (args) => modernExtend.numeric({
        name: 'noise_detect_level',
        cluster: 'sprutNoise',
        attribute: 'noiseDetectLevel',
        description: 'The minimum noise level at which the detector will work (default: 50)',
        valueMin: 0,
        valueMax: 150,
        unit: 'dBA',
        access: 'ALL',
        entityCategory: 'config',
        zigbeeCommandOptions: manufacturerOptions,
        ...args,
    }),
    sprutNoiseDetected: (args) => modernExtend.binary({
        name: 'noise_detected',
        cluster: 'sprutNoise',
        attribute: 'noiseDetected',
        valueOn: [true, 1],
        valueOff: [false, 0],
        description: 'Indicates whether the device detected noise',
        access: 'STATE_GET',
        ...args,
    }),
    sprutNoiseTimeout: (args) => modernExtend.numeric({
        name: 'noise_timeout',
        cluster: 'sprutNoise',
        attribute: 'noiseAfterDetectDelay',
        description: 'Time in seconds after which noise is cleared after detecting it (default: 60)',
        valueMin: 0,
        valueMax: 2000,
        unit: 's',
        access: 'ALL',
        entityCategory: 'config',
        ...args,
    }),
    sprutVoc: (args) => modernExtend.numeric({
        name: 'voc',
        label: 'VOC',
        cluster: 'sprutVoc',
        attribute: 'voc',
        reporting: { min: '10_SECONDS', max: '1_MINUTE', change: 10 },
        description: 'Measured VOC level',
        unit: 'µg/m³',
        access: 'STATE_GET',
        ...args,
    }),
    sprutIrBlaster: () => {
        const toZigbee = [{
                key: ['play_store', 'learn_start', 'learn_stop', 'clear_store', 'play_ram', 'learn_ram_start', 'learn_ram_stop'],
                convertSet: async (entity, key, value, meta) => {
                    const options = {
                        frameType: 0, manufacturerCode: sprutCode, disableDefaultResponse: true,
                        disableResponse: true, reservedBits: 0, direction: 0, writeUndiv: false,
                        // @ts-expect-error
                        transactionSequenceNumber: null,
                    };
                    switch (key) {
                        case 'play_store':
                            await entity.command('sprutIrBlaster', 'playStore', { param: value['rom'] }, options);
                            break;
                        case 'learn_start':
                            await entity.command('sprutIrBlaster', 'learnStart', { value: value['rom'] }, options);
                            break;
                        case 'learn_stop':
                            await entity.command('sprutIrBlaster', 'learnStop', { value: value['rom'] }, options);
                            break;
                        case 'clear_store':
                            await entity.command('sprutIrBlaster', 'clearStore', {}, options);
                            break;
                        case 'play_ram':
                            await entity.command('sprutIrBlaster', 'playRam', {}, options);
                            break;
                        case 'learn_ram_start':
                            await entity.command('sprutIrBlaster', 'learnRamStart', {}, options);
                            break;
                        case 'learn_ram_stop':
                            await entity.command('sprutIrBlaster', 'learnRamStop', {}, options);
                            break;
                    }
                },
            }];
        const configure = async (device, coordinatorEndpoint, logger) => {
            const endpoint1 = device.getEndpoint(1);
            await reporting.bind(endpoint1, coordinatorEndpoint, ['sprutIrBlaster']);
            device.save();
        };
        return { toZigbee, configure, isModernExtend: true };
    },
};
const { sprutActivityIndicator, sprutOccupancyLevel, sprutNoise, sprutVoc, sprutNoiseDetected, sprutOccupancyTimeout, sprutNoiseTimeout, sprutTemperatureOffset, sprutThHeater, sprutOccupancySensitivity, sprutNoiseDetectLevel, sprutIrBlaster, } = sprutModernExtend;
const definitions = [
    {
        zigbeeModel: ['WBMSW3'],
        model: 'WB-MSW-ZIGBEE v.3',
        vendor: 'Wirenboard',
        description: 'Wall-mounted multi sensor',
        fromZigbee: [fzLocal.temperature, fromZigbee_1.default.illuminance, fromZigbee_1.default.humidity, fromZigbee_1.default.occupancy, fzLocal.occupancy_level, fromZigbee_1.default.co2, fzLocal.voc,
            fzLocal.noise, fzLocal.noise_detected, fromZigbee_1.default.on_off, fzLocal.occupancy_timeout, fzLocal.noise_timeout, fzLocal.co2_mh_z19b_config,
            fzLocal.th_heater, fzLocal.occupancy_sensitivity, fzLocal.noise_detect_level],
        toZigbee: [toZigbee_1.default.on_off, tzLocal.sprut_ir_remote, tzLocal.occupancy_timeout, tzLocal.noise_timeout, tzLocal.co2_mh_z19b_config,
            tzLocal.th_heater, tzLocal.temperature_offset, tzLocal.occupancy_sensitivity, tzLocal.noise_detect_level],
        exposes: [e.temperature(), e.illuminance(), e.illuminance_lux(), e.humidity(), e.occupancy(), e.occupancy_level(), e.co2(),
            e.voc(), e.noise(), e.noise_detected(), e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'),
            e.switch().withEndpoint('l3'),
            e.numeric('noise_timeout', ea.ALL).withValueMin(0).withValueMax(2000).withUnit('s').withCategory('config')
                .withDescription('Time in seconds after which noise is cleared after detecting it (default: 60)'),
            e.numeric('occupancy_timeout', ea.ALL).withValueMin(0).withValueMax(2000).withUnit('s').withCategory('config')
                .withDescription('Time in seconds after which occupancy is cleared after detecting it (default: 60)'),
            e.numeric('temperature_offset', ea.SET).withValueMin(-10).withValueMax(10).withUnit('°C').withCategory('config')
                .withDescription('Self-heating compensation. The compensation value is subtracted from the measured temperature'),
            e.numeric('occupancy_sensitivity', ea.ALL).withValueMin(0).withValueMax(2000).withCategory('config')
                .withDescription('If the sensor is triggered by the slightest movement, reduce the sensitivity, ' +
                'otherwise increase it (default: 50)'),
            e.numeric('noise_detect_level', ea.ALL).withValueMin(0).withValueMax(150).withUnit('dBA').withCategory('config')
                .withDescription('The minimum noise level at which the detector will work (default: 50)'),
            e.enum('co2_autocalibration', ea.ALL, switchActionValues).withCategory('config')
                .withDescription('Automatic calibration of the CO2 sensor. If ON, the CO2 sensor will automatically calibrate ' +
                'every 7 days. (MH-Z19B sensor)'),
            e.enum('co2_manual_calibration', ea.ALL, switchActionValues).withCategory('config')
                .withDescription('Ventilate the room for 20 minutes, turn on manual calibration, and turn it off after one second. ' +
                'After about 5 minutes the CO2 sensor will show 400ppm. Calibration completed. (MH-Z19B sensor)'),
            e.enum('th_heater', ea.ALL, switchActionValues).withCategory('config')
                .withDescription('Turn on when working in conditions of high humidity (more than 70 %, RH) or condensation, ' +
                'if the sensor shows 0 or 100 %.'),
        ],
        configure: async (device, coordinatorEndpoint, logger) => {
            const endpoint1 = device.getEndpoint(1);
            const binds = ['genBasic', 'msTemperatureMeasurement', 'msIlluminanceMeasurement', 'msRelativeHumidity',
                'msOccupancySensing', 'msCO2', 'sprutVoc', 'sprutNoise', 'sprutIrBlaster', 'genOta'];
            await reporting.bind(endpoint1, coordinatorEndpoint, binds);
            // report configuration
            await reporting.temperature(endpoint1);
            await reporting.illuminance(endpoint1);
            await reporting.humidity(endpoint1);
            await reporting.occupancy(endpoint1);
            let payload = reporting.payload('sprutOccupancyLevel', 10, constants.repInterval.MINUTE, 5);
            await endpoint1.configureReporting('msOccupancySensing', payload, manufacturerOptions);
            payload = reporting.payload('noise', 10, constants.repInterval.MINUTE, 5);
            await endpoint1.configureReporting('sprutNoise', payload);
            // led_red
            await device.getEndpoint(2).read('genOnOff', ['onOff']);
            // led_green
            await device.getEndpoint(3).read('genOnOff', ['onOff']);
            // buzzer
            await device.getEndpoint(4).read('genOnOff', ['onOff']);
        },
        endpoint: (device) => {
            return { 'default': 1, 'l1': 2, 'l2': 3, 'l3': 4 };
        },
        meta: { multiEndpoint: true, multiEndpointSkip: ['humidity'] },
        extend: [ota()],
    },
    {
        zigbeeModel: ['WBMSW4'],
        model: 'WB-MSW-ZIGBEE v.4',
        vendor: 'Wirenboard',
        description: 'Wall-mounted multi sensor',
        extend: [
            forcePowerSource({ powerSource: 'Mains (single phase)' }),
            deviceEndpoints({
                endpoints: { 'default': 1, 'l1': 2, 'l2': 3, 'l3': 4, 'indicator': 5 },
            }),
            onOff({ powerOnBehavior: false, endpointNames: ['l1', 'l2', 'l3'] }),
            sprutActivityIndicator({ endpointName: 'indicator' }),
            temperature(),
            sprutTemperatureOffset(),
            humidity(),
            sprutThHeater(),
            co2(),
            illuminance(),
            occupancy(),
            sprutOccupancySensitivity(),
            sprutOccupancyLevel(),
            sprutOccupancyTimeout(),
            sprutNoise(),
            sprutNoiseDetectLevel(),
            sprutNoiseDetected(),
            sprutNoiseTimeout(),
            sprutVoc(),
            sprutIrBlaster(),
            ota(),
        ],
    },
];
exports.default = definitions;
module.exports = definitions;
//# sourceMappingURL=wirenboard.js.map