def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.last_print_stats: Dict[str, Any] = {} self.server.register_event_handler( "server:klippy_started", self._handle_started) self.server.register_event_handler( "server:status_update", self._status_update)
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.ioloop = IOLoop.current() self.stat_update_cb = PeriodicCallback( self._handle_stat_update, STAT_UPDATE_TIME_MS) # type: ignore self.vcgencmd: Optional[shell_command.ShellCommand] = None if os.path.exists(VC_GEN_CMD_FILE): logging.info("Detected 'vcgencmd', throttle checking enabled") shell_cmd: shell_command.ShellCommandFactory shell_cmd = self.server.load_component(config, "shell_command") self.vcgencmd = shell_cmd.build_shell_command( "vcgencmd get_throttled") self.server.register_notification("proc_stats:cpu_throttled") else: logging.info("Unable to find 'vcgencmd', throttle checking " "disabled") self.temp_file = pathlib.Path(TEMPERATURE_PATH) self.smaps = pathlib.Path(STATM_FILE_PATH) self.server.register_endpoint( "/machine/proc_stats", ["GET"], self._handle_stat_request) self.server.register_event_handler( "server:klippy_shutdown", self._handle_shutdown) self.server.register_notification("proc_stats:proc_stat_update") self.proc_stat_queue: Deque[Dict[str, Any]] = deque(maxlen=30) self.last_update_time = time.time() self.last_proc_time = time.process_time() self.throttle_check_lock = Lock() self.total_throttled: int = 0 self.last_throttled: int = 0 self.update_sequence: int = 0 self.stat_update_cb.start()
def __init__(self, config: ConfigHelper) -> None: 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.type: str = config.get('type') self.state: str = "init" self.locked_while_printing = config.getboolean('locked_while_printing', False) self.off_when_shutdown = config.getboolean('off_when_shutdown', False) self.off_when_shutdown_delay = 0. if self.off_when_shutdown: self.off_when_shutdown_delay = config.getfloat( 'off_when_shutdown_delay', 0., minval=0.) self.shutdown_timer_handle: Optional[asyncio.TimerHandle] = None self.restart_delay = 1. self.klipper_restart = config.getboolean( 'restart_klipper_when_powered', False) if self.klipper_restart: self.restart_delay = config.getfloat('restart_delay', 1.) if self.restart_delay < .000001: raise config.error("Option 'restart_delay' must be above 0.0") self.bound_service: Optional[str] = config.get('bound_service', None) self.need_scheduled_restart = False self.on_when_queued = config.getboolean('on_when_upload_queued', False)
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.temp_store_size = config.getint('temperature_store_size', 1200) self.gcode_store_size = config.getint('gcode_store_size', 1000) # Temperature Store Tracking self.last_temps: Dict[str, Tuple[float, ...]] = {} self.gcode_queue: GCQueue = deque(maxlen=self.gcode_store_size) self.temperature_store: TempStore = {} self.temp_update_cb = PeriodicCallback( self._update_temperature_store, TEMPERATURE_UPDATE_MS) # Register status update event self.server.register_event_handler( "server:status_update", self._set_current_temps) self.server.register_event_handler( "server:gcode_response", self._update_gcode_store) self.server.register_event_handler( "server:klippy_ready", self._init_sensors) # Register endpoints self.server.register_endpoint( "/server/temperature_store", ['GET'], self._handle_temp_store_request) self.server.register_endpoint( "/server/gcode_store", ['GET'], self._handle_gcode_store_request)
def __init__(self, config: confighelper.ConfigHelper) -> None: self.server = config.get_server() self.uds_address: str = config.get( 'klippy_uds_address', "/tmp/klippy_uds") self.writer: Optional[asyncio.StreamWriter] = None self.connection_mutex: asyncio.Lock = asyncio.Lock() self.event_loop = self.server.get_event_loop() self.log_no_access = True # Connection State self.connection_task: Optional[asyncio.Task] = None self.closing: bool = False self._klippy_info: Dict[str, Any] = {} self.init_list: List[str] = [] self._klipper_version: str = "" self._missing_reqs: Set[str] = set() self._peer_cred: Dict[str, int] = {} self.init_attempts: int = 0 self._state: str = "disconnected" self.subscriptions: Dict[Subscribable, Dict[str, Any]] = {} # Setup remote methods accessable to Klippy. Note that all # registered remote methods should be of the notification type, # they do not return a response to Klippy after execution self.pending_requests: Dict[int, KlippyRequest] = {} self.remote_methods: Dict[str, FlexCallback] = {} self.klippy_reg_methods: List[str] = [] self.register_remote_method( 'process_gcode_response', self._process_gcode_response, need_klippy_reg=False) self.register_remote_method( 'process_status_update', self._process_status_update, need_klippy_reg=False) self.server.register_component("klippy_connection", self)
def __init__(self: Strip, name: str, color_order: ColorOrder, cfg: ConfigHelper): self.server = cfg.get_server() self.client = AsyncHTTPClient() self.request_mutex = asyncio.Lock() self.name = name self.color_order = color_order # Read the uri information addr: str = cfg.get("address") port: int = cfg.getint("port", 80) protocol: str = cfg.get("protocol", "http") self.url = f"{protocol}://{addr}:{port}/json" self.timeout: float = cfg.getfloat("timeout", 2.) self.initial_preset: int = cfg.getint("initial_preset", -1) self.initial_red: float = cfg.getfloat("initial_red", 0.5) self.initial_green: float = cfg.getfloat("initial_green", 0.5) self.initial_blue: float = cfg.getfloat("initial_blue", 0.5) self.initial_white: float = cfg.getfloat("initial_white", 0.5) self.chain_count: int = cfg.getint("chain_count", 1) self._chain_data = bytearray(self.chain_count * color_order.Elem_Size()) self.onoff = OnOff.off self.preset = self.initial_preset
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() dist_info: Dict[str, Any] dist_info = {'name': distro.name(pretty=True)} dist_info.update(distro.info()) dist_info['release_info'] = distro.distro_release_info() self.inside_container = False self.system_info: Dict[str, Any] = { 'python': { "version": sys.version_info, "version_string": sys.version.replace("\n", " ") }, 'cpu_info': self._get_cpu_info(), 'sd_info': self._get_sdcard_info(), 'distribution': dist_info, 'virtualization': self._check_inside_container() } self._update_log_rollover(log=True) providers: Dict[str, type] = { "none": BaseProvider, "systemd_cli": SystemdCliProvider, "systemd_dbus": SystemdDbusProvider } ptype = config.get('provider', 'systemd_dbus') pclass = providers.get(ptype) if pclass is None: raise config.error(f"Invalid Provider: {ptype}") self.sys_provider: BaseProvider = pclass(config) logging.info(f"Using System Provider: {ptype}") self.server.register_endpoint("/machine/reboot", ['POST'], self._handle_machine_request) self.server.register_endpoint("/machine/shutdown", ['POST'], self._handle_machine_request) self.server.register_endpoint("/machine/services/restart", ['POST'], self._handle_service_request) self.server.register_endpoint("/machine/services/stop", ['POST'], self._handle_service_request) self.server.register_endpoint("/machine/services/start", ['POST'], self._handle_service_request) self.server.register_endpoint("/machine/system_info", ['GET'], self._handle_sysinfo_request) self.server.register_notification("machine:service_state_changed") # Register remote methods self.server.register_remote_method("shutdown_machine", self.sys_provider.shutdown) self.server.register_remote_method("reboot_machine", self.sys_provider.reboot) # IP network shell commands shell_cmd: SCMDComp = self.server.load_component( config, 'shell_command') self.addr_cmd = shell_cmd.build_shell_command("ip -json address") iwgetbin = "/sbin/iwgetid" if not pathlib.Path(iwgetbin).exists(): iwgetbin = "iwgetid" self.iwgetid_cmd = shell_cmd.build_shell_command(iwgetbin) self.init_evt = asyncio.Event()
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)
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.temp_store_size = config.getint('temperature_store_size', 1200) self.gcode_store_size = config.getint('gcode_store_size', 1000) # Temperature Store Tracking self.last_temps: Dict[str, Tuple[float, ...]] = {} self.gcode_queue: GCQueue = deque(maxlen=self.gcode_store_size) self.temperature_store: TempStore = {} eventloop = self.server.get_event_loop() self.temp_update_timer = eventloop.register_timer( self._update_temperature_store) # Register status update event self.server.register_event_handler("server:status_update", self._set_current_temps) self.server.register_event_handler("server:gcode_response", self._update_gcode_store) self.server.register_event_handler("server:klippy_ready", self._init_sensors) self.server.register_event_handler("klippy_connection:gcode_received", self._store_gcode_command) # Register endpoints self.server.register_endpoint("/server/temperature_store", ['GET'], self._handle_temp_store_request) self.server.register_endpoint("/server/gcode_store", ['GET'], self._handle_gcode_store_request)
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.gpiod: Any = load_system_module("gpiod") self.chips: Dict[str, Any] = {} self.reserved_gpios: Dict[str, GpioOutputPin] = {} version: str = self.gpiod.version_string() self.gpiod_version = tuple(int(v) for v in version.split('.'))
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.debug_enabled = config.getboolean('enable_repo_debug', False) if self.debug_enabled: logging.warning("UPDATE MANAGER: REPO DEBUG ENABLED") shell_cmd: SCMDComp = self.server.lookup_component('shell_command') self.scmd_error = shell_cmd.error self.build_shell_command = shell_cmd.build_shell_command self.pkg_updater: Optional[PackageDeploy] = None self.http_client = AsyncHTTPClient() self.github_request_cache: Dict[str, CachedGithubResponse] = {} # database management db: DBComp = self.server.lookup_component('database') db.register_local_namespace("update_manager") self.umdb = db.wrap_namespace("update_manager") # Refresh Time Tracking (default is to refresh every 28 days) reresh_interval = config.getint('refresh_interval', 672) # Convert to seconds self.refresh_interval = reresh_interval * 60 * 60 # GitHub API Rate Limit Tracking self.gh_rate_limit: Optional[int] = None self.gh_limit_remaining: Optional[int] = None self.gh_limit_reset_time: Optional[float] = None # Update In Progress Tracking self.cur_update_app: Optional[str] = None self.cur_update_id: Optional[int] = None self.full_complete: bool = False
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.namespaces: Dict[str, object] = {} self.enable_debug = config.getboolean("enable_database_debug", False) self.database_path = os.path.expanduser( config.get('database_path', "~/.moonraker_database")) if not os.path.isdir(self.database_path): os.mkdir(self.database_path) self.lmdb_env = lmdb.open(self.database_path, map_size=MAX_DB_SIZE, max_dbs=MAX_NAMESPACES) with self.lmdb_env.begin(write=True, buffers=True) as txn: # lookup existing namespaces cursor = txn.cursor() remaining = cursor.first() while remaining: key = bytes(cursor.key()) self.namespaces[key.decode()] = self.lmdb_env.open_db(key, txn) remaining = cursor.next() cursor.close() if "moonraker" not in self.namespaces: mrdb = self.lmdb_env.open_db(b"moonraker", txn) self.namespaces["moonraker"] = mrdb txn.put(b'database_version', self._encode_value(DATABASE_VERSION), db=mrdb) # Read out all namespaces to remove any invalid keys on init for ns in self.namespaces.keys(): self._get_namespace(ns) # Protected Namespaces have read-only API access. Write access can # be granted by enabling the debug option. Forbidden namespaces # have no API access. This cannot be overridden. self.protected_namespaces = set( self.get_item("moonraker", "database.protected_namespaces", ["moonraker"])) self.forbidden_namespaces = set( self.get_item("moonraker", "database.forbidden_namespaces", [])) debug_counter: int = self.get_item("moonraker", "database.debug_counter", 0) if self.enable_debug: debug_counter += 1 self.insert_item("moonraker", "database.debug_counter", debug_counter) if debug_counter: logging.info(f"Database Debug Count: {debug_counter}") # Track unsafe shutdowns unsafe_shutdowns: int = self.get_item("moonraker", "database.unsafe_shutdowns", 0) logging.info(f"Unsafe Shutdown Count: {unsafe_shutdowns}") # Increment unsafe shutdown counter. This will be reset if # moonraker is safely restarted self.insert_item("moonraker", "database.unsafe_shutdowns", unsafe_shutdowns + 1) self.server.register_endpoint("/server/database/list", ['GET'], self._handle_list_request) self.server.register_endpoint("/server/database/item", ["GET", "POST", "DELETE"], self._handle_item_request)
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() secrets: Secrets = self.server.load_component(config, 'secrets') self.jenv = jinja2.Environment('{%', '%}', '{', '}') self.jenv.add_extension("jinja2.ext.do") self.jenv.filters['fromjson'] = json.loads self.add_environment_global('raise_error', self._raise_error) self.add_environment_global('secrets', secrets)
def test_get_gpio_deprecated(self, gpio_config: ConfigHelper): server = gpio_config.get_server() gpio_config.getgpioout("test_gpio", deprecate=True) expected = ( f"[test_options]: Option 'test_gpio' is " "deprecated, see the configuration documention " "at https://moonraker.readthedocs.io/en/latest/configuration") assert expected in server.warnings
def __init__(self, identifier: str, event_name: str, config: ConfigHelper): self.identifier = identifier self.event_name = event_name self.server = config.get_server() self.notifiers: Dict[str, NotifierInstance] = {} self.config = config self.server.register_event_handler(self.event_name, self._handle)
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
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.client = AsyncHTTPClient() self.response_cache: Dict[str, HttpResponse] = {} self.gh_rate_limit: Optional[int] = None self.gh_limit_remaining: Optional[int] = None self.gh_limit_reset_time: Optional[float] = None
def __init__(self: WLED, config: ConfigHelper) -> None: # root_logger = logging.getLogger() # root_logger.setLevel(logging.DEBUG) self.server = config.get_server() prefix_sections = config.get_prefix_sections("wled") logging.info(f"WLED component loading strips: {prefix_sections}") strip_types = {"HTTP": StripHttp, "SERIAL": StripSerial} self.strips = {} for section in prefix_sections: cfg = config[section] try: name_parts = cfg.get_name().split(maxsplit=1) if len(name_parts) != 2: raise cfg.error(f"Invalid Section Name: {cfg.get_name()}") name: str = name_parts[1] logging.info(f"WLED strip: {name}") # Discard old color_order setting, always support 4 color strips _ = cfg.get("color_order", "", deprecate=True) strip_type: str = cfg.get("type", "http") strip_class: Optional[Type[Strip]] strip_class = strip_types.get(strip_type.upper()) if strip_class is None: raise config.error(f"Unsupported Strip Type: {strip_type}") self.strips[name] = strip_class(name, cfg) except Exception as e: # Ensures errors such as "Color not supported" are visible msg = f"Failed to initialise strip [{cfg.get_name()}]\n{e}" self.server.add_warning(msg) continue # Register two remote methods for GCODE self.server.register_remote_method("set_wled_state", self.set_wled_state) self.server.register_remote_method("set_wled", self.set_wled) # As moonraker is about making things a web api, let's try it # Yes, this is largely a cut-n-paste from power.py self.server.register_endpoint("/machine/wled/strips", ["GET"], self._handle_list_strips) self.server.register_endpoint("/machine/wled/status", ["GET"], self._handle_batch_wled_request) self.server.register_endpoint("/machine/wled/on", ["POST"], self._handle_batch_wled_request) self.server.register_endpoint("/machine/wled/off", ["POST"], self._handle_batch_wled_request) self.server.register_endpoint("/machine/wled/toggle", ["POST"], self._handle_batch_wled_request) self.server.register_endpoint("/machine/wled/strip", ["GET", "POST"], self._handle_single_wled_request)
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() database: MoonrakerDatabase database = self.server.lookup_component("database") database.register_local_namespace("announcements") self.announce_db = database.wrap_namespace("announcements") self.entry_id_map: Dict[str, str] = {} self.next_key = 0 self.dismiss_handles: Dict[str, asyncio.TimerHandle] = {}
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.software_version = config['system_args'].get('software_version') # Local variables self.klippy_apis: APIComp = self.server.lookup_component('klippy_apis') self.heaters: Dict[str, Dict[str, Any]] = {} self.last_print_stats: Dict[str, Any] = {} # Register status update event self.server.register_event_handler('server:klippy_ready', self._init) self.server.register_event_handler('server:status_update', self._handle_status_update) # Version & Server information self.server.register_endpoint('/api/version', ['GET'], self._get_version, wrap_result=False) self.server.register_endpoint('/api/server', ['GET'], self._get_server, wrap_result=False) # Login, User & Settings self.server.register_endpoint('/api/login', ['POST'], self._post_login_user, wrap_result=False) self.server.register_endpoint('/api/currentuser', ['GET'], self._post_login_user, wrap_result=False) self.server.register_endpoint('/api/settings', ['GET'], self._get_settings, wrap_result=False) # File operations # Note that file upload is handled in file_manager.py # TODO: List/info/select/delete files # Job operations self.server.register_endpoint('/api/job', ['GET'], self._get_job, wrap_result=False) # TODO: start/cancel/restart/pause jobs # Printer operations self.server.register_endpoint('/api/printer', ['GET'], self._get_printer, wrap_result=False) self.server.register_endpoint('/api/printer/command', ['POST'], self._post_command, wrap_result=False) # TODO: head/tool/bed/chamber specific read/issue # Printer profiles self.server.register_endpoint('/api/printerprofiles', ['GET'], self._get_printerprofiles, wrap_result=False)
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.gpiod: Any = load_system_module("gpiod") GpioEvent.init_constants(self.gpiod) self.chips: Dict[str, Any] = {} self.reserved_gpios: Dict[str, GpioBase] = {} version: str = self.gpiod.version_string() self.gpiod_version = tuple(int(v) for v in version.split('.')) self.server.add_log_rollover_item("gpiod_version", f"libgpiod version: {version}")
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.runner = AsyncRunner(IPVersion.All) hi = self.server.get_host_info() addresses: Optional[List[bytes]] = [socket.inet_aton(hi["address"])] self.bound_all = hi["address"] == "0.0.0.0" self.service_info = self._build_service_info(addresses) if self.bound_all: self.server.register_event_handler( "machine:net_state_changed", self._update_service)
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.agents: Dict[str, WebSocket] = {} self.server.register_endpoint("/connection/send_event", ["POST"], self._handle_agent_event, transports=["websocket"]) self.server.register_endpoint("/server/extensions/list", ["GET"], self._handle_list_extensions) self.server.register_endpoint("/server/extensions/request", ["POST"], self._handle_call_agent)
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() if not HAS_GPIOD: self.server.add_warning("Unable to load gpiod library, GPIO power " "devices will not be loaded") self.chip_factory = GpioChipFactory() self.devices: Dict[str, PowerDevice] = {} prefix_sections = config.get_prefix_sections("power") logging.info(f"Power component loading devices: {prefix_sections}") dev_types = { "gpio": GpioDevice, "tplink_smartplug": TPLinkSmartPlug, "tasmota": Tasmota, "shelly": Shelly, "homeseer": HomeSeer, "homeassistant": HomeAssistant, "loxonev1": Loxonev1 } try: for section in prefix_sections: cfg = config[section] dev_type: str = cfg.get("type") dev_class: Optional[Type[PowerDevice]] dev_class = dev_types.get(dev_type) if dev_class is None: raise config.error(f"Unsupported Device Type: {dev_type}") dev = dev_class(cfg) if isinstance(dev, GpioDevice): if not HAS_GPIOD: continue dev.configure_line(cfg, self.chip_factory) self.devices[dev.get_name()] = dev except Exception: self.chip_factory.close() raise self.server.register_endpoint("/machine/device_power/devices", ['GET'], self._handle_list_devices) self.server.register_endpoint("/machine/device_power/status", ['GET'], self._handle_batch_power_request) self.server.register_endpoint("/machine/device_power/on", ['POST'], self._handle_batch_power_request) self.server.register_endpoint("/machine/device_power/off", ['POST'], self._handle_batch_power_request) self.server.register_endpoint("/machine/device_power/device", ['GET', 'POST'], self._handle_single_power_request) self.server.register_remote_method("set_device_power", self.set_device_power) self.server.register_event_handler("server:klippy_shutdown", self._handle_klippy_shutdown) self.server.register_notification("power:power_changed") event_loop = self.server.get_event_loop() event_loop.register_callback(self._initalize_devices, list(self.devices.values()))
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.entry_mgr = EntryManager(config) self.eventloop = self.server.get_event_loop() self.update_timer = self.eventloop.register_timer( self._handle_update_timer ) self.request_lock = asyncio.Lock() self.dev_mode = config.getboolean("dev_mode", False) self.subscriptions: Dict[str, RssFeed] = { "moonraker": RssFeed("moonraker", self.entry_mgr, self.dev_mode), "klipper": RssFeed("klipper", self.entry_mgr, self.dev_mode) } self.stored_feeds: List[str] = [] sub_list: List[str] = config.getlist("subscriptions", []) self.configured_feeds: List[str] = ["moonraker", "klipper"] for sub in sub_list: sub = sub.lower() if sub in self.subscriptions: continue self.configured_feeds.append(sub) self.subscriptions[sub] = RssFeed( sub, self.entry_mgr, self.dev_mode ) self.server.register_endpoint( "/server/announcements/list", ["GET"], self._list_announcements ) self.server.register_endpoint( "/server/announcements/dismiss", ["POST"], self._handle_dismiss_request ) self.server.register_endpoint( "/server/announcements/update", ["POST"], self._handle_update_request ) self.server.register_endpoint( "/server/announcements/feed", ["POST", "DELETE"], self._handle_feed_request ) self.server.register_endpoint( "/server/announcements/feeds", ["GET"], self._handle_list_feeds ) self.server.register_notification( "announcements:dismissed", "announcement_dismissed" ) self.server.register_notification( "announcements:entries_updated", "announcement_update" ) self.server.register_notification( "announcements:dismiss_wake", "announcement_wake" )
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.devices: Dict[str, PowerDevice] = {} prefix_sections = config.get_prefix_sections("power") logging.info(f"Power component loading devices: {prefix_sections}") dev_types = { "gpio": GpioDevice, "tplink_smartplug": TPLinkSmartPlug, "tasmota": Tasmota, "shelly": Shelly, "homeseer": HomeSeer, "homeassistant": HomeAssistant, "loxonev1": Loxonev1, "rf": RFDevice, "mqtt": MQTTDevice } for section in prefix_sections: cfg = config[section] dev_type: str = cfg.get("type") dev_class: Optional[Type[PowerDevice]] dev_class = dev_types.get(dev_type) if dev_class is None: raise config.error(f"Unsupported Device Type: {dev_type}") try: dev = dev_class(cfg) except Exception as e: msg = f"Failed to load power device [{cfg.get_name()}]\n{e}" self.server.add_warning(msg) continue self.devices[dev.get_name()] = dev self.server.register_endpoint( "/machine/device_power/devices", ['GET'], self._handle_list_devices) self.server.register_endpoint( "/machine/device_power/status", ['GET'], self._handle_batch_power_request) self.server.register_endpoint( "/machine/device_power/on", ['POST'], self._handle_batch_power_request) self.server.register_endpoint( "/machine/device_power/off", ['POST'], self._handle_batch_power_request) self.server.register_endpoint( "/machine/device_power/device", ['GET', 'POST'], self._handle_single_power_request) self.server.register_remote_method( "set_device_power", self.set_device_power) self.server.register_event_handler( "server:klippy_shutdown", self._handle_klippy_shutdown) self.server.register_event_handler( "file_manager:upload_queued", self._handle_upload_queued) self.server.register_notification("power:power_changed")
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.http_server: Optional[HTTPServer] = None self.secure_server: Optional[HTTPServer] = None self.api_cache: Dict[str, APIDefinition] = {} self.registered_base_handlers: List[str] = [] self.max_upload_size = config.getint('max_upload_size', 1024) self.max_upload_size *= 1024 * 1024 # SSL config self.cert_path: str = self._get_path_option( config, 'ssl_certificate_path') self.key_path: str = self._get_path_option( config, 'ssl_key_path') # Set Up Websocket and Authorization Managers self.wsm = WebsocketManager(self.server) self.api_transports: Dict[str, APITransport] = { "websocket": self.wsm } mimetypes.add_type('text/plain', '.log') mimetypes.add_type('text/plain', '.gcode') mimetypes.add_type('text/plain', '.cfg') self.debug = config.getboolean('enable_debug_logging', False) log_level = logging.DEBUG if self.debug else logging.INFO logging.getLogger().setLevel(log_level) app_args: Dict[str, Any] = { 'serve_traceback': self.debug, 'websocket_ping_interval': 10, 'websocket_ping_timeout': 30, 'parent': self, 'default_handler_class': AuthorizedErrorHandler, 'default_handler_args': {}, 'log_function': self.log_request } # Set up HTTP only requests self.mutable_router = MutableRouter(self) app_handlers: List[Any] = [ (AnyMatches(), self.mutable_router), (r"/websocket", WebSocket), (r"/server/redirect", RedirectHandler)] self.app = tornado.web.Application(app_handlers, **app_args) self.get_handler_delegate = self.app.get_handler_delegate # Register handlers logfile = self.server.get_app_args().get('log_file') if logfile: self.register_static_file_handler( "moonraker.log", logfile, force=True) self.register_static_file_handler( "klippy.log", DEFAULT_KLIPPY_LOG_PATH, force=True)
def gpio_config(test_config: ConfigHelper, monkeypatch: pytest.MonkeyPatch) -> ConfigHelper: def load_gpio_mock(name: str) -> MockGpiod: return MockGpiod() monkeypatch.setattr(gpio, "load_system_module", load_gpio_mock) yield test_config server = test_config.get_server() gpio_comp = server.lookup_component("gpio", None) if gpio_comp is not None: gpio_comp.close() gpio_comp.reserved_gpios = {}
def __init__(self, config: ConfigHelper, paneldue: PanelDue) -> None: self.event_loop = config.get_server().get_event_loop() self.paneldue = paneldue self.port: str = config.get('serial') self.baud = config.getint('baud', 57600) self.partial_input: bytes = b"" self.ser: Optional[serial.Serial] = None self.fd: Optional[int] = None self.connected: bool = False self.send_busy: bool = False self.send_buffer: bytes = b"" self.attempting_connect: bool = True
def __init__(self, config: ConfigHelper) -> None: self.server = config.get_server() self.file_manager: FileManager = self.server.lookup_component( 'file_manager') self.request_lock = Lock() database: DBComp = self.server.lookup_component("database") self.job_totals: Dict[str, float] = database.get_item( "moonraker", "history.job_totals", { 'total_jobs': 0, 'total_time': 0., 'total_print_time': 0., 'total_filament_used': 0., 'longest_job': 0., 'longest_print': 0. }).result() self.server.register_event_handler( "server:klippy_disconnect", self._handle_disconnect) self.server.register_event_handler( "server:klippy_shutdown", self._handle_shutdown) self.server.register_event_handler( "job_state:started", self._on_job_started) self.server.register_event_handler( "job_state:complete", self._on_job_complete) self.server.register_event_handler( "job_state:cancelled", self._on_job_cancelled) self.server.register_event_handler( "job_state:standby", self._on_job_standby) self.server.register_event_handler( "job_state:error", self._on_job_error) self.server.register_notification("history:history_changed") self.server.register_endpoint( "/server/history/job", ['GET', 'DELETE'], self._handle_job_request) self.server.register_endpoint( "/server/history/list", ['GET'], self._handle_jobs_list) self.server.register_endpoint( "/server/history/totals", ['GET'], self._handle_job_totals) self.server.register_endpoint( "/server/history/reset_totals", ['POST'], self._handle_job_total_reset) database.register_local_namespace(HIST_NAMESPACE) self.history_ns = database.wrap_namespace(HIST_NAMESPACE, parse_keys=False) self.current_job: Optional[PrinterJob] = None self.current_job_id: Optional[str] = None self.next_job_id: int = 0 self.cached_job_ids = self.history_ns.keys().result() if self.cached_job_ids: self.next_job_id = int(self.cached_job_ids[-1], 16) + 1