Mike Sandstrom
Mike Sandstrom

Reputation: 73

Running GPIO commands from a Dictionary

I am publishing/subscribing to/from messages between a raspberry pi and a remote webserver. When I send messages to the pi using mqtt I am sending a string named after the channel on the pi I want to run. I have variables in the script named pump1, pump2, etc... that have their respective RPi channels. I have a dictionary who's keys are the RPi channels I want to turn on and values are the GPIO commands to do so.The mqtt messages are supposed to match the dictionary keys. If the keys match I want to run the value associated with that key.

Below is my dictionary. When I access the dictionary I get None for the values if I don't wrap them in quotes. When I use as strings around the GPIO commands I cant run the command. Anyone have any idea to run these commands?

I've also tried running something like this. This method does not work because the pump1 is not an integer denoting what channel to switch on the pi, but I have variables named pump1, pump2, etc.. associated with the RPi channels so I thought it might work but python still see's a string.

mqtt.message = ['pump1','on']
GPIO.output(mqtt.message[0], False)

Dictionary:

pumps = {
    "pump1:on": GPIO.output(pump1,False),
    "pump1:off": GPIO.output(pump1,True),
    "pump2:on": GPIO.output(pump2,False),
    "pump2:off": GPIO.output(pump2,True),
    "pump3:on": GPIO.output(pump3,False),
    "pump3:off": GPIO.output(pump3,True),
    "waterpump:on": GPIO.output(waterpump,False),
    "waterpump:off": GPIO.output(waterpump,True),
}

Upvotes: 1

Views: 183

Answers (1)

sshashank124
sshashank124

Reputation: 32197

They way you have specified it currently will cause the functions to be invoked during the construction of the pumps dictionary. Instead, you want to store a dictionary of keys to functions which you can then call when desired. We can use lambdas for this. Here's a simplified example:

funcs = {
    'print_int': lambda: print(1),
    'print_string': lambda: print("one"),
    'print_list': lambda: print([]),
}

You can then call then by indexing with the key and invoking the function as follows:

>>> funcs['print_int']()
1
>>> funcs['print_string']()
one
>>> funcs['print_list']()
[]

You can also have functions that take arguments as follows:

funcs = {
    'print_num': lambda num: print(num),
}

>>> funcs['print_num'](123)
123

For your use case, using arguments, this could look like

pumps = {
    "pump1": lambda state: GPIO.output(pump1, not state),
}

pumps['pump1'](True)  # to turn pump on

or if you don't want to use arguments, simply:

pumps = {
    "pump1:on":  lambda: GPIO.output(pump1, False),
    "pump1:off": lambda: GPIO.output(pump1, True),
}

Upvotes: 2

Related Questions