EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Do you have questions about writing plugins or scripts in Python? Meet the coders here.
Post Reply
daniel.n
Posts: 8
Joined: Sun Dec 20, 2009 11:05 pm

EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by daniel.n » Sun Dec 20, 2009 11:32 pm

Hi,

I made a small web-GUI using the default webserver-plugin, that I thought someone might find useful. It's very simple, but the selling point is that the webpage is generated by reading EGs own settings-file, so there is no need to keep the web-part and EG "in synch" in any way. Events with names ending in "on" or "off" are shown as icons, otherwise as the respective strings used in EG.

I'm very new to this so this might already be done by someone somewhere, if so, I apologize.

Any-who, my code snippet goes from 'EG.jpg' below to 'brytarweb.jpg' with nothing configured at all in the attached zipped index.html. I use it to control Nexa, Waveman and other RF-breakers with a Telldus Tellstick, some with the Tellstick plugin, others by calling a command-line utility. This is a first version with some swedish variable names and such, but as an example to build from I hope it may still be of value.

Use in any way you fancy. To try it out: Icons from http://www.famfamfam.com/lab/icons/silk/.

All in all this just maps an EG configuration tree, if configured in a way that the parser understands ("breakers" - "somebreaker X" - macros X1, X2, ..), to a simple webpage. It is not limited to the Tellstick plugin.
Attachments
index.zip
(1.38 KiB) Downloaded 402 times
brytarweb.jpg
EG.jpg

daniel.n
Posts: 8
Joined: Sun Dec 20, 2009 11:05 pm

Re: EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by daniel.n » Sun Dec 20, 2009 11:59 pm

Btw, yes, this will expose any and all information in the EG config file, to anyone with access to the webserver. You would just have to look at how the requests are made while the GUI is generated to be able to insert queries for other parts of the settings tree. So don't store VISA card information there and then turn off the authentication for the webserver :). A better solution would probably be to parse the file server-side with python instead. But I don't know python yet.

User avatar
Livin
Experienced User
Posts: 792
Joined: Wed Oct 08, 2008 4:56 am

Re: EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by Livin » Mon Dec 21, 2009 6:25 am

daniel,
This is nice work. A while back I asked for a feature like this to be built into EG's default pages but the request fell on def ears.

Ideally there would be an object property for each EG object that would enable/disable its display on the web pages... so the user could "filter" what is shown. I'm sure this can be done script-side but it is less desirable in the grand scheme of things.
setup... XBMC, W7MC for DVR & Live OTA TV, JRMC for multi-zone audio, EG, MiCasaVerde Vera3, USB-UIRT IR receiver, Harmony remote, 5.2 home theater system

User avatar
Livin
Experienced User
Posts: 792
Joined: Wed Oct 08, 2008 4:56 am

Re: EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by Livin » Fri Dec 25, 2009 6:39 pm

daniel,
I have tried using your code with the original 'Webserver' and 'Dynamic Webserver' plugins, all I get with either of them is a black screen and "11:36:59:848 parsed EventGhost-config" ? (I have copied the .JS into the HTML folder)
setup... XBMC, W7MC for DVR & Live OTA TV, JRMC for multi-zone audio, EG, MiCasaVerde Vera3, USB-UIRT IR receiver, Harmony remote, 5.2 home theater system

daniel.n
Posts: 8
Joined: Sun Dec 20, 2009 11:05 pm

Re: EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by daniel.n » Fri Dec 25, 2009 7:20 pm

Livin, I'm off to see 2012 in a few minutes, I'll get back to you on this.

daniel.n
Posts: 8
Joined: Sun Dec 20, 2009 11:05 pm

Re: EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by daniel.n » Sat Dec 26, 2009 7:29 pm

Hi,

The code is very hard coded to what the EG settings tree looks like for me, just putting this out there for inspiration, not as a v1.0 production-ready something, so we're clear on that ;)

What it assumes is a settings tree which has a subtree like this (shown in screenshot too in first post):

Code: Select all

folder 'breakers' (expected to be called exactly that)
  folder 'breakerX' (any suitable name for the device)
    macro 'operation X1' (any suitable name for the operation)
      event 'HTTP.something' (has to start with 'HTTP.')
      action that performs the operation (anything)
    macro 'operation X2' (any suitable name for the operation)
      event 'HTTP.something' (has to start with 'HTTP.')
      action that performs the operation (anything)
  folder 'breakerY' (any suitable name for the device)
    macro 'operation Y1' (any suitable name for the operation)
      event 'HTTP.something' (has to start with 'HTTP.')
      action that performs the operation (anything)
    macro 'operation Y2' (any suitable name for the operation)
      event 'HTTP.something' (has to start with 'HTTP.')
      action that performs the operation (anything)
It then generates a webpage that will send the HTTP.something events found in the settings tree. Only if all criteria mentioned above are met will it work, so, your settings tree is lacking at least one of the mandatory parts ('breakers' folder, having one or more device folders, each having on or more macros, each one with one or more HTTP.something triggers).

User avatar
Livin
Experienced User
Posts: 792
Joined: Wed Oct 08, 2008 4:56 am

Re: EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by Livin » Sat Dec 26, 2009 9:32 pm

now I understand... I thought it simply 'walked' (mapped) the entire tree. I like the idea you have, only mapping a specific branch. It would be cool if you could have an INI file that the code read and have the user allow one/more branches of their wish to be mapped.


anyway, still not working for me, same problem. see my test config...
Attachments
eg.JPG
eg.JPG (32.36 KiB) Viewed 10061 times
setup... XBMC, W7MC for DVR & Live OTA TV, JRMC for multi-zone audio, EG, MiCasaVerde Vera3, USB-UIRT IR receiver, Harmony remote, 5.2 home theater system

daniel.n
Posts: 8
Joined: Sun Dec 20, 2009 11:05 pm

Re: EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by daniel.n » Sat Dec 26, 2009 11:12 pm

Darn, who coded this?! That should work :) Apart from debugging by adding logs like below (edit index.html, around line ~70-80), if you could send me or post your XML file here (the breakers-part of it atleast), I can try it and try to find out what fails.

Code: Select all

log("found breakers-folder");
log("found macro " + macroName + " for device " + breakerName);
log("adding event " + eventName);

User avatar
Livin
Experienced User
Posts: 792
Joined: Wed Oct 08, 2008 4:56 am

Re: EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by Livin » Sat Dec 26, 2009 11:54 pm

here's the XML...

Code: Select all

    <Folder Name="breakers" Expanded="True">
        <Macro Name="System.OFF" Expanded="True">
            <Event Name="HTTP.System Off" />
            <Action Name="Dining Accent off">
                EventGhost.PythonScript(u'# Send HTTP Post\nimport urllib\nWEBSVR = "http://htpc/"\ndevicename = "Dining Room Accent Light"\naction = "action_on"\ncmd = "On"\n# Encode the data\nparams = urllib.urlencode({\'control_device\':devicename, action:cmd, \'selectdim\':0})\n# Send POST command to Homeseer\nurllib.urlopen(WEBSVR, params)')
            </Action>
        </Macro>
    </Folder>
full XML from 'html' folder attached
Attachments
EventGhost-config.xml
(177.04 KiB) Downloaded 305 times
setup... XBMC, W7MC for DVR & Live OTA TV, JRMC for multi-zone audio, EG, MiCasaVerde Vera3, USB-UIRT IR receiver, Harmony remote, 5.2 home theater system

daniel.n
Posts: 8
Joined: Sun Dec 20, 2009 11:05 pm

Re: EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by daniel.n » Sun Dec 27, 2009 10:59 am

Hmm where's the 'lighting'-folder from the screenshot? Seems one level is missing from both the attached full XML and the pasted parts, that could be it?

User avatar
Livin
Experienced User
Posts: 792
Joined: Wed Oct 08, 2008 4:56 am

Re: EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by Livin » Sun Dec 27, 2009 8:37 pm

daniel.n wrote:Hmm where's the 'lighting'-folder from the screenshot? Seems one level is missing from both the attached full XML and the pasted parts, that could be it?
DOH - I had copied an old version of the XML. Working now :)


It would be cool if you could work with paseant to combine the work you both have done. He has a slick interface and you have code to auto-generate buttons... to have both would be sweet!

here's his thread... http://www.eventghost.org/forum/viewtop ... 194#p12194
setup... XBMC, W7MC for DVR & Live OTA TV, JRMC for multi-zone audio, EG, MiCasaVerde Vera3, USB-UIRT IR receiver, Harmony remote, 5.2 home theater system

daniel.n
Posts: 8
Joined: Sun Dec 20, 2009 11:05 pm

Re: EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by daniel.n » Wed Dec 30, 2009 11:37 pm

Maybe one day :)

FWIW, googled some python and this in a python script action would work for extracting the relevant portions of the EG config file to a separate file the webserver can present without security considerations. What it does is strip a section out and write it to a new file. The jquery index.html thingy posted in the first post of this thread still works, just edit it to point to the new 'subset-file'.

Code: Select all

import xml.etree.ElementTree as ET

# Control variables:
egcfg_websection = 'breakers' # copy only this top level folder of EG config to new file
egcfg = r'\\WHS\Software\Add-Ons\EventGhost-Webserver-docroot\EventGhost-config.xml'
parsedout = r'\\WHS\Software\Add-Ons\EventGhost-Webserver-docroot\EventGhost-config-parsed.xml'

def ParseEventGhostConfig(egconfig, outputfile):
    egConfDoc = ET.parse(egconfig).getroot()
    toplevelfolders = egConfDoc.findall('Folder')
    for f1 in toplevelfolders:
        if f1.get('Name') == egcfg_websection:
            # Found section of interest, here's the chance to change what webserver sees!
            # for now, change nothing, just produce a log of what was found
            for f2 in f1.findall('Folder'):
                breakerName = f2.get('Name') 
                line = breakerName
                for macro in f2.findall('Macro'):
                    macroName = macro.get('Name') 
                    for event in macro.findall('Event'):
                        eventName = event.get('Name')                         
                        line += " - " + macroName + " - " + eventName[5:]
                print line                
            # Write the section of interest to the output file
            ET.ElementTree(f1).write(outputfile, "UTF-8")
            return
    outTree = ET.ElementTree(outRoot)
    outTree.write(outputhtml)    

ParseEventGhostConfig(egcfg, parsedout)
I'm using this for my own purposes and I'm quite happy for now, it fills my needs. Timing would be nice, don't need advanced sunrise-adaptions and stuff, but I'll probably add some code that'll read comments attached to the macros for finding timing info later, and starts timers from that.

Ideally, I don't want multiple settings having to be in synch. I couldn't be without EG, so anything I'll do from this point on will probably be in line with this, trying to go from EG configuration as the base, without other files. I'll need an iPhone-gui when I get one, but it should be able to use the index.html-thingy I've already made, or I'll make a new one, that still goes from the exposed parts of the EG config file. A complete plugin with its own settings just feels like too much. I need EG but will try to stick with what is shipped with EG from the beginning.

That's just how I roll.

User avatar
Livin
Experienced User
Posts: 792
Joined: Wed Oct 08, 2008 4:56 am

Re: EG with webserver-plugin, AJAX w/jQuery, simple example GUI

Post by Livin » Fri Jan 01, 2010 8:48 pm

You should be able to easily use the nice iPhone UI from paseant's pages ( http://www.eventghost.org/forum/viewtop ... 194#p12194 ) and just pop your code in.
setup... XBMC, W7MC for DVR & Live OTA TV, JRMC for multi-zone audio, EG, MiCasaVerde Vera3, USB-UIRT IR receiver, Harmony remote, 5.2 home theater system

Mama70
Posts: 5
Joined: Sun Dec 18, 2011 10:28 am

Re: EG with webserver-plugin, AJAX w/jQuery, simple example

Post by Mama70 » Sun Dec 18, 2011 11:34 am

Hi,
I made a simple remote page for controlling the video & audio and present it here so it's easier/faster for people to create for instance buttons with custom icons.

The foundations for the code came from viewtopic.php?f=2&t=2892
Then I updated jQuery Mobile to version 1.0. You have to understand I don't have prior knowledge about how AJAX&jQuery works and still don't know much. This is just copy&paste code from the vaults of the internet. That why there's also still some code in pages that are not really needed. I don't plan to learn everything about these things, I only need remote pages that work smooth. I will be using Android tablet as remote.

The top navigation bar is a simple ripoff of the original code. Because the active button did not stay active, I had to update jQuery Mobile to version 1.0. Now it works. I don't actually use the other pages right now, so I present only the main page.

The video section simply calls a batch file in EG that changes display settings. I don't plan to make it show which is the active configuration.

The audio section is because I'm using convolvers for equalizers and the buttons start the Vst-convolver programs. I can have multiple convolvers on at the same time, so there's two buttons for each convolver, one that switches individual convolver on/off and one the stops all other convolvers and starts the selected. For this section I'd like to have status information updated. I have already python script for updating the global variables and it works when I manually refresh the page but pressing the button does not refresh the page. So, how do I refresh the page when a button is pressed? I have found some code for only doing the refresh but I need the button that sends an EG event AND refreshes the page after that. ( There's seems to be some code in config.js from the original example that handles the button events )

Another question is how I make the transient background work for the whole screen? In Honeycomb's stock browser the black background is only seen for the page part where there's text, after that it's white background. In PC's Firefox browser it works as intended. Is this simply a bug in Android's browser?

Used icons were from glyphish and a mono icon set from some free icons site. Used Paint.NET to simply invert the colors or change it to red like the on/off-icon. Paint.NET preservers the alpha channel.

Code: Select all

<!DOCTYPE html>
<html manifest="minifest.manifest">
    <head>
	<meta name="viewport" content="width=device-width, height=device-height,initial-scale=1">
        <title>Dashboard</title>
        <link rel="stylesheet"  href="css/jquery.mobile-1.0.min.css" />
        <link rel="stylesheet"  href="css/my_own.css" />
        <script src="js/jquery.js"></script>
        <script src="js/config.js"></script>
        <script src="js/jquery.mobile-1.0.min.js"></script>
        <link rel="shortcut icon" href="favicon.ico"/>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <meta content="width=device-width,height=device-height,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport2"/>
        <meta content="telephone=no" name="format-detection"/>
        <meta content="address=no" name="format-detection"/>
    </head>
    <body>
        <div data-role="page" data-theme="a" id="jqm-home">
    <div data-role="header" data-position="fixed" data-id="mynavigation">
	<div data-role="navbar" >
        	<ul>
			<li><a href="index.html" class="ui-state-persist ui-btn-active">Main</a></li>	
		        <li><a href="audio.html" >Audio</a></li>
		        <li><a href="icm.html" >ICM</a></li>
        		<li><a href="xbmc.html" >Xbmc</a></li>
		        <li><a href="tv.html" >TV</a></li>
			</ul>
		</div>
	</div>
<style>	
	.nav-big-icons .ui-btn .ui-btn-inner { padding-top: 40px !important; }
	.nav-big-icons .ui-btn .ui-icon { width: 30px!important; height: 30px!important; margin-left: -15px !important; box-shadow: none!important; -moz-box-shadow: none!important; -webkit-box-shadow: none!important; -webkit-border-radius: 0 !important; border-radius: 0 !important; }

	.nav-big-two-icons .ui-btn .ui-btn-inner { padding-top: 40px !important; }
	.nav-big-two-icons .ui-btn .ui-icon { width: 70px!important; height: 30px!important; margin-left: -35px !important; box-shadow: none!important; -moz-box-shadow: none!important; -webkit-box-shadow: none!important; -webkit-border-radius: 0 !important; border-radius: 0 !important; }
	
	#tv 			.ui-icon { background: url("icons/70-tv-neg.png") 		no-repeat; background-size: 22px 24px;  }
	#monitor 		.ui-icon { background: url("icons/69-display-neg.png") 		no-repeat; background-size: 22px 20px;  }
	#projector 		.ui-icon { background: url("icons/Projector-48-neg.png") 	no-repeat; background-size: 32px 32px;  }
	#movies 		.ui-icon { background: url("icons/45-movie-1-neg.png") 		no-repeat; background-size: 19px 25px;  }
	#music 			.ui-icon { background: url("icons/194-note-2-neg.png") 		no-repeat; background-size: 23px 23px;  }
	#headphones 		.ui-icon { background: url("icons/120-headphones-neg.png") 	no-repeat; background-size: 22px 21px;  }
	#speaker 		.ui-icon { background: url("icons/speaker-neg.png") 		no-repeat; background-size: 22px 21px;  }
	#music_headphones	.ui-icon { background: url("icons/194-note-2-neg.png") 		top left no-repeat,	url("icons/120-headphones-neg.png") 	top right no-repeat; background-size: 30px 30px;  }
	#music_speakers		.ui-icon { background: url("icons/194-note-2-neg.png") 		top left no-repeat,	url("icons/speaker-neg.png")	 	top right no-repeat; background-size: 30px 30px;  }

	#movies_headphones 	.ui-icon { background: url("icons/45-movie-1-neg.png") 		top left no-repeat,	url("icons/120-headphones-neg.png") 	top right no-repeat; background-size: 30px 30px;  }
	#movies_speakers 	.ui-icon { background: url("icons/45-movie-1-neg.png") 		top left no-repeat,	url("icons/speaker-neg.png") 		top right no-repeat; background-size: 30px 30px;  }
	#movies_tv	 	.ui-icon { background: url("icons/45-movie-1-neg.png") 		top left no-repeat,	url("icons/70-tv-neg.png") 		top right no-repeat; background-size: 30px 30px;  }
	#on 			.ui-icon { background: url("icons/on.png") 			top center no-repeat; background-size: 24px 24px;  }
	#off	 		.ui-icon { background: url("icons/off.png")		 	top center no-repeat; background-size: 24px 24px;  }

</style>

<div class="ui-grid-a" >
	<div class="ui-block-a">
		<div data-role="content" class="nav-big-icons" >
        	        <div data-role="controlgroup" data-type="horizontal" >
        	        	<div title="projector.on" data-role="button">Projector On</div>
                		<div title="projector.off" data-role="button">Projector Off</div>
                	</div>
                	<div data-role="controlgroup" data-type="horizontal">
                		<div title="CCC_Profiles.Monitor.60Hz" data-role="button" id="monitor" data-icon="custom" data-iconpos="top" style="width: 200px;" >Monitor 60Hz</div>
                	</div>
                	<div data-role="controlgroup" data-type="horizontal" >
                    		<div title="CCC_Profiles.Projector.24Hz" data-role="button" id="projector" data-icon="custom" data-iconpos="top" style="width: 200px;" >Projector 24Hz</div>
                    		<div title="CCC_Profiles.Projector.50Hz" data-role="button" id="projector" data-icon="custom" data-iconpos="top" style="width: 200px;" >Projector 50Hz</div>
                    		<div title="CCC_Profiles.Projector.60Hz" data-role="button" id="projector" data-icon="custom" data-iconpos="top" style="width: 200px;" >Projector 60Hz</div>
                	</div>
                	<div data-role="controlgroup" data-type="horizontal">
                    		<div title="CCC_Profiles.TV.24Hz" data-role="button" id="tv" data-icon="custom" data-iconpos="top" style="width: 200px;" >TV 24Hz</div>
                    		<div title="CCC_Profiles.TV.50Hz" data-role="button" id="tv" data-icon="custom" data-iconpos="top" style="width: 200px;" >TV 50Hz</div>
                    		<div title="CCC_Profiles.TV.60Hz" data-role="button" id="tv" data-icon="custom" data-iconpos="top" style="width: 200px;" >TV 60Hz</div>
                	</div>
            	</div>
        </div>
	<div class="ui-block-b">
    		<div data-role="content"  class="nav-big-two-icons">
        		<div data-role="controlgroup" data-type="horizontal">
            			<div title="VstHost.MusicHeadphonesOnly" data-role="button" id="music_headphones" data-icon="custom" data-iconpos="top" style="width: 250px;" >Music Headphones</div>
            			<div title="VstHost.MusicHeadphones"	data-role="button" id="{{"on" if eg.globals.Music_Headphones else "off"}}" data-icon="custom" data-iconpos="top">{{"On" if eg.globals.Music_Headphones else "Off"}}</div>
        		</div>
        		<div data-role="controlgroup" data-type="horizontal">
            			<div title="VstHost.MusicSpeakersOnly"	data-role="button" id="music_speakers" data-icon="custom" data-iconpos="top" style="width: 250px;" >Music Speakers</div>
            			<div title="VstHost.MusicSpeakers"	data-role="button" id="{{"on" if eg.globals.Music            else "off"}}" data-icon="custom" data-iconpos="top">{{"On" if eg.globals.Music else "Off"}}</div>
        		</div>
        		<div data-role="controlgroup" data-type="horizontal">
            			<div title="VstHost.MoviesHeadphonesOnly" data-role="button" id="movies_headphones" data-icon="custom" data-iconpos="top" style="width: 250px;" >Movies Headphones</div>
            			<div title="VstHost.MoviesHeadphones"	data-role="button" id="{{"on" if eg.globals.Movies_Headphones else "off"}}" data-icon="custom" data-iconpos="top">{{"On" if eg.globals.Movies_Headphones else "Off"}}</div>
        		</div>
        		<div data-role="controlgroup" data-type="horizontal">
            			<div title="VstHost.MoviesSpeakersOnly" data-role="button" id="movies_speakers" data-icon="custom" data-iconpos="top" style="width: 250px;" >Movies Speakers</div>
        			<div title="VstHost.MoviesSpeakers" 	data-role="button" id="{{"on" if eg.globals.Movies else "off"}}" data-icon="custom" data-iconpos="top">{{"On" if eg.globals.Movies else "Off"}}</div>
        		</div>
        		<div data-role="controlgroup" data-type="horizontal">
            			<div title="VstHost.MoviesTVOnly" 	data-role="button" id="movies_tv" data-icon="custom" data-iconpos="top" style="width: 250px;" >Movies TV</div>
            			<div title="VstHost.MoviesTV"  		data-role="button" id="{{"on" if eg.globals.Movies_HDMI else "off"}}" data-icon="custom" data-iconpos="top">{{"On" if eg.globals.Movies_HDMI else "Off"}}</div>
        		</div>
		</div>
	</div>

<!-- /grid-a -->
</body>
</html>

Attachments
Dashboard.PNG
Last edited by Mama70 on Sun Dec 18, 2011 4:27 pm, edited 1 time in total.

User avatar
Livin
Experienced User
Posts: 792
Joined: Wed Oct 08, 2008 4:56 am

Re: EG with webserver-plugin, AJAX w/jQuery, simple example

Post by Livin » Sun Dec 18, 2011 4:15 pm

nice job!

Wish we had a web guru who could made this into something more like creating a skin (simple XML layout) so people could simply make layout based on predefined buttons/actions/etc.
setup... XBMC, W7MC for DVR & Live OTA TV, JRMC for multi-zone audio, EG, MiCasaVerde Vera3, USB-UIRT IR receiver, Harmony remote, 5.2 home theater system

Post Reply