diff --git a/README.md b/README.md index 2674e4c..d978048 100755 --- a/README.md +++ b/README.md @@ -51,6 +51,9 @@ For outlets the value for `NEWSTATE` is either `true` for on or `false` for off. For outlets the additional state `stateOutletInUse` is available. The value for `NEWSTATE` is either `true` for on or `false` for off and can be changed by calling the url `http://yourHomebridgeServerIp:webhook_port/?accessoryId=theAccessoryIdToTrigger&stateOutletInUse=NEWSTATE` +## Fanv2 +For fanv2 the value for `NEWSTATE` is either `true` for on or `false` for off. + # Trigger action ## Switch @@ -65,6 +68,9 @@ For lights you can trigger a url of any system for switching the light on or off ## Outlet For outlets you can trigger a url of any system for switching the outlet on or off. +## Fanv2 +For fanv2 you can trigger a url of any system for switching the fanv2 on or off. + # Update a numeric accessory To update a numeric accessory you need to call the url `http://yourHomebridgeServerIp:webhook_port/?accessoryId=theAccessoryIdToUpdate&value=NEWVALUE` @@ -127,6 +133,14 @@ Setting of target position you can realize by send link to: open, 20%, 40%, 60% If you dont use callbacks to let your covering give feedback of current position back to homekit you can set "auto_set_current_position" to true. +# Fanv2 +To update a fanv2 you can update five different values: +* Rotation Speed (%): `http://yourHomebridgeServerIp:webhook_port/?accessoryId=theAccessoryIdToUpdate&speed=%s` (%s is replaced by fan's rotation speed) +* Swing Mode (DISABLED=0 / ENABLED=1): `http://yourHomebridgeServerIp:webhook_port/?accessoryId=theAccessoryIdToUpdate&swingMode=0 (or 1)` (To use this feature, "enableSwingModeControls" in confing must be set to true.) +* Rotation Direction (CLOCKWISE=0 / COUNTER_CLOCKWISE=1): `http://yourHomebridgeServerIp:webhook_port/?accessoryId=theAccessoryIdToUpdate&rotationDirection=0 (or 1)` +* Lock Physical Controls (DISABLED=0 / ENABLED=1): `http://yourHomebridgeServerIp:webhook_port/?accessoryId=theAccessoryIdToUpdate&lockstate=0 (or 1)` (To use this feature, "enableLockPhysicalControls" in confing must be set to true.) +* Target Fan State (MANUAL=0 / AUTO=1): `http://yourHomebridgeServerIp:webhook_port/?accessoryId=theAccessoryIdToUpdate&targetState=0 (or 1)`(To use this feature, "enableTargetStateControls" in confing must be set to true.) + # Configuration Example config.json: @@ -361,6 +375,49 @@ Example config.json: "close_body": "{ \"open\": false }", // (optional only for POST and PUT; use "close_form" for x-www-form-urlencoded JSON) "close_headers": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}" // (optional) } + ], + "fanv2s": [ + { + "id": "fanv2-1", + "name": "Fanv2-1", + "rejectUnauthorized": true, // (optional) + "on_url": "your url to switch the fanv2 on", + "on_method": "GET", + "on_body": "{ \"on\" : true }", + "on_headers": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "off_url": "your url to switch the fanv2 off", + "off_method": "GET", + "off_body": "{ \"off\" : true }", + "off_headers": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "speed_url": "your url to change the fanv2 rotation speed", + "speed_method": "GET", + "speed_body": "{ \"on\" : %statusPlaceholder, \"speed\" : %speedPlaceholder}", + "speed_headers": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "speed_factor":2.55, + "enableLockPhysicalControls": true, + "lock_url": "your url to lock the fanv2's physical controls", + "lock_method": "GET", + "lock_body": "{ \"physicalLock\": true }", + "lock_headers": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "unlock_url": "your url to unlock the fanv2's physical controls", + "unlock_method": "GET", + "unlock_body": "{ \"physicalLock\": false }", + "unlock_headers": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "enableTargetStateControls": true, + "target_state_url": "your url to change the fanv2's target state", + "target_state_method": "GET", + "target_state_body": "{ \"mode\": %targetState }", + "target_state_headers": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "enableSwingModeControls": true, + "swing_mode_url": "your url to change the fanv2's swing mode", + "swing_mode_method": "GET", + "swing_mode_body": "{ \"swing_mode\": %swingMode }", + "swing_mode_headers": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "rotation_direction_url": "your url to change the fanv2's rotation direction", + "rotation_direction_method": "GET", + "rotation_direction_body": "{ \"rotation_direction\": %rotationDirection }", + "rotation_direction_headers": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}" + } ] } ] diff --git a/config.schema.json b/config.schema.json index fffa32d..a3a2bae 100644 --- a/config.schema.json +++ b/config.schema.json @@ -946,6 +946,253 @@ } } } + }, + "fanv2s": { + "type": "array", + "title": "Fanv2", + "description": "Turn On and Off Fanv2 by triggering a URL of any system.", + "items": { + "title": "Fanv2s", + "type": "object", + "properties": { + "id": { + "title": "ID", + "type": "string", + "placeholder": "fanv2-1", + "required": false + }, + "name": { + "title": "Name", + "type": "string", + "placeholder": "Fanv2 1", + "required": false + }, + "rejectUnauthorized": { + "title": "Reject Unauthorized SSL Certificate", + "type": "boolean", + "placeholder": true, + "required": false + }, + "on_url": { + "title": "On URL", + "type": "string", + "placeholder": "your url to switch the fanv2 on", + "required": false + }, + "on_method": { + "title": "On Method", + "type": "string", + "placeholder": "GET", + "required": false + }, + "on_body": { + "title": "On Body", + "type": "string", + "placeholder": "{ \"on\" : true }", + "required": false + }, + "on_headers": { + "title": "On Headers", + "type": "string", + "placeholder": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "required": false + }, + "off_url": { + "title": "Off URL", + "type": "string", + "placeholder": "your url to switch the fanv2 off", + "required": false + }, + "off_method": { + "title": "Off Method", + "type": "string", + "placeholder": "GET", + "required": false + }, + "off_body": { + "title": "Off Body", + "type": "string", + "placeholder": "{ \"on\": false }", + "required": false + }, + "off_headers": { + "title": "Off Headers", + "type": "string", + "placeholder": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "required": false + }, + "speed_url": { + "title": "Speed URL", + "type": "string", + "placeholder": "your url to change the fanv2 rotation speed", + "required": false + }, + "speed_method": { + "title": "Speed Method", + "type": "string", + "placeholder": "GET", + "required": false + }, + "speed_body": { + "title": "Speed Body", + "type": "string", + "placeholder": "{ \"on\" : %statusPlaceholder, \"speed\" : %speedPlaceholder}", + "required": false + }, + "speed_headers": { + "title": "Speed Headers", + "type": "string", + "placeholder": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "required": false + }, + "speed_factor": { + "title": "Speed Factor", + "type": "number", + "placeholder": 2.55, + "required": false, + "typeahead": { + "source": [ + 2.55 + ] + } + }, + "enableLockPhysicalControls": { + "title": "Enable lock physical controls", + "type": "boolean", + "required": false + }, + "lock_url": { + "title": "Lock URL", + "type": "string", + "placeholder": "your url to lock the fanv2's physical controls", + "required": false + }, + "lock_method": { + "title": "Lock Method", + "type": "string", + "placeholder": "GET", + "required": false + }, + "lock_body": { + "title": "Lock Body", + "type": "string", + "placeholder": "{ \"physicalLock\": true }", + "required": false + }, + "lock_headers": { + "title": "Lock Headers", + "type": "string", + "placeholder": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "required": false + }, + "unlock_url": { + "title": "Unlock URL", + "type": "string", + "placeholder": "your url to unlock the fanv2's physical controls", + "required": false + }, + "unlock_method": { + "title": "Unlock Method", + "type": "string", + "placeholder": "GET", + "required": false + }, + "unlock_body": { + "title": "Unlock Body", + "type": "string", + "placeholder": "{ \"physicalLock\": false }", + "required": false + }, + "unlock_headers": { + "title": "Unlock Headers", + "type": "string", + "placeholder": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "required": false + }, + "enableTargetStateControls": { + "title": "Enable Target State Controls", + "type": "boolean", + "required": false + }, + "target_state_url": { + "title": "Target State URL", + "type": "string", + "placeholder": "your url to change the fanv2's target state", + "required": false + }, + "target_state_method": { + "title": "Target State Method", + "type": "string", + "placeholder": "GET", + "required": false + }, + "target_state_body": { + "title": "Target State Body", + "type": "string", + "placeholder": "{ \"mode\": %targetState }", + "required": false + }, + "target_state_headers": { + "title": "Target State Headers", + "type": "string", + "placeholder": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "required": false + }, + "enableSwingModeControls": { + "title": "Enable Swing Mode Controls", + "type": "boolean", + "required": false + }, + "swing_mode_url": { + "title": "Swing Mode URL", + "type": "string", + "placeholder": "your url to change the fanv2's swing mode", + "required": false + }, + "swing_mode_method": { + "title": "Swing Mode Method", + "type": "string", + "placeholder": "GET", + "required": false + }, + "swing_mode_body": { + "title": "Swing Mode Body", + "type": "string", + "placeholder": "{ \"swing_mode\": %swingMode }", + "required": false + }, + "swing_mode_headers": { + "title": "Swing Mode Headers", + "type": "string", + "placeholder": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "required": false + }, + "rotation_direction_url": { + "title": "Rotation Direction URL", + "type": "string", + "placeholder": "your url to change the fanv2's rotation direction", + "required": false + }, + "rotation_direction_method": { + "title": "Rotation Direction Method", + "type": "string", + "placeholder": "GET", + "required": false + }, + "rotation_direction_body": { + "title": "Rotation Direction Body", + "type": "string", + "placeholder": "{ \"rotation_direction\": %rotationDirection }", + "required": false + }, + "rotation_direction_headers": { + "title": "Rotation Direction Headers", + "type": "string", + "placeholder": "{\"Authorization\": \"Bearer ABCDEFGH\", \"Content-Type\": \"application/json\"}", + "required": false + } + } + } } } }, @@ -1288,6 +1535,60 @@ ] } ] + }, + { + "type": "section", + "title": "Fanv2", + "expandable": true, + "expanded": false, + "items": [ + { + "title": "Fanv2", + "type": "array", + "orderable": false, + "items": [ + "fanv2s[].id", + "fanv2s[].name", + "fanv2s[].rejectUnauthorized", + "fanv2s[].on_url", + "fanv2s[].on_method", + "fanv2s[].on_body", + "fanv2s[].on_headers", + "fanv2s[].off_url", + "fanv2s[].off_method", + "fanv2s[].off_body", + "fanv2s[].off_headers", + "fanv2s[].speed_url", + "fanv2s[].speed_method", + "fanv2s[].speed_body", + "fanv2s[].speed_headers", + "fanv2s[].speed_factor", + "fanv2s[].enableLockPhysicalControls", + "fanv2s[].lock_url", + "fanv2s[].lock_method", + "fanv2s[].lock_body", + "fanv2s[].lock_headers", + "fanv2s[].unlock_url", + "fanv2s[].unlock_method", + "fanv2s[].unlock_body", + "fanv2s[].unlock_headers", + "fanv2s[].enableTargetStateControls", + "fanv2s[].target_state_url", + "fanv2s[].target_state_method", + "fanv2s[].target_state_body", + "fanv2s[].target_state_headers", + "fanv2s[].enableSwingModeControls", + "fanv2s[].swing_mode_url", + "fanv2s[].swing_mode_method", + "fanv2s[].swing_mode_body", + "fanv2s[].swing_mode_headers", + "fanv2s[].rotation_direction_url", + "fanv2s[].rotation_direction_method", + "fanv2s[].rotation_direction_body", + "fanv2s[].rotation_direction_headers" + ] + } + ] } ] } diff --git a/index.js b/index.js index 9e3ad6c..5571460 100755 --- a/index.js +++ b/index.js @@ -10,6 +10,7 @@ var HttpWebHookGarageDoorOpenerAccessory = require('./src/homekit/accessories/Ht var HttpWebHookStatelessSwitchAccessory = require('./src/homekit/accessories/HttpWebHookStatelessSwitchAccessory'); var HttpWebHookLockMechanismAccessory = require('./src/homekit/accessories/HttpWebHookLockMechanismAccessory'); var HttpWebHookWindowCoveringAccessory = require('./src/homekit/accessories/HttpWebHookWindowCoveringAccessory'); +var HttpWebHookFanv2Accessory = require('./src/homekit/accessories/HttpWebHookFanv2Accessory'); module.exports = function(homebridge) { homebridge.registerPlatform("homebridge-http-webhooks", "HttpWebHooks", HttpWebHooksPlatform); @@ -24,4 +25,5 @@ module.exports = function(homebridge) { homebridge.registerAccessory("homebridge-http-webhooks", "HttpWebHookStatelessSwitch", HttpWebHookStatelessSwitchAccessory); homebridge.registerAccessory("homebridge-http-webhooks", "HttpWebHookLockMechanism", HttpWebHookLockMechanismAccessory); homebridge.registerAccessory("homebridge-http-webhooks", "HttpWebHookWindowCovering", HttpWebHookWindowCoveringAccessory); + homebridge.registerAccessory("homebridge-http-webhooks", "HttpWebHookFanv2", HttpWebHookFanv2Accessory); }; \ No newline at end of file diff --git a/src/homekit/HttpWebHooksPlatform.js b/src/homekit/HttpWebHooksPlatform.js index 15ea5bb..522c21b 100644 --- a/src/homekit/HttpWebHooksPlatform.js +++ b/src/homekit/HttpWebHooksPlatform.js @@ -12,6 +12,7 @@ var HttpWebHookGarageDoorOpenerAccessory = require('./accessories/HttpWebHookGar var HttpWebHookStatelessSwitchAccessory = require('./accessories/HttpWebHookStatelessSwitchAccessory'); var HttpWebHookLockMechanismAccessory = require('./accessories/HttpWebHookLockMechanismAccessory'); var HttpWebHookWindowCoveringAccessory = require('./accessories/HttpWebHookWindowCoveringAccessory'); +var HttpWebHookFanv2Accessory = require('./accessories/HttpWebHookFanv2Accessory'); var Service, Characteristic; @@ -37,6 +38,7 @@ function HttpWebHooksPlatform(log, config, homebridge) { this.statelessSwitches = config["statelessswitches"] || []; this.windowCoverings = config["windowcoverings"] || []; this.lockMechanisms = config["lockmechanisms"] || []; + this.fanv2s = config["fanv2s"] || []; this.server = new Server(Service, Characteristic, this, config); }; @@ -99,6 +101,11 @@ HttpWebHooksPlatform.prototype.accessories = function(callback) { accessories.push(lockMechanismAccessory); } + for (var i = 0; i < this.fanv2s.length; i++) { + var fanv2Accessory = new HttpWebHookFanv2Accessory(Service, Characteristic, this, this.fanv2s[i]); + accessories.push(fanv2Accessory); + } + this.server.setAccessories(accessories); this.server.start(); diff --git a/src/homekit/accessories/HttpWebHookFanv2Accessory.js b/src/homekit/accessories/HttpWebHookFanv2Accessory.js new file mode 100644 index 0000000..3379c55 --- /dev/null +++ b/src/homekit/accessories/HttpWebHookFanv2Accessory.js @@ -0,0 +1,318 @@ +const { parse } = require('node-persist'); +const Constants = require('../../Constants'); +const Util = require('../../Util'); + +function HttpWebHookFanv2Accessory(ServiceParam, CharacteristicParam, platform, fanv2Config) { + Service = ServiceParam; + Characteristic = CharacteristicParam; + + this.platform = platform; + this.log = platform.log; + this.storage = platform.storage; + + this.id = fanv2Config["id"]; + this.type = "fanv2"; + this.name = fanv2Config["name"]; + this.rejectUnauthorized = fanv2Config["rejectUnauthorized"] === undefined ? true : + fanv2Config["rejectUnauthorized"] === true; + + this.onURL = fanv2Config["on_url"] || ""; + this.onMethod = fanv2Config["on_method"] || "GET"; + this.onBody = fanv2Config["on_body"] || ""; + this.onForm = fanv2Config["on_form"] || ""; + this.onHeaders = fanv2Config["on_headers"] || "{}"; + this.offURL = fanv2Config["off_url"] || ""; + this.offMethod = fanv2Config["off_method"] || "GET"; + this.offBody = fanv2Config["off_body"] || ""; + this.offForm = fanv2Config["off_form"] || ""; + this.offHeaders = fanv2Config["off_headers"] || "{}"; + this.speedURL = fanv2Config["speed_url"] || ""; + this.speedMethod = fanv2Config["speed_method"] || "GET"; + this.speedBody = fanv2Config["speed_body"] || ""; + this.speedForm = fanv2Config["speed_form"] || ""; + this.speedHeaders = fanv2Config["speed_headers"] || "{}"; + this.speedFactor = fanv2Config["speed_factor"] || 1; + + this.enableLockPhysicalControls = fanv2Config["enableLockPhysicalControls"] || false; + this.lockURL = fanv2Config["lock_url"] || ""; + this.lockMethod = fanv2Config["lock_method"] || "GET"; + this.lockBody = fanv2Config["lock_body"] || ""; + this.lockForm = fanv2Config["lock_form"] || ""; + this.lockHeaders = fanv2Config["lock_headers"] || "{}"; + this.unlockURL = fanv2Config["unlock_url"] || ""; + this.unlockMethod = fanv2Config["unlock_method"] || "GET"; + this.unlockBody = fanv2Config["unlock_body"] || ""; + this.unlockForm = fanv2Config["unlock_form"] || ""; + this.unlockHeaders = fanv2Config["unlock_headers"] || "{}"; + + this.enableTargetStateControls = fanv2Config["enableTargetStateControls"] || false; + this.targetStateURL = fanv2Config["target_state_url"] || ""; + this.targetStateMethod = fanv2Config["target_state_method"] || "GET"; + this.targetStateBody = fanv2Config["target_state_body"] || ""; + this.targetStateForm = fanv2Config["target_state_form"] || ""; + this.targetStateHeaders = fanv2Config["target_state_headers"] || "{}"; + + this.enableSwingModeControls = fanv2Config["enableSwingModeControls"] || false; + this.swingModeURL = fanv2Config["swing_mode_url"] || ""; + this.swingModeMethod = fanv2Config["swing_mode_method"] || "GET"; + this.swingModeBody = fanv2Config["swing_mode_body"] || ""; + this.swingModeForm = fanv2Config["swing_mode_form"] || ""; + this.swingModeHeaders = fanv2Config["swing_mode_headers"] || "{}"; + + this.rotationDirectionURL = fanv2Config["rotation_direction_url"] || ""; + this.rotationDirectionMethod = fanv2Config["rotation_direction_method"] || "GET"; + this.rotationDirectionBody = fanv2Config["rotation_direction_body"] || ""; + this.rotationDirectionForm = fanv2Config["rotation_direction_form"] || ""; + this.rotationDirectionHeaders = fanv2Config["rotation_direction_headers"] || "{}"; + + this.informationService = new Service.AccessoryInformation(); + this.informationService.setCharacteristic(Characteristic.Manufacturer, "HttpWebHooksPlatform"); + this.informationService.setCharacteristic(Characteristic.Model, "HttpWebHookFanv2Accessory-" + this.name); + this.informationService.setCharacteristic(Characteristic.SerialNumber, "HttpWebHookFanv2Accessory-" + this.id); + + this.service = new Service.Fanv2(this.name); + this.service.getCharacteristic(Characteristic.Active).on('get', this.getState.bind(this)).on('set', this.setState.bind(this)); + this.service.getCharacteristic(Characteristic.RotationSpeed).on('get', this.getSpeed.bind(this)).on('set', this.setSpeed.bind(this)); + this.service.getCharacteristic(Characteristic.RotationDirection).on('get', this.getRotationDirection.bind(this)).on('set', this.setRotationDirection.bind(this)); + + if (this.enableLockPhysicalControls) { + this.service.getCharacteristic(Characteristic.LockPhysicalControls).on('get', this.getLockState.bind(this)).on('set', this.setLockState.bind(this)); + } + + if (this.enableTargetStateControls) { + this.service.getCharacteristic(Characteristic.TargetFanState).on('get', this.getTargetState.bind(this)).on('set', this.setTargetState.bind(this)); + } + + if (this.enableSwingModeControls) { + this.service.getCharacteristic(Characteristic.SwingMode).on('get', this.getSwingMode.bind(this)).on('set', this.setSwingMode.bind(this)); + } +} + +HttpWebHookFanv2Accessory.prototype.changeFromServer = function (urlParams) { + var cachedState = this.storage.getItemSync("http-webhook-" + this.id); + if (cachedState === undefined) { + cachedState = false; + } + if (urlParams.state != cachedState) { + this.log("Change state for fanv2 to '%d'.", urlParams.state); + this.service.getCharacteristic(Characteristic.Active).updateValue((urlParams.state == "true"), undefined, Constants.CONTEXT_FROM_WEBHOOK); + } + if (urlParams.speed != null) { + var cachedSpeed = this.storage.getItemSync("http-webhook-speed-" + this.id); + var speed = parseInt(urlParams.speed); + if (cachedSpeed != speed) { + this.log("Change speed for fanv2 to '%d'.", speed); + this.service.getCharacteristic(Characteristic.RotationSpeed).updateValue(speed, undefined, Constants.CONTEXT_FROM_WEBHOOK); + } + } + if (urlParams.swingMode != null && this.enableSwingModeControls) { + var cachedSwingMode = this.storage.getItemSync("http-webhook-swingmode-" + this.id); + var swingMode = parseInt(urlParams.swingMode); + if (cachedSwingMode != swingMode) { + this.log("Change swing mode for fanv2 to '%d'.", swingMode); + this.service.getCharacteristic(Characteristic.SwingMode).updateValue(swingMode, undefined, Constants.CONTEXT_FROM_WEBHOOK); + } + } + if (urlParams.rotationDirection != null) { + var cachedRotationDirection = this.storage.getItemSync("http-webhook-rotationdirection-" + this.id); + var rotationDirection = parseInt(urlParams.rotationDirection); + if (cachedRotationDirection != rotationDirection) { + this.log("Change rotation direction for fanv2 to '%d'.", rotationDirection); + this.service.getCharacteristic(Characteristic.RotationDirection).updateValue(rotationDirection, undefined, Constants.CONTEXT_FROM_WEBHOOK); + } + } + if (urlParams.lockstate != null && this.enableLockPhysicalControls) { + var cachedLockstate = this.storage.getItemSync("http-webhook-lockstate-" + this.id); + var lockstate = parseInt(urlParams.lockState); + if (cachedLockstate != lockstate) { + this.log("Change lock state for fanv2 to '%d'.", lockstate); + this.service.getCharacteristic(Characteristic.LockPhysicalControls).updateValue(lockstate, undefined, Constants.CONTEXT_FROM_WEBHOOK); + } + } + if (urlParams.targetState != null && this.enableTargetStateControls) { + var cachedTargetstate = this.storage.getItemSync("http-webhook-targetstate-" + this.id); + var targetState = parseInt(urlParams.targetState); + if (cachedTargetstate != targetState) { + this.log("Change target state for fanv2 to '%d'.", targetState); + this.service.getCharacteristic(Characteristic.TargetFanState).updateValue(targetState, undefined, Constants.CONTEXT_FROM_WEBHOOK); + } + } + return { + "success": true + }; +} + +HttpWebHookFanv2Accessory.prototype.getState = function (callback) { + this.log.debug("Getting current state for '%s'...", this.id); + var state = this.storage.getItemSync("http-webhook-" + this.id); + if (state === undefined) { + state = false; + } + callback(null, state); +}; + +HttpWebHookFanv2Accessory.prototype.setState = function (powerOn, callback, context) { + this.log("Fanv2 state for '%s'...", this.id); + this.storage.setItemSync("http-webhook-" + this.id, powerOn); + var urlToCall = this.onURL; + var urlMethod = this.onMethod; + var urlBody = this.onBody; + var urlForm = this.onForm; + var urlHeaders = this.onHeaders; + if (!powerOn) { + urlToCall = this.offURL; + urlMethod = this.offMethod; + urlBody = this.offBody; + urlForm = this.offForm; + urlHeaders = this.offHeaders; + } + Util.callHttpApi(this.log, urlToCall, urlMethod, urlBody, urlForm, urlHeaders, this.rejectUnauthorized, callback, context); +}; + +HttpWebHookFanv2Accessory.prototype.getSpeed = function (callback) { + this.log.debug("Getting current speed for '%s'...", this.id); + var state = this.storage.getItemSync("http-webhook-" + this.id); + if (state === undefined) { + state = false; + } + var speed = 0; + if (state) { + speed = this.storage.getItemSync("http-webhook-speed-" + this.id); + if (speed === undefined) { + speed = 100; + } + } + callback(null, parseInt(speed)); +}; + +HttpWebHookFanv2Accessory.prototype.setSpeed = function (speed, callback, context) { + this.log("Fanv2 rotation speed for '%s'...", this.id); + var newState = speed > 0; + this.storage.setItemSync("http-webhook-" + this.id, newState); + this.storage.setItemSync("http-webhook-speed-" + this.id, speed); + var speedFactor = this.speedFactor; + var speedToSet = Math.ceil(speed * speedFactor); + var urlToCall = this.replaceVariables(this.speedURL, newState, speedToSet); + var urlMethod = this.speedMethod; + var urlBody = this.speedBody; + var urlForm = this.speedForm; + var urlHeaders = this.speedHeaders; + + if (urlForm) { + urlForm = this.replaceVariables(urlForm, newState, speedToSet); + } + else if (urlBody) { + urlBody = this.replaceVariables(urlBody, newState, speedToSet); + } + + Util.callHttpApi(this.log, urlToCall, urlMethod, urlBody, urlForm, urlHeaders, this.rejectUnauthorized, callback, context); +}; + +HttpWebHookFanv2Accessory.prototype.getLockState = function (callback) { + this.log.debug("Getting current lock state for '%s'...", this.id); + var lockstate = this.storage.getItemSync("http-webhook-lockstate-" + this.id); + if (lockstate === undefined) { + lockstate = false; + } + callback(null, lockstate); +}; + +HttpWebHookFanv2Accessory.prototype.setLockState = function (lockState, callback, context) { + this.log("Fanv2 lock state for '%s'...", this.id); + this.storage.setItemSync("http-webhook-lockstate-" + this.id, lockState); + var urlToCall = this.lockURL; + var urlMethod = this.lockMethod; + var urlBody = this.lockBody; + var urlForm = this.lockForm; + var urlHeaders = this.lockHeaders; + if (!lockState) { + urlToCall = this.unlockURL; + urlMethod = this.unlockMethod; + urlBody = this.unlockBody; + urlForm = this.unlockForm; + urlHeaders = this.unlockHeaders; + } + Util.callHttpApi(this.log, urlToCall, urlMethod, urlBody, urlForm, urlHeaders, this.rejectUnauthorized, callback, context); +}; + +HttpWebHookFanv2Accessory.prototype.getTargetState = function (callback) { + this.log.debug("Getting current target state for '%s'...", this.id); + var targetState = this.storage.getItemSync("http-webhook-targetstate-" + this.id); + if (targetState === undefined) { + targetState = false; + } + callback(null, targetState); +}; + +HttpWebHookFanv2Accessory.prototype.setTargetState = function (targetState, callback, context) { + this.log("Fanv2 target state for '%s'...", this.id); + this.storage.setItemSync("http-webhook-targetstate-" + this.id, targetState); + var state = this.storage.getItemSync("http-webhook-" + this.id); + if (state === undefined) { + state = false; + } + var urlToCall = this.targetStateURL.replace("%targetState", targetState); + var urlMethod = this.targetStateMethod; + var urlBody = this.targetStateBody.replace("%targetState", targetState);; + var urlForm = this.targetStateForm; + var urlHeaders = this.targetStateHeaders; + + Util.callHttpApi(this.log, urlToCall, urlMethod, urlBody, urlForm, urlHeaders, this.rejectUnauthorized, callback, context); +}; + +HttpWebHookFanv2Accessory.prototype.getSwingMode = function (callback) { + this.log.debug("Getting current swing mode for '%s'...", this.id); + var swingMode = this.storage.getItemSync("http-webhook-swingmode-" + this.id); + if (swingMode === undefined) { + swingMode = false; + } + callback(null, swingMode); +}; + +HttpWebHookFanv2Accessory.prototype.setSwingMode = function (swingMode, callback, context) { + this.log("Fanv2 swing mode for '%s'...", this.id); + this.storage.setItemSync("http-webhook-swingmode-" + this.id, swingMode); + var state = this.storage.getItemSync("http-webhook-" + this.id); + if (state === undefined) { + state = false; + } + var urlToCall = this.swingModeURL.replace("%swingMode", swingMode); + var urlMethod = this.swingModeMethod; + var urlBody = this.swingModeBody.replace("%swingMode", swingMode);; + var urlForm = this.swingModeForm; + var urlHeaders = this.swingModeHeaders; + + Util.callHttpApi(this.log, urlToCall, urlMethod, urlBody, urlForm, urlHeaders, this.rejectUnauthorized, callback, context); +}; + +HttpWebHookFanv2Accessory.prototype.getRotationDirection = function (callback) { + this.log.debug("Getting current rotation direction for '%s'...", this.id); + var rotationDirection = this.storage.getItemSync("http-webhook-rotationdirection-" + this.id); + if (rotationDirection === undefined) { + rotationDirection = false; + } + callback(null, rotationDirection); +}; + +HttpWebHookFanv2Accessory.prototype.setRotationDirection = function (rotationDirection, callback, context) { + this.log("Fanv2 rotation direction for '%s'...", this.id); + this.storage.setItemSync("http-webhook-rotationdirection-" + this.id, rotationDirection); + var urlToCall = this.rotationDirectionURL.replace("%rotationDirection", rotationDirection); + var urlMethod = this.rotationDirectionMethod; + var urlBody = this.rotationDirectionBody.replace("%rotationDirection", rotationDirection);; + var urlForm = this.rotationDirectionForm; + var urlHeaders = this.rotationDirectionHeaders; + + Util.callHttpApi(this.log, urlToCall, urlMethod, urlBody, urlForm, urlHeaders, this.rejectUnauthorized, callback, context); +}; + +HttpWebHookFanv2Accessory.prototype.replaceVariables = function (text, state, speed) { + return text.replace("%statusPlaceholder", state).replace("%speedPlaceholder", speed); +}; + + +HttpWebHookFanv2Accessory.prototype.getServices = function () { + return [this.service, this.informationService]; +}; + +module.exports = HttpWebHookFanv2Accessory; \ No newline at end of file