示例#1
0
class Tracker:

    """ Main tracking object.
    Acts as interface between TLE objects and hardware.
    """

    def __init__(self, tle_provider, tle_parser, hardware):
        self.tle_parser = tle_parser
        self.tle_provider = tle_provider
        self.task_handler = TaskHandler(self)
        self.task = self.task_handler.add_function(self.update_task, 100, False)

        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.INFO)

        self.hardware = hardware

    def run(self, start_az, start_al):

        """
        Should be called by application. Does not return.
        Initialises hardware and starts regular updates
        """

        while not self.hardware.is_ready:
            self.hardware.update()

        self.hardware.set_azimuth(start_az)
        self.hardware.set_altitude(start_al)
        self.hardware.start()

        self.task.set_active(True)

        while True:
            sleep(0.01)
            self.task_handler.tick()

    def update_task(self):
        """
        Should be called every second.
        Asks TLE parser to update and sends new data to hardware
        """

        try:
            if self.tle_provider.refresh_tle(self.tle_parser.tle) == False:
                self.logger.warn("Warning: TLE failed to refresh")

            self.tle_parser.update()

            self.hardware.set_az_speed(self.tle_parser.azimuth_speed())
            self.hardware.set_al_speed(self.tle_parser.altitude_speed())
            self.hardware.set_target_azimuth(self.tle_parser.get_azimuth())
            self.hardware.set_target_altitude(self.tle_parser.get_altitude())

            self.hardware.update()

        except KeyboardInterrupt:
            self.hardware.stop()
            exit()
示例#2
0
class DBTester:

    def __init__(self):
        self.task_handler = TaskHandler(self)
        
        self.dbaccess = DbClient(True, self.task_handler)
        
    def start(self):
        while (1):
            sleep(0.001)
            self.task_handler.tick()
示例#3
0
class Snackspace:  # pylint: disable=R0902
    """ Implements the main snackspace class. Responsible for:
    DB and screen managers
    RFID and barcode scanners
    UI interaction via pygame
    pylint R0902 disabled: too many instance attributes
    """
    def __init__(self, window, size, options):
        """ Initialise and start the snackspace application """

        self.inittime = int(time.time())

        self.options = options

        self.input_handler = InputHandler()

        self.task_handler = TaskHandler(self)
        self.task_handler.add_function(self.rfid_task, 500, True)

        self.logger = logging.getLogger("snackspace")

        self.rfid = RFIDReader(self.options.rfid_port)

        self.is_fullscreen = True
        self.cursor_visible = False

        self.window_size = size
        self.screen_manager = ScreenManager(self, window, size)

        self.user = None
        self.products = []

        self.reply_queue = Queue.Queue()

        self.dbaccess = DbClient(self.options.hostip, self.task_handler,
                                 self.db_state_callback)
        self.dbaccess.daemon = True
        self.dbaccess.start()

    def start(self):
        """ The main snackspace event loop """
        ticks = 0

        while (1):
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.quit()
                if event.type == pygame.MOUSEBUTTONUP:
                    self.logger.debug("GUI Event")
                    self.screen_manager.current.on_gui_event(event.pos)

                if event.type == pygame.KEYDOWN:
                    self.keypress(event)

            try:
                packet = self.reply_queue.get(False)
                self.handle_new_packet(packet)

            except Queue.Empty:
                pass

            if (pygame.time.get_ticks() - ticks) > 0:

                ticks = pygame.time.get_ticks()

                self.task_handler.tick()

    def quit(self):

        #Request the DB client thread stop and wait for it to stop
        self.dbaccess.stop()
        while self.dbaccess.is_alive():
            pass
        sys.exit()

    def set_fullscreen(self, fullscreen):

        screen = pygame.display.get_surface()
        tmp = screen.convert()
        caption = pygame.display.get_caption()

        flags = screen.get_flags()

        if fullscreen:
            flags = flags | pygame.FULLSCREEN
        else:
            flags = flags & ~pygame.FULLSCREEN

        bits = screen.get_bitsize()

        #pygame.display.quit()
        #pygame.display.init()

        screen = pygame.display.set_mode(self.window_size, flags, bits)
        screen.blit(tmp, (0, 0))
        pygame.display.set_caption(*caption)

        self.is_fullscreen = fullscreen

    def handle_new_packet(self, packet):
        if packet.type == PacketTypes.ProductData:
            self.on_db_got_product_data(packet)
        elif packet.type == PacketTypes.UnknownProduct:
            self.on_db_got_unknown_product(packet)
        elif packet.type == PacketTypes.UserData:
            self.on_db_got_user_data(packet)
        elif packet.type == PacketTypes.RandomProduct:
            self.on_db_random_product_callback(packet)
        elif packet.type == PacketTypes.Result:
            if packet.data['action'] == PacketTypes.Transaction:
                self.charge_all_handler.on_db_send_transactions_callback(
                    packet)
            elif packet.data['action'] == PacketTypes.AddCredit:
                self.charge_all_handler.on_db_add_credit_callback(packet)
            elif packet.data['action'] == PacketTypes.AddProduct:
                self.on_db_add_product_callback(packet)

    def keypress(self, event):
        """ Handle a keyboard press or barcode scan character """
        # Push keypress to the current screen
        self.screen_manager.current.on_key_event(event.dict['unicode'])

        # Then do our own handling via the input handler
        result = self.input_handler.new_event(event)

        if result == InputHandler.FAKE_BAD_PRODUCT:
            # # Fake a bad product scan
            self.on_scan_event('BADBARCODE')

        elif result == InputHandler.FAKE_GOOD_PRODUCT:
            # # Fake a good product scan
            self.dbaccess.get_random_product(self.reply_queue)

        elif result == InputHandler.FAKE_RFID:
            # # Fake an RFID swipe
            self.rfid.set_fake_rfid()

        elif result == InputHandler.NEW_SCANNED_INPUT:
            # # Buffer is complete, process it
            scanned_input = self.input_handler.scanned_input
            self.input_handler.scanned_input = ''
            self.logger.debug("Got raw input '%s'" % scanned_input)
            self.on_scan_event(scanned_input)

        elif result == InputHandler.PRODUCT_ENTRY:
            # # Go to product entry screen
            self.screen_manager.req(Screens.PRODUCTENTRY)

        elif result == InputHandler.FULLSCREEN_TOGGLE:
            self.set_fullscreen(not self.is_fullscreen)
            self.screen_manager.req(self.screen_manager.currentscreen, True)

        elif result == InputHandler.CURSOR_TOGGLE:
            self.cursor_visible = not self.cursor_visible
            pygame.mouse.set_visible(self.cursor_visible)

        elif result == InputHandler.QUIT:
            self.quit()

    def rfid_task(self):
        """ To be run periodically to check for an RFID swipe """
        rfid = self.rfid.poll()

        if rfid is not None:
            self.on_swipe_event(self.rfid.mangle_rfid(rfid))

    def db_state_callback(self, old_state, new_state, first_update):
        """ Callback when database state changes """

        if old_state != new_state or first_update:
            self.screen_manager.get(
                Screens.INTROSCREEN).set_db_state(new_state)
            if not new_state:
                self.screen_manager.get(Screens.MAINSCREEN).clear_all()
                self.forget_products()
                self.forget_user()

    def on_swipe_event(self, cardnumber):
        """ When an RFID swipe is made, gets user from the database """
        if not self.dbaccess.found_server:
            return
        else:
            self.dbaccess.get_user_data(cardnumber, self.reply_queue)

    def on_scan_event(self, barcode):
        """ When a barcode scan is made, pulls product from the database """
        if not self.dbaccess.found_server or len(barcode) == 0:
            return

        self.add_product_to_basket(barcode)

    def charge_all(self, callback):
        """ Charge the current user for the current set of products """
        self.charge_all_handler = ChargeAllHandler(self.dbaccess, self.user,
                                                   self.products, callback,
                                                   self.reply_queue)

    def credit_user(self, amount):
        """ Adds credit to a user's account """
        self.user.add_credit(amount)

    def forget_user(self):
        """ Clear the user """
        self.user = None

    def total_price(self):
        """ Get the total price of the basket """
        return sum([product.total_price for product in self.products])

    def remove_product(self, product_to_remove):
        """ Remove a product from the basket """

        # First reduce the count of this product.
        # If zero, the product itself can be removed from the list
        if product_to_remove.decrement() == 0:
            self.products = [
                product for product in self.products
                if product != product_to_remove
            ]

        return product_to_remove.count

    def forget_products(self):
        """ Delete the product basket """
        self.products = []

    def new_product(self, barcode, description, priceinpence, callback):
        """ Add a new product to the database """
        self.dbaccess.add_product(barcode, description, priceinpence, callback)

    def add_product_to_basket(self, barcode):
        """ Adds a new scanned product to the list ('basket') of scanned products """
        product = next(
            (product
             for product in self.products if barcode == product.barcode), None)

        if product is not None:
            product.increment(
            )  # Product already exists once, so just increment its count
            self.screen_manager.current.on_scan(product)
        else:
            # Otherwise need to get product info from the database
            self.dbaccess.get_product(barcode, self.reply_queue)

    def on_db_random_product_callback(self, packet):
        """ Callback when random product data is returned from the database """
        barcode = packet.data['barcode']
        self.on_scan_event(barcode)

    def on_db_got_user_data(self, packet):
        """ Callback when user data returned """

        member_id = packet.data['memberid']
        username = packet.data['username']
        balance = packet.data['balance']
        credit_limit = packet.data['limit']

        self.user = User(member_id, username, balance, credit_limit,
                         self.options)
        self.logger.debug("Got user %s" % self.user.name)
        self.screen_manager.current.on_rfid()

    def on_db_got_unknown_user(self, packet):
        self.logger.debug("Bad RFID %s" % packet.data['rfid'])
        self.screen_manager.current.OnBadRFID()

    def on_db_got_product_data(self, packet):
        """ Called when product data returned """
        barcode = packet.data['barcode']
        description = packet.data['description']
        priceinpence = packet.data['priceinpence']

        product = Product(barcode, description, priceinpence)  # pylint: disable=W0142

        if product.valid:
            self.products.append(product)
            self.screen_manager.current.on_scan(product)

    def on_db_got_unknown_product(self, packet):
        """ Called when user data request failed """
        barcode = packet.data['barcode']
        self.screen_manager.current.on_bad_scan(barcode)