TuyaAPI / cli

🔧 A CLI for Tuya devices
MIT License
270 stars 44 forks source link

Set color of RGB Led lamp #104

Closed tefracky closed 3 years ago

tefracky commented 3 years ago

Hello,

how can I use the cli to set the RGB lamp to a specific color, e.g. red or blue? Does anyone has an example?

Thanks a lot!

Best regards

codetheweb commented 3 years ago

I would recommend taking a look at other projects that allow controlling RGB lights to see how it's done. For example, here's the source of a Homebridge plugin that controls RGB lights.

tefracky commented 3 years ago

I was able to set the color and simulate a sunrise using https://github.com/codetheweb/tuyapi:

function sunrise() {
    console.log('Start sunrise');

    // https://github.com/codetheweb/tuyapi
    const TuyAPI = require('tuyapi');

    // Setting device properties
    const device = new TuyAPI({
        id: 'xxx',
        key: 'yyy',
        ip: 'zzz',  // not needed, but connection will be much faster
        version: 3.3});

    // Sleep delay  etweeen each color change (in s)
    const sleepDelay = 2;

    // https://www.computerhilfen.de/info/sonnenaufgang-mit-alexa-fhem-und-philips-hue.html
    const sun = ['030100','0B0300','190601','230902','2F0D03','370F03','401204','481405','521806', '622108','6E2508','772809','7F2A09','882D0A','90300A','96320A','9D330A','A6360A','B0390A', 'B0450A','B9480B','C1580B','CB610B','D3650C','D6740C','DC770B','DC810B','E5860B','ED8E12','F2A113', 'F2B013','F5B51A','F9BA22','FBBD29','FEC232','FFC742','FECC55','FED166','FDD473', 'FDD880','FEDD8C','FDDF97','FDE4A7','FDEABC','FDEEC8','FDF0D1','FDF3DA','FCF4E2'];

    const size = sun.length;

    let stateHasChanged = false;

    // Find device on network
    device.find().then(() => {
        // Connect to device
        device.connect();
    });

    // Add event listeners
    device.on('connected', () => {
        console.log('Connected to device');
    });

    device.on('disconnected', () => {
        console.log('Disconnected from device');
    });

    device.on('error', error => {
        console.log('Error!', error);
    });

    // https://stackoverflow.com/questions/57803/how-to-convert-decimal-to-hexadecimal-in-javascript
    function DecToHex( decimal ) {
        return Math.round(Number(decimal)).toString(16).padStart(2, '0').toUpperCase();
    }

    // https://www.html-code-generator.com/javascript/color-converter-script
    function HEXtoRGB(hex) {
        hex = hex.replace(/#/g, '');
        if (hex.length === 3) {
            hex = hex.split('').map(function (hex) {
                return hex + hex;
            }).join('');
        }
        var result = /^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})[\da-z]{0,0}$/i.exec(hex);
        if (result) {
            var red = parseInt(result[1], 16);
            var green = parseInt(result[2], 16);
            var blue = parseInt(result[3], 16);

            return [red, green, blue];
        } else {
            return null;
        }
    }

    // https://gist.github.com/mjackson/5311256
    function RGBtoHSV(r, g, b) {
      r /= 255, g /= 255, b /= 255;

      var max = Math.max(r, g, b), min = Math.min(r, g, b);
      var h, s, v = max;

      var d = max - min;
      s = max == 0 ? 0 : d / max;

      if (max == min) {
        h = 0; // achromatic
      } else {
        switch (max) {
          case r: h = (g - b) / d + (g < b ? 6 : 0); break;
          case g: h = (b - r) / d + 2; break;
          case b: h = (r - g) / d + 4; break;
        }

        h /= 6;
      }

      return [ h*360, s*255, v*255 ];
    }

    function sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }

    function setColor(color) {
            device.set({
            multiple: true,
            data: {
                '2': 'colour',
                '5': color
            }
        })
    }

    // https://github.com/codetheweb/tuyapi/issues/5#issuecomment-361212775
    function getColor(color) {
        let rgb = HEXtoRGB(color);
        let hsvDec = RGBtoHSV(rgb[0], rgb[1], rgb[2]);
        let hsvHex = [DecToHex(hsvDec[0]), DecToHex(hsvDec[1]), DecToHex(hsvDec[2])];
        //console.log('rgb:', rgb);
        //console.log('hsvDec:', hsvDec);
        //console.log('hsvHex:', hsvHex);
        let newColor = color + "00" + hsvHex[0] + hsvHex[2] + hsvHex[2];
        console.log('New Color:', newColor);
        return newColor;
    }

    async function sunrise() {
        console.log('Start sunrise loop');

        var i = 0;
        console.log('Iteration', i);

        setColor(getColor(sun[0]));
        device.set({dps: 1, set: true})

        for (i = 1; i < size; i++) {
            await sleep(sleepDelay*1000);
            console.log('Iteration', i);
            setColor(getColor(sun[i]));
        }

        console.log('Sunrise loop finished');
    }

    device.on('data', data => {
        // Set sunrise loop
        if (!stateHasChanged) {
            console.log('Get initial data');

            console.log('Data from device:', data);

            console.log(`On/Off (=true/false): ${data.dps['1']}`);
            console.log(`White/colour: ${data.dps['2']}`);
            console.log(`Brightness: ${data.dps['3']}`);
            console.log(`Warm/Cold: ${data.dps['4']}`);
            console.log(`Color: ${data.dps['5']}`);

            console.log('Sunrise size', size);
            sunrise();

            // Otherwise we'll be stuck in an endless
            // loop of toggling the state.
            stateHasChanged = true;
        }
    });

    // Disconnect after certain time seconds
    let timeout = (size)*(sleepDelay);
    console.log('Setting timeout to', timeout, 'seconds');
    setTimeout(() => { device.disconnect(); }, timeout*1000);
}

sunrise();
codetheweb commented 3 years ago

Nice, that's pretty cool!

Glad you figured it out.