Overview
After installing pyobs, you have the new command pyobs, which creates and
starts pyobs modules from the command line based on a configuration file, written
in YAML.
A simple configuration file (standalone.yaml) might look like this:
class: pyobs.modules.test.StandAlone
message: Hello world
interval: 10
Every block always defines a class together with its parameters. When pyobs loads this file, it
instantiates the given class and passes the remaining keys as keyword arguments to its constructor.
In this example, the module is of type StandAlone, which logs a message
repeatedly at a given interval. Its implementation looks like this:
import asyncio
import logging
from typing import Any
from pyobs.modules import Module
log = logging.getLogger(__name__)
class StandAlone(Module):
"""Example module that only logs the given message forever in the given interval."""
def __init__(self, message: str = "Hello world", interval: int = 10, **kwargs: Any):
Module.__init__(self, **kwargs)
self._message = message
self._interval = interval
self.add_background_task(self._message_func)
async def _message_func(self) -> None:
while True:
log.info(self._message)
await asyncio.sleep(self._interval)
The constructor calls Module.__init__ (forwarding **kwargs so
that comm, vfs, and other shared parameters are handled automatically) and registers a background
task using add_background_task(). Background tasks are async coroutines that
run concurrently while the module is open. The task here loops indefinitely, logging the message and
then sleeping.
If the configuration file is saved as standalone.yaml, start it with:
pyobs standalone.yaml
The program shuts down gracefully when it receives an interrupt (Ctrl+c).
For a deeper look at how Object and Module work, see
Objects (pyobs.object) and Modules (pyobs.modules).
Modules
A Module defines a single process in pyobs, as defined in Module. Modules can work
completely independently of each other, but usually they communicate with and call methods on other modules.
The functionality that a module exports for remote calling is defined by its interfaces — classes derived from
Interface. See Interfaces (pyobs.interfaces) for the full list.
Location of observatory
Many modules need to know where the telescope is located and what the local time is. This is configured at the top level of any module configuration file:
timezone: Africa/Johannesburg
location:
longitude: 20.810808
latitude: -32.375823
elevation: 1798.
From these values, pyobs automatically builds an Observer object, which is available
inside any module via the observer property. The location itself is accessible
via location, and the timezone via timezone:
async def open(self) -> None:
await Module.open(self)
print(self.observer.location)
Communication between modules
For a module to communicate with others, it needs a Comm object, defined in the
configuration like this:
comm:
class: pyobs.comm.xmpp.XmppComm
jid: some_module@my.domain.com
Once configured, other modules on the network can be reached via a proxy:
telescope = await self.proxy("telescope", ITelescope)
await telescope.move_radec(ra=83.8, dec=-5.4)
More details about this can be found in the Communication between modules (pyobs.comm) section.
Virtual File System
In a pyobs system, modules are typically distributed across several computers. To make file exchange straightforward, pyobs has a built-in virtual file system (VFS) that maps logical file paths to real locations transparently.
A typical VFS setup in a module configuration file looks like this:
vfs:
class: pyobs.vfs.VirtualFileSystem
roots:
cache:
class: pyobs.vfs.LocalFile
root: /path/to/data
This maps every filename beginning with cache to the path /path/to/data on the local file system.
Opening /cache/test.txt for writing via vfs.open_file('/cache/test.txt', 'w') actually writes to
/path/to/data/test.txt.
The same path on a different machine can be mapped over SSH:
vfs:
class: pyobs.vfs.VirtualFileSystem
roots:
cache:
class: pyobs.vfs.SSHFile
hostname: othercomputer
username: xxx
password: xxx
root: /path/to/data
Both machines use the same vfs.open_file('/cache/test.txt', ...) call — the VFS handles the transport
transparently. See Virtual File System (pyobs.vfs) for more information.
Events
In addition to calling each other’s methods, pyobs modules can send and receive events asynchronously. See Events (pyobs.events) for details.