def cmdparse(self,cmd): try: if cmd == "exit": self.transport.loseConnection() return elif cmd == "jpeg": url = previewjpeg() if url: self.transport.write(url) else: self.transport.write("nothing") print("nothing to take jpeg") return elif cmd == "auto": td_auto.automode = True print("Enter the auto mode , The car will drive itself") return elif cmd == "manul": td_auto.automode = False print("Enter the manul mode ,You can control it remote") return part,partcmd = cmd.split(" ",1) if part=="motor": td_dcmotor.runcmd(partcmd) elif part=="tts": reactor.callInThread(netTalk,partcmd) except Exception as e: print("ahahah...",e)
def run_import_thread(self): log.debug("run_import_thread current size: %d", self.q.qsize()) if self.q.qsize() >= settings.DB_LOADER_REC_MIN or time.time() >= self.next_force_import_time: # Don't incur thread overhead if we're not going to run reactor.callInThread(self.import_thread) self.scheduleImport()
def interactive_main(args): remote = args.remote shell = RemoteShell(remote, args.username, args.password) response = yield shell.create() intro = '\n'.join(response.stdout) winrs_cmd = WinrsCmd(shell) reactor.callInThread(winrs_cmd.cmdloop, intro)
def msg_received(self, conn, msg): """Handles messages received from the TI server. Starts the TopologyInteractor command-line interface once authentication is complete.""" if msg is not None: if msg.get_type() == VNSAuthRequest.get_type(): print 'Authenticating as %s' % self.username sha1_of_salted_pw = hashlib.sha1(msg.salt + self.auth_key).digest() conn.send(VNSAuthReply(self.username, sha1_of_salted_pw)) elif msg.get_type() == VNSAuthStatus.get_type(): if msg.auth_ok: print 'Authentication successful.' conn.send(TIOpen(self.tid)) reactor.callInThread(TopologyInteractor(self).cmdloop) else: print 'Authentication failed.' elif msg.get_type() == TIBadNodeOrPort.get_type(): txt = str(msg) if self.prev_bn_msg == txt: self.prev_bn_msg = None # only stop it once else: if self.prev_bn_msg != None: print '***%s!=%s'%(self.prev_bn_msg,txt) self.prev_bn_msg = txt print '\n', txt elif msg.get_type() == TIBanner.get_type(): print '\n', msg.msg elif msg.get_type() == TIPacket.get_type(): self.got_tapped_packet(msg) else: print 'unexpected TI message received: %s' % msg
def consume(self, msg): """Called with each incoming fedmsg. From here we trigger an rpm-ostree compose by touching a specific file under the `touch_dir`. Then our `doRead` method is called with the output of the rpm-ostree-toolbox treecompose, which we monitor to determine when it has completed. """ self.log.info(msg) body = msg['body'] topic = body['topic'] repo = None if 'rawhide' in topic: arch = body['msg']['arch'] self.log.info('New rawhide %s compose ready', arch) repo = 'rawhide' elif 'branched' in topic: arch = body['msg']['arch'] branch = body['msg']['branch'] self.log.info('New %s %s branched compose ready', branch, arch) log = body['msg']['log'] if log != 'done': self.log.warn('Compose not done?') return repo = branch elif 'updates.fedora' in topic: self.log.info('New Fedora %(release)s %(repo)s compose ready', body['msg']) repo = 'f%(release)s-%(repo)s' % body['msg'] else: self.log.warn('Unknown topic: %s', topic) release = self.releases[repo] reactor.callInThread(self.compose, release)
def main(server_url, identity_server_url, username, token, config_path): print "Synapse command line client" print "===========================" print "Server: %s" % server_url print "Type 'help' to get started." print "Close this console with CTRL+C then CTRL+D." if not username or not token: print "- 'register <username>' - Register an account" print "- 'stream' - Connect to the event stream" print "- 'create <roomid>' - Create a room" print "- 'send <roomid> <message>' - Send a message" http_client = TwistedHttpClient() # the command line client syn_cmd = SynapseCmd(http_client, server_url, identity_server_url, username, token) # load synapse.json config from a previous session global CONFIG_JSON CONFIG_JSON = config_path # bit cheeky, but just overwrite the global try: with open(config_path, 'r') as config: syn_cmd.config = json.load(config) try: http_client.verbose = "on" == syn_cmd.config["verbose"] except: pass print "Loaded config from %s" % config_path except: pass # Twisted-specific: Runs the command processor in Twisted's event loop # to maintain a single thread for both commands and event processing. # If using another HTTP client, just call syn_cmd.cmdloop() reactor.callInThread(syn_cmd.cmdloop) reactor.run()
def run(self): self.factory = get_factory(WebSocketServerFactory)("ws://0.0.0.0:%i" % self.port, debug=False) self.factory.protocol = get_protocol(WebSocketServerProtocol) reactor.listenTCP(self.port, self.factory) reactor.callInThread(self.backend_reader) reactor.callLater(1, self.keepalive_sender) reactor.run()
def userKicked(self, nick, channel, kicker, message): self.nicks[channel].remove(nick) self.logger.log(channel, nick, "has been kicked by %s (%s)" % (kicker, message)) for name, module in self.loaded.items(): for hook in module["hooks"]: if hasattr(hook, "onKick") and hook.onKick: reactor.callInThread(hook, self, nick, channel, kicker, message)
def action(self, nick, channel, action): nick = re.match(self.nick_regex, nick) self.logger.log(channel, nick.group(1), action) for name, module in self.loaded.items(): for hook in module["hooks"]: if hasattr(hook, "onAction") and hook.onAction: reactor.callInThread(hook, self, nick, channel, action)
def userJoined(self, nick, channel): self.nicks[channel].append(nick) self.logger.log(channel, nick, "has joined.") for name, module in self.loaded.items(): for hook in module["hooks"]: if hasattr(hook, "onJoin") and hook.onJoin: reactor.callInThread(hook, self, nick, channel)
def userLeft(self, nick, channel): self.nicks[channel].remove(nick) self.logger.log(channel, nick, "has left.") for name, module in self.loaded.items(): for hook in module["hooks"]: if hasattr(hook, "onPart") and hook.onPart: reactor.callInThread(hook, self, nick, channel)
def __thread_write(self): if not hasattr(self, '__thread_write_status') : self.__thread_write_status = 'stopped' if self.__thread_write_status == 'running' : return if not self.buffer_dirty : return bfd = self.buffer_dirty.copy() def call_in_thread(): # Writing to disk for idx in sorted(bfd.keys()) : data = bfd[idx] self.write(idx, data) reactor.callFromThread(call_from_thread) def call_from_thread(): self.__thread_write_status = 'stopped' for idx, data in bfd.iteritems() : if data is self.buffer_dirty[idx] : del self.buffer_dirty[idx] if self.__thread_write_status == 'stopped' : self.__thread_write_status = 'running' reactor.callInThread(call_in_thread)
def _flush(self): "Called on a scheudle by twisted to flush the filters" self.logger.info("Starting scheduled flush") for name,filt in self.filters.items(): if isinstance(filt, ProxyFilter): continue reactor.callInThread(self.flush_filter, name) self.logger.debug("Ending scheduled flush.")
def callMultipleInThread(tupleList): """Run a list of functions in the same thread. tupleList should be a list of (function, argsList, kwargsDict) tuples. """ from twisted.internet import reactor reactor.callInThread(_runMultiple, tupleList)
def __launch_blocker_to_badboy(self, user_id): session_uid = self.quarterback.win32top.get_current_user_session() if int(session_uid) == int(user_id) : reactor.callInThread(self.__launch_blocker_thread, user_id, self) else: self.block_status.pop(self.block_status.index(user_id)) return False
def deferToThreadInReactor(reactor, f, *args, **kwargs): """ Run function in thread and return result as Deferred. """ d = defer.Deferred() reactor.callInThread(_putResultInDeferred, reactor, d, f, args, kwargs) return d
def post(self, *args): if len(args) >= 1: name = args[0] project = Projects(name) for key, value in self.request.arguments.iteritems(): if key in ("git_url", "version", "build_cmd", "install_cmd"): setattr(project, key, value[0]) project.save() try: if not Projects(self.get_argument('name')).exists(): raise except Exception, e: project = Projects() project.name = self.get_argument('name')[0] project.git_url = self.get_argument('git_url')[0] for name, parm in self.request.arguments.iteritems(): if name not in ('branch', 'version'): setattr(project, str(name), parm[0]) try: project.add_branch(self.get_argument('branch')) project.version(self.get_argument('branch'), self.get_argument('version')) project.group_name = self.get_argument('group_name') project.save() log.msg('Project created:', project.name) reactor.callInThread(queue.enqueue, 'build', 'builder.build_project', {'project': project.name, 'branch': self.get_argument('branch'), 'force': True}) self.write(cyclone.escape.json_encode({'status': 'ok'})) except Exception, e: log.err() self.write(cyclone.escape.json_encode({'status': "fail"}))
def notify(self, event, origin=None, args=[]): event = event.lower() logging.debug('Dispatching event {0}'.format(event)) for priority in ('high', 'medium', 'low'): items = self.commands[priority] if not event in items: logging.debug('No observers for {0}.{1}'.format(priority, event)) continue for func in items.get(event): if event == 'privmsg': text = unicode(args[0], 'utf-8', errors='ignore') else: text = ','.join(args) match = False if func.regexp: for regex in func.regexp: match = regex.match(text) logging.debug('Checking {1}: {2}'.format(text.encode('utf-8'), regex.pattern, bool(match))) if match: break else: match = True if match: #if self.limit(origin, func): continue bot = self.wrapped(origin, args) input = self.input(origin, text, match, event, args) if func.thread: reactor.callInThread(self.call, func, origin, bot, input) else: self.call(func, origin, bot, input)
def call(self, f, *args, **kwargs): tc, self.tc = self.tc + 1, self.tc + 1 self.th[tc] = (f, args, kwargs) if config.USE_THREADS: reactor.callInThread(self._call, f, tc, *args, **kwargs) else: self._call(f, tc, *args, **kwargs) try: self.th.pop(tc) except: self.log.err('Something wrong with threads management: can\'t self.th.pop(%s)' % (tc, ))
def testCallFromThread(self): for i in range(self.numRounds): reactor.callInThread(self.tcmf_2, time.time()) self.wait() assert len(self.in_times) == len(self.from_times) assert len(self.in_times) == self.numRounds self.printResult()
def message_from_client(self, message, client): if message[0] == 'C': if client in self.__delayed_config: # The client asks for a second time in a short while. Don't send anything now, but do send it a bit later logger.info('Delaying config for %s', client) self.__delayed_config[client] = True return logger.debug('Sending config to %s', client) self.__delayed_config[client] = False # We know about the client, but it hasn't asked twice yet. if self.version(client) < 2: self.send(self.__build_config(''), client) else: self.send(self.__build_config('-diff'), client) for a in self._addresses: self.send(self.__build_filter_version(a, self._addresses[a][0], self._addresses[a][1]), client) elif message[0] == 'D': logger.debug('Flows from %s', client) activity.log_activity(client, 'flow') if not self.__rate_limiter.check_rate(client, 1): logger.warn("Storing flows for client %s blocked by rate limiter.", client) return # the limit for the number of records in a message is 2*max_flows because the client may buffer up to two times the number if he disconnects/reconnects reactor.callInThread(store_flows, 2 * int(self._conf['max_flows']), client, message[1:], int(self._conf['version']), database.now()) elif message[0] == 'U': self._provide_diff(message[1:], client)
def __flow_stat_job(mk_db): def execute(mk_db): log.msg("start flow stat task..") db = mk_db() try: nodes = db.query(models.SlcNode) for node in nodes: r = db.query( func.sum(models.SlcRadOnline.input_total).label("input_total"), func.sum(models.SlcRadOnline.output_total).label("output_total") ).filter( models.SlcRadOnline.account_number == models.SlcRadAccount.account_number, models.SlcRadAccount.member_id == models.SlcMember.member_id, models.SlcMember.node_id == node.id ).first() if r: stat = models.SlcRadFlowStat() stat.node_id = node.id stat.stat_time = int(time.time()) stat.input_total = r.input_total stat.output_total = r.output_total db.add(stat) db.commit() log.msg("flow stat task done") except Exception as err: db.rollback() log.err(err,'flow_stat_job err') finally: db.close() reactor.callInThread(execute,mk_db)
def onMessage(self, payload, isBinary): if not isBinary: doc = json.loads(payload) # If type is "_attach", treat as attachment metadata if doc.get("type") == "_attach": self.factory.binmeta[self.peer] = doc else: # Interpret incoming comands as database updates if doc.get("_deleted", False): did_delete = self.factory.db.delete_doc(doc["_id"], initiator=self) upd = {"ok": did_delete, "_id": doc["_id"]} else: upd = self.factory.db._try_update(doc, initiator=self) # Indicate success # TODO: indicate failure self.sendMessage(json.dumps(upd)) else: metadoc = self.factory.binmeta[self.peer] del self.factory.binmeta[self.peer] docid = metadoc["id"] attachname = metadoc["name"] dbdoc = self.factory.db.docs.get(docid) reactor.callInThread(dbdoc._async_put_attachment, StringIO(payload), None, attachname)
def task_check_for_job_state_changes(): """ Checks for job state changes in a non-blocking manner. Calls :py:func:`threaded_check_for_job_state_changes`. """ reactor.callInThread(threaded_check_for_job_state_changes)
def task_manage_ec2_instances(): """ Calls the instance creation logic in a non-blocking manner. Calls :py:func:`threaded_manage_ec2_instances`. """ reactor.callInThread(threaded_manage_ec2_instances)
def initializeWAMP(self): # define read and write locks self.rlock = None self.wlock = None # connect to the spectrometer self.raw = bool(RAW) self.spectrometer = oceanoptics.USB2000plus() self.spectrometer.integration_time(time_sec=INTEGRATION_TIME) self.wl = list(self.spectrometer.wavelengths()) self.sp = list(self.spectrometer.intensities()) # read new values off of spectrometer, lock while reading or writing @inlineCallbacks def capture(): yield self.rlock self.wlock = Deferred() self.sp = list(self.spectrometer.intensities()) time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f") self.latestTime = time self.wlock.callback(None) self.wlock = None reactor.callLater(.1,capture) reactor.callInThread(capture) ## complete initialization BaseWAMP.initializeWAMP(self)
def loop(xbmc_uri, auth, s, last_playing=None, use_reactor=False): print "loop(%r, %r, %r, %r, %r)" % (xbmc_uri, auth, s, last_playing, use_reactor) try: playing = get_xbmc_current_playing(xbmc_uri, auth).encode("ascii", "ignore") except: print "error getting xbmc data" playing = None # print repr(playing) # print repr(last_playing) # print if playing != last_playing: if playing == None: playing_f = s.format_text("", RED, 0) else: playing_f = s.format_text(playing, GREEN, 0) s.send_text(2, playing_f, speed=15) s.set_clock() # s.send_text(0, s.format_text('LOO', RED, 0)) last_playing = playing sleep(3.0) if use_reactor: reactor.callInThread(loop, xbmc_uri, auth, s, last_playing, True)
def __online_stat_job(mk_db): def execute(mk_db): log.msg("start online stat task..") db = mk_db() try: nodes = db.query(models.SlcNode) for node in nodes: online_count = db.query(models.SlcRadOnline.id).filter( models.SlcRadOnline.account_number == models.SlcRadAccount.account_number, models.SlcRadAccount.member_id == models.SlcMember.member_id, models.SlcMember.node_id == node.id ).count() stat = models.SlcRadOnlineStat() stat.node_id = node.id stat.stat_time = int(time.time()) stat.total = online_count db.add(stat) db.commit() log.msg("online stat task done") except Exception as err: db.rollback() log.err(err,'online_stat_job err') finally: db.close() reactor.callInThread(execute,mk_db)
def build_reactor(options, **kwargs): web_socket_instance = FilteredWebSocketFactory(**kwargs) subscriber = kwargs.pop("subscriber", None) if options.key and options.cert: with open(options.key) as keyFile: with open(options.cert) as certFile: cert = ssl.PrivateCertificate.loadPEM(keyFile.read() + certFile.read()) reactor.listenSSL(options.port, web_socket_instance, cert.options()) else: reactor.listenTCP( options.port, web_socket_instance ) if subscriber is not None: reactor.callInThread( subscriber.listener, web_socket_instance ) reactor.addSystemEventTrigger( "before", "shutdown", subscriber.kill ) # Start the consumer loop consumer_loop = LoopingCall( web_socket_instance.consumer ) consumer_loop.start(0.001, now=False) return web_socket_instance
def received(self, msg): """ This is a direct callback from the protocol object. This call is forwarded to the dispatcher in a thread from the threadpool. The """ if self.dispatcher is not None: reactor.callInThread(self.dispatcher.receivedEvent, msg)
def main(just_launched=False): # set to false by exit process, which signals other processes to end (exit also sends an 'exit' or 'quit' is_program_running = multiprocessing.Event() is_program_running.set() # used set to true when block mining and then to false after block winner has been chosen # used by exit process, to avoid stopping program in the middle of this process. # which can result in a loss of value is_not_in_process_of_creating_new_block = multiprocessing.Event() is_not_in_process_of_creating_new_block.set() # input admin name and password admin_name = input("admin name: ") password = getpass("password: "******"Wrong Password" if admin is None: ans = input( "No admin id under that admin name, would you like to create a new admin id? y/N " ) if ans.lower() == "y": admin = Admin(admin_name=admin_name, password=password, newAdmin=True, is_sandbox=False) else: exit(0) print(admin) print(vars(admin)) admin.load_startup_files() # instantiate a levelDB manager class db_manager = OrsesLevelDBManager(admin_inst=admin) db_manager.load_required_databases() admin.load_db_manager(db_manager=db_manager) # *** instantiate queue variables *** q_for_compete = multiprocessing.Queue() if ( admin.isCompetitor is True and admin.currenty_competing is True) else None q_for_validator = multiprocessing.Queue() q_for_propagate = multiprocessing.Queue() q_for_bk_propagate = multiprocessing.Queue() q_for_block_validator = multiprocessing.Queue( ) # between block validators and block propagators q_for_initial_setup = multiprocessing.Queue() # goes to initial setup q_object_from_protocol = multiprocessing.Queue( ) # goes from protocol to message sorter q_object_from_compete_process_to_mining = multiprocessing.Queue( ) # q between compete_process and handle_new_block # instantiate mempool object mempool = MemPool(admin_inst=admin) admin.load_mempool_instance(mempool_inst=mempool) # instantiate the competitor class competitor = Competitor( reward_wallet="W884c07be004ee2a8bc14fb89201bbc607e75258d", admin_inst=admin, just_launched=just_launched, is_program_running=is_program_running) def callback_non_compete(prev_block): reactor.callInThread(competitor.non_compete_process, q_for_block_validator=q_for_block_validator, reactor_inst=reactor, last_block=prev_block) # start compete(mining) process, if compete is yes. process is started using separate process (not just thread) if admin.isCompetitor is True and admin.currenty_competing is True: # multiprocessing event objects is_generating_block = multiprocessing.Event() has_received_new_block = multiprocessing.Event() # start compete thread using twisted reactor's thread reactor.callInThread(competitor.compete, q_for_compete=q_for_compete, q_object_from_compete_process_to_mining= q_object_from_compete_process_to_mining, is_generating_block=is_generating_block, has_received_new_block=has_received_new_block, is_not_in_process_of_creating_new_block= is_not_in_process_of_creating_new_block) # start process for actual hashing p = multiprocessing.Process( target=competitor.handle_new_block, kwargs={ "q_object_from_compete_process_to_mining": q_object_from_compete_process_to_mining, "q_for_block_validator": q_for_block_validator, "is_generating_block": is_generating_block, "has_received_new_block": has_received_new_block, "is_program_running": is_program_running, "is_not_in_process_of_creating_new_block": is_not_in_process_of_creating_new_block }) p.daemon = False p.start() elif admin.is_validator: # callback_non_compete() will be passed as a callback function to BlockchainPropagator.initial_setup # once initial setup is done and recent block is not none it will be called in # send_response_to_other_threads function defined in initial_setup method pass # *** start blockchain propagator in different thread *** blockchain_propagator = BlockChainPropagator( mempool=mempool, q_object_connected_to_block_validator=q_for_block_validator, q_object_to_competing_process=q_for_compete, q_for_bk_propagate=q_for_bk_propagate, q_object_between_initial_setup_propagators=q_for_initial_setup, reactor_instance=reactor, admin_instance=admin, is_program_running=is_program_running) # *** set intial setup to start in 3 seconds. This will get new blocks and data before other processes start *** reactor.callLater(3.0, blockchain_propagator.initial_setup, callback_non_compete) # *** start blockchain propagator manager in separate thread *** reactor.callInThread(blockchain_propagator.run_propagator_convo_manager) # *** start blockchain propagator initiator in separate thread *** reactor.callInThread(blockchain_propagator.run_propagator_convo_initiator) # *** Instantiate Network Propagator *** propagator = NetworkPropagator( mempool=mempool, q_object_connected_to_validator=q_for_validator, q_for_propagate=q_for_propagate, reactor_instance=reactor, q_object_between_initial_setup_propagators=q_for_initial_setup, is_sandbox=False, q_object_to_competing_process=q_for_compete, admin_inst=admin) # *** start propagator manager in another thread *** reactor.callInThread(propagator.run_propagator_convo_manager) # *** start propagator initiator in another thread *** reactor.callInThread(propagator.run_propagator_convo_initiator) # *** instantiate network message sorter *** network_message_sorter = NetworkMessageSorter( q_object_from_protocol, q_for_bk_propagate, q_for_propagate, node=None, admin=admin, b_propagator_inst=blockchain_propagator, n_propagator_inst=propagator) # *** start network manaager and run veri node factory and regular factory using reactor.callFromThread *** network_manager = NetworkManager( admin=admin, q_object_from_protocol=q_object_from_protocol, q_object_to_validator=q_for_validator, net_msg_sorter=network_message_sorter, reg_listening_port=55600, reg_network_sandbox=False) # *** run sorter in another thread *** reactor.callInThread(network_message_sorter.run_sorter) # *** use to connect to and listen for connection from other verification nodes *** reactor.callFromThread(network_manager.run_veri_node_network, reactor) # *** use to listen for connections from regular nodes *** reactor.callFromThread(network_manager.run_regular_node_network, reactor) # *** creates a deferral, which allows user to exit program by typing "exit" or "quit" *** reactor.callWhenRunning( send_stop_to_reactor, reactor, None, # q object to each node is None is_program_running, # Event object to set to true or false is_not_in_process_of_creating_new_block, # Event object used to wait for best time to exit None, # DummyInternet is None q_for_propagate, q_for_bk_propagate, q_for_compete, q_object_from_protocol, q_for_validator, q_for_block_validator, 0 # number of nodes is zero because this is main function ) # *** set propagator's network manager variable to network manager instance *** propagator.network_manager = network_manager # create wallets balance db with genesis block, if does not exist db_manager.create_load_wallet_balances_from_genesis_block() # *** start reactor *** reactor.run() # *** This will only print when reactor is stopped print("Node Stopped") # *** when reactor is stopped save admin details *** admin.save_admin()
def aggregate_region_operation_metric(self): reactor.callInThread(self.aggregate_region_operation_metric_in_thread)
def update_metrics(self, metricsRawData): try: reactor.callInThread(self.update_metrics_in_thread, metricsRawData) except Eception, e: self.schedule_next_fetch()
def do_long_thread_command(self, finished): log.msg('Starting command handling thread.') reactor.callInThread(threading_command, finish_defer=finished)
def resumeProducing(self): self.paused = False if not self.running: self.running = True reactor.callInThread(self._collectData)
def start(self): self._stop = False reactor.callInThread(self.mine)
def callback_non_compete(prev_block): reactor.callInThread(competitor.non_compete_process, q_for_block_validator=q_for_block_validator, reactor_inst=reactor, last_block=prev_block)
def plot(self, c, settings_json='{}'): settings = json.loads(settings_json) if not self.is_plotting: reactor.callInThread(self._plot, settings) else: print 'still making previous plot'
class GrpcClient(object): def __init__(self, connection_manager, channel, grpc_timeout, core_binding_key, core_transaction_key): self.connection_manager = connection_manager self.channel = channel self.grpc_timeout = grpc_timeout self.grpc_stub = VolthaServiceStub(channel) # This is the rw-core cluster to which an OFAgent is bound. # It is the affinity router that forwards all OFAgent # requests to a specific rw-core in this back-end cluster. self.core_group_id = '' self.core_group_id_key = core_binding_key # Since the api-router binds an OFAgent to two RW Cores in a pair and # transparently forward requests between the two then the onus is on # the OFAgent to fulfill part of the function of the api-server which # involves sending a transaction key to both RW Cores for the latter # to figure out which Core will handle the transaction. To prevent # collision between the api-server ID and the one from OFAgent then the # OFAgent ID will be prefixed with "O-". self.core_transaction_key = core_transaction_key self.stopped = False self.packet_out_queue = Queue() # queue to send out PacketOut msgs self.packet_in_queue = DeferredQueue() # queue to receive PacketIn self.change_event_queue = DeferredQueue() # queue change events def start(self): log.debug('starting', grpc_timeout=self.grpc_timeout, core_binding_key=self.core_group_id_key, core_transaction_key=self.core_transaction_key) self.start_packet_out_stream() self.start_packet_in_stream() self.start_change_event_in_stream() reactor.callLater(0, self.packet_in_forwarder_loop) reactor.callLater(0, self.change_event_processing_loop) log.info('started') return self def stop(self): log.debug('stopping') self.stopped = True log.info('stopped') def get_core_transaction_metadata(self): return (self.core_transaction_key, "O-" + uuid.uuid4().hex) def start_packet_out_stream(self): def packet_generator(): while 1: try: packet = self.packet_out_queue.get(block=True, timeout=1.0) except Empty: if self.stopped: return else: yield packet def stream_packets_out(): generator = packet_generator() try: self.grpc_stub.StreamPacketsOut( generator, metadata=( (self.core_group_id_key, self.core_group_id), self.get_core_transaction_metadata(), )) except _Rendezvous, e: log.error('grpc-exception', status=e.code()) if e.code() == StatusCode.UNAVAILABLE: os.system("kill -15 {}".format(os.getpid())) reactor.callInThread(stream_packets_out)
def sandbox_main(number_of_nodes: int, reg_network_sandbox=False, preferred_no_of_mining_nodes=0, just_launched=True): """ :param number_of_nodes: number of dummy nodes to create + main node for user :param reg_network_sandbox: if false regular network will not be sandbox. This allows to send data to main node and then see how it reacts with the sandbox nodes :param preferred_no_of_mining_nodes: number of mining nodes out of created nodes must be =< number of nodes :param just_launched: tells node just launched and to start immediately mining :return: """ # set to false by exit process, which signals other processes to end (exit also sends an 'exit' or 'quit' is_program_running = multiprocessing.Event() is_program_running.set() # used set to true when block mining and then to false after block winner has been chosen # used by exit process, to avoid stopping program in the middle of this process. # which can result in a loss of value is_not_in_process_of_creating_new_block = multiprocessing.Event() is_not_in_process_of_creating_new_block.set() assert number_of_nodes >= preferred_no_of_mining_nodes, "number of mining nodes should be less than or equal " \ "to number of created nodes" # ThreadPool setup, 15 thread pools * number of node instances + 15 for main node: t_pool = reactor.getThreadPool() print(f"ThreadPool size is: {t_pool.max}") t_pool.adjustPoolsize(minthreads=0, maxthreads=int((number_of_nodes * 15) + 15)) print(f"ThreadPool size is: {reactor.getThreadPool().max}") print("You Are Running In Sandbox Mode") print("You will be able connect to the sandbox network using a regular client node and test by sending txs\n") if\ reg_network_sandbox is False else \ print("You will not be able to connect to the sandbox network and can only view automated interactions\n") admin_name = input("Type your admin name: ") password = getpass("Type your password: "******"Wrong Password" if admin is None: ans = input( "\nNo admin id under that admin name, would you like to create a new admin id? y/N " ) if ans.lower() == "y": admin = Admin(admin_name=admin_name, password=password, newAdmin=True, is_sandbox=True) else: exit(0) admin.load_startup_files() # instantiate a levelDB manager class db_manager = OrsesLevelDBManager(admin_inst=admin) db_manager.load_required_databases() admin.load_db_manager(db_manager=db_manager) # instantiated Dummy Internet dummy_internet = DummyInternet() # instantiate main node main_node = DummyAdminNode(admin=admin, dummy_internet=dummy_internet, real_reactor_instance=reactor, is_program_running=is_program_running) # *** instantiate queue variables *** q_for_compete = multiprocessing.Queue() if ( admin.isCompetitor is True and admin.currenty_competing is True) else None q_for_validator = multiprocessing.Queue() q_for_propagate = multiprocessing.Queue() q_for_bk_propagate = multiprocessing.Queue() q_for_block_validator = multiprocessing.Queue( ) # between block validators and block propagators q_for_initial_setup = multiprocessing.Queue() # goes to initial setup q_object_from_protocol = multiprocessing.Queue( ) # goes from protocol to message sorter q_object_to_each_node = multiprocessing.Queue() # for exit signal q_object_from_compete_process_to_mining = multiprocessing.Queue( ) # q between compete_process and handle_new_block # instantiate mempool object mempool = MemPool(admin_inst=admin) admin.load_mempool_instance(mempool_inst=mempool) # instantiate the competitor class competitor = Competitor( reward_wallet="W884c07be004ee2a8bc14fb89201bbc607e75258d", admin_inst=admin, is_program_running=is_program_running, just_launched=just_launched, ) def callback_non_compete(prev_block): reactor.callInThread(competitor.non_compete_process, q_for_block_validator=q_for_block_validator, reactor_inst=reactor, last_block=prev_block) # start compete(mining) process, if compete is yes. process is started using separate process (not just thread) if admin.isCompetitor is True and admin.currenty_competing is True: # multiprocessing event objects is_generating_block = multiprocessing.Event() has_received_new_block = multiprocessing.Event() # start compete thread using twisted reactor's thread reactor.callInThread(competitor.compete, q_for_compete=q_for_compete, q_object_from_compete_process_to_mining= q_object_from_compete_process_to_mining, is_generating_block=is_generating_block, has_received_new_block=has_received_new_block, is_not_in_process_of_creating_new_block= is_not_in_process_of_creating_new_block) # start process for actual hashing p = multiprocessing.Process( target=competitor.handle_new_block, kwargs={ "q_object_from_compete_process_to_mining": q_object_from_compete_process_to_mining, "q_for_block_validator": q_for_block_validator, "is_generating_block": is_generating_block, "has_received_new_block": has_received_new_block, "is_program_running": is_program_running, "is_not_in_process_of_creating_new_block": is_not_in_process_of_creating_new_block }) p.daemon = False p.start() elif admin.is_validator: # callback_non_compete() will be passed as a callback function to BlockchainPropagator.initial_setup # once initial setup is done and recent block is not none it will be called in # send_response_to_other_threads function defined in initial_setup method pass # *** start blockchain propagator in different thread *** blockchain_propagator = BlockChainPropagator( mempool=mempool, q_object_connected_to_block_validator=q_for_block_validator, q_object_to_competing_process=q_for_compete, q_for_bk_propagate=q_for_bk_propagate, q_object_between_initial_setup_propagators=q_for_initial_setup, reactor_instance=main_node. reactor, # use DummyReactor which implements real reactor.CallFromThread admin_instance=admin, is_program_running=is_program_running) # *** set intial setup to start in 3 seconds. This will get new blocks and data before other processes start *** reactor.callLater(3.0, blockchain_propagator.initial_setup, callback_non_compete) # *** start blockchain propagator manager in separate thread *** reactor.callInThread(blockchain_propagator.run_propagator_convo_manager) # *** start blockchain propagator initiator in separate thread *** reactor.callInThread(blockchain_propagator.run_propagator_convo_initiator) # *** Instantiate Network Propagator *** propagator = NetworkPropagator( mempool=mempool, q_object_connected_to_validator=q_for_validator, q_for_propagate=q_for_propagate, reactor_instance=main_node.reactor, q_object_between_initial_setup_propagators=q_for_initial_setup, is_sandbox=True, q_object_to_competing_process=q_for_compete, admin_inst=admin) # *** start propagator manager in another thread *** reactor.callInThread(propagator.run_propagator_convo_manager) # *** start propagator initiator in another thread *** reactor.callInThread(propagator.run_propagator_convo_initiator) # *** instantiate network message sorter *** network_message_sorter = NetworkMessageSorter( q_object_from_protocol, q_for_bk_propagate, q_for_propagate, node=main_node, b_propagator_inst=blockchain_propagator, n_propagator_inst=propagator) # *** start network manaager and run veri node factory and regular factory using reactor.callFromThread *** network_manager = NetworkManager( admin=admin, q_object_from_protocol=q_object_from_protocol, q_object_to_validator=q_for_validator, net_msg_sorter=network_message_sorter, reg_listening_port=55600, reg_network_sandbox=reg_network_sandbox) # *** run sorter in another thread *** reactor.callInThread(network_message_sorter.run_sorter) # *** use to connect to or listen for connection from other verification nodes *** reactor.callFromThread(network_manager.run_veri_node_network, main_node.reactor) # *** use to listen for connections from regular nodes *** if reg_network_sandbox is False: # will run regular network with real reactor allowing outside client node testing reactor.callFromThread(network_manager.run_regular_node_network, reactor) else: # will run regular network with dummy reactor for complete Sandbox testing reactor.callFromThread(network_manager.run_regular_node_network, main_node.reactor) # *** creates a deferral, which allows user to exit program by typing "exit" or "quit" *** reactor.callWhenRunning(send_stop_to_reactor, reactor, q_object_to_each_node, is_program_running, is_not_in_process_of_creating_new_block, dummy_internet, q_for_propagate, q_for_bk_propagate, q_for_compete, q_object_from_protocol, q_for_validator, q_for_block_validator, number_of_nodes=number_of_nodes) # *** set propagator's network manager variable to network manager instance *** propagator.network_manager = network_manager # **** CREATE OTHER NODE INSTANCES **** # node_dict = create_node_instances( dummy_internet=dummy_internet, number_of_nodes_to_create=number_of_nodes, preferred_no_of_mining_nodes=preferred_no_of_mining_nodes, is_program_running=is_program_running) # separate processes are created for competing nodes in the Main thread, these processes will wait for most # recent block to be sent before starting to actually compete. for temp_node in node_dict["competing"]: node_compete_process = temp_node.run_compete_thread() reactor.callInThread(temp_node.run_node, real_reactor_instance=reactor, q_object_to_each_node=q_object_to_each_node, reg_network_sandbox=True, compete_process=node_compete_process) for temp_node in node_dict["non-competing"]: reactor.callInThread(temp_node.run_node, real_reactor_instance=reactor, q_object_to_each_node=q_object_to_each_node, reg_network_sandbox=True) # create wallet_balance db_manager.create_load_wallet_balances_from_genesis_block() # *** start reactor *** reactor.run() # *** This will only print when reactor is stopped print("Node Stopped") # *** when reactor is stopped save admin details *** admin.save_admin()
def main(): parser = argparse.ArgumentParser() # Network group group = parser.add_mutually_exclusive_group() group.add_argument("-m", "--mainnet", action="store_true", default=False, help="Use MainNet instead of the default TestNet") group.add_argument( "-p", "--privnet", nargs="?", metavar="host", const=True, default=False, help= "Use a private net instead of the default TestNet, optionally using a custom host (default: 127.0.0.1)" ) group.add_argument( "--coznet", action="store_true", default=False, help="Use the CoZ network instead of the default TestNet") group.add_argument("-c", "--config", action="store", help="Use a specific config file") # Theme parser.add_argument( "-t", "--set-default-theme", dest="theme", choices=["dark", "light"], help= "Set the default theme to be loaded from the config file. Default: 'dark'" ) # Verbose parser.add_argument("-v", "--verbose", action="store_true", default=False, help="Show smart-contract events by default") # Where to store stuff parser.add_argument("--datadir", action="store", help="Absolute path to use for database directories") # peers parser.add_argument("--maxpeers", action="store", default=5, help="Max peers to use for P2P Joining") # Show the neo-python version parser.add_argument( "--version", action="version", version="neo-python v{version}".format(version=__version__)) args = parser.parse_args() # Setting the datadir must come before setting the network, else the wrong path is checked at net setup. if args.datadir: settings.set_data_dir(args.datadir) # Setup depending on command line arguments. By default, the testnet settings are already loaded. if args.config: settings.setup(args.config) elif args.mainnet: settings.setup_mainnet() elif args.privnet: try: settings.setup_privnet(args.privnet) except PrivnetConnectionError as e: logger.error(str(e)) return elif args.coznet: settings.setup_coznet() # Logfile settings & setup logfile_fn = os.path.join(settings.DATA_DIR_PATH, 'prompt.log') logfile_max_bytes = 5e7 # 50 MB logfile_backup_count = 3 # 3 logfiles history settings.set_logfile(logfile_fn, logfile_max_bytes, logfile_backup_count) if args.theme: preferences.set_theme(args.theme) if args.verbose: settings.set_log_smart_contract_events(True) if args.maxpeers: settings.set_max_peers(args.maxpeers) # Instantiate the blockchain and subscribe to notifications blockchain = LevelDBBlockchain(settings.chain_leveldb_path) Blockchain.RegisterBlockchain(blockchain) # Try to set up a notification db if NotificationDB.instance(): NotificationDB.instance().start() # Start the prompt interface fn_prompt_history = os.path.join(settings.DATA_DIR_PATH, '.prompt.py.history') cli = PromptInterface(fn_prompt_history) # Run things # reactor.suggestThreadPoolSize(15) reactor.callInThread(cli.run) NodeLeader.Instance().Start() # reactor.run() is blocking, until `quit()` is called which stops the reactor. reactor.run() # After the reactor is stopped, gracefully shutdown the database. NotificationDB.close() Blockchain.Default().Dispose() NodeLeader.Instance().Shutdown()
def start_gnutella(port, ip): server = Sender.GnutellaFactory() reactor.listenTCP(8000 + port, server) gnutella_connect(port, ip) reactor.callInThread(Sender.get_user_input) reactor.run()
def check_for_changes(self): if self.filesystem_modified: self.filesystem_modified = False else: reactor.callFromThread(self.local_checker.stop) reactor.callInThread(self.sync, force_backup=True)
metadata=( (self.core_group_id_key, self.core_group_id), self.get_core_transaction_metadata(), )) try: for packet_in in iterator: reactor.callFromThread(self.packet_in_queue.put, packet_in) log.debug('enqueued-packet-in', packet_in=packet_in, queue_len=len(self.packet_in_queue.pending)) except _Rendezvous, e: log.error('grpc-exception', status=e.code()) if e.code() == StatusCode.UNAVAILABLE: os.system("kill -15 {}".format(os.getpid())) reactor.callInThread(receive_packet_in_stream) def start_change_event_in_stream(self): def receive_change_events(): streaming_rpc_method = self.grpc_stub.ReceiveChangeEvents iterator = streaming_rpc_method( empty_pb2.Empty(), metadata=( (self.core_group_id_key, self.core_group_id), self.get_core_transaction_metadata(), )) try: for event in iterator: reactor.callFromThread(self.change_event_queue.put, event) log.debug('enqueued-change-event', change_event=event,
def _stop(): reactor.callInThread(reactor.stop)
def do_main(argv): """The main user-facing portion of the script.""" usage = ("Usage: %prog [options] [DIRECTORY]\n" " %prog --list-shares [options]\n" " %prog --init [--share=SHARE_UUID] [options] DIRECTORY\n" " %prog --diff [--share=SHARE_UUID] [options] DIRECTORY") parser = OptionParser(usage=usage) parser.add_option("--port", dest="port", metavar="PORT", default=443, help="The port on which to connect to the server") parser.add_option("--host", dest="host", metavar="HOST", default='fs-1.one.ubuntu.com', help="The server address") action_list = ", ".join(sorted(MERGE_ACTIONS.keys())) parser.add_option("--action", dest="action", metavar="ACTION", default=None, help="Select a sync action (%s; default is %s)" % (action_list, DEFAULT_MERGE_ACTION)) parser.add_option("--dry-run", action="store_true", dest="dry_run", default=False, help="Do a dry run without actually " "making changes") parser.add_option("--quiet", action="store_true", dest="quiet", default=False, help="Produces less output") parser.add_option("--list-shares", action="store_const", dest="mode", const="list-shares", default="sync", help="List available shares") parser.add_option("--init", action="store_const", dest="mode", const="init", help="Initialize a local directory for syncing") parser.add_option("--no-ssl-verify", action="store_true", dest="no_ssl_verify", default=False, help=SUPPRESS_HELP) parser.add_option("--diff", action="store_const", dest="mode", const="diff", help="Compare tree on server with local tree " "(does not require previous --init)") parser.add_option("--share", dest="share", metavar="SHARE_UUID", default=None, help="Sync the directory with a share rather than the " "user's own volume") parser.add_option("--subtree", dest="subtree", metavar="PATH", default=None, help="Mirror a subset of the share or volume") (options, args) = parser.parse_args(args=list(argv[1:])) if options.share is not None and options.mode not in ("init", "diff"): parser.error("--share is only valid with --init or --diff") directory = None if options.mode in ("sync", "init" or "diff"): if len(args) > 1: parser.error("Too many arguments") elif len(args) < 1: if options.mode == "init" or options.mode == "diff": parser.error("--%s requires a directory to " "be specified" % options.mode) else: directory = "." else: directory = args[0] if options.mode in ("init", "list-shares", "diff"): if options.action is not None: parser.error("--%s does not take the --action parameter" % options.mode) if options.dry_run: parser.error("--%s does not take the --dry-run parameter" % options.mode) if options.mode == "list-shares": if len(args) != 0: parser.error("--list-shares does not take a directory") if options.mode not in ("init", "diff"): if options.subtree is not None: parser.error("--%s does not take the --subtree parameter" % options.mode) if options.action is not None and options.action not in MERGE_ACTIONS: parser.error("--action: Unknown action %s" % options.action) if options.action is None: options.action = DEFAULT_MERGE_ACTION if options.share is not None: try: uuid.UUID(options.share) except ValueError as e: parser.error("Invalid --share argument: %s" % e) share_spec = options.share else: share_spec = None client = Client(reactor=reactor) signal.signal(signal.SIGINT, lambda s, f: client.force_shutdown()) signal.signal(signal.SIGTERM, lambda s, f: client.force_shutdown()) def run_client(): """Run the blocking client.""" client.connect_ssl(options.host, int(options.port), options.no_ssl_verify) try: client.set_capabilities() if options.mode == "sync": do_sync(client=client, directory=directory, action=options.action, dry_run=options.dry_run, quiet=options.quiet) elif options.mode == "init": do_init(client=client, share_spec=share_spec, directory=directory, quiet=options.quiet, subtree_path=options.subtree) elif options.mode == "list-shares": do_list_shares(client=client) elif options.mode == "diff": do_diff(client=client, share_spec=share_spec, directory=directory, quiet=options.quiet, subtree_path=options.subtree, ignore_symlinks=False) finally: client.disconnect() def capture_exception(queue, func): """Capture the exception from calling func.""" try: func() except Exception: queue.put(sys.exc_info()) else: queue.put(None) finally: reactor.callWhenRunning(reactor.stop) queue = Queue() reactor.callInThread(capture_exception, queue, run_client) reactor.run(installSignalHandlers=False) exc_info = queue.get(True, 0.1) if exc_info: raise exc_info[0], exc_info[1], exc_info[2]
def get_profile(self, username, domain): defer = Deferred() reactor.callInThread(self.retrieve_profile, username, domain, lambda profile: profile, False, defer) return defer
def _process(data): " takes data, sends it on the stream" reactor.callInThread(_process_reactor, data)
def delete_all(self, uri): defer = Deferred() operation = lambda profile: self._delete_all_operation(uri, profile) reactor.callInThread(self.retrieve_profile, uri.user.username, uri.user.domain, operation, True, defer) return defer
def __init__(self, node, **kwargs): """Constructor for the Gossip class. Args: node (Node): The local node. MinimumRetries (int): The minimum number of retries on message transmission. RetryInterval (float): The time between retries, in seconds. """ super(Gossip, self).__init__() self.blacklist = [] if 'MinimumRetries' in kwargs: self.MinimumRetries = kwargs['MinimumRetries'] if 'RetryInterval' in kwargs: self.RetryInterval = kwargs['RetryInterval'] self.LocalNode = node self.NodeMap = {} self.PendingAckMap = {} self.MessageHandledMap = {} self.MessageHandlerMap = {} self.SequenceNumber = 0 self.NextCleanup = time.time() + self.CleanupInterval self.NextKeepAlive = time.time() + self.KeepAliveInterval self._initgossipstats() connect_message.register_message_handlers(self) gossip_debug.register_message_handlers(self) shutdown_message.register_message_handlers(self) topology_message.register_message_handlers(self) random_walk_message.register_message_handlers(self) # setup connectivity events self.onNodeDisconnect = event_handler.EventHandler('onNodeDisconnect') # setup the timer events self.onHeartbeatTimer = event_handler.EventHandler('onHeartbeatTimer') self.onHeartbeatTimer += self._timertransmit self.onHeartbeatTimer += self._timercleanup self.onHeartbeatTimer += self._keepalive self._HeartbeatTimer = task.LoopingCall(self._heartbeat) self._HeartbeatTimer.start(0.05) self.MessageQueue = MessageQueue() try: self.ProcessIncomingMessages = True self.Listener = reactor.listenUDP(self.LocalNode.NetPort, self) reactor.callInThread(self._dispatcher) except: logger.critical( "failed to connect local socket, server shutting down", exc_info=True) raise GossipException("Failed to connect local " "socket, server shutting down")
def adminRespond(self, user): reactor.callInThread(self.spawnAdmin, user)
def get(self, uri): defer = Deferred() operation = lambda profile: self._get_operation(uri, profile) reactor.callInThread(self.retrieve_profile, uri.user.username, uri.user.domain, operation, False, defer) return defer
def rotate_logs(): reactor.callInThread(do_rotate_logs, "usr/log/yombo.json", "json") reactor.callInThread(do_rotate_logs, "usr/log/yombo.text", "text")
renew() def renew_safe(): # Make sure there aren't two attempts to use the DB at once. with lock: try: renew() except Exception as e: print "Failed to cache data: " + str(e) # Reconnect the database, it may have been because of that openDB() renew_timer = LoopingCall(lambda: reactor.callInThread(renew_safe)) renew_timer.start(900, False) class AuthClient(basic.LineReceiver): def connectionMade(self): self.delimiter = "\n" def lineReceived(self, line): if line == "QUIT": self.transport.loseConnection() print "Asked to terminate" return print("Line: " + line) match = auth.match(line) if match:
def dispatchCommand(self, command, sender, originalMessage, twistedStanza, room, messageType): """Find plugins that can respond to the command or execute all the plugins responding to default""" self.logger.debug('Dispatching command %s' % command) """Command is meant for the bot""" self.logger.debug('This is our command') plg = command.pop(0).lower() args = [] for arg in command: args.append(arg.strip()) message = '' """Handle a few high level commands: help, mute, unmute""" if plg == 'help': self.logger.debug('Finding plugins with help') message = 'In a groupchat, all commands start with "%s:" or "!."\nIn private chat, simply type the command.\nThese are the commands available. For help on a command, try -h\n' % self.username pluginNames = [] for plugin in getPluginsByCapability('help', self): self.logger.debug('plugins %s has help' % plugin) try: pluginNames.append(plugin.name) except AttributeError: # baaad plugin, doesn't assign a name for itself pass message += ', '.join(pluginNames) self.sendMessage(message, sender, messageType) return if plg == 'default': # this is necessary to prevent users from invoking the catchall (default) plugins self.sendMessage('Unknown command. Try help.', sender, messageType) else: # find the plugins having the command name plugin_arguments = { 'args': args, 'command': 'something', 'client': self, 'message': originalMessage, 'messageType': messageType, 'sender': sender, 'twxml': twistedStanza, 'room': room, 'log': self.pluginLogger } foundCommand = False for plugin in getPluginsByCapability(plg, self): if not plugin.private: foundCommand = True self.logger.debug('Calling plugin %s with %s' % (plg, plugin_arguments)) plugin_arguments['command'] = plg if plugin.threadsafe: self.logger.debug('%s is marked as threadsafe' % plg) reactor.callInThread(plugin.call, **plugin_arguments) else: plugin.call(**plugin_arguments) else: self.logger.debug( 'Would have called plugins %s, but it is private' % plg) if not foundCommand: self.sendMessage('Unknown command. Try help.', sender, messageType)
def visitLink(self, uid, url): reactor.callInThread(self.spawnModerator, uid, url)
def dataReceived(self, data): reactor.callInThread(self._write, data)
data = {"user_id": self.user_id, "bet_list": bet_list} self.send_data(10005, data, ws) else: print "q is empty!!!" def send_999999(self, ws, params={}): pass # print "stop..." if __name__ == '__main__': input_thread.start() reactor.suggestThreadPoolSize(100) for i in range(0, 1): user_id = 2 robot = RobotClient("config.ini", user_id=user_id, user_name="15012822291") reactor.callInThread(robot.run) reactor.run() # config_dict= { # "1": "config1.ini", # "2": "config2.ini", # "3": "config3.ini", # "4": "config4.ini" # } # config_index = None # try: # config_index = sys.argv[1] # print config_index in config_dict.keys() # except IndexError,e: # print u"请输入config_index (1,2,3,4)" # if config_index is not None and config_index in config_dict.keys(): # robot = RobotClient(config_dict[config_index])
def record(self, rel_data_path): self.recording_name = rel_data_path if self.recording: raise Exception('already recording') callInThread(self.do_record_data, rel_data_path)
def exit(self): try: reactor.callInThread(self.view.stream.disconnect) except Exception: pass raise urwid.ExitMainLoop()