Ignore:
Timestamp:
04/01/12 13:17:53 (12 years ago)
Author:
István Váradi <ivaradi@…>
Branch:
default
Phase:
public
Message:

A very basic server and client works for the PyUIPC simulator

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/mlx/pyuipc_sim.py

    r52 r53  
    44import const
    55
     6import cmd
     7import threading
     8import socket
    69import time
     10import sys
     11import struct
     12import cPickle
    713
    814#------------------------------------------------------------------------------
     
    136142    def _convertFrequency(frequency):
    137143        """Convert the given frequency into BCD."""
    138         return Values._convertBCD(int(frequency-100.0)*100)
     144        return Values._convertBCD(int(frequency*100.0))
    139145
    140146    @staticmethod
     
    143149        bcd = (value/1000) % 10
    144150        bcd <<= 4
    145         bcd |= (value/100) & 10
     151        bcd |= (value/100) % 10
    146152        bcd <<= 4
    147153        bcd |= (value/10) % 10
     
    296302            return self._getFuelCapacity(self.FUEL_LEFT_TIP)
    297303        elif offset==0x0b94:       # Right aux tank level
     304            return self._getFuelLevel(self.FUEL_RIGHT)
     305        elif offset==0x0b98:       # Right aux tank capacity
     306            return self._getFuelCapacity(self.FUEL_RIGHT)
     307        elif offset==0x0b9c:       # Right tank level
    298308            return self._getFuelLevel(self.FUEL_RIGHT_AUX)
    299         elif offset==0x0b98:       # Right aux tank capacity
     309        elif offset==0x0ba0:       # Right tank capacity
    300310            return self._getFuelCapacity(self.FUEL_RIGHT_AUX)
    301         elif offset==0x0b9c:       # Right tank level
    302             return self._getFuelLevel(self.FUEL_RIGHT)
    303         elif offset==0x0ba0:       # Right tank capacity
    304             return self._getFuelCapacity(self.FUEL_RIGHT)
    305311        elif offset==0x0ba4:       # Right tip tank level
    306312            return self._getFuelLevel(self.FUEL_RIGHT_TIP)
     
    367373            return self.n1[self.ENGINE_3]
    368374        elif offset==0x30c0:       # Grossweight
    369             return (self.zfw + sum(self.fuelWeights)) * const.KGSTOLB
     375            return int((self.zfw + sum(self.fuelWeights)) * const.KGSTOLB)
    370376        elif offset==0x31e4:       # Radio altitude
    371377            # FIXME: if self.radioAltitude is None, calculate from the
     
    378384            return 1 if self.frozen else 0
    379385        elif offset==0x3bfc:       # ZFW
    380             return int(self.zfw) * 256.0 * const.KGSTOLB
     386            return int(self.zfw * 256.0 * const.KGSTOLB)
    381387        elif offset==0x3c00:       # Path of the current AIR file
    382388            return self.airPath
     
    439445
    440446#------------------------------------------------------------------------------
     447
     448PORT=15015
     449
     450CALL_READ=1
     451CALL_WRITE=2
     452CALL_CLOSE=3
     453
     454RESULT_RETURNED=1
     455RESULT_EXCEPTION=2
     456
     457#------------------------------------------------------------------------------
     458
     459class Server(threading.Thread):
     460    """The server thread."""
     461    def __init__(self):
     462        """Construct the thread."""
     463        super(Server, self).__init__()
     464        self.daemon = True
     465
     466    def run(self):
     467        """Perform the server's operation."""
     468        serverSocket = socket.socket()
     469
     470        serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
     471        serverSocket.bind(("", PORT))
     472   
     473        serverSocket.listen(5)
     474   
     475        while True:
     476            (clientSocket, clientAddress) = serverSocket.accept()
     477            thread = threading.Thread(target = self._process, args=(clientSocket,))
     478            thread.start()
     479
     480    def _process(self, clientSocket):
     481        """Process the commands arriving on the given socket."""
     482        socketFile = clientSocket.makefile()
     483        try:
     484            while True:               
     485                (length,) = struct.unpack("I", clientSocket.recv(4))
     486                data = clientSocket.recv(length)
     487                (call, args) = cPickle.loads(data)
     488                exception = None
     489               
     490                try:
     491                    if call==CALL_READ:
     492                        result = read(args[0])
     493                    elif call==CALL_WRITE:
     494                        result = write(args[0])
     495                    else:
     496                        break
     497                except Exception, e:
     498                    exception = e
     499
     500                if exception is None:
     501                    data = cPickle.dumps((RESULT_RETURNED, result))
     502                else:
     503                    data = cPickle.dumps((RESULT_EXCEPTION, exception))
     504                clientSocket.send(struct.pack("I", len(data)) + data)
     505        except Exception, e:
     506            print >> sys.stderr, "pyuipc_sim.Server._process: failed with exception:", str(e)
     507        finally:
     508            try:
     509                socketFile.close()
     510            except:
     511                pass
     512            clientSocket.close()
     513                   
     514#------------------------------------------------------------------------------
     515
     516class Client(object):
     517    """Client to the server."""
     518    def __init__(self, serverHost):
     519        """Construct the client and connect to the given server
     520        host."""
     521        self._socket = socket.socket()
     522        self._socket.connect((serverHost, PORT))
     523
     524        self._socketFile = self._socket.makefile()
     525
     526    def read(self, data):
     527        """Read the given data."""
     528        data = cPickle.dumps((CALL_READ, [data]))
     529        self._socket.send(struct.pack("I", len(data)) + data)
     530        (length,) = struct.unpack("I", self._socket.recv(4))
     531        data = self._socket.recv(length)
     532        (resultCode, result) = cPickle.loads(data)
     533        if resultCode==RESULT_RETURNED:
     534            return result
     535        else:
     536            raise result
     537
     538#------------------------------------------------------------------------------
     539#------------------------------------------------------------------------------
     540
     541# FIXME: implement proper completion and history
     542class CLI(threading.Thread, cmd.Cmd):
     543    """The command-line interpreter."""
     544    def __init__(self, clientSocket):
     545        """Construct the CLI."""
     546        self._socket = clientSocket
     547        self._socketFile = clientSocket.makefile("rwb")
     548       
     549        threading.Thread.__init__(self)
     550        cmd.Cmd.__init__(self,
     551                         stdin = self._socketFile, stdout = self._socketFile)
     552       
     553        self.use_rawinput = False
     554        self.intro = "\nPyUIPC simulator command prompt\n"
     555        self.prompt = "PyUIPC> "
     556
     557        self.daemon = True
     558
     559    def run(self):
     560        """Execute the thread."""
     561        try:
     562            self.cmdloop()
     563        except Exception, e:
     564            print "pyuipc_sim.CLI.run: command loop terminated abnormally: " + str(e)
     565           
     566        try:
     567            self._socketFile.close()
     568        except:
     569            pass
     570       
     571        self._socket.close()
     572
     573    def do_set(self, args):
     574        """Handle the set command."""
     575        words = args.split()
     576        if len(words)==2:
     577            variable = words[0]
     578            if variable in ["zfw"]:
     579                values.__setattr__(variable, float(words[1]))
     580            else:
     581                print >> self._socketFile, "Unhandled variable: " + variable
     582        return False
     583
     584    def help_set(self):
     585        """Print help for the set command."""
     586        print >> self._socketFile, "set <variable> <value>"
     587
     588    def do_quit(self, args):
     589        """Handle the quit command."""
     590        return True
     591
     592#------------------------------------------------------------------------------
     593
     594if __name__ == "__main__":
     595    client = Client("127.0.0.1")
     596    print client.read([(0x3bfc, "d")])
     597else:
     598    server = Server()
     599    server.start()   
     600
     601#------------------------------------------------------------------------------
Note: See TracChangeset for help on using the changeset viewer.