source: thinkgear_emulator/puzzlebox_thinkgear_client_twisted.py @ 117

Last change on this file since 117 was 89, checked in by sc, 11 years ago
  • preparation for 0.2.0 release
File size: 9.4 KB
RevLine 
[48]1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
[64]4# Puzzlebox - Client - ThinkGear Connector
[48]5#
6# Copyright Puzzlebox Productions, LLC (2010)
7#
8# This code is released under the GNU Pulic License (GPL) version 2
9# For more information please refer to http://www.gnu.org/copyleft/gpl.html
10#
[60]11# Last Update: 2010.06.22
[48]12#
13#####################################################################
14
15import os, sys
16import simplejson as json
17
18from twisted.internet import reactor, protocol, defer
[50]19from twisted.protocols import basic
[48]20
[64]21import puzzlebox_thinkgear_emulator_configuration as configuration
[48]22
23#####################################################################
24# Globals
25#####################################################################
26
27DEBUG = 1
28
29SERVER_HOST = configuration.THINKGEAR_SERVER_HOST
30SERVER_PORT = configuration.THINKGEAR_SERVER_PORT
31
32MAX_CONNECTION_ATTEMPTS = configuration.MAX_CONNECTION_ATTEMPTS
33NO_REPLY_WAIT = configuration.NO_REPLY_WAIT
34
[53]35THINKGEAR_DELIMITER = '\r'
[50]36
[62]37ENABLE_THINKGEAR_AUTHORIZATION = configuration.ENABLE_THINKGEAR_AUTHORIZATION
[48]38AUTHORIZATION_REQUEST = configuration.THINKGEAR_AUTHORIZATION_REQUEST
39
[50]40THINKGEAR_PARAMETERS = {"enableRawOutput": False, "format": "Json"}
41#THINKGEAR_PARAMETERS = {"enableRawOutput": True, "format": "Json"}
[56]42#THINKGEAR_PARAMETERS = configuration.FLASH_POLICY_FILE_REQUEST
[49]43
[48]44#####################################################################
45# Classes
46#####################################################################
47
[64]48class puzzlebox_thinkgear_client:
[49]49       
50        def __init__(self, log, \
[68]51                          server_host=SERVER_HOST, \
52                          server_port=SERVER_PORT, \
53                          DEBUG=DEBUG):
[49]54               
55                self.log = log
56                self.DEBUG=DEBUG
57               
58                self.server_host = server_host
59                self.server_port = server_port
60                self.max_connection_attempts = MAX_CONNECTION_ATTEMPTS
[68]61               
62                self.is_authorized = True
63       
64       
[50]65        ##################################################################
[68]66       
[57]67        def authorize_and_send_parameters(self,\
68                                          thinkgear_parameters, \
69                                          authorization_request):
[68]70               
[57]71                if self.DEBUG:
[60]72                        print "--> [ThinkGear Client] Sending Authorization Request:",
[57]73                        print authorization_request
[68]74               
75               
[57]76                d = self.send_parameters(thinkgear_parameters, authorization_request)
77                d.addCallback(self.update_authorization)
[68]78       
79       
[57]80        ##################################################################
[68]81       
[57]82        def update_authorization(self, authorization):
[68]83               
[57]84                if self.DEBUG:
85                        print "--> [ThinkGear Client] Authorization:",
86                        print authorization
[68]87               
[57]88                self.is_authorized = authorization
[68]89       
90       
[57]91        ##################################################################
[68]92       
[57]93        def send_parameters(self, \
[68]94                                 parameters, \
95                                 authentication=None, \
96                                 max_connection_attempts=MAX_CONNECTION_ATTEMPTS):
[50]97               
[68]98                self.factory = puzzlebox_thinkgear_client_factory( \
99                                  self.log, \
100                                  parameters, \
101                                  authentication, \
102                                  self.server_host, \
103                                  self.server_port, \
104                                  max_connection_attempts, \
105                                  self.DEBUG)
[50]106               
[57]107                reactor.connectTCP(self.server_host, self.server_port, self.factory)
[68]108               
[57]109                return self.factory.replyDefer
[68]110       
111       
[49]112        ##################################################################
[68]113       
[57]114        def send_parameters_and_print_response(self, parameters):
[68]115               
[49]116                if self.DEBUG:
[57]117                        print "----> [ThinkGear Client] Sending:",
118                        print parameters
[68]119               
120               
[57]121                d = self.send_parameters(parameters)
[55]122                d.addCallback(self.print_response)
[68]123       
124       
[49]125        ##################################################################
[68]126       
[49]127        def print_response(self, response):
128               
129                if self.DEBUG:
[57]130                        print "--> [ThinkGear Client] Server Response:",
[49]131                        print response
132
[68]133
[50]134#####################################################################
135# ThinkGear Client Protocol class
136#####################################################################
137
[68]138class puzzlebox_thinkgear_client_protocol(basic.LineReceiver):
[49]139       
[68]140        delimiter = THINKGEAR_DELIMITER
141       
[51]142        def __init__(self):
143               
144                self.DEBUG = DEBUG
[50]145       
[68]146       
[50]147        ##################################################################
148       
[52]149        def connectionMade(self):
[78]150               
151                if self.DEBUG:
[68]152                                        print "----> [ThinkGear Client] Connected to %s:%i" % \
153                                                        (self.factory.server_host, \
154                                                         self.factory.server_port)
155               
156               
[57]157                if (self.factory.authentication != None):
158                        self.send_data(self.factory.authentication)
[68]159               
[57]160                else:
161                        self.send_data(self.factory.parameters)
[68]162       
163       
164        ##################################################################
165       
166        def send_data(self, data):
167               
[57]168                packet = json.dumps(data)
[68]169               
[57]170                if self.DEBUG:
171                        print "----> [ThinkGear Client] Sending:",
172                        print packet
[52]173               
[68]174               
[57]175                self.sendLine(packet)
[52]176               
[68]177                #self.factory.noReply = reactor.callLater(NO_REPLY_WAIT, self.noReply)
[50]178       
179       
180        ##################################################################
181       
[52]182        def noReply(self):
183               
184                try:
185                        self.factory.replyDefer.callback('NO_REPLY')
186                except:
187                        if self.DEBUG:
188                                print "noReply failed to call callback"
[68]189       
190       
[50]191        ##################################################################
[68]192       
[57]193        def lineReceived(self, line):
[68]194       
[57]195                # Ignore blank lines
196                if not line:
197                        return
[68]198               
[57]199                try:
200                        data = json.loads(line)
201                except Exception, e:
[62]202                        if self.DEBUG:
[53]203                                print "Partial data received (or error:",
204                                print e
205                                print ")."
[68]206                               
[53]207                                print "line:",
208                                print line
[68]209                               
[62]210                                # We've received back an unrecognized response
211                                # so we'll attempt to reset the server's
212                                # parameters for JSON communication
213                                self.send_data(self.factory.parameters)
[68]214               
[57]215                else:
[68]216                       
[57]217                        if (type(data) == type({})):
[68]218                       
[57]219                                self.factory.process_response(data)
[68]220                                #self.factory.replyDefer.callback(data)
221                               
[57]222                        else:
223                                if self.DEBUG:
224                                        print "data:",
225                                        print data
[68]226       
227       
[57]228        ##################################################################
[68]229       
[57]230        def connectionLost(self, reason):
[68]231               
[53]232                if self.DEBUG > 1:
233                        print "Connection lost:",
234                        print reason
[68]235       
236       
237        ##################################################################
238       
239        def connectionDone(self, reason):
240               
[54]241                if self.DEBUG > 1:
242                        print "Connection done:",
243                        print reason
244
[68]245
[48]246#####################################################################
[50]247# ThinkGear Client Factory class
248#####################################################################
249
[64]250class puzzlebox_thinkgear_client_factory(protocol.ClientFactory):
[50]251       
252        def __init__(self, log, \
[57]253                     parameters, \
[68]254                     authentication, \
[57]255                     server_host=SERVER_HOST, \
256                     server_port=SERVER_PORT, \
257                     max_connection_attempts=MAX_CONNECTION_ATTEMPTS, \
258                     DEBUG=DEBUG):
[50]259               
260                self.log = log
261                self.DEBUG = DEBUG
262                self.server_host = server_host
263                self.server_port = server_port
[57]264                self.parameters = parameters
265                self.authentication = authentication
[50]266               
267                self.max_connection_attempts = max_connection_attempts
268                self.connection_attempt = 1
269               
270                self.protocol = \
[64]271                   puzzlebox_thinkgear_client_protocol
[50]272               
273                self.replyDefer = defer.Deferred()
[68]274       
275       
[57]276        ##################################################################
[68]277       
[57]278        def process_response(self, response):
[68]279               
[57]280                if self.DEBUG:
281                        if (('rawEeg' not in response.keys()) or \
282                            (self.DEBUG > 1)):
283                                print "<-- [ThinkGear Client] Received:",
284                                print response
[68]285               
286               
[57]287                if response.has_key('isAuthorized'):
[68]288                       
[57]289                        if (response['isAuthorized'] == True):
290                                self.replyDefer.callback(True)
291                        else:
292                                self.replyDefer.callback(False)
[68]293       
294       
[62]295        ##################################################################
296       
297        def clientConnectionFailed(self, connector, reason):
298               
299                if self.DEBUG:
300                        print "Client failed to connect to remote component at %s:%i" % \
301                           (self.server_host, self.server_port)
302               
303                reply = 'FAILED_TO_CONNECT'
304               
305                self.connection_attempt = self.connection_attempt + 1
306               
307                if ((self.max_connection_attempts == None) or \
308                         (self.connection_attempt <= self.max_connection_attempts)):
309                       
310                        # If connection failed retry after one second
311                        reactor.callLater(1, connector.connect)
312               
313                else:
314                        if self.DEBUG:
315                                print "Maximum connection retries reached, aborting"
316                       
317                       
318                        self.replyDefer.callback(reply)
319       
320       
321        ##################################################################
322       
323        def clientConnectionLost(self, connector, reason):
324               
325                # Losing Connection is expected after data exchange is complete
326                try:
327                        self.replyDefer.callback(reason)
328                except:
329                        pass
330
331
[50]332#####################################################################
[48]333# Main
334#####################################################################
335
336if __name__ == '__main__':
337       
[64]338        #log = puzzlebox_logger.puzzlebox_logger(logfile='thinkgear_client')
[48]339        log = None
340       
[57]341        authorization_request = AUTHORIZATION_REQUEST
[50]342        thinkgear_parameters = THINKGEAR_PARAMETERS
[48]343       
[64]344        thinkgear_client = puzzlebox_thinkgear_client( \
[48]345                    log, \
346                    server_host=SERVER_HOST, \
347                    server_port=SERVER_PORT, \
348                    DEBUG=DEBUG)
[68]349       
350       
[62]351        if ENABLE_THINKGEAR_AUTHORIZATION:
352                # Use ThinkGear authentication
353                reactor.callWhenRunning( \
354                        thinkgear_client.authorize_and_send_parameters, \
355                        thinkgear_parameters, \
356                        authorization_request)
[68]357       
[62]358        else:   
359                # Do not use ThinkGear authentication
360                authorization_request = None
361                reactor.callWhenRunning( \
362                        thinkgear_client.send_parameters, \
363                        thinkgear_parameters, \
364                        authorization_request)
[68]365       
366       
[48]367        reactor.run()
368
Note: See TracBrowser for help on using the repository browser.