class Schedule(dictobj.Spec): days = dictobj.NullableField( sb.listof(enum_spec(None, Days, unpacking=True))) hour = dictobj.Field(range_spec(sb.integer_spec(), 0, 23), wrapper=sb.required) minute = dictobj.Field(range_spec(sb.integer_spec(), 0, 59), wrapper=sb.required) task = dictobj.Field(task_spec) hue = dictobj.Field(range_spec(sb.float_spec(), 0, 360), default=0) saturation = dictobj.Field(range_spec(sb.float_spec(), 0, 1), default=0) brightness = dictobj.Field(range_spec(sb.float_spec(), 0, 1), default=1) kelvin = dictobj.Field(range_spec(sb.integer_spec(), 1500, 9000), default=3500) transform_options = dictobj.NullableField( sb.dictof(sb.string_spec(), sb.boolean())) duration = dictobj.NullableField(sb.float_spec) power = dictobj.NullableField(power_spec) colors = dictobj.NullableField(colors_spec) override = dictobj.NullableField( sb.dictof(sb.string_spec(), range_spec(sb.float_spec(), 0, 1))) reference = dictobj.Field(reference_spec) @property def hsbk(self): if self.task == 'lan:transform': keys = ["hue", "saturation", "brightness", "kelvin"] options = {k: v for k, v in self.as_dict().items() if k in keys} return {k: v for k, v in options.items() if v is not None} else: return {} @property def extra(self): keys_except = [ "days", "hour", "minute", "reference", "task", "hue", "saturation", "brightness", "kelvin" ] options = { k: v for k, v in self.as_dict().items() if k not in keys_except } return {k: v for k, v in options.items() if v is not None} @property def dow(self): days = self.days if not self.days: days = list(Days) return [day.value for day in days]
async def set_chain_state(collector, target, reference, artifact, **kwargs): """ Set the state of colors on your tile ``lan:set_chain_state d073d5f09124 -- '{"colors": [[[0, 0, 0, 3500], [0, 0, 0, 3500], ...], [[0, 0, 1, 3500], ...], ...], "tile_index": 1, "length": 1, "x": 0, "y": 0, "width": 8}'`` Where the colors is a grid of 8 rows of 8 ``[h, s, b, k]`` values. """ # noqa options = collector.photons_app.extra_as_json if "colors" in options: spec = sb.listof( sb.listof( list_spec(sb.integer_spec(), sb.float_spec(), sb.float_spec(), sb.integer_spec()))) colors = spec.normalise(Meta.empty().at("colors"), options["colors"]) row_lengths = [len(row) for row in colors] if len(set(row_lengths)) != 1: raise PhotonsAppError( "Please specify colors as a grid with the same length rows", got=row_lengths) num_cells = sum(len(row) for row in colors) if num_cells != 64: raise PhotonsAppError("Please specify 64 colors", got=num_cells) cells = [] for row in colors: for col in row: cells.append({ "hue": col[0], "saturation": col[1], "brightness": col[2], "kelvin": col[3] }) options["colors"] = cells else: raise PhotonsAppError( "Please specify colors in options after -- as a grid of [h, s, b, k]" ) missing = [] for field in TileMessages.Set64.Payload.Meta.all_names: if field not in options and field not in ("duration", "reserved6"): missing.append(field) if missing: raise PhotonsAppError("Missing options for the SetTileState message", missing=missing) options["res_required"] = False msg = TileMessages.Set64.empty_normalise(**options) await target.send(msg, reference)
async def execute_task(self, **kwargs): extra = self.photons_app.extra_as_json positions = sb.listof(sb.listof(sb.float_spec())).normalise( Meta.empty(), extra) if any(len(position) != 2 for position in positions): raise PhotonsAppError( "Please enter positions as a list of two item lists of user_x, user_y" ) async def gen(reference, sender, **kwargs): ps = sender.make_plans("capability") async for serial, _, info in sender.gatherer.gather( ps, reference, **kwargs): if info["cap"].has_matrix: for i, (user_x, user_y) in enumerate(positions): yield TileMessages.SetUserPosition( tile_index=i, user_x=user_x, user_y=user_y, res_required=False, target=serial, ) await self.target.send(FromGenerator(gen), self.reference)
async def set_tile_positions(collector, target, reference, **kwargs): """ Set the positions of the tiles in your chain. ``lan:set_tile_positions d073d5f09124 -- '[[0, 0], [-1, 0], [-1, 1]]'`` """ extra = collector.photons_app.extra_as_json positions = sb.listof(sb.listof(sb.float_spec())).normalise( Meta.empty(), extra) if any(len(position) != 2 for position in positions): raise PhotonsAppError( "Please enter positions as a list of two item lists of user_x, user_y" ) async def gen(reference, sender, **kwargs): ps = sender.make_plans("capability") async for serial, _, info in sender.gatherer.gather( ps, reference, **kwargs): if info["cap"].has_matrix: for i, (user_x, user_y) in enumerate(positions): yield TileMessages.SetUserPosition( tile_index=i, user_x=user_x, user_y=user_y, res_required=False, target=serial, ) await target.send(FromGenerator(gen), reference)
def normalise_filled(self, meta, val): if type(val) is str: val = val.split(",") if type(val) is list: res = [] for pair in val: if type(pair) is not str: res.append(pair) else: if "-" in pair: res.append(tuple(v.strip() for v in pair.split("-", 1))) else: res.append((pair.strip(), pair.strip())) val = res return sb.listof(sb.tuple_spec(sb.float_spec(), sb.float_spec())).normalise(meta, val)
class Options(dictobj.Spec): colors = dictobj.Field(colors_spec) duration = dictobj.Field(sb.float_spec(), default=1) power_on = dictobj.Field(sb.boolean, default=True) overrides = dictobj.Field(Overrides.FieldSpec) @hp.memoized_property def override_layer(self): def layer(point, canvas): c = canvas[point] if c is not None: return canvas.override(point, **self.overrides) else: return c return layer
def __init__(self, minimum, maximum, spec=None): self.minimum = minimum self.maximum = maximum self.spec = spec or sb.float_spec()
def normalise_filled(self, meta, val): return int(sb.float_spec().normalise(meta, val))
async def execute_task(self, **kwargs): options = self.photons_app.extra_as_json width = options.get("width", 8) options["width"] = width if "colors" in options: spec = sb.listof( sb.listof( list_spec(sb.integer_spec(), sb.float_spec(), sb.float_spec(), sb.integer_spec()))) colors = spec.normalise(Meta.empty().at("colors"), options["colors"]) row_lengths = [len(row) for row in colors] if len(set(row_lengths)) != 1: raise PhotonsAppError( "Please specify colors as a grid with the same length rows", got=row_lengths) cells = [] for row in colors: while len(row) < width: row.append(None) for col in row: if col is None: cells.append({ "hue": 0, "saturation": 0, "brightness": 0, "kelvin": 3500 }) continue cells.append({ "hue": col[0], "saturation": col[1], "brightness": col[2], "kelvin": col[3], }) options["colors"] = cells else: raise PhotonsAppError( "Please specify colors in options after -- as a grid of [h, s, b, k]" ) missing = [] for field in TileMessages.Set64.Payload.Meta.all_names: if field not in options and field not in ("duration", "reserved6"): missing.append(field) if missing: raise PhotonsAppError( "Missing options for the SetTileState message", missing=missing) options["res_required"] = False msg = TileMessages.Set64.create(**options) await self.target.send(msg, self.reference)
# coding: spec from interactor.commander.spec_description import signature from delfick_project.norms import sb describe "signature": def assertSignature(self, spec, want): assert " ".join(signature(spec)) == want it "knows about integer_spec": self.assertSignature(sb.integer_spec(), "integer") it "knows about float_spec": self.assertSignature(sb.float_spec(), "float") it "knows about string_spec": self.assertSignature(sb.string_spec(), "string") it "knows about boolean": self.assertSignature(sb.boolean(), "boolean") it "knows about dictionary_spec": self.assertSignature(sb.dictionary_spec(), "dictionary") it "knows about string_choice_spec": self.assertSignature(sb.string_choice_spec(["one", "two"]), "choice of (one | two)") it "knows about optional_spec": self.assertSignature(sb.optional_spec(sb.integer_spec()), "integer (optional)")
def normalise_filled(self, meta, val): return sb.listof(tuple_spec(sb.float_spec(), sb.float_spec())).normalise(meta, val)
class Options(dictobj.Spec): colors = dictobj.Field(colors_spec, wrapper=sb.required) theme = dictobj.Field(sb.string_choice_spec(appliers.keys()), default="SPLOTCH") duration = dictobj.Field(sb.float_spec(), default=1) overrides = dictobj.Field(sb.dictionary_spec)