Notice: This forum has been recovered from an old backup, so some content, links, and dates may be outdated. The forum is currently read-only while we restore sign-in and registration functionality. Details

If you find this forum valuable and would like to help keep it online, donations to help cover hosting and domain costs are greatly appreciated, but never expected. You can support the forum through Buy Me a Coffee or Ko-fi. Thank you for helping preserve the EventGhost community.

Websocket Plugin

Do you have questions about writing plugins or scripts in Python? Meet the coders here.
cfull1
Experienced User
Posts: 124
Joined: Thu Aug 19, 2010 4:52 am

Websocket Plugin

Post by cfull1 »

WebSocket is a technology providing for bi-directional, full-duplex communications channels, over a single Transmission Control Protocol (TCP) socket. It is designed to be implemented in web browsers and web servers, but it can be used by any client or server application
This makes client-side polling obsolete, as the server(eventghost) can send data at any time.

Currently supported browsers:
Chrome, Safari, iOS 4.2+.
Firefox and Opera also have them implemented but they are disabled by default and I can't not confirm their compatibility.
I am looking into the possibility of supporting the Android browser through flash.


Here's the lastest version of my WebSocket Plugin.

Version 0.9.3 updated 7/9
Websocket.zip
(7.72 KiB) Downloaded 444 times
Any testers would be greatly appreciated!

Carson
Last edited by cfull1 on Sat Jul 09, 2011 10:08 pm, edited 5 times in total.
krambriw
Plugin Developer
Posts: 2570
Joined: Sat Jun 30, 2007 2:51 pm
Location: Stockholm, Sweden
Contact:

Re: Websocket Plugin

Post by krambriw »

There are many plugins that are using threads. In those you find code for starting and stopping threads as well as other good examples like configuration settings, actions etc etc

The best is to study the code of one of the plugins. All plugins are with the source code, you find them in the eg install folder under plugins

Right know, I can't point you in any diection which one you should start looking at, there are so many that are using threads

Best regards, Walter


EDIT:
You mention that it is working ok but from command line. That's at least a good start. It seems that the functionality you are looking is provided by the thread. When you consider making a plugin, you should put the thread "logic" into the thread section of the plugin. If you add methods in the plugin to start and to stop the thread, you will do this when you enable/disable the plugin. You should add som print statements (to print "Thread started..." and "Thread stopped..." at least in the start of your testing to see that it is working ok)

Important when you design the plugin is to analyse what more functions you would like to give the user:
- what shall be configurable?
- do you need any actions?
- do you want the plugin to generate some events?
- do you want to allow multiple instances?
- make it possible to easy translate (keep texts away from the code, put it in foreseen sections)

All this you can find in most of the plugins
cfull1
Experienced User
Posts: 124
Joined: Thu Aug 19, 2010 4:52 am

Re: Websocket Plugin

Post by cfull1 »

Walter,

Thanks for your input.
I have been considering these things.
My thought was to try to get all the functionality worked out before I put it into eg, since that will cause its own problems.
I've been looking through the plugins, the director watcher one is good. It's pretty clean so its not so hard to understand whats going on.
There are very few that have more than just the __init__ file, this leads me to believe that I should try to combine my files into one.

I have found a way to stop the client threads. I'm still working on the server loop and combining the stop action into one function for everything.

EDIT:
The problem I'm running into is that I'm waiting for a line of code in the thread and/or the server loop before they will close.

client thread:

Code: Select all

while (self.running == True):
    self.interact(self.channel)                      #This line
    if(self.websocket.running == False):
        print 'server is telling me to stop thread'
        self.running = False
print 'thread stopped'
server:

Code: Select all

while (self.running == True):
    channel, details = server.accept()               #This line
    if(self.running == True):
        self.uid = self.uid + 1
        self.users.append(user.user(channel, self.uid))
        wsthread.WebSocketThread (channel, details, self)
print 'server stopped'
As soon as the client tries to do something the thread will close.
As soon as a client tries to connect to the server the server will close.

Is there any way to fix this?
User avatar
Pako
Plugin Developer
Posts: 2294
Joined: Sat Nov 11, 2006 1:31 pm
Location: Czech Republic
Contact:

Re: Websocket Plugin

Post by Pako »

For several days, I deal with it.
I think it will go.
I'm just not sure if it will have some sense because here are plugins Webserver, Network sender, Network receiver and Broadcaster.

Pako
cfull1
Experienced User
Posts: 124
Joined: Thu Aug 19, 2010 4:52 am

Re: Websocket Plugin

Post by cfull1 »

Pako,

Thank you for your time and effort.
The problem was the socket connection was setup as blocking instead of nonblocking.
Unfortunately this ment most of the code had to be changed, but I think I have it fully functional now.
The code is alot cleaner, which I'm happy about.
I just want to do a bit more testing, but I'll upload it shortly.
I'm just not sure if it will have some sense because here are plugins Webserver, Network sender, Network receiver and Broadcaster.
I'm not sure I understand what you are trying to say.
Can any of these plugins send data directly to an html client without polling? That is my main goal with this plugin.

Thanks,
Carson
User avatar
Pako
Plugin Developer
Posts: 2294
Joined: Sat Nov 11, 2006 1:31 pm
Location: Czech Republic
Contact:

Re: Websocket Plugin

Post by Pako »

cfull1 wrote:
I'm just not sure if it will have some sense because here are plugins Webserver, Network sender, Network receiver and Broadcaster.
I'm not sure I understand what you are trying to say.
Can any of these plugins send data directly to an html client without polling? That is my main goal with this plugin.
It will probably be the fact that I was by this time had never heard about Websocket.
Although I found something on the internet and it seems that it is a perspective thing.
However, I am probably not fully understand to what is it good.
Can you please give an example of how it can be used in conjunction with EventGhost?

Pako
cfull1
Experienced User
Posts: 124
Joined: Thu Aug 19, 2010 4:52 am

Re: Websocket Plugin

Post by cfull1 »

Websockets provide an "upgraded" connection between html clients and servers.
The downfall of standard connections is there is no way for the server to send data to the client without the client asking for it.
For example, if you want to display the currently playing itunes song / artist / album, the client would have to ask for it either by clicking a button or polling the server at a set interval.
With websocket connection, eventghost gets notified of the track change and immediately sends the data to the client, which can then display it properly.
The way I currently display itunes data on my remote client is by writing the data to a file in eventghost and then the client goes and gets the file.
This is messy and its impossible to time right.
Maybe I'm wrong but this was the only method I knew of to send data to html clients.

The uses are very open. Besides sending data for the currently playing media, the client could get alerted by eventghost for something, such as to confirm a macro completed successfully. For me, I can change who eventghost allows to connect so I can lock my roommates out for whatever reason, and their clients (iphones) will receive this data and not send anymore commands. It all depends on your setup.

My html client is the only way I control eventghost outside of opening the application.
Rather than using it as a standard remote, its shows more dynamic data.

I hope this explains its usefulness.
Carson

EDIT: Updated the original download, with the latest working version
User avatar
Pako
Plugin Developer
Posts: 2294
Joined: Sat Nov 11, 2006 1:31 pm
Location: Czech Republic
Contact:

Re: Websocket Plugin

Post by Pako »

Thank you for your explanation, now I understand it much better.
BTW - your new version (0.9.2) I did not get to work.
But I'm not going to deal with it. Meanwhile, I worked on my implementation.
It even allows to run multiple servers (with different or the same functions) on various network interfaces / ports.
And also has the function of the client, so this plugin can be used for "communication" between two (or more) EventGhost.
But it still requires a lot of work to do.
BTW - I also proceeded to use select.select, but in another place.

Pako
cfull1
Experienced User
Posts: 124
Joined: Thu Aug 19, 2010 4:52 am

Re: Websocket Plugin

Post by cfull1 »

What part did not work?
Would you upload your edits with the select.select?

Will your implementation be able to run on a html client?

Carson
User avatar
Pako
Plugin Developer
Posts: 2294
Joined: Sat Nov 11, 2006 1:31 pm
Location: Czech Republic
Contact:

Re: Websocket Plugin

Post by Pako »

cfull1 wrote:What part did not work?
I do not know. It does not report any error, but it just does nothing.
Html client does not display any messages at all, the server does not respond to button POKE, the action "SendMessage" also has no response. Well, probably it will be easier if I find why it does not work for me ...
cfull1 wrote:Would you upload your edits with the select.select?
Meanwhile I can not really, it is in a state that I can not publish. But at least I attach two pictures. Anyway - I came to the conclusion that it must fundamentally remake. As it stands, I need too many threads.
cfull1 wrote:Will your implementation be able to run on a html client?
If I understand the question correctly, so I think the answer is obvious from the attached pictures.

Pako
Attachments
WebsocketTree.gif
WebsocketStartServer.gif
krambriw
Plugin Developer
Posts: 2570
Joined: Sat Jun 30, 2007 2:51 pm
Location: Stockholm, Sweden
Contact:

Re: Websocket Plugin

Post by krambriw »

Hi,
Pls write some lines how you would configure. Its ok to add the plugin and to create an action to send message. But where do you want the html page placed? Is the EG web server plugin needed too?

Best regards, Walter
Mannyman
Posts: 4
Joined: Sat Jul 09, 2011 7:38 am

Re: Websocket Plugin

Post by Mannyman »

Win XP
EG 0.3.7.r1462

I added client.html to the EG webServer root.
I then opened the html in Chrome:
Image
What is the desired result?



Thanks,
Manny
User avatar
Pako
Plugin Developer
Posts: 2294
Joined: Sat Nov 11, 2006 1:31 pm
Location: Czech Republic
Contact:

Re: Websocket Plugin

Post by Pako »

Pako wrote:Well, probably it will be easier if I find why it does not work for me ...
So I figured it out. I proceeded as follows:
1. I found that my PC the expression "socket.gethostbyname(socket.gethostname())" evaluates to 192.168.56.1 . This address has a virtual adapter "VirtualBox Host-Only Ethernet Adapter".
2. I am instead of "socket.gethostbyname(socket.gethostname())" use empty string "" (ie All available interfaces). Unfortunately, even now it did not work. BTW - which browser you use? I used Chrome or Black Hawk. Both behave the same - it reported an error - see picture:
Websocket-Chrome-Error.gif
3. I replaced expression "window.location.hostname" in the file client.html by string "127.0.0.1". Now it has been a little better. Server response to client connection, but immediately disconnected. Chrome now reported error as follows:
Websocket-Chrome-Error2.gif
Websocket-Chrome-Error2.gif (4.59 KiB) Viewed 10406 times
4. In the plugin file and it the file client.html I replaced the host address
by the fixed IP address of my WiFi interface ("192.168.178.21") and voila - it started to work!

@krambriw:
No, the Webserver plugin is not required to do so. Conversely, in some cases may be a new plugin Websocket used instead of Webserver plugin.
As he wrote cfull1, it has one big advantage. Websocket may change the contents pages without polling.

Pako
cfull1
Experienced User
Posts: 124
Joined: Thu Aug 19, 2010 4:52 am

Re: Websocket Plugin

Post by cfull1 »

Pako,
my mistake. I tried to simplify things last minute with socket.gethostbyname(socket.gethostname()). I uploaded a new version allowing you to give the host ip address. As long as this address and the address listed in the html client are the same it should connect. I use chrome, and safari on my iphone.
If you are still having problems try loading the html file through that ip address and not "localhost" or "file:///". As part as the websocket security it has to make sure its all the same.

It should be noted currently websockets are not supported in internet explorer. I'm not sure about firefox. Chrome and Safari work fine though.

krambriw and Mannyman,
Download the new version (0.9.3). As I told Pako you should specify the ip address of your computer eventghost is running on.
If your using the tester configuration, I would change the host address, then disable it.
The html file's location is where ever your webserver is configured. I use eventghost's webserver plugin.
The websocket connection function can just be added to your existing setup.

Code: Select all

var ws = '';
function WebSocket() {
	ws = new WebSocket("ws://192.168.0.101:1235");
	ws.onopen = function() {
		alert("Connected");
	};
	ws.onmessage = function (event) { 
		alert(event.data);		 
	};
	ws.onclose = function() {
		ws = ''
		alert('Connection Closed');
	};
}
You need to change
ws = new WebSocket("ws://192.168.0.101:1235");
to the same ip address listed in eventghost.

The ws variable listed before the function allows you to access the websocket outside of the function. Such as,

Code: Select all

ws.send("Whatever")
I don't really see the use for this though, since html clients can already send data to eventghost whenever.
Like I said before the main advantage of using websockets is the ability for eventghost to send data to the html client immediately without polling or separate text files.

You can put whatever you want in onopen/onmessage/onclose.
onopen is called when the client connects to the server
onclose is called when the client disconnects from the server
onmessage is called when the send message action in eventghost is triggered

The poke button triggers an event in eventghost.
You could setup a macro in eventghost to send an event when poke is received.

Code: Select all

if (eg.event.payload == "POKE"):
    eg.plugins.WebSocketPlugin.SendMessageAll("Quit Poking Me!")
Right now, when you send a message to eventghost (with ws.send) it triggers the action WebSocket.Message is the payload as the message.
Is this a good way to do it? Or should I just have the message as the eventname?
Mannyman
Posts: 4
Joined: Sat Jul 09, 2011 7:38 am

Re: Websocket Plugin

Post by Mannyman »

The functionality of sending to browser client is very exciting. I'd like to incorporate this for my smartphone.

Would your plugin allow one to send files (images, or other types) to/from a webkit browser (chrome, safari, etc) to/from the PC running EventGhost?

I've been reading this page: http://www.tutorialspoint.com/python/py ... amming.htm and was wondering if I can incorporate file uploads from/to EventGhost from another PC or smartphone, but it looks like a separate webServer that supports CGI is needed. Maybe your webSocket plugin can help.


The following is from the tutorial:
File Upload Example:
To upload a file the HTML form must have the enctype attribute set to multipart/form-data. The input tag with the file type will create a "Browse" button.

Code: Select all

<html>
<body>
   <form enctype="multipart/form-data" 
                     action="save_file.py" method="post">
   <p>File: <input type="file" name="filename" /></p>
   <p><input type="submit" value="Upload" /></p>
   </form>
</body>
</html>

The result of this code is the following form:

Image

Here is the script save_file.py to handle file upload:

Code: Select all

#!/usr/bin/python

import cgi, os
import cgitb; cgitb.enable()

form = cgi.FieldStorage()

# Get filename here.
fileitem = form['filename']

# Test if the file was uploaded
if fileitem.filename:
   # strip leading path from file name to avoid 
   # directory traversal attacks
   fn = os.path.basename(fileitem.filename)
   open('/tmp/' + fn, 'wb').write(fileitem.file.read())

   message = 'The file "' + fn + '" was uploaded successfully'
   
else:
   message = 'No file was uploaded'
   
print """\
Content-Type: text/html\n
<html>
<body>
   <p>%s</p>
</body>
</html>
""" % (message,)
Post Reply