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 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 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 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"]))