Closed ErikDeBruijn closed 9 years ago
Brief introduction: I created Artemis-Glitter a while back - https://github.com/IvanSanchez/artemis-glitter
My approach on DMX/physical relays/LCD screens right now would be to create a separate game client for that kind of hardware devices, and not tie it to the game core itself. I plan to do that in Glitter: write a small Glitter client which listens to very specific messages and triggers stuff in my RaspPi I2C interface.
So I'd vote for exposing these kind of interactions through the network, in a way clients can subscribe to certain events. e.g. I could have an Arduino listening to the energy level of the player ship and displaying it in a LCD 7-segment display, a RaspPi listening to red alerts and shield status and controlling a RGB LCD strips, and a laptop listening for comms and using text-to-speech.
If this functionality were to be integrated in the game core, there'd be no way of running it in an Arduino, I guess.
Now, which specific protocol to use, I don't know. I would consider some kind of lightweight custom UDP, or maybe some heavier protocol with publish-subscribe capabilities like RabbitMQ or websockets.
I have to agree with Ivan. It makes much more sense to have a 'hardware' client that can subscribe to certain events. This gives us much more flexibility, without having to completly merge things deeply inside the core of things (which will mess things up further down the stream).
Also, wouldn't it be possible to re-use the glitter code for empty epsilon? It looks like a lot of effort & time went in to it. I believe it could be possible with an aditional (swapable?) translator object of some kind.
One of the problems would be to hooking into the EE protocol. As the protocol is "unstable", it changes with code changes. The code behind it makes it very easy and quick to make the network code, but a side effect is that there is no defined protocol other then "update variable X on object Y", and the variables linked to X change with code changes.
However, this does not mean the end of the world. I think hooking into the EE script engine would be the best place. For example:
ship = getPlayerShip(1)
if ship ~= nil then
front_shield_level = ship:getFrontShield() / ship:getFrontShieldMax()
end
Will get the shield level of the first player ship.
Now it's just looking into give a way to hook into this engine remotely. Maybe a http server where you can do lua script requests and get the output as response?
Now it's just looking into give a way to hook into this engine remotely.
I, for one, would like to have websockets or even socket.io. But I'm biased towards that because of how artemis-glitter works anyway.
I'm a bit worried about network&processor load, though. My RaspPi struggles to manage the world model from Glitter with more than a few dozen ships, so I don't want to think how an Arduino with an ethernet shield will do.
That's why I have a strong opinion towards a pub-sub (publish-subscribe) model. e.g. a "red alert arduino" would connect to EE and say "I'm only interested in game start, game end, and red alert events from player ship 1".
I think either solution makes sense, but luckily they are not mutually exclusive. If someone adds a headless version of a client which becomes a pub/sub server that's great. Awesome client libraries like @IvanSanchez would definitely be nice to have. Especially for those who have web-development experience in writing aux. interfaces. As long as such a client shared most of the codebase and it compiles similarly, that's fine. The server @daid is talking about is nice because it would be very easy to independently write code without worrying about protocol too much. I think it gives a lot of freedom that the lua-bindings now offer and I'd be able to work with that quickly without introducing a huge implementation.
Not going to do socket.io or websockets, for the simple reason, it sucks for anything but node.js
And I don't think you want an Arduino with ethernet shield. I would run a small script on the server (or any client), attach the arduino to that, and have a small tool that translates the info from the server to information the Arduino needs and send that trough the USB line (cheaper and easier)
That your pi struggles with the data from artemis could be because of a couple of reasons. One of them could be that artemis is just sending way too much info, would be no surprise to mee, seeing the odd out-of-sync issues I've seen. Could also be that your code is just slow :-)
I'm much more for a polling model. Why? Because it's easy on my side (have all the elements, just need to hook them together) and you can load balance quite easy, if your Pi cannot keep up, you just request info less often.
Not to mention, if I add remote calls to the script engine, you can also modify the gameworld remotely if you wanted. As a lot of stuff is already done with script engine calls.
Any physical setup people will make will be "one offs" possibly inspired by what others are making, and they will probably have simple scripts like @daid mentions. So it's best to let people work independently even when protocol is very much in flux. O.t.o.h. @IvanSanchez may have seen uses of his client code that I didn't think off.
If someone adds a headless version of a client which becomes a pub/sub server that's great.
Definitely an option, but now I'm not in the mood to implement another low-level packet-parsing interface (specially if EE's network code is prone to change), thankyouverymuch.
Unless there would be an easy way to auto-generate packet descriptions, or some nodejs interface to seriousproton, I guess.
Maybe I will look into doing some EE+lua+nodejs+socketio mess in the future.
it sucks for anything but node.js
Every time someone talks badly about Node.js, I will kill a kitten. So think of the kittens. :-P
I would run a small script on the server (or any client), attach the arduino to that
Actually sounds good. I haven't really looked at EE's code, so: what kind of stuff could you do with lua scripts on a client?
Is there any easy way to create a headless EE client, able to run custom lua scripts?
That your pi struggles with the data from artemis could be because of a couple of reasons.
I'm pretty sure it's because of floating-point arithmetic to calculate the distances (for the proximity alert) O:-)
Every time someone talks badly about Node.js, I will kill a kitten. So think of the kittens. :-P
Guess it's who you backed all those millions in exploding kittens then. As I've been ranting a LOT about node.js and specificly socket.io the last few weeks. https://www.kickstarter.com/projects/elanlee/exploding-kittens
Actually sounds good. I haven't really looked at EE's code, so: what kind of stuff could you do with lua scripts on a client?
Scripts are normally run on the server, and not on the clients. Right now I setup the scenarios with scripts. Example: https://github.com/daid/EmptyEpsilon/blob/master/scripts/scenario_01_waves.lua
But supply drops are also handled with a script: https://github.com/daid/EmptyEpsilon/blob/master/scripts/supply_drop.lua This script is called from the comms station communication script: https://github.com/daid/EmptyEpsilon/blob/master/scripts/comms_station.lua#L20 And keeps running till the drop is made or the ship is destroyed.
The functions available to the scripts are located in the code with each C++ object. For example, a spaceship has the following functions: https://github.com/daid/EmptyEpsilon/blob/master/src/spaceship.cpp#L22 But, as a spaceship is also an spaceObject (an object in space) it also has these functions: https://github.com/daid/EmptyEpsilon/blob/master/src/spaceObject.cpp#L9
The advantage of adding a function to the scripting engine is that it makes it available for a lot of places. Instead of making a custom system for each.
Is there any easy way to create a headless EE client, able to run custom lua scripts?
That can be done, but then the scripts should only query data, not modify it (as the server has authority). Does need some minor engine modifications, as the main loop is bound to the drawing routines. But nothing serious.
That can be done, but then the scripts should only query data, not modify it (as the server has authority).
What if CrewUI.cpp
also exposed functions to the lua interface? I can only guess that will trigger client-to-server communication. And that should make happy those nerds with switches for physically raising/lowering shields.
I would simply have to expose all the "command???" functions in playerSpaceship.cpp, these are all the commands that get send from the clients to the server. Should be easy. (no need to go trough CrewUI stuff for that, those just link the command functions to screen buttons)
Well, yeah, you've got my point. Sorry for not knowing how the innards of EE work :-)
No problem in not knowing, that's why I'm here :-) I hope to do some work on this this weekend.
Still got some hardware that could be hooked up at some point: http://daid.eu/~daid/20150110_145649.small.jpg http://daid.eu/~daid/IMG_20130626_211925.small.jpg (would make a nice jump drive button :) )
And we already have a touchscreen hardware setup: http://daid.eu/~daid/20150219_204125.small.jpg
And not on photos, we have a strobe light, a red alarm light and a smoke generator as well. But also need to hook those up.
Only daid knows how the innards work ;) Documentation is rather sparse.
I've been reading most of the code EE and some of the Serious Proton to get an idea of how it works.
From my own script I can perform a HTTP POST /script/lua HTTP/1.1
with the following data:
local json = require( "json" ) -- Include the Corona JSON library
ship = getPlayerShip(1)
if ship ~= nil then
shields_active = ship:getShieldsActive()
hull = ship:getHull()
hullMax = ship:getHullMax()
end
local returnValues = { shields_active = shields_active, hull = hull, hullMax = hullMax }
print ( json.encode( returnValues ) )
I'm a bit uncertain about that last two lines. Basically I'd like to get back a json string that's easy to parse for me. Based on that data I can check if any relays need to change to do something physical, e.g. switch a relay :)
I noticed that you have a webserver already in serious proton, however it appears it's not run from the EE code. But it seems like everything is prepared to do this, since arbitrary lua code could be executed with something along these lines:
P<ScriptObject> so = new ScriptObject();
so->runCode(postBody);
so->destroy();
With a few hints I might be able to get something like this working, or not. I'd be happy to give it a try.
I've now got a ~ 50 line ruby script that performs a HTTP request lua code, listens for a response, parses json (if present) and interprets if there are relevant changes. If so, it controls the Arduino resulting in switching of a relay, for example.
The Arduino is bootstrapped by the dino gem, which basically turns the Arduino into a dumb slave to be controlled through usbserial (and gets automatically discovered). No user code has to run on the Arduino.
Code is in this gist: https://gist.github.com/ErikDeBruijn/ebef5db43fe224969b40
Note, the HTTP server code in SP is old code, just stored there for safekeeping. It needs fixes and updates to work proper.
Ok, updated the script engine, and the http server.
You can now add a "httpserver=80" in the options.ini and it will run a http server on port 80. It will serve files from a directory "www", and when you send a post request to "/exec.lua" with a script, you get the return value of that script as json result.
Example test HTML file: https://gist.github.com/daid/585b589207c5a8f1d62b
Awesome!!! Can't wait to use it. The example is clear to me too. Nice that I can just return and that it gets passed back as JSON.
B.t.w. I'm getting a compilation error since the new logging.
/home/emptyepsilon/Dev/SeriousProton/src/collisionable.cpp|180|error: ambiguous overload for ‘operator<<’ (operand types are ‘const Logging’ and ‘std::vector<sf::Vector2<float> >::size_type {aka long unsigned int}’)|
This << var.size() <<
occurs in a few places, removing those temporarily helped it getting compiled.
Finally I had a missing header file:
/home/emptyepsilon/Dev/EmptyEpsilon/src/main.cpp|10|fatal error: httpScriptAccess.h: No such file or directory|
Perhaps you still need to commit it to the repo?
Ok, with commit fd52d7 I get further:
[68%] g++ -Wall -I../SeriousProton/src -O2 -o _build_Linux_Linux_Release/commsScriptInterface.o -c src/commsScriptInterface.cpp
In file included from src/spaceObjects/spaceship.h:5:0,
from src/spaceObjects/playerSpaceship.h:4,
from src/commsScriptInterface.h:22,
from src/commsScriptInterface.cpp:1:
src/spaceObjects/spaceObject.h:5:18: fatal error: mesh.h: No such file or directory
#include "mesh.h"
^
Commited the missing file, and possibly commited a fix for the other issues.
The JSON conversion might not be perfect right now, but I think it will be good enough. (Does not do arrays properly yet, but key value pairs work fine)
okay, key val pairs are just fine! :) It compile now! :)
I couldn't figure out how to run EE not in full screen, so it was difficult to try it with one system. After some network changes I can access a linux VM on its own IP and run scripts from the host while the VM has the app running in fullscreen. I've tried your lua code from the gist, but I get back {"ERROR": "Script error"}
. Even with simplified versions (e.g. return {hull = 1}
). The good thing: I can access the webserver and it attempts running lua code, but it's not quite there yet.
doh, and now I find the fullscreen option. :)
The error from the script is logged in the terminal where you start the game. Not really user friendly yet.
Error was syntax related because the requests were URL encoded (in the body).
I'm currently adding support for openHAB, a home-automation-hub which supports a huge amount of protocols and devices, web-interfaces and apps. Connecting EmptyEpsilon to real-world devices should be rather easy using this.
I've got a test-setup running where I'm using HTTP GET-request to poll the state of EmptyEpsilon twice per second, this works really nice :) See daid/SeriousProton#1 for more info...
I've uploaded my version of the physical interactions client to github, it can be found here: https://github.com/ErikDeBruijn/epsilon-phys-client
Given that we now have a http server that responds to lua, I guess we can close this issue since that gives us a lot of options.
B.t.w. I'm getting a compilation error since the new logging.
/home/emptyepsilon/Dev/SeriousProton/src/collisionable.cpp|180|error: ambiguous overload for ‘operator<<’ (operand types are ‘const Logging’ and ‘std::vector<sf::Vector2<float> >::size_type {aka long unsigned int}’)|
This<< var.size() <<
occurs in a few places, removing those temporarily helped it getting compiled.
I know that this is very long ago so this is just for posterity, but I just fixed this compile error that Erik had encountered, because I had encountered it as well. The fix is here: https://github.com/daid/SeriousProton/pull/21/commits/0073134d34e55af869ecd3e280acd9be6478c522 It would be merged along with my pull request to build Serious Proton using CMake.
My plan is to add a signal light, smoke generator and stroboscope to an Arduino which has a shield with relays. The physical devices should augment the game with effects that are being synchronised with what happens in the game. E.g. shields go up, alarm light goes off.
It runs this really basic sketch that I can build and upload with inotool.org. I can use inotool serial and press captial
A
to turn on relay 1, and lowercasea
to turn it off. B, C and D are relay 2, 3 and 4 respectively.I need some way of knowing what happens in the game. Either a "minimal" client that uses no GUI, or a lua binding that can send serial commands. E.g. https://github.com/edartuz/lua-serial
Another way is that a client writes to a log file which I can tail and feed to my (independent) script. E.g. lines like: spaceShip:shieldUp would turn on the strobe. spaceShip:hullDamage=xx% would create smoke and an occasional flash.