Category: Hardware

Controlling Elgato Key Light under Ubuntu with Ruby

Recently I've acquired Elgato Key Light. It is a WiFi controllable LED lighting panel.

The panel uses 160 LEDs to provide up to 2800 lumens of brightness and a color range of 2900-7000K. While you can control it from a mobile device, doing it directly from the shell makes the whole experience way more convenient.

Key Light officially does not support Linux, however it uses ESP32, and it does run an unprotected HTTP server that accepts JSON commands. You can not only turn it on and off but also adjust both light temperature and brightness with simple JSON requests.

Here's the code that I use to control my lights written in Ruby:

#!/usr/bin/env ruby

require 'uri'
require 'net/http'
require 'json'
require 'yaml'

# Set your lights IPs
LIGHTS = %w[
  192.168.0.199
]

COMMAND = ARGV[0]
DETAIL1 = ARGV[1].to_i
DETAIL2 = ARGV[2].to_i

# Sends a json request to a given elgato light
def dispatch(ip, payload, endpoint, method)
  uri = URI("http://#{ip}:9123/elgato/#{endpoint}")
  req = method.new(uri)
  req.body = payload.to_json

  res = Net::HTTP.start(uri.hostname, uri.port) do |http|
    http.request(req)
  end

  puts res.body
end

def on(light_ip)
  dispatch(
    light_ip,
    { 'numberOfLights': 1, 'lights': [{ 'on': 1 }] },
    'lights',
    Net::HTTP::Put
  )
end

def off(light_ip)
  dispatch(
    light_ip,
    { 'numberOfLights': 1, 'lights': [{ 'on': 0 }] },
    'lights',
    Net::HTTP::Put
  )
end

def temperature(light_ip, value)
  raise "Needs to be between 143 and 344, was: #{value}" if value < 143 || value > 344

  dispatch(
    light_ip,
    { 'numberOfLights': 1, 'lights': [{ 'on': 1, 'temperature': value }] },
    'lights',
    Net::HTTP::Put
  )
end

def brightness(light_ip, value)
  raise "Needs to be between 3 and 100, was: #{value}"  if value < 3 || value > 100

  dispatch(
    light_ip,
    { 'numberOfLights': 1, 'lights': [{ 'on': 1, 'brightness': value }] },
    'lights',
    Net::HTTP::Put
  )
end

def info(light_ip)
  dispatch(
    light_ip,
    {},
    'accessory-info',
    Net::HTTP::Get
  )
end

def command(command, light_ip)
  case command
  when 'on'
    on(light_ip)
  when 'off'
    off(light_ip)
  when 'temperature'
    temperature(light_ip, DETAIL1)
  when 'brightness'
    brightness(light_ip, DETAIL1)
  when 'theme'
    temperature(light_ip, DETAIL1)
    brightness(light_ip, DETAIL2)
  when 'info'
    info(light_ip)
  else
    raise "Unknown COMMAND #{COMMAND}"
  end
end

LIGHTS.each { |light_ip| puts command(COMMAND, light_ip) }

You can place this code in /usr/local/bin under elgato name with executable permissions and then you can just:

elgato on # turn your lights on
elgato off # turn your lights off
elgato info # get info on your lights
elgato brightness 50 # set brightness to 50%
elgato temperature 280 # make  light temperature quite warm

Extracting the device token from Xiaomi Air Purifier 2S EU for Domoticz usage

Xiaomi Air Purifier is one of the best on the market in the price/value category. Like many other Xiaomi devices, it can be controlled using a great home automation system called Domoticz.

The only problem that I had is that for the 2S version, there is no way to obtain the device token needed for controlling the device using the miIO library.

Here are the steps needed to obtain this token using a Linux machine and a non-rooted Android phone.

Getting the Mi Home data backup

  1. Download and install the Mi Home application. You need to have the 5.0.19 version of this app. The newer versions don't persist the token locally in the SQLite database. You can get it from the APKMirror page. Note, that you will have to allow the Unknown sources to do that. Here's a description on how to do that.
  2. Enable developer mode and USB debugging on your phone (instruction).
  3. Download and extract the Android Platform tools for Linux from here.
  4. Install the most recent Java version if you don't have it.
  5. Enable developer mode and USB debugging on your phone and connect it to your computer.
  6. Unlock the phone and allow the computer for data transfers (not USB charging only).
  7. Authorize the Linux machine on your Android phone.
  8. Run the following command from your Linux machine:
    ./adb backup -noapk com.xiaomi.smarthome -f backup.ab
    
  9. Unlock your device and confirm the backup operation. If your phone is encrypted, you will also have to provide the backup password.
  10. If everything went smooth, you should have a backup.ab file in the platform tools for further processing. From this moment, you won't need the phone to be connected to your laptop.

Getting the device token out of the Mi Home backup

  1. Download and unpack the ADB extractor.
  2. Navigate to the android-backup-tookit/android-backup-extractor/android-backup-extractor-20180521-bin directory.
  3. Copy the abe.jar file to where your backup.ab is.
  4. Run the following command and follow the instructions (if any):
    java -jar abe.jar unpack backup.ab backup.tar
    
  5. Unpack the extracted backup:
    tar -xvf backup.tar
    
  6. Go to the apps/com.xiaomi.smarthome/db directory.
  7. Install and run the DB Browser for SQLite:
    sudo apt-get install sqlitebrowser
    
  8. Open the miio2.db file using the DB Browsers for SQLite.
  9. Click on the Execute SQL tab and run the following query:
    SELECT localIP, token FROM devicerecord
    

    As a result, you will get a list of the tokens with the IPs of the devices in your networks to which they belong (I've blurred the tokens just in case in the picture):

Now you can take the appropriate token and use it within your Domoticz setup.

Copyright © 2022 Closer to Code

Theme by Anders NorenUp ↑