diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..dc9ea49
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..d85f0c0
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/screen_status_to_mqtt.iml b/.idea/screen_status_to_mqtt.iml
new file mode 100644
index 0000000..d0876a7
--- /dev/null
+++ b/.idea/screen_status_to_mqtt.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..6b17b51
--- /dev/null
+++ b/main.py
@@ -0,0 +1,76 @@
+import logging
+import socket
+import sys
+from time import sleep
+
+import servicemanager
+import win32event
+import win32service
+import win32serviceutil
+
+from win32_notification_receiver import Win32NotificationReceiver
+
+logPath = 'C:/Users/seb65/Documents/Gitea/screen_status_to_mqtt/'
+
+logging.basicConfig(
+ level=logging.DEBUG,
+ format="%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s",
+ handlers=[
+ logging.FileHandler(logPath + "debug.log"),
+ logging.StreamHandler()
+ ]
+)
+
+logger = logging.getLogger()
+
+
+class ScreenStatusToMqttService(win32serviceutil.ServiceFramework):
+ _svc_name_ = "ScreenStatusToMqtt"
+ _svc_display_name_ = "Screen Status To MQTT"
+ _svc_description_ = "Send your screen status to MQTT Broker"
+
+ win32_notification_receiver: Win32NotificationReceiver = None
+ running_flag = False
+
+ def __init__(self, args):
+ super().__init__(args)
+ self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
+ socket.setdefaulttimeout(60)
+
+ def SvcStop(self):
+ logger.info("Stopping Service...")
+ self.running_flag = False
+ self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
+ win32event.SetEvent(self.hWaitStop)
+
+ def SvcDoRun(self):
+ self.running_flag = True
+ servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
+ servicemanager.PYS_SERVICE_STARTED,
+ (self._svc_name_, ''))
+ if self.ssh is None:
+ logger.critical("Can't be run in debug mode !")
+ sys.exit(1)
+ else:
+ self.main()
+
+ def SvcOtherEx(self, control, event_type, data):
+ if control == win32service.SERVICE_CONTROL_POWEREVENT:
+ self.win32_notification_receiver.event_handler(event_type, data)
+ else:
+ logger.warning("Unsupported control: ")
+ logger.warning(control)
+
+ def main(self):
+ self.win32_notification_receiver = Win32NotificationReceiver(self.ssh)
+ while self.running_flag:
+ sleep(1)
+
+
+if __name__ == '__main__':
+ if len(sys.argv) == 1:
+ servicemanager.Initialize()
+ servicemanager.PrepareToHostSingle(ScreenStatusToMqttService)
+ servicemanager.StartServiceCtrlDispatcher()
+ else:
+ win32serviceutil.HandleCommandLine(ScreenStatusToMqttService)
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..cfe3195
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,3 @@
+pywin32=303
+comtypes=1.1.11
+pyinstaller=4.10
\ No newline at end of file
diff --git a/sm_win_service.py b/sm_win_service.py
new file mode 100644
index 0000000..e69de29
diff --git a/win32_notification_receiver.py b/win32_notification_receiver.py
new file mode 100644
index 0000000..64535af
--- /dev/null
+++ b/win32_notification_receiver.py
@@ -0,0 +1,68 @@
+import threading
+
+import win32con
+import win32api
+import win32gui
+import time
+import logging
+from ctypes import POINTER, windll, Structure, cast, CFUNCTYPE, c_int, c_uint, c_void_p, c_bool
+from comtypes import GUID
+from ctypes.wintypes import HANDLE, DWORD
+
+PBT_POWERSETTINGCHANGE = 0x8013 # 32787
+GUID_CONSOLE_DISPLAY_STATE = "{6FE69556-704A-47A0-8F24-C28D936FDA47}"
+GUID_MONITOR_POWER_ON = "{02731015-4510-4526-99E6-E5A17EBD1AEA}"
+
+logger = logging.getLogger()
+
+
+class Win32NotificationReceiver():
+ running_flag = False
+
+ def __init__(self, recipient):
+ super().__init__()
+ self.recipient = recipient
+ self.__prepare_win32gui_message()
+
+ def __prepare_win32gui_message(self):
+ guids_info = {
+ "GUID_MONITOR_POWER_ON": GUID_MONITOR_POWER_ON,
+ "GUID_CONSOLE_DISPLAY_STATE": GUID_CONSOLE_DISPLAY_STATE,
+ }
+ logger.info("----")
+ for name, guid_info in guids_info.items():
+ logger.info(self.recipient)
+ result = windll.user32.RegisterPowerSettingNotification(HANDLE(self.recipient), GUID(guid_info), DWORD(1))
+ logger.info(f'registering {name}')
+ logger.info(f"result: {hex(result)}")
+ logger.info(f"lastError: {win32api.GetLastError()}")
+ logger.info("----")
+
+ def event_handler(self, event_type, raw_data):
+ if event_type == PBT_POWERSETTINGCHANGE:
+ logger.debug("Power setting changed...")
+ logger.debug("raw_data:")
+ logger.debug(raw_data)
+
+ power_setting = str(raw_data[0])
+ logger.debug("Power Setting: ")
+ logger.debug(power_setting)
+
+ data = list(raw_data[1])
+ logger.debug("Data: ")
+ logger.debug(data)
+
+ if power_setting == GUID_CONSOLE_DISPLAY_STATE:
+ if data[0] == 0:
+ logger.debug("Display off")
+ if data[0] == 1:
+ logger.debug("Display on")
+ if data[0] == 2:
+ logger.debug("Display dimmed")
+ elif power_setting == GUID_MONITOR_POWER_ON:
+ if data[0] == 0:
+ logger.debug("Monitor off")
+ if data[0] == 1:
+ logger.debug("Monitor on")
+ else:
+ logger.warning("unknown GUID")