This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Panasonic Viera TV IP control
#12
(10.03.2016, 14:32)admin Wrote: Try these functions, they are untested so might not work at all. You have to parse any XML response manually
Code:
function request(host, url, urn, action, args)
  local body, http, ltn12, sink, res, err

  ltn12 = require('ltn12')
  http = require('socket.http')
  body = [[<?xml version="1.0" encoding="utf-8"?>
  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <s:Body><u:]] .. action .. [[ xmlns:u="urn:]] .. urn .. [[">]] .. args .. [[</u:]] .. action .. [[></s:Body>
  </s:Envelope>]]

  sink = {}

  res, err = http.request({
    url = 'http://' .. host .. ':55000/' .. url,
    method = 'POST',
    headers = {
      ['soapaction'] = '"urn:' .. urn .. '#' .. action .. '"',
      ['Content-Length'] = #body,
    },
    sink = ltn12.sink.table(sink),
    source = ltn12.source.string(body),
  })

  if res then
    return table.concat(sink)
  else
    return nil, err
  end
end

function sendkey(host, code)
  local args = '<X_KeyEvent>' .. code .. '</X_KeyEvent>'
  return request(host, 'nrc/control_0', 'panasonic-com:service:p00NetworkControl:1', 'X_SendKey', args)
end

function getmute(host)
  return request(host, 'dmr/control_0', 'schemas-upnp-org:service:RenderingControl:1', 'GetMute', '<InstanceID>0</InstanceID><Channel>Master</Channel>')
end

IP = '192.168.1.2'
log(getmute(IP))
Now in my region as of 2019 Panasonic have implemented Auth before i can send commands, 
i found this (https://github.com/florianholzapfel/pana...a/issues/9) explaining how it is achieved, but it is python, im not sure where to start to work out how to port it to lua,
I have soap command working to return the iv key my goal is to return the encrypted_payload to send to the tv to make connection.

import binascii
import base64
import hmac, hashlib
from Crypto.Cipher import AES

# Example challenge (which is our IV)
iv = base64.b64decode("mUQdS7/RyJTMsiojPz9i1Q==")

# Get character codes from IV bytes
iv_vals = [ord© for c in iv]

# Initialise key character codes array
key_vals = [0] * 16

# Derive key from IV
i = 0
while i < 16:
    key_vals[i] = ~iv_vals[i + 3] & 0xFF
    key_vals[i + 1] = ~iv_vals[i + 2] & 0xFF
    key_vals[i + 2] = ~iv_vals[i + 1] & 0xFF
    key_vals[i + 3] = ~iv_vals[i] & 0xFF
    i += 4

# Convert our key character codes to bytes
key = ''.join(chr© for c in key_vals)

# Initialise HMAC key mask (taken from libtvconnect.so)
hmac_key_mask_vals = [ord© for c in binascii.unhexlify("15C95AC2B08AA7EB4E228F811E34D04FA54BA7DCAC9879FA8ACDA3FC244F3854")]

# Initialise HMAC key character codes array
hmac_vals = [0] * 32

# Calculate HMAC key using HMAC key mask and IV
i = 0
while i < 32:
    hmac_vals[i] = hmac_key_mask_vals[i] ^ iv_vals[(i + 2) & 0xF]
    hmac_vals[i + 1] = hmac_key_mask_vals[i + 1] ^ iv_vals[(i + 3) & 0xF]
    hmac_vals[i + 2] = hmac_key_mask_vals[i + 2] ^ iv_vals[i & 0xF]
    hmac_vals[i + 3] = hmac_key_mask_vals[i + 3] ^ iv_vals[(i + 1) & 0xF]
    i += 4

# Convert our HMAC key character codes to bytes
hmac_key = ''.join(chr© for c in hmac_vals)

# This is our plaintext SOAP argument for the pin code shown on the TV
authinfo = "<X_PinCode>4410</X_PinCode>"

# First 12 bytes are randomised, let's just set them to 0 because it doesn't matter
payload = "000000000000"

# The next 4 bytes contain the plaintext (SOAP arg) length in big endian
n = len(authinfo)
payload += chr(n >> 24)
payload += chr((n >> 16) & 0xFF)
payload += chr((n >> 8) & 0xFF)
payload += chr(n & 0xFF)

# Now we concatenate our payload, which is starting at byte 17 of the payload
payload += authinfo

# Let's encrypt it with AES-CBC! We need to make sure we pad it to a multiple of 16 bytes beforehand
aes = AES.new(key, AES.MODE_CBC, iv)
ciphertext = aes.encrypt(pad(payload))

# Calculate the HMAC-SHA-256 signature of our encrypted payload
sig = hmac.new(hmac_key, ciphertext, hashlib.sha256).digest()

# Concatenate the HMAC signature to the encrypted payload and base64 encode it, and we're done!
encrypted_payload = base64.b64encode(ciphertext + sig)
Reply


Messages In This Thread
Panasonic Viera TV IP control - by jetsetter - 29.02.2016, 11:54
RE: Panasonic Viera TV IP control - by admin - 10.03.2016, 14:32
RE: Panasonic Viera TV IP control - by benanderson_475 - 18.01.2020, 01:07
RE: Panasonic Viera TV IP control - by admin - 16.03.2016, 08:25
RE: Panasonic Viera TV IP control - by andeug - 10.10.2016, 14:41
RE: Panasonic Viera TV IP control - by Habib - 08.04.2018, 11:32
RE: Panasonic Viera TV IP control - by admin - 08.04.2018, 11:58
RE: Panasonic Viera TV IP control - by Habib - 08.04.2018, 13:37
RE: Panasonic Viera TV IP control - by admin - 20.01.2020, 08:32
RE: Panasonic Viera TV IP control - by admin - 14.04.2020, 07:57
RE: Panasonic Viera TV IP control - by admin - 25.12.2020, 13:49
RE: Panasonic Viera TV IP control - by admin - 28.12.2020, 07:46
RE: Panasonic Viera TV IP control - by admin - 06.04.2021, 05:43
RE: Panasonic Viera TV IP control - by admin - 06.04.2021, 09:39

Forum Jump: