Samsung TV anyone?

Kevin

Well-Known Member
Licensed User
I'm making a plugin app for my main satellite remote app that adds volume control for several TV types. I only had one person offer to test on Samsung and he says it isn't working. However, I don't see anything wrong in my code. If anyone has a newer model Samsung (internet/network connected) and would be interested in trying my app, please post a message here or send me a PM.

In the meantime, anyone see anything wrong?

Original VBScript code:
B4X:
Imports System.Net.Sockets
    Const mType As String = "drhs_SamsungTV"
    Const tvip As String = "1.1.1.1"      'Set a static IP address for your TV  and edit this string to match that.
    Const tvport As Int32 = 55000      'This is the standard port that the TV listens on.  Do not change it.
    Const mymac = "00-00-00-00-00-00"     ' Enter your HS host MAC address here.  This is used for the access control/validation, but not after that AFAIK
    Const appstring = "iphone..iapp.samsung" ' What the iPhone app reports
    Const tvappstring = "iphone.UN55C8000.iapp.samsung" ' Might need changing to match your TV type
    Const remotename = "Homeseer Samsung Remote" ' What gets reported when it asks for permission/also shows in General->Wireless Remote Control menu

    Public Sub Main(ByVal Params As Object)
        If Params IsNot Nothing Then
            Dim tcpClient As New System.Net.Sockets.TcpClient()
            tcpClient.Connect(tvip, tvport)
            Dim networkStream As NetworkStream = tcpClient.GetStream()
            If networkStream.CanWrite Then
                Dim Messagepart3 As String = ""
                Dim ByteArrayOut() As Byte = StrToByteArray(MessagePart1)
                networkStream.Write(ByteArrayOut, 0, ByteArrayOut.Length)
                ByteArrayOut = StrToByteArray(MessagePart2)
                networkStream.Write(ByteArrayOut, 0, ByteArrayOut.Length)
                Dim argv As String() = Params.ToString.Split("|")
                If Left(UCase(argv(0)),4) = "KEY_" Then
                    Dim mp3 As String = Chr(0) & Chr(0) & Chr(0) & Chr(Len(Base64Encode(argv(0)))) & Chr(0) & Base64Encode(argv(0))
                    MessagePart3 = Chr(0) & Chr(Len(tvappstring)) & Chr(0) & tvappstring & Chr(Len(mp3)) & Chr(0) & mp3
                Else
                    Dim mp3 As String = Chr(1) & Chr(0) & Chr(0) & Chr(Len(Base64Encode(argv(0)))) & Chr(0) & Base64Encode(argv(0))
                    MessagePart3 = Chr(1) & Chr(Len(tvappstring)) & Chr(0) & tvappstring & Chr(Len(mp3)) & Chr(0) & mp3
                End If
                ByteArrayOut = StrToByteArray(MessagePart3)
                networkStream.Write(ByteArrayOut, 0, ByteArrayOut.Length)
                networkStream.Close()
                tcpClient.Close()
            End If
        End If
    End Sub

    Private Function MessagePart1() As String
        'Dim myip As String = hs.GetIPAddress ' Doesn't seem to be really used
        Dim myip as String = "2.2.2.2"   'Set your HS Host IP address here
        Dim messagepart1x As String = Chr(&H64) & Chr(0) & Chr(Len(Base64Encode(myip))) & Chr(0) & Base64Encode(myip) & Chr(Len(Base64Encode(mymac))) & Chr(0) & Base64Encode(mymac) & Chr(Len(Base64Encode(remotename))) & Chr(0) & Base64Encode(remotename)
        Dim part1 As String = Chr(0) & Chr(Len(appstring)) & Chr(0) & appstring & Chr(Len(messagepart1x)) & Chr(0) & messagepart1x
        Return part1
    End Function

    Private Function MessagePart2() As String
        Dim messagepart2x As String = Chr(&HC8) & Chr(0)
        Dim part2 As String = Chr(0) & Chr(Len(appstring)) & Chr(0) & appstring & Chr(Len(messagepart2x)) & Chr(0) & messagepart2x
        Return part2
    End Function

    Private Function Base64Encode(ByVal InputString As String)
        Dim byt As Byte() = System.Text.Encoding.UTF8.GetBytes(InputString)
        Return Convert.ToBase64String(byt)
    End Function

    Private Function StrToByteArray(str As String) As Byte()
   Dim ByteArray(Len(str)-1) as Byte
   For n As Short = 0 To UBound(ByteArray)
      ByteArray(n) = Asc(Mid(str,n + 1,1))
   Next
   Return ByteArray
    End Function

Original Python code:
B4X:
#!  /usr/bin/python
#   Title: samsungremote.py
#   Author: Asif Iqbal
#   Date: 05APR2012
#   Info: To send remote control commands to the Samsung tv over LAN
#   TODO:
 
import socket
import base64
import time, datetime
 
#IP Address of TV
tvip = "100.0.0.123"
#IP Address of TV
myip = "100.0.0.112"
#Used for the access control/validation, but not after that AFAIK
mymac = "00-0c-29-3e-b1-4f"
#What the iPhone app reports
appstring = "iphone..iapp.samsung"
#Might need changing to match your TV type
tvappstring = "iphone.UE55C8000.iapp.samsung"
#What gets reported when it asks for permission
remotename = "Python Samsung Remote"
 
# Function to send keys
def sendKey(skey, dataSock, appstring):
 messagepart3 = chr(0x00) + chr(0x00) + chr(0x00) + chr(len(
base64.b64encode(skey))) + chr(0x00) + base64.b64encode(skey);
 part3 = chr(0x00) + chr(len(appstring)) + chr(0x00) \
+ appstring + chr(len(messagepart3)) + chr(0x00) + messagepart3
 dataSock.send(part3);
 
# Open Socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((tvip, 55000))
 
# 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
#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
 
# First configure the connection
ipencoded = base64.b64encode(myip)
macencoded = base64.b64encode(mymac)
messagepart1 = chr(0x64) + chr(0x00) + chr(len(ipencoded)) \
+ chr(0x00) + ipencoded + chr(len(macencoded)) + chr(0x00) \
+ macencoded + chr(len(base64.b64encode(remotename))) + chr(0x00) \
+ base64.b64encode(remotename)
 
part1 = chr(0x00) + chr(len(appstring)) + chr(0x00) + appstring \
+ chr(len(messagepart1)) + chr(0x00) + messagepart1
sock.send(part1)
 
messagepart2 = chr(0xc8) + chr(0x00)
part2 = chr(0x00) + chr(len(appstring)) + chr(0x00) + appstring \
+ chr(len(messagepart2)) + chr(0x00) + messagepart2
sock.send(part2)
 
# Now send the keys as you like, e.g.,
sendKey("KEY_VOLUP",sock,tvappstring)
time.sleep(1)
sendKey("KEY_TOOLS",sock,tvappstring)
time.sleep(1)
sendKey("KEY_RIGHT",sock,tvappstring)
time.sleep(1)
sendKey("KEY_DOWN",sock,tvappstring)
time.sleep(1)
sendKey("KEY_RIGHT",sock,tvappstring)
 
# Close the socket when done
sock.close()

My B4A code:
B4X:
Sub SendSammy (iCommand As Int)
   Dim sCMD As String

   Select Case iCommand
      Case 1 ' Power Toggle
         sCMD = ""
      Case 2 ' Power On
         sCMD = ""
      Case 3 ' Power Off
         sCMD = "KEY_POWEROFF"
      Case 4 ' Volume Up
         sCMD = "KEY_VOLUP"
      Case 5 ' Volume Down
         sCMD = "KEY_VOLDOWN"
      Case 6 ' Mute Toggle
         sCMD = "KEY_MUTE"
      Case 7 ' Mute On
         sCMD = ""  ' or "NRC_TV_MUTE_ON-ONOFF"
      Case 8 ' Mute Off
         sCMD = ""  ' or "NRC_TV_MUTE_OFF-ONOFF"
      Case 9 ' Select Input
         sCMD = "KEY_SOURCE"
   End Select
   
   If sCMD = "" Then Return  ' Shouldn't happen because we checked earlier for unsupported commands but whatever.....
   
   If VCTest <> 999 Then 'Test
       ToastMessageShow ("Samsung Test > Sending command to " & Common.AVRDeviceName & "...", False)
       Else 'Real
         If VCToast = True Then ToastMessageShow ("Sending command to " & Common.AVRDeviceName & "...", False)
   End If
   
   ' GET IP
   If Common.DeviceIP = "" Then Common.DeviceIP = Common.GetIP
   ' Get MAC
   If Common.DeviceMAC = "" Then Common.DeviceMAC = Common.GetMAC
   
   If Common.Logging Then Log ("IP = " & Common.DeviceIP)
   If Common.Logging Then Log ("MAC = " & Common.DeviceMAC)
   
   Dim SamsungAppstring As String = "iphone..iapp.samsung"
   If Common.TVName = "" Then Common.TVName = "samsung"
   Dim SamsungTVappstring As String = "iphone." & Common.TVName & ".iapp.samsung" ' xxxx = is typically model # I guess.  Just try without for now...
   Dim SamsungRemoteName As String = "DirecTV Remote Plus"
      
   Common.ForConnectAVRIP = Common.AVRIP
   Common.ForConnectAVRPort = Common.AVRPort
   Common.ForConnectAVRType = 6 ' Samsung
   Common.ForConnectAVRCommand = iCommand
   
   Dim IPEncoded As String = Common.Base64Encode (Common.DeviceIP)
   Dim MACEncoded As String = Common.Base64Encode (Common.DeviceMAC)
   Dim SRNameEncoded As String = Common.Base64Encode (SamsungRemoteName)
   Dim sCMDEncoded As String = Common.Base64Encode (sCMD)
   
  Dim messagepart1x As String = Chr(0x64) & Chr(0) & Chr(IPEncoded.Length) & Chr(0) & IPEncoded & Chr(MACEncoded.Length) & Chr(0) & MACEncoded & Chr(SRNameEncoded.Length) & Chr(0) & SRNameEncoded
  Common.SamsungSendString1 = Chr(0) & Chr(SamsungAppstring.Length) & Chr(0) & SamsungAppstring & Chr(messagepart1x.Length) & Chr(0) & messagepart1x

   Dim messagepart2x As String = Chr(0xc8) & Chr(0)
  Common.SamsungSendString2 = Chr(0) & Chr(SamsungAppstring.Length) & Chr(0) & SamsungAppstring & Chr(messagepart2x.Length) & Chr(0) & messagepart2x  ' Said SamsungSendString1 before!  Oops
            
   Dim mp3 As String = Chr(0) & Chr(0) & Chr(0) & Chr(sCMDEncoded.Length) & Chr(0) & sCMDEncoded
  Common.SamsungSendString3 = Chr(0) & Chr(SamsungTVappstring.Length) & Chr(0) & SamsungTVappstring & Chr(mp3.Length) & Chr(0) & mp3
   
   If Common.ConnectServiceRunning = True AND Common.ConnectServiceConnected = True Then
      If Common.ForConnectAVRType <> 6 Then ' Force disconnect and restart the service
         Common.SamsungIsInitialized = False
         StopService (ConnectAVR):DoEvents
            Else
               CallSubDelayed (ConnectAVR,"SendCommand")
               Return
      End If
   End If

   StartService (ConnectAVR)
End Sub

Sub InitNetInfo
   Try
      If MyIP.IsInitialized = False Then
         MyIP.Initialize (1059,"")
      End If
      Catch ' Possibly left other app (free or pro) running
         If MyIP.IsInitialized = False Then
            MyIP.Initialize (1060,"")
         End If
   End Try
End Sub

Sub GetIP As String

   InitNetInfo
   Try
      DeviceIP = MyIP.GetMyWifiIP ' WiFi IP
      Catch
   End Try
      
   If DeviceIP <> "" AND DeviceIP <> "127.0.0.1" Then ' WiFi must be on and connected because we have only checked for the WiFiIP
   End If
   
   Try
      DeviceIP = MyIP.GetMyIP ' Non-WiFi IP
      Catch
      DeviceIP = ""
   End Try
   
   MyIP.Close
   Return DeviceIP
   
End Sub

Sub GetMAC As String
   Dim MyWiFi As ABWifi, r As Boolean
   r = MyWiFi.ABLoadWifi()
   If r = False Then
      DeviceMAC = "00:00:00:00:00:00"
         Else
            DeviceMAC = MyWiFi.ABGetCurrentWifiInfo.MacAddress
   End If

   Return DeviceMAC
   
End Sub

Sub Base64Encode (strIn As String) As String
   Dim su As StringUtils
   Return su.EncodeBase64 (strIn.GetBytes("UTF8"))
End Sub

'Service module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.

    Dim AStreams As AsyncStreams
    Dim Socket1 As Socket
    Dim OpeningSocket As Boolean
      Dim TimerKeepServiceAlive As Timer
      Dim AwaitingResponse As Boolean
      
      ' For TESTING *******
      Dim TestingToasts As Boolean = False
      
End Sub
Sub Service_Create
   TimerKeepServiceAlive.Initialize ("TimerKeepServiceAlive",30000) ' Keep service / connection active for 30 seconds to speed up consecutive commands
End Sub

Sub Service_Start (StartingIntent As Intent)
   Common.ConnectServiceRunning = True
   Common.ConnectServiceConnected = False
   ConnectToSocket
End Sub

Sub Service_Destroy
   AStreams.Close
  Socket1.Close
   AwaitingResponse = False
   TimerKeepServiceAlive.Enabled = False
   Common.ConnectServiceConnected = False
   Common.ConnectServiceRunning = False
   Common.SamsungIsInitialized = False
End Sub

Sub TimerKeepServiceAlive_tick
   If AwaitingResponse = True Then Return 'We're in the middle of sending a command
   
   TimerKeepServiceAlive.Enabled = False
   If Common.Logging = True Then Log ("Socket Service stopped due to inactivity")
   StopService ("")
End Sub

Sub ConnectToSocket    
       TimerKeepServiceAlive.Enabled = True
    OpeningSocket = True 
      If Common.Logging = True Then Log("Attempting connection to " & Common.ForConnectAVRIP & ":" & Common.ForConnectAVRPort)
      If TestingToasts = True Then ToastMessageShow ("Attempting connection to " & Common.ForConnectAVRIP & ":" & Common.ForConnectAVRPort, False)
    Try
        Socket1.Initialize("Socket1")
        Socket1.Connect(Common.ForConnectAVRIP, Common.ForConnectAVRPort, 10000) ' changed from 5 to 10 seconds timeout
    Catch
    
    End Try
End Sub

Sub Socket1_Connected (Successful As Boolean)
    Try        
        If Successful Then
               TimerKeepServiceAlive.Enabled = False: TimerKeepServiceAlive.Enabled = True  ' Reset the timer
               If Common.Logging = True Then Log("Connected to " & Common.ForConnectAVRIP)
               If TestingToasts = True Then ToastMessageShow ("Connected to " & Common.ForConnectAVRIP, True)
               Common.ConnectServiceConnected = True
            AStreams.Initialize (Socket1.InputStream, Socket1.OutputStream, "AStreams")
               DoEvents
               SendCommand
        End If
        OpeningSocket = False
    Catch
        OpeningSocket = False
            Common.ConnectServiceConnected = False
    End Try        
End Sub

Sub SendCommand
   Dim sCMD As String
   
   Select Case Common.ForConnectAVRType
      Case 1  ' Advanced HTTP   
         sCMD = Common.ForPOSTGETRequest
      Case 2 ' Denon/Marantz
         sCMD = Common.ForPOSTGETRequest
      Case 5 ' Panasonic VIERA
         sCMD = Common.ForPOSTGETRequest
      Case 6 ' Samsung TV
         If Common.SamsungIsInitialized = False Then
            SendDataToSocket (Common.SamsungSendString1)
            SendDataToSocket (Common.SamsungSendString2)
            Common.SamsungIsInitialized = True
         End If
         sCMD = Common.SamsungSendString3
      Case Else 'What are we doing here?
         StopService ("")
   End Select
   
   ' Send whatever data we determined we need to send depending on device type...
   SendDataToSocket (sCMD)
   TimerKeepServiceAlive.Enabled = False:TimerKeepServiceAlive.Enabled = True 'Reset the timer
End Sub

Sub SendDataToSocket (sDataToSend As String)
   If AStreams.IsInitialized = False Then
      If Common.Logging = True Then Log ("Failed to send data to socket because the stream was not initialized!")
      If TestingToasts = True Then ToastMessageShow ("Failed to send data to socket because the stream was not initialized!", True)
      Return
   End If
   
  If sDataToSend.Length > 0 Then
      AwaitingResponse = True
    Dim buffer() As Byte
    Dim data As String
    data = sDataToSend
    buffer = data.GetBytes ("UTF8")
    AStreams.Write (buffer)
   If Common.Logging = True Then Log ("Sending data to socket: " & sDataToSend )
      If TestingToasts = True Then ToastMessageShow ("Sending data to socket...", True)
  End If
End Sub

Sub AStreams_NewData (Buffer() As Byte)
   Dim msg As String
  msg = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
  'ToastMessageShow(msg, False)
  If Common.Logging = True Then Log ("Received: " & msg)
   If TestingToasts = True Then ToastMessageShow ("Received: " & msg, True)
   If AwaitingResponse = True Then AwaitingResponse = False
End Sub

Sub AStreams_Error
   If Common.Logging = True Then Log ("Socket connection error: " & LastException.Message)
   ToastMessageShow ("Socket connection error: " & LastException.Message,True)
   If AwaitingResponse = True Then AwaitingResponse = False
   Common.SamsungIsInitialized = False
End Sub

Sub AStreams_Terminated
   If Common.Logging = True Then Log ("Stream terminated")
   'If TestingToasts = True Then ToastMessageShow ("Stream terminated",True)
   If AwaitingResponse = True Then AwaitingResponse = False
   TimerKeepServiceAlive.Enabled = False
   StopService ("")
End Sub

I can send the compiled APK and/or code if necessary to anyone with a Samsung TV. It is difficult testing code on a device you do not own! :eek:

The guy testing for me says the official Samsung remote app works. The code samples above were originally obtained by reverse engineering an iPhone app's network packets.
 

moster67

Expert
Licensed User
I have a Samsung SmartTV. I was also looking into this some months ago but I never had time to spare for such a project.

I found this web-page with lots of information:

Jumirlc: Gather Information - SamyGO

If you want me to test, you can post the source here. If you prefer, you can PM me and I will send you my e-mail address.
 
Upvote 0

Kevin

Well-Known Member
Licensed User
I had a look at the SamyGo source and other than that it appears to wait for a reply after sending each set of data, it looks essentially the same. The only reason I didn't code mine to wait for replies is because the other several code samples I saw (two of which I posted above) just sent the three strings one after another.

I'll send a PM.
 
Upvote 0

psdos

Active Member
Licensed User
I have a Samsung TV too, my model is 46C8000. Post de apk here and i test it in my TV.

Is very interesting this proyect...
 
Upvote 0

Kevin

Well-Known Member
Licensed User
Well, most of the code is quoted above. I don't want to post the APK or code here but if you really want to try it, send me a PM and I can send you the project.

Unfortunately, neither I nor Moster67 were able to figure out what is wrong with the code. He intends to wrap some working java code and make it into a B4A library.

As it is, my B4A code apparently partially works in that the TV will ask you to allow or deny the app's control of your TV but the commands do nothing.
 
Upvote 0

Jon Eskdale

Member
Licensed User
Samsung have changed something for the new 2014 models as not even the python code works on these. Interested to know if anyone has any details on the new protocol
Jon
 
Upvote 0

Horst Leistner

Member
Licensed User
Hi Kevin,

please could you give me some additional information concerning your B4A Code. I integrated the libraries ABWiFi, RandomAccesFile, Network and StringUtils but the following items remain unknown (Red):
VCTest
VCToast
Common.
ConnectAVR
MyIP
DeviceIP
Device Mac
I would like to understand your code to modify it for my brandnew SAMSUNG TV.

Greetings and many thanks in advance
Horst Leistner
 
Upvote 0
Top