2 * Copyright (c) 2013, Ford Motor Company All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * · Redistributions of source code must retain the above copyright notice,
7 * this list of conditions and the following disclaimer.
8 * · Redistributions in binary form must reproduce the above copyright notice,
9 * this list of conditions and the following disclaimer in the documentation
10 * and/or other materials provided with the distribution.
11 * · Neither the name of the Ford Motor Company nor the names of its
12 * contributors may be used to endorse or promote products derived from this
13 * software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
28 * Base class for RPC client
30 * Class provides access to basic functionality of RPC components Message Broker
31 * as: registerComponent unregisterComponent subscription to notifications logic
32 * to calculate request id
35 FFW.RPCClient = Em.Object.extend( {
38 * transport layer for messages exchange
40 socket: null, // instance of websocket
43 * url for message broker
45 url: "ws://localhost:8087",
48 * Component name in RPC system It is unique.
53 * observer of RPC states
58 * these variables are used to have unique request ids for different
59 * components in RPC bus idStart is received as a response for
60 * registerRPCComponent messages. space for ids for specific RPC component
61 * is allocated by message broker
67 registerRequestId: -1,
68 unregisterRequestId: -1,
71 * Open WebSocket and initialize handlers
73 connect: function( observer, startId ) {
74 this.observer = observer;
75 this.idStart = startId;
77 this.socket = new WebSocket( this.url, 'sample' );
81 this.socket.onopen = function( evt ) {
84 this.socket.onclose = function( evt ) {
87 this.socket.onmessage = function( evt ) {
88 self.onWSMessage( evt )
90 this.socket.onerror = function( evt ) {
97 * Close WebSocket connection Please make sure that component was
98 * unregistered in advance
100 disconnect: function() {
101 this.unregisterRPCComponent();
105 * WebSocket connection is ready Now RPC component can be registered in
108 onWSOpen: function( evt ) {
109 Em.Logger.log( "RPCCLient.onWSOpen" );
111 this.registerRPCComponent();
115 * when result is received from RPC component this function is called It is
116 * the propriate place to check results of reuqest execution Please use
117 * previously store reuqestID to determine to which request repsonse belongs
120 onWSMessage: function( evt ) {
121 Em.Logger.log( "Message received: " + evt.data );
123 var jsonObj = JSON.parse( evt.data );
125 // handle component registration
126 if( jsonObj.id == this.registerRequestId ){
127 if( jsonObj.error == null ){
128 this.requestId = this.idStart = jsonObj.result;
129 this.observer.onRPCRegistered();
131 // handle component unregistration
132 }else if( jsonObj.id == this.unregisterRequestId ){
133 if( jsonObj.error == null ){
135 this.observer.onRPCUnregistered();
137 // handle result, error, notification, requests
139 if( jsonObj.id == null ){
140 this.observer.onRPCNotification( jsonObj );
142 if( jsonObj.result != null )
143 this.observer.onRPCResult( jsonObj );
144 else if( jsonObj.error != null )
145 this.observer.onRPCError( jsonObj );
147 this.observer.onRPCRequest( jsonObj );
153 * WebSocket connection is closed Please make sure that RPCComponent was
154 * dunregistered in advance
156 onWSClose: function( evt ) {
157 Em.Logger.log( "RPCClient: Connection is closed" );
158 this.observer.onRPCDisconnected();
162 * WebSocket connection errors handling
164 onWSError: function( evt ) {
165 // Em.Logger.log("ERROR: " + evt.data);
166 Em.Logger.log( "ERROR: " );
170 * register component is RPC bus
172 registerRPCComponent: function() {
173 this.registerRequestId = this.idStart;
177 "id": this.registerRequestId,
178 "method": "MB.registerComponent",
180 "componentName": this.componentName
183 this.send( JSONMessage );
187 * unregister component is RPC bus
189 unregisterRPCComponent: function() {
190 this.unregisterRequestId = this.generateId();
194 "id": this.unregisterRequestId,
195 "method": "MB.unregisterComponent",
197 "componentName": this.componentName
200 this.send( JSONMessage );
204 * Subscribes to notification. Returns the request's id.
206 subscribeToNotification: function( notification ) {
207 var msgId = this.generateId();
211 "method": "MB.subscribeTo",
213 "propertyName": notification
216 this.send( JSONMessage );
221 * Unsubscribes from notification. Returns the request's id.
223 unsubscribeFromNotification: function( notification ) {
224 var msgId = this.client.generateId();
228 "method": "MB.unsubscribeFrom",
230 "propertyName": notification
233 this.send( JSONMessage );
238 * stringify object and send via socket connection
240 send: function( obj ) {
241 if( this.socket.readyState == this.socket.OPEN ){
242 var strJson = JSON.stringify( obj );
243 Em.Logger.log( strJson );
244 this.socket.send( strJson );
246 Em.Logger.error( "RPCClient: Can't send message since socket is not ready" );
251 * Generate id for new request to RPC component Function has to be used as
254 generateId: function() {
256 if( this.requestId >= this.idStart + this.idRange )
257 this.requestId = this.idStart;
258 return this.requestId;