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

Scheduling Goldair Wifi controllable Heaters using tuyapi #31

Closed
GabesSmith opened this issue Apr 17, 2018 · 17 comments
Closed

Scheduling Goldair Wifi controllable Heaters using tuyapi #31

GabesSmith opened this issue Apr 17, 2018 · 17 comments

Comments

@GabesSmith
Copy link

GabesSmith commented Apr 17, 2018

Firstly, I love the work you have done with the tuyapi library.

I am using tuyapi library with these Goldair Wifi controllable heaters http://www.goldair.co.nz/product-catalogue/heating/panel-heaters which I found use the Tuya IOT framework. The mobile app annoyingly does not have a schedule feature - only a simple timer you have to set every day. I have implemented my own schedule using crontab running on a Raspberry Pi.

Here are some notes on how I got this working.

Device Encryption Key discovery is done by finding these in the mobile app log file.

Heater Settings

'1': true, -on/off
'2': 14, -setpoint
'3': 19, -current Temp, readonly
'4': 'C', - 'C' comfort, 'ECO', 'AF' AntiFreeze
'6': false, -child lock on
'12': 0, -fault, readonly
'101': 'stop', -power level 'stop','1','2','3','4','5','auto'
'102': 1440, -timer in mins
'103': false, -timer on
'104': true, -led display on
'105': 'auto', -mode 'auto', 'user' - what is the difference?
'106': 14 -eco temp set point between 5-31

Code snippet of scheduling (crontab calls this with a scene param)

 if (scene == 'evening'){
            //evening 18 deg, on, LED on
            tuya.set({id: Heater1Id, dpscommand:'{"1":true,"2":18,"6":true,"104":true}'}).then(() => console.log('Heater1Id was changed')); 
            tuya.set({id: Heater2Id, dpscommand:'{"1":true,"2":18,"6":true,"104":true}'}).then(() => console.log('Heater2Id was changed')); 
            tuya.set({id: Heater3Id, dpscommand:'{"1":true,"2":18,"6":true,"104":true}'}).then(() => console.log('Heater3Id was changed')); 
        }

        if (scene == 'night'){
            //night 18 deg, locked, LED off
            tuya.set({id: Heater1Id, dpscommand:'{"1":true,"2":18,"6":true,"104":false}'}).then(() => console.log('Heater1Id was changed')); 
            tuya.set({id: Heater2Id, dpscommand:'{"1":true,"2":18,"6":true,"104":false}'}).then(() => console.log('Heater2Id was changed')); 
            tuya.set({id: Heater3Id, dpscommand:'{"1":true,"2":18,"6":true,"104":false}'}).then(() => console.log('Heater3Id was changed')); 
        }

        if (scene == 'morning'){
            //morning 7am, turn off, LED on, locked
            tuya.set({id: Heater1Id, dpscommand:'{"1":false,"2":18,"6":true,"104":true}'}).then(() => console.log('Heater1Id was changed')); 
            tuya.set({id: Heater2Id, dpscommand:'{"1":false,"2":18,"6":true,"104":true}'}).then(() => console.log('Heater2Id was changed')); 
            tuya.set({id: Heater3Id, dpscommand:'{"1":false,"2":18,"6":true,"104":true}'}).then(() => console.log('Heater3Id was changed')); 
        }

Extension to device set method to allow multiple settings to be changed at one time

/*
* @param {Object} options - options for setting properties
* @param {String} [options.id] - ID of device
* @param {Boolean} options.set - `true` for on, `false` for off
* @param {Number} [options.dps] - dps index to change
* @param {String} [options.dpscommand] - dps command string
*/
...
  if (options.dpscommand !== undefined) {
    thisRequest.dps = JSON.parse(options.dpscommand)
  }

I hope this helps.

@codetheweb
Copy link
Owner

This is great, thanks for your work.
The option to change multiple DPS indexes at once is a good idea, I'll try to include that in the next release.

See this comment for details, but eventually when TuyAPI gets split up I'd love it if you published a package for controlling heaters using TuyAPI as a dependency. The more device-specific community packages the better.

@codetheweb
Copy link
Owner

Also, did you have to modify requests.json at all @TarxBoy?

@GabesSmith
Copy link
Author

No modification of requests.json was required.

@codetheweb
Copy link
Owner

Huh, interesting.

@deiphid
Copy link

deiphid commented Jun 19, 2018

I have managed to get one of these heaters working on Homebridge by essentially adding it as a power outlet using the homebridge-tuya-outlet plugin. Now I can turn it on and off through my home app, or ask Siri to turn it on and off.

Any suggestions on how I might add other functionality?

For me, the most used functions would be turning the heater on and off (done), turning the LED on and off, and checking the room temperature. It would be great to do this all in one HomeKit "device", but would be equally useful to have three separate devices: heater (fan), led (light) and temperature (sensor).

@codetheweb
Copy link
Owner

I would suggest you make a custom Homebridge plugin for your heater. The gist of the process:

  1. Call .get({schema: true}) to find the DIP index of each property you want to use.
  2. Look at the source code of homebridge-tuya-outlet and base your plugin off that.
  3. For each property (fan, light, temperature)( you want to be controllable/readable, you'll have to create a separate class and publish that class as an accessory. For example, here's a snippet for temperature:
// -- Common to all accessories:
module.exports = function(homebridge) {
  Service = homebridge.hap.Service;
  Characteristic = homebridge.hap.Characteristic;
  //...
  // params: plugin name, accessory name, accessory constructor
  // call .registerAccessory for each parameter you want to control
  homebridge.registerAccessory("homebridge-tuya-heater", "TuyaHeaterTemperature", TuyaHeaterTemperature);
  //...
}

// -- End common code

//...

function TuyaHeaterTemperature(log, config) {
  // create a tuya instance

  // ...

  this._service = new Service.TemperatureSensor(this.name);
  this._service.getCharacteristic(Characteristic.CurrentTemperature).on('get', this._get.bind(this));
}

TuyaHeaterTemperature.prototype._get = function(callback) {
  debug("Getting temperature...");
  this.tuya.get({schema: true}).then(data => {
    debug("Data", data); // <- figure out the right DIP
    return callback(null, data.dip.2);
  }).catch(error => {
    callback(error, null);
  });
}
  

Find supported characteristics and services here.

Hopefully you can figure it out from there.

@deiphid
Copy link

deiphid commented Jun 19, 2018

Awesome, thanks! I am going to have a play with this over the next few weeks. If I’m successful I’ll share it.

@charlietomo
Copy link

@TarxBoy thanks for this it looks interesting. Are you happy share a complete (without keys etc) file that can be used to control the heater?

I have got my uuid, productID and localKey however am having trouble doing any basic control. I'm trying to get the minimum amount to turn heater on/off to start with but the following does not work (running as node filename.js).

I get the error UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error communicating with device. Make sure nothing else is trying to control it or connected to it.

Any ideas?

const TuyaDevice = require('tuyapi');

let tuya = new TuyaDevice({
  id: 'uuid',
  key: 'key'});

tuya.set({dpscommand:'{"1":false}'}).then(() => console.log('heater was turned off')); 

@codetheweb
Copy link
Owner

@charlietomo please see the docs on set() here. Your set command should look like this:

tuya.set({dps: 1, set: false}).then(() => console.log('heater was turned off')); 

@charlietomo
Copy link

Thanks. It was the rest of the code I was struggling with but got it to work. Full code:

const TuyaDevice = require('tuyapi');

let tuya = new TuyaDevice({
  id: '[id]',
  key: '[key]'});

tuya.resolveId().then(() => {  
  tuya.set({dps: 1, set: false}).then(status => {
    console.log('Status:', status);

        return;
  });
});

@codetheweb
Copy link
Owner

Glad to hear you got it working @charlietomo. I realize now that your issue was that you didn't pass in an IP or call resolveId(), so tuyapi was trying to connect to an undefined IP address.

I've added a check which throws an error if the IP is missing.

@charlietomo
Copy link

@codetheweb that check sounds useful. You are right, it was the missing IP / resolveID which was the main issue, but not apparent to me.

@deiphid I am also interested in a home bridge plugin so please update this thread if you make progress. I am actually more interested in a Home Assistant plugin, and then would expose it to homebridge (and iOS Home) that way.

@nicole-ashley
Copy link

nicole-ashley commented Jul 15, 2018

While not strictly related to this repo, I've developed an initial Home Assistant integration (made possible by the awesome research done in this thread). It needs specs and a few more features (eg, adding extra sensors and supporting power levels) but it's working well as a climate device and is robust enough for automation.

https://github.com/nikrolls/homeassistant-goldair-heater

// @charlietomo who specifically mentioned HA

@charlietomo
Copy link

Amazing @nikrolls that looks great. Will test it on my heaters / HA setup. Thanks in advance for the work you put into this.

@deiphid
Copy link

deiphid commented Jul 27, 2018

I have found that the homebridge-igenix-air-conditioner plugin works for these heaters. The plugin provides on/off, current temp, and target temp functionality. I am going to see if I can figure out a way to add control of the led screen, and maybe tailor the plugin towards a heater rather than an air conditioner.

@nicole-ashley
Copy link

nicole-ashley commented Jul 27, 2018

Just another heads-up: for those using Home Assistant, my integration now also supports the LED light, child lock, a standalone temperature sensor, and manual power levels. Now I'm working on official integration into the core so it can work on hass.io and HassOS.

@codetheweb
Copy link
Owner

Closing this because of inactivity.

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

No branches or pull requests

5 participants