computer status plugin, eg.globals and more

Do you have questions about writing plugins or scripts in Python? Meet the coders here.
Post Reply
Koke
Posts: 9
Joined: Fri Jul 10, 2009 1:52 am

computer status plugin, eg.globals and more

Post by Koke » Fri Jul 10, 2009 3:04 am

Hi guys,

I just started getting into EG scripting/Python and have come across a few hurdles I was hoping you guys could help me out with.

First my pet project if anyone is interested. I thought it would be neat to be able to receive status updates from the computers on my network. ie. I WOL a computer so I can VNC into it, instead of guessing when to connect I now get an online notice from that computer. So I've been hacking the NetworkSender to fit my needs. Let me know if anyone would be interested in this and I'll post it when it's not all hard coded.

Features so far:
- Polls a list of computers for NetworkReceiver, keeps a list of active computers
- Sends out startup, shutdown and crash recovery notices to active computers on the network
- Polls the router to check for network connectivity (so I can time the startup notice)
- displays MIA message if a poll fails without receiving a shutdown notice from that computer

On to the questions:
1. Is there a way to dynamically set eg.globals variables? ie. globals()['test'] but for eg.globals... eg.globals() gives a "TypeError: 'Bunch' object is not callable"
2. Is there a EG exit or system.shutdown event?
3. Is there a way for a plugin to hook into events? Or can you only assign them via EG?
4. I'm syncing my EG configurations/plugins across my network, is there any call I can make to reload the configuration/plugins or restart EG?

Thanks for any help

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

Re: computer status plugin, eg.globals and more

Post by stottle » Fri Jul 10, 2009 1:38 pm

It sounds like you are working on some cool stuff, I'd like to see the code when you're done.

As for the questions....
1. Is there a way to dynamically set eg.globals variables? ie. globals()['test'] but for eg.globals... eg.globals() gives a "TypeError: 'Bunch' object is not callable"
When you have EG running, you should try running help->Python Shell. That runs a shell that can access EG's variables and see live changes. Very helpful if you want to figure out what EG is doing.... I pulled up a shell and typed eg.globals, and it said it was an object of type eg.Utils.Bunch. That class is in EventGhost\Event\eg\Utils.py, with these comments:

Code: Select all

    """
    Universal collection of a bunch of named stuff.

    Often we want to just collect a bunch of stuff together, naming each
    item of the bunch. A dictionary is OK for that; however, when names are
    constants and to be used just like variables, the dictionary-access syntax
    ("if bunch['squared'] > threshold", etc) is not maximally clear. It takes
    very little effort to build a little class, as in this 'Bunch', that will
    both ease the initialisation task and provide elegant attribute-access
    syntax ("if bunch.squared > threshold", etc).

    Usage is simple::

        point = eg.Bunch(x=100, y=200)

        # and of course you can read/write the named
        # attributes you just created, add others, del
        # some of them, etc, etc:
        point.squared = point.x * point.y
        if point.squared > threshold:
            point.isok = True
    """
In the PyCrust Shell, you can look for particular variables as eg.globals.eg.<whatever> to see what is listed.

I think that answers the question you asked. But before you start changing globals - which could easily impact other's code - make sure that's what you really need. You can easily create and store your own variables within your plugin object and access the globals as read only, so there are other options.
2. Is there a EG exit or system.shutdown event?
There is a Main.OnClose event that you can add to a macro (I just tested with an OSD action).
3. Is there a way for a plugin to hook into events? Or can you only assign them via EG?
I'm not sure I understand. If you add an action to your plugin, you can add that action to a macro to call your plugins actions. That's so common, I think you mean something else, but I'm not sure what.
4. I'm syncing my EG configurations/plugins across my network, is there any call I can make to reload the configuration/plugins or restart EG?
I don't think there is a way to reload plugins without restarting EG. As for restarting, I also don't think there is a way to restart EG from within EG. The best I can think of would be to a .bat file that starts EG, after maybe a 1 sec pause. Then call that .bat file (using a System->Start Application action).

Good luck,
Brett

Koke
Posts: 9
Joined: Fri Jul 10, 2009 1:52 am

Re: computer status plugin, eg.globals and more

Post by Koke » Sat Jul 11, 2009 12:14 am

Thanks for the wealth of information stottle, python shell is definitely going to be handy.

1. I'm throwing away all globals, that's obviously the wrong way to do it, and now that I know more about Python I can do it the right way.

3. I'm thinking of a way for the plugin to capture/detect events on it's own. ie. I get a computer online event from another computer on the network, I'd rather have my plugin automated enough to catch that event on it's own rather than have to create an EG event and tell my plugin that an event occured. More streamlining the user experience than anything I guess

4. I'll just whip something up myself that will restart EG, time to brush up on the windows API

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

Re: computer status plugin, eg.globals and more

Post by stottle » Sat Jul 11, 2009 3:22 am

Koke wrote:3. I'm thinking of a way for the plugin to capture/detect events on it's own. ie. I get a computer online event from another computer on the network, I'd rather have my plugin automated enough to catch that event on it's own rather than have to create an EG event and tell my plugin that an event occured. More streamlining the user experience than anything I guess
I've been looking at ways to streamline the user experience myself. The short answer is that without changing the core of EG, it isn't possible to get events without a macro. I've reworked the EventGhostEvent code to force certain events to a certain plugin, as well as a few other techniques. For right now though, I decided to just add the macro. At some point it may be necessary to change the core event handling, but it is a lot easier to prototype without changing the guts of EG. To make it easier on the end-user, you manually set up one computer and push the config or (even easier) pass along an xml config file with that macro included.

BTW, changing configs remotely is something I want to do as well, so I'm definitely interested in your progress. Also, you may be interested in my efforts to make configuration easier. I will post details in this thread when I have it working.

Brett

Koke
Posts: 9
Joined: Fri Jul 10, 2009 1:52 am

Re: computer status plugin, eg.globals and more

Post by Koke » Mon Jul 13, 2009 9:51 pm

I got EG restarting after some work. I was hoping to create a eg.app.Restart() method but EG has issues when a copy of itself is starting while another is exiting. I also tried a batch as well which would work but EG doesn't always exit fast for me and didn't want to stick a long delay in there. In the end I just ended up just writing my own program that would restart it when the process ends.

Fake Service.exe:
Fake Service.exe [Path to exe] [optional - Create fake service 'bool' (default false)] [optional - poll timer in seconds 'int' (default 1)]
All it does is find the process for the exe given and wait for it to exit, then restart it. if you set the second option to true it will stay running and always restart the program when it exits, 3rd option is how often to check to see if the process is running.
Fake Service.rar
(3.21 KiB) Downloaded 249 times
So DirectoryWatcher and EG restart:

autostart script:

Code: Select all

import time

eg.globals.LastFileOperation = time.time()
DirectoryWatcher macro:
DirectoryWatcher.Deleted
DirectoryWatcher.Updated
script:

Code: Select all

import sys
import time

watchList = ('slave.xml', '.py')

if eg.event.string == 'DirectoryWatcher.Deleted' and eg.event.payload[0].lower().endswith(watchList):
    eg.globals.LastFileOperation = time.time()
elif eg.event.string == 'DirectoryWatcher.Updated' and eg.event.payload[0].lower().endswith(watchList) and time.time() - eg.globals.LastFileOperation > 1:
    eg.globals.LastFileOperation = time.time()
    eg.plugins.System.Execute('Fake Service.exe', ''.join(['"', sys.argv[0], '"']), 3, False, 2, '')
    eg.app.Exit()
A couple notes with script: watchList needs a full xml name not just .xml. That's because EG creates a temp xml when saving and that will trigger the bug below. Also we have to handle the Deleted event which EG also does on save so that EG won't be restarted when we click save.

Bug: EG will crash if eg.document.CheckFileNeedsSave() is called twice in a row, most likely an issue trying to handle a second dialog box Unfortunately I couldn't figure out how to check if the dialog box was already open and exit to see if that would work.

Koke
Posts: 9
Joined: Fri Jul 10, 2009 1:52 am

Re: computer status plugin, eg.globals and more

Post by Koke » Sat Aug 01, 2009 1:38 am

Here's the end result if anyone is interested, it's still rough, I didn't bother turning it into a real plugin with a config window since there's not much interest in it.

Required plugins:
  • Network Event Receiver
    Network Messaging
    __init__.py
    Network Messaging plugin
    (12.6 KiB) Downloaded 311 times
EG Macro: Network Messaging Handler
  • System.Resume
    System.Suspend
    Main.OnClose
    Network Messaging: EventHandler
configs (under __start__) in plugin code
  • self.pollTime = 30 -- How often to query other computers in seconds (roughly)
    self.timeout = 65 -- how long to wait before a MIA message is displayed for none responding computers
    self.networkRouter = '1.1.1.1' -- Router IP, LAN for this plugin to work in
    self.statusFileName = '!Status.txt' -- Name of the file to keep the computer status in (for crash/update checks)
If you want this to work smoothly with "EG Restarting" add this before "eg.plugins.NetworkMessaging.SetStatus('Offline')"
  • eg.plugins.FileOperations.Write(3, 'Info.EG updated', '!Status.txt', 0, 0, False, False, False, 'ascii')
Some other calls you can make:

Show Status Report:

Code: Select all

statusList = eg.plugins.NetworkMessaging.GetStatus()

hostlist = statusList.keys()
hostlist.sort()

for host in hostlist:
    print ''.join([host, ' - ', statusList[host]])
Get a popup message for all online and responding computers:
All messages are prepended with the name of the computer that is sending the message
  • eg.plugins.NetworkMessaging.SendMessage('RequestsStatus')
Send an event to a computer just like Network Sender:
  • eg.plugins.NetworkMessaging.SendMessage('event name', 'Computer')
Send an info popup message:
  • eg.plugins.NetworkMessaging.SendMessage('Info.Message to send', 'ToComputer')
Tell a computer to standby:
  • eg.plugins.NetworkMessaging.SendMessage('ToComputer.Standby', 'ToComputer')
Bug list:
  • 1. Sporadically on system resume on the 3rd or 4th failed attempt to connect to a computer the call "sock.connect((host, self.port))" (line 110) bombs even though it is inside a try statement

    2. Sporadically on system standby when calling "eg.scheduler.CancelTask(self.PollTask)" (line 250) the call bombs, my guess is because the task is being called at the same time this is happening. I stuck the line in a try statement and haven't seen it pop up again

Post Reply