def create_payload(dht_sensor): dht_sensor.measure() measures = OrderedDict([('temperature', dht_sensor.temperature()), ('humidity', dht_sensor.humidity())]) values = [v for _, v in measures.items()] packed = pack('>HH', *values) base64 = b2a_base64(packed) return base64.strip() # dump trailing \n
# # Copyright (c) 2006-2019, RT-Thread Development Team # # SPDX-License-Identifier: MIT License # # Change Logs: # Date Author Notes # 2019-06-13 SummerGift first version # from ucollections import OrderedDict from ucollections import namedtuple print("namedtuple example:") MyTuple = namedtuple("MyTuple", ("id", "name")) t1 = MyTuple(1, "foo") t2 = MyTuple(2, "bar") print(t1.name) print(t2.name) assert t2.name == t2[1] print("\nOrderedDict example:") # To make benefit of ordered keys, OrderedDict should be initialized # from sequence of (key, value) pairs. d = OrderedDict([("z", 1), ("a", 2)]) # More items can be added as usual d["w"] = 5 d["b"] = 3 for k, v in d.items(): print("%s %s" % (k, v))
class Store: __store__ = "./store" __schema__ = "" __config__ = [] def __init__(self, schema=None, store_path=None, store_config=None, store_schema=None): self.schema = schema self.config = None if store_path: Store.__store__ = store_path if store_config: Store.__config__ = store_config if store_schema: Store.__schema__ = store_schema self.schema = store_schema # store directory self.store_location() # store schema directory self.schema_location() def schema_init(self): self.config = None if self.schema == Store.__schema__: self.config = Store.__config__ else: sch_obj = self.select_one(self.schema, schema=True) if sch_obj: self.config = OrderedDict(sch_obj["sch"]) self.schema_location() @classmethod def get_store(cls, name): return cls(schema=name) @classmethod def path_to_store(cls): return "{}".format(cls.__store__) def path_to_schema(self): return "{}/{}".format(self.__store__, self.schema) def path_to_data(self, data, schema=False): if schema: schema = self.__schema__ else: schema = self.schema return "{}/{}/{}".format(self.__store__, schema, data) @classmethod def list_dir(cls, path): try: return uos.listdir(path) except OSError as e: log.debug("LSDIR: {}".format(e)) return None @classmethod def create_dir(cls, name): try: uos.mkdir(name) except OSError as e: log.debug("MKDIR: {}, {}".format(e, name)) return False log.info("MKDIR: {}".format(name)) return True @classmethod def store_location(cls): _path = cls.path_to_store() if not isdir(_path): cls.create_dir(_path) def schema_location(self): _path = self.path_to_schema() if not isdir(_path): self.create_dir(_path) def validate(self, cfg): ''' val[0] = type val[1] = default value ''' error = False remove = [k for k in cfg.keys() if k.startswith("_")] for k in remove: del cfg[k] for key, val in self.config.items(): _type = getattr(builtins, val[0]) if key not in cfg: cfg[key] = self.default(val[1]) elif type(cfg[key]) != _type and not callable(val[1]): try: if val[0] == "bool": cfg[key] = self.str2bool(cfg[key]) else: cfg[key] = _type(cfg[key]) except Exception as e: log.error("VALIDATE:{}".format(e, )) cfg[key] = self.default(val[1]) error = "error:{}".format(e) break cfg[key] = self.secret(cfg[key]) # log.debug("VALIDATE: {}".format(cfg)) log.debug("VALIDATE: {}".format("OK")) return error @staticmethod def from_file(file): result = {} if isfile(file): with open(file) as f: try: fc = f.read() result = ujson.loads(fc) except Exception as e: log.error("Error: from file: {} - {}".format( file, e, )) pass return result def write(self, config): error = False if "name" in config: _name = config["name"] _upd = None if "_upd" in config: _upd = config["_upd"] mode = False is_file = isfile(self.path_to_data(_name)) if not is_file: mode = "w" elif _upd: mode = "w+" new_config = self.select_one(_name) if new_config: del config["name"] new_config.update(config) config = new_config if _upd is not None and not _upd: mode = False log.debug("Open Mode: {}, path:{}".format( mode, self.path_to_data(_name))) if mode: error = self.validate(config) if not error: file = self.path_to_data(_name) log.debug("fullpath: {}".format(file)) data = ujson.dumps(config) log.debug("Data dump !") with open(file, mode) as f: log.debug("File Opened !") # data_to_file = ujson.dumps(config) f.write(data) log.info("+") return error @staticmethod def default(default): if callable(default): default = default() return default @staticmethod def str2bool(val): return val.lower() in ("yes", "true", "1") @staticmethod def secret(val): secret = "!secret " if isinstance(val, str) and val.startswith(secret): val = val.split(secret, 1)[-1] try: with open("./secret") as f: for line in f: if line.startswith(val): val = line.split(":")[-1].rstrip() except Exception as e: log.error("Error: secret file: {}".format(e)) pass return val # select def select_one(self, name, schema=False): file = self.path_to_data(name, schema=schema) if isfile(file): with open(file) as f: data = f.read() if data: return ujson.loads(data) def select(self, **fields): for cfg_name in self.list_dir(self.path_to_schema()): with open(self.path_to_data(cfg_name)) as f: f_cfg = f.read() if f_cfg: row = ujson.loads(f_cfg) for key in self.config: if key in fields and key in row: if row[key] == fields[key]: yield row # scan def scan(self): _list = [] for cfg_name in self.list_dir(self.path_to_schema()): _list.append(self.select_one(cfg_name)) return _list @classmethod def scan_store(cls): for file_name in cls.list_dir(cls.path_to_store()): yield file_name def scan_name(self): for file_name in self.list_dir(self.path_to_schema()): yield file_name # delete def delete(self, where): _name = "name" if len(where) == 1 and _name in where: uos.remove(self.path_to_data(where[_name])) return True
class Led: def __init__(self, scr, num, pin, rings=None): self.screen = scr self.screen.print("{:d} leds, pin {:d}".format(num, pin)) self.leds = neopixel.NeoPixel(machine.Pin(pin), num, timing=1, use_dma=True) self.leds.fill((0, 0, 0)) self.leds.write() self._patterns = OrderedDict([("rainbow", self.pat_rainbow), ("cylon", self.pat_bounce), ("rainbow cylon", self.pat_rainbowcyl), ("marquee", self.pat_marquee), ("solid", self.pat_solid), ("pulse", self.pat_pulse), ("rgb party", self.pat_rgb_party), ("flame", self.pat_flame), ("flame_g", self.pat_flame_g), ("flame_b", self.pat_flame_b)]) self._oneshots = OrderedDict([ ("bump", self.one_bump), ("whoosh", self.one_whoosh), ("rgb", self.one_rgb), ]) if (rings): ring_pats = OrderedDict([("r_radar", self.pat_radar), ("r_tunnel", self.pat_tunnel), ("r_bubbles", self.pat_bubbles)]) self.rings = rings self._patterns.update(ring_pats) else: self.rings = None self.hue = 0 self._colors = OrderedDict([("red", 0), ("orange", 30), ("yellow", 50), ("green", 120), ("blue", 240), ("indigo", 260), ("violet", 280)]) self.intens = 0.2 # 0-1, float self._active = self.pat_rainbow self.period = 0.2 # seconds self.stop_thread = False self.pat_chg = False _thread.start_new_thread(self.led_timer_thread, (None, )) def led_timer_thread(self, unused): num = self.leds.n while True: if (not self.stop_thread): self._active(num) sleep(self.period) self.pat_chg = False def led_timer_stop(self): self.stop_thread = True self.pat_chg = True def led_timer_start(self): if (self.stop_thread): self.stop_thread = False # RGB/HSV stuff from http://code.activestate.com/recipes/576919-python-rgb-and-hsv-conversion/ def hsv2rgb(self, h, s, v): h = float(h) s = float(s) v = float(v) h60 = h / 60.0 h60f = math.floor(h60) hi = int(h60f) % 6 f = h60 - h60f p = v * (1 - s) q = v * (1 - f * s) t = v * (1 - (1 - f) * s) r, g, b = 0, 0, 0 if hi == 0: r, g, b = v, t, p elif hi == 1: r, g, b = q, v, p elif hi == 2: r, g, b = p, v, t elif hi == 3: r, g, b = p, q, v elif hi == 4: r, g, b = t, p, v elif hi == 5: r, g, b = v, p, q r, g, b = int(r * 255), int(g * 255), int(b * 255) return r, g, b def rgb2hsv(self, r, g, b): r, g, b = r / 255.0, g / 255.0, b / 255.0 mx = max(r, g, b) mn = min(r, g, b) df = mx - mn if mx == mn: h = 0 elif mx == r: h = (60 * ((g - b) / df) + 360) % 360 elif mx == g: h = (60 * ((b - r) / df) + 120) % 360 elif mx == b: h = (60 * ((r - g) / df) + 240) % 360 if mx == 0: s = 0 else: s = df / mx v = mx return h, s, v @property def patterns(self): return list(self._patterns.keys()) @property def oneshots(self): return list(self._oneshots.keys()) @property def colors(self): return list(self._colors.keys()) @property def color_str(self): try: return next(key for key, self.hue in self._colors.items()) except StopIteration: return "red" @color_str.setter def color_str(self, name): self.hue = self._colors[name] @property def active_pat(self): try: return self.patterns[list(self._patterns.values()).index( self._active)] except StopIteration: raise ValueError @active_pat.setter def active_pat(self, name): self.screen.print("Selected " + name) self._active = self._patterns[name] self.pat_chg = True def do_oneshot(self, name): self.screen.print("OneShot " + name) self.pat_chg = True self.stop_thread = True self._oneshots[name]() self.stop_thread = False def pat_rainbow(self, num): step = 360 / num pos = 0 while (not self.pat_chg): for i in range(0, num): hue = ((i + pos) * step) % 360 rgb = self.hsv2rgb(hue, 1, self.intens) #print("hue {:f} pos {:d} rgb ".format(hue, self.pos) + str(rgb)) self.leds[i] = rgb self.leds.write() pos = (pos + 1) % num sleep(self.period) def pat_bounce(self, num): pos = 0 reverse = 0 while (not self.pat_chg): if (reverse): i = num - pos - 1 else: i = pos self.leds[i] = self.hsv2rgb(self.hue, 1, self.intens) self.leds.write() self.leds[i] = (0, 0, 0) if (pos == (num - 1)): reverse = not reverse pos = (pos + 1) % num sleep(self.period / 8) def pat_marquee(self, num): pos = 0 while (not self.pat_chg): for i in range(0, num): if ((i + pos) % 4 == 0): self.leds[i] = self.hsv2rgb(self.hue, 1, self.intens) else: self.leds[i] = (0, 0, 0) self.leds.write() pos = (pos + 1) % num sleep(self.period / 2) def pat_rainbowcyl(self, num): pos = 0 reverse = 0 step = 360 / num while (not self.pat_chg): if (reverse): i = num - pos - 1 else: i = pos hue = (pos * step) % 360 self.leds[i] = self.hsv2rgb(hue, 1, self.intens) self.leds.write() self.leds[i] = (0, 0, 0) if (pos == (num - 1)): reverse = not reverse pos = (pos + 1) % num sleep(self.period / 8) def pat_solid(self, num): self.leds.fill(self.hsv2rgb(self.hue, 1, self.intens)) self.leds.write() self.led_timer_stop() def pat_pulse(self, num): pos = 0 pulsing = 0 while (not self.pat_chg): if (pos == 0): pulsing = not pulsing self.leds.fill(self.hsv2rgb(self.hue, 1, self.intens)) if (pulsing): for i in range(pos - 8, pos): if (i >= 0): self.leds[i] = self.hsv2rgb( self.hue, 1, self.intens / (2**(9 - (pos - i)))) self.leds[pos] = (0, 0, 0) elif (pos < 8): for i in range(1, 9 - pos): self.leds[num - i] = self.hsv2rgb( self.hue, 1, self.intens / (2**(9 - (i + pos)))) self.leds.write() pos = (pos + 1) % num sleep(self.period / 4) def pat_radar(self, num): self.leds.fill((0, 0, 0)) pos = 0 while (not self.pat_chg): self.leds.fill((0, 0, 0)) for j, len in enumerate(self.rings): offset = sum(self.rings[:j]) index = (pos % len) + offset self.leds[index] = self.hsv2rgb(self.hue, 1, self.intens) self.leds.write() pos = (pos + 1) % num sleep(self.period / 4) def pat_tunnel(self, num): ring = 0 while (not self.pat_chg): self.leds.fill((0, 0, 0)) offset = sum(self.rings[:ring]) for i in range(offset, offset + self.rings[ring]): self.leds[i] = self.hsv2rgb(self.hue, 1, self.intens) self.leds.write() ring = (ring + 1) % len(self.rings) sleep(self.period) def pat_bubbles(self, num): ring = 0 self.leds.fill((0, 0, 0)) while (not self.pat_chg): self.leds.fill((0, 0, 0)) ring = random.randint(0, len(self.rings) - 1) offset = sum(self.rings[:ring]) color = self.hsv2rgb(random.randint(0, 359), 1, self.intens) for i in range(offset, offset + self.rings[ring]): self.leds[i] = color self.leds.write() sleep(self.period) def pat_rgb_party(self, num): pos = 0 cycle = 0 while (not self.pat_chg): self.leds[pos] = self.hsv2rgb(cycle * 90, 1, self.intens) self.leds.write() pos = (pos + 1) % num if (pos == 0): cycle = (cycle + 1) % 3 sleep(self.period / 16) # adapted from an arduino pattern at: # http://www.funkboxing.com/wordpress/wp-content/_postfiles/fluxbox_octo.ino def _pat_flame_internal(self, hmin, hmax, num): acolor = (0, 0, 0) hdif = hmax - hmin ahue = hmin self.leds.fill((0, 0, 0)) self.leds.write() while (not self.pat_chg): idelay = random.randint(1, 10) randtemp = random.randint(0, 3) hinc = (hdif / float(num)) + randtemp spread = random.randint(1, 5) start = random.randint(0, num - spread) for i in range(start, start + spread): if ((ahue + hinc) > hmax): ahue = hmin else: ahue = ahue + hinc acolor = self.hsv2rgb(ahue, 1, self.intens) self.leds[i] = acolor self.leds[num - i - 1] = acolor self.leds.write() sleep(idelay / 100.0) def pat_flame(self, num): self._pat_flame_internal(0.1, 40.0, num) def pat_flame_g(self, num): self._pat_flame_internal(80.0, 160.0, num) def pat_flame_b(self, num): self._pat_flame_internal(180.0, 280.0, num) def one_bump(self): time = self.period / 4 for i in range(0, 4): self.leds.fill(self.hsv2rgb(self.hue, 1, self.intens)) self.leds.write() sleep(time) self.leds.fill((0, 0, 0)) self.leds.write() sleep(time) def one_whoosh(self): color = self.hsv2rgb(self.hue, 1, self.intens) for i in range(0, self.leds.n): self.leds[i] = color if (i - 1 > 0): self.leds[i - 1] = color if (i - 2 > 0): self.leds[i - 2] = color if (i - 3 > 0): self.leds[i - 3] = color if (i - 4 > 0): self.leds[i - 4] = color self.leds.write() def one_rgb(self): time = self.period / 2 self.leds.fill((0, 0, 0)) self.leds.write() sleep(time) self.leds.fill((255, 0, 0)) self.leds.write() sleep(time) self.leds.fill((0, 255, 0)) self.leds.write() sleep(time) self.leds.fill((0, 0, 255)) self.leds.write() sleep(time)
# -*- coding: utf-8 -*- """LED Color Helpers and Definitions""" from ucollections import OrderedDict, namedtuple Color = namedtuple('RGB', ('red', 'green', 'blue')) COLORS = {} class RGB(Color): """RGB Color Abstraction""" def to_hex(self): """convert color to hex""" return '#{:02X}{:02X}{:02X}'.format(self.red, self.green, self.blue) # Colors WHITESMOKE = RGB(245, 245, 245) ORANGE = RGB(255, 128, 0) RED4 = RGB(139, 0, 0) COLORS['whitesmoke'] = WHITESMOKE COLORS['orange'] = ORANGE COLORS['red4'] = RED4 COLORS = OrderedDict(sorted(COLORS.items()), key=lambda x: x[0])