class Client: def __init__(self, host='localhost', port='8888'): self._url = 'ws://{}:{}/exchange'.format(host, port) self.conn = None self.opened = Subject() self.messages = Subject() def connect(self): def on_connect(conn): self.conn = conn self.opened.on_next(conn) self.opened.on_completed() self.opened.dispose() def on_message_callback(message): self.messages.on_next(message) future = websocket_connect( self._url, on_message_callback=on_message_callback ) Observable.from_future(future).subscribe(on_connect) def write_message(self, message): self.conn.write_message(message)
class TtyScanner(object): def __init__(self) -> None: self.__added_devices = Subject() self.__removed_devices = Subject() self.__stop_flag = threading.Event() def scan(self) -> None: threading.Thread(target=self.__work).start() def __work(self) -> None: context = pyudev.Context() monitor = pyudev.Monitor.from_netlink(context) monitor.filter_by(subsystem="tty") monitor.enable_receiving() for device in context.list_devices(subsystem="tty", ID_BUS="usb"): self.__added_devices.on_next(device) while not self.__stop_flag.is_set(): device = monitor.poll(timeout=1) if device is None: continue if not re.search("ttyUSB\\d+", device.sys_name): continue if device.action == "add": self.__added_devices.on_next(device) elif device.action == "remove": self.__removed_devices.on_next(device) def stop(self) -> None: self.__stop_flag.set() self.__added_devices.dispose() self.__removed_devices.dispose() @property def added_devices(self) -> Observable[Device]: return self.__added_devices @property def removed_devices(self) -> Observable[Device]: return self.__removed_devices
class Device(Generic[T], Closeable, ABC): def __init__(self): super().__init__() self.__latest_values: Dict[ValueType, DeviceValue] = dict() self.__value_subject = Subject() def close(self, reason: str = None) -> None: super().close(reason) self.__value_subject.dispose() def get_values(self) -> Observable: return rx.concat(rx.from_list(self.__latest_values.values()), self.__value_subject) @abstractmethod def get_type(self) -> DeviceType: pass @abstractmethod def get_product(self) -> str: pass @abstractmethod def get_serial_number(self) -> str: pass def _publish_value(self, value: DeviceValue) -> None: self.__latest_values[value.type] = value self.__value_subject.on_next(value) def __hash__(self) -> int: return hash(self.get_serial_number()) def __eq__(self, other: Device) -> bool: return self.get_serial_number() == other.get_serial_number() def __str__(self): return f"{self.get_product()} ({self.get_serial_number()})"
class DockerExperiment(): def __init__(self, env): self.counter = 0 self.state = "work" self.env = env self.problem_id = env["problem"]["problem_id"] self.consumed_messages = Subject() self.messages = Subject() self.population_objects_topic = "population-objects" self.consumed_messages\ .filter(lambda x: x["problem"]["problem_id"] == self.problem_id) \ .take(env["problem"]["max_iterations"])\ .buffer_with_count(3)\ .subscribe( on_next=lambda x : self.population_mixer(x),on_completed = self.finish) self.consumed_messages.subscribe( lambda message: self.one_more(message), on_completed=lambda: print("MESSAGES COMPLETED")) self.messages.publish() self.messages.subscribe( lambda populations: self.produce(populations), on_completed=lambda: print("MESSAGES COMPLETED")) def one_more(self, message): #print(message) print('CONSUMED:{}, Max {}'.format( self.counter, self.env["problem"]["max_iterations"])) self.counter += 1 if 'best_score' in message: error = abs(message['best_score'] - message["fopt"]) print('Best:{}, Fopt {}, Error {}'.format(message['best_score'], message["fopt"], error)) if 1e-8 >= error: self.finish() def finish(self): print("Consume Finished") self.state = "stop" self.messages.on_completed() self.messages.dispose() #sys.exit(0) def population_mixer(self, populations): if len(populations) == 3: print("MIXER:", len(populations)) #populations = [json.loads(message.data) for message in populations]contr populations[0]['population'] = cxBestFromEach( populations[0]['population'], populations[1]['population']) populations[1]['population'] = cxBestFromEach( populations[1]['population'], populations[2]['population']) populations[2]['population'] = cxBestFromEach( populations[2]['population'], populations[0]['population']) # I can´t fo map(...on_next, populations ) self.messages.on_next(populations[0]) self.messages.on_next(populations[1]) self.messages.on_next(populations[2]) def read_from_queue(self): print("worker start") while self.state == 'work': print('working') data = None message = r.blpop(TOPIC_CONSUME, 2) if not message: print("NO DATA, WAITING...") time.sleep(2) else: data = message[1] pop_dict = json.loads(data) #print("message:data:", pop_dict) #print("message:type:", type(pop_dict)) #if 'best_score' in pop_dict: # error = abs(pop_dict['best_score']-pop_dict["fopt"]) # print ('Best:{}, Fopt {}, Error {}'.format( pop_dict['best_score'], pop_dict["fopt"], error )) #if 1e-8 >= error: # self.finish() print("message read from queue") self.log_to_redis_coco(pop_dict) self.consumed_messages.on_next(pop_dict) return self.problem_id def produce(self, population): print("pop sent:", "population") json_data = json.dumps(population) # Data must be a bytestring message = json_data.encode('utf-8') ack = r.lpush(TOPIC_PRODUCE, message) print("Produce:", ack) def log_to_redis_coco(self, population): log_name = "log:swarm" r.lpush(log_name, json.dumps(self.get_benchmark_data(population))) def get_benchmark_data(self, population): #print("\n\npopulation\n\n", population) return { "time_stamp": datetime.timestamp(datetime.now()), "evals": population["iterations"], "instance": population["problem"]["instance"], "worker_id": population["worker_id"], "params": { "sample_size": population["population_size"], "init": "random:[-5,5]", "NGEN": population["params"]["GA"]["iterations"] }, "experiment_id": population['experiment']["experiment_id"], "algorithm": population["algorithm"], "alg_params": population["params"][population["algorithm"]], "dim": population["problem"]["dim"], "benchmark": population["problem"]["function"], "fopt": population["fopt"], "message_counter": self.counter, "message_id": population["message_id"], "best_score": ("best_score" in population and population["best_score"]) or None }
class ControlledSubject(Observable): def __init__(self, enable_queue=True): super(ControlledSubject, self).__init__(self._subscribe) self.subject = Subject() self.enable_queue = enable_queue self.queue = [] if enable_queue else None self.requested_count = 0 self.requested_disposable = Disposable.empty() self.error = None self.has_failed = False self.has_completed = False self.controlled_disposable = Disposable.empty() def _subscribe(self, observer): return self.subject.subscribe(observer) def on_completed(self): check_disposed(self) self.has_completed = True if not self.enable_queue or not len(self.queue): self.subject.on_completed() def on_error(self, error): check_disposed(self) self.has_failed = True self.error = error if not self.enable_queue or not len(self.queue): self.subject.on_error(error) def on_next(self, value): check_disposed(self) has_requested = False if not self.requested_count: if self.enable_queue: self.queue.push(value) else: if self.requested_count != -1: requested_count = self.requested_count self.requested_count -= 1 if requested_count == 0: self.dispose_current_request() has_requested = True if has_requested: self.subject.on_next(value) def _process_request(self, number_of_items): if self.enable_queue: #console.log('queue length', self.queue.length) while len(self.queue) >= number_of_items and number_of_items > 0: # console.log('number of items', number_of_items) self.subject.on_next(self.queue.shift()) number_of_items -= 1 if len(self.queue): return { "number_of_items": number_of_items, "return_value": True } else: return { "number_of_items": number_of_items, "return_value": False } if self.has_failed: self.subject.on_error(self.error) self.controlled_disposable.dispose() self.controlled_disposable = Disposable.empty() elif self.has_completed: self.subject.on_completed() self.controlled_disposable.dispose() self.controlled_disposable = Disposable.empty() return {"number_of_items": number_of_items, "return_value": False} def request(self, number): check_disposed(self) self.dispose_current_request() r = self._process_request(number) number = r["number_of_items"] if not r["return_value"]: self.requested_count = number def action(): self.requested_count = 0 self.requested_disposable = Disposable(action) return self.requested_disposable else: return Disposable.empty() def dispose_current_request(self): self.requested_disposable.dispose() self.requested_disposable = Disposable.empty() def dispose(self): self.is_disposed = True # FIXME: something wrong in RxJS? self.error = None self.subject.dispose() self.requested_disposable.dispose()
class ControlledSubject(Observable): def __init__(self, enable_queue=True): super(ControlledSubject, self).__init__(self._subscribe) self.subject = Subject() self.enable_queue = enable_queue self.queue = [] if enable_queue else None self.requested_count = 0 self.requested_disposable = Disposable.empty() self.error = None self.has_failed = False self.has_completed = False self.controlled_disposable = Disposable.empty() def _subscribe(self, observer): return self.subject.subscribe(observer) def on_completed(self): check_disposed(self) self.has_completed = True if not self.enable_queue or not len(self.queue): self.subject.on_completed() def on_error(self, error): check_disposed(self) self.has_failed = True self.error = error if not self.enable_queue or not len(self.queue): self.subject.on_error(error) def on_next(self, value): check_disposed(self) has_requested = False if not self.requested_count: if self.enable_queue: self.queue.push(value) else: if self.requested_count != -1: requested_count = self.requested_count self.requested_count -= 1 if requested_count == 0: self.dispose_current_request() has_requested = True if has_requested: self.subject.on_next(value) def _process_request(self, number_of_items): if self.enable_queue: #console.log('queue length', self.queue.length) while len(self.queue) >= number_of_items and number_of_items > 0: # console.log('number of items', number_of_items) self.subject.on_next(self.queue.shift()) number_of_items -= 1 if len(self.queue): return { "number_of_items": number_of_items, "return_value": True } else: return { "number_of_items": number_of_items, "return_value": False } if self.has_failed: self.subject.on_error(self.error) self.controlled_disposable.dispose() self.controlled_disposable = Disposable.empty() elif self.has_completed: self.subject.on_completed() self.controlled_disposable.dispose() self.controlled_disposable = Disposable.empty() return { "number_of_items": number_of_items, "return_value": False } def request(self, number): check_disposed(self) self.dispose_current_request() r = self._process_request(number) number = r["number_of_items"] if not r["return_value"]: self.requested_count = number def action(): self.requested_count = 0 self.requested_disposable = Disposable(action) return self.requested_disposable else: return Disposable.empty() def dispose_current_request(self): self.requested_disposable.dispose() self.requested_disposable = Disposable.empty() def dispose(self): self.is_disposed = True # FIXME: something wrong in RxJS? self.error = None self.subject.dispose() self.requested_disposable.dispose()
from rx.subjects import Subject print("50以下は無効化してしまう壁\n") stream = Subject() d = stream.do_action(lambda x: print(x)) \ .filter(lambda param: param>50) \ .subscribe(lambda result: print("壁を貫通!{0}のダメージ".format(result))) # 攻撃! stream.on_next(0) stream.on_next(50) stream.on_next(51) stream.on_next(49) stream.on_next(100) stream.on_next(-50) stream.dispose() print("===================") stream = Subject() d = stream.do_action(lambda x: print(x)).subscribe() stream.on_next(0) stream.on_next(-50) stream.dispose() print("===================") from rx import Observable from rx.subjects import Subject # l1 = [1,2,3,4,5] # l = Subject() # grouped = l.group_by(lambda x: x % 2).do_action(lambda x: print(x)).subscribe()
class AbstractObservableCollection(ABC, Iterable): def __init__(self): self._collectionChanges = Subject() self.lock = threading.RLock() self.is_disposed = False self._suppressNotification = False @abstractmethod def __iter__(self): pass @abstractmethod def __eq__(self, other): pass @abstractmethod def __ne__(self, other): pass @abstractmethod def __contains__(self, item): pass @abstractmethod def __len__(self): pass @abstractmethod def dispose(self): """ Clears all the values from the set, unsubscribe all the subscribers and release resources """ self.check_disposed() self._collectionChanges.dispose() self.is_disposed = True def when_collection_changes(self) -> ObservableBase: return Observable.create(lambda obs: self._subscribe(obs)) def _subscribe(self, observer: Observer) -> Disposable: if self.is_disposed: return Observable.throw(DisposedException('Trying to access an already disposed object')) \ .subscribe(observer) else: return self._collectionChanges.subscribe(observer) def _onCollectionChanges(self, item: CollectionChange): if not self._suppressNotification: try: self._collectionChanges.on_next(item) except Exception as ex: self._collectionChanges.on_error(ex) # internal methods def _beginSuppressNotification(self) -> None: """ Suppresses all change notification from firing """ self._suppressNotification = True def _endSuppressNotification(self) -> None: """ Resumes or Begins pushing change notifications for every subsequent change operations made """ self._suppressNotification = False def check_disposed(self): if self.is_disposed: raise DisposedException( 'Trying to access an already disposed object')
class BusManager(object): def __init__(self) -> None: self.__bus_subject = Subject() self.__bus_map: Dict[str, Bus] = dict() self.__scanner = TtyScanner() x = Observer() self.__scanner.added_devices.s self.__scanner.added_devices.subscribe( lambda device: self.__tty_opened(device)) self.__scanner.removed_devices.subscribe(self.__tty_closed) self.__scanner.removed_devices.subscribe(Observer()) self.__scanner.scan() def __tty_opened(self, device: pyudev.Device) -> None: try: bus = self.__create_bus(device) self.__bus_map[device.device_node] = bus self.__bus_subject.on_next(bus) except NoPortConfigException as e: logging.warning(e) def __tty_closed(self, device: pyudev.Device) -> None: if device.device_node not in self.__bus_map: return bus = self.__bus_map.pop(device.device_node) bus.close(f"Port {bus.serial.port} disconnected") def get_buses(self) -> Observable: return rx.concat(rx.from_list(self.__bus_map.values()), self.__bus_subject) def dispose(self) -> None: self.__scanner.stop() for bus in self.__bus_map.values(): bus.close() self.__bus_subject.dispose() @staticmethod def __create_bus(device: pyudev.Device) -> Bus: protocol = portconfig.get_protocol(device) serial = Serial(port=device.device_node, baudrate=9600) if protocol is Protocol.MODBUS: return ModBus(serial) if protocol is Protocol.CANBUS: return CanBus(serial) raise NoPortConfigException(device)