2 * Copyright (c) 2012, Intel Corporation.
4 * This program is licensed under the terms and conditions of the
5 * Apache License, version 2.0. The full text of the Apache License is at
6 * http://www.apache.org/licenses/LICENSE-2.0
10 /*****************************************************************************
13 * A javascript implementation of the IVI vehicle API that communicates
14 * to the automotive message broker through a websocket
15 * Optional constructor arguments:
16 * sCB: success callback, called when socket is connected, argument is
17 * success message string
18 * eCB: error callback, called on socket close or error, argument is error
20 * url: the URL to use for the websocket, in the form "ws://host:port/script"
21 * protocol: the protocol to use for the websocket, default is "http-only"
23 * [Public Member functions]
24 * Function name: getSupportedEventTypes(type, writeable, successCB, errorCB)
26 * Retrieves a list of vehicle events for the requested type
28 * type: target event or group to query (use empty string for all events)
29 * writeable: if true, return only writeable events, otherwise get all
30 * successCB: success callback, gets called with a string list of names
31 * for all the events and event groups that are children of the
32 * target. e.g. "vehicle_info" returns all events/groups with the
33 * vehicle_info prefix. If the target is an event group, it's
34 * omitted from the returned list
35 * errorCB: error callback, called with error message string
37 * Function name: get(eventlist, successCB, errorCB)
39 * Retrieves a list of event/value pairs for a target list of event names
41 * eventlist[]: list of events to read (use empty string for all events)
42 * successCB: success callback, gets called with the event/value pair list
43 * for all requested events. The list is the in the
44 * form of data[n].name/data[n].value
45 * errorCB: error callback, called with error message string
47 * Function name: getHistory(event, startTime, endTime, successCB, errorCB)
49 * Retrieves a list of event/value pairs for a target list of event names
51 * event: event to read
52 * startTime: start date/time
53 * endTime: end date/time
54 * successCB: success callback, gets called with the event/value pair list
55 * for all requested events. The list is the in the
56 * form of data[n].name/data[n].value
57 * errorCB: error callback, called with error message string
60 * Function name: set(eventlist, valuelist, successCB, errorCB)
62 * Sets a gourp of event's values (triggers error on read-only events)
64 * eventlist: target events to set
65 * valuelist: target event values
66 * successCB: success callback, gets called with the eventlist
67 * that was successfully set
68 * errorCB: error callback, called with error message string
70 * Function name: subscribe(eventlist, successCB, errorCB)
72 * Subscribe to a list of events so you can listen to value changes, they
73 * can be monitored with document.addEventListener(eventname, callback, false);
74 * The Event object passed to the callback has two parameters, e.name and
75 * e.value. Events are sent to the handler individually.
77 * eventlist: target events to listen to
78 * successCB: success callback, gets called with the eventlist
79 * that was successfully subscribed
80 * errorCB: error callback, called with the eventlist that failed to subscribe
82 * Function name: unsubscribe(eventlist, successCB, errorCB)
84 * Unsubscribe to a list of events to let the server know you're not listening,
85 * they should stop being sent from the server if no other clients are using them,
86 * but will at least stop being triggered in your app.
88 * eventlist: target events to stop listening to
89 * successCB: success callback, gets called with the eventlist
90 * that was successfully unsubscribed
91 * errorCB: error callback, called with the eventlist that failed to unsubscribe
93 ******************************************************************************/
97 function Vehicle(sCB, eCB, url, protocol)
99 /* store a copy of Vehicle this for reference in callbacks */
102 this.iSuccessCB = sCB;
105 /* variables for call management, supports up to 100 simultaneously */
107 this.methodCalls = [];
108 for(var i = 0; i < 100; i++)
110 this.methodCalls[i] = null;
113 /* number of connection retries to attempt if the socket closes */
115 this.connected = false;
117 /* timeout for method calls in milliseconds */
118 this.timeouttime = 5000;
120 /* default values for WebSocket */
121 this.socketUrl = "ws://localhost:23000/vehicle";
122 this.socketProtocol = "http-only";
124 /* override the websocket address if parameters are given */
125 if(url !== undefined) this.socketUrl = url;
126 if(protocol !== undefined) this.socketProtocol = protocol;
128 this.VehicleMethodCall = function(id, name, successCB, errorCB)
131 this.successCB = successCB;
132 this.errorCB = errorCB;
133 this.transactionid = id;
136 this.start = function()
138 me.timeout = setTimeout(function(){
139 if(me.errorCB !== undefined)
141 me.errorCB("\""+me.name+"\" method timed out after "+self.timeouttime+"ms");
144 }, self.timeouttime);
146 this.finish = function()
148 if(me.timeout !== undefined)
150 clearTimeout(me.timeout);
157 if ("WebSocket" in window)
159 if(self.socketProtocol.length > 0)
161 self.socket = new WebSocket(self.socketUrl, self.socketProtocol);
165 self.socket = new WebSocket(self.socketUrl);
167 self.socket.onopen = function()
169 self.connected = true;
170 self.iSuccessCB((self.retries < 5)?"(RECONNECTED)":"");
173 self.socket.onclose = function()
175 self.connected = false;
176 self.iErrorCB("socket closed "+((self.retries > 0)?"retrying in 5 seconds ...":""));
179 setTimeout(function(){
185 self.socket.onerror = function(e)
187 self.iErrorCB(e.data);
189 self.socket.onmessage = function (e)
191 self.receive(e.data);
196 console.log("This browser doesn't appear to support websockets!");
202 Vehicle.prototype.generateTransactionId = function()
205 for(i = 0; i < 8; i++)
207 var num = Math.floor((Math.random()+1)*65536);
208 val[i] = num.toString(16).substring(1);
210 var uuid = val[0]+val[1]+"-"+
211 val[2]+"-"+val[3]+"-"+val[4]+"-"+
212 val[5]+val[6]+val[7];
216 Vehicle.prototype.send = function(obj, successCB, errorCB)
220 if(errorCB !== undefined)
222 errorCB("\""+obj.name+"\" method failed because socket is closed");
226 var i = this.methodIdx;
227 this.methodIdx = (this.methodIdx + 1)%100;
228 this.methodCalls[i] = new this.VehicleMethodCall(obj.transactionid,
229 obj.name, successCB, errorCB);
230 this.socket.send(JSON.stringify(obj));
231 this.methodCalls[i].start();
235 Vehicle.prototype.getSupportedEventTypes = function(type, writeable, successCB, errorCB)
239 "name" : "getSupportedEventTypes",
240 "writeable" : writeable,
241 "transactionid" : this.generateTransactionId(),
244 this.send(obj, successCB, errorCB);
247 Vehicle.prototype.get = function(namelist, zone, successCB, errorCB)
249 if(namelist.length <= 0)
256 for(var i = 0; i < namelist.length; i++)
258 properties[i] = {"property" : namelist[i], "zone" : zone};
263 "transactionid" : this.generateTransactionId(),
266 this.send(obj, successCB, errorCB);
269 Vehicle.prototype.getHistory = function(event, startTime, endTime, successCB, errorCB)
273 "name": "getHistory",
274 "transactionid" : this.generateTransactionId(),
275 "data" : [event, (startTime.getTime()/1000).toString(), (endTime.getTime()/1000).toString()]
278 this.send(obj, successCB, errorCB);
282 Vehicle.prototype.set = function(namelist, valuelist, zoneList, successCB, errorCB)
284 if((namelist.length != valuelist.length)||(namelist.length <= 0))
292 "transactionid" : this.generateTransactionId(),
296 for(var i = 0; i < namelist.length; i++)
298 var val = {"property" : namelist[i], "value" : valuelist[i],"zone" : zoneList[i]};
299 list[list.length] = val;
302 this.send(obj, successCB, errorCB);
305 Vehicle.prototype.subscribe = function(namelist, zoneList, successCB, errorCB)
310 "transactionid" : this.generateTransactionId(),
314 this.send(obj, successCB, errorCB);
317 Vehicle.prototype.unsubscribe = function(namelist, zoneList, successCB, errorCB)
321 "name": "unsubscribe",
322 "transactionid" : this.generateTransactionId(),
326 this.send(obj, successCB, errorCB);
329 Vehicle.prototype.sendEvent = function(name, value)
331 var evt = document.createEvent("Event");
332 evt.initEvent(name, true, true);
335 document.dispatchEvent(evt);
339 Vehicle.prototype.receive = function(msg)
344 event = JSON.parse(msg);
347 self.iErrorCB("GARBAGE MESSAGE: "+msg);
351 if((event === undefined)||(event.type === undefined)||
352 (event.name === undefined))
354 self.iErrorCB("BADLY FORMED MESSAGE: "+msg);
359 if(event.type === "methodReply")
361 var calls = this.methodCalls;
362 for(var i = 0; i < calls.length; i++)
365 if(call&&(!call.done)&&(call.transactionid === event.transactionid))
368 if(event.error !== undefined)
370 call.errorCB(event.error);
372 else if(event.data !== undefined && call.successCB !== undefined)
374 call.successCB(event.data);
380 else if(event.type === "valuechanged")
382 self.sendEvent(event.name, event.data);
389 if (typeof define !== 'undefined' && define.amd) {
390 define([], function () {
397 else if (typeof module !== 'undefined' && module.exports) {
402 // included directly via <script> tag