The devices are all dependent on an instance of Gadgets being up and running. For that reason, the example usage for each device shows how to create each device by creating the proper configuration dictionary and passing it to the get_gadgets function.
Device is what should be subclassed if you want a Gadget that controls a physical device.
Each device has an io attribute. The object represented by io only has to have an on and off method. The built in devices use io such as GPIO, PWM, and Poller.
When a Device is turned on with arguments, it should start up a trigger. A trigger is a threaded class that starts up and waits for some event to happen. When the event happens it does two things: turns off the io object and notifies the reset of the system with a ‘completed’ event.
For example, if you have a gadgets system for watering the grass you could send a RCL command like this:
>>> from gadgets import Sockets
>>> sock = Sockets()
>>> sock.send('turn on front yard sprinkers')
This is an example of an RCL command that has no arguments. If this command was send instead:
>>> sock.send('turn on front yard sprinkers for 15 minutes')
the command is considered to have arguments. If the Device that controls the front yard sprinklers is a Switch, then its trigger is a GPIOTimer. A GPIOTimer would be started up and after 15 minutes it would turn off the GPIO of the Switch that started it.
Called whenever one of the events returned by self.events is received.
Unless the user passes in the on event or a subclass overrides this message, then this device turns on in response to this message. So if this is a garage door opener, self._location is garage, self._name is opener. The default on event will be:
‘turn on garage door’
You might want to pass in the on event manually
on=’open {location}’
so that it becomes
‘open garage door’
Every device must have an io property. Switch uses a GPIO, ElectricHeater uses PWM. ElectricMotor uses GPIO and PWM. The object returned here must follow the API defined at
gadgets.io.io:IO
Gets called by event_received in the case of an off event. If a trigger is currently running it invalidates the trigger. It also calls self._update_status to notifiy the whole gadgets system of a state change.
Gets called by event_received in the case of an on event being received. It calls on of self.io and starts a trigger. It also calls self._update_status to notify the whole gadgets system of a state change.
A gadget uid us composed of the location and name properties. No two Gadget instances should have the same uid.
A Switch is used to control items that just need to be turned on and off. Here is an example:
>>> from gadgets.pins.beaglebone import pins
>>> from gadgets import get_gadgets
>>> arguments = {
... "locations": {
... "living room": {
... "light": {
... "type": "switch",
... "pin": pins["gpio"][8][3]
... },
... "back yard": {
... "sprinklers": {
... "type": "switch",
... "pin": pins["gpio"][8][11],
... },
... },
... },
... }
>>> gadgets = get_gadgets(arguments)
>>> gadgets.start()
Now you can turn it on by creating a socket and giving the switches a RCL command:
>>> from gadgets import Sockets
>>> s = Sockets()
>>> s.send("turn on living room light")
To turn on the sprinklers in the back yard for 15 minutes, you would send this command:
>>> s.send("turn on back yard sprinklers for 15 minutes")
Motor is a general class for controlling a motor. It should be able to control any motor, as long as it is initialized with an io object that can interface with the physical interface that is being used.
>>> from gadgets import get_gadgets
>>> from gadgets.pins.beaglebone import pins
>>> brewery_def = {
... 'locations': {
... 'front yard': {
... 'camera': {
... 'type': 'motor',
... 'gpio_a': 'gpio_a': pins['gpio'][8][24],
... 'gpio_b': pins['gpio'][8][25],
... 'pwm': pins['pwm'][8][13],
... 'poller': pins['gpio'][8][27]
... }
... }
... }
... }
If the motor you are controlling comes with an encoder (the example above assumes an encoder) then you can turn it on with a RCL command that uses ‘ticks’ as its units:
>>> from gadgets import Sockets
>>> sock = Sockets()
>>> sock.send('turn on top motor for 40 ticks')
Used to control electric heating coils on my brewery. Here is an example of its use:
>>> from gadgets import get_gadgets
>>> from gadgets.pins.beaglebone import pins
>>> brewery_def = {
... 'locations': {
... 'boiler': {
... 'heater': {
... 'type': 'electric heater',
... 'pin': pins['pwm'][8][13],
... }
... }
... }
... }
>>> brewery = get_gadgets(brewery_def)
>>> brewery.start()
If you turn on the electric heater with a target temperature like this:
>>> from gadgets import Sockets
>>> sock = Sockets()
>>> sock.send('heat boiler 180 F')
then as the temperature of the pot approaches the target temperature it will use its pwm pin to apply less heat to the pot so the heater won’t over heat the container.
Valve is pretty close to Switch, but uses volume units for its triggers instead of time units. On the surface Valve is pretty simple, but it has 4 different triggers making it the most complicated Device. All of these triggers were designed for my automatic brewery. They are:
FloatTrigger - Waits until a float switch is activated.
The valve triggers have more documentation.
Here is an example with four tanks (to illustrate all four triggers). The first tank uses a FloatTrigger and the one below it uses a GravityTrigger.
>>> from gadgets import get_gadgets
>>> from gadgets.pins.beaglebone import pins
>>> brewery_def = {
... 'locations': {
... 'hot liquor tank': {
... 'valve': {
... 'type': 'valve',
... 'pin': pins['gpio'][8][11],
... 'trigger': {
... 'type': 'float',
... 'pin': pins['gpio'][8][12],
... 'volume': 26.5,
... }
... }
... },
... 'mash tun': {
... 'valve': {
... 'type': 'valve',
... 'pin': pins['gpio'][8][12],
... 'trigger': {
... 'type': 'gravity',
... 'source': 'hot liquor tank',
... 'tank_radius': 7.5,
... 'valve_radius': 0.1875,
... 'valve_coefficient': 0.43244,
... }
... }
... },
... 'boiler': {
... 'valve': {
... 'type': 'valve',
... 'pin': pins['gpio'][8][12],
... 'trigger': {
... 'type': 'timer',
... 'source': 'mash tun',
... 'drain_time': 240 #seconds
... }
... }
... }
... 'carboy': {
... 'valve': {
... 'type': 'valve',
... 'pin': pins['gpio'][8][12],
... 'trigger': {
... 'type': 'user',
... 'source': 'boiler',
... }
... }
... },
... }
... }
>>> from gadgets import Sockets
>>> sock = Sockets()
>>> sock.send('fill hot liquor tank')
You don’t have to tell the hot liquor tank a volume in the command, because it can only be filled to one known volume (26.5 liters in this case)
Once the hot liquor tank is filled you can add any amount of water into the mash tun:
>>> sock.send('fill mash tun to 6.5 liters')
Knowing about the laws of physics, the GravityTrigger will turn off its valve after the appropriate amount of time.