B4A Library Samsung TV Wrapper-library (sending remote-control code to Samsung TVs)

[Library] Samsung TV Wrapper (sending remote-control code to Samsung TVs)

Samsung TV Wrapper-library (sending remote-control code to Samsung TVs)

In this thread (http://www.b4x.com/forum/basic4android-updates-questions/23765-samsung-tv-anyone.html#post139014) Kevin asked for some assistance in testing some code to simulate some remote-control commands for Samsung TVs. I tried the code but could not get it to work with my Samsung TV. Instead, I opted for writing a wrapper-library of some existing and well-tested Java-code to perform the same task.

This library wraps code found in the the following app SamyGo Remote by Tom Quist which can be found on Google Play (https://play.google.com/store/apps/details?id=de.quist.app.samyGoRemote). The source of this app was available here https://github.com/tomquist/SamyGo-Android-Remote until yesterday when I noted the page was not available any longer (perhaps a temporary error?).

Prerequisites:

1) This code should work with most Samsung TVs starting from the C-series and upwards although not all models are supported. I made my test on my Samsung TV which is a D-series TV and it works nicely. I have read that it should work also with the E-series. Previous series such as the B-series are not supported. This is the description of the app and I guess this information applies to this wrapper-library as well.

If you have a C-Series or D-Series TV, make sure you activated "Remote Control" in your TVs Menu under System-Settings. If there is no such setting, your TV is not supported.
The following TVs are Supported without modification:
• TVs from 2010 with Internet@TV feature: Models greater or equal to LCD 650, LED 6500, PDP 6500
• TV from 2011 with AllShare feature: Models greater or equal to LCD 550, LED 5500, PDP 5500
• TV from 2012 with AllShare feature: Models greater or equal to LCD 550, LED 5500, PDP 5500
• Bluerad Disc Player released in 2011 with Smart Hub feature
The following TVs are currently known to be unsupported: C490, C5100, C6300, C680, C687


2) The java-code seems to run on the main-thread and therefore it will not work with ICS (perhaps also Honeycomb). In order to resolve this you must not target said SDK(s) in the Manifest. Perhaps using Agraham's Threading-library you can find a work-around although I have not tried it.

Usage:

-add the 2 library-files in your Additional Library folder.
-you also need the ABWifi-library (for the MAC-address=b4auniqueId) found here:
http://www.b4x.com/forum/additional-libraries-classes-official-updates/8613-wifi-library.html#post48035

The methods are the following ones (self-explanatory I think). Thanks to Martin (warwound) for the script:

b4asamsungtv
Author: moster67
Version: 1.4
  • RemoteSession
    Methods:
    • Connect
    • Initialize (b4aapplicationName As String, b4auniqueId As String, b4ahost As String, b4aport As Int)
      Initialize the RemoteSession object
    • IsInitialized As Boolean
    • sendCode (mykey As String)
    • uninitialize

If the TV is supported, the first time the app is being run, the user will be prompted on the TV-screen to allow your app to be used with the TV. The user must say YES. As far as I know, this verification cannot be by-passed. I am not sure if it is the application-name, the device's MAC-address (uniqueId) or a combination of both which determine this verification. You will need to test yourself.

I have also attached a sample B4A-project. In the B4A-project you can find all remote-codes supported from C-series and onwards although I have only tested the most common ones on my TV. Note: if you power off the TV, you cannot power it on again from your app since the TV's LAN will be shut down and the TVs do not support Wake On LAN.

IMPORTANT NOTES:

Since the original code is under GNU General Public License, I guess also my wrapper must be the same.
Therefore read this carefully:

' ****
' * SAMSUNG TV WRAPPER-LIBRARY for B4A by moster67 (December 5, 2012)
' * ONLY WORKS WITH SAMSUNG TV C, D and probably E-series (B-serie DOES NOT work)
' * This wrapper is free software; you can redistribute it AND/OR modify
' * it under the terms of the GNU General Public License as published by
' * the Free Software Foundation; either version 2 of the License, OR
' * (at your option) any later version.
' * This wrapper Is distributed in the hope that it will be useful,
' * but WITHOUT ANY WARRANTY; without even the implied warranty of
' * MERCHANTABILITY OR FITNESS For A PARTICULAR PURPOSE.
'
' * IF YOU BRICK YOUR TV OR SOMEONE ELSE'S TV, THAT IS YOUR PROBLEM, NOT MINE,
' * ALTHOUGH IT WAS TESTED ON MY D-SERIES TV AND WORKED NICELY.
' * SOURCE OF WRAPPER IS AVAILABLE IN THIS POST.
'
' WRAPPER-LIBRARY BASED ON CODE FROM
' https://github.com/tomquist/SamyGo-Android-Remote.
'
' * Copyright (C) 2011 Tom Quist
' *
' * This program Is free software; you can redistribute it AND/OR modify
' * it under the terms of the GNU General Public License As published by
' * the Free Software Foundation; either version 2 of the License, OR
' * (at your option) any later version.
' *
' * This program Is distributed In the hope that it will be useful,
' * but WITHOUT ANY WARRANTY; without even the implied warranty of
' * MERCHANTABILITY OR FITNESS For A PARTICULAR PURPOSE. See the
' * GNU General Public License For more details.
' *
' * You can get the GNU General Public License at
' * The GNU General Public License v3.0 - GNU Project - Free Software Foundation (FSF)


I am not a lawyer but I think the license implies that if someone wants to see your sources,
you must provide the same. Maybe a workaround would be to write the remote-control as a plugin
and if sources are requested, you can give the sources of the plugin (and not your app). But
as I said, I am not a lawyer so I cannot tell.

Alternatively you can write your own code in B4A using the code-base Kevin provided in the link I posted in the beginning of this post.

Future:
I might add a discovery-class which will search for Samsung TVs available on the LAN
and indicate if it is compatible or not (i.e. C-serie or upwards). We'll see.

I hope this wrapper will work for you.

Good luck!
 

Attachments

  • samsungtv_library.zip
    21.7 KB · Views: 557
  • SamsungTVRemoteB4aSampleProject.zip
    10.3 KB · Views: 540
  • Eclipsesamsungtv.zip
    44 KB · Views: 461
Last edited:

Kevin

Well-Known Member
Licensed User
Longtime User
... added to my app and sent on to my tester. :D

I'll post back with results when I hear them.

Thanks!!!
 

Kevin

Well-Known Member
Licensed User
Longtime User
Just wanted to post another message to say that the library works great and much thanks to moster67 for writing it!

I need to learn how to do this stuff! :sign0188:
 

psdos

Active Member
Licensed User
Longtime User
in my Samsung TV 46C8000 dont go the example proyect moster67, there is some code of you example that i do not understand, for example, you wrote this

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

End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
    Dim myWifi As ABWifi
End Sub

Sub Activity_Create(FirstTime As Boolean)
   'Do not forget to load the layout file created with the visual designer. For example:
   Activity.LoadLayout("two")

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub BTN_Click
   Dim remote As RemoteSession
   Dim devicemac As String
   Dim Command As String 
   Dim sCMD As String
   
   
   
   Dim b As Button
    b = Sender
    Command=b.Tag

   Select Case Command
      
      Case "up" ' Volume Up
         sCMD = "KEY_VOLUP"
      Case "down" ' Volume Down
         sCMD = "KEY_VOLDOWN"
      Case "mute" ' Mute Toggle
         sCMD = "KEY_MUTE"
      Case "off" ' Power Off
         sCMD = "KEY_POWEROFF"
   End Select
   
   devicemac=Get_Mac
   
   If devicemac = Null Then
      devicemac = "00:50:C2:00:11:22" ' Virtual MAc-address. Only For devices without an wifi interface (e.g. the emulator)
   End If
   
   Try
      remote.Initialize("Mike remote",devicemac,"192.168.1.3","55000")
      remote.Connect
      remote.sendCode(sCMD)
   Catch
      Log("Something went wrong! What? No idea.")
      remote.uninitialize
   End Try
      remote.uninitialize
   
   'available buttons for Samsung C, D and probably E-series
   
'      MAPPINGS.put(BTN_POWER_OFF, KEY_POWEROFF);
'      MAPPINGS.put(BTN_TV, KEY_TV);
'      MAPPINGS.put(BTN_1, KEY_1);
'      MAPPINGS.put(BTN_2, KEY_2);
'      MAPPINGS.put(BTN_3, KEY_3);
'      MAPPINGS.put(BTN_4, KEY_4);
'      MAPPINGS.put(BTN_5, KEY_5);
'      MAPPINGS.put(BTN_6, KEY_6);
'      MAPPINGS.put(BTN_7, KEY_7);
'      MAPPINGS.put(BTN_8, KEY_8);
'      MAPPINGS.put(BTN_9, KEY_9);
'      MAPPINGS.put(BTN_0, KEY_0);
'      MAPPINGS.put(BTN_FAVOURITE_CHANNEL, KEY_FAVCH);
'      MAPPINGS.put(BTN_PREVIOUS_CHANNEL, KEY_PRECH);
'      MAPPINGS.put(BTN_VOLUME_UP, KEY_VOLUP);
'      MAPPINGS.put(BTN_VOLUME_DOWN, KEY_VOLDOWN);
'      MAPPINGS.put(BTN_CHANNEL_UP, KEY_CHUP);
'      MAPPINGS.put(BTN_CHANNEL_DOWN, KEY_CHDOWN);
'      MAPPINGS.put(BTN_MUTE, KEY_MUTE);
'      MAPPINGS.put(BTN_SOURCE, KEY_SOURCE);
'      MAPPINGS.put(BTN_INFO, KEY_INFO);
'      MAPPINGS.put(BTN_TOOLS, KEY_TOOLS);
'      MAPPINGS.put(BTN_GUIDE, KEY_GUIDE);
'      MAPPINGS.put(BTN_RETURN, KEY_RETURN);
'      MAPPINGS.put(BTN_MENU, KEY_MENU);
'      MAPPINGS.put(BTN_ENTER, KEY_ENTER);
'      MAPPINGS.put(BTN_UP, KEY_UP);
'      MAPPINGS.put(BTN_DOWN, KEY_DOWN);
'      MAPPINGS.put(BTN_LEFT, KEY_LEFT);
'      MAPPINGS.put(BTN_RIGHT, KEY_RIGHT);
'      MAPPINGS.put(BTN_INTERNET, KEY_RSS);
'      MAPPINGS.put(BTN_EXIT, KEY_EXIT);
'      MAPPINGS.put(BTN_RED, KEY_RED);
'      MAPPINGS.put(BTN_GREEN, KEY_GREEN);
'      MAPPINGS.put(BTN_YELLOW, KEY_YELLOW);
'      MAPPINGS.put(BTN_BLUE, KEY_CYAN);
'      MAPPINGS.put(BTN_TELETEXT, KEY_TTX_MIX);
'      MAPPINGS.put(BTN_MEDIA, KEY_W_LINK);
'      MAPPINGS.put(BTN_CONTENT, KEY_CONTENTS);
'      MAPPINGS.put(BTN_CHANNEL_LIST, KEY_CH_LIST);
'      MAPPINGS.put(BTN_AD, KEY_AD);
'      MAPPINGS.put(BTN_SUBTITLE, KEY_SUB_TITLE);
'      MAPPINGS.put(BTN_FORWARD, KEY_FF);
'      MAPPINGS.put(BTN_PAUSE, KEY_PAUSE);
'      MAPPINGS.put(BTN_BACKWARD, KEY_REWIND);
'      MAPPINGS.put(BTN_RECORD, KEY_REC);
'      MAPPINGS.put(BTN_PLAY, KEY_PLAY);
'      MAPPINGS.put(BTN_STOP, KEY_STOP);
'      MAPPINGS.put(BTN_SLEEP, KEY_SLEEP);
'      MAPPINGS.put(BTN_PICTURE_IN_PICTURE, KEY_PIP_ONOFF);
'      MAPPINGS.put(BTN_PSIZE, KEY_PICTURE_SIZE);
'      MAPPINGS.put(BTN_ENERGY, KEY_ESAVING);
'      MAPPINGS.put(BTN_SRS, KEY_SRS);
'      MAPPINGS.put(BTN_PMODE, KEY_PMODE);
'      MAPPINGS.put(BTN_P_DYNAMIC, KEY_DYNAMIC);
'      MAPPINGS.put(BTN_P_STANDARD, KEY_STANDARD);
'      MAPPINGS.put(BTN_P_MOVIE1, KEY_MOVIE1);
'      MAPPINGS.put(BTN_ASPECT_43, KEY_4_3);
'      MAPPINGS.put(BTN_ASPECT_169, KEY_16_9);
'      MAPPINGS.put(BTN_S_AV, KEY_AV1);
'      MAPPINGS.put(BTN_S_HDMI1, KEY_HDMI1);
'      MAPPINGS.put(BTN_S_HDMI2, KEY_HDMI2);
'      MAPPINGS.put(BTN_S_HDMI3_DVI, KEY_HDMI3);
'      MAPPINGS.put(BTN_S_HDMI4, KEY_HDMI4);
   
   

End Sub


Sub Get_Mac() As String
    myWifi.ABLoadWifi()
    mymac = myWifi.ABGetCurrentWifiInfo().MacAddress 
    Return mymac
End Sub


why you read MAC of celular? MAC is not from TV?, and i think IP from TV too, is ok?

Thanks.
 

moster67

Expert
Licensed User
Longtime User
@psdos

You need to pass on :

1) a name (name of your app for example),
2) mac-address of your android-device (this is a uniqueID which the TV needs)
3) host-address = ip-address of your TV
4) port = should be 55000 *

* = in my sample I used 55000 as a string by mistake but it should be an Int as the signature says. It seems like it works nevertheless (maybe B4A takes care of the casting)
 
Last edited:

susu

Well-Known Member
Licensed User
Longtime User
Hi Moster, I tried your wrapper on Smart TV 2012 (E series) and it worked. But how can we send text to TV?
 

Kevin

Well-Known Member
Licensed User
Longtime User
2) The java-code seems to run on the main-thread and therefore it will not work with ICS (perhaps also Honeycomb). In order to resolve this you must not target said SDK(s) in the Manifest. Perhaps using Agraham's Threading-library you can find a work-around although I have not tried it.

I recently tried changing my "target" API level in order to fix a market problem where Google Play showed my app as being incompatible with larger tablets. This broke the Samsung library and it was only a slight memory of reading the above quote that helped me figure out why it broke before I pulled more of my hair out. :) I just wound up re-targeting a lower API for now, but...

Does anyone know how the code could be modified to force it to run in its own thread? Does B4A offer an easy way to force a certain library to run in its own thread?
 

Kevin

Well-Known Member
Licensed User
Longtime User
I should have been clearer... No, the target SDK should not directly affect tablet compatibility in the market listing, but not having "x-large" screens listed in the manifest will.

Unfortunately you cannot declare x-large screen compatibility without targeting a higher SDK version in the manifest.

Doing this fixed 2 of my 3 apps as showing incompatible on a 10" Asus Transformer. It probably would have fixed the other if I hadn't had to change it back for reasons cited above.
 

moster67

Expert
Licensed User
Longtime User
I actually made an update to this library some time ago where I added the "sendtext" function but I never posted it.

I might post this library and at the same time have a look if I can resolve the issue although it might be out of my league (I never had time to get to grips with Java-syntax). If anyone else would like to have a look, please do so. The source is in the first post of this thread.
 

Kevin

Well-Known Member
Licensed User
Longtime User
I tried fixing this the "cheating" way (using StrictMode) but I don't know if it worked or not since I don't have a Samsung TV. I really need to move my app on to a higher API level to address some other issues but this one is holding me back. Attached is my update to the library and below is the new code after my changes. The only changes I made were in the "RemoteSession.java" file, then I rebuilt in Eclipse.

I also tried forcing a timeout of 5 seconds but it still seems to wait almost a whole minute. I don't know Java... :(


B4X:
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.concurrent.TimeoutException;

import android.util.Log;

import android.os.StrictMode;



public class RemoteSession {

    private static final String TAG = "TAG_B4A";
    public static final String REPORT_TAG = "report";
   
    private static final String APP_STRING = "iphone.iapp.samsung";
    private static final String TV_APP_STRING = "iphone..iapp.samsung";
   
    private static final char[] ALLOWED_BYTES = new char[] {0x64, 0x00, 0x01, 0x00};
    private static final char[] DENIED_BYTES = new char[] {0x64, 0x00, 0x00, 0x00};
    private static final char[] TIMEOUT_BYTES = new char[] {0x65, 0x00};

    public static final String ALLOWED = "ALLOWED";
    public static final String DENIED = "DENIED";
    public static final String TIMEOUT = "TIMEOUT";
    //private static final String TAG = RemoteSession.class.getSimpleName();
   
    private String applicationName;
    private String uniqueId;
    private String host;
    private int port;
    private String myword;

    private Socket socket;
    private String mykey;

    private InputStreamReader reader;

    private BufferedWriter writer;
    //private Loggable logger;

   

   
    RemoteSession(String applicationName, String uniqueId, String host, int port,String myword) {
        this.applicationName = applicationName;
        this.uniqueId = uniqueId;
        if (uniqueId == null) {
            uniqueId = "";
        }
        this.host = host;
        this.port = port;
        this.myword = myword;
        //this.logger = logger;
    }
   
    public static RemoteSession create(String applicationName, String uniqueId, String host, int port, String myword) throws IOException, ConnectionDeniedException, TimeoutException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        Log.v(TAG,"createsub 1st part");
        RemoteSession session = new RemoteSession(applicationName, uniqueId, host, port, myword);
        Log.v(TAG,"createsub 2nd part");
        String result = session.initialize();
        Log.v(TAG,"getting result from initialize");
        if (result.equals(ALLOWED)) {
            Log.v(TAG,"result from initialize was ALLOWED");
            return session;
        } else if (result.equals(DENIED)) {
            Log.v(TAG,"result from initialize was DENIED");
            throw new ConnectionDeniedException();
        } else if (result.equals(TIMEOUT)) {
            Log.v(TAG,"result from initialize was TIMEOUT");
            throw new TimeoutException();
        } else {
            Log.v(TAG,"result from initialize was ELSE-probably connected");
            return session; // TODO For now we just assume to be connected
            //throw new UnknownError("TV returned " + result);
        }
    }
   
    public static RemoteSession create(String applicationName, String uniqueId, String host, int port) throws IOException, ConnectionDeniedException, TimeoutException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        return create(applicationName, uniqueId, host, port, null);
    }

    private String initialize() throws UnknownHostException, IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        socket = new Socket(host, port);
        socket.setSoTimeout(5000); //5 second timeout
        InetAddress localAddress = socket.getLocalAddress();
        Log.v(TAG,"init-locAddress is " + localAddress);
        writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        writer.append((char)0x00);
        writeText(writer, APP_STRING);
        writeText(writer, getRegistrationPayload(localAddress.getHostAddress()));
        writer.flush();
       
        InputStream in = socket.getInputStream();
        reader = new InputStreamReader(in);
        String result = readRegistrationReply(reader);
        //sendPart2();
        int i;
        while ((i = in.available()) > 0) {
            in.skip(i);
        }
        return result;
    }
   
    private void sendPart2() throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        writer.append((char)0x00);
        writeText(writer, TV_APP_STRING);
        writeText(writer, new String(new char[] {0xc8, 0x00}));
    }
   
    private void checkConnection() throws UnknownHostException, IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        Log.v(TAG, "verifying CheckConnetion routine");
        //Log.v(TAG,"Socket status is " + socket.isClosed() + " other " + socket.getLocalAddress());
               
        if (socket==null ) {
            Log.v(TAG, "socket value is null");
            initialize();
        }
       
        if (socket.isClosed() || !socket.isConnected()) {
            Log.v(TAG, "Connection closed, trying to reconnect...");
            try {
                socket.close();
            } catch (UnknownHostException u) {
                Log.v(TAG,"connection error " + u);
           
            } catch (IOException e) {
                Log.v(TAG,"connection exception");
                // Ignore any exception
            }
            Log.v(TAG,"we are in CheckConnetion routine. just before initialize. ");
            initialize();
           
        }
    }
   
    public void destroy() {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        try {
            socket.close();
        } catch (IOException e) {
            // Ignore exception
        }
    }
   
    private String readRegistrationReply(Reader reader) throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        reader.read(); // Unknown byte 0x02
        String text1 = readText(reader); // Read "unknown.livingroom.iapp.samsung" for new RC and "iapp.samsung" for already registered RC
        char[] result = readCharArray(reader); // Read result sequence
        if (Arrays.equals(result, ALLOWED_BYTES)) {
            Log.v(TAG, "allowed");
            return ALLOWED;
        } else if (Arrays.equals(result, DENIED_BYTES)) {
            Log.v(TAG, "denied");
            return DENIED;
        } else if (Arrays.equals(result, TIMEOUT_BYTES)) {
            Log.v(TAG, "timeout");
            return TIMEOUT;
        } else {
            StringBuilder sb = new StringBuilder();
            for (char c : result) {
                sb.append(Integer.toHexString(c));
                sb.append(' ');
            }
            String hexReturn = sb.toString();
            Log.v(TAG, "returning hexreturn");
            return hexReturn;
        }
    }
   
    private String getRegistrationPayload(String ip) throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        StringWriter writer = new StringWriter();
        writer.append((char)0x64);
        writer.append((char) 0x00);
        writeBase64Text(writer, ip);
        writeBase64Text(writer, uniqueId);
        writeBase64Text(writer, applicationName);
        writer.flush();
        return writer.toString();
    }
   
    private static String readText(Reader reader) throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        char[] buffer = readCharArray(reader);
        return new String(buffer);
    }
   
    private static char[] readCharArray(Reader reader) throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        if (reader.markSupported()) reader.mark(1024);
        int length = reader.read();
        int delimiter = reader.read();
        if (delimiter != 0) {
            if (reader.markSupported()) reader.reset();
            throw new IOException("Unsupported reply exception");
        }
        char[] buffer = new char[length];
        reader.read(buffer);
        return buffer;
    }
   
    private static Writer writeText(Writer writer, String text) throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        return writer.append((char)text.length()).append((char) 0x00).append(text);
    }
   
    private static Writer writeBase64Text(Writer writer, String text) throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        String b64 = Base64.encodeBytes(text.getBytes());
        return writeText(writer, b64);
    }
   
    private void internalSendKey(String mykey) throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        Log.v(TAG,"mykey is " + mykey);
        writer.append((char)0x00);
        writeText(writer, TV_APP_STRING);
        writeText(writer, getKeyPayload(mykey));
        writer.flush();
        int i = reader.read(); // Unknown byte 0x00
        String t = readText(reader);  // Read "iapp.samsung"
        char[] c = readCharArray(reader);
        System.out.println(i);
        System.out.println(t);
        for (char a : c) System.out.println(Integer.toHexString(a));
       
    }
   
    public void sendKey(String mykey) throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        Log.v(TAG,"now we try checkConnetion routine");
        checkConnection();
        Log.v(TAG,"we got back from check connection");
        try {
            Log.v(TAG,"sending key internalsendkey");
            internalSendKey(mykey);
        } catch (SocketException e) {
            Log.v(TAG,"there was a socket-error. We are re-initialising");
            initialize();
            internalSendKey(mykey);
        }
       
    }

    private String getKeyPayload(String mykey) throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        StringWriter writer = new StringWriter();
        writer.append((char)0x00);
        writer.append((char)0x00);
        writer.append((char)0x00);
        writeBase64Text(writer, mykey);
        writer.flush();
        return writer.toString();
    }
   
    private void internalSendText(String text) throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        writer.append((char)0x01);
        writeText(writer, TV_APP_STRING);
        writeText(writer, getTextPayload(text));
        writer.flush();
        if (!reader.ready()) {
            return;
        }
        int i = reader.read(); // Unknown byte 0x02
        System.out.println(i);
        String t = readText(reader); // Read "iapp.samsung"
        char[] c = readCharArray(reader);
        System.out.println(i);
        System.out.println(t);
        for (char a : c) System.out.println(Integer.toHexString(a));
    }
   
    public void sendText(String text) throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        checkConnection();
        try {
            internalSendText(text);
        } catch (SocketException e) {
            initialize();
            internalSendText(text);
        }
       
    }

    private String getTextPayload(String text) throws IOException {
       
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
       
        StringWriter writer = new StringWriter();
        writer.append((char)0x01);
        writer.append((char)0x00);
        writeBase64Text(writer, text);
        writer.flush();
        return writer.toString();
    }

}
 

Attachments

  • b4aSamsungKevin.zip
    22.3 KB · Views: 258

AlpVir

Well-Known Member
Licensed User
Longtime User
I tried the library but does not work. I own a smart TV Samsung UE32H5500 (H series). In the module "remote" I added both the IP that the Mac-address of the smartphone that the Smart TV.
The smartphone has Android 2.3.3
The only result is a series of log discouraging
Log ("Something went wrong! What? No idea.")

Can anyone give me some suggestions?
 

moster67

Expert
Licensed User
Longtime User
I tried the library but does not work. I own a smart TV Samsung UE32H5500 (H series). In the module "remote" I added both the IP that the Mac-address of the smartphone that the Smart TV.
The smartphone has Android 2.3.3
The only result is a series of log discouraging
Log ("Something went wrong! What? No idea.")

Can anyone give me some suggestions?

Were you prompted on the TV-screen to allow your app to be used with the TV?
Also, check if the original app (which the wrapper is based upon) works with your TV. You can find it here. If it works, then I think the wrapper should work as well unless H-series requires extra or modified code not included in the wrapper.
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Thank you for your quick response.

I installed SamyGo Remote.
The TV is recognized (192.168.1.4) but pressing any button the message
""192.148.1.4:55000 - Connection refused."

The H series is produced in 2014 and is not listed among those compatible with SamyGo (only B or C and D).

My TV is usually connected to the internet via wifi. I have to set something in particular TV?
 

moster67

Expert
Licensed User
Longtime User
It seems like the H-series is different from previous versions. If you search for other remote control apps, they indicate they are working on a solution for H-series so apparently there is no solution yet. It seems like port 55000 is disabled. You could try with a port-scanner and see if it is open.

Some links:
http://sc0ty.pl/2012/02/samsung-tv-network-remote-control-protocol/
http://wiki.samygo.tv/index.php5/Samsung_TV_network_remote_control_protocol

I am afraid your TV might be not supported since Samsung seems to have changed things starting from the H-series. Mi spiace :(
 
Top