iobroker.airzone 1.0.1 → 2.0.0
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.
- package/Airzone.png +0 -0
- package/LocalApi/AirzoneLocalApi.js +78 -0
- package/LocalApi/Constants.js +14 -0
- package/LocalApi/System.js +150 -0
- package/LocalApi/Zone.js +116 -0
- package/README.md +12 -0
- package/Utils/asyncRequest.js +35 -2
- package/admin/Airzone.png +0 -0
- package/admin/AirzoneSmall.png +0 -0
- package/admin/index_m.html +97 -104
- package/admin/style.css +29 -0
- package/admin/words.js +53 -0
- package/io-package.json +141 -68
- package/main.js +153 -135
- package/package.json +65 -65
- package/Cloud/AirzoneCloud.js +0 -137
- package/Cloud/Constants.js +0 -81
- package/Cloud/Device.js +0 -139
- package/Cloud/System.js +0 -214
- package/Cloud/Zone.js +0 -139
- package/settings/secrets/AUTO_MERGE_TOKEN +0 -1
package/Airzone.png
CHANGED
|
Binary file
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const AsyncRequest = require('../Utils/asyncRequest');
|
|
4
|
+
const System = require('./System')
|
|
5
|
+
|
|
6
|
+
// Allow to connect to Airzone local API
|
|
7
|
+
|
|
8
|
+
let log;
|
|
9
|
+
let adapter;
|
|
10
|
+
class AirzoneLocalApi {
|
|
11
|
+
constructor(a, local_ip)
|
|
12
|
+
{
|
|
13
|
+
adapter = a;
|
|
14
|
+
log = a.log;
|
|
15
|
+
this.local_ip = local_ip;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async init(system_id) {
|
|
19
|
+
|
|
20
|
+
this.system = new System(adapter, this, system_id);
|
|
21
|
+
await this.system.init();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async update() {
|
|
25
|
+
if(this.system == undefined)
|
|
26
|
+
return;
|
|
27
|
+
|
|
28
|
+
await this.system.update();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
logInfo(msg) {
|
|
32
|
+
log.info(msg);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
logError(msg) {
|
|
36
|
+
log.error(msg);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async getZoneState() {
|
|
40
|
+
var url = "http://"+this.local_ip+":3000/api/v1/hvac";
|
|
41
|
+
const data = JSON.stringify({"systemID":this.system?.id, "ZoneID":0});
|
|
42
|
+
var response = await AsyncRequest.jsonPostRequest(url, data);
|
|
43
|
+
|
|
44
|
+
var errors = response["errors"];
|
|
45
|
+
if(errors)
|
|
46
|
+
{
|
|
47
|
+
this.logError("Failed to get zone state: (statusCode: "+response["statusCode"]+") - "+response["errors"]);
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
var body = response["body"];
|
|
51
|
+
var zones = JSON.parse(body)["data"];
|
|
52
|
+
|
|
53
|
+
return zones;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async sendUpdate(zoneid, key, value)
|
|
57
|
+
{
|
|
58
|
+
try
|
|
59
|
+
{
|
|
60
|
+
var url = "http://"+this.local_ip+":3000/api/v1/hvac";
|
|
61
|
+
var payload = '{\"systemID\":'+this.system?.id+', \"ZoneID\":'+zoneid+', \"'+key+'\":'+value+'}';
|
|
62
|
+
var response = await AsyncRequest.jsonPutRequest(url, payload);
|
|
63
|
+
var errors = response["errors"];
|
|
64
|
+
if(errors)
|
|
65
|
+
{
|
|
66
|
+
this.logError("Failed to update '"+key+"' with value '"+value+"': (statusCode: "+response["statusCode"]+") - "+response["errors"]);
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
var body = response["body"];
|
|
70
|
+
var responseData = JSON.parse(body)["data"];
|
|
71
|
+
return responseData.hasOwnProperty(key);
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
this.logError('error during sendUpdate '+e+'\r\n'+e.stack);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
module.exports = AirzoneLocalApi;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module.exports = Object.freeze({
|
|
2
|
+
MODES_CONVERTER : {
|
|
3
|
+
"1": {"name": "Stop"},
|
|
4
|
+
"2": {"name": "Cooling"},
|
|
5
|
+
"3": {"name": "Heating"},
|
|
6
|
+
"4": {"name": "Fan"},
|
|
7
|
+
"5": {"name": "Dry"}
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
UNIT_CONVERTER : {
|
|
11
|
+
"0": {"name": "Celsius", "unit": "°C"},
|
|
12
|
+
"1": {"name": "Fahrenheit", "unit": "°F"}
|
|
13
|
+
},
|
|
14
|
+
});
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
const Zone = require('./Zone')
|
|
2
|
+
const AsyncRequest = require('../Utils/asyncRequest');
|
|
3
|
+
const Constants = require('./Constants');
|
|
4
|
+
|
|
5
|
+
class System {
|
|
6
|
+
constructor(adapter, localApi, id)
|
|
7
|
+
{
|
|
8
|
+
this.adapter = adapter;
|
|
9
|
+
this.localApi = localApi;
|
|
10
|
+
this.id = id;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Initialize the system with the data from the airzone local api
|
|
15
|
+
*/
|
|
16
|
+
async init() {
|
|
17
|
+
this.path = "System"+this.id;
|
|
18
|
+
await this.adapter.setObjectNotExistsAsync(this.path, {
|
|
19
|
+
type: 'device',
|
|
20
|
+
common: {
|
|
21
|
+
name: this.path,
|
|
22
|
+
type: 'object',
|
|
23
|
+
read: true,
|
|
24
|
+
write: false,
|
|
25
|
+
},
|
|
26
|
+
native: {},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
await this.adapter.createProperty(this.path, 'mode_raw', 'string', true, true, 'state');
|
|
30
|
+
await this.adapter.createProperty(this.path, 'mode', 'string', true, false, 'text');
|
|
31
|
+
|
|
32
|
+
this.adapter.subscribeState(this.path+'.mode_raw', this, this.reactToModeRawChange);
|
|
33
|
+
|
|
34
|
+
var masterZone = await this.load_zones(this.path);
|
|
35
|
+
if(masterZone == undefined)
|
|
36
|
+
return false;
|
|
37
|
+
|
|
38
|
+
await this.updateData(masterZone);
|
|
39
|
+
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Synchronized the system data from airzone into the iobroker data points
|
|
45
|
+
*/
|
|
46
|
+
async updateData(masterZoneData)
|
|
47
|
+
{
|
|
48
|
+
if(masterZoneData == undefined)
|
|
49
|
+
{
|
|
50
|
+
this.localApi.logError("Missing master Zone");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.mode_raw = masterZoneData["mode"];
|
|
55
|
+
await this.adapter.updatePropertyValue(this.path, 'mode_raw', this.mode_raw);
|
|
56
|
+
this.mode = Constants.MODES_CONVERTER[this.mode_raw]["name"];
|
|
57
|
+
await this.adapter.updatePropertyValue(this.path, 'mode', this.mode);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Synchronized the system data from airzone into the iobroker data points and call update for all sub zones
|
|
62
|
+
*/
|
|
63
|
+
async update() {
|
|
64
|
+
var masterZoneData = await this.update_zones();
|
|
65
|
+
|
|
66
|
+
await this.updateData(masterZoneData);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Load and initialize the zones of this system from airzone local api
|
|
71
|
+
*/
|
|
72
|
+
async load_zones(path) {
|
|
73
|
+
|
|
74
|
+
var zones_relations = await this.localApi.getZoneState();
|
|
75
|
+
if(zones_relations == undefined)
|
|
76
|
+
return undefined;
|
|
77
|
+
|
|
78
|
+
var masterZoneData = undefined;
|
|
79
|
+
this.zones = [];
|
|
80
|
+
for (let index = 0; index < zones_relations.length; index++) {
|
|
81
|
+
var zoneData = zones_relations[index];
|
|
82
|
+
var zone = new Zone(this.adapter, this.localApi);
|
|
83
|
+
await zone.init(path, zoneData)
|
|
84
|
+
this.zones[index] = zone;
|
|
85
|
+
|
|
86
|
+
if(zoneData.hasOwnProperty("mode"))
|
|
87
|
+
{
|
|
88
|
+
masterZoneData = zoneData;
|
|
89
|
+
this.masterZoneId = this.zones[index].id;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return masterZoneData;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Update zones with the current zone data from airzone local api
|
|
98
|
+
*/
|
|
99
|
+
async update_zones() {
|
|
100
|
+
|
|
101
|
+
var zones_relations = await this.localApi.getZoneState();
|
|
102
|
+
if(zones_relations == undefined)
|
|
103
|
+
return undefined;
|
|
104
|
+
|
|
105
|
+
if(this.zones == undefined)
|
|
106
|
+
return undefined;
|
|
107
|
+
|
|
108
|
+
var masterZoneData = undefined;
|
|
109
|
+
|
|
110
|
+
for (let index = 0; index < zones_relations.length; index++) {
|
|
111
|
+
var zoneData = zones_relations[index];
|
|
112
|
+
var zId = zoneData["zoneID"];
|
|
113
|
+
|
|
114
|
+
if(zoneData.hasOwnProperty("mode"))
|
|
115
|
+
masterZoneData = zoneData;
|
|
116
|
+
|
|
117
|
+
for(let i = 0;i<this.zones.length;i++) {
|
|
118
|
+
if(this.zones[i].id == zId) {
|
|
119
|
+
await this.zones[i].updateData(zoneData);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return masterZoneData;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Is called when the state of mode was changed
|
|
130
|
+
*/
|
|
131
|
+
async reactToModeRawChange(self, id, state) {
|
|
132
|
+
|
|
133
|
+
if(state.val == 0)
|
|
134
|
+
{
|
|
135
|
+
self.zones.forEach(zone => {
|
|
136
|
+
zone.turn_off();
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
self.sendEvent('mode', state.val);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Send event to the airzone local api
|
|
145
|
+
*/
|
|
146
|
+
async sendEvent(option, value) {
|
|
147
|
+
await this.localApi.sendUpdate(this.masterZoneId, option, value)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
module.exports = System;
|
package/LocalApi/Zone.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const Constants = require('./Constants');
|
|
2
|
+
|
|
3
|
+
class Zone {
|
|
4
|
+
constructor(adapter, localApi)
|
|
5
|
+
{
|
|
6
|
+
this.adapter = adapter;
|
|
7
|
+
this.localApi = localApi;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Initialize the zone with the data from the airzone local api
|
|
12
|
+
*/
|
|
13
|
+
async init(path, zoneData) {
|
|
14
|
+
this.id = parseInt(zoneData['zoneID']);
|
|
15
|
+
this.name = zoneData.hasOwnProperty('name') ? zoneData['name'] : '';
|
|
16
|
+
this.min_temp = zoneData['minTemp'];
|
|
17
|
+
this.max_temp = zoneData['maxTemp'];
|
|
18
|
+
|
|
19
|
+
this.path = path+'.Zone'+this.id;
|
|
20
|
+
await this.adapter.setObjectNotExistsAsync(this.path, {
|
|
21
|
+
type: 'device',
|
|
22
|
+
common: {
|
|
23
|
+
name: 'Zone_'+this.id,
|
|
24
|
+
type: 'object',
|
|
25
|
+
read: true,
|
|
26
|
+
write: false,
|
|
27
|
+
},
|
|
28
|
+
native: {},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
var unitRaw = zoneData['units'];
|
|
32
|
+
var unitName = Constants.UNIT_CONVERTER[unitRaw]["name"];
|
|
33
|
+
var unitUnit = Constants.UNIT_CONVERTER[unitRaw]["unit"];
|
|
34
|
+
|
|
35
|
+
await this.adapter.createPropertyAndInit(this.path, 'id', 'number', true, false, this.id, 'number');
|
|
36
|
+
await this.adapter.createPropertyAndInit(this.path, 'name', 'string', true, false, this.name, 'text');
|
|
37
|
+
await this.adapter.createPropertyAndInit(this.path, 'min_temp', 'number', true, false, this.min_temp, 'value.min');
|
|
38
|
+
await this.adapter.createPropertyAndInit(this.path, 'max_temp', 'number', true, false, this.max_temp, 'value.max');
|
|
39
|
+
await this.adapter.createPropertyAndInit(this.path, 'unitRaw', 'string', true, false, unitRaw, 'number');
|
|
40
|
+
await this.adapter.createPropertyAndInit(this.path, 'unitName', 'string', true, false, unitName, 'text');
|
|
41
|
+
await this.adapter.createPropertyAndInit(this.path, 'unit', 'string', true, false, unitUnit, 'text');
|
|
42
|
+
await this.adapter.createProperty(this.path, 'is_on', 'boolean', true, false, 'switch.power');
|
|
43
|
+
await this.adapter.createUnitProperty(this.path, 'current_temperature', 'number', 0, 100, unitUnit, true, false, 'value.temperature');
|
|
44
|
+
await this.adapter.createUnitProperty(this.path, 'current_humidity', 'number', 0, 100, '%', true, false, 'value.humidity');
|
|
45
|
+
await this.adapter.createUnitProperty(this.path, 'target_temperature', 'number', this.min_temp, this.max_temp, unitUnit, true, true, 'state');
|
|
46
|
+
|
|
47
|
+
// Register callbacks to react on value changes
|
|
48
|
+
this.adapter.subscribeState(this.path+'.target_temperature', this, this.reactToTargetTemperatureChange);
|
|
49
|
+
this.adapter.subscribeState(this.path+'.is_on', this, this.reactToIsOnChange);
|
|
50
|
+
|
|
51
|
+
await this.updateData(zoneData);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Synchronized the zone data from airzone into the iobroker data points
|
|
56
|
+
*/
|
|
57
|
+
async updateData(zoneData)
|
|
58
|
+
{
|
|
59
|
+
this.current_temperature = zoneData['roomTemp'];
|
|
60
|
+
await this.adapter.updatePropertyValue(this.path, 'current_temperature', this.current_temperature);
|
|
61
|
+
|
|
62
|
+
this.current_humidity = zoneData['humidity'];
|
|
63
|
+
await this.adapter.updatePropertyValue(this.path, 'current_humidity', this.current_humidity);
|
|
64
|
+
|
|
65
|
+
this.target_temperature = zoneData['setpoint'];
|
|
66
|
+
await this.adapter.updatePropertyValue(this.path, 'target_temperature', this.target_temperature);
|
|
67
|
+
|
|
68
|
+
this.is_on = zoneData['on'] == '1';
|
|
69
|
+
await this.adapter.updatePropertyValue(this.path, 'is_on', this.is_on);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Is called when the state of target_temperature was changed
|
|
74
|
+
*/
|
|
75
|
+
async reactToTargetTemperatureChange(self, id, state) {
|
|
76
|
+
var temperature = state.val;
|
|
77
|
+
if(self.min_temp != undefined && temperature < self.min_temp)
|
|
78
|
+
temperature = self.min_temp;
|
|
79
|
+
if(self.max_temp != undefined && temperature > self.max_temp)
|
|
80
|
+
temperature = self.max_temp;
|
|
81
|
+
|
|
82
|
+
await self.sendEvent('setpoint', temperature);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Is called when the state of is_on was changed
|
|
87
|
+
*/
|
|
88
|
+
async reactToIsOnChange(self, id, state) {
|
|
89
|
+
if(state.val)
|
|
90
|
+
await self.turn_on();
|
|
91
|
+
else
|
|
92
|
+
await self.turn_off();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Send event to the airzone cloud
|
|
97
|
+
*/
|
|
98
|
+
async sendEvent(option, value) {
|
|
99
|
+
await this.localApi.sendUpdate(this.id, option, value)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Turn zone on
|
|
104
|
+
*/
|
|
105
|
+
async turn_on() {
|
|
106
|
+
await this.sendEvent('on', 1);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Turn zone off
|
|
111
|
+
*/
|
|
112
|
+
async turn_off() {
|
|
113
|
+
await this.sendEvent('on', 0);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
module.exports = Zone;
|
package/README.md
CHANGED
|
@@ -16,6 +16,18 @@ Control and monitor airzone devices with ioBroker.
|
|
|
16
16
|
**Tests:**
|
|
17
17
|
|
|
18
18
|
## Changelog
|
|
19
|
+
### 2.0.0
|
|
20
|
+
* (SilentPhoenix11) Using the local API instead of cloud web service.
|
|
21
|
+
|
|
22
|
+
### 1.0.4
|
|
23
|
+
* (SilentPhoenix11) Small fixes
|
|
24
|
+
|
|
25
|
+
### 1.0.3
|
|
26
|
+
* (SilentPhoenix11) Fix of "SyntaxError: Unexpected end of JSON input" when calling "askSystemInfo"
|
|
27
|
+
|
|
28
|
+
### 1.0.2
|
|
29
|
+
* (SilentPhoenix11) Corrections after code review by Apollon77
|
|
30
|
+
|
|
19
31
|
### 1.0.1
|
|
20
32
|
* (SilentPhoenix11) Various corrections in the project structure
|
|
21
33
|
|
package/Utils/asyncRequest.js
CHANGED
|
@@ -23,7 +23,8 @@ class AsyncRequest {
|
|
|
23
23
|
}
|
|
24
24
|
else
|
|
25
25
|
{
|
|
26
|
-
var
|
|
26
|
+
var body = response.body;
|
|
27
|
+
var errorMsg = JSON.parse(body)["errors"];
|
|
27
28
|
if(errorMsg)
|
|
28
29
|
result = JSON.stringify({statusCode:response.statusCode,errors:errorMsg});
|
|
29
30
|
else
|
|
@@ -33,6 +34,37 @@ class AsyncRequest {
|
|
|
33
34
|
return JSON.parse(result);
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
static async jsonPutRequest(url, data) {
|
|
38
|
+
|
|
39
|
+
const response = await asyncRequest({
|
|
40
|
+
method: 'PUT',
|
|
41
|
+
uri: url,
|
|
42
|
+
headers: {
|
|
43
|
+
'Content-Type': 'application/json'
|
|
44
|
+
},
|
|
45
|
+
body: data
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
var result;
|
|
49
|
+
|
|
50
|
+
if(response.error)
|
|
51
|
+
{
|
|
52
|
+
result = JSON.stringify({statusCode:response.statusCode,errors:error});
|
|
53
|
+
}
|
|
54
|
+
else
|
|
55
|
+
{
|
|
56
|
+
var body = response.body;
|
|
57
|
+
var errorMsg = JSON.parse(body)["errors"];
|
|
58
|
+
if(errorMsg)
|
|
59
|
+
result = JSON.stringify({statusCode:response.statusCode,errors:errorMsg});
|
|
60
|
+
else
|
|
61
|
+
result = JSON.stringify({statusCode:response.statusCode,body:response.body});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return JSON.parse(result);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
36
68
|
static async jsonGetRequest(url) {
|
|
37
69
|
|
|
38
70
|
const response = await asyncRequest({
|
|
@@ -48,7 +80,8 @@ class AsyncRequest {
|
|
|
48
80
|
}
|
|
49
81
|
else
|
|
50
82
|
{
|
|
51
|
-
var
|
|
83
|
+
var body = response.body;
|
|
84
|
+
var errorMsg = JSON.parse(body)["errors"];
|
|
52
85
|
if(errorMsg)
|
|
53
86
|
result = JSON.stringify({statusCode:response.statusCode,errors:errorMsg});
|
|
54
87
|
else
|
package/admin/Airzone.png
CHANGED
|
Binary file
|
package/admin/AirzoneSmall.png
CHANGED
|
Binary file
|
package/admin/index_m.html
CHANGED
|
@@ -1,105 +1,98 @@
|
|
|
1
|
-
<html>
|
|
2
|
-
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
<!-- Load ioBroker scripts and styles-->
|
|
6
|
-
<link rel="stylesheet" type="text/css" href="../../css/adapter.css" />
|
|
7
|
-
<link rel="stylesheet" type="text/css" href="../../lib/css/materialize.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
|
-
<script type="text/javascript">
|
|
21
|
-
// This will be called by the admin adapter when the settings page loads
|
|
22
|
-
function load(settings, onChange) {
|
|
23
|
-
// example: select elements with id=key and class=value and insert value
|
|
24
|
-
if (!settings) return;
|
|
25
|
-
$('.value').each(function () {
|
|
26
|
-
var $key = $(this);
|
|
27
|
-
var id = $key.attr('id');
|
|
28
|
-
if ($key.attr('type') === 'checkbox') {
|
|
29
|
-
// do not call onChange direct, because onChange could expect some arguments
|
|
30
|
-
$key.prop('checked', settings[id])
|
|
31
|
-
.on('change', () => onChange())
|
|
32
|
-
;
|
|
33
|
-
} else {
|
|
34
|
-
// do not call onChange direct, because onChange could expect some arguments
|
|
35
|
-
$key.val(settings[id])
|
|
36
|
-
.on('change', () => onChange())
|
|
37
|
-
.on('keyup', () => onChange())
|
|
38
|
-
;
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
onChange(false);
|
|
42
|
-
// reinitialize all the Materialize labels on the page if you are dynamically adding inputs:
|
|
43
|
-
if (M) M.updateTextFields();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// This will be called by the admin adapter when the user presses the save button
|
|
47
|
-
function save(callback) {
|
|
48
|
-
// example: select elements with class=value and build settings object
|
|
49
|
-
var obj = {};
|
|
50
|
-
$('.value').each(function () {
|
|
51
|
-
var $this = $(this);
|
|
52
|
-
if ($this.attr('type') === 'checkbox') {
|
|
53
|
-
obj[$this.attr('id')] = $this.prop('checked');
|
|
54
|
-
} else {
|
|
55
|
-
obj[$this.attr('id')] = $this.val();
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
callback(obj);
|
|
59
|
-
}
|
|
60
|
-
</script>
|
|
61
|
-
|
|
62
|
-
</head>
|
|
63
|
-
|
|
64
|
-
<body>
|
|
65
|
-
|
|
66
|
-
<div class="m adapter-container">
|
|
67
|
-
|
|
68
|
-
<div class="row">
|
|
69
|
-
<div class="col s12 m4 l2">
|
|
70
|
-
<img src="Airzone.png" class="logo" style="width:
|
|
71
|
-
</div>
|
|
72
|
-
</div>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
<
|
|
91
|
-
<
|
|
92
|
-
</div>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
</div>
|
|
100
|
-
|
|
101
|
-
</div>
|
|
102
|
-
|
|
103
|
-
</body>
|
|
104
|
-
|
|
1
|
+
<html>
|
|
2
|
+
|
|
3
|
+
<head>
|
|
4
|
+
|
|
5
|
+
<!-- Load ioBroker scripts and styles-->
|
|
6
|
+
<link rel="stylesheet" type="text/css" href="../../css/adapter.css" />
|
|
7
|
+
<link rel="stylesheet" type="text/css" href="../../lib/css/materialize.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
|
+
<script type="text/javascript">
|
|
21
|
+
// This will be called by the admin adapter when the settings page loads
|
|
22
|
+
function load(settings, onChange) {
|
|
23
|
+
// example: select elements with id=key and class=value and insert value
|
|
24
|
+
if (!settings) return;
|
|
25
|
+
$('.value').each(function () {
|
|
26
|
+
var $key = $(this);
|
|
27
|
+
var id = $key.attr('id');
|
|
28
|
+
if ($key.attr('type') === 'checkbox') {
|
|
29
|
+
// do not call onChange direct, because onChange could expect some arguments
|
|
30
|
+
$key.prop('checked', settings[id])
|
|
31
|
+
.on('change', () => onChange())
|
|
32
|
+
;
|
|
33
|
+
} else {
|
|
34
|
+
// do not call onChange direct, because onChange could expect some arguments
|
|
35
|
+
$key.val(settings[id])
|
|
36
|
+
.on('change', () => onChange())
|
|
37
|
+
.on('keyup', () => onChange())
|
|
38
|
+
;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
onChange(false);
|
|
42
|
+
// reinitialize all the Materialize labels on the page if you are dynamically adding inputs:
|
|
43
|
+
if (M) M.updateTextFields();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// This will be called by the admin adapter when the user presses the save button
|
|
47
|
+
function save(callback) {
|
|
48
|
+
// example: select elements with class=value and build settings object
|
|
49
|
+
var obj = {};
|
|
50
|
+
$('.value').each(function () {
|
|
51
|
+
var $this = $(this);
|
|
52
|
+
if ($this.attr('type') === 'checkbox') {
|
|
53
|
+
obj[$this.attr('id')] = $this.prop('checked');
|
|
54
|
+
} else {
|
|
55
|
+
obj[$this.attr('id')] = $this.val();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
callback(obj);
|
|
59
|
+
}
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
</head>
|
|
63
|
+
|
|
64
|
+
<body>
|
|
65
|
+
|
|
66
|
+
<div class="m adapter-container">
|
|
67
|
+
|
|
68
|
+
<div class="row">
|
|
69
|
+
<div class="col s12 m4 l2">
|
|
70
|
+
<img src="Airzone.png" class="logo" style="width: 198px;">
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div class="row">
|
|
75
|
+
<div class="input-field col s12 m4 l3">
|
|
76
|
+
<input placeholder="192.168.178.1" type="text" minlength="7" maxlength="15" size="15" pattern="^((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$" class="value validate" id="local_ip">
|
|
77
|
+
<label data-error="invalid format" data-success="ok" for="local_ip" class="translate">Local IP</label>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
<div class="row">
|
|
81
|
+
<div class="input-field col s12 m4 l3">
|
|
82
|
+
<input placeholder="1" type="number" class="value validate" id="system_id" min="1"/>
|
|
83
|
+
<label data-error="numbers only" data-success="ok" class="translate active" for="system_id" class="translate">System Id</label>
|
|
84
|
+
<span class="helper-text translate">(default is 1)</span>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
<div class="row">
|
|
88
|
+
<div class="input-field col s12 m4 l3">
|
|
89
|
+
<input placeholder="5" type="number" id="sync_time" class="value validate" min="1"/>
|
|
90
|
+
<label data-error="numbers only" data-success="ok" class="translate active" for="sync_time" class="translate">Sync time</label>
|
|
91
|
+
<span class="helper-text translate">(default is 5 s, minimum is 1 s)</span>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
</body>
|
|
97
|
+
|
|
105
98
|
</html>
|