async def queue_go(): q = Queue(10) asyncio.create_task(foo(q)) asyncio.create_task(bar(q)) await asyncio.sleep(3) for n in range(4): asyncio.create_task(q_put(n, q)) await asyncio.sleep(1) assert q.qsize() == 10 await q.get() await asyncio.sleep(0.1) assert q.qsize() == 10 while not q.empty(): await q.get() await asyncio.sleep(0.1) assert q.empty() print('Competing put tasks test complete') for n in range(4): asyncio.create_task(q_get(n, q)) await asyncio.sleep(1) x = 0 while not q.full(): await q.put(x) await asyncio.sleep(0.3) x += 1 assert q.qsize() == 10 print('Competing get tasks test complete') await asyncio.gather(putter(q), getter(q)) print('Queue tests complete') print("I've seen starships burn off the shoulder of Orion...") print("Time to die...")
def __init__(self, name, url, fw_version, actuators, timer, uart, tx_en, events_callback=None): self.events_cb = events_callback self.uart = uart # Serial TX enable pin self.tx_en = tx_en self.tx_en.off() self.send_queue = Queue(maxsize=50) self.event_queue = Queue(maxsize=50) self.cc_device = CCDevice(name, url, fw_version, actuators=actuators) self.cc_slave = CCSlave(self.on_response, self.on_event, timer, self.cc_device) # Allocate fixed buffers once up-front and use memoryviews # to save on allocations and reduce memory fragmentation self.rx_buf_size = 2 * RX_BUFFER_SIZE self._rx_buffer = bytearray(self.rx_buf_size) self._tx_buffer = bytearray(TX_BUFFER_SIZE) self.RX_BUF = memoryview(self._rx_buffer) self.TX_BUF = memoryview(self._tx_buffer) # asyncio event set by the hard UART interrupt handler self.rx_event = IRQ_EVENT() # Hook up our callback to the UART receive interrupt. This will simply set # the asyncio event and get the heck out. The asyncio handler will be the # workhorse and do the work outside of the hard interrupt handler # TODO: This may not be fully public/finished API but seems to work well for my STM32 board #self.uart.irq(handler, trigger, hard) # Not properly documented in uPython # TODO: machine.UART.IRQ_RXIDLE seems specific to STM32? self.uart.irq(self.on_serial_rx_data, machine.UART.IRQ_RXIDLE, True) asyncio.create_task(self.handle_serial_rx()) asyncio.create_task(self.handle_serial_tx()) asyncio.create_task(self.cc_slave_process()) asyncio.create_task(self.process_events())
class ThreadPool: def __init__(self, max_workers): self.max_workers = max_workers self.runnables = Queue() self.workers = [] for _ in range(max_workers): self.workers.append(Worker(self.runnables)) def __enter__(self): return self def __exit__(self, exc_type, exc_value, exc_traceback): self.join() def submit(self, f, *args): self.runnables.put({"function": f, "args": args}) def join(self): for worker in self.workers: worker.is_closed = True for worker in self.workers: worker.thread.join()
def init(self, queue_size=QUEUE_SIZE_DEFAULT, long_keypress_count=LONG_KEYPRESS_COUNT_DEFAULT): ## Create the queue to push key events to. self.queue = Queue(maxsize=queue_size) self.running = False self.long_keypress_count = long_keypress_count ## The chars on the keypad keys = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#', ] ## The chars to display/return when the key is pressed down for a long time. self.chars_long = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', ] ## Initialise all keys to the UP state. self.keys = [ { 'char':key, 'state':self.KEY_UP, 'down_count':0 } for key in keys ] ## Pin names for rows and columns. self.rows = env.KEYPAD_ROW_PINS self.cols = env.KEYPAD_COL_PINS ## Initialise row pins as outputs. self.row_pins = [ Pin(pin_name, mode=Pin.OUT, pull=None) for pin_name in self.rows ] ## Initialise column pins as inputs. self.col_pins = [ Pin(pin_name, mode=Pin.IN, pull=Pin.PULL_DOWN) for pin_name in self.cols ] self.row_scan_delay_ms = 40 // len(self.rows)
cond02 4 triggered. tim = 3 cond02 1 triggered. tim = 5 cond02 2 triggered. tim = 5 cond02 0 triggered. tim = 7 cond04 99 Awaiting notification and predicate. cond04 99 triggered. tim = 9 Done. ''', 13) asyncio.run(cond_go()) # ************ Queue test ************ from primitives.queue import Queue q = Queue() async def slow_process(): await asyncio.sleep(2) return 42 async def bar(): print('Waiting for slow process.') result = await slow_process() print('Putting result onto queue') await q.put(result) # Put result on q async def foo():
class Keypad_uasyncio(): ## Key states/events KEY_UP = 0 KEY_DOWN = 1 KEY_DOWN_LONG = 2 KEY_UP_LONG = 3 ## an event only, not a state. def __init__(self, queue_size=QUEUE_SIZE_DEFAULT, long_keypress_count=LONG_KEYPRESS_COUNT_DEFAULT): self.init(queue_size=queue_size, long_keypress_count=long_keypress_count) #------------------------------------------------------------------------- def init(self, queue_size=QUEUE_SIZE_DEFAULT, long_keypress_count=LONG_KEYPRESS_COUNT_DEFAULT): ## Create the queue to push key events to. self.queue = Queue(maxsize=queue_size) self.running = False self.long_keypress_count = long_keypress_count ## The chars on the keypad keys = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#', ] ## The chars to display/return when the key is pressed down for a long time. self.chars_long = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', ] ## Initialise all keys to the UP state. self.keys = [ { 'char':key, 'state':self.KEY_UP, 'down_count':0 } for key in keys ] ## Pin names for rows and columns. self.rows = env.KEYPAD_ROW_PINS self.cols = env.KEYPAD_COL_PINS ## Initialise row pins as outputs. self.row_pins = [ Pin(pin_name, mode=Pin.OUT, pull=None) for pin_name in self.rows ] ## Initialise column pins as inputs. self.col_pins = [ Pin(pin_name, mode=Pin.IN, pull=Pin.PULL_DOWN) for pin_name in self.cols ] self.row_scan_delay_ms = 40 // len(self.rows) #------------------------------------------------------------------------- def start(self): self.running = True #------------------------------------------------------------------------- def stop(self): self.running = False for _, row_pin in enumerate(self.row_pins): row_pin.value(1) # prepare rows up and to cols wake up from deep sleep #------------------------------------------------------------------------- def get_key(self): key = self.queue.get() return key #------------------------------------------------------------------------- def key_process(self, key_code, col_pin): key = self.keys[key_code] key_event = None if col_pin.value(): ## key pressed down if key['state'] == self.KEY_UP: ## just pressed (up => down) key_event = self.KEY_DOWN key['state'] = key_event elif key['state'] == self.KEY_DOWN: ## key still down key['down_count'] += 1 if key['down_count'] >= self.long_keypress_count: key_event = self.KEY_DOWN_LONG key['state'] = key_event else: ## key not pressed (up) if key['state'] == self.KEY_DOWN: ## just released (down => up) key_event = self.KEY_UP if key['down_count'] < self.long_keypress_count else self.KEY_UP_LONG key['state'] = self.KEY_UP key['down_count'] = 0 return key_event async def scan_coro(self): """A coroutine to scan each row and check column for key events.""" while self.running: key_code = 0 for row, row_pin in enumerate(self.row_pins): ## Assert row. row_pin.value(1) ## Delay between processing each row. await asyncio.sleep_ms(self.row_scan_delay_ms) ## Check for key events for each column of current row. for col, col_pin in enumerate(self.col_pins): ## Process pin state. key_event = self.key_process(key_code=key_code, col_pin=col_pin) ## Process key event. if key_event == self.KEY_UP: key_char = self.keys[key_code]['char'] await self.queue.put(key_char) elif key_event == self.KEY_DOWN_LONG: key_char = self.chars_long[key_code] await self.queue.put(key_char) key_code += 1 ## Deassert row. row_pin.value(0)
class ControlChainSlaveDevice: def __init__(self, name, url, fw_version, actuators, timer, uart, tx_en, events_callback=None): self.events_cb = events_callback self.uart = uart # Serial TX enable pin self.tx_en = tx_en self.tx_en.off() self.send_queue = Queue(maxsize=50) self.event_queue = Queue(maxsize=50) self.cc_device = CCDevice(name, url, fw_version, actuators=actuators) self.cc_slave = CCSlave(self.on_response, self.on_event, timer, self.cc_device) # Allocate fixed buffers once up-front and use memoryviews # to save on allocations and reduce memory fragmentation self.rx_buf_size = 2 * RX_BUFFER_SIZE self._rx_buffer = bytearray(self.rx_buf_size) self._tx_buffer = bytearray(TX_BUFFER_SIZE) self.RX_BUF = memoryview(self._rx_buffer) self.TX_BUF = memoryview(self._tx_buffer) # asyncio event set by the hard UART interrupt handler self.rx_event = IRQ_EVENT() # Hook up our callback to the UART receive interrupt. This will simply set # the asyncio event and get the heck out. The asyncio handler will be the # workhorse and do the work outside of the hard interrupt handler # TODO: This may not be fully public/finished API but seems to work well for my STM32 board #self.uart.irq(handler, trigger, hard) # Not properly documented in uPython # TODO: machine.UART.IRQ_RXIDLE seems specific to STM32? self.uart.irq(self.on_serial_rx_data, machine.UART.IRQ_RXIDLE, True) asyncio.create_task(self.handle_serial_rx()) asyncio.create_task(self.handle_serial_tx()) asyncio.create_task(self.cc_slave_process()) asyncio.create_task(self.process_events()) def on_serial_rx_data(self, arg): ''' Callback called as an ISR whenever there are characters waiting in the RX buffer. ''' # Set the asyncio event and return ASAP self.rx_event.set() async def handle_serial_rx(self, ): while True: await self.rx_event.wait() # Wait for the next interrupt bytes_read = 0 bytes_avail = self.uart.any() # Read as many bytes as we can into our buffer. This should hopefully # avoid many calls to the interrupt handler if a long transmission # comes in. We can grab as many bytes as we can as they come in, in realtime. while bytes_avail > 0 and bytes_read + bytes_avail < self.rx_buf_size: buffer = self.RX_BUF[bytes_read:bytes_read + bytes_avail] length = len(buffer) remaining = length while remaining > 0: _read = self.uart.readinto(buffer[length - remaining:], remaining) remaining -= _read bytes_read += length bytes_avail = self.uart.any() if bytes_read > 0: messages = self.cc_slave.protocol.receive_data( self.RX_BUF[0:bytes_read]) for message in messages: self.cc_slave.handle_message(message) async def handle_serial_tx(self, ): while True: # Service any queued messages to be sent message = await self.send_queue.get() # Enable serial TX self.tx_en.on() # TODO - Figure out what this should be... time.sleep_us(300) num_tx_bytes = message.get_tx_bytes(self.TX_BUF[0:]) bytes_written = 0 while bytes_written < num_tx_bytes: # print("Sending: %s" % [w for w in self.TX_BUF[bytes_written:num_tx_bytes]]) bytes_written += self.uart.write( self.TX_BUF[bytes_written:num_tx_bytes]) self.tx_en.off() del message # Callbacks def on_response(self, message, priority=CC_MSG_PRIORITY_LOW): try: if priority == CC_MSG_PRIORITY_HIGH: self.send_queue.insert_nowait(message) else: self.send_queue.put_nowait(message) except QueueFull: print("Send queue full! Dropping message!", message.__dict__) def on_event(self, event): try: self.event_queue.put_nowait(event) except QueueFull: print("Event queue full! Dropping event!", event.__dict__) async def cc_slave_process(self, ): ''' Advance the control chain slave state machines. ''' while True: self.cc_slave.process() await asyncio.sleep_ms(0) async def process_events(self, ): ''' Asynchronously process the event queue and handle any queued messages found in it, and advance the control chain slave state machines. ''' while True: # Process any events in the event queue event = await self.event_queue.get() if self.events_cb is not None: self.events_cb(event) await asyncio.sleep_ms(0) ######################### # User-exposed API calls ######################### @property def is_connected(self, ): return self.cc_slave.comm_state == LISTENING_REQUESTS @property def assignments(self, ): return self.cc_device.assignments @property def actuators(self, ): return self.cc_device.actuators
def __init__(self, max_workers): self.max_workers = max_workers self.runnables = Queue() self.workers = [] for _ in range(max_workers): self.workers.append(Worker(self.runnables))
from config import config, serial # MQTT Section from mqtt_as import MQTTClient # game mode NORMAL = const(1) VERSUS = const(2) config_topic = "buzz/{}/config".format(serial) event_topic = "buzz/{}/events".format(serial) announce_topic = "buzz/ping" ping = False locked = False # queue to push message to mqtt notification_queue = Queue(maxsize=16) # Reset pin reset_pin = Pin(19, Pin.IN, Pin.PULL_UP) def button_press(pos: int) -> None: """ Handler for button press """ global locked # Prevent creating local variable if locked: print("locked no press") return if players_lock[pos]: print("Player lock") return
import signal from requests_handlers import make_initial_request, make_request from primitives.thread_pool import ThreadPool from data_handlers import get_aggregate_data from primitives.queue import Queue from server import TCPServer if __name__ == "__main__": access_token, url = make_initial_request() q_out = Queue() q_in = Queue() q_in.put(url) with ThreadPool(max_workers=6) as executor: for _ in range(6): executor.submit(make_request, access_token, q_in, q_out) data = get_aggregate_data(q_out) server = TCPServer() server.start(data)
async def queue_go(delay): queue = Queue() asyncio.create_task(consume(queue)) asyncio.create_task(produce(queue)) await asyncio.sleep(delay) print("Done")