Chrome.sockets.tcp problem to receive onReceive.addListener

Hello!
I’m using the cordova plugin chrome.sockets.tcp. I have created a provider for managing sockets operations in my Ionic 3 app.

Whenever I use the “invioPacchetto” (english -> sendPackage) function of this provider, socket creation and connection is successful … and the package is sent with a reply by device to which I am connected.
The onReceive.addListener event (present in the “invioPacchetto” function of this provider) sometimes receives the answer and sometimes not! I’m going crazy.

I’m 100% sure that the deviceto which I am connected responds to the send received from the app but the onReceive.addListener event does NOT occur on the app

N.B. I debug the device I communicate with in real time, so I see everything that arrives and leaves via sockets connections… and everything works

Here is the provider code with which I manage all sockets communications.

This is the code of provider (sorry for comments inside):

import { Platform, LoadingController } from 'ionic-angular';
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import 'rxjs/add/operator/map';

@Injectable()
export class TCPServices {

  public array_qui:Array<Object> = [];
  public tipo_platform: string;
  public array_risposta_invioPacchetto:Array<Object> = [];
  public appoggio_tempo: number;

  constructor(public http: HttpClient, public loadingCtrl: LoadingController, platform:Platform) {
    console.log('Hello FunzioniSocketsProvider Provider');

    platform.ready().then((readySource) => {
      //inizio misurazione del tempo
      this.appoggio_tempo = Date.now();

      if(readySource=='cordova'){
        this.tipo_platform = readySource;

        this.array_qui['piattaforma'] = this.tipo_platform;
        this.array_qui['tempo_esecuzione'] = (Date.now()-this.appoggio_tempo);
      
      } else {
        this.tipo_platform = "browser";

        this.array_qui['piattaforma'] = "browser";
        this.array_qui['tempo_esecuzione'] = (Date.now()-this.appoggio_tempo);
      }

      console.log("constructor FunzioniSocketsProvider -> "+this.array_qui['piattaforma']);
    });
  }

  testfunzione(){
    console.log("controllo platform su TCPServices -> "+this.tipo_platform);
    //alert("controllo platform su TCPServices -> "+this.tipo_platform);

    return new Promise(resolve => {
      resolve(this.array_qui);

    });
  }

  arrayBuffer2str(buf) {
		var str= '';
		var ui8= new Uint8Array(buf);
		for (var i= 0 ; i < ui8.length ; i++) {
			str= str+String.fromCharCode(ui8[i]);
		}
		return str;
	}

	str2arrayBuffer(str) {
		var buf= new ArrayBuffer(str.length);
		var bufView= new Uint8Array(buf);
		for (var i= 0 ; i < str.length ; i++) {
			bufView[i]= str.charCodeAt(i);
  		}
		return buf;
  }

	invioPacchetto(ipAddr,ipPort,testo_loader,data,tipo_funzione_per_test) {
    return new Promise(resolve => {
      if(this.tipo_platform=='cordova'){
        if(data!=''){
          //se ci sono dati da inviare -> proseguo l'operazione
          console.log("siamo in invioPacchetto ;-) ... e i dati da inviare ci sono");
          
          //carica componente loading
          let loading = this.loadingCtrl.create({
            content: testo_loader,
            duration: 5000
          });
          loading.present();

          var delay= 5000;	/// 5 seconds timeout
          (<any>window).chrome.sockets.tcp.create({}, createInfo => { //callback function with createInfo as the parameter
            var _socketTcpId= createInfo.socketId;
            console.log("invioPacchetto A1 ... idsockets: "+_socketTcpId);

            (<any>window).chrome.sockets.tcp.connect(_socketTcpId, ipAddr, ipPort, result => { //callback function with result as the parameter
              if (result === 0) {
                this.array_risposta_invioPacchetto['result'] = result;
                this.array_risposta_invioPacchetto['testo_errore'] = '';

                var data2send= this.str2arrayBuffer(data);
                /// connection ok, send the packet
                (<any>window).chrome.sockets.tcp.send(_socketTcpId, data2send);
              } else {
                //error of connection
                this.array_risposta_invioPacchetto['result'] = result;
                this.array_risposta_invioPacchetto['testo_errore'] = 'Errore di connessione rilevato ...';
                this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = '';

                //restituisci errore di connessione
                resolve(this.array_risposta_invioPacchetto);
                //togli loading
                loading.dismiss();
              }
            });
            (<any>window).chrome.sockets.tcp.onReceive.addListener( info => { //callback function with info as the parameter
              /// recived, then close connection
              //(<any>window).chrome.sockets.tcp.close(_socketTcpId); chiude l'attuale processo -> mai io devo chiudere il socket della risposta!
              (<any>window).chrome.sockets.tcp.close(info.socketId);
              this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = this.arrayBuffer2str(info.data);

              resolve(this.array_risposta_invioPacchetto);
              //togli loading
              loading.dismiss();
            });
            (<any>window).chrome.sockets.tcp.onReceiveError.addListener( info => {
              (<any>window).chrome.sockets.tcp.close(info.socketId);
              this.array_risposta_invioPacchetto['result'] = -999; //codice errore scelto da me
              this.array_risposta_invioPacchetto['testo_errore'] = this.arrayBuffer2str(info.data);
              this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = ''; //essendo un errore
              
              resolve(this.array_risposta_invioPacchetto);
              //togli loading
              loading.dismiss();
            });
            /// set the timeout
            setTimeout(function() {
              (<any>window).chrome.sockets.tcp.close(_socketTcpId);
              this.array_risposta_invioPacchetto['testo_errore'] = 'Timeout connessione socket eseguita';
              this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = '';

              resolve(this.array_risposta_invioPacchetto);
              //togli loading
              loading.dismiss();
            }, delay);
          });

        } else {
          //nessuna dato passato da inviare
          this.array_risposta_invioPacchetto['result'] = -1;
          this.array_risposta_invioPacchetto['testo_errore'] = 'Nessuna stringa passata da inviare tramite sockets ...';
          this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = '';

          resolve(this.array_risposta_invioPacchetto);
        }
      } else {
        let loading = this.loadingCtrl.create({
          content: testo_loader,
          duration: 1000
        });
        loading.present();

        //dati di risposta con la stessa struttura del socket sopra in cordova
        this.array_risposta_invioPacchetto['result'] = -1;
        this.array_risposta_invioPacchetto['testo_errore'] = 'La connessione Socket non è attiva perchè siamo su '+this.tipo_platform;
        
        if(tipo_funzione_per_test=='lista funzioni'){
          //risposta vuota -> come dovrebbe essere ;-)
          //this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = '';
        
          // *** LISTA FUNZIONI *** risposta con dati -> per fare i test ;-)
          this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = '{"Info":{"HW":"ICON100 demo","ID":"101.100.100.100","NAME":"ICON500","VERSION":"0.4.42.32","TYPE":1,"TIMER":"1 minuto 5 secondi","cmd_supp":["Funzione demo ;-)","Info","Program","GetRTConfig","GetRTVal"]}}';
        }

        if(tipo_funzione_per_test=='invio programmazione'){
          // *** INVIO PROGRAMMAZIONE *** simulazione di valore "Error" restituito
          //this.array_risposta_invioPacchetto['testo_errore'] = 'Similuazione di errore...';
          //this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = '{"Program":"impianto.exp","Chunk":1,"Total":4,"Error":"Invalid CRC"}';
          // *** INVIO PROGRAMMAZIONE *** simulazione pacchetto ricevuto OK
          //this.array_risposta_invioPacchetto['testo_errore'] = '';
          //this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = '{"Program":"impianto.exp","Chunk":1,"Total":3,"TimeMS":4210}';

          /*** SIMULAZIONE ERRORE GENERALE SOCKETS PER INVIO PROGRAMMAZIONE
          this.array_risposta_invioPacchetto['result'] = -999; //codice errore scelto da me
          this.array_risposta_invioPacchetto['testo_errore'] = 'Un testo di errore a caso...';
          this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = ''; //essendo un errore
          */
        }

        /*** LISTE PER REALTIME */
        if(tipo_funzione_per_test=='liste realtime'){
          this.array_risposta_invioPacchetto['testo_errore'] = '';
          this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = '{"GetRTConfig":{"Chunk":1,"Total":1,"Len":1208,"CRC":"b1e7","BASE64":"eyJvYmpzIjpbeyJpZCI6IjAwMC4wMDAuMDA1LjAyMV8wMDAiLCJkZXNjIjoiSW5jcmVtLiBDdXRvZmYgQW1iLiIsIm1heCI6IjEwMC4wIiwibWluIjoiMC4wIiwidW0iOiImZGVnO0MiLCJiZyI6IiNDMEMwQzAiLCJmb3IiOiIjMDAwMDAwIiwidmlzIjoiVEVTVE8yIiwiUk8iOiIwIiwibW9kIjoiRk9STV9GTE9BVF8wMSIsInBhZyI6IlBhcmFtZXRyaSIsIlgiOiI0NTBweCIsIlkiOiIyMHB4IiwiRFgiOiIyMDBweCIsIkRZIjoiNjRweCJ9LAp7ImlkIjoiMDAwLjAwMC4wMDUuMDI1XzAwMSIsImRlc2MiOiJDdXRvZmYgRXh0IiwibWF4IjoiMTAwLjAiLCJtaW4iOiIwLjAiLCJ1bSI6IiZkZWc7QyIsImJnIjoiI0MwQzBDMCIsImZvciI6IiMwMDAwMDAiLCJ2aXMiOiJURVNUTzIiLCJSTyI6IjAiLCJtb2QiOiJGT1JNX0ZMT0FUXzAxIiwicGFnIjoiU2lub3R0aWNvIiwiWCI6IjY3NXB4IiwiWSI6IjIwcHgiLCJEWCI6IjIwMHB4IiwiRFkiOiI2NHB4In0sCnsiaWQiOiIwMDAuMDAwLjAwNS4wMTVfMDAyIiwiZGVzYyI6Ik1pbiBULiBNYW5kLiIsIm1heCI6IjEwMC4wIiwibWluIjoiMC4wIiwidW0iOiImZGVnO0MiLCJiZyI6IiNDMEMwQzAiLCJmb3IiOiIjMDAwMDAwIiwidmlzIjoiVEVTVE8yIiwiUk8iOiIwIiwibW9kIjoiRk9STV9GTE9BVF8wMSIsInBhZyI6IlBhcmFtZXRyaSIsIlgiOiIwcHgiLCJZIjoiMTU5cHgiLCJEWCI6IjIwMHB4IiwiRFkiOiI2NHB4In1dCn0="}}';
        }

        //togli loading
        //loading.dismiss();

        resolve(this.array_risposta_invioPacchetto);
      }
    });
	}

}

Any ideas ?
I’m looking for help! Give me a hand, please

p.s. this could also become a job for a freelance

Maybe I could use:

(<any>window).chrome.sockets.tcp.setPaused(_socketTcpId,false);

after

(<any>window).chrome.sockets.tcp.connect

if set .setPaused on false, when a socket is connected and un-paused, onReceive events are raised again when messages are received (I read about the documentation … link below)

https://developer.chrome.com/apps/sockets_tcp#method-setPaused

what do you think about?

This is not the solution because default value of “chrome.sockets.tcp.setPaused” is “false”.

Help me please! :weary:

you’ve got a timing window \

create {
connect
send
}
----
onReceive.addlistener({
 });
onReceiveError.addlistener({
 });
---

move the connect/send AFTER adding the listeners…

----
onReceive.addlistener({
 });
onReceiveError.addlistener({
 });
---
create({
connect
send
})
---

otherwise there is a timing window, where the send might happen before the listeners are setup… sometimes…
which is what you are seeing…

Ok, I moved onReceive.addlistener and onReceiveError.addlistener before Create -> connect -> send.

This is the code updated:

(<any>window).chrome.sockets.tcp.onReceive.addListener( info => { //callback function with info as the parameter
            /// recived, then close connection
            (<any>window).chrome.sockets.tcp.close(info.socketId);
            this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = this.arrayBuffer2str(info.data);

            resolve(this.array_risposta_invioPacchetto);
            //togli loading
            loading.dismiss();
          });
          (<any>window).chrome.sockets.tcp.onReceiveError.addListener( info => {
            (<any>window).chrome.sockets.tcp.close(info.socketId);
            this.array_risposta_invioPacchetto['result'] = -999; //codice errore scelto da me
            this.array_risposta_invioPacchetto['testo_errore'] = this.arrayBuffer2str(info.data);
            this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = ''; //essendo un errore
            
            resolve(this.array_risposta_invioPacchetto);
            //togli loading
            loading.dismiss();
          });

          var delay= 5000;	/// 5 seconds timeout
          (<any>window).chrome.sockets.tcp.create({}, createInfo => { //callback function with createInfo as the parameter
            var _socketTcpId = createInfo.socketId;

            (<any>window).chrome.sockets.tcp.connect(_socketTcpId, ipAddr, ipPort, result => { //callback function with result as the parameter
              if (result === 0) {
                this.array_risposta_invioPacchetto['result'] = result;
                this.array_risposta_invioPacchetto['testo_errore'] = '';

                var data2send= this.str2arrayBuffer(data);
                /// connection ok, send the packet
                (<any>window).chrome.sockets.tcp.send(_socketTcpId, data2send);
              } else {
                //error of connection
                this.array_risposta_invioPacchetto['result'] = result;
                this.array_risposta_invioPacchetto['testo_errore'] = 'Errore di connessione rilevato ...';
                this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = '';

                //restituisci errore di connessione
                resolve(this.array_risposta_invioPacchetto);
                //togli loading
                loading.dismiss();
              }
            });

            /// set the timeout
            setTimeout(function() {
              (<any>window).chrome.sockets.tcp.close(_socketTcpId);
              this.array_risposta_invioPacchetto['testo_errore'] = 'Timeout connessione socket eseguita';
              this.array_risposta_invioPacchetto['data_risposta_in_stringa'] = '';

              resolve(this.array_risposta_invioPacchetto);
              //togli loading
              loading.dismiss();
            }, delay);
          });

unfortunately, sometimes it still does not receive the “chrome.sockets.tcp.onReceive.addListener”.

HELP!

I found another “( window) .chrome.sockets.tcp.onReceive.addListener” on 1 page of app. On this page, the operations related to this addListener do not always work well.

I think this “listener” on the single page should be removed and managed through the provider, is not it?

Another topic: through the realtime debugging of the device (not smartphone but, I saw that the response to the command I send by “send” is fast but the relative “listener” grabs the answer after a few seconds (sometimes even more). normal?

Many thanks in advance

Yes, you should move that single listener to your provider.

On the close issue. Move the
var _socketTcpId
out of the create routine. Then it will be a provider instance variable.

I will look at my code again. I don’t see any delay from sender to receiver

My app sends a udp broadacst to locate the server on my network.

The server does a tcp send back to the mobile app with some connection info

                var p = {persistent:false};

//            console.log("chrome="+JSON.stringify((<any>window).chrome));

//console.log("sockets="+JSON.stringify((<any>window).chrome.sockets));

(<any>window).chrome.sockets.tcpServer.create(p,

function(createInfo)

{

console.log("socket created");

try

{

(<any>window).chrome.sockets.tcpServer.listen(createInfo.socketId,ip, 0,1,

function(result)

{

console.log("get socket info");

(<any>window).chrome.sockets.tcpServer.getInfo(this.socketId,

function(info)

{

console.log("socket info ="+ JSON.stringify(info))                                                                                                                ;

//this.port=info.localPort

console.log("using port="+info.localPort);

var ha= handleAccept;

console.log(" handleaccept function ="+ha);

(<any>window).chrome.sockets.tcpServer.onAccept.addListener(ha);

(<any>window).chrome.sockets.tcp.onReceive.addListener(recvListener)              ;

(<any>window).chrome.sockets.tcp.onReceiveError.addListener(

function(info)

{

console.log("socket error="+JSON.stringify(info));

}

);

Many thanks Pippo

I have another question: in the case of more sockets.send on the same page. I always the provider but how many times do I have to instantiate “onReceive.addListener” and “onReceiveError.addListener”?
Only once, right?

Let me explain:

Case 1:
A. page -> calls provider sockets function
B. sockets provider -> execute function (set addListener, create sockets, connect and send - in this way, each call of the function is set addListener)
C. page -> receives data from the provider function (from addListener in sockets provider)

Case 2:
A. page -> set addListener sockets both “onReceive.addListener” and "onReceiveError.addListener (addListeners set only once -> receive all answers for each time the sockets.send function of the provider is called)
B. page -> calls the provider sockets function
C. sockets provider -> execute function (create sockets, connect and send - no addListener here)
D. page -> addListener in the page receives all sockets responses in asynchronous for each call to the provider sockets function

Having to do more sockets.send on the same page (like a “streaming”), which of the 2 cases would you do?
I would do case 2, you?

Instantiate once per socket create

Ok, thanks … but
to have this “sockets connection streaming and relative receptions” how would you set it?

I think to do this:

  1. set addListeners (only once)
  2. creation of the sockets connection (chrome.sockets.tcp.create + chrome.sockets.tcp.connect) (only once)
  3. creation of the send function to send packets (which I will use many times when I want to make the “streaming” last)

What do you think about it?

it should be

create socket
addListener(s)
connect
send
send
send
send

I try this.

One question: if I had to use this “streaming sockets” on several different pages of the app (with different socket.send), is it possible that addlister(s) of one page intercept the addlister(s) of the other? if yes, how can I solve it?

Many thanks

i do not know what happens when u have multiple listeners of the same class…

first listener added (fifo),
last listener added (lifo),
all listeners,
or something else