Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion limitlessled/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

# Various constants.
MIN_WAIT = 0.1
REPS = 3
DEFAULT_REPS = 3
MAX_GROUPS = 4


Expand Down
25 changes: 18 additions & 7 deletions limitlessled/bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import time
import threading

from limitlessled import MIN_WAIT, REPS
from limitlessled import MIN_WAIT, DEFAULT_REPS
from limitlessled.group.rgbw import RgbwGroup, RGBW
from limitlessled.group.white import WhiteGroup, WHITE

Expand All @@ -15,6 +15,7 @@
BRIDGE_SHORT_VERSION_MIN = 3
BRIDGE_LONG_BYTE = 0x55
SELECT_WAIT = 0.025
DEFAULT_PRIORITY = 10


def group_factory(bridge, number, name, led_type):
Expand All @@ -37,7 +38,8 @@ def group_factory(bridge, number, name, led_type):
class Bridge(object):
""" Represents a LimitlessLED bridge. """

def __init__(self, ip, port=BRIDGE_PORT, version=BRIDGE_VERSION):
def __init__(self, ip, port=BRIDGE_PORT, version=BRIDGE_VERSION,
reps=DEFAULT_REPS):
""" Initialize bridge.

Bridge version 3 through 5 (latest as of this release)
Expand All @@ -50,16 +52,17 @@ def __init__(self, ip, port=BRIDGE_PORT, version=BRIDGE_VERSION):
:param version: Bridge version.
"""
self.wait = MIN_WAIT
self.reps = REPS
self.reps = reps
self.groups = []
self.ip = ip
self.version = version
self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self._socket.connect((ip, port))
self._command_queue = queue.Queue()
self._command_queue = queue.PriorityQueue()
self._lock = threading.Lock()
self.active = 0
self._selected_number = None
self._seqnum = 0
# Start queue consumer thread.
consumer = threading.Thread(target=self._consume)
consumer.daemon = True
Expand Down Expand Up @@ -87,7 +90,8 @@ def add_group(self, number, name, led_type):
self.groups.append(group)
return group

def send(self, group, command, reps=REPS, wait=MIN_WAIT, select=False):
def send(self, group, command, reps=None, wait=MIN_WAIT, select=False,
priority=DEFAULT_PRIORITY):
""" Send a command to the physical bridge.

:param group: Run on this group.
Expand All @@ -96,8 +100,14 @@ def send(self, group, command, reps=REPS, wait=MIN_WAIT, select=False):
:param wait: Wait time in seconds.
:param select: Select group if necessary.
"""
if reps is None:
reps = self.reps

seqnum = self._seqnum
self._seqnum += 1
# Enqueue the command.
self._command_queue.put((group, command, reps, wait, select))
self._command_queue.put((priority, seqnum, group, command, reps, wait,
select))
# Wait before accepting another command.
# This keeps indvidual groups relatively synchronized.
sleep = reps * wait * self.active
Expand All @@ -120,7 +130,8 @@ def _consume(self):
"""
while True:
# Get command from queue.
(group, command, reps, wait, select) = self._command_queue.get()
(priority, seqnum, group, command, reps, wait, select) = \
self._command_queue.get()
# Select group if a different group is currently selected.
if select and self._selected_number != group.number:
self._socket.send(bytearray(group.get_select_cmd()))
Expand Down
11 changes: 5 additions & 6 deletions limitlessled/group/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
import threading
import queue

from limitlessled import MIN_WAIT, REPS
from limitlessled import MIN_WAIT
from limitlessled.pipeline import Pipeline, PipelineQueue


def rate(wait=MIN_WAIT, reps=REPS):
def rate(wait=MIN_WAIT, reps=None):
""" Rate limit a command function.

:param wait: How long to wait between commands.
Expand Down Expand Up @@ -60,7 +60,6 @@ def __init__(self, bridge, number, name):
self._thread.daemon = True
self._thread.start()
self.wait = MIN_WAIT
self.reps = REPS

@property
def on(self):
Expand Down Expand Up @@ -91,7 +90,7 @@ def send(self, cmd, select=False):
:param select: If command requires selection.
"""
self._bridge.send(self, cmd, wait=self.wait,
reps=self.reps, select=select)
reps=self.bridge.reps, select=select)

def enqueue(self, pipeline):
""" Start a pipeline.
Expand All @@ -114,7 +113,7 @@ def _wait(self, duration, commands):
:returns: Wait in seconds.
"""
wait = (duration / commands) - \
(self.wait * self.reps * self._bridge.active)
(self.wait * self.bridge.reps * self._bridge.active)
if wait < 0:
wait = 0
return wait
Expand All @@ -128,7 +127,7 @@ def _scaled_steps(self, duration, steps, total):
:returns: Steps scaled to time and total.
"""
return math.ceil(duration /
(self.wait * self.reps * self._bridge.active) *
(self.wait * self.bridge.reps * self._bridge.active) *
(steps / total))

def __str__(self):
Expand Down