forked from thkl/homebridge-homematic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHomeMaticChannelLoader.js
203 lines (161 loc) · 5.28 KB
/
HomeMaticChannelLoader.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
'use strict';
const path = require('path');
const fs = require('fs');
const rootClazzPath = path.join(__dirname,'ChannelServices','HomeKitGenericService');
var HomeKitGenericService = require(rootClazzPath);
var HomeMaticChannelLoader = function (log) {
this.log = log;
}
HomeMaticChannelLoader.prototype.init = function(customServices) {
var that = this;
this.config = this.internalConfig(customServices);
}
HomeMaticChannelLoader.prototype.loadChannelService = function(list, deviceType, channel, platform, special, cfg, access, Service, Characteristic) {
var that = this;
var channelType = channel.type;
var log = platform.log;
var id = channel.id;
var name = channel.name;
var adress = channel.address;
var intf = channel.intf;
this.platform = platform
this.localPath = platform.localPath;
// try to load device:type
var serviceclass;
var options;
var sv = this.getServiceClass(deviceType+':' + channelType);
serviceclass = sv['class']
if (sv['options'] == undefined) {
options = this.getOptions(deviceType+':' + channelType);
} else {
options = sv['options']
}
if (serviceclass == undefined) {
// not found try to find channeltype
sv = this.getServiceClass(channelType);
serviceclass = sv['class']
if (sv['options'] == undefined) {
options = this.getOptions(channelType);
} else {
options = sv['options']
}
}
if (serviceclass == undefined) {
// not found try to find devicetype
sv = this.getServiceClass(deviceType);
serviceclass = sv['class']
if (sv['options'] == undefined) {
options = this.getOptions(deviceType);
} else {
options = sv['options']
}
}
if (serviceclass != undefined) {
var service = this.loadClass(serviceclass);
if (service) { // require ('./ChannelServices/' + serviceclass);
// add Options
if (options != undefined) {
if (cfg != undefined) {
cfg.push.apply(cfg, options);
} else {
cfg = options;
}
}
if (cfg==undefined) {
cfg = {};
}
cfg['interface'] = channel.intf;
// Replace Chars in name https://github.com/thkl/homebridge-homematic/issues/56
name = name.replace(/[.:#_()-]/g,' ');
that.log.debug('service for %s:%s is %s' , deviceType, channelType, serviceclass);
let cfgOptions = this.getConfigOptions(deviceType + ':' + channelType)
if (cfgOptions != undefined) {
// Add config.json options
Object.keys(cfgOptions).forEach(function (key) {
cfg[key] = cfgOptions[key]
})
}
var accessory = new service(log, platform, id, name, channelType, adress, special, cfg, Service, Characteristic, deviceType);
accessory.setReadOnly(access != 255)
accessory.serviceClassName = serviceclass
// Only add if there are more than 1 Service (number 1 is the informationService)
// see https://github.com/thkl/homebridge-homematic/issues/234#issuecomment-375764819
this.log.debug("Number of Services in %s is %s",name,accessory.getServices().length)
if (accessory.getServices().length > 1) {
list.push(accessory);
}
}
} else {
that.log.warn('There is no service for ' + deviceType+':' + channelType );
}
};
HomeMaticChannelLoader.prototype.loadClass = function(serviceclass) {
if (fs.existsSync(path.join(__dirname,'ChannelServices',serviceclass+'.js'))) {
this.log.debug('Load BuildIn Service Class %s',serviceclass)
return require(path.join(__dirname,'ChannelServices',serviceclass))
}
if (fs.existsSync(path.join(this.localPath,serviceclass+'.js'))) {
this.log.debug('Load Custom Service Class %s',serviceclass)
return require(path.join(this.localPath,serviceclass))
}
this.log.warn('No class found in %s or %s',path.join(__dirname,'ChannelServices',serviceclass+'.js'),path.join(this.localPath,serviceclass+'.js'))
return undefined;
}
HomeMaticChannelLoader.prototype.getOptions = function(type) {
var that = this;
var options = undefined;
if (this.config != undefined) {
var ci = this.config['channelconfig'];
ci.map(function(service) {
if (service['type']==type) {
options = service['options'];
}
});
}
return options;
}
// load options from config.json
HomeMaticChannelLoader.prototype.getConfigOptions = function(type) {
this.log.debug('Check config for %s',type)
var options = undefined;
let coptions = this.platform.config[type]
if (coptions) {
options = coptions
}
return options
}
HomeMaticChannelLoader.prototype.getServiceClass = function(type) {
var that = this;
var serviceclass = undefined;
var serviceoptions = undefined;
if (this.config != undefined) {
var ci = this.config['channelconfig'];
ci.map(function(service) {
if (service['type']==type) {
serviceclass = service['service']
serviceoptions = service['options']
}
});
}
return {'class':serviceclass,'options':serviceoptions};
}
HomeMaticChannelLoader.prototype.internalConfig = function(customServices) {
try {
var config_path = path.join(__dirname, './ChannelServices/channel_config.json');
var config = JSON.parse(fs.readFileSync(config_path));
if (customServices != undefined) {
customServices.map(function(service) {
config['channelconfig'].push(service);
});
}
return config;
}
catch (err) {
this.log.warn('Internal Channel config has errors, or was not found. You may ceck the file ChannelService/channel_config.json');
throw err;
}
return undefined;
};
module.exports = {
HomeMaticChannelLoader : HomeMaticChannelLoader
}