class PyrebaseDatabase(object): def __init__(self): with open('pyrebase_config.json') as f: config = json.load(f) #print() self.firebase = pyrebase.initialize_app(config) self.db = self.firebase.database() def start(self): self.ee = EventEmitter() self.new_data_listener(self.new_data_handler) self.my_stream = self.db.child("users").child("0").stream( self.stream_handler) def stop(self): print('closing stream to firebase') self.my_stream.close() def stream_handler(self, message): print(message["event"]) # put print(message["path"]) # /-K7yGTTEp7O549EzTYtI print(message["data"]) # {'title': 'Pyrebase', "body": "etc..."} s = json.dumps(message["data"]) self.ee.emit("new_data_event", s) def new_data_handler(self, args): print(args) def new_data_listener(self, func): self.ee.on("new_data_event", func)
class PyrebaseDatabase(object): def __init__(self): with open( '/home/pi/Documents/american_gothic/american_gothic_1/python/pyrebase_config.json' ) as f: config = json.load(f) #print() self.firebase = pyrebase.initialize_app(config) self.db = self.firebase.database() def start(self, node): self.ee = EventEmitter() self.new_data_listener(self.new_data_handler) self.my_stream = self.db.child(node).stream(self.stream_handler) def stop(self): print('closing stream to firebase') self.my_stream.close() def stream_handler(self, message): print(message["event"]) # put print(message["path"]) # /-K7yGTTEp7O549EzTYtI print(message["data"]) # {'title': 'Pyrebase', "body": "etc..."} s = json.dumps(message["data"]) self.ee.emit("new_data_event", s) def new_data_handler(self, args): print(args) def new_data_listener(self, func): self.ee.on("new_data_event", func) def send_data(self, data): self.db.child("american_gothic").update({"buffer_1": data})
def createFactorDartListener(self, ee: EventEmitter) -> None: ee.on(EVENT_DART_API_CRAWLING_ON_DOWNLOADING_CODES, self.onDownloadingCodes) ee.on(EVENT_DART_API_CRAWLING_ON_CRAWLING_FACTOR_DATA, self.onCrawlingFactorData) ee.on(EVENT_DART_API_CRAWLING_ON_COMPLETE_YEAR, self.onCompleteYear) ee.on(EVENT_DART_API_CRAWLING_ON_RESULT_OF_FACTOR, self.onResultOfFactor) ee.on(EVENT_DART_API_CRAWLING_ON_CANCEL, self.onCancelled)
def test_async_callback_usage(self): ee = EventEmitter() stack = [] async def handler(arg): stack.append("async_callback_usage_" + arg) ee.on("async_callback_usage", handler) ee.emit("async_callback_usage", "foo") self.assertTrue(stack[-1] == "async_callback_usage_foo")
async def test_await_async_callback_usage(self): ee = EventEmitter() stack = [] async def handler(arg): stack.append("await_async_callback_usage_" + arg) ee.on("await_async_callback_usage", handler) res = ee.emit_async("await_async_callback_usage", "foo") self.assertEqual(len(stack), 0) await res self.assertTrue(stack[-1] == "await_async_callback_usage_foo")
class Receiver: def __init__(self, *args, **kwargs): self.queue = kwargs.pop("__queue") self.event_emitter = EventEmitter() def on(self, event_str, lambda_func): self.event_emitter.on(event_str, lambda: lambda_func()) async def start(self, port): q = self.queue e = self.event_emitter # look at all network interfaces await (asyncio.get_event_loop()).create_server( protocol_factory=lambda: EventProtocol(q, e), host=None, port=port)
def __init__(self, fireAlarmKey, name="default_name", memCacheAddress='127.0.0.1:11211', debug=0): self.name = name self.memCacheAddress = memCacheAddress self.debug = debug #fire alarm event emitter/handler ee = EventEmitter() fireAlarm = FireAlarm(fireAlarmKey, ee) ee.on("fireAlarmEvent", self.handleFireAlarmEvent) fireAlarmProcess = Process(target=fireAlarm.listenKB) fireAlarmProcess.start()
def test_new(self): ee = EventEmitter(new_listener=True) stack = [] @ee.on("new_listener") def handler(func, event=None): stack.append((func, event)) def newhandler(): pass ee.on("new", newhandler) ee.on_any(newhandler) self.assertTrue(stack[-2] == (newhandler, "new")) self.assertTrue(stack[-1] == (newhandler, None))
class AulaActor: def __init__(self, websocket_manager, rc_service, models): self.websocket_manager = websocket_manager self.rc_service = rc_service self.models = models self.event_emitter = EventEmitter() self.bind_events() def emit_event(self, event): self.event_emitter.emit(event.get("action"), event) def bind_events(self): self.event_emitter.on("aula.add_room", self.on_add_room) self.event_emitter.on("aula.move_student", self.on_move_student) self.event_emitter.on_any(func=self.broadcast_to_aula) def broadcast_to_aula(self, event): """ Adapts AulaService's messages to the WebsocketManager's broadcast interface""" active_session_id = event.get("active_session_id") aula_channel = f"aula-{active_session_id}" self.websocket_manager.broadcast(event, aula_channel) def on_add_room(self, event): room_name = event.get("data").get("room") slug = event.get("data").get("slug") channel_name = f"{room_name}-{slug}" res = self.rc_service.create_channel(channel_name) LOG.info(f"Result of adding room:", res) def on_move_student(self, event): data = event.get("data") to_channel = data.get("to_room") from_channel = data.get("from_room") student_id = data.get("student") slug = data.get("slug") from_room_name = f"{from_channel}-{slug}" to_room_name = f"{to_channel}-{slug}" user = self.models.User.query.filter_by(id=student_id).one() remove_res = self.rc_service.remove_user_from_channel( user.rocketchat_id, channel_name=from_room_name) add_res = self.rc_service.add_user_to_channel( user.rocketchat_id, channel_name=to_room_name) LOG.debug(f"User channel add result: {add_res}")
class InputCommands(object): def __init__(self, func): #Setup listeners for input thread = Thread(target=self.key_listener) thread.start() self.ee = EventEmitter() self.ee.on("exit_event", func) #Input callbacks def on_release(self, key): print('{0} released'.format(key)) if key == keyboard.Key.esc: self.ee.emit("exit_event") return False def key_listener(self): # Collect events until released with keyboard.Listener(on_release=self.on_release) as listener: listener.join()
class AllTestCase(unittest.TestCase): def __init__(self, *args, **kwargs): super(AllTestCase, self).__init__(*args, **kwargs) self.ee1 = EventEmitter() self.ee2 = EventEmitter(wildcard=True) self.ee3 = EventEmitter(wildcard=True, delimiter=":") self.ee4 = EventEmitter(new_listener=True) self.ee5 = EventEmitter(max_listeners=1) self.stack = [] def test_1_callback_usage(self): def handler(arg): self.stack.append("1_callback_usage_" + arg) self.ee1.on("1_callback_usage", handler) self.ee1.emit("1_callback_usage", "foo") self.assertTrue(self.stack[-1] == "1_callback_usage_foo") def test_1_decorator_usage(self): @self.ee1.on("1_decorator_usage") def handler(arg): self.stack.append("1_decorator_usage_" + arg) self.ee1.emit("1_decorator_usage", "bar") self.assertTrue(self.stack[-1] == "1_decorator_usage_bar") def test_1_ttl(self): # same as once @self.ee1.on("1_ttl", ttl=1) def handler(arg): self.stack.append("1_ttl_" + arg) self.ee1.emit("1_ttl", "foo") self.assertTrue(self.stack[-1] == "1_ttl_foo") self.ee1.emit("1_ttl", "bar") self.assertTrue(self.stack[-1] == "1_ttl_foo") def test_2_on_all(self): @self.ee2.on("2_on_all.*") def handler(): self.stack.append("2_on_all") self.ee2.emit("2_on_all.foo") self.assertTrue(self.stack[-1] == "2_on_all") def test_2_emit_all(self): @self.ee2.on("2_emit_all.foo") def handler(): self.stack.append("2_emit_all.foo") self.ee2.emit("2_emit_all.*") self.assertTrue(self.stack[-1] == "2_emit_all.foo") def test_3_delimiter(self): @self.ee3.on("3_delimiter:*") def handler(): self.stack.append("3_delimiter") self.ee3.emit("3_delimiter:foo") self.assertTrue(self.stack[-1] == "3_delimiter") def test_4_new(self): @self.ee4.on("new_listener") def handler(func, event=None): self.stack.append((func, event)) def newhandler(): pass self.ee4.on("4_new", newhandler) self.assertTrue(self.stack[-1] == (newhandler, "4_new")) def test_5_max(self): @self.ee5.on("5_max") def handler1(): self.stack.append("5_max_1") @self.ee5.on("5_max") def handler2(): self.stack.append("5_max_2") self.ee5.emit("5_max") self.assertTrue(self.stack[-1] == "5_max_1")
class ChannelHandler(threading.Thread): context = None CA_File = None node_crt_file = None node_key_file = None ECDH_curve = "secp256k1" ssock = None host = None port = None request_counter = itertools.count() logger = None recvThread = None sendThread = None keepWorking = False socketClosed = False pushDispacher = None def __init__(self, max_timeout=10, name="channelHandler"): self.timeout = max_timeout threading.Thread.__init__(self) self.callbackEmitter = EventEmitter() self.requests = [] self.name = name self.blockNumber = 0 self.onResponsePrefix = "onResponse" self.getResultPrefix = "getResult" self.lock = threading.RLock() def initTLSContext(self, ca_file, node_crt_file, node_key_file, protocol=ssl.PROTOCOL_TLSv1_2, verify_mode=ssl.CERT_REQUIRED): try: context = ssl.SSLContext(protocol) context.check_hostname = False context.load_verify_locations(ca_file) context.load_cert_chain(node_crt_file, node_key_file) # print(context.get_ca_certs()) context.set_ecdh_curve(self.ECDH_curve) context.verify_mode = verify_mode self.context = context except Exception as e: raise ChannelException(("init ssl context failed," " please check the certificatsreason: {}"). format(e)) def __del__(self): self.finish() def disconnect(self): self.lock.acquire() if self.ssock is not None and self.socketClosed is False: self.socketClosed = True self.ssock.shutdown(socket.SHUT_RDWR) self.ssock.close() self.logger.info( "disconnect for read/write error, host: {}, port: {}".format(self.host, self.port)) self.lock.release() def reconnect(self): if self.socketClosed is True: self.lock.acquire() self.logger.info("reconnect, host: {}, port: {}".format(self.host, self.port)) try: self.start_connect() self.socketClosed = False self.logger.info( "reconnect success, host: {}, port: {}".format(self.host, self.port)) except Exception as e: self.logger.error("reconnect failed, error: {}".format(e)) self.lock.release() def finish(self): self.disconnect() self.ssock = None if self.keepWorking is True: self.keepWorking = False self.join(timeout=1) if self.recvThread is not None: self.recvThread.finish() self.recvThread.join(timeout=2) if self.sendThread is not None: self.sendThread.finish() self.sendThread.join(timeout=2) if self.pushDispacher is not None: self.pushDispacher.finish() def run(self): try: self.keepWorking = True self.logger.debug(self.name + ":start thread-->") while self.keepWorking: try: # try to reconnect self.reconnect() responsepack = self.recvThread.recvQueue.get_nowait() # pop msg from queue if responsepack is None and self.keepWorking: time.sleep(0.001) continue emitter_str = ChannelHandler.getEmitterStr(self.onResponsePrefix, responsepack.seq, responsepack.type) if emitter_str in self.requests: self.lock.acquire() self.callbackEmitter.emit(emitter_str, responsepack) self.lock.release() else: # 并非客户端指定的等待接受的来自节点的包,可能是push来的消息,包括amop,event push等 # 独立接口处理 # print("push type ",hex(responsepack.type) ) self.pushDispacher.push(responsepack) except Empty: time.sleep(0.001) except Exception as e: self.logger.error("{} recv error {}".format(self.name, e)) finally: self.logger.debug("{}:thread finished ,keepWorking = {}".format( self.name, self.keepWorking)) def start_connect(self): sock = socket.create_connection((self.host, self.port)) self.logger.debug("connect {}:{},as socket {}".format(self.host, self.port, sock)) # 将socket打包成SSL socket self.ssock = self.context.wrap_socket(sock) def start_channel(self, host, port): try: self.socketClosed = False self.keepWorking = False self.host = host self.port = port self.start_connect() self.recvThread = ChannelRecvThread(self) self.recvThread.start() self.sendThread = ChannelSendThread(self) self.sendThread.start() self.pushDispacher = ChannelPushDispatcher() self.pushDispacher.start() super().start() except Exception as e: raise ChannelException(("start channelHandler Failed for {}," " host: {}, port: {}").format(e, self.host, self.port)) def decode_rpc_response(self, response): text_response = to_text(response) return FriendlyJsonSerde().json_decode(text_response) def encode_rpc_request(self, method, params): rpc_dict = { "jsonrpc": "2.0", "method": method, "params": params or [], "id": next(self.request_counter), } encoded = FriendlyJsonSerde().json_encode(rpc_dict) return to_bytes(text=encoded) ''' result: 0 成功 100 节点不可达 101 SDK不可达 102 超时 ''' errorMsg = dict() errorMsg[0] = "success" errorMsg[100] = "node unreachable" errorMsg[101] = "sdk unreachable" errorMsg[102] = "timeout" def make_channel_request(self, data, packet_type, response_type=None): seq = ChannelPack.make_seq32() request_pack = ChannelPack(packet_type, seq, 0, data) self.send_pack(request_pack) onresponse_emitter_str = ChannelHandler.getEmitterStr(self.onResponsePrefix, seq, response_type) # register onResponse emitter self.lock.acquire() self.callbackEmitter.on(onresponse_emitter_str, self.onResponse) self.lock.release() self.requests.append(onresponse_emitter_str) # register onResponse emitter of RPC rpc_onresponse_emitter_str = None rpc_result_emitter_str = None if response_type is ChannelPack.TYPE_TX_COMMITTED \ or response_type is ChannelPack.CLIENT_REGISTER_EVENT_LOG: rpc_onresponse_emitter_str = ChannelHandler.getEmitterStr(self.onResponsePrefix, seq, packet_type) self.requests.append(rpc_onresponse_emitter_str) rpc_result_emitter_str = ChannelHandler.getEmitterStr(self.getResultPrefix, seq, packet_type) self.lock.acquire() self.callbackEmitter.on(rpc_onresponse_emitter_str, self.onResponse) self.lock.release() emitter_str = ChannelHandler.getEmitterStr(self.getResultPrefix, seq, response_type) def resolve_promise(resolve, reject): """ resolve promise """ # register getResult emitter self.lock.acquire() self.callbackEmitter.on(emitter_str, (lambda result, is_error: resolve(result))) # 1. if send transaction failed, return the error message directly # and erase the registered 0x1002 emitter # 2. if send transaction success, remove the registered 0x12 emitter if rpc_result_emitter_str is not None: self.callbackEmitter.on( rpc_result_emitter_str, (lambda result, is_error: resolve(result) and self.requests.remove(onresponse_emitter_str) if is_error is True else self.requests.remove(rpc_onresponse_emitter_str) if self.requests.count(rpc_onresponse_emitter_str) else None)) self.lock.release() p = Promise(resolve_promise) # default timeout is 60s return p.get(60) def make_channel_rpc_request(self, method, params, packet_type=ChannelPack.TYPE_RPC, response_type=ChannelPack.TYPE_RPC): rpc_data = self.encode_rpc_request(method, params) #self.logger.debug("request rpc_data : {}".format(rpc_data)) return self.make_channel_request(rpc_data, packet_type, response_type) def setBlockNumber(self, blockNumber): """ init block number """ self.blockNumber = blockNumber def getBlockNumber(self, groupId): """ get block number notify """ block_notify_emitter = ChannelHandler.getEmitterStr(self.onResponsePrefix, ChannelPack.get_seq_zero(), ChannelPack.TYPE_TX_BLOCKNUM) self.callbackEmitter.on(block_notify_emitter, self.onResponse) self.logger.debug("block notify emitter: {}".format(block_notify_emitter)) self.requests.append(block_notify_emitter) seq = ChannelPack.make_seq32() topic = json.dumps(["_block_notify_{}".format(groupId)]) request_pack = ChannelPack(ChannelPack.TYPE_TOPIC_REPORT, seq, 0, topic) self.send_pack(request_pack) @staticmethod def getEmitterStr(prefix, seq, response_type): """ get emitter str """ return "{}_{}_{}".format(prefix, str(seq), str(response_type)) def onResponse(self, responsepack): """ obtain the response of given type """ result = responsepack.result data = responsepack.data.decode("utf-8") # get onResponse emitter onresponse_emitter = ChannelHandler.getEmitterStr(self.onResponsePrefix, responsepack.seq, responsepack.type) if onresponse_emitter in self.requests and responsepack.type != ChannelPack.TYPE_TX_BLOCKNUM: self.requests.remove(onresponse_emitter) emitter_str = ChannelHandler.getEmitterStr(self.getResultPrefix, responsepack.seq, responsepack.type) self.logger.debug("onResponse, emitter: {}".format(emitter_str)) if result != 0: self.logger.error("response from server failed , seq: {}, type:{}, result: {}". format(responsepack.seq, responsepack.type, result)) self.callbackEmitter.emit(emitter_str, result, True) return try: # json packet if responsepack.type == ChannelPack.TYPE_RPC or \ responsepack.type == ChannelPack.TYPE_TX_COMMITTED: response = FriendlyJsonSerde().json_decode(data) response_item = None error_status = False if 'error' in response.keys(): error_status = True response_item = dict() response_item["result"] = response elif "result" not in response.keys(): response_item = dict() response_item["result"] = response else: response_item = response self.callbackEmitter.emit(emitter_str, response_item, error_status) self.logger.debug("response from server , seq: {}, type:{}". format(responsepack.seq, responsepack.type)) # block notify elif responsepack.type == ChannelPack.TYPE_TX_BLOCKNUM: number = int(data.split(',')[1], 10) self.logger.debug("receive block notify: seq: {} type:{}, data:{}". format(responsepack.seq, responsepack.type, data)) if self.blockNumber < number: self.blockNumber = number self.logger.debug("currentBlockNumber: {}".format(self.blockNumber)) elif responsepack.type == ChannelPack.CLIENT_REGISTER_EVENT_LOG: self.logger.debug("receive event register result: seq: {} type:{}". format(responsepack.seq, responsepack.type)) #print("receive event register result: seq: {} type:{}".format(responsepack.seq, responsepack.type)) self.callbackEmitter.emit(emitter_str, responsepack.data, 0) elif responsepack.type == ChannelPack.EVENT_LOG_PUSH: print("event log push:", responsepack.data) except Exception as e: self.logger.error("decode response failed, seq:{}, type:{}, error info: {}" .format(responsepack.seq, responsepack.type, e)) error_msg = "decode response failed, seq:{}, type:{}, message: {}".format( responsepack.seq, responsepack.type, result) self.callbackEmitter.emit(emitter_str, error_msg, True) def send_pack(self, pack): if self.sendThread.packQueue.full(): self.logger.error("channel send Queue full!") raise BcosError(-1, None, "channel send Queue full!") self.sendThread.packQueue.put(pack)
class Building(object): #when using non default port, make sure the service setting is changed def __init__(self, fireAlarmKey, name="default_name", port=11211, debug=0): self.name = name #fire alarm event emitter/handler self.ee = EventEmitter() self.fireAlarm = FireAlarm(fireAlarmKey, self.ee) self.ee.on("fireAlarmEvent", self.handleFireAlarmEvent) self.fireAlarmProcess = Process(target=self.fireAlarm.listenKB, args=()) self.fireAlarmProcess.start() #shared memory address = '127.0.0.1:' + str(port) self.sharedMemory = memcache.Client([address], debug=debug) #to see full debug logs self.debug = debug == 1 def processFireAlarmEvent(self): print("Fire alarm event received in building " + self.name) #Procedure to change the status of an employee based on their ID to #currently inside the building def processPersonelEnteringEvent(self, personelId): #read the tuple t = self.sharedMemory.get(personelId) if self.debug: print("personel entering " + personelId + " " + t) #modify the tuple's status field t["status"] = "CURRENTLY INSIDE" #write the tuple self.sharedMemory.set(personelId, t) #Procedure to change the status of an employee based on their ID to #authorized after leaving the building def processPersonelLeavingEvent(self, personelId): #read the tuple t = self.sharedMemory.get(personelId) if self.debug: print("personel entering " + personelId + " " + t) #modify the tuple's status field t["status"] = "AUTHORIZED" #write the tuple self.sharedMemory.set(personelId, t) def handleFireAlarmEvent(self): print("Received Alarm in building " + self.name) print(self.sharedMemory)
class Watch(object): # def __init__(self, gpio, trig, echo, func_in, func_out, offset): def __init__(self, **kwargs): """ Watch(gpio=GPIO, trig=23, echo=24, func_in=None, func_out=None, offset=200) The Watch class. Please always use *kwargs* in the constructor. - *gpio*: Pass the GPIO object - *trig*: Pin for trigger - *echo*: Pin for trigger - *func_in*: handler when a objects comes into field - *func_out*: handler when a objects goes out of field - *offset*: offset in cm to determine if the object is IN zone or OUT zone """ def dummy_func_in(): print("Dummy in function") def dummy_func_out(): print("Dummy out function") super(Watch, self).__init__() func_in = kwargs.get("func_in", dummy_func_in) func_out = kwargs.get("func_out", dummy_func_out) self._ee = EventEmitter(wildcard=True, new_listener=True, max_listeners=-1) self._ee.on("ObjectIn", func_in) self._ee.on("ObjectOut", func_out) self._gpio = kwargs.get("gpio", None) self._trig = kwargs.get("trig", 23) self._echo = kwargs.get("echo", 24) self._offset = kwargs.get("offset", 200) self._wasIn = False self._observer = ThreadPoolExecutor(max_workers=1) self._observer_on = True self._future = None def trigger_pin(self): return self._trig def echo_pin(self): return self._echo def ping(self): distance = self.get_distance() if distance < self._offset: if not self._wasIn: self._ee.emit("ObjectIn", distance) self._wasIn = True else: if self._wasIn: self._ee.emit("ObjectOut", distance) self._wasIn = False return def poll(self): while True: if self._observer_on: self.ping() else: return def observe(self): self._future = self._observer.submit(self.poll) return def stop(self): self._observer_on = False time.sleep(3) try: self._future.shutdown(wait=False) except: if self._future.running(): self._observer.shutdown(wait=False) return def get_distance(self): print("Distance Measurement In Progress") self._gpio.setup(self._trig, self._gpio.OUT) self._gpio.setup(self._echo, self._gpio.IN) self._gpio.output(self._trig, False) print("Waiting For Sensor To Settle") time.sleep(2) self._gpio.output(self._trig, True) time.sleep(0.00001) self._gpio.output(self._trig, False) pulse_start = time.time() pulse_end = time.time() while self._gpio.input(self._echo) == 0: pulse_start = time.time() while self._gpio.input(self._echo) == 1: pulse_end = time.time() pulse_duration = pulse_end - pulse_start distance = pulse_duration * 17150 distance = round(distance, 2) print("Distance:", distance, "cm") self._gpio.cleanup() return distance
from pymitter import EventEmitter ee = EventEmitter() # decorator usage @ee.on("myevent") def handler1(arg): print("handler1 called with " + arg) # callback usage def handler2(arg): print("handler2 called with " + arg) ee.on("myotherevent", handler2) # emit ee.emit("myevent", "foo") # -> "handler1 called with foo" ee.emit("myotherevent", "bar") # -> "handler2 called with bar"
def createListners(self, ee: EventEmitter) -> None: ee.on(EVENT_MARCAP_CRAWLING_ON_RESULT_OF_STOCK_DATA, self.onResultOfStockData) ee.on(EVENT_MARCAP_CRAWLING_ON_CONNECTING_WEBDRIVER, self.onConnectingWebDriver) ee.on(EVENT_MARCAP_CRAWLING_ON_START_CRAWLING, self.onStartCrawling) ee.on(EVENT_MARCAP_CRAWLING_ON_DOWNLOAD_START, self.onDownloadStart) ee.on(EVENT_MARCAP_CRAWLING_ON_DOWNLOAD_COMPLETE, self.onDownloadComplete) ee.on(EVENT_MARCAP_CRAWLING_ON_PARSING_COMPLETE, self.onParsingComplete) ee.on(EVENT_MARCAP_CRAWLING_ON_ERROR, self.onError) ee.on(EVENT_MARCAP_CRAWLING_ON_CANCEL, self.onCancelled)
class Wuzei: def __init__(self, config: WuzeiConfig, logger=None): if not logger: logger = partial(print, sep='\t') self.logger = logger self.ee = EventEmitter() self.ee.on('lock', self._on_lock) self.ee.on('unlock', self._on_unlock) self.ee.on('hotkey', self._on_hotkey) self.ee.on('timer', self._on_timer) self.threads = [] self.running_event = InterruptibleEvent() self._update_time() self.config = config self.paused = config.paused self.interval = config.interval self._sources = [path for key, path in config.sources.items()] self.manager = WallpaperManager(paths=self._sources, cache_dir=config.cache_dir, blurred=config.blurred, shuffled=config.shuffled, logger=self.logger) def _monitor_hotkeys(self): actions = dict( prev=Action.PREV_WALLPAPER, next=Action.NEXT_WALLPAPER, prev_source=Action.PREV_SOURCE, next_source=Action.NEXT_SOURCE, toggle_shuffle=Action.TOGGLE_SHUFFLE, toggle_blur=Action.TOGGLE_BLUR, blur=Action.BLUR, exit=Action.EXIT, pause=Action.PAUSE, view=Action.VIEW, ) hotkeys = { hotkey: actions[name] for name, hotkey in self.config.hotkeys.items() } for combination, action in hotkeys.items(): keyboard.add_hotkey(combination, callback=self.ee.emit, args=['hotkey', action]) def _monitor_session(self): sm = SessionMonitor() sm.subscribe(SessionEvent.SESSION_LOCK, self.ee.emit, 'lock') sm.subscribe(SessionEvent.SESSION_UNLOCK, self.ee.emit, 'unlock') sm.listen() def _monitor_dirs(self): cooldown = self.config.dir_monitor_cooldown def make_callback(path: str): @throttle(cooldown=cooldown + 5) def cb(*args): self.logger('SOURCE CHANGED', path) time.sleep(cooldown) self.manager.sync(path) return cb for path in self._sources: callback = make_callback(path) watcher = DirectoryWatcher(path=path, on_deleted=callback, on_created=callback, on_renamed=callback) while True: time.sleep(10) def _setup_timer(self): while True and self.interval > 0: time.sleep(1) elapsed = time.time() - self.last_change if elapsed < self.interval: continue if not self.paused: self.ee.emit('timer') def _on_timer(self): self.logger('TIMER') self.manager.next_wallpaper() self._update_time() def _on_lock(self): self.logger('LOCKED') self.manager.blur() def _on_unlock(self): self.logger('UNLOCKED') keyboard.stash_state() def _on_mouse(self, desktop: WindowSpy, taskbar: WindowSpy): if desktop.is_under_mouse: self.logger('DESKTOP CLICKED') self.manager.toggle_blur() if taskbar.is_under_mouse: self.logger('TASKBAR CLICKED') if keyboard.is_pressed('alt'): self.manager.blur() else: self.manager.toggle_blur() def _rehook(self): while True: time.sleep(self.config.hook_refresh_interval) keyboard.stash_state() def _hook_mouse(self): desktop = WindowSpy.desktop() taskbar = WindowSpy.taskbar() mouse.on_double_click(self._on_mouse, args=(desktop, taskbar)) def _on_hotkey(self, action: Action): self.logger('HOTKEY', action) self.handle_action(action) def handle_action(self, action: Action): try: handlers = { Action.PREV_WALLPAPER: self.manager.prev_wallpaper, Action.NEXT_WALLPAPER: self.manager.next_wallpaper, Action.PREV_SOURCE: self.manager.prev_source, Action.NEXT_SOURCE: self.manager.next_source, Action.TOGGLE_SHUFFLE: self.manager.toggle_shuffle, Action.TOGGLE_BLUR: self.manager.toggle_blur, Action.BLUR: self.manager.blur, Action.PAUSE: self.pause, Action.VIEW: self.view_current, Action.EXIT: self.exit, } handlers[action]() self._update_time() except KeyError: self.logger('Unhandled action', action) raise NotImplementedError def _update_time(self): self.last_change = time.time() def pause(self): self.paused = not self.paused self.logger('PAUSED' if self.paused else 'RUNNING') def view_current(self): os.startfile(self.manager.wallpaper) def exit(self): self.running_event.set() self.logger('Bye') os._exit(0) def run(self): threads = dict( keyboard=threading.Thread(target=self._monitor_hotkeys), timer=threading.Thread(target=self._setup_timer), rehook=threading.Thread(target=self._rehook), ) if self.config.blur_on_lock: threads['session'] = threading.Thread(target=self._monitor_session) if self.config.monitor_dirs: threads['directory'] = threading.Thread(target=self._monitor_dirs) if self.config.hook_mouse: threads['mouse'] = threading.Thread(target=self._hook_mouse) self.threads = threads for name, th in threads.items(): th.start() self.running_event.wait()
class Agent(object): """ Agent implementation with a Finite State Machine. The agent uses a Machine instance to move through the FSM that's created based on a given strategy. The class describes with methods all the possible operations the Agent can perform. """ def __init__(self, config='strategies.json', strategy='normal', name='Pandora', testing=False, verbose=False): """ Initializes the agent. :param :name The name of the agent. Defaults to Pandora. :param :strategy Defines the configuration that will be loaded from the Agent. :param :config A yaml/json file that contains the agent strategies. The file should be located in the config folder of this package. """ # Configuration folder config_dir = RosPack().get_path(PKG) + '/config/' self.name = name self.verbose = verbose self.testing = testing self.strategy = strategy self.config = config_dir + config # Dispatcher for event based communication. self.dispatcher = EventEmitter() # SUBSCRIBERS. self.world_model_sub = Subscriber(topics.world_model, WorldModel, self.receive_world_model) # ACTION CLIENTS. self.explorer = clients.Explorer(self.dispatcher) self.data_fusion = clients.DataFusion() self.navigator = clients.Navigator(self.dispatcher) self.gui_client = clients.GUI() self.effector = clients.Effector() if not self.testing: Service('/gui/kill_agent', Empty, self.destroy_agent) self.transform_listener = tf.TransformListener() # State client if not self.testing: log.debug('Connecting to state manager.') self.state_changer = StateClient() self.state_changer.client_initialize() log.debug('Connection established.') self.state_changer.change_state_and_wait(RobotModeMsg.MODE_OFF) # General information. self.current_pose = Pose() self.exploration_mode = DoExplorationGoal.TYPE_DEEP # Victim information. self.available_targets = [] self.gui_result = ValidateVictimGUIResult() # Between-transition information. self.base_converged = threading.Event() self.poi_found_lock = threading.Lock() # Utility Variables self.MOVE_BASE_RETRIES = 0 self.target = Target(self.dispatcher) # Expose client methods to class setattr(self, 'test_end_effector', self.effector.test) setattr(self, 'park_end_effector', self.effector.park) setattr(self, 'preempt_end_effector', self.effector.cancel_all_goals) setattr(self, 'preempt_explorer', self.explorer.cancel_all_goals) setattr(self, 'scan', self.effector.scan) self.generate_global_state_transitions() self.load() log.info('Agent initialized...') ###################################################### # UTILITIES # ###################################################### def set_breakpoint(self, state): """ Stops the execution of the FSM after a given state. Removes the implementation from the state. :param :state The last state we want to go. After this state the FSM will stop. """ # Removing the implementation of the given state. self.machine.get_state(state).empty() def wait_for_map(self): sleep(5.0) def load(self): """ Loads the configuration file and sets up the FSM accordingly. """ try: # Read the configuration file. with open(self.config) as file_handler: data = yaml.load(file_handler) except IOError: log.critical('Could not read configuration file.') sys.exit(1) try: states = data[self.strategy]['states'] except KeyError: log.critical('%s is not a valid strategy.', self.strategy) sys.exit(1) # Setting up the FSM self.machine = Machine(model=self) # Get all the states for the given strategy. self.states = [state['name'] for state in states] # Set up states tasks. for state in states: self.machine.add_states(state['name'], on_enter=state['tasks'], on_exit=state['clean']) # Create the transition table. self.transitions = [] for state in states: for transition in state['transitions']: self.machine.add_transition(transition['trigger'], state['name'], transition['to'], before=transition['before'], after=transition['after'], conditions=transition['conditions'] ) # Sets up the initial state self.machine.set_state(self.states[0]) log.debug('FSM has been loaded.') def clean_up(self): """ Kills agent and cleans the environment. """ self.explorer.cancel_all_goals() self.navigator.cancel_all_goals() self.effector.cancel_all_goals() log.info('Agent is sleeping...') def disable_events(self): """ Disable all EventEmitter events. It should be called before the main tasks of a state. """ self.dispatcher.off_all() ###################################################### # DISPATCHER'S CALLBACKS # ###################################################### def exploration_success(self): """ Called on 'exploration.success' event. The event is triggered from the exploration client when the current goal has succeeded. Enables the agent to move from the exploration state to end. """ if self.state == 'exploration': log.warning('Map covered!') self.map_covered() else: log.warning('Exploration success caught outside of exploration.') def exploration_retry(self): """ Called on 'exploration.retry' event. The event is triggered from the exploration client when the current goal has failed and the agent sends again a goal. """ if self.state == 'exploration': log.warning('Retrying exploration goal.') self.explore() else: log.warning('Exploration failure while not on exploration state.') def poi_found(self): """ Called on 'poi.found' event. The event is triggered when there are available points of interest on the received world model. Enables the agent to move from the exploration state to identification. """ if self.state != 'exploration': # This is a bug. log.warning('Called poi_found outside of exploration.') return # Ensure that poi found is not called twice with the same target. self.poi_found_lock.acquire(False) log.warning('A point of interest has been discovered.') log.info('Pursuing target #%d.', self.target.info.id) self.poi_found_lock.release() self.point_of_interest_found() def move_base_success(self, result): """ The event is triggered from the move_base client when the current goal has succeeded. :param result: The result of the action. """ self.MOVE_BASE_RETRIES = 0 if self.state != 'identification': log.error('Received move base success outside identification.') return log.warning('Approached potential victim.') self.base_timer.cancel() self.valid_victim() def move_base_retry(self, status): """ The event is triggered from the move_base client when the current goal has failed and the agent will send again the goal. After a number of failures the agent will change state and delete the current victim. :param :status The goal status. """ if self.state != 'identification': log.error('Received move_base retry event outside identification.') return if self.MOVE_BASE_RETRIES < conf.MOVE_BASE_RETRY_LIMIT: # The agent tries again. log.warning('Retrying...%s goal', ACTION_STATES[status]) remain = conf.MOVE_BASE_RETRY_LIMIT - self.MOVE_BASE_RETRIES log.warning('%d remaining before aborting the current target.', remain) self.MOVE_BASE_RETRIES += 1 self.navigator.move_base(self.target.info.victimPose) else: self.MOVE_BASE_RETRIES = 0 self.base_timer.cancel() # The agent changes state. if self.target.is_identified(): # The target is valid and the next state is hold_sensors. log.warning('Victim with high probability identified.') self.valid_victim() elif self.base_converged.is_set(): log.warning('Base is close enough to the target.') self.valid_victim() else: # The target is not valid and we delete it. log.warning('Victim has been aborted.') self.abort_victim() def move_base_feedback(self, current, goal): """ The event is triggered from the move_base client when the action server sends feedback with the current pose. Given the goal and the current pose the agent checks if it is close enough to the point of interest. This will work if the move_base server takes too long to succeed. :param :current The current PoseStamped received from the action client. :param :goal The PoseStamped goal of the current action. """ self.current_pose = current.base_position.pose if distance_2d(goal.pose, self.current_pose) < conf.BASE_THRESHOLD: log.warning('Base converged.') self.base_converged.set() def move_base_resend(self, pose): """ Send a new MoveBase goal. The old one is outdated because the current target's pose has been updated. :param pose: The new pose to go to. """ if self.state == 'identification': log.warning('Move base goal is outdated...') log.debug(pose) self.navigator.cancel_all_goals() self.approach_target() ###################################################### # SUBSCRIBER'S CALLBACKS # ###################################################### def destroy_agent(self, stop): """ Kill the agent's process and stop all running goals. """ # Change to teleoperation self.mode_teleoperated_locomotion() # Cancel all goals self.clean_up() # Kill the process pid = os.getpid() p = psutil.Process(pid) log.warning("Shutting down.") p.terminate() def receive_world_model(self, model): """ Receives the world model from data fusion. """ # If no targets are available there is nothing to do. if not model.victims: return # Remember the available targets. self.available_targets = model.victims if self.target.is_empty: # Set a new target from the available ones. new_target = self.choose_target(model.victims) self.target.set(new_target) else: # Check for invalid target acquisition. idx = self.target.info.id for target in model.victims: if idx == target.id: break else: log.error('A non-existent target #%d has been acquired.', idx) self.target.clean() return # Update the current target. self.target.update(model.victims) self.dispatcher.emit('poi.found') ###################################################### # AGENT'S ACTIONS # ###################################################### def reset_environment(self): """ Sets the environment ready for the next exploration. """ self.gui_result.victimValid = False self.target.clean() def notify_data_fusion(self): """ Notify data fusion about the current target. """ self.available_targets = self.data_fusion.announce_target(self.target.info.id) def validate_victim(self): """ Sends information about the current target. """ if not self.target.is_empty: self.available_targets = self.data_fusion.validate_victim(self.target.info.id, valid=self.gui_result.victimValid, verified=self.target.is_verified()) else: log.critical('Reached data fusion validation without target.') def delete_victim(self): """ Send deletion request to DataFusion about the current target victim. """ self.available_targets = self.data_fusion.delete_victim(self.target.info.id) self.victim_deleted() def wait_for_verification(self): """ Check if the probability of the target exceeds the verification threshold. """ log.info("Starting victim verification...") if self.target.verified.wait(conf.VERIFICATION_TIMEOUT): log.warning('Victim verified.') self.verified() else: log.warning('Victim failed to be verified within %d secs.', conf.VERIFICATION_TIMEOUT) self.gui_result.victimValid = False self.timeout() def wait_for_operator(self): if self.gui_client.send_request(self.target.info): self.gui_result = self.gui_client.result() else: self.gui_result.victimValid = False def approach_target(self): """ The agent will try to approach the target's location and point all sensors to its direction. """ log.info('Approaching victim...') self.base_converged.clear() # Move base to the target. self.navigator.move_base(self.target.info.victimPose) # Point sensors to the target. self.effector.point_to(self.target.info.victimFrameId) # Start timer to cancel all goals if the move base is unresponsive. self.base_timer = threading.Timer(conf.MOVE_BASE_TIMEOUT, self.timer_handler) self.base_timer.start() def slowly_track_target(self): """ The end effector slowly tracks the current target so the captured image is staying as still as possible. """ # Point sensors to the target. self.effector.slowly_point_to(self.target.info.victimFrameId) def explore(self): """ Send exploration goal to the explorer. A different exploration strategy is used depending on the global state. """ global_state = self.state_changer.get_current_state() coverage = DoExplorationGoal.TYPE_DEEP fast = DoExplorationGoal.TYPE_FAST if global_state == RobotModeMsg.MODE_EXPLORATION_RESCUE: log.info("** COVERAGE EXPLORATION **") self.explorer.explore(exploration_type=coverage) else: log.info("** FAST EXPLORATION **") self.explorer.explore(exploration_type=fast) def check_for_targets(self): """ Check for available targets and choose one now. Don't wait until the next update of the world model. """ log.debug("Checking for available targets...") if self.target.is_empty: if self.available_targets != []: new_target = self.choose_target(self.available_targets) self.target.set(new_target) self.dispatcher.emit('poi.found') else: log.debug('World model is empty. Searching for targets...') self.explore() else: if self.target.info in self.available_targets: self.dispatcher.emit('poi.found') else: target_id = self.target.info.id log.error('Acquired non existent target #%s' % (target_id)) self.target.clean() if self.available_targets != []: new_target = self.choose_target(self.available_targets) self.target.set(new_target) self.dispatcher.emit('poi.found') else: log.debug('World model is empty. Searching for targets...') self.explore() def timer_handler(self): if self.state == 'identification': log.warning('Move base is unresponsive or it takes too long.') self.navigator.cancel_all_goals() self.base_timer.cancel() self.abort_victim() else: log.error('Timer fired outside of identification state.') def print_results(self): """ Prints results of the mission. """ log.info('The agent is shutting down...') def enable_exploration_events(self): """ Enable EventEmitter events for the exploration state. """ self.dispatcher.on('exploration.success', self.exploration_success) self.dispatcher.on('exploration.retry', self.exploration_retry) self.dispatcher.on('poi.found', self.poi_found) def enable_identification_events(self): """ Enable EventEmitter events for the identfication state. """ self.dispatcher.on('move_base.success', self.move_base_success) self.dispatcher.on('move_base.retry', self.move_base_retry) self.dispatcher.on('move_base.feedback', self.move_base_feedback) self.dispatcher.on('move_base.resend', self.move_base_resend) ###################################################### # AGENT LOGIC # ###################################################### def choose_target(self, targets): """ Choose the neareset possible target. """ # Should never be called with empty targets. if not targets: log.error('choose_target was called with no targets.') return None closest_target = targets[0] min_distance = 1000 if len(targets) == 1: return closest_target # self.current_pose = self.explorer.pose_stamped.pose for target in targets: try: (trans, rot) = self.transform_listener.lookupTransform(target.victimPose.header.frame_id, '/base_footprint', Time(0)) except: log.error("Transform listener failed to acquire transformation") return closest_target self.current_pose = Pose() self.current_pose.position.x = trans[0] self.current_pose.position.y = trans[1] self.current_pose.position.z = trans[2] target_pose = target.victimPose.pose target_distance = distance_2d(target_pose, self.current_pose) if target_distance < min_distance: min_distance = target_distance closest_target = target return closest_target ###################################################### # GLOBAL STATE TRANSITIONS # ###################################################### def generate_global_state_transitions(self): """ Generates a function for every global state. The agent will be able to call this function in order to change the global state. Reads all the available modes from the RobotModeMsg and creates a function with the same name. """ for member, value in inspect.getmembers(RobotModeMsg): if member.startswith('MODE_'): func = partial(self.global_state_transition, mode=value) setattr(self, member.lower(), func) log.debug('Global state transitions have been generated.') def global_state_transition(self, mode=0): """ Is used to generate state_transition functions. Given a desired mode the state_client will will try to change the global state. :param :mode A global mode from RobotModeMsg. """ params = (mode, conf.STATE_CHANGE_TIMEOUT) while True: success = self.state_changer.change_state_and_wait(*params) if success: log.info('==> %s', GLOBAL_STATES[mode]) break sleep(2) log.error('Failed to change the global state [%d]. Retrying...', mode)
class App: # Give us access to the input and output devices. audio_manager = pyaudio.PyAudio() # The sensitivity for the VAD. vad_aggression_factor = 3 # Sample rate for the VAD tool. sample_rate = 16000 # nospinner = True # The path for the saved audio files. savewav = None file_path = None # wake up word = command_set = { "commands": [ "hilfe", "anrufen", "schmerzen", "ich habe schmerzen", "ich brauche hilfe", "hallo" ] } # Initializes a new instance of the app class. def __init__(self, wake_up_word, model_file, scorer_file): self.command_set["wake_up_word"] = wake_up_word self.model_file = model_file self.scorer_file = scorer_file self.input_device = pyaudio.PyAudio.get_default_input_device_info( self.audio_manager) self.input_device_index = self.input_device.get("index") def notify_client(self, data: data_processing_result.DataProcessingResult): print("Eingabe:", "\n", "Cubo ist bereit:", data.is_wake_up_word, "\n", "Verstanden:", data.sentence, "\n", "Vermutung:", data.guess, "\n") # Callback for the onDataReceived event. # @on_data_received_emitter.on("handle_received_data") # def handleData(self, data): # print("Received data: %s" % data) # Runs the app. def run(self): # Fired when input is available. self.on_data_received_emitter = EventEmitter() self.on_notification_emitter = EventEmitter() self.on_notification_emitter.on("notify_client", self.notify_client) self.data_processing_unit = data_processing_unit.DataProcessingUnit( self.on_data_received_emitter, self.on_notification_emitter, self.command_set) self.data_processing_unit.start_processing() args = mic_vad_streaming_args.VADArgs( self.model_file, self.scorer_file, self.vad_aggression_factor, self.input_device_index, self.sample_rate, self.file_path, self.nospinner, self.savewav, self.on_data_received_emitter) vadToDeepSpeechTool.main(args)