spaceapi-server/README.md

3.8 KiB

SpaceAPI Server

pipeline status coverage report

A lightweight server for SpaceAPI endpoints. Includes support for pluggable templating, so dynamic content, like sensor values, can be added.

Dependencies

License

MIT License

Usage

python -m spaceapi_server config.json

Configuration

{
    "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, e.g. `.plugins.sqlite.database`
    }
}

Serve a Static SpaceAPI Endpoint

Have a look at SpaceAPI: Getting Started. If you only want to serve static content, your template.json may consist of regular JSON data, which is served almost-as-is (once parsed and re-serialized).

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.

  1. Create a plugin to fetch the data. Let's name it mybackend.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('mybackend')
        # 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.

  2. 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.

  3. Configure the server:

    # ...
    "template": "template.json",
    "plugins_dir": "plugins",
    "plugins": {
        "mybackend": {
            "filename", "/var/space_state"
        }
    }
    # ...
    
  4. Start the server and query it.