class Relay(flx.Component): number_of_connections = flx.IntProp(settable=True) def init(self): self.update_number_of_connections() self.refresh() @flx.manager.reaction('connections_changed') def update_number_of_connections(self, *events): n = 0 for name in flx.manager.get_app_names(): sessions = flx.manager.get_connections(name) n += len(sessions) self.set_number_of_connections(n) @flx.emitter def system_info(self): return dict(cpu=psutil.cpu_percent(), mem=psutil.virtual_memory().percent, sessions=self.number_of_connections, total_sessions=flx.manager.total_sessions, ) def refresh(self): self.system_info() asyncio.get_event_loop().call_later(1, self.refresh)
class Example(flx.Widget): counter = flx.IntProp(3, settable=True) def init(self): super().init() with flx.HBox(): self.but1 = flx.Button(text='reset') self.but2 = flx.Button(text='increase') self.label = flx.Label(text='', flex=1) # take all remaining space @flx.action def increase(self): self._mutate_counter(self.counter + 1) @flx.reaction('but1.pointer_click') def but1_clicked(self, *events): self.set_counter(0) @flx.reaction('but2.pointer_click') def but2_clicked(self, *events): self.increase(0) @flx.reaction def update_label(self, *events): self.label.set_text('count is ' + str(self.counter))
class Web(flx.Widget): name = flx.StringProp('John Doe', settable=True) age = flx.IntProp(22, settable=True) @flx.action def increase_age(self): self._mutate_age(self.age + 1) def _create_dom(self): # Use this method to create a root element for this widget. # If you just want a <div> you don't have to implement this. return flx.create_element('div') # the default is <div> def _render_dom(self): # Use this to determine the content. This method may return a # string, a list of virtual nodes, or a single virtual node # (which must match the type produced in _create_dom()). return [ flx.create_element('span', {}, 'Hello', flx.create_element('b', {}, self.name), '! '), flx.create_element( 'span', {}, 'I happen to know that your age is %i.' % self.age), flx.create_element('br'), flx.create_element('button', {'onclick': self.increase_age}, 'Next year ...') ]
class Relay(flx.Component): number_of_connections = flx.IntProp(settable=True) def init(self): self.update_number_of_connections() self.current_idx = 0 if platform.system() == 'Windows': directories = glob.glob(r'Y:\log_pool\*') self.ROOT_PATH = r'Y:\log_pool' else: directories = glob.glob( r'/Users/xiaoprime/Documents/GitHub/Q-learning-NW-SRCH/Simulator/log_pool/*' ) self.ROOT_PATH = r'/Users/xiaoprime/Documents/GitHub/Q-learning-NW-SRCH/Simulator/log_pool' time.sleep(1) directories = sorted(list( filter(lambda f: os.path.isdir(f), directories)), reverse=True) #self.stock_list = list(enumerate(directories, start=1)) self.stock_list = [ x.split('\\' if platform.system() == 'Windows' else '/')[-1] for x in directories ] #self.refresh() @flx.manager.reaction('connections_changed') def update_number_of_connections(self, *events): n = 0 for name in flx.manager.get_app_names(): sessions = flx.manager.get_connections(name) n += len(sessions) self.set_number_of_connections(n) @flx.emitter def system_info(self, dat, stockname, otherseries=None): dat = dat.to_dict('split') dat['label'] = [str(x).split(' ')[0] for x in dat['index']] dat['index'] = list(date2num(dat['index'])) dat['rec'] = {} dat['min'] = {} dat['max'] = {} dat['min']['index'] = np.nanmin(dat['index']) dat['max']['index'] = np.nanmax(dat['index']) for idx, tp in zip(range(len(dat['columns'])), dat['columns']): dat['rec'][tp] = [x[idx] for x in dat['data']] dat['min'][tp] = np.nanmin(dat['rec'][tp]) dat['max'][tp] = np.nanmax(dat['rec'][tp]) del dat['data'] return dict(dat=dat, stockname=stockname, otherseries=otherseries, sessions=self.number_of_connections, total_sessions=flx.manager.total_sessions)
class Relay(flx.Component): number_of_connections = flx.IntProp(settable=True) def init(self): self.update_number_of_connections() @flx.manager.reaction('connections_changed') def update_number_of_connections(self, *events): n = 0 for name in flx.manager.get_app_names(): sessions = flx.manager.get_connections(name) n += len(sessions) self.set_number_of_connections(n) @flx.emitter def new_data(self, serial_data): return dict(serial_data=serial_data, sessions=self.number_of_connections, total_sessions=flx.manager.total_sessions)
class ReticoModule(flx.Widget): p_left = flx.IntProp(settable=True) p_top = flx.IntProp(settable=True) p_width = flx.IntProp(settable=True) p_height = flx.IntProp(settable=True) active = flx.BoolProp(settable=True) def init(self, retico_widget): self.retico_widget = retico_widget self.l_title = flx.Label(text="", css_class="title-label") self.close_button = flx.Button(text="X", css_class="close-button") with flx.VBox( style= "cursor: default; padding-bottom: 30px; padding-left: 20px; padding-right:20px; padding-top: 30px;" ) as self.content_box: self.content_box.set_padding("20px") self.out_button_l = flx.Button(text="◀", css_class="out-button left-button") self.out_button_r = flx.Button(text="▶", css_class="out-button right-button") self.in_button_l = flx.Button(text="▶", css_class="in-button left-button") self.in_button_r = flx.Button(text="◀", css_class="in-button right-button") self.enable_button = flx.Button(text="enabled", css_class="enable-button") self.trigger_edit = flx.LineEdit(self.content_box) self.trigger_button = flx.Button(parent=self.content_box, text="Trigger") self.trigger_edit.set_parent(None) self.trigger_button.set_parent(None) self.trigger_button.set_disabled(True) self.set_active(True) self.set_position() def set_position(self): rect = self.node.getBoundingClientRect() mpane = self.retico_widget.mpane.node self.set_p_left(rect.left + mpane.scrollLeft) self.set_p_top(rect.top + mpane.scrollTop) self.set_p_width(rect.width) self.set_p_height(rect.height) window.setTimeout(self.set_position, 100) @flx.action def clear_content(self): for child in self.content_box.children: child.set_parent(None) child.dispose() @flx.action def add_info(self, text): style = "font-size: 10pt; text-align: center;" lbl = flx.Label(style=style, parent=self.content_box) lbl.set_html(text) @flx.action def update_info(self, text): style = "font-size: 10pt; text-align: center;" if len(self.content_box.children) > 1: self.clear_content() flx.Label(style=style, parent=self.content_box) self.content_box.children[0].set_html(text) @flx.action def create_trigger(self): self.trigger_edit.set_parent(self.content_box) self.trigger_button.set_parent(self.content_box) @flx.reaction("trigger_button.pointer_click") def trigger_clicked(self): params_txt = self.trigger_edit.text print("TRIGGER CLICKED!", str(params_txt)) self.retico_widget.model.handle_trigger(self, params_txt) # @flx.action # def set_content(self, content_list): # for child in self.content_box.children: # child.set_parent(None) # child.dispose() # for element in content_list: # element.set_parent(self.content_box) @flx.action def disable_input_buttons(self): self.in_button_l.set_disabled(True) self.in_button_r.set_disabled(True) @flx.action def disable_output_buttons(self): self.out_button_l.set_disabled(True) self.out_button_r.set_disabled(True) @flx.action def enable_input_buttons(self): self.in_button_l.set_disabled(False) self.in_button_r.set_disabled(False) @flx.action def enable_output_buttons(self): self.out_button_l.set_disabled(False) self.out_button_r.set_disabled(False) @flx.action def enable_close_button(self): self.close_button.set_disabled(False) self.trigger_button.set_disabled(True) @flx.action def disable_close_button(self): self.close_button.set_disabled(True) self.trigger_button.set_disabled(False) @flx.action def highlight(self, active, color="#ffd"): self.node.style["box-shadow"] = None if active: if color == "border": self.node.style[ "box-shadow"] = "rgba(255, 255, 255, 0.6) 0px 0px 20px" elif color == "red-border": self.node.style[ "box-shadow"] = "rgba(255, 0, 0, 0.6) 0px 0px 20px" else: self.node.style["background-color"] = color else: self.node.style["background-color"] = "#fff" @flx.reaction("out_button_l.pointer_click", "out_button_r.pointer_click") def out_button_click(self): if not self.retico_widget.model.connecting_state: self.retico_widget.model.init_out_click(self) else: self.retico_widget.model.connect_to(self) @flx.reaction("in_button_l.pointer_click", "in_button_r.pointer_click") def in_button_click(self): if not self.retico_widget.model.connecting_state: self.retico_widget.model.init_in_click(self) else: self.retico_widget.model.connect_to(self) @flx.reaction("close_button.pointer_click") def _close(self): self.retico_widget.model.delete_module(self) @flx.reaction("enable_button.pointer_click") def enable_button_click(self): self.retico_widget.model.toggle_module(self) @flx.action def set_mtitle(self, thing): self.l_title.set_text(thing) def in_pos(self): rect = self.node.getBoundingClientRect() mp_node = self.retico_widget.mpane.node return ( rect.left + (rect.width / 2) + mp_node.scrollLeft, rect.bottom - 13 + mp_node.scrollTop, ) def out_pos(self): rect = self.node.getBoundingClientRect() mp_node = self.retico_widget.mpane.node return ( rect.left + (rect.width / 2) + mp_node.scrollLeft, rect.top + 45 + mp_node.scrollTop, ) @flx.action def setup(self): self.disable_input_buttons() self.disable_output_buttons() self.disable_close_button() self.highlight(True, "red-border") @flx.action def stop(self): self.enable_close_button() self.highlight(False) @flx.action def display_active(self): if self.active: self.node.style["opacity"] = 1 self.enable_button.set_text("enabled") else: self.node.style["opacity"] = 0.1 self.enable_button.set_text("disabled")
class SlowControlGUI(flx.PyComponent): led = flx.IntProp(0, settable=True) hv = flx.IntProp(0, settable=True) vsel = flx.IntProp(0, settable=True) chillerStat = flx.IntProp(0, settable=True) chillerSwitch = flx.IntProp(0, settable=True) tempchiller = flx.FloatProp(0, settable=True) tempbench = flx.FloatProp(0, settable=True) tempext = flx.FloatProp(0, settable=True) humbench = flx.FloatProp(0, settable=True) humext = flx.FloatProp(0, settable=True) # sercon = flx.ComponentProp() # serconChiller = flx.ComponentProp() # serconSensirion = flx.ComponentProp() # ledcon = flx.ComponentProp() initialised = 0 def init(self): super().init() # self._mutate_sercon(SerialConnection('/dev/ttyACM1')) self.sercon = SerialConnection('/dev/sensor_0') # self._mutate_serconChiller(SerialConnectionChiller('/dev/ttyUSB0')) self.serconChiller = SerialConnectionChiller('/dev/ttyUSB0') # self._mutate_serconSensirion(SerialConnectionSensirion('/dev/ttyACM0')) self.serconSensirion = SerialConnectionSensirion('/dev/sensor_1') # self._mutate_ledcon(LedPulser()) self.ledcon = LedPulser() self.hvcon = SerialConnectionHV('/dev/ttyUSB4') self.t0 = datetime.now() #Always start in inhbit mode reply=self.sercon.sendCommand('i') if (reply!='INH'): print('Please check serial connection') reply=self.sercon.sendCommand('0') if (reply!='V0'): print('Please check serial connection') ret=self.ledcon.ledSwitch(0) if (ret!=0): print('Please check led pulser connection') # with flx.HBox(flex=0, spacing=10): with flx.PinboardLayout(): self.tempText = flx.Label(text='T: XX.XX H: YY.YY',style='left:10px; top:120px; width:300px;height:20px;') self.sensirionText = flx.Label(text='T_EXT:XXX.XX H_EXT:YYY.YY DEW_EXT:ZZZ.ZZ',style='left:10px; top:140px; width:400px;height:20px;') self.hvText = flx.Label(text='VSET:XXX.XX VMON:XXX.XX',style='left:10px; top:180px; width:300px;height:20px;') self.chillerText = flx.Label(text='CHILLER TBATH:XXX.XX TSET:YYY.YY PUMP:ZZ',style='left:10px; top:160px; width:400px;height:20px;') self.but1 = flx.Button(text='Led Pulser',css_class="border-black",style='left:10px; top:10px; width:180px;height:100px;') self.but2 = flx.Button(text='HV',css_class="border-black",style='left:200px; top:10px; width:150px;height:100px;') self.but3 = flx.Button(text='VSEL',css_class="border-black",style='left:360px; top:10px; width:100px;height:100px;') self.chillerStatus = flx.Button(text='COOLING OK',css_class="border-black",style='left:470px; top:10px; width:250px;height:100px;') # self.label = flx.Label(text='', flex=1) # take all remaining space self.refreshTemperature() self.refreshChiller() self.refreshSensirion() self.refreshHV() #upload to things speak (every 60s) self.refreshThingSpeak() self.initialised=1 @flx.action def refreshTemperature(self): if (self.initialised != 0): reply=self.sercon.sendCommand('t') self.tempText.set_text(reply) logging.info(reply) temp=reply.split(' ')[1] self._mutate_tempbench(temp) hum=reply.split(' ')[3] self._mutate_humbench(hum) asyncio.get_event_loop().call_later(5, self.refreshTemperature) @flx.action def refreshSensirion(self): if (self.initialised != 0): reply=self.serconSensirion.sendCommand('t') if (len(reply.split(' ')) == 10): temp=reply.split(' ')[1] self._mutate_tempext(temp) hum=reply.split(' ')[7] self._mutate_humext(hum) dew=reply.split(' ')[9] self.sensirionText.set_text('T_EXT:'+temp+' H_EXT:'+hum+' DEW_EXT:'+dew) logging.info('T_EXT:'+temp+' H_EXT:'+hum+' DEW_EXT:'+dew) asyncio.get_event_loop().call_later(6, self.refreshSensirion) @flx.action def refreshHV(self): if (self.initialised != 0): vmon=self.hvcon.sendCommand('m') vset=self.hvcon.sendCommand('s') stat=self.hvcon.sendCommand('i') self.hvText.set_text('VSET:'+vset+' VMON:'+vmon) logging.info('VSET:'+vset+' VMON:'+vmon+' STATUS:'+stat) if ( (int(stat) & 1) == 1): self._mutate_hv(1) elif ( (int(stat) & 1) == 0): self._mutate_hv(0) asyncio.get_event_loop().call_later(7, self.refreshHV) @flx.action def refreshChiller(self): try: if (self.initialised != 0): tbath=self.serconChiller.sendCommand('t') # print(tbath) tset=self.serconChiller.sendCommand('g') pump=self.serconChiller.sendCommand('p') status=self.serconChiller.sendCommand('s') self.chillerText.set_text('CHILLER TBATH:'+tbath+' TSET:'+tset+' PUMP:'+pump) if (pump== '000.00' and status == '0'): self.chillerStatus.set_text('COOLING OFF') self.chillerStatus.apply_style('background:yellow;') self._mutate_chillerSwitch(0) elif (status == '0' and pump== '003.00'): self.chillerStatus.set_text('COOLING OK') self.chillerStatus.apply_style('background:green;') self._mutate_chillerStat(1) self._mutate_chillerSwitch(1) else: self.chillerStatus.set_text('COOLING KO') self.chillerStatus.apply_style('background:red;') self._mutate_chillerStat(0) if not 'ERR' in tbath: self._mutate_tempchiller(float(tbath)) logging.info('CHILLER TBATH: '+tbath+' STATUS: '+status+' TSET:'+tset+' PUMP:'+pump) except: logging.info('Got an exception') asyncio.get_event_loop().call_later(10, self.refreshChiller) def refreshThingSpeak(self): if (self.initialised != 0): params = {'field1': self.tempbench, 'field2': self.humbench, 'field3': self.tempchiller, 'field4': self.chillerStat, 'field5': self.tempext, 'field6': self.humext, 'key': thingspeak_key} logThingSpeak(params) asyncio.get_event_loop().call_later(60, self.refreshThingSpeak) @flx.action def hv_switch(self): if (self.hv==0): reply=self.hvcon.sendCommand('o') if (reply=='OK'): self._mutate_hv(1) elif (self.hv==1): reply=self.hvcon.sendCommand('k') if (reply=='OK'): self._mutate_hv(0) @flx.action def led_switch(self): if (self.led==0): ret=self.ledcon.ledSwitch(1) if (ret==0): self._mutate_led(1) elif (self.led==1): ret=self.ledcon.ledSwitch(0) if (ret==0): self._mutate_led(0) @flx.action def chiller_switch(self): if (self.chillerSwitch==0): reply=self.serconChiller.sendCommand('o') if (reply=='OK'): self._mutate_chillerSwitch(1) elif (self.chillerSwitch==1): reply=self.serconChiller.sendCommand('k') if (reply=='OK'): self._mutate_chillerSwitch(0) @flx.action def vsel_switch(self): if (self.vsel==0): reply=self.sercon.sendCommand('1') if (reply=='V1'): self._mutate_vsel(1) elif (self.vsel==1): reply=self.sercon.sendCommand('0') if (reply=='V0'): self._mutate_vsel(0) @flx.reaction('but1.pointer_click') def but1_clicked(self, *events): self.led_switch() @flx.reaction('but2.pointer_click') def but2_clicked(self, *events): self.hv_switch() @flx.reaction('but3.pointer_click') def but3_clicked(self, *events): self.vsel_switch() @flx.reaction('chillerStatus.pointer_click') def chillerButton_clicked(self, *events): self.chiller_switch() # @flx.reaction # def update_label(self, *events): @flx.reaction def update_buttons(self, *events): if (self.hv==1): self.but2.set_text('HV ON') self.but2.apply_style('background:red;') if (self.hv==0): self.but2.set_text('HV OFF') self.but2.apply_style('background:yellow;') if (self.led==1): self.but1.set_text('LED ON') self.but1.apply_style('background:red;') if (self.led==0): self.but1.set_text('LED OFF') self.but1.apply_style('background:yellow;') if (self.chillerSwitch==0): self.chillerStatus.set_text('COOLING OFF') self.chillerStatus.apply_style('background:yellow;') if (self.chillerSwitch==1 and self.chillerStat==0): self.chillerStatus.set_text('COOLING ON') self.chillerStatus.apply_style('background:orange;') if (self.chillerSwitch==1 and self.chillerStat==1): self.chillerStatus.set_text('COOLING OK') self.chillerStatus.apply_style('background:green;') if (self.vsel==1): self.but3.set_text('V1') if (self.vsel==0): self.but3.set_text('V0')
class Run(flx.PyWidget): exterior_wall_tuple = flx.TupleProp((1, 10), settable=True) exterior_roof_tuple = flx.TupleProp((1, 9), settable=True) exterior_window_tuple = flx.TupleProp((1, 3), settable=True) eastrate_tuple = flx.TupleProp((0.05, 0.3), settable=True) westrate_tuple = flx.TupleProp((0.05, 0.3), settable=True) southrate_tuple = flx.TupleProp((0.05, 0.3), settable=True) northrate_tuple = flx.TupleProp((0.05, 0.3), settable=True) direction_tuple = flx.TupleProp((0, 359), settable=True) airchange_tuple = flx.TupleProp((0, 39), settable=True) cop_tuple = flx.TupleProp((1, 4), settable=True) east_shading_tuple = flx.TupleProp((0, 1), settable=True) west_shading_tuple = flx.TupleProp((0, 1), settable=True) south_shading_tuple = flx.TupleProp((0, 1), settable=True) north_shading_tuple = flx.TupleProp((0, 1), settable=True) infiltration_airchange_tuple = flx.TupleProp((1, 3), settable=True) mutation_param_int = flx.IntProp(4, settable=True) num_of_generation_int = flx.IntProp(50, settable=True) num_of_individual_int = flx.IntProp(50, settable=True) num_of_tour_particps_int = flx.IntProp(2, settable=True) max_proc_int = flx.IntProp(8, settable=True) floor_height_float = flx.FloatProp(2.8, settable=True) window_height_float = flx.FloatProp(1.5, settable=True) window_edge_height_float = flx.FloatProp(1, settable=True) heating_setpoint_float = flx.FloatProp(18, settable=True) cooling_setpoint_float = flx.FloatProp(26, settable=True) apmv_upper_float = flx.FloatProp(0.5, settable=True) apmv_lower_float = flx.FloatProp(-0.5, settable=True) weather_file_str = flx.StringProp( '../WeatherData/CHN_Chongqing.Chongqing.Shapingba.575160_CSWD.epw', settable=True) idf_file_str = flx.StringProp('shading_model_6-0603-1.idf', settable=True) output_path_str = flx.StringProp('temp/', settable=True) def init(self): self.moo = MooWidget(self) @flx.action def run_moo(self): # the actual range used by the algorithm is set here. paras = [ discrete_interval(tuple(self.moo.root.exterior_wall_tuple)), discrete_interval(tuple(self.moo.root.exterior_roof_tuple)), discrete_interval(tuple(self.moo.root.exterior_window_tuple)), tuple(self.moo.root.eastrate_tuple), tuple(self.moo.root.westrate_tuple), tuple(self.moo.root.southrate_tuple), tuple(self.moo.root.northrate_tuple), tuple(self.moo.root.direction_tuple), tuple(self.moo.root.airchange_tuple), discrete_interval(tuple(self.moo.root.cop_tuple)), discrete_interval(tuple(self.moo.root.east_shading_tuple)), discrete_interval(tuple(self.moo.root.west_shading_tuple)), discrete_interval(tuple(self.moo.root.south_shading_tuple)), discrete_interval(tuple(self.moo.root.north_shading_tuple)), discrete_interval(tuple( self.moo.root.infiltration_airchange_tuple)) ] """Algorithm parameter""" hyperparameter: Dict = { "MUTATION_PARAM": int(self.moo.root.mutation_param_int), "NUM_OF_GENERATIONS": int(self.moo.root.num_of_generation_int), "NUM_OF_INDIVIDUALS": int(self.moo.root.num_of_individual_int), "NUM_OF_TOUR_PARTICIPS": int(self.moo.root.num_of_tour_particps_int), "CONCURRENCY": True, "MAX_PROC": int(self.moo.root.max_proc_int) } """other constants""" constants: Dict = { "FLOOR_HEIGHT": float(self.moo.root.floor_height_float), "WINDOW_HEIGHT": float(self.moo.root.window_height_float), "WINDOW_EDG_HEIGHT": float(self.moo.root.window_edge_height_float), "HEATING_SETPOINT": float(self.moo.root.heating_setpoint_float), "COOLING_SETPOINT": float(self.moo.root.cooling_setpoint_float), "APMV_UPPER": float(self.moo.root.apmv_upper_float), "APMV_LOWER": float(self.moo.root.apmv_lower_float) } """path constants""" paths: Dict = { "WEATHER_FILE": str(self.moo.root.weather_file_str), "IDF_FILE": str(self.moo.root.idf_file_str), "OUTPUT_PATH": str(self.moo.root.output_path_str) } __import__('pprint').pprint(paras) __import__('pprint').pprint(hyperparameter) __import__('pprint').pprint(constants) __import__('pprint').pprint(paths) moo_run(paras, hyperparameter, constants, paths) @flx.action def stop(self): sys.exit(0)
class Relay(flx.Component): # def init(self): # super().init() # self.time = "Relay Default Time" # self.newTime = False # # def setTime(self, time): # self.time = time # self.newTime = True vin = flx.StringProp("", settable=True) timeString = flx.StringProp("", settable=True) voltage = flx.FloatProp(0, settable=True) capacity = flx.FloatProp(0, settable=True) pandaRecording = flx.IntProp(0, settable=True) pandaGps = flx.IntProp(0, settable=True) vehicleControlRunning = flx.BoolProp(False, settable=True) @flx.reaction('vin') def on_vin(self, *events): for ev in events: self.updateVin(ev.new_value) @flx.reaction('timeString') def on_timeString(self, *events): for ev in events: self.updateTime(ev.new_value) @flx.reaction('voltage') def on_voltage(self, *events): for ev in events: self.updateVoltage(ev.new_value) @flx.reaction('capacity') def on_voltage(self, *events): for ev in events: self.updateCapacity(ev.new_value) @flx.reaction('pandaRecording') def on_pandaRecording(self, *events): for ev in events: self.updatePandaRecording(ev.new_value) @flx.reaction('pandaGps') def on_pandaGps(self, *events): for ev in events: self.updatePandaGps(ev.new_value) @flx.reaction('vehicleControlRunning') def on_vehicleControlRunning(self, *events): for ev in events: self.updateVehicleControlRunning(ev.new_value) """ Global object to relay paint events to all participants. """ @flx.emitter def updateVin(self, value): return dict(value=value) @flx.emitter def updateTime(self, value): return dict(value=value) @flx.emitter def updateVoltage(self, value): return dict(value=value) @flx.emitter def updateCapacity(self, value): return dict(value=value) @flx.emitter def updatePandaRecording(self, value): return dict(value=value) @flx.emitter def updatePandaGps(self, value): return dict(value=value) @flx.emitter def updateVehicleControlRunning(self, value): return dict(value=value)
class LeafletWidget(flx.Widget): """ A widget that shows a slippy/tile-map using Leaflet. """ layers = flx.ListProp([], doc=""" List of tilemap layer tuples: (url, 'Layer'). """) zoom = flx.IntProp(8, settable=True, doc=""" Zoom level for the map. """) min_zoom = flx.IntProp(0, settable=True, doc=""" self zoom level for the map. """) max_zoom = flx.IntProp(18, settable=True, doc=""" Maximum zoom level for the map. """) center = flx.FloatPairProp((5.2, 5.5), settable=True, doc=""" The center of the map. """) show_layers = flx.BoolProp(False, settable=True, doc=""" Whether to show layers-icon on the top-right of the map. """) show_scale = flx.BoolProp(False, settable=True, doc=""" Whether to show scale at bottom-left of map. """) @flx.action def add_layer(self, url, name=None): """ Add a layer to the map. """ # Avoid duplicates self.remove_layer(url) if name: self.remove_layer(name) # Add layer layers = self.layers + [(url, name or 'Layer')] self._mutate_layers(layers) @flx.action def remove_layer(self, url_or_name): """ Remove a layer from the map by url or name. """ layers = list(self.layers) for i in reversed(range(len(layers))): if url_or_name in layers[i]: layers.pop(i) self._mutate_layers(layers) def _create_dom(self): global L, document node = document.createElement('div') self.mapnode = document.createElement('div') node.appendChild(self.mapnode) self.mapnode.id = 'maproot' self.mapnode.style.position = 'absolute' self.mapnode.style.top = '0px' self.mapnode.style.left = '0px' self.map = L.map(self.mapnode) self.map.on('zoomend', self.map_handle_zoom) self.map.on('moveend', self.map_handle_move) self.map.on('click', self.map_handle_mouse) self.map.on('dblclick', self.map_handle_mouse) # Container to keep track of leaflet layer objects self.layer_container = [] self.layer_control = L.control.layers() self.scale = L.control.scale({'imperial': False, 'maxWidth': 200}) # Set the path for icon images L.Icon.Default.prototype.options.imagePath = '_data/shared/' return node def map_handle_zoom(self, e): global isNaN zoom = self.map.getZoom() if isNaN(zoom): return if zoom != self.zoom: self.set_zoom(zoom) def map_handle_move(self, e): center_coord = self.map.getCenter() center = center_coord.lat, center_coord.lng if center != self.center: self.set_center(center) def map_handle_mouse(self, e): latlng = [e.latlng.lat, e.latlng.lng] xy = [e.layerPoint.x, e.layerPoint.y] self.pointer_event(e.type, latlng, xy) @flx.emitter def pointer_event(self, event, latlng, xy): return {'event': event, 'latlng': latlng, 'xy': xy} @flx.reaction def __handle_zoom(self): self.map.setZoom(self.zoom) @flx.reaction def __handle_min_zoom(self): self.map.setMinZoom(self.min_zoom) @flx.reaction def __handle_max_zoom(self): self.map.setMaxZoom(self.max_zoom) @flx.reaction def __handle_center(self): self.map.panTo(self.center) @flx.reaction def __handle_show_layers(self): if self.show_layers: self.map.addControl(self.layer_control) else: self.map.removeControl(self.layer_control) @flx.reaction def __handle_show_scale(self): if self.show_scale: self.map.addControl(self.scale) else: self.map.removeControl(self.scale) @flx.reaction def __size_changed(self): size = self.size if size[0] or size[1]: self.mapnode.style.width = size[0] + 'px' self.mapnode.style.height = size[1] + 'px' # Notify the map that it's container's size changed self.map.invalidateSize() @flx.reaction def __layers_changed(self): global L for layer in self.layer_container: self.layer_control.removeLayer(layer) if self.map.hasLayer(layer): self.map.removeLayer(layer) for layer_url, layer_name in self.layers: if not layer_url.endswith('.png'): if not layer_url.endswith('/'): layer_url += '/' layer_url += '{z}/{x}/{y}.png' new_layer = L.tileLayer(layer_url) self.layer_container.append(new_layer) self.map.addLayer(new_layer) self.layer_control.addOverlay(new_layer, layer_name)
class RobotModelWidget(flx.Widget): """ A Robot model Rviz window based on ros3djs. """ host_ip = flx.StringProp("127.0.0.1", settable=True, doc=""" The IP of the host computer. """) base_link = flx.StringProp("/base_link", settable=True, doc=""" The base link frame of the robot. """) rosbridge_port = flx.IntProp(9090, settable=True, doc=""" The port of rosbridge websocket. """) resources_port = flx.IntProp(9091, settable=True, doc=""" The port of web server serving .dae files for urdf. """) robot_description = flx.StringProp("/sam/simple_description", settable=True, doc=""" The ros param with the robot description. """) def _create_dom(self): global document node = document.createElement('div') self.viewernode = document.createElement('div') self.viewernode.id = 'urdf' node.appendChild(self.viewernode) return node def _render_dom(self): self.viewer_init() return super()._render_dom() @flx.action def viewer_init(self): global window #, document if self.initialised: return self.ros = window.ROSLIB.Ros( {'url': 'ws://' + self.host_ip + ':' + str(self.rosbridge_port)}) # Create the main viewer. self.viewer = window.ROS3D.Viewer({ 'divID': 'urdf', 'width': window.innerWidth, 'height': window.innerHeight, 'antialias': True, 'background': '#002233' }) # Add a grid. self.viewer.addObject(window.ROS3D.Grid({'color': '#0181c4'})) # Setup a client to listen to TFs. self.tfClient = window.ROSLIB.TFClient({ 'ros': self.ros, 'fixedFrame': self.base_link, #"sam/base_link", 'angularThres': 0.01, 'transThres': 0.01, 'rate': 10.0 }) # Setup the URDF client. self.urdfClient = window.ROS3D.UrdfClient({ 'param': self.robot_description, 'path': 'http://' + self.host_ip + ':' + str(self.resources_port), 'ros': self.ros, 'tfClient': self.tfClient, 'rootObject': self.viewer.scene, 'loader': window.ROS3D.COLLADA_LOADER_2 }) self.initialised = True @flx.reaction('size') def __on_size(self, *events): if self.viewer: self.viewer.resize(window.innerWidth, window.innerHeight)
class IGraph(flx.PyComponent): CSS = """ .flx-main-widget{ overflow:scroll; } .configure{ overflow:scroll; } """ graph = flx.AnyProp(None, settable=True) graph_options = { # "height": "90%", } graph_list = flx.ListProp([]) current_graph = flx.IntProp(0, settable=True) def init(self): with ui.VSplit(): with ui.HFix(flex=0): self.previous = ui.Button(text="<-", disabled=True, flex=1) self.content = ui.Label(flex=0) self.next = ui.Button(text="->", disabled=True, flex=1) with ui.HSplit(flex=1, spacing=20): self.configure = flx.Widget(css_class="configure", flex=0) with ui.HFix(flex=1): self.visjs = VisJS( style="background-color: #dddddd;", flex=1, ) self.refresh() @event.reaction("graph") def update_viz(self, *events): ev = events[-1] graph = ev["new_value"] old_graph = ev["old_value"] if old_graph is None: self.visjs.load_viz(graph) else: def find_by_id(id, iterable): try: return [elem for elem in iterable if elem["id"] == id][0] except IndexError: return None self.visjs.update_viz({ "nodes": { "add": [ node for node in graph["nodes"] if not find_by_id(node["id"], old_graph["nodes"]) ], "remove": [ node["id"] for node in old_graph["nodes"] if not find_by_id(node["id"], graph["nodes"]) ], "update": [ node for node in graph["nodes"] if find_by_id(node["id"], old_graph["nodes"]) and find_by_id(node["id"], old_graph["nodes"]) != node ] }, "edges": { "add": [ edge for edge in graph["edges"] if not find_by_id(edge["id"], old_graph["edges"]) ], "remove": [ edge["id"] for edge in old_graph["edges"] if not find_by_id(edge["id"], graph["edges"]) ], "update": [ edge for edge in graph["edges"] if find_by_id(edge["id"], old_graph["edges"]) and find_by_id(edge["id"], old_graph["edges"]) != edge ], }, "options": graph["options"], }) @flx.action def refresh(self): try: graph = nx.nx_agraph.read_dot(self.file) except ImportError: try: graph = nx.nx_pydot.read_dot(self.file) except TypeError: print("TypeError") asyncio.get_event_loop().call_later(0.1, self.refresh) return def uniq_id(): i = 0 while True: yield i i = i + 1 genid = uniq_id() for src in graph.nodes: for dst in graph[src]: for number in graph[src][dst]: if "smooth.type" not in graph[src][dst][number]: graph[src][dst][number]["smooth.type"] = "curvedCW" if "smooth.roundness" not in graph[src][dst][number]: graph[src][dst][number]["smooth.roundness"] = float( number) / 5. graph_desc = { "nodes": [{ "id": node_id, "label": graph.nodes[node_id].get("label", node_id), **dotted_dict_to_nested_dict({ k: cast_it(v) for k, v in graph.nodes[node_id].items() }), } for node_id in graph.nodes], "edges": [{ "id": next(genid), "arrows": "to", "from": src, "to": dst, "number": number, **dotted_dict_to_nested_dict({ k: cast_it(v) for k, v in graph[src][dst][number].items() }), } for src in graph.nodes for dst in graph[src] for number in graph[src][dst]], "options": dotted_dict_to_nested_dict({ **self.graph_options, **dict_cast(graph.graph.get("graph", {})), }) } gl = len(self.graph_list) cg = self.current_graph last_graph = (gl != 0 and self.graph_list[-1]) or None if graph_desc != last_graph: self._mutate_graph_list([graph_desc], 'insert', gl) if cg == (gl - 1): self.set_current_graph(cg + 1) asyncio.get_event_loop().call_later(0.1, self.refresh) @flx.reaction("graph_list", "current_graph") def _update_buttons(self, *evs): self.previous.set_disabled( len(self.graph_list) == 1 or self.current_graph == 0) self.previous.set_text( "{} <-".format(self.current_graph - 1) if self.current_graph else "|") self.content.set_text("{}".format(self.current_graph)) self.next.set_disabled(self.current_graph == len(self.graph_list) - 1) self.next.set_text("-> {}".format( self.current_graph + 1) if self.current_graph < len(self.graph_list) - 1 else "|") @flx.reaction("current_graph") def _update_graph(self, *evs): self.set_graph(self.graph_list[self.current_graph]) @event.reaction("previous.pointer_click") def _previous(self, *evs): self.set_current_graph(self.current_graph - 1) @event.reaction("next.pointer_click") def _next(self, *evs): self.set_current_graph(self.current_graph + 1)
class PanelRxView(flx.Widget): CSS = """ .detail { boarder: solid green 3px; font-size:small; word-wrap:break-word; overflow: auto; } .packet_list { overflow: auto; } .flx-TreeWidget { border: gray solid 1px; font-size: small; } .flx-TreeItem { border-top: white solid 1px; text-overflow:ellipse; white-space:nowrap; } .flx-TreeItem:hover { background-color: #EEEEEE; } .flx-TreeItem.selected-true { background: blue; color: white; } .flx-TreeWidget .flx-TreeItem > .text.hastitle { width: 95%; } .flx-TreeItem > .title { background: white; color: gray; } """ labels = flx.ListProp(settable=True) label_idx = flx.IntProp(settable=True) packets = flx.ListProp(settable=True) def init(self): with flx.HSplit(): with flx.VBox(flex=1): self.summary = flx.TreeWidget(flex=1, max_selected=1) with flx.VSplit(flex=1): with flx.GroupWidget(css_class="list", flex=6, title="Detail"): self.detail = flx.Label(flex=1, css_class="detail") self.detail.set_wrap(2) with flx.GroupWidget(css_class="list", flex=4, title="hexdump"): self.hexdump = flx.Label(flex=1, css_class="detail") self.hexdump.set_wrap(1) @flx.action def add_pkt(self, info): self.packets.append( dict(summary=info['pkt_summary'], detail=info['pkt_detail'], hex=info['pkt_hex'])) self.add_one_label(info['pkt_summary']) @flx.action def update_info(self, info): if info['packets']: self.add_labels(info['packets']) if info['hexdump_txt']: line = '<pre><code>' + info['hexdump_txt'] + '</ code></ pre>' self.hexdump.set_html(line) if info['detail_txt']: line = '<pre><code>' + info['detail_txt'] + '</ code></ pre>' self.detail.set_html(line) @flx.action def add_labels(self, msg): with self.summary: for l in msg.splitlines(): self.add_one_label(l) @flx.action def add_one_label(self, msg): with self.summary: l = flx.TreeItem(text=msg, title=str(self.label_idx), checked=None) self._mutate_labels([l], 'insert', len(self.labels)) self._mutate_label_idx(self.label_idx + 1) @flx.action def clear_labels(self): for l in self.labels: l.dispose() self.labels.clear() self._mutate_label_idx(0) self.hexdump.set_text('') self.detail.set_text('') @flx.action def clear_info(self): self.set_packets([]) self.clear_labels() @flx.reaction('summary.children**.checked', 'summary.children**.selected') def _update_detail(self, *events): e = events[-1] id = int(e.source.title) self.show_detail(self.packets[id]['detail']) self.show_hexdump(self.packets[id]['hex']) def show_detail(self, msg): msg = '<pre><code>' + msg + '</code></pre>' self.detail.set_html(msg) def show_hexdump(self, msg): msg = '<pre><code>' + msg + '</code></pre>' self.hexdump.set_html(msg)
class MyPrompt(MyWidget): options = flx.ListProp([]) n_options = flx.IntProp(5) ref = flx.StringProp('MyID') def init(self): super().init() self.label = {} with flx.VBox() as self.wmain: self.label['above'] = flx.Label(text='Text above', flex=1) with flx.HBox(): self.winput = MyLineEdit(flex=1) with flx.VBox(): self.dots_above = MyDots(text='···') with flx.VBox() as self.woptions_box: pass self.dots_below = MyDots(text='···') self.woptions = [] self.show_more = 0 self.index = 0 self.shift = 0 self.focus_element = self.winput @flx.emitter def emit_option(self, option): return dict(value=option, ref=self.ref, text=self.winput.text) @flx.emitter def emit_text(self, text): return dict(value=text, ref=self.ref) @flx.emitter def emit_escape(self): return dict(ref=self.ref) @flx.emitter def emit_interrupt(self): return dict(ref=self.ref) @flx.action def set_focus(self): self._set_focus() async def _set_focus(self): elem = self.focus_element while elem.node.offsetParent == None: await self.sleep(50) elem.node.focus() return async def select_text(self): await self.sleep(50) self.winput.node.select() return @flx.action def set_properties(self, kwargs): if 'prefill' in kwargs: self.winput.set_text(kwargs.pop('prefill')) self.select_text() if 'placeholder' in kwargs: self.winput.set_placeholder_text(kwargs.pop('placeholder')) for key in ['above']: if key in kwargs: value = kwargs.pop(key) elem = self.label[key] if value is None: elem.set_text('hidden') elem.node.hidden = True else: elem.node.hidden = False elem.set_text(value) if 'ref' in kwargs: self._mutate_ref(kwargs['ref']) keys = ['options', 'n_options'] if any([key in kwargs for key in keys]): kw = kwargs kw['options'] = kw.get('options', self.options) kw['n_options'] = kw.get('n_options', self.n_options) self.set_options(kw.pop('options'), kw.pop('n_options')) for key, val in kwargs.items(): print(f'Error: unhandled key={key}, val={val}') return @flx.action def set_options(self, options, n_options=None): if n_options == None: n_options = 5 if not self.winput: return self._mutate_options(options) self._mutate_n_options(n_options) self.pre_match = {} for s in self.options: self.pre_match[s] = self.my_grams(s) self.filtered = self.options self.index = 0 self.shift = 0 self.redraw_options() @flx.reaction('woptions_box.children*.pointer_click') def _listen_clicks(self, *events): for ev in events: self.listen_click(ev.source.text) def listen_click(self, option): self.winput.node.select() # Select text self.emit_option(option) self.options.remove(option) self.options.insert(0, option) self.index = 0 self.shift = 0 self.redraw_options() return @flx.reaction('key_down') def listen_keys(self, *events): for ev in events: if ev.modifiers == 'Ctrl' and ev.key == 'c' and self.winput.text == '': self.emit_interrupt() elif ev.modifiers: continue elif ev.key == 'Escape': self.emit_escape() elif ev.key == 'Enter': if len(self.woptions): option = self.woptions[self.index].text self.listen_click(option) else: self.emit_text(self.winput.text) elif ev.key == 'ArrowDown': if self.index + 1 < len(self.woptions): self.index += 1 elif self.shift + self.n_options < len(self.filtered): self.shift += 1 self.redraw_options() elif ev.key == 'ArrowUp': redraw = True if self.index > 0: self.index -= 1 elif self.shift: self.shift -= 1 else: redraw = False if redraw: self.redraw_options() return @flx.reaction('winput.text') def listen_winput(self, *events): if self.winput.text == '': self.filtered = self.options else: score = self.fuzzy_scores(self.winput.text) thr = max(max(score.values()) / 2, 1 / 3) self.filtered = sorted( [s for s in self.options if score[s] > thr], key=lambda s: -score[s], ) self.index = 0 self.shift = 0 self.redraw_options() return def redraw_options(self): to_show = self.filtered[self.shift:self.shift + self.n_options] with self.woptions_box: while len(self.woptions) < len(to_show): self.woptions.append(flx.Button()) while len(self.woptions) > len(to_show): self.woptions.pop().dispose() for i in range(len(to_show)): self.woptions[i].set_text(to_show[i]) style = 'background:#ccc' if i == self.index else 'background:#eee' self.woptions[i].node.style = style if len(self.options) == 1: self.winput.node.hidden = True self.focus_element = self.woptions[0] else: self.winput.node.hidden = False self.focus_element = self.winput self.dots_above.set_visible(self.shift > 0) self.dots_below.set_visible( len(self.filtered) - self.shift > self.n_options) return def my_grams(self, s): n = len(s) s = s.lower() g = {} for i in range(n): g[s[i]] = (g[s[i]] or 0) + 1 if i + 1 < n: g[s[i] + s[i + 1]] = (g[s[i] + s[i + 1]] or 0) + 1 if i + 2 < n: g[s[i] + s[i + 2]] = (g[s[i] + s[i + 1]] or 0) + 1 return g def fuzzy_scores(self, text): x = self.my_grams(text) score = {} for key, y in self.pre_match.items(): hits = total = 0 z = y.copy() for k, v in x.items(): z[k] = (z[k] or 0) - x[k] hits += z[k] >= 0 total += 1 score[key] = hits / total return score