MainUI gets disconnected

Hi Yannick (@ysc ),
sorry for bothering you. I’d like to bring this problem to your attention:
When launching MainUI as PWA after a while the client gets disconnected from the server.
I have seen this problem rarely on older OH3 versions and have this problem with OH3.2 ~10 times a day.
This problem has been confirmed here and the disconnection problem does not appear when running MainUI from regular browser app and activating full screen mode manually.

  • Colors, Icons and Labels do not represent the actual state anymore
  • If I click on a cell which his configured with actionCommandAlt: it only sends one of the two commands even when pressing multiple times (as can be seen in the log)
  • If I launch one of my status widgets which just shows current states of selected items, none of the states can be retrieved from the server
  • after restarting the browser app everything works fine again.

Server details:

  • OH3 Version 3.2
  • Zulu Java
  • Kernel version Linux 5.10.63-v7l+ (latest openhabian)

Client details:

  • iPad mini 4 iOS 15.2, Safari browser, (wall mounted, constantly connected to OH3)
  • everything which might interfere from a networking point of view ist deactivated (e.g. private MAC address)

Unfortunately it is not a solution to start MainUI within browser and manually activate full screen mode because if you scroll up a page safari browser interpreetes this to exit fullscreen mode.
See here manifest and json file:

<html>
<head>
	<meta charset="UTF-8"/>
	<meta http-equiv="Content-Security-Policy" content="default-src * 'self' 'unsafe-inline' 'unsafe-eval' data: gap: content: blob:; style-src 'self' 'unsafe-inline';"/>
	<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,minimal-ui,viewport-fit=cover"/>
	<meta name="theme-color" content="#f7f7f7"/>
	<meta name="format-detection" content="telephone=no"/>
	<meta name="msapplication-tap-highlight" content="no"/>
	<title>openHAB</title>
	<meta name="apple-mobile-web-app-capable" content="yes"/>
	<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
	<meta name="mobile-web-app-capable" content="yes"/>
	<meta name="mobile-web-app-status-bar-style" content="black-translucent"/>

	<link rel="apple-touch-icon" href="/res/icons/apple-touch-icon.png" type="image/png" sizes="180x180" crossorigin="use-credentials"/>
	<link rel="icon" href="/res/icons/favicon.svg" type="image/svg+xml" sizes="any" crossorigin="use-credentials"/>
	<link rel="icon" href="/res/icons/128x128.png" type="image/png" sizes="128x128" crossorigin="use-credentials"/>
	<link rel="manifest" href="/static/manifest/manifest.webmanifest" type="application/manifest+json" crossorigin="use-credentials"/>
	<link href="/css/app.css" rel="stylesheet">
</head>
<body>
	<h1>Add to homescreen now</h1>
</body>
</html>
{
  "name": "openHAB",
  "short_name": "openHAB",
  "description": "openHAB",
  "lang": "de-DE",
  "start_url": "/page/Home",
  "scope": "/",
  "display": "fullscreen",
  "background_color": "#ffffff",
  "theme_color": "#f7f7f7",
  "icons": [
    {
      "src": "/res/icons/128x128.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "/res/icons/144x144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "/res/icons/152x152.png",
      "sizes": "152x152",
      "type": "image/png"
    },
    {
      "src": "/res/icons/192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/res/icons/256x256.png",
      "sizes": "256x256",
      "type": "image/png"
    },
    {
      "src": "/res/icons/512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

Looks like a SSE connection problem.
When that happens go to Developer Tools, Debug (the 2nd tab at the top), click Stream Events and check that you have events coming in. (Change some items with another device if necessary).

If you have problems, and if it’s specific to iOS Safari, then you might have some success trying this: How to Debug Websites on iPhone Safari | BrowserStack and then look in the JS console, if there are SSE disconnections they should appear there.

Hi Yannick,
I think I found the culprit.
After a while the browser makes a call to this website:
safebrowsing.googleapis.com
after that app.js is not “connected” anymore

the browser lost all items’ states:

I did some more testing: neither disabling “Fraudulent Website Warning” in Safari settings nor disabling internet access on the router solved the problem. I guess it is simply the fact that the browser does an API call (safebrwosing API) which stops the connection to APP.JS no matter if the API call gets connection to the target URL or not.

I don’t know if that helps, but after 30 minutes or so, scrolling a page in MainUI behaves “fragmented”.

Just in case if it is of any interest to you:

  • When running MainUI in Chrome iOS browser, MainUI does not show the fullscreen icon (the one in the upper right corner)
  • When running MainUI in Firefox iOS browser, MainUI shows the fullscreen icon (the one in the upper right corner) but it does not switch to full screen mode

EDIT: latest test results:

Safari:

  • problems with full screen mode and “regular” mode
  • scrolling fragmented

Chrome:

  • problems with full screen mode and “regular” mode
  • full screen icon in upper right corner not available
  • scrolling fragmented

Firefox

  • problems with “regular” mode
  • icon for full screen mode available but not working
  • scrolling fragmented

Is this remote debugging on your iPad, it looks like Chrome’s dev tools?
Anyways there are a number of scripts that aren’t related to the UI - basically everything above app.js on that screenshot, and the last “threatListU…”. Maybe that’s normal if you display iframes, they could be interfering, try removing those iframes temporarily if you have them, and see if it fixes the problem.

Hi Yannik,
yes, I used the link you provided above. the screenshot is taken from there (it starts a virtual iOS device embedded within inspection tools which look like chrome dev tools).

The last entry you see and what you mentioned (threatListU…) is exactly what causes the problem. I saw it with my own eyes in realtime. “threatListU…” appeared after a few minutes and instantly all widgets lost their status.
If you hover on threatListU., you saw that it was calling safebrowsing.googleapis.com/

EDIT: at the same time, the blue bar next to app.js disappeared

ah ok, you used the BrowerStack cloud service itself, not your actual iPad.
I was confused because I didn’t know Safari used Google’s Safe Browsing API.

That’s weird because app.js is the main script that shouldn’t keep the connection open after it’s loaded, contrary to SSE endpoints like /rest/events or /rest/events/states.

So I fail to see if there’s a relation here. But since you’ve established that there’s really a correlation, maybe you can try disabling Safe Browsing: Apple Safe Browsing Explained - Why Apple sends your data to Google and Tencent and how to turn it off
Especially if you’re using that iPad just for OH the risk might be acceptable.

Maybe if you can try launching a new, blank OH instance with the same device and add a minimal amount of things to it and try to reproduce the problem - to see if the problem is caused by your configuration or if it’s an inherent problem.

I already did:

yeah. and I found out that even Firefox uses this API, too. And with all of these browser I have the same problems.
This behaviour is also confirmed by another user here

Another proof is the following:
When using iOS App (Beta version which supports MainUI) then there are no problems at all.
However, the app is not capable of showing oh-popups

Do you mean popups in widgets ? Those are working over here, no issue with that.

sorry - let me be more precise. Within that popup there is a webframe which shows my video camera (mjpeg format). The popup appears but there is no video. I guess that the iOS app does not support javascript which is required to refresh video images.

Title changed from “MainUI gets disconnected when launched as PWA” to
MainUI gets disconnected

Hi Yannick,
I did what you said.
I set up a complete new system (openhabian, OH3.2 release, but runs on an SSD) and deleted two complex widgets from the page.
Surprise! Even after 3 days no lost cpnnections anymore.
When I added one of these complex widgets, after ~half a day the connection was lost.
I deleted this widget and added the other one: Same. Connection lost.
I did the same test with another iOS device. That one lost its connection, too, in the same way.

I really don’t care about these two widgets but I wanted to pursue this further as I think it is not a problem with my configuration, but more of a generic problem.

Here are the two widgets which lead to a lost connection (most probably when the browser does his safebrowsing API call):

Weather widget:

uid: my-wetter-cell
tags: []
props:
  parameters: []
  parameterGroups: []
timestamp: Dec 25, 2021, 10:01:41 PM
component: oh-cell
config:
  color: gray
  expandable: true
  on: true
slots:
  default:
    - component: oh-webframe
      config:
        height: 270px
        src: /static/wetter/fc_tage.html
        style:
          align-content: center
          align-items: center
          display: flex
  header:
    - component: f7-block
      config:
        class:
          - card-opened-fade-out
        style:
          display: flex
          flex-direction: column
          margin: 0px
          padding: 0px
          position: absolute
          top: -35px
      slots:
        default:
          - component: f7-block
            config:
              style:
                align-items: center
                display: flex
                flex-direction: row
                margin: 0px
                padding: 0px
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: "=(items.OWM_IconID.state != '-') ? 'oh:owm-' + items.OWM_IconID.state.toString() + '.png' : ''"
                    style:
                      width: 55px
                - component: Label
                  config:
                    style:
                      fontSize: 34px
                      padding-left: 25px
                      padding-right: 8px
                    text: =items.OWM_Aussentemperatur.displayState
                - component: Label
                  config:
                    style:
                      fontSize: 16px
                      fontWeight: normal
                    text: ="(" + items.OWM_GefuhlteTemperatur.displayState + ")"
                - component: oh-icon
                  config:
                    icon: "=(items.Mondphase.state != '-') ? 'mymoon-' + items.Mondphase.state.toString() + '.svg' : ''"
                    style:
                      padding-left: 25px
                      width: 30px
          - component: Label
            config:
              style:
                fontSize: 16px
                fontWeight: 600
                margin-top: -10px
              text: =items.OWM_Wetterlage.state
          - component: f7-block
            config:
              style:
                display: flex
                flex-direction: row
                fontSize: 14px
                fontWeight: normal
                padding: 0px
            slots:
              default:
                - component: f7-block
                  config:
                    style:
                      display: flex
                      flex-direction: column
                      margin: 0px
                      padding: 0px 8px 0px 0px
                      white-space: nowrap
                      width: auto
                  slots:
                    default:
                      - component: Label
                        config:
                          text: ="🌤 " + items.OWM_Bewolkung.displayState
                      - component: Label
                        config:
                          text: ="∿ " + items.OWM_Wind.displayState
                - component: f7-block
                  config:
                    style:
                      border-left: 1px solid gray
                      display: flex
                      flex-direction: column
                      padding: 0px 0px 0px 8px
                      white-space: nowrap
                      width: auto
                  slots:
                    default:
                      - component: Label
                        config:
                          text: ="🔆 " + dayjs(items.OWM_SunriseTime.state).format("HH:mm") + "-" + dayjs(items.OWM_SunsetTime.state).format("HH:mm")
                      - component: Label
                        config:
                          text: ="🔅 " + items.SNMPcameingang_Helligkeit.displayState

“openHAB health” widget:

uid: my-status-cell
tags: []
props:
  parameters: []
  parameterGroups: []
timestamp: Dec 25, 2021, 12:09:46 PM
component: oh-cell
config:
  color: "=(items.gAlarms.state > 0) ? 'red' : ((items.gFaults.state > 0) ? 'yellow' : 'gray')"
  expandable: true
  on: true
slots:
  default:
    - component: f7-block
      config:
        class:
          - margin
          - padding
        style:
          left: 0
          position: absolute
          top: 0
          width: auto
      slots:
        default:
          - component: Label
            config:
              style:
                color: gray
                fontSize: 20px
                fontWeight: 700
                text-align: left
              text: openHAB Status
          - component: oh-repeater
            config:
              filter: loop.rItem.state === "ON"
              for: rItem
              fragment: true
              groupItem: gAlarms
              sourceType: itemsInGroup
            slots:
              default:
                - component: oh-list
                  config:
                    mediaList: true
                  slots:
                    default:
                      - component: oh-list-item
                        config:
                          _textColor: red
                          badge: Alarm
                          badgeColor: red
                          subtitle: =loop.rItem.name
                          title: =loop.rItem.label
          - component: oh-repeater
            config:
              filter: loop.rItem.state === "ON"
              for: rItem
              fragment: true
              groupItem: gFaults
              sourceType: itemsInGroup
            slots:
              default:
                - component: oh-list
                  config:
                    mediaList: true
                  slots:
                    default:
                      - component: oh-list-item
                        config:
                          _textColor: yellow
                          badge: Störung
                          badgeColor: yellow
                          subtitle: =loop.rItem.name
                          title: =loop.rItem.label
          - component: oh-repeater
            config:
              filter: loop.rItem.state === "ON"
              for: rItem
              fragment: true
              groupItem: gInfo
              sourceType: itemsInGroup
            slots:
              default:
                - component: oh-list
                  config:
                    mediaList: true
                  slots:
                    default:
                      - component: oh-list-item
                        config:
                          _textColor: yellow
                          badge: Störung
                          badgeColor: yellow
                          subtitle: =loop.rItem.name
                          title: =loop.rItem.label
          - component: Label
            config:
              style:
                color: gray
                fontSize: 20px
                fontWeight: 700
                margin-top: 20px
              text: Shelly Status
          - component: f7-row
            config:
              noGap: true
              style:
                height: 25px
                text-align: center
                width: 100%
            slots:
              default:
                - component: f7-col
                  config:
                    style:
                      white-space: nowrap
                      width: 30%
                - component: oh-repeater
                  config:
                    for: rHeader
                    fragment: true
                    in:
                      - Signal
                      - Temperatur
                    sourceType: array
                  slots:
                    default:
                      - component: f7-col
                        config:
                          style:
                            white-space: nowrap
                            width: 20%
                        slots:
                          default:
                            - component: Label
                              config:
                                text: =loop.rHeader
          - component: oh-repeater
            config:
              for: rThing
              fragment: true
              groupItem: gShellys
              sourceType: itemsInGroup
            slots:
              default:
                - component: f7-row
                  config:
                    style:
                      --f7-grid-gap: 1px
                      --f7-grid-row-gap: 1px
                      height: 25px
                      text-align: center
                      width: 100%
                  slots:
                    default:
                      - component: f7-col
                        config:
                          style:
                            text-align: left
                            white-space: nowrap
                            width: 30%
                        slots:
                          default:
                            - component: Label
                              config:
                                text: =loop.rThing.label
                      - component: oh-repeater
                        config:
                          for: rItem
                          fragment: true
                          in:
                            - Signalstarke
                            - Geratetemperatur
                          sourceType: array
                        slots:
                          default:
                            - component: f7-col
                              config:
                                style:
                                  font-weight: normal
                                  white-space: nowrap
                                  width: 20%
                              slots:
                                default:
                                  - component: Label
                                    config:
                                      text: =items[loop.rThing.name + "_" + loop.rItem].state
          - component: Label
            config:
              style:
                color: gray
                fontSize: 20px
                fontWeight: 700
                margin-top: 20px
              text: Rauchmelder Status
          - component: f7-row
            config:
              noGap: true
              style:
                height: 25px
                text-align: center
                width: auto
            slots:
              default:
                - component: f7-col
                  config:
                    style:
                      width: 15%
                - component: oh-repeater
                  config:
                    for: rHeader
                    fragment: true
                    in:
                      - Status
                      - Batterie
                      - Signal
                      - Error
                      - letzter Test
                    sourceType: array
                  slots:
                    default:
                      - component: f7-col
                        config:
                          style:
                            white-space: nowrap
                            width: 17%
                        slots:
                          default:
                            - component: Label
                              config:
                                text: =loop.rHeader
          - component: oh-repeater
            config:
              _itemTags: Rauchmelder
              _sourceType: itemsWithTags
              fetchMetadata: semantics
              for: rThing
              fragment: true
              groupItem: gRM
              sourceType: itemsInGroup
            slots:
              default:
                - component: f7-row
                  config:
                    style:
                      --f7-grid-gap: 1px
                      --f7-grid-row-gap: 1px
                      height: 25px
                      text-align: center
                      width: 100%
                  slots:
                    default:
                      - component: f7-col
                        config:
                          style:
                            text-align: left
                            white-space: nowrap
                            width: 15%
                        slots:
                          default:
                            - component: Label
                              config:
                                text: =loop.rThing.metadata.semantics.config.hasLocation
                      - component: oh-repeater
                        config:
                          for: rItem
                          fragment: true
                          in:
                            - SmokeDetectorAlarmStatus
                            - NiedrigerBatteriestatus
                            - Signalstarke
                            - ErrorCode
                            - TestDate
                          sourceType: array
                        slots:
                          default:
                            - component: f7-col
                              config:
                                style:
                                  font-weight: normal
                                  white-space: nowrap
                                  width: 17%
                              slots:
                                default:
                                  - component: Label
                                    config:
                                      text: =items[loop.rThing.name + "_" + loop.rItem.split("=")[0]].state
  header:
    - component: Label
      config:
        style:
          font-weight: normal
          fontSize: 24px
        text: Status
    - component: oh-list
      config:
        mediaList: true
        noHairlinesBetween: true
      slots:
        default:
          - component: oh-list-item
            config:
              badge: =Number.parseInt(items.gAlarms.state).toString()
              badgeColor: "=(items.gAlarms.state != 0) ? 'red' : 'gray'"
              style:
                --f7-list-media-item-title-font-weight: normal
                height: 19px
              title: Alarme
          - component: oh-list-item
            config:
              badge: =Number.parseInt(items.gFaults.state).toString()
              badgeColor: "=(items.gFaults.state != 0) ? 'yellow' : 'gray'"
              style:
                --f7-list-media-item-title-font-weight: normal
                height: 19px
              title: Störungen
          - component: oh-list-item
            config:
              badge: =Number.parseInt(items.gInfo.state).toString()
              badgeColor: "=(items.gFaults.state != 0) ? 'yellow' : 'gray'"
              style:
                --f7-list-media-item-title-font-weight: normal
                height: 19px
              title: Infos

1 Like

Hi Yannick,
this problem has been confirmed here

and today here.

Is there anything we can do to support you finding the problem?

I also noticed, when the display stays connected for about three days (during that time it works perfectly without disconnects) then all widgets disappear which are visible on the screen. However, if you scroll down, all other widgets are there. It is just that those widgets dissappear which are initially visible at the top .

I opened a ticket for this here