From 7bdce37fd3f18e2712e18c4e2c64cac69af0aca1 Mon Sep 17 00:00:00 2001 From: Jakob Stendahl Date: Sun, 19 Sep 2021 19:43:11 +0200 Subject: :boom: Introduce new UI based on svelte, and rewrite a lot of the node app and the NeoRuntime --- NeoRuntime/Runtime/luxcena_neo/__init__.py | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 NeoRuntime/Runtime/luxcena_neo/__init__.py (limited to 'NeoRuntime/Runtime/luxcena_neo/__init__.py') diff --git a/NeoRuntime/Runtime/luxcena_neo/__init__.py b/NeoRuntime/Runtime/luxcena_neo/__init__.py new file mode 100644 index 0000000..dfec639 --- /dev/null +++ b/NeoRuntime/Runtime/luxcena_neo/__init__.py @@ -0,0 +1,2 @@ +from .neo_behaviour import NeoBehaviour, VariableType +import luxcena_neo.color_utils as utils \ No newline at end of file -- cgit v1.2.3 From 076c967a8aaac929735694f295ade5adaf8c9ff3 Mon Sep 17 00:00:00 2001 From: Jakob Stendahl Date: Sun, 3 Oct 2021 16:41:40 +0200 Subject: :sparkles: Add actual different variable types, this also changes slightly how they are defined --- NeoRuntime/Runtime/luxcena_neo/__init__.py | 2 +- NeoRuntime/Runtime/luxcena_neo/neo_behaviour.py | 131 +++++++++++++++++++++--- 2 files changed, 117 insertions(+), 16 deletions(-) (limited to 'NeoRuntime/Runtime/luxcena_neo/__init__.py') diff --git a/NeoRuntime/Runtime/luxcena_neo/__init__.py b/NeoRuntime/Runtime/luxcena_neo/__init__.py index dfec639..fbbc670 100644 --- a/NeoRuntime/Runtime/luxcena_neo/__init__.py +++ b/NeoRuntime/Runtime/luxcena_neo/__init__.py @@ -1,2 +1,2 @@ -from .neo_behaviour import NeoBehaviour, VariableType +from .neo_behaviour import NeoBehaviour, VariableType, ColorVariable, FloatVariable, IntegerVariable import luxcena_neo.color_utils as utils \ No newline at end of file diff --git a/NeoRuntime/Runtime/luxcena_neo/neo_behaviour.py b/NeoRuntime/Runtime/luxcena_neo/neo_behaviour.py index 9920ca4..66678c4 100644 --- a/NeoRuntime/Runtime/luxcena_neo/neo_behaviour.py +++ b/NeoRuntime/Runtime/luxcena_neo/neo_behaviour.py @@ -1,6 +1,8 @@ import json from os import path from enum import Enum +from .strip import detect_format_convert_color +from .color_utils import rgb_from_24bit, hex_from_24bit class NeoBehaviour: """ @@ -14,7 +16,11 @@ class NeoBehaviour: THIS METHOD SHOULD NOT BE OVERIDDEN! Use onStart if you want a setup-method!!! Contains basic setup """ - self.vars = Variables(package_path) + self.var = Variables(package_path) + + self.declare = self.var.declare + self.declare_variables() + del self.declare def declare_variables(self): """ This should be overridden, and ALL variables should be declared here. """ @@ -47,14 +53,14 @@ class NeoBehaviour: class VariableType(Enum): TEXT = 1 INT = 2 - RANGE = 3 + FLOAT = 3 COLOR = 4 class Variables: def __init__(self, package_path): self.__vars = {} - self.__vars_save_file = f"{package_path}/variables.json" + self.__vars_save_file = f"{package_path}/state.json" self.__saved_variables = {} self.read_saved_variables() @@ -66,8 +72,6 @@ class Variables: def __setattr__(self, name, value): if name in ["_Variables__vars", "_Variables__vars_save_file", "_Variables__saved_variables"]: super(Variables, self).__setattr__(name, value) - elif type(value) == Variable: - self.__vars[name] = value else: self.__vars[name].value = value @@ -101,12 +105,15 @@ class Variables: def __iter__(self): return iter(self.__vars.items()) - def declare(self, name: str, default: any, var_type: VariableType, on_change = None, **kwargs): + def declare(self, variable): """ Declare a new variable. """ - if name in self.__saved_variables: - default = self.__saved_variables[name] - var = Variable(self.save_variables, name, default, var_type, on_change, **kwargs) - self.__setattr__(name, var) + if variable.name in self.__vars: + raise Exception(f"Variable with name {variable.name} already defined.") + if variable.name in self.__saved_variables: + variable.value = self.__saved_variables[variable.name] + + variable.set_save_func(self.save_variables) + self.__vars[variable.name] = variable def read_saved_variables(self): """ Read saved variable values from file. """ @@ -123,17 +130,20 @@ class Variables: with open(self.__vars_save_file, "w") as f: f.write(json.dumps(self.__saved_variables)) + def to_dict(self): + return {x.name: x.to_dict() for x in self.__vars.values()} + class Variable: - def __init__(self, save_func, key, default, var_type, on_change): - self.__save_func = save_func - self.__key = key + def __init__(self, name, default, var_type: VariableType, on_change = None): + self.__name = name self.__value = default self.__var_type = var_type self.__on_change = on_change + self.__save_func = None @property - def key(self): return self.__key + def name(self): return self.__name @property def value(self): return self.__value @@ -141,9 +151,100 @@ class Variable: @value.setter def value(self, value): self.__value = value - self.__save_func() + if self.__save_func is not None: + self.__save_func() if self.__on_change is not None: self.__on_change(self.value) @property def var_type(self): return self.__var_type.name + + def to_dict(self): + return {"name": self.name, "value": self.value, "type": self.var_type} + + def __str__(self): + return f"{self.name}: {self.value}" + + def set_save_func(self, save_func): + self.__save_func = save_func + +class ColorVariable(Variable): + + def __init__(self, name: str, *color, **kwargs): + if not self.verify_color(*color): + raise Exception(f"Invalid color {color}") + super().__init__(name, self.extract_interesting(*color), VariableType.COLOR, **kwargs) + + @Variable.value.setter + def value(self, *color): + if not self.verify_color(*color): + print(f"Attempting to set {self.name} to invalid value {color}") + return + super(ColorVariable, type(self)).value.fset(self, self.extract_interesting(*color)) + + def verify_color(self, *color): + if (len(color) == 1) and (isinstance(color[0], str)): + return True + if (len(color) == 1) and (isinstance(color[0], tuple)): + if len(color[0]) != 3: return False + for c in color[0]: + if not (0 <= c <= 255): return False + return True + if (len(color) == 1) and (isinstance(color[0], int)): + return True + if (len(color) == 3): + for c in color: + if not isinstance(c, int): return False + if not (0 <= c <= 255): return False + return True + return False + + def extract_interesting(self, *color): + if (len(color) == 1): return color[0] + return color + +class IntegerVariable(Variable): + + def __init__(self, name: str, default: int = 0, min_val: int = 0, max_val: int = 255, **kwargs): + self.__min = min_val + self.__max = max_val + super().__init__(name, default, VariableType.INT) + + @Variable.value.setter + def value(self, value): + try: + value = int(value) + if (self.__min <= value <= self.__max): + super(ColorVariable, type(self)).value.fset(self, value) + else: + print(f"Attempted to set {self.name} to {value} but range is [{self.__min},{self.__max}].") + except ValueError: + print(f"Attempted to set {self.name} to \"{value}\", which is not a valid integer...") + + def to_dict(self): + return {"name": self.name, "value": self.value, "type": self.var_type, "min": self.__min, "max": self.__max} + + +class FloatVariable(Variable): + + def __init__(self, name: str, default: float = 0.0, min_val: float = 0.0, max_val: float = 255.0, **kwargs): + self.__min = min_val + self.__max = max_val + super().__init__(name, default, VariableType.FLOAT) + + @Variable.value.setter + def value(self, value): + try: + value = float(value) + if (self.__min <= value <= self.__max): + super(ColorVariable, type(self)).value.fset(self, value) + else: + print(f"Attempted to set {self.name} to {value} but range is [{self.__min},{self.__max}].") + except ValueError: + print(f"Attempted to set {self.name} to \"{value}\", which is not a valid float...") + + def __str__(self): + return round(self.value, 2) + + def to_dict(self): + return {"name": self.name, "value": self.value, "type": self.var_type, "min": self.__min, "max": self.__max} -- cgit v1.2.3 From 4850c11d87df287beacf5a5bd9012f7b54f13566 Mon Sep 17 00:00:00 2001 From: Jakob Stendahl Date: Sun, 3 Oct 2021 20:01:31 +0200 Subject: :sprakles: Add BooleanVariable --- NeoRuntime/Runtime/luxcena_neo/__init__.py | 4 ++-- NeoRuntime/Runtime/luxcena_neo/neo_behaviour.py | 15 +++++++++++++++ NeoRuntime/Runtime/neo_runtime.py | 14 ++++++-------- 3 files changed, 23 insertions(+), 10 deletions(-) (limited to 'NeoRuntime/Runtime/luxcena_neo/__init__.py') diff --git a/NeoRuntime/Runtime/luxcena_neo/__init__.py b/NeoRuntime/Runtime/luxcena_neo/__init__.py index fbbc670..606f365 100644 --- a/NeoRuntime/Runtime/luxcena_neo/__init__.py +++ b/NeoRuntime/Runtime/luxcena_neo/__init__.py @@ -1,2 +1,2 @@ -from .neo_behaviour import NeoBehaviour, VariableType, ColorVariable, FloatVariable, IntegerVariable -import luxcena_neo.color_utils as utils \ No newline at end of file +from .neo_behaviour import NeoBehaviour, VariableType, ColorVariable, FloatVariable, IntegerVariable, BooleanVariable +import luxcena_neo.color_utils as utils diff --git a/NeoRuntime/Runtime/luxcena_neo/neo_behaviour.py b/NeoRuntime/Runtime/luxcena_neo/neo_behaviour.py index 66678c4..dc4609c 100644 --- a/NeoRuntime/Runtime/luxcena_neo/neo_behaviour.py +++ b/NeoRuntime/Runtime/luxcena_neo/neo_behaviour.py @@ -55,6 +55,7 @@ class VariableType(Enum): INT = 2 FLOAT = 3 COLOR = 4 + BOOL = 5 class Variables: @@ -248,3 +249,17 @@ class FloatVariable(Variable): def to_dict(self): return {"name": self.name, "value": self.value, "type": self.var_type, "min": self.__min, "max": self.__max} + + + +class BooleanVariable(Variable): + + def __init__(self, name: str, default: bool, **kwargs): + super().__init__(name, default, VariableType.BOOL) + + @Variable.value.setter + def value(self, value): + try: + value = bool(value) + except: + print(f"Attempted to set {self.name} to \"{value}\", which is not a valid bool...") diff --git a/NeoRuntime/Runtime/neo_runtime.py b/NeoRuntime/Runtime/neo_runtime.py index 4ecbc97..d132bff 100644 --- a/NeoRuntime/Runtime/neo_runtime.py +++ b/NeoRuntime/Runtime/neo_runtime.py @@ -59,7 +59,7 @@ class NeoRuntime: self.__module_th = None self.__socket_file = socket_file self.__send_strip_buffer = False - + def start(self): # The mode is starting in it's own thread @@ -82,7 +82,7 @@ class NeoRuntime: def __bind_socket(self): if path.exists(self.__socket_file): remove(self.__socket_file) - + self.__s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.__s.bind(self.__socket_file) self.__s.listen(1) @@ -126,7 +126,7 @@ class NeoRuntime: rs.close() else: self.__execute_command(data) - + def __close_socket(self): if (self.__s is None): return r, w, e = select.select([self.__s, *self.__s_clients], self.__s_clients, [], 0) @@ -145,22 +145,20 @@ class NeoRuntime: """ command should be of type bytes first byte indicates command type (currently setglob or setvar) - + for command type 1 byte 1 indicates which globvar byte 2 indicates value for command type 2 first 32 bytes are the var name - + """ # print(command.hex(" ")) if command[0] == 0: if command[1] == 0: self.__strip.power_on = (command[2] == 1) - print(f"Strip power: {self.__strip.power_on}") elif command[1] == 1: self.__strip.brightness = command[2] - print(f"Strip brightness: {self.__strip.brightness}") else: print(f"Unknown globvar {command[1]}.") elif command[0] == 1: @@ -236,7 +234,7 @@ if __name__ == "__main__": if not path.exists(f"{args.mode_path}/{args.mode_entry}.py"): print(f"Mode entry not found in mode path ({args.mode_path}/{args.mode_entry}).") sys.exit(1) - + print(f"StripConfig: {args.strip_config}") print(f"Module : {args.mode_path}/{args.mode_entry}") -- cgit v1.2.3