# if the cell is removed if v < CELL_DETECTION_THRESHOLD: channel.set_empty() elif channel.state == "discharging": channel.discharge_stats.add_current(c, ) # if we're discharging and the voltage gets to the lvc stop the discharge if v < channel.low_voltage_cutoff: channel.stop_discharge() # channel.send_stats() # TODO: implement channel.set_complete() # if the temp gets too high if t and t > channel.temperature_cutoff: channel.stop_discharge() # channel.send_stats() # TODO: implement channel.set_error() # TODO: send message indicating over temperature error except Exception as e: # if we hit any unhandled exceptions, shut everything down, kill the timers, and set the LEDs red for 1s. Then reset the board. for channel in channels: channel.discharge_pin.off() Timer(0).deinit() Timer(1).deinit() Timer(2).deinit() status_leds.set_all(RED) log.error(e) time.sleep(1) raise e
class RRouter(object): """ Router controller program. """ def __init__(self): self.pins = {} self.sounds_is_on = True self.animations_is_on = True self.animation_sets = [] self.idle_time_to_sleep = 8 self.oled_port = 1 self.oled_i2c_address = 0x0 self.images_path = '' self.sleeping = True self.last_key_press_time = 0 self.wake_up_last_time = 0 self.wake_up_timeout = 20 self.inet_check_last_time = 0 self.inet_check_timeout = 40 self.inet_check_sound_notified = False self.oled = None self.menu = None self.beeper = None self.usrinfo = None self.sysinfo = None def prepare(self): """ Prepare environment. """ # Prepare GPIO. GPIO.setmode(GPIO.BCM) for pin in self.pins: if self.pins[pin][1] == 'out': GPIO.setup(self.pins[pin][0], GPIO.OUT) GPIO.output(self.pins[pin][0], GPIO.HIGH) elif self.pins[pin][1] == 'in': GPIO.setup(self.pins[pin][0], GPIO.IN) # Initialize modules. self.oled = Display(port=self.oled_port, address=self.oled_i2c_address) self.oled.images_path = self.images_path self.menu = Menu(rr=self) self.beeper = Beeper(gpio=GPIO, speaker_pin=self.pins['Beeper'][0]) self.beeper.mute = not self.sounds_is_on self.leds = Leds(gpio=GPIO, pins=self.pins) self.usrinfo = UsrInfo(display=self.oled, leds=self.leds) self.sysinfo = SysInfo(display=self.oled, leds=self.leds) # Set interrupts for buttons. for pin in self.pins: if 'BTN_' in pin: GPIO.add_event_detect(self.pins[pin][0], GPIO.FALLING, callback=self.button_pressed, bouncetime=100) def button_pressed(self, channel=0): """ Buttons actions. """ # Get button name by it's channel. btn_name = '' for pin in self.pins: if self.pins[pin][0] == channel: btn_name = pin break if not btn_name: return False # Blink LED. self.leds.blink('B') # Play sound on button press. if btn_name in ['BTN_1', 'BTN_4', 'BTN_5']: self.beeper.play('alien-signal', length=1) else: self.beeper.play('click') # Actions for buttons. if btn_name == 'BTN_1': if self.sleeping: self.menu.show() else: # Menu items actions. if self.menu.selected_item == 1: self.usrinfo.show() elif self.menu.selected_item == 2: self.sysinfo.show() elif self.menu.selected_item == 3: if self.beeper.mute: self.beeper.mute = False self.show_image_center('sound-on.png') else: self.beeper.mute = True self.show_image_center('sound-off.png') elif self.menu.selected_item == 4: if self.animations_is_on: self.animations_is_on = False self.show_image_center('animation-off.png') else: self.animations_is_on = True self.show_image_center('animation-on.png') elif self.menu.selected_item == 5: self.power_off() elif btn_name == 'BTN_2': self.menu.select_prev() elif btn_name == 'BTN_3': self.menu.select_next() elif btn_name == 'BTN_4': self.sysinfo.show() elif btn_name == 'BTN_5': self.usrinfo.show() # Deactivate sleeping mode. self.sleeping = False self.last_key_press_time = time() def power_off(self): """ Powering OFF. """ # Show message + simple countdown. self.leds.set_one('R', 1) self.oled.clean() self.oled.font_set('NotoMono', 17) self.oled.add_text('Powering OFF', x=0, y=21) self.oled.show() for i in range(0, 8): x = i * 5 self.oled.add_text('.', x=x, y=40) self.oled.show() # Shutdown. call('poweroff', shell=True) def show_animation(self, set_name='', repeat=1): """ Showing animation from PNG files. """ set_prefix = 'anim_' + set_name files = [] for f in os.listdir(self.images_path): if set_prefix in f \ and os.path.isfile(os.path.join(self.images_path, f)): files.append(f) files.sort() for i in range(0, repeat): for img_file in files: self.show_image_center(img_file) def show_image_center(self, img_file=''): """ Show image in center of the screen. """ self.oled.clean() self.oled.add_image_center(img_file) self.oled.show() def start(self): """ Main function for daemon. """ # Main cycle. self.leds.set_all(1) self.show_animation('deb', repeat=2) self.leds.set_all(0) try: while True: # Sleeping mode guard. if self.last_key_press_time + self.idle_time_to_sleep < time(): self.sleeping = True self.menu.selected_item = 0 self.oled.clean() self.oled.show() # Wake UP + animations. if self.sleeping\ and self.wake_up_last_time + self.wake_up_timeout < time() \ and self.animations_is_on: if self.wake_up_last_time: self.show_animation(choice(self.animation_sets)) self.wake_up_last_time = time() # Internet connection checker. if self.sleeping\ and self.inet_check_last_time + \ self.inet_check_timeout < time(): if not self.sysinfo.check_host_port('8.8.8.8', 53): self.leds.set_one('R', 1) self.show_image_center('no-internet.png') if not self.inet_check_sound_notified: self.beeper.play('error') self.inet_check_sound_notified = True else: self.leds.set_one('R', 0) self.inet_check_sound_notified = False self.inet_check_last_time = time() sleep(1) except KeyboardInterrupt: pass print('OK') GPIO.cleanup()