The main program to run is server.py. It will listen for websocket connections on port 8001
and should be reachable at the URL ws://localhost:8001/.
It can load dynamically load the recipe lists from a Google spreadsheet. To use this feature it
is required to have a jSON file with "service account" credentials. Supply it on the command
line with the --creds option, e.g.:
./server.py --creds khc-test-452819-7fb17e9939af.jsonIn addition to or in place of the spreadsheet, it is possible to serve static json files from a
directory. Supply the path to the directory with the --datadir option. This will serve the
contents of the pump-status.json file as the response to the pump status request and will use the
recipes.json file as the response to the recipes request. The files are served as-is, without
checking that their contents match the documented format. They do need to be valid jSON.
If DBus isn't available, i.e. on Windows, then jSON files from the data directory will be used
in place of the information normally gathered via DBus, e.g. for network-status.
Example data has been included in example-data for requests that need DBus.
There are a number of configuration settings available. These are placed in a jSON
file, the default location of which is /data/config.json. An alternate location can
be specified on the command line.
keydir: Path to directory containing various keys used by the software.github_id: The Github client ID used for the Github App which has software download access.github_key: Name of private key file for Github App.github_install: Github install ID.sheet_key: File containing the recipe sheets' Service Account keyrecipes_id: The spreadsheet key for the recipe spreadsheet.admixture_id: The spreadsheet key for the master admixture table spreadsheet.cert: The file (in keydir) to use as the X509 Client Certificate and identify file.cert_key: The password to unlock the cert key, if encrypted.service_url: The URL for the cloud log upload service.service_poll: The polling interval for the upload service in seconds.
This server downloads packages from GitHub. It needs a GitHub "App" to be allowed access to the repositories. An account which has access to the repositories and has the permission to create Apps in the organization that owns the repositories is necessary to perform these actions.
Create a Github App by following the instructions for Registering a GitHubApp
The App name does not matter. There is no Callback URL. Do not check "Request user authorization" or "Enable Device Flow". Not enabling these means the app cannot take actions on behalf of a user, which is more secure. Disable the Webhook. The only permission necessary is read-only access to Repository Contents.
The Client ID from the App's "About" page should be used as the github_id configuration
setting. Generate a private key and specify the file it's stored in as the github_key
setting. It should be placed into keydir, which is /data/keys by default.
See Installing your own Github App. In step 9, select the appropriate repositories to grant access to.
Requests are sent as jSON format messages. Responses are also jSON format. Each request has a
property request with a string value that determines the request type. The response for the
server will have a response property with a matching value.
Example requests:
{ "request": "status" }
{ "request": "dispense", "recipe": "fry-sauce" }Currently known requests:
pingrecipesdispenseprimepump-statusnetwork-statuscell-statuswifi-scanwifi-joinfw-info
The dispense request has an argument, recipes.
For wifi-join, there are arguments ssid and password, with the latter optional for unsecured networks.
Example responses:
{ "response": "dispense", "error": "Unknown recipe" }
{ "response": "pump-status", "pumps": [ … ] }
{ "response": "ping", "time": 1742323740.2018378 }If the response is some sort of error, there will be a property named error with a string
value identifying the error.
The server may broadcast status updates that are not in response to a specific request. An example is updates to the dispense operation:
{"status": "dispense", "id": 2, "percent": 38, "finished": false}Another example is the status of the cup detection:
{"status": "cup-detect", "state": "empty-cup"}There are some debug commands. These are of the form:
{"debug": "command-name", … }Unlike requests, the debug commands produce no response.
Current debug commands:
cup-detect
The cup detect command can set the current cup status. This can be done to simulate removing or placing a cup. Note that the server support multiple web sockets open at once and that the cup state is global. I.e., the debug command to set the cup state can be sent from another socket than the one the app is using.