becvert / cordova-plugin-zeroconf

Cordova ZeroConf Plugin
MIT License
81 stars 57 forks source link

Plugin sample #66

Closed haddadnidal closed 6 years ago

haddadnidal commented 6 years ago

Hi all, can anyone provide me with a sample code, i can't get it running thank you.

emcniece commented 6 years ago

What framework & what version? Ionic 3?

haddadnidal commented 6 years ago

Apache Cordova 7.0.0. thank you.

emcniece commented 6 years ago

Here you go: https://github.com/emcniece/ZeroconfDemo

Tested & working on Android 8.0.0

emcniece commented 6 years ago

Particular file of interest: https://github.com/emcniece/ZeroconfDemo/blob/master/www/js/index.js#L37

haddadnidal commented 6 years ago

thank you very much man.

emcniece commented 6 years ago

Out of curiosity, did you find your issue?

haddadnidal commented 6 years ago

No i did not find my issue, still can't see anything. If i publish a service i can see it on my pc, but not the other way around. [EDIT] i did not find my issue but it works, thank you very much.

emcniece commented 6 years ago

If you'd like to share your code, I'm happy to take a look. 😄

Are you testing on Android or iOS?

haddadnidal commented 6 years ago

there is a Weird thing going on, it takes me ages to see my services. is it normal on android ?

emcniece commented 6 years ago

Hard to say without more details and a look at some code.

This can be a finicky interface, due to the number of layers and variables. Often we find that there are strange issues with mobile hardware, OS versions, the Android JmDNS library, certain Wifi routers, on and on. The examples in the README of this repo provide some more tried-and-true methods but not everyone has luck with it.

I am using this library successfully in a published app that works for Android 5+. It took a good deal of effort to troubleshoot each OS version - they all have quirks.

That said, my scan results show up very quickly (within seconds) and I have created a refresh/reinit pattern that resets the plugin at a low level.

You may be dealing with a timing issue - over here a user realizes that they were watching the wrong event (added instead of resolved) and learned to reset the Zeroconf plugin to get results to show up when expected.

I'm happy to help, but we really do need more info.

Are you able to run the example app that I created with better results than your current app?

haddadnidal commented 6 years ago

hi, after numerous attempts my code works, it is a mess but at least it works thank you very much

onDeviceReady: function() {
        this.receivedEvent('deviceready');

        var loop = [];
        var zeroconf = window.cordova.plugins.zeroconf;
        console.log("refresh"+loop);
        window.cordova.plugins.zeroconf.watch('_http._tcp.', 'local.', function(result) {
            var action = result.action;
            var service = result.service;
            if (action == 'added') {
                console.log('service added', service);
                console.log(loop);
            } else if (action == 'resolved') {
                console.log('service resolved', service);
                if (!(loop.includes(service.name)) && (service.ipv4Addresses[0]!= undefined))
                {
                  console.log("here is good");
                  loop[loop.length] = service.ipv4Addresses[0];
                  console.log(loop);
                  add(service.name,service.ipv4Addresses[0])
                  // document.getElementById('deviceready').insertAdjacentHTML('afterbegin','<p><a href=  '+'http://'+service.ipv4Addresses[0]+' >'+service.name+'</a></p>');
                }
            } else {
                console.log('service removed', service);
                // console.log("new loop "+loop);
                erase(service.name)

            }
        });
    },

    // Update DOM on a Received Event
    receivedEvent: function(id) {
        var parentElement = document.getElementById(id);
        var listeningElement = parentElement.querySelector('.listening');
        var receivedElement = parentElement.querySelector('.received');
        listeningElement.setAttribute('style', 'display:none;');
        receivedElement.setAttribute('style', 'display:block;');
        console.log('Received Event: ' + id);
    }

};

  function erase(value) {
    $( "p" ).remove("#"+value );
    console.log("remove"+value);
  }

function add(value,ipad) {
  document.getElementById('deviceready').insertAdjacentHTML('afterbegin','<p id = '+value+'><a href=  '+'http://'+ipad+' >'+value+'</a></p>');
}
app.initialize();
haddadnidal commented 6 years ago

the reason i use remove is when i advertise on my pc i get multiple advertisements of the same service and each on of them is added to my DOM. any advise on how to optimize this code would be welcomed. Again thank you.

haddadnidal commented 6 years ago

Anyway to change the type in window.cordova.plugins.zeroconf.watch('_http._tcp.', 'local.', to see all services on the network ?

emcniece commented 6 years ago

Good to hear you got it working!

if (!(loop.includes(service.name)) && (service.ipv4Addresses[0]!= undefined))

Since this is inside the resolved action, you're guaranteed to get an IP address. What you may not get is an IPv4 address. To force IPv4, use zeroconf.watchAddressFamily = 'ipv4';:

var zeroconf = window.cordova.plugins.zeroconf;
zeroconf.watchAddressFamily = 'ipv4';
...

I also think that service always have a hostname, and it is unique - so you can use the hostname as an array key. This makes managing a list of devices a bit easier.

const devices = {}; // This will hold a list of devices

var zeroconf = window.cordova.plugins.zeroconf;
zeroconf.watchAddressFamily = 'ipv4';

window.cordova.plugins.zeroconf.watch('_http._tcp.', 'local.', function(result) {
  var action = result.action;
  var service = result.service;

  // We don't need the `added` action because it doesn't have IP addresses
  // The `resolved` action DOES have addresses!
  if (action == 'resolved') {
    add(service)
  } else {
    erase(service)
  }

  // Rebuild the HTML service list on every action. Shouldn't take long!
  redraw();
}

// Push a new service to the `devices` object
function add(service) {
  devices[service.hostname] = service
}

// Remove a service from the `devices` object
function erase(service) {
  delete devices[service.hostname]
}

// Redraw the HTML listing discovered services
function redraw() {
  const parent = document.getElementById('deviceready')

  // Clear out existing content
  parent.innerHTML = '';

  // Add each listed device to HTML content
  for(let i=0; i<devices.length; i++){
    const device = devices[i];
    const hostname = device.hostname;
    const ip = device.ipv4Addresses[0];

    // Append next service as HTML
    parent.innerHTML += `<p id="${hostname}"><a href="http://${ip}">${hostname}</a></p>`
  }
}

To discover more devices, relax the _http._tcp. watch filter to _tcp.:

zeroconf.watch('_tcp.', 'local.', function(result) {
...
haddadnidal commented 6 years ago

thank you very much, i will test it, as far as

if (!(loop.includes(service.name)) && (service.ipv4Addresses[0]!= undefined))

i did it because when i advertise for a service the first one resolved is always like this resolve undefined.

emcniece commented 6 years ago

Precisely! The resolved action guarantees an IP address, but it does not guarantee an IPv4 address - you might get an IPv6 address instead, like in your screenshot.

To force IPv4, use zeroconf.watchAddressFamily = 'ipv4';

haddadnidal commented 6 years ago

Again thank you this is what missing from my script. Any idea on how to reload the script if i went from a internal browser webpage to the main menu ?

emcniece commented 6 years ago

Not sure that I understand. Did you click one of the <a href="http://${ip}"> links that opened a new page?

haddadnidal commented 6 years ago

yes, i have an express server running on the same machine that advertise, and when i press the back button to go back to main, the dom is empty.

haddadnidal commented 6 years ago

I was thinking on using a swipe event to reload the dom but if i refresh the page nothing work.

emcniece commented 6 years ago

You'll need to inspect the app with chrome://inspect/#devices to see if there are errors present, and debug them if possible.

A simple solution might be to place a hard home link in the DOM (like <a href="/">Home</a>) that never goes away - this should let you re-navigate to the app root without using Javascript.

haddadnidal commented 6 years ago

I did inspect, and there was no errors. As for the home button ill try it and then get back to you.

smarta1980 commented 1 year ago

I have mdns server as echo.local so how to get ip address of it using zeroconf plugin?