Post

LG ThinQ API control devices

LG ThinQ API control devices

Air conditioner I’m fortunate enough to have air conditioning units installed at my house. It was one of the first things I had installed when I moved in, as coming from my previous super-warm flat, it was pretty horrible in summer just relying on fans to blow some hot air around. When I think of air conditioners, I think of cooling a room, not heating it. However, the great thing about these air conditioners is that they also blow hot air.

During the recent cold spell in the UK, my heating bill has been extortionate, as it’s currently heated by gas. Even keeping the house at 18 degrees maximum in the morning has cost me a fair bit. So when I’ve been working in my office, I’ve kept my door closed and have been putting the air conditioning on to get it up to a reasonable temperature. However, one of the issues I’ve found is that no matter what temperature I set it on, for example, 21 degrees, the air conditioner keeps heating until I turn it off. I’ve been manually doing this via the remote control or the LG App on my phone. But, as an engineer, I know there must be a better way to do this.

Enter the LG API!

There are two different places I’ve found for LG ThinQ documentation

  1. https://smartsolution.developer.lge.com/en/apiManage/thinq_connect
  2. https://thinq.developer.lge.com/en/cloud/docs/thinq-connect/api-reference/device-api/

I’ve found that the 1st one is the more accurate and up-to-date documentation - and even that isn’t particularly helpful or easy to understand. I think the 2nd link must be old documentation.

My objectives

  1. To turn on the air con, when the temperature is below 20 degrees
  2. To turn off the air con, when the temperature is above 20 degrees
  3. To retain control of the script, so only when I run it, the above will work

So, what did I end up with? (click here to see full script and skip breakdown)

The breakdown

First off, lets setup some basic variables

1
2
3
4
5
6
7
8
9
import requests
import time

ACCESS_TOKEN = "your_pat_here"
DEVICE_ID = "1234"
API_BASE_URL = "https://api-eic.lgthinq.com/" # You may need to change this - see the API docs

TEMP_THRESHOLD = 20  # Celsius
CHECK_INTERVAL = 300  # 5 minutes in seconds
  1. ACCESS_TOKEN: can be generated from here - there’s also a link on the API documentation
  2. DEVICE_ID: this is the device we’ll be controlling - but we can leave that as is for now, as we’ll be calling the API first to get the ID
  3. API_BASE_URL: I’m in the UK, so my base URL is the Europe one. See the docs for other base URLs

Now we have that, let’s get the list of available devices (note: the x-api-key, x-message-id etc I don’t think are used, so anything is ok here? I’ve taken these values straight from the documentation.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def headers():
    return {
        "Authorization": f"Bearer {ACCESS_TOKEN}",
        "Content-Type": "application/json",
        "x-api-key": "v6GFvkweNo7DK7yD3ylIZ9w52aKBU0eJ7wLXkSR3",
        "x-country": "GB",
        "x-message-id": "fNvdZ1brTn-wWKUlWGoSVw",
        "x-client-id": "test-client-123456"
    }
    
def list_devices():
    url = f"{API_BASE_URL}devices"
    response = requests.get(url, headers=headers())
    response.raise_for_status()
    print(response.status_code)
    print(response.json())
    devices = response.json().get("response", [])
    print("Available Devices:")
    for device in devices:
        print(f"ID: {device.get('deviceId')}, Name: {device.get('deviceInfo')['alias']}, Type: {device.get('deviceInfo')['deviceType']}")
    return devices

Once you have found the device ID you want to control, you can update the DEVICE_ID above.

The script below is for heating a room, so if you wanted to cool a room instead, you’d have to flip the logic around the current_temp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
def get_device_status(device_id):
    url = f"{API_BASE_URL}devices/{device_id}/state"
    response = requests.get(url, headers=headers())
    response.raise_for_status()
    return response.json()['response']

def set_device_operation(device_id, operation_mode):
    url = f"{API_BASE_URL}devices/{device_id}/control"
    payload = {
        "operation": {'airConOperationMode': operation_mode } # "on" or "off"
    }
    response = requests.post(url, headers=headers(), json=payload)
    response.raise_for_status()
    return response.json()

def control_aircon():
    while True:
        try:
            # Get the current status of the air conditioner
            status = get_device_status(DEVICE_ID)
            # print(status)
            # exit(1)
            current_temp = status.get("temperature")['currentTemperature']
            ac_power_state = status.get("operation")['airConOperationMode']

            print(f"Current room temperature: {current_temp}°C")
            print(f"AC power state: {ac_power_state}")
            print(f"Threshold: {TEMP_THRESHOLD}")

            if current_temp > TEMP_THRESHOLD and ac_power_state == "POWER_ON":
                print("Temperature is above the threshold. Turning off the air conditioner.")
                set_device_operation(DEVICE_ID, "POWER_OFF")

            elif current_temp < TEMP_THRESHOLD and ac_power_state == "POWER_OFF":
                print("Temperature is below the threshold. Turning on the air conditioner.")
                set_device_operation(DEVICE_ID, "POWER_ON")

            for remaining in range(CHECK_INTERVAL, 0, -1):
                print(f"\rWaiting {remaining} seconds...", end="")
                time.sleep(1)

        except Exception as e:
            print(f"An error occurred: {e}")
            time.sleep(CHECK_INTERVAL)

if __name__ == "__main__":
    control_aircon()
    # list_devices()

Full script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import requests
import time

# LG ThinQ API credentials
ACCESS_TOKEN = "your_pat_here"
DEVICE_ID = "1234"
API_BASE_URL = "https://api-eic.lgthinq.com/" # You may need to change this - see the API docs

# Threshold temperature
TEMP_THRESHOLD = 20  # Celsius
CHECK_INTERVAL = 300  # 5 minutes in seconds

def headers():
    return {
        "Authorization": f"Bearer {ACCESS_TOKEN}",
        "Content-Type": "application/json",
        "x-api-key": "v6GFvkweNo7DK7yD3ylIZ9w52aKBU0eJ7wLXkSR3",
        "x-country": "GB",
        "x-message-id": "fNvdZ1brTn-wWKUlWGoSVw",
        "x-client-id": "test-client-123456"
    }

def list_devices():
    url = f"{API_BASE_URL}devices"
    response = requests.get(url, headers=headers())
    response.raise_for_status()
    print(response.status_code)
    print(response.json())
    devices = response.json().get("response", [])
    print("Available Devices:")
    for device in devices:
        print(f"ID: {device.get('deviceId')}, Name: {device.get('deviceInfo')['alias']}, Type: {device.get('deviceInfo')['deviceType']}")
    return devices

def get_device_status(device_id):
    url = f"{API_BASE_URL}devices/{device_id}/state"
    response = requests.get(url, headers=headers())
    response.raise_for_status()
    return response.json()['response']

def set_device_operation(device_id, operation_mode):
    url = f"{API_BASE_URL}devices/{device_id}/control"
    payload = {
        "operation": {'airConOperationMode': operation_mode } # "on" or "off"
    }
    response = requests.post(url, headers=headers(), json=payload)
    response.raise_for_status()
    return response.json()

def control_aircon():
    while True:
        try:
            # Get the current status of the air conditioner
            status = get_device_status(DEVICE_ID)
            # print(status)
            # exit(1)
            current_temp = status.get("temperature")['currentTemperature']
            ac_power_state = status.get("operation")['airConOperationMode']

            print(f"Current room temperature: {current_temp}°C")
            print(f"AC power state: {ac_power_state}")
            print(f"Threshold: {TEMP_THRESHOLD}")

            if current_temp > TEMP_THRESHOLD and ac_power_state == "POWER_ON":
                print("Temperature is above the threshold. Turning off the air conditioner.")
                set_device_operation(DEVICE_ID, "POWER_OFF")

            elif current_temp < TEMP_THRESHOLD and ac_power_state == "POWER_OFF":
                print("Temperature is below the threshold. Turning on the air conditioner.")
                set_device_operation(DEVICE_ID, "POWER_ON")

            for remaining in range(CHECK_INTERVAL, 0, -1):
                print(f"\rWaiting {remaining} seconds...", end="")
                time.sleep(1)

        except Exception as e:
            print(f"An error occurred: {e}")
            time.sleep(CHECK_INTERVAL)

if __name__ == "__main__":
    control_aircon()
    # list_devices()
This post is licensed under CC BY 4.0 by the author.