Please add ability to change from pause to finish
Moderators: Site Moderators, FAHC Science Team
-
- Site Moderator
- Posts: 1476
- Joined: Sat Dec 08, 2007 1:33 am
- Location: San Francisco, CA
- Contact:
Re: Please add ability to change from pause to finish
Some informal documentation is in client discussions, particularly
https://github.com/FoldingAtHome/fah-cl ... ssions/215
Other than that, there is the web control source code, and watching the JavaScript console in your browser while using web control.
https://github.com/FoldingAtHome/fah-cl ... ssions/215
Other than that, there is the web control source code, and watching the JavaScript console in your browser while using web control.
-
- Site Moderator
- Posts: 1476
- Joined: Sat Dec 08, 2007 1:33 am
- Location: San Francisco, CA
- Contact:
Re: Please add ability to change from pause to finish
If you can read python, there is my sloppy code
https://github.com/kbernhagen/lufah
https://github.com/kbernhagen/lufah
Re: Please add ability to change from pause to finish
Completely undocumented but not at all secret. All of the API is handled by a single 190 line C++ file which is open source in src/fah/client/Remote.cpp.TheMikeyDK wrote: ↑Fri May 02, 2025 6:35 pmHow undocumented is it? Is it possible to somehow find some information about that?
The websocket communicates using JSON. Here is a simple Python function that lets you send commands via the websocket:
Code: Select all
import websocket, json
def sendcmd(cmd, arg):
ws = websocket.create_connection('ws://localhost:7396/api/websocket')
ws.send(json.dumps({'cmd': cmd, cmd: arg}))
ws.close()
Here are a few examples of JSON you could send. To pause all units:
Code: Select all
{
"cmd": "state",
"state": "pause"
}
Code: Select all
{
"cmd": "config",
"config": {
"groups": {
"": {
"cpus": 6,
"beta": true
},
"mygroup": {
"on_battery": false,
"beta": false
}
}
}
}
Last edited by arisu on Sat May 03, 2025 4:06 am, edited 1 time in total.
Re: Please add ability to change from pause to finish
OP, the solution to your problem is to send a config command instead a state command. Here's a super simple Python script that will change the state from pause to finish atomically (without first going through fold). The script takes one optional argument which is the group name. If no argument is given, it will apply to the default group:
Code: Select all
#!/usr/bin/python3
import sys, json, websocket
HOST = 'localhost'
PORT = '7396'
try:
GROUP = sys.argv[1]
except KeyError:
GROUP = ''
ws = websocket.create_connection(f'ws://{HOST}:{PORT}/api/websocket')
state = json.loads(ws.recv())
groups = dict.fromkeys(state['groups'], {})
if state['info']['version'] != '8.4.9':
sys.exit('unsupported client version')
if GROUP not in groups:
sys.exit(f'group {GROUP} does not exist')
groups.update({GROUP: {'finish': True, 'paused': False}})
ws.send(json.dumps({'cmd': 'config', 'config': {'groups': groups}}))
ws.close()
Last edited by arisu on Sun May 04, 2025 6:15 am, edited 3 times in total.
-
- Site Moderator
- Posts: 1476
- Joined: Sat Dec 08, 2007 1:33 am
- Location: San Francisco, CA
- Contact:
Re: Please add ability to change from pause to finish
The dump command requires the uuid of the unit.
The config command must contain at least an empty dict for every group.
Not including a group will cause it to be deleted.
Adding an unknown group will create it.
I believe it is this way for the convenience of coding web control.
The config command must contain at least an empty dict for every group.
Not including a group will cause it to be deleted.
Adding an unknown group will create it.
I believe it is this way for the convenience of coding web control.
-
- Site Moderator
- Posts: 1476
- Joined: Sat Dec 08, 2007 1:33 am
- Location: San Francisco, CA
- Contact:
Re: Please add ability to change from pause to finish
I’m pretty sure the client doesn’t support going from pause straight to running with finish.
-
- Site Moderator
- Posts: 1476
- Joined: Sat Dec 08, 2007 1:33 am
- Location: San Francisco, CA
- Contact:
Re: Please add ability to change from pause to finish
You absolutely should not manipulate the pause and finish flags on a group. They are internal state flags, not valid configuration items.
Even if it works there could be bad side effects and it may break in the future.
You should use the pause, fold, and finish commands.
Even if it works there could be bad side effects and it may break in the future.
You should use the pause, fold, and finish commands.
Re: Please add ability to change from pause to finish
It does support going straight to pause to finish but only if you adjust the state. I checked the code and directly adjusting the pause and finish flags is exactly what using the state command does (see Config::setState() in src/fah/client/Config.cpp). There are no side-effects.
Good point that it might break in the future although it looks unlikely based on the code. But I didn't even think about that. I'll edit my script to add a check for the current version as a safety guardrail.
Good point that it might break in the future although it looks unlikely based on the code. But I didn't even think about that. I'll edit my script to add a check for the current version as a safety guardrail.
-
- Site Moderator
- Posts: 1476
- Joined: Sat Dec 08, 2007 1:33 am
- Location: San Francisco, CA
- Contact:
Re: Please add ability to change from pause to finish
Interesting. I don’t expect it to be part of the official api. Maybe the semantics of the finish command will be changed to do this.
Your dump command would need to get the uuid for the unit at the adjusted index.
Your dump command would need to get the uuid for the unit at the adjusted index.
Re: Please add ability to change from pause to finish
Since those were just examples it was easier for me to just remove that dump example.
The state command runs app.setState(state) which will run setPaused(false) if state == "fold", setPaused(true) if state == "pause", or insertBoolean("finish", true) if state == "finish". But the setPaused() function runs insertBoolean("finish", false) no matter what value it is passed, which is why it's currently not directly possible to change the pause state without simultaneously unsetting the finish flag. I think this is done to clear the finish flag so people aren't confused by clicking "fold" (which just runs setPaused(false)) and seeing the state change to finish. It just aligns the client's behavior with the mental model that users have of its UI, ie users think fold means "start folding" when OP wants it to mean "set paused to false, but don't touch the finish flag".
The whole issue stems from any call to setPaused() unsetting the finish flag.
The script I posted just bypasses setPaused() completely and directly changes the state. There are no sanity checks done and you could probably send {"finish": "foo"} which would change it to an invalid state. What happens then depends on how getBoolean() is defined in cbang which I haven't checked.
The state command runs app.setState(state) which will run setPaused(false) if state == "fold", setPaused(true) if state == "pause", or insertBoolean("finish", true) if state == "finish". But the setPaused() function runs insertBoolean("finish", false) no matter what value it is passed, which is why it's currently not directly possible to change the pause state without simultaneously unsetting the finish flag. I think this is done to clear the finish flag so people aren't confused by clicking "fold" (which just runs setPaused(false)) and seeing the state change to finish. It just aligns the client's behavior with the mental model that users have of its UI, ie users think fold means "start folding" when OP wants it to mean "set paused to false, but don't touch the finish flag".
The whole issue stems from any call to setPaused() unsetting the finish flag.
The script I posted just bypasses setPaused() completely and directly changes the state. There are no sanity checks done and you could probably send {"finish": "foo"} which would change it to an invalid state. What happens then depends on how getBoolean() is defined in cbang which I haven't checked.
-
- Site Moderator
- Posts: 1476
- Joined: Sat Dec 08, 2007 1:33 am
- Location: San Francisco, CA
- Contact:
Re: Please add ability to change from pause to finish
I’m sure the client needs more rigorous checks on input.
Do you think I should change lufah to support pause to finish? Maybe with a force flag?
Do you think I should change lufah to support pause to finish? Maybe with a force flag?
-
- Site Moderator
- Posts: 1476
- Joined: Sat Dec 08, 2007 1:33 am
- Location: San Francisco, CA
- Contact:
Re: Please add ability to change from pause to finish
What happens if you set paused false, finish true on a group that is paused and has no units? Is a new WU started? That would seem undesirable.
Re: Please add ability to change from pause to finish
If paused is set to false, then it will try to download a new unit no matter what the value of finish is. And you can't override that using just the state command because going from paused to fold will, annoyingly, clear the finish flag.
I think it would be fine for lufah to have that feature although first it should be tested with a client in several states. For example, everything I described and tested happens when a unit is in the UNIT_RUN state (which can be paused, folding, finished or whatever, it just means the unit is ready). But I have no idea what happens if you directly change the config to unpause a unit that is in some different state like UNIT_DUMP or UNIT_CORE. Although you could just check that it's in UNIT_RUN before performing the action.
Btw another possible way to do this using more "standard" parts of the API (only using API features that the web client also uses) would be taking the resources away from the units, i.e. setting CPUs to 0 and removing any GPU, then setting the state from paused to fold the normal way, then set the state to finish, then give the resources back. I haven't tested it but that might also move the units from pause to finish without putting all of them in a runnable state at any point in time (which would cause a finished unit to begin its download).
Honestly none of this would be an issue if "resource groups" were more ergonomic (I never recommend random people use them because the FAQ even warns that it is for experts only), or if you could change the state of individual units. The dev is insistent that there's no need for that ability because you can "just use resource groups", but resource groups come with a whole can of caveats that break the mental model people have of the program.
I think it would be fine for lufah to have that feature although first it should be tested with a client in several states. For example, everything I described and tested happens when a unit is in the UNIT_RUN state (which can be paused, folding, finished or whatever, it just means the unit is ready). But I have no idea what happens if you directly change the config to unpause a unit that is in some different state like UNIT_DUMP or UNIT_CORE. Although you could just check that it's in UNIT_RUN before performing the action.
Btw another possible way to do this using more "standard" parts of the API (only using API features that the web client also uses) would be taking the resources away from the units, i.e. setting CPUs to 0 and removing any GPU, then setting the state from paused to fold the normal way, then set the state to finish, then give the resources back. I haven't tested it but that might also move the units from pause to finish without putting all of them in a runnable state at any point in time (which would cause a finished unit to begin its download).
Honestly none of this would be an issue if "resource groups" were more ergonomic (I never recommend random people use them because the FAQ even warns that it is for experts only), or if you could change the state of individual units. The dev is insistent that there's no need for that ability because you can "just use resource groups", but resource groups come with a whole can of caveats that break the mental model people have of the program.
-
- Site Moderator
- Posts: 1476
- Joined: Sat Dec 08, 2007 1:33 am
- Location: San Francisco, CA
- Contact:
Re: Please add ability to change from pause to finish
BTW, your example deletes all groups except the targeted one. You need an empty dict for every other group in the config group command.