From 1612b97115520950a6c42a54ddadd249753bc1b0 Mon Sep 17 00:00:00 2001 From: "K. Siedentopp" Date: Mon, 11 Jun 2018 09:37:52 +0200 Subject: [PATCH] initial script --- .gitignore | 70 +++++++++++++++++++++++++++++++++++++++++ package.json | 16 ++++++++++ tuya-mqtt.js | 57 +++++++++++++++++++++++++++++++++ tuya-status.js | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ tuya.js | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 312 insertions(+) create mode 100644 .gitignore create mode 100644 package.json create mode 100644 tuya-mqtt.js create mode 100644 tuya-status.js create mode 100644 tuya.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..64abaf6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,70 @@ +devices/ + + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless diff --git a/package.json b/package.json new file mode 100644 index 0000000..a221cc5 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "tuya-api", + "version": "1.0.0", + "description": "", + "main": "tuya.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "mqtt": "^2.18.0", + "tuyapi": "github:codetheweb/tuyapi", + "yargs": "^11.0.0" + } +} diff --git a/tuya-mqtt.js b/tuya-mqtt.js new file mode 100644 index 0000000..267f491 --- /dev/null +++ b/tuya-mqtt.js @@ -0,0 +1,57 @@ +const mqtt = require('mqtt'); +var Topic = '#'; //subscribe to all topics +var options = { + clientId: 'MyMQTT', + port: 1883, + keepalive: 60 +}; + +const client = mqtt.connect({ + host: 'localhost', + port: 1883 +}); + +client.on('connect', mqtt_connect); +client.on('reconnect', mqtt_reconnect); +client.on('error', mqtt_error); +client.on('message', mqtt_messsageReceived); +client.on('close', mqtt_close); + +function mqtt_connect() { + console.log("Connecting MQTT"); + client.subscribe(Topic, mqtt_subscribe); +} + +function mqtt_subscribe(err, granted) { + console.log("Subscribed to " + Topic); + if (err) { + console.log(err); + } +} + +function mqtt_reconnect(err) { + console.log("Reconnect MQTT"); + if (err) { + console.log(err); + } + client = mqtt.connect(Broker_URL, options); +} + +function mqtt_error(err) { + console.log("Error!"); + if (err) { + console.log(err); + } +} + +function after_publish() { + //do nothing +} + +function mqtt_messsageReceived(topic, message, packet) { + console.log('Topic=' + topic + ' Message=' + message); +} + +function mqtt_close() { + console.log("Close MQTT"); +} \ No newline at end of file diff --git a/tuya-status.js b/tuya-status.js new file mode 100644 index 0000000..e0f367c --- /dev/null +++ b/tuya-status.js @@ -0,0 +1,84 @@ +const TuyaDevice = require('tuyapi'); +let tuya = undefined; +_DEBUG = true; + +function bmap(istate) { + return istate ? 'ON' : "OFF"; +} + +exports.setDebug = function (debug) { + _DEBUG = debug; +} + +exports.setDevice = function (newTuya) { + tuya = newTuya; +} + +exports.hasDevice = function () { + var device = (tuya != undefined); + if (!device) { + console.error("TuyaStatus - Device not set"); + } + return device; +} + +exports.get = function (callback) { + if (this.hasDevice()) { + tuya.resolveIds().then(() => { + tuya.get().then(status => { + if (_DEBUG) { + console.log('Current Status: ' + status); + } + callback.call(this, status); + }); + }); + } +} + +exports.set = function (newState) { + if (this.hasDevice()) { + tuya.set({ + set: newState + }).then(result => { + if (_DEBUG) { + console.log('Result of setting status to ' + newState + ': ' + result); + } + + tuya.get().then(status => { + if (_DEBUG) { + console.log('New status: ' + status); + } + console.log(bmap(status)); + return; + }); + }); + } +} + +exports.getCurrent = function () { + var self = this; + self.get(function (status) { + console.log(bmap(status)); + }); +} + +exports.toggle = function () { + var self = this; + self.get(function (newStatus) { + self.set(!newStatus); + }) +} + +exports.on = function () { + var self = this; + tuya.resolveIds().then(() => { + self.set(true); + }); +} + +exports.off = function () { + var self = this; + tuya.resolveIds().then(() => { + self.set(false); + }); +} \ No newline at end of file diff --git a/tuya.js b/tuya.js new file mode 100644 index 0000000..3fbc173 --- /dev/null +++ b/tuya.js @@ -0,0 +1,85 @@ +/* + * Simple wrapper for tuyapi for use with openhab or command line +npm install codetheweb/tuyapi +node ohtuya.js args +arg format -ip 192.168.x.x -id 1231204564df -key dsf456sdf TOGGLE +args can be, ON, OFF, or TOGGLE. No arguement returns state +@todo set up js to log properly, sending to console messes up output. +@todo limit connection frequency seem to get connection errors +*/ + +const TuyaDevice = require('tuyapi'); +const TuyaStatus = require('./tuya-status'); +var args = require('yargs').argv; +var tuyaConnect = this; + +_DEBUG = false; +TuyaStatus.setDebug(_DEBUG); + +var switchStatus = args._[0]; +switchStatus = switchStatus.toLowerCase(); +var tuyaID = args.id; +var tuyaKey = args.key; +var tuyaIP = args.ip; +let tuya = undefined; + +exports.createDevice = function (tuyaID, tuyaKey, tuyaIP) { + if (tuyaID != undefined && tuyaKey != undefined) { + try { + var config = { + id: tuyaID + "", + key: tuyaKey + }; + if (tuyaIP != undefined) { + config.ip = tuyaIP; + } + if (_DEBUG) { + console.log(config); + } + return new TuyaDevice(config); + } catch (e) { + //console.error(e); + console.error(config); + } + } + return undefined; +}; + +exports.hasDevice = function () { + var device = (tuya != undefined); + if (!device) { + console.error("Tuya - Device not set"); + } + return device; +} + +exports.setStatus = function (newState) { + if (this.hasDevice()) { + if (_DEBUG) { + console.log('Status: ' + newState); + } + + if (newState == "toogle".toLowerCase()) { + TuyaStatus.toggle(); + } + if (newState == "on".toLowerCase()) { + TuyaStatus.on(); + } + if (newState == "off".toLowerCase()) { + TuyaStatus.off(); + } + } +} + +tuya = module.exports.createDevice(tuyaID, tuyaKey, tuyaIP); +TuyaStatus.setDevice(tuya); +if (switchStatus == "now".toLowerCase()) { + if (module.exports.hasDevice()) { + TuyaStatus.getCurrent(); + } +} else { + if (module.exports.hasDevice()) { + module.exports.setStatus(switchStatus); + } +} +