def __init__(self, key, config): ct.print_info("New {} named {} initialised with {}".format(type(self).__name__, key, config)) self.name = key if not isinstance(config, dict): #initialize single line component from str by converting it into a multi line component ct.print_debug("Converting from single line to multi line Component") config = {"input": config} # init name of the component # default implementation creates "output" connected to a signal with the configured name, driven by this component self.init_name(config) #initialize multi line components from config dictionary # create signals or constants for inputs, adds self to fanout ct.print_debug("Initializing Inputs") self.init_ports_from_dict(config, type(self).inputs, Signal.create_by_input_string) # create constants for parameter, adds self to fantout ct.print_debug("Initializing Params") self.init_ports_from_dict(config, type(self).params, type(self).init_param) #create additional outputs, sets self as source ct.print_debug("Initializing Outputs") self.init_ports_from_dict(config, type(self).outputs, Signal.get_by_name, False) self.post_init(config) # when done there should be no connections left in configuration if len(config) != 0: ct.print_warning("unmatched connections".format(config.items()))
def netlist_from_config(cls, config): for compname, compconfig in config.items(): modname = "components." + compname classname = "".join(word[0].upper() + word[1:] for word in compname.split("_")) #output heading for each part type in blue ct.print_heading("Initializing component: {} (import {} from {})".format(compname, classname, modname)) if compconfig is None: ct.print_warning("Component list for {} is empty".format(compname)) continue try: imported = __import__("components." + compname, globals(), locals(), [classname]) except Exception as e: ct.format_exception(e, "Import failed") continue try: cls = getattr(imported, classname) except Exception as e: ct.format_exception(e, "getattr failed:") continue try: cls.boot(compconfig) ct.print_info("booted {}".format(cls.__name__)) except Exception as e: ct.format_exception(e, "Class boot failed:") raise e continue cls.first_eval_all()
def subscribe(cls, topic, callback, use_prefix=True): topic = MQTT.prefix(topic, use_prefix) ct.print_debug("subscribing topic {}".format(topic)) subscription = cls.subscriptions.get(topic, None) # if we allready are subscribed to this, just add another callback if subscription is not None: callbacks = subscription["callbacks"] if callback in callbacks: ct.print_warning( "Callback allready exists for this topic, doing nothing") else: ct.print_debug( "adding callback to existing subscription {}".format( topic)) subscription["callbacks"].append(callback) return subscription cls.subscriptions[topic] = {"topic": topic, "callbacks": [callback]} ct.print_info("Added subscription for {}".format(topic)) if cls.connected: try: print("~~~ MQTT subscribe on {0}".format(topic)) cls.client.subscribe(topic) except Exception as e: ct.format_exception(e, "subscription failed") cls.set_connected(False) return subscription
def on_connect(cls): print("o-o MQTT connected") for topic in cls.subscriptions: ct.print_info("~~~ MQTT subscribe on {0}".format(topic)) try: cls.client.subscribe(topic) except: cls.set_connected(False)
def __init__(self, result_name, expression_string): self.set_name(result_name) matches = Expression.name_re.match(expression_string) self.expr_locals = {} self.python = Expression.name_re.sub(self._replace_in_expr, expression_string) ct.print_info("Expression = {}".format(self.python)) out = Signal.get_by_name(self.name, self) setattr(self, "output", out)
def on_mqtt(self, topic, data): mine_before = self.mine self.set_data(data) self.write_cache(data) #comparing jsons is not reliable because the ordering of elements can change. #Therefore we just compare the date the config was published if (mine_before is None) or (self.mine is None): same_date = False else: same_date = (mine_before["published"] == self.mine["published"]) if not same_date: ct.print_warning("Config changed, rebooting") # My config has changed. Reboot. sync() machine.reset() ct.print_info("Received config with identical date {}".format( self.mine["published"]))
def init_name(self, config): self.pin = Component.board.get_pin(self.name) self.ds = DS18X20(OneWire(self.pin)) addresses = self.ds.scan() self.sensors = [] read_all_sensors = ("ids" in config) or ("temperatures" in config) for address in addresses: hex_address = Sensor.to_hex_address(address) signal_name = None if hex_address in config: sensor = Sensor(address, self, config.pop(hex_address)) self.sensors.append(sensor) elif read_all_sensors: sensor = Sensor(address, self, None) self.sensors.append(sensor) ct.print_info("Found {} DS18x20 sensors.".format(len(self.sensors))) ct.print_debug("\n".join(str(x) for x in self.sensors)) self.countdown = self.interval = -1
def print_signals(cls): for sig in Signal.by_name.values(): ct.print_heading(str(sig)) for fanout in sig.fanouts: ct.print_info(fanout.name)
def print_components(cls): for name, comp in Component.by_name.items(): ct.print_heading("component {} of type {}".format(name, type(comp))) ct.print_info(str(comp))