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 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 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 SplineWidget(flx.CanvasWidget): spline_type = flx.EnumProp(SPLINES, 'cardinal', settable=True, doc=""" "The type of spline """) closed = flx.BoolProp(False, settable=True, doc=""" Whether the spline is closed """) tension = flx.FloatProp(0.5, settable=True, doc=""" The tension parameter for the Cardinal spline. """) _current_node = flx.Property(None, settable=True) def init(self): self.ctx = self.node.getContext('2d') self.xx = [0.90, 0.80, 0.70, 0.60, 0.50, 0.40, 0.10, 0.23, 0.61, 0.88] self.yy = [0.90, 0.60, 0.90, 0.60, 0.90, 0.70, 0.55, 0.19, 0.11, 0.38] def factors_linear(self, t): return [0, t, (1 - t), 0] def factors_basis(self, t): f0 = (1 - t)**3 / 6.0 f1 = (3 * t**3 - 6 * t**2 + 4) / 6.0 f2 = (-3 * t**3 + 3 * t**2 + 3 * t + 1) / 6.0 f3 = t**3 / 6.0 return f0, f1, f2, f3 def factors_cardinal(self, t): tension = self.tension tau = 0.5 * (1 - tension) f0 = -tau * (t**3 - 2 * t**2 + t) f3 = +tau * (t**3 - 1 * t**2) f1 = 2 * t**3 - 3 * t**2 + 1 - f3 f2 = -2 * t**3 + 3 * t**2 - f0 return f0, f1, f2, f3 def factors_catmullrom(self, t): f0 = -0.5 * t**3 + 1.0 * t**2 - 0.5 * t f1 = +1.5 * t**3 - 2.5 * t**2 + 1 f2 = -1.5 * t**3 + 2.0 * t**2 + 0.5 * t f3 = +0.5 * t**3 - 0.5 * t**2 return f0, f1, f2, f3 def factors_lagrange(self, t): k = -1.0 f0 = t / k * (t - 1) / (k - 1) * (t - 2) / (k - 2) k = 0 f1 = (t + 1) / (k + 1) * (t - 1) / (k - 1) * (t - 2) / (k - 2) k = 1 f2 = (t + 1) / (k + 1) * t / k * (t - 2) / (k - 2) k = 2 f3 = (t + 1) / (k + 1) * t / k * (t - 1) / (k - 1) return f0, f1, f2, f3 def factors_lanczos(self, t): sin = window.Math.sin pi = window.Math.PI tt = (1 + t) f0 = 2 * sin(pi * tt) * sin(pi * tt / 2) / (pi * pi * tt * tt) tt = (2 - t) f3 = 2 * sin(pi * tt) * sin(pi * tt / 2) / (pi * pi * tt * tt) if t != 0: tt = t f1 = 2 * sin(pi * tt) * sin(pi * tt / 2) / (pi * pi * tt * tt) else: f1 = 1 if t != 1: tt = (1 - t) f2 = 2 * sin(pi * tt) * sin(pi * tt / 2) / (pi * pi * tt * tt) else: f2 = 1 return f0, f1, f2, f3 @flx.reaction('pointer_down') def _on_pointer_down(self, *events): for ev in events: w, h = self.size # Get closest point closest, dist = -1, 999999 for i in range(len(self.xx)): x, y = self.xx[i] * w, self.yy[i] * h d = ((x - ev.pos[0])**2 + (y - ev.pos[1])**2)**0.5 if d < dist: closest, dist = i, d # Did we touch it or not if dist < 9: i = closest if 'Shift' in ev.modifiers: # Remove point self.xx.pop(i) self.yy.pop(i) self._set_current_node(None) self.update() else: self._set_current_node(i) else: if 'Shift' in ev.modifiers: # Add point if not self.xx: i = 0 # There were no points else: # Add in between two points. Compose the vectors # from closest points to neightbour points and to the # cicked point. Check with which vector the latter vector # aligns the best by calculating their angles. # # Get the three points p0 = self.xx[closest + 0] * w, self.yy[closest + 0] * h if closest == 0: p2 = self.xx[closest + 1] * w, self.yy[closest + 1] * h p1 = p0[0] - (p2[0] - p0[0]), p0[1] - (p2[1] - p0[1]) elif closest == len(self.xx) - 1: p1 = self.xx[closest - 1] * w, self.yy[closest - 1] * h p2 = p0[0] - (p1[0] - p0[0]), p0[1] - (p1[1] - p0[1]) else: p1 = self.xx[closest - 1] * w, self.yy[closest - 1] * h p2 = self.xx[closest + 1] * w, self.yy[closest + 1] * h # Calculate vectors, and normalize v1 = p1[0] - p0[0], p1[1] - p0[1] v2 = p2[0] - p0[0], p2[1] - p0[1] v3 = ev.pos[0] - p0[0], ev.pos[1] - p0[1] m1 = (v1[0]**2 + v1[1]**2)**0.5 m2 = (v2[0]**2 + v2[1]**2)**0.5 m3 = (v3[0]**2 + v3[1]**2)**0.5 v1 = v1[0] / m1, v1[1] / m1 v2 = v2[0] / m2, v2[1] / m2 v3 = v3[0] / m3, v3[1] / m3 # Calculate angle a1 = window.Math.acos(v1[0] * v3[0] + v1[1] * v3[1]) a2 = window.Math.acos(v2[0] * v3[0] + v2[1] * v3[1]) i = closest if a1 < a2 else closest + 1 self.xx.insert(i, ev.pos[0] / w) self.yy.insert(i, ev.pos[1] / h) self._set_current_node(i) @flx.reaction('pointer_up') def _on_pointer_up(self, *events): self._set_current_node(None) @flx.reaction('pointer_move') def _on_pointer_move(self, *events): ev = events[-1] if self._current_node is not None: i = self._current_node w, h = self.size self.xx[i] = ev.pos[0] / w self.yy[i] = ev.pos[1] / h self.update() @flx.reaction('size', 'spline_type', 'tension', 'closed', '_current_node') def update(self, *events): # Init ctx = self.ctx w, h = self.size ctx.clearRect(0, 0, w, h) # Get coordinates xx = [x * w for x in self.xx] yy = [y * h for y in self.yy] # if self.closed: xx = xx[-1:] + xx + xx[:2] yy = yy[-1:] + yy + yy[:2] else: xx = [xx[0] - (xx[1] - xx[0])] + xx + [xx[-1] - (xx[-2] - xx[-1])] yy = [yy[0] - (yy[1] - yy[0])] + yy + [yy[-1] - (yy[-2] - yy[-1])] # Draw grid ctx.strokeStyle = '#eee' ctx.lineWidth = 1 for y in range(0, h, 20): ctx.beginPath() ctx.moveTo(0, y) ctx.lineTo(w, y) ctx.stroke() for x in range(0, w, 20): ctx.beginPath() ctx.moveTo(x, 0) ctx.lineTo(x, h) ctx.stroke() # Draw nodes ctx.fillStyle = '#acf' ctx.strokeStyle = '#000' ctx.lineWidth = 2 for i in range(1, len(xx) - 1): ctx.beginPath() ctx.arc(xx[i], yy[i], 9, 0, 6.2831) ctx.fill() ctx.stroke() # Select interpolation function fun = self['factors_' + self.spline_type.lower()] if not fun: fun = lambda: (0, 1, 0, 0) # Draw lines for i in range(1, len(xx) - 2): ctx.lineCap = "round" ctx.lineWidth = 3 ctx.strokeStyle = '#008' support = 1 if self.spline_type == 'LINEAR' else 2 if self._current_node is not None: if i - (support + 1) < self._current_node < i + support: ctx.strokeStyle = '#08F' ctx.lineWidth = 5 # Get coordinates of the four points x0, y0 = xx[i - 1], yy[i - 1] x1, y1 = xx[i + 0], yy[i + 0] x2, y2 = xx[i + 1], yy[i + 1] x3, y3 = xx[i + 2], yy[i + 2] # Interpolate ctx.beginPath() # lineto = ctx.moveTo.bind(ctx) lineto = ctx.lineTo.bind(ctx) n = 30 for t in [i / n for i in range(n + 1)]: f0, f1, f2, f3 = fun(t) x = x0 * f0 + x1 * f1 + x2 * f2 + x3 * f3 y = y0 * f0 + y1 * f1 + y2 * f2 + y3 * f3 lineto(x, y) lineto = ctx.lineTo.bind(ctx) ctx.stroke()