c4cfd4e9f9a7de55a5f801a71dfaf98131f32164
[profile/ivi/Modello_Common.git] / js / services / carIndicator.js
1 /**
2  * @module Services
3  */
4
5 /**
6  * Class provides AMB related functionality utilizing `tizen.vehicle` API for signals used in HTML applications. This component is usually initialized by {{#crossLink "Bootstrap"}}{{/crossLink}} class
7  * and can be later accessed using {{#crossLink "Bootstrap/carIndicator:property"}}{{/crossLink}} property. Signals recognized by this class needs to be registered in property
8  * {{#crossLink "CarIndicator/_mappingTable:property"}}{{/crossLink}}.
9  *
10  * To attach and detach to particular property register new callback object using {{#crossLink "Bootstrap/carIndicator:addListener"}}{{/crossLink}} method, e.g.:
11  *
12  *     var listenerId = bootstrap.carIndicator.addListener({
13  *        onSteeringWheelAngleChanged: function(newValue){
14  *           // Process new value
15  *        },
16  *        onWheelBrakeChanged : function(newValue){
17  *           // Process new value
18  *        }
19  *     });
20  *
21  *     // Unregister listener
22  *     bootstrap.carIndicator.removeListener(listenerId);
23  *
24  * Currently following signals are recognized:
25  *
26  * * SteeringWheelAngle
27  *   * SteeringWheelAngle
28  * * WheelBrake
29  *   * Engaged
30  * * TirePressure
31  *   * leftFront
32  *   * rightFront
33  *   * leftRear
34  *   * rightRear
35  * * DoorStatus
36  *   * ChildLockStatus
37  * * WindowStatus
38  *   * FrontDefrost
39  *   * RearDefrost
40  * * HVAC
41  *   * FanSpeed
42  *   * TargetTemperatureRight
43  *   * TargetTemperatureLeft
44  *   * SeatHeaterRight
45  *   * SeatHeaterLeft
46  *   * AirConditioning
47  *   * AirRecirculation
48  *   * AirflowDirection
49  * * LightStatus
50  *   * Hazard
51  *   * Head
52  *   * Parking
53  * * BatteryStatus
54  * * FullBatteryRange
55  * * ExteriorTemperature
56  *   * Exterior
57  * * InteriorTemperature
58  *   * Interior
59  * * WheelInformation
60  *   * FrontWheelRadius
61  * * AvgKW
62  *   * AvgKW
63  * * VehicleSpeed
64  * * Odometer
65  * * Transmission
66  *   * ShiftPosition
67  * * ExteriorBrightness
68  * * NightMode
69  * * DirectionIndicationINST
70  * * DirectionIndicationMS
71  * * ACCommand
72  * * RecircReq
73  * * FrontTSetRightCmd
74  * * FrontTSetLeftCmd
75  * * FrontBlwrSpeedCmd
76  * * HeatedSeatFRModeRequest
77  * * HeatedSeatFRRequest
78  * * HeatedSeatFLModeRequest
79  * * HeatedSeatFLRequest
80  * * FLHSDistrCmd
81  * * FRHSDistrCmd
82  *
83  * @class CarIndicator
84  * @constructor
85  */
86 var CarIndicator = function() {
87         "use strict";
88         console.info("Starting up service CarIndicator");
89 };
90
91 function parseInteger(value) {
92         "use strict";
93         return parseInt(value, 10);
94 }
95
96 function parseTirePressure(value) {
97         "use strict";
98         var floatValue = parseFloat(value).toFixed(2);
99         if (floatValue > 180 && floatValue < 220) {
100                 floatValue = "OK";
101         }
102         return floatValue;
103 }
104
105 /**
106  * Array of registered listeners
107  * @type Object
108  * @property _listeners
109  * @private
110  */
111 CarIndicator.prototype._listeners = {};
112
113 /**
114  * Array of registered listener IDs.
115  * @type Array
116  * @property _listenerIDs
117  * @private
118  */
119 CarIndicator.prototype._listenerIDs = [];
120
121 /**
122  * Signal mapping table.
123  * Each entry should form an object
124  * @property _mappingTable
125  * @private
126  * @type Object
127  */
128 CarIndicator.prototype._mappingTable = {
129         /*
130         ZONE_None   = 000000;
131         ZONE_Front  = 000001;
132         ZONE_Middle = 000010;
133         ZONE_Right  = 000100;
134         ZONE_Left   = 001000;
135         ZONE_Rear   = 010000;
136         ZONE_Center = 100000;
137         */
138         /* this is for steeringWheel game controler */
139         "SteeringWheelAngle" : {
140                 propertyName : "SteeringWheelAngle",
141                 callBackPropertyName : "SteeringWheelAngle",
142                 subscribeName : "SteeringWheelAngle",
143                 conversionFunction : function(value) {
144                         "use strict";
145                         value = parseInt(value, 10);
146                         var returnValue = 0;
147                         if (value <= 180 && value > 0) {
148                                 returnValue = (1 * (value / 6)) - 30;
149                         } else if (value <= 360 && value > 180) {
150                                 returnValue = ((value - 179) / 6);
151                         } else if (value === 0) {
152                                 returnValue = -30;
153                         }
154                         return returnValue;
155                 },
156                 zone : "000000"
157
158         },
159         "WheelBrake" : {
160                 propertyName : "Engaged",
161                 callBackPropertyName : "WheelBrake",
162                 subscribeName : "WheelBrake",
163                 zone : "000000"
164         },
165         /* end steeringWheel game controler*/
166         "TirePressureLeftFront" : {
167                 propertyName : "leftFront",
168                 callBackPropertyName : "tirePressureLeftFront",
169                 subscribeName : "TirePressure",
170                 conversionFunction : parseTirePressure,
171                 zone : "000000"
172         },
173         "TirePressureRightFront" : {
174                 propertyName : "rightFront",
175                 callBackPropertyName : "tirePressureRightFront",
176                 subscribeName : "TirePressure",
177                 conversionFunction : parseTirePressure,
178                 zone : "000000"
179         },
180         "TirePressureLeftRear" : {
181                 propertyName : "leftRear",
182                 callBackPropertyName : "tirePressureLeftRear",
183                 subscribeName : "TirePressure",
184                 conversionFunction : parseTirePressure,
185                 zone : "000000"
186         },
187         "TirePressureRightRear" : {
188                 propertyName : "rightRear",
189                 callBackPropertyName : "tirePressureRightRear",
190                 subscribeName : "TirePressure",
191                 conversionFunction : parseTirePressure,
192                 zone : "000000"
193         },
194         "ChildLock" : {
195                 propertyName : "ChildLockStatus",
196                 callBackPropertyName : "childLock",
197                 subscribeName : "DoorStatus",
198                 zone : "000000"
199         },
200         "FrontDefrost" : {
201                 propertyName : "Defrost",
202                 callBackPropertyName : "frontDefrost",
203                 subscribeName : "WindowStatus",
204                 zone : "000001"
205         },
206         "RearDefrost" : {
207                 propertyName : "Defrost",
208                 callBackPropertyName : "rearDefrost",
209                 subscribeName : "WindowStatus",
210                 zone : "010000"
211         },
212         "FanSpeed" : {
213                 propertyName : "FanSpeed",
214                 callBackPropertyName : "fanSpeed",
215                 subscribeName : "HVAC",
216                 conversionFunction : parseInteger,
217                 zone : "000000"
218         },
219         "TargetTemperatureRight" : {
220                 propertyName : "TargetTemperature",
221                 callBackPropertyName : "targetTemperatureRight",
222                 subscribeName : "HVAC",
223                 conversionFunction : parseInteger,
224                 zone : "000100"
225         },
226         "TargetTemperatureLeft" : {
227                 propertyName : "TargetTemperature",
228                 callBackPropertyName : "targetTemperatureLeft",
229                 subscribeName : "HVAC",
230                 conversionFunction : parseInteger,
231                 zone : "001000"
232         },
233         "Hazard" : {
234                 propertyName : "Hazard",
235                 callBackPropertyName : "hazard",
236                 subscribeName : "LightStatus",
237                 zone : "000000"
238         },
239         "Head" : {
240                 propertyName : "Head",
241                 callBackPropertyName : "frontLights",
242                 subscribeName : "LightStatus",
243                 zone : "000000"
244         },
245         "SeatHeaterRight" : {
246                 propertyName : "SeatHeater",
247                 callBackPropertyName : "seatHeaterRight",
248                 subscribeName : "HVAC",
249                 zone : "000101"
250         },
251         "SeatHeaterLeft" : {
252                 propertyName : "SeatHeater",
253                 callBackPropertyName : "seatHeaterLeft",
254                 subscribeName : "HVAC",
255                 zone : "001001"
256         },
257         "Parking" : {
258                 propertyName : "Parking",
259                 callBackPropertyName : "rearLights",
260                 subscribeName : "LightStatus",
261                 zone : "000000"
262         },
263         "AirConditioning" : {
264                 propertyName : "AirConditioning",
265                 callBackPropertyName : "fan",
266                 subscribeName : "HVAC",
267                 zone : "000000"
268         },
269         "AirRecirculation" : {
270                 propertyName : "AirRecirculation",
271                 callBackPropertyName : "airRecirculation",
272                 subscribeName : "HVAC",
273                 zone : "000000"
274         },
275         "AirflowDirection" : {
276                 propertyName : "AirflowDirection",
277                 callBackPropertyName : "airflowDirection",
278                 subscribeName : "HVAC",
279                 conversionFunction : parseInteger,
280                 zone : "000000"
281         },
282         "BatteryStatus" : {
283                 propertyName : "BatteryStatus",
284                 callBackPropertyName : "batteryStatus",
285                 conversionFunction : parseInteger,
286                 zone : "000000"
287         },
288         "FullBatteryRange" : {
289                 propertyName : "FullBatteryRange",
290                 callBackPropertyName : "fullBatteryRange",
291                 conversionFunction : parseInteger,
292                 zone : "000000"
293         },
294         "Exterior" : {
295                 propertyName : "Exterior",
296                 callBackPropertyName : "outsideTemp",
297                 subscribeName : "ExteriorTemperature",
298                 conversionFunction : parseInteger,
299                 zone : "000000"
300         },
301         "Interior" : {
302                 propertyName : "Interior",
303                 callBackPropertyName : "insideTemp",
304                 subscribeName : "InteriorTemperature",
305                 conversionFunction : parseInteger,
306                 zone : "000000"
307         },
308         "WheelAngle" : {
309                 propertyName : "FrontWheelRadius",
310                 callBackPropertyName : "wheelAngle",
311                 subscribeName : "WheelInformation",
312                 conversionFunction : parseInteger,
313                 zone : "000000"
314         },
315         "Weather" : {
316                 propertyName : "Weather",
317                 callBackPropertyName : "weather",
318                 conversionFunction : parseInteger,
319                 zone : "000000"
320         },
321         "AvgKW" : {
322                 propertyName : "AvgKW",
323                 callBackPropertyName : "avgKW",
324                 subscribeName : "AvgKW",
325                 conversionFunction : function(newValue) {
326                         "use strict";
327                         return parseFloat(newValue).toFixed(2);
328                 },
329                 zone : "000000"
330         },
331         "VehicleSpeed" : {
332                 propertyName : "VehicleSpeed",
333                 callBackPropertyName : "speed",
334                 conversionFunction : parseInteger,
335                 zone : "000000"
336         },
337         "Odometer" : {
338                 propertyName : "Odometer",
339                 callBackPropertyName : "odoMeter",
340                 conversionFunction : parseInteger,
341                 zone : "000000"
342         },
343         "TransmissionShiftPosition" : {
344                 propertyName : "ShiftPosition",
345                 callBackPropertyName : "gear",
346                 conversionFunction : function(value) {
347                         "use strict";
348                         switch (value) {
349                         case 0:
350                                 value = "N";
351                                 break;
352                         case 64:
353                                 value = "C";
354                                 break;
355                         case 96:
356                                 value = "D";
357                                 break;
358                         case 128:
359                                 value = "R";
360                                 break;
361                         case 255:
362                                 value = "P";
363                                 break;
364                         }
365                         return value;
366                 },
367                 subscribeName : "Transmission",
368                 zone : "000000"
369         },
370         "Randomize" : {
371                 propertyName : "Randomize",
372                 callBackPropertyName : "randomize",
373                 subscribeName : "Randomize",
374                 zone : "000000"
375         },
376         "ExteriorBrightness" : {
377                 propertyName : "ExteriorBrightness",
378                 callBackPropertyName : "exteriorBrightness",
379                 zone : "000000"
380         },
381         "NightMode" : {
382                 propertyName : "NightMode",
383                 callBackPropertyName : "nightMode",
384                 zone : "000000"
385         },
386         "DirectionIndicationINST" : {
387                 propertyName : "DirectionIndicationINST",
388                 callBackPropertyName : "DirectionIndicationINST",
389                 subscribeName : "DirectionIndicationINST",
390                 zone : "000000"
391         },
392         "DirectionIndicationMS" : {
393                 propertyName : "DirectionIndicationMS",
394                 callBackPropertyName : "DirectionIndicationMS",
395                 subscribeName : "DirectionIndicationMS",
396                 zone : "000000"
397         },
398         "ACCommand" : {
399                 propertyName : "ACCommand",
400                 callBackPropertyName : "ACCommand",
401                 subscribeName : "ACCommand",
402                 zone : "000000"
403         },
404         "RecircReq" : {
405                 propertyName : "RecircReq",
406                 callBackPropertyName : "RecircReq",
407                 subscribeName : "RecircReq",
408                 zone : "000000"
409         },
410         "FrontTSetRightCmd" : {
411                 propertyName : "FrontTSetRightCmd",
412                 callBackPropertyName : "FrontTSetRightCmd",
413                 subscribeName : "FrontTSetRightCmd",
414                 zone : "000000"
415         },
416         "FrontTSetLeftCmd" : {
417                 propertyName : "FrontTSetLeftCmd",
418                 callBackPropertyName : "FrontTSetLeftCmd",
419                 subscribeName : "FrontTSetLeftCmd",
420                 zone : "000000"
421         },
422         "FrontBlwrSpeedCmd" : {
423                 propertyName : "FrontBlwrSpeedCmd",
424                 callBackPropertyName : "FrontBlwrSpeedCmd",
425                 subscribeName : "FrontBlwrSpeedCmd",
426                 zone : "000000"
427         },
428         "HeatedSeatFRModeRequest" : {
429                 propertyName : "HeatedSeatFRModeRequest",
430                 callBackPropertyName : "HeatedSeatFRModeRequest",
431                 subscribeName : "HeatedSeatFRModeRequest",
432                 zone : "000000"
433         },
434         "HeatedSeatFRRequest" : {
435                 propertyName : "HeatedSeatFRRequest",
436                 callBackPropertyName : "HeatedSeatFRRequest",
437                 subscribeName : "HeatedSeatFRRequest",
438                 zone : "000000"
439         },
440         "HeatedSeatFLModeRequest" : {
441                 propertyName : "HeatedSeatFLModeRequest",
442                 callBackPropertyName : "HeatedSeatFLModeRequest",
443                 subscribeName : "HeatedSeatFLModeRequest",
444                 zone : "000000"
445         },
446         "HeatedSeatFLRequest" : {
447                 propertyName : "HeatedSeatFLRequest",
448                 callBackPropertyName : "HeatedSeatFLRequest",
449                 subscribeName : "HeatedSeatFLRequest",
450                 zone : "000000"
451         },
452         "FLHSDistrCmd" : {
453                 propertyName : "FLHSDistrCmd",
454                 callBackPropertyName : "FLHSDistrCmd",
455                 subscribeName : "FLHSDistrCmd",
456                 zone : "000000"
457         },
458         "FRHSDistrCmd" : {
459                 propertyName : "FRHSDistrCmd",
460                 callBackPropertyName : "FRHSDistrCmd",
461                 subscribeName : "FRHSDistrCmd",
462                 zone : "000000"
463         }
464 };
465
466 /**
467  * This method adds listener object for car events. Object should define function callbacks taking signal names from mapping table, e.g.:
468  * @example
469  *     {
470  *        onBatteryChange: function(newValue, oldValue) {}
471  *     }
472  * Methods are called back with new and last known values.
473  * @method addListener
474  * @param callback {Object} object with callback functions.
475  * @return {Integer} WatchID for later removal of listener.
476  */
477 CarIndicator.prototype.addListener = function(aCallbackObject) {
478         "use strict";
479         var id = Math.floor(Math.random() * 1000000);
480         var self = this;
481         this._listeners[id] = aCallbackObject;
482         this._listenerIDs.push(id);
483
484         var subscribeCallback = function(data) {
485                 self.onDataUpdate(data, self);
486         };
487         for ( var i in aCallbackObject) {
488                 if (aCallbackObject.hasOwnProperty(i)) {
489                         var prop = i.replace("on", "").replace("Changed", "");
490
491                         for ( var signal in this._mappingTable) {
492                                 if (this._mappingTable.hasOwnProperty(signal)) {
493                                         var mapping = this._mappingTable[signal];
494                                         var zone = parseInt(mapping.zone, 2);
495                                         var subscribeName = signal;
496
497                                         if (mapping.subscribeName !== undefined) {
498                                                 subscribeName = mapping.subscribeName;
499                                         }
500
501                                         if (mapping.callBackPropertyName.toLowerCase() === prop.toLowerCase() && !mapping.subscribeCount) {
502                                                 mapping.subscribeCount = typeof (mapping.subscribeCount) === 'undefined' ? 0 : mapping.subscribeCount++;
503
504                                                 if (typeof (tizen) !== 'undefined') {
505                                                         if (!(subscribeName.toString().trim().toLowerCase() === "nightmode" && id === this._listenerIDs[0])) {
506                                                                 var setUpData = tizen.vehicle.get(subscribeName, zone);
507                                                                 self.onDataUpdate(setUpData, self, id);
508                                                         }
509
510                                                         tizen.vehicle.subscribe(subscribeName, subscribeCallback, zone);
511                                                 } else {
512                                                         console.warn("Tizen API is not available, cannot subscribe to signal", signal);
513                                                 }
514                                         }
515                                 }
516                         }
517                 }
518         }
519
520         return id;
521 };
522 /**
523  * This method is call as callback if data oon tizen.vehicle was change onDataUpdate
524  * @method onDataUpdate
525  * @param data {object} object whit new data.
526  * @param self {object} this carIndicator Object.
527  * @param lisenersID {int} id of listener.
528  */
529 CarIndicator.prototype.onDataUpdate = function(data, self, lisenersID) {
530         "use strict";
531         if (data !== undefined) {
532                 var zone = data.zone.toString(2);
533                 var mapping;
534
535                 for ( var property in data) {
536                         if (data.hasOwnProperty(property)) {
537                                 mapping = undefined;
538                                 if (property !== "time" && property !== "zone" && property.search("Sequence") === -1) {
539                                         for ( var element in self._mappingTable) {
540                                                 if (self._mappingTable.hasOwnProperty(element)) {
541                                                         if (self._mappingTable[element].propertyName.toLowerCase() === property.toLowerCase()) {
542                                                                 /* jshint bitwise: false */
543                                                                 if (!(zone ^ self._mappingTable[element].zone)) {
544                                                                         /* jshint bitwise: true */
545                                                                         mapping = self._mappingTable[element];
546                                                                         break;
547                                                                 }
548                                                         }
549                                                 }
550                                         }
551
552                                         if (typeof (mapping) !== 'undefined') {
553                                                 var value = data[property];
554                                                 value = mapping.conversionFunction ? mapping.conversionFunction(value) : value;
555
556                                                 var oldValue = self.status[mapping.callBackPropertyName];
557                                                 if (oldValue !== value || property.toUpperCase() === "nightMode".toUpperCase()) {
558                                                         console.info("AMB property '" + property + "' has changed to new value:" + value);
559                                                         self.status[mapping.callBackPropertyName] = value;
560
561                                                         var callbackName = "on" + mapping.callBackPropertyName[0].toUpperCase() + mapping.callBackPropertyName.substring(1) + "Changed";
562                                                         var listener;
563
564                                                         if (lisenersID !== undefined) {
565                                                                 listener = self._listeners[lisenersID];
566
567                                                                 if (typeof (listener[callbackName]) === 'function') {
568                                                                         try {
569                                                                                 listener[callbackName](value, oldValue);
570                                                                         } catch (ex) {
571                                                                                 console.error("Error occured during executing listener", ex);
572                                                                         }
573                                                                 }
574                                                         } else {
575                                                                 for ( var i in self._listeners) {
576                                                                         if (self._listeners.hasOwnProperty(i)) {
577                                                                                 listener = self._listeners[i];
578
579                                                                                 if (typeof (listener[callbackName]) === 'function') {
580                                                                                         try {
581                                                                                                 listener[callbackName](value, oldValue);
582                                                                                         } catch (ex) {
583                                                                                                 console.error("Error occured during executing listener", ex);
584                                                                                         }
585                                                                                 }
586                                                                         }
587                                                                 }
588                                                         }
589                                                 }
590
591                                         } else {
592                                                 console.warn("Mapping for property '" + property + "' is not defined");
593                                         }
594                                 }
595                         }
596                 }
597         }
598 };
599
600 /**
601  * This method removes previosly added listener object. Use WatchID returned from addListener method.
602  * @method removeListener
603  * @param aId {Integer} WatchID.
604  */
605 CarIndicator.prototype.removeListener = function(aId) {
606         "use strict";
607         var listener = this._listeners[aId];
608
609         for ( var i in listener) {
610                 if (listener.hasOwnProperty(i)) {
611                         var prop = i.replace("on", "").replace("Changed", "");
612
613                         for ( var signal in this._mappingTable) {
614                                 if (this._mappingTable.hasOwnProperty(signal)) {
615                                         var mapping = this._mappingTable[signal];
616
617                                         if (mapping.subscribeCount === 0) { // Last signal, unscubscribe
618                                                 tizen.vehicle.unsubscribe(signal);
619                                                 mapping.subscribeCount = undefined;
620                                         } else if (typeof (mapping.subscribeCount) !== 'undefined') {
621                                                 mapping.subscribeCount--;
622                                         }
623                                 }
624                         }
625                 }
626         }
627
628         this._listeners[aId] = undefined;
629 };
630
631 /**
632  * status object
633  * @property status
634  * @type Object
635  * @private
636  */
637 CarIndicator.prototype.status = {
638         fanSpeed : 0,
639         targetTemperatureRight : 0,
640         targetTemperatureLeft : 0,
641         hazard : false,
642         frontDefrost : false,
643         rearDefrost : false,
644         frontLeftwhell : "",
645         frontRightwhell : "",
646         rearLeftwhell : "",
647         rearRightwhell : "",
648         childLock : false,
649         frontLights : false,
650         rearLights : false,
651         fan : false,
652         seatHeaterRight : 0,
653         seatHeaterLeft : 0,
654         airRecirculation : false,
655         airflowDirection : 0,
656         batteryStatus : 58,
657         fullBatteryRange : 350,
658         outsideTemp : 74.2,
659         insideTemp : 68.2,
660         wheelAngle : 0,
661         weather : 1,
662         avgKW : 0.28,
663         speed : 65,
664         odoMeter : 75126,
665         gear : "D",
666         nightMode : false,
667         randomize : false,
668         exteriorBrightness : 1000
669 };
670
671 /**
672  * This method return status object in callback
673  * @method getStatus
674  * @param callback {function} callback function.
675  */
676 CarIndicator.prototype.getStatus = function(callback) {
677         "use strict";
678         callback(this.status);
679 };
680
681 /**
682  * this method set status for property in tizen.vehicle and status object
683  * @method setStatus
684  * @param indicator {string} indicator name.
685  * @param status {??} ??.
686  * @param text_status {string} new status .
687  * @param callback {function} callback function.
688  */
689 CarIndicator.prototype.setStatus = function(indicator, newValue, callback, zone) {
690         "use strict";
691         var mappingElement, mappingProperty;
692         for ( var element in this._mappingTable) {
693                 if (this._mappingTable.hasOwnProperty(element)) {
694                         mappingProperty = undefined;
695                         if (this._mappingTable[element].callBackPropertyName.toLowerCase() === indicator.toLowerCase()) {
696                                 mappingElement = this._mappingTable[element];
697                                 mappingProperty = this._mappingTable[element].propertyName;
698                                 break;
699                         }
700                 }
701         }
702
703         // this.status[indicator] = status === "true";
704         if (mappingProperty !== undefined) {
705                 var objectName = mappingElement.subscribeName;
706                 var propertyZone = parseInt(mappingElement.zone, 2);
707                 var propertyValue = {};
708                 propertyValue[mappingProperty] = newValue;
709                 propertyValue.zone = propertyZone;
710
711                 tizen.vehicle.set(objectName, propertyValue, function(msg) {
712                         console.error("Set error: " + msg);
713                 });
714         }
715         if (!!callback) {
716                 callback();
717         }
718 };