scrool/xled

Turn device on doesn't work after factory reset

Closed this issue · 3 comments

Summary

Turning lights on with CLI doesn't work after factory reset and before any movie is uploaded.

Affected XLED components

  • Command Line Interface (CLI)
  • Libary
  • Documentation
  • Other

XLED version

git checkout v0.6.1-21-g2eb4bbe

Twinkly device details

Device information

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
}

Firmware version

TW105SEUM06:

{
  "version": "2.3.8",
  "code": 1000
}

TWS250STP:

{
  "version": "2.2.1",
  "code": 1000
}

TWI190SPP:

{
  "version": "2.4.22",
  "code": 1000
}

Operating system

  • Fedora release 32 (Thirty Two)
  • Fedora release 33 (Thirty Three)

Python version

  • Python 3.8.6
  • Python 3.9.1

Steps to reproduce

  1. factory reset the device
  2. connect to its AP or connect it to WiFi so it can be controlled
  3. run: xled --name Twinkly_XXXXXX on

Expected behavior

Lights turn on or error is printed.

Actual results

$ 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

Additional information

Apparently return value isn't passed across multiple layers. And in the end CLI tool doesn't check return value.

With this quick debug:

diff --git a/xled/cli.py b/xled/cli.py
index 905bc8a..c369d92 100644
--- a/xled/cli.py
+++ b/xled/cli.py
@@ -104,7 +104,8 @@ def get_mode(ctx):
 def turn_on(ctx):
     control_interface = common_preamble(ctx.obj.get("name"), ctx.obj.get("hostname"))
     log.debug("Turning on...")
-    control_interface.turn_on()
+    retval = control_interface.turn_on()
+    click.echo(retval.status_code)
     click.echo("Turned on.")
 
 
diff --git a/xled/control.py b/xled/control.py
index 072e444..7a42b17 100644
--- a/xled/control.py
+++ b/xled/control.py
@@ -329,6 +329,7 @@ class ControlInterface(object):
         app_response = ApplicationResponse(response)
         required_keys = [u"code"]
         assert all(key in app_response.keys() for key in required_keys)
+        return app_response
 
     def set_led_movie_full(self, movie):
         """

An status code: 1104 is printed.

Application apparently continues with call:

{
"mode": "effect",
"effect_id": 0
}

I guess CLI tool/high level interface should do the same.

I stumbled upon this myself, and think I understand why it happens:

After factory reset, the led movie config parameters "frame_delay" and "frames_number" are both set to zero, because of course there is no movie uploaded yet. In this situation it refuses to go into "movie" mode, which actually makes sense.

In my resent pull request #80 to enhance the control interface I have included a fix for this. What I do to handle it is twofold:

First, when uploading a movie, the commands are run in the reverse order to the previous code: first set the movie parameters, then upload the movie, and finally switch to movie mode. Then it works fine, also the first time, since the movie is uploaded when trying to switch the mode.

Second, when running "turn_on", the new code tries to remember what mode was used last and returns to that, unless it is the first time, in which case the code checks the movie parameters and only goes to movie mode if there is a non-zero number of uploaded frames, and goes to "effects" mode otherwise (which seems to be the default mode after factory reset, and consistent with the log above).

/ Anders Holst

After factory reset, the led movie config parameters "frame_delay" and "frames_number" are both set to zero, because of course there is no movie uploaded yet. In this situation it refuses to go into "movie" mode, which actually makes sense.

@Anders-Holst I have looked into this and indeed these two values are set to 0. On the top of that, while frames_number could be set to 0 by API, frame_delay doesn't accept 0 so it would be possible to determine factory reset out from this heuristic.

But in the end I have looked into traffic from the app (3.3.8) against device with lowest FW version I got handy (2.6.2) and it clearly tries to set mode: "playlist", if that doesn't work it continues with "movie" and if that doesn't work either it ends up with "effect".

Rather than using heuristic and internal state, which CLI wouldn't use, I ended up implementing the same logic in #124.