forked from platypush/platypush
113 lines
3.2 KiB
Python
113 lines
3.2 KiB
Python
|
import json
|
||
|
import random
|
||
|
import threading
|
||
|
|
||
|
from enum import Enum
|
||
|
|
||
|
from platypush.message import Message
|
||
|
|
||
|
class Event(Message):
|
||
|
""" Event message class """
|
||
|
|
||
|
def __init__(self, target, type, origin, id=None, **kwargs):
|
||
|
"""
|
||
|
Params:
|
||
|
target -- Target node [String]
|
||
|
type -- Event type [EventType]
|
||
|
origin -- Origin node (default: current node) [String]
|
||
|
id -- Event ID (default: auto-generated)
|
||
|
kwargs -- Additional arguments for the event [kwDict]
|
||
|
"""
|
||
|
|
||
|
self.id = id if id else self._generate_id()
|
||
|
self.target = target
|
||
|
self.origin = origin
|
||
|
self.type = type
|
||
|
self.args = kwargs
|
||
|
|
||
|
@classmethod
|
||
|
def build(cls, msg):
|
||
|
""" Builds an event message from a JSON UTF-8 string/bytearray, a
|
||
|
dictionary, or another Event """
|
||
|
|
||
|
msg = super().parse(msg)
|
||
|
event_type = msg['args'].pop('type')
|
||
|
event_class = getattr(EventType, event_type).cls
|
||
|
|
||
|
args = {
|
||
|
'target' : msg['target'],
|
||
|
'origin' : msg['origin'],
|
||
|
**(msg['args'] if 'args' in msg else {}),
|
||
|
}
|
||
|
|
||
|
args['id'] = msg['id'] if 'id' in msg else cls._generate_id()
|
||
|
return event_class(**args)
|
||
|
|
||
|
@staticmethod
|
||
|
def _generate_id():
|
||
|
""" Generate a unique event ID """
|
||
|
id = ''
|
||
|
for i in range(0,16):
|
||
|
id += '%.2x' % random.randint(0, 255)
|
||
|
return id
|
||
|
|
||
|
def __str__(self):
|
||
|
"""
|
||
|
Overrides the str() operator and converts
|
||
|
the message into a UTF-8 JSON string
|
||
|
"""
|
||
|
|
||
|
return json.dumps({
|
||
|
'type' : 'event',
|
||
|
'target' : self.target,
|
||
|
'origin' : self.origin if hasattr(self, 'origin') else None,
|
||
|
'id' : self.id if hasattr(self, 'id') else None,
|
||
|
'args' : {
|
||
|
'type' : self.type.name,
|
||
|
**self.args,
|
||
|
},
|
||
|
})
|
||
|
|
||
|
|
||
|
class StopEvent(Event):
|
||
|
""" StopEvent message. When received on a Bus, it will terminate the
|
||
|
listening thread having the specified ID. Useful to keep listeners in
|
||
|
sync and make them quit when the application terminates """
|
||
|
|
||
|
def __init__(self, target, origin, thread_id, id=None, **kwargs):
|
||
|
""" Constructor.
|
||
|
Params:
|
||
|
target -- Target node
|
||
|
origin -- Origin node
|
||
|
thread_id -- thread_iden() to be terminated if listening on the bus
|
||
|
id -- Event ID (default: auto-generated)
|
||
|
kwargs -- Extra key-value arguments
|
||
|
"""
|
||
|
|
||
|
super().__init__(target=target, origin=origin, id=id,
|
||
|
type=EventType.STOP, thread_id=thread_id, **kwargs)
|
||
|
|
||
|
def targets_me(self):
|
||
|
""" Returns true if the stop event is for the current thread """
|
||
|
return self.args['thread_id'] == threading.get_ident()
|
||
|
|
||
|
|
||
|
class EventType(Enum):
|
||
|
""" Event types enum """
|
||
|
|
||
|
def __new__(cls, *args, **kwds):
|
||
|
value = len(cls.__members__) + 1
|
||
|
obj = object.__new__(cls)
|
||
|
obj._value_ = value
|
||
|
return obj
|
||
|
|
||
|
def __init__(self, label, cls):
|
||
|
self.label = label
|
||
|
self.cls = cls
|
||
|
|
||
|
STOP = 'STOP', StopEvent
|
||
|
|
||
|
|
||
|
# vim:sw=4:ts=4:et:
|
||
|
|