Panasonic Comfort Cloud integration

Very good news @seime , thank you for your work. I would be happy to try it. Just one question: does it work with openhab 3 or it is for openhab 2.x?

Tested with OH 3.2 only

Hi! Cool. I’ve tried it. First impressions:

  • works like a charm, thank you!
  • automatic discovery works but it writes deviceId in this format: “CS-TZ20WKEW-XXXXXXXXX” but if you want to add it in a tet config file (.things) it has to be link this: “CS-TZ20WKEW+XXXXXXXXX”
  • something is wrong with this temperature item:
2022-02-23 08:57:04.024 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'currentOutdoorTemperature' changed from NULL to 126 °C

It is 126 when the AC is off, but it changes to 5 (what is ok) when the AC is ON.

Regarding the deviceId - I had to remove the ‘+’ from the thingId when producing a discovery result (openhab did not like a plus sign). I will look into it and see if there could be another solution.

Regarding the temperature - there is no “processing” of the data. I’ve noticed myself that the indoor temperature seems to drift upwards when I switch off the AC (going from 20 → 28-29), but that could be due to placement of the temperature sensor itself and excess heat being accumulated when the fan stops (I run mine in heating mode during winter).

The temperature channel could be changed to UNDEF when the AC is switched off, but in that case I need to create a connection between the multiple indoor units connected to a common outdoor compressor.

Thanks for testing!

Hmm - here I am struggling with the deviceID and cannot do discovery.

My CS-NZ9SKE is connected to wifi with the CZ.TACG1 dongle. Works well with comfort cloud - and I can easily set up my account in this binding, but cannot get my AC to work.
On the CZ-TACG1 dongle, I have a deviceID listed/printed. Is that the one I should use instead of the XXXXXX ? (that doesnt work…)

OK - it picked up the deviceID listed on my dongle - without the need for anything else (no model id etc). Now it seems to be working. Will be interesting to get some experience with this :wink:

Thanks for the good effort Arne !

I can confirm that the binding does the trick with my AC (CS-NZ9SKE with CZ-TACG1 dongle). All relevant functions are supported…

Tested and working with CS-TZ35WKEW & CU-TZ35WKE. Big great thank you for this binding!

I tested on CS-TZ20WKEW and CS-TZ35WKEW, works very well!

Let me know if you want to test with more devices. I have a A2W Heat Pump, WH-MXC09H3E8, connected to Comfort Cloud. I can’t get the device-id to work manually or via auto discovery.

Hi Henrik, could you enable DEBUG logging and post the logs? Make sure you remove any credentials etc.


Hi Arne,
Thanks for creating this binding.
Meanwhile I have already 3 out of 5 airco’s up & running.
However with one of them I get the following error.

Error retrieving data from server: Error sending request to server. Server responded with 404 and payload <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" ""> <html> <head> <title>404 Not found</title> <style type="text/css"> <!-- BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;font-size:12px;} H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} PRE, TT {border: 1px dotted #525D76} A {color : black;} {color : black;} --> </style> </head> <body> <h1>404 Not found</h1> <p> The page you tried to access does not exist. </p> </body> </html>

I think it is because of the slightly strange deviceID which is CS-A73C5095/20200204/M100008#.
I presume the Jason request is interpreting it as a path instead of an id?
Any idea how to resolve this? (I tried to add double or single quote codes but then it says it cannot find the device).
Tx in advance,

Hi @PBrou, I’ve added a new jar file (see marketplace posting or download directly here: with a possible fix for your problem. Not sure if it helps. If not, please enable debug logging and post the logs (either here or by PM). Make sure to remove any sensitive information as the full request/response is logged.


Hi Arne, I installed your latest version from the market place. The problem is however still present.
(though one strange thing is that under add Thing I have twice the binding & twice the condition thing type)
I wonder how this can be solved because the https will keep on interpreting the slash as a sub-path.
On the other hand, if it works in the app… unless the app is always interrogating via the group level, but if we do a set then it needs to do that on device level, so.

My 3 airco units with the deviceID as device model “+” some other code work fine: they are also show up when using the ‘scan’ option.

There are 2 others where I have a problem.
The first one is with this strange device id = device model “/” code “/” other code, with this error.
A second one is less problematic because I could add it manually (it appeared in the log file during discovery) - this unit has an ad hoc added Wifi module - this one shows up as only one string “C097936750”, it has deviceType=“1” (all others “3”) & it does not have adevideModuleName nor a deviceHashGuid.

2022-05-04 12:14:48.678 [DEBUG] 
[cloud.internal.logging.RequestLogger] - Request accountName-3883
accountName-3883 > GET
accountName-3883 > Accept-Encoding: gzip
accountName-3883 > User-Agent: G-RAC
accountName-3883 > Accept: application/json
accountName-3883 > Content-Type: application/json
accountName-3883 > X-APP-TYPE: 1
accountName-3883 > X-APP-VERSION: 1.20.0
accountName-3883 > X-User-Authorization: XXXXXXXXXXXXXXXXXXXXXXXXX
accountName-3883 > Host:

2022-05-04 12:14:48.928 [DEBUG] [cloud.internal.logging.RequestLogger] - Could not reformat malformed JSON due to ' Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 12 path $'
2022-05-04 12:14:48.929 [DEBUG] [cloud.internal.logging.RequestLogger] - Response accountName-3883
accountName-3883 < HTTP/1.1 404
accountName-3883 < Date: Wed, 04 May 2022 10:14:48 GMT
accountName-3883 < Content-Type: text/html;charset=ISO-8859-1
accountName-3883 < Content-Length: 618
accountName-3883 < Connection: keep-alive
accountName-3883 < Server: nginx

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "">
  <title>404 Not found</title>
  <style type="text/css">
    BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;font-size:12px;}
    H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;}
    PRE, TT {border: 1px dotted #525D76}
    A {color : black;} {color : black;}
   <h1>404 Not found</h1>
    The page you tried to access does not exist.

Another idea… does the API support the GET with the hashed value of the device? (I tried to use these ID’s but that does not seem to work) .

When trying to do this via the python script pcomfortcloud it seems that it is indeed working rather via this hashed value deviceHashedGuid - and there is does work ok:

openhabian@openhab:/etc/openhab/panasonic $ python USER PWD list
list of devices and its device id (1-x)
device #1
    model                : CS-MTZ16WKE
    group                : Boven
    id                   : c3f161d25d9139c7937afa01536601xxxxxxxxxxxxxxxx
    name                 : Slaapkamer ouders

device #2
    model                : 
    group                : Boven
    id                   : 8bc17a3d0855f670290xxxxxxxxxxxx
    name                 : Airco zolder

device #3
    model                : CS-MTZ16WKE
    group                : Boven
    id                   : 82b06f5efe544c941771f6cb0d7382c81f3xxxxxxxxxxxxx
    name                 : Airco Thomas

device #4
    model                : CS-MTZ16WKE
    group                : Boven
    id                   : bb4815bbeaa95af5825380abd2de5f7xxxxxxxxxx
    name                 : Airco Mathias

device #5
    model                : CS-Z50VKEW
    group                : Gelijkvloers
    id                   : cb4afc3e80a19d42fb9b8d8dbc3cb93f0992c6f4093f33xxxxxx
    name                 : Airco Living

openhabian@openhab:/etc/openhab/panasonic $ python USER PWD get 5
reading from device 'Airco Living' (cb4afc3e80a19d42fb9b8d8dbc3cb93f0992c6f4093f33xxxxxx)
id                       : cb4afc3e80a19d42fb9b8d8dbc3cb93f0992c6f4093f33xxxxxx
    airSwingVertical     : Auto
    temperature          : 21.0
    power                : Off
    eco                  : Auto
    nanoe                : Off
    temperatureInside    : 18
    temperatureOutside   : 16
    airSwingHorizontal   : Auto
    mode                 : Auto
    fanSpeed             : Auto

The number here is a request counter. If you refresh every minute your binding has been running for 10 hours. Is this correct? If not I suspect you’re still running the previous version. Try to delete the existing Things (if created from Inbox) and restart openhab.

I tested with a slash in the deviceId myself, and it is indeed escaped (%2B) in the url.

Using the deviceGuidHash did not work, and by reading the source code of the script you referred to it appears that they send the deviceGuid and not the deviceGuidHash in the requests.

If you could provide a complete log for the first set of requests I might see something more.

I did not catch the actual second problem - could you elaborate?


Hi Arne,
There was an issue because I installed the jar first via the addons directory & forgot to remove it…:frowning: (that explained the the doubles in my thing types & the old+new bundle popping up in my bundle:list - and
I removed it all & reinstalled it, full restart… is now only present.
The request counter is now at 10. The escaped characters are indeed clearly there.
Unfortunately I still get the error.

2022-05-04 22:36:14.837 [DEBUG] [cloud.internal.logging.RequestLogger] - Request PanasonicComfortCloudBridge-8
PanasonicComfortCloudBridge-8 > GET
PanasonicComfortCloudBridge-8 > Accept-Encoding: gzip
PanasonicComfortCloudBridge-8 > User-Agent: G-RAC
PanasonicComfortCloudBridge-8 > Accept: application/json
PanasonicComfortCloudBridge-8 > Content-Type: application/json
PanasonicComfortCloudBridge-8 > X-APP-TYPE: 1
PanasonicComfortCloudBridge-8 > X-APP-VERSION: 1.20.0
PanasonicComfortCloudBridge-8 > X-User-Authorization: pKU842yBs5BJX3CNgZ7q1N19NWyVNTO5
PanasonicComfortCloudBridge-8 > Host:
2022-05-04 22:38:17.161 [DEBUG] [cloud.internal.logging.RequestLogger] - Could not reformat malformed JSON due to ' Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 12 path $'
2022-05-04 22:38:17.163 [DEBUG] [cloud.internal.logging.RequestLogger] - Response PanasonicComfortCloudBridge-10

Below the piece from the log that is probably of interest for you:

2022-05-04 22:32:17.816 [INFO ] [g.discovery.internal.PersistentInbox] - Added new thing 'panasoniccomfortcloud:aircondition:PanasonicComfortCloudBridge:CS-MTZ16WKE-4426105778' to inbox.
2022-05-04 22:32:17.819 [DEBUG] [anasonicComfortCloudDiscoveryService] - Found device of type 1 which is currently not supported (not known by the developer) - please report back
2022-05-04 22:32:17.829 [INFO ] [g.discovery.internal.PersistentInbox] - Added new thing 'panasoniccomfortcloud:aircondition:PanasonicComfortCloudBridge:CS-MTZ16WKE-4426102106' to inbox.
2022-05-04 22:32:17.854 [INFO ] [g.discovery.internal.PersistentInbox] - Added new thing 'panasoniccomfortcloud:aircondition:PanasonicComfortCloudBridge:CS-MTZ16WKE-4426102047' to inbox.
2022-05-04 22:32:17.858 [ERROR] [nternal.DiscoveryServiceRegistryImpl] - Cannot trigger scan for thing types '[panasoniccomfortcloud:aircondition]' on 'PanasonicComfortCloudDiscoveryService'!
java.lang.IllegalArgumentException: ID segment 'CS-A73C5095/20200204/M100008#' contains invalid characters. Each segment of the ID must match the pattern [\w-]*.
	at org.openhab.core.common.AbstractUID.validateSegment( ~[?:?]
	at org.openhab.core.common.AbstractUID.<init>( ~[?:?]
	at org.openhab.core.common.AbstractUID.<init>( ~[?:?]
	at org.openhab.core.thing.UID.<init>( ~[?:?]
	at org.openhab.core.thing.ThingUID.<init>( ~[?:?]
	at org.openhab.binding.panasoniccomfortcloud.internal.discovery.PanasonicComfortCloudDiscoveryService.startScan( ~[?:?]
	at org.openhab.core.config.discovery.AbstractDiscoveryService.startScan( ~[?:?]
	at org.openhab.core.config.discovery.internal.DiscoveryServiceRegistryImpl.startScan( ~[?:?]
	at org.openhab.core.config.discovery.internal.DiscoveryServiceRegistryImpl.startScans( ~[?:?]
	at org.openhab.core.config.discovery.internal.DiscoveryServiceRegistryImpl.startScan( ~[?:?]
	at ~[?:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke( ~[?:?]
	at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke( ~[?:?]
	at java.lang.reflect.Method.invoke( ~[?:?]
	at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation( ~[bundleFile:3.4.5]
	at org.apache.cxf.service.invoker.AbstractInvoker.invoke( ~[bundleFile:3.4.5]
	at org.apache.cxf.jaxrs.JAXRSInvoker.invoke( ~[bundleFile:3.4.5]
	at org.apache.cxf.jaxrs.JAXRSInvoker.invoke( ~[bundleFile:3.4.5]
	at org.apache.cxf.interceptor.ServiceInvokerInterceptor$ ~[bundleFile:3.4.5]
	at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage( ~[bundleFile:3.4.5]
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept( ~[bundleFile:3.4.5]
	at org.apache.cxf.transport.ChainInitiationObserver.onMessage( ~[bundleFile:3.4.5]
	at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke( ~[bundleFile:3.4.5]
	at org.apache.cxf.transport.servlet.ServletController.invokeDestination( ~[bundleFile:3.4.5]
	at org.apache.cxf.transport.servlet.ServletController.invoke( ~[bundleFile:3.4.5]
	at org.apache.cxf.transport.servlet.ServletController.invoke( ~[bundleFile:3.4.5]
	at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke( ~[bundleFile:3.4.5]
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest( ~[bundleFile:3.4.5]
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost( ~[bundleFile:3.4.5]
	at javax.servlet.http.HttpServlet.service( ~[bundleFile:3.1.0]
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service( ~[bundleFile:3.4.5]
	at org.eclipse.jetty.servlet.ServletHolder.handle( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.servlet.ServletHandler.doHandle( ~[bundleFile:9.4.43.v20210629]
	at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle( ~[bundleFile:?]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle( ~[bundleFile:9.4.43.v20210629]
	at ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.session.SessionHandler.doHandle( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle( ~[bundleFile:9.4.43.v20210629]
	at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle( ~[bundleFile:?]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.servlet.ServletHandler.doScope( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.session.SessionHandler.doScope( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.handler.ContextHandler.doScope( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle( ~[bundleFile:9.4.43.v20210629]
	at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle( ~[bundleFile:?]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.Server.handle( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.HttpChannel.lambda$handle$1( ~[bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.HttpChannel.dispatch( [bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.HttpChannel.handle( [bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.server.HttpConnection.onFillable( [bundleFile:9.4.43.v20210629]
	at$ReadCallback.succeeded( [bundleFile:9.4.43.v20210629]
	at [bundleFile:9.4.43.v20210629]
	at$ [bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask( [bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce( [bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce( [bundleFile:9.4.43.v20210629]
	at [bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ [bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob( [bundleFile:9.4.43.v20210629]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$ [bundleFile:9.4.43.v20210629]
	at [?:?]

Concerning the 2nd problem: it is because of the type 1 which is not yet supported apparently.
Below of the response in the get list for this type 1 device (structure seems quite similar to that of type 3):

          "deviceGuid": "C097936750",
          "deviceType": "1",
          "deviceName": "Airco zolder",
          "permission": 3,
          "summerHouse": 0,
          "iAutoX": false,
          "nanoe": false,
          "nanoeStandAlone": false,
          "autoMode": true,
          "heatMode": true,
          "fanMode": false,
          "dryMode": true,
          "coolMode": true,
          "ecoNavi": false,
          "powerfulMode": true,
          "quietMode": true,
          "airSwingLR": true,
          "autoSwingUD": false,
          "ecoFunction": 0,
          "temperatureUnit": 0,
          "modeAvlList": {
            "autoMode": 1,
            "fanMode": 1
          "parameters": {
            "operate": 0,
            "operationMode": 1,
            "temperatureSet": 25.0,
            "fanSpeed": 0,
            "fanAutoMode": 1,
            "airSwingLR": 2,
            "airSwingUD": 2,
            "ecoMode": 0,
            "ecoNavi": 1,
            "nanoe": 0,
            "iAuto": 0,
            "actualNanoe": 0,
            "airDirection": 1,
            "ecoFunctionData": 0,
            "lastSettingMode": 0


the problem now seems to be that openhab does not like slashes in the thing uid. I will fix the problem later, but I assume you can circumvent it by adding the thing manually.

The second problem; I see that I put in a blocker there since I only knew about type 3 (regular aircons). I will add support for type 1 as well (wifi dongle apparently). I think you can circumvent this problem as well by adding this thing manually. Could of course be that I need to do some code changes as well if the data reported isn’t quite like I expected though.

Regards Arne

I’ve published a new version where hopefully your issues have been resolved.

Would you like to test and report back?


Here’s the feedback on your new version.
Installed bundle:

The scan now nicely shows all my 5 devices, so the error at scan time because of the invalid characters is solved and the type1 device with wifi-add-on is now also appearing in the scan! :slight_smile:

Unfortunately the other challenge with the annoying url is not yet solved.

Not yet completely there but getting closer…:wink:

15:01:20.416 [DEBUG] [asonicComfortCloudAirconditionHandler] - Initializing air conditioner using config AirConditionerConfiguration{deviceId='CS-A73C5095/20200204/M100008#'}
15:01:21.488 [DEBUG] [tcloud.internal.logging.RequestLogger] - Request fd74594e11-3
fd74594e11-3 > GET
fd74594e11-3 > Accept-Encoding: gzip
fd74594e11-3 > User-Agent: G-RAC
fd74594e11-3 > Accept: application/json
fd74594e11-3 > Content-Type: application/json
fd74594e11-3 > X-APP-TYPE: 1
fd74594e11-3 > X-APP-VERSION: 1.20.0
fd74594e11-3 > X-User-Authorization: tY3JecEZT7C3ik3HtoxNV56sIyDJXCzy
fd74594e11-3 > Host:

15:01:21.736 [DEBUG] [tcloud.internal.logging.RequestLogger] - Could not reformat malformed JSON due to ' Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 12 path $'
15:01:21.744 [DEBUG] [tcloud.internal.logging.RequestLogger] - Response fd74594e11-3
fd74594e11-3 < HTTP/1.1 404
fd74594e11-3 < Date: Mon, 16 May 2022 13:01:21 GMT
fd74594e11-3 < Content-Type: text/html;charset=ISO-8859-1
fd74594e11-3 < Content-Length: 618
fd74594e11-3 < Connection: keep-alive
fd74594e11-3 < Server: nginx

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "">
  <title>404 Not found</title>
  <style type="text/css">
    BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;font-size:12px;}
    H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;}
    PRE, TT {border: 1px dotted #525D76}
    A {color : black;} {color : black;}
   <h1>404 Not found</h1>
    The page you tried to access does not exist.

I do not know what the problem is, and the logs you are sending are quite limited.

I’ve added another test jar; Release Alpha 4 · seime/openhab2-addons · GitHub

This one just strips away anything and including the slash in the url when doing the request. I have no idea if it works, but you can try it out. I did get some different error responses from the API when I forged some requests, so there is a tiny hope.