diff --git a/doc/mode-button.md b/doc/mode-button.md index 2ac3149b..547396d5 100644 --- a/doc/mode-button.md +++ b/doc/mode-button.md @@ -16,7 +16,7 @@ Mode button with multiple presses Description ----------- -This script extend the functionality of mode button. Instead of just one +These scripts extend the functionality of mode button. Instead of just one you can trigger several actions by pressing the mode button several times. The hardware needs to have a mode button, see @@ -39,9 +39,9 @@ Copy this code to terminal to check: Requirements and installation ----------------------------- -Just install the script: +Just install the scripts: - $ScriptInstallUpdate mode-button; + $ScriptInstallUpdate mode-button,mode-button-scheduler; Then configure the mode button to run `mode-button`: diff --git a/global-functions.rsc b/global-functions.rsc index 8685346f..85744878 100644 --- a/global-functions.rsc +++ b/global-functions.rsc @@ -15,7 +15,7 @@ # Git commit id & info, expected configuration version :global CommitId "unknown"; :global CommitInfo "unknown"; -:global ExpectedConfigVersion 143; +:global ExpectedConfigVersion 144; # global variables not to be changed by user :global GlobalFunctionsReady false; diff --git a/mode-button-scheduler.rsc b/mode-button-scheduler.rsc new file mode 100644 index 00000000..a7bedfb6 --- /dev/null +++ b/mode-button-scheduler.rsc @@ -0,0 +1,84 @@ +#!rsc by RouterOS +# RouterOS script: mode-button-scheduler +# Copyright (c) 2018-2026 Christian Hesse +# https://rsc.eworm.de/COPYING.md +# +# requires RouterOS, version=7.21 +# requires device-mode, scheduler +# +# act on multiple mode and reset button presses +# https://rsc.eworm.de/doc/mode-button.md + +:local ExitOK false; +:onerror Err { + :global GlobalConfigReady; :global GlobalFunctionsReady; + :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \ + do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50; + :local ScriptName [ :jobname ]; + + :global ModeButton; + + :global LogPrint; + :global ModeButtonScheduler; + :global ValidateSyntax; + + :local LEDInvert do={ + :global ModeButtonLED; + + :global IfThenElse; + + :local LED [ /system/leds/find where leds=$ModeButtonLED \ + !disabled type~"^(on|off)\$" interface=[] ]; + :if ([ :len $LED ] = 0) do={ + :return false; + } + /system/leds/set type=[ $IfThenElse ([ get $LED type ] = "on") "off" "on" ] $LED; + } + + :local Scheduler [ /system/scheduler/find where name="mode-button-scheduler" ]; + + :if ([ :len $Scheduler ] = 0) do={ + $LogPrint error $ScriptName ("Scheduler does not exist."); + :set ExitOK true; + :error false; + } + + :local Count ([ :deserialize from=json [ /system/scheduler/get $Scheduler comment ] ]->"count"); + :local Code ($ModeButton->[ :tostr $Count ]); + + /system/scheduler/remove $Scheduler; + + :if ([ :len $Code ] = 0) do={ + $LogPrint info $ScriptName ("No action defined for " . $Count . " mode-button presses."); + :set ExitOK true; + :error false; + } + + :if ([ $ValidateSyntax $Code ] = false) do={ + $LogPrint warning $ScriptName \ + ("The code for " . $Count . " mode-button presses failed syntax validation!"); + :set ExitOK true; + :error false; + } + + $LogPrint info $ScriptName ("Acting on " . $Count . " mode-button presses: " . $Code); + + :for I from=1 to=$Count do={ + $LEDInvert; + :if ([ /system/routerboard/settings/get silent-boot ] = false) do={ + :beep length=200ms; + } + :delay 200ms; + $LEDInvert; + :delay 200ms; + } + + :onerror Err { + [ :parse $Code ]; + } do={ + $LogPrint warning $ScriptName \ + ("The code for " . $Count . " mode-button presses failed with runtime error: " . $Err); + } +} do={ + :global ExitError; $ExitError $ExitOK [ :jobname ] $Err; +} diff --git a/mode-button.rsc b/mode-button.rsc index f46eaa3c..364fa33f 100644 --- a/mode-button.rsc +++ b/mode-button.rsc @@ -10,86 +10,21 @@ # https://rsc.eworm.de/doc/mode-button.md :onerror Err { - :global GlobalConfigReady; :global GlobalFunctionsReady; - :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \ - do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50; :local ScriptName [ :jobname ]; - :global ModeButton; - - :global LogPrint; - - :set ($ModeButton->"count") ($ModeButton->"count" + 1); - - :local Scheduler [ /system/scheduler/find where name="_ModeButtonScheduler" ]; + :local Scheduler [ /system/scheduler/find where name="mode-button-scheduler" ]; :if ([ :len $Scheduler ] = 0) do={ - $LogPrint info $ScriptName ("Creating scheduler _ModeButtonScheduler, counting presses..."); - :global ModeButtonScheduler do={ :onerror Err { - :local FuncName $0; - - :global ModeButton; - - :global LogPrint; - :global ModeButtonScheduler; - :global ValidateSyntax; - - :local LEDInvert do={ - :global ModeButtonLED; - - :global IfThenElse; - - :local LED [ /system/leds/find where leds=$ModeButtonLED \ - !disabled type~"^(on|off)\$" interface=[] ]; - :if ([ :len $LED ] = 0) do={ - :return false; - } - /system/leds/set type=[ $IfThenElse ([ get $LED type ] = "on") "off" "on" ] $LED; - } - - :local Count ($ModeButton->"count"); - :local Code ($ModeButton->[ :tostr $Count ]); - - :set ($ModeButton->"count") 0; - :set ModeButtonScheduler; - /system/scheduler/remove [ find where name="_ModeButtonScheduler" ]; - - :if ([ :len $Code ] > 0) do={ - :if ([ $ValidateSyntax $Code ] = true) do={ - $LogPrint info $FuncName ("Acting on " . $Count . " mode-button presses: " . $Code); - - :for I from=1 to=$Count do={ - $LEDInvert; - :if ([ /system/routerboard/settings/get silent-boot ] = false) do={ - :beep length=200ms; - } - :delay 200ms; - $LEDInvert; - :delay 200ms; - } - - :onerror Err { - [ :parse $Code ]; - } do={ - $LogPrint warning $FuncName \ - ("The code for " . $Count . " mode-button presses failed with runtime error: " . $Err); - } - } else={ - $LogPrint warning $FuncName \ - ("The code for " . $Count . " mode-button presses failed syntax validation!"); - } - } else={ - $LogPrint info $FuncName ("No action defined for " . $Count . " mode-button presses."); - } - } do={ - :global ExitOnError; $ExitOnError $0 $Err; - } } - /system/scheduler/add name="_ModeButtonScheduler" \ - on-event=":global ModeButtonScheduler; \$ModeButtonScheduler;" interval=3s; + :log info ($ScriptName . ": Creating scheduler mode-button-scheduler, counting presses..."); + /system/scheduler/add name="mode-button-scheduler" interval=3s \ + comment=[ :serialize to=json ({ count=1 }) ] \ + on-event="/system/script/run mode-button-scheduler;"; } else={ - $LogPrint debug $ScriptName ("Updating scheduler _ModeButtonScheduler..."); - /system/scheduler/set $Scheduler start-time=[ /system/clock/get time ]; + :log debug ($ScriptName . ": Updating scheduler mode-button-scheduler..."); + :local Presses (([ :deserialize from=json [ /system/scheduler/get $Scheduler comment ] ]->"count") + 1); + /system/scheduler/set $Scheduler start-time=[ /system/clock/get time ] \ + comment=[ :serialize to=json ({ count=$Presses }) ]; } } do={ - :global ExitOnError; $ExitOnError [ :jobname ] $Err; + :log error ([ :jobname ] . ": " . $Err); } diff --git a/news-and-changes.rsc b/news-and-changes.rsc index ed60a6c2..1b3adb26 100644 --- a/news-and-changes.rsc +++ b/news-and-changes.rsc @@ -68,6 +68,7 @@ 141="Introduced script 'dhcpv6-client-lease' to run several scripts on IPv6 DHCP client lease."; 142="Added a setting for 'mod/notification-email' to check availability of certificate chain."; 143="Made backup scripts 'backup-email' and 'backup-upload' support date & time in filenames."; + 144="Split and reworked 'mode-button' for compatibility with RouterOS 7.24, configuration was updated automatically."; }; # Migration steps to be applied on script updates @@ -79,4 +80,5 @@ 132=":if ([ :len [ /system/script/find where name=\"check-health\" ] ] > 0) do={ :local Code \":local Install \\\"check-health\\\"; :if ([ :len [ /system/health/find where type=\\\"\\\" name~\\\"-state\\\\\\\$\\\" ] ] > 0) do={ :set Install (\\\$Install . \\\",check-health.d/state\\\"); }; :if ([ :len [ /system/health/find where type=\\\"C\\\" ] ] > 0) do={ :set Install (\\\$Install . \\\",check-health.d/temperature\\\"); }; :if ([ :len [ /system/health/find where type=\\\"V\\\" ] ] > 0) do={ :set Install (\\\$Install . \\\",check-health.d/voltage\\\"); }; :global ScriptInstallUpdate; \\\$ScriptInstallUpdate \\\$Install;\"; :global ValidateSyntax; :if ([ \$ValidateSyntax \$Code ] = true) do={ :do { [ :parse \$Code ]; } on-error={ }; }; };"; 138="/certificate/set trusted=yes [ find where trusted=yes ];"; 140=":if ([ :len [ /system/script/find where name=\"lease-script\" ] ] > 0) do={ /system/script/set name=\"dhcpv4-server-lease\" \"lease-script\"; :global ScriptInstallUpdate; \$ScriptInstallUpdate; /ip/dhcp-server/set lease-script=\"dhcpv4-server-lease\" [ find where lease-script=\"lease-script\" ]; };"; + 144=":if ([ :len [ /system/script/find where name=\"mode-button\" ] ] > 0) do={ :global ScriptInstallUpdate; \$ScriptInstallUpdate mode-button-scheduler; };"; };