I am trying to create a web interface for an OF app.
What I want to achieve is:
Get video stream from OF displayed in the webpage,
Get webpage UI control (slider/buttons/checkboxes/…) to OF,
Set webpage UI control values from OF.
I started using ofxHTTP and got the video stream part done looking at “example_basic_ip_video_server”.
Now I am having hard time to understand how can I get access back and forth (OF <-> Webpage) to the UI elements…especially since my knowledge of Web/HTML is very limited
Looking at this topic, @bakercp recommend to use ofxJSONRPC.
I tried it but couldn’t get the example to work because Xcode cannot find ‘json/json.h’. I installed json from here but without any success.
So I have some questions:
Is ofxJSONRPC the way to go for what I want to do?
Can I achieve what I want to do using only ofxHTTP?
(to what I understand I need to send/receive GET or POST requests from the web page. Am I right?)
I looked at ofxHTTP “example_basic_post_server” but I don’t want to use forms. Also I couldn’t get both the video server and the POST server running at the same time (which I am not sure is a good idea anyway).
This is totally possible to do! It’s how we made ofSketch. I can go into detail at the moment, but the first order of business is to make sure you are using ofxJSON. Secondly, could you post some screen shots and more errors so we can get it compiling? Thanks!
Ok I think I am now going somewhere
I had difficulties to understand how the OF app, the index.html and the main.js work together but I start to get it.
So far I managed to create some button, slider and dropdown elements on the webpage. I registered new method in the json server in OF. When I change the UI element, I have the correct function being called in OF and sending the UI element’s value correctly.
But I couldn’t understand how to do it the other way around:
How can I call some function in OF that would change the value of an item of my UI?
One questions about the registered method called in OF:
Is it possible to return more than 1 argument?
If for example I have several sliders on my webpage and want to call in OF a single getSlider() function: can I send the value and the name of the slider at once?
I tried to combine both the JSONRPC and the Video example in the same app but cannot get them to work at the same time together. I end up having 2 servers and only the one started before the other is working.
Is it possible to create somehow a server variable that can be of type both
ofx::HTTP::BasicJSONRPCServer and ofx::HTTP::BasicIPVideoServer?
Hi there. Basic Http is a client driven protocol (get, post, head, delete messages), so every communication must be started by the client (the browser).
If you want to submit events initiated at the server (I understand that this is what you want, changing values from the server to the UI in the browser) the basic way to do it is to simulate push by polling. You shoud send a post periodically from the browser, like a keepalive message, and in the response from the server you would include data useful to the browser (in this case, UI data).
This approach has a lot of lag, and might put excessive stress on the server (responding to posts periodically from different clients, when there might not be data to transmit).
The modern eay to do it, and more efficient, is to manage communication through a websocket. A web socket is just like a tcp socket, but runs on top on http, it requires browser support, and server support. Luckily, there are a few addons that wrap libwebsocket lib that will allow you to set up a websocket server in your ofapp.
With the websocket established, you will be able to send and receive messages from client or server indistinctivley.
(You may be able to maintain most of your current architecture, since you can still send json through the websocket)
Thank you for this explanation!
I also found some presentation that explained this same principle and the strength behind websockets, compared to basic http.
From the description of ofSketch, about ofxJSONRPC:
This is a JSONRPC 2.0 compliant server built on top of ofxHTTP. It allows
us to interact with the jquery jsonrpc client on the front end. It can
handle round trip JSONRPC requests and notifications over POST requests and
WebSockets (we are using the WebSockets exclusively).
So I am now trying to understand how to create json messages that can be sent from OF correctly. And also if for each json message I am sending, I need a function on the client side to catch it.
Hey @Meach sorry for the delay getting back to you.
Sending messages from the server to the client is a somewhat manual process at this point.
If the client calls a method (like the ping or pong in the example), the server will respond and the jquery.jsonrpcclient.js will take care of routing the responses back to the right callback. Thus, with the jsonrpc model, the only messages that are automatically handled are those that come as a response to the client’s direct request.
So, to send unsolicited messages from the server to the client (which we do when new connections are made, etc) we have to set up another protocol. Basically we define a “module” (for routing purposes) and a “method” and some “data” (in the form of some JSON) to send with it. We use this method to package it all up before sending from the server to the client:
Here is an example of a packet that we send to the client that includes the server’s version info, etc:
All of this version info is sent without being requested, so on the client side, we are prepared to parse it here …
First we look at the “module”
Then we pass it to the right handler, where the json is used:
Anyway, I hope this makes sense. It’s basically client-driven model (because of the GUI nature of it) with the JSONRPC calls only initiated by the client. Any information that you need to send from that server that is not explicitly requested by the client must be handled as I mentioned above.
PS. I’m working on this stuff today and will hopefully have a clearer example of the mechanics of server-sent data. The ofSketch code has a lot of other stuff going on so it’s not a great way to learn …
Thanks for the explanation bakercp, it definitely helps!
I will check this out very soon but I think I start to understand how things are working. I will try it out myself and will let you know if there are things that I don’t manage or if I am some questions.
I can now control all UI elements I have from OF, this is awesome!
But I realised that onWebSocketOpen function needs to be called before I can send anything from OF.
Is there any way to do this when the web page load directly?
One way to get the function called is to use some UI element at first on the page but it’s not super convenient.
Also, is there a way to send a JSON message with a vector as parameter? For example I have a dropdown element on the webpage that I would like to populate at once from a vector< string > in OF.
At the moment I am sending as many JSON messages as string in this vector but it would be much more convenient to be able to send them all at once.
Anyway, right now the websocket does not open until the first jsonrpc call. So there are two options.
To send a vector, just construct a json array from your std::vector<string> in oF. An array of strings might look like:
"arrayOfStrings":[ "one", "two", "three"]
To create an array of strings using ofxJSON (aka jsoncpp) you can use the “append()” method.
Thanks for your answer. Yes I love it, I think it’s really cool!
I chose the solution 1. to open the webSocket when the web page load and it works fine now. Same with the vector, works perfectly.
Only tiny problem I still have is the float value of my slider that I am sending from the client cannot be converted to float using asFloat() function. Might be something very trivial and I didn’t try to solve this for now.
If some people are interested, I enclosed my project to this post as well.
Thank you for this!
Is it possible to establish a connection to the video- and json-server from the web?
In example, i’d like to have my webgui.html hosted on my webspace,
so if i browse mydomain.com/webgui.html i can send and receive data to and from the ofApp.