修复切换WIFI后 ssdp无法扫描到问题
修复未获取到下位机版本号时会升级的问题 新增P800配置 Squashed commit of the following: commit f20f64f6e27842a6a76302a8a9dff32d3db66cc9 Merge: f546156 b48fdc7 Author: zkk <1007518571@qq.com> Date: Sat Jun 21 11:17:37 2025 +0800 Merge commit 'b48fdc708c052b6c4342db499307518db13d702b' into release
This commit is contained in:
parent
b05f6b5b02
commit
9c91d48cfb
131
config/moonraker_P800.conf
Normal file
131
config/moonraker_P800.conf
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
[server]
|
||||||
|
host: 0.0.0.0
|
||||||
|
port: %PORT%
|
||||||
|
klippy_uds_address: %UDS%
|
||||||
|
|
||||||
|
[authorization]
|
||||||
|
trusted_clients:
|
||||||
|
%LAN%
|
||||||
|
10.0.0.0/8
|
||||||
|
127.0.0.0/8
|
||||||
|
169.254.0.0/16
|
||||||
|
172.16.0.0/12
|
||||||
|
192.168.0.0/16
|
||||||
|
FE80::/10
|
||||||
|
::1/128
|
||||||
|
cors_domains:
|
||||||
|
*.lan
|
||||||
|
*.local
|
||||||
|
*://localhost
|
||||||
|
*://localhost:*
|
||||||
|
*://my.mainsail.xyz
|
||||||
|
*://app.fluidd.xyz
|
||||||
|
|
||||||
|
[octoprint_compat]
|
||||||
|
|
||||||
|
[firmware_manager]
|
||||||
|
|
||||||
|
[history]
|
||||||
|
|
||||||
|
[power Printer]
|
||||||
|
type: gpio
|
||||||
|
pin: gpiochip4/gpio13
|
||||||
|
initial_state: on
|
||||||
|
off_when_shutdown: true
|
||||||
|
off_when_shutdown_delay: 86400
|
||||||
|
on_when_job_queued: true
|
||||||
|
locked_while_printing: true
|
||||||
|
restart_klipper_when_powered: true
|
||||||
|
# restart_delay: 1
|
||||||
|
bound_services:
|
||||||
|
klipper
|
||||||
|
KlipperScreen
|
||||||
|
crowsnest
|
||||||
|
|
||||||
|
[button switch_button]
|
||||||
|
type: gpio
|
||||||
|
pin: ^gpiochip4/gpio12
|
||||||
|
debounce_period: .02
|
||||||
|
minimum_event_time: 0
|
||||||
|
on_press:
|
||||||
|
{% if event.elapsed_time > 5.0 %}
|
||||||
|
{% do call_method("machine.shutdown") %}
|
||||||
|
{% endif %}
|
||||||
|
on_release:
|
||||||
|
{% do call_method("machine.device_power.post_device", device="Printer", action="toggle") %}
|
||||||
|
|
||||||
|
[button power_outage]
|
||||||
|
type: gpio
|
||||||
|
pin: ^!gpiochip4/gpio19
|
||||||
|
debounce_period: .01
|
||||||
|
minimum_event_time: 0
|
||||||
|
on_press:
|
||||||
|
{% do call_method("printer.gcode.script", script="TURN_OFF_HEATERS") %}
|
||||||
|
{% do call_method("printer.gcode.script", script="GET_TASKLINE") %}
|
||||||
|
{% set query_objs = {"print_stats": ["state"], "toolhead": ["extruder"], "virtual_sdcard": ["file_path", "file_position", "file_line"]} %}
|
||||||
|
{% set status = call_method("printer.objects.query", objects=query_objs) %}
|
||||||
|
{% do call_method("printer.emergency_stop") %}
|
||||||
|
{% set data = status | tojson | fromjson %}
|
||||||
|
{% set print_state = data['status']['print_stats']['state'] %}
|
||||||
|
# Judging the printer status
|
||||||
|
{% if print_state | string == 'printing' or print_state | string == 'paused' %}
|
||||||
|
{% set hotend = data['status']['toolhead']['extruder'] %}
|
||||||
|
{% set position = data['status']['virtual_sdcard']['file_position'] %}
|
||||||
|
{% set line = data['status']['virtual_sdcard']['file_line'] %}
|
||||||
|
{% set filepath = data['status']['virtual_sdcard']['file_path'] %}
|
||||||
|
# save file position and line
|
||||||
|
{% do call_method("printer.gcode.script", script="SAVE_VARIABLE VARIABLE=power_resume_position VALUE=" + position | string) %}
|
||||||
|
{% do call_method("printer.gcode.script", script="SAVE_VARIABLE VARIABLE=power_resume_line VALUE=" + line | string) %}
|
||||||
|
{% set script = "SAVE_VARIABLE VARIABLE=power_loss_paused VALUE=" ~ ("False" if print_state | string == 'printing' else "True") %}
|
||||||
|
{% if print_state | string in ['printing', 'paused'] %}
|
||||||
|
{% do call_method("printer.gcode.script", script=script) %}
|
||||||
|
{% endif %}
|
||||||
|
# save extruder
|
||||||
|
{% do call_method("printer.gcode.script", script="SAVE_VARIABLE VARIABLE=power_resume_extruder VALUE=\"'" + hotend | string + "'\"") %}
|
||||||
|
# save file
|
||||||
|
{% do call_method("printer.gcode.script", script="SAVE_VARIABLE VARIABLE=filepath VALUE=\"'" + filepath | string + "'\"") %}
|
||||||
|
save interrupt
|
||||||
|
{% do call_method("printer.gcode.script", script="SAVE_VARIABLE VARIABLE=was_interrupted VALUE=True") %}
|
||||||
|
{% else %}
|
||||||
|
{% do call_method("printer.gcode.script", script="SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False") %}
|
||||||
|
{% endif %}
|
||||||
|
# shutdown
|
||||||
|
{% do call_method("machine.shutdown") %}
|
||||||
|
|
||||||
|
[update_manager]
|
||||||
|
channel: stable
|
||||||
|
refresh_interval: 168
|
||||||
|
|
||||||
|
[update_manager klipper]
|
||||||
|
channel: stable
|
||||||
|
|
||||||
|
[update_manager KlipperScreen]
|
||||||
|
type: git_repo
|
||||||
|
path: /home/klipper/KlipperScreen
|
||||||
|
origin: https://github.com/CreatBotOfficail/CreatBotKlipperScreen.git
|
||||||
|
env: /home/klipper/.KlipperScreen-env/bin/python
|
||||||
|
requirements: scripts/KlipperScreen-requirements.txt
|
||||||
|
install_script: scripts/KlipperScreen-install.sh
|
||||||
|
channel: stable
|
||||||
|
primary_branch: P800
|
||||||
|
|
||||||
|
[update_manager mainsail-config]
|
||||||
|
type: git_repo
|
||||||
|
primary_branch: master
|
||||||
|
path: ~/mainsail-config
|
||||||
|
origin: https://github.com/mainsail-crew/mainsail-config.git
|
||||||
|
managed_services: klipper
|
||||||
|
|
||||||
|
[update_manager mainsail]
|
||||||
|
type: web
|
||||||
|
channel: stable
|
||||||
|
repo: mainsail-crew/mainsail
|
||||||
|
path: ~/mainsail
|
||||||
|
|
||||||
|
# Crowsnest update_manager entry
|
||||||
|
[update_manager crowsnest]
|
||||||
|
type: git_repo
|
||||||
|
path: ~/crowsnest
|
||||||
|
origin: https://github.com/CreatBotOfficail/CreatBotCrowsnest.git
|
||||||
|
managed_services: crowsnest
|
||||||
|
install_script: tools/pkglist.sh
|
@ -118,6 +118,8 @@ class FirmwareUpdate:
|
|||||||
logging.error(f"Error querying {mcu}: {e}")
|
logging.error(f"Error querying {mcu}: {e}")
|
||||||
|
|
||||||
def _compare_versions(self, version1, version2):
|
def _compare_versions(self, version1, version2):
|
||||||
|
if not version1 or not version2:
|
||||||
|
return 0
|
||||||
v1_parts = [int(part) for part in version1.split('.') if part]
|
v1_parts = [int(part) for part in version1.split('.') if part]
|
||||||
v2_parts = [int(part) for part in version2.split('.') if part]
|
v2_parts = [int(part) for part in version2.split('.') if part]
|
||||||
|
|
||||||
@ -139,6 +141,9 @@ class FirmwareUpdate:
|
|||||||
logging.info(f"klipper version: {self.klipper_version}")
|
logging.info(f"klipper version: {self.klipper_version}")
|
||||||
for mcu in self.mcu_info:
|
for mcu in self.mcu_info:
|
||||||
mcu_version = self.mcu_info[mcu].get('mcu_version', "")
|
mcu_version = self.mcu_info[mcu].get('mcu_version', "")
|
||||||
|
if not mcu_version:
|
||||||
|
self.mcu_info[mcu]['need_update'] = False
|
||||||
|
continue
|
||||||
|
|
||||||
mcu_vs_min = self._compare_versions(mcu_version, self.min_version)
|
mcu_vs_min = self._compare_versions(mcu_version, self.min_version)
|
||||||
mcu_vs_klipper = self._compare_versions(mcu_version, self.klipper_version)
|
mcu_vs_klipper = self._compare_versions(mcu_version, self.klipper_version)
|
||||||
|
@ -138,8 +138,7 @@ class ZeroconfRegistrar:
|
|||||||
name = f"{instance_name} ({host})"
|
name = f"{instance_name} ({host})"
|
||||||
if len(name) > 64:
|
if len(name) > 64:
|
||||||
name = instance_name
|
name = instance_name
|
||||||
await self.ssdp_server.start()
|
await self.ssdp_server.start(addr, name, hi["port"])
|
||||||
self.ssdp_server.register_service(name, addr, hi["port"])
|
|
||||||
|
|
||||||
async def close(self) -> None:
|
async def close(self) -> None:
|
||||||
await self.runner.unregister_services([self.service_info])
|
await self.runner.unregister_services([self.service_info])
|
||||||
@ -151,6 +150,14 @@ class ZeroconfRegistrar:
|
|||||||
addresses = [x for x in self._extract_ip_addresses(network)]
|
addresses = [x for x in self._extract_ip_addresses(network)]
|
||||||
self.service_info.addresses = addresses
|
self.service_info.addresses = addresses
|
||||||
await self.runner.update_services([self.service_info])
|
await self.runner.update_services([self.service_info])
|
||||||
|
if self.ssdp_server is not None:
|
||||||
|
machine: Machine = self.server.lookup_component("machine")
|
||||||
|
addr = machine.public_ip
|
||||||
|
if not addr:
|
||||||
|
addr = f"{self.mdns_name}.local"
|
||||||
|
name = self.ssdp_server.name
|
||||||
|
hi = self.server.get_host_info()
|
||||||
|
await self.ssdp_server.update_service(addr, name, hi["port"])
|
||||||
|
|
||||||
def _extract_ip_addresses(self, network: Dict[str, Any]) -> Iterator[bytes]:
|
def _extract_ip_addresses(self, network: Dict[str, Any]) -> Iterator[bytes]:
|
||||||
for ifname, ifinfo in network.items():
|
for ifname, ifinfo in network.items():
|
||||||
@ -208,6 +215,7 @@ class SSDPServer(asyncio.protocols.DatagramProtocol):
|
|||||||
self.running: bool = False
|
self.running: bool = False
|
||||||
self.close_fut: Optional[asyncio.Future] = None
|
self.close_fut: Optional[asyncio.Future] = None
|
||||||
self.response_handle: Optional[asyncio.TimerHandle] = None
|
self.response_handle: Optional[asyncio.TimerHandle] = None
|
||||||
|
self.transport: Optional[asyncio.DatagramTransport] = None
|
||||||
eventloop = self.server.get_event_loop()
|
eventloop = self.server.get_event_loop()
|
||||||
self.boot_id = int(eventloop.get_loop_time())
|
self.boot_id = int(eventloop.get_loop_time())
|
||||||
self.config_id = 1
|
self.config_id = 1
|
||||||
@ -242,20 +250,22 @@ class SSDPServer(asyncio.protocols.DatagramProtocol):
|
|||||||
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, ip_combo)
|
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, ip_combo)
|
||||||
return sock
|
return sock
|
||||||
|
|
||||||
async def start(self) -> None:
|
async def start(self, addr: str, name: str, port: int) -> None:
|
||||||
if self.running:
|
if self.running:
|
||||||
return
|
await self.stop()
|
||||||
try:
|
try:
|
||||||
sock = self._create_ssdp_socket()
|
sock = self._create_ssdp_socket(source_addr=(addr, 0))
|
||||||
sock.settimeout(0)
|
sock.settimeout(0)
|
||||||
sock.setblocking(False)
|
sock.setblocking(False)
|
||||||
sock.bind(("", SSDP_ADDR[1]))
|
sock.bind(("", SSDP_ADDR[1]))
|
||||||
_loop = asyncio.get_running_loop()
|
_loop = asyncio.get_running_loop()
|
||||||
ret = await _loop.create_datagram_endpoint(lambda: self, sock=sock)
|
ret = await _loop.create_datagram_endpoint(lambda: self, sock=sock)
|
||||||
self.transport, _ = ret
|
self.transport, _ = ret
|
||||||
except (socket.error, OSError):
|
self.running = True
|
||||||
|
self.register_service(name, addr, port)
|
||||||
|
except (socket.error, OSError) as e:
|
||||||
|
logging.error(f"Failed to start SSDP server: {e}")
|
||||||
return
|
return
|
||||||
self.running = True
|
|
||||||
|
|
||||||
async def stop(self) -> None:
|
async def stop(self) -> None:
|
||||||
if not self.running:
|
if not self.running:
|
||||||
@ -265,18 +275,22 @@ class SSDPServer(asyncio.protocols.DatagramProtocol):
|
|||||||
if self.response_handle is not None:
|
if self.response_handle is not None:
|
||||||
self.response_handle.cancel()
|
self.response_handle.cancel()
|
||||||
self.response_handle = None
|
self.response_handle = None
|
||||||
if self.transport.is_closing():
|
if self.transport is not None and not self.transport.is_closing():
|
||||||
logging.info("Transport already closing")
|
for notification in self._build_notifications("ssdp:byebye"):
|
||||||
return
|
self.transport.sendto(notification, SSDP_ADDR)
|
||||||
for notification in self._build_notifications("ssdp:byebye"):
|
self.close_fut = self.server.get_event_loop().create_future()
|
||||||
self.transport.sendto(notification, SSDP_ADDR)
|
self.transport.close()
|
||||||
self.close_fut = self.server.get_event_loop().create_future()
|
try:
|
||||||
self.transport.close()
|
await asyncio.wait_for(self.close_fut, 2.)
|
||||||
try:
|
except asyncio.TimeoutError:
|
||||||
await asyncio.wait_for(self.close_fut, 2.)
|
logging.warning("Timeout waiting for SSDP transport to close")
|
||||||
except asyncio.TimeoutError:
|
self.close_fut = None
|
||||||
pass
|
self.transport = None
|
||||||
self.close_fut = None
|
|
||||||
|
async def update_service(self, addr: str, name: str, port: int) -> None:
|
||||||
|
if self.running:
|
||||||
|
await self.stop()
|
||||||
|
await self.start(addr, name, port)
|
||||||
|
|
||||||
def register_service(
|
def register_service(
|
||||||
self, name: str, host_name_or_ip: str, port: int
|
self, name: str, host_name_or_ip: str, port: int
|
||||||
@ -292,7 +306,6 @@ class SSDPServer(asyncio.protocols.DatagramProtocol):
|
|||||||
model = self.name.rsplit("-", 1)[0]
|
model = self.name.rsplit("-", 1)[0]
|
||||||
if "(" in self.name and ")" in self.name:
|
if "(" in self.name and ")" in self.name:
|
||||||
device_name = self.name.split("(", 1)[1].split(")", 1)[0]
|
device_name = self.name.split("(", 1)[1].split(")", 1)[0]
|
||||||
app: MoonrakerApp = self.server.lookup_component("application")
|
|
||||||
self.base_url = f"http://{host_name_or_ip}"
|
self.base_url = f"http://{host_name_or_ip}"
|
||||||
self.response_headers = [
|
self.response_headers = [
|
||||||
f"USN: uuid:{self.serial_number}::upnp:rootdevice::urn:creatbot-com:device:3dprinter:2",
|
f"USN: uuid:{self.serial_number}::upnp:rootdevice::urn:creatbot-com:device:3dprinter:2",
|
||||||
@ -308,7 +321,7 @@ class SSDPServer(asyncio.protocols.DatagramProtocol):
|
|||||||
]
|
]
|
||||||
self.registered = True
|
self.registered = True
|
||||||
advertisements = self._build_notifications("ssdp:alive")
|
advertisements = self._build_notifications("ssdp:alive")
|
||||||
if self.running:
|
if self.running and self.transport is not None:
|
||||||
for ad in advertisements:
|
for ad in advertisements:
|
||||||
self.transport.sendto(ad, SSDP_ADDR)
|
self.transport.sendto(ad, SSDP_ADDR)
|
||||||
self.advertisements = cycle(advertisements)
|
self.advertisements = cycle(advertisements)
|
||||||
@ -335,7 +348,7 @@ class SSDPServer(asyncio.protocols.DatagramProtocol):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _advertise_presence(self, eventtime: float) -> float:
|
def _advertise_presence(self, eventtime: float) -> float:
|
||||||
if self.running and self.registered:
|
if self.running and self.registered and self.transport is not None:
|
||||||
cur_ad = next(self.advertisements)
|
cur_ad = next(self.advertisements)
|
||||||
self.transport.sendto(cur_ad, SSDP_ADDR)
|
self.transport.sendto(cur_ad, SSDP_ADDR)
|
||||||
delay = random.uniform(SSDP_MAX_AGE / 6., SSDP_MAX_AGE / 3.)
|
delay = random.uniform(SSDP_MAX_AGE / 6., SSDP_MAX_AGE / 3.)
|
||||||
@ -344,6 +357,7 @@ class SSDPServer(asyncio.protocols.DatagramProtocol):
|
|||||||
def connection_made(
|
def connection_made(
|
||||||
self, transport: asyncio.transports.BaseTransport
|
self, transport: asyncio.transports.BaseTransport
|
||||||
) -> None:
|
) -> None:
|
||||||
|
self.transport = transport
|
||||||
logging.debug("SSDP Server Connected")
|
logging.debug("SSDP Server Connected")
|
||||||
|
|
||||||
def connection_lost(self, exc: Exception | None) -> None:
|
def connection_lost(self, exc: Exception | None) -> None:
|
||||||
@ -396,7 +410,7 @@ class SSDPServer(asyncio.protocols.DatagramProtocol):
|
|||||||
self._respond_to_discovery(addr)
|
self._respond_to_discovery(addr)
|
||||||
|
|
||||||
def _respond_to_discovery(self, addr: tuple[str | Any, int]) -> None:
|
def _respond_to_discovery(self, addr: tuple[str | Any, int]) -> None:
|
||||||
if not self.running:
|
if not self.running or self.transport is None:
|
||||||
return
|
return
|
||||||
self.response_handle = None
|
self.response_handle = None
|
||||||
response: List[str] = ["HTTP/1.1 200 OK"]
|
response: List[str] = ["HTTP/1.1 200 OK"]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user