Closed felix920506 closed 7 months ago
Indeed. The API is still in flux. Once we are closer to a public release of the v8 client it will make more sense to release documentation on the API.
In the meantime here is a rough outline. All of this is subject to change.
The web frontend (fah-web-client-bastet) connects to the backend (fah-client-bastet) via at Websocket at /api/websocket
. This is the only communication channel between the front and back ends.
The frontend can send the following commands to the backend by sending a JSON object over the Websocket. This object must contain a cmd
variable which can be one of the following:
unit
)time
and state
. state
can be pause
, fold
or finish
)config
)token
and string
)unit
and frame
)enable
and offset
)Upon Websocket connection the backend will send an JSON object. It will then send updates to this object. The object is the entire available internal state of the backend client. You can see what this looks like by monitoring the Websocket connection in the browser via the browser's developer console.
Object updates are applied by with the Javascript function update_obj()
in machine.js
. Updates are JSON arrays. The array is format like this:
[<path 0>, <path 1>, . . ., <path n>, <value>]
Where path
is either a key (string) of an object or an integer representing an index in to an array.
Two special index values -1
and -2
must be handled separately. -1
means append the value to the end of the array. -2
means concatenate the value, which must be an array, to the end of the array.
If an array or object does not yet exist it its automatically added. The value
is inserted at the specified location possibly replacing the previous value. The special value null
does not insert a null
but removes any value at that location. Otherwise the value could be any valid JSON.
You may notice that update_obj()
also cleans the keys by replacing -
with _
. This is only necessary for backwards compatibility with older clients.
Here is an example client state:
{
"info": {
"version": "8.2.4",
"os": "linux",
"os_version": 6,
"cpu": "amd64",
"cpu_brand": "AMD Ryzen 9 3900X 12-Core Processor",
"cpus": 24,
"gpus": {
"gpu:45:00:00": {
"vendor": 4318,
"type": "nvidia",
"description": "NVIDIA GeForce RTX 3060",
"uuid": "2d31c03a-3d11-88b3-010b-4fc7b7a20a75",
"opencl": {
"platform": 0,
"device": 0,
"compute": "3.0",
"driver": "525.89"
},
"cuda": {
"platform": 0,
"device": 0,
"compute": "8.6",
"driver": "12.0"
},
"device": 9476,
"supported": true
}
},
"mach_name": "luma",
"hostname": "luma",
"id": "tWhTIJhhbYOQW6lPeLYTxGrJKk-NohQtejdwb2eAw9k",
"account": "15_5Co2Ml3AXv_P6-Ux1PPBxxIDOLj6yrmO_icWmuoM"
},
"config": {
"user": "jcoffland",
"team": 1234,
"passkey": "<redacted>",
"on_idle": false,
"paused": true,
"finish": false,
"beta": false,
"cause": "any",
"key": 0,
"cpus": 22,
"gpus": {
"gpu:45:00:00": {
"enabled": true,
"beta": false,
"key": 0
}
},
"priority": "idle"
},
"units": [
{
"number": 91,
"cpus": 21,
"gpus": [],
"state": "RUN",
"paused": false,
"id": "qIFTSOkedztyVJiKoWqhn1n9baFPi4ntEDFAhfBmsXY",
"progress": 0.014,
"assignment": {
"time": "2023-11-28T13:15:07Z",
"ws": "vav20.fah.temple.edu",
"port": 443,
"project": 12413,
"deadline": 432000,
"timeout": 302400,
"credit": 150542,
"cpus": 21,
"min_cpus": 1,
"max_cpus": 64,
"core": {
"type": "0xa8",
"url": "https://cores.foldingathome.org/fahcore-a8-lin-64bit-avx2_256-0.0.12.tar.bz2",
"sha256": "5d81e2df84fb0857e9804ce4c263e412d632b0e7c65bada542b608f1f8a2f204"
}
},
"wu": {
"time": "2023-11-28T13:15:07Z",
"cs": [
"129.32.209.205",
"129.32.209.200",
"129.32.209.202",
"129.32.209.206",
"highland4.seas.upenn.edu",
"highland3.seas.upenn.edu",
"vav24.fah.temple.edu",
"129.32.209.204",
"129.32.209.201",
"fahwork01.psivant.com",
"ds03.scs.illinois.edu",
"ds01.scs.illinois.edu"
],
"server": 2166411723,
"run": 104,
"clone": 3,
"gen": 21,
"sha256": "n69sF1jr32fDyedhv4uho0J3v0jwtcLwcni0hja3NGw="
},
"eta": "22 hours 43 mins",
"ppd": 309186,
"frames": 2,
"run_time": 1182,
"delay": 0,
"wait": "2023-11-28T13:38:46Z",
"pause_reason": "Paused by user"
}
]
}
Here is an example update:
["config", "paused", false]
There is also support for legacy v8.1 commands cmd
of pause
, unpause
, finish
.
time
must be a UTC string, like 2023-11-28T13:15:07Z
The client may occasionally send the JSON fragment "ping"
This is for the benefit of Web Control, which cannot easily see a protocol-level ping.
Argument config
is a sparse dictionary containing the keys/values to change.
Do not directly alter paused
or finish
; use the state
command.
If a machine is associated with an account, you should probably refrain from altering account settings, such as user
, team
, passkey
, cause
.
Those legacy commands are deprecated.
FYI, the time format is called ISO 8601.
To accommodate the "ping"
message the frontend just ignores anything after the first message that is not an array.
Yes, legacy deprecated. But used by the current beta v8.1.
Example snapshot from v8.3.2:
{
"info": {
"version": "8.3.2",
"os": "macosx",
"os_version": "14.3",
"cpu": "arm64",
"cpu_brand": "Apple M1",
"cpus": 8,
"gpus": {},
"mach_name": "Panda",
"hostname": "Panda",
"id": "<redacted>",
"account": "<redacted>"
},
"config": {
"user": "calxalot",
"team": 1971,
"passkey": "<redacted>",
"cause": "alzheimers"
},
"groups": {
"": {
"config": {
"on_idle": false,
"on_battery": false,
"keep_awake": true,
"paused": false,
"finish": true,
"beta": false,
"key": 0,
"cpus": 4,
"gpus": {}
},
"wait": "2024-01-26T18:42:14Z"
},
"alt": {
"config": {
"on_idle": false,
"on_battery": false,
"keep_awake": false,
"paused": true,
"finish": false,
"beta": false,
"key": 0,
"cpus": 0,
"gpus": {}
},
"wait": "2024-01-26T23:40:02Z"
}
},
"units": [
{
"group": "",
"number": 1293,
"cpus": 4,
"gpus": [],
"state": "RUN",
"paused": false,
"id": "v3iZj649Pz9UkLmko22Xn8XCUoVqbrff9nXq87Hh-TU",
"progress": 0.932,
"assignment": {
"time": "2024-01-26T18:42:10Z",
"ws": "vav20.fah.temple.edu",
"port": 443,
"project": 12416,
"deadline": 432000,
"timeout": 302400,
"credit": 9260,
"cpus": 4,
"min_cpus": 1,
"max_cpus": 64,
"core": {
"type": "0xa8",
"url": "https://cores.foldingathome.org/fahcore-a8-osx-64bit-aarch64-0.0.12.tar.bz2",
"sha256": "045ecffcbc2a3e04edc6d29ab6d56f7dab8fb356042e263dddd26f02a496f0b6"
}
},
"wu": {
"time": "2024-01-26T18:42:10Z",
"cs": [
"129.32.209.202",
"129.32.209.205",
"129.32.209.200",
"129.32.209.206",
"fahwork01.psivant.com",
"highland4.seas.upenn.edu",
"vav24.fah.temple.edu",
"highland3.seas.upenn.edu",
"ds03.scs.illinois.edu",
"ds01.scs.illinois.edu",
"129.32.209.204",
"129.32.209.201"
],
"server": 2166411723,
"run": 39,
"clone": 0,
"gen": 110,
"sha256": "LV0F7UWRP371NwzdanWWcjOwldm/LneeZESGOOs/Ax4="
},
"eta": "22 mins 39 secs",
"ppd": 159789,
"frames": 94
}
]
}
For v8.3.2 state commands directed at a group, there must be a group
argument.
Example:
{"state": "finish", "cmd": "state", "group": "alt", "time": "2024-01-27T00:05:22.722479Z"}
Without group
, the state command applies to all groups.
Note that the default group is ""
(the empty string).
user
, team
, passkey
and cause
can be set on the client and affect all groups.
Example:
{"cmd": "config", "config": {"cause": "any"}, "time": "2024-01-27T00:14:47.783101Z"}
Changes to a group config must include all groups. A missing group will be deleted. An extra group would be created. Example:
{"cmd": "config", "config": {"groups": {"": {}, "alt": {"on_idle": false}}}, "time": "2024-01-27T00:17:48.516350Z"}
Currently, a simple way to create a group is to send a state command:
{"state": "pause", "cmd": "state", "group": "create me"}
Groups cannot be renamed.
Currently there doesn't appear to be any documentation available for the client API apart from the code itself. It would be much easier for 3rd party programs to be able to control the FAH client if such documentation was made available.