Reverse Engineering a LumeCube

One of our upcoming hardware projects (more on this later) requires a very bright, controllable light source. In the past, we’ve just used bare LEDs with our own cooling, power, control, etc. Not being someone who really understands how electricity works though, it always feels like a hassle to get a reliable setup. For this project, we instead decided to just give a LumeCube a try. They’re far from cheap, but they’re very bright, and hopefully have rock solid reliability.

LumeCube has an iOS app which allows for control over bluetooth. Although it also has a USB port, that’s only used for charging. We wanted to be able to do basic brightness control from within the Python application that will run the rest of the hardware. It doesn’t appear anyone has gone to the trouble of reverse engineering the LumeCube before, so we figured we’d give it a go. There were just two challenges:

  1. We’ve never reverse engineered a Bluetooth communications protocol.
  2. We don’t really understand how Bluetooth works.

Sticking with our philosophy of obtaining minimum-viable-knowledge, we started Googling “how to reverse engineer a bluetooth device” and ended up on this Medium post by Uri Shaked. Uri pointed us towards the “nRF Connect” app, which allows you to scan for Bluetooth devices and enumerate all of their characteristics (look at me using the lingo).

Acting on the assumption that LumeCube wasn’t going to go out of their way to secure their Bluetooth connection, we assumed brightness control would be pretty straightforward. It was just a matter of tracking down the characteristic ID and the structure of the data. To do that, we began by listing all of the characteristics in nRF Connect. Then we would disconnect and launch the official app. From there, we could adjust the brightness, then flip back to nRF Connect, rescan the characteristics, and see what had changed.

The relevant characteristic popped out very quickly. The third byte of 33826a4d-486a-11e4-a545-022807469bf0 varied from 0x00 to 0x64, or 0-100. Writing new values back to that characteristic confirmed that hunch – huzzah!

Once we’d identified the characteristic, it was just a matter of implementing some controls in Python. For that we used Bleak, which offers good documentation and cross-platform support. Below is a quick example that turns brightness to 100 (0x64).

import asyncio
import logging
from bleak import BleakClient

address = "819083F8-A230-4F61-8F94-CB69FF63D340"
LIGHT_UUID = "33826a4d-486a-11e4-a545-022807469bf0"
#logging.basicConfig(level=logging.DEBUG)

async def run(address):
    async with BleakClient(address) as client:
        await client.write_gatt_char(LIGHT_UUID, bytearray(b"\xfc\xa1\x64\x00"), True)
loop = asyncio.get_event_loop()
loop.run_until_complete(run(address))

2015 Alfa Romeo 4C Coupe

I’m selling my 2015 Alfa Romeo 4C Coupe in Rosso Alfa over black leather. The car has 13,262 miles and I’m asking $42,000 OBO.

I’m the original owner for this car – I waited patiently (kind of) for the non-LE cars so that I could spec it myself, and took delivery in August 2015. I’m selling because I bought a 1979 Alfa Spider in the fall, and we don’t have space to keep both “fun” cars.

The car has always been serviced at Alfa Romeo of Minneapolis (the selling dealer) and has followed the Alfa servicing guide. Last year it had its 5 year service, including the timing belt and water pump. It’s only ever needed routine servicing.

I’ve used this car as my daily driver during summer months, as well as for road trips around Minnesota. I had the car fully wrapped in paint protection film after purchasing, so that we could go on adventures without worrying about a stray stone or an unexpected gravel road. It’s a ridiculous car which can’t help but make you giggle, with its absurd turbo whooshes and exhaust growl. Surprisingly comfortable for longer distances as well, with cruise control, bluetooth, and decent seats.

Spec

  • Rosso Alfa over black leather
  • Silver 5-hole 18″/19″ wheels
  • Red calipers
  • “Standard package” (Race exhaust, Bi-Xenon, cruise control, park assist, “premium” audio)
  • Window sticker

Modifications

  • Full body 3M Pro self healing paint protection film (PPF). Covers every panel, including the headlights.
  • Alfaworks UK “Helmholtz” exhaust with carbon tips (reduces highway drone). Sale includes the stock “race” exhaust as well.
  • Carbon fiber shift paddle extensions (snap on / snap off)

Condition

  • The rear tires were replaced in mid-2019 and have about 2500 miles on them. The fronts are original and have plenty of life left.
  • Car is mechanically perfect – it’s never had a problem.
  • There are a few nicks in the paint protection film, where it has sacrificed itself to a stone. They’re detailed in the photos. There’s also a spot at the rear where the film has lifted a bit – this could be trimmed back. I’ve taken the “don’t pull on a scab” approach.
  • There’s one nick in the passenger rear wheel, where I shamefully clipped a curb.

Incident history

When the PPF was originally fitted, a quarter-sized bit of clear coat lifted and had to be repaired (see thread). In 2016, I was an idiot and cracked the passenger side side-sill while putting the car on ramps. The piece was removed and repaired. In 2017, the car was rear-ended in stop-and-go traffic. Repair involved replacing the rear bumper cover and lower diffuser. After repair, the rear bumper was re-PPF’d.

Miscellaneous Other Stuff

The sale includes everything I got with the car – the car cover, charger, manuals, keys, etc. I believe I’ve also got various bits of swag that Alfa sent early owners, which I’m happy to pass on.

For more information, contact me via cmcfadden@gmail.com.

Photos

In addition to the gallery below, you can download the full resolution images.

Faults