Grayed out Items in iOS app

Hello, I have a weird issue: since one of the latest updates (maybe 5.1, but I’m not 100% sure) items related to the control of the Faikin module are grayed out in iOS App.

I did configure everything manually (no autodiscover) so this isn’t a problem related to the module itself and the items do work fine everywhere else (rules, alexa, web, admin interface)… Except in the iOS app. I do not own an android so I’m not sure how to test to see if it’s a general App problem or is it specific of the iOS version.

I don’t recall since which version exactly but after 5.0.0 for sure. I didn’t open an issue before because I tought it would eventually be sorted out but apparently I’m the only one experiencing this?

I am for sure missing something simple, if it’s a bug it would happen to many more people I guess?

Here are the screenshots

iOS - App - Grayed out and impossible to interact with:

iOS - Browser - Everything normal:

PC - Browser - Everything normal:

Thing configuration:

Thing mqtt:topic:Faikin:faikin02 "faikin02_Thing" (mqtt:broker:brokerv2) {
    Channels:

        // State - si aggiorna SOLO ad ogni cambio di stato - livestatus=ON
        Type number   : temp            [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.temp"]
        Type number   : home            [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.home"]
        Type number   : fanrpm          [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.fanrpm"]
        Type number   : comp            [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.comp"]
        Type number   : outside         [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.outside"]
        Type number   : liquid          [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.liquid"]
        Type number   : anglev          [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.anglev"]
        Type number   : demand          [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.demand"]
        Type number   : Wh              [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.Wh"]
        Type string   : fan             [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.fan"]
        Type string   : mode            [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.mode"]

        // Faikin - si aggiorna SOLO ogni minuto
        Type string   : ts              [stateTopic="Faikin/faikin02",  transformationPattern="JSONPATH:$.ts"]

        // Switch (like a string)
        Type switch   : power           [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.power",    on="true", off="false"]
        Type switch   : swingv          [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.swingv",   on="true", off="false"]
        Type switch   : econo           [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.econo",    on="true", off="false"]
        Type switch   : powerful        [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.powerful", on="true", off="false"]
        Type switch   : swingh          [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.swingh",   on="true", off="false"]
        Type switch   : streamer        [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.streamer", on="true", off="false"]
        Type switch   : quiet           [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.quiet",    on="true", off="false"]

} 

Items configuration:

Group g_faikin02
Group g_faikin02_cmd

// SWITCH
Switch faikin02_power    "Power"         <switch>               (g_faikin02,g_faikin02_cmd) {channel="mqtt:topic:Faikin:faikin02:power"}
Switch faikin02_econo    "Econo"         <price>                (g_faikin02,g_faikin02_cmd) {channel="mqtt:topic:Faikin:faikin02:econo"}
Switch faikin02_powerful "Powerful"      <pump>                 (g_faikin02,g_faikin02_cmd) {channel="mqtt:topic:Faikin:faikin02:powerful"}
Switch faikin02_streamer "Streamer"      <smiley>               (g_faikin02,g_faikin02_cmd) {channel="mqtt:topic:Faikin:faikin02:streamer"}
Switch faikin02_quiet    "Quiet Outdoor" <soundvolume_mute>     (g_faikin02,g_faikin02_cmd) {channel="mqtt:topic:Faikin:faikin02:quiet"}
Switch faikin02_swingv   "Swing ↕"       <flow>                 (g_faikin02,g_faikin02_cmd) {channel="mqtt:topic:Faikin:faikin02:swingv"}
Switch faikin02_swingh   "Swing ↔"       <flow>                 (g_faikin02,g_faikin02_cmd) {channel="mqtt:topic:Faikin:faikin02:swingh"}

// NUMBER
Number faikin02_home    "faikin02 - home [%.1f °C]"     <temperature>  (g_faikin02,gGraph)                      {channel="mqtt:topic:Faikin:faikin02:home"}
Number faikin02_fanrpm  "faikin02 - fanrpm [%s rpm]"    <wind>         (g_faikin02,gGraph)                      {channel="mqtt:topic:Faikin:faikin02:fanrpm"}
Number faikin02_comp    "faikin02 - comp [%s %%]"       <pump>         (g_faikin02,gGraph)                      {channel="mqtt:topic:Faikin:faikin02:comp"}
Number faikin02_outside "faikin02 - outside [%s °C]"    <temperature>  (g_faikin02,gGraph)                      {channel="mqtt:topic:Faikin:faikin02:outside"}
Number faikin02_liquid  "faikin02 - liquid [%s °C]"     <temperature>  (g_faikin02,gGraph)                      {channel="mqtt:topic:Faikin:faikin02:liquid"}
Number faikin02_anglev  "faikin02 - anglev [%s °]"      <incline>      (g_faikin02)                             {channel="mqtt:topic:Faikin:faikin02:anglev"}
Number faikin02_temp    "faikin02 - Setpoint [%.1f °C]" <heating>      (g_faikin02,g_faikin02_cmd,gGraph)       {channel="mqtt:topic:Faikin:faikin02:temp"}
Number faikin02_demand  "faikin02 - demand [%s %%]"     <settings>     (g_faikin02)                             {channel="mqtt:topic:Faikin:faikin02:demand"}
Number faikin02_Wh      "faikin02 - Wh [%s Wh]"         <price>       (g_faikin02)                              {channel="mqtt:topic:Faikin:faikin02:Wh"}

// STRING
String faikin02_fan       "Fan"        <fan>        (g_faikin02,g_faikin02_cmd)         {channel="mqtt:topic:Faikin:faikin02:fan"}
String faikin02_mode      "Mode"       <heating>    (g_faikin02,g_faikin02_cmd)         {channel="mqtt:topic:Faikin:faikin02:mode"}
String faikin02_ts        "TimeStamp"  <time>       (g_faikin02)                        {channel="mqtt:topic:Faikin:faikin02:ts"}

Switch faikin02_AutoQuiet   "Auto Quiet on Power ON" <settings>   (g_faikin02)
Switch faikin02_AutoRestore "Auto restore Auto"      <settings>   (g_faikin02)

// Retrocompatibilità Grafici
Number:Temperature acSoggiornoOutsideTemp "2P Davanti [%.1f]" (gTemp,Fuori_Temperature_Chart)  { channel="mqtt:topic:Faikin:faikin02:outside" }

Extract of sitemap visible in the screenshots:

     Frame label="A/C Control" {        Switch    item=faikin02_power
        Selection item=faikin02_fan     mappings=["A"="Auto", "Q"="Silent", "1"="1", "2"="2", "3"="3", "4"="4", "5"="5"]
        Setpoint  item=faikin02_temp    label="Setpoint" minValue=16 maxValue=32 step=0.5
        Text      item=faikin02_fanrpm  label="Extra Settings" icon=settings {
          Frame label="A/C Mode" {             Selection item=faikin02_mode    mappings=["H"="Heat", "C"="Cool", "D"="Dry", "A"="Auto", "F"="Fan"]
          }  
          Frame label="A/C Options" {
                Switch    item=faikin02_swingv   
                Switch    item=faikin02_swingh   
                Switch    item=faikin02_econo    
                Switch    item=faikin02_powerful
                Switch    item=faikin02_streamer
                Switch    item=faikin02_quiet 
                Switch    item=faikin02_AutoQuiet
                Switch    item=faikin02_AutoRestore
          }
        }

I’m running the latest dockerhub version (openhab/openhab:5.1.4 at the time of writing) on a raspberry pi5 with DietPI as OS.

Thanks in advance to anyone chiming in for help!

Hi @engiopd

Which version of the iOS app are you running, and have you also tried with the latest TestFlight build?

And could you also try the following for some of your greyed out switches in the items definitions

// SWITCH
Switch faikin02_power    "Power []"         <switch>               (g_faikin02,g_faikin02_cmd) {channel="mqtt:topic:Faikin:faikin02:power"}
Switch faikin02_econo    "Econo []"         <price>                (g_faikin02,g_faikin02_cmd) {channel="mqtt:topic:Faikin:faikin02:econo"}
…

ADDENDUM: I am also wondering that there are only stateTopic definitions in your Things definitions, but no commandTopic, which also makes me wonder why control is working in BasicUI :wink: Must read up on any changes or documentation on this.

@DigiH is giving the right direction.

The issue is not a bug in the iOS app — it is a server-side mismatch between stateDescription.readOnly and actual item commandability, triggered by certain binding configurations.

What happens technically

  1. The iOS chain:
    Server → stateDescription.readOnly = true in EnrichedItemDTO → OpenHABStateDescription.readOnly = true → WidgetRendering.readOnly = true →
    ToggleRowInput.readOnly = true → .disabled(true) on the Toggle in SwitchRowView
  2. Why readOnly = true is sent:
    The MQTT binding marks items as readOnly: true when they are linked to a state-only channel (e.g. an MQTT state topic with a JSON path transform). Even when a separate command channel also exists (making the item genuinely writable), the stateDescription is derived from the state channel alone and incorrectly carries readOnly: true.
  3. Why in the label is a workaround:
    Adding to a sitemap widget label forces the openHAB server to re-evaluate the embedded item’s state description via its label pattern resolution code path. This path appears to pick up the aggregated state description (considering all linked channels), which correctly produces readOnly: false. Without , the server uses a faster path that propagates the raw channel-level readOnly: true.
  4. Why it appears fine in BasicUI / web:
    Historically, no sitemap-based UI respected the readOnly flag at all — only MainUI did. The Android and iOS apps now correctly honour it, which surfaced the latent server-side bug. BasicUI/old sitemaps still ignore readOnly entirely.

@engiopd It would be great if you could provide the JSON representation of your sitemap:

With
curl http://<server>:8080/rest/sitemaps | jq . | less
you can get all configured sitemaps. From there get the sitemap itself with
http://<server>:8080/rest/sitemaps/<sitemap>/<pageId>

Thank you @Hans_Lree for pointing me to the right direction and thanks to @timbms for the detailed server sided explanation.

As a matter of fact the issue was indeed the missing commandTopic

After adding it, it works. I won’t bore everyone the whole sitemap json (unless it’s useful, then I’ll gladly post it) but this is a working item with commandTopic correctly set up

        {
          "widgetId": "020001030104",
          "type": "Switch",
          "visibility": true,
          "label": "Streamer [ON]",
          "labelSource": "ITEM_LABEL",
          "icon": "smiley",
          "staticIcon": false,
          "pattern": "%s",
          "unit": "",
          "mappings": [],
          "item": {
            "link": "http://pi5:8080/rest/items/faikin02_streamer",
            "state": "ON",
            "stateDescription": {
              "pattern": "%s",
              "readOnly": false,
              "options": []
            },
            "lastState": "OFF",
            "lastStateUpdate": 1780348842975,
            "lastStateChange": 1780348813806,
            "type": "Switch",
            "name": "faikin02_streamer",
            "label": "Streamer",
            "category": "smiley",
            "tags": [],
            "groupNames": [
              "g_faikin02",
              "g_faikin02_cmd"
            ]
          },
          "widgets": []
        },

Item definition:

        Type switch   : streamer        [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.streamer", on="true", off="false", commandTopic="state/faikin02/status"]

And this is a not working item

        {
          "widgetId": "020001030105",
          "type": "Switch",
          "visibility": true,
          "label": "Quiet Outdoor [OFF]",
          "labelSource": "ITEM_LABEL",
          "icon": "soundvolume_mute",
          "staticIcon": false,
          "pattern": "%s",
          "unit": "",
          "mappings": [],
          "item": {
            "link": "http://pi5:8080/rest/items/faikin02_quiet",
            "state": "OFF",
            "stateDescription": {
              "pattern": "%s",
              "readOnly": true,
              "options": []
            },
            "lastState": "NULL",
            "lastStateUpdate": 1780348842973,
            "lastStateChange": 1780330246355,
            "type": "Switch",
            "name": "faikin02_quiet",
            "label": "Quiet Outdoor",
            "category": "soundvolume_mute",
            "tags": [],
            "groupNames": [
              "g_faikin02",
              "g_faikin02_cmd"
            ]
          },
          "widgets": []
        },

With the commandTopic missing in its item definition:

        Type switch   : quiet           [stateTopic="state/faikin02/status",  transformationPattern="JSONPATH:$.quiet",    on="true", off="false"]

And the readOnly is indeed set to true as per @timbms explanation.

As a matter of fact the workaround @Hans_Lree did not work:

Item:

Switch faikin02_econo    "Econo []"      <price>                (g_faikin02,g_faikin02_cmd) {channel="mqtt:topic:Faikin:faikin02:econo"}

Json:

        {
          "widgetId": "020001030102",
          "type": "Switch",
          "visibility": true,
          "label": "Econo",
          "labelSource": "ITEM_LABEL",
          "icon": "price",
          "staticIcon": false,
          "pattern": "",
          "unit": "",
          "mappings": [],
          "item": {
            "link": "http://pi5:8080/rest/items/faikin02_econo",
            "state": "OFF",
            "stateDescription": {
              "pattern": "",
              "readOnly": true,
              "options": []
            },
            "lastState": "NULL",
            "lastStateUpdate": 1780349527961,
            "lastStateChange": 1780330246355,
            "type": "Switch",
            "name": "faikin02_econo",
            "label": "Econo",
            "category": "price",
            "tags": [],
            "groupNames": [
              "g_faikin02",
              "g_faikin02_cmd"
            ]
          },
          "widgets": []
        },

Sorry if I didn’t post the iOS app version as it auto updates but its 3.2.41 (249).

I dit not try the testflight beta, but I am more than willing to do that if it helps the community somehow.

Thanks again for the detailed reply, the insight of the server side process and, of course, pointing me to solving the problem.

Sorry if I didn’t reply sooner, this account was on hold and I must have misconfigured the email notificaiton.

Let me know if you need more info from my side, otherwise I’ll gladly mark it as solved as technically it was user error: it does make sense that a commandTopic is needed to send a command to an item - even if it was working for years (since 2.4 as a matter of fact) without and is still working everywhere except in the app.

Thanks for the feedback
Please mark the thread as resolved and leave a review on the Apple AppStore