source: remote_control/puzzlebox_brainstorms_server_thinkgear.py @ 54

Last change on this file since 54 was 54, checked in by sc, 11 years ago

client_thinkgear:

  • general cleanup

server_thinkgear:

  • structure in place for packet updating

server:

  • comment cleanup
File size: 6.7 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Puzzlebox - Brainstorms - Server - ThinkGear Emulator
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#
11# Last Update: 2010.06.18
12#
13#####################################################################
14
15import os, signal, sys, time
16import simplejson as json
17
18from twisted.internet import reactor, protocol, defer, task
19from twisted.protocols import basic
20
21import puzzlebox_brainstorms_configuration as configuration
22#import puzzlebox_logger
23
24#####################################################################
25# Globals
26#####################################################################
27
28DEBUG = 1
29
30SERVER_INTERFACE = configuration.SERVER_INTERFACE
31SERVER_PORT = configuration.THINKGEAR_SERVER_PORT
32
33THINKGEAR_DELIMITER = '\r'
34
35MESSAGE_FREQUENCY_TIMER = 1 # 1 Hz
36BLINK_FREQUENCY_TIMER = 10 # 10 seconds
37
38DEFAULT_SIGNAL_LEVEL_MESSAGE = \
39        {"poorSignalLevel": 0}
40                # A quantifier of the quality of the brainwave signal.
41                # This is an integer value that is generally in the
42                # range of 0 to 200, with 0 indicating a
43                # good signal and 200 indicating an off-head state.
44
45DEFAULT_EEG_POWER_MESSAGE = \
46        {'eegPower': { \
47                'lowGamma': 0, \
48                'highGamma': 0, \
49                'highAlpha': 0, \
50                'delta': 0, \
51                'highBeta': 0, \
52                'lowAlpha': 0, \
53                'lowBeta': 0, \
54                'theta': 0, \
55                }, \
56         } # A container for the EEG powers. These may
57           # be either integer or floating-point values.
58
59DEFAULT_ESENSE_MESSAGE = \
60        {'eSense': { \
61                'meditation': 0, \
62                'attention': 0, \
63                }, \
64        } # A container for the eSense™ attributes.
65          # These are integer values between 0 and 100,
66          # where 0 is perceived as a lack of that attribute
67          # and 100 is an excess of that attribute.
68               
69DEFAULT_BLINK_MESSAGE = {"blinkStrength": 100}
70        # The strength of a detected blink. This is
71        # an integer in the range of 0-255.
72
73DEFAULT_RAWEEG_MESSAGE = {"rawEeg": 255}
74        # The raw data reading off the forehead sensor.
75        # This may be either an integer or a floating-point value.
76
77DEFAULT_PACKET = {}
78DEFAULT_PACKET.update(DEFAULT_EEG_POWER_MESSAGE)
79DEFAULT_PACKET.update(DEFAULT_SIGNAL_LEVEL_MESSAGE)
80DEFAULT_PACKET.update(DEFAULT_ESENSE_MESSAGE)
81
82DEFAULT_RESPONSE_MESSAGE = DEFAULT_SIGNAL_LEVEL_MESSAGE
83
84#####################################################################
85# Classes
86#####################################################################
87
88class puzzlebox_brainstorms_server_thinkgear(protocol.ServerFactory):
89       
90        def __init__(self, log, DEBUG=DEBUG):
91               
92                self.log = log
93                self.DEBUG = DEBUG
94               
95                self.protocol = puzzlebox_brainstorms_server_protocol
96
97                self.status_packet = DEFAULT_PACKET
98                self.client_connected = False
99       
100       
101        ##################################################################
102       
103        def process_data(self, data):
104               
105                d = defer.Deferred()
106               
107                response = DEFAULT_RESPONSE_MESSAGE
108               
109                if self.DEBUG:
110                        print "--> [ThinkGear Emulator] Received:",
111                        print data
112               
113                if response:
114                        d.callback(response)
115               
116                return d
117       
118       
119        ##################################################################
120       
121        def process_connection_lost(self):
122               
123                print "--> [ThinkGear Emulator] Connection lost"
124                self.client_connected = False
125
126
127        ##################################################################
128
129        def update_status(self):
130
131                if self.DEBUG > 1:
132                        print "status:",
133                        print self.status_packet
134               
135
136        ##################################################################
137
138        def start_updating(self):
139
140                self.client_connected = True
141                self.looping_timer = task.LoopingCall(self.update_status)
142                self.looping_timer.start(MESSAGE_FREQUENCY_TIMER)
143
144
145#####################################################################
146# Protocol
147#####################################################################
148
149class puzzlebox_brainstorms_server_protocol(basic.LineReceiver):
150
151        delimiter='\r'
152       
153        def __init__(self):
154               
155                self.DEBUG = DEBUG
156                self.data = None
157                self.data_chunk = ""
158
159       
160        ##################################################################
161       
162        def connectionMade(self):
163               
164                if self.DEBUG:
165                        print "--> [ThinkGear Emulator] Client connected"
166                       
167                self.factory.start_updating()
168
169
170        ##################################################################
171       
172        def noReply(self):
173               
174                try:
175                        self.factory.replyDefer.callback('NO_REPLY')
176                except:
177                        if self.DEBUG:
178                                print "noReply failed to call callback"
179               
180                self.transport.loseConnection()
181       
182       
183        ##################################################################
184
185        def lineReceived(self, line):
186
187                # Ignore blank lines
188                if not line:
189                        return
190               
191                self.data = json.loads(line)
192
193                if self.DEBUG:
194                        print "line received:",
195                        print self.data
196
197                d = self.factory.process_data("%s" % self.data)
198                d.addCallback(self.send_response)
199
200       
201        ##################################################################
202       
203        def dataReceived(self, data):
204               
205                self.data_chunk += data
206               
207                try:
208                        self.data = json.loads(self.data_chunk)
209               
210                except Exception, e:
211                        if DEBUG:
212                                print "Partial data received (or error:",
213                                print e
214                                print ")."
215               
216                else:
217                        self.data_chunk = ""
218                       
219                        d = self.factory.process_data("%s" % self.data)
220                        d.addCallback(self.send_response)
221       
222       
223        ##################################################################
224       
225        def send_response(self, response):
226
227                if self.factory.client_connected:
228                        if self.DEBUG:
229                                print "--> [ThinkGear Emulator] Sending:",
230                                print response
231                       
232                response = json.dumps(response)
233                self.sendLine(response)
234
235                reactor.callLater(MESSAGE_FREQUENCY_TIMER, \
236                                  self.send_response, \
237                                  self.factory.status_packet)
238
239       
240       
241        ##################################################################
242       
243        def connectionLost(self, reason):
244               
245                self.factory.process_connection_lost()
246
247
248#####################################################################
249# Main
250#####################################################################
251
252if __name__ == '__main__':
253       
254        #log = puzzlebox_logger.puzzlebox_logger(logfile='master_control')
255        log = None
256       
257        # Collect default settings and command line parameters
258        server_interface = SERVER_INTERFACE
259        server_port = SERVER_PORT
260       
261        for each in sys.argv:
262               
263                if each.startswith("--interface="):
264                        server_interface = each[ len("--interface="): ]
265                if each.startswith("--port="):
266                        server_port = each[ len("--port="): ]
267       
268       
269        thinkgear_server = puzzlebox_brainstorms_server_thinkgear(log, DEBUG=DEBUG)
270       
271        if DEBUG:
272                print "--> [ThinkGear Emulator] Initializing server on %s:%i" % \
273                        (server_interface, server_port)
274       
275        reactor.listenTCP(interface=server_interface, \
276                          port=server_port, \
277                          factory=thinkgear_server)
278        reactor.run()
279
Note: See TracBrowser for help on using the repository browser.