UNPKG

node-red-contrib-tuya-smart-device

Version:
459 lines (445 loc) 14.1 kB
<script type="text/javascript"> RED.nodes.registerType('tuya-smart-device', { category: 'smarthome', color: '#C7E9C0', credentials: { secretConfig: { value: '', }, }, defaults: { deviceName: { value: '', required: true }, disableAutoStart: { value: false, required: true }, deviceId: { value: '', required: false, validate: function (v) { let value = v; let credsOffline = false; const storeAsCreds = this.storeAsCreds || false; if (storeAsCreds) { if (typeof this.credentials !== 'object') { credsOffline = true; } else { const secretConfig = this.credentials.secretConfig || '{}'; const secret = JSON.parse(secretConfig); value = secret.deviceId; } } return typeof this.deviceIp === 'string' && this.deviceIp.trim().length == 0 ? storeAsCreds && credsOffline ? true : value.trim().length > 0 : true; }, }, deviceKey: { value: '', required: false, validate: function (v) { let value = v; let credsOffline = false; const storeAsCreds = this.storeAsCreds || false; if (storeAsCreds) { if (typeof this.credentials !== 'object') { credsOffline = true; } else { const secretConfig = this.credentials.secretConfig || '{}'; const secret = JSON.parse(secretConfig); value = secret.deviceKey; } } return storeAsCreds && credsOffline ? true : value.trim().length > 0; }, }, storeAsCreds: { value: false, }, deviceIp: { value: '', required: false, validate: function (v) { return $('#node-input-deviceId').val() && $('#node-input-deviceId').val().trim().length == 0 ? v.trim().length > 0 : true; }, }, retryTimeout: { value: 1000, required: true, validate: RED.validators.number(), }, findTimeout: { value: 10000, required: true, validate: RED.validators.number(), }, tuyaVersion: { value: '3.1', required: false }, eventMode: { value: 'event-both', required: true }, logLevel: { value: 'log-level-debug', required: false }, }, inputs: 1, outputs: 2, inputLabels: 'Command for the device', outputLabels: ['Data from the device', 'Client State'], icon: 'bridge.svg', label: function () { return this.deviceName || 'tuya smart device'; }, oneditprepare: function () { let eventMode = this.eventMode || 'event-both'; $("select[name='node-input-eventMode']") .find(`option[value='${eventMode}']`) .attr('selected', true); let logLevel = this.logLevel || 'log-level-debug'; $("select[name='node-input-logLevel']") .find(`option[value='${logLevel}']`) .attr('selected', true); const storeAsCreds = this.storeAsCreds || false; if (storeAsCreds) { const secretConfig = this.credentials.secretConfig || '{}'; const secret = JSON.parse(secretConfig); console.log('Loading config from secret'); $('#node-input-deviceId').val(secret.deviceId); $('#node-input-deviceKey').val(secret.deviceKey); } $('#node-input-findTimeout').val(this.findTimeout || 1000); $('#node-input-retryTimeout').val(this.retryTimeout || 1000); if ( this.tuyaVersion == null || typeof this.tuyaVersion == 'undefined' || this.tuyaVersion.trim().length == 0 ) { $('#node-input-tuyaVersion').val(3.1); } }, oneditsave: function () { const storeAsCreds = $('#node-input-storeAsCreds').is(':checked') || false; if (storeAsCreds) { const secret = { deviceId: $('#node-input-deviceId').val(), deviceKey: $('#node-input-deviceKey').val(), }; console.log('Saving secret'); $('#node-input-secretConfig').val(JSON.stringify(secret)); $('#node-input-deviceId').val(''); $('#node-input-deviceKey').val(''); } else { $('#node-input-secretConfig').val('{}'); } }, }); </script> <script type="text/html" data-template-name="tuya-smart-device"> <input type="hidden" id="node-input-secretConfig" placeholder="Device Secret" /> <div class="form-row"> <label style="width:100%" for="node-input-deviceName" ><i class="fa fa-tag"></i> Device Name</label > <input type="text" id="node-input-deviceName" placeholder="Bulb" /> </div> <hr /> <div class="form-row" style="font-weight: bold;">Connection Details</div> <div style="margin-bottom:10px;font-style: italic;color: brown;font-size: smaller;" > Use Device IP or Device Virtual ID (Don't use both) </div> <div class="form-row"> <label style="width:100%" for="node-input-deviceId" ><i class="fa fa-id-card-o"></i> Device Virtual ID</label > <input type="text" id="node-input-deviceId" placeholder="Device Virtual ID" /> </div> <div class="form-row"> <label style="width:100%" for="node-input-deviceKey" ><i class="fa fa-key"></i> Device Key</label > <input type="text" id="node-input-deviceKey" placeholder="Device Key" /> </div> <div class="form-row"> <label style="width:100%" for="node-input-storeAsCreds"> <input type="checkbox" style="width: auto;" id="node-input-storeAsCreds" /> Store Device Id and Device Key as credentials (Credentials will not appear in the flow export)</label > </div> <div style="color:blue"> <i class="fa fa-question"></i>&nbsp;&nbsp;How to get the device ID and Key ?<a href="https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md" target="_blank" >Click here</a > </div> <br /> <div class="form-row"> <label style="width:100%" for="node-input-deviceIp" ><i class="fa fa-info"></i> Device IP (Use Static IP) </label> <input type="text" id="node-input-deviceIp" placeholder="The ip of the device" /> </div> <hr /> <div class="form-row" style="font-weight: bold;">Advanced Options</div> <div class="form-row"> <input type="checkbox" id="node-input-disableAutoStart" placeholder="" style="width:auto" /> <label for="node-input-disableAutoStart" style="width:auto"> Disable auto connect on start </label> <br /> (You have to manually issue the CONNECT CONTROL COMMAND. Refer the help panel) <br /> </div> <div class="form-row"> <label style="width:100%" for="node-input-retryTimeout" ><i class="fa fa-clock-o"></i> Interval for retry connection incase of error (milliseconds)</label > </div> <div class="form-row"> <input type="number" id="node-input-retryTimeout" placeholder="" value="1000" /> </div> <div class="form-row"> <label style="width:100%" for="node-input-findTimeout" ><i class="fa fa-clock-o"></i> Interval for find operation incase of error (milliseconds)</label > <input type="number" id="node-input-findTimeout" placeholder="" value="1000" /> </div> <div class="form-row"> <label style="width:100%" for="node-input-tuyaVersion" ><i class="fa fa-lock"></i> Tuya Protocol Version, Default : 3.1 (don't change if you are not sure)</label > <input type="text" id="node-input-tuyaVersion" placeholder="" value="3.1" /> </div> <div class="form-row"> <label style="width:100%" for="node-input-subscribeMode" ><i class="fa fa-wrench"></i> Listen to tuya events</label > </div> <div class="form-row"> <select name="node-input-eventMode" id="node-input-eventMode"> <option value="event-data">Data Event</option> <option value="event-dp-refresh">DP-Refresh Event</option> <option value="event-both">Both Events</option> </select> </div> <div class="form-row"> <label style="width:100%" for="node-input-loglevel" ><i class="fa fa-file"></i> Log Level (Will not override the node-red logging config. Only applies to this node)</label > </div> <div class="form-row"> <select name="node-input-logLevel" id="node-input-logLevel"> <option value="log-level-error">Error</option> <option value="log-level-info">Info</option> <option value="log-level-debug">Debug</option> <option value="log-level-disable">Disable</option> </select> </div> </script> <script type="text/html" data-help-name="tuya-smart-device"> <p>This node will help you to configure any tuya smart device.</p> <h3>Details</h3> <p> Instructions for getting the device id is available <a href="https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md" >here</a > </p> <code >You will get the device id and the key once you run the wizard program as per the instructiions</code > <p> The node takes the input which needs to be sent to the device and outouts the message if the state of the device changes. </p> <h3>Input</h3> <h4>payload</h4> <dl class="message-properties"> <dt class="optional"> operation <span class="property-type">SET/GET</span> </dt> <dd> <p> <b>SET</b> (default): Use SET the run a set operation in the device <a href="https://codetheweb.github.io/tuyapi/index.html#tuyadeviceset" >SET documentation</a > </p> <p> <b>GET</b>: Use GET the run a get operation in the device <a href="https://codetheweb.github.io/tuyapi/index.html#tuyadeviceget" >GET documentation</a > </p> <p> <b>REFRESH</b>: Use REFRESH to refresh a device status <a href="https://codetheweb.github.io/tuyapi/index.html#tuyadevicerefresh" >REFRESH documentation</a > </p> <p> <b>CONTROL</b>: Send the control events to the node. This can be used to issue actions like connect, disconnect etc. </p> Any output of the operation will be triggered on the output of the node. </dd> <dt class="">dps <span class="property-type">Number</span></dt> <dd>The dps index you want to update or query</dd> <dt class="">set <span class="property-type">Any</span></dt> <dd>The value you want to set for the dps index</dd> <dt class="optional"> multiple <span class="property-type">Boolean</span> </dt> <dd> Incase you want to send multiple dps index for a SET operation. Use the data argument in that case. </dd> <dt class="optional">data <span class="property-type">Object</span></dt> <dd> Object of the below format with multiple dps index and the values <code> payload = { "multiple": true, "data": { "20": true, "24": "00e203e803de" } }</code > </dd> <dt class="">action <span class="property-type">string</span></dt> <dd> This property works only with operation is set as "CONTROL" <table border> <tr> <td>Action</td> <td>Purpose</td> </tr> <tr> <td>CONNECT</td> <td>Connects to the device</td> </tr> <tr> <td>DISCONNECT</td> <td>Disconnect from the device</td> </tr> <tr> <td>RECONNECT</td> <td>Reconnects to the device</td> </tr> <tr> <td>SET_FIND_TIMEOUT</td> <td> Sets the find timeout dynamically. This is not saved in the config </td> </tr> <tr> <td>SET_RETRY_TIMEOUT</td> <td> Sets the retry timeout dynamically. This is not saved in the config </td> </tr> <tr> <td>SET_EVENT_MODE</td> <td> Sets the event mode dynamically. This is not saved in the config. <br /> <br /> value = event-data //for subscribing to only data event <br /> <br /> value = event-dp-refresh //for subscribing to only dp-refresh event <br /> <br /> value = both //for subscribing to both events </td> </tr> </table> example : <div> action : CONNECT <code> payload = { "operation": "CONTROL", "action": "CONNECT" } </code> </div> <div> action : SET_EVENT_MODE <code> payload = { "operation": "CONTROL", "action": "SET_EVENT_MODE", "value": "event-data" } </code> </div> </dd> </dl> <h3>Output</h3> <ol class="node-ports"> <li> Data from device <dl class="message-properties"> <dt class=""> deviceId <span class="property-type">String</span> </dt> <dd>Device Id</dd> <dt class="">deviceName <span class="property-type">String</span></dt> <dd>Device Name</dd> <dt class="optional">data <span class="property-type">Object</span></dt> <dd> The response from the Tuya device. Sample response is shown below. <code> data: { dps : { 1 : false }, t: 1600955043 }, deviceId: "39390e7421ia", deviceName: "Monitor Plug" </code> </dd> </dl> </li> <li> Client state <dl class="message-properties"> <dt class=""> state <span class="property-type">String</span> </dt> <dd> Shows the current status of the node (CONNECTED, CONNECTING, DISCONNECTED,ERROR) </dd> </dl> </li> </ol> </script>