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()
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()
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)