Socket
Socket
Sign inDemoInstall

node-red-contrib-deconz

Package Overview
Dependencies
53
Maintainers
2
Versions
144
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.3.8 to 2.3.9

6

CHANGELOG.md

@@ -10,2 +10,8 @@ # Changelog

## [2.3.9] - 2023-01-04 ![Relative date](https://img.shields.io/date/1672868800?label=)
### Fixed
- Fix UI not loading on Safari again. (#217) @Zehir
## [2.3.8] - 2022-12-21 ![Relative date](https://img.shields.io/date/1671643824?label=)

@@ -12,0 +18,0 @@

4

package.json
{
"name": "node-red-contrib-deconz",
"version": "2.3.8",
"version": "2.3.9",
"description": "deCONZ connectivity nodes for node-red",

@@ -83,4 +83,4 @@ "keywords": [

"engines": {
"node": ">=12.0.0"
"node": ">=14"
}
}
# Node-Red deCONZ
[![GitHub](https://img.shields.io/github/license/deconz-community/node-red-contrib-deconz)](https://github.com/deconz-community/node-red-contrib-deconz/blob/main/LICENSE)
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/deconz-community/node-red-contrib-deconz/NPM%20Publish)](https://github.com/deconz-community/node-red-contrib-deconz/actions)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/deconz-community/node-red-contrib-deconz/npm-publish.yml?branch=main)](https://github.com/deconz-community/node-red-contrib-deconz/actions)
[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/deconz-community/node-red-contrib-deconz?include_prereleases&label=github&sort=semver)](https://github.com/deconz-community/node-red-contrib-deconz/releases)

@@ -18,10 +18,10 @@ [![npm](https://img.shields.io/npm/v/node-red-contrib-deconz)](https://www.npmjs.com/package/node-red-contrib-deconz)

__This new version requires Node-Red version 1.2.9 or newer.__
**This new version requires Node-Red version 1.2.9 or newer.**
Some new features ([Changelog](https://github.com/deconz-community/node-red-contrib-deconz/blob/master/CHANGELOG.md)):
* Multiple device selection.
* Select device using [queries](https://deconz-community.github.io/node-red-contrib-deconz/device_queries/).
* Multiple commands at once.
* Query multiple devices and merge the result.
- Multiple device selection.
- Select device using [queries](https://deconz-community.github.io/node-red-contrib-deconz/device_queries/).
- Multiple commands at once.
- Query multiple devices and merge the result.

@@ -40,7 +40,7 @@ ### Migrate from 1.3.4

* deconz-in: A node to subscribe to deCONZ events.
* deconz-get: get state of device or group.
* deconz-out: send actions or data to device or group.
* deconz-battery: get battery status of device
* deconz-event: get all deconz events
- deconz-in: A node to subscribe to deCONZ events.
- deconz-get: get state of device or group.
- deconz-out: send actions or data to device or group.
- deconz-battery: get battery status of device
- deconz-event: get all deconz events

@@ -47,0 +47,0 @@ [![Flow sample](https://raw.githubusercontent.com/deconz-community/node-red-contrib-deconz/master/readme/flow_sample.png)](https://raw.githubusercontent.com/deconz-community/node-red-contrib-deconz/master/readme/flow_sample.png)

@@ -1,2 +0,2 @@

class DeconzEditor{constructor(node,options={}){this.node=node,this.options=options}get elements(){return{}}get NRCD(){return"node-red-contrib-deconz"}findElements(){this.$elements={},Object.keys(this.elements).forEach(k=>{this.$elements[k]=this.findElement(this.elements[k])})}findElement(identifier){return"#"!==identifier.charAt(0)&&"."!==identifier.charAt(0)&&(identifier="#"+identifier),$(identifier)}async init(){this.findElements()}async connect(){}sendError(msg,timeout=1e4){let myNotification=RED.notify(msg,{timeout:timeout,type:"error",buttons:[{text:"Ok",class:"primary",click:()=>myNotification.close()}]})}getIcon(icon,includeClass=!1){return"deconz"===icon?"icons/node-red-contrib-deconz/icon-color.png":"homekit"===icon?"icons/node-red-contrib-deconz/homekit-logo.png":RED.nodes.fontAwesome.getIconList().includes("fa-"+icon)?`${includeClass?"fa ":""}fa-`+icon:icon}createIconElement(icon,container,isLarge=!1){if("fa-"===icon.substr(0,3)){if(RED.nodes.fontAwesome.getIconUnicode(icon))return void $("<i/>").appendTo(container).addClass("fa "+icon+(isLarge?" fa-lg":""));icon=RED.settings.apiRootUrl+"icons/node-red/arrow-in.svg"}$("<div/>").appendTo(container).css("backgroundImage","url("+icon+")")}getI18n(prefix,suffix,data={}){let _path=prefix;suffix&&(_path+="."+suffix),data.defaultValue="_deconz_undefined_";prefix=RED._(_path,data);if("_deconz_undefined_"!==prefix)return prefix}async generateSimpleListField(container,options){var input=$("<select/>",{id:options.id});if(options.choices)for(var[key,value]of options.choices)input.append($("<option/>").attr("value",key).html(RED._(value)));var row=await this.generateInputWithLabel(input,options);return container.append(row),void 0!==options.currentValue&&input.val(options.currentValue),input}async generateTypedInput(id,placeholder){placeholder=$("<input/>",{id:id,placeholder:RED._(placeholder)}),id=$("<input/>",{id:id+"_type",type:"hidden"});return placeholder.append(id),placeholder}async initTypedInput(input,options){options=$.extend({addDefaultTypes:!0,displayOnlyIcon:!1,value:{},width:"200px"},options);var typedInputOptions=$.extend({types:["msg","flow","global"]},options.typedInput);if(typedInputOptions.typeField=options.typeId,options.addDefaultTypes)for(var type of["msg","flow","global","jsonata"])typedInputOptions.types.includes(type)||typedInputOptions.types.push(type);if(options.displayOnlyIcon){let that=this;var valueLabel=function(a,b){let typeDefinition;for(const type of this.typeList)"object"==typeof type&&type.value===this.propertyType&&(typeDefinition=type);void 0!==typeDefinition&&void 0!==typeDefinition.icon&&(this.oldValue=this.input.val(),this.input.val(""),this.valueLabelContainer.hide(),that.createIconElement(typeDefinition.icon,this.selectLabel),this.selectTrigger.addClass("red-ui-typedInput-full-width"),this.selectLabel.show())};for(let type of typedInputOptions.types)"string"!=typeof type&&(type.hasValue=!0,type.valueLabel=valueLabel)}input.typedInput(typedInputOptions),void 0!==options.width&&input.typedInput("width",options.width),options.value&&(void 0!==options.value.type&&input.typedInput("type",options.value.type),void 0!==options.value.value)&&input.typedInput("value",options.value.value)}async generateTypedInputField(container,options){var input=await this.generateTypedInput(options.id,this.getI18n(options.i18n,"placeholder")),row=await this.generateInputWithLabel(input,options);return container.append(row),await this.initTypedInput(input,options),input}async generateDoubleTypedInputField(container,optionsFirst,optionsSecond){var inputFirst=await this.generateTypedInput(optionsFirst.id,optionsFirst.placeholder),row=await this.generateInputWithLabel(inputFirst,optionsFirst),inputSecond=await this.generateTypedInput(optionsSecond.id,optionsSecond.placeholder);row.append(inputSecond),container.append(row),optionsFirst.displayOnlyIcon=!0,optionsFirst.width="50px",optionsSecond.width="150px",await this.initTypedInput(inputFirst,optionsFirst),await this.initTypedInput(inputSecond,optionsSecond)}generateTypedInputType(i18n,name,data={}){if(data.value=name,void 0===data.label&&(data.label=this.getI18n(i18n,`options.${name}.label`,{})||name),!1!==data.icon&&void 0===data.icon&&(data.icon=this.getIcon(this.getI18n(i18n,`options.${name}.icon`))),data.icon&&"fa-"===data.icon.substr(0,3)&&(data.icon="fa "+data.icon),Array.isArray(data.subOptions)){Array.isArray(data.options)||(data.options=[]);for(const opt of data.subOptions)data.options.push(this.generateTypedInputType(i18n+".options."+name,"string"==typeof opt?opt:opt.name,{icon:!1}))}return data}async generateCheckboxField(container,options){var input=$("<input/>",{id:options.id,type:"checkbox",style:"display: table-cell; width: 14px;vertical-align: top;margin-right: 5px",checked:options.currentValue}),input=await this.generateInputWithLabel(input,options);input.append($("<span/>").html(RED._(options.descText)).css("display","table-cell")),container.append(input)}async generateInputWithLabel(input,options={}){var labelElement,row=$("<div/>",{class:"form-row",style:"padding:5px;margin:0;display:table;min-width:420px;"}),inputID=input.attr("id");return inputID&&((labelElement=$("<label/>")).attr("for",inputID),labelElement.attr("class","l-width"),labelElement.attr("style","display:table-cell;"),void 0===options.title&&(options.title=this.getI18n(options.i18n,"title")),options.title&&labelElement.attr("title",this.getI18n(options.i18n,"title")),void 0===options.icon&&(options.icon=this.getI18n(options.i18n,"icon")),options.icon&&(this.createIconElement(this.getIcon(options.icon),labelElement),labelElement.append("&nbsp;")),void 0===options.label&&(options.label=this.getI18n(options.i18n,"label")),options.label&&labelElement.append(`<span>${options.label}</span>`),row.append(labelElement)),input.css("display","table-cell"),row.append(input),row}async generateHR(container,topBottom="5px",leftRight="50px"){container.append(`<hr style="margin: ${topBottom} ${leftRight};">`)}async generateSeparator(container,label){container.append(`<div class="separator">${RED._(label)}</div>`)}static versionCompare(v1,v2,options={}){const lexicographical=options&&options.lexicographical;options=options&&options.zeroExtend;let v1parts=v1.split("."),v2parts=v2.split(".");function isValidPart(x){return(lexicographical?/^\d+[A-Za-z]*$/:/^\d+$/).test(x)}if(!v1parts.every(isValidPart)||!v2parts.every(isValidPart))return NaN;if(options){for(;v1parts.length<v2parts.length;)v1parts.push("0");for(;v2parts.length<v1parts.length;)v2parts.push("0")}lexicographical||(v1parts=v1parts.map(Number),v2parts=v2parts.map(Number));for(let i=0;i<v1parts.length;++i){if(v2parts.length===i)return 1;if(v1parts[i]!==v2parts[i])return v1parts[i]>v2parts[i]?1:-1}return v1parts.length!==v2parts.length?-1:0}}class DeconzMainEditor extends DeconzEditor{constructor(node,options={}){if(super(node,$.extend(!0,{have:{statustext:!0,query:!0,device:!0,output_rules:!1,commands:!1,specific:!1},device:{batteryFilter:!1},output_rules:{format:{single:!0,array:!1,sum:!1,average:!1,min:!1,max:!1},type:{attribute:!0,state:!0,config:!0,homekit:!1,scene_call:!1}},commands:{type:{deconz_state:!0,homekit:!0,custom:!0,pause:!0}},specific:{api:{},output:{},server:{}}},options)),this.subEditor={},this.initDone=!1,this.options.have.statustext&&(this.subEditor.statustext=new DeconzStatusTextEditor(this.node,this.options.statustext)),this.options.have.device&&(this.subEditor.device=new DeconzDeviceEditor(this.node,this.options.device)),this.options.have.query&&(this.subEditor.query=new DeconzQueryEditor(this.node,this.options.query)),this.options.have.specific)switch(this.node.type){case"deconz-api":this.subEditor.specific=new DeconzSpecificApiEditor(this.node,this.options.specific.api);break;case"deconz-output":this.subEditor.specific=new DeconzSpecificOutputEditor(this.node,this.options.specific.output);break;case"deconz-server":this.subEditor.specific=new DeconzSpecificServerEditor(this.node,this.options.specific.server)}this.options.have.output_rules&&(this.subEditor.output_rules=new DeconzOutputRuleListEditor(this.node,this.options.output_rules)),this.options.have.commands&&(this.subEditor.commands=new DeconzCommandListEditor(this.node,this.options.commands))}get elements(){return{tipBox:"node-input-tip-box",server:"node-input-server"}}async configurationMigration(){if(!((this.node.config_version||0)>=this.node._def.defaults.config_version.value)){var config={};for(const key of Object.keys(this.node._def.defaults))config[key]=this.node[key];var data={id:this.node.id,type:this.node.type,config:JSON.stringify(config)};let errorMsg="Error while migrating the configuration of the node from version "+(this.node.config_version||0)+" to version "+this.node._def.defaults.config_version.value+".";data=await $.getJSON(this.NRCD+"/configurationMigration",data).catch((t,u)=>{this.$elements.tipBox.append(`<div class="form-tips form-warning"><p>Migration errors:</p><p>${errorMsg}</p></div>`)});if(data&&!data.notNeeded){if(data.new)for(var[key,value]of Object.entries(data.new))this.node[key]=value;if(data.delete&&Array.isArray(data.delete))for(const key of data.delete)delete this.node[key];var mapI18N=msg=>"node-red-contrib-deconz"===msg.substr(0,23)?RED._(msg):msg;data.errors&&Array.isArray(data.errors)&&0<data.errors.length&&this.$elements.tipBox.append('<div class="form-tips form-warning"><p>Migration errors:</p><ul>'+`<li>${data.errors.map(mapI18N).join("</li><li>")}</li>`+"</ul></div>"),data.info&&Array.isArray(data.info)&&0<data.info.length&&this.$elements.tipBox.append('<div class="form-tips"><p>Migration info:</p><ul>'+`<li>${data.info.map(mapI18N).join("</li><li>")}</li>`+"</ul></div>")}}}async init(){await new Promise(resolve=>setTimeout(resolve,100)),await super.init(),await this.configurationMigration(),this.initPromises=[];for(const editor of Object.values(this.subEditor))this.initPromises.push(editor.init(this));await Promise.all(this.initPromises),this.initDone=!0,delete this.initPromises;var connectPromises=[];for(const editor of Object.values(this.subEditor))connectPromises.push(editor.connect());await Promise.all(connectPromises)}get serverNode(){return"deconz-server"===this.node.type?this.node:RED.nodes.node(this.$elements.server.val())}async isInitialized(){this.initDone||await Promise.all(this.initPromises)}async updateQueryDeviceDisplay(options){var type=this.subEditor.query.$elements.select.typedInput("type");switch(type){case"device":await this.subEditor.device.updateList(options);break;case"json":case"jsonata":this.subEditor.query.$elements.select.typedInput("validate")&&await this.subEditor.query.updateList(options)}await this.subEditor.device.display("device"===type),await this.subEditor.query.display("device"!==type)}oneditsave(){var newRules;this.options.have.output_rules&&(newRules=this.subEditor.output_rules.value,this.node.outputs=newRules.length,this.node.output_rules=newRules),this.options.have.commands&&(this.node.commands=this.subEditor.commands.value),this.options.have.specific&&(this.node.specific=this.subEditor.specific.value)}}class DeconzStatusTextEditor extends DeconzEditor{constructor(node,options={}){super(node,$.extend({allowedTypes:["msg","jsonata"]},options))}get elements(){return{statustext:"node-input-statustext"}}async init(mainEditor){await super.init(),this.mainEditor=mainEditor,this.initTypedInput()}initTypedInput(){var options=[];this.mainEditor.options.have.statustext&&options.push({value:"auto",label:RED._(this.NRCD+"/server:editor.inputs.statustext.options.auto"),icon:`icons/${this.NRCD}/icon-color.png`,hasValue:!1}),this.$elements.statustext.typedInput({type:"auto",types:options.concat(this.options.allowedTypes),typeField:`#${this.elements.statustext}_type`})}}class DeconzDeviceListEditor extends DeconzEditor{constructor(node,options={}){super(node,options)}get xhrURL(){return this.NRCD+"/itemlist"}get xhrParams(){return{controllerID:this.mainEditor.serverNode.id,forceRefresh:this.options.refresh}}async display(display=!0){if(this.$elements.showHide)return display?this.$elements.showHide.show():this.$elements.showHide.hide(),this.$elements.showHide.promise()}async getItems(options,xhrParams){xhrParams.forceRefresh=options.refresh;xhrParams=await $.getJSON(this.xhrURL,xhrParams).catch((t,u)=>{this.sendError(400===t.status&&t.responseText?t.responseText:u.toString())});if(!xhrParams||!xhrParams.error_message)return this.formatItemList(xhrParams.items,options.keepOnlyMatched);console.warn(xhrParams.error_message),RED.notify("Warning : "+xhrParams.error_message,{type:"warning",timeout:1e4})}async updateList(options){var list,params;options=$.extend({refresh:!0},options),this.mainEditor.serverNode&&(list=this.$elements.list,params=this.xhrParams,!0===this.options.batteryFilter&&(options.keepOnlyMatched=!0,params.query=JSON.stringify({type:"match",match:{"config.battery":{type:"complex",operator:"!==",value:void 0}}})),options=await this.getItems(options,params),list.children().remove(),options&&this.generateHtmlItemList(options,this.$elements.list),list.multipleSelect("refresh"),options)&&list.multipleSelect("enable")}formatItemList(items,keepOnlyMatched=!1){let itemList={};var injectItems=(part,matched)=>{part.forEach(item=>{var device_type=item.type;void 0===itemList[device_type]&&(itemList[device_type]=[]),item.query_match=matched,itemList[device_type].push(item)})};return injectItems(items.matched,!0),!1===keepOnlyMatched&&injectItems(items.rejected,!1),itemList}generateHtmlItemList(items,htmlContainer){var group_key,item_list,queryMode=this.constructor===DeconzQueryEditor;for([group_key,item_list]of Object.entries(items).sort((a,b)=>{a=a[0].toLowerCase(),b=b[0].toLowerCase();return a<b?-1:b<a?1:0})){var groupHtml=$("<optgroup/>").attr("label",group_key);for(const item of item_list.sort((a,b)=>{a=a.name.toLowerCase(),b=b.name.toLowerCase();return a<b?-1:b<a?1:0})){let label=item.name;"groups"===item.device_type&&(label+=" (lights: "+item.lights.length,item.scenes.length&&(label+=", scenes: "+item.scenes.length),label+=")");var opt=$("<option>"+label+"</option>").attr("value",item.device_path);queryMode&&item.query_match&&opt.attr("selected",""),opt.appendTo(groupHtml)}groupHtml.appendTo(htmlContainer)}}}class DeconzQueryEditor extends DeconzDeviceListEditor{constructor(node,options={}){super(node,$.extend({allowedTypes:["json","jsonata"]},options))}get elements(){return{select:"node-input-query",list:"node-input-query_result",showHide:".deconz-query-selector",refreshButton:"#force-refresh-query-result"}}get type(){return this.$elements.select.typedInput("type")}set type(val){this.$elements.list.typedInput("type",val)}get value(){return this.$elements.select.typedInput("value")}set value(val){this.$elements.list.typedInput("value",val)}get xhrParams(){var params=super.xhrParams;return params.query=this.value,params.queryType=this.type,params.nodeID=this.node.id,params}async init(mainEditor){await super.init(),this.mainEditor=mainEditor,this.initTypedInput(),this.$elements.list.multipleSelect({maxHeight:300,dropWidth:320,width:320,single:!1,selectAll:!1,filter:!0,filterPlaceholder:RED._(this.NRCD+"/server:editor.inputs.device.device.filter"),placeholder:RED._(this.NRCD+"/server:editor.multiselect.none_selected"),numberDisplayed:1,disableIfEmpty:!0,showClear:!1,hideOptgroupCheckboxes:!0,filterGroup:!0,onClick:view=>{this.$elements.list.multipleSelect(view.selected?"uncheck":"check",view.value)}}),await this.mainEditor.updateQueryDeviceDisplay({useSavedData:!0})}initTypedInput(){var options=[];this.mainEditor.options.have.device&&options.push({value:"device",label:RED._(this.NRCD+"/server:editor.inputs.device.query.options.device"),icon:`icons/${this.NRCD}/icon-color.png`,hasValue:!1}),this.$elements.select.typedInput({type:"text",types:options.concat(this.options.allowedTypes),typeField:"#node-input-search_type"})}async connect(){await super.connect(),this.$elements.select.on("change",()=>{this.mainEditor.updateQueryDeviceDisplay({useSavedData:!0}),this.mainEditor.options.have.output_rules&&this.mainEditor.subEditor.output_rules.refresh()}),this.$elements.refreshButton.on("click",()=>{this.updateList(),this.mainEditor.options.have.output_rules&&this.mainEditor.subEditor.output_rules.refresh()})}}class DeconzDeviceEditor extends DeconzDeviceListEditor{constructor(node,options={}){super(node,$.extend({batteryFilter:!1},options))}get elements(){return{list:"node-input-device_list",showHide:".deconz-device-selector",refreshButton:"#force-refresh"}}get value(){return this.$elements.list.multipleSelect("getSelects")}set value(val){this.$elements.list.multipleSelect("setSelects",val)}async init(mainEditor){await super.init(),this.mainEditor=mainEditor,this.$elements.list.multipleSelect({maxHeight:300,dropWidth:320,width:320,single:"multiple"!==this.$elements.list.attr("multiple"),filter:!0,filterPlaceholder:RED._(this.NRCD+"/server:editor.inputs.device.device.filter"),placeholder:RED._(this.NRCD+"/server:editor.multiselect.none_selected"),showClear:!0})}async connect(){await super.connect();var refreshDeviceList=()=>{this.updateList($.extend(this.options,{useSelectedData:!0})),this.mainEditor.options.have.output_rules&&this.mainEditor.subEditor.output_rules.refresh()};this.mainEditor.$elements.server.on("change",refreshDeviceList),this.$elements.refreshButton.on("click",refreshDeviceList),this.mainEditor.options.have.output_rules&&this.$elements.list.on("change",()=>{this.mainEditor.subEditor.output_rules.refresh()})}async updateList(options){let itemsSelected;(options=$.extend({useSavedData:!1,useSelectedData:!1},options)).useSelectedData&&(itemsSelected=this.$elements.list.multipleSelect("getSelects")),await super.updateList(options),options.useSavedData&&Array.isArray(this.node.device_list)?this.$elements.list.multipleSelect("setSelects",this.node.device_list):options.useSelectedData&&Array.isArray(itemsSelected)&&this.$elements.list.multipleSelect("setSelects",itemsSelected)}}class DeconzSpecificApiEditor extends DeconzEditor{constructor(node,options={}){super(node,$.extend({},options))}get elements(){return{container:"deconz-api-form",name:"node-config-input-name",method:"node-config-input-method",endpoint:"node-config-input-endpoint",payload:"node-config-input-payload"}}get default(){return{name:"",method:{type:"GET"},endpoint:{type:"str",value:"/"},payload:{type:"json",value:"{}"}}}async init(){this.node.specific=$.extend(!0,this.default.specific,this.node.specific);var container=this.findElement(this.elements.container);await this.generateMethodField(container,this.node.specific.method),await this.generateEndpointField(container,this.node.specific.endpoint),await this.generatePayloadField(container,this.node.specific.payload),await super.init()}async connect(){await super.connect()}get value(){return{method:{type:this.$elements.method.typedInput("type"),value:this.$elements.method.typedInput("value")},endpoint:{type:this.$elements.endpoint.typedInput("type"),value:this.$elements.endpoint.typedInput("value")},payload:{type:this.$elements.payload.typedInput("type"),value:this.$elements.payload.typedInput("value")}}}set value(newValues){this.$elements.name.val(newValues.name);for(var field of["method","endpoint","payload"])this.$elements[field].typedInput("type",newValues[field].type),this.$elements[field].typedInput("value",newValues[field].value);for(const element of Object.values(this.$elements))element.trigger("change")}async generateMethodField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.specific.api.method";await this.generateTypedInputField(container,{id:this.elements.method,i18n:i18n,value:value,width:"250px",typedInput:{types:[this.generateTypedInputType(i18n,"GET",{hasValue:!1}),this.generateTypedInputType(i18n,"POST",{hasValue:!1}),this.generateTypedInputType(i18n,"PUT",{hasValue:!1}),this.generateTypedInputType(i18n,"DELETE",{hasValue:!1})]}})}async generateEndpointField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.specific.api.endpoint";await this.generateTypedInputField(container,{id:this.elements.endpoint,i18n:i18n,value:value,width:"250px",typedInput:{types:["str"]}})}async generatePayloadField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.specific.api.payload";await this.generateTypedInputField(container,{id:this.elements.payload,i18n:i18n,value:value,width:"250px",typedInput:{types:["json","jsonata"]}})}}class DeconzSpecificOutputEditor extends DeconzEditor{constructor(node,options={}){super(node,$.extend({},options))}get elements(){return{container:"specific-container",delay:"node-input-delay",result:"node-input-result"}}get default(){return{delay:{type:"num",value:50},result:{type:"at_end"}}}async init(){this.node.specific=$.extend(!0,this.default,this.node.specific);var container=this.findElement(this.elements.container);await this.generateSeparator(container,this.NRCD+"/server:editor.inputs.separator.specific"),await this.generateDelayField(container,this.node.specific.delay),await this.generateResultField(container,this.node.specific.result),await super.init()}async generateDelayField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.specific.output.delay";await this.generateTypedInputField(container,{id:this.elements.delay,i18n:i18n,value:value,width:"250px",typedInput:{types:["num"]}})}async generateResultField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.specific.output.result";await this.generateTypedInputField(container,{id:this.elements.result,i18n:i18n,value:value,width:"250px",typedInput:{types:[this.generateTypedInputType(i18n,"never",{hasValue:!1}),this.generateTypedInputType(i18n,"after_command",{hasValue:!1}),this.generateTypedInputType(i18n,"at_end",{hasValue:!1})]}})}async connect(){await super.connect()}get value(){return{delay:{type:this.$elements.delay.typedInput("type"),value:this.$elements.delay.typedInput("value")},result:{type:this.$elements.result.typedInput("type"),value:this.$elements.result.typedInput("value")}}}}class DeconzSpecificServerEditor extends DeconzEditor{constructor(node,options={}){super(node,$.extend({},options))}get elements(){return{name:"node-config-input-name",ip:"node-config-input-ip",port:"node-config-input-port",apikey:"node-config-input-secured_apikey",ws_port:"node-config-input-ws_port",secure:"node-config-input-secure",polling:"node-config-input-polling",getSettingsButton:"node-contrib-deconz-get-settings"}}get default(){return{name:"",ip:"",port:"",apikey:"",ws_port:"",secure:!1,polling:15}}get xhrURL(){return this.NRCD+"/serverAutoconfig"}async init(){this.node.specific=$.extend(!0,this.default,this.node.specific),await super.init(),this.node.migration_secured_apikey&&(this.$elements.apikey.val(this.node.migration_secured_apikey),this.$elements.apikey.trigger("change"))}async connect(){await super.connect(),this.$elements.getSettingsButton.on("click",()=>this.discoverParams())}async discoverParams(overrideSettings){void 0===overrideSettings&&(overrideSettings={});let myNotification,stop=!1,closeNotification=()=>{myNotification&&"function"==typeof myNotification.close&&myNotification.close(),stop=!0};myNotification=RED.notify("<p>Trying to find the server settings, please wait...<br>This can take up to 15 seconds.</p>",{modal:!0,fixed:!0,type:"info",buttons:[{text:"Cancel",class:"primary",click:closeNotification}]});try{var params=Object.assign({},this.value,overrideSettings);void 0===params.discoverParam&&(params.discoverParam={}),params.discoverParam.devicetype="Node-Red Deconz Plugin"+(this.node?" id:"+this.node.id:"");let request=await $.getJSON(this.xhrURL,{config:JSON.stringify(params)}).catch((t,u)=>{this.sendError(400===t.status&&t.responseText?t.responseText:u.toString())});if(!stop)if(request.error){let html=`<p>Error ${request.error.code}: ${request.error.description}</p>`;var buttons=[{text:"Cancel",click:closeNotification}];switch(request.error.code){case"GATEWAY_CHOICE":html+="<p>There is multiple Deconz device in you network, please select the one you want to configure.</p>";let node=this;for(const[index,gateway]of request.error.gateway_list.entries())buttons.push({text:`#${index+1}: `+gateway.name,id:"node-red-contrib-deconz-gateway-id-"+index,class:"primary",click:()=>{return gateway_id=gateway.bridge_id,closeNotification(),gateway_id&&(request.currentSettings.discoverParam.targetGatewayID=gateway_id),void node.discoverParams(request.currentSettings);var gateway_id}});buttons.push(buttons.shift());break;case"DECONZ_ERROR":101===request.error.type&&(buttons.unshift({text:"I pressed the link button",class:"primary",click:()=>{closeNotification(),this.discoverParams(request.currentSettings)}}),html=(html+="<p>The reason why the request failed is that the gateway was not unlocked. This mechanism is needed to prevent anybody from access to the gateway without being permitted to do so.</p><ul><li>In a new browser tab open the <a href='http://phoscon.de/pwa/' target='_blank'>Phoscon App</a></li><li>Click on Menu -> Settings -> Gateway</li><li>Click on \"Advanced\" button</li><li>Click on the \"Authenticate app\" button</li></ul>")+`<p>Within 60 seconds after unlocking the gateway, click on the button "${buttons[0].text}".</p>`);break;default:buttons[buttons.length-1].text="Cancel"}html+=`<p>Logs:</p><pre>${request.log.join("\n")}</pre>`,closeNotification(),myNotification=RED.notify(html,{modal:!0,fixed:!0,type:"error",buttons:buttons})}else request.success?(closeNotification(),myNotification=RED.notify("<p>Settings fetched successfully !</p>",{modal:!1,fixed:!1,type:"success"}),this.value=request.currentSettings):(closeNotification(),myNotification=RED.notify(`<p>Unknown error : ${JSON.stringify(request)}</p>`,{modal:!0,fixed:!0,type:"error",buttons:[{text:"Ok",class:"primary",click:closeNotification}]}))}catch(error){closeNotification(),myNotification=RED.notify(`<p>Error while processing request: ${error.toString()}</p>`,{type:"error"})}}get value(){return{name:this.$elements.name.val(),ip:this.$elements.ip.val(),port:this.$elements.port.val(),apikey:this.$elements.apikey.val(),ws_port:this.$elements.ws_port.val(),secure:this.$elements.secure.prop("checked"),polling:this.$elements.polling.val()}}set value(newValues){this.$elements.name.val(newValues.name),this.$elements.ip.val(newValues.ip),this.$elements.port.val(newValues.port),this.$elements.apikey.val(newValues.apikey),this.$elements.ws_port.val(newValues.ws_port),this.$elements.secure.prop("checked",newValues.secure),this.$elements.polling.val(newValues.polling);for(const element of Object.values(this.$elements))element.trigger("change")}}class DeconzListItemEditor extends DeconzEditor{constructor(node,listEditor,container,options={}){super(node,options),this.listEditor=listEditor,container.uniqueId(),this.uniqueId=container.attr("id"),this.container=container}set index(value){void 0!==value&&this.$elements&&this.$elements.outputButton&&this.$elements.outputButton.find(".node-input-rule-index").html(value+1),this._index=value}get index(){return this._index}async init(){await this.generateOutputButton(this.container.children().first()),await super.init()}async generateOutputButton(container){$("<a/>",{id:this.elements.outputButton,class:"red-ui-button top-right-badge",title:RED._(this.options.button_title)}).append(`&nbsp;&#8594;&nbsp;<span class="node-input-rule-index">${this.index+1}</span>&nbsp;`).appendTo(container)}}class DeconzListItemListEditor extends DeconzEditor{constructor(node,options={}){super(node,options),this.items={}}get listType(){return"item"}get buttons(){return[]}async init(mainEditor){await super.init(),this.mainEditor=mainEditor}async initList(itemEditorClass,items=[]){var buttons=this.buttons,addButton=0===buttons.length||DeconzEditor.versionCompare(RED.settings.version,"1.3.0")<0;this.$elements.list.editableList({sortable:!0,removable:!0,height:"auto",addButton:addButton,buttons:buttons,addItem:(row,index,item)=>{row=new itemEditorClass(this.node,this,row,this.options);item.uniqueId=row.uniqueId,(this.items[item.uniqueId]=row).init(item,index)},removeItem:item=>{if(!item.uniqueId||!this.items[item.uniqueId])throw new Error(`Error while removing the ${this.listType}, the ${this.listType} ${item.uniqueId} does not exist.`);var deletedIndex=this.items[item.uniqueId].index;delete this.items[item.uniqueId];for(const item of Object.values(this.items))item.index>deletedIndex&&item.index--},sortItems:items=>{items.each((index,item)=>{if(!this.items[item.attr("id")])throw new Error(`Error while moving the ${this.listType}, the ${this.listType} ${index+1} does not exist.`);this.items[item.attr("id")].index=index})}}),0<items.length&&this.$elements.list.editableList("addItems",items)}get value(){var result=[];for(const rule of Object.values(this.items).sort((a,b)=>a.index-b.index))result.push(rule.value);return result}refresh(){}}class DeconzOutputRuleEditor extends DeconzListItemEditor{constructor(node,listEditor,container,options={}){super(node,listEditor,container,options=$.extend({enableEachState:!0},options))}get elements(){var elements={};for(const key of["format","type","payload","output","onstart","onerror","outputButton"])elements[key]=`node-input-output-rule-${this.uniqueId}-`+key;return elements}get value(){var value={};switch(value.type=this.$elements.type.val(),value.format=this.$elements.format.val(),value.type){case"attribute":case"state":case"config":"deconz-input"===this.node.type&&(value.output=this.$elements.output.val()),["deconz-input","deconz-battery"].includes(this.node.type)&&(value.onstart=this.$elements.onstart.is(":checked")),["deconz-input","deconz-get"].includes(this.node.type)&&(value.payload=this.$elements.payload.multipleSelect("getSelects"));break;case"homekit":["deconz-input","deconz-battery"].includes(this.node.type)&&(value.onstart=this.$elements.onstart.is(":checked")),"deconz-input"===this.node.type&&(value.onerror=this.$elements.onerror.is(":checked")),["deconz-input","deconz-get"].includes(this.node.type)&&(value.payload=this.$elements.payload.multipleSelect("getSelects"))}return value}get defaultRule(){var rule={type:"state",payload:["__complete__"],format:"single"};return"deconz-input"===this.node.type&&(rule.output="always",rule.onstart=!0,rule.onerror=!0),"deconz-battery"===this.node.type&&(rule.onstart=!0),rule}async init(rule,index){this._index=index,rule=$.extend(!0,this.defaultRule,rule),await this.generatePayloadTypeField(this.container,rule.type),["deconz-input","deconz-get"].includes(this.node.type)&&await this.generatePayloadField(this.container),await this.generatePayloadFormatField(this.container,rule.format),"deconz-input"===this.node.type&&await this.generateOutputField(this.container,(void 0!==rule.output?rule:this.defaultRule).output),["deconz-input","deconz-battery"].includes(this.node.type)&&await this.generateOnStartField(this.container,(void 0!==rule.onstart?rule:this.defaultRule).onstart),"deconz-input"===this.node.type&&await this.generateOnErrorField(this.container,(void 0!==rule.onerror?rule:this.defaultRule).onerror),await super.init(),await this.listEditor.mainEditor.isInitialized(),await this.initPayloadList(rule.payload),await this.updateShowHide(rule.type),await this.connect()}async connect(){await super.connect(),this.$elements.type.on("change",()=>{var type=this.$elements.type.val();["attribute","state","config","homekit"].includes(type)&&this.updatePayloadList(),this.updateShowHide(type)}),this.$elements.outputButton.on("click",()=>{try{var nodes=RED.nodes.filterLinks({source:this.node,sourcePort:this.index}).map(l=>{var result=l.target.type;return""!==l.target.name?result+":"+l.target.name:void 0!==l.target._def.label?result+":"+l.target._def.label():result});let myNotification=RED.notify(`The output ${this.index+1} is sending message to ${nodes.length} nodes :<br>`+nodes.join("<br>"),{modal:!0,timeout:5e3,buttons:[{text:"okay",class:"primary",click:()=>myNotification.close()}]})}catch(e){this.sendError("This is using not documented API so can be broken at anytime.<br>Error while getting connected nodes: "+e.toString())}})}async updateShowHide(type){switch(type){case"attribute":case"state":case"config":this.$elements.payload.closest(".form-row").show(),this.$elements.output.closest(".form-row").show(),this.$elements.onstart.closest(".form-row").show(),this.$elements.onerror.closest(".form-row").hide();break;case"homekit":this.$elements.payload.closest(".form-row").show(),this.$elements.output.closest(".form-row").hide(),this.$elements.onstart.closest(".form-row").show(),this.$elements.onerror.closest(".form-row").show();break;case"scene_call":this.$elements.payload.closest(".form-row").hide(),this.$elements.output.closest(".form-row").hide(),this.$elements.onstart.closest(".form-row").hide(),this.$elements.onerror.closest(".form-row").hide()}}async updatePayloadList(){if(this.listEditor.mainEditor.serverNode){this.$elements.payload.multipleSelect("disable"),this.$elements.payload.children().remove();var queryType=this.listEditor.mainEditor.subEditor.query.type,devices=this.listEditor.mainEditor.subEditor.device.value,type=this.$elements.type.val();if(["attribute","state","config","homekit"].includes(type)){var i18n=this.NRCD+"/server:editor.inputs.outputs.payload";let html="";if("homekit"===type?html+='<option value="__auto__">'+RED._(i18n+".options.auto")+"</option>":(html+='<option value="__complete__">'+RED._(i18n+".options.complete")+"</option>",!0===this.options.enableEachState&&(html+='<option value="__each__">'+RED._(i18n+".options.each")+"</option>")),this.$elements.payload.html(html),"device"===queryType){var data=await $.getJSON(this.NRCD+`/${type}list`,{controllerID:this.listEditor.mainEditor.serverNode.id,devices:JSON.stringify(this.listEditor.mainEditor.subEditor.device.value)});for(const _type of"attribute"===type?["attribute","state","config"]:[type]){let label=this.getI18n(i18n+".group_label."+_type);void 0===label&&(label=_type);var groupHtml=$("<optgroup/>",{label:label});for(const item of Object.keys(data.count[_type]).sort()){let sample=data.sample[_type][item];sample="string"==typeof sample?`"${sample}"`:Array.isArray(sample)?`[${sample.toString()}]`:null===sample||void 0===sample?"NULL":sample.toString();let label;var count=data.count[_type][item];label=count===devices.length?RED._(i18n+".item_list",{name:item,sample:sample}):RED._(i18n+".item_list_mix",{name:item,sample:sample,item_count:count,device_count:devices.length}),$("<option>"+label+"</option>").attr("value","attribute"===type&&"attribute"!==_type?_type+"."+item:item).appendTo(groupHtml)}$.isEmptyObject(data.count[_type])||groupHtml.appendTo(this.$elements.payload)}}this.$elements.payload.multipleSelect("refresh").multipleSelect("enable")}}}async initPayloadList(value){let list=this.$elements.payload;list.addClass("multiple-select"),list.multipleSelect({maxHeight:300,dropWidth:300,width:200,numberDisplayed:1,single:!1,selectAll:!1,container:".node-input-output-container-row",filter:!0,filterPlaceholder:RED._(this.NRCD+"/server:editor.inputs.device.device.filter"),placeholder:RED._(this.NRCD+"/server:editor.multiselect.none_selected"),onClick:view=>{if(view.selected)switch(view.value){case"__complete__":case"__each__":case"__auto__":list.multipleSelect("setSelects",[view.value]);break;default:list.multipleSelect("uncheck","__complete__"),list.multipleSelect("uncheck","__each__"),list.multipleSelect("uncheck","__auto__")}},onUncheckAll:()=>{list.multipleSelect("setSelects",["__complete__","__auto__"])},onOptgroupClick:view=>{view.selected&&(list.multipleSelect("uncheck","__complete__"),list.multipleSelect("uncheck","__each__"),list.multipleSelect("uncheck","__auto__"))}}),await this.updatePayloadList(),value&&list.multipleSelect("setSelects",value)}async generatePayloadTypeField(container,value){var type,enabled,i18n=this.NRCD+"/server:editor.inputs.outputs.type",choices=[];for([type,enabled]of Object.entries(this.listEditor.options.type))enabled&&choices.push([type,i18n+".options."+type]);await this.generateSimpleListField(container,{id:this.elements.type,i18n:i18n,choices:choices,currentValue:value})}async generatePayloadField(container){var i18n=this.NRCD+"/server:editor.inputs.outputs.payload";await this.generateSimpleListField(container,{id:this.elements.payload,i18n:i18n})}async generatePayloadFormatField(container,value){var format,enabled,i18n=this.NRCD+"/server:editor.inputs.outputs.format",choices=[];for([format,enabled]of Object.entries(this.listEditor.options.format))enabled&&choices.push([format,i18n+".options."+format]);await this.generateSimpleListField(container,{id:this.elements.format,i18n:i18n,choices:choices,currentValue:value})}async generateOutputField(container,value){var i18n=this.NRCD+"/server:editor.inputs.outputs.output";await this.generateSimpleListField(container,{id:this.elements.output,i18n:i18n,choices:[["always",i18n+".options.always"],["onchange",i18n+".options.onchange"],["onupdate",i18n+".options.onupdate"]],currentValue:value})}async generateOnStartField(container,value){var i18n=this.NRCD+"/server:editor.inputs.outputs.on_start";await this.generateCheckboxField(container,{id:this.elements.onstart,i18n:i18n,currentValue:value})}async generateOnErrorField(container,value){var i18n=this.NRCD+"/server:editor.inputs.outputs.on_error";await this.generateCheckboxField(container,{id:this.elements.onerror,i18n:i18n,currentValue:value})}}class DeconzOutputRuleListEditor extends DeconzListItemListEditor{get elements(){return{list:"node-input-output-container"}}get listType(){return"rule"}get buttons(){var type_name,buttons=[],i18n=this.NRCD+"/server:editor.inputs.outputs.type";for(const[type,enabled]of Object.entries(this.options.type))enabled&&(type_name=this.getI18n(i18n+".options."+type),buttons.push({label:this.getI18n(i18n+".add_button","label",{type:type_name}),icon:this.getIcon(this.getI18n(i18n+".add_button","icon"),!0),title:this.getI18n(i18n+".add_button","title",{type:type_name}),click:()=>this.$elements.list.editableList("addItem",{type:type})}));return buttons}async init(mainEditor){await super.init(mainEditor),await this.initList(DeconzOutputRuleEditor,this.node.output_rules)}refresh(){for(const rule of Object.values(this.items))rule.updatePayloadList()}}class DeconzCommandEditor extends DeconzListItemEditor{constructor(node,listEditor,container,options={}){super(node,listEditor,container,options=$.extend({},options)),this.containers={}}get lightKeys(){return["bri","sat","hue","ct","xy"]}get argKeys(){return["on","alert","effect","colorloopspeed","open","stop","lift","tilt","scene_mode","group","scene","scene_name","target","command","payload","delay","transitiontime","retryonerror","aftererror"]}get elements(){var keys=this.argKeys;keys.push("typedomain"),keys.push("outputButton"),keys.push("scene_picker"),keys.push("scene_picker_refresh");for(const lightKey of this.lightKeys)keys.push(lightKey),keys.push(lightKey+"_direction");var elements={};for(const key of keys)elements[key]=`node-input-output-rule-${this.uniqueId}-`+key;return elements}set value(command){}get value(){var value={arg:{}};value.type=this.$elements.typedomain.typedInput("type"),value.domain=this.$elements.typedomain.typedInput("value");for(const key of this.argKeys)this.$elements[key].parent(".form-row").is(":visible")&&(value.arg[key]={type:this.$elements[key].typedInput("type"),value:this.$elements[key].typedInput("value")});for(const key of this.lightKeys)this.$elements[key].parent(".form-row").is(":visible")&&(value.arg[key]={direction:this.$elements[key+"_direction"].typedInput("type"),type:this.$elements[key].typedInput("type"),value:this.$elements[key].typedInput("value")});return value}get defaultCommand(){return{type:"deconz_state",domain:"lights",target:"state",arg:{on:{type:"keep"},bri:{direction:"set",type:"num"},sat:{direction:"set",type:"num"},hue:{direction:"set",type:"num"},ct:{direction:"set",type:"num"},xy:{direction:"set",type:"num"},alert:{type:"str"},effect:{type:"str"},colorloopspeed:{type:"num"},transitiontime:{type:"num"},command:{type:"str",value:"on"},payload:{type:"msg",value:"payload"},delay:{type:"num",value:2e3},target:{type:"state"},group:{type:"num"},scene_mode:{type:"single"},scene_call:{type:"num"},scene_name:{type:"str"},retryonerror:{type:"num",value:0},aftererror:{type:"continue"}}}}async init(command,index){this._index=index,command=$.extend(!0,this.defaultCommand,command),await this.generateTypeDomainField(this.container,{type:command.type,value:command.domain}),this.containers.light=$("<div>").appendTo(this.container),await this.generateLightOnField(this.containers.light,command.arg.on);for(const lightType of["bri","sat","hue","ct","xy"])await this.generateLightColorField(this.containers.light,lightType,command.arg[lightType]),"bri"===lightType&&await this.generateHR(this.containers.light);await this.generateHR(this.containers.light),await this.generateLightAlertField(this.containers.light,command.arg.alert),await this.generateLightEffectField(this.containers.light,command.arg.effect),await this.generateLightColorLoopSpeedField(this.containers.light,command.arg.colorloopspeed),this.containers.windows_cover=$("<div>").appendTo(this.container),await this.generateCoverOpenField(this.containers.windows_cover,command.arg.open),await this.generateCoverStopField(this.containers.windows_cover,command.arg.stop),await this.generateCoverLiftField(this.containers.windows_cover,command.arg.lift),await this.generateCoverTiltField(this.containers.windows_cover,command.arg.tilt),this.containers.scene_call=$("<div>").appendTo(this.container),await this.generateSceneModeField(this.containers.scene_call,command.arg.scene_mode),this.containers.scene_call_single=$("<div>").appendTo(this.containers.scene_call),await this.generateScenePickerField(this.containers.scene_call_single,command.arg.group+"."+command.arg.scene),await this.generateSceneGroupField(this.containers.scene_call_single,command.arg.group),await this.generateSceneSceneField(this.containers.scene_call_single,command.arg.scene),this.containers.scene_call_dynamic=$("<div>").appendTo(this.containers.scene_call),await this.generateSceneNameField(this.containers.scene_call_dynamic,command.arg.scene_name),this.containers.target=$("<div>").appendTo(this.container),await this.generateTargetField(this.containers.target,command.arg.target),this.containers.command=$("<div>").appendTo(this.container),await this.generateCommandField(this.containers.command,command.arg.command),this.containers.payload=$("<div>").appendTo(this.container),await this.generatePayloadField(this.containers.payload,command.arg.payload),this.containers.pause=$("<div>").appendTo(this.container),await this.generatePauseDelayField(this.containers.pause,command.arg.delay),this.containers.transition=$("<div>").appendTo(this.container),await this.generateHR(this.containers.transition),await this.generateCommonTransitionTimeField(this.containers.transition,command.arg.transitiontime),this.containers.common=$("<div>").appendTo(this.container),await this.generateHR(this.containers.common),await this.generateCommonOnErrorRetryField(this.containers.common,command.arg.retryonerror),await this.generateCommonOnErrorAfterField(this.containers.common,command.arg.aftererror),await super.init(),await this.listEditor.mainEditor.isInitialized(),await this.updateShowHide(command.type,command.domain),await this.connect()}async connect(){await super.connect(),this.$elements.typedomain.on("change",(event,type,value)=>{this.updateShowHide(type,value)}),this.$elements.outputButton.on("click",async()=>{try{if("device"!==this.listEditor.mainEditor.subEditor.query.type)this.sendError("Error : The run command can only work with device list.",5e3);else{var command=this.value,devices=this.listEditor.mainEditor.subEditor.device.value;if(0!==devices.length||("deconz_state"===command.type&&"scene_call"===command.domain||"custom"===command.type&&"scene_call"===command.arg.target.type))if("pause"===command.type)this.sendError("Error : Can't test pause command.",5e3);else{for(var[name,value]of Object.entries(command.arg))if(["msg","flow","global","jsonata"].includes(value.type))return void this.sendError(`Error : Cant run this command because the value "${name}" is type "${value.type}".`,5e3);let myNotification=RED.notify("Sending request...",{type:"info"});await $.post(this.NRCD+"/testCommand",{controllerID:this.listEditor.mainEditor.serverNode.id,device_list:devices,command:command,delay:this.listEditor.mainEditor.subEditor.specific.value.delay}).catch((t,u)=>{this.sendError(400===t.status&&t.responseText?t.responseText:u.toString())});myNotification.close(),myNotification=RED.notify("Ok",{timeout:1e3,type:"success"})}else this.sendError("Error : No device selected.",5e3)}}catch(e){let myNotification=RED.notify(e.toString(),{type:"error",buttons:[{class:"error",click:()=>myNotification.close()}]})}});const updateSceneGroupSelection=()=>{var value=this.$elements.scene_picker.multipleSelect("getSelects");1===value.length&&(this.$elements.group.off("change",updateScenePickerSelection),this.$elements.scene.off("change",updateScenePickerSelection),value=value[0].split("."),this.$elements.group.typedInput("type","num"),this.$elements.group.typedInput("value",value[0]),this.$elements.scene.typedInput("type","num"),this.$elements.scene.typedInput("value",value[1]),this.$elements.group.on("change",updateScenePickerSelection),this.$elements.scene.on("change",updateScenePickerSelection))},updateScenePickerSelection=()=>{this.$elements.scene_picker.off("change",updateSceneGroupSelection),this.$elements.scene_picker.multipleSelect("setSelects","num"!==this.$elements.group.typedInput("type")||"num"!==this.$elements.group.typedInput("type")?[]:[this.$elements.group.typedInput("value")+"."+this.$elements.scene.typedInput("value")]),this.$elements.scene_picker.on("change",updateSceneGroupSelection)};this.$elements.scene_mode.on("change",()=>{var isSingle="single"===this.$elements.scene_mode.typedInput("type");this.containers.scene_call_single.toggle(isSingle),this.containers.scene_call_dynamic.toggle(!isSingle)}),this.$elements.scene_picker.on("change",updateSceneGroupSelection),this.$elements.group.on("change",updateScenePickerSelection),this.$elements.scene.on("change",updateScenePickerSelection),this.$elements.scene_picker_refresh.on("click",()=>this.updateSceneList()),this.$elements.target.on("change",(event,type,value)=>{this.containers.command.toggle("scene_call"!==type)})}async updateShowHide(type,domain){var key,value,containers=[];switch(type){case"deconz_state":switch(domain){case"lights":case"groups":containers.push("light"),containers.push("transition");break;case"covers":containers.push("windows_cover");break;case"scene_call":containers.push("scene_call"),await this.updateSceneList(),containers.push("scene_call_"+("single"===this.$elements.scene_mode.typedInput("type")?"single":"dynamic"))}containers.push("common");break;case"homekit":this.$elements.payload.typedInput("types",["msg","flow","global","json","jsonata"]),containers.push("payload"),containers.push("transition"),containers.push("common");break;case"custom":containers.push("target"),"scene_call"!==this.$elements.target.typedInput("type")&&containers.push("command"),this.$elements.payload.typedInput("types",["msg","flow","global","str","num","bool","json","jsonata","date"]),containers.push("payload"),containers.push("transition"),containers.push("common");break;case"pause":containers.push("pause")}for([key,value]of Object.entries(this.containers))value.toggle(containers.includes(key))}async updateSceneList(){this.$elements.scene_picker.multipleSelect("disable"),this.$elements.scene_picker.children().remove();var queryEditor=this.listEditor.mainEditor.subEditor.query;if(void 0!==queryEditor){var params=queryEditor.xhrParams,queryEditor=(params.queryType="json",params.query=JSON.stringify({match:{device_type:"groups"}}),await queryEditor.getItems({refresh:!0,keepOnlyMatched:!0},params));if(void 0!==queryEditor&&void 0!==queryEditor.LightGroup){for(const group of queryEditor.LightGroup){var groupHtml=$("<optgroup/>",{label:group.id+" - "+group.name});if(group.scenes&&0<group.scenes.length){for(const scene of group.scenes)$(`<option>${scene.id} - ${scene.name}</option>`).attr("value",group.id+"."+scene.id).appendTo(groupHtml);groupHtml.appendTo(this.$elements.scene_picker)}}this.$elements.scene_picker.multipleSelect("refresh").multipleSelect("enable"),this.$elements.scene_picker.multipleSelect("setSelects","num"!==this.$elements.group.typedInput("type")||"num"!==this.$elements.group.typedInput("type")?[]:[this.$elements.group.typedInput("value")+"."+this.$elements.scene.typedInput("value")])}}}async generateTypeDomainField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type";await this.generateTypedInputField(container,{id:this.elements.typedomain,i18n:i18n,value:value,addDefaultTypes:!1,typedInput:{default:"deconz_state",types:[this.generateTypedInputType(i18n,"deconz_state",{subOptions:["lights","covers","groups","scene_call"]}),this.generateTypedInputType(i18n,"homekit",{hasValue:!1}),this.generateTypedInputType(i18n,"custom",{hasValue:!1}),this.generateTypedInputType(i18n,"pause",{hasValue:!1})]}})}async generateLightOnField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.lights.fields.on";await this.generateTypedInputField(container,{id:this.elements.on,i18n:i18n,value:value,typedInput:{default:"keep",types:[this.generateTypedInputType(i18n,"keep",{hasValue:!1}),this.generateTypedInputType(i18n,"set",{subOptions:["true","false"]}),this.generateTypedInputType(i18n,"toggle",{hasValue:!1})]}})}async generateLightColorField(container,fieldName,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.lights.fields";let fieldFormat=["num"];var directionsFormat=[this.generateTypedInputType(i18n+".lightFields","set",{hasValue:!1})];switch(fieldName){case"bri":fieldFormat.push("str"),directionsFormat.push(this.generateTypedInputType(i18n+".lightFields","inc",{hasValue:!1})),directionsFormat.push(this.generateTypedInputType(i18n+".lightFields","dec",{hasValue:!1})),directionsFormat.push(this.generateTypedInputType(i18n+".lightFields","detect_from_value",{hasValue:!1}));break;case"ct":fieldFormat.push("str"),fieldFormat.push(this.generateTypedInputType(i18n+".ct","deconz",{subOptions:["cold","white","warm"]})),directionsFormat.push(this.generateTypedInputType(i18n+".lightFields","inc",{hasValue:!1})),directionsFormat.push(this.generateTypedInputType(i18n+".lightFields","dec",{hasValue:!1})),directionsFormat.push(this.generateTypedInputType(i18n+".lightFields","detect_from_value",{hasValue:!1}));break;case"xy":fieldFormat=["json"]}await this.generateDoubleTypedInputField(container,{id:this.elements[fieldName+"_direction"],i18n:i18n+"."+fieldName,addDefaultTypes:!1,value:{type:value.direction},typedInput:{types:directionsFormat}},{id:this.elements[fieldName],value:{type:value.type,value:["xy"===fieldName&&void 0===value.value?"[]":value.value]},typedInput:{types:fieldFormat}})}async generateLightAlertField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.lights.fields.alert";await this.generateTypedInputField(container,{id:this.elements.alert,i18n:i18n,value:value,typedInput:{types:["str",this.generateTypedInputType(i18n,"deconz",{subOptions:["none","select","lselect"]})]}})}async generateLightEffectField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.lights.fields.effect";await this.generateTypedInputField(container,{id:this.elements.effect,i18n:i18n,value:value,typedInput:{types:["str",this.generateTypedInputType(i18n,"deconz",{subOptions:["none","colorloop"]})]}})}async generateLightColorLoopSpeedField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.lights.fields.colorloopspeed";await this.generateTypedInputField(container,{id:this.elements.colorloopspeed,i18n:i18n,value:value,typedInput:{types:["num"]}})}async generateCoverOpenField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.covers.fields.open";await this.generateTypedInputField(container,{id:this.elements.open,i18n:i18n,value:value,typedInput:{types:[this.generateTypedInputType(i18n,"keep",{hasValue:!1}),this.generateTypedInputType(i18n,"set",{subOptions:["true","false"]}),this.generateTypedInputType(i18n,"toggle",{hasValue:!1})]}})}async generateCoverStopField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.covers.fields.stop";await this.generateTypedInputField(container,{id:this.elements.stop,i18n:i18n,value:value,typedInput:{types:[this.generateTypedInputType(i18n,"keep",{hasValue:!1}),this.generateTypedInputType(i18n,"set",{subOptions:["true","false"]})]}})}async generateCoverLiftField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.covers.fields.lift";await this.generateTypedInputField(container,{id:this.elements.lift,i18n:i18n,value:value,typedInput:{types:["num","str",this.generateTypedInputType(i18n,"stop",{hasValue:!1})]}})}async generateCoverTiltField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.covers.fields.tilt";await this.generateTypedInputField(container,{id:this.elements.tilt,i18n:i18n,value:value,typedInput:{types:["num"]}})}async generateSceneModeField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.scene_call.fields.mode";await this.generateTypedInputField(container,{id:this.elements.scene_mode,i18n:i18n,value:value,addDefaultTypes:!1,typedInput:{types:[this.generateTypedInputType(i18n,"single",{hasValue:!1}),this.generateTypedInputType(i18n,"dynamic",{hasValue:!1})]}})}async generateScenePickerField(container,value=0){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.scene_call.fields.picker",container=await this.generateSimpleListField(container,{id:this.elements.scene_picker,i18n:i18n}),i18n=(container.addClass("multiple-select"),container.multipleSelect({maxHeight:300,dropWidth:300,width:200,numberDisplayed:1,single:!0,singleRadio:!0,hideOptgroupCheckboxes:!0,showClear:!0,selectAll:!1,filter:!0,filterPlaceholder:this.getI18n(i18n,"filter_place_holder"),placeholder:RED._(this.NRCD+"/server:editor.multiselect.none_selected"),container:".node-input-output-container-row"}),$("<a/>",{id:this.elements.scene_picker_refresh,class:"red-ui-button",style:"margin-left:10px;"}));this.createIconElement(this.getIcon("refresh"),i18n),container.closest(".form-row").append(i18n)}async generateSceneGroupField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.scene_call.fields.group";await this.generateTypedInputField(container,{id:this.elements.group,i18n:i18n,value:value,typedInput:{types:["num"]}})}async generateSceneSceneField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.scene_call.fields.scene";await this.generateTypedInputField(container,{id:this.elements.scene,i18n:i18n,value:value,typedInput:{types:["num","str",this.generateTypedInputType(i18n,"deconz",{subOptions:["next","prev"]})]}})}async generateSceneNameField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.scene_call.fields.scene_name";await this.generateTypedInputField(container,{id:this.elements.scene_name,i18n:i18n,value:value,typedInput:{types:["str","re"]}})}async generateTargetField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.common.fields.target";await this.generateTypedInputField(container,{id:this.elements.target,i18n:i18n,value:value,typedInput:{types:[this.generateTypedInputType(i18n,"attribute",{hasValue:!1}),this.generateTypedInputType(i18n,"state",{hasValue:!1}),this.generateTypedInputType(i18n,"config",{hasValue:!1}),this.generateTypedInputType(i18n,"scene_call",{hasValue:!1})]}})}async generateCommandField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.common.fields.command";await this.generateTypedInputField(container,{id:this.elements.command,i18n:i18n,value:value,typedInput:{types:["str",this.generateTypedInputType(i18n,"object",{hasValue:!1})]}})}async generatePayloadField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.common.fields.payload";await this.generateTypedInputField(container,{id:this.elements.payload,i18n:i18n,value:value,addDefaultTypes:!1,typedInput:{types:["msg","flow","global","str","num","bool","json","jsonata","date"]}})}async generatePauseDelayField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.pause.fields.delay";await this.generateTypedInputField(container,{id:this.elements.delay,i18n:i18n,value:value,typedInput:{types:["num"]}})}async generateCommonTransitionTimeField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.common.fields.transitiontime";await this.generateTypedInputField(container,{id:this.elements.transitiontime,i18n:i18n,value:value,typedInput:{types:["num"]}})}async generateCommonOnErrorRetryField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.common.fields.retryonerror";await this.generateTypedInputField(container,{id:this.elements.retryonerror,i18n:i18n,value:value,typedInput:{types:["num"]}})}async generateCommonOnErrorAfterField(container,value={}){var i18n=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.common.fields.aftererror";await this.generateTypedInputField(container,{id:this.elements.aftererror,i18n:i18n,value:value,typedInput:{types:[this.generateTypedInputType(i18n,"continue",{hasValue:!1}),this.generateTypedInputType(i18n,"stop",{hasValue:!1})]}})}}class DeconzCommandListEditor extends DeconzListItemListEditor{get elements(){return{list:"node-input-output-container"}}get listType(){return"command"}get buttons(){var type_name,buttons=[],i18n=this.NRCD+"/server:editor.inputs.commands.type";for(const[type,enabled]of Object.entries(this.options.type))enabled&&(type_name=this.getI18n(i18n+".options."+type,"label"),buttons.push({label:this.getI18n(i18n+".add_button","label",{type:type_name}),icon:this.getIcon(this.getI18n(i18n+".add_button","icon"),!0),title:this.getI18n(i18n+".add_button","title",{type:type_name}),click:()=>this.$elements.list.editableList("addItem",{type:type})}));return buttons}async init(mainEditor){await super.init(mainEditor),await this.initList(DeconzCommandEditor,this.node.commands)}}
class DeconzEditor{constructor(e,t={}){this.node=e,this.options=t}get elements(){return{}}get NRCD(){return"node-red-contrib-deconz"}findElements(){this.$elements={},Object.keys(this.elements).forEach(e=>{this.$elements[e]=this.findElement(this.elements[e])})}findElement(e){return"#"!==e.charAt(0)&&"."!==e.charAt(0)&&(e="#"+e),$(e)}async init(){this.findElements()}async connect(){}sendError(e,t=1e4){let i=RED.notify(e,{timeout:t,type:"error",buttons:[{text:"Ok",class:"primary",click:()=>i.close()}]})}getIcon(e,t=!1){return"deconz"===e?"icons/node-red-contrib-deconz/icon-color.png":"homekit"===e?"icons/node-red-contrib-deconz/homekit-logo.png":RED.nodes.fontAwesome.getIconList().includes("fa-"+e)?`${t?"fa ":""}fa-`+e:e}createIconElement(e,t,i=!1){if("fa-"===e.substr(0,3)){if(RED.nodes.fontAwesome.getIconUnicode(e))return void $("<i/>").appendTo(t).addClass("fa "+e+(i?" fa-lg":""));e=RED.settings.apiRootUrl+"icons/node-red/arrow-in.svg"}$("<div/>").appendTo(t).css("backgroundImage","url("+e+")")}getI18n(e,t,i={}){let s=e;t&&(s+="."+t),i.defaultValue="_deconz_undefined_";var n=RED._(s,i);if("_deconz_undefined_"!==n)return n}async generateSimpleListField(e,t){var i=$("<select/>",{id:t.id});if(t.choices)for(var[s,n]of t.choices)i.append($("<option/>").attr("value",s).html(RED._(n)));var a=await this.generateInputWithLabel(i,t);return e.append(a),void 0!==t.currentValue&&i.val(t.currentValue),i}async generateTypedInput(e,t){var i=$("<input/>",{id:e,placeholder:RED._(t)}),s=$("<input/>",{id:e+"_type",type:"hidden"});return i.append(s),i}async initTypedInput(e,t){t=$.extend({addDefaultTypes:!0,displayOnlyIcon:!1,value:{},width:"200px"},t);var i=$.extend({types:["msg","flow","global"]},t.typedInput);if(i.typeField=t.typeId,t.addDefaultTypes)for(var s of["msg","flow","global","jsonata"])i.types.includes(s)||i.types.push(s);if(t.displayOnlyIcon){let n=this;var a,o=function(e,t){let i;for(const s of this.typeList)"object"==typeof s&&s.value===this.propertyType&&(i=s);void 0!==i&&void 0!==i.icon&&(this.oldValue=this.input.val(),this.input.val(""),this.valueLabelContainer.hide(),n.createIconElement(i.icon,this.selectLabel),this.selectTrigger.addClass("red-ui-typedInput-full-width"),this.selectLabel.show())};for(a of i.types)"string"!=typeof a&&(a.hasValue=!0,a.valueLabel=o)}e.typedInput(i),void 0!==t.width&&e.typedInput("width",t.width),t.value&&(void 0!==t.value.type&&e.typedInput("type",t.value.type),void 0!==t.value.value)&&e.typedInput("value",t.value.value)}async generateTypedInputField(e,t){var i=await this.generateTypedInput(t.id,this.getI18n(t.i18n,"placeholder")),s=await this.generateInputWithLabel(i,t);return e.append(s),await this.initTypedInput(i,t),i}async generateDoubleTypedInputField(e,t,i){var s=await this.generateTypedInput(t.id,t.placeholder),n=await this.generateInputWithLabel(s,t),a=await this.generateTypedInput(i.id,i.placeholder);n.append(a),e.append(n),t.displayOnlyIcon=!0,t.width="50px",i.width="150px",await this.initTypedInput(s,t),await this.initTypedInput(a,i)}generateTypedInputType(e,t,i={}){if(i.value=t,void 0===i.label&&(i.label=this.getI18n(e,`options.${t}.label`,{})||t),!1!==i.icon&&void 0===i.icon&&(i.icon=this.getIcon(this.getI18n(e,`options.${t}.icon`))),i.icon&&"fa-"===i.icon.substr(0,3)&&(i.icon="fa "+i.icon),Array.isArray(i.subOptions)){Array.isArray(i.options)||(i.options=[]);for(const s of i.subOptions)i.options.push(this.generateTypedInputType(e+".options."+t,"string"==typeof s?s:s.name,{icon:!1}))}return i}async generateCheckboxField(e,t){var i=$("<input/>",{id:t.id,type:"checkbox",style:"display: table-cell; width: 14px;vertical-align: top;margin-right: 5px",checked:t.currentValue}),i=await this.generateInputWithLabel(i,t);i.append($("<span/>").html(RED._(t.descText)).css("display","table-cell")),e.append(i)}async generateInputWithLabel(e,t={}){var i,s=$("<div/>",{class:"form-row",style:"padding:5px;margin:0;display:table;min-width:420px;"}),n=e.attr("id");return n&&((i=$("<label/>")).attr("for",n),i.attr("class","l-width"),i.attr("style","display:table-cell;"),void 0===t.title&&(t.title=this.getI18n(t.i18n,"title")),t.title&&i.attr("title",this.getI18n(t.i18n,"title")),void 0===t.icon&&(t.icon=this.getI18n(t.i18n,"icon")),t.icon&&(this.createIconElement(this.getIcon(t.icon),i),i.append("&nbsp;")),void 0===t.label&&(t.label=this.getI18n(t.i18n,"label")),t.label&&i.append(`<span>${t.label}</span>`),s.append(i)),e.css("display","table-cell"),s.append(e),s}async generateHR(e,t="5px",i="50px"){e.append(`<hr style="margin: ${t} ${i};">`)}async generateSeparator(e,t){e.append(`<div class="separator">${RED._(t)}</div>`)}static versionCompare(e,t,i={}){const s=i&&i.lexicographical;var n=i&&i.zeroExtend;let a=e.split("."),o=t.split(".");function r(e){return(s?/^\d+[A-Za-z]*$/:/^\d+$/).test(e)}if(!a.every(r)||!o.every(r))return NaN;if(n){for(;a.length<o.length;)a.push("0");for(;o.length<a.length;)o.push("0")}s||(a=a.map(Number),o=o.map(Number));for(let l=0;l<a.length;++l){if(o.length===l)return 1;if(a[l]!==o[l])return a[l]>o[l]?1:-1}return a.length!==o.length?-1:0}}class DeconzMainEditor extends DeconzEditor{constructor(e,t={}){if(super(e,$.extend(!0,{have:{statustext:!0,query:!0,device:!0,output_rules:!1,commands:!1,specific:!1},device:{batteryFilter:!1},output_rules:{format:{single:!0,array:!1,sum:!1,average:!1,min:!1,max:!1},type:{attribute:!0,state:!0,config:!0,homekit:!1,scene_call:!1}},commands:{type:{deconz_state:!0,homekit:!0,custom:!0,pause:!0}},specific:{api:{},output:{},server:{}}},t)),this.subEditor={},this.initDone=!1,this.options.have.statustext&&(this.subEditor.statustext=new DeconzStatusTextEditor(this.node,this.options.statustext)),this.options.have.device&&(this.subEditor.device=new DeconzDeviceEditor(this.node,this.options.device)),this.options.have.query&&(this.subEditor.query=new DeconzQueryEditor(this.node,this.options.query)),this.options.have.specific)switch(this.node.type){case"deconz-api":this.subEditor.specific=new DeconzSpecificApiEditor(this.node,this.options.specific.api);break;case"deconz-output":this.subEditor.specific=new DeconzSpecificOutputEditor(this.node,this.options.specific.output);break;case"deconz-server":this.subEditor.specific=new DeconzSpecificServerEditor(this.node,this.options.specific.server)}this.options.have.output_rules&&(this.subEditor.output_rules=new DeconzOutputRuleListEditor(this.node,this.options.output_rules)),this.options.have.commands&&(this.subEditor.commands=new DeconzCommandListEditor(this.node,this.options.commands))}get elements(){return{tipBox:"node-input-tip-box",server:"node-input-server"}}async configurationMigration(){if(!((this.node.config_version||0)>=this.node._def.defaults.config_version.value)){var e={};for(const o of Object.keys(this.node._def.defaults))e[o]=this.node[o];var t={id:this.node.id,type:this.node.type,config:JSON.stringify(e)};let i="Error while migrating the configuration of the node from version "+(this.node.config_version||0)+" to version "+this.node._def.defaults.config_version.value+".";t=await $.getJSON(this.NRCD+"/configurationMigration",t).catch((e,t)=>{this.$elements.tipBox.append(`<div class="form-tips form-warning"><p>Migration errors:</p><p>${i}</p></div>`)});if(t&&!t.notNeeded){if(t.new)for(var[s,n]of Object.entries(t.new))this.node[s]=n;if(t.delete&&Array.isArray(t.delete))for(const r of t.delete)delete this.node[r];var a=e=>"node-red-contrib-deconz"===e.substr(0,23)?RED._(e):e;t.errors&&Array.isArray(t.errors)&&0<t.errors.length&&this.$elements.tipBox.append('<div class="form-tips form-warning"><p>Migration errors:</p><ul>'+`<li>${t.errors.map(a).join("</li><li>")}</li>`+"</ul></div>"),t.info&&Array.isArray(t.info)&&0<t.info.length&&this.$elements.tipBox.append('<div class="form-tips"><p>Migration info:</p><ul>'+`<li>${t.info.map(a).join("</li><li>")}</li>`+"</ul></div>")}}}async init(){await new Promise(e=>setTimeout(e,100)),await super.init(),await this.configurationMigration(),this.initPromises=[];for(const t of Object.values(this.subEditor))this.initPromises.push(t.init(this));await Promise.all(this.initPromises),this.initDone=!0,delete this.initPromises;var e=[];for(const i of Object.values(this.subEditor))e.push(i.connect());await Promise.all(e)}get serverNode(){return"deconz-server"===this.node.type?this.node:RED.nodes.node(this.$elements.server.val())}async isInitialized(){this.initDone||await Promise.all(this.initPromises)}async updateQueryDeviceDisplay(e){var t=this.subEditor.query.$elements.select.typedInput("type");switch(t){case"device":await this.subEditor.device.updateList(e);break;case"json":case"jsonata":this.subEditor.query.$elements.select.typedInput("validate")&&await this.subEditor.query.updateList(e)}await this.subEditor.device.display("device"===t),await this.subEditor.query.display("device"!==t)}oneditsave(){var e;this.options.have.output_rules&&(e=this.subEditor.output_rules.value,this.node.outputs=e.length,this.node.output_rules=e),this.options.have.commands&&(this.node.commands=this.subEditor.commands.value),this.options.have.specific&&(this.node.specific=this.subEditor.specific.value)}}class DeconzStatusTextEditor extends DeconzEditor{constructor(e,t={}){super(e,$.extend({allowedTypes:["msg","jsonata"]},t))}get elements(){return{statustext:"node-input-statustext"}}async init(e){await super.init(),this.mainEditor=e,this.initTypedInput()}initTypedInput(){var e=[];this.mainEditor.options.have.statustext&&e.push({value:"auto",label:RED._(this.NRCD+"/server:editor.inputs.statustext.options.auto"),icon:`icons/${this.NRCD}/icon-color.png`,hasValue:!1}),this.$elements.statustext.typedInput({type:"auto",types:e.concat(this.options.allowedTypes),typeField:`#${this.elements.statustext}_type`})}}class DeconzDeviceListEditor extends DeconzEditor{constructor(e,t={}){super(e,t)}get xhrURL(){return this.NRCD+"/itemlist"}get xhrParams(){return{controllerID:this.mainEditor.serverNode.id,forceRefresh:this.options.refresh}}async display(e=!0){if(this.$elements.showHide)return e?this.$elements.showHide.show():this.$elements.showHide.hide(),this.$elements.showHide.promise()}async getItems(e,t){t.forceRefresh=e.refresh;var i=await $.getJSON(this.xhrURL,t).catch((e,t)=>{this.sendError(400===e.status&&e.responseText?e.responseText:t.toString())});if(!i||!i.error_message)return this.formatItemList(i.items,e.keepOnlyMatched);console.warn(i.error_message),RED.notify("Warning : "+i.error_message,{type:"warning",timeout:1e4})}async updateList(e){var t,i;e=$.extend({refresh:!0},e),this.mainEditor.serverNode&&(t=this.$elements.list,i=this.xhrParams,!0===this.options.batteryFilter&&(e.keepOnlyMatched=!0,i.query=JSON.stringify({type:"match",match:{"config.battery":{type:"complex",operator:"!==",value:void 0}}})),i=await this.getItems(e,i),t.children().remove(),i&&this.generateHtmlItemList(i,this.$elements.list),t.multipleSelect("refresh"),i)&&t.multipleSelect("enable")}formatItemList(e,t=!1){let s={};var i=(e,i)=>{e.forEach(e=>{var t=e.type;void 0===s[t]&&(s[t]=[]),e.query_match=i,s[t].push(e)})};return i(e.matched,!0),!1===t&&i(e.rejected,!1),s}generateHtmlItemList(e,t){var i,s,n=this.constructor===DeconzQueryEditor;for([i,s]of Object.entries(e).sort((e,t)=>{var i=e[0].toLowerCase(),s=t[0].toLowerCase();return i<s?-1:s<i?1:0})){var a=$("<optgroup/>").attr("label",i);for(const r of s.sort((e,t)=>{var i=e.name.toLowerCase(),s=t.name.toLowerCase();return i<s?-1:s<i?1:0})){let e=r.name;"groups"===r.device_type&&(e+=" (lights: "+r.lights.length,r.scenes.length&&(e+=", scenes: "+r.scenes.length),e+=")");var o=$("<option>"+e+"</option>").attr("value",r.device_path);n&&r.query_match&&o.attr("selected",""),o.appendTo(a)}a.appendTo(t)}}}class DeconzQueryEditor extends DeconzDeviceListEditor{constructor(e,t={}){super(e,$.extend({allowedTypes:["json","jsonata"]},t))}get elements(){return{select:"node-input-query",list:"node-input-query_result",showHide:".deconz-query-selector",refreshButton:"#force-refresh-query-result"}}get type(){return this.$elements.select.typedInput("type")}set type(e){this.$elements.list.typedInput("type",e)}get value(){return this.$elements.select.typedInput("value")}set value(e){this.$elements.list.typedInput("value",e)}get xhrParams(){var e=super.xhrParams;return e.query=this.value,e.queryType=this.type,e.nodeID=this.node.id,e}async init(e){await super.init(),this.mainEditor=e,this.initTypedInput(),this.$elements.list.multipleSelect({maxHeight:300,dropWidth:320,width:320,single:!1,selectAll:!1,filter:!0,filterPlaceholder:RED._(this.NRCD+"/server:editor.inputs.device.device.filter"),placeholder:RED._(this.NRCD+"/server:editor.multiselect.none_selected"),numberDisplayed:1,disableIfEmpty:!0,showClear:!1,hideOptgroupCheckboxes:!0,filterGroup:!0,onClick:e=>{this.$elements.list.multipleSelect(e.selected?"uncheck":"check",e.value)}}),await this.mainEditor.updateQueryDeviceDisplay({useSavedData:!0})}initTypedInput(){var e=[];this.mainEditor.options.have.device&&e.push({value:"device",label:RED._(this.NRCD+"/server:editor.inputs.device.query.options.device"),icon:`icons/${this.NRCD}/icon-color.png`,hasValue:!1}),this.$elements.select.typedInput({type:"text",types:e.concat(this.options.allowedTypes),typeField:"#node-input-search_type"})}async connect(){await super.connect(),this.$elements.select.on("change",()=>{this.mainEditor.updateQueryDeviceDisplay({useSavedData:!0}),this.mainEditor.options.have.output_rules&&this.mainEditor.subEditor.output_rules.refresh()}),this.$elements.refreshButton.on("click",()=>{this.updateList(),this.mainEditor.options.have.output_rules&&this.mainEditor.subEditor.output_rules.refresh()})}}class DeconzDeviceEditor extends DeconzDeviceListEditor{constructor(e,t={}){super(e,$.extend({batteryFilter:!1},t))}get elements(){return{list:"node-input-device_list",showHide:".deconz-device-selector",refreshButton:"#force-refresh"}}get value(){return this.$elements.list.multipleSelect("getSelects")}set value(e){this.$elements.list.multipleSelect("setSelects",e)}async init(e){await super.init(),this.mainEditor=e,this.$elements.list.multipleSelect({maxHeight:300,dropWidth:320,width:320,single:"multiple"!==this.$elements.list.attr("multiple"),filter:!0,filterPlaceholder:RED._(this.NRCD+"/server:editor.inputs.device.device.filter"),placeholder:RED._(this.NRCD+"/server:editor.multiselect.none_selected"),showClear:!0})}async connect(){await super.connect();var e=()=>{this.updateList($.extend(this.options,{useSelectedData:!0})),this.mainEditor.options.have.output_rules&&this.mainEditor.subEditor.output_rules.refresh()};this.mainEditor.$elements.server.on("change",e),this.$elements.refreshButton.on("click",e),this.mainEditor.options.have.output_rules&&this.$elements.list.on("change",()=>{this.mainEditor.subEditor.output_rules.refresh()})}async updateList(e){let t;(e=$.extend({useSavedData:!1,useSelectedData:!1},e)).useSelectedData&&(t=this.$elements.list.multipleSelect("getSelects")),await super.updateList(e),e.useSavedData&&Array.isArray(this.node.device_list)?this.$elements.list.multipleSelect("setSelects",this.node.device_list):e.useSelectedData&&Array.isArray(t)&&this.$elements.list.multipleSelect("setSelects",t)}}class DeconzSpecificApiEditor extends DeconzEditor{constructor(e,t={}){super(e,$.extend({},t))}get elements(){return{container:"deconz-api-form",name:"node-config-input-name",method:"node-config-input-method",endpoint:"node-config-input-endpoint",payload:"node-config-input-payload"}}get default(){return{name:"",method:{type:"GET"},endpoint:{type:"str",value:"/"},payload:{type:"json",value:"{}"}}}async init(){this.node.specific=$.extend(!0,this.default.specific,this.node.specific);var e=this.findElement(this.elements.container);await this.generateMethodField(e,this.node.specific.method),await this.generateEndpointField(e,this.node.specific.endpoint),await this.generatePayloadField(e,this.node.specific.payload),await super.init()}async connect(){await super.connect()}get value(){return{method:{type:this.$elements.method.typedInput("type"),value:this.$elements.method.typedInput("value")},endpoint:{type:this.$elements.endpoint.typedInput("type"),value:this.$elements.endpoint.typedInput("value")},payload:{type:this.$elements.payload.typedInput("type"),value:this.$elements.payload.typedInput("value")}}}set value(e){this.$elements.name.val(e.name);for(var t of["method","endpoint","payload"])this.$elements[t].typedInput("type",e[t].type),this.$elements[t].typedInput("value",e[t].value);for(const i of Object.values(this.$elements))i.trigger("change")}async generateMethodField(e,t={}){var i=this.NRCD+"/server:editor.inputs.specific.api.method";await this.generateTypedInputField(e,{id:this.elements.method,i18n:i,value:t,width:"250px",typedInput:{types:[this.generateTypedInputType(i,"GET",{hasValue:!1}),this.generateTypedInputType(i,"POST",{hasValue:!1}),this.generateTypedInputType(i,"PUT",{hasValue:!1}),this.generateTypedInputType(i,"DELETE",{hasValue:!1})]}})}async generateEndpointField(e,t={}){var i=this.NRCD+"/server:editor.inputs.specific.api.endpoint";await this.generateTypedInputField(e,{id:this.elements.endpoint,i18n:i,value:t,width:"250px",typedInput:{types:["str"]}})}async generatePayloadField(e,t={}){var i=this.NRCD+"/server:editor.inputs.specific.api.payload";await this.generateTypedInputField(e,{id:this.elements.payload,i18n:i,value:t,width:"250px",typedInput:{types:["json","jsonata"]}})}}class DeconzSpecificOutputEditor extends DeconzEditor{constructor(e,t={}){super(e,$.extend({},t))}get elements(){return{container:"specific-container",delay:"node-input-delay",result:"node-input-result"}}get default(){return{delay:{type:"num",value:50},result:{type:"at_end"}}}async init(){this.node.specific=$.extend(!0,this.default,this.node.specific);var e=this.findElement(this.elements.container);await this.generateSeparator(e,this.NRCD+"/server:editor.inputs.separator.specific"),await this.generateDelayField(e,this.node.specific.delay),await this.generateResultField(e,this.node.specific.result),await super.init()}async generateDelayField(e,t={}){var i=this.NRCD+"/server:editor.inputs.specific.output.delay";await this.generateTypedInputField(e,{id:this.elements.delay,i18n:i,value:t,width:"250px",typedInput:{types:["num"]}})}async generateResultField(e,t={}){var i=this.NRCD+"/server:editor.inputs.specific.output.result";await this.generateTypedInputField(e,{id:this.elements.result,i18n:i,value:t,width:"250px",typedInput:{types:[this.generateTypedInputType(i,"never",{hasValue:!1}),this.generateTypedInputType(i,"after_command",{hasValue:!1}),this.generateTypedInputType(i,"at_end",{hasValue:!1})]}})}async connect(){await super.connect()}get value(){return{delay:{type:this.$elements.delay.typedInput("type"),value:this.$elements.delay.typedInput("value")},result:{type:this.$elements.result.typedInput("type"),value:this.$elements.result.typedInput("value")}}}}class DeconzSpecificServerEditor extends DeconzEditor{constructor(e,t={}){super(e,$.extend({},t))}get elements(){return{name:"node-config-input-name",ip:"node-config-input-ip",port:"node-config-input-port",apikey:"node-config-input-secured_apikey",ws_port:"node-config-input-ws_port",secure:"node-config-input-secure",polling:"node-config-input-polling",getSettingsButton:"node-contrib-deconz-get-settings"}}get default(){return{name:"",ip:"",port:"",apikey:"",ws_port:"",secure:!1,polling:15}}get xhrURL(){return this.NRCD+"/serverAutoconfig"}async init(){this.node.specific=$.extend(!0,this.default,this.node.specific),await super.init(),this.node.migration_secured_apikey&&(this.$elements.apikey.val(this.node.migration_secured_apikey),this.$elements.apikey.trigger("change"))}async connect(){await super.connect(),this.$elements.getSettingsButton.on("click",()=>this.discoverParams())}async discoverParams(e){void 0===e&&(e={});let t,s=!1,n=()=>{t&&"function"==typeof t.close&&t.close(),s=!0};t=RED.notify("<p>Trying to find the server settings, please wait...<br>This can take up to 15 seconds.</p>",{modal:!0,fixed:!0,type:"info",buttons:[{text:"Cancel",class:"primary",click:n}]});try{var a=Object.assign({},this.value,e);void 0===a.discoverParam&&(a.discoverParam={}),a.discoverParam.devicetype="Node-Red Deconz Plugin"+(this.node?" id:"+this.node.id:"");let i=await $.getJSON(this.xhrURL,{config:JSON.stringify(a)}).catch((e,t)=>{this.sendError(400===e.status&&e.responseText?e.responseText:t.toString())});if(!s)if(i.error){let e=`<p>Error ${i.error.code}: ${i.error.description}</p>`;var o=[{text:"Cancel",click:n}];switch(i.error.code){case"GATEWAY_CHOICE":e+="<p>There is multiple Deconz device in you network, please select the one you want to configure.</p>";let t=this;for(const[r,l]of i.error.gateway_list.entries())o.push({text:`#${r+1}: `+l.name,id:"node-red-contrib-deconz-gateway-id-"+r,class:"primary",click:()=>{return e=l.bridge_id,n(),e&&(i.currentSettings.discoverParam.targetGatewayID=e),void t.discoverParams(i.currentSettings);var e}});o.push(o.shift());break;case"DECONZ_ERROR":101===i.error.type&&(o.unshift({text:"I pressed the link button",class:"primary",click:()=>{n(),this.discoverParams(i.currentSettings)}}),e=(e+="<p>The reason why the request failed is that the gateway was not unlocked. This mechanism is needed to prevent anybody from access to the gateway without being permitted to do so.</p><ul><li>In a new browser tab open the <a href='http://phoscon.de/pwa/' target='_blank'>Phoscon App</a></li><li>Click on Menu -> Settings -> Gateway</li><li>Click on \"Advanced\" button</li><li>Click on the \"Authenticate app\" button</li></ul>")+`<p>Within 60 seconds after unlocking the gateway, click on the button "${o[0].text}".</p>`);break;default:o[o.length-1].text="Cancel"}e+=`<p>Logs:</p><pre>${i.log.join("\n")}</pre>`,n(),t=RED.notify(e,{modal:!0,fixed:!0,type:"error",buttons:o})}else i.success?(n(),t=RED.notify("<p>Settings fetched successfully !</p>",{modal:!1,fixed:!1,type:"success"}),this.value=i.currentSettings):(n(),t=RED.notify(`<p>Unknown error : ${JSON.stringify(i)}</p>`,{modal:!0,fixed:!0,type:"error",buttons:[{text:"Ok",class:"primary",click:n}]}))}catch(e){n(),t=RED.notify(`<p>Error while processing request: ${e.toString()}</p>`,{type:"error"})}}get value(){return{name:this.$elements.name.val(),ip:this.$elements.ip.val(),port:this.$elements.port.val(),apikey:this.$elements.apikey.val(),ws_port:this.$elements.ws_port.val(),secure:this.$elements.secure.prop("checked"),polling:this.$elements.polling.val()}}set value(e){this.$elements.name.val(e.name),this.$elements.ip.val(e.ip),this.$elements.port.val(e.port),this.$elements.apikey.val(e.apikey),this.$elements.ws_port.val(e.ws_port),this.$elements.secure.prop("checked",e.secure),this.$elements.polling.val(e.polling);for(const t of Object.values(this.$elements))t.trigger("change")}}class DeconzListItemEditor extends DeconzEditor{constructor(e,t,i,s={}){super(e,s),this.listEditor=t,i.uniqueId(),this.uniqueId=i.attr("id"),this.container=i}set index(e){void 0!==e&&this.$elements&&this.$elements.outputButton&&this.$elements.outputButton.find(".node-input-rule-index").html(e+1),this._index=e}get index(){return this._index}async init(){await this.generateOutputButton(this.container.children().first()),await super.init()}async generateOutputButton(e){$("<a/>",{id:this.elements.outputButton,class:"red-ui-button top-right-badge",title:RED._(this.options.button_title)}).append(`&nbsp;&#8594;&nbsp;<span class="node-input-rule-index">${this.index+1}</span>&nbsp;`).appendTo(e)}}class DeconzListItemListEditor extends DeconzEditor{constructor(e,t={}){super(e,t),this.items={}}get listType(){return"item"}get buttons(){return[]}async init(e){await super.init(),this.mainEditor=e}async initList(n,e=[]){var t=this.buttons,i=0===t.length||DeconzEditor.versionCompare(RED.settings.version,"1.3.0")<0;this.$elements.list.editableList({sortable:!0,removable:!0,height:"auto",addButton:i,buttons:t,addItem:(e,t,i)=>{var s=new n(this.node,this,e,this.options);i.uniqueId=s.uniqueId,(this.items[i.uniqueId]=s).init(i,t)},removeItem:e=>{if(!e.uniqueId||!this.items[e.uniqueId])throw new Error(`Error while removing the ${this.listType}, the ${this.listType} ${e.uniqueId} does not exist.`);var t=this.items[e.uniqueId].index;delete this.items[e.uniqueId];for(const e of Object.values(this.items))e.index>t&&e.index--},sortItems:e=>{e.each((e,t)=>{if(!this.items[t.attr("id")])throw new Error(`Error while moving the ${this.listType}, the ${this.listType} ${e+1} does not exist.`);this.items[t.attr("id")].index=e})}}),0<e.length&&this.$elements.list.editableList("addItems",e)}get value(){var e=[];for(const t of Object.values(this.items).sort((e,t)=>e.index-t.index))e.push(t.value);return e}refresh(){}}class DeconzOutputRuleEditor extends DeconzListItemEditor{constructor(e,t,i,s={}){super(e,t,i,s=$.extend({enableEachState:!0},s))}get elements(){var e={};for(const t of["format","type","payload","output","onstart","onerror","outputButton"])e[t]=`node-input-output-rule-${this.uniqueId}-`+t;return e}get value(){var e={};switch(e.type=this.$elements.type.val(),e.format=this.$elements.format.val(),e.type){case"attribute":case"state":case"config":"deconz-input"===this.node.type&&(e.output=this.$elements.output.val()),["deconz-input","deconz-battery"].includes(this.node.type)&&(e.onstart=this.$elements.onstart.is(":checked")),["deconz-input","deconz-get"].includes(this.node.type)&&(e.payload=this.$elements.payload.multipleSelect("getSelects"));break;case"homekit":["deconz-input","deconz-battery"].includes(this.node.type)&&(e.onstart=this.$elements.onstart.is(":checked")),"deconz-input"===this.node.type&&(e.onerror=this.$elements.onerror.is(":checked")),["deconz-input","deconz-get"].includes(this.node.type)&&(e.payload=this.$elements.payload.multipleSelect("getSelects"))}return e}get defaultRule(){var e={type:"state",payload:["__complete__"],format:"single"};return"deconz-input"===this.node.type&&(e.output="always",e.onstart=!0,e.onerror=!0),"deconz-battery"===this.node.type&&(e.onstart=!0),e}async init(e,t){this._index=t,e=$.extend(!0,this.defaultRule,e),await this.generatePayloadTypeField(this.container,e.type),["deconz-input","deconz-get"].includes(this.node.type)&&await this.generatePayloadField(this.container),await this.generatePayloadFormatField(this.container,e.format),"deconz-input"===this.node.type&&await this.generateOutputField(this.container,(void 0!==e.output?e:this.defaultRule).output),["deconz-input","deconz-battery"].includes(this.node.type)&&await this.generateOnStartField(this.container,(void 0!==e.onstart?e:this.defaultRule).onstart),"deconz-input"===this.node.type&&await this.generateOnErrorField(this.container,(void 0!==e.onerror?e:this.defaultRule).onerror),await super.init(),await this.listEditor.mainEditor.isInitialized(),await this.initPayloadList(e.payload),await this.updateShowHide(e.type),await this.connect()}async connect(){await super.connect(),this.$elements.type.on("change",()=>{var e=this.$elements.type.val();["attribute","state","config","homekit"].includes(e)&&this.updatePayloadList(),this.updateShowHide(e)}),this.$elements.outputButton.on("click",()=>{try{var t=RED.nodes.filterLinks({source:this.node,sourcePort:this.index}).map(e=>{var t=e.target.type;return""!==e.target.name?t+":"+e.target.name:void 0!==e.target._def.label?t+":"+e.target._def.label():t});let e=RED.notify(`The output ${this.index+1} is sending message to ${t.length} nodes :<br>`+t.join("<br>"),{modal:!0,timeout:5e3,buttons:[{text:"okay",class:"primary",click:()=>e.close()}]})}catch(e){this.sendError("This is using not documented API so can be broken at anytime.<br>Error while getting connected nodes: "+e.toString())}})}async updateShowHide(e){switch(e){case"attribute":case"state":case"config":this.$elements.payload.closest(".form-row").show(),this.$elements.output.closest(".form-row").show(),this.$elements.onstart.closest(".form-row").show(),this.$elements.onerror.closest(".form-row").hide();break;case"homekit":this.$elements.payload.closest(".form-row").show(),this.$elements.output.closest(".form-row").hide(),this.$elements.onstart.closest(".form-row").show(),this.$elements.onerror.closest(".form-row").show();break;case"scene_call":this.$elements.payload.closest(".form-row").hide(),this.$elements.output.closest(".form-row").hide(),this.$elements.onstart.closest(".form-row").hide(),this.$elements.onerror.closest(".form-row").hide()}}async updatePayloadList(){if(this.listEditor.mainEditor.serverNode){this.$elements.payload.multipleSelect("disable"),this.$elements.payload.children().remove();var t=this.listEditor.mainEditor.subEditor.query.type,i=this.listEditor.mainEditor.subEditor.device.value,s=this.$elements.type.val();if(["attribute","state","config","homekit"].includes(s)){var n=this.NRCD+"/server:editor.inputs.outputs.payload";let e="";if("homekit"===s?e+='<option value="__auto__">'+RED._(n+".options.auto")+"</option>":(e+='<option value="__complete__">'+RED._(n+".options.complete")+"</option>",!0===this.options.enableEachState&&(e+='<option value="__each__">'+RED._(n+".options.each")+"</option>")),this.$elements.payload.html(e),"device"===t){var a=await $.getJSON(this.NRCD+`/${s}list`,{controllerID:this.listEditor.mainEditor.serverNode.id,devices:JSON.stringify(this.listEditor.mainEditor.subEditor.device.value)});for(const l of"attribute"===s?["attribute","state","config"]:[s]){let e=this.getI18n(n+".group_label."+l);void 0===e&&(e=l);var o=$("<optgroup/>",{label:e});for(const p of Object.keys(a.count[l]).sort()){let e=a.sample[l][p];e="string"==typeof e?`"${e}"`:Array.isArray(e)?`[${e.toString()}]`:null===e||void 0===e?"NULL":e.toString();let t;var r=a.count[l][p];t=r===i.length?RED._(n+".item_list",{name:p,sample:e}):RED._(n+".item_list_mix",{name:p,sample:e,item_count:r,device_count:i.length}),$("<option>"+t+"</option>").attr("value","attribute"===s&&"attribute"!==l?l+"."+p:p).appendTo(o)}$.isEmptyObject(a.count[l])||o.appendTo(this.$elements.payload)}}this.$elements.payload.multipleSelect("refresh").multipleSelect("enable")}}}async initPayloadList(e){let t=this.$elements.payload;t.addClass("multiple-select"),t.multipleSelect({maxHeight:300,dropWidth:300,width:200,numberDisplayed:1,single:!1,selectAll:!1,container:".node-input-output-container-row",filter:!0,filterPlaceholder:RED._(this.NRCD+"/server:editor.inputs.device.device.filter"),placeholder:RED._(this.NRCD+"/server:editor.multiselect.none_selected"),onClick:e=>{if(e.selected)switch(e.value){case"__complete__":case"__each__":case"__auto__":t.multipleSelect("setSelects",[e.value]);break;default:t.multipleSelect("uncheck","__complete__"),t.multipleSelect("uncheck","__each__"),t.multipleSelect("uncheck","__auto__")}},onUncheckAll:()=>{t.multipleSelect("setSelects",["__complete__","__auto__"])},onOptgroupClick:e=>{e.selected&&(t.multipleSelect("uncheck","__complete__"),t.multipleSelect("uncheck","__each__"),t.multipleSelect("uncheck","__auto__"))}}),await this.updatePayloadList(),e&&t.multipleSelect("setSelects",e)}async generatePayloadTypeField(e,t){var i,s,n=this.NRCD+"/server:editor.inputs.outputs.type",a=[];for([i,s]of Object.entries(this.listEditor.options.type))s&&a.push([i,n+".options."+i]);await this.generateSimpleListField(e,{id:this.elements.type,i18n:n,choices:a,currentValue:t})}async generatePayloadField(e){var t=this.NRCD+"/server:editor.inputs.outputs.payload";await this.generateSimpleListField(e,{id:this.elements.payload,i18n:t})}async generatePayloadFormatField(e,t){var i,s,n=this.NRCD+"/server:editor.inputs.outputs.format",a=[];for([i,s]of Object.entries(this.listEditor.options.format))s&&a.push([i,n+".options."+i]);await this.generateSimpleListField(e,{id:this.elements.format,i18n:n,choices:a,currentValue:t})}async generateOutputField(e,t){var i=this.NRCD+"/server:editor.inputs.outputs.output";await this.generateSimpleListField(e,{id:this.elements.output,i18n:i,choices:[["always",i+".options.always"],["onchange",i+".options.onchange"],["onupdate",i+".options.onupdate"]],currentValue:t})}async generateOnStartField(e,t){var i=this.NRCD+"/server:editor.inputs.outputs.on_start";await this.generateCheckboxField(e,{id:this.elements.onstart,i18n:i,currentValue:t})}async generateOnErrorField(e,t){var i=this.NRCD+"/server:editor.inputs.outputs.on_error";await this.generateCheckboxField(e,{id:this.elements.onerror,i18n:i,currentValue:t})}}class DeconzOutputRuleListEditor extends DeconzListItemListEditor{get elements(){return{list:"node-input-output-container"}}get listType(){return"rule"}get buttons(){var e,t=[],i=this.NRCD+"/server:editor.inputs.outputs.type";for(const[s,n]of Object.entries(this.options.type))n&&(e=this.getI18n(i+".options."+s),t.push({label:this.getI18n(i+".add_button","label",{type:e}),icon:this.getIcon(this.getI18n(i+".add_button","icon"),!0),title:this.getI18n(i+".add_button","title",{type:e}),click:()=>this.$elements.list.editableList("addItem",{type:s})}));return t}async init(e){await super.init(e),await this.initList(DeconzOutputRuleEditor,this.node.output_rules)}refresh(){for(const e of Object.values(this.items))e.updatePayloadList()}}class DeconzCommandEditor extends DeconzListItemEditor{constructor(e,t,i,s={}){super(e,t,i,s=$.extend({},s)),this.containers={}}get lightKeys(){return["bri","sat","hue","ct","xy"]}get argKeys(){return["on","alert","effect","colorloopspeed","open","stop","lift","tilt","scene_mode","group","scene","scene_name","target","command","payload","delay","transitiontime","retryonerror","aftererror"]}get elements(){var e=this.argKeys;e.push("typedomain"),e.push("outputButton"),e.push("scene_picker"),e.push("scene_picker_refresh");for(const i of this.lightKeys)e.push(i),e.push(i+"_direction");var t={};for(const s of e)t[s]=`node-input-output-rule-${this.uniqueId}-`+s;return t}set value(e){}get value(){var e={arg:{}};e.type=this.$elements.typedomain.typedInput("type"),e.domain=this.$elements.typedomain.typedInput("value");for(const t of this.argKeys)this.$elements[t].parent(".form-row").is(":visible")&&(e.arg[t]={type:this.$elements[t].typedInput("type"),value:this.$elements[t].typedInput("value")});for(const i of this.lightKeys)this.$elements[i].parent(".form-row").is(":visible")&&(e.arg[i]={direction:this.$elements[i+"_direction"].typedInput("type"),type:this.$elements[i].typedInput("type"),value:this.$elements[i].typedInput("value")});return e}get defaultCommand(){return{type:"deconz_state",domain:"lights",target:"state",arg:{on:{type:"keep"},bri:{direction:"set",type:"num"},sat:{direction:"set",type:"num"},hue:{direction:"set",type:"num"},ct:{direction:"set",type:"num"},xy:{direction:"set",type:"num"},alert:{type:"str"},effect:{type:"str"},colorloopspeed:{type:"num"},transitiontime:{type:"num"},command:{type:"str",value:"on"},payload:{type:"msg",value:"payload"},delay:{type:"num",value:2e3},target:{type:"state"},group:{type:"num"},scene_mode:{type:"single"},scene_call:{type:"num"},scene_name:{type:"str"},retryonerror:{type:"num",value:0},aftererror:{type:"continue"}}}}async init(e,t){this._index=t,e=$.extend(!0,this.defaultCommand,e),await this.generateTypeDomainField(this.container,{type:e.type,value:e.domain}),this.containers.light=$("<div>").appendTo(this.container),await this.generateLightOnField(this.containers.light,e.arg.on);for(const i of["bri","sat","hue","ct","xy"])await this.generateLightColorField(this.containers.light,i,e.arg[i]),"bri"===i&&await this.generateHR(this.containers.light);await this.generateHR(this.containers.light),await this.generateLightAlertField(this.containers.light,e.arg.alert),await this.generateLightEffectField(this.containers.light,e.arg.effect),await this.generateLightColorLoopSpeedField(this.containers.light,e.arg.colorloopspeed),this.containers.windows_cover=$("<div>").appendTo(this.container),await this.generateCoverOpenField(this.containers.windows_cover,e.arg.open),await this.generateCoverStopField(this.containers.windows_cover,e.arg.stop),await this.generateCoverLiftField(this.containers.windows_cover,e.arg.lift),await this.generateCoverTiltField(this.containers.windows_cover,e.arg.tilt),this.containers.scene_call=$("<div>").appendTo(this.container),await this.generateSceneModeField(this.containers.scene_call,e.arg.scene_mode),this.containers.scene_call_single=$("<div>").appendTo(this.containers.scene_call),await this.generateScenePickerField(this.containers.scene_call_single,e.arg.group+"."+e.arg.scene),await this.generateSceneGroupField(this.containers.scene_call_single,e.arg.group),await this.generateSceneSceneField(this.containers.scene_call_single,e.arg.scene),this.containers.scene_call_dynamic=$("<div>").appendTo(this.containers.scene_call),await this.generateSceneNameField(this.containers.scene_call_dynamic,e.arg.scene_name),this.containers.target=$("<div>").appendTo(this.container),await this.generateTargetField(this.containers.target,e.arg.target),this.containers.command=$("<div>").appendTo(this.container),await this.generateCommandField(this.containers.command,e.arg.command),this.containers.payload=$("<div>").appendTo(this.container),await this.generatePayloadField(this.containers.payload,e.arg.payload),this.containers.pause=$("<div>").appendTo(this.container),await this.generatePauseDelayField(this.containers.pause,e.arg.delay),this.containers.transition=$("<div>").appendTo(this.container),await this.generateHR(this.containers.transition),await this.generateCommonTransitionTimeField(this.containers.transition,e.arg.transitiontime),this.containers.common=$("<div>").appendTo(this.container),await this.generateHR(this.containers.common),await this.generateCommonOnErrorRetryField(this.containers.common,e.arg.retryonerror),await this.generateCommonOnErrorAfterField(this.containers.common,e.arg.aftererror),await super.init(),await this.listEditor.mainEditor.isInitialized(),await this.updateShowHide(e.type,e.domain),await this.connect()}async connect(){await super.connect(),this.$elements.typedomain.on("change",(e,t,i)=>{this.updateShowHide(t,i)}),this.$elements.outputButton.on("click",async()=>{try{if("device"!==this.listEditor.mainEditor.subEditor.query.type)this.sendError("Error : The run command can only work with device list.",5e3);else{var t=this.value,i=this.listEditor.mainEditor.subEditor.device.value;if(0!==i.length||("deconz_state"===t.type&&"scene_call"===t.domain||"custom"===t.type&&"scene_call"===t.arg.target.type))if("pause"===t.type)this.sendError("Error : Can't test pause command.",5e3);else{for(var[s,n]of Object.entries(t.arg))if(["msg","flow","global","jsonata"].includes(n.type))return void this.sendError(`Error : Cant run this command because the value "${s}" is type "${n.type}".`,5e3);let e=RED.notify("Sending request...",{type:"info"});await $.post(this.NRCD+"/testCommand",{controllerID:this.listEditor.mainEditor.serverNode.id,device_list:i,command:t,delay:this.listEditor.mainEditor.subEditor.specific.value.delay}).catch((e,t)=>{this.sendError(400===e.status&&e.responseText?e.responseText:t.toString())});e.close(),e=RED.notify("Ok",{timeout:1e3,type:"success"})}else this.sendError("Error : No device selected.",5e3)}}catch(e){let t=RED.notify(e.toString(),{type:"error",buttons:[{class:"error",click:()=>t.close()}]})}});const e=()=>{var e=this.$elements.scene_picker.multipleSelect("getSelects");1===e.length&&(this.$elements.group.off("change",t),this.$elements.scene.off("change",t),e=e[0].split("."),this.$elements.group.typedInput("type","num"),this.$elements.group.typedInput("value",e[0]),this.$elements.scene.typedInput("type","num"),this.$elements.scene.typedInput("value",e[1]),this.$elements.group.on("change",t),this.$elements.scene.on("change",t))},t=()=>{this.$elements.scene_picker.off("change",e),this.$elements.scene_picker.multipleSelect("setSelects","num"!==this.$elements.group.typedInput("type")||"num"!==this.$elements.group.typedInput("type")?[]:[this.$elements.group.typedInput("value")+"."+this.$elements.scene.typedInput("value")]),this.$elements.scene_picker.on("change",e)};this.$elements.scene_mode.on("change",()=>{var e="single"===this.$elements.scene_mode.typedInput("type");this.containers.scene_call_single.toggle(e),this.containers.scene_call_dynamic.toggle(!e)}),this.$elements.scene_picker.on("change",e),this.$elements.group.on("change",t),this.$elements.scene.on("change",t),this.$elements.scene_picker_refresh.on("click",()=>this.updateSceneList()),this.$elements.target.on("change",(e,t,i)=>{this.containers.command.toggle("scene_call"!==t)})}async updateShowHide(e,t){var i,s,n=[];switch(e){case"deconz_state":switch(t){case"lights":case"groups":n.push("light"),n.push("transition");break;case"covers":n.push("windows_cover");break;case"scene_call":n.push("scene_call"),await this.updateSceneList(),n.push("scene_call_"+("single"===this.$elements.scene_mode.typedInput("type")?"single":"dynamic"))}n.push("common");break;case"homekit":this.$elements.payload.typedInput("types",["msg","flow","global","json","jsonata"]),n.push("payload"),n.push("transition"),n.push("common");break;case"custom":n.push("target"),"scene_call"!==this.$elements.target.typedInput("type")&&n.push("command"),this.$elements.payload.typedInput("types",["msg","flow","global","str","num","bool","json","jsonata","date"]),n.push("payload"),n.push("transition"),n.push("common");break;case"pause":n.push("pause")}for([i,s]of Object.entries(this.containers))s.toggle(n.includes(i))}async updateSceneList(){this.$elements.scene_picker.multipleSelect("disable"),this.$elements.scene_picker.children().remove();var e=this.listEditor.mainEditor.subEditor.query;if(void 0!==e){var t=e.xhrParams,e=(t.queryType="json",t.query=JSON.stringify({match:{device_type:"groups"}}),await e.getItems({refresh:!0,keepOnlyMatched:!0},t));if(void 0!==e&&void 0!==e.LightGroup){for(const s of e.LightGroup){var i=$("<optgroup/>",{label:s.id+" - "+s.name});if(s.scenes&&0<s.scenes.length){for(const n of s.scenes)$(`<option>${n.id} - ${n.name}</option>`).attr("value",s.id+"."+n.id).appendTo(i);i.appendTo(this.$elements.scene_picker)}}this.$elements.scene_picker.multipleSelect("refresh").multipleSelect("enable"),this.$elements.scene_picker.multipleSelect("setSelects","num"!==this.$elements.group.typedInput("type")||"num"!==this.$elements.group.typedInput("type")?[]:[this.$elements.group.typedInput("value")+"."+this.$elements.scene.typedInput("value")])}}}async generateTypeDomainField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type";await this.generateTypedInputField(e,{id:this.elements.typedomain,i18n:i,value:t,addDefaultTypes:!1,typedInput:{default:"deconz_state",types:[this.generateTypedInputType(i,"deconz_state",{subOptions:["lights","covers","groups","scene_call"]}),this.generateTypedInputType(i,"homekit",{hasValue:!1}),this.generateTypedInputType(i,"custom",{hasValue:!1}),this.generateTypedInputType(i,"pause",{hasValue:!1})]}})}async generateLightOnField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.lights.fields.on";await this.generateTypedInputField(e,{id:this.elements.on,i18n:i,value:t,typedInput:{default:"keep",types:[this.generateTypedInputType(i,"keep",{hasValue:!1}),this.generateTypedInputType(i,"set",{subOptions:["true","false"]}),this.generateTypedInputType(i,"toggle",{hasValue:!1})]}})}async generateLightColorField(e,t,i={}){var s=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.lights.fields";let n=["num"];var a=[this.generateTypedInputType(s+".lightFields","set",{hasValue:!1})];switch(t){case"bri":n.push("str"),a.push(this.generateTypedInputType(s+".lightFields","inc",{hasValue:!1})),a.push(this.generateTypedInputType(s+".lightFields","dec",{hasValue:!1})),a.push(this.generateTypedInputType(s+".lightFields","detect_from_value",{hasValue:!1}));break;case"ct":n.push("str"),n.push(this.generateTypedInputType(s+".ct","deconz",{subOptions:["cold","white","warm"]})),a.push(this.generateTypedInputType(s+".lightFields","inc",{hasValue:!1})),a.push(this.generateTypedInputType(s+".lightFields","dec",{hasValue:!1})),a.push(this.generateTypedInputType(s+".lightFields","detect_from_value",{hasValue:!1}));break;case"xy":n=["json"]}await this.generateDoubleTypedInputField(e,{id:this.elements[t+"_direction"],i18n:s+"."+t,addDefaultTypes:!1,value:{type:i.direction},typedInput:{types:a}},{id:this.elements[t],value:{type:i.type,value:["xy"===t&&void 0===i.value?"[]":i.value]},typedInput:{types:n}})}async generateLightAlertField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.lights.fields.alert";await this.generateTypedInputField(e,{id:this.elements.alert,i18n:i,value:t,typedInput:{types:["str",this.generateTypedInputType(i,"deconz",{subOptions:["none","select","lselect"]})]}})}async generateLightEffectField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.lights.fields.effect";await this.generateTypedInputField(e,{id:this.elements.effect,i18n:i,value:t,typedInput:{types:["str",this.generateTypedInputType(i,"deconz",{subOptions:["none","colorloop"]})]}})}async generateLightColorLoopSpeedField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.lights.fields.colorloopspeed";await this.generateTypedInputField(e,{id:this.elements.colorloopspeed,i18n:i,value:t,typedInput:{types:["num"]}})}async generateCoverOpenField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.covers.fields.open";await this.generateTypedInputField(e,{id:this.elements.open,i18n:i,value:t,typedInput:{types:[this.generateTypedInputType(i,"keep",{hasValue:!1}),this.generateTypedInputType(i,"set",{subOptions:["true","false"]}),this.generateTypedInputType(i,"toggle",{hasValue:!1})]}})}async generateCoverStopField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.covers.fields.stop";await this.generateTypedInputField(e,{id:this.elements.stop,i18n:i,value:t,typedInput:{types:[this.generateTypedInputType(i,"keep",{hasValue:!1}),this.generateTypedInputType(i,"set",{subOptions:["true","false"]})]}})}async generateCoverLiftField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.covers.fields.lift";await this.generateTypedInputField(e,{id:this.elements.lift,i18n:i,value:t,typedInput:{types:["num","str",this.generateTypedInputType(i,"stop",{hasValue:!1})]}})}async generateCoverTiltField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.covers.fields.tilt";await this.generateTypedInputField(e,{id:this.elements.tilt,i18n:i,value:t,typedInput:{types:["num"]}})}async generateSceneModeField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.scene_call.fields.mode";await this.generateTypedInputField(e,{id:this.elements.scene_mode,i18n:i,value:t,addDefaultTypes:!1,typedInput:{types:[this.generateTypedInputType(i,"single",{hasValue:!1}),this.generateTypedInputType(i,"dynamic",{hasValue:!1})]}})}async generateScenePickerField(e,t=0){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.scene_call.fields.picker",s=await this.generateSimpleListField(e,{id:this.elements.scene_picker,i18n:i}),i=(s.addClass("multiple-select"),s.multipleSelect({maxHeight:300,dropWidth:300,width:200,numberDisplayed:1,single:!0,singleRadio:!0,hideOptgroupCheckboxes:!0,showClear:!0,selectAll:!1,filter:!0,filterPlaceholder:this.getI18n(i,"filter_place_holder"),placeholder:RED._(this.NRCD+"/server:editor.multiselect.none_selected"),container:".node-input-output-container-row"}),$("<a/>",{id:this.elements.scene_picker_refresh,class:"red-ui-button",style:"margin-left:10px;"}));this.createIconElement(this.getIcon("refresh"),i),s.closest(".form-row").append(i)}async generateSceneGroupField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.scene_call.fields.group";await this.generateTypedInputField(e,{id:this.elements.group,i18n:i,value:t,typedInput:{types:["num"]}})}async generateSceneSceneField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.scene_call.fields.scene";await this.generateTypedInputField(e,{id:this.elements.scene,i18n:i,value:t,typedInput:{types:["num","str",this.generateTypedInputType(i,"deconz",{subOptions:["next","prev"]})]}})}async generateSceneNameField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.scene_call.fields.scene_name";await this.generateTypedInputField(e,{id:this.elements.scene_name,i18n:i,value:t,typedInput:{types:["str","re"]}})}async generateTargetField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.common.fields.target";await this.generateTypedInputField(e,{id:this.elements.target,i18n:i,value:t,typedInput:{types:[this.generateTypedInputType(i,"attribute",{hasValue:!1}),this.generateTypedInputType(i,"state",{hasValue:!1}),this.generateTypedInputType(i,"config",{hasValue:!1}),this.generateTypedInputType(i,"scene_call",{hasValue:!1})]}})}async generateCommandField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.common.fields.command";await this.generateTypedInputField(e,{id:this.elements.command,i18n:i,value:t,typedInput:{types:["str",this.generateTypedInputType(i,"object",{hasValue:!1})]}})}async generatePayloadField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.common.fields.payload";await this.generateTypedInputField(e,{id:this.elements.payload,i18n:i,value:t,addDefaultTypes:!1,typedInput:{types:["msg","flow","global","str","num","bool","json","jsonata","date"]}})}async generatePauseDelayField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.pause.fields.delay";await this.generateTypedInputField(e,{id:this.elements.delay,i18n:i,value:t,typedInput:{types:["num"]}})}async generateCommonTransitionTimeField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.common.fields.transitiontime";await this.generateTypedInputField(e,{id:this.elements.transitiontime,i18n:i,value:t,typedInput:{types:["num"]}})}async generateCommonOnErrorRetryField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.common.fields.retryonerror";await this.generateTypedInputField(e,{id:this.elements.retryonerror,i18n:i,value:t,typedInput:{types:["num"]}})}async generateCommonOnErrorAfterField(e,t={}){var i=this.NRCD+"/server:editor.inputs.commands.type.options.deconz_state.options.common.fields.aftererror";await this.generateTypedInputField(e,{id:this.elements.aftererror,i18n:i,value:t,typedInput:{types:[this.generateTypedInputType(i,"continue",{hasValue:!1}),this.generateTypedInputType(i,"stop",{hasValue:!1})]}})}}class DeconzCommandListEditor extends DeconzListItemListEditor{get elements(){return{list:"node-input-output-container"}}get listType(){return"command"}get buttons(){var e,t=[],i=this.NRCD+"/server:editor.inputs.commands.type";for(const[s,n]of Object.entries(this.options.type))n&&(e=this.getI18n(i+".options."+s,"label"),t.push({label:this.getI18n(i+".add_button","label",{type:e}),icon:this.getIcon(this.getI18n(i+".add_button","icon"),!0),title:this.getI18n(i+".add_button","title",{type:e}),click:()=>this.$elements.list.editableList("addItem",{type:s})}));return t}async init(e){await super.init(e),await this.initList(DeconzCommandEditor,this.node.commands)}}
//# sourceMappingURL=deconz-editor.js.map

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc