examples | ||
package | ||
spaceapi_server | ||
.gitignore | ||
.gitlab-ci.yml | ||
CHANGELOG.md | ||
LICENSE | ||
README.md | ||
requirements.txt | ||
setup.cfg | ||
setup.py |
SpaceAPI Server
A lightweight server for SpaceAPI endpoints. Includes support for pluggable templating, so dynamic content, like sensor values, can be added.
Dependencies
License
Introduction
This project is an attempt to implement a lightweight, yet versatile SpaceAPI endpoint server. In its simplest configuration, it just serves a plain, static, boring JSON document.
In order to provide dynamic content (e.g. whether your space is currently open), you can replace parts of the JSON document (anything except object keys) with Jinja2 templates, from which you can invoke custom plugins, which look up and return your dynamic content.
Usage
0. Download
Head over to the Releases, download and install the package that suits your needs. Alternatively, clone the repo and get started.
The remainder of this document will assume that you installed the server as an OS distribution package.
1. Overview
The configuration of this server consists of three parts:
- The main configuration file, usually located at
/etc/spaceapi-server/config.json
. This file controls all the internal settings of the server. - The response template file, located at
/etc/spaceapi-server/template.json
. This file defines the content served by your sever. - The plugins directory, located at
/etc/spaceapi-server/plugins/
. Here you can put your plugins for rendering dynamic content.
2. Configure the Server
Open the file /etc/spaceapi-server/config.json
.
The following options are currently available:
{
"address": "::1", # The address to listen on.
"port": 8000, # The TCP port to listen on.
"server": "wsgiref", # The Bottle backend server to use.
"template": "template.json", # Path to the SpaceAPI response template file.
"plugins_dir": "plugins", # Path to the directory containing your plugins.
"plugins": {
# Plugin-specific configuration should go in here, separated by plugin
"my_plugin": {
"my_option": "Hello, World!",
"my_other_option: [ 42, 1337 ]
}
}
}
3. Configure a Static SpaceAPI Endpoint
Open the file /etc/spaceapi-server/template.json
. By default it
contains a minimal example response. If you only want to serve static
content, your template.json
should simply contain the SpaceAPI JSON
response you want to serve.
The content is served "almost-as-is" (once parsed and re-serialized).
To learn about how a SpaceAPI response should look like, have a look at SpaceAPI: Getting Started.
4. Add Dynamic Content
This example guides you through adding a dynamic state
property to
your SpaceAPI endpoint. We'll use the following (rather simple, and
probably not too useful) data source: Check a certain file, and mark
the space as open depending on its existence.
-
Create a plugin to fetch the data. Let's name it
filestate.py
and put in in our plugins directory:import os from spaceapi_server import config, plugins @plugins.template_function def space_state(): # Get the plugin config dict conf = config.get_plugin_config(filestate') # Get the filename filename = conf.get('filename', '/var/space_state') try: # Get the file's properties stat = os.stat(filename) except FileNotFoundError: # File doesn't exist, aka. space is closed return { 'open': False } # File exists, aka. space is open. Also report the mtime as "last changed" timestamp return { 'open': True, 'lastchange': int(stat.st_mtime) }
The
@template_function
decorator registers the function as a callable in Jinja's globals. There's also@template_filter
, which registers a Jinja2 filter, and@template_test
, which registers a test. For more information on the Jinja2 templating engine, see Jinja2. -
Call the template function in your template:
{ # ... "state": "{{ space_state() }}" # ... }
Although the value for the
state
key is a string containing the Jinja2 template, the return value of your template function is a complex data type, which will be inserted into the result as such. Please be aware that only the first token of a templated string is used in the result. This limitation is caused by the way Jinja2 is (ab-) used. -
Configure the server:
# ... "template": "template.json", "plugins_dir": "plugins", "plugins": { "filestate": { "filename": "/var/space_state" } } # ...
5. Start the Server
Start the server with e.g.:
systemctl start spaceapi-server.service
To reload the configuration, template and plugins, send a SIGHUP,
e.g. through systemctl reload
.
If you need to run the server ad-hoc, you can start it with:
python3 -m spaceapi_server /path/to/config.json
6. Test the Server
curl http://localhost:8000/
You should be greeted with the SpaceAPI endpoint response.