Skip to content

Commit 74b4135

Browse files
committed
Fixed, Linted, Moved to projects
1 parent 4326d47 commit 74b4135

File tree

2 files changed

+267
-150
lines changed

2 files changed

+267
-150
lines changed

examples/mqtt.py

Lines changed: 38 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,23 @@
11
#!/usr/bin/env python
2-
32
from sys import exit
4-
import argparse
5-
import time
63

74
try:
85
import paho.mqtt.client as mqtt
96
except ImportError:
10-
exit("This example requires the paho-mqtt module\nInstall with: sudo pip install paho-mqtt")
7+
exit('This example requires the paho-mqtt module\nInstall with: sudo pip install paho-mqtt')
118

129
import blinkt
1310

1411

15-
MQTT_SERVER = "iot.eclipse.org"
12+
MQTT_SERVER = 'iot.eclipse.org'
1613
MQTT_PORT = 1883
17-
MQTT_TOPIC = "pimoroni/blinkt"
14+
MQTT_TOPIC = 'pimoroni/blinkt'
1815

1916
# Set these to use authorisation
2017
MQTT_USER = None
2118
MQTT_PASS = None
2219

23-
description = """\
20+
print("""
2421
MQTT Blinkt! Control
2522
2623
This example uses public MQTT messages from {server} on port {port} to control Blinkt!
@@ -29,7 +26,6 @@
2926
3027
rgb,<pixel>,<r>,<g>,<b> - Set a single pixel to an RGB colour. Example: rgb,1,255,0,255
3128
clr - Clear Blinkt!
32-
bri,<val> - Set global brightness (for val in range 0.0-1.0)
3329
3430
You can use the online MQTT tester at http://www.hivemq.com/demos/websocket-client/ to send messages.
3531
@@ -38,176 +34,68 @@
3834
server=MQTT_SERVER,
3935
port=MQTT_PORT,
4036
topic=MQTT_TOPIC
41-
)
42-
parser = argparse.ArgumentParser(description = description, formatter_class = argparse.RawDescriptionHelpFormatter)
43-
parser.add_argument( '-H', '--host', default = MQTT_SERVER,
44-
help = 'MQTT broker to connect to' )
45-
parser.add_argument( '-P', '--port', default = MQTT_PORT, type = int,
46-
help = 'port on MQTT broker to connect to' )
47-
parser.add_argument( '-T', '--topic', action = 'append',
48-
help = 'MQTT topic to subscribe to; can be repeated for multiple topics' )
49-
parser.add_argument( '-u', '--user',
50-
help = 'MQTT broker user name' )
51-
parser.add_argument( '-p', '--pass', dest = 'pw',
52-
help = 'MQTT broker password' )
53-
parser.add_argument( '-q', '--quiet', default = False, action = 'store_true',
54-
help = 'Minimal output (eg for running as a daemon)' )
55-
parser.add_argument( '-g', '--green-hack', default = False, action = 'store_true',
56-
help = 'Apply hack to green channel to improve colour saturation' )
57-
parser.add_argument( '--timeout', default = '0',
58-
help = 'Pixel timeout(s). Pixel will blank if last update older than X seconds. May be a single number or comma-separated list. Use 0 for no timeout' )
59-
parser.add_argument( '-D', '--daemon', metavar='PIDFILE',
60-
help = 'Run as a daemon (implies -q)' )
61-
args = parser.parse_args()
62-
63-
# Get timeout list into expected form
64-
args.timeout = args.timeout.split( ',' )
65-
if len(args.timeout) == 1:
66-
args.timeout = args.timeout * blinkt.NUM_PIXELS
67-
elif len(args.timeout) != blinkt.NUM_PIXELS:
68-
exit("--timeout list must be %s elements long" % (blinkt.NUM_PIXELS,))
69-
try:
70-
args.timeout = [int(x) for x in args.timeout]
71-
except ValueError as e:
72-
exit("Bad timeout value: %s" % (e,))
73-
args.timeout = [x and x or None for x in args.timeout]
74-
args.min_timeout = min(args.timeout)
75-
76-
if args.daemon:
77-
import signal
78-
try:
79-
import daemon
80-
except ImportError:
81-
exit("--daemon requires the daemon module. Install with: sudo pip install python-daemon")
82-
try:
83-
import lockfile.pidlockfile
84-
except ImportError:
85-
exit("--daemon requires the lockfile module. Install with: sudo pip install lockfile")
86-
if not args.topic:
87-
args.topic = [MQTT_TOPIC]
88-
89-
class PixelClient( mqtt.Client ):
90-
def __init__( self, prog_args, *args, **kwargs ):
91-
super( PixelClient, self ).__init__( *args, **kwargs )
92-
self.args = prog_args
93-
self.update_time = [None] * blinkt.NUM_PIXELS
94-
self.on_connect = self.on_connect
95-
self.on_message = self.on_message
96-
97-
blinkt.set_clear_on_exit()
98-
# Some stuff doesn't get set up until the first time show() is called
99-
blinkt.show()
37+
))
38+
39+
40+
def on_connect(client, userdata, flags, rc):
41+
print('Connected with result code ' + str(rc))
10042

101-
if self.args.user is not None and self.args.pw is not None:
102-
self.username_pw_set(username=self.args.user, password=self.args.pw)
103-
self.connect(self.args.host, self.args.port, 60)
43+
client.subscribe(MQTT_TOPIC)
10444

105-
def cmd_clear( self ):
45+
46+
def on_message(client, userdata, msg):
47+
48+
data = msg.payload
49+
if type(data) is bytes:
50+
data = data.decode('utf-8')
51+
data = data.split(',')
52+
command = data.pop(0)
53+
54+
if command == 'clr' and len(data) == 0:
10655
blinkt.clear()
10756
blinkt.show()
57+
return
10858

109-
def cmd_brightness( self, bri ):
59+
if command == 'rgb' and len(data) == 4:
11060
try:
111-
bri = float(bri)
112-
except ValueError:
113-
print("Malformed command: ", str(msg.payload))
114-
return
115-
blinkt.set_brightness(bri)
116-
blinkt.show()
61+
pixel = data.pop(0)
11762

118-
def cmd_rgb( self, pixel, data ):
119-
try:
120-
if pixel == "*":
63+
if pixel == '*':
12164
pixel = None
12265
else:
12366
pixel = int(pixel)
12467
if pixel > 7:
125-
print("Pixel out of range: " + str(pixel))
68+
print('Pixel out of range: ' + str(pixel))
12669
return
12770

12871
r, g, b = [int(x) & 0xff for x in data]
129-
if self.args.green_hack:
130-
# Green is about twice the luminosity for a given value
131-
# than red or blue, so apply a hackish linear compensation
132-
# here taking care of corner cases at 0 and 255. To do it
133-
# properly, it should really be a curve but this approximation
134-
# is quite a lot better than nothing.
135-
if r not in [0,255]:
136-
r = r + 1
137-
if g not in [0]:
138-
g = g/2 + 1
139-
if b not in [0,255]:
140-
b = b + 1
141-
142-
if not self.args.quiet:
143-
print('rgb', pixel, r, g, b)
72+
73+
print(command, pixel, r, g, b)
14474

14575
except ValueError:
146-
print("Malformed command: " + str(msg.payload))
76+
print('Malformed command: ' + str(msg.payload))
14777
return
14878

14979
if pixel is None:
15080
for x in range(blinkt.NUM_PIXELS):
15181
blinkt.set_pixel(x, r, g, b)
152-
self.update_time[x] = time.time()
15382
else:
15483
blinkt.set_pixel(pixel, r, g, b)
155-
self.update_time[pixel] = time.time()
15684

15785
blinkt.show()
86+
return
15887

159-
def on_connect(self, client, userdata, flags, rc):
160-
if not self.args.quiet:
161-
print("Connected to {s}:{p} listening for topics {t} with result code {r}.\nSee {c} --help for options.".format(s = self.args.host, p = self.args.port, t = ', '.join(self.args.topic), r = rc, c = parser.prog))
162-
163-
for topic in self.args.topic:
164-
client.subscribe(topic)
165-
166-
def on_message(self, client, userdata, msg):
16788

168-
data = msg.payload.split(',')
169-
command = data.pop(0)
89+
blinkt.set_clear_on_exit()
17090

171-
if command == "clr" and len(data) == 0:
172-
self.cmd_clear()
173-
return
91+
client = mqtt.Client()
92+
client.on_connect = on_connect
93+
client.on_message = on_message
17494

175-
if command == "bri" and len(data) == 1:
176-
self.cmd_brightness( data[0] )
177-
return
95+
if MQTT_USER is not None and MQTT_PASS is not None:
96+
print('Using username: {un} and password: {pw}'.format(un=MQTT_USER, pw='*' * len(MQTT_PASS)))
97+
client.username_pw_set(username=MQTT_USER, password=MQTT_PASS)
17898

179-
if command == "rgb" and len(data) == 4:
180-
self.cmd_rgb( data[0], data[1:] )
181-
return
182-
183-
def blank_timed_out_pixels( self ):
184-
now = time.time()
185-
to_upt_pairs = zip(self.args.timeout,self.update_time)
186-
for pixel, (to, uptime) in enumerate(to_upt_pairs):
187-
if to is not None and uptime is not None and uptime < now - to:
188-
blinkt.set_pixel( pixel, 0, 0, 0 )
189-
self.update_time[pixel] = None
190-
blinkt.show()
99+
client.connect(MQTT_SERVER, MQTT_PORT, 60)
191100

192-
def loop( self, timeout = 1.0, max_packets = 1 ):
193-
self.blank_timed_out_pixels()
194-
return super( PixelClient, self ).loop( timeout, max_packets )
195-
196-
197-
def sigterm( signum, frame ):
198-
client._thread_terminate = True
199-
200-
if args.daemon:
201-
# Monkey-patch daemon so's the daemon starts reasonably quickly. FDs don't
202-
# strictly speaking need closing anyway because we haven't opened any (yet).
203-
daemon.daemon.get_maximum_file_descriptors = lambda: 32
204-
args.quiet = True
205-
pidlf = lockfile.pidlockfile.PIDLockFile( args.daemon )
206-
with daemon.DaemonContext(
207-
pidfile = pidlf,
208-
signal_map = {signal.SIGTERM: sigterm} ):
209-
client = PixelClient( args )
210-
client.loop_forever()
211-
else:
212-
client = PixelClient( args )
213-
client.loop_forever()
101+
client.loop_forever()

0 commit comments

Comments
 (0)