Developer's guide to event callbacks in seestar_alp - smart-underworld/seestar_alp GitHub Wiki

Developer's guide to event callbacks in seestar_alp

This write-up is intended for developers, to describe how to make use of the newly added functionality in seestar_alp, that allows for actions to be taken in a reaction to events, rather than a timed schedule.

An event callback is a class, based off of the abstract class EventCallback, defined in device/event_callbacks.py

Child classes implementing this interface must implement 3 things:

  1. Initialization
  2. Define what events to take action on
  3. Define what to do when these events occur.

The intent is to initialize the callback class from the current device state at start time, and all future action should be based off of events, or inspecting the current state of the device object. All efforts should be made to avoid costly calls back out to the scope.

This is meant to be a passive callback system that reacts to the events being reported by the scope. Think of it as a "push" system vs a "pull", or "poll" system.

When are callback classes initialized?

Callbacks are registered with the system, and initialized in seestar_device.py in a method named event_callbacks_init

This gets called from start_watch_thread at device (re)connnect time.

After that point, the callback classes should wait for their eventFired call to be executed.

We have 2 general categories of callbacks at this time:

  • Specific code-based subclasses to do specific things

    These callbacks have access to the internals of the device context, so can make changes to ALP state.

  • User supplied "script" based hooks, that get executed by the system

    These scripts get passed some context, like event details, and what device it occurred on, but cannot make changes to the internals of ALP state. These hooks are defined in a top-level directory from seestar_alp, named user_hooks

    More details are in the callback class types section below.

How do callbacks get executed?

In seestar_device.py, we monitor the open connection to the scope for messages it sends to ALP, in the receive_message_thread_fn method. In that method, we handle both jsonrpc - and Event message types.

Events supported

  • Any event sent from the SeeStar Eg:
{'Event': 'PiStatus', 'Timestamp': '5804.822674860', 'temp': 43.099998}
  • Event wildcard special-case: event_*

Callback class types

At the time of this writing, there are 2 active callback types, and 1 in development:

This is intended to expand over time, as we identify additional use cases. Several have been proposed, and should be worked on as time allows. The intent of this guide is to make this infrastructure something that any developer could add to.

BatteryWatch:

A callback class to watch battery levels, so we can do a safe shutdown if the battery gets too low

This callback class monitors the state of the battery, and will safely shutdown the scope, if it goes below a certain level. This has the advantage of running through the process to properly park the scope, if imaging below-horizon targets

SensorTempWatch (IN DEVELOPMENT)

A callback class to watch the sensor temp, and re-take darks if if changes more than a set value.

When merged, this event will optionally

  1. pause imaging
  2. re-take darks
  3. resume imaging

UserScriptEvent

As mentioned above, UserScriptEvents are initialized from the user_hooks subdir. The system will process files with a .conf or a .hcon extension. All others (like .example) are ignored.

The format for these hooks are in HOCON format - a superset of JSON

An example hook might look like the following:

events: ["PiStatus"]
execute: "./local/run"

When initialized, this hook will be executed when the PiStatus event is encountered.

It will execute the ./local/run script, with the following environment variables supplied to it:

DEVNUM=<device number>
DEVICENAME=<device name>
NAME=<event name>
EVENT_DATA=<json representation of event>
⚠️ **GitHub.com Fallback** ⚠️