Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Arksine/moonraker
Browse files Browse the repository at this point in the history
  • Loading branch information
actions-user committed Feb 8, 2025
2 parents bff7c16 + 1117890 commit d6a62c9
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 7 deletions.
8 changes: 8 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,17 @@ The format is based on [Keep a Changelog].
should use the new endpoint, however it may be desirable to also
support the deprecated `full` and `client` endpoints for compatibility
with older API versions.
- **build**: Bump PDM-Backend to 2.4.3.
- **build**: Bump Apprise to 1.9.2
- **build**: Bump Tornado to 6.4.2
- **build**: Bump Streaming-form-data to 1.19.1
- **build**: Bump Jinja2 to 3.1.5

### Fixed
- **python_deploy**: fix "dev" channel updates for GitHub sources.
- **mqtt**: Publish the result of the Klipper status subscription request.
This fixes issues with MQTT clients missing the initial status updates
after Klippy restarts.

### Added
- **application**: Verify that a filename is present when parsing the
Expand Down
11 changes: 11 additions & 0 deletions docs/printer_objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ The format is [X, Y, Z, E].

## webhooks

/// warning
Websocket and Unix Socket subscribers to the `webhooks` object
should not rely on it for asynchronous `startup`, `ready`, or
`error` state updates. By the time Moonraker has established
a connection to Klipper it is possible that the `webhooks`
state is already beyond the startup phase.

MQTT subscriptions will publish the first `state` detected
after Klippy exits the `startup` phase.
///

```{.json title="Printer Object Example"}
{
"state": "startup",
Expand Down
3 changes: 3 additions & 0 deletions moonraker/components/klippy_apis.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,12 +266,15 @@ async def subscribe_from_transport(
objects: Mapping[str, Optional[List[str]]],
transport: APITransport,
default: Union[Sentinel, _T] = Sentinel.MISSING,
full_response: bool = False
) -> Union[_T, Dict[str, Any]]:
params = {"objects": dict(objects)}
result = await self._send_klippy_request(
SUBSCRIPTION_ENDPOINT, params, default, transport
)
if isinstance(result, dict) and "status" in result:
if full_response:
return result
return result["status"]
if default is not Sentinel.MISSING:
return default
Expand Down
5 changes: 4 additions & 1 deletion moonraker/components/klippy_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,8 @@ async def _request_subscripton(self, web_request: WebRequest) -> Dict[str, Any]:
raise self.server.error(
"No connection associated with subscription request"
)
# if the connection has an existing subscription pop it off
self.subscriptions.pop(conn, None)
requested_sub: Subscription = args.get('objects', {})
all_subs: Subscription = dict(requested_sub)
# Build the subscription request from a superset of all client subscriptions
Expand Down Expand Up @@ -695,7 +697,8 @@ async def _request_subscripton(self, web_request: WebRequest) -> Dict[str, Any]:
if obj_name not in all_status:
del self.subscription_cache[obj_name]
result['status'] = pruned_status
self.subscriptions[conn] = requested_sub
if requested_sub:
self.subscriptions[conn] = requested_sub
return result

async def _request_standard(
Expand Down
17 changes: 11 additions & 6 deletions moonraker/components/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,9 +453,13 @@ async def component_init(self) -> None:
async def _handle_klippy_started(self, state: KlippyState) -> None:
if self.status_objs:
kapi: KlippyAPI = self.server.lookup_component("klippy_apis")
await kapi.subscribe_from_transport(
self.status_objs, self, default=None,
result = await kapi.subscribe_from_transport(
self.status_objs, self, default=None, full_response=True
)
if result is not None:
status: Dict[str, Any] = result["status"]
eventtime: float = result["eventtime"]
self.send_status(status, eventtime)
if self.status_update_timer is not None:
self.status_update_timer.start(delay=self.status_interval)

Expand Down Expand Up @@ -496,7 +500,7 @@ def _on_connect(self,
{'server': 'online'}, retain=True)
subs = [(k, v[0]) for k, v in self.subscribed_topics.items()]
if subs:
res, msg_id = client.subscribe(subs)
_, msg_id = client.subscribe(subs)
if msg_id is not None:
sub_fut: asyncio.Future = self.eventloop.create_future()
topics = list(self.subscribed_topics.keys())
Expand Down Expand Up @@ -618,7 +622,7 @@ def subscribe_topic(self,
need_sub = qos != prev_qos
self.subscribed_topics[topic] = (qos, sub_handles)
if self.is_connected() and need_sub:
res, msg_id = self.client.subscribe(topic, qos)
_, msg_id = self.client.subscribe(topic, qos)
if msg_id is not None:
sub_fut: asyncio.Future = self.eventloop.create_future()
sub_fut.add_done_callback(
Expand All @@ -636,7 +640,7 @@ def unsubscribe(self, hdl: SubscriptionHandle) -> None:
pass
if not sub_hdls:
del self.subscribed_topics[topic]
res, msg_id = self.client.unsubscribe(topic)
_, msg_id = self.client.unsubscribe(topic)
if msg_id is not None:
unsub_fut: asyncio.Future = self.eventloop.create_future()
unsub_fut.add_done_callback(
Expand Down Expand Up @@ -814,7 +818,8 @@ def _publish_status_update(self, status: Dict[str, Any], eventtime: float) -> No
payload = {'eventtime': eventtime, 'value': objval[statekey]}
self.publish_topic(
f"{self.klipper_state_prefix}/{objkey}/{statekey}",
payload, retain=True)
payload, retain=True
)
else:
payload = {'eventtime': eventtime, 'status': status}
self.publish_topic(self.klipper_status_topic, payload)
Expand Down

0 comments on commit d6a62c9

Please sign in to comment.