WIN7 Away mode

If you have a question or need help, this is the place to be.
Kommakul
Posts: 4
Joined: Thu Jun 03, 2010 7:39 pm

WIN7 Away mode

Post by Kommakul » Thu Jun 03, 2010 7:52 pm

Hi

New to Eventghost, but knows a little Python and C#.
Has anyone got a plugin, that registers when the pc goes to away mode?
Alternative: can I find the source for handling of the implemented power events?
I´m using WIN7 and EG 0.3.7.r1462

Thanks in advance.
Christian

stottle
Plugin Developer
Posts: 636
Joined: Sun Apr 26, 2009 10:59 pm

Re: WIN7 Away mode

Post by stottle » Sat Jun 05, 2010 2:06 pm

All of the source is included with the download, since python compiles the text source when it runs. So all of the power code should be in one of the plugins in the plugins folder (probably system). Note however that EG uses a dynamic module to build binding to windows systems calls for a lot of that type of stuff. So if the binding is already there for the system calls you need, you could probably make any necessary changes purely in python.

Otherwise it gets more complicated, as you need to install all of the components (like gccxml/python and all of the modules) to build your own instance of EG.

Brett

Kommakul
Posts: 4
Joined: Thu Jun 03, 2010 7:39 pm

Re: WIN7 Away mode

Post by Kommakul » Fri Jun 11, 2010 9:33 pm

Thanks.

YG78
Posts: 14
Joined: Tue Feb 02, 2010 7:53 pm

Re: WIN7 Away mode

Post by YG78 » Sat Jun 12, 2010 6:28 am

Hello

Did you find an issue ?

Is you problem similar http://www.eventghost.org/forum/viewtop ... f=2&t=2567

In fact, i think that in my case when a record is running, Win 7 does'n enter suspend mode, perhaps in away mode ? i dont know how to be sure.

I tried another soft Hibernate trigger (http://www.desimonesystems.com/suspendtrigger/index.php) => this is the same problem

Regards

Kommakul
Posts: 4
Joined: Thu Jun 03, 2010 7:39 pm

Re: WIN7 Away mode

Post by Kommakul » Sun Jun 13, 2010 6:43 pm

Hi

I looked at it briefly, but chose another solution. (Sending an ekstra IR command from my remote)

But what I know about the issue from working a little with the power notifications in C#: (I'm not a developer, so bare with me)


I can get a Away mode notification by registering for WM_POWERBROADCAST messages.
For the regular power messages (the ones imlemented in EG) we can look at Message.Wparam (Ex. when resuming we get Message.Wparam=PBT_APMRESUMESUSPEND)
When entering or leaving Away mode we get Message.Wparam=PBT_POWERSETTINGCHANGE and we must do an additional query to find out what happened as we get Message.Wparam=PBT_POWERSETTINGCHANGE for lots of different events.

What I used in C# was this:

Code: Select all

		private void PowerSettingChange(Message m)
		{
			POWERBROADCAST_SETTING ps =
								(POWERBROADCAST_SETTING)Marshal.PtrToStructure(
												m.LParam, typeof(POWERBROADCAST_SETTING));

			IntPtr pData = (IntPtr)((int)m.LParam + Marshal.SizeOf(ps));

			// Handle a change to the power plan.
			if (ps.PowerSetting == GUID_POWERSCHEME_PERSONALITY)
			{
				SetPowerPlan(ps, pData);
			}
			else 
			if (ps.DataLength == Marshal.SizeOf(typeof(Int32)))
			{
				Int32 iData = (Int32)Marshal.PtrToStructure(pData, typeof(Int32));
				if (ps.PowerSetting == GUID_BATTERY_PERCENTAGE_REMAINING)
				{
					SetBatteryLevel(iData);
				}
				else if (ps.PowerSetting == GUID_MONITOR_POWER_ON)
				{
					SetMonitorState(iData);
				}
                else if (ps.PowerSetting == GUID_ACDC_POWER_SOURCE)
                {
                    SetPowerSource(iData);
                }
                else if (ps.PowerSetting == GUID_SYSTEM_AWAYMODE)
                {
                    SetAwayState(iData);
                }

			}

		}
With
const int PBT_POWERSETTINGCHANGE = 0x8013;
and
Guid GUID_SYSTEM_AWAYMODE = new Guid(0x98A7F580, 0x01F7, 0x48AA, 0x9C, 0x0F, 0x44, 0x35, 0x2C, 0x29, 0xE5, 0xC0);

I don't have the time at the moment to look into the implementation in Python and EG, but if anyone makes any progress I would like to here about it.

Regards

Paul_Martinsen
Posts: 1
Joined: Tue Sep 28, 2010 8:21 am

Re: WIN7 Away mode

Post by Paul_Martinsen » Tue Sep 28, 2010 9:04 am

Hi Kommakul & al.

I am also new to EG & Python etc and encountered the same problem as you.

PowerBroadcastNotifier.py seems to handle power notifications & I have hacked this to detect the "Monitor Power On" event and the "Away Mode" event. This file lives in EventGhost\plugins\System\ folder. Replacing the default version with the one attached will cause System.MonitorPower.On, System.MonitorPower.Off, System.AwayMode.Entering and System.AwayMode.Exiting events to be raised.

I am running this on Win 7 x64. I offer this as proof of concept. Hopefully someone familiar with EG and Python can code this properly and incorporate into the official version (after they stop laughing at my hack :-) ).

Copy of modified code below & attached.
Paul.

Code: Select all

# This file is part of EventGhost.
# Copyright (C) 2005 Lars-Peter Voss <bitmonster@eventghost.org>
# 
# EventGhost is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# EventGhost is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with EventGhost; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#
#
# $LastChangedDate: 2009-05-24 18:32:01 +0200 (So, 24 Mai 2009) $
# $LastChangedRevision: 1013 $
# $LastChangedBy: Bitmonster $

# Hacked by Paul M 2010-09-28 to respond to MonitorPowerOn & SystemAwayMode 
# messages in Windows 7 x64.
 

import eg
import comtypes
import ctypes

from eg.WinApi.Dynamic import (
    WM_POWERBROADCAST, PBT_APMSUSPEND, PBT_APMRESUMEAUTOMATIC, 
    PBT_APMBATTERYLOW, PBT_APMOEMEVENT, PBT_APMPOWERSTATUSCHANGE, 
    PBT_APMQUERYSUSPEND, PBT_APMQUERYSUSPENDFAILED, PBT_APMRESUMECRITICAL,
    PBT_APMRESUMESUSPEND,  windll, byref, cast, POINTER,    
)

# Define a structure to hold information delivered during PBT_POWERSETTINGCHANGE
# message (it is in the lParam). Data is actually Length uchar's, but I don't know
# how to do that in python. For the MonitorPowerOn & AwayMode state, Length is 4 
# (DWORD) so pretend that Data is always a c_ulong.
# See: http://msdn.microsoft.com/en-us/library/aa372723(v=VS.85).aspx
class POWERBROADCAST_SETTING(ctypes.Structure):
  _fields_ = [("PowerSetting", comtypes.GUID),
              ("Length", ctypes.c_ulong),
              ("Data", ctypes.c_ulong)  
             ] 

PBT_POWERSETTINGCHANGE = 0x8013

PBT_MESSAGES = {
    PBT_APMBATTERYLOW: "BatteryLow", # not in vista, use 
                                     # PBT_APMPOWERSTATUSCHANGE instead
    PBT_APMOEMEVENT: "OemEvent",
    PBT_APMPOWERSTATUSCHANGE: "PowerStatusChange",
    PBT_APMQUERYSUSPEND: "QuerySuspend", # removed in Vista
    PBT_APMQUERYSUSPENDFAILED: "QuerySuspendFailed", # removed in Vista
    PBT_APMRESUMEAUTOMATIC: "ResumeAutomatic",
    PBT_APMRESUMECRITICAL: "ResumeCritical",
    PBT_APMRESUMESUSPEND: "Resume",
    PBT_APMSUSPEND: "Suspend",
#    PBT_POWERSETTINGCHANGE: "PowerSettingsChange", # PJM: now handled explictly
}

# New GUIDs associated with PBT_POWERSETTINGCHANGE message. See:
#  http://msdn.microsoft.com/en-us/library/aa373195(v=VS.85).aspx
GUID_MONITOR_POWER_ON = comtypes.GUID("{02731015-4510-4526-99e6-e5a17ebd1aea}")
GUID_SYSTEM_AWAYMODE = comtypes.GUID("{98a7f580-01f7-48aa-9c0f-44352c29e5C0}") 

class PowerBroadcastNotifier:
    
    def __init__(self, plugin):
        self.plugin = plugin
        
        # PJM: Ask Windows to notify us about Monitor & Away Mode power events.
        # Notification will be through WM_POWERBROADCAST message that has 
        # wParam of PBT_POWERSETTINGCHANGE
        self.hNotify1 = windll.user32.RegisterPowerSettingNotification(
          eg.messageReceiver.hwnd, byref(GUID_MONITOR_POWER_ON), 0)
        self.hNotify2 = windll.user32.RegisterPowerSettingNotification(
          eg.messageReceiver.hwnd, byref(GUID_SYSTEM_AWAYMODE), 0)
          
        eg.messageReceiver.AddHandler(
            WM_POWERBROADCAST, 
            self.OnPowerBroadcast
        )


    def Close(self):
        windll.user32.UnregisterPowerSettingNotification(self.hNotify1)
        windll.user32.UnregisterPowerSettingNotification(self.hNotify2)
        eg.messageReceiver.RemoveHandler(
            WM_POWERBROADCAST, 
            self.OnPowerBroadcast
        )
        
        
    @eg.LogIt
    def OnPowerBroadcast(self, dummyHwnd, msg, wparam, LParam):
        if wparam == PBT_APMRESUMEAUTOMATIC:
            eg.actionThread.CallWait(eg.actionThread.OnComputerResume)
        msg = PBT_MESSAGES.get(wparam, None)
        if msg is not None:
            eg.eventThread.TriggerEventWait(
                msg, 
                prefix="System", 
                source=self.plugin
            )
            
        # PJM: Pull apart the data supplied in lParam to decide 
        # what windows is telling us. lParam is a pointer to a
        # POWERBROADCAST_SETTING structure. The PowerSetting parameter
        # is a GUID that tells us what happened.  
        if wparam == PBT_POWERSETTINGCHANGE:
          Data = cast(LParam, POINTER(POWERBROADCAST_SETTING))
          PowerSetting = Data.contents.PowerSetting
          if PowerSetting == GUID_MONITOR_POWER_ON:
            State = Data.contents.Data 
            if State == 0:
              eg.TriggerEvent("MonitorPowerState.Off", payload=None, prefix="System")
            elif State == 1:
              eg.TriggerEvent("MonitorPowerState.On", payload=None, prefix="System")
            else:
              print "System.MonitorPowerState.Unknown" # Currently other values are undocumented
          elif PowerSetting == GUID_SYSTEM_AWAYMODE:
            Mode = Data.contents.Data
            if Mode == 0:
              eg.TriggerEvent("AwayMode.Exiting", payload=None, prefix="System")
            elif Mode == 1:
              eg.TriggerEvent("AwayMode.Entering", payload=None, prefix="System")
            else:
              print "System.SystemAwayMode.Unknown" # Currently other values are undocumented
          else:
            # Not expecting any other GUIDs. But could look them up here:
            # http://msdn.microsoft.com/en-us/library/aa373195(v=VS.85).aspx
            print "Unexpected PowerSettingChange", Data.contents.PowerSetting, Data.contents.Length, Data.contents.Data
            
        if wparam == PBT_APMSUSPEND:
            eg.actionThread.CallWait(eg.actionThread.OnComputerSuspend)
        return 1

Attachments
PowerBroadcastNotifier.py
(6.01 KiB) Downloaded 396 times

barnabas1969
Experienced User
Posts: 131
Joined: Sat Feb 04, 2012 1:42 am

Re: WIN7 Away mode

Post by barnabas1969 » Mon Apr 23, 2012 6:58 pm

I know this is an old thread, but I'll vote for this to be included in the base install of EG. I was having the same problem, and the file attached to the previous post solved it. Thanks!

Johnson
Posts: 48
Joined: Sun May 24, 2009 9:05 pm

Re: WIN7 Away mode

Post by Johnson » Thu Jan 09, 2014 8:53 pm

Great! It's work!

Now I can on/off my TV when system on/off monitor.

to Moderator
Please add this patch to main project. But there is some problem with Win8. In Win8 GUID_MONITOR_POWER_ON must by replased by GUID_CONSOLE_DISPLAY_STATE.

mindvis
Posts: 2
Joined: Sat Dec 17, 2016 3:12 pm

Re: WIN7 Away mode

Post by mindvis » Sat Dec 17, 2016 3:24 pm

Hi,

First thanks to Paul_Martinsen. I am using MonitorPowerState.Off and MonitorPowerState.On events to switch off and on my TV based on Windows power saving settings. It was however not working "always" on Win10, but thanks to Johnson tip it is working perfectly now.

It should definitely be included into main project.

Thanks,
Minda

mindvis
Posts: 2
Joined: Sat Dec 17, 2016 3:12 pm

Re: WIN7 Away mode

Post by mindvis » Sat Dec 17, 2016 5:15 pm

What I have noticed, that the event System.MonitorPowerState.Off is not issued if the Screen-Saver was running before the monitor is switched off in the system. Running Win10 x64. Any ideas why and how to fix that?

User avatar
kgschlosser
Site Admin
Posts: 3113
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: WIN7 Away mode

Post by kgschlosser » Mon Dec 19, 2016 8:31 am

you can paste this code into a python script and then execute the script

I have not tested it. but it may solve your problem.

if it does you will want to put the action Main.OnInit in a macro with this script.

that way it will get executed every time you run EventGhost

Code: Select all

import eg
import wx

def OnSuspending(evt):
    eg.TriggerEvent(prefix='System', suffix='Suspending')
    
def OnSuspended(evt):
    eg.TriggerEvent(prefix='System', suffix='Suspended')

def OnCanceled(evt):
    eg.TriggerEvent(prefix='System', suffix='SuspendCanceled')
    
def OnResume(evt):
    eg.TriggerEvent(prefix='System', suffix='Resumed')

frame = wx.Frame(None)
frame.Bind(wx.EVT_POWER_SUSPENDING, OnSuspending)
frame.Bind(wx.EVT_POWER_SUSPENDED, OnSuspended) 
frame.Bind(wx.EVT_POWER_SUSPEND_CANCEL, OnCanceled)
frame.Bind(wx.EVT_POWER_RESUME, OnResume)

eg.globals.systemState = frame
If you like the work I have been doing then feel free to Image

AceoStar
Posts: 9
Joined: Thu Jan 12, 2017 1:28 am

Re: WIN7 Away mode

Post by AceoStar » Thu Jan 12, 2017 1:55 am

Hello! I registered just to say thanks for the updates for PowerBroadcaster! I agree with a previous poster that this would be great to add to a release. I'm using it to fully replicate my monitor status as a switch in my Smartthigns / home assistant setup. Only problem I still have left is Re-enable monitor not working, but that's for another thread!

User avatar
kgschlosser
Site Admin
Posts: 3113
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: WIN7 Away mode

Post by kgschlosser » Fri Jan 13, 2017 5:59 pm

has anyone tested that code i put up there to see if it works?
If you like the work I have been doing then feel free to Image

AceoStar
Posts: 9
Joined: Thu Jan 12, 2017 1:28 am

Re: WIN7 Away mode

Post by AceoStar » Sat Jan 14, 2017 12:48 am

kgschlosser wrote:has anyone tested that code i put up there to see if it works?
Hey again. I placed the code above in EventGhost\test.py, ran it and got the following error. I am currently running the modified PowerBroadcastNotifier.py posted earlier, if that matters.

Code: Select all

7:46:49 PM: Debug: src/helpers.cpp(140): 'CreateActCtx' failed with error 0x00000715 (the specified resource type cannot be found in the image file.).

User avatar
kgschlosser
Site Admin
Posts: 3113
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: WIN7 Away mode

Post by kgschlosser » Sat Jan 14, 2017 2:55 am

not sure what that error is.. what version of EG are you running?
If you like the work I have been doing then feel free to Image

Post Reply