def split_get_request(req): req_split = req.split(' ') if len(req_split) > 1: request_url = req_split[1] else: request_url = "" request_page = request_url request_urlparams = {} if '?' in request_page: request_page = request_url[:request_url.index('?')] request_urlparams = request_url[request_url.index('?') + 1:] d = {} try: pairs = request_urlparams.split('&') for p in pairs: if "=" in p: ei = p.index("=") k = p[0:ei].lstrip().rstrip() v = p[ei + 1:] if len(k) > 0: d.update({k: v}) elif p is not None: p = p.lstrip().rstrip() if len(p) > 0: d.update({p: None}) except ValueError as exc: exclogger.log_exception(exc, to_print=False, to_file=False) except Exception as exc: exclogger.log_exception(exc) request_urlparams = d return request_page, request_urlparams
def kick(self): self.last_http_time = -1 if self.debug: print("server being kicked") if self.s is not None: try: self.s.close() except Exception as exc: exclogger.log_exception(exc, to_print=True, to_file=False) finally: self.s = None self.need_kill = False if self.winc_mode != network.WINC.MODE_AP and self.udps is not None: try: self.udps.close() except Exception as exc: exclogger.log_exception(exc, to_print=True, to_file=False) finally: self.udps = None gc.collect() if self.wlan is not None: self.wlan.closeall() #try: # self.start_wifi() #except Exception as exc: # exclogger.log_exception(exc, fatal = True, reboot = False) gc.collect()
def __init__(self, debug=False, simulate_file=None, use_leds=True): exclogger.init() self.simulate = False self.cam = astro_sensor.AstroCam(simulate=simulate_file) self.cam.init(gain_db=-1, shutter_us=250000) self.time_mgr = time_location.TimeLocationManager() self.has_time = False self.debug = debug self.use_leds = use_leds self.sleeping = False self.cam_err = False t = pyb.millis() self.diag_cnt = 0 self.frm_cnt = 0 self.tick_all = t self.dur_all = -1 self.snap_millis = 0 self.settings = {} self.settings.update({"time": self.time_mgr.get_sec()}) self.settings.update({"center_x": self.cam.width / 2}) self.settings.update({"center_y": self.cam.height / 2}) self.settings.update({"gain": self.cam.gain}) self.settings.update({"shutter": self.cam.shutter}) self.settings.update({"thresh": (0)}) self.settings.update({"max_stars": 0}) self.settings.update({"force_solve": False}) self.load_settings() self.time_mgr.readiness = False exclogger.log_exception("Time Guessed (%u)" % pyb.millis(), time_str=time_location.fmt_time( self.time_mgr.get_time())) self.portal = captive_portal.CaptivePortal(debug=self.debug) self.img = None self.img_compressed = None self.extra_fb = None self.expo_code = 0 self.histogram = None self.img_stats = None self.stars = [] self.hot_pixels = [] self.max_stars = 0 self.packjpeg = False self.zoom = 1 self.prevzoom = 1 self.mem_errs = 0 self.accel_sec = 0 if self.portal is not None: self.register_http_handlers() while self.cam.check_init() == False: self.cam.check_init() self.cam.snapshot_start() self.snap_millis = pyb.millis() self.stream_sock = None self.stream_sock_err = 0
def start_wifi_hw(self): if self.wlan is None: try: self.wlan = network.WINC(mode=self.winc_mode) self.hw_retries = 0 except OSError as exc: exclogger.log_exception(exc) exclogger.log_exception("most likely hardware fault") self.wlan = None self.hw_retries += 1 if self.wlan is None: self.wifi_timestamp = pyb.millis() return if self.winc_mode == network.WINC.MODE_AP: if self.winc_security == network.WINC.WPA_PSK: self.winc_security = network.WINC.WEP self.wlan.start_ap(self.ssid, key=self.password, security=self.winc_security) self.ip = self.wlan.ifconfig()[0] if self.ip == "0.0.0.0": self.ip = "192.168.1.1" else: self.wlan.connect(self.ssid, key=self.password, security=self.winc_security) self.ip = "0.0.0.0" self.wifi_timestamp = pyb.millis()
def start_wifi_hw(self): if self.wlan is None: try: self.wlan = network.WINC(mode=self.winc_mode) self.hw_retries = 0 except OSError as exc: excstr = exclogger.log_exception(exc) if "irmware version mismatch" in excstr: print("WiFi shield requires a firmware update!") attempt_fw_update() else: exclogger.log_exception("most likely hardware fault") self.wlan = None self.hw_retries += 1 if self.wlan is None: self.wifi_timestamp = pyb.millis() return if self.winc_mode == network.WINC.MODE_AP: if self.winc_security == network.WINC.WPA_PSK: self.winc_security = network.WINC.WEP self.wlan.start_ap(self.ssid, key=self.password, security=self.winc_security) self.ip = self.wlan.ifconfig()[0] if self.ip == "0.0.0.0": self.ip = "192.168.1.1" else: self.wlan.connect(self.ssid, key=self.password, security=self.winc_security) self.ip = "0.0.0.0" self.wifi_timestamp = pyb.millis()
def handle_query(self, client_stream, req, reply=True, save=True): need_save = False try: request_page, request_urlparams = captive_portal.split_get_request( req) if self.debug and reply: print(" keys %u" % len(request_urlparams)) for i in request_urlparams.keys(): v = request_urlparams[i] v = self.try_parse_setting(v) if i in self.settings: need_save = True self.settings[i] = v if self.debug and (reply or save): print("setting \"%s\" value \"%s\"" % (i, str(v))) if i == "time": if self.has_time == False: self.time_mgr.set_utc_time_epoch(v) exclogger.log_exception( "Time Obtained (%u)" % pyb.millis(), time_str=time_location.fmt_time( self.time_mgr.get_time())) self.has_time = True elif i == "max_stars": self.max_stars = v elif i == "hotpixels": self.hot_pixels = star_finder.decode_hotpixels(v) elif i == "use_debug": self.debug = v elif i == "use_leds": self.use_leds = v if v == False: red_led.off() green_led.off() blue_led.off() elif i == "sleep": self.sleeping = v if v == False: self.use_leds = False red_led.off() green_led.off() blue_led.off() elif i == "save": save = (v == True) need_save = True else: print("unknown setting \"%s\": \"%s\"" % (i, str(v))) if need_save and save: self.save_settings() if reply: self.reply_ok(client_stream) except KeyboardInterrupt: raise except Exception as exc: s = exclogger.log_exception(exc) if reply: self.reply_ok(client_stream, sts=False, err=s)
def main(debug=False): guidescope = AutoguiderScope(debug=True) while True: try: guidescope.task() except KeyboardInterrupt: raise except MemoryError as exc: exclogger.log_exception(exc, to_file=False) micropython.mem_info(True) except Exception as exc: exclogger.log_exception(exc)
def task(self): if self.gps_ok == False: self.gps_ok = self.gps.test_connect() if self.gps_ok == False: return False try: self.gps.task() return True except Exception as exc: self.gps_ok = False exclogger.log_exception(exc) return False
def main(): pyb.delay(3000) scope = polarscope.PolarScope(debug=False) while True: try: scope.task() except KeyboardInterrupt: raise except MemoryError as exc: exclogger.log_exception(exc, to_file=False) micropython.mem_info(True) except Exception as exc: exclogger.log_exception(exc)
def snapshot_start(self): if self.snap_started == True: return if self.simulate: self.sim_t = pyb.millis() self.snap_started = True return try: sensor.snapshot_start() self.snap_started = True except RuntimeError as exc: exclogger.log_exception(exc) self.has_error = True
def main(debug = False): #polarscope = PolarScope(debug = True, simulate_file = "simulate.bmp") polarscope = PolarScope(debug = True) while True: try: polarscope.task() except KeyboardInterrupt: raise except MemoryError as exc: exclogger.log_exception(exc, to_file = False) micropython.mem_info(True) except Exception as exc: exclogger.log_exception(exc)
def websocket_readmsg(sock): sock.settimeout(0) try: hd1 = sock.recv(2) sock.settimeout(0.1) if len(hd1) != 2: if len(hd1) != 0: print("incomplete websocket reply") return None sock.settimeout(0.5) except: return None try: # assume no fragmentation mask = False opcode0 = hd1[0] opcode1 = hd1[1] if (opcode1 & 0x80) != 0: mask = True opcode1 &= 0x7F paylen = opcode1 datalen = 0 if paylen <= 125: datalen = paylen elif paylen == 126: hd2 = sock.recv(2) datalen = hd2[0] << 8 datalen += hd2[1] elif paylen == 127: hd2 = sock.recv(8) i = 0 while i < 8: datalen += hd2[i] << (8 * (7 - i)) i += 1 if mask: mask = sock.recv(4) data = sock.recv(datalen) data = bytearray(data) if mask != False: i = 0 while i < datalen: data[i] = data[i] ^ mask[i % 4] i += 1 if (opcode0 & 0x0F) == 0x01: return data.decode('utf-8') return data except Exception as exc: print("incomplete websocket reply") exclogger.log_exception(exc, to_file=False) return None
def try_parse_setting(self, v): try: # micropython doesn't have "is_numeric" v = v.lstrip().rstrip() if v.lower() == "false": v = False elif v.lower() == "true": v = True elif "." in v: v = float(v) else: v = int(v) except Exception as exc: exclogger.log_exception(exc, to_print = False, to_file = False) return v
def update_imgstream(self): if self.imgstream_sock is None: return try: self.portal.update_imgstream(self.imgstream_sock, self.img_compressed) self.stream_sock_err = 0 except Exception as exc: self.stream_sock_err += 1 if self.stream_sock_err > 5: if self.debug: print("img stream too many errors") exclogger.log_exception(exc, to_file=False) self.kill_imgstreamer() pass
def task_dns(self): if self.winc_mode != network.WINC.MODE_AP: return STS_IDLE # no DNS server if we are not a soft-AP if self.enable_dns == False: return STS_IDLE if self.wlan is None: return STS_IDLE # some code borrowed from https://github.com/amora-labs/micropython-captive-portal/blob/master/captive.py if self.udps is None: self.start_dns() try: data, addr = self.udps.recvfrom(1024) if len(data) <= 0: return STS_IDLE if self.debug: print("dns rx[%s] %u" % (str(addr), len(data))) dominio = '' m = data[2] # ord(data[2]) tipo = (m >> 3) & 15 # Opcode bits if tipo == 0: # Standard query ini = 12 lon = data[ini] # ord(data[ini]) while lon != 0: dominio += data[ini + 1:ini + lon + 1].decode("utf-8") + '.' ini += lon + 1 lon = data[ini] # ord(data[ini]) packet = b'' if dominio: packet += data[:2] + b"\x81\x80" packet += data[4:6] + data[ 4:6] + b'\x00\x00\x00\x00' # Questions and Answers Counts packet += data[12:] # Original Domain Name Question packet += b'\xc0\x0c' # Pointer to domain name packet += b'\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04' # Response type, ttl and resource data length -> 4 bytes packet += bytes(map(int, self.ip.split('.'))) # 4 bytes of IP self.udps.sendto(packet, addr) if self.debug: print("dns resoved %u bytes %s" % (len(packet), dominio)) return True except KeyboardInterrupt: raise except OSError as e: print("dns OSError " + str(e)) self.udps.close() self.udps = None except Exception as e: exclogger.log_exception(e) pass return STS_IDLE
def handle_getimg(self, client_stream, req, headers, content): if self.debug: print("handle_getimg", end="") try: if self.img_compressed is None: client_stream.write( captive_portal.default_reply_header( content_type="image/jpeg", content_length=0)) client_stream.close() if self.debug: print(" no image") return sz = self.img_compressed.size() client_stream.write( captive_portal.default_reply_header(content_type="image/jpeg", content_length=sz)) sent = client_stream.write(self.img_compressed) client_stream.close() if self.debug: print(" sent %u" % sent) except KeyboardInterrupt: raise except Exception as exc: s = exclogger.log_exception(exc) self.reply_ok(client_stream, sts=False, err=s)
def load_settings(self, filename = "settings.json"): obj = None try: with open(filename, mode="rb") as f: obj = ujson.load(f) for i in obj.keys(): v = obj[i] if i in self.settings: self.settings[i] = self.try_parse_setting(v) else: print("extra JSON setting \"%s\": \"%s\"" % (i, str(v))) except KeyboardInterrupt: raise except Exception as exc: exclogger.log_exception(exc) self.apply_settings()
def compress_img(self): if self.img is None: self.img_compressed = None return try: if self.extra_fb is None: self.extra_fb = sensor.alloc_extra_fb(self.cam.width // 2, self.cam.height // 2, sensor.GRAYSCALE) if self.debug: print("compressing (%u %u) ..." % (self.img.height(), self.img.size()), end="") gc.collect() if self.zoom <= 1: self.img_compressed = self.img.scale( x_scale=0.5, y_scale=0.5, copy_to_fb=self.extra_fb).compress(quality=50) else: iw = int(math.floor(self.cam.width / self.zoom)) ih = int(math.floor(self.cam.height / self.zoom)) iwh = int(round(iw / 2.0)) ihh = int(round(ih / 2.0)) roi = (int(math.floor(self.settings["center_x"] - iwh)), int(math.floor(self.settings["center_y"] - ihh)), iw, ih) while roi[0] < 0: roi[0] += 1 while roi[1] < 0: roi[1] += 1 while roi[0] + roi[2] > self.cam.width: roi[0] -= 1 while roi[1] + roi[3] > self.cam.height: roi[1] -= 1 self.img_compressed = self.img.crop( roi, copy_to_fb=self.extra_fb).compress(quality=50) self.prevzoom = self.zoom if self.debug: print( "done (%u %u)" % (self.img_compressed.height(), self.img_compressed.size())) except MemoryError as exc: exclogger.log_exception(exc, to_file=False) pass except Exception as exc: exclogger.log_exception(exc) pass
def decode_hotpixels(str): res = [] split = str.split(";") for i in split: try: istr = i.lstrip().rstrip() isplit = i.split(",") if len(isplit) != 2: continue # isnumeric doesn't exist so no checks available # if it can't be parsed, it will throw an exception x = float(isplit[0]) y = float(isplit[1]) res.append([x, y]) except Exception as exc: exclogger.log_exception(exc, to_file=False) return res
def show(self): if self.oled_ok == False: self.oled_ok = self.oled.test_connect() try: if self.oled_ok: self.oled.init_display() except Exception as exc: self.oled_ok = False exclogger.log_exception(exc) if self.oled_ok == False: return try: if self.framebuffer is None: return self.oled.write_data(self.framebuffer) except Exception as exc: self.oled_ok = False exclogger.log_exception(exc)
def decode_hotpixels(str): res = [] split = str.split(";") for i in split: try: istr = i.lstrip().rstrip() isplit = i.split(",") if len(isplit) != 2: continue # isnumeric doesn't exist so no checks available # if it can't be parsed, it will throw an exception x = int(round(float(isplit[0]))) y = int(round(float(isplit[1]))) # note: custom firmware expects integers, cannot handle floats # note: custom firmware expects a tuple, not a list, use tuple notation res.append((x, y)) except Exception as exc: exclogger.log_exception(exc, to_file=False) return res
def snapshot_finish(self): if self.snap_started == False: return None if self.snap_started == False: return False if self.simulate: while self.snapshot_check() == False: gc.collect() self.snap_started = False return self.img try: self.img = sensor.snapshot_finish() self.has_error = False except RuntimeError as exc: exclogger.log_exception(exc) self.img = None self.has_error = True self.snap_started = False return self.img
def update_websocket(self): if self.websock is None: return state = self.fill_state() json_str = ujson.dumps(state) self.websock.settimeout(10) try: self.portal.websocket_send(self.websock, json_str) self.stream_sock_err = 0 self.websock_millis = pyb.millis() except Exception as exc: self.stream_sock_err += 1 if self.stream_sock_err > 5: if self.debug: print("websock too many errors") exclogger.log_exception(exc, to_file=False) self.kill_websocket() pass while self.check_websocket() == True: pass
def snapshot(self, filename = None): if self.simulate: pyb.delay(self.shutter // 1000) self.snap_started = False return self.img try: if self.snap_started == True: self.img = self.snapshot_finish() else: self.img = sensor.snapshot() if filename == "auto": filename = "%u_%u_%u.jpg" % (self.fileseq, round(self.gain), self.shutter) self.fileseq += 1 if filename is not None: self.img.save(filename, quality = 100) return self.img except RuntimeError as exc: exclogger.log_exception(exc) self.has_error = True return None
def handle_query(self, client_stream, req, reply = True, save = True): try: self.execute_query(req, reply, save) if reply: self.reply_ok(client_stream) except KeyboardInterrupt: raise except Exception as exc: s = exclogger.log_exception(exc) if reply: self.reply_ok(client_stream, sts=False, err=s) return True
def split_post_form(headers, content): d = {} if "content-type" in headers: if headers["content-type"] == "application/x-www-form-urlencoded": try: pairs = content.split('&') for p in pairs: if "=" in p: ei = p.index("=") k = p[0:ei].lstrip().rstrip() v = p[ei + 1:] if len(k) > 0: d.update({k: v}) elif p is not None: p = p.lstrip().rstrip() if len(p) > 0: d.update({p: None}) except ValueError as exc: exclogger.log_exception(exc, to_print=False, to_file=False) except Exception as exc: exclogger.log_exception(exc) return d
def attempt_fw_update(fpath="/winc_19_6_1.bin"): try: st = uos.stat(fpath) wlan = network.WINC(mode=network.WINC.MODE_FIRMWARE) wlan.fw_update(fpath) except OSError as exc2: if exc2.args[0] == 2: while True: print("WiFi shield firmware update file is missing at \"" + fpath + "\"") pyb.delay(500) pass else: exclogger.log_exception(exc2) while True: print("WiFi shield firmware update failed") pyb.delay(500) pass except Exception as exc2: exclogger.log_exception(exc2) while True: print("WiFi shield firmware update failed") pyb.delay(500) pass
def handle_default(self, client_stream, req, headers, content): if self.debug: print("default http handler", end="") request_page, request_urlparams = split_get_request(req) if request_page == "/": request_page = "index.htm" f, fname, fsize, content_type = self.file_try_open(request_page) if f is not None: if self.debug: print(", file \"%s\" as \"%s\" size %u ..." % (fname, content_type, fsize), end="") try: client_stream.write( "HTTP/1.0 200 OK\r\ncontent-type: %s\r\ncache-control: no-cache\r\ncontent-length: %u\r\n\r\n" % (content_type, fsize)) stream_file(client_stream, f) except Exception as exc: exclogger.log_exception(exc) try: f.close() except Exception as exc: exclogger.log_exception(exc, to_print=False, to_file=False) if self.debug: print(" done") else: if self.debug: print(", error 404 \"%s\"" % request_page) client_stream.write( "HTTP/1.0 404\r\ncontent-type: text/html\r\ncache-control: no-cache\r\n\r\n<html><h1>Error 404</h1><br /><h3>File Not Found</h3><br />%s</html>" % request_page) try: client_stream.close() except Exception as exc: exclogger.log_exception(exc, to_print=False, to_file=False)
def task(self): gc.collect() self.diag_cnt += 1 self.t = pyb.millis() self.time_mgr.tick(latest_millis = self.t) self.tick_all, self.dur_all = self.diag_tick(self.t, self.tick_all, self.dur_all) # debug loop speed if self.debug: if (self.diag_cnt % 20) == 0: print("tick %u %u" % (self.diag_cnt, self.frm_cnt)) self.task_network() if self.cam.check_init() == False: if self.websock is not None and pyb.elapsed_millis(self.websock_millis) > 500: self.update_websocket() return if self.cam.snapshot_check(): # camera has finished an exposure self.img = self.cam.snapshot_finish() if self.img is not None: self.frm_cnt += 1 else: self.cam_err = True if self.sleeping: #red_led.off() green_led.off() blue_led.off() if self.extdisp is not None: if self.cam_err: self.extdisp.set_error("ERR + SLP") else: self.extdisp.set_error("SLEEP") self.extdisp.prep(None, None, None) self.extdisp.show() return # day mode is just auto exposure for testing if self.daymode: self.cam.init(gain_db = -1, shutter_us = -1) self.snap_millis = pyb.millis() if self.img is not None: self.histogram = self.img.get_histogram() self.img_stats = self.histogram.get_statistics() if self.packjpeg: self.compress_img() self.cam.snapshot_start() if self.use_leds: green_led.toggle() return # this will skip solving # take the next frame with settings according to mode self.cam.init(gain_db = self.settings["gain"], shutter_us = self.settings["shutter"], force_reset = self.cam_err) already_done = False if self.cam.check_init() == False: already_done = True if self.imgstream_sock is None: self.solve() if self.packjpeg or self.imgstream_sock is not None: self.compress_img() if self.imgstream_sock is not None: self.update_imgstream() while self.cam.check_init() == False: self.task_network() if self.packjpeg == False and self.imgstream_sock is None: self.cam.snapshot_start() self.snap_millis = pyb.millis() if self.use_leds: green_led.toggle() if self.imgstream_sock is None and already_done == False: self.solve() if self.packjpeg or self.imgstream_sock is not None: if already_done == False: self.compress_img() if self.imgstream_sock is not None: self.update_imgstream() self.cam.snapshot_start() self.snap_millis = pyb.millis() self.cam_err = self.cam.has_error self.update_websocket() if self.extdisp is not None: if self.cam_err: self.extdisp.set_error("CAM ERR") elif self.img is None: self.extdisp.set_error("IMG ERR") elif self.expo_code != star_finder.EXPO_JUST_RIGHT: self.extdisp.set_error("EXPO ERR") else: self.extdisp.set_error(None) stable_solution = self.stable_solution() if stable_solution is None: self.extdisp.prep(None, None, None) self.extdisp.show() else: stable_solution.get_pole_coords() rot = stable_solution.get_rotation() + self.time_mgr.get_angle() polecoords = (stable_solution.x, stable_solution.y) if self.settings["use_refraction"]: refrac = comutils.get_refraction(self.time_mgr.latitude) polecoords = comutils.move_point_vector(polecoods, (refrac * stable_solution.pix_per_deg, rot + 90)) self.extdisp.prep(polecoords, (self.settings["center_x"], self.settings["center_y"]), rot) self.extdisp.show() else: if self.extdisp is not None: self.extdisp.task() t = self.extdisp.get_date() if t != 0: self.time_mgr.set_utc_time_epoch(t) self.time_mgr.set_location(self.extdisp.get_longitude(), self.extdisp.get_latitude()) self.settings["longitude"] = self.time_mgr.longitude self.settings["latitude"] = self.time_mgr.latitude if self.has_time == False: exclogger.log_exception("Time Obtained (%u)" % pyb.millis(), time_str=comutils.fmt_time(self.time_mgr.get_time())) self.has_time = True if pyb.elapsed_millis(self.snap_millis) > 5000: self.cam_err = True if self.debug: print("warning: camera timeout") if self.daymode: self.cam.init(gain_db = -1, shutter_us = -1, force_reset = True) else: self.cam.init(gain_db = self.settings["gain"], shutter_us = self.settings["shutter"], force_reset = True) while self.cam.check_init() == False: self.task_network() self.cam.snapshot_start() self.snap_millis = pyb.millis() if self.extdisp is not None: self.extdisp.set_error("CAM ERR") self.extdisp.show() if self.websock is not None and pyb.elapsed_millis(self.websock_millis) > 500: self.update_websocket()
def execute_query(self, req, reply = False, save = False): need_save = False request_page, request_urlparams = captive_portal.split_get_request(req) if self.debug and reply: print(" keys %u" % len(request_urlparams)) for i in request_urlparams.keys(): v = request_urlparams[i] v = self.try_parse_setting(v) if i in self.settings: need_save = True self.settings[i] = v if self.debug and (reply or save): print("setting \"%s\" value \"%s\"" % (i, str(v))) if i == "time": self.time_mgr.set_utc_time_epoch(v) if self.has_time == False: exclogger.log_exception("Time Obtained (%u)" % pyb.millis(), time_str=comutils.fmt_time(self.time_mgr.get_time())) self.has_time = True elif i == "longitude": self.time_mgr.set_location(v, None) self.settings[i] = self.time_mgr.longitude # normalized elif i == "latitude": self.time_mgr.set_location(None, v) self.settings[i] = self.time_mgr.latitude # normalized elif i == "max_stars": self.max_stars = v elif i == "rand_id": self.websock_randid = v elif i == "packjpeg": self.packjpeg = (v == True) if self.zoom != self.prevzoom and self.packjpeg: self.compress_img() elif i == "zoom": self.zoom = v if self.zoom != self.prevzoom and self.packjpeg: self.compress_img() elif i == "hotpixels": self.hot_pixels = star_finder.decode_hotpixels(v) elif i == "accel_sec": self.accel_sec = v elif i == "use_debug": self.debug = v elif i == "use_leds": self.use_leds = v if v == False: red_led.off() green_led.off() blue_led.off() elif i == "sleep": self.sleeping = v if v == False: self.use_leds = False red_led.off() green_led.off() blue_led.off() elif i == "save": save = (v == True) need_save = True else: print("unknown setting \"%s\": \"%s\"" % (i, str(v))) if need_save and save: self.save_settings()