Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bitron-Video Wall Thermostat support (base functions) #134

Closed
wants to merge 14 commits into from
Closed

Bitron-Video Wall Thermostat support (base functions) #134

wants to merge 14 commits into from

Conversation

Chrischi-
Copy link
Contributor

Base functions added

fromZigbee.js

  • local temperature
  • running state
  • occupied heating setpoint
  • battery voltage
  • battery alarm state

toZigbee.js

  • set heating setpoint
  • set temperature calibration

@Chrischi- Chrischi- changed the title Bitron-Video Wall Thermostat support added Bitron-Video Wall Thermostat support (base functions) Nov 18, 2018
@sebastianheierhoff
Copy link
Contributor

Seems as if we're implementing the same functionality (see #132) for different devices. Maybe it would make sense to join forces?

@Chrischi-
Copy link
Contributor Author

Chrischi- commented Nov 28, 2018

Maybe it would make sense to join forces?

@sebastianheierhoff
absolutely

@sebastianheierhoff
Copy link
Contributor

Maybe it would make sense to join forces?

@sebastianheierhoff
absolutely

We will definitely need the devices.js entry for both Bitron and ecozy, but I feel that the converters should be more or less identical.

@sebastianheierhoff
Copy link
Contributor

My fork has a working occupiedHeatingSetpoint (https://github.com/sebastianheierhoff/zigbee-shepherd-converters/tree/dev)

@Chrischi-
Copy link
Contributor Author

Let's have a look at the converters.

    bitron_genPowerCfg_attReport: {
        cid: 'genPowerCfg',
        type: 'attReport',
        convert: (model, msg, publish, options) => {
            const battery = {max: 3200, min: 2500};
            const voltage = msg.data.data['batteryVoltage'] * 100;
            return {
                battery: toPercentage(voltage, battery.min, battery.max),
                voltage: voltage,
            };
        },
    },
    bitron_hvacThermostat_attReport: {
        cid: 'hvacThermostat',
        type: 'attReport',
        convert: (model, msg, publish, options) => {
            const deviceID = msg.endpoints[0].device.ieeeAddr;
            if (!store[deviceID]) {
                store[deviceID] = {localTemp: null};
                store[deviceID] = {occupiedHeatingSetpoint: null};
                store[deviceID] = {runningState: null};
            }
            if (typeof msg.data.data.localTemp == 'number') {
                store[deviceID].localTemp = msg.data.data.localTemp;
            }
            if ( typeof msg.data.data.occupiedHeatingSetpoint == 'number') {
                store[deviceID].occupiedHeatingSetpoint = msg.data.data.occupiedHeatingSetpoint;
            }
            if (typeof msg.data.data.runningState == 'number') {
                store[deviceID].runningState = msg.data.data.runningState;
            }
            return {
                localTemp: precisionRound(store[deviceID].localTemp, 2)/100,
                occupiedHeatingSetpoint: precisionRound(store[deviceID].occupiedHeatingSetpoint, 2)/100,
                runningState: store[deviceID].runningState === 1 ? 'ON' : 'OFF',
                batteryAlarmState: msg.data.data.batteryAlarmState === 1 ? 'ON' : 'OFF',
            };
        },
    },
    bitron_hvacThermostat_devChange: {
        cid: 'hvacThermostat',
        type: 'devChange',
        convert: (model, msg, publish, options) => {
            const deviceID = msg.endpoints[0].device.ieeeAddr;
            if (!store[deviceID]) {
                store[deviceID] = {localTemp: null};
                store[deviceID] = {occupiedHeatingSetpoint: null};
                store[deviceID] = {runningState: null};
            }
            if (typeof msg.data.data.localTemp == 'number') {
                store[deviceID].localTemp = msg.data.data.localTemp;
            }
            if (typeof msg.data.data.occupiedHeatingSetpoint == 'number') {
                store[deviceID].occupiedHeatingSetpoint = msg.data.data.occupiedHeatingSetpoint;
            }
            if (typeof msg.data.data.runningState == 'number') {
                store[deviceID].runningState = msg.data.data.runningState;
            }
            return {
                localTemp: precisionRound(store[deviceID].localTemp, 2)/100,
                occupiedHeatingSetpoint: precisionRound(store[deviceID].occupiedHeatingSetpoint, 2)/100,
                runningState: store[deviceID].runningState === 1 ? 'ON' : 'OFF',
                batteryAlarmState: msg.data.data.batteryAlarmState === 1 ? 'ON' : 'OFF',
            };
        },
},

@Chrischi-
Copy link
Contributor Author

@sebastianheierhoff

is there a reason why you're doing this?

if (!msg.data.data.occupiedHeatingSetpoint == null || !msg.data.data.occupiedHeatingSetpoint == '') {

this would be my solution

typeof msg.data.data.occupiedHeatingSetpoint == 'number'

@sebastianheierhoff
Copy link
Contributor

@sebastianheierhoff

is there a reason why you're doing this?

if (!msg.data.data.occupiedHeatingSetpoint == null || !msg.data.data.occupiedHeatingSetpoint == '') {

this would be my solution

typeof msg.data.data.occupiedHeatingSetpoint == 'number'

Not really. This is actually taken from the initial PR (#41) by @tb-killa

@sebastianheierhoff
Copy link
Contributor

Let's have a look at the converters.

    bitron_genPowerCfg_attReport: {
        cid: 'genPowerCfg',
        type: 'attReport',
        convert: (model, msg, publish, options) => {
            const battery = {max: 3200, min: 2500};
            const voltage = msg.data.data['batteryVoltage'] * 100;
            return {
                battery: toPercentage(voltage, battery.min, battery.max),
                voltage: voltage,
            };
        },
    },
    bitron_hvacThermostat_attReport: {
        cid: 'hvacThermostat',
        type: 'attReport',
        convert: (model, msg, publish, options) => {
            const deviceID = msg.endpoints[0].device.ieeeAddr;
            if (!store[deviceID]) {
                store[deviceID] = {localTemp: null};
                store[deviceID] = {occupiedHeatingSetpoint: null};
                store[deviceID] = {runningState: null};
            }
            if (typeof msg.data.data.localTemp == 'number') {
                store[deviceID].localTemp = msg.data.data.localTemp;
            }
            if ( typeof msg.data.data.occupiedHeatingSetpoint == 'number') {
                store[deviceID].occupiedHeatingSetpoint = msg.data.data.occupiedHeatingSetpoint;
            }
            if (typeof msg.data.data.runningState == 'number') {
                store[deviceID].runningState = msg.data.data.runningState;
            }
            return {
                localTemp: precisionRound(store[deviceID].localTemp, 2)/100,
                occupiedHeatingSetpoint: precisionRound(store[deviceID].occupiedHeatingSetpoint, 2)/100,
                runningState: store[deviceID].runningState === 1 ? 'ON' : 'OFF',
                batteryAlarmState: msg.data.data.batteryAlarmState === 1 ? 'ON' : 'OFF',
            };
        },
    },
    bitron_hvacThermostat_devChange: {
        cid: 'hvacThermostat',
        type: 'devChange',
        convert: (model, msg, publish, options) => {
            const deviceID = msg.endpoints[0].device.ieeeAddr;
            if (!store[deviceID]) {
                store[deviceID] = {localTemp: null};
                store[deviceID] = {occupiedHeatingSetpoint: null};
                store[deviceID] = {runningState: null};
            }
            if (typeof msg.data.data.localTemp == 'number') {
                store[deviceID].localTemp = msg.data.data.localTemp;
            }
            if (typeof msg.data.data.occupiedHeatingSetpoint == 'number') {
                store[deviceID].occupiedHeatingSetpoint = msg.data.data.occupiedHeatingSetpoint;
            }
            if (typeof msg.data.data.runningState == 'number') {
                store[deviceID].runningState = msg.data.data.runningState;
            }
            return {
                localTemp: precisionRound(store[deviceID].localTemp, 2)/100,
                occupiedHeatingSetpoint: precisionRound(store[deviceID].occupiedHeatingSetpoint, 2)/100,
                runningState: store[deviceID].runningState === 1 ? 'ON' : 'OFF',
                batteryAlarmState: msg.data.data.batteryAlarmState === 1 ? 'ON' : 'OFF',
            };
        },
},

Looks pretty similiar to me, except for "runningState" and "batteryAlarmState".

@Chrischi-
Copy link
Contributor Author

Yeah, I tried to get everything into one handler.

I don't know exactly if the Bitron thermostats send values like:

setpointChangeSource
setpointChangeAmount
setpointChangeSourceTimeStamp

@Chrischi-
Copy link
Contributor Author

here is my toZigbee.js

    thermostat_setHeatingSetpoint: {
        key: 'setHeatingSetpoint',
        attr: [],
        convert: (value, message, type) => {
            const cid = 'hvacThermostat';
            const attrId = 0x12;

            if (type === 'set') {
                return {
                    cid: cid,
                    type: 'foundation',
                    cmd: 'write',
                    zclData: {
                        attrId: attrId, // occupiedHeatingSetpoint
                        dataType: 0x29, // dataType int16
                        attrData: (Math.round((value * 2).toFixed(1))/2).toFixed(1) * 100,
                    },
                };
            }
        },
    },
    thermostat_setTemperatureCalibration: {
        key: 'setTemperatureCalibration',
        attr: [],
        convert: (value, message, type) => {
            const cid = 'hvacThermostat';
            const attrId = 0x10;

            if (type === 'set') {
                return {
                    cid: cid,
                    type: 'foundation',
                    cmd: 'write',
                    zclData: {
                        attrId: attrId, // localTemperatureCalibration 0x10
                        dataType: 0x28, // dataType int8
                        attrData: Math.round(value * 10),
                    },
                };
            }
        },
},

zclData array + cmdType fixed
@Chrischi-
Copy link
Contributor Author

will make a new pull request tomorrow.

made some adjustments that matches the ecozy PR from @sebastianheierhoff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants