Browse Source

initial checkin, added MQTTmsgOnShutdown PowerShell script

FloKra 2 years ago
commit
3cf2e6a950
2 changed files with 150 additions and 0 deletions
  1. 61 0
      MQTTmsgOnShutdown/README.md
  2. 89 0
      MQTTmsgOnShutdown/onShutdown.ps1

+ 61 - 0
MQTTmsgOnShutdown/README.md

@@ -0,0 +1,61 @@
+# MQTT-Message on Shutdown/Restart
+
+PowerShell script for Windows 10 to send MQTT messages on Shutdown and Restart. 
+
+Intended to switch off a Tasmota plug, delayed, after shutdown, but NOT on restart. 
+
+
+
+## Prerequisites
+
+- download Mosquitto Windows x64 installer
+- extract and copy mosquitto_pub.exe, mosquitto.dll, libssl-1_1-x64.dll and libcrypto-1_1-x64.dll to 
+  c:\Tools\mosquitto (or anywhere and change $mosquittoPubPath accordingly)
+- create folder C:\LOG (or comment out $logFile to disable logging)
+
+
+
+## Description
+
+This script checks if there is a Event 1074 (source: User32) in the System Event Log, that is less than 15 seconds old. 
+If so, it checks the content of this event, which contains the info if we are about to "power off" or "restart". 
+
+The script must be set as shutdown script via Windows Group Policy (local GPO).
+
+
+
+## Setup
+
+- copy script to C:\scripts\onShutdown.ps1
+- edit topics, MQTT host, etc.
+- Start -> Run -> gpedit.msc
+- Computer Configuration -> Windows Settings -> Scripts (Startup/Shutdown) -> Shutdown
+- there, go to tab "PowerShell Scripts" and simply browse for this script. 
+     Group Policy service seems to handle the PS Execution-Policy, so that it does not have to be set to unrestricted system-wide. 
+
+Starting it via Task Scheduler on Event 1074 unfortunately does not work, as the script 
+is getting killed before it actually has done anything most times. 
+Via Group Policy, the shutdown will be delayed until the script has finished its work. 
+
+
+
+## Tasmota
+
+In order to implement the "delayedOff" function, a rule has to be added to the Tasmota device. 
+
+Add it via console on Tasmota´s Web Interface: 
+
+`rule1 on event#delayedOff do RuleTimer1 25 endon on rules#Timer=1 do power1 0 endon`
+
+Enable the rule:
+
+`rule1 1`
+
+In this example, Relais 1 is switched off 25 seconds after the event "delayedOff" was triggered. 
+
+Now the delayedOff-function can be triggered via MQTT: 
+
+```
+topic:   cmnd/[TasmotaTopic]/event
+payload: delayedOff
+```

+ 89 - 0
MQTTmsgOnShutdown/onShutdown.ps1

@@ -0,0 +1,89 @@
+# onShutdown.ps1
+#
+# for Windows 10
+# - sends an MQTT message on Shutdown and a different one on Restart
+# - intended to switch off a Tasmota plug, delayed, after shutdown, but NOT on restart
+#
+# Prerequisites:
+# - download Mosquitto Windows x64 installer
+# - extract and copy mosquitto_pub.exe, mosquitto.dll, libssl-1_1-x64.dll and libcrypto-1_1-x64.dll to
+#   c:\Tools\mosquitto (or anywhere and change $mosquittoPubPath accordingly)
+#
+# This script checks if there is a Event 1074 (source: User32) in the System Event Log, that is
+# less than 15 seconds old. 
+# If so, it checks the content of this event, which contains the info if we are about to 
+# "power off" or "restart". 
+#
+# The script must be set as shutdown script via Windows Group Policy (local GPO)
+# Setup: Start -> Run -> gpedit.msc
+#   -> Computer Configuration -> Windows Settings -> Scripts (Startup/Shutdown) -> Shutdown
+#   -> there, go to tab "PowerShell Scripts" and simply browse for this script. 
+#      Group Policy service seems to handle the PS Execution-Policy, 
+#      so that it does not have to be set to unrestricted system-wide. 
+#      I saved the script to C:\scripts\onShutdown.ps1
+#
+# Starting it via Task Scheduler on Event 1074 unfortunately does not work, as the script 
+# is getting killed before it actually has done anything most times. 
+# Via Group Policy, the shutdown will be delayed until the script has finished its work. 
+
+$logFile = "C:\LOG\onShutdown_PS.log"
+
+$mosquittoPubPath = "c:\Tools\mosquitto\mosquitto_pub.exe"
+$mqttHost = "mqtt.lan"
+#$mqttUser = "username"
+#$mqttPwd = "password"
+
+# Topic to send status info to (SHUTDOWN or RESTART)
+$mqttStatTopic = "MediaPC/ShutdownEvent"
+
+# Topic/Payload on Shutdown (i.E. send an Event to a Tasmota device)
+$mqttTopicOnShutdown = "cmnd/TasmotaMediaPC/event"
+$mqttPayloadOnShutdown = "delayedOff"
+
+# Topic/Payload on Restart (i.E. send an Event to a Tasmota device)
+#$mqttTopicOnRestart = ""
+#$mqttPayloadOnRestart = ""
+
+###########
+
+$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
+
+$mosquittoPubUserPassword = ""
+if($mqttUser -and $mqttPwd -and $mqttUser -ne "" -and $mqttPwd -ne "") {
+	$mosquittoPubUserPassword = "-u $mqttUser -P $mqttPwd "
+}
+
+$logDate = "{0:yyyy-MM-dd HH:mm:ss}" -f (Get-Date)
+if($logFile) { Write-Output $logDate >> $logFile }
+
+Get-WinEvent -FilterHashtable @{logname='System'; id=1074} -MaxEvents 1 | ForEach-Object {
+    $ts_event = [datetime]$_.TimeCreated
+    $ts_delta = (New-TimeSpan -Start $ts_event).TotalSeconds
+    $ts_str = $ts_delta.ToString("#")
+	$command = $_.Properties[4].Value
+    
+    if($logFile) { Write-Output "  last shutdown-event was '$command', $ts_str s ago" >> $logFile }
+
+	if($ts_delta -lt 15) {
+		if($logFile) { Write-Output "    ==> OK, publish MQTT messages." >> $logFile }
+        if($command -eq "power off") {
+			$cmdLine = "$mosquittoPubPath -h $mqttHost $mosquittoPubUserPassword-t $mqttStatTopic -m SHUTDOWN"
+			Invoke-Expression $cmdLine
+			if($mqttTopicOnShutdown -and $mqttTopicOnShutdown -ne "") {
+				$cmdLine = "$mosquittoPubPath -h $mqttHost $mosquittoPubUserPassword-t $mqttTopicOnShutdown -m $mqttPayloadOnShutdown"
+				Invoke-Expression $cmdLine
+			}
+        }
+        elseif($command -eq "restart") {
+			$cmdLine = "$mosquittoPubPath -h $mqttHost $mosquittoPubUserPassword-t $mqttStatTopic -m RESTART"
+			Invoke-Expression $cmdLine
+			if($mqttTopicOnRestart -and $mqttTopicOnRestart -ne "") {
+				$cmdLine = "$mosquittoPubPath -h $mqttHost $mosquittoPubUserPassword-t $mqttTopicOnRestart -m $mqttPayloadOnRestart"
+				Invoke-Expression $cmdLine
+			}
+        }
+    }
+    else {
+        if($logFile) { Write-Output "    ==> too old. Nothing to do." >> $logFile }
+    }
+}