A python port for the TracimDaemonSDK, an SDK for the TracimDaemon project
For a quickstart see TracimDaemon Quickstart
Get the package
pip install tracim_daemon_sdk
Create a new TracimDaemon client
from tracim_daemon_sdk import TracimDaemonClient
if __name__ == "__main__":
client = TracimDaemonClient(
master_socket_path='/home/user/.config/TracimDaemon/master.sock',
client_socket_path='/home/user/.config/MiniClient/socket.sock',
)
Create and listen to the client socket
from tracim_daemon_sdk import TracimDaemonClient
if __name__ == "__main__":
client = TracimDaemonClient(
master_socket_path='/home/user/.config/TracimDaemon/master.sock',
client_socket_path='/home/user/.config/MyApp/tracim_daemon.sock',
)
client.create_client_socket()
From now on it is recommended to wrap the rest of the code in a try/finally block to ensure the socket is closed properly
from tracim_daemon_sdk import TracimDaemonClient
if __name__ == "__main__":
client = TracimDaemonClient(
master_socket_path='/home/user/.config/TracimDaemon/master.sock',
client_socket_path='/home/user/.config/MyApp/tracim_daemon.sock',
)
client.create_client_socket()
try:
pass
finally:
client.close()
Set up various handlers then register the client to the daemon and start listening to events
from tracim_daemon_sdk import TracimDaemonClient
from tracim_daemon_sdk.event import DAEMON_TRACIM_EVENT
from tracim_daemon_sdk.daemon_event import DaemonEvent
from tracim_daemon_sdk.data import TLMEvent
from tracim_daemon_sdk.helper import decode_json
def default_event_handler(c: TracimDaemonClient, e: DaemonEvent):
tlm: TLMEvent = decode_json(e.data)
print(tlm.event_type)
if __name__ == "__main__":
client = TracimDaemonClient(
master_socket_path='/home/user/.config/TracimDaemon/master.sock',
client_socket_path='/home/user/.config/MyApp/tracim_daemon.sock',
)
client.create_client_socket()
try:
client.event_handlers[DAEMON_TRACIM_EVENT] = default_event_handler
client.register_to_master()
client.listen_to_events()
finally:
client.close()
The "minimal" client code is as above.
A handler follows the EventHandler
definition (see below).
If the event type is expecting data, it is possible to parse it using the helper functions
from tracim_daemon_sdk import TracimDaemonClient
from tracim_daemon_sdk.daemon_event import DaemonEvent
from tracim_daemon_sdk.data import TLMEvent
from tracim_daemon_sdk.helper import decode_json
def default_event_handler(c: TracimDaemonClient, e: DaemonEvent):
tlm: TLMEvent = decode_json(e.data)
print(tlm.event_type)
This handler stores the parsed data in a TLMEvent
object and prints the event type.
TLMEvent is the class that represents the data sent by Tracim (see tracim TLM documentation)
from time import time
from typing import Any
class TLMEvent:
def __init__(self,
event_id: int = 0,
event_type: str = "",
read: Any = None,
created: time = None,
fields: Any = None):
self.event_id: int = event_id
self.event_type: str = event_type
self.read: Any = read
self.created: time = created
self.fields: Any = fields
DaemonEvent is the event format used to communicate between apps
from typing import Any
class DaemonEvent:
def __init__(self, path: str = "", event_type: str = "", data: Any = None):
self.path: str = path
self.type: str = event_type
self.data: Any = data
- The
path
field is the path to the client socket (as defined in the config) - The
type
field is any of the constants defined in event.py - The
data
field can contain additional information of any format
A type
is expected to contain additional data if there is a <eventType>Data
class defined in data.py
.
EventHandler is the function definition for the event handlers.
It takes a TracimDaemonClient
and a DaemonEvent
as parameters
from tracim_daemon_sdk import TracimDaemonClient
from tracim_daemon_sdk.daemon_event import DaemonEvent
def handler(c: TracimDaemonClient, e: DaemonEvent) -> None:
pass
By default, handlers for DAEMON_ACCOUNT_INFO
and DAEMON_PING
are already defined, it is possible to override them.
Event types are defined by tracim. It is also possible to set handlers for every DaemonEvent
type.
There also is events defined by the SDK, for convenience.
# EVENT_TYPE_GENERIC is the event type for generic events (every DaemonEvent)
EVENT_TYPE_GENERIC = "custom_message"
# EVENT_TYPE_ERROR is the event type for errors
EVENT_TYPE_ERROR = "custom_error"
Client and daemons communicate with the DaemonEvent
format, i.e. JSON data following this format:
{
"type": "event_type",
"path": "/path/to/client/socket",
"data": {}
}
(See above DaemonEvent
section for details about each field)
When registering / unregistering a client a DaemonEvent
must be sent on the daemon socket.
{
"type": "client_add",
"path": "/path/to/client/socket",
"data": {
"path": "/path/to/client/socket",
"pid": "999"
}
}
To register a client, the client must send the message to the daemon socket, with the type
field set to client_add
.
To unregister a client, the client must send the message to the daemon socket, with the type
field set to client_delete
.
In both, additional info, defined as follows, is required:
{
"path": "/path/to/client/socket",
"pid": "999"
}
With pid
being the PID of the client process.
Once registered, the client will receive DaemonEvent
s from the daemon.
(See above DaemonEvent
section for details about types and data)
The daemon will send a DaemonAck
upon receiving any managed events not expecting a response, otherwise the
expected response is sent. As for now, a DaemonPong
for a DaemonPing
and a DaemonAccountInfo
for a DaemonClientAdd
The daemon expects no DaemonAck
on its messages.
The daemon will periodically (once every minute) send a DaemonPing
event, clients have a minute to respond with DaemonPong
,
If not, it will unregister un-responding clients at the next ping.
It is possible to test the daemon responsiveness by sending it DaemonPing
events. It will respond with a DaemonPong
as soon as possible.