code
Controlling My Office Light with Natural Language (A Weekend Tinkering Story)
"Starting with an NMAP Scan The first thing I did was scan the light's IP address to see what it was exposing."
Wtih today being a holiday (Good Friday) and a chance to finally start to tackle my "todo" list around the house I installed a new smart light in my office, an Artika Skyshade I picked up from Costco about 6 months ago (it's been on the todo list for a while.....). Like most smart lights sold today, it ships with the expectation that you'll use the manufacturer's app, route everything through the cloud, and never think about what's actually happening on your local network. I had other plans.
What started as idle curiosity ("can I talk to this thing locally?") turned into a surprisingly satisfying afternoon project: building a custom MCP server that lets me control my office light using plain English through Claude. Is it practical? Not really. Is it cool? Absolutely.
Starting with an NMAP Scan
The first thing I did was scan the light's IP address to see what it was exposing. The results were interesting. Port 6668 was open, which nmap identified as IRC. On a smart light, that's obviously not IRC. It's the Tuya local control protocol port. Port 53 was also open, which is unusual for an IoT device and suggests it's running a local DNS responder to handle its own cloud traffic.
A quick search for the model number (FLP14-SSWTR-C1WH) confirmed what the port scan hinted at: this device runs a BK7231N (Beken) chip and uses Tuya firmware. The community has documented hundreds of teardowns of this exact device. That meant two things. First, local control was definitely possible. Second, I wouldn't need to reflash anything to get it working.
Getting the Local Key
For those not familiar, Tuya devices communicate locally using an encrypted protocol. To talk to the device on your own LAN without going through Tuya's cloud, you need three pieces of information: the device ID, the device's IP address (easy enough to find), and the "local key," which is essentially the encryption key the device uses for local communication.
The local key extraction process involves creating an account on the Tuya Developer Platform, setting up a cloud project, and linking your Tuya/Smart Life app account to expose your devices in the developer portal. Remco Kersten's guide walks through the whole process clearly. It's a bit tedious but straightforward, and once you have the key, you're done with the cloud forever (or at least until the key rotates).
Talking to the Light with Python
With the device ID, IP, and local key in hand, I used tinytuya, a Python library for local Tuya device control. After one false start with protocol version 3.3 (the device actually speaks 3.4), I had a working connection and could see the device's data points:
{'dps': {'20': True, '21': 'white', '22': 1000, '23': 0, '24': '000003e803e8', '25': '000e0d0000000000000000c80000', '26': 0}}
Each data point (DP) maps to a specific function: DP 20 is power on/off, DP 21 is the mode (white, colour, scene), DP 22 is brightness on a 10-1000 scale, DP 23 is colour temperature (0 for warm, 1000 for cool), and DP 24 is an HSV colour value encoded as a hex string. From here, controlling the light locally was just a matter of setting values.
Building the MCP Server
So what can we do about this? The whole point was to talk to the light in English, not send raw Python commands. That's where MCP (Model Context Protocol) comes in. MCP lets you expose tools that Claude can call directly, so I wrapped the tinytuya calls in a simple MCP server using the mcp Python library's FastMCP helper.
The server exposes six tools: get the light's current status, turn it on or off, set brightness, set colour temperature, set an RGB colour, and activate named "scenes" (like focus, relax, energize, and bedtime, each mapping to specific brightness and temperature presets). The whole thing is about 90 lines of Python.
The RGB-to-Tuya conversion is the only mildly interesting bit. Tuya expects HSV values packed into a hex string (HHHHSSSSVVVV format, with hue 0-360 and saturation/value 0-1000), so the server handles the conversion from the RGB values that Claude naturally thinks in.
Wiring it into Claude Desktop is one JSON block in claude_desktop_config.json:
{
"mcpServers": {
"office-light": {
"command": "python3.10",
"args": ["/path/to/light_mcp.py"]
}
}
}
Restart Claude Desktop, and suddenly you can say things like "set the light to a warm dim glow" or "change it to blue" or "put it in focus mode" and Claude figures out the right tool calls. The tool descriptions do the heavy lifting. Claude maps natural language to the correct function and parameters without you needing to be precise about numbers or modes.
Let's Be Honest About What This Is
The bottom line is this: this is not Home Assistant. It's not even close. Home Assistant gives you automations, dashboards, device grouping, presence detection, and integrations with hundreds of device types. It's a proper home automation platform, and setting it up properly is still on my to-do list.
What this is, though, is a fun weekend project that gives you natural language control of a single device with minimal setup. No Docker containers, no YAML files, no add-on store, no learning curve beyond "install two Python packages and write 90 lines of code." If you already have Claude Desktop running and you want to see what local IoT control feels like without committing to a full home automation stack, this is a satisfying way to spend an afternoon.
There's something undeniably fun about sitting at your desk and typing "make it warmer and a bit dimmer" and watching your office light shift in response. Impractical? Sure, I could just reach for the remote. But as a proof of concept for what MCP can do, and as a first step toward understanding your devices' local protocols, it's a worthwhile exercise.
What's Next
Home Assistant is the obvious next step, and when I get around to it, the localtuya integration will let me bring this light (and any future Tuya devices) into a proper automation setup. The OpenBeken reflash path is also tempting for eliminating the Tuya cloud dependency entirely, since the BK7231N chip is well-supported and the pin mapping is documented.
But for now, I'm enjoying telling Claude to set my light to "focus mode" when I sit down to work. It's a small thing, but it's my small thing, running locally, no cloud required.
Topics: