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}}.
10 * To attach and detach to particular property register new callback object using {{#crossLink "Bootstrap/carIndicator:addListener"}}{{/crossLink}} method, e.g.:
12 * var listenerId = bootstrap.carIndicator.addListener({
13 * onSteeringWheelAngleChanged: function(newValue){
14 * // Process new value
16 * onWheelBrakeChanged : function(newValue){
17 * // Process new value
21 * // Unregister listener
22 * bootstrap.carIndicator.removeListener(listenerId);
24 * Currently following signals are recognized:
26 * * SteeringWheelAngle
27 * * SteeringWheelAngle
42 * * TargetTemperatureRight
43 * * TargetTemperatureLeft
55 * * ExteriorTemperature
57 * * InteriorTemperature
67 * * ExteriorBrightness
69 * * DirectionIndicationINST
70 * * DirectionIndicationMS
76 * * HeatedSeatFRModeRequest
77 * * HeatedSeatFRRequest
78 * * HeatedSeatFLModeRequest
79 * * HeatedSeatFLRequest
86 var CarIndicator = function() {
88 console.info("Starting up service CarIndicator");
91 if (typeof Zone !== 'function')
93 window.Zone = function(){return undefined;};
96 function parseInteger(value) {
98 return parseInt(value, 10);
101 function parseTirePressure(value) {
103 var floatValue = parseFloat(value).toFixed(2);
104 if (floatValue > 180 && floatValue < 220) {
111 * Array of registered listeners
113 * @property _listeners
116 CarIndicator.prototype._listeners = {};
119 * Array of registered listener IDs.
121 * @property _listenerIDs
124 CarIndicator.prototype._listenerIDs = [];
127 * Signal mapping table.
128 * Each entry should form an object
129 * @property _mappingTable
133 CarIndicator.prototype._mappingTable = {
137 ZONE_Middle = 000010;
141 ZONE_Center = 100000;
143 /* this is for steeringWheel game controler */
144 "SteeringWheelAngle" : {
145 attributeName : "steeringWheelAngle",
146 callBackPropertyName : "SteeringWheelAngle",
147 interfaceName : "steeringWheel",
148 conversionFunction : function(value) {
150 value = parseInt(value, 10);
152 if (value <= 180 && value > 0) {
153 returnValue = (1 * (value / 6)) - 30;
154 } else if (value <= 360 && value > 180) {
155 returnValue = ((value - 179) / 6);
156 } else if (value === 0) {
163 attributeName : "engaged",
164 callBackPropertyName : "WheelBrake",
165 interfaceName : "brakeOperation"
167 /* end steeringWheel game controler*/
168 "TirePressureLeftFront" : {
169 attributeName : "leftFront",
170 callBackPropertyName : "tirePressureLeftFront",
171 interfaceName : "tire",
172 conversionFunction : parseTirePressure,
173 zone : new Zone(["Front","Left"])
175 "TirePressureRightFront" : {
176 attributeName : "rightFront",
177 callBackPropertyName : "tirePressureRightFront",
178 interfaceName : "tire",
179 conversionFunction : parseTirePressure,
180 zone : new Zone(["Front","Right"])
182 "TirePressureLeftRear" : {
183 attributeName : "leftRear",
184 callBackPropertyName : "tirePressureLeftRear",
185 interfaceName : "tire",
186 conversionFunction : parseTirePressure,
187 zone : new Zone(["Rear","Left"])
189 "TirePressureRightRear" : {
190 attributeName : "rightRear",
191 callBackPropertyName : "tirePressureRightRear",
192 interfaceName : "tire",
193 conversionFunction : parseTirePressure,
194 zone : new Zone(["Rear","Right"])
197 attributeName : "childLock",
198 callBackPropertyName : "childLock",
199 interfaceName : "childSafetyLock"
202 attributeName : "defrostWindow",
203 callBackPropertyName : "frontDefrost",
204 interfaceName : "defrost",
205 zone : new Zone(["Front"])
208 attributeName : "defrostWindow",
209 callBackPropertyName : "rearDefrost",
210 interfaceName : "defrost",
211 zone : new Zone(["Rear"])
214 attributeName : "fanSpeed",
215 callBackPropertyName : "fanSpeed",
216 interfaceName : "climateControl",
217 conversionFunction : parseInteger
219 "TargetTemperatureRight" : {
220 attributeName : "targetTemperature",
221 callBackPropertyName : "targetTemperatureRight",
222 interfaceName : "climateControl",
223 conversionFunction : parseInteger,
224 zone : new Zone(["Right"])
226 "TargetTemperatureLeft" : {
227 attributeName : "targetTemperature",
228 callBackPropertyName : "targetTemperatureLeft",
229 interfaceName : "climateControl",
230 conversionFunction : parseInteger,
231 zone : new Zone(["Left"])
234 attributeName : "hazard",
235 callBackPropertyName : "hazard",
236 interfaceName : "lightStatus"
239 attributeName : "head",
240 callBackPropertyName : "frontLights",
241 interfaceName : "lightStatus"
243 "SeatHeaterRight" : {
244 attributeName : "seatHeater",
245 callBackPropertyName : "seatHeaterRight",
246 interfaceName : "climateControl",
247 zone : new Zone(["Right"])
250 attributeName : "seatHeater",
251 callBackPropertyName : "seatHeaterLeft",
252 interfaceName : "climateControl",
253 zone : new Zone(["Left"])
256 attributeName : "parking",
257 callBackPropertyName : "rearLights",
258 interfaceName : "lightStatus",
260 "AirConditioning" : {
261 attributeName : "airConditioning",
262 callBackPropertyName : "fan",
263 interfaceName : "climateControl"
265 "AirRecirculation" : {
266 attributeName : "airRecirculation",
267 callBackPropertyName : "airRecirculation",
268 interfaceName : "climateControl"
270 "AirflowDirection" : {
271 attributeName : "airflowDirection",
272 callBackPropertyName : "airflowDirection",
273 interfaceName : "climateControl",
274 conversionFunction : parseInteger
277 attributeName : "chargeLevel",
278 callBackPropertyName : "batteryStatus",
279 interfaceName : "batteryStatus",
280 conversionFunction : parseInteger
282 "FullBatteryRange" : {
283 attributeName : "fullBatteryRange",
284 callBackPropertyName : "fullBatteryRange",
285 conversionFunction : parseInteger
288 attributeName : "exteriorTemperature",
289 callBackPropertyName : "outsideTemp",
290 interfaceName : "temperature",
291 conversionFunction : parseInteger
294 attributeName : "interiorTemperature",
295 callBackPropertyName : "insideTemp",
296 interfaceName : "temperature",
297 conversionFunction : parseInteger
300 attributeName : "frontWheelRadius",
301 callBackPropertyName : "wheelAngle",
302 //interfaceName : "wheelConfiguration",
303 conversionFunction : parseInteger
306 attributeName : "weather",
307 callBackPropertyName : "weather",
308 conversionFunction : parseInteger
311 attributeName : "avgKW",
312 callBackPropertyName : "avgKW",
313 //interfaceName : "AvgKW",
314 conversionFunction : function(newValue) {
316 return parseFloat(newValue).toFixed(2);
320 attributeName : "vehicleSpeed",
321 callBackPropertyName : "speed",
322 interfaceName : "vehicleSpeed",
323 conversionFunction : parseInteger
326 attributeName : "odometer",
327 callBackPropertyName : "odoMeter",
328 interfaceName : "odometer",
329 conversionFunction : parseInteger
331 "TransmissionShiftPosition" : {
332 attributeName : "mode",
333 callBackPropertyName : "gear",
334 conversionFunction : function(value) {
361 interfaceName : "transmission"
364 attributeName : "randomize",
365 callBackPropertyName : "randomize",
366 interfaceName : "Randomize"
368 "ExteriorBrightness" : {
369 attributeName : "exteriorBrightness",
370 callBackPropertyName : "exteriorBrightness"
373 attributeName : "mode",
374 callBackPropertyName : "nightMode",
375 interfaceName : "nightMode"
377 "DirectionIndicationINST" : {
378 attributeName : "DirectionIndicationINST",
379 callBackPropertyName : "DirectionIndicationINST",
380 //interfaceName : "DirectionIndicationINST"
382 "DirectionIndicationMS" : {
383 attributeName : "DirectionIndicationMS",
384 callBackPropertyName : "DirectionIndicationMS",
385 //interfaceName : "DirectionIndicationMS"
388 attributeName : "ACCommand",
389 callBackPropertyName : "ACCommand",
390 //interfaceName : "ACCommand"
393 attributeName : "RecircReq",
394 callBackPropertyName : "RecircReq",
395 //interfaceName : "RecircReq"
397 "FrontTSetRightCmd" : {
398 attributeName : "FrontTSetRightCmd",
399 callBackPropertyName : "FrontTSetRightCmd",
400 //interfaceName : "FrontTSetRightCmd"
402 "FrontTSetLeftCmd" : {
403 attributeName : "FrontTSetLeftCmd",
404 callBackPropertyName : "FrontTSetLeftCmd",
405 //interfaceName : "FrontTSetLeftCmd"
407 "FrontBlwrSpeedCmd" : {
408 attributeName : "FrontBlwrSpeedCmd",
409 callBackPropertyName : "FrontBlwrSpeedCmd",
410 //interfaceName : "FrontBlwrSpeedCmd"
412 "HeatedSeatFRModeRequest" : {
413 attributeName : "HeatedSeatFRModeRequest",
414 callBackPropertyName : "HeatedSeatFRModeRequest",
415 //interfaceName : "HeatedSeatFRModeRequest"
417 "HeatedSeatFRRequest" : {
418 attributeName : "HeatedSeatFRRequest",
419 callBackPropertyName : "HeatedSeatFRRequest",
420 //interfaceName : "HeatedSeatFRRequest"
422 "HeatedSeatFLModeRequest" : {
423 attributeName : "HeatedSeatFLModeRequest",
424 callBackPropertyName : "HeatedSeatFLModeRequest",
425 //interfaceName : "HeatedSeatFLModeRequest"
427 "HeatedSeatFLRequest" : {
428 attributeName : "HeatedSeatFLRequest",
429 callBackPropertyName : "HeatedSeatFLRequest",
430 //interfaceName : "HeatedSeatFLRequest"
433 attributeName : "FLHSDistrCmd",
434 callBackPropertyName : "FLHSDistrCmd",
435 //interfaceName : "FLHSDistrCmd"
438 attributeName : "FRHSDistrCmd",
439 callBackPropertyName : "FRHSDistrCmd",
440 //interfaceName : "FRHSDistrCmd"
445 * This method adds listener object for car events. Object should define function callbacks taking signal names from mapping table, e.g.:
448 * onBatteryChange: function(newValue, oldValue) {}
450 * Methods are called back with new and last known values.
451 * @method addListener
452 * @param callback {Object} object with callback functions.
453 * @return {Integer} WatchID for later removal of listener.
455 CarIndicator.prototype.addListener = function(aCallbackObject) {
457 var id = Math.floor(Math.random() * 1000000);
459 this._listeners[id] = aCallbackObject;
460 this._listenerIDs.push(id);
462 var subscribeCallback = function(data) {
463 self.onDataUpdate(data, self);
465 for ( var i in aCallbackObject) {
466 if (aCallbackObject.hasOwnProperty(i)) {
467 var prop = i.replace("on", "").replace("Changed", "");
469 for ( var signal in this._mappingTable) {
470 if (this._mappingTable.hasOwnProperty(signal)) {
471 var mapping = this._mappingTable[signal];
472 var zone = mapping.zone;
473 var interfaceName = signal;
475 if (mapping.interfaceName !== "undefined") {
476 interfaceName = mapping.subscribeName;
479 if (mapping.callBackPropertyName.toLowerCase() === prop.toLowerCase() && !mapping.subscribeCount) {
480 mapping.subscribeCount = typeof (mapping.subscribeCount) === "undefined" ? 0 : mapping.subscribeCount++;
482 if (typeof (tizen.vehicle[interfaceName]) !== "undefined") {
483 if (!(interfaceName.toString().trim().toLowerCase() === "nightmode" && id === this._listenerIDs[0])) {
484 if (tizen.vehicle[interfaceName]){
485 var setUpData = tizen.vehicle[interfaceName].get(zone);
486 if (setUpData !== undefined)
487 self.onDataUpdate(setUpData, self, id);
490 if (typeof (tizen.vehicle[interfaceName].subscribe) !== "undefined")
492 console.log("Modello: Subscribing to AMB signal - " + interfaceName);
493 tizen.vehicle[interfaceName].subscribe(subscribeCallback, zone);
496 if (typeof (tizen.vehicle[interfaceName]) === "undefined")
497 console.warn(interfaceName + " is not available to subscribe to");
499 console.warn("Tizen API is not available, cannot subscribe to signal", signal);
510 * This method is call as callback if data oon tizen.vehicle was change onDataUpdate
511 * @method onDataUpdate
512 * @param data {object} object whit new data.
513 * @param self {object} this carIndicator Object.
514 * @param lisenersID {int} id of listener.
516 CarIndicator.prototype.onDataUpdate = function(data, self, lisenersID) {
518 if (data !== undefined) {
519 if (data.zone !== undefined)
520 var zone = data.zone.toString(2);
525 for ( var property in data) {
526 if (data.hasOwnProperty(property)) {
528 if (property !== "time" && property !== "zone" && property.search("Sequence") === -1) {
529 for ( var element in self._mappingTable) {
530 if (self._mappingTable.hasOwnProperty(element)) {
531 if (self._mappingTable[element].attributeName.toLowerCase() === property.toLowerCase()) {
532 /* jshint bitwise: false */
533 if (!(zone ^ self._mappingTable[element].zone)) {
534 /* jshint bitwise: true */
535 mapping = self._mappingTable[element];
542 if (typeof (mapping) !== 'undefined') {
543 var value = data[property];
544 value = mapping.conversionFunction ? mapping.conversionFunction(value) : value;
546 var oldValue = self.status[mapping.callBackPropertyName];
547 if (oldValue !== value || property.toUpperCase() === "nightMode".toUpperCase()) {
548 console.info("AMB property '" + property + "' has changed to new value:" + value);
549 self.status[mapping.callBackPropertyName] = value;
551 var callbackName = "on" + mapping.callBackPropertyName[0].toUpperCase() + mapping.callBackPropertyName.substring(1) + "Changed";
554 if (lisenersID !== undefined) {
555 listener = self._listeners[lisenersID];
557 if (typeof (listener[callbackName]) === 'function') {
559 listener[callbackName](value, oldValue);
561 console.error("Error occured during executing listener", ex);
565 for ( var i in self._listeners) {
566 if (self._listeners.hasOwnProperty(i)) {
567 listener = self._listeners[i];
569 if (typeof (listener[callbackName]) === 'function') {
571 listener[callbackName](value, oldValue);
573 console.error("Error occured during executing listener", ex);
582 console.warn("Mapping for property '" + property + "' is not defined");
591 * This method removes previosly added listener object. Use WatchID returned from addListener method.
592 * @method removeListener
593 * @param aId {Integer} WatchID.
595 CarIndicator.prototype.removeListener = function(aId) {
597 var listener = this._listeners[aId];
599 for ( var i in listener) {
600 if (listener.hasOwnProperty(i)) {
601 var prop = i.replace("on", "").replace("Changed", "");
603 for ( var signal in this._mappingTable) {
604 if (this._mappingTable.hasOwnProperty(signal)) {
605 var mapping = this._mappingTable[signal];
607 if (mapping.subscribeCount === 0) { // Last signal, unscubscribe
608 tizen.vehicle.unsubscribe(signal);
609 mapping.subscribeCount = undefined;
610 } else if (typeof (mapping.subscribeCount) !== 'undefined') {
611 mapping.subscribeCount--;
618 this._listeners[aId] = undefined;
627 CarIndicator.prototype.status = {
629 targetTemperatureRight : 0,
630 targetTemperatureLeft : 0,
632 frontDefrost : false,
635 frontRightwhell : "",
644 airRecirculation : false,
645 airflowDirection : 0,
647 fullBatteryRange : 350,
658 exteriorBrightness : 1000
662 * This method return status object in callback
664 * @param callback {function} callback function.
666 CarIndicator.prototype.getStatus = function(callback) {
668 callback(this.status);
672 * this method set status for property in tizen.vehicle and status object
674 * @param indicator {string} indicator name.
675 * @param status {??} ??.
676 * @param text_status {string} new status .
677 * @param callback {function} callback function.
679 CarIndicator.prototype.setStatus = function(indicator, newValue, callback, zone) {
681 var mappingElement, mappingProperty;
682 for ( var element in this._mappingTable) {
683 if (this._mappingTable.hasOwnProperty(element)) {
684 mappingProperty = undefined;
685 if (this._mappingTable[element].callBackPropertyName.toLowerCase() === indicator.toLowerCase()) {
686 mappingElement = this._mappingTable[element];
687 mappingProperty = this._mappingTable[element].attributeName;
693 // this.status[indicator] = status === "true";
694 if (mappingProperty !== undefined) {
695 var objectName = mappingElement.interfaceName;
696 var propertyZone = parseInt(mappingElement.zone, 2);
697 var propertyValue = {};
698 propertyValue[mappingProperty] = newValue;
699 propertyValue.zone = propertyZone;
701 tizen.vehicle.set(objectName, propertyValue, function(msg) {
702 console.error("Set error: " + msg);