[SOLVED] Millheat Wifi Electric heater openhab binding

Simple answer: Nothing is lost. But if you are using the room program setup, the heaters will remain at their current temperature until connection is restored - not following the room program.

Cheers

Hello,
I have OH2.5 installation and I have been using the MillHeat binding for few months. It was working properly earlier but I recently noticed that the MillHeat server does not change the setting when I make change in OH. If I look at the OH logs it looks like the temperature is changed but the setting is not changing anything in the heater and after minute or two I can see in the OH log it looks like it changes back to the previous temperature (even though nothing never really changed in the heater setting). When I monitor the MillHeat mobile app there is no change at all in the settings. This happened after the MillHeat mobile app was updated.

OK, it might be that they have changed the API (which is unpublished and require reverse engineering of the app).

I will try to fix this, but I am unable to do it at the moment unfortunately.

Regards

Trying to set it up in OH3 and Mill Heating API is stuck at INITIALIZING. Credentials are correct and don’t have any connection problems using their iOS app.

OK, I have yet to test on the latest OH3.

Could you send some logs? Be careful to mask any personal details before sending.

Regards

When initializing the thing (mill heating api):

2021-03-01 19:16:07.892 [DEBUG] [ernal.handler.MillheatAccountHandler] - Finished initializing!
2021-03-01 19:16:07.916 [DEBUG] [llheat.internal.client.RequestLogger] - Request a2f435b80d-0
a2f435b80d-0 > POST https://eurouter.ablecloud.cn:9005/zc-account/v1/login
a2f435b80d-0 > Accept-Encoding: gzip
a2f435b80d-0 > User-Agent: Jetty/9.4.20.v20190813
a2f435b80d-0 > Connection: Keep-Alive
a2f435b80d-0 > X-Zc-Major-Domain: seanywell
a2f435b80d-0 > X-Zc-Msg-Name: millService
a2f435b80d-0 > X-Zc-Sub-Domain: milltype
a2f435b80d-0 > X-Zc-Seq-Id: 1
a2f435b80d-0 > X-Zc-Version: 1
a2f435b80d-0 > Content-Type: application/x-zc-object
a2f435b80d-0 > Host: eurouter.ablecloud.cn:9005
a2f435b80d-0 > Content-Length: 62
{
  "account": "xxx",
  "password": "xxx"
}
2021-03-01 19:16:08.045 [DEBUG] [llheat.internal.client.RequestLogger] - Response a2f435b80d-0
a2f435b80d-0 < HTTP/1.1 200 OK
a2f435b80d-0 < Content-Length: 269
a2f435b80d-0 < Content-Type: application/x-zc-object
a2f435b80d-0 < Date: Mon, 01 Mar 2021 18:16:08 GMT
a2f435b80d-0 < X-Zc-Msg-Name: X-Zc-Ack
a2f435b80d-0 < X-Zc-Trace-Id: 23cece7c40a7b82d80523c7ad344238e
{
  "email": "xxx",
  "nickName": "xxx",
  "phone": "",
  "refreshToken": "xxx",
  "refreshTokenExpire": "2021-03-31 18:16:07",
  "token": "xxx",
  "tokenExpire": "2021-03-01 20:16:07",
  "userId": xxx,
  "userProfile": {
    "nick_name": "Jacob",
    "privacyPolicy": 1
  }
}
2021-03-01 19:16:08.053 [DEBUG] [llheat.internal.client.RequestLogger] - Request a2f435b80d-1
a2f435b80d-1 > POST https://eurouter.ablecloud.cn:9005/millService/v1/selectHomeList
a2f435b80d-1 > Accept-Encoding: gzip
a2f435b80d-1 > User-Agent: Jetty/9.4.20.v20190813
a2f435b80d-1 > Connection: Keep-Alive
a2f435b80d-1 > X-Zc-Major-Domain: seanywell
a2f435b80d-1 > X-Zc-Msg-Name: millService
a2f435b80d-1 > X-Zc-Sub-Domain: milltype
a2f435b80d-1 > X-Zc-Seq-Id: 1
a2f435b80d-1 > X-Zc-Version: 1
a2f435b80d-1 > Content-Type: application/x-zc-object
a2f435b80d-1 > X-Zc-Timestamp: 1614622568
a2f435b80d-1 > X-Zc-Timeout: 300
a2f435b80d-1 > X-Zc-Nonce: T1YT612DGZ1HO8VA
a2f435b80d-1 > X-Zc-User-Id: xxx
a2f435b80d-1 > X-Zc-User-Signature: xxx
a2f435b80d-1 > X-Zc-Content-Length: 2
a2f435b80d-1 > Host: eurouter.ablecloud.cn:9005
a2f435b80d-1 > Content-Length: 2
{}
2021-03-01 19:16:08.177 [DEBUG] [llheat.internal.client.RequestLogger] - Response a2f435b80d-1
a2f435b80d-1 < HTTP/1.1 200 OK
a2f435b80d-1 < Content-Length: 514
a2f435b80d-1 < Content-Type: application/x-zc-object
a2f435b80d-1 < Server: Jetty(9.1.5.v20140505)
a2f435b80d-1 < X-Zc-Msg-Name: X-Zc-Ack
a2f435b80d-1 < X-Zc-Trace-Id: 78ca216c40afce9780d359b78192aded
a2f435b80d-1 < Date: Mon, 01 Mar 2021 18:16:08 GMT
{
  "hourSystem": 1,
  "homeList": [
    {
      "maxTemperature": 0,
      "maxTemperatureMsg": "Temperature range is limited by administrator to 5-35℃",
      "homeAlways": 0,
      "changeTemperature": 0,
      "homeName": "xxx",
      "isHoliday": 0,
      "holidayStartTime": 0,
      "timeZone": "+1:00",
      "modeMinute": 0,
      "modeStartTime": 0,
      "holidayTemp": 10,
      "modeHour": 0,
      "changeTemperatureMsg": "Temperature change not allowed by administrator",
      "currentMode": 0,
      "holidayEndTime": 0,
      "holidayTempType": 1,
      "homeType": 0,
      "homeId": 202012301029070016,
      "programId": 202012301029070016
    }
  ]
}
2021-03-01 19:16:08.183 [WARN ] [mmon.WrappedScheduledExecutorService] - Scheduled runnable ended with an exception: 
java.time.DateTimeException: Invalid ID for ZoneOffset, non numeric characters found: +1:00
	at java.time.ZoneOffset.parseNumber(ZoneOffset.java:269) ~[?:?]
	at java.time.ZoneOffset.of(ZoneOffset.java:221) ~[?:?]
	at org.openhab.binding.millheat.internal.model.Home.<init>(Home.java:62) ~[?:?]
	at org.openhab.binding.millheat.internal.handler.MillheatAccountHandler.refreshModel(MillheatAccountHandler.java:267) ~[?:?]
	at org.openhab.binding.millheat.internal.handler.MillheatAccountHandler.lambda$0(MillheatAccountHandler.java:183) ~[?:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) ~[?:?]
	at java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) ~[?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
	at java.lang.Thread.run(Thread.java:834) [?:?]
==> /var/log/openhab/events.log <==
2021-03-01 19:16:07.878 [INFO ] [ab.event.ThingStatusInfoChangedEvent] - Thing 'millheat:account:xxx' changed from UNINITIALIZED (DISABLED) to INITIALIZING

When scanning for things:

2021-03-01 19:18:51.030 [DEBUG] [l.discovery.MillheatDiscoveryService] - Start scan for Millheat devices on account millheat:account:a2f435b80d
2021-03-01 19:18:51.037 [DEBUG] [llheat.internal.client.RequestLogger] - Request a2f435b80d-2
a2f435b80d-2 > POST https://eurouter.ablecloud.cn:9005/millService/v1/selectHomeList
a2f435b80d-2 > Accept-Encoding: gzip
a2f435b80d-2 > User-Agent: Jetty/9.4.20.v20190813
a2f435b80d-2 > Connection: Keep-Alive
a2f435b80d-2 > X-Zc-Major-Domain: seanywell
a2f435b80d-2 > X-Zc-Msg-Name: millService
a2f435b80d-2 > X-Zc-Sub-Domain: milltype
a2f435b80d-2 > X-Zc-Seq-Id: 1
a2f435b80d-2 > X-Zc-Version: 1
a2f435b80d-2 > Content-Type: application/x-zc-object
a2f435b80d-2 > X-Zc-Timestamp: 1614622731
a2f435b80d-2 > X-Zc-Timeout: 300
a2f435b80d-2 > X-Zc-Nonce: Y282AZ6QNVDB4P6D
a2f435b80d-2 > X-Zc-User-Id: xxx
a2f435b80d-2 > X-Zc-User-Signature: 3845a61ae62140d03a7813f52891c1bdc4677ede
a2f435b80d-2 > X-Zc-Content-Length: 2
a2f435b80d-2 > Host: eurouter.ablecloud.cn:9005
a2f435b80d-2 > Content-Length: 2
{}
2021-03-01 19:18:51.137 [DEBUG] [llheat.internal.client.RequestLogger] - Response a2f435b80d-2
a2f435b80d-2 < HTTP/1.1 200 OK
a2f435b80d-2 < Content-Length: 514
a2f435b80d-2 < Content-Type: application/x-zc-object
a2f435b80d-2 < Server: Jetty(9.1.5.v20140505)
a2f435b80d-2 < X-Zc-Msg-Name: X-Zc-Ack
a2f435b80d-2 < X-Zc-Trace-Id: 581c8220402aa1e980603f915754bd42
a2f435b80d-2 < Date: Mon, 01 Mar 2021 18:18:51 GMT
{
  "hourSystem": 1,
  "homeList": [
    {
      "maxTemperature": 0,
      "maxTemperatureMsg": "Temperature range is limited by administrator to 5-35℃",
      "homeAlways": 0,
      "changeTemperature": 0,
      "homeName": "xxx",
      "isHoliday": 0,
      "holidayStartTime": 0,
      "timeZone": "+1:00",
      "modeMinute": 0,
      "modeStartTime": 0,
      "holidayTemp": 10,
      "modeHour": 0,
      "changeTemperatureMsg": "Temperature change not allowed by administrator",
      "currentMode": 0,
      "holidayEndTime": 0,
      "holidayTempType": 1,
      "homeType": 0,
      "homeId": 202012301029070016,
      "programId": 202012301029070016
    }
  ]
}
2021-03-01 19:18:51.142 [ERROR] [nternal.DiscoveryServiceRegistryImpl] - Cannot trigger scan for thing types '[millheat:room, millheat:heater, millheat:home]' on 'MillheatDiscoveryService'!
java.time.DateTimeException: Invalid ID for ZoneOffset, non numeric characters found: +1:00
	at java.time.ZoneOffset.parseNumber(ZoneOffset.java:269) ~[?:?]
	at java.time.ZoneOffset.of(ZoneOffset.java:221) ~[?:?]
	at org.openhab.binding.millheat.internal.model.Home.<init>(Home.java:62) ~[?:?]
	at org.openhab.binding.millheat.internal.handler.MillheatAccountHandler.refreshModel(MillheatAccountHandler.java:267) ~[?:?]
	at org.openhab.binding.millheat.internal.handler.MillheatAccountHandler.updateModel(MillheatAccountHandler.java:331) ~[?:?]
	at org.openhab.binding.millheat.internal.handler.MillheatAccountHandler.updateModelFromServerWithRetry(MillheatAccountHandler.java:308) ~[?:?]
	at org.openhab.binding.millheat.internal.discovery.MillheatDiscoveryService.startScan(MillheatDiscoveryService.java:65) ~[?:?]
	at org.openhab.core.config.discovery.AbstractDiscoveryService.startScan(AbstractDiscoveryService.java:194) ~[bundleFile:?]
	at org.openhab.core.config.discovery.internal.DiscoveryServiceRegistryImpl.startScan(DiscoveryServiceRegistryImpl.java:377) [bundleFile:?]
	at org.openhab.core.config.discovery.internal.DiscoveryServiceRegistryImpl.startScans(DiscoveryServiceRegistryImpl.java:362) [bundleFile:?]
	at org.openhab.core.config.discovery.internal.DiscoveryServiceRegistryImpl.startScan(DiscoveryServiceRegistryImpl.java:211) [bundleFile:?]
	at org.openhab.core.io.rest.core.internal.discovery.DiscoveryResource.scan(DiscoveryResource.java:105) [bundleFile:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
	at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
	at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
	at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:179) [bundleFile:1.0.9]
	at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) [bundleFile:1.0.9]
	at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:201) [bundleFile:1.0.9]
	at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:104) [bundleFile:1.0.9]
	at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59) [bundleFile:1.0.9]
	at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96) [bundleFile:1.0.9]
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) [bundleFile:1.0.9]
	at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) [bundleFile:1.0.9]
	at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:216) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:301) [bundleFile:1.0.9]
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:220) [bundleFile:1.0.9]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) [bundleFile:3.1.0]
	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:276) [bundleFile:1.0.9]
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:852) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:544) [bundleFile:9.4.20.v20190813]
	at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71) [bundleFile:?]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:536) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1581) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1307) [bundleFile:9.4.20.v20190813]
	at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:293) [bundleFile:?]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:482) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1549) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1204) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [bundleFile:9.4.20.v20190813]
	at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80) [bundleFile:?]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.Server.handle(Server.java:494) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:374) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:268) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:367) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:782) [bundleFile:9.4.20.v20190813]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:918) [bundleFile:9.4.20.v20190813]
	at java.lang.Thread.run(Thread.java:834) [?:?]

java.time.DateTimeException: Invalid ID for ZoneOffset, non numeric characters found: +1:00

It appears that they are no longer following the ISO8601 standard on timezone information; the standard mandates 2 digits for each segment (hour/minutes) while they are sending just 1.

I won’t be able to create a workaround for this very soon, but please file a bug on github. You may try to adjust the timezone in the Millheat app to UTC to see if they send something parseable then.

Regards
Arne

Ok, just filed a bug report.

Can’t find a way to change the time zone using the Millheat app, tried both iOS and Android.
It is displayed under Settings>Date and time, but can’t be changed. And there is no info at their site either, just that it gets the time from the cloud.

Check this out:
https://api.millheat.com/

Best regards

1 Like

Cool!

Yes I am aware of it. Unfortunately it is quite limited.

Regards

Hello Together,

I’ve ordered an “mill PA900Wifi3” because of this OpenHab binding.

Summary: I’m not happy with it… → I think it goes back.

My Idea:
I want to control the temperature of my small Bathroom by OpenHab.

What works well:
Adding the “mill PA900Wifi3” into my local network.
Installing the Smartphone app “Mill Norway”
Control the Heater by this app, works also well
Adding and connectiing the OpenHab Binding (Gateway) works well
->If you add your Heater to an Room in the app “Mill Norway”
Then adding a Room to OpenHab works also well.
->If you add your Heater as standalone the app “Mill Norway”
Then adding the Heater as standalone in OpenHab works also well…

Now the Problems:
→ I’m not able to control the temperature of the Room!
→ The documentation says it sould be possible to R/W these variables. But it isn’t.

Here in this test. I try to set the Away and Sleep Mode to 27 degree. After a view seconds the old values are back…
(I have done several tests and tries, no success.)


@bjovas
Do you have an Idea what is wrong here in openHAB 3.1.0 Release Build ?

Also if I add the Heater as “Standalone” this means without connection to any Room. Then you are not able to see the additional settings like “targetTemperature”. (Mentioned in the binding documentation)

Last problem:
I’m not able to switch the heater off by OpenHab…

If I add

Not so beautiful:
The Temperature is shown as wrong value:
image

Solution:
Send the heater back, buy a more simple heater and control it by an switchable socket…

If the heater is marked as “independent” in the app, the setpoint and master switch channels should become available. You might have to disable/enable the bridge for the binding to update the available channels.

You even might have to delete the thing in OH3 for the channels to show up.

Regarding the temperature, could you set logging to DEBUG for the binding and send over the logs? Make sure to remove any credentials etc if showing.

@seime
I have deleted all Items and also the thing “millheat:heater” and also the thing “millheat:account” completely.
I also tried to with the things online/offline but no difference.
I also tried to add the thing manually, the connection works well but no setpoint and master switch channels.

→ But the channels do not appear…

Is there a difference between Openhab V3.1 and V3.2?

I do not what changed between 3.1 and 3.2.

Did you try to add the items via item files?

@seime
! Thank you very much for your intensive help !

I have now also tried to add the items by file.
Now I can see the item, but

.

Here an outtake of my log in DEBUG mode:
→ For me it looks not bad, the heater says: " “canChangeTemp”: 1,"

Hier der gesamte auszug:
==> /var/log/openhab/openhab.log <==
2022-01-31 20:15:47.445 [DEBUG] [llheat.internal.client.RequestLogger] - Request 1b5362a9a8-16
1b5362a9a8-16 > POST https://eurouter.ablecloud.cn:9005/millService/v1/selectHomeList
1b5362a9a8-16 > Accept-Encoding: gzip
1b5362a9a8-16 > User-Agent: Jetty/9.4.40.v20210413
1b5362a9a8-16 > Connection: Keep-Alive
1b5362a9a8-16 > X-Zc-Major-Domain: seanywell
1b5362a9a8-16 > X-Zc-Msg-Name: millService
1b5362a9a8-16 > X-Zc-Sub-Domain: milltype
1b5362a9a8-16 > X-Zc-Seq-Id: 1
1b5362a9a8-16 > X-Zc-Version: 1
1b5362a9a8-16 > Content-Type: application/x-zc-object
1b5362a9a8-16 > X-Zc-Timestamp: 1643656547
1b5362a9a8-16 > X-Zc-Timeout: 300
1b5362a9a8-16 > X-Zc-Nonce: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1b5362a9a8-16 > X-Zc-User-Id: 216231
1b5362a9a8-16 > X-Zc-User-Signature: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1b5362a9a8-16 > X-Zc-Content-Length: 2
1b5362a9a8-16 > Host: eurouter.ablecloud.cn:9005
1b5362a9a8-16 > Content-Length: 2
{}
2022-01-31 20:15:47.573 [DEBUG] [llheat.internal.client.RequestLogger] - Response 1b536xxxxxxxxx
1b5362a9a8-16 < HTTP/1.1 200 OK
1b5362a9a8-16 < Content-Length: 523
1b5362a9a8-16 < Content-Type: application/x-zc-object
1b5362a9a8-16 < Server: Jetty(9.1.5.v20140505)
1b5362a9a8-16 < X-Zc-Msg-Name: X-Zc-Ack
1b5362a9a8-16 < X-Zc-Trace-Id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1b5362a9a8-16 < Date: Mon, 31 Jan 2022 19:15:47 GMT
{
  "hourSystem": 1,
  "homeList": [
    {
      "maxTemperature": 0,
      "maxTemperatureMsg": "Temperature range is limited by administrator to 5-35℃",
      "homeAlways": 0,
      "changeTemperature": 0,
      "homeName": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "isHoliday": 0,
      "postcode": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "holidayStartTime": 0,
      "timeZone": "+01:00",
      "modeMinute": 0,
      "modeStartTime": 0,
      "holidayTemp": 10,
      "modeHour": 0,
      "changeTemperatureMsg": "Temperature change not allowed by administrator",
      "currentMode": 0,
      "holidayEndTime": 0,
      "holidayTempType": 1,
      "homeType": 0,
      "homeId": xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
      "programId": xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    }
  ]
}
2022-01-31 20:15:47.577 [DEBUG] [llheat.internal.client.RequestLogger] - Request 1b536XXXXX
1b5362a9a8-17 > POST https://eurouter.ablecloud.cn:9005/millService/v1/selectRoombyHome
1b5362a9a8-17 > Accept-Encoding: gzip
1b5362a9a8-17 > User-Agent: Jetty/9.4.40.v20210413
1b5362a9a8-17 > Connection: Keep-Alive
1b5362a9a8-17 > X-Zc-Major-Domain: seanywell
1b5362a9a8-17 > X-Zc-Msg-Name: millService
1b5362a9a8-17 > X-Zc-Sub-Domain: milltype
1b5362a9a8-17 > X-Zc-Seq-Id: 1
1b5362a9a8-17 > X-Zc-Version: 1
1b5362a9a8-17 > Content-Type: application/x-zc-object
1b5362a9a8-17 > X-Zc-Timestamp: 1643656547
1b5362a9a8-17 > X-Zc-Timeout: 300
1b5362a9a8-17 > X-Zc-Nonce: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1b5362a9a8-17 > X-Zc-User-Id: 216231
1b5362a9a8-17 > X-Zc-User-Signature: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1b5362a9a8-17 > X-Zc-Content-Length: 61
1b5362a9a8-17 > Host: eurouter.ablecloud.cn:9005
1b5362a9a8-17 > Content-Length: 61
{
  "homeId": xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
  "timeZoneNum": "+01:00"
}
2022-01-31 20:15:47.681 [DEBUG] [llheat.internal.client.RequestLogger] - Response 1b536xxxxxx
1b5362a9a8-17 < HTTP/1.1 200 OK
1b5362a9a8-17 < Content-Length: 486
1b5362a9a8-17 < Content-Type: application/x-zc-object
1b5362a9a8-17 < Server: Jetty(9.1.5.v20140505)
1b5362a9a8-17 < X-Zc-Msg-Name: X-Zc-Ack
1b5362a9a8-17 < X-Zc-Trace-Id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1b5362a9a8-17 < Date: Mon, 31 Jan 2022 19:15:47 GMT
{
  "maxTemperature": 0,
  "backMinute": 0,
  "maxTemperatureMsg": "Temperature range is limited by administrator to 5-35℃",
  "homeAlways": 0,
  "changeTemperature": 0,
  "homeName": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "isHoliday": 0,
  "changeTemperatureMsg": "Temperature change not allowed by administrator",
  "backHour": 0,
  "roomInfo": [],
  "offLineDeviceNum": 0,
  "mode": 0,
  "onlineDeviceNum": 0,
  "programList": [
    {
      "programName": "Standard Program",
      "homeId": xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
      "programId": xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    }
  ],
  "homeType": 0,
  "homeId": xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
}
2022-01-31 20:15:47.686 [DEBUG] [llheat.internal.client.RequestLogger] - Request 1b5362xxxxxx
1b5362a9a8-18 > POST https://eurouter.ablecloud.cn:9005/millService/v1/getIndependentDevices
1b5362a9a8-18 > Accept-Encoding: gzip
1b5362a9a8-18 > User-Agent: Jetty/9.4.40.v20210413
1b5362a9a8-18 > Connection: Keep-Alive
1b5362a9a8-18 > X-Zc-Major-Domain: seanywell
1b5362a9a8-18 > X-Zc-Msg-Name: millService
1b5362a9a8-18 > X-Zc-Sub-Domain: milltype
1b5362a9a8-18 > X-Zc-Seq-Id: 1
1b5362a9a8-18 > X-Zc-Version: 1
1b5362a9a8-18 > Content-Type: application/x-zc-object
1b5362a9a8-18 > X-Zc-Timestamp: 1643656547
1b5362a9a8-18 > X-Zc-Timeout: 300
1b5362a9a8-18 > X-Zc-Nonce: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1b5362a9a8-18 > X-Zc-User-Id: 216231
1b5362a9a8-18 > X-Zc-User-Signature: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1b5362a9a8-18 > X-Zc-Content-Length: 34
1b5362a9a8-18 > Host: eurouter.ablecloud.cn:9005
1b5362a9a8-18 > Content-Length: 34
{
  "homeId": xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
}
2022-01-31 20:15:47.809 [DEBUG] [llheat.internal.client.RequestLogger] - Response 1b5362a9a8-18
1b5362a9a8-18 < HTTP/1.1 200 OK
1b5362a9a8-18 < Content-Length: 368
1b5362a9a8-18 < Content-Type: application/x-zc-object
1b5362a9a8-18 < Server: Jetty(9.1.5.v20140505)
1b5362a9a8-18 < X-Zc-Msg-Name: X-Zc-Ack
1b5362a9a8-18 < X-Zc-Trace-Id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1b5362a9a8-18 < Date: Mon, 31 Jan 2022 19:15:47 GMT
{
  "deviceInfo": [
    {
      "fanStatusShow": 1,
      "manualControlTime": 0,
      "isManualControl": 0,
      "isHoliday": 0,
      "description": "",
      "canChangeTemp": 1,
      "holidayTemp": 3000,
      "deviceId": 304730,
      "deviceName": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "roomId": xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
      "deviceStatus": 0,
      "timer": "",
      "heaterFlag": 0,
      "powerStatus": 0,
      "times": "",
      "fanStatus": 0,
      "subDomainId": 6979,
      "coolingStatus": 0,
      "currentTemp": 451.0,
      "open": 3
    }
  ]
}

It looks like I have the same issue, also on Openhab 3.2.0. I followed the steps described and deleted all millheat:heater and millheat:account things, and added the account again. Added items via item files, and tried setting the account and things online/offline.

The heater in question (155417) is not added to a room in the Millheat app.

I see the same result as @SmartHome4all - no channels.

Debug log looks similar, too:

2022-02-01 20:57:45.020 [DEBUG] [llheat.internal.client.RequestLogger] - Request xxx-109
b5c300cb5a-109 > POST https://eurouter.ablecloud.cn:9005/millService/v1/selectHomeList
b5c300cb5a-109 > Accept-Encoding: gzip
b5c300cb5a-109 > User-Agent: Jetty/9.4.43.v20210629
b5c300cb5a-109 > Connection: Keep-Alive
b5c300cb5a-109 > X-Zc-Major-Domain: seanywell
b5c300cb5a-109 > X-Zc-Msg-Name: millService
b5c300cb5a-109 > X-Zc-Sub-Domain: milltype
b5c300cb5a-109 > X-Zc-Seq-Id: 1
b5c300cb5a-109 > X-Zc-Version: 1
b5c300cb5a-109 > Content-Type: application/x-zc-object
b5c300cb5a-109 > X-Zc-Timestamp: 1643745465
b5c300cb5a-109 > X-Zc-Timeout: 300
b5c300cb5a-109 > X-Zc-Nonce: XXX
b5c300cb5a-109 > X-Zc-User-Id: 110030
b5c300cb5a-109 > X-Zc-User-Signature: XXX
b5c300cb5a-109 > X-Zc-Content-Length: 2
b5c300cb5a-109 > Host: eurouter.ablecloud.cn:9005
b5c300cb5a-109 > Content-Length: 2

{}
2022-02-01 20:57:45.059 [DEBUG] [llheat.internal.client.RequestLogger] - Response xxx-109
b5c300cb5a-109 < HTTP/1.1 200 OK
b5c300cb5a-109 < Content-Length: 521
b5c300cb5a-109 < Content-Type: application/x-zc-object
b5c300cb5a-109 < Server: Jetty(9.1.5.v20140505)
b5c300cb5a-109 < X-Zc-Msg-Name: X-Zc-Ack
b5c300cb5a-109 < X-Zc-Trace-Id: XXX
b5c300cb5a-109 < Date: Tue, 01 Feb 2022 19:57:45 GMT

{
  "hourSystem": 1,
  "homeList": [
    {
      "maxTemperature": 0,
      "maxTemperatureMsg": "Temperature range is limited by administrator to 5-35℃",
      "homeAlways": 0,
      "changeTemperature": 0,
      "homeName": "House",
      "isHoliday": 0,
      "postcode": "XXX",
      "holidayStartTime": 0,
      "timeZone": "+01:00",
      "modeMinute": 0,
      "modeStartTime": 0,
      "holidayTemp": 14,
      "modeHour": 0,
      "changeTemperatureMsg": "Temperature change not allowed by administrator",
      "currentMode": 0,
      "holidayEndTime": 0,
      "holidayTempType": 0,
      "homeType": 0,
      "homeId": XXX,
      "programId": XXX
    }
  ]
}
2022-02-01 20:57:45.060 [DEBUG] [llheat.internal.client.RequestLogger] - Request xxx-110
b5c300cb5a-110 > POST https://eurouter.ablecloud.cn:9005/millService/v1/selectRoombyHome
b5c300cb5a-110 > Accept-Encoding: gzip
b5c300cb5a-110 > User-Agent: Jetty/9.4.43.v20210629
b5c300cb5a-110 > Connection: Keep-Alive
b5c300cb5a-110 > X-Zc-Major-Domain: seanywell
b5c300cb5a-110 > X-Zc-Msg-Name: millService
b5c300cb5a-110 > X-Zc-Sub-Domain: milltype
b5c300cb5a-110 > X-Zc-Seq-Id: 1
b5c300cb5a-110 > X-Zc-Version: 1
b5c300cb5a-110 > Content-Type: application/x-zc-object
b5c300cb5a-110 > X-Zc-Timestamp: 1643745465
b5c300cb5a-110 > X-Zc-Timeout: 300
b5c300cb5a-110 > X-Zc-Nonce: XXX
b5c300cb5a-110 > X-Zc-User-Id: 110030
b5c300cb5a-110 > X-Zc-User-Signature: XXX
b5c300cb5a-110 > X-Zc-Content-Length: 61
b5c300cb5a-110 > Host: eurouter.ablecloud.cn:9005
b5c300cb5a-110 > Content-Length: 61

{
  "homeId": 202002231649150016,
  "timeZoneNum": "+01:00"
}
2022-02-01 20:57:45.221 [DEBUG] [llheat.internal.client.RequestLogger] - Response xxx-110
b5c300cb5a-110 < HTTP/1.1 200 OK
b5c300cb5a-110 < Content-Length: 743
b5c300cb5a-110 < Content-Type: application/x-zc-object
b5c300cb5a-110 < Server: Jetty(9.1.5.v20140505)
b5c300cb5a-110 < X-Zc-Msg-Name: X-Zc-Ack
b5c300cb5a-110 < X-Zc-Trace-Id: XXX
b5c300cb5a-110 < Date: Tue, 01 Feb 2022 19:57:45 GMT

{
  "maxTemperature": 0,
  "backMinute": 0,
  "maxTemperatureMsg": "Temperature range is limited by administrator to 5-35℃",
  "homeAlways": 0,
  "changeTemperature": 0,
  "homeName": "House",
  "isHoliday": 0,
  "changeTemperatureMsg": "Temperature change not allowed by administrator",
  "backHour": 0,
  "roomInfo": [],
  "offLineDeviceNum": 0,
  "mode": 0,
  "onlineDeviceNum": 0,
  "programList": [
    {
      "programName": "Standard Program",
      "homeId": XXX,
      "programId": XXX
    },
    {
      "programName": "Homeoffice",
      "homeId": XXX,
      "programId": XXX
    },
    {
      "programName": "Kitchen",
      "homeId": XXX,
      "programId": XXX
    },
    {
      "programName": "Lekerom",
      "homeId": XXX,
      "programId": XXX
    }
  ],
  "homeType": 0,
  "homeId": 202002231649150016
}
2022-02-01 20:57:45.224 [DEBUG] [llheat.internal.client.RequestLogger] - Request xxx-111
b5c300cb5a-111 > POST https://eurouter.ablecloud.cn:9005/millService/v1/getIndependentDevices
b5c300cb5a-111 > Accept-Encoding: gzip
b5c300cb5a-111 > User-Agent: Jetty/9.4.43.v20210629
b5c300cb5a-111 > Connection: Keep-Alive
b5c300cb5a-111 > X-Zc-Major-Domain: seanywell
b5c300cb5a-111 > X-Zc-Msg-Name: millService
b5c300cb5a-111 > X-Zc-Sub-Domain: milltype
b5c300cb5a-111 > X-Zc-Seq-Id: 1
b5c300cb5a-111 > X-Zc-Version: 1
b5c300cb5a-111 > Content-Type: application/x-zc-object
b5c300cb5a-111 > X-Zc-Timestamp: 1643745465
b5c300cb5a-111 > X-Zc-Timeout: 300
b5c300cb5a-111 > X-Zc-Nonce: XXX
b5c300cb5a-111 > X-Zc-User-Id: 110030
b5c300cb5a-111 > X-Zc-User-Signature: XXX
b5c300cb5a-111 > X-Zc-Content-Length: 34
b5c300cb5a-111 > Host: eurouter.ablecloud.cn:9005
b5c300cb5a-111 > Content-Length: 34

{
  "homeId": XXX
}
2022-02-01 20:57:45.605 [DEBUG] [llheat.internal.client.RequestLogger] - Response xxx-111
b5c300cb5a-111 < HTTP/1.1 200 OK
b5c300cb5a-111 < Content-Length: 729
b5c300cb5a-111 < Content-Type: application/x-zc-object
b5c300cb5a-111 < Server: Jetty(9.1.5.v20140505)
b5c300cb5a-111 < X-Zc-Msg-Name: X-Zc-Ack
b5c300cb5a-111 < X-Zc-Trace-Id: XXX
b5c300cb5a-111 < Date: Tue, 01 Feb 2022 19:57:45 GMT

{
  "deviceInfo": [
    {
      "fanStatusShow": 0,
      "manualControlTime": 0,
      "isManualControl": 0,
      "isHoliday": 0,
      "description": "",
      "canChangeTemp": 1,
      "holidayTemp": 22,
      "deviceId": 155417,
      "deviceName": "Kjeller",
      "roomId": XXX,
      "deviceStatus": 0,
      "timer": "",
      "heaterFlag": 1,
      "powerStatus": 1,
      "times": "",
      "fanStatus": 0,
      "subDomainId": 5316,
      "coolingStatus": 0,
      "currentTemp": 22.0,
      "open": 0
    },
    {
      "fanStatusShow": 0,
      "manualControlTime": 0,
      "isManualControl": 0,
      "isHoliday": 0,
      "description": "OFF",
      "canChangeTemp": 0,
      "holidayTemp": 21,
      "deviceId": 157618,
      "deviceName": "Kjøkken",
      "roomId": XXX,
      "deviceStatus": 0,
      "timer": "OFF in 00:32",
      "heaterFlag": 1,
      "powerStatus": 1,
      "times": "00:32",
      "fanStatus": 0,
      "subDomainId": 5316,
      "coolingStatus": 0,
      "currentTemp": 21.0,
      "open": 0
    }
  ]
}
2022-02-01 20:57:45.607 [DEBUG] [ternal.handler.MillheatHeaterHandler] - Cannot update power for heater as the nominal power has not been configured for thing millheat:heater:xxx:157618
2022-02-01 20:58:03.340 [DEBUG] [ternal.handler.MillheatHeaterHandler] - Initializing Millheat heater using config MillheatHeaterConfiguration [macAddress=null, heaterId=155417, power=null]

The thing is online and all channels, except masterSwitch and targetTemperature are available:

I did look into the code of the binding, and there is something that grabbed my attention. In MillheatHeaterHandler.java, where the heater is initialized (I believe), there is a check for canChangeTemp and no room set before adding the two channels in question:

    private void addOptionalChannels(final Heater heater) {
        final List<Channel> newChannels = new ArrayList<>();
        newChannels.addAll(getThing().getChannels());
        if (heater.canChangeTemp() && heater.getRoom() == null) {
            // Add power switch channel
            newChannels
                    .add(ChannelBuilder
                            .create(new ChannelUID(getThing().getUID(), MillheatBindingConstants.CHANNEL_MASTER_SWITCH),
                                    "Switch")
                            .withType(MillheatBindingConstants.CHANNEL_TYPE_MASTER_SWITCH_UID).build());
            // Add independent heater target temperature
            newChannels.add(ChannelBuilder
                    .create(new ChannelUID(getThing().getUID(), MillheatBindingConstants.CHANNEL_TARGET_TEMPERATURE),
                            "Number:Temperature")
                    .withType(MillheatBindingConstants.CHANNEL_TYPE_TARGET_TEMPERATURE_HEATER_UID).build());
        }

        updateThing(editThing().withChannels(newChannels).build());
    }

From the debug log, it looks like the roomId is set, despite the heater not beeing assigned to a room. If that is the case, the check above would return false, and no additional channels would be added?

Or did I miss something?

That was a red herring… I finally got around to install the dev environment and started to debug what is happening on my end.

I noticed that the Heater class is initialised with dto.holiday instead of dto.canChangeTemp in model/Heater.java:

    public Heater(final DeviceDTO dto) {
        id = dto.deviceId;
        name = dto.deviceName;
        macAddress = dto.macAddress;
        heatingActive = dto.heaterFlag;
        canChangeTemp = dto.canChangeTemp;
        subDomain = dto.subDomainId;
        currentTemp = (int) dto.currentTemp;
        setTargetTemp(dto.holidayTemp);
        setFanActive(dto.fanStatus);
        setPowerStatus(dto.powerStatus);
        windowOpen = dto.openWindow;
    }

I tried and changed this to dto.canChangeTemp and suddenly everything is working!

The two channels are available, and I can control the heater - both the master switch and temperature :smile:

I assume that the response has somehow been changed on the server side, as I can’t see that there where any code changes. I have no idea whether this will work for others, let me know if you need any more information.

@seime I can do a merge request if you prefer, but I’d rather have someone with more Java experience look into this before I do that :wink:

1 Like

I’ll have a look at it in a few weeks!

Regards

2 Likes