Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TPLink power off delay doesn't work correct #366

Open
Caipitrooper opened this issue Feb 14, 2022 · 9 comments
Open

TPLink power off delay doesn't work correct #366

Caipitrooper opened this issue Feb 14, 2022 · 9 comments
Labels
enhancement New feature or request

Comments

@Caipitrooper
Copy link

What happened

I have a TPLink Smartplug HS110 that powers the printers as well as the Raspberry which runs Mainsail/moonraker/Klipper.
Mainsail is v2.1.1
moonraker (v0.7.1-365-g9be93ff)
Klipper is v0.10.0-263-ge3cbe7ea.

I set up a power section for my HS110 TPLink Smartplug in moonraker:
[power wifi_switch]
type: tplink_smartplug
address: 192.168.178.111
off_when_shutdown: True
off_when_shutdown_delay: 20
locked_while_printing: True

I have the following behaviour:

  • When I shutdown the system per "Shutdown" from the Mainsail power menu the system will shutdown,
    but no power off after the set 20 seconds.

When I shutdown with this gcode the TPLink will power off immediately and doesn't wait for the system to shutdown:
[gcode_macro POWER_OFF_PRINTER]
gcode:
{% if printer.idle_timeout.state != "Printing" %}
{action_call_remote_method("set_device_power", device="wifi_switch", state="off")}
{action_call_remote_method("shutdown_machine")}
{% endif %}

It seems that the delay procedure doesn't use TPLink_Smartplug's capabilities of a native delay but uses its own delay which doesn't work when the system has already shut down.

The TPLink Plugin in Octoprint however works fine with the delay.

Client

Mainsail

Browser

Firefox

How to reproduce

  1. Use a TPLink Smartplus to power the printer as well the the Raspi running Mainsail, moonraker and Klipper.
  2. Set up the power-section in moonraker.conf for the TPLink Smartplug with a delay like above.
  3. Shutdown the system with the help of e.g. Mainsail's shutdown menu or use the gcode from above.

Additional information

No response

@Caipitrooper Caipitrooper added the bug Something isn't working label Feb 14, 2022
@Caipitrooper Caipitrooper changed the title TPLink delay doesn't work correct TPLink power off delay doesn't work correct Feb 14, 2022
@Arksine Arksine removed the bug Something isn't working label Feb 14, 2022
@Arksine
Copy link
Owner

Arksine commented Feb 14, 2022

This is expected behavior. The delay is generic, it applies to all devices and cannot execute if Moonraker is not running. Moonraker isn't a good candidate for controlling a switch that toggles its host's power, simply because even if you can cut it off you can't cut it back on.

FWIW, the "off_when_shutdown" option refers to Klipper's shutdown state, not the host machine. See the configuration documentation for details.

@Caipitrooper
Copy link
Author

OK, thanks for the fast feedback.
I guess the issue can be closed then.
Are there any plans to have this special TPLink native delay support added?

@Arksine
Copy link
Owner

Arksine commented Feb 14, 2022

I would have to think about it. The issue is that the [power] module is intended to provide a generic interface that toggles any number of underlying devices. From an API perspective I'm not sure about the best way to expose functionality particular to a specific device. I'm not opposed to it, but it needs careful consideration.

I think we can keep this open and label it as a feature request.

@Arksine Arksine added the enhancement New feature or request label Feb 14, 2022
@Caipitrooper
Copy link
Author

Caipitrooper commented Feb 16, 2022

I probably found a fix.
While examining "power.py" I found that the class TPLinkSmartPlug tries to read the value of "timer" from the
config. Since this isn't there, the value is 0 and the smartplug will switch off immediately.

class TPLinkSmartPlug(PowerDevice):
    START_KEY = 0xAB
    def __init__(self, config: ConfigHelper) -> None:
        super().__init__(config)
        self.timer = config.get("timer", "")
...

If you add the variable "timer" with a reasonable value in the moonraker.conf in the section [power], it works fine.

Since TPLink's own count_down routine, which will send the value of timer to the device.
The device will itself then take care about powering off.

This gcode will also perfectly work and first send the timer value to tplink's count_down routine and while
tplink is waiting to switch off the system will shutdown:

[gcode_macro POWER_OFF_PRINTER]
gcode:
{% if printer.idle_timeout.state != "Printing" %}
{action_call_remote_method("set_device_power", device="wifi_switch", state="off")}
{action_call_remote_method("shutdown_machine")}
{% endif %}

Here is my [power} section:

[power wifi_switch]
type: tplink_smartplug
address: 192.168.178.111
off_when_shutdown: True
#off_when_shutdown_delay: 12
locked_while_printing: True
timer: 12

The "off_when_shutdown_delay" is not needed for TPLinkSmartPlug in this case.

My suggestion is either change the documentation for the TPLink Smartplug Configuration in the moonraker docs, or also use "off_when_shutdown_delay" in power.py in the TPLinkSmartPlug class.

@Caipitrooper
Copy link
Author

Caipitrooper commented Feb 21, 2022

I would like to add the latest information on this topic.
The previous procedure "POWER_OFF_PRINTER" doesn't work as expected. It is called in the context of the current printing process, so the status is still "printing", therefore the enclosed {action_call...} are not performed.
Rewriting the gcode macro so that the {action_call...} lines are performed directly will shutdown the Raspi, but still not switch off the TPLink Smartplug after the set timer period, because the code in power.py checks if the status is "printing" and if yes, it prevents the power off and throws an error message in moonraker's log.

The only feasible solution might be to use the idle_timeout to shutdown the printer.
I use a marco "TURNOFF_CHANGE" to set a variable "turnoff" to "0" or to "1", depending if I want to switch off the printer
after the print has finished. With a marco POWER_OFF_PRINTER I can also manually trigger the power down.
Here is an example:

PRINT_END macro, performed at the end of the print checking, if the variable "turnoff" is set so that we shutdown the printer:

[gcode macro PRINT_END]
gcode:
.
.
{% if printer["gcode_macro TURNOFF_CHANGE"].turnoff|int > 0 %}
        POWER_OFF_PRINTER
{% endif %}

TURNOFF_CHANGE macro to set the variable turnoff to "0" or "1". Can be set by the printing gcode from the slicer, terminal command or per buttons:

[gcode_macro TURNOFF_CHANGE]
variable_turnoff=0
gcode:
    SET_GCODE_VARIABLE MACRO=TURNOFF_CHANGE VARIABLE=turnoff VALUE={params.S|default(1)|int}

This POWER_OFF_PRINTER macro might haven been called by the "PRINT_END" macro or manually, so we set the turnoff to "1" just in case:

[gcode_macro POWER_OFF_PRINTER]
gcode:
TURNOFF_CHANGE S=1
set_idle_timeout timeout=10    #call idle_timeout after 10 seconds

Called when idle_timeout time reached:

idle_timeout
timeout: 600
gcode:
{% if printer["gcode_macro TURNOFF_CHANGE"].turnoff|int > 0 %}
        TEMPERATURE_WAIT SENSOR=extruder MAXIMUM=60      #Don't switch off when hot
        {action_call_remote_method("set_device_power", device="wifi_switch", state="off")}
        {action_call_remote_method("shutdown_machine")}
{% endif %}
        M84   #switch off motors in any case

@Caipitrooper
Copy link
Author

After testing this recently, found out that this is not working as hoped.
The "TEMPERATURE_WAIT" command within the idle_timeout's gcode is not working and is not waiting.
Instead it will right away perform the action commands and will switch off the TPLink after 12 seconds and before shutdown the Raspi. When setting this sequence of commands into a separate gcode_macro, it will wait for the temperature to drop first and afterwards shutdwon the Raspi, unfortunatelly it will not powerdown the TPLink. I guess because then the printer is in in idle mode any more?

Since the TPLink wifi_switch shutdown method is not working as expected, no matter what tricks I tried, I will have to go back to Octopi/Octodash.

@Arksine
Copy link
Owner

Arksine commented Apr 3, 2022

It isn't waiting due to macro expansion. In other words, when the idle_timeout template is evaluated it immediately calls action_call_remote method.

The solution is to wrap the two remote calls in their own respective macros. For example:

[gcode_macro SHUTDOWN_MACHINE]
gcode:
   {action_call_remote_method("shutdown_machine")}

[gcode_macro SEND_POWER_OFF]:
gcode:
  {action_call_remote_method("set_device_power", device="wifi_switch", state="off")}

[idle_timeout]
timeout: 600
gcode:
{% if printer["gcode_macro TURNOFF_CHANGE"].turnoff|int > 0 %}
        TEMPERATURE_WAIT SENSOR=extruder MAXIMUM=60      #Don't switch off when hot
        SEND_POWER_OFF
        SHUTDOWN_MACHINE
{% endif %}
        M84   #switch off motors in any case

By placing the commands in their own macros, expansion is delayed until the previous gcode has been executed.

That said, there are likely alternatives to using idle_timeout as well. For example, you could use a delayed_gcode execute POWER_OFF_PRINTER so that it runs after the idle timeout state changes from printing to idle.

@Caipitrooper
Copy link
Author

Thanks for the solution

@luco85
Copy link

luco85 commented Feb 14, 2024

There is some news to add support to set the delay timer to turn off smartplug?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants