scrool / xled Goto Github PK
View Code? Open in Web Editor NEW🎄Unofficial control for Twinkly - Smart Decoration LED lights.
License: MIT License
🎄Unofficial control for Twinkly - Smart Decoration LED lights.
License: MIT License
Hello, is it possible to have the firmware file. I have several ESP-01 modules and I would like to order Ws2811 LED ribbons with this application.
DiscoveryInterface() calls InterfaceAgent() incorrectly, such that destination_host gets lost. The result is that the cli --hostname argument does nothing: InterfaceAgent ends up pinging the broadcast address regardless of whether or not --hostname address is specified.
v0.6.1-109-g91da7b1 (origin/develop)
N/A
xled --verbosity-discover=DEBUG --hostname {some BOGUS IP addess} get-mode
...The --hostname argument should actually work as documented.
See https://github.com/scrool/xled-docs/issues/17 . My preliminary tests looks like cryptography
library needs to be replaced because it doesn't support 48 byte (384 bit) long encryption key. arc4
seems like a good candidate.
The problem has similarities to a previous issue (#66), but I did not do a factory reset or other reset. So when I run the command to switch the lights on, it shows in the CLI that it has switched them on. However, nothing happens. When I switch them on with the Twinkly app and then switch them off via the CLI it works fine. It was all working fine yesterday and I'm pretty sure I did not change anything.
Name: xled
Version: 0.7.0
Summary: Python library and command line interface to control Twinkly - Smart Decoration LED lights for Christmas.
Home-page: https://github.com/scrool/xled
Author: Pavol Babinčák
Author-email: [email protected]
License: MIT license
Location: /usr/local/lib/python3.7/dist-packages
Requires: click-log, pyzmq, Click, cryptography, tornado, requests, netaddr, requests-toolbelt
Required-by:
{
"product_name": "Twinkly",
"hardware_version": "100",
"bytes_per_led": 3,
"hw_id": "XXXXXX",
"flash_size": 64,
"led_type": 19,
"product_code": "TWS600STP",
"fw_family": "M",
"device_name": "Twinkly_XXXXXX",
"uptime": "3046141",
"mac": "XX:XX:XX:XX:XX:XX",
"uuid": "XXXXXXXXXXXXXXXXXXXX",
"max_supported_led": 600,
"number_of_led": 600,
"led_profile": "RGB",
"frame_rate": 9,
"measured_frame_rate": 9.8,
"movie_capacity": 2245,
"wire_type": 1,
"copyright": "LEDWORKS 2021",
"code": 1000
}
{
"version": "2.8.3",
"code": 1000
}
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
Python 2.7.16
Python 3.7.3
Expect lights to switch on.
Nothing happens
xled --verbosity-cli DEBUG --verbosity-control DEBUG --verbosity-auth DEBUG --name Twinkly_XXXXXX on
Looking for a device with name: Twinkly_XXXXXX...
Working on requested device.
debug: HW address = XX:XX:XX:XX:XX:XX
debug: IP address = XXX.XXX.XXX.XXX
debug: Turning on...
debug: Generated new state 'W\xd9\x04\xa1s\x98MN\xf7\x14M\x0b\x8c\x1c\xc9\xed\xc3%IC2\x14\xe9<e\xdb\x13n_\xd6\xeaI'.
debug: ClientApplication(): Challenge: 'W\xd9\x04\xa1s\x98MN\xf7\x14M\x0b\x8c\x1c\xc9\xed\xc3%IC2\x14\xe9<e\xdb\x13n_\xd6\xeaI'
debug: receive_authentication_token(): got token: LaPx6RSxcCw=
debug: challenge-response is correct.
debug: Requesting url http://XXX.XXX.XXX.XXX/xled/v1/led/mode using method POST.
debug: Supplying headers {'X-Auth-Token': u'LaPx6RSxcCw='}
debug: Passing through key word arguments {'json': {'mode': 'movie'}, 'data': None}.
Turned on.
I'am running the latest Raspberry Pi OS and a fresh Python3.7 venv. When I try xled on
I get this validation error:
xled on
Looking for any device...
Working on device: b'Twinkly_EBEA99'
ERROR:xled.auth:challenge-response invalid. Received challenge-response: '4b8af...' but '0fdb2...' was expected.
Traceback (most recent call last):
File "/home/pi/xledvenv/bin/xled", line 10, in <module>
sys.exit(main())
File "/home/pi/xledvenv/lib/python3.7/site-packages/click/core.py", line 1137, in __call__
return self.main(*args, **kwargs)
File "/home/pi/xledvenv/lib/python3.7/site-packages/click/core.py", line 1062, in main
rv = self.invoke(ctx)
File "/home/pi/xledvenv/lib/python3.7/site-packages/click/core.py", line 1668, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/pi/xledvenv/lib/python3.7/site-packages/click/core.py", line 1404, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/pi/xledvenv/lib/python3.7/site-packages/click/core.py", line 763, in invoke
return __callback(*args, **kwargs)
File "/home/pi/xledvenv/lib/python3.7/site-packages/click/decorators.py", line 26, in new_func
return f(get_current_context(), *args, **kwargs)
File "/home/pi/xledvenv/lib/python3.7/site-packages/xled/cli.py", line 107, in turn_on
control_interface.turn_on()
File "/home/pi/xledvenv/lib/python3.7/site-packages/xled/control.py", line 554, in turn_on
return self.set_mode("movie")
File "/home/pi/xledvenv/lib/python3.7/site-packages/xled/control.py", line 322, in set_mode
response = self.session.post(url, json=json_payload)
File "/home/pi/xledvenv/lib/python3.7/site-packages/requests/sessions.py", line 590, in post
return self.request('POST', url, data=data, json=json, **kwargs)
File "/home/pi/xledvenv/lib/python3.7/site-packages/xled/auth.py", line 329, in request
headers = self.add_authorization(headers)
File "/home/pi/xledvenv/lib/python3.7/site-packages/xled/auth.py", line 354, in add_authorization
self.fetch_token()
File "/home/pi/xledvenv/lib/python3.7/site-packages/xled/auth.py", line 272, in fetch_token
self.client.challenge_response_valid(self.hw_address)
File "/home/pi/xledvenv/lib/python3.7/site-packages/xled/auth.py", line 403, in challenge_response_valid
raise ValidationError()
xled.exceptions.ValidationError
core
Command Line Interface (CLI)
Libary
Documentation
Other
Name: xled
Version: 0.6.1
Summary: Python library and command line interface to control Twinkly - Smart Decoration LED lights for Christmas.
Home-page: https://github.com/scrool/xled
Author: Pavol Babinčák
Author-email: [email protected]
License: MIT license
Location: /home/pi/xledvenv/lib/python3.7/site-packages
Requires: Click, arpreq, tornado, netaddr, pyzmq, cryptography, click-log, requests, requests-toolbelt
Required-by:
TWF020STP 192.168.2.122
{
"product_name": "Twinkly",
"hardware_version": "100",
"bytes_per_led": 3,
"hw_id": "ebea98",
"flash_size": 64,
"led_type": 14,
"product_code": "TWF020STP",
"fw_family": "F",
"device_name": "Twinkly_EBEA99",
"uptime": "232837887",
"mac": "f0...:eb:ea:99",
"uuid": "A5804158-...",
"max_supported_led": 510,
"number_of_led": 20,
"led_profile": "RGB",
"frame_rate": 81,
"measured_frame_rate": 90.91,
"movie_capacity": 992,
"wire_type": 1,
"copyright": "LEDWORKS 2021",
"code": 1000
}
{
"version": "2.7.1",
"code": 1000
}
Raspberry Pi OS Linux pi4 5.10.52-v7l+ #1440 SMP Tue Jul 27 09:55:21 BST 2021 armv7l GNU/Linux
Python 3.7.3
I'm running the sample code and get the following error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/michael.whitley/Developer/xled/xled/control.py", line 226, in get_device_info
response = self.session.get(url)
File "/Users/michael.whitley/opt/anaconda3/lib/python3.8/site-packages/requests/sessions.py", line 543, in get
return self.request('GET', url, **kwargs)
File "/Users/michael.whitley/Developer/xled/xled/auth.py", line 329, in request
headers = self.add_authorization(headers)
File "/Users/michael.whitley/Developer/xled/xled/auth.py", line 354, in add_authorization
self.fetch_token()
File "/Users/michael.whitley/Developer/xled/xled/auth.py", line 272, in fetch_token
self.client.challenge_response_valid(self.hw_address)
File "/Users/michael.whitley/Developer/xled/xled/auth.py", line 396, in challenge_response_valid
expected = xled.security.make_challenge_response(self._challenge, hw_address)
AttributeError: module 'xled' has no attribute 'security'```
# Affected XLED components
- [ ] Command Line Interface (CLI)
- [x] Libary
- [ ] Documentation
- [ ] Other
# XLED version
v0.6.1-62-g624b519
# Twinkly device details
<!--- Project support only some device models. Provide details by calling its API where HOSTNAME is either IP address or host name of your device. -->
## Device information
```{"product_name":"Twinkly","hardware_version":"304","bytes_per_led":3,"hw_id":"c55a6c","flash_size":64,"led_type":14,"product_code":"TWS400STP","fw_family":"F","device_name":"Twinkly_C55A6D","uptime":"236293617","mac":"a4:e5:7c:xx:xx:xx","uuid":"FFB78939-XXXX-XXXX-XXXX-A11CB1AXXXXX","max_supported_led":510,"number_of_led":400,"led_profile":"RGB","frame_rate":13,"measured_frame_rate":15.38,"movie_capacity":3382,"wire_type":2,"copyright":"LEDWORKS 2021","code":1000}
MacOS
Python 3.8.5
import xled
discovered_device = xled.discover.discover()
discovered_device.id
control = xled.ControlInterface(discovered_device.ip_address, discovered_device.hw_address)
control.get_device_info()['number_of_led']
Return number of LEDs
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/michael.whitley/Developer/xled/xled/control.py", line 226, in get_device_info
response = self.session.get(url)
File "/Users/michael.whitley/opt/anaconda3/lib/python3.8/site-packages/requests/sessions.py", line 543, in get
return self.request('GET', url, **kwargs)
File "/Users/michael.whitley/Developer/xled/xled/auth.py", line 329, in request
headers = self.add_authorization(headers)
File "/Users/michael.whitley/Developer/xled/xled/auth.py", line 354, in add_authorization
self.fetch_token()
File "/Users/michael.whitley/Developer/xled/xled/auth.py", line 272, in fetch_token
self.client.challenge_response_valid(self.hw_address)
File "/Users/michael.whitley/Developer/xled/xled/auth.py", line 396, in challenge_response_valid
expected = xled.security.make_challenge_response(self._challenge, hw_address)
AttributeError: module 'xled' has no attribute 'security'```
# Additional information
<!--- Anything else you would like to add? -->
I love the work done on this and look forward to using it!
I have an issue with the current Twinkly app version 1.5.2 (build 478) when controlling my LED string.
The LEDs are running firmware version 1.99.10 (older than yours) and the app refuses to map the LEDs because the firmware is too old.
However, the firmware update fails because the app times out before the response to the firmware update completes.
I reported it to Twinkly last week - but so far have no solution.
So ... I am thinking about using your xled to do the firmware write (I have captured what the official app was trying to upload and my SHA1 checksums for the captured data matches what the LEDs return in the fw update response).
Given that writing firmware could go horribly wrong ... I would like to know if that function in your xled has library has been tested.
For example - it does not appear to set "Content-Type: application/octet-stream" via
headers={'Content-Type': 'application/octet-stream'}
Is that because it is not needed - or is it untested?
The comment in the upload fw routines say that "firmware" parameter is a "file-like object that points to firmware file".
So should I pass in the name of a file?
Finally, I managed to get my script working. Now I can turn my Twinkly on/off and read information via HTTP requests.
I want to try uploading movie:
https://xled-docs.readthedocs.io/en/latest/rest_api.html#upload-new-movie-to-list-of-movies
but have no ideas what's the movie format and what should I put in octet-stream.
Has anyone tried that before or does anyone know an information source?
Thanks
python setup.py install
/develop
should install all the dependencies.
On Darwin Kernel Version 19.6.0 == MacOS 10.15.7 (and also 10.13), this gets:
error: The 'requests' distribution was not found and is required by xled
If you run the same command twice more it works.
The develop
branch
MacOS 10.15.7 but I also saw this on a 10.13
Python 3.6.6 and 3.8.9
python setup.py develop
or install
I have seen this issue reported before on a different project by a Mac user, so I have a fix (coming), but I don't know the cause, or really why the fix works.
I use set_rt_frame_socket
to send individual frames to my light strings. These are shown for 60 seconds before the string reverts to its last stored movie. Because the xled.control.ControlInterface
does not set a short timeout when communicating with the lights, sometimes I see many-minute hangs during which communication is lost. These failed connections are intermittent, so in the absence of an xled
timeout argument I’ve found that this wrapper class works well:
class TimeoutControlInterface:
interface = None
def __init__(self, *args, **kwargs):
"""Initialize xled.control.ControlInterface with same arguments"""
self.interface = xled.control.ControlInterface(*args, **kwargs)
def __getattr__(self, name):
"""Retrieve versions of self.interface methods that use a threaded timeout"""
original_method, responses = getattr(self.interface, name), []
def wrapped_method(*args, **kwargs):
"""Call the original method and stash its response"""
responses.append(original_method(*args, **kwargs))
def threaded_method(*args, **kwargs):
"""Call the wrapped method inside a thread and return its response"""
thread = threading.Thread(target=wrapped_method, args=args, kwargs=kwargs)
thread.start()
thread.join(timeout=5.0)
if thread.is_alive():
raise Exception("Thread still alive")
return responses[0]
return threaded_method
It’s used just like xled.control.ControlInterface
but raises an exception when a method call requires more than five seconds to complete. Hope it’s useful to someome!
UPDATE:
IGNORE THIS ...
In the docs you show a command line example as
xled on
I can see the various command line options in cli.py but am missing a way to invoke them.
I have made a small Python launcher that calls cli.main but not seeing any output, including when using obviously bad command line parameters.
Is there a helper/wrapper to make it easy for the cli to be used?
Edit:
I did try
python3 cli.py on
first.
I put some print statements in it to show that it is launched ... they came out ... but no sign of the command line being processed.
Edit2:
Looks like I had to logout / login to get the xled shim available ... I guess it was not in the path before and is now. So now I can type
xled on
and it works.
Thanks.
Discovery is currently implemented as a broadcast. On some networks broadcasts are not propagated. That effectively means Twinkly devices cannot be found. Unicast connections work just fine (e.g. because they are forwarded across networks).
Twinkly app falls back to unicast for each address on the network. It does this only once - when new device is added to the app and then stores information about the device and addresses it directly.
Doing unicast discovery by CLI would be too expensive.
I'd like to mitigate this by ability to skip discovery - probably implicitly when --hostname
is specified.
Skip of discovery might require #59.
There is an option in the Github settings for a Discussion tab. Wouln't that be useful for xled?
Not everything people like to share fits under "issues". It might be that someone needs help, or wants to ask people with different variants of the lights of their experiences, or wants to share experiences, or give tips of how to produce nice effects on their leds.
I think such a possibility would be nice.
/ Anders
(.venv) m@spore:~/go/src/github.com/scrool/xled$ xled --verbosity-auth DEBUG --verbosity-discover DEBUG --verbosity-control DEBUG --hostname 192.168.4.33 get-mode
Looking for device with address: 192.168.4.33...
DEBUG:xled.discover:Sending ping
DEBUG:xled.discover:Waiting for a beacon.
DEBUG:xled.discover:Ignoring ping message received from network from 192.168.4.21.
DEBUG:xled.discover:Waiting for a beacon.
DEBUG:xled.discover:Received a beacon from 192.168.4.38.
DEBUG:xled.discover:Received b'&\x04\xa8\xc0OKTwinkly_36DE85\x00'
DEBUG:xled.discover:Getting hardware address of b'192.168.4.38'.
ERROR:asyncio:Exception in callback BaseAsyncIOLoop._handle_events(20, 1)
handle: <Handle BaseAsyncIOLoop._handle_events(20, 1)>
Traceback (most recent call last):
File "/usr/lib/python3.8/asyncio/events.py", line 81, in _run
self._context.run(self._callback, *self._args)
File "/home/m/go/src/github.com/scrool/xled/.venv/lib/python3.8/site-packages/tornado/platform/asyncio.py", line 189, in _handle_events
handler_func(fileobj, events)
File "/home/m/go/src/github.com/scrool/xled/xled/discover.py", line 465, in handle_beacon
hw_address = bytes(hw_address, "utf-8")
TypeError: encoding without a string argument
DEBUG:xled.discover:Waiting for a beacon.
DEBUG:xled.discover:Received a beacon from 192.168.4.39.
DEBUG:xled.discover:Received b"'\x04\xa8\xc0OKTwinkly_396D45\x00"
DEBUG:xled.discover:Getting hardware address of b'192.168.4.39'.
ERROR:asyncio:Exception in callback BaseAsyncIOLoop._handle_events(20, 1)
handle: <Handle BaseAsyncIOLoop._handle_events(20, 1)>
Traceback (most recent call last):
File "/usr/lib/python3.8/asyncio/events.py", line 81, in _run
self._context.run(self._callback, *self._args)
File "/home/m/go/src/github.com/scrool/xled/.venv/lib/python3.8/site-packages/tornado/platform/asyncio.py", line 189, in _handle_events
handler_func(fileobj, events)
File "/home/m/go/src/github.com/scrool/xled/xled/discover.py", line 465, in handle_beacon
hw_address = bytes(hw_address, "utf-8")
TypeError: encoding without a string argument
DEBUG:xled.discover:Waiting for a beacon.
DEBUG:xled.discover:Received a beacon from 192.168.4.43.
DEBUG:xled.discover:Received b'+\x04\xa8\xc0OKTwinkly_3C5095\x00'
DEBUG:xled.discover:Getting hardware address of b'192.168.4.43'.
ERROR:asyncio:Exception in callback BaseAsyncIOLoop._handle_events(20, 1)
handle: <Handle BaseAsyncIOLoop._handle_events(20, 1)>
Traceback (most recent call last):
File "/usr/lib/python3.8/asyncio/events.py", line 81, in _run
self._context.run(self._callback, *self._args)
File "/home/m/go/src/github.com/scrool/xled/.venv/lib/python3.8/site-packages/tornado/platform/asyncio.py", line 189, in _handle_events
handler_func(fileobj, events)
File "/home/m/go/src/github.com/scrool/xled/xled/discover.py", line 465, in handle_beacon
hw_address = bytes(hw_address, "utf-8")
TypeError: encoding without a string argument
DEBUG:xled.discover:Waiting for a beacon.
DEBUG:xled.discover:Received a beacon from 192.168.4.40.
DEBUG:xled.discover:Received b'(\x04\xa8\xc0OKTwinkly_35F259\x00'
DEBUG:xled.discover:Getting hardware address of b'192.168.4.40'.
ERROR:asyncio:Exception in callback BaseAsyncIOLoop._handle_events(20, 1)
handle: <Handle BaseAsyncIOLoop._handle_events(20, 1)>
Traceback (most recent call last):
File "/usr/lib/python3.8/asyncio/events.py", line 81, in _run
self._context.run(self._callback, *self._args)
File "/home/m/go/src/github.com/scrool/xled/.venv/lib/python3.8/site-packages/tornado/platform/asyncio.py", line 189, in _handle_events
handler_func(fileobj, events)
File "/home/m/go/src/github.com/scrool/xled/xled/discover.py", line 465, in handle_beacon
hw_address = bytes(hw_address, "utf-8")
TypeError: encoding without a string argument
DEBUG:xled.discover:Waiting for a beacon.
DEBUG:xled.discover:Received a beacon from 192.168.4.36.
DEBUG:xled.discover:Received b'$\x04\xa8\xc0OKTwinkly_36FC01\x00'
DEBUG:xled.discover:Getting hardware address of b'192.168.4.36'.
ERROR:asyncio:Exception in callback BaseAsyncIOLoop._handle_events(20, 1)
handle: <Handle BaseAsyncIOLoop._handle_events(20, 1)>
Traceback (most recent call last):
File "/usr/lib/python3.8/asyncio/events.py", line 81, in _run
self._context.run(self._callback, *self._args)
File "/home/m/go/src/github.com/scrool/xled/.venv/lib/python3.8/site-packages/tornado/platform/asyncio.py", line 189, in _handle_events
handler_func(fileobj, events)
File "/home/m/go/src/github.com/scrool/xled/xled/discover.py", line 465, in handle_beacon
hw_address = bytes(hw_address, "utf-8")
TypeError: encoding without a string argument
DEBUG:xled.discover:Waiting for a beacon.
DEBUG:xled.discover:Received a beacon from 192.168.4.32.
DEBUG:xled.discover:Received b' \x04\xa8\xc0OKTwinkly_377851\x00'
DEBUG:xled.discover:Getting hardware address of b'192.168.4.32'.
ERROR:asyncio:Exception in callback BaseAsyncIOLoop._handle_events(20, 1)
handle: <Handle BaseAsyncIOLoop._handle_events(20, 1)>
Traceback (most recent call last):
File "/usr/lib/python3.8/asyncio/events.py", line 81, in _run
self._context.run(self._callback, *self._args)
File "/home/m/go/src/github.com/scrool/xled/.venv/lib/python3.8/site-packages/tornado/platform/asyncio.py", line 189, in _handle_events
handler_func(fileobj, events)
File "/home/m/go/src/github.com/scrool/xled/xled/discover.py", line 465, in handle_beacon
hw_address = bytes(hw_address, "utf-8")
TypeError: encoding without a string argument
DEBUG:xled.discover:Waiting for a beacon.
DEBUG:xled.discover:Received a beacon from 192.168.4.42.
DEBUG:xled.discover:Received b'*\x04\xa8\xc0OKTwinkly_35E54D\x00'
DEBUG:xled.discover:Getting hardware address of b'192.168.4.42'.
ERROR:asyncio:Exception in callback BaseAsyncIOLoop._handle_events(20, 1)
handle: <Handle BaseAsyncIOLoop._handle_events(20, 1)>
Traceback (most recent call last):
File "/usr/lib/python3.8/asyncio/events.py", line 81, in _run
self._context.run(self._callback, *self._args)
File "/home/m/go/src/github.com/scrool/xled/.venv/lib/python3.8/site-packages/tornado/platform/asyncio.py", line 189, in _handle_events
handler_func(fileobj, events)
File "/home/m/go/src/github.com/scrool/xled/xled/discover.py", line 465, in handle_beacon
hw_address = bytes(hw_address, "utf-8")
TypeError: encoding without a string argument
DEBUG:xled.discover:Sending ping
DEBUG:xled.discover:Waiting for a beacon.
DEBUG:xled.discover:Ignoring ping message received from network from 192.168.4.21.
DEBUG:xled.discover:Waiting for a beacon.
DEBUG:xled.discover:Received a beacon from 192.168.4.36.
DEBUG:xled.discover:Received b'$\x04\xa8\xc0OKTwinkly_36FC01\x00'
DEBUG:xled.discover:Getting hardware address of b'192.168.4.36'.
ERROR:asyncio:Exception in callback BaseAsyncIOLoop._handle_events(20, 1)
handle: <Handle BaseAsyncIOLoop._handle_events(20, 1)>
Traceback (most recent call last):
I suspect this is only an issue on Py3 - the checks here are in the wrong order, PR to follow
First: Thanks to all for developing this!
Any good simple examples of how to send a movie using the library?
Another example I could use is how to use RT mode - I thought I saw references to it somewhere but set_mode only supports 'on', 'off', 'movie' and 'demo'.
Thanks again!
Is it possible to read the current movie from the lights? That would allow us to draw figures using the Twinkly app and to re-send to the tree using xled.
This might be related to #61
I'd like to use xled
with Home Assistant, and for that I consder using autodiscovery.
My setup is Raspberry PI which is connected to home automation WiFi. and also a regular ethernet, and Twinkly that is registered in the home automation WiFi.
It appears to me that the discovery process is running only on one interface: if both interfaces are up, xled.discover.discover()
takes a long time (and I have stopped it with ^C). Unplugging the ethernet cord resulted in a quick response from my twinkly.
I think that the discoverer should try all running interfaces.
P.S. I could try implementing this myself if you could provide me with outline how this could be achieved
Hey
So I've tweaked my led layout slightly, just to clean it up a bit from the mapping. I've successfully pushed the new layout config with set_led_layout
, and can retrieve the updated layout via get_led_layout
. However, the app must cache the last known state that it was aware of.
Does anyone know a trick to force the app to pick up the updated layout? I've tried to delete the scene, remove the set in question from the app and re-added, but it comes with the default Christmas tree layout.
For ref, and in case it helps anyone that's trying to do similar, this is how I've been working with the layout, plotting via matplotlib to get the visualisation, and adjusting layouts via another script.
`
import xled
import numpy as np
from matplotlib import pyplot as plt
c = xled.ControlInterface("192.168.8.118")
coord = c.get_led_layout().data['coordinates']
a = []
for item in coord:
a.append([item['x'], item['y']])
arr = np.array(a)
x, y = arr.T
plt.scatter(x,y)
plt.show()
`
Line 69 in 69ce41a
File "/home/pi/wakeupcall/.venv/src/xled/xled/response.py", line 69, in data raise ApplicationError(msg, response=self.response) File "/home/pi/wakeupcall/.venv/src/xled/xled/exceptions.py", line 6, in __init__ super(XledException, self).__init__(*args, **kwargs) TypeError: ApplicationError() takes no keyword arguments
Trying to create a toggle function but in order to do this, need to get the current state. I am able to set_mode('movie') or set_mode('off'), but unable to read the state.
`import os
import xled
hosts = ['192.168.2.196']
for host in hosts:
response = os.system('ping ' + host + ' -n 1 -w 250|find /i "TTL=" /c')
if response == 0:
print('Checking ' + host + '...')
control = xled.ControlInterface(host)
print(control.get_mode())
`
returns:
Checking 192.168.2.196...
<ApplicationResponse [None]>
interactive in Python 2.7 brings the same "None" response as well.
ERROR: Failed building wheel for arpreq
Running setup.py clean for arpreq
Successfully built xled
Failed to build arpreq
Installing collected packages: arpreq, monotonic, pyzmq, backports-abc, futures, tornado, xled
Running setup.py install for arpreq ... error
ERROR: Command errored out with exit status 1:
command: /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/bh/fv5yblvn2f9_s4zl3v0tjm2w0000gn/T/pip-install-XrQqXv/arpreq/setup.py'"'"'; file='"'"'/private/var/folders/bh/fv5yblvn2f9_s4zl3v0tjm2w0000gn/T/pip-install-XrQqXv/arpreq/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' install --record /private/var/folders/bh/fv5yblvn2f9_s4zl3v0tjm2w0000gn/T/pip-record-QAkkgv/install-record.txt --single-version-externally-managed --user --prefix= --compile --install-headers /Users/vjee/Library/Python/2.7/include/python2.7/arpreq
cwd: /private/var/folders/bh/fv5yblvn2f9_s4zl3v0tjm2w0000gn/T/pip-install-XrQqXv/arpreq/
Complete output (37 lines):
running install
running build
running build_ext
building 'arpreq' extension
creating build
creating build/temp.macosx-10.15-x86_64-2.7
creating build/temp.macosx-10.15-x86_64-2.7/src
cc -fno-strict-aliasing -fno-common -dynamic -g -Os -pipe -fno-common -fno-strict-aliasing -fwrapv -DENABLE_DTRACE -DMACOSX -DNDEBUG -Wall -Wstrict-prototypes -Wshorten-64-to-32 -iwithsysroot /usr/local/libressl/include -DNDEBUG -g -fwrapv -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE -arch x86_64 -pipe -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c src/arpreq.c -o build/temp.macosx-10.15-x86_64-2.7/src/arpreq.o -std=c99
src/arpreq.c:215:39: error: use of undeclared identifier 'SIOCGIFHWADDR'
if (ioctl(st->socket, SIOCGIFHWADDR, &ifreq) == -1) {
^
src/arpreq.c:218:49: error: no member named 'ifr_hwaddr' in 'struct ifreq'
memcpy(&mac_address, &ifreq.ifr_hwaddr, sizeof(mac_address));
~~~~~ ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/secure/_string.h:63:33: note: expanded from macro 'memcpy'
__builtin___memcpy_chk (dest, VA_ARGS, __darwin_obsz0 (dest))
^~~~~~~~~~~
src/arpreq.c:226:28: error: no member named 'arp_dev' in 'struct arpreq'
strncpy(arpreq.arp_dev, ifa->ifa_name, IFNAMSIZ);
~~~~~~ ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/secure/_string.h:128:28: note: expanded from macro 'strncpy'
__builtin___strncpy_chk (dest, VA_ARGS, __darwin_obsz (dest))
^~~~
src/arpreq.c:226:28: error: no member named 'arp_dev' in 'struct arpreq'
strncpy(arpreq.arp_dev, ifa->ifa_name, IFNAMSIZ);
~~~~~~ ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/secure/_string.h:128:62: note: expanded from macro 'strncpy'
__builtin___strncpy_chk (dest, VA_ARGS, __darwin_obsz (dest))
^~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/secure/_common.h:39:54: note: expanded from macro '__darwin_obsz'
#define __darwin_obsz(object) __builtin_object_size (object, _USE_FORTIFY_LEVEL > 1 ? 1 : 0)
^~~~~~
src/arpreq.c:227:35: error: use of undeclared identifier 'SIOCGARP'
if (ioctl(st->socket, SIOCGARP, &arpreq) == -1) {
^
5 errors generated.
error: command 'cc' failed with exit status 1
----------------------------------------
ERROR: Command errored out with exit status 1: /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/bh/fv5yblvn2f9_s4zl3v0tjm2w0000gn/T/pip-install-XrQqXv/arpreq/setup.py'"'"'; file='"'"'/private/var/folders/bh/fv5yblvn2f9_s4zl3v0tjm2w0000gn/T/pip-install-XrQqXv/arpreq/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' install --record /private/var/folders/bh/fv5yblvn2f9_s4zl3v0tjm2w0000gn/T/pip-record-QAkkgv/install-record.txt --single-version-externally-managed --user --prefix= --compile --install-headers /Users/vjee/Library/Python/2.7/include/python2.7/arpreq Check the logs for full command output.
For reference, I am sharing a Wireshark packet capture between the iOS Twinkly app and my Gen 2 750 light RGB Christmas tree. This capture includes the app launch, editing a solid color effect (rt mode), then applying that effect as a movie.
My primary reason for sharing is because I believe the realtime UDP protocol has changed, or at least is different for such a a large number of lights. I believe the movie API may have changed a bit as well.
I'm hoping that anyone who understands the code but does not have access to this kinds of device might be able to improve the documentation and code to support newer devices and firmware.
Twinkly Gen 2 750 Lights - App Launch & Effect Change.pcapng.zip
Fall back to mac address reported by device itself in gestalt
API as an alternative to arpreq
or getmac
.
I know that most of rest API calls require authentication. Due the way how requests auth handler is written request to get auth token is done only after HTTP 403 Forbidden is received.
Make it possible to login first. One HTTP round-trip less.
Hello,
Using Twinkly Gen2, Debian Buster amd64 and xled with python 3.7, I get this following error using cli:
Looking for any device...
Working on device: 'Twinkly_*****'
ERROR:xled.auth:challenge-response invalid. Received challenge-response: 'a28de0d5a2149a2073b2beadfbb1099a19828fe3' but '2ed085ade3f9b16c9195407436327b86331cf2a4' was expected.
Do you have an idea of what happends?
Thank you!
This is not really an issue, but rather an announcement:
I have moved out my proposed xled additions (previously in pull request #80) into its own repository xled_plus. It adds features on top of xled for creating different types of effects on your lights, removing the need to use the (rather limited and awkward) app for that.
There is a discussion forum there too, which we can use to discuss both xled and xled_plus things (which doesn't fit better here as issues of course). I will, as a kind of "advent calendar", publish daily effects there, starting tomorrow Dec 1.
You are welcome to check it out!
Hey, I found a way to use the library on Mac, didn't I send you a pull request? I would offer to test and maintain this package for Mac if that's ok with you.
Can you give an example of how to discover multiple devices please? Names/MAC/IP data is not known.
When I try to install xled on MacOS, I get
Abort trap: 6
during pip3 install xled
Installation on Linux works without a problem.
The reverse engineered documentation of the Twinkly API talks about an operating mode "rt - receive effect in real time".
This is intriguing but the API doesn't seem to have any way to actually send the data.
(If you were to point me in approximately the right direction, I could probably send you a pull request to accomplish this...)
Trying to use discovery with CLI ends up in loop tracebacks:
$ xled off
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib64/python3.4/threading.py", line 911, in _bootstrap_inner
self.run()
File "/usr/lib64/python3.4/threading.py", line 859, in run
self._target(*self._args, **self._kwargs)
File "…/xled/xled/discover.py", line 278, in start
pc.start()
File "…/.virtualenvs/[email protected]/lib/python3.4/site-packages/tornado-5.1.1-py3.4-linux-x86_64.egg/tornado/ioloop.py", line 1206, in start
self.io_loop = IOLoop.current()
File "…/.virtualenvs/[email protected]/lib/python3.4/site-packages/tornado-5.1.1-py3.4-linux-x86_64.egg/tornado/ioloop.py", line 282, in current
loop = asyncio.get_event_loop()
File "/usr/lib64/python3.4/asyncio/events.py", line 626, in get_event_loop
return get_event_loop_policy().get_event_loop()
File "/usr/lib64/python3.4/asyncio/events.py", line 572, in get_event_loop
% threading.current_thread().name)
RuntimeError: There is no current event loop in thread 'Thread-1'.
^C
Aborted!
Attempted to follow https://xled-docs.readthedocs.io/en/latest/rest_api.html#login, but when I issue a challenge I get an 1106 status code back from the lights.
I've attempted to packet sniff via Wireshark against a local android emulator running in Android Studio, but I couldn't get it to see the lights via the Twinkly app. I could however do the http://<ip>/xled/v1/gestalt URL, so it can definitely see the lights if you know where to look.
Any further ideas what to do to investigate how the login works now?
Cheers,
Stuart
TODO: figure out why or why not :)
I'm new here. I'm using Miniconda virtual environment. When I ruan following command it got frozen:
(xled) PS C:\Users\home> xled on
Looking for any device...
When I tried to specify the name of the device I got this:
(xled) PS C:\Users\home> xled --name Twinkly_71B12D on
Looking for a device with name: Twinkly_71B12D...
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Users\home\AppData\Local\Programs\Python\Python37\lib\threading.py", line 926, in _bootstrap_inner
self.run()
File "C:\Users\home\AppData\Local\Programs\Python\Python37\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\home\AppData\Local\Programs\Python\Python37\lib\site-packages\xled-0.6.1-py3.7.egg\xled\discover.py", line 370, in start
self.udp.handle.fileno(), self.handle_beacon, self.loop.READ
File "C:\Users\home\AppData\Local\Programs\Python\Python37\lib\site-packages\xled-0.6.1-py3.7.egg\xled\udp_client.py", line 59, in handle
_handle.bind(("", self.port))
OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
I've googled a bit and I saw something to do with port already used by other application. Any suggestion how to fix this?
Thanks in advance.
GitHub renders block fine:
Local run of Sphinx the same:
Even on PyPI it renders fine:
But on Read the Docs it is missing code blocks:
Problematic section:
Installation
------------
Both library and CLI tool are supported on Linux, primarily Fedora.
#. First make sure that you have `pip installed`_. E.g. for Fedora:
::
$ sudo dnf install python3-pip python3-wheel
#. You might want to `create and activate a virtual environment`_. E.g.:
::
$ mkdir -p ~/.virtualenvs
$ python3 -m venv ~/.virtualenvs/xled
$ source ~/.virtualenvs/xled/bin/activate
#. Install `xled from PyPI`_:
::
$ python3 -m pip install --upgrade xled
Turning lights on with CLI doesn't work after factory reset and before any movie is uploaded.
git checkout v0.6.1-21-g2eb4bbe
Gen I TW105SEUM06:
{
"product_name": "Twinkly",
"product_version": "2",
"hardware_version": "6",
"flash_size": 16,
"led_type": 5,
"led_version": "1",
"product_code": "TW105SEUM06",
"device_name": "Twinkly_XXXXXX",
"uptime": "2847430",
"rssi": -57,
"hw_id": "XXXXXXX",
"mac": "5c:cf:7f:XX:XX:XX",
"uuid": "00000000-0000-0000-0000-000000000000",
"max_supported_led": 255,
"base_leds_number": 105,
"number_of_led": 105,
"led_profile": "RGB",
"frame_rate": 25,
"movie_capacity": 719,
"copyright": "LEDWORKS 2017",
"code": 1000
}
Gen II TWS250STP
{
"product_name": "Twinkly",
"hardware_version": "100",
"bytes_per_led": 3,
"hw_id": "XXXXXX",
"flash_size": 64,
"led_type": 14,
"product_code": "TWS250STP",
"fw_family": "F",
"device_name": "Twinkly_XXXXXX",
"uptime": "1020612",
"mac": "24:0a:c4:xx:xx:xx",
"uuid": "XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXXX",
"max_supported_led": 510,
"number_of_led": 250,
"led_profile": "RGB",
"frame_rate": 30.3,
"movie_capacity": 1984,
"copyright": "LEDWORKS 2018",
"code": 1000
}
Gen II TWI190SPP
{
"product_name": "Twinkly",
"hardware_version": "100",
"bytes_per_led": 4,
"hw_id": "XXXXXX",
"flash_size": 64,
"led_type": 12,
"product_code": "TWI190SPP",
"fw_family": "G",
"device_name": "Twinkly_XXXXXX",
"uptime": "3542784",
"mac": "fc:f5:c4:xx:xx:xx",
"uuid": "XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXXX",
"max_supported_led": 1200,
"number_of_led": 190,
"led_profile": "RGBW",
"frame_rate": 27.78,
"movie_capacity": 992,
"wire_type": 4,
"copyright": "LEDWORKS 2018",
"code": 1000
}
TW105SEUM06:
{
"version": "2.3.8",
"code": 1000
}
TWS250STP:
{
"version": "2.2.1",
"code": 1000
}
TWI190SPP:
{
"version": "2.4.22",
"code": 1000
}
xled --name Twinkly_XXXXXX on
Lights turn on or error is printed.
$ xled --verbosity-cli DEBUG --verbosity-control DEBUG --verbosity-auth DEBUG --name Twinkly_XXXXXX on
Looking for a device with name: Twinkly_D49CED...
Working on requested device.
debug: HW address = 24:0a:c4:XX:XX:XX
debug: IP address = 192.168.1.248
debug: Turning on...
debug: Generated new state b'\xad\xbf\x8bMi\x90\x04\xc7K=\x1e\xb8,\xfb\xb8\x81\xe0\x12j\x84\x0c\x14F\x04\x9d\xa3\xb1N\x83\x94\xc3u'.
debug: ClientApplication(): Challenge: b'\xad\xbf\x8bMi\x90\x04\xc7K=\x1e\xb8,\xfb\xb8\x81\xe0\x12j\x84\x0c\x14F\x04\x9d\xa3\xb1N\x83\x94\xc3u'
debug: receive_authentication_token(): got token: 5e42MMP7h+A=
debug: challenge-response is correct.
debug: Requesting url http://192.168.1.248/xled/v1/led/mode using method POST.
debug: Supplying headers {'X-Auth-Token': '5e42MMP7h+A='}
debug: Passing through key word arguments {'data': None, 'json': {'mode': 'movie'}}.
Turned on.
But lights stay turned off
I have a strand of Twinkly lights (Model TWS250STP-GUS) that I wanted to try this API on however I can not get a simple "get" to function as intended. The light strand is connected to same Wi-Fi network as the Raspberry Pi and I can get requests such as "set_mode()", "set_brightness()", "turn_off()" and "turn_on()" to work however when I try "is_on()", the code always returns the except statement "Could not determine". I can not figure out how to get it to return "True" or "False". Code provided below:
import xled
host = ip_address #Redacted
def LightState():
try:
State = xled.HighControlInterface(host)
Power_State = State.is_on()
return Power_State
except:
return "Could not determine"
print (LightState())
I run into the same issue with "get_mode", "get_device_info()" or "get_device_name()". Reading through the documentation, I saw this specific product was not listed in hardware however I wanted to make sure I was not missing anything.
Does the API provide a way to toggle the USB music dongle on/off? It's their standalone mic, that picks up ambient sound (presumably from music playing nearby) and uses that to influence patterns on the lights. It'd be great to have on/off control of it.
The strips will fall back to using their saved playlist of lighting effects if the music is turned off.
nl_langinfo seems to be unsupported on Windows.
More curious on how you'd like to see this approached.
It's used at least in get-timer to format the times.
if sys.platform == 'win32':
format = "%H:%M:%S"
else:
format = locale.nl_langinfo(locale.T_FMT)
Thoughts appreciated.
When using xdiscover and having two devices on the network, the following example code causes an exception on the second next
call
devices = []
discovered_devices = xled.discover.xdiscover()
while True:
try:
device = next(discovered_devices)
devices.append(device)
except StopIteration:
break
return devices
ERROR:asyncio:Exception in callback BaseAsyncIOLoop._handle_events(24, 1)
handle: <Handle BaseAsyncIOLoop._handle_events(24, 1)>
Traceback (most recent call last):
File "/usr/local/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/events.py", line 88, in _run
self._context.run(self._callback, *self._args)
File "/Users/alex/.local/share/virtualenvs/wakeupcall-EJzfLl60/lib/python3.7/site-packages/tornado/platform/asyncio.py", line 138, in _handle_events
handler_func(fileobj, events)
File "/Users/alex/.local/share/virtualenvs/wakeupcall-EJzfLl60/src/xled/xled/discover.py", line 442, in handle_beacon
data, host = self._next_packet()
File "/Users/alex/.local/share/virtualenvs/wakeupcall-EJzfLl60/src/xled/xled/discover.py", line 421, in _next_packet
data, host = self.udp.recv(64)
File "/Users/alex/.local/share/virtualenvs/wakeupcall-EJzfLl60/src/xled/xled/udp_client.py", line 110, in recv
buf, addrinfo = self.handle.recvfrom(bufsize)
OSError: [Errno 9] Bad file descriptor
Received error:
error: Microsoft Visual C++ 9.0 is required. Get it from http://aka.ms/vcpython27
installed from that location and tried again, continued slightly further but got another error:
src/arpreq.c(3) : fatal error C1083: Cannot open include file: 'stdbool.h': No such file or directory
after some searching in Google, found this message and several other similar .h file errors pointing to header files that are for *nix not for Win32/64. I tried creating blank files for all the subsequent error'ing .h missing files and ended up with many other errors:
src/arpreq.c(42) : error C2054: expected '(' to follow 'inline'
src/arpreq.c(44) : error C2085: 'mac_to_string' : not in formal parameter list
src/arpreq.c(44) : error C2143: syntax error : missing ';' before '{'
src/arpreq.c(62) : error C2054: expected '(' to follow 'inline'
src/arpreq.c(63) : error C2085: 'address_from_long' : not in formal parameter list
src/arpreq.c(63) : error C2143: syntax error : missing ';' before '{'
src/arpreq.c(84) : error C2054: expected '(' to follow 'inline'
src/arpreq.c(85) : error C2085: 'address_from_bytes' : not in formal parameter list
src/arpreq.c(85) : error C2143: syntax error : missing ';' before '{'
src/arpreq.c(102) : error C2054: expected '(' to follow 'inline'
src/arpreq.c(103) : error C2085: 'address_from_unicode' : not in formal parameter list
src/arpreq.c(103) : error C2143: syntax error : missing ';' before '{'
src/arpreq.c(117) : error C2054: expected '(' to follow 'inline'
src/arpreq.c(118) : error C2085: 'coerce_argument' : not in formal parameter list
src/arpreq.c(118) : error C2143: syntax error : missing ';' before '{'
src/arpreq.c(179) : error C2079: 'ip_address' uses undefined struct 'sockaddr_in'
src/arpreq.c(181) : error C2224: left of '.sin_family' must have struct/union type
src/arpreq.c(181) : error C2065: 'AF_INET' : undeclared identifier
src/arpreq.c(182) : warning C4013: 'coerce_argument' undefined; assuming extern returning int
src/arpreq.c(182) : error C2224: left of '.sin_addr' must have struct/union type
src/arpreq.c(186) : error C2065: 'uint32_t' : undeclared identifier
src/arpreq.c(186) : error C2146: syntax error : missing ';' before identifier 'addr'
src/arpreq.c(186) : error C2065: 'addr' : undeclared identifier
src/arpreq.c(186) : error C2224: left of '.sin_addr' must have struct/union type
etc (there were many more than that)...
Clearly this isn't the right way to work around the system for a Windows build, so any other guidance for a python/pip novice?
Usually when there are network issues the driver raises an exception, but sometimes it just hangs forever.
Tried with both the most recent pip version, and HEAD here.
[I skipped the device information because I can't get it right now, but I will if necessary.]
Darwin bantam.local 19.6.0 Darwin Kernel Version 19.6.0: Thu Sep 16 20:58:47 PDT 2021; root:xnu-6153.141.40.1~1/RELEASE_X86_64 x86_64
Linux raspberrypi 5.10.63-v7+ #1459 SMP Wed Oct 6 16:41:10 BST 2021 armv7l GNU/Linux
Python 3.6.6, also tried 3.8.x on Mac
On RP, 3.9.1
I've been running this driver 24/7 for over a month, on two different machines.
I thought my network was solid, but it seems there are occasional short outages which I never notice (e.g. when watching Netflix). (In my experience, this is typical of home systems.)
After a day or two, one of three different behaviors seems to happen:
GOOD:
File "/code/xled/xled/control.py", line 1314, in show_rt_frame
self.set_rt_frame_socket(frame, 3)
File "/code/xled/xled/control.py", line 893, in set_rt_frame_socket
self.udpclient.send(packet)
File "/code/xled/xled/udp_client.py", line 95, in send
return self.handle.sendto(message, 0, (self.destination_host, self.port))
OSError: [Errno 101] Network is unreachable
GOOD:
File "/Users/tom/synthetic/code/xled/xled/control.py", line 1314, in show_rt_frame
self.set_rt_frame_socket(frame, 3)
File "/Users/tom/synthetic/code/xled/xled/control.py", line 893, in set_rt_frame_socket
self.udpclient.send(packet)
File "/Users/tom/synthetic/code/xled/xled/udp_client.py", line 95, in send
return self.handle.sendto(message, 0, (self.destination_host, self.port))
OSError: [Errno 65] No route to host
BAD: nothing - it just hangs and the animation stops working, and there is no output.
I reran both programs with --verbose
and I'll let you know what happens. This should also give me a stack trace when I break out of the hanging program, which was before suppressed by the calling program.
There will probably be more information coming, but I wanted to get all this down to start with to see if this were familiar to you!
Thanks again for an excellent program.
This is a question rather than an issue.
I have been experimenting with using CLI from shell scripts and it is working well.
However, the discovery process seems to take between 2 and 4 seconds ... so I modified cli.py to support passing in a MAC address ... and if the host address (ip address) and new mac address are given on the command line then I skip the discovery phase and use the given parameters.
This does mean that the device name is not known as a result of discovery ... but are there any other consequences that you can think of that could cause problems?
For cli it is a fire once and exit function - so the background discovery functionality should not matter.
Of course, the user might get the parameters incorrect - but that is easily fixed by the user.
This may only be a documentation issue. The private protocol documentation sets out the movie format, and a few words about how it's uploaded (https://xled.readthedocs.io/en/latest/protocol_details.html#upload-full-movie-led-effect), but I can't see the ability to actually upload it in the Python xled package. Nor does the API reference make this very clear.
Am I missing something (I know very little python) or is this not implemented yet?
Thanks very much for your work on this so far though - it's appreciated.
The bot created this issue to inform you that pyup.io has been set up on this repo.
Once you have closed it, the bot will open pull requests for updates as soon as they are available.
hi guys,
i'm looking into an API method to control those leds brightness (equivalent of brightness slider in the app). anyone?
Install on OS X fails:
use of undeclared identifier 'SIOCGIFHWADDR'
Is this a known issue?
It would be super helpful if you could publish an example movie file that can be uploaded onto the Twinkly lights and played.
It would also be great if there was a file or directions on how to send real time data to the Twinkly's.
I am trying to get these lights to run the way I want them to, not based on the lame animations that come with the iPhone App!
Thanks!
Hi, guys
Not an issue of this library (btw, I like the old single file version more, now it become a monster) but the xled
protocol itself.
The problem happen with device polling (check mode and brightness from time to time). It kills mobile app session because of auth token changed. This way its not possible to setup new effects etc when some smarthome controller polling the device.
Any ideas?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.