// Original wrapper class:
package b4a.tillekesoft.samsungtv;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.concurrent.TimeoutException;
import android.util.Log;
import anywheresoftware.b4a.AbsObjectWrapper;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.BA;
@Author("moster67")
@BA.ShortName("RemoteSession")
@Version(1.4f)
public class b4aRemoteSession extends AbsObjectWrapper<RemoteSession> {
private String applicationName;
private String uniqueId;
private String host;
private int port;
private String myword;
private String b4amyword;
private RemoteSession session;
private static final String TAG = "TAG_B4AWrapper";
/**
* Initialize the RemoteSession object
* @throws TimeoutException
* @throws ConnectionDeniedException
* @throws IOException
*/
public void Initialize(String b4aapplicationName, String b4auniqueId, String b4ahost, int b4aport) throws IOException, ConnectionDeniedException, TimeoutException{
this.applicationName = b4aapplicationName;
this.uniqueId = b4auniqueId;
if (uniqueId == null) {
uniqueId = "";
}
this.host = b4ahost;
this.port = b4aport;;
this.b4amyword = "anything";
this.myword = "anything";
Log.v(TAG,"Initvalues are " + b4aapplicationName + "-" + b4auniqueId + "-" + b4ahost + "-" + b4aport);
setObject(new RemoteSession(b4aapplicationName, b4auniqueId,b4ahost,b4aport,b4amyword));
}
public void Connect() throws IOException, ConnectionDeniedException, TimeoutException{
Log.v(TAG,"Connecting");
RemoteSession.create(applicationName, uniqueId, host, port, myword);
}
public void sendCode(String mykey) throws UnknownHostException, IOException, InterruptedException, ConnectionDeniedException, TimeoutException {
Log.v(TAG,"Before sendcode values are " + applicationName + "-" + uniqueId + "-" + host + "-" + port);
Log.v(TAG,"Session value is " + session);
if ( session == null) Initialize(applicationName, uniqueId, host, port);
if (mykey != null) {
Log.v(TAG,"Launching sendkey");
getObject().sendKey(mykey);
}
}
public void uninitialize() {
Log.v(TAG, "Uninitializing C-Series Sender...");
if (session != null) {
getObject().destroy();
Log.v(TAG, "...Uninitialized C-Series Sender");
} else {
Log.v(TAG, "...Nothing to uninitialize, session is null");
}
}
}
------------------------------------------------------------------------------------------------------------
// Original Java class:
/*
* 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
* http://www.gnu.org/licenses/gpl.html
*/
package b4a.tillekesoft.samsungtv;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.concurrent.TimeoutException;
import android.util.Log;
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 {
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 {
return create(applicationName, uniqueId, host, port, null);
}
private String initialize() throws UnknownHostException, IOException {
socket = new Socket(host, port);
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 {
writer.append((char)0x00);
writeText(writer, TV_APP_STRING);
writeText(writer, new String(new char[] {0xc8, 0x00}));
}
private void checkConnection() throws UnknownHostException, IOException {
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() {
try {
socket.close();
} catch (IOException e) {
// Ignore exception
}
}
private String readRegistrationReply(Reader reader) throws IOException {
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 {
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 {
char[] buffer = readCharArray(reader);
return new String(buffer);
}
private static char[] readCharArray(Reader reader) throws IOException {
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 {
return writer.append((char)text.length()).append((char) 0x00).append(text);
}
private static Writer writeBase64Text(Writer writer, String text) throws IOException {
String b64 = Base64.encodeBytes(text.getBytes());
return writeText(writer, b64);
}
private void internalSendKey(String mykey) throws IOException {
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 {
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 {
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 {
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 {
checkConnection();
try {
internalSendText(text);
} catch (SocketException e) {
initialize();
internalSendText(text);
}
}
private String getTextPayload(String text) throws IOException {
StringWriter writer = new StringWriter();
writer.append((char)0x01);
writer.append((char)0x00);
writeBase64Text(writer, text);
writer.flush();
return writer.toString();
}
}