Unifi - How to know if the Internet is online?

Hi.

I’m running a self-hosted instance of the Unifi Network App (v9.3.45), OH 5.1.3, and I’m wondering whether it’s possible to store the Internet connection status in an item.

I didn’t see any channels in the documentation of the accessPoint or network things that could tell me that.

I only have a U6-Lite AP and USW LIte 8 switch. The DSL modem is also the DHCP server, and it’s connected directly to the switch. Some servers and the AP are connected to the switch.

O.o this… is actually a good question. I have a similar setup to yours. Docker container too?

What I have is a speedtest that runs once every 12 hours that but doesn’t warn me the moment connectivity goes down..

To check the connectivity, I use the logreader binding to trigger a connection test.

In the logreader binding, I connected a string item ‘Logfile_newest_custom_log’ to the lastCustomEvent channel.
Then with a JavaScript rule I set a switch ‘VirtualSwitch_OpenHabCloudConnected’ to ON or OFF:

rules.JSRule({
  name: 'OpenhabLog_Watcher',
  triggers: [triggers.ChannelEventTrigger('logreader:reader:27b968b02e:newCustomEvent')],
  execute: () => {
    const lastEvent = items.getItem('Logfile_newest_custom_log').state;

    if (lastEvent.includes('Disconnected from the openHAB Cloud service')) {
      items.getItem('VirtualSwitch_OpenHabCloudConnected').sendCommand('OFF');
    }

    if (lastEvent.includes('Connected to the openHAB Cloud service')) {
      items.getItem('VirtualSwitch_OpenHabCloudConnected').sendCommand('ON');
    }
  },
});

With another rule and UPNP functionality, I check a) if I can get the public IP from my router and b) if a specific IP service can be requested:

// Needs to be determined with upnpc -s
const LOCAL_UPNP = { PORT: 56688, URL: 'http://192.168.1.1' };

/**
 * Get the current external IP from the router via UPnP
 * @returns  {string|null} The current public IP address or null if retrieval fails.
 */
const getIpLocally = function () {
  // SOAP request for UPnP WANIPConnection service
  const soapEnvelope = `
    <?xml version="1.0"?>
    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <s:Body>
        <u:GetExternalIPAddress xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1" />
      </s:Body>
    </s:Envelope>
  `;

  // Headers for the SOAP request
  const headers = {
    'Content-Type': 'text/xml; charset="utf-8"',
    'SOAPAction': '"urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress"',
    'Connection': 'Close',
  };

  // UPnP service URL (adjust IP, port, and control path as needed)
  const upnpUrl = `${LOCAL_UPNP.URL}:${LOCAL_UPNP.PORT}/upnp/control/WANIPConn1`;

  /**
   * Extracts the public IP address from a UPnP SOAP response using regex.
   * @param {string} xml The SOAP response XML.
   * @returns {string|null} The public IP address or null if extraction fails.
   */
  const extractIpFromUpnpResponse = function (xml) {
    try {
      // Regex to match the IP address in the SOAP response
      const ipRegex = /<NewExternalIPAddress>([\d.]+)<\/NewExternalIPAddress>/;
      const match = xml.match(ipRegex);
      if (match && match[1]) {
        return match[1];
      }
      console.warn('No IP found in UPnP response.');
    } catch (e) {
      console.error(`Error parsing UPnP response: ${e}`);
    }
    return null;
  };

  try {
    console.debug('Fetching public IP via UPnP...');
    const response = actions.HTTP.sendHttpPostRequest(upnpUrl, 'text/xml', soapEnvelope, headers, 10000);
    if (response) {
      const ip = extractIpFromUpnpResponse(response);
      if (ip) {
        console.debug(`Public IP fetched via UPnP: ${ip}`);
        return ip;
      }
      console.warn('Failed to get external IP locally');
    }
  } catch (e) {
    console.error(`Error fetching IP via UPnP: ${e}`);
  }
  return null;
};

const IP_SERVICES = [
  { name: 'ipwho.de', url: 'https://4.ipwho.de/ip' },
  { name: 'myip.wtf', url: 'https://myip.wtf/text' },
  { name: 'ipapi.is', url: 'https://api.ipapi.is/ip' },
];

/**
 * Shuffles a list
 * @param {Object} arr The list that should be shuffled
 * @returns {Object} The shuffled list
 */
const shuffle = function (arr) {
  const a = arr.slice();
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
};

let currentlyOffline = false;

rules.JSRule({
  name: 'Online_Watcher',
  triggers: [triggers.ItemStateChangeTrigger('VirtualSwitch_OpenHabCloudConnected')],
  execute: (event) => {
    if (event.newState === 'OFF') {
      let result = null;
      const url = shuffle(IP_SERVICES)[0].url;
      try {
        // Double check connectivity
        result = getIpLocally();
        if (result === null) {
          result = actions.HTTP.sendHttpGetRequest(url, httpHeaderHashMap, 10000);
        }
      } catch (e) {
        console.warn(e);
      }
      if (result === null) {
        currentlyOffline = true;
        sendNotificationLaMetric({
          text: 'No online connection!',
          type: 'alert',
          icon: 'i29040', //Network-Offline
          sound: 'sound_picker_track_245_eerie',
        });
        console.warn('ONLINE-STATE: Currently offline!');
      }
    }
    if (event.newState === 'ON' && currentlyOffline) {
      currentlyOffline = false;
      sendNotificationLaMetric({
        text: 'Online connection is back again!',
        type: 'info',
        icon: 'i29041', //Network-Online
        sound: 'sound_picker_track_402_reveal',
      });
      console.info('ONLINE-STATE: Online again!');
    }
  },
});

If internet is gone, I send a notification to my Lametric Time with a custom function. But you could also store the information in a switch item instead.

I don’t know anything about Unifi, but the OH Network binding can do this by itself. Just configure a Thing to ping some address that requires the internet to reach (e.g. weather.com).

Hi, @Pedro_Liberal. No, I don’t use Docker or any other virtualization. OH runs on a Pi and the Unifi Network App on an older Pi that used to run OH.

@rlkoshak, I’m actually hoping there is an “easier” and faster way than to “flood” the network with pings if I want to have a “fairly instant” visual notification once the connection goes down. I don’t even know if the Network App is aware of the internet status and could potentially be retrieved via the binding.
I had seen the Network binding, but I’m keeping it as the last resort. I would like to avoid generating unnecessary network traffic every 2 mins if the Unifi binding could already provide the data.

In any case, thanks a lot for your suggestion, that is definitely an option.

If you have a Unifi router, you should be able to have the internet available status. But without it, I don’t think it is possible from the Unifi Network App. Check your Network App. Is there anything? I have a Unifi router and I see an internet availability status.

Still, I think the router also just pings a network address on a regular interval to check the internet. There for sure is an extra routing step when you do it from OH, but that shouldn’t have a big impact as I see it.

A 56-byte packet ourt and 64-byte packet reply once every second even is hardly a flood. Given various timeouts and such, I don’t know that a 5 second ping would be much slower than the Unifi device itself timing out and discovering it’s offline.

:smiley: I know, it’s gotta be more like a drop of water in the ocean than a flood.

@Mherwege, can you show me where you see it? In the Unifi Devices tab or somewhere else?

On the dashboard page, I can switch between Internet and Wifi. It shows me an Internet activity graph and a graph with latency over time.
It also shows the details of my internet provider settings in the Unifi Cloud Gateway and details about it. There is an SLA Monitor listed with 3 different verification servers, measuring availability and latency for each of these.

The key element is the Unifi Cloud Gateway running the Network App software and all functionality in the Unifi Cloud Gateway. It is not the Network App doing this internet check, but the router software I think.

Useful as always :slight_smile: I pointed it to 1.1.1.1 and it’s pinging it once every minute. Super useful binding!

Note, the state of the Thing does not represent the ONLINE status. The Item linked to the Online Channel does that. Some get confused by that. Even if 1.1.1.1 cannot be reached, the Thing will show ONLINE but the Item will show OFF.

Also, if you have a specific service you want to check, you can create a serviceDevice Thing and supply a port to “ping” (I think it actually just tries to connect a socket in this case).

It’s certainly no replacement for a proper network monitoring system, but it can be handy for soem things. I use the network binding to tell OH whether my garage door controller is offline. If it is and I try to trigger the garage door through openHAB, OH will send a broadcast alert to indicate it’s not going to work. Now that we have the source of events, I think I can adjust that to only send the alert to the person who triggered the door instead of to everyone.

Yep, made sense, and funnily enough after a while I had an outage:

Funny that, my wife had complained that we were losing connectivity but I had never caught it first hand… not even 30 minutes after… baam. -.-

Generally, while I agree that it’s crude and not really nice, it should be mentioned that all kind of services/things use regular pings to check for online connectivity. The problem is that there isn’t always anything better available.

The router doesn’t normally “exchange” data with the ISP router if nothing is going on, so there’s no inherit way to “know” when the connection is lost. This only becomes known once communication is attempted and the other end can’t be reached. But, in reality, some network device will almost always do some chatter, there are so many devices that “call home” these days that I doubt most routers will see much “quiet time”.

The router is therefor the device best equipped to know when connectivity is lost, because it knows when the communication fails. Whether it does explicit pings in addition I don’t know, but it would be reasonable that it at least shows “online” for a while after the last successful transmission took place. If nothing happens on the connection, perhaps it will do some pings itself.

Sadly, few routers “share this knowledge” in an easily digestible way, but it sounds like the Unifi routers might actually do that. But, pinging to know the status is very widespread, expect all kind of software and devices that you have to already be doing this.

detecting unavailablity of the internet shouldn’t be the problem, but how to inform my mobile if not at home? I’m using Pushover as my event manager and that won’t work when the internet is down. If I’m at home, I could do something with OH messages, but in that situation I can easily ‘detect’ unavailablity otherwise (screeming kids etc).

For that situation I’v connected a 5G modem to my unifi router which can switch over and unifi can inform me of a internet switch over.