Creating a remote control for Samsung Smart TV

In this post I show you how you can control a Samsung Smart TV (model 2010, type UE4700) with Fibaro Home Center 2. Most Samsung TV’s will work with the TCP protocol and are able to receive commands. The following list represents the commands which may be sent to the TV:

# Key Reference # Normal remote keys
 #KEY_0
 #KEY_1
 #KEY_2
 #KEY_3
 #KEY_4
 #KEY_5
 #KEY_6
 #KEY_7
 #KEY_8
 #KEY_9
 #KEY_UP
 #KEY_DOWN
 #KEY_LEFT
 #KEY_RIGHT
 #KEY_MENU
 #KEY_PRECH
 #KEY_GUIDE
 #KEY_INFO
 #KEY_RETURN
 #KEY_CH_LIST
 #KEY_EXIT
 #KEY_ENTER
 #KEY_SOURCE
 #KEY_AD #KEY_PLAY
 #KEY_PAUSE
 #KEY_MUTE
 #KEY_PICTURE_SIZE
 #KEY_VOLUP
 #KEY_VOLDOWN
 #KEY_TOOLS
 #KEY_POWEROFF
 #KEY_CHUP
 #KEY_CHDOWN
 #KEY_CONTENTS
 #KEY_W_LINK #Media P
 #KEY_RSS #Internet
 #KEY_MTS #Dual
 #KEY_CAPTION #Subt
 #KEY_REWIND
 #KEY_FF
 #KEY_REC
 #KEY_STOP
# Bonus buttons not on the normal remote:
 #KEY_TV
There are also some commands which don’t work:
#Don't work/wrong codes:
 #KEY_CONTENT
 #KEY_INTERNET
 #KEY_PC
 #KEY_HDMI1
 #KEY_OFF
 #KEY_POWER
 #KEY_STANDBY
 #KEY_DUAL
 #KEY_SUBT
 #KEY_CHANUP
 #KEY_CHAN_UP
 #KEY_PROGUP
 #KEY_PROG_UP
Now that we now the commands we can program a remote control.
For a reference I created a remote control which looks likes the original one.
First start with creating the virtual device, in my case Samsung TV.
Fill in the ip address of the TV and port 55000.
If you need extra controls, it’s as easy as creating a new button and use the
following Lua code:
-- <configuration> -- 
tvIpAddress = "172.16.100.60" 
tvPort = 55000 
keycodestring = "KEY_POWEROFF" 

tvAuthString = string.char(0x00,0x14,0x00,0x69,0x70,0x68,0x6f,0x6e,0x65,0x2e,0x2e,0x69,0x61,0x70,0x70,0x2e,0x73,0x61,0x6d,0x73,0x75,0x6e,0x67,0x38,0x00,0x64,0x00,0x14,0x00,0x4d,0x54,0x6b,0x79,0x4c,0x6a,0x45,0x32,0x4f,0x43,0x34,0x77,0x4c,0x6a,0x45,0x78,0x4d,0x41,0x3d,0x3d,0x18,0x00,0x4e,0x45,0x4d,0x74,0x4e,0x7a,0x49,0x74,0x51,0x6a,0x6b,0x74,0x4e,0x44,0x4d,0x74,0x4d,0x6a,0x51,0x74,0x4f,0x45,0x49,0x3d,0x04,0x00,0x54,0x51,0x3d,0x3d)
-- </configuration> -- 

-- character table string 
local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' 

-- encoding to base64 
function enc(data) 
    return ((data:gsub('.', function(x) 
        local r,b='',x:byte() 
        for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end 
        return r; 
    end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x) 
        if (#x < 6) then return '' end 
        local c=0 
        for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end 
        return b:sub(c+1,c+1) 
    end)..({ '', '==', '=' })[#data%3+1]) 
end 

-- helper function 
function num2bytes(num)    
    local retStr="" 
    for i=1,2 do 
        retStr = retStr .. string.char(num%256) 
        num = math.floor(num/256) 
    end 
      return retStr 
end 

tcpSocket = Net.FTcpSocket(tvIpAddress, tvPort) 

-- say hello to the TV 😉 
bytes, errorCode = tcpSocket:write(tvAuthString) 

keycodebase = string.char(0x00,0x13,0x00,0x69,0x70,0x68,0x6f,0x6e,0x65,0x2e,0x69,0x61,0x70,0x70,0x2e,0x73,0x61,0x6d,0x73,0x75,0x6e,0x67) 

-- payload 
payloadinit = string.char(0x00,0x00,0x00) 
keycode = enc(keycodestring) 

keycodesize = num2bytes(string.len(keycode)) 

payloadsize = num2bytes(string.len(payloadinit .. keycode ..keycodesize)) 

-- combining the message 
message = keycodebase .. payloadsize .. payloadinit .. keycodesize .. keycode 

-- sending keycode 
bytes, errorCode2 = tcpSocket:write(message) 

if errorCode == 0 and errorCode2 == 0 
then 
  -- printing log under virtual device 
  fibaro:log("transfer OK: " .. keycodestring) 
else 
  fibaro:log("transfer failed") 
end

Note the –configuration — part of the Lua code above. The key part is the only thing which needs to be changed for each button / slider.