def test_get_dict_deprecate(self, test_config: ConfigHelper): server = test_config.get_server() test_config.getdict("test_dict", deprecate=True) expected = ( f"[test_options]: Option 'test_dict' is " "deprecated, see the configuration documention " "at https://moonraker.readthedocs.io/en/latest/configuration") assert expected in server.warnings
def test_get_dict_empty_fields_fail(self, test_config: ConfigHelper): with pytest.raises(ConfigError): test_config.getdict("test_dict_empty_field")
def test_get_dict_empty_fields(self, test_config: ConfigHelper): val = test_config.getdict("test_dict_empty_field", allow_empty_fields=True) assert val == {"one": "test", "two": None, "three": None}
def test_get_dict_default(self, test_config: ConfigHelper): assert test_config.getdict("invalid_option", None) is None
def test_get_dict_fail(self, test_config: ConfigHelper): with pytest.raises(ConfigError): test_config.getdict("invalid_option")
def test_get_dict_exists(self, test_config: ConfigHelper): val = test_config.getdict("test_dict", dict_type=int) assert val == {"one": 1, "two": 2, "three": 3}
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.event_loop = self.server.get_event_loop() self.address: str = config.get('address') self.port: int = config.getint('port', 1883) user = config.gettemplate('username', None) self.user_name: Optional[str] = None if user: self.user_name = user.render() pw_file_path = config.get('password_file', None, deprecate=True) pw_template = config.gettemplate('password', None) self.password: Optional[str] = None if pw_file_path is not None: pw_file = pathlib.Path(pw_file_path).expanduser().absolute() if not pw_file.exists(): raise config.error( f"Password file '{pw_file}' does not exist") self.password = pw_file.read_text().strip() if pw_template is not None: self.password = pw_template.render() protocol = config.get('mqtt_protocol', "v3.1.1") self.protocol = MQTT_PROTOCOLS.get(protocol, None) if self.protocol is None: raise config.error( f"Invalid value '{protocol}' for option 'mqtt_protocol' " "in section [mqtt]. Must be one of " f"{MQTT_PROTOCOLS.values()}") self.instance_name = config.get('instance_name', socket.gethostname()) if '+' in self.instance_name or '#' in self.instance_name: raise config.error( "Option 'instance_name' in section [mqtt] cannot " "contain a wildcard.") self.qos = config.getint("default_qos", 0) if self.qos > 2 or self.qos < 0: raise config.error( "Option 'default_qos' in section [mqtt] must be " "between 0 and 2") self.client = paho_mqtt.Client(protocol=self.protocol) self.client.on_connect = self._on_connect self.client.on_message = self._on_message self.client.on_disconnect = self._on_disconnect self.client.on_publish = self._on_publish self.client.on_subscribe = self._on_subscribe self.client.on_unsubscribe = self._on_unsubscribe self.connect_evt: asyncio.Event = asyncio.Event() self.disconnect_evt: Optional[asyncio.Event] = None self.reconnect_task: Optional[asyncio.Task] = None self.subscribed_topics: SubscribedDict = {} self.pending_responses: List[asyncio.Future] = [] self.pending_acks: Dict[int, asyncio.Future] = {} self.server.register_endpoint( "/server/mqtt/publish", ["POST"], self._handle_publish_request, transports=["http", "websocket", "internal"]) self.server.register_endpoint( "/server/mqtt/subscribe", ["POST"], self._handle_subscription_request, transports=["http", "websocket", "internal"]) # Subscribe to API requests self.json_rpc = JsonRPC(transport="MQTT") self.api_request_topic = f"{self.instance_name}/moonraker/api/request" self.api_resp_topic = f"{self.instance_name}/moonraker/api/response" self.klipper_status_topic = f"{self.instance_name}/klipper/status" self.moonraker_status_topic = f"{self.instance_name}/moonraker/status" status_cfg: Dict[str, Any] = config.getdict("status_objects", {}, allow_empty_fields=True) self.status_objs: Dict[str, Any] = {} for key, val in status_cfg.items(): if val is not None: self.status_objs[key] = [v.strip() for v in val.split(',') if v.strip()] else: self.status_objs[key] = None if status_cfg: logging.debug(f"MQTT: Status Objects Set: {self.status_objs}") self.server.register_event_handler("server:klippy_identified", self._handle_klippy_identified) self.timestamp_deque: Deque = deque(maxlen=20) self.api_qos = config.getint('api_qos', self.qos) if config.getboolean("enable_moonraker_api", True): api_cache = self.server.register_api_transport("mqtt", self) for api_def in api_cache.values(): if "mqtt" in api_def.supported_transports: self.register_api_handler(api_def) self.subscribe_topic(self.api_request_topic, self._process_api_request, self.api_qos) self.server.register_remote_method("publish_mqtt_topic", self._publish_from_klipper) logging.info( f"\nReserved MQTT topics:\n" f"API Request: {self.api_request_topic}\n" f"API Response: {self.api_resp_topic}\n" f"Moonraker Status: {self.moonraker_status_topic}\n" f"Klipper Status: {self.klipper_status_topic}")