gama-platform / gama.old

Main repository for developing the 1.x versions of GAMA
GNU General Public License v3.0
304 stars 99 forks source link

Adding websocket message simulation status on Gama Server GUI #3924

Closed leonsi7 closed 11 months ago

leonsi7 commented 1 year ago

Is your request related to a problem? Please describe. I'm working on the developement of a monitor of a Gama Server which can ask Gama to load, start, stop a simulation and can interact with it. The probem I have is that when we apply a command on Gama Server GUI, Gama Server does not notify the change to my monitor an so my monitor is not up to date about the simulation status.

Describe the improvement you'd like When a change is applied on GAMA (load, play, pause, stop...) Gama send a websocket message to its clients about the new status of the simulation.

Describe alternatives you've considered Currently, in order to know the status of the experiment, my monitor reads the WS messages "command executed sucessfully" which works until there is only the monitor which control Gama Server. If an other WS client send a command, my first monitor will not know the status changes.

hqnghi88 commented 1 year ago

You mean broadcast to all clients instead of send to a specific client?

lesquoyb commented 1 year ago

I think the idea would be to be able to subscribe to gama events basically

AlexisDrogoul commented 1 year ago

We already have a mechanism in place to report status changes in the UI. It shouldn't be too complicated to extend it to GamaServer (i.e. every time a change occurs, the server receives the same messages than the instance of IStatusDisplayer). Is it what you had in mind ?

leonsi7 commented 1 year ago

Why not, it could be something like :

{type:"SimulationStatus", content:"simulation_lauched" or "simulation_stopped" or "simulation_paused"} 

for instance. These are the most important information for me, but this kind of message can contain more information to fit to any use case.

AlexisDrogoul commented 1 year ago

I have implemented all the internal mechanisms (and removed them from the GUI components) to allow the GamaWebSocketServer to listen to experiment state changes. This means that every time a change occurs, the server will receive the following message

    @Override
    public void updateStateTo(final IExperimentPlan experiment, final State state) {

    }

I let you now, @hqnghi88 @leonsi7 implement in this method the part about the message to be sent back to the clients when such an event occurs ? (state can be queried for its name : "STOPPED", "RUNNING", etc.)

hqnghi88 commented 1 year ago

@lesquoyb @leonsi7 can you share your current developmen, i would like to test the solution or some implementatiom but not sure we are on the same page ? It would better if there is an example (netherless js python ruby....). Thanks.

hqnghi88 commented 1 year ago

@leonsi7 If i use your monitor, connect to headless server, after click on Launch the simulation, my terminal is flooded with this message: { type: 'SimulationOutput', content: { message: '{}', color: null }, exp_id: '1058' } AND if i switch to use gamaGUI server, i got no SimulationOutput after this :

{ type: 'CommandExecutedSuccessfully', content: '', command: { type: 'play', exp_id: 'test' } }

Is this the issue you mentioned? or it was another use case?

leonsi7 commented 1 year ago

Yes actually you pointed out a problem that I have currently, I'm tring to solve it but I don't know if its my code/my gama server configuration which is wrong or a problem in gama server source code.I just commited a new version of my gama server connector that doesnt log the SimulationOutput messages (but the other one are conserved).

Le dim., oct. 29, 2023 à 19:45, HUYNH @.***> a écrit:

@leonsi7 If i use your monitor, connect to headless server, after click on Launch the simulation, my terminal is flooded with this message: { type: 'SimulationOutput', content: { message: '{}', color: null }, exp_id: '1058' } AND if i switch to use gamaGUI server, i got no SimulationOutput after this :

{ type: 'CommandExecutedSuccessfully', content: '', command: { type: 'play', exp_id: 'test' } }

Is this the issue you mentioned? or it was another use case?

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.***>

hqnghi88 commented 1 year ago

(i did not see your newest commit yet, but just a filter condition , right?) The flooded simulationOutput, because you write to console in GAML model, and for headless, it is redirect to SimulationOutput messages, if you dont want to get it, make console:false in the json sent to load model. So, can you redefine the issue? what are the chain-actions that lead to ? when open multiple time the localhost/monitor?

leonsi7 commented 1 year ago

My commit is online. I use the simulationOutput messages to get all the information at every cycle. The fact that at the beginning simulationoutput is {} is beacause there is no agent yet and gama is waiting for a new player. You can trigger a new player by going to localhost:8000/game and then add the new player on the monitor in the VR headset part. My problem is that with GamaGUI I don't receive any Simulation Output.

Le dimanche 29 octobre 2023 à 20:18:45 UTC+7, HUYNH Quang-Nghi ***@***.***> a écrit :  

(i did not see your newest commit yet, but just a filter condition , right?) The flooded simulationOutput, because you write to console in GAML model, and for headless, it is redirect to SimulationOutput messages, if you dont want to get it, make console:false in the json sent to load model. So, can you redefine the issue? what are the chain-actions that lead to ? when open multiple time the localhost/monitor?

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.***>

hqnghi88 commented 1 year ago

OK , so it was not about Simulation 'status. As i mentioned before, SimulationOutput is what you get in the console (by using write statement). So in headless, you have the special "console" which redirected and send to clients the messages through websocket, but in normal UI, it is there , the console for write statement, obviously there is no redirect and no msg sent on channels. @lesquoyb @AlexisDrogoul what are your opinions? we can re-structure the IConsoleDisplayer to have a ServerConsoleDisplayer which exists always in headless and GUI ?

leonsi7 commented 1 year ago

I think the best solutin is to add a new parameter in gama server GUI which allows us to decide if written messages are written both in console and wWSmessages or only in console. What do you think ? Le lundi 30 octobre 2023 à 09:36:45 UTC+7, HUYNH Quang-Nghi @.***> a écrit :

OK , so it was not about Simulation 'status. As i mentioned before, SimulationOutput is what you get in the console (by using write statement). So in headless, you have the special <> which redirected and send to clients the messages through websocket, but in normal UI, it is there , the console for write statement, obviously there is no redirect and no msg sent on channels. @lesquoyb @AlexisDrogoul what are your opinions? we can re-structure the IConsoleDisplayer to have a ServerConsoleDisplayer which exists always in headless and GUI ?

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.***>

AlexisDrogoul commented 12 months ago

I think it would be a good idea anyway to consider not only one IConsoleDisplayer, but (possibly) several IConsoleListener...

AlexisDrogoul commented 12 months ago

I have made a first implementation in https://github.com/gama-platform/gama/commit/96ba695b58e93011fd46e6a32636692fb6bea79f -- however, it's unclear for me how the console obtains the socket to which to send the message. @hqnghi88 @leonsi7 can you try ?

hqnghi88 commented 12 months ago

Thanks Alexis, but with the first try, it gives null exceptions (with latest commit of Leon on his repo):

java.lang.NullPointerException: Cannot invoke "msi.gama.common.interfaces.IConsoleListener.informConsole(String, msi.gama.kernel.experiment.ITopLevelAgent)" because "console" is null at msi.gama.common.CompositeConsoleListener.informConsole(CompositeConsoleListener.java:45) at msi.gaml.statements.WriteStatement.privateExecuteIn(WriteStatement.java:108) at msi.gaml.statements.AbstractStatement.executeOn(AbstractStatement.java:47) at msi.gama.runtime.ExecutionScope.execute(ExecutionScope.java:510) at msi.gama.runtime.IScope.execute(IScope.java:440) at msi.gama.runtime.IScope.execute(IScope.java:411) at msi.gaml.statements.AbstractStatementSequence.privateExecuteIn(AbstractStatementSequence.java:69) at msi.gaml.architecture.reflex.ReflexStatement.privateExecuteIn(ReflexStatement.java:90) at msi.gaml.statements.AbstractStatement.executeOn(AbstractStatement.java:47) at msi.gaml.statements.AbstractStatementSequence.executeOn(AbstractStatementSequence.java:59) at msi.gama.runtime.ExecutionScope.execute(ExecutionScope.java:510) at msi.gama.runtime.IScope.execute(IScope.java:440) at msi.gama.runtime.IScope.execute(IScope.java:411) at msi.gaml.architecture.reflex.ReflexArchitecture.executeReflexes(ReflexArchitecture.java:126) at msi.gaml.architecture.reflex.ReflexArchitecture.executeOn(ReflexArchitecture.java:112) at msi.gama.runtime.ExecutionScope.execute(ExecutionScope.java:510) at msi.gama.runtime.IScope.execute(IScope.java:440) at msi.gama.metamodel.agent.AbstractAgent.doStep(AbstractAgent.java:269) at msi.gama.metamodel.agent.MinimalAgent.doStep(MinimalAgent.java:261) at msi.gama.metamodel.agent.AbstractAgent.step(AbstractAgent.java:240) at msi.gama.runtime.ExecutionScope.step(ExecutionScope.java:547) at msi.gama.common.interfaces.IScopedStepable.step(IScopedStepable.java:27) at msi.gama.runtime.concurrent.SimulationRunner.lambda$0(SimulationRunner.java:111) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:833)

hqnghi88 commented 12 months ago

@AlexisDrogoul and you are right, there is a hidden link of connected socket and experiment. In gamaserver, the GamaServerExperimentController will bind this link to the scope when schedule agent

public void schedule(final ExperimentAgent agent) {
    scope = agent.getScope();
    scope.setData("socket", socket); <-------

while in normal GUI , in the DefaultExperimentController, this link is not there. I think it was in the beginning that we dont have the good hierachy of controller, experiment for both normal and server. But now we must think about the link : experiment know its socket (?? strange for normal gui??)

AlexisDrogoul commented 12 months ago

Actually, in GUI experiments, there will only be one experiment at a time. So only one socket active at a time. So I guess we could easily do the same : whenever a controller is created, it checks whether a server is running or not and, if yes, binds the socket/channel it is using to the scope of its experiment..

AlexisDrogoul commented 12 months ago

The NPE are my fault. I just need to figure out exactly when we can have access to the UI services in osgi (I try to initialise them too soon).

AlexisDrogoul commented 12 months ago

Regarding the "socket" in the scope, I find this construction/binding extremely fragile (esp. since there were no constants declared).

Wouldn't it be possible to have one class, for GamaServerExperimentConfiguration or something like this, that can be accessed from the scope (e.g. scope.getServerConfiguration() / scope.setServerConfiguraiton(...)) and give access to the socket, the exp_id, the various redirections, etc. And maybe we can even put more information in there.

What do you think ?

hqnghi88 commented 12 months ago

Yea i am totally agree that we avoid the setting data in scope without explicit declared classes. i try to propose the change today.

AlexisDrogoul commented 12 months ago

Trial implementation of GamaServerExperimentConfiguration has been done in https://github.com/gama-platform/gama/commit/d999bb8f6bc0d692a967f5dac0f980567b377be4

The current configuration is always reachable from anywhere via the scope. GamaWebSocketServer maintains a configuration with the current web socket and parameters for the GUI.

Two things :

hqnghi88 commented 12 months ago

Dear Alexis, Your first thought is what i am asking : the exp_id in headless is a generated unique string from specific counter . I am wonder if we can use the hash of experiment agent in place of? 2nd point, i did not get your idea, because it have many thing to change/merge?

AlexisDrogoul commented 12 months ago

@hqnghi88 ... I think that 0 would make more sense (as there is only one experiment) 😃 I just say that there are a number of things (like launchedExperiments) in the web socket server that are not interesting at all for the GUI version. So maybe restructuring this and having a GUI and a Headless socket server could be more relevant... I'll do it and propose an implementation :)

AlexisDrogoul commented 11 months ago

I think this one is ok now. Closing it (please reopen if something new appears).