Jump to content

Subscribe to Portal using Web Socket


Javi

Recommended Posts

Posted (edited)

Is it possible to subscribe to the Portal using REST?

I can send REST commands to ISY from portal with the same Credentials

        String credential = Credentials.basic(mUserName, mPassword);
        mRequest = new Request.Builder()
                .url(baseUrl)
                .header("Authorization", credential)
                .addHeader("Sec-WebSocket-Protocol", "ISYSUB")
                .addHeader("Sec-WebSocket-Version", "13")
                .addHeader("Origin", "com.universal-devices.websockets.isy")
                .build();
        mListener = new IsyWebSocketListener();

 

I get the following Error:

unexpected end of stream on Connection{my.isy.io:443, proxy=DIRECT hostAddress=my.isy.io/34.237.193.77:443 cipherSuite=TLS_RSA_WITH_AES_128_GCM_SHA256 protocol=http/1.1}

Edited by Javi
Posted (edited)

Does the ISY Portal require headers different from the ISY for event subscription? Is there Portal subscription documentation which may assist me?

I can get SOAP subscription to work on local network but I am having problems connecting to the Portal. The Java Thread below woks with my local network. I have commented out ("//" for java)  the lines changed for connection to the Portal.  IF (username:password  && URL && Port) are changed I get no response from the Portal.  IF (username:password && URL) are changed and port left at 80 than I get the following Lines:

LineBuffer: HTTP/1.1 400 BAD_REQUEST
LineBuffer: Content-Length: 0
LineBuffer: Connection: Close

Java Thread:

@Override
    public void run() {
        Log.v(LOG_TAG, "Runnable Started");
        String usernamePassword = "localUserName" + ":" + "localPassword";
        //String usernamePassword = "myEmailAddress@gmail.com" + ":" + "myPortalPassword";
        String base64UsernamePassword;

        try {
            byte[] usernamePasswordByte = usernamePassword.getBytes("UTF-8");
            base64UsernamePassword = Base64.encodeToString(usernamePasswordByte, Base64.DEFAULT);
            Log.v(LOG_TAG, "base64 username is: " + base64UsernamePassword);
        } catch (UnsupportedEncodingException e) {
            Log.v(LOG_TAG, "Error: " + e);
            return;
        }


        try {
            URL url = new URL("http://192.168.5.2");
            //URL url = new URL("https://my.isy.io");
            String host = url.getHost();
            int port = 80;
            //int port = 443;

            Socket socket = new Socket();
            socket.connect(new InetSocketAddress(host, port));
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(socket.getOutputStream());
            InputStream inputStream = socket.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);


            String body = "<s:Envelope><s:Body>" +
                    "<u:Subscribe xmlns:u='urn:udi-com:service:X_Insteon_Lighting_Service:1'>" +
                    "<reportURL>REUSE_SOCKET</reportURL><duration>infinite</duration>" +
                    "</u:Subscribe></s:Body></s:Envelope>";

            outputStreamWriter.write("POST /services HTTP/1.1\n" +
                    "Content-Type: text/xml; charset=utf-8\n" +
                    "Authorization: " + "Basic " + base64UsernamePassword + "\n" +
                    "Content-Length: " + (body.length()) + "\n" +
                    "SOAPAction: urn:udi-com:device:X_Insteon_Lighting_Service:1#Subscribe" +
                    "\r\n" +
                    "\r\n" +
                    body);
            outputStreamWriter.flush();

            StringBuffer headerBuffer = new StringBuffer();

            StringBuilder stringBuilder = new StringBuilder();
            String messageFromServer;


            while ((messageFromServer = bufferedReader.readLine()) != null) {
                //Log each line
                Log.v(LOG_TAG, "LineBuffer: " + messageFromServer);
            }

            headerBuffer.setLength(0);
        } catch (IOException e) {
            Log.v(LOG_TAG, "IOException is: " + e);
        }

        //TODO: Stop Android Service. This is only a test. Service stopSelf() may not be called
        stopSelf();
    }

<Edit>

I just noticed I was looking at 2 versions of documentation will try again tomorrow 

 

ISY-WS-SDK

SUBSCRIBE /eventing HTTP/1.1
Host: 192.168.0.208:80
Content-Length: 129
Content-Type: text/xml; charset="utf-8"
Authorization: Basic YWRtaW46YWRtaW4=
CALLBACK:<REUSE_SOCKET>
NT:upnp:event
TIMEOUT:Second-infinite
SOAPACTION:"urn:udi-com:service:X_Insteon_Lighting_Service:1#Subscribe"
<s:Envelope><s:Body><u:Subscribe xmlns:u="urn:udicom:
service:X_Insteon_Lighting_Service:1"></u:Subscribe></s:Body></s:Envel
ope>
  
  
  
  

ISY Developer's Cookbook

(Text not enabled to copy) Search for "3. Subscribe"

</Edit>

Edited by Javi
Posted (edited)

Thanks Michel!

 

I spent 3 hours trying to get a connection which turned out to be on one line of code  that was adding a new line char to the encoded username and password that the ISY accepted but the Portal did not.  There are not many great examples for Java connections to the portal. So hopefully the code below will save the next person a few hours.

package com.voiceforiot.iotsecuritypanel.Services;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Base64;
import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class SSLSoapSocketService extends Service {

    private String LOG_TAG = SSLSoapSocketService.class.getSimpleName();

    private Thread backgroundThread;

    private Runnable attemptSocketConnection = new Runnable() {
        @Override
        public void run() {

            String usernamePassword = "myEmalAddressUsedForPortal@gmail.com" + ":" + "myPortalPassword";
            String base64UsernamePassword;

            try {
                byte[] usernamePasswordByte = usernamePassword.getBytes("UTF-8");
                //NO_WRAP NEEDED AS DEFAULT APPENDS NEW LINE CHAR
                base64UsernamePassword = Base64.encodeToString(usernamePasswordByte, Base64.NO_WRAP);
                Log.v(LOG_TAG, "base64 username is: " + base64UsernamePassword);
            } catch (UnsupportedEncodingException e) {
                Log.v(LOG_TAG, "Error: " + e);
                return;
            }

            URL url = null;
            try {
                //get this from my.isy.io, click on Select Tools | ISY Information and then copy/paste the URL for your ISY (not the Admin Console).
                url = new URL("https://my.isy.io/isy/someVeryLongStringHere");
            } catch (MalformedURLException e) {
                Log.v(LOG_TAG, "MalformedURLException: " + e);
            }
            String urlString = url.toString();
            String host = url.getHost();

            String body = "<s:Envelope><s:Body>" +
                    "<u:Subscribe xmlns:u='urn:udi-com:service:X_Insteon_Lighting_Service:1'>" +
                    "<reportURL>REUSE_SOCKET</reportURL><duration>infinite</duration>" +
                    "</u:Subscribe></s:Body></s:Envelope>";

            String writeString = "POST /services HTTP/1.1\n" +
                    "Host: " + urlString +"\n" +
                    "Content-Type: text/xml; charset=utf-8\n" +
                    "Authorization: " + "Basic " + base64UsernamePassword + "\n" +
                    "Content-Length: " + (body.length()) + "\n" +
                    "SOAPAction: urn:udi-com:device:X_Insteon_Lighting_Service:1#Subscribe" +
                    "\r\n" +
                    "\r\n" +
                    body +
                    "\r\n";

            Log.v(LOG_TAG,"writeString\n" + writeString);

            try{
                SSLSocketFactory factory =
                        (SSLSocketFactory)SSLSocketFactory.getDefault();
                SSLSocket socket =
                        (SSLSocket)factory.createSocket(host, 443);

                socket.startHandshake();

                PrintWriter out = new PrintWriter(
                        new BufferedWriter(
                                new OutputStreamWriter(
                                        socket.getOutputStream())));
                out.print(writeString);
                out.print("");
                out.flush();

                //check if any errors exist
                if (out.checkError()){
                    Log.v(LOG_TAG, "SSLSocketClient: java.io.PrintWriter error");
                }

                //Read
                BufferedReader in = new BufferedReader(
                        new InputStreamReader(
                                socket.getInputStream()));

                String inputLine;
                while ((inputLine = in.readLine()) != null){
                    Log.v(LOG_TAG, inputLine);
                }

                Log.v(LOG_TAG, "Closing Socket");
                in.close();
                out.close();
                socket.close();




            }catch (UnknownHostException e){
                Log.v(LOG_TAG, "UnknownHostException: " + e);
            }catch (IOException e){
                Log.v(LOG_TAG, "IOException: " + e);
            }



        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        if (intent != null) {
            //TODO: need to check if service is already started before re-attemptSocketConnection
            Log.v(LOG_TAG, "onStartCommandStarted");
            this.backgroundThread = new Thread(attemptSocketConnection);
            this.backgroundThread.start();
            return super.onStartCommand(intent, flags, startId);
        }

        return super.onStartCommand(intent, flags, startId);
    }
}

 

Edited by Javi
  • Like 2

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...