Add create pattern
This commit is contained in:
parent
7db59c7588
commit
74c6ee0987
|
@ -1,12 +1,13 @@
|
||||||
from ssdpy import SSDPClient
|
from ssdpy import SSDPClient
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
from flickerstrip import Flickerstrip
|
from flickerstrip_py.flickerstrip import Flickerstrip
|
||||||
|
|
||||||
|
|
||||||
class FlickerstripDiscoveryClient:
|
class FlickerstripDiscoveryClient:
|
||||||
def __init__(self):
|
def __init__(self, max_attempts=3):
|
||||||
self.client = SSDPClient(timeout=15)
|
self.max_attempts = max_attempts
|
||||||
|
self.client = SSDPClient()
|
||||||
|
|
||||||
def __discovered(self, device):
|
def __discovered(self, device):
|
||||||
loc = device["location"]
|
loc = device["location"]
|
||||||
|
@ -15,13 +16,16 @@ class FlickerstripDiscoveryClient:
|
||||||
return Flickerstrip(ip_address)
|
return Flickerstrip(ip_address)
|
||||||
|
|
||||||
def discover(self):
|
def discover(self):
|
||||||
print("Discovering devices...")
|
for i in range(self.max_attempts):
|
||||||
devices = self.client.m_search("ssdp:all")
|
print(f"Discovering devices... (Attempt {i + 1})")
|
||||||
print(f"Discovered {len(devices)} device(s).")
|
devices = self.client.m_search("ssdp:all")
|
||||||
filtered = [d for d in devices if "Flickerstrip" in d["server"]]
|
print(f"Discovered {len(devices)} device(s).")
|
||||||
print(f"Discovered {len(filtered)} flickerstrip(s).")
|
filtered = [d for d in devices if "Flickerstrip" in d["server"]]
|
||||||
mapped = [self.__discovered(d) for d in filtered]
|
print(f"Discovered {len(filtered)} flickerstrip(s).")
|
||||||
return mapped
|
if len(filtered) > 0:
|
||||||
|
mapped = [self.__discovered(d) for d in filtered]
|
||||||
|
return mapped
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import requests
|
import requests
|
||||||
from status import Status
|
from flickerstrip_py.status import Status
|
||||||
from pattern import PatternMeta
|
from flickerstrip_py.pattern import PatternMeta, PatternBuilder
|
||||||
|
|
||||||
|
|
||||||
class Flickerstrip:
|
class Flickerstrip:
|
||||||
|
@ -20,9 +20,17 @@ class Flickerstrip:
|
||||||
response (requests.Response): The response from the request.
|
response (requests.Response): The response from the request.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was successful
|
bool: If the request was successful
|
||||||
"""
|
"""
|
||||||
data = response.json()
|
data = response.json()
|
||||||
|
|
||||||
|
if "type" not in data:
|
||||||
|
if "id" in data: # create pattern response.
|
||||||
|
return True
|
||||||
|
print("ERROR: Unable to get response type!")
|
||||||
|
print(data)
|
||||||
|
return False
|
||||||
|
|
||||||
respType = data["type"]
|
respType = data["type"]
|
||||||
if respType == "error":
|
if respType == "error":
|
||||||
message = data["message"]
|
message = data["message"]
|
||||||
|
@ -35,6 +43,7 @@ class Flickerstrip:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print(f"ERROR: Unrecognized response type: {respType}.")
|
print(f"ERROR: Unrecognized response type: {respType}.")
|
||||||
|
print(data)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __get_request(self, path, params=None):
|
def __get_request(self, path, params=None):
|
||||||
|
@ -46,32 +55,34 @@ class Flickerstrip:
|
||||||
request. Defaults to None.
|
request. Defaults to None.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was successful
|
bool: If the request was successful
|
||||||
"""
|
"""
|
||||||
resp = requests.get(f"http://{self.ip_address}/{path}", params=params)
|
resp = requests.get(f"http://{self.ip_address}/{path}", params=params)
|
||||||
return self.__check_response(resp)
|
return self.__check_response(resp)
|
||||||
|
|
||||||
def __post_request(self, path, json=None, data=None):
|
def __post_request(self, path, json=None, params=None, data=None):
|
||||||
"""Send a POST request to the strip.
|
"""Send a POST request to the strip.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path (string): The path for the URL to request.
|
path (string): The path for the URL to request.
|
||||||
json (dictionary, optional): The JSON encodable body for the
|
json (dictionary, optional): The JSON encodable body for the
|
||||||
request. Defaults to None.
|
request. Defaults to None.
|
||||||
|
params (dictionary, optional): The query string params for the
|
||||||
|
request. Defaults to None.
|
||||||
data (string, optional): The raw data body. Defaults to None.
|
data (string, optional): The raw data body. Defaults to None.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was successful
|
bool: If the request was successful
|
||||||
"""
|
"""
|
||||||
resp = requests.post(f"http://{self.ip_address}/{path}",
|
resp = requests.post(f"http://{self.ip_address}/{path}",
|
||||||
json=json, data=data)
|
params=params, json=json, data=data)
|
||||||
return self.__check_response(resp)
|
return self.__check_response(resp)
|
||||||
|
|
||||||
def force_update(self):
|
def force_update(self):
|
||||||
"""Force updates the status of the strip.
|
"""Force updates the status of the strip.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__get_request("status")
|
return self.__get_request("status")
|
||||||
|
|
||||||
|
@ -79,7 +90,7 @@ class Flickerstrip:
|
||||||
"""Trigger the strip to turn the lights on.
|
"""Trigger the strip to turn the lights on.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__get_request("power/on")
|
return self.__get_request("power/on")
|
||||||
|
|
||||||
|
@ -87,7 +98,7 @@ class Flickerstrip:
|
||||||
"""Trigger the strip to turn the lights off.
|
"""Trigger the strip to turn the lights off.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__get_request("power/off")
|
return self.__get_request("power/off")
|
||||||
|
|
||||||
|
@ -95,7 +106,7 @@ class Flickerstrip:
|
||||||
"""Trigger the strip to toggle the power status.
|
"""Trigger the strip to toggle the power status.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__get_request("power/toggle")
|
return self.__get_request("power/toggle")
|
||||||
|
|
||||||
|
@ -103,7 +114,7 @@ class Flickerstrip:
|
||||||
"""Trigger the strip to switch to the next pattern in memory.
|
"""Trigger the strip to switch to the next pattern in memory.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__get_request("pattern/next")
|
return self.__get_request("pattern/next")
|
||||||
|
|
||||||
|
@ -114,18 +125,19 @@ class Flickerstrip:
|
||||||
frame (int): The frame number to freeze on.
|
frame (int): The frame number to freeze on.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__get_request("pattern/frame", {"value": frame})
|
return self.__get_request("pattern/frame", {"value": frame})
|
||||||
|
|
||||||
def select_pattern(self, index):
|
def select_pattern(self, index):
|
||||||
"""Change the current pattern to the pattern at the specified index.
|
"""Change the current pattern to the pattern at the specified index.
|
||||||
|
s of the flickerstrip.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
index (int): The index of the pattern.
|
index (int): The index of the pattern.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__get_request("pattern/select", {"index": index})
|
return self.__get_request("pattern/select", {"index": index})
|
||||||
|
|
||||||
|
@ -143,6 +155,40 @@ class Flickerstrip:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
"Deleting a pattern requires one of the three args.")
|
"Deleting a pattern requires one of the three args.")
|
||||||
|
|
||||||
|
def create_pattern(self, pattern, preview=True):
|
||||||
|
"""Create a pattern on the flickerstrip.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pattern (PatternBuilder): The pattern to send.
|
||||||
|
preview (bool, optional): Whether to only preview the pattern.
|
||||||
|
Defaults to True.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: If the request was succesful
|
||||||
|
"""
|
||||||
|
return self.__post_request("pattern/create", params={
|
||||||
|
"name": pattern.name,
|
||||||
|
"fps": pattern.fps,
|
||||||
|
"frames": pattern.frame_count,
|
||||||
|
"pixels": pattern.pixel_count,
|
||||||
|
"preview": preview
|
||||||
|
}, data=pattern.to_binary_string())
|
||||||
|
|
||||||
|
def set_color(self, r, g, b):
|
||||||
|
"""Sets the strip to a solid color (given as an RGB value).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
r (int): The red value (0 - 255)
|
||||||
|
g (int): The green value (0 - 255)
|
||||||
|
b (int): The blue value (0 - 255)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: If the request was successful
|
||||||
|
"""
|
||||||
|
pattern = PatternBuilder("Solid")
|
||||||
|
pattern.add_pixel(r, g, b)
|
||||||
|
return self.create_pattern(pattern)
|
||||||
|
|
||||||
def set_brightness(self, value):
|
def set_brightness(self, value):
|
||||||
"""Set the brightness of the flickerstrip.
|
"""Set the brightness of the flickerstrip.
|
||||||
|
|
||||||
|
@ -150,7 +196,7 @@ class Flickerstrip:
|
||||||
value (int): The brightness level as an int from 0 to 100.
|
value (int): The brightness level as an int from 0 to 100.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__get_request("brightness", {"value": value})
|
return self.__get_request("brightness", {"value": value})
|
||||||
|
|
||||||
|
@ -161,7 +207,7 @@ class Flickerstrip:
|
||||||
value (string): The new name.
|
value (string): The new name.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__post_request("config/name", {"name": value})
|
return self.__post_request("config/name", {"name": value})
|
||||||
|
|
||||||
|
@ -172,7 +218,7 @@ class Flickerstrip:
|
||||||
value (string): The new group.
|
value (string): The new group.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__post_request("config/group", {"name": value})
|
return self.__post_request("config/group", {"name": value})
|
||||||
|
|
||||||
|
@ -184,7 +230,7 @@ class Flickerstrip:
|
||||||
Value is handled in seconds.
|
Value is handled in seconds.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__get_request("config/cycle", {"value": value})
|
return self.__get_request("config/cycle", {"value": value})
|
||||||
|
|
||||||
|
@ -196,7 +242,7 @@ class Flickerstrip:
|
||||||
Value is handled in seconds.
|
Value is handled in seconds.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__get_request("config/fade", {"value": value})
|
return self.__get_request("config/fade", {"value": value})
|
||||||
|
|
||||||
|
@ -207,7 +253,7 @@ class Flickerstrip:
|
||||||
value (int): The length of the strip in pixels.
|
value (int): The length of the strip in pixels.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__get_request("config/length", {"value": value})
|
return self.__get_request("config/length", {"value": value})
|
||||||
|
|
||||||
|
@ -221,7 +267,7 @@ class Flickerstrip:
|
||||||
value (int): The new first pixel of the strip.
|
value (int): The new first pixel of the strip.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was successful.
|
bool: If the request was successful.
|
||||||
"""
|
"""
|
||||||
return self.__get_request("config/start", {"value": value})
|
return self.__get_request("config/start", {"value": value})
|
||||||
|
|
||||||
|
@ -235,7 +281,7 @@ class Flickerstrip:
|
||||||
value (int): The new last pixel of the strip.
|
value (int): The new last pixel of the strip.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was successful.
|
bool: If the request was successful.
|
||||||
"""
|
"""
|
||||||
return self.__get_request("config/end", {"value": value})
|
return self.__get_request("config/end", {"value": value})
|
||||||
|
|
||||||
|
@ -243,11 +289,11 @@ class Flickerstrip:
|
||||||
"""Set the reversed state of the flickerstrip.
|
"""Set the reversed state of the flickerstrip.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
value (boolean): If the flickerstrip should animate
|
value (bool): If the flickerstrip should animate
|
||||||
patterns in reverse.
|
patterns in reverse.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
boolean: If the request was succesful
|
bool: If the request was succesful
|
||||||
"""
|
"""
|
||||||
return self.__get_request("config/reversed",
|
return self.__get_request("config/reversed",
|
||||||
{"value": 1 if value else 0})
|
{"value": 1 if value else 0})
|
||||||
|
|
|
@ -19,3 +19,30 @@ class PatternMeta:
|
||||||
json["id"], json["name"], json["frames"],
|
json["id"], json["name"], json["frames"],
|
||||||
json["pixels"], json["flags"], json["fps"]
|
json["pixels"], json["flags"], json["fps"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class PatternBuilder:
|
||||||
|
def __init__(self, name, fps=1):
|
||||||
|
self.pixels = []
|
||||||
|
self.name = name
|
||||||
|
self.fps = fps
|
||||||
|
self.frame_count = 1
|
||||||
|
self.pixel_count = 0
|
||||||
|
self.frame_pixels = 0
|
||||||
|
|
||||||
|
def add_pixel(self, r, g, b):
|
||||||
|
if self.frame_count == 1:
|
||||||
|
self.pixel_count += 1
|
||||||
|
|
||||||
|
self.frame_pixels += 1
|
||||||
|
self.pixels += [r, g, b]
|
||||||
|
|
||||||
|
def next_frame(self):
|
||||||
|
self.frame_count += 1
|
||||||
|
self.frame_pixels = 0
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
self.frame_pixels == self.pixel_count
|
||||||
|
|
||||||
|
def to_binary_string(self):
|
||||||
|
return ''.join([chr(item) for item in self.pixels])
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from pattern import PatternMeta
|
from flickerstrip_py.pattern import PatternMeta
|
||||||
|
|
||||||
|
|
||||||
class MemoryUsage:
|
class MemoryUsage:
|
||||||
|
|
Loading…
Reference in New Issue