The components that run in the gadgets system should be a subclass of Gadget.
After a gadget starts and registers, it listens for zmq messages that are specified by the events attribute. (see the gadgets.sockets module for more details). After a message is received the ‘event_received’ method is called.
There are many possible uses of Gadget subclasses. One of the main subclasses built into Gadgets is Device. It is meant for controlling physical devices. A Gadget subclass isn’t just for interfacing with hardware. For example, here is a class that records all of the goings on of the system:
>>> class Recorder(Gadget):... @property ... def events(self): ... return [‘UPDATE’] ... ... def event_received(self, event, message): ... with open(‘/tmp/gadgets_data.txt’, ‘a’) as buf: ... buf.write(json.dumps(message) + ‘
‘)
It would probably better to make one that saves the messages to a database.
In order to make a Gadgets subclass, you must define an events property and implement event_received. The event_received will only receive messages that you specified in the events property.
override this if your subclass needs to do more stuff in order to shutdown cleanly.
override this if you need to do something before the main loop starts
The Coordinator keeps track of the state of all the gadgets and provides a few ways for gadgets to request information. Coordinator listens for the following events (this defines the zmq-based API for gadgets):
The register message just lets the Coordinator know that there is a new Gadget. If the Gadget is a Device then the register message also includes the commands that turn the device on and off.
>>> sockets.send('register', {
'location': '<some location>',
'name': '<some name>',
'on': '<some on event>',
'off': '<some off event>',
})
receives a method message it starts up an instance of MethodRunner which then executes the method.
>>> sockets.send('method', {
'method': [
'turn on living room light',
'wait for 1 hour',
'turn off living room light'
]
})
send an update message. The Coordinator reads the message and updates its _state attribute. The _state attribute is accessible to the outside world via the status message (see status below). After Coordinator receives an update event, it sends an UPDATE event that contains the _state dict. The UPDATE event is intended for GUIs. Whenever something changes a GUI would want to be immediately notified.
>>> sockets.send('update', {
'<some location>': {
'<some name>': {
'value': True
}
}
})
of the Coordinator. Do with that state what you will. The message should contain the id of the entity that sent the request.
>>> sockets.send('status', {
'id': '<some unique id>'
})
>>> _id, status = sockets.recv()
on and off events that the Coordinator knows of due to gadgets registering and including ‘on’ and ‘off’ in the register message (see register above). This is useful for GUIs to be able to know how to turn things on and off.
>>> sockets.send('events', {
'id': '<some unique id>'
})
>>> _id, events = sockets.recv()
is a list of all the locations in the system that are registered with the Coordinator.
>>> sockets.send('locations', {
'id': '<some unique id>'
})
>>> _id, locations = sockets.recv()
and the Coordinator will exit their main loops and die. This message shuts down the whole system.
>>> sockets.send('shutdown')
in the _state attribute of the Coordinator.
>>> sockets.send('error', {
'error': '<some error message>'
'id': '<some unique id>'
})