Package org.openhab.binding.lgtv.lginteraction

Source Code of org.openhab.binding.lgtv.lginteraction.LgTvInteractor

/**
* Copyright (c) 2010-2014, openHAB.org and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* LGInteraction / Implementation of LG API
* Author Martin Fluch martinfluch@gmx.net
*/
package org.openhab.binding.lgtv.lginteraction;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.EventObject;

import javax.xml.bind.JAXBException;

import org.openhab.binding.lgtv.internal.LgtvConnection;
import org.openhab.binding.lgtv.internal.LgtvEventListener;
import org.openhab.binding.lgtv.internal.LgtvStatusUpdateEvent;
import org.openhab.binding.lgtv.lginteraction.LgTvAppSet.oneapp;
import org.openhab.binding.lgtv.lginteraction.LgTvChannelSet.onechannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* This class handles the interaction between one tv and the plugin
*
* @author Martin Fluch
* @since 1.6.0
*/
public class LgTvInteractor implements LgtvEventListener {

  // status of connection to tv
  public enum lgtvconnectionstatus {
    CS_NOTCONNECTED, CS_CONNECTED, CS_WAITFORPAIRKEY, CS_PAIRED,

  }

  /**
   * @param args
   */
  private static Logger logger = LoggerFactory.getLogger(LgtvConnection.class);
  private int lgport = 8080; // tv's communication port
  private String lgip; // tv's ip
  private int lglocalport; // local port for message server
  private String pairkey = ""; // pair key
  private String xmldatafiles = ""; // location to save xml files (application
                    // list of tv, channel list of tv)
  private lgtvconnectionstatus connectionstatus = lgtvconnectionstatus.CS_NOTCONNECTED;
  private long lastsuccessfulinteraction = 0;

  // Lists for Applications &Channels
  private LgTvChannelSet channelset = new LgTvChannelSet();
  private LgTvAppSet appset = new LgTvAppSet();

  // the message reader server
  private LgTvMessageReader associatedreader = null;

  private int waitafterbyebye = 10; // wait 10secs for new interaction with tv
                    // after byebye event
  private long byebyeseen = -1; // time when last byebye event occured

  public String quickfind(String sourcestring, String tag) {
    String retval = "#notfound";
    String starttag = "<" + tag + ">";
    int startpt = sourcestring.indexOf(starttag);
    if (startpt >= 0) {
      int endpt = sourcestring.indexOf("</" + tag + ">");
      if (endpt >= 0) {
        retval = sourcestring.substring(startpt + starttag.length(), endpt);
      }
    }
    return retval;
  }

  // used to reach list of eventlisteners to promote connectionstatus
  public void associatereader(LgTvMessageReader m) {
    associatedreader = m;
  }

  public lgtvconnectionstatus getconnectionstatus() {
    return connectionstatus;
  }

  public void setconnectionstatus(lgtvconnectionstatus s) {
    if (s != connectionstatus) {
      logger.info("lgtv connectionstatus of ip=" + lgip + " changed from " + connectionstatus + " to " + s);
      connectionstatus = s;

      if (associatedreader != null) {
        String status = "CONNECTION_STATUS=" + ((s == lgtvconnectionstatus.CS_PAIRED) ? "1" : "0");
        LgtvStatusUpdateEvent event = new LgtvStatusUpdateEvent(this);
        associatedreader.sendtohandlers(event, lgip, status);

        if (s == lgtvconnectionstatus.CS_NOTCONNECTED) {
          associatedreader.sendtohandlers(event, lgip, status);

          String name = "CHANNEL_CURRENTNAME=0";
          String number = "CHANNEL_CURRENTNUMBER=0";
          String vol = "VOLUME_CURRENT=0";
          associatedreader.sendtohandlers(event, lgip, name);
          associatedreader.sendtohandlers(event, lgip, number);
          associatedreader.sendtohandlers(event, lgip, vol);
        }

      }

    }

  }

  public boolean ispaired() {
    return (connectionstatus == lgtvconnectionstatus.CS_PAIRED);
  }

  public LgTvInteractor(String ip, int port, int localport, String xmldf) throws InterruptedException {

    lgip = ip;
    lgport = port;
    lglocalport = localport;
    xmldatafiles = xmldf;

  }

  public void seensuccessfulinteraction() {
    lastsuccessfulinteraction = System.currentTimeMillis();
  }

  public long getlastsuccessfulinteraction() {
    return lastsuccessfulinteraction;
  }

  public String requestpairkey() {
    String message = "";
    message = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"pairing\"><name>showKey</name></api></envelope>";
    String answer = sendtotv("POST", "udap/api/pairing", message);
    logger.debug("answer: " + answer);
    if (answer.startsWith("200"))
      setconnectionstatus(lgtvconnectionstatus.CS_WAITFORPAIRKEY);
    else
      setconnectionstatus(lgtvconnectionstatus.CS_NOTCONNECTED);
    return new String(answer);
  }

  public String getcurrentchannel() {
    String message = "";
    message = "";
    String answer = "#notpaired";
    if (ispaired()) {
      answer = sendtotv("GET", "udap/api/data?target=cur_channel", message);
    }
    return new String(answer);
  }

  public String getallchannels() {
    String message = "";
    message = "";
    String answer = "#notpaired";

    if (ispaired()) {
      answer = sendtotv("GET", "udap/api/data?target=channel_list", message);

      try {
        channelset.loadchannels(answer);
        int i = channelset.getsize();
        String s = String.valueOf(i);
        answer = s;
        if (this.xmldatafiles.length() > 0) {

          String filename = this.xmldatafiles + lgip + "_lgtvallchannels.xml";
          logger.debug("xmldatafiles is set - writing file=" + filename);
          channelset.savetofile(filename);

        }

      } catch (JAXBException e) {

        logger.error("exception in getallchannels: ", e);
        org.xml.sax.SAXParseException f = (org.xml.sax.SAXParseException) e.getLinkedException();
        logger.error("parse exception e=" + e.toString() + " line=" + f.getLineNumber() + " columns="
            + f.getColumnNumber() + " local=" + f.getLocalizedMessage());
      }
    }

    return new String(answer);
  }

  public String getallapps() {
    String message = "";
    message = "";
    String answer = "#notpaired";
    if (ispaired()) {
      answer = sendtotv("GET", "udap/api/data?target=applist_get&type=1&index=1&number=1024", message);

      logger.debug("answer: " + answer);
      try {
        appset.loadapps(answer);
        int i = appset.getsize();
        String s = String.valueOf(i);
        answer = s;

        if (this.xmldatafiles.length() > 0) {

          String filename = this.xmldatafiles + lgip + "_lgtvallapps.xml";
          logger.debug("xmldatafiles is set - writing file=" + filename);
          appset.savetofile(filename);

        }

      } catch (JAXBException e) {

        logger.error("error in getallapps", e);
        org.xml.sax.SAXParseException f = (org.xml.sax.SAXParseException) e.getLinkedException();
        logger.error("parse exception e=" + e.toString() + " line=" + f.getLineNumber() + " columns="
            + f.getColumnNumber() + " local=" + f.getLocalizedMessage());
      }

    }
    return new String(answer);
  }

  public String getvolumeinfo(int dontcheckpairing) {
    String message = "";
    message = "";
    String answer = "#notpaired";

    if (dontcheckpairing == 1 || ispaired()) {
      answer = sendtotv("GET", "udap/api/data?target=volume_info", message);
      logger.debug("answer: " + answer);
    }

    return new String(answer);
  }

  public String handlevolchangeeasy(String sval) {
    String res = "#notpaired";
    int val;

    int pos = sval.indexOf(".");
    if (pos > 0) {
      String ns = sval.substring(0, pos);
      val = Integer.parseInt(ns);
    } else
      val = Integer.parseInt(sval);

    if (ispaired()) {
      res = getvolumeinfo(0);
      String currentvol = quickfind(res, "level");
      int cvol = Integer.parseInt(currentvol);
      int todo = val - cvol;
      logger.debug("currentvolume=" + cvol + " newvolume=" + val + " todo=" + todo);

      LgTvCommand volup = LgTvCommand.valueOf("VOLUME_UP");
      LgTvCommand voldown = LgTvCommand.valueOf("VOLUME_DOWN");

      String usecommand = todo > 0 ? volup.getLgSendCommand() : voldown.getLgSendCommand();

      if (todo < 0)
        todo = todo * -1;
      for (int i = 0; i < todo; i++) {
        handlekeyinput(usecommand);
      }

      logger.debug("currentvolume=" + cvol + " newvolume=" + val + " todo=" + todo + " usecommand=" + usecommand);

      if (todo != 0) {
        res = getvolumeinfo(0);
        currentvol = quickfind(res, "level");

        if (associatedreader != null) {
          String volume = "VOLUME_CURRENT=" + val;
          LgtvStatusUpdateEvent event = new LgtvStatusUpdateEvent(this);
          associatedreader.sendtohandlers(event, lgip, volume);
        }

      }
    }

    return new String(res);
  }

  public void setpairkey(String s) {
    pairkey = s;
  }

  public String getpairkey() {
    return pairkey;
  }

  public long getbyebyeseen() {
    return byebyeseen;
  }

  public void checkpairing() {
    int nobyebyeproblem = 1;

    long duration = System.currentTimeMillis() - byebyeseen;

    nobyebyeproblem = ((duration > (waitafterbyebye * 1000)) == true) ? 1 : 0;

    if (byebyeseen == -1 || nobyebyeproblem == 1) {
      if (connectionstatus != lgtvconnectionstatus.CS_PAIRED && pairkey.length() > 0) {
        sendpairkey();
      } else if (pairkey.length() == 0)
        logger.error("no pairkey defined");
    }

  }

  public String sendpairkey() {
    logger.debug("sending pairkey key=" + pairkey);
    String message = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"pairing\"><name>hello</name><value>"
        + pairkey + "</value><port>" + Integer.toString(lglocalport) + "</port></api></envelope>";
    String answer = sendtotv("POST", "udap/api/pairing", message);
    logger.debug("answer: " + answer);
    String success = "";
    if (answer.startsWith("200")) {
      success = "success";
      setconnectionstatus(lgtvconnectionstatus.CS_PAIRED);
    }

    logger.info("sendpairkey with result=" + answer + " " + success + "connectionstatus=" + connectionstatus.name());
    return new String(answer);
  }

  public String handlekeyinput(String key) {
    String answer = "#notpaired";
    String message = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"command\"><name>HandleKeyInput</name><value>"
        + key + "</value></api></envelope>";

    if (ispaired()) {
      answer = sendtotv("POST", "udap/api/command", message);
      logger.debug("answer: " + answer);
    }
    return new String(answer);
  }

  public String appexecute(String appname, String id, String contentid) {
    String answer = "#notpaired";

    String message = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"command\"><name>AppExecute</name><auid>"
        + id
        + "</auid><appname>"
        + appname
        + "</appname><contentId>"
        + contentid
        + "</contentId></api></envelope>";
    if (ispaired()) {
      answer = sendtotv("POST", "udap/api/command", message);
      logger.debug("answer: " + answer);
    }
    return new String(answer);
  }

  public String appexecuteeasy(String name) {

    String cid = "";
    String id = "";

    if (name.length() == 0)
      return new String("#appnotfound");

    LgTvAppSet.envelope env = appset.getenvel();
    if (env == null) {
      logger.error("envelope=null maybe not connected");
      return new String("#appnotfound");
    } else {

      oneapp e = appset.getenvel().find(name);
      if (e != null) {

        cid = String.valueOf(e.getcpid());
        id = e.getid();

        return new String(appexecute(name, id, cid));
      } else {
        id = cid = name = "";
        return new String("#appnotfound");
      }
    }

  }

  public String appterminate(String appname, String id) {

    String message = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"command\"><name>AppTerminate</name><auid>"
        + id + "</auid><appname>" + appname + "</appname></api></envelope>";
    String answer = "#notpaired";
    if (ispaired()) {
      answer = sendtotv("POST", "udap/api/command", message);
      logger.debug("answer: " + answer);
    }
    return new String(answer);
  }

  public String appterminateeasy(String name) {
    String id = "";

    if (name.length() == 0)
      return new String("#appnotfound");

    oneapp e = appset.getenvel().find(name);
    if (e != null) {

      id = e.getid();

      return new String(appterminate(name, id));
    } else {
      id = name = "";
      return new String("#appnotfound");
    }

  }

  public String handlechannelchange(String major, String minor, String sourceindex, int phys) {
    String message = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"command\"><name>HandleChannelChange</name><major>"
        + major
        + "</major><minor>"
        + minor
        + "</minor><sourceIndex>"
        + sourceindex
        + "</sourceIndex>"
        + "<physicalNum>" + String.valueOf(phys) + "</physicalNum>" + "</api></envelope>";
    String answer = "#notpaired";
    if (ispaired()) {
      answer = sendtotv("POST", "udap/api/command", message);
      logger.debug("answer: " + answer);
    }
    return new String(answer);
  }

  public String handlechannelchangeeasy(String major) {
    String minor = "";
    String sourceindex = "";

    String c = major;
    // String chname="";
    // String chtype="";
    int phys = -1;
    String res = "#error";

    int pos = major.indexOf(".");
    if (pos > 0) {
      String ns = major.substring(0, pos);
      c = ns;
    }

    // logger.debug("hceasy: "+major+" -- "+c);
    LgTvChannelSet.envelope env = null;
    if (channelset == null) {
      logger.error("channelset=null");
    } else {
      env = channelset.getenvel();
    }

    if (env == null)
      logger.error("envelope=null maybe not connected");
    else {
      onechannel e = channelset.getenvel().find(Integer.parseInt(c));
      if (e != null) {
        minor = String.valueOf(e.getminor());
        phys = e.getphysicalnum();
        // chtype=e.getchtype();
        // chname=e.getchname();
        sourceindex = String.valueOf(e.getsourceindex());
        res = handlechannelchange(c, minor, sourceindex, phys);
      } else {
        minor = "";
        // chtype="";
      }
    }

    // channelset.getchannelinfo(Integer.parseInt(major), minor, chname,
    // chtype, sourceindex);
    return new String(res);
  }

  public String sendtotv(String typ, String command, String s) {
    HttpURLConnection connection = null;
    OutputStreamWriter wr = null;
    String conf_tv_url;
    Integer responsecode = -1;

    conf_tv_url = "http://" + lgip + ":" + Integer.toString(lgport); // 192.168.77.15:8080";

    logger.debug("sendtotv: url=" + conf_tv_url + " typ=" + typ + " command=" + command + " s=" + s);
    if (connectionstatus != lgtvconnectionstatus.CS_PAIRED)
      logger.error("sendtotv but connection status is " + connectionstatus.name());

    BufferedReader rd = null;
    StringBuilder sb = null;
    String line = null;
    String returnmessage = "#error";
    URL serverAddress = null;
    String serverAddressString = conf_tv_url + "/" + command;

    try {
      serverAddress = new URL(serverAddressString);

      // set up out communications stuff
      connection = null;

      // Set up the initial connection
      connection = (HttpURLConnection) serverAddress.openConnection();

      connection.setRequestProperty("content-type", "text/xml; charset=utf-8");
      connection.setRequestProperty("Host", lgip + ":" + Integer.toString(lgport)); // "192.168.77.15:8080");

      connection.setRequestProperty("Connection", "close");
      connection.setRequestProperty("User-Agent", "Linux/2.6.18 UDAP/2.0 CentOS/5.8");
      connection.setUseCaches(false);
      connection.setReadTimeout(10000);

      if (typ.equals("POST")) {
        connection.setDoOutput(true);
      }
      connection.setDoInput(true);
      connection.setRequestMethod(typ);
      connection.connect();

      if (typ.equals("POST")) {
        wr = new OutputStreamWriter(connection.getOutputStream());
        wr.write(s);
        wr.flush();
      }

      // read the result from the server
      rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
      sb = new StringBuilder();

      while ((line = rd.readLine()) != null) {
        sb.append(line + '\n');
      }

      logger.debug(sb.toString());
      returnmessage = sb.toString();
      responsecode = connection.getResponseCode();

    } catch (MalformedURLException e) {
      e.printStackTrace();
      logger.error("MalformedUrlException at Connection to: " + serverAddressString);
      returnmessage = "#error/url";
    } catch (ProtocolException e) {
      e.printStackTrace();
      logger.error("Protocol Exception at Connection to: " + serverAddressString);
      returnmessage = "#error/protocol";
    } catch (IOException e) {
      logger.error("IO Exception at Connection to: " + serverAddressString);
      // logger.debug(e.toString());
      returnmessage = "#error/connect";
      setconnectionstatus(lgtvconnectionstatus.CS_NOTCONNECTED);
      // e.printStackTrace();
    }
    // close the connection, set all objects to null
    returnmessage += Integer.toString(responsecode);

    if (connectionstatus != lgtvconnectionstatus.CS_NOTCONNECTED)
      seensuccessfulinteraction();
    if (connection != null)
      connection.disconnect();
    rd = null;
    sb = null;
    wr = null;
    connection = null;
    return new String(returnmessage);
  }

  public void statusUpdateReceived(EventObject event, String ip, String data) {

    if (ip.equals(lgip)) {

      if (data.startsWith("BYEBYE_SEEN") == true) {
        byebyeseen = System.currentTimeMillis(); // as tv keeps alive
                              // for ~10secs we
                              // have to prevent
                              // any further
                              // communication
        setconnectionstatus(lgtvconnectionstatus.CS_NOTCONNECTED);
      }

    }

  }

}
TOP

Related Classes of org.openhab.binding.lgtv.lginteraction.LgTvInteractor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.