iobroker.openknx 0.1.9 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,421 +1,494 @@
1
1
  <html>
2
- <head>
3
- <!-- Load ioBroker scripts and styles-->
4
- <link rel="stylesheet" type="text/css" href="../../css/adapter.css" />
5
- <link rel="stylesheet" type="text/css" href="../../lib/css/materialize.css" />
6
2
 
7
- <link rel="stylesheet" type="text/css" href="../../lib/css/themes/jquery-ui/redmond/jquery-ui.min.css" />
8
-
9
- <script type="text/javascript" src="../../lib/js/jquery-3.2.1.min.js"></script>
10
- <script type="text/javascript" src="../../socket.io/socket.io.js"></script>
11
-
12
- <script type="text/javascript" src="../../js/translate.js"></script>
13
- <script type="text/javascript" src="../../lib/js/materialize.js"></script>
14
- <script type="text/javascript" src="../../js/adapter-settings.js"></script>
15
-
16
- <!-- Load our own files -->
17
- <link rel="stylesheet" type="text/css" href="style.css" />
18
- <script type="text/javascript" src="words.js"></script>
19
-
20
- <style>
21
- #progress {
22
- display: none;
23
- }
24
-
25
- #drop-zone {
26
- width: calc(100% - 10px);
27
- height: calc(100% - 10px);
28
- position: absolute;
29
- opacity: 0.8;
30
- top: 0;
31
- left: 0;
32
- background: #eee;
33
- -webkit-border-radius: 15px;
34
- -moz-border-radius: 15px;
35
- border-radius: 15px;
36
- z-index: 1;
37
- font-size: 32px;
38
- font-weight: bold;
39
- text-align: center;
40
- border: 5px dashed darkgray;
41
- }
42
-
43
- .dropZone-error {
44
- background: #faa !important;
45
- color: #f00;
46
- }
47
-
48
- /* Tooltip container */
49
- .tooltip {
50
- position: relative;
51
- display: inline-block;
52
- border-bottom: 1px dotted black;
53
- /* If you want dots under the hoverable text */
54
- }
55
-
56
- /* Tooltip text */
57
- .tooltip .tooltiptext {
58
- visibility: hidden;
59
- width: 120px;
60
- background-color: black;
61
- color: #fff;
62
- text-align: center;
63
- padding: 5px 0;
64
- border-radius: 6px;
65
-
66
- /* Position the tooltip text */
67
- position: absolute;
68
- z-index: 1;
69
- }
70
-
71
- /* Show the tooltip text when you mouse over the tooltip container */
72
- .tooltip:hover .tooltiptext {
73
- visibility: visible;
74
- }
75
-
76
- .instructions {
77
- font-size: 16px;
78
- }
3
+ <head>
4
+ <!-- Load ioBroker scripts and styles-->
5
+ <link rel="stylesheet" type="text/css" href="../../css/adapter.css" />
6
+ <link rel="stylesheet" type="text/css" href="../../lib/css/materialize.css" />
7
+
8
+ <link rel="stylesheet" type="text/css" href="../../lib/css/themes/jquery-ui/redmond/jquery-ui.min.css" />
9
+
10
+ <script type="text/javascript" src="../../lib/js/jquery-3.2.1.min.js"></script>
11
+ <script type="text/javascript" src="../../socket.io/socket.io.js"></script>
12
+
13
+ <script type="text/javascript" src="../../js/translate.js"></script>
14
+ <script type="text/javascript" src="../../lib/js/materialize.js"></script>
15
+ <script type="text/javascript" src="../../js/adapter-settings.js"></script>
16
+
17
+ <!-- Load our own files -->
18
+ <link rel="stylesheet" type="text/css" href="style.css" />
19
+ <script type="text/javascript" src="words.js"></script>
20
+
21
+ <style>
22
+ #progress {
23
+ display: none;
24
+ }
25
+
26
+ #drop-zone {
27
+ width: calc(100% - 10px);
28
+ height: calc(100% - 10px);
29
+ position: absolute;
30
+ opacity: 0.8;
31
+ top: 0;
32
+ left: 0;
33
+ background: #eee;
34
+ -webkit-border-radius: 15px;
35
+ -moz-border-radius: 15px;
36
+ border-radius: 15px;
37
+ z-index: 1;
38
+ font-size: 32px;
39
+ font-weight: bold;
40
+ text-align: center;
41
+ border: 5px dashed darkgray;
42
+ }
43
+
44
+ .dropZone-error {
45
+ background: #faa !important;
46
+ color: #f00;
47
+ }
48
+
49
+ /* Tooltip container */
50
+ .tooltip {
51
+ position: relative;
52
+ display: inline-block;
53
+ border-bottom: 1px dotted black;
54
+ /* If you want dots under the hoverable text */
55
+ }
56
+
57
+ /* Tooltip text */
58
+ .tooltip .tooltiptext {
59
+ visibility: hidden;
60
+ width: 120px;
61
+ background-color: black;
62
+ color: #fff;
63
+ text-align: center;
64
+ padding: 5px 0;
65
+ border-radius: 6px;
66
+
67
+ /* Position the tooltip text */
68
+ position: absolute;
69
+ z-index: 1;
70
+ }
71
+
72
+ /* Show the tooltip text when you mouse over the tooltip container */
73
+ .tooltip:hover .tooltiptext {
74
+ visibility: visible;
75
+ }
76
+
77
+ .instructions {
78
+ font-size: 16px;
79
+ }
80
+
81
+ .page {
82
+ height: calc(100% - 120px) !important;
83
+ }
84
+
85
+ .modal-header {
86
+ padding: 16px 16px;
87
+ color: #fff;
88
+ }
89
+
90
+ .tab-active {
91
+ background-color: white !important;
92
+ color: #39a1f4 !important;
93
+ }
94
+
95
+ .dialog {
96
+ width: 100%;
97
+ height: calc(100% - 64px);
98
+ overflow: auto;
99
+ }
100
+ </style>
101
+
102
+ <script type="text/javascript">
103
+ var etsFile = '<input type="file" id="etsFile" style="display: inline-block"/>';
104
+
105
+ // This will be called by the admin adapter when the settings page loads
106
+ function load(settings, onChange) {
107
+ if (!settings) return;
108
+
109
+ // Check adapter is alive
110
+ window.isProcessingRequest = false
111
+ this.checkInterval = setInterval(() => {
112
+
113
+ this.getIsAdapterAlive( function (isAlive) {
114
+ if (isAlive && !window.isProcessingRequest) {
115
+ $("#onlyAddNewObjects").removeClass("disabled");
116
+ $(".file-field .btn").removeClass("disabled");
117
+ $(".file-field .file-path").prop("disabled", false);
118
+ $("#etsFile").prop("disabled", false);
119
+ $("#createAlias").removeClass("disabled");
120
+ } else {
121
+ $("#etsFile").prop("disabled", true);
122
+ $("#createAlias").addClass("disabled");
123
+ $(".file-field .btn").addClass("disabled");
124
+ $(".file-field .file-path").prop("disabled", true);
125
+ }
126
+ });
127
+ }, 1000)
128
+ if (settings.gwip === undefined) settings.gwip = "127.0.0.1";
129
+ if (settings.gwipport === undefined) settings.gwipport = 3671;
130
+ if (settings.debugLevel === undefined) settings.debugLevel = 0; //todo
131
+ if (settings.frameInterval === undefined) settings.frameInterval = 40;
132
+ if (settings.bind === undefined) settings.bind = ""; //local network interface
133
+ if (settings.eibadr === undefined) settings.eibadr = "1.1.1";
134
+ if (settings.onlyAddNewObjects === undefined) settings.onlyAddNewObjects = false;
135
+
136
+ //fill dropdown list bind
137
+ getIPs(function (ips) {
138
+ for (var i = 0; i < ips.length; i++) {
139
+ if (ips[i].family.indexOf("ipv4") > -1 && ips[i].address !== "0.0.0.0") {
140
+ $("#bind").append('<option value="' + ips[i].address + '">' + ips[i].name + "</option>");
141
+ }
142
+ }
143
+ $("#bind.value").val(settings.bind).select();
144
+ });
79
145
 
80
- .page {
81
- height: calc(100% - 120px) !important;
82
- }
146
+ fillSelectIPs("#adapterAddress", settings.adapterAddress, false, true);
83
147
 
84
- .modal-header {
85
- padding: 16px 16px;
86
- color: #fff;
87
- }
148
+ showConfigDialog();
149
+ $("#progress").hide();
150
+ $("#progress2").hide();
88
151
 
89
- .tab-active {
90
- background-color: white !important;
91
- color: #39a1f4 !important;
92
- }
152
+ $(".value").each(function () {
153
+ var $key = $(this);
154
+ var id = $key.attr("id");
155
+ if ($key.attr("type") === "checkbox") {
156
+ // do not call onChange direct, because onChange could expect some arguments
157
+ $key.prop("checked", settings[id]).on("change", () => onChange());
158
+ } else {
159
+ // do not call onChange direct, because onChange could expect some arguments
160
+ $key.val(settings[id])
161
+ .on("change", () => onChange())
162
+ .on("keyup", () => onChange());
163
+ }
93
164
 
94
- .dialog {
95
- width: 100%;
96
- height: calc(100% - 64px);
97
- overflow: auto;
98
- }
99
- </style>
100
-
101
- <script type="text/javascript">
102
- var knxprojFile = '<input type="file" id="knxprojFile" style="display: inline-block"/>';
103
-
104
- // This will be called by the admin adapter when the settings page loads
105
- function load(settings, onChange) {
106
- if (!settings) return;
107
-
108
- if (settings.gwip === undefined) settings.gwip = "127.0.0.1";
109
- if (settings.gwipport === undefined) settings.gwipport = 3671;
110
- if (settings.debugLevel === undefined) settings.debugLevel = 0; //todo
111
- if (settings.frameInterval === undefined) settings.frameInterval = 40;
112
- if (settings.bind === undefined) settings.bind = ""; //local network interface
113
- if (settings.eibadr === undefined) settings.eibadr = "1.1.1";
114
- if (settings.onlyAddNewObjects === undefined) settings.onlyAddNewObjects = false;
115
-
116
- //fill dropdown list bind
117
- getIPs(function (ips) {
118
- for (var i = 0; i < ips.length; i++) {
119
- if (ips[i].family.indexOf("ipv4") > -1 && ips[i].address !== "0.0.0.0") {
120
- $("#bind").append('<option value="' + ips[i].address + '">' + ips[i].name + "</option>");
165
+ //add sanity checks
166
+ $key.val(settings[id]).focusout("change", function () {
167
+ if (id === "gwip") {
168
+ var ip1 = $("#gwip").val();
169
+ if (isIpValid(ip1)) {
170
+ $("#gwip").val(ip1);
171
+ } else {
172
+ alert("invalid IP address");
121
173
  }
122
174
  }
123
- $("#bind.value").val(settings.bind).select();
124
- });
125
-
126
- fillSelectIPs("#adapterAddress", settings.adapterAddress, false, true);
127
-
128
- showConfigDialog();
129
-
130
- $(".value").each(function () {
131
- var $key = $(this);
132
- var id = $key.attr("id");
133
- if ($key.attr("type") === "checkbox") {
134
- // do not call onChange direct, because onChange could expect some arguments
135
- $key.prop("checked", settings[id]).on("change", () => onChange());
136
- } else {
137
- // do not call onChange direct, because onChange could expect some arguments
138
- $key.val(settings[id])
139
- .on("change", () => onChange())
140
- .on("keyup", () => onChange());
141
- }
142
175
 
143
- //add sanity checks
144
- $key.val(settings[id]).focusout("change", function () {
145
- if (id === "gwip") {
146
- var ip1 = $("#gwip").val();
147
- if (ValidateIPaddress(ip1)) {
148
- $("#gwip").val(ip1);
149
- } else {
150
- alert("invalid IP address");
151
- }
152
- }
153
-
154
- if (id === "gwipport") {
155
- var gwipport1 = $("#gwipport").val();
156
- if (ValidatePortaddress(gwipport1)) {
157
- $("#gwipport").val(gwipport1);
158
- } else {
159
- alert("invalid port number");
160
- }
176
+ if (id === "gwipport") {
177
+ var gwipport1 = $("#gwipport").val();
178
+ if (isPortValid(gwipport1)) {
179
+ $("#gwipport").val(gwipport1);
180
+ } else {
181
+ alert("invalid port number");
161
182
  }
183
+ }
162
184
 
163
- if (id === "eibadr") {
164
- var eibadr1 = $("#eibadr").val();
165
- if (ValidateEIBaddress(eibadr1)) {
166
- $("#eibadr").val(eibadr1);
167
- } else {
168
- alert("physical KNX address in format a/b/c not valid");
169
- }
185
+ if (id === "eibadr") {
186
+ var eibadr1 = $("#eibadr").val();
187
+ if (isKnxAddressValid(eibadr1)) {
188
+ $("#eibadr").val(eibadr1);
189
+ } else {
190
+ alert("physical KNX address in format a/b/c not valid");
170
191
  }
192
+ }
171
193
 
172
- if (id === "frameInterval") {
173
- var fI = $("#frameInterval").val();
174
- if (!isNaN(fI * 1)) {
175
- if (fI > 0) {
176
- $("#frameInterval").val(fI);
177
- } else {
178
- alert("min 1");
179
- }
194
+ if (id === "frameInterval") {
195
+ var fI = $("#frameInterval").val();
196
+ if (!isNaN(fI * 1)) {
197
+ if (fI > 0) {
198
+ $("#frameInterval").val(fI);
180
199
  } else {
181
- alert("This is not a number");
200
+ alert("min 1");
182
201
  }
202
+ } else {
203
+ alert("This is not a number");
183
204
  }
184
-
185
- if (id === "bind") {
186
- var bindIP = $("#bind").val();
187
- $("#bind").val(bindIP);
188
- }
189
-
190
- if (id === "debugLevel") {
191
- var dbgLevel = $("#debugLevel").val();
192
- $("#debugLevel").val(dbgLevel);
193
- }
194
- });
195
- });
196
-
197
- //if not alive disable buttons
198
- getIsAdapterAlive(function (isAlive) {
199
- if (isAlive) {
200
- $("#knxprojFile").change(fileHandler);
201
- } else {
202
- $("#knxprojFile").prop("disabled", true);
203
- $(".file-field .btn").addClass("disabled");
204
- $(".file-field .file-path").prop("disabled", true);
205
205
  }
206
- });
207
206
 
208
- //start with no changed settings, disable save button
209
- onChange(false);
210
- // reinitialize all the Materialize labels on the page if you are dynamically adding inputs:
211
- if (M) M.updateTextFields();
212
- }
207
+ if (id === "bind") {
208
+ var bindIP = $("#bind").val();
209
+ $("#bind").val(bindIP);
210
+ }
213
211
 
214
- // This will be called by the admin adapter when the user presses the save button
215
- function save(callback) {
216
- // example: select elements with class=value and build settings object
217
- var obj = {};
218
- $(".value").each(function () {
219
- var $this = $(this);
220
- if ($this.attr("type") === "checkbox") {
221
- obj[$this.attr("id")] = $this.prop("checked");
222
- } else if ($this.attr("type") === "number") {
223
- obj[$this.attr("id")] = parseFloat($this.val());
224
- } else {
225
- obj[$this.attr("id")] = $this.val();
212
+ if (id === "debugLevel") {
213
+ var dbgLevel = $("#debugLevel").val();
214
+ $("#debugLevel").val(dbgLevel);
226
215
  }
227
216
  });
228
- sendTo(null, "reload", null);
229
- callback(obj);
230
- }
231
-
232
- function fileHandler(event) {
233
- event.preventDefault();
234
-
235
- var file = event.dataTransfer ? event.dataTransfer.files[0] : event.target.files[0];
236
-
237
- if (!file) {
238
- console.warn("invalid file object");
239
- return false;
217
+ });
218
+
219
+ $("#etsFile").change(processXmlFile);
220
+ $("#createAlias").change(processAlias);
221
+ //if not alive disable buttons
222
+ getIsAdapterAlive(function (isAlive) {
223
+ if (!isAlive) {
224
+ $("#etsFile").prop("disabled", true);
225
+ $("#createAlias").addClass("disabled");
226
+ $(".file-field .btn").addClass("disabled");
227
+ $(".file-field .file-path").prop("disabled", true);
240
228
  }
241
-
242
- $("#knxprojFile").prop("disabled", true);
243
- $(".file-field .btn").addClass("disabled");
244
- $(".file-field .file-path").prop("disabled", true);
245
-
246
- if (file.name.split(".").pop() == "xml") {
247
- var reader = new FileReader();
248
- reader.addEventListener("load", function readFile(event) {
249
- transmitXML();
250
-
251
- function transmitXML() {
252
- $("#knxprojFile").replaceWith($(knxprojFile));
253
- $("#knxprojFile").change(fileHandler);
254
-
255
- showToast(null, _("Import started..."), null, 3000);
256
- $("#progress").show();
257
- $("#onlyAddNewObjects").addClass("disabled");
258
- sendTo(null, "import", { xml: event.target.result, onlyAddNewObjects: $("#onlyAddNewObjects").prop("checked") }, function (result) {
259
- $("#onlyAddNewObjects").removeClass("disabled");
260
- $("#progress").hide();
261
- if (!result || result.error) {
262
- showMessage(_("Error: ") + (result ? result.error : _("Unknown")));
263
- sendTo(null, "reset", null);
264
- showToast(null, _("Restarting adapter"), null, 10000);
265
- } else {
266
- showMessage(_("Extracted %s states", result.count));
267
- sendTo(null, "reset", null);
268
- showToast(null, _("Restarting adapter"), null, 10000);
269
- }
270
-
271
- $("#knxprojFile").prop("disabled", true);
272
- $(".file-field .btn").addClass("disabled");
273
- $(".file-field .file-path").prop("disabled", true);
274
- });
275
- }
276
- });
277
- reader.readAsText(file);
278
- } else if (file.name.split(".").pop() == "knxproj") {
279
- showMessage(_("KNXproj are not supported, please open in ETS the Group Adresses and right click on group addresses and then group adresse export"));
280
- $("#onlyAddNewObjects").removeClass("disabled");
281
- $(".file-field .btn").removeClass("disabled");
282
- $(".file-field .file-path").prop("disabled", false);
283
- $("#progress").hide();
229
+ });
230
+
231
+ $('#createAlias').on('click', function () {
232
+ processAlias();
233
+ });
234
+
235
+ //start with no changed settings, disable save button
236
+ onChange(false);
237
+ // reinitialize all the Materialize labels on the page if you are dynamically adding inputs:
238
+ if (M) M.updateTextFields();
239
+ }
240
+
241
+ // This will be called by the admin adapter when the user presses the save button
242
+ function save(callback) {
243
+ // example: select elements with class=value and build settings object
244
+ var obj = {};
245
+ $(".value").each(function () {
246
+ var $this = $(this);
247
+ if ($this.attr("type") === "checkbox") {
248
+ obj[$this.attr("id")] = $this.prop("checked");
249
+ } else if ($this.attr("type") === "number") {
250
+ obj[$this.attr("id")] = parseFloat($this.val());
284
251
  } else {
285
- showMessage(_("Unsupported file format"));
286
- $("#onlyAddNewObjects").removeClass("disabled");
287
- $(".file-field .btn").removeClass("disabled");
288
- $(".file-field .file-path").prop("disabled", false);
289
- $("#progress").hide();
252
+ obj[$this.attr("id")] = $this.val();
290
253
  }
254
+ });
255
+ sendTo(null, "reload", null);
256
+ callback(obj);
257
+ }
258
+
259
+ function processXmlFile(event) {
260
+ event.preventDefault();
261
+ var file = event.dataTransfer ? event.dataTransfer.files[0] : event.target.files[0];
262
+ if (!file) {
263
+ console.warn("invalid file object");
264
+ return false;
291
265
  }
292
-
293
- function checkIPs(ip1, ip2) {
294
- var i1 = ip1.split(".");
295
- var i2 = ip2.split(".");
296
- // If ipv6 or DNS name
297
- if (i1.length !== i2.length || i1.length !== 4) return 1;
298
- if (i1[0] !== i2[0]) return 0;
299
- if (i1[1] !== i2[1]) return 1;
300
- if (i1[2] !== i2[2]) return 2;
301
- if (i1[3] !== i2[3]) return 3;
302
- return 4;
303
- }
304
-
305
- function ValidateIPaddress(inputText) {
306
- var format = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
307
- return !!inputText.match(format);
308
- }
309
-
310
- function ValidatePortaddress(inputText) {
311
- var format = /^([1-9][0-9]{0,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/;
312
- return !!inputText.match(format);
313
- }
314
-
315
- function ValidateEIBaddress(inputText) {
316
- var format = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
317
- return !!inputText.match(format);
318
- }
319
-
320
- //todo ??
321
- $(".switch")
322
- .find("input[type=checkbox]")
323
- .on("change", function () {
324
- var status = $(this).prop("checked");
325
- $.ajax({
326
- url: url,
327
- type: "post",
328
- data: { status: status },
266
+
267
+ if (file.name.split(".").pop() == "xml") {
268
+ $("#etsFile").prop("disabled", true);
269
+ $("#createAlias").addClass("disabled");
270
+ $(".file-field .btn").addClass("disabled");
271
+ $(".file-field .file-path").prop("disabled", true);
272
+ window.isProcessingRequest=true;
273
+ var reader = new FileReader();
274
+ reader.addEventListener("load", function readFile(event) {
275
+ $("#etsFile").replaceWith($(etsFile));
276
+ $("#etsFile").change(processXmlFile);
277
+ showToast(null, _("Import started..."), null, 3000);
278
+ $("#progress").show();
279
+ $("#onlyAddNewObjects").addClass("disabled");
280
+ sendTo(null, "import", { xml: event.target.result, onlyAddNewObjects: $("#onlyAddNewObjects").prop("checked") }, function (result) {
281
+ $("#onlyAddNewObjects").removeClass("disabled");
282
+ $("#progress").hide();
283
+ if (!result || result.error) {
284
+ let message = "Unknown error"
285
+ if (result && result.error) {
286
+ message = `Extracted ${result.count} states successfully<br/><br/>\n${result.error}`
287
+ }
288
+ showMessage(_(message));
289
+ sendTo(null, "reset", null);
290
+ showToast(null, _("Restarting adapter"), null, 10000);
291
+ } else {
292
+ showMessage(_("Extracted %s states successfully", result.count));
293
+ sendTo(null, "reset", null);
294
+ showToast(null, _("Restarting adapter"), null, 10000);
295
+ }
296
+ window.isProcessingRequest=false;
329
297
  });
330
298
  });
331
-
332
- function disableAllDialogs() {
333
- $(".c-tab").removeClass("tab-active");
334
- var x = document.getElementsByClassName("dialog");
335
- for (var cnt = 0; cnt < x.length; cnt++) {
336
- x[cnt].style.display = "none";
299
+ reader.readAsText(file);
300
+ } else if (file.name.split(".").pop() == "knxproj") {
301
+ showMessage(_("KNXproj are not supported, please open in ETS the Group Adresses and right click on group addresses and then group adresse export"));
302
+ } else {
303
+ showMessage(_("Unsupported file format"));
304
+ }
305
+ }
306
+
307
+ function processAlias() {
308
+ $("#etsFile").prop("disabled", true);
309
+ $("#createAlias").addClass("disabled");
310
+ $(".file-field .btn").addClass("disabled");
311
+ $(".file-field .file-path").prop("disabled", true);
312
+ $("#progress2").show();
313
+ window.isProcessingRequest = true;
314
+ sendTo(null, "createAlias", null, function (result) {
315
+ if (!result || result.error) {
316
+ showMessage(_("Error"));
317
+ sendTo(null, "reset", null);
318
+ showToast(null, _("Restarting adapter"), null, 10000);
319
+ } else {
320
+ showMessage(_("Generated %s aliases", result.count));
321
+ sendTo(null, "reset", null);
322
+ showToast(null, _("Restarting adapter"), null, 10000);
337
323
  }
324
+ window.isProcessingRequest=false;
325
+ $("#progress2").hide();
326
+ });
327
+ }
328
+
329
+ function isIpValid(inputText) {
330
+ var format = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$/;
331
+ return !!inputText.match(format);
332
+ }
333
+
334
+ function isPortValid(inputText) {
335
+ var format = /^([1-9][0-9]{0,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/;
336
+ return !!inputText.match(format);
337
+ }
338
+
339
+ function isKnxAddressValid(inputText) {
340
+ var format = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
341
+ return !!inputText.match(format);
342
+ }
343
+
344
+ function disableAllDialogs() {
345
+ $(".c-tab").removeClass("tab-active");
346
+ var x = document.getElementsByClassName("dialog");
347
+ for (var cnt = 0; cnt < x.length; cnt++) {
348
+ x[cnt].style.display = "none";
338
349
  }
350
+ }
351
+
352
+ function showConfigDialog() {
353
+ disableAllDialogs();
354
+ $(".dialog-config").addClass("tab-active");
355
+ var x = document.getElementById("configDialog");
356
+ x.style.display = "block";
357
+ }
358
+
359
+ function showExtendedDialog() {
360
+ disableAllDialogs();
361
+ $('.dialog-extended').addClass('tab-active');
362
+ var x = document.getElementById("extendedDialog");
363
+ x.style.display = "block";
364
+ }
365
+ </script>
366
+ </head>
367
+
368
+ <body>
369
+ <!-- you have to put your config page in a div with id adapter-container -->
370
+
371
+ <div class="m adapter-container">
372
+
373
+ <nav>
374
+ <div class="row">
375
+ <div class="col s12 m4 l2">
376
+ <img src="openknx.png" class="logo">
377
+ </div>
378
+ </div>
379
+ </nav>
380
+ <div class="row">
381
+ <ul class="tabs">
382
+ <li class="tab col s5 dialog-config c-tab translate"><a onclick="showConfigDialog()">Settings and Import</a></li>
383
+ <li class="tab col s5 dialog-extended c-tab translate"><a onclick="showExtendedDialog()">Alias Generation</a></li>
384
+ </ul>
385
+ </div>
339
386
 
340
- function showConfigDialog() {
341
- disableAllDialogs();
342
- $(".dialog-config").addClass("tab-active");
343
- var x = document.getElementById("configDialog");
344
- x.style.display = "block";
345
- }
346
- </script>
347
- </head>
348
-
349
- <body>
350
- <!-- you have to put your config page in a div with id adapter-container -->
351
- <div class="m adapter-container">
352
- <div id="configDialog" class="dialog">
353
- <div class="card">
354
- <div class="card-content">
355
- <div class="row">
356
- <div class="col s6 l2 input-field">
357
- <input class="value" id="gwip" type="text" />
358
- <label for="gwip" class="translate">Gateway IP</label>
359
- </div>
360
- <div class="col s6 l2 input-field">
361
- <input type="number" min="1025" max="65535" class="value" id="gwipport" />
362
- <label for="gwipport" class="translate">Port</label>
363
- </div>
364
- <div class="col s6 l2 input-field">
365
- <input id="frameInterval" class="value" type="number" min="20" max="1000" />
366
- <label for="frameInterval" class="translate">Frames per second</label>
367
- </div>
387
+ <div id="configDialog" class="dialog">
388
+ <div class="card">
389
+ <div class="card-content">
390
+ <div class="row">
391
+ <div class="col s6 l2 input-field">
392
+ <input class="value" id="gwip" type="text" />
393
+ <label for="gwip" class="translate">Gateway IP</label>
394
+ </div>
395
+ <div class="col s6 l1 input-field">
396
+ <input type="number" min="1025" max="65535" class="value" id="gwipport" />
397
+ <label for="gwipport" class="translate">Port</label>
398
+ </div>
399
+ <div class="col s6 l1 input-field">
400
+ <input id="frameInterval" class="value" type="number" min="20" max="1000" />
401
+ <label for="frameInterval" class="translate">Frames per second</label>
368
402
  </div>
369
403
  </div>
370
- </div>
371
-
372
- <div class="card">
373
- <div class="card-content">
374
- <div class="row">
375
- <div class="col s12 l5 input-field">
376
- <select class="value" id="bind"></select>
377
- <label class="translate" for="bind">local network interface</label>
378
- </div>
379
- <div class="col s12 l2 input-field">
380
- <input class="value" id="eibadr" type="text" />
381
- <label for="eibadr" class="translate">physical KNX address</label>
382
- </div>
404
+ <div class="row">
405
+ <div class="col s12 l4 input-field">
406
+ <select class="value" id="bind"></select>
407
+ <label class="translate" for="bind">local network interface</label>
408
+ </div>
409
+ <div class="col s12 l2 input-field">
410
+ <input class="value" id="eibadr" type="text" />
411
+ <label for="eibadr" class="translate">physical KNX address</label>
383
412
  </div>
384
413
  </div>
385
414
  </div>
386
-
387
- <div class="card">
388
- <div class="card-content">
389
- <div class="col">
390
- <div class="row">
391
- <div class="input-field col s6 m6 l4">
415
+ </div>
416
+ <div class="card">
417
+ <div class="card-content">
418
+ <div class="row">
419
+ <div style="display: flex">
420
+ <div class="col l6">
421
+ <div class="input-field">
392
422
  <input class="value" id="onlyAddNewObjects" type="checkbox" />
393
423
  <label class="translate" for="onlyAddNewObjects">add only new Objects</label>
394
424
  </div>
395
- </div>
396
- <div class="col s6">
425
+
397
426
  <div class="file-field input-field">
398
427
  <div class="btn" id="fileUploadButton">
399
- <span class="translate">GA XML Export from ETS</span>
400
- <input type="file" id="knxprojFile" />
428
+ <span class="translate">Import XML from ETS</span>
429
+ <input type="file" id="etsFile" />
401
430
  </div>
402
431
  <div class="file-path-wrapper">
403
432
  <input class="file-path validate" type="text" />
404
433
  </div>
405
434
  </div>
406
-
407
435
  <div class="progress" id="progress">
408
436
  <div class="indeterminate" style="width: 70%"></div>
409
437
  </div>
438
+ <a href="https://github.com/iobroker-community-adapters/ioBroker.openknx#adaptermigration" target="_blank"
439
+ ><h6><div class="translate">Click here for a manual to migrate from knx.0 to openknx.0</div></h6></a
440
+ >
410
441
  </div>
411
- <div class="col s6 l2 input-field">
412
- <h6 class="translate">How to export GA XML from ETS:</h6>
413
- <img src="./exportGA.png" alt="exportGA" />
442
+ <div class="col l6">
443
+ <div class="input-field">
444
+ <h6 class="translate">How to export GA XML from ETS:</h6>
445
+ <img src="./exportGA.png" alt="exportGA" />
446
+ </div>
414
447
  </div>
415
448
  </div>
416
449
  </div>
417
450
  </div>
418
451
  </div>
419
452
  </div>
420
- </body>
421
- </html>
453
+
454
+ <div id="extendedDialog" class="dialog">
455
+ <div class="card">
456
+ <div class="card-content">
457
+ <div class="row">
458
+ <div class="col s12">
459
+ <h6><span class="translate">To merge Action and Status GA in one ioBroker Object you can let the Adapter generate</span><span> <a href="https://www.iobroker.net/#de/documentation/dev/aliases.md" target="_blank">Aliases</a></span></h6>
460
+ <div class="input-field col s6 m6 l5">
461
+ <input class="value" id="statusRegex" type="text" />
462
+ <label class="translate" for="statusRegex">Regex to identify Status GAs (ending with status, rm, rückmeldung..).</label>
463
+
464
+ </div>
465
+ <div class="input-field col s6 m6 l2">
466
+ <input class="value" id="regexSimil" type="number" />
467
+ <label class="translate" for="regexSimil">Minimum Similarity 0-1</label>
468
+
469
+ </div>
470
+ <div class="input-field col s6 m6 l2">
471
+ <input class="value" id="aliasPath" type="text" />
472
+ <label class="translate" for="aliasPath">Alias path</label>
473
+ </div>
474
+ <div class="col s12">
475
+ <a id="createAlias" class="waves-effect waves-light btn"><i
476
+ class="material-icons right">list</i><span class="translate">generate aliases</span></a>
477
+ </div>
478
+ <div class="input-field">
479
+ <input class="value" id="aliasRange" type="checkbox" />
480
+ <label class="translate" for="aliasRange">include group range in search (save first)</label>
481
+ </div>
482
+ <div class="progress" id="progress2">
483
+ <div class="indeterminate"></div>
484
+ </div>
485
+
486
+ </div>
487
+ </div>
488
+ </div>
489
+ </div>
490
+
491
+ </div>
492
+ </body>
493
+
494
+ </html>