Logic Machine Forum
Has someone already integrated LG ThinQ - Printable Version

+- Logic Machine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Gateway (https://forum.logicmachine.net/forumdisplay.php?fid=10)
+--- Thread: Has someone already integrated LG ThinQ (/showthread.php?tid=4752)



Has someone already integrated LG ThinQ - Joep - 06.05.2023

Hi All,

I like to integrate my LG devices like AC for example by the LG Thinq API. Has someone already done this and could share the script here?
I found a start at this website https://forum.fibaro.com/topic/51441-hc3-with-lg-smartthinq/ with the script below. Would be great if we can get it to work.

The script berlow is not mine but copied from the website i shared. It seems you'll need a secret key and client key but i'm not sure where to get it as i could not find clear information about it. So all help is much appriciated to get this work.

Code:
OAUTH_SECRET_KEY = "c053c2a6ddeb7ad97cb0eed0dcb31cf8"
OAUTH_CLIENT_KEY = "LGAO221A02"
DATE_FORMAT = "!%a, %d %b %Y %H:%M:%S"
V2_AUTH_PATH = "/oauth/1.0/oauth2/token"

function oauth2_signature(message, secret)
    local hmac = sha.hmac
    local hashed = hmac(sha.sha1, secret, message)
    local binary_hash = sha.hex2bin(hmac(sha.sha1, secret, message))
    return sha.bin2base64(binary_hash)
end

function auth_request(oauth_url, reqdata)
    if string.sub(oauth_url, -1):lower() == "/" then  oauth_url = string.sub(oauth_url, 0, #oauth_url-1) end
    local url = oauth_url .. V2_AUTH_PATH
    local timestamp = tostring(os.date(DATE_FORMAT, os.time())) .. " +0000"
    local data_list = {}
    for k, v in pairs(reqdata) do  table.insert(data_list, string.format("%s=%s", k, v)) end
    local req_url = string.format("%s?%s", V2_AUTH_PATH, table.concat(data_list, "&"))
    local message = string.format("%s\n%s", req_url, timestamp)
    local sig = oauth2_signature(message, OAUTH_SECRET_KEY)
    local headers = {
        ["x-lge-appkey"] = OAUTH_CLIENT_KEY,
        ["x-lge-oauth-signature"] = sig,
        ["x-lge-oauth-date"] = timestamp,
        ["Content-Type"] = "application/x-www-form-urlencoded",
        ["Accept"] = "application/json"
    }
    castdata = table.concat(data_list, "&")
    self.http:request(url,{
        options = {
            headers = headers,
            data = castdata,
            method = "POST",
            timeout = 5000,
        },
        success = function(response)
            log("auth_request success", response.data)
        end,
        error = function(error)
            self:debug('error: ' .. json.encode(error))
        end
    })
   end
   local requestBody = {
        grant_type = "refresh_token",
        refresh_token = "4ed29cb48cc1cb6228658d50817b789d67d37dbad56bf561cc6389a4ab69070d8ee808edb3377ad3b07e243c467f1d36"
    }
    auth_request("https://us.lgeapi.com/", requestBody)



RE: Has someone already integrated LG ThinQ - admin - 08.05.2023

With slight modifications this code should work - HTTP request via socket.http and hashing via encdec.hmacsha1
Client / secret key are fixed. You need your own access / refresh tokens to make requests and periodically update tokens.


RE: Has someone already integrated LG ThinQ - Joep - 08.05.2023

(08.05.2023, 08:55)admin Wrote: With slight modifications this code should work - HTTP request via socket.http and hashing via encdec.hmacsha1
Client / secret key are fixed. You need your own access / refresh tokens to make requests and periodically update tokens.

Could you make this modifications please just to make sure everything is set correct so far? Otherwise it will be a lot trial before it might work.
Many thanks in advance!

I changed print to log already but i have no idea how to change the hash part correct.
Also i see
Code:
self:debug
and i believe it's not valid code for the LM correct?


RE: Has someone already integrated LG ThinQ - admin - 08.05.2023

Try this for the signature calculation. You might need to swap message and secret arguments if it does not work.
Code:
function oauth2_signature(message, secret)
  local encdec = require('encdec')
  local hashed = encdec.hmacsha1(secret, message, true)
  return encdec.base64enc(hashed)
end

Use log() instead of self:debug. There are no callbacks for HTTP requests anyway, just the return values. Search the forums, there are many similar HTTP request examples available.


RE: Has someone already integrated LG ThinQ - Joep - 08.05.2023

Here is my code so far.

I get this error when executing the code:

LG Thinq 08.05.2023 14:35:56
Library socket/http:0: bad argument #1 to 'escape' (string expected, got function)
stack traceback:
[C]: in function 'request'
Resident script:31: in function 'auth_request'

Code:
require('socket.http')
require('encdec')

OAUTH_SECRET_KEY = "c053c2a6ddeb7ad97cb0eed0dcb31cf8"
OAUTH_CLIENT_KEY = "LGAO221A02"
DATE_FORMAT = "!%a, %d %b %Y %H:%M:%S"
V2_AUTH_PATH = "/oauth/1.0/oauth2/token"

function oauth2_signature(message, secret)
  local hashed = encdec.hmacsha1(message, secret, true)
  return encdec.base64enc(hashed)
end

function auth_request(oauth_url, reqdata)
    if string.sub(oauth_url, -1):lower() == "/" then  oauth_url = string.sub(oauth_url, 0, #oauth_url-1) end
    local url = oauth_url .. V2_AUTH_PATH
    local timestamp = tostring(os.date(DATE_FORMAT, os.time())) .. " +0000"
    local data_list = {}
    for k, v in pairs(reqdata) do  table.insert(data_list, string.format("%s=%s", k, v)) end
    local req_url = string.format("%s?%s", V2_AUTH_PATH, table.concat(data_list, "&"))
    local message = string.format("%s\n%s", req_url, timestamp)
    local sig = oauth2_signature(message, OAUTH_SECRET_KEY)
    local headers = {
        ["x-lge-appkey"] = OAUTH_CLIENT_KEY,
        ["x-lge-oauth-signature"] = sig,
        ["x-lge-oauth-date"] = timestamp,
        ["Content-Type"] = "application/x-www-form-urlencoded",
        ["Accept"] = "application/json"
    }
    castdata = table.concat(data_list, "&")
    socket.http.request(url,{
        options = {
            headers = headers,
            data = castdata,
            method = "POST",
            timeout = 5000,
        },
        success = function(response)
            log("auth_request success", response.data)
        end,
        error = function(error)
            log('error: ' .. json.encode(error))
        end
    })
end
   
local requestBody = {
    grant_type = "refresh_token",
    refresh_token = "4ed29cb48cc1cb6228658d50817b789d67d37dbad56bf561cc6389a4ab69070d8ee808edb3377ad3b07e243c467f1d36"
}

auth_request("https://us.lgeapi.com/", requestBody)



RE: Has someone already integrated LG ThinQ - admin - 08.05.2023

As I've said check other examples on what parameters the socket.http.request call accepts. But it won't work as is anyway without tokens generated using your own access credentials.
These threads might be helpful:
https://forum.logicmachine.net/showthread.php?tid=3014
https://forum.logicmachine.net/showthread.php?tid=3308


RE: Has someone already integrated LG ThinQ - Joep - 08.05.2023

No i have this code working with the below response. Do you think it's due to the wrong credentials or is it part of the code? ( Is still can't find any information on how to get my own credentials from LG..)

LG Thinq 08.05.2023 16:35:17
* arg: 1
  * string: {"error":{"request":"/oauth/1.0/oauth2/token","code":"LG.OAUTH.EC.2105","service":"oauth","message":"Signature doesn't match request."}}
* arg: 2
  * number: 406

Code:
require('json')
require('encdec')
require('socket.http')

OAUTH_SECRET_KEY = "c053c2a6ddeb7ad97cb0eed0dcb31cf8"
OAUTH_CLIENT_KEY = "LGAO221A02"
DATE_FORMAT = "!%a, %d %b %Y %H:%M:%S"
V2_AUTH_PATH = "/oauth/1.0/oauth2/token"

function oauth2_signature(message, secret)
  local hashed = encdec.hmacsha1(secret, message, true)
  return encdec.base64enc(hashed)
end

function auth_request(oauth_url, reqdata)
    if string.sub(oauth_url, -1):lower() == "/" then  oauth_url = string.sub(oauth_url, 0, #oauth_url-1) end
    local url = oauth_url .. V2_AUTH_PATH
    local timestamp = tostring(os.date(DATE_FORMAT, os.time())) .. " +0000"
    local data_list = {}
    for k, v in pairs(reqdata) do  table.insert(data_list, string.format("%s=%s", k, v)) end
    local req_url = string.format("%s?%s", V2_AUTH_PATH, table.concat(data_list, "&"))
    local message = string.format("%s\n%s", req_url, timestamp)
    local sig = oauth2_signature(message, OAUTH_SECRET_KEY)
    local headers = {
        ["x-lge-appkey"] = OAUTH_CLIENT_KEY,
        ["x-lge-oauth-signature"] = sig,
        ["x-lge-oauth-date"] = timestamp,
        ["Content-Type"] = "application/x-www-form-urlencoded",
        ["Accept"] = "application/json"
    }
    castdata = table.concat(data_list, "&")
    res, err = socket.http.request({
                url = url,
            headers = headers,
            data = castdata,
            method = "POST",
            timeout = 5000,
    })
end
   
local requestBody = {
    grant_type = "refresh_token",
    refresh_token = "4ed29cb48cc1cb6228658d50817b789d67d37dbad56bf561cc6389a4ab69070d8ee808edb3377ad3b07e243c467f1d36"
}

auth_request("https://nl.lgeapi.com/", requestBody)

log(res, err)



RE: Has someone already integrated LG ThinQ - Joep - 22.06.2023

The problem is that LG only accepts developers to use their API. I see others like Home Assistant use Wideq. I read onine (from recent posts) that is working succesfull. Only problem is that it's in Python script. Is someone interested to 'translate' it to Lua?

https://github.com/majki09/domoticz_lg_thinq_plugin
https://community.home-assistant.io/t/in-development-lg-smartthinq-component/40157/333