コード例 #1
0
ファイル: power.py プロジェクト: ihrapsa/moonraker
    def __init__(self, config: ConfigHelper) -> None:
        super().__init__(config)
        self.mqtt: MQTTClient = self.server.load_component(config, 'mqtt')
        self.eventloop = self.server.get_event_loop()
        self.cmd_topic: str = config.get('command_topic')
        self.cmd_payload: JinjaTemplate = config.gettemplate('command_payload')
        self.retain_cmd_state = config.getboolean('retain_command_state',
                                                  False)
        self.query_topic: Optional[str] = config.get('query_topic', None)
        self.query_payload = config.gettemplate('query_payload', None)
        self.must_query = config.getboolean('query_after_command', False)
        if self.query_topic is not None:
            self.must_query = False

        self.state_topic: str = config.get('state_topic')
        self.state_timeout = config.getfloat('state_timeout', 2.)
        self.state_response = config.load_template('state_response_template',
                                                   "{payload}")
        self.qos: Optional[int] = config.getint('qos',
                                                None,
                                                minval=0,
                                                maxval=2)
        self.mqtt.subscribe_topic(self.state_topic, self._on_state_update,
                                  self.qos)
        self.query_response: Optional[asyncio.Future] = None
        self.request_mutex = asyncio.Lock()
        self.server.register_event_handler("mqtt:connected",
                                           self._on_mqtt_connected)
        self.server.register_event_handler("mqtt:disconnected",
                                           self._on_mqtt_disconnected)
コード例 #2
0
ファイル: notifier.py プロジェクト: Arksine/moonraker
    def __init__(self, config: ConfigHelper) -> None:

        self.config = config
        name_parts = config.get_name().split(maxsplit=1)
        if len(name_parts) != 2:
            raise config.error(f"Invalid Section Name: {config.get_name()}")
        self.server = config.get_server()
        self.name = name_parts[1]
        self.apprise = apprise.Apprise()
        self.warned = False

        self.attach_requires_file_system_check = True
        self.attach = config.get("attach", None)
        if self.attach is None or \
            (self.attach.startswith("http://") or
             self.attach.startswith("https://")):
            self.attach_requires_file_system_check = False

        url_template = config.gettemplate('url')
        self.url = url_template.render()

        if len(self.url) < 2:
            raise config.error(f"Invalid url for: {config.get_name()}")

        self.title = config.gettemplate('title', None)
        self.body = config.gettemplate("body", None)

        self.events: List[str] = config.getlist("events", separator=",")

        self.apprise.add(self.url)
コード例 #3
0
ファイル: test_config.py プロジェクト: Arksine/moonraker
 def test_get_template_deprecate(self, test_config: ConfigHelper):
     server = test_config.get_server()
     test_config.gettemplate("test_template", deprecate=True)
     expected = (
         f"[test_options]: Option 'test_template' is "
         "deprecated, see the configuration documention "
         "at https://moonraker.readthedocs.io/en/latest/configuration")
     assert expected in server.warnings
コード例 #4
0
ファイル: ldap.py プロジェクト: Arksine/moonraker
 def __init__(self, config: ConfigHelper) -> None:
     self.server = config.get_server()
     self.ldap_host = config.get('ldap_host')
     self.ldap_port = config.getint("ldap_port", None)
     self.ldap_secure = config.getboolean("ldap_secure", False)
     base_dn_template = config.gettemplate('base_dn')
     self.base_dn = base_dn_template.render()
     self.group_dn: Optional[str] = None
     group_dn_template = config.gettemplate("group_dn", None)
     if group_dn_template is not None:
         self.group_dn = group_dn_template.render()
     self.active_directory = config.getboolean('is_active_directory', False)
     self.bind_dn: Optional[str] = None
     self.bind_password: Optional[str] = None
     bind_dn_template = config.gettemplate('bind_dn', None)
     bind_pass_template = config.gettemplate('bind_password', None)
     if bind_dn_template is not None:
         self.bind_dn = bind_dn_template.render()
         if bind_pass_template is None:
             raise config.error("Section [ldap]: Option 'bind_password' is "
                                "required when 'bind_dn' is provided")
         self.bind_password = bind_pass_template.render()
     self.lock = asyncio.Lock()
コード例 #5
0
 def __init__(self, config: ConfigHelper) -> None:
     self.server = config.get_server()
     self.eventloop = self.server.get_event_loop()
     self.name = config.get_name().split()[-1]
     self.itransport: ITransport = self.server.lookup_component(
         'internal_transport')
     self.mutex = asyncio.Lock()
     gpio: GpioFactory = self.server.load_component(config, 'gpio')
     self.gpio_event = gpio.register_gpio_event(config.get('pin'),
                                                self._on_gpio_event)
     min_event_time = config.getfloat('minimum_event_time',
                                      .05,
                                      minval=.010)
     self.gpio_event.setup_debounce(min_event_time, self._on_gpio_error)
     self.press_template = config.gettemplate("on_press",
                                              None,
                                              is_async=True)
     self.release_template = config.gettemplate("on_release",
                                                None,
                                                is_async=True)
     if (self.press_template is None and self.release_template is None):
         raise config.error(
             f"[{config.get_name()}]: No template option configured")
     self.notification_sent: bool = False
     self.user_data: Dict[str, Any] = {}
     self.context: Dict[str, Any] = {
         'call_method': self.itransport.call_method,
         'send_notification': self._send_notification,
         'event': {
             'elapsed_time': 0.,
             'received_time': 0.,
             'render_time': 0.,
             'pressed': False,
         },
         'user_data': self.user_data
     }
コード例 #6
0
ファイル: test_config.py プロジェクト: Arksine/moonraker
 def test_get_template_default(self, test_config: ConfigHelper):
     assert test_config.gettemplate("invalid_option", None) is None
コード例 #7
0
ファイル: test_config.py プロジェクト: Arksine/moonraker
 def test_get_template_render_fail(self, test_config: ConfigHelper):
     with pytest.raises(ServerError):
         test_config.gettemplate("test_template", is_async=True).render()
コード例 #8
0
ファイル: test_config.py プロジェクト: Arksine/moonraker
 def test_get_template_fail(self, test_config: ConfigHelper):
     with pytest.raises(ConfigError):
         test_config.gettemplate("invalid_option")
コード例 #9
0
ファイル: test_config.py プロジェクト: Arksine/moonraker
 def test_get_template_plain(self, test_config: ConfigHelper):
     val = test_config.gettemplate("test_string").render()
     assert val == "Hello World"
コード例 #10
0
ファイル: test_config.py プロジェクト: Arksine/moonraker
 async def test_get_template_async(self, test_config: ConfigHelper):
     templ = test_config.gettemplate("test_template", is_async=True)
     val = await templ.render_async()
     assert val == "mqttuser"
コード例 #11
0
ファイル: test_config.py プロジェクト: Arksine/moonraker
 def test_get_template_exists(self, test_config: ConfigHelper):
     val = test_config.gettemplate("test_template").render()
     assert val == "mqttuser"
コード例 #12
0
    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}")
コード例 #13
0
ファイル: power.py プロジェクト: ihrapsa/moonraker
 def __init__(self, config: ConfigHelper) -> None:
     super().__init__(config, default_port=8123)
     self.device: str = config.get("device")
     self.token: str = config.gettemplate("token").render()
     self.domain: str = config.get("domain", "switch")
     self.status_delay: float = config.getfloat("status_delay", 1.)