node-red-contrib-loewe-tv 0.2.3 → 0.4.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/lib/loewe.js CHANGED
@@ -1,433 +1,1337 @@
1
- module.exports = function(RED) {
2
-
3
- function LoeweTvNode(config) {
4
- var node = this;
5
- const Loewe = require('loewetv');
6
-
7
- RED.nodes.createNode(node, config);
8
-
9
- var LoeweTV = new Loewe(config.ip);
10
- LoeweTV.name = node.name;
11
-
12
- console.log('[', node.name, ']');
13
- console.log(LoeweTV);
14
-
15
- node.status({fill:"red",shape:"ring",text:"disconnected"});
16
-
17
- LoeweTV.onAction = function(action, data) {
18
-
19
- console.log('[' + node.name + '] ' + action);
20
- switch ( action ) {
21
- case "RequestAccess":
22
- break;
23
-
24
- case "Subscribe":
25
- console.log(data);
26
- break;
27
-
28
- case "GetChannelList":
29
- console.log(data);
30
- break;
31
-
32
- case "GetListOfChannelLists":
33
- console.log(data);
34
- break;
35
-
36
- case "GetMediaItem":
37
- console.log(data);
38
- break;
39
-
40
- case "GetMediaEvent":
41
- console.log(data);
42
- break;
43
-
44
- case "GetCurrentEvent":
45
- console.log(data);
46
- break;
47
-
48
- case "GetNextEvent":
49
- console.log(data);
50
- break;
51
-
52
- case "GetFeature":
53
- console.log(data);
54
- break;
55
-
56
- case "GetDeviceData":
57
- console.log(data);
58
- break;
59
-
60
- case "GetChannelInfo":
61
- console.log(data);
62
- break;
63
-
64
- case "GetCurrentPlayback":
65
- console.log(data);
66
- break;
67
-
68
- case "GetVolume":
69
- console.log(data);
70
- break;
71
-
72
- case "GetMute":
73
- console.log(data);
74
- break;
75
-
76
- case "SetActionField":
77
- console.log(data);
78
- break;
79
-
80
- case "SetVolume":
81
- console.log(data);
82
- break;
83
-
84
- case "SetMute":
85
- console.log(data);
86
- break;
87
-
88
- case "InjectRCKey":
89
- console.log(data);
90
- break;
91
-
92
- case "Standby":
93
- console.log(data);
94
- break;
95
-
96
- case "ActivateFeaturePackage":
97
- console.log(data);
98
- break;
99
-
100
- case "CreateIterator":
101
- console.log(data);
102
- break;
103
-
104
- default:
105
- break;
106
- }
107
-
108
- };
109
-
110
- node.on('input', function(msg) {
111
- var action = msg.topic;
112
- switch ( action ) {
113
- case "RequestAccess":
114
- LoeweTV.onEvent('alive');
115
- break;
116
- case "Subscribe":
117
- LoeweTV.subscribe(LoeweTV.onAction);
118
- break;
119
- case "GetChannelList":
120
- LoeweTV.execAction(action, '', LoeweTV.onAction);
121
- // LoeweTV.getChannelList(msg.payload, function(){});
122
- break;
123
-
124
- case "GetCurrentEvent":
125
- LoeweTV.execAction(action, '', LoeweTV.onAction);
126
- // LoeweTV.getCurrentEvent(function(){});
127
- break;
128
-
129
- case "GetNextEvent":
130
- LoeweTV.execAction(action, '', LoeweTV.onAction);
131
- // LoeweTV.getNextEvent(function(){});
132
- break;
133
-
134
- case "GetMediaItem":
135
- LoeweTV.execAction(action, '', LoeweTV.onAction);
136
- // LoeweTV.getMediaItem(msg.payload, function(){});
137
- break;
138
-
139
- case "GetMediaEvent":
140
- LoeweTV.execAction(action, '', LoeweTV.onAction);
141
- // LoeweTV.getMediaEvent(function(){});
142
- break;
143
-
144
- case "PlayerPrepare":
145
- LoeweTV.execAction(action, '', LoeweTV.onAction);
146
- break;
147
-
148
- case "PlayerReleasePrepared":
149
- LoeweTV.execAction(action, '', LoeweTV.onAction);
150
- break;
151
-
152
- case "PlayerPlay":
153
- LoeweTV.execAction(action, '', LoeweTV.onAction);
154
- break;
155
-
156
- case "PlayerPause":
157
- LoeweTV.execAction(action, '', LoeweTV.onAction);
158
- break;
159
-
160
- case "PlayerResume":
161
- LoeweTV.execAction(action, '', LoeweTV.onAction);
162
- break;
163
-
164
- case "PlayerStop":
165
- LoeweTV.execAction(action, '', LoeweTV.onAction);
166
- break;
167
-
168
- case "PlayerSetSpeed":
169
- LoeweTV.execAction(action, '', LoeweTV.onAction);
170
- break;
171
-
172
- case "PlayerSeekTo":
173
- LoeweTV.execAction(action, '', LoeweTV.onAction);
174
- break;
175
-
176
- case "GetVolume":
177
- LoeweTV.getVolume(LoeweTV.onAction);
178
- break;
179
-
180
- case "SetVolume":
181
- LoeweTV.setVolume(msg.payload, LoeweTV.onAction);
182
- break;
183
-
184
- case "GetMute":
185
- LoeweTV.getMute(LoeweTV.onAction);
186
- break;
187
-
188
- case "SetMute":
189
- LoeweTV.setMute(msg.payload, LoeweTV.onAction);
190
- break;
191
-
192
- case "Standby":
193
- // LoeweTV.standby(msg.payload, LoeweTV.onAction);
194
- LoeweTV.execAction(action, '', LoeweTV.onAction);
195
- break;
196
-
197
- case "ProgramTimer":
198
- LoeweTV.execAction(action, '', LoeweTV.onAction);
199
- break;
200
-
201
- case "GetDeviceData":
202
- LoeweTV.getDeviceData(LoeweTV.onAction);
203
- break;
204
-
205
- case "GetValueFromBrowserJS":
206
- LoeweTV.execAction(action, '', LoeweTV.onAction);
207
- break;
208
-
209
- case "GetBrowserJSChangeList":
210
- LoeweTV.execAction(action, '', LoeweTV.onAction);
211
- break;
212
-
213
- case "SetValueToBrowserJS":
214
- LoeweTV.execAction(action, '', LoeweTV.onAction);
215
- break;
216
-
217
- case "GetCurrentPlayback":
218
- LoeweTV.execAction(action, '', LoeweTV.onAction);
219
- break;
220
-
221
- case "GetCurrentStatus":
222
- LoeweTV.getCurrentStatus(LoeweTV.onAction);
223
- break;
224
-
225
- case "ZapToApplication":
226
- LoeweTV.execAction(action, '', LoeweTV.onAction);
227
- break;
228
-
229
- case "ZapToMedia":
230
- LoeweTV.execAction(action, '', LoeweTV.onAction);
231
- break;
232
-
233
- case "InjectRCKey":
234
- LoeweTV.execAction(action, '', LoeweTV.onAction);
235
- break;
236
-
237
- case "InjectRCKey":
238
- LoeweTV.injectRCKey(msg.payload, LoeweTV.onAction);
239
- break;
240
-
241
- case "InjectKeyboardKey":
242
- LoeweTV.execAction(action, '', LoeweTV.onAction);
243
- break;
244
-
245
- case "SetActionField":
246
- LoeweTV.setActionField(msg.payload, LoeweTV.onAction);
247
- break;
248
-
249
- case "GetActionField":
250
- LoeweTV.execAction(action, '', LoeweTV.onAction);
251
- break;
252
-
253
- case "GetFeature":
254
- LoeweTV.execAction(action, '', LoeweTV.onAction);
255
- // LoeweTV.getFeature(function(){});
256
- break;
257
-
258
- case "ActivateFeaturePackage":
259
- LoeweTV.activateFeaturePackage(msg.payload, LoeweTV.onAction);
260
- break;
261
-
262
- case "DectivateFeaturePackage":
263
- LoeweTV.execAction(action, '', LoeweTV.onAction);
264
- break;
265
-
266
- case "GetUpgradeInfo":
267
- LoeweTV.execAction(action, '', LoeweTV.onAction);
268
- break;
269
-
270
- case "GetListOfChannelLists":
271
- LoeweTV.execAction(action, '', LoeweTV.onAction);
272
- // LoeweTV.getListOfChannelLists(function(){});
273
- break;
274
-
275
- case "AddFavoriteList":
276
- LoeweTV.execAction(action, '', LoeweTV.onAction);
277
- break;
278
-
279
- case "RemoveFavoriteList":
280
- LoeweTV.execAction(action, '', LoeweTV.onAction);
281
- break;
282
- case "RenameFavoriteList":
283
- LoeweTV.execAction(action, '', LoeweTV.onAction);
284
- break;
285
-
286
- case "AddServicesFavoriteList":
287
- LoeweTV.execAction(action, '', LoeweTV.onAction);
288
- break;
289
-
290
- case "RemoveServicesFavoriteList":
291
- LoeweTV.execAction(action, '', LoeweTV.onAction);
292
- break;
293
-
294
- case "MoveServicesFavoriteList":
295
- LoeweTV.execAction(action, '', LoeweTV.onAction);
296
- break;
297
-
298
- case "AddFavoriteListFromVirtual":
299
- LoeweTV.execAction(action, '', LoeweTV.onAction);
300
- break;
301
-
302
- case "GetListOfVirtualLists":
303
- LoeweTV.execAction(action, '', LoeweTV.onAction);
304
- break;
305
-
306
- case "ImportServiceLists":
307
- LoeweTV.execAction(action, '', LoeweTV.onAction);
308
- break;
309
-
310
- case "ExportServiceLists":
311
- LoeweTV.execAction(action, '', LoeweTV.onAction);
312
- break;
313
-
314
- case "GetDRPlusArchive":
315
- LoeweTV.execAction(action, '', LoeweTV.onAction);
316
- break;
317
-
318
- case "GetVolumes":
319
- LoeweTV.execAction(action, '', LoeweTV.onAction);
320
- break;
321
-
322
- case "PlayMultiroom":
323
- LoeweTV.execAction(action, '', LoeweTV.onAction);
324
- break;
325
-
326
- case "GetSettings":
327
- LoeweTV.execAction(action, '', LoeweTV.onAction);
328
- break;
329
-
330
- case "SetSetting":
331
- LoeweTV.execAction(action, '', LoeweTV.onAction);
332
- break;
333
-
334
- case "ParentalLock":
335
- LoeweTV.execAction(action, '', LoeweTV.onAction);
336
- break;
337
-
338
- case "GetParentalLock":
339
- LoeweTV.execAction(action, '', LoeweTV.onAction);
340
- break;
341
-
342
- case "GetTimerList":
343
- LoeweTV.execAction(action, '', LoeweTV.onAction);
344
- break;
345
-
346
- case "CreateIterator":
347
- LoeweTV.createIterator(LoeweTV.onAction);
348
- break;
349
-
350
- case "CloseIterator":
351
- LoeweTV.execAction(action, '', LoeweTV.onAction);
352
- break;
353
- default:
354
- break;
355
- }
356
- });
357
-
358
- LoeweTV.updateNodeStatus = function() {
359
- var statusFill ='';
360
- console.log('[' + node.name + '] updateNodeStatus');
361
-
362
- switch (LoeweTV.Status.Power) {
363
- case "idle":
364
- statusFill = "blue";
365
- break;
366
- case "standby":
367
- statusFill = "yellow";
368
- break;
369
- case "switch_on":
370
- case "tv":
371
- statusFill = "green";
372
- break;
373
- default:
374
- statusFill = "grey";
375
- break;
376
- }
377
- node.status({fill:statusFill,shape:"ring",text:"ClientId: " + LoeweTV.ClientId});
378
- var newmsg = { payload:LoeweTV.name, ClientId:LoeweTV.ClientId, Status:LoeweTV.Status.Power, topic:'Status' };
379
- node.send(newmsg);
380
- };
381
-
382
- LoeweTV.onEvent = function(event) {
383
- var self = this;
384
- node.debug('[' + node.name + '] received Event:' + event);
385
-
386
- if (event === 'alive') {
387
- node.debug('[' + node.name + '] handle Event:' + event);
388
- // if (LoeweTV.ClientId === '') {
389
- if (LoeweTV.Status.Power === 'idle' || LoeweTV.Status.Power !== 'idle') {
390
- LoeweTV.RequestAccess(function() {
391
- console.log('[', node.name, '] Registriere ClientId: ', LoeweTV.ClientId);
392
- console.log('[', node.name, '] SDDP uuid: ', LoeweTV.uuid);
393
- // LoeweTV.subscribe(function(){
394
- LoeweTV.getSettings(function(){
395
- LoeweTV.activateFeaturePackage('72413U80', function(){
396
- LoeweTV.getDeviceData(function(){
397
- LoeweTV.createIterator(function(){
398
- LoeweTV.getVolume(function(){
399
- LoeweTV.getMute(function(){
400
- LoeweTV.getCurrentStatus(function(){
401
- LoeweTV.updateNodeStatus();
402
- });
403
- });
404
- });
405
- });
406
- });
407
- });
408
- });
409
-
410
- // });
411
- });
412
- }
413
- node.debug('[' + node.name + '] handle Event:' + event + 'ok');
414
- }
415
- else if (event === 'byebye') {
416
- node.debug('[' + node.name + '] handle Event:' + event);
417
- if (LoeweTV.Status.Power === 'tv') {
418
- console.log('[', node.name, '] schaltet ab');
419
- LoeweTV.getCurrentStatus(LoeweTV.updateNodeStatus);
420
- // LoeweTV.ClientId = '';
421
- }
422
- node.debug('[' + node.name + '] handle Event:' + event + 'ok');
423
- }
424
- else {
425
- node.warn('[' + node.name + '] received unhandeld Event');
426
- }
427
- node.debug('[' + node.name + '] received Event OK');
428
- };
429
-
430
- LoeweTV.onEvent('alive');
431
- }
432
- RED.nodes.registerType("LOEWE-TV", LoeweTvNode);
433
- };
1
+ module.exports = function(RED) {
2
+ "use strict";
3
+
4
+ const dgram = require('dgram');
5
+ console.debug = function (){};
6
+ console.debug('[LoeweTV]************************************************************');
7
+ console.debug('[LoeweTV]************************************************************');
8
+
9
+ var TVs = {};
10
+
11
+ const socket = dgram.createSocket('udp4');
12
+
13
+ socket.bind(1900, () => {
14
+ socket.addMembership('239.255.255.250');
15
+ console.log('[LoeweTV] SDDP Client lauscht an Port 1900');
16
+ });
17
+
18
+ socket.on('message', (msg, rinfo) => {
19
+ var sddpMsg = msg.toString();
20
+ // console.log('[LoeweTV SDDP:1900] ' + rinfo.address);
21
+ // console.log(sddpMsg);
22
+ if ( TVs.hasOwnProperty(rinfo.address) ) {
23
+ var lines = sddpMsg.split('\r');
24
+ var objSddpMsg = {};
25
+ // console.log('[LoeweTV SDDP:1900] ' + rinfo.address);
26
+ // console.log(sddpMsg);
27
+ lines.forEach((line) => {
28
+ // console.debug('[LoeweTV SDDP:1900]' + line);
29
+ var del = line.indexOf(':');
30
+ if(del>1) {
31
+ var key = line.substring(0,del).trim().toLowerCase();
32
+ var value = line.substring(del+1).trim();
33
+ // console.debug('[LoeweTV SDDP:1900] Key: ' + key + ' Value: ' + value);
34
+ objSddpMsg[key]=value;
35
+ }
36
+ });
37
+ TVs[rinfo.address].onSDDP(objSddpMsg);
38
+ }
39
+ });
40
+
41
+ const socket1902 = dgram.createSocket('udp4');
42
+
43
+ socket1902.bind(1902, () => {
44
+ socket1902.addMembership('239.255.255.250');
45
+ console.log('[LoeweTV] SDDP Client lauscht an Port 1902');
46
+ });
47
+
48
+ socket1902.on('message', (msg, rinfo) => {
49
+ var sddpMsg = msg.toString();
50
+ // console.log('[LoeweTV SDDP:1902] ' + rinfo.address);
51
+ // console.log(sddpMsg);
52
+ if ( TVs.hasOwnProperty(rinfo.address) ) {
53
+ var lines = sddpMsg.split('\r');
54
+ var objSddpMsg = {};
55
+ console.log('[LoeweTV SDDP:1902] ' + rinfo.address);
56
+ console.log(sddpMsg);
57
+ lines.forEach((line) => {
58
+ // console.debug('[LoeweTV SDDP:1902]' + line);
59
+ var del = line.indexOf(':');
60
+ if(del>1) {
61
+ var key = line.substring(0,del).trim().toLowerCase();
62
+ var value = line.substring(del+1).trim();
63
+ // console.debug('[LoeweTV SDDP:1902] Key: ' + key + ' Value: ' + value);
64
+ objSddpMsg[key]=value;
65
+ }
66
+ });
67
+
68
+ TVs[rinfo.address].onSDDP(objSddpMsg);
69
+ }
70
+ });
71
+
72
+ function LoeweTvNode(config) {
73
+ const http = require('http');
74
+ const os = require('os');
75
+ const xml2js = require('xml2js');
76
+ const wol = require('wol');
77
+ var parseString = xml2js.parseString;
78
+ var node = this;
79
+ node.ClientId = '';
80
+ node.sddpUuid = '';
81
+ node.Volume = '';
82
+ node.Mute = '';
83
+ node.data = {CurrentStatus:{Power:'disconnected'}};
84
+
85
+ RED.nodes.createNode(node, config);
86
+
87
+ this.tv = RED.nodes.getNode(config.tv);
88
+
89
+ node.name = this.tv.name;
90
+
91
+ var interfaces = os.networkInterfaces();
92
+
93
+ for ( var i in interfaces) {
94
+ interfaces[i].forEach(function(details) {
95
+ details.interface = i;
96
+ if (!details.internal) {
97
+ delete details.netmask;
98
+ delete details.mac;
99
+ delete details.internal;
100
+ this.HostIP = details.address;
101
+ }
102
+ });
103
+ break;
104
+ }
105
+
106
+ // Check if ipAddress is valid IP address
107
+ var ipRegExp = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/;
108
+
109
+ if(ipRegExp.test(this.tv.ip)) {
110
+ this.ipAddress = this.tv.ip;
111
+ node.log('neuer LOEWE TV \"' + this.name + '\" angemeldet IP: ' + this.ipAddress);
112
+ }
113
+ else {
114
+ throw new TypeError('IP address not valid!');
115
+ }
116
+
117
+ var ipRegExp = /^([0-9])*/;
118
+
119
+ if(ipRegExp.test(this.tv.fcid)) {
120
+ this.fcid = this.tv.fcid;
121
+ console.debug('FCID: ' + this.fcid);
122
+ }
123
+ else {
124
+ throw new TypeError('fcid not valid!');
125
+ }
126
+
127
+ TVs[this.ipAddress] = this;
128
+
129
+ node.onActionTemplate = function(action, actionData) {
130
+ var self = this;
131
+ var newmsg = { payload:{
132
+ Name:node.name,
133
+ ClientId:node.ClientId,
134
+ Status:node.data.CurrentStatus.Power
135
+ },
136
+ action:action,
137
+ actionData:actionData,
138
+ topic:'LoeweTV'
139
+ };
140
+ node.updateNodeStatus();
141
+ node.send(newmsg);
142
+ };
143
+
144
+ node.onAction = function(action, actionData) {
145
+ var self = this;
146
+ node.log(action);
147
+ switch ( action ) {
148
+ case "GetVolume":
149
+ node.log('Volume: ', node.Volume);
150
+ var newmsg = { payload:{Name:node.name, ClientId:node.ClientId, Status:node.data.CurrentStatus.Power}, action:action, actionData:{Volume:node.Volume}, topic:action };
151
+ node.send(newmsg);
152
+ break;
153
+
154
+ case "GetMute":
155
+ node.log('Mute: ', node.Mute);
156
+ var newmsg = { payload:{Name:node.name, ClientId:node.ClientId, Status:node.data.CurrentStatus.Power}, action:action, actionData:{Volume:node.Mute}, topic:action };
157
+ node.send(newmsg);
158
+ break;
159
+
160
+ case "SetVolume":
161
+ node.log('Set Volume to: ', node.Volume);
162
+ var newmsg = { payload:{Name:node.name, ClientId:node.ClientId, Status:node.data.CurrentStatus.Power}, action:action, actionData:{Volume:node.Volume}, topic:action };
163
+ node.send(newmsg);
164
+ break;
165
+
166
+ case "SetMute":
167
+ node.log('Set Mute to: ', node.Mute);
168
+ var newmsg = { payload:{Name:node.name, ClientId:node.ClientId, Status:node.data.CurrentStatus.Power}, action:action, actionData:{Volume:node.Mute}, topic:action };
169
+ node.send(newmsg);
170
+ break;
171
+
172
+ default:
173
+ node.log(actionData);
174
+ break;
175
+ }
176
+ };
177
+
178
+ node.on('input', function(msg) {
179
+ var action = msg.topic;
180
+ switch ( action ) {
181
+ case "SDDPDiscover":
182
+ node.sddpDiscover();
183
+ break;
184
+ case "SwitchOn":
185
+ node.switchOn();
186
+ break;
187
+ case "WakeUp":
188
+ node.wakeUp(msg.payload);
189
+ break;
190
+ case "InjectSoapRequest":
191
+ node.injectSoapRequest(msg.payload, node.onAction);
192
+ break;
193
+ case "RequestAccess":
194
+ node.onEvent('alive');
195
+ break;
196
+ case "GetChannelList":
197
+ node.getChannelList(msg.payload, node.onActionTemplate);
198
+ break;
199
+ case "GetCurrentEvent":
200
+ node.getEvent('CurrentEvent', msg.payload, node.onActionTemplate);
201
+ break;
202
+ case "GetNextEvent":
203
+ node.getEvent('NextEvent', msg.payload, node.onActionTemplate);
204
+ break;
205
+ case "GetMediaItem":
206
+ node.getMediaItem(msg.payload, node.onActionTemplate);
207
+ break;
208
+ case "GetMediaEvent":
209
+ node.getMediaEvent(msg.payload, node.onActionTemplate);
210
+ // node.getMediaEvent(function(){});
211
+ break;
212
+ case "PlayerPrepare":
213
+ node.playerPrepare(msg.payload, node.onActionTemplate);
214
+ break;
215
+ case "PlayerReleasePrepared":
216
+ node.execAction(action, '', node.onAction);
217
+ break;
218
+ case "PlayerPlay":
219
+ node.execAction(action, '', node.onAction);
220
+ break;
221
+ case "PlayerPause":
222
+ node.execAction(action, '', node.onAction);
223
+ break;
224
+ case "PlayerResume":
225
+ node.execAction(action, '', node.onAction);
226
+ break;
227
+ case "PlayerStop":
228
+ node.execAction(action, '', node.onAction);
229
+ break;
230
+ case "PlayerSetSpeed":
231
+ node.execAction(action, '', node.onAction);
232
+ break;
233
+ case "PlayerSeekTo":
234
+ node.execAction(action, '', node.onAction);
235
+ break;
236
+ case "GetVolume":
237
+ node.getValue('Volume', node.onAction);
238
+ break;
239
+ case "SetVolume":
240
+ let volume = msg.payload.toString() + '0000';
241
+ node.setValue('Volume', volume, node.onAction);
242
+ break;
243
+ case "GetMute":
244
+ node.getValue('Mute', node.onAction);
245
+ break;
246
+ case "SetMute":
247
+ node.setValue('Mute', msg.payload, node.onAction);
248
+ break;
249
+ case "Standby":
250
+ node.standby(msg.payload, node.onAction);
251
+ // node.standby(msg.payload, node.onAction);
252
+ // node.execAction(action, '', node.onAction);
253
+ break;
254
+ case "ProgramTimer":
255
+ node.execAction(action, '', node.onAction);
256
+ break;
257
+ case "GetDeviceData":
258
+ node.execAction(action, '', node.onActionTemplate);
259
+ break;
260
+ case "GetValueFromBrowserJS":
261
+ node.execAction(action, '', node.onAction);
262
+ break;
263
+ case "GetBrowserJSChangeList":
264
+ node.execAction(action, '', node.onAction);
265
+ break;
266
+ case "SetValueToBrowserJS":
267
+ node.execAction(action, '', node.onAction);
268
+ break;
269
+ case "GetCurrentPlayback":
270
+ node.execAction(action, '', node.onActionTemplate);
271
+ break;
272
+ case "GetCurrentStatus":
273
+ node.execAction(action, '', node.onActionTemplate);
274
+ break;
275
+ case "ZapToApplication":
276
+ node.execAction(action, '', node.onAction);
277
+ break;
278
+ case "ZapToMedia":
279
+ node.execAction(action, '', node.onAction);
280
+ break;
281
+ case "InjectRCKey":
282
+ node.injectRCKey(msg.payload, node.onAction);
283
+ // node.injectRCKey(msg.payload, function(){});
284
+ // setTimeout( node.execAction, 3000, ['GetCurrentStatus', '', ]
285
+ break;
286
+ case "InjectKeyboardKey":
287
+ node.execAction(action, '', node.onAction);
288
+ break;
289
+ case "SetActionField":
290
+ node.setActionField(msg.payload, node.onAction);
291
+ break;
292
+ case "GetActionField":
293
+ node.getActionField(msg.payload, node.onAction);
294
+ break;
295
+ case "GetFeature":
296
+ node.getFeature(msg.payload, node.onActionTemplate);
297
+ break;
298
+ case "ActivateFeaturePackage":
299
+ node.activateFeaturePackage(msg.payload, node.onAction);
300
+ break;
301
+ case "DectivateFeaturePackage":
302
+ node.execAction(action, '', node.onAction);
303
+ break;
304
+ case "GetUpgradeInfo":
305
+ node.execAction(action, '', node.onAction);
306
+ break;
307
+ case "GetListOfChannelLists":
308
+ node.getListOfChannelLists(msg.payload, node.onActionTemplate);
309
+ break;
310
+ case "AddFavoriteList":
311
+ node.execAction(action, '', node.onAction);
312
+ break;
313
+ case "RemoveFavoriteList":
314
+ node.execAction(action, '', node.onAction);
315
+ break;
316
+ case "RenameFavoriteList":
317
+ node.execAction(action, '', node.onAction);
318
+ break;
319
+ case "AddServicesFavoriteList":
320
+ node.execAction(action, '', node.onAction);
321
+ break;
322
+ case "RemoveServicesFavoriteList":
323
+ node.execAction(action, '', node.onAction);
324
+ break;
325
+ case "MoveServicesFavoriteList":
326
+ node.execAction(action, '', node.onAction);
327
+ break;
328
+ case "AddFavoriteListFromVirtual":
329
+ node.execAction(action, '', node.onAction);
330
+ break;
331
+ case "GetListOfVirtualLists":
332
+ node.getListOfVirtualLists(msg.payload, node.onActionTemplate);
333
+ break;
334
+ case "ImportServiceLists":
335
+ node.execAction(action, '', node.onAction);
336
+ break;
337
+ case "ExportServiceLists":
338
+ node.execAction(action, '', node.onAction);
339
+ break;
340
+ case "GetDRPlusArchive":
341
+ node.getDRPlusArchive(msg.payload, node.onActionTemplate);
342
+ break;
343
+ case "GetVolumes":
344
+ node.getVolumes(msg.payload, node.onActionTemplate);
345
+ break;
346
+ case "PlayMultiroom":
347
+ node.execAction(action, '', node.onAction);
348
+ break;
349
+ case "GetSettings":
350
+ node.execAction(action, '',node.onActionTemplate);
351
+ break;
352
+ case "SetSetting":
353
+ node.execAction(action, '', node.onAction);
354
+ break;
355
+ case "ParentalLock":
356
+ node.execAction(action, '', node.onAction);
357
+ break;
358
+ case "GetParentalLock":
359
+ node.execAction(action, '', node.onActionTemplate);
360
+ break;
361
+ case "GetTimerList":
362
+ node.execAction(action, '', node.onActionTemplate);
363
+ break;
364
+ case "CreateIterator":
365
+ node.createIterator(node.onAction);
366
+ break;
367
+ case "CloseIterator":
368
+ node.execAction(action, '', node.onAction);
369
+ break;
370
+ default:
371
+ break;
372
+ }
373
+ });
374
+
375
+ node.updateNodeStatus = function() {
376
+ var statusFill = "";
377
+ var statusShape = "ring";
378
+ var power = node.data.CurrentStatus.Power;
379
+ node.debug('updateNodeStatus');
380
+ switch (power) {
381
+ case "idle":
382
+ statusFill = "blue";
383
+ node.log('TV ist im \"Leerlauf\"');
384
+ break;
385
+ case "standby":
386
+ statusFill = "grey";
387
+ node.log('TV ist im Standby');
388
+ break;
389
+ case "switch_on":
390
+ case "tv":
391
+ statusFill = "green";
392
+ statusShape = "dot";
393
+ node.log('TV ist Eingeschaltet');
394
+ break;
395
+ default:
396
+ statusFill = "grey";
397
+ node.log('TV status unknown');
398
+ break;
399
+ }
400
+ node.status({fill:statusFill,shape:statusShape,text:node.data.CurrentStatus.Power});
401
+ var newmsg = { payload:{
402
+ Name:node.name,
403
+ ClientId:node.ClientId,
404
+ Status:node.data.CurrentStatus.Power
405
+ },
406
+ data:node.data,
407
+ topic:'Status'
408
+ };
409
+ node.send(newmsg);
410
+ };
411
+
412
+ node.onEvent = function(event) {
413
+ var self = this;
414
+ node.debug('received SDDP Event: ' + event);
415
+ node.debug('TV Status: ' + node.data.CurrentStatus.Power);
416
+
417
+ if (event === 'alive') {
418
+ node.debug('handle SDDP Event: ' + event);
419
+ if (node.ClientId === '' |
420
+ node.data.CurrentStatus.Power === 'switchon' |
421
+ node.data.CurrentStatus.Power === 'disconnected' |
422
+ node.data.CurrentStatus.Power === 'standby' ) {
423
+ node.requestAccess(function() {
424
+ node.execAction('GetCurrentStatus', '', function () {
425
+ node.log('Registriere ClientId: ' + node.ClientId);
426
+ if (node.sddpUuid !== '') {
427
+ node.log('SDDP uuid: ' + node.sddpUuid);
428
+ }
429
+ if (node.data.CurrentStatus.Power === 'switchon') {
430
+ node.log('schalte ein');
431
+ node.injectRCKey('12', function () {});
432
+ setTimeout(node.onEvent, 500, 'alive');
433
+ } else {
434
+ node.execAction('GetSettings', '', function () {
435
+ node.activateFeaturePackage({"Package":"72413U80"}, function(){
436
+ node.execAction('GetDeviceData', '', function () {
437
+ if (self.tv.mac === undefined | self.tv.mac === '') {
438
+ if ( self.data.hasOwnProperty("DeviceData") ) {
439
+ if ( self.data.DeviceData.hasOwnProperty("MAC-Address-LAN") ) {
440
+ self.tv.mac = self.data.DeviceData['MAC-Address-LAN'];
441
+ }
442
+ }
443
+ }
444
+
445
+ node.createIterator(function(){
446
+ node.getValue('Volume', function(){
447
+ node.getValue('Mute', function(){
448
+ // node.execAction('GetCurrentStatus', '', function () {
449
+ node.updateNodeStatus();
450
+ // });
451
+ });
452
+ });
453
+ });
454
+ });
455
+ });
456
+ });
457
+ }
458
+ });
459
+ });
460
+ }
461
+ node.debug('handle SDDP Event: ' + event + ' ok');
462
+ }
463
+ else if (event === 'byebye') {
464
+ node.debug('handle SDDP Event: ' + event);
465
+ if (node.data.CurrentStatus.Power === 'tv' | node.data.CurrentStatus.Power === 'idle' | node.data.CurrentStatus.Power === 'disconnected') {
466
+ node.debug('schaltet ab');
467
+ // node.execAction('GetCurrentStatus', '', function() {});
468
+ node.data.CurrentStatus.Power = "standby";
469
+ node.ClientId = '';
470
+ }
471
+ node.debug('handle SDDP Event: ' + event + ' ok');
472
+ }
473
+ else {
474
+ node.warn('SDDP: received unhandeld Event');
475
+ }
476
+ node.updateNodeStatus();
477
+ node.debug('TV Status: ' + node.data.CurrentStatus.Power);
478
+ node.debug('received SDDP Event END');
479
+ };
480
+
481
+ node.onSDDP = function() {
482
+ var self = this;
483
+ return function(objSddpMsg){
484
+ if (objSddpMsg.hasOwnProperty("nt")) {
485
+ if (objSddpMsg.nt === 'upnp:rootdevice') {
486
+ if (objSddpMsg.nts === 'ssdp:alive') {
487
+ try {
488
+ var sddpUuid = (objSddpMsg.usn).split(':')[1].trim();
489
+ if (self.sddpUuid === '') {
490
+ self.sddpUuid = sddpUuid;
491
+ node.log('SDDP uuid: ' + self.sddpUuid);
492
+ self.onEvent('alive');
493
+ }
494
+ }
495
+ catch {
496
+ node.error('*********************** ERROR ***********************');
497
+ node.error(objSddpMsg);
498
+ node.error('********************* END ERROR *********************');
499
+ }
500
+
501
+ } else {
502
+ if ( objSddpMsg.nts === 'ssdp:byebye' ) {
503
+ self.sddpUuid = '';
504
+ self.ClientId = '';
505
+ self.onEvent('byebye');
506
+ }
507
+ else if ( objSddpMsg.nts === 'ssdp:discover' | objSddpMsg.man === '\"ssdp:discover\"') {
508
+ }
509
+ else {
510
+ node.error('[LoeweTV ERROR] ', objSddpMsg);
511
+ }
512
+ }
513
+ }
514
+ } else {
515
+ console.log("[" + node.name + "] SDDP:");
516
+ console.log(objSddpMsg);
517
+ }
518
+ };
519
+ };
520
+
521
+ node.sddpDiscover = function() {
522
+ const client = dgram.createSocket('udp4');
523
+ client.bind({
524
+ address: 'localhost',
525
+ port: 0
526
+ }, (err) => {
527
+ !!err && console.error(err);
528
+ });
529
+
530
+ let msg_txt = 'M-SEARCH * HTTP/1.1\r\n' +
531
+ 'HOST:239.255.255.250:1900\r\n' +
532
+ 'ST:upnp:rootdevice\r\n' +
533
+ 'MX:2\r\n' +
534
+ 'MAN:"ssdp:discover"\r\n\r\n';
535
+
536
+ const message = Buffer.from(msg_txt);
537
+
538
+ // client.bind(); // So that we get a port so we can listen before sending
539
+ // listen(client.address().port);
540
+ client.send(message, 0, message.length, 1900, "239.255.255.250", (err) => {
541
+ !!err && console.error(err); // err != null);
542
+ });
543
+ client.close();
544
+ };
545
+
546
+ node.getTimeString = function(time) {
547
+ var seconds = Math.floor(time/1000)%60;
548
+ var minutes = Math.floor(time/60000)%60;
549
+ var hours = Math.floor(time/3600000)%24;
550
+ var timeString;
551
+
552
+ if (seconds < 10) { seconds = "0" + seconds; }
553
+ if (minutes < 10) { minutes = "0" + minutes; }
554
+ if (hours < 10) { hours = " " + hours; }
555
+ timeString = hours + ":" + minutes + ":" + seconds;
556
+ return timeString;
557
+ };
558
+
559
+ node.wakeUp = function(mac) {
560
+ var self = this;
561
+ if (mac === undefined | mac === '') {
562
+ node.log('mac undefined');
563
+
564
+ if ( this.data.hasOwnProperty("DeviceData") ) {
565
+ if ( this.data.DeviceData.hasOwnProperty("MAC-Address-LAN") ) {
566
+ mac = this.data.DeviceData['MAC-Address-LAN'];
567
+ }
568
+ }
569
+ }
570
+ if (mac !== undefined & mac !== '') {
571
+ node.log('wakeUp: ' + mac);
572
+ wol.wake(mac, function(err, res){
573
+ // node.log('', err);
574
+ node.log('', res);
575
+ });
576
+ } else {
577
+ node.error('*********************** ERROR ***********************');
578
+ node.error('wakeUp: no MAC');
579
+ node.error('********************* END ERROR *********************');
580
+ }
581
+ }
582
+
583
+ node.switchOn = function() {
584
+ var self = this;
585
+ node.log('switchOn');
586
+ node.log('Status: ' + self.data.CurrentStatus.Power);
587
+
588
+ if (self.data.CurrentStatus.Power !== 'idle' & self.data.CurrentStatus.Power !== 'tv') {
589
+ self.wakeUp();
590
+ self.data.CurrentStatus.Power = 'switchon';
591
+ }else if (self.data.CurrentStatus.Power === 'idle' | self.data.CurrentStatus.Power === 'standby') {
592
+ self.injectRCKey('12', function () {});
593
+ } else {
594
+ node.log('[LoeweTV ' + self.name + '] ist bereits an');
595
+ }
596
+ }
597
+
598
+ /**
599
+ * Create and send request to the TV
600
+ *
601
+ * @param {String} ClientId The ClientId from RequestAccess
602
+ * @param {String} action The action to perform
603
+ * @param {Array} data like RC-Key number
604
+ * @param {Array} options Options array (mostly for callback)
605
+ */
606
+ node.sendSOAPRequest = function(action, actionData, options) {
607
+ var url, urn;
608
+ var responseData = '';
609
+ var self = this;
610
+
611
+ url = '/loewe_tablet_0001';
612
+ urn = 'loewe.de:RemoteTV:Tablet';
613
+
614
+
615
+ // var body = '<?xml version="1.0" encoding="utf-8"?>' +
616
+ var body = '<SOAP-ENV:Envelope ' +
617
+ 'xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" ' +
618
+ 'xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" ' +
619
+ 'xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing/" ' +
620
+ 'xmlns:wse="http://www.w3.org/2009/02/ws-evt" ' +
621
+ 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
622
+ 'xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' +
623
+ 'xmlns:m="urn:loewe.de:RemoteTV:Tablet">' +
624
+ '<SOAP-ENV:Body>' +
625
+ '<m:' + action + '>' +
626
+ '<fcid>' + this.fcid + '</fcid>' +
627
+ '<ClientId>' + this.ClientId + '</ClientId>' +
628
+ actionData +
629
+ '</m:' + action + '>' +
630
+ '</SOAP-ENV:Body>' +
631
+ '</SOAP-ENV:Envelope>';
632
+
633
+ var postRequest = {
634
+ host: this.ipAddress,
635
+ path: url,
636
+ port: 905,
637
+ method: "POST",
638
+ headers: {
639
+ 'SOAPAction': action,
640
+ 'Accept': '*/*',
641
+ 'Accept-Encoding': 'gzip, deflate',
642
+ 'Accept-Language': 'de-de',
643
+ 'Content-Type': 'application/soap+xml; charset=utf-8',
644
+ 'Connection': 'keep-alive',
645
+ 'User-Agent': 'Assist Media/23 CFNetwork/808 Darwin/16.0.0'
646
+ }
647
+ };
648
+
649
+ if(options !== undefined) {
650
+ self.callback = options.callback;
651
+ } else {
652
+ self.callback = function (soapRequest, soapResponse) {
653
+ node.log('SOAP Request: ');
654
+ node.log(soapRequest);
655
+ node.log('SOAP Response: ');
656
+ node.log(soapResponse);
657
+ };
658
+ }
659
+
660
+ var req = http.request(postRequest, function(res) {
661
+ res.setEncoding('utf8');
662
+ res.on('data', (chunk) => {
663
+ responseData += chunk.toString();
664
+ });
665
+
666
+ res.on('end', function() {
667
+ var match = /<SOAP-ENV:Fault>/gm.exec(responseData);
668
+ if(match !== null) {
669
+ node.error('*********************** ERROR ***********************');
670
+ node.error('SOAP body: ');
671
+ node.error(body);
672
+ node.error('---------------------------------------------------------------');
673
+ node.error('SOAP Response: ');
674
+ node.error(responseData);
675
+ node.error('********************* END ERROR *********************');
676
+ }
677
+ self.callback(body, responseData);
678
+ });
679
+
680
+
681
+ });
682
+
683
+ req.on('error', function(e) {
684
+ node.log('' + e.address + ' ist nicht erreichbar!');
685
+ self.sddpUuid = '';
686
+ self.ClientId = '';
687
+ });
688
+
689
+ req.write(body);
690
+ node.debug('sendSOAPRequest: ');
691
+ node.debug(body);
692
+ req.end();
693
+
694
+ return this;
695
+ };
696
+
697
+ node.getObjectFromResponse = function(action, soapRequest, soapResponse, callback) {
698
+ var self = this;
699
+ node.debug('-------------------- ' + action + ' ------------------');
700
+
701
+ var regex = new RegExp("<SOAP-ENV:Body>((.|\n)*)<\/SOAP-ENV:Body>", "gm");
702
+ var dataFromAction = ((regex.exec(soapResponse))[1].replace(/m:|:m/gm, "")).replace(/xmlns="urn:loewe.de:RemoteTV:Tablet"/,"" );
703
+ node.debug(soapResponse);
704
+ /*
705
+ var responseData = (regex.exec(soapResponse))[1];
706
+ node.debug(responseData);
707
+ responseData = responseData.replace(/m:|:m/gm, "");
708
+ node.debug('--------------------------------------');
709
+ console.debug(responseData);
710
+ responseData = responseData.replace(/xmlns="urn:loewe.de:RemoteTV:Tablet"/,"");
711
+ node.debug('--------------------------------------');
712
+ console.debug(responseData);
713
+ node.debug('--------------------------------------');
714
+ */
715
+ var options = {};
716
+ var objResponse;
717
+
718
+ node.debug(dataFromAction)
719
+
720
+ options.async = false;
721
+ options.trim = true;
722
+ options.explicitArray = false;
723
+ options.attrkey = options.attrkey || '$';
724
+ options.charkey = options.charkey || '_';
725
+
726
+ parseString(dataFromAction, options, function (err, result) {
727
+ if (err) {
728
+ node.error('*********************** ERROR ***********************');
729
+ node.error(action);
730
+ node.error(err)
731
+ node.error('********************* END ERROR *********************');
732
+ }
733
+ else {
734
+ for (var key in result) {
735
+ for (var reponseKey in result[key]) {
736
+ break
737
+ }
738
+ break
739
+ }
740
+ if (result[key] === undefined | result[key] === '' | result[key] === ' ' | reponseKey == 0) {
741
+ node.error('*********************** ERROR ***********************');
742
+ node.error('SoapRequest');
743
+ node.error(soapRequest);
744
+ node.error('---------------------------------------------------------------');
745
+ node.error('SoapResponse');
746
+ node.error(soapResponse);
747
+ node.error('---------------------------------------------------------------');
748
+ node.error(result);
749
+ node.error('********************* END ERROR *********************');
750
+ } else {
751
+ objResponse = result;
752
+ }
753
+ }
754
+ });
755
+
756
+ var objName = action.replace('Get', '');
757
+ if (objResponse !== undefined) {
758
+ this.data[objName] = objResponse[action+'Response'];
759
+ node.debug('result obj: ' + objName);
760
+ node.debug(this.data[objName]);
761
+ } else {
762
+ this.data[objName] = {};
763
+ }
764
+ callback(action, this.data[objName]);
765
+ };
766
+
767
+ node.injectSoapRequest = function(soapRequest, callback) {
768
+ var self = this;
769
+ self.actionCallback = callback;
770
+
771
+ node.log('', soapRequest);
772
+
773
+ var action = (/<m:(\w*)>/gm.exec(soapRequest))[1];
774
+ node.log('****************************************************');
775
+ node.log('****************************************************');
776
+ node.log('-------------------- ' + action + ' ------------------');
777
+
778
+ var regex = new RegExp("<m:" + action + ">((.)*)<\/m:" + action + ">", "gm");
779
+ var actionData = (regex.exec(soapRequest))[1];
780
+
781
+ node.log('', actionData);
782
+
783
+ /*
784
+ this.sendSOAPRequest(action, actionData, {
785
+ callback: function(soapRequest, soapResponse){
786
+ node.debug('soapResponse:');
787
+ console.debug(soapResponse);
788
+ self.actionCallback(action, soapResponse);
789
+ }
790
+ });
791
+ */
792
+
793
+ this.sendSOAPRequest(action, actionData, {
794
+ callback: function(soapRequest, soapResponse){
795
+ node.log('soapResponse:');
796
+ node.log(soapResponse);
797
+ self.getObjectFromResponse(action, soapRequest, soapResponse, function (action, responseData) {
798
+ self.actionCallback(action, responseData)
799
+ node.log('****************************************************');
800
+ node.log('****************************************************');
801
+ });
802
+ }
803
+ });
804
+ };
805
+
806
+ node.getEvent = function(event, player, callback) {
807
+ var self = this;
808
+ var action = 'Get'+event;
809
+ var actionData = '<Player>' + player + '</Player>';
810
+ node.debug('-------------------- ' + action + ' ------------------');
811
+
812
+ self.actionCallback = callback;
813
+
814
+ this.sendSOAPRequest(action, actionData, {
815
+ callback: function(soapRequest, soapResponse){
816
+ node.debug('soapResponse:');
817
+ console.debug(soapResponse);
818
+ self.getObjectFromResponse(action, soapRequest, soapResponse, self.actionCallback);
819
+ }
820
+ });
821
+ };
822
+
823
+ node.getMediaItem = function(mediaItemUuid, callback) {
824
+ var self = this;
825
+ var action = 'GetMediaItem';
826
+ var actionData = '<MediaItemReference mediaItemUuid=\"' + mediaItemUuid + '\"/>';
827
+
828
+ self.actionCallback = callback;
829
+
830
+ self.sendSOAPRequest(action, actionData, {
831
+ callback: function(soapRequest, soapResponse){
832
+ self.getObjectFromResponse(action, soapRequest, soapResponse, self.actionCallback);
833
+ }
834
+ });
835
+ };
836
+
837
+ node.getMediaEvent = function(mediaEventUuid, callback) {
838
+ var self = this;
839
+ var action = 'GetMediaEvent';
840
+ var actionData = '<MediaEventReference mediaEventUuid=\"' + mediaEventUuid + '\"/>';
841
+
842
+ self.actionCallback = callback;
843
+
844
+ self.sendSOAPRequest(action, actionData, {
845
+ callback: function(soapRequest, soapResponse){
846
+ self.getObjectFromResponse(action, soapRequest, soapResponse, self.actionCallback);
847
+ }
848
+ });
849
+ };
850
+
851
+ node.playerPrepare = function(data, callback) {
852
+ var self = this;
853
+ var action = 'PlayerPrepare';
854
+ var actionData = '<Player>' + data.Player + '</Player><Locator>' + data.Locator + '</Locator>';
855
+
856
+ self.actionCallback = callback;
857
+
858
+ self.sendSOAPRequest(action, actionData, {
859
+ callback: function(soapRequest, soapResponse){
860
+ self.getObjectFromResponse(action, soapRequest, soapResponse, self.actionCallback);
861
+ }
862
+ });
863
+ };
864
+
865
+ node.execAction = function(action, actionData, callback) {
866
+ var self = this;
867
+
868
+ self.actionCallback = callback;
869
+
870
+ self.sendSOAPRequest(action, actionData, {
871
+ callback: function(soapRequest, soapResponse){
872
+ self.getObjectFromResponse(action, soapRequest, soapResponse, self.actionCallback);
873
+ }
874
+ });
875
+ };
876
+
877
+ node.standby = function(value, callback) {
878
+ var self = this;
879
+ var action = 'Standby';
880
+ var actionData = '<Value>' + value + '</Value>';
881
+ self.actionCallback = callback;
882
+
883
+ self.sendSOAPRequest(action, actionData, {
884
+ callback: function(soapRequest, soapResponse){
885
+ var regex = new RegExp("<m:Value>(\\d*)<\/m:Value>", "gm");
886
+ var responseValue = regex.exec(soapResponse);
887
+ node.debug('----------------- ' + action + ' -----------------------');
888
+ node.debug(soapResponse);
889
+ node.debug('----------------- ' + action + ' -----------------------');
890
+ if(responseValue !== null) {
891
+ node.log('' + action + ' value: ' + responseValue[1])
892
+ self[value] = responseValue[1];
893
+ self.actionCallback(action, responseValue[1]);
894
+ } else {
895
+ regex = new RegExp("<m:" + action + "Response [A-Za-z:=\".]*>(.*)<\/m:" + action + "Response>", "gm");
896
+ console.debug(soapResponse);
897
+ var responseData = (regex.exec(soapResponse))[1];
898
+ if (responseData !== null) {
899
+ node.debug(action + ' data: ' + responseData);
900
+ self.actionCallback(action, responseData);
901
+ } else {
902
+ node.error('*********************** ERROR ***********************');
903
+ node.error('SoapRequest');
904
+ node.error(soapRequest);
905
+ node.error('---------------------------------------------------------------');
906
+ node.error('error: ', action);
907
+ node.error('data: ', soapResponse);
908
+ node.error('********************* END ERROR *********************');
909
+ }
910
+ }
911
+ }
912
+ });
913
+ };
914
+
915
+ node.setValue = function(valueName, value, callback) {
916
+ var self = this;
917
+ var action = 'Set'+valueName;
918
+ var actionData = '<Value>' + value + '</Value>';
919
+ self.actionCallback = callback;
920
+
921
+ self.sendSOAPRequest(action, actionData, {
922
+ callback: function(soapRequest, soapResponse){
923
+ var regex = new RegExp("<m:Value>(\\d*)<\/m:Value>", "gm");
924
+ var responseValue = regex.exec(soapResponse);
925
+ node.debug('----------------- ' + action + ' -----------------------');
926
+ node.debug(soapResponse);
927
+ node.debug('----------------- ' + action + ' -----------------------');
928
+ if(responseValue !== null) {
929
+ node.log('' + action + ' value: ' + responseValue[1])
930
+ self[value] = responseValue[1];
931
+ self.actionCallback(action, responseValue[1]);
932
+ } else {
933
+ regex = new RegExp("<m:" + action + "Response [A-Za-z:=\".]*>(.*)<\/m:" + action + "Response>", "gm");
934
+ console.debug(soapResponse);
935
+ var responseData = (regex.exec(soapResponse))[1];
936
+ if (responseData !== null) {
937
+ node.debug(action + ' data: ' + responseData);
938
+ self.actionCallback(action, responseData);
939
+ } else {
940
+ node.error('*********************** ERROR ***********************');
941
+ node.error('SoapRequest');
942
+ node.error(soapRequest);
943
+ node.error('---------------------------------------------------------------');
944
+ node.error('error: ', action);
945
+ node.error('data: ', soapResponse);
946
+ node.error('********************* END ERROR *********************');
947
+ }
948
+ }
949
+ }
950
+ });
951
+ };
952
+
953
+ node.getValue = function(valueName, callback) {
954
+ var self = this;
955
+ var action = 'Get'+valueName;
956
+ var actionData = '';
957
+ self.actionCallback = callback;
958
+
959
+ self.sendSOAPRequest(action, actionData, {
960
+ callback: function(soapRequest, soapResponse){
961
+ var regex = new RegExp("<m:Value>(\\d*)<\/m:Value>", "gm");
962
+ var responseValue = regex.exec(soapResponse);
963
+ node.debug('----------------- ' + action + ' -----------------------');
964
+ node.debug(soapResponse);
965
+ node.debug('----------------- ' + action + ' -----------------------');
966
+ if(responseValue !== null) {
967
+ node.debug(action + ' ' + valueName + ': ' + responseValue[1])
968
+ self[valueName] = responseValue[1];
969
+ self.actionCallback(action, self[valueName]);
970
+ } else {
971
+ regex = new RegExp("<m:" + action + "Response [A-Za-z:=\".]*>(.*)<\/m:" + action + "Response>", "gm");
972
+ var responseData = (regex.exec(soapResponse))[1];
973
+ if (responseData !== null) {
974
+ node.debug(action + ' data: ' + responseData);
975
+ self.actionCallback(action, responseData);
976
+ } else {
977
+ node.error('*********************** ERROR ***********************');
978
+ node.error('SoapRequest');
979
+ node.error(soapRequest);
980
+ node.error('---------------------------------------------------------------');
981
+ node.error('error: ', action);
982
+ node.error('data: ', soapResponse);
983
+ node.error('********************* END ERROR *********************');
984
+ }
985
+ }
986
+ }
987
+ });
988
+ };
989
+
990
+ node.getDRPlusArchive = function(startindex, callback) {
991
+ var self = this;
992
+ var action = 'GetDRPlusArchive';
993
+ var actionData = '<m:QueryParameters>' +
994
+ '<m:Range startIndex="' + startindex + '" maxItems="5"/>' +
995
+ '</m:QueryParameters>';
996
+
997
+ self.actionCallback = callback;
998
+
999
+ self.sendSOAPRequest(action, actionData, {
1000
+ callback: function(soapRequest, soapResponse){
1001
+ self.getObjectFromResponse(action, soapRequest, soapResponse, self.actionCallback);
1002
+ }
1003
+ });
1004
+ };
1005
+
1006
+ node.getListOfVirtualLists = function(startindex, callback) {
1007
+ var self = this;
1008
+ var action = 'GetListOfVirtualLists';
1009
+ var actionData = '<m:QueryParameters>' +
1010
+ '<m:Range startIndex="' + startindex + '" maxItems="5"/>' +
1011
+ '</m:QueryParameters>';
1012
+
1013
+ self.actionCallback = callback;
1014
+
1015
+ self.sendSOAPRequest(action, actionData, {
1016
+ callback: function(soapRequest, soapResponse){
1017
+ self.getObjectFromResponse(action, soapRequest, soapResponse, self.actionCallback);
1018
+ }
1019
+ });
1020
+ };
1021
+
1022
+ node.getVolumes = function(startindex, callback) {
1023
+ var self = this;
1024
+ var action = 'GetVolumes';
1025
+ var actionData = '<m:QueryParameters>' +
1026
+ '<m:Range startIndex="' + startindex + '" maxItems="5"/>' +
1027
+ '</m:QueryParameters>';
1028
+
1029
+ self.actionCallback = callback;
1030
+
1031
+ self.sendSOAPRequest(action, actionData, {
1032
+ callback: function(soapRequest, soapResponse){
1033
+ self.getObjectFromResponse(action, soapRequest, soapResponse, self.actionCallback);
1034
+ }
1035
+ });
1036
+ };
1037
+
1038
+ node.getListOfChannelLists = function(startindex, callback) {
1039
+ var self = this;
1040
+ var action = 'GetListOfChannelLists';
1041
+ var actionData = '<m:QueryParameters>' +
1042
+ '<m:Range startIndex="' + startindex + '" maxItems="5"/>' +
1043
+ '</m:QueryParameters>' +
1044
+ '<m:AdditionalParameters>' +
1045
+ '<m:Properties isActiveList="0"/>' +
1046
+ '</m:AdditionalParameters>';
1047
+
1048
+ self.actionCallback = callback;
1049
+
1050
+ self.sendSOAPRequest(action, actionData, {
1051
+ callback: function(soapRequest, soapResponse){
1052
+ self.getObjectFromResponse(action, soapRequest, soapResponse, self.actionCallback);
1053
+ }
1054
+ });
1055
+ };
1056
+
1057
+ node.getChannelList = function(startindex, callback) {
1058
+ var self = this;
1059
+ var action = 'GetChannelList';
1060
+ var actionData = '<ChannelListView>fastscansl7f33a470-7d6e-4b60-a103-f7739be9484d</ChannelListView>' +
1061
+ '<QueryParameters>' +
1062
+ '<Range startIndex="' + startindex + '" maxItems="1"/>' +
1063
+ '<OrderField field="userChannelNumber" type="ascending"/>' +
1064
+ '</QueryParameters>';
1065
+
1066
+ self.actionCallback = callback;
1067
+
1068
+ self.sendSOAPRequest(action, actionData, {
1069
+ callback: function(soapRequest, soapResponse){
1070
+ self.getObjectFromResponse(action, soapRequest, soapResponse, self.actionCallback);
1071
+ }
1072
+ });
1073
+ };
1074
+
1075
+ node.createIterator = function(callback) {
1076
+ var self = this;
1077
+ var action = 'CreateIterator';
1078
+ var actionData = '<TableName>de.loewe.sl2.volume.table.main</TableName>' +
1079
+ '<Type>0</Type>' +
1080
+ '<Selections>' +
1081
+ '<Selection>' +
1082
+ '<Field>4</Field>' +
1083
+ '<Condition>7</Condition>' +
1084
+ '<Value>1052708</Value>' +
1085
+ '</Selection>' +
1086
+ '</Selections>' +
1087
+ '<Fields>' +
1088
+ '<Field>0</Field>' +
1089
+ '<Field>1</Field>' +
1090
+ '</Fields>' +
1091
+ '<Orders>' +
1092
+ '<Order>' +
1093
+ '<Field>1</Field>' +
1094
+ '<Direction>1</Direction>' +
1095
+ '</Order>' +
1096
+ '</Orders>' +
1097
+ '<NotifyUpdate>yes</NotifyUpdate>';
1098
+
1099
+
1100
+ self.actionCallback = callback;
1101
+
1102
+ self.sendSOAPRequest(action, actionData, {
1103
+ callback: function(soapRequest, soapResponse){
1104
+ node.debug(action);
1105
+ var regex = new RegExp("<SOAP-ENV:Body>((.|\n)*)<\/SOAP-ENV:Body>", "gm");
1106
+ var responseData = ((regex.exec(soapResponse))[1].replace(/m:|:m/gm, "")).replace(/xmlns="urn:loewe.de:RemoteTV:Tablet"/,"" );
1107
+ if (responseData !== null) {
1108
+ var options = {};
1109
+ options.async = false;
1110
+ options.trim = true;
1111
+ options.explicitArray = false;
1112
+ options.attrkey = options.attrkey || '$';
1113
+ options.charkey = options.charkey || '_';
1114
+ console.debug(responseData);
1115
+
1116
+ parseString(responseData, options, function (err, result) {
1117
+ if (err) {
1118
+ node.error('*********************** ERROR ***********************');
1119
+ node.error('error: ', action);
1120
+ node.error('err: ', err)
1121
+ node.error(responseData);
1122
+ node.error('********************* END ERROR *********************');
1123
+ }
1124
+ else {
1125
+ console.debug(result['CreateIteratorResponse']);
1126
+ self.data['Iterator'] = result['CreateIteratorResponse'];
1127
+ node.debug(action + ' Id: ' + self.data.Iterator.Id);
1128
+ }
1129
+ });
1130
+ }
1131
+ else {
1132
+ node.error('*********************** ERROR ***********************');
1133
+ node.error('SoapRequest');
1134
+ node.error(soapRequest);
1135
+ node.error('---------------------------------------------------------------');
1136
+ node.error('error: ', action);
1137
+ node.error('data: ', responseData)
1138
+ node.error('********************* END ERROR *********************');
1139
+ }
1140
+ self.actionCallback(action, responseData);
1141
+ }
1142
+ });
1143
+ };
1144
+
1145
+ node.setActionField = function(actionText, callback) {
1146
+ var self = this;
1147
+ var action = 'SetActionField';
1148
+ var actionData = '<m:InputText>' + actionText + '</m:InputText>';
1149
+ self.actionCallback = callback;
1150
+
1151
+ self.sendSOAPRequest(action, actionData, {
1152
+ callback: function(soapRequest, soapResponse){
1153
+ node.debug(action);
1154
+ node.debug(soapResponse);
1155
+
1156
+ var regex = new RegExp("<m:" + action + "Response [A-Za-z:=\".]*>(.*)<\/m:" + action + "Response>", "gm");
1157
+ var responseData = (regex.exec(soapResponse))[1];
1158
+
1159
+ if (responseData !== null) {
1160
+ node.debug(' result: ', responseData)
1161
+ }
1162
+ else {
1163
+ node.error('*********************** ERROR ***********************');
1164
+ node.error('error: ', action);
1165
+ node.error('---------------------------------------------------------------');
1166
+ node.error('SoapRequest');
1167
+ node.error(soapRequest);
1168
+ node.error('---------------------------------------------------------------');
1169
+ node.error('soapResponse');
1170
+ node.error(soapResponse);
1171
+ node.error('********************* END ERROR *********************');
1172
+ }
1173
+ self.actionCallback(action, responseData);
1174
+ }
1175
+ });
1176
+ }
1177
+
1178
+ node.getActionField = function(RequestId, callback) {
1179
+ var self = this;
1180
+ var action = 'GetActionField';
1181
+ var actionData = '<m:RequestId>' + RequestId + '</m:RequestId>';
1182
+ self.actionCallback = callback;
1183
+
1184
+ self.sendSOAPRequest(action, actionData, {
1185
+ callback: function(soapRequest, soapResponse){
1186
+ node.debug(action);
1187
+ node.debug(soapResponse);
1188
+
1189
+ var regex = new RegExp("<m:" + action + "Response [A-Za-z:=\".]*>(.*)<\/m:" + action + "Response>", "gm");
1190
+ var responseData = (regex.exec(soapResponse))[1];
1191
+
1192
+ if (responseData !== null) {
1193
+ node.debug(' result: ', responseData)
1194
+ }
1195
+ else {
1196
+ node.error('*********************** ERROR ***********************');
1197
+ node.error('error: ', action);
1198
+ node.error('---------------------------------------------------------------');
1199
+ node.error('SoapRequest');
1200
+ node.error(soapRequest);
1201
+ node.error('---------------------------------------------------------------');
1202
+ node.error('soapResponse');
1203
+ node.error(soapResponse);
1204
+ node.error('********************* END ERROR *********************');
1205
+ }
1206
+ self.actionCallback(action, responseData);
1207
+ }
1208
+ });
1209
+ }
1210
+
1211
+ node.injectRCKey = function(key, callback) {
1212
+ var self = this;
1213
+ var action = 'InjectRCKey';
1214
+ var actionData = '<InputEventSequence>' +
1215
+ '<RCKeyEvent alphabet="l2700" value="' + key + '" mode="press"/>' +
1216
+ '<RCKeyEvent alphabet="l2700" value="' + key + '" mode="release"/>' +
1217
+ '</InputEventSequence>';
1218
+ self.actionCallback = callback;
1219
+
1220
+ self.sendSOAPRequest(action, actionData, {
1221
+ callback: function(soapRequest, soapResponse){
1222
+ node.debug(soapResponse);
1223
+ node.debug(action);
1224
+ var regex = new RegExp("<m:" + action + "Response [A-Za-z:=\".]*>(.*)<\/m:" + action + "Response>", "gm");
1225
+ var responseData = (regex.exec(soapResponse))[1];
1226
+ if (responseData !== null) {
1227
+ node.debug(' result: ', responseData)
1228
+ }
1229
+ else {
1230
+ node.error('*********************** ERROR ***********************');
1231
+ node.error('error: ', action);
1232
+ node.error('---------------------------------------------------------------');
1233
+ node.error('SoapRequest');
1234
+ node.error(soapRequest);
1235
+ node.error('---------------------------------------------------------------');
1236
+ node.error('soapResponse');
1237
+ node.error(soapResponse);
1238
+ node.error('********************* END ERROR *********************');
1239
+ }
1240
+ self.actionCallback(action, soapResponse);
1241
+ }
1242
+ });
1243
+ }
1244
+
1245
+ node.activateFeaturePackage = function(featurePackageData, callback) {
1246
+ var self = this;
1247
+ var action = 'ActivateFeaturePackage';
1248
+ var actionData = '<m:Package>' + featurePackageData.Package + '</m:Package>';
1249
+ if ( featurePackageData.ActivationCode !== undefined & featurePackageData.ActivationCode !== '') {
1250
+ actionData += '<m:ActivationCode>' + featurePackageData.ActivationCode + '</m:ActivationCode>';
1251
+ }
1252
+
1253
+ self.actionCallback = callback;
1254
+
1255
+ self.sendSOAPRequest(action, actionData, {
1256
+ callback: function(soapRequest, soapResponse){
1257
+ var match = /<m:ActivateFeaturePackageResponse [A-Za-z:=\".]*>((.|\n)*)<\/m:ActivateFeaturePackageResponse>/gm.exec(soapResponse);
1258
+ if(match !== null) {
1259
+ var result = (/<m:Result>(.*)<\/m:Result>/gm.exec(soapResponse))[1];
1260
+ node.debug('FeaturePackage ' + featurePackageData.Package + ' ' + result + ' activated');
1261
+ }
1262
+ else {
1263
+ node.error('*********************** ERROR ***********************');
1264
+ node.error('activating Feature ' + featurePackageData);
1265
+ node.error('---------------------------------------------------------------');
1266
+ node.error('SoapRequest');
1267
+ node.error(soapRequest);
1268
+ node.error('---------------------------------------------------------------');
1269
+ node.error('soapResponse');
1270
+ node.error(soapResponse);
1271
+ node.error('********************* END ERROR *********************');
1272
+ }
1273
+ self.actionCallback(action, soapResponse);
1274
+ }
1275
+ });
1276
+ };
1277
+
1278
+ /**
1279
+ * Get ClientId from TV
1280
+ *
1281
+ * @param {Function} callback
1282
+ */
1283
+ node.requestAccess = function(callback) {
1284
+ var self = this;
1285
+ var action = 'RequestAccess';
1286
+ var actionData = '<DeviceType>----------------</DeviceType>';
1287
+
1288
+ this.actionCallback = callback;
1289
+
1290
+ this.sendSOAPRequest(action, actionData, {
1291
+ callback: function(soapRequest, soapResponse){
1292
+ var clientId = (/<m:ClientId>(.*)<\/m:ClientId>/gm.exec(soapResponse))[1];
1293
+ var accessStatus = 'undefined';
1294
+ node.debug(soapResponse);
1295
+ if(clientId !== null) {
1296
+ accessStatus = (/<m:AccessStatus>(.*)<\/m:AccessStatus>/gm.exec(soapResponse))[1];
1297
+ self.ClientId = clientId;
1298
+ node.debug('Access ClientId: ' + clientId);
1299
+ node.debug('Access Status: ' + accessStatus);
1300
+ }
1301
+ else {
1302
+ node.error('*********************** ERROR ***********************');
1303
+ node.error('error: ', actionData);
1304
+ node.error('---------------------------------------------------------------');
1305
+ node.error('SoapRequest');
1306
+ node.error(soapRequest);
1307
+ node.error('---------------------------------------------------------------');
1308
+ node.error('soapResponse');
1309
+ node.error(soapResponse);
1310
+ node.error('********************* END ERROR *********************');
1311
+ }
1312
+ self.actionCallback(action, soapResponse);
1313
+ }
1314
+ });
1315
+ };
1316
+
1317
+ node.getFeature = function(featureName, callback) {
1318
+ var self = this;
1319
+ var action = 'GetFeature';
1320
+ var actionData = '<m:Name>' + featureName + '</m:Name>';
1321
+
1322
+ self.actionCallback = callback;
1323
+
1324
+ self.sendSOAPRequest(action, actionData, {
1325
+ callback: function(soapRequest, soapResponse){
1326
+ self.getObjectFromResponse(action, soapRequest, soapResponse, self.actionCallback);
1327
+ }
1328
+ });
1329
+ };
1330
+
1331
+ this.onSDDP = node.onSDDP();
1332
+
1333
+ node.status({fill:"red",shape:"ring",text:node.data.CurrentStatus.Power});
1334
+ node.onEvent('alive');
1335
+ }
1336
+ RED.nodes.registerType("LOEWE-TV", LoeweTvNode);
1337
+ };