class Zeroconf(dictobj.Spec, hp.AsyncCMMixin): enabled = dictobj.Field(sb.boolean, default=False, help="Whether zeroconf is enabled") ip_address = dictobj.Field( format_into=ip_address_spec, help= "The IP address of this computer. Defaults to automatic discovery.", ) name = dictobj.Field( format_into=sb.string_spec, default=socket.getfqdn().split(".")[0], help= "The name of this Photons Interactor instance. Defaults to the hostname.", ) async def start(self, ts, host, port, sender, finder): self.register = ZeroconfRegisterer(self, ts, host, port, sender, finder) await self.register.start() async def finish(self, exc_typ=None, exc=None, tb=None): if hasattr(self, "register"): await self.register.finish() del self.register
class Wat(dictobj.Spec): one = dictobj.Field(format_into=sb.string_spec) two = dictobj.Field(format_into=sb.string_spec) @property def thing(self): return "{0}.{1}".format(self.one, self.two)
class TileNyanOptions(AnimationOptions): user_coords = dictobj.Field(sb.boolean, default=False) num_iterations = dictobj.Field(sb.integer_spec, default=-1) random_orientations = dictobj.Field(sb.boolean, default=False) speed = dictobj.Field(sb.integer_spec, default=1) @property def direction(self): return MarqueeDirection.RIGHT @property def text_width(self): return 11 @property def text_color(self): class Color: color = None return Color def final_iteration(self, iteration): if self.num_iterations == -1: return False return self.num_iterations <= iteration
class EffectCommand(store.Command): finder = store.injected("finder") target = store.injected("targets.lan") timeout = df.timeout_field matcher = df.matcher_field refresh = df.refresh_field apply_theme = dictobj.Field( sb.boolean, default=False, help= "Whether to apply a theme to the devices before running an animation", ) theme_options = dictobj.Field( sb.dictionary_spec, help="Any options to give to applying a theme") def theme_msg(self, gatherer): everything = {} theme_options = dict(self.theme_options) if "overrides" in theme_options: everything["overrides"] = theme_options["overrides"] if "colors" not in theme_options: theme_options["colors"] = default_colors options = ThemeOptions.FieldSpec().normalise(Meta(everything, []), theme_options) return ApplyTheme.script(options, gatherer=gatherer)
class Options(dictobj.Spec): clean_indication = dictobj.Field(sb.boolean, default=False) clean_last_result = dictobj.Field( enum_spec(None, LightLastHevCycleResult, unpacking=True), default=LightLastHevCycleResult.NONE, ) clean_default_duration_s = dictobj.Field(sb.float_spec, default=7200)
class GlobalOptions(dictobj.Spec): noisy_network = dictobj.Field(noisy_network_option_spec) inflight_limit = dictobj.Field(inflight_limit_option_spec) @classmethod def create(kls, **options): return kls.FieldSpec().empty_normalise(**options)
class LineOptions(dictobj.Spec): rate = dictobj.Field(options.range_spec((0.2, 0.4), rate=True)) line_hues = dictobj.Field(options.color_range_spec("rainbow")) fade_amount = dictobj.Field(sb.float_spec, default=0.1) def make_line(self, length): return Line(length, self.line_hues.color)
class TilePacmanOptions(AnimationOptions): user_coords = dictobj.Field(sb.boolean, default=False) num_iterations = dictobj.Field(sb.integer_spec, default=-1) def final_iteration(self, iteration): if self.num_iterations == -1: return False return self.num_iterations <= iteration
class Options(dictobj.Spec): zones = dictobj.Field(sb.listof(color_spec())) zones_count = dictobj.NullableField(sb.integer_spec) zones_effect = dictobj.Field(enum_spec(None, MultiZoneEffectType, unpacking=True), default=MultiZoneEffectType.OFF)
class NoEnvDiscoveryOptions(DiscoveryOptions): """ A DiscoveryOptions that doesn't care about environment variables """ serial_filter = dictobj.Field(serial_filter_spec(see_env=False)) hardcoded_discovery = dictobj.Field( hardcoded_discovery_spec(see_env=False))
class NoDiscoveryOptions(DiscoveryOptions): """ A DiscoveryOptions object that will never have hardcoded_discovery or serial_filter """ serial_filter = dictobj.Field(sb.overridden(None)) hardcoded_discovery = dictobj.Field(sb.overridden(None))
class Highlight(store.Command): arranger = store.injected("arranger") serial = dictobj.Field(serial_spec, wrapper=sb.required) part_number = dictobj.Field(sb.integer_spec, wrapper=sb.required) async def execute(self): await self.arranger.add_highlight((self.serial, self.part_number))
class Database(dictobj.Spec): uri = dictobj.Field(format_into=database_uri_spec(), help="Uri to our database") db_migrations = dictobj.Field( sb.overridden( os.path.join("{interactor:resource}", "database", "migrations")), format_into=sb.directory_spec, )
class Options(dictobj.Spec): twinkles_color_range = dictobj.Field(options.color_range_spec("rainbow")) twinkles_max_percent = dictobj.Field( options.range_spec((0.1, 0.3), rate=True)) twinkles_percent_added_at_once = dictobj.Field( options.range_spec((0.01, 0.02), rate=True)) fade_in_speed = dictobj.Field(options.range_spec((0.1, 0.2), rate=True)) fade_out_speed = dictobj.Field(options.range_spec((0.1, 0.2), rate=True))
class Options(dictobj.Spec): hour24 = dictobj.Field(sb.boolean, default=True) ignore_coordinates = dictobj.Field(sb.boolean, default=False) progress_times = dictobj.Field(sb.integer_spec, default=8) number_color_range = dictobj.Field( options.color_range_spec("0,0,0.8,6000")) progress_color_range = dictobj.Field( options.color_range_spec("0-360,1,0.2,3500"))
class Fields(dictobj.Spec): uuid = dictobj.Field(sb.string_spec, wrapper=sb.required) matcher = dictobj.Field( json_string_spec(sb.dictionary_spec(), storing), wrapper=sb.required ) power = dictobj.NullableField(sb.boolean) color = dictobj.NullableField(sb.string_spec) zones = dictobj.NullableField(json_string_spec(sb.listof(hsbk()), storing)) chain = dictobj.NullableField(json_string_spec(sb.listof(chain_spec), storing)) duration = dictobj.NullableField(sb.integer_spec)
class C(dictobj.Spec): hue = dictobj.Field(sb.float_spec, default=h) saturation = dictobj.Field(sb.float_spec, default=s) brightness = dictobj.Field(sb.float_spec, default=b) kelvin = dictobj.Field(sb.integer_spec, default=k) @property def color(self): return Color(self.hue, self.saturation, self.brightness, self.kelvin)
class MemoryTarget(Target): """ Knows how to talk to fake devices as if they were on the network. """ devices = dictobj.Field(sb.listof(sb.any_spec()), wrapper=sb.required) default_broadcast = dictobj.Field( sb.defaulted(sb.string_spec(), "255.255.255.255")) session_kls = makeMemorySession(NetworkSession)
class Options(dictobj.Spec): chain = dictobj.Field(sb.listof(TileChild.FieldSpec())) chain_length = dictobj.NullableField(sb.integer_spec) palette = dictobj.Field(sb.listof(color_spec())) palette_count = dictobj.NullableField(sb.integer_spec) matrix_effect = dictobj.Field(enum_spec(None, TileEffectType, unpacking=True), default=TileEffectType.OFF)
class Database(dictobj.Spec): uri = dictobj.Field(sb.string_spec, wrapper=sb.required, formatted=True, help="Uri to our database") db_migrations = dictobj.Field( sb.overridden( os.path.join("{photons_interactor:resource}", "database", "migrations")), format_into=sb.directory_spec, )
class ChanegPosition(store.Command): arranger = store.injected("arranger") serial = dictobj.Field(serial_spec, wrapper=sb.required) part_number = dictobj.Field(sb.integer_spec, wrapper=sb.required) user_x = dictobj.Field(sb.integer_spec, wrapper=sb.required) user_y = dictobj.Field(sb.integer_spec, wrapper=sb.required) async def execute(self): await self.arranger.change_position(self.serial, self.part_number, self.user_x, self.user_y)
class LanTarget(Target): """ Knows how to talk to a device over the local network. It's one configuration option is default_broadcast which says what address to broadcast discovery if broadcast is given to run calls as True. """ default_broadcast = dictobj.Field( sb.defaulted(sb.string_spec(), "255.255.255.255")) discovery_options = dictobj.Field(discovery_options_spec) session_kls = NetworkSession
class TileTwinklesOptions(AnimationOptions): num_iterations = dictobj.Field(sb.integer_spec, default=-1) palette = dictobj.Field(choose_palette()) num_twinkles = dictobj.Field(sb.integer_spec, default=20) fade_in_speed = dictobj.Field(sb.float_spec, default=0.125) fade_out_speed = dictobj.Field(sb.float_spec, default=0.078) def final_iteration(self, iteration): if self.num_iterations == -1: return False return self.num_iterations <= iteration
class EffectCommand(store.Command, DeviceChangeMixin): apply_theme = dictobj.Field( sb.boolean, default=False, help= "Whether to apply a theme to the devices before running an animation", ) theme_options = dictobj.Field( sb.dictionary_spec, help="Any options to give to applying a theme") def theme_msg(self): return ApplyTheme.msg(self.theme_options)
class BackgroundOption(dictobj.Spec): type = dictobj.Field(sb.string_choice_spec(["specified", "current"]), default="specified") hue = dictobj.Field(sb.float_spec, default=0) saturation = dictobj.Field(sb.float_spec, default=0) brightness = dictobj.Field(sb.float_spec, default=0) kelvin = dictobj.Field(sb.float_spec, default=3500) @property def default_color(self): return Color(self.hue, self.saturation, self.brightness, self.kelvin)
class HighlightArrangeCommand(store.Command): finder = store.injected("finder") target = store.injected("targets.lan") arranger = store.injected("arranger") serial = dictobj.Field(sb.string_spec, wrapper=sb.required) tile_index = dictobj.Field(sb.integer_spec, wrapper=sb.required) async def execute(self): afr = await self.finder.args_for_run() await self.arranger.highlight(self.serial, self.tile_index, self.target, afr) return {"ok": True}
class Thing(dictobj.Spec): one = dictobj.Field(sb.integer_spec) two = dictobj.Field( sb.integer_spec, default=20, help=""" two is good """, ) three = dictobj.Field(sb.string_spec, wrapper=sb.required, help="three")
class Collection(dictobj.Spec): label = dictobj.Field(sb.string_spec, default="") identity = dictobj.Field(identity_spec, default=b"") updated_at = dictobj.Field(sb.integer_spec, default=0) @classmethod def create(self, *, identity=sb.NotSpecified, label=sb.NotSpecified, updated_at=sb.NotSpecified): return Collection.FieldSpec().empty_normalise(identity=identity, label=label, updated_at=updated_at)
class TransformCommand(store.Command): """ Apply a http api like transformation to the lights """ finder = store.injected("finder") target = store.injected("targets.lan") matcher = df.matcher_field timeout = df.timeout_field refresh = df.refresh_field transform = dictobj.Field( sb.dictionary_spec(), wrapper=sb.required, help=""" A dictionary of what options to use to transform the lights with. For example, ``{"power": "on", "color": "red"}`` Or, ``{"color": "blue", "effect": "breathe", "cycles": 5}`` """, ) transform_options = dictobj.Field( sb.dictionary_spec(), help=""" A dictionay of options that modify the way the tranform is performed: keep_brightness Ignore brightness options in the request transition_color If the light is off and we power on, setting this to True will mean the color of the light is not set to the new color before we make it appear to be on. This defaults to False, which means it will appear to turn on with the new color """, ) async def execute(self): fltr = chp.filter_from_matcher(self.matcher, self.refresh) msg = Transformer.using(self.transform, **self.transform_options) script = self.target.script(msg) return await chp.run( script, fltr, self.finder, add_replies=False, message_timeout=self.timeout )
class Options(dictobj.Spec): host = dictobj.Field(host_spec, default="127.0.0.1", help="The host to serve the server on") port = dictobj.Field( port_spec, help="The port to serve the server on. Not Specifying this will result in choosing a port on your computer that isn't currently in use", ) assets = dictobj.Field( Assets.FieldSpec(formatter=MergedOptionStringFormatter), help="Options for where assets can be found", ) animation_options = dictobj.Field(get_animation_options)