honestly i have a lot of doubts you can use windows contact sensor with this integration. Quite sure the official integration behaves the same (since i did not touch the update part).
As i wrote above (eQ-3 MAX! integration - #23 by MassiPi) to have a different refresh time you shoul write a proper coordinator. And it would be in any case a poll refresh, not a push from the sensors. My workaround for climate entities is to call a refresh after a command is sent, but i have no windows sensor so that’s not an issue for me (i have aqara windows sensors)
Hi,
thanks for the quick reply. I will once more read through your postings. My difficulty is to understand what you actually mean with the coordinator. Is this a term used for a specific kind of implementation of a integration?
Same for the “refresh after a command is sent”. Does this mean, that in your integration of the climate you have called a refresh command or function, after the integration has sent a command TO the cube?
Because in the case of a window contact/sensor, at least to my understanding this is not an option, because the communication is always the other way around…
Nevertheless, I will try to dig a bit deeper and maybe you will provide a response to help me to get on the right track.
BR
I think I have found what you have referred to as a refresh…
line 381 in maxcube/cube.py
#trigger an update
self.update() code here
is this correct?
The question is where is the main update function called, by whom on which cycle?
Because this seems to be the reason for not having faster update rates… in my humble opinion.
@MassiPi after reading a bit through the documentation of integrations, I believe I at least have a basic understanding, of what you are telling.
Maybe within the next days or weeks I will give it a try and put in a basic coordinator and test it.
My main misunderstanding was, that scan_interval is NOT the update_interval…
you totally got it.
The only part that is not correct of what you wrote is this:
Wrong. it SHOULD be (push and not poll). But with MAX system you can’t, because the information is sent from the sensor to the cube and the cube has no method to push the info somewhere. You can get the info later (when you refresh the cube), not just when it happens. So if you plan to use it for heating (what it is intended to be: turn down thermostats when windows are open) the cube is managing it and you can afford a “lagged” info of the sensor, but if you plan to use it for other purposes time-sensitive (alarm?) i assume you should change the system
yes, coordinator is something connected with HA integrations. The MAX integration is as old as hell and does not have a proper coordinator, for my use case it is working ok how it is today (with the custom refresh as soon as i send a cube command), but if you want to have some fun coding i’m with you lol
probably the integration would need a full rewrite (async based, for example), a lot of work and probably there are at maximun 10 guys out there still using MAX
Hi.
Thanks for the reply. The system is to my taste still good enough. I don’t want wifi or bluetooth devices to take over the job. That is totally oversized for my small setup.
My use-case is something maybe closer to the alarm. I want to count how often (and maybe long) the fridge is opened during a day. I want to correlate the data with the energy consumption of the fridge. It is more a fun “side-project” than a real life serious use-case… I admit.
Coming back to the technical aspect of our thread:
For sure the CUBE must be polled, but to my knowledge, as well as for the button, the communication is initiated by the device (and not the CUBE). That is different to sending a new temperature set value to a valve. Or am I wrong?
Anyhow, I guess I will start modifying the existing integration a bit, and maybe I am lucky. A complete rewrite is not what I am starting.
PS: HA counts 200 active installations of the original integration… there is still some hope.
i don’t trust that number: the original integration is totally bugged, noone can be using it…
for the push/poll, you are right that it is the window sensor to initiate the connection to the cube to send data, your problem is that you in any case need to poll the cube, so the fact that the sensor is pushing data to the cube for you is totally transparent. You’ll read window open only if it lasts less than your reading period.
however, if you can manage to write a coordinator, since the integration has static connection with the cube you can poll data every second or so, probably good enough for your use case
Hi, trying to install your eq-3 integration. Everything looks fine except that when I try to change a thermostat value in HA, nothing happens and after a few seconds it switches back to its original value.
Here is what I can see in the logs :
2024-09-15 11:49:50.677 DEBUG (SyncWorker_28) [custom_components.maxcube.maxcube.cube] Setting temperature 18.0 and mode 1 on device 1A7EA8! Room 0C - starting device mode 1 (command: 0004400000001A7EA80C64)
2024-09-15 11:49:50.679 DEBUG (SyncWorker_28) [custom_components.maxcube.maxcube.connection] readline timed out
2024-09-15 11:49:50.679 DEBUG (SyncWorker_28) [custom_components.maxcube.maxcube.connection] sent: s:AARAAAAAGn6oDGQ=
2024-09-15 11:49:50.835 DEBUG (SyncWorker_28) [custom_components.maxcube.maxcube.connection] received: S:00,0,31
2024-09-15 11:49:50.835 DEBUG (SyncWorker_28) [custom_components.maxcube.maxcube.commander] Radio message s:AARAAAAAGn6oDGQ= was sent [DutyCycle:00, StatusCode:0, FreeSlots:31]
2024-09-15 11:49:50.837 DEBUG (SyncWorker_28) [custom_components.maxcube.maxcube.connection] readline timed out
2024-09-15 11:49:50.838 DEBUG (SyncWorker_28) [custom_components.maxcube.maxcube.connection] sent: l:
2024-09-15 11:49:50.936 DEBUG (SyncWorker_28) [custom_components.maxcube.maxcube.connection] received: L:Cxp+QvEaGQ4oANcACxp+/0AaGVAuAOQACxp+pAMaGQ4qAOYACxqBMPEaGQAqAO4ACxp+qAMaCQAjAAAACxp+nUAaGRgqAOMACxp+pwMaGR4qAOIACxqCGwMaGQAjAAAACxp+jQMaGQAjAAAACxp/CAMaGQAmAAAACxp/A0AaGQ0oANYACxp+PwMaGRgqAOcACxp+PEAaGUUuAOoACxqCyAMaGWQuAAAACxp/GAMaGRgqAOIA
2024-09-15 11:49:50.936 DEBUG (SyncWorker_28) [custom_components.maxcube.maxcube.cube] Parsing l_message: Cxp+QvEaGQ4oANcACxp+/0AaGVAuAOQACxp+pAMaGQ4qAOYACxqBMPEaGQAqAO4ACxp+qAMaCQAjAAAACxp+nUAaGRgqAOMACxp+pwMaGR4qAOIACxqCGwMaGQAjAAAACxp+jQMaGQAjAAAACxp/CAMaGQAmAAAACxp/A0AaGQ0oANYACxp+PwMaGRgqAOcACxp+PEAaGUUuAOoACxqCyAMaGWQuAAAACxp/GAMaGRgqAOIA
How can I correct this ? Thanks
it’s strangely timeoutting on receive (i assume from error message), even then the cube is returning che correct feedback (che S: message is saying the cube received and worked the message), that’s very strange
Would you try editing in connection.py file, line 34, from this
self.__socket.settimeout(deadline.remaining(lower_bound=0.001))
to something like this (just a try)
self.__socket.settimeout(deadline.remaining(lower_bound=0.1))
or
self.__socket.settimeout(deadline.remaining(lower_bound=0.5))
0.1 or 0.5 both give the same result as 0.001
Hi, any hints on how to go more in-depth on this bug?
As i had lots of issue with official MAX! integration, i’ve made this rednode flow that works since 2 years i think.
[{"id":"fb5296f3c4de2a23","type":"subflow","name":"Create HA Helpers","info":"","category":"HA Actions","in":[{"x":84,"y":96,"wires":[{"id":"fc18bdbb57e2fd63"}]}],"out":[],"env":[{"name":"serverName","type":"str","value":"Home Assistant","ui":{"label":{"en-US":"HA Server Name"},"type":"input","opts":{"types":["str"]}}},{"name":"helpers","type":"json","value":"[]","ui":{"label":{"en-US":"Helpers"},"type":"input","opts":{"types":["json"]}}}],"meta":{},"color":"#46B1EF","status":{"x":246,"y":48,"wires":[{"id":"ea6dc8ad6d9ece17","port":0}]}},{"id":"fc18bdbb57e2fd63","type":"function","z":"fb5296f3c4de2a23","name":"process helpers","func":"const serverName = toCamelCase(env.get('serverName'));\nconst haServer = global.get(\"homeassistant\")[serverName];\nif(!haServer) {\n node.error(\"Invalid HA server name\");\n return;\n}\nconst states = haServer.states;\nconst helpers = env.get(\"helpers\");\n\nhelpers.forEach(h => {\n const entityId = `${h.type}.${h.id}`;\n if(!states[entityId]) {\n const {id, type, ...data} = h;\n const apiData = {\n entity: h,\n payload: { \n data \n }\n };\n apiData.payload.data.type = `${type}/create`;\n \n node.send(apiData);\n node.status({text: `Creating ${entityId}`});\n }\n});\n\nnode.done();\n\nfunction toCamelCase(str) {\n return str.replace(/(?:^\\w|[A-Z]|\\b\\w|\\s+)/g, (match, index) => {\n if (+match === 0) return '';\n return index === 0 ? match.toLowerCase() : match.toUpperCase();\n });\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":224,"y":96,"wires":[["2b8e82c6d93d38e5"]]},{"id":"2b8e82c6d93d38e5","type":"ha-api","z":"fb5296f3c4de2a23","name":"create helper","server":"e89e2dad.1bf6","version":1,"debugenabled":false,"protocol":"websocket","method":"get","path":"","data":"","dataType":"json","responseType":"json","outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"results"}],"x":390,"y":96,"wires":[["767624d22ee0c819"]]},{"id":"372232586f5e138f","type":"ha-api","z":"fb5296f3c4de2a23","name":"rename helper entity id","server":"e89e2dad.1bf6","version":1,"debugenabled":false,"protocol":"websocket","method":"get","path":"","data":"{\t \"type\":\"config/entity_registry/update\",\t \"entity_id\": entity.type & \".\" & payload.id,\t \"new_entity_id\": entity.type & \".\" & entity.id\t}","dataType":"jsonata","responseType":"json","outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"results"}],"x":788,"y":96,"wires":[[]]},{"id":"767624d22ee0c819","type":"switch","z":"fb5296f3c4de2a23","name":"need to rename?","property":"payload.id","propertyType":"msg","rules":[{"t":"neq","v":"entity.id","vt":"msg"}],"checkall":"true","repair":false,"outputs":1,"x":570,"y":96,"wires":[["372232586f5e138f","815fe31e9d239e53"]]},{"id":"ea6dc8ad6d9ece17","type":"status","z":"fb5296f3c4de2a23","name":"","scope":["fc18bdbb57e2fd63","815fe31e9d239e53"],"x":124,"y":48,"wires":[[]]},{"id":"815fe31e9d239e53","type":"function","z":"fb5296f3c4de2a23","name":"rename status","func":"const oldEntityId = `${msg.entity.type}.${msg.payload.id}`;\nconst newEntityId = `${msg.entity.type}.${msg.entity.id}`;\n\nnode.status({text: `Renaming ${oldEntityId} to ${newEntityId}`});","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":768,"y":144,"wires":[[]]},{"id":"bae136fa5a77790e","type":"subflow","name":"On Restart","info":"","category":"","in":[],"out":[{"x":320,"y":320,"wires":[{"id":"c67631f89e6451f4","port":0}]}],"env":[],"meta":{},"color":"#DDAA99"},{"id":"4a91394f75614da1","type":"server-events","z":"bae136fa5a77790e","name":"","server":"e89e2dad.1bf6","version":3,"exposeAsEntityConfig":"","eventType":"home_assistant_client","eventData":"","waitForRunning":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"eventData"}],"x":140,"y":220,"wires":[["95e9d47ed2be5007"]]},{"id":"95e9d47ed2be5007","type":"switch","z":"bae136fa5a77790e","name":"running?","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"running","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":352,"y":220,"wires":[["4b7a32290de02cf7"]]},{"id":"648dd9ac108befdc","type":"api-call-service","z":"bae136fa5a77790e","name":"","server":"e89e2dad.1bf6","version":5,"debugenabled":false,"domain":"input_boolean","service":"turn_off","areaId":[],"deviceId":[],"entityId":["input_boolean.home_assistant_restarted"],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":758,"y":220,"wires":[["3754cbf709193071"]]},{"id":"4b7a32290de02cf7","type":"api-current-state","z":"bae136fa5a77790e","name":"has restarted?","server":"e89e2dad.1bf6","version":3,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_boolean.home_assistant_restarted","state_type":"str","blockInputOverrides":false,"outputProperties":[],"for":0,"forType":"num","forUnits":"minutes","x":516,"y":220,"wires":[["648dd9ac108befdc"],[]]},{"id":"f89ae68a99bb4e65","type":"server-state-changed","z":"bae136fa5a77790e","name":"restarted?","server":"e89e2dad.1bf6","version":5,"outputs":2,"exposeAsEntityConfig":"","entityId":"input_boolean.home_assistant_restarted","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"on","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":false,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[],"x":528,"y":268,"wires":[["648dd9ac108befdc"],[]]},{"id":"b5993f580d9eb5b8","type":"comment","z":"bae136fa5a77790e","name":"Home Assistant Restarted","info":"","x":130,"y":124,"wires":[]},{"id":"3754cbf709193071","type":"link out","z":"bae136fa5a77790e","name":"Home Assistant Restarted","links":["c67631f89e6451f4"],"x":1010,"y":220,"wires":[],"l":true},{"id":"c67631f89e6451f4","type":"link in","z":"bae136fa5a77790e","name":"Home Assistant Restarted","links":["3754cbf709193071"],"x":130,"y":316,"wires":[[]],"l":true},{"id":"bcfea616e335904d","type":"inject","z":"bae136fa5a77790e","name":"Click to create","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":106,"y":172,"wires":[["447721875af4431a","5a92fd8241edd308"]]},{"id":"447721875af4431a","type":"ha-api","z":"bae136fa5a77790e","name":"HA automation","server":"e89e2dad.1bf6","version":1,"debugenabled":false,"protocol":"http","method":"post","path":"/api/config/automation/config/nrrestartnotification","data":"{\t \"alias\": \"Home Assistant Restart\",\t \"description\": \"\",\t \"trigger\": [\t {\t \"platform\": \"homeassistant\",\t \"event\": \"start\" \t } \t ],\t \"condition\": [],\t \"action\": [\t {\t \"service\": \"input_boolean.turn_on\",\t \"data\": {\t \"entity_id\": \"input_boolean.home_assistant_restarted\" \t }\t } \t ],\t \"mode\": \"single\" \t}","dataType":"jsonata","responseType":"json","outputProperties":[],"x":372,"y":124,"wires":[[]]},{"id":"5a92fd8241edd308","type":"subflow:fb5296f3c4de2a23","z":"bae136fa5a77790e","name":"","env":[{"name":"serverName","value":"Home Assistant Working","type":"str"},{"name":"helpers","value":"[{\"id\":\"home_assistant_restarted\",\"type\":\"input_boolean\",\"name\":\"Home Assistant Restarted\",\"icon\":\"mdi:restart-alert\"}]","type":"json"}],"x":382,"y":172,"wires":[]},{"id":"e89e2dad.1bf6","type":"server","name":"Home Assistant Working","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","entitySelector":"id","statusSeparator":"","enableGlobalContextStore":false},{"id":"103b1fd4c70bd5ad","type":"tab","label":"Max! 2 MQTT","disabled":false,"info":"","env":[]},{"id":"fd3ce805ed926c80","type":"inject","z":"103b1fd4c70bd5ad","name":"timer","props":[{"p":"reason","v":"repeat","vt":"str"}],"repeat":"30","crontab":"","once":true,"onceDelay":"1","topic":"","x":90,"y":540,"wires":[["248a31587c7960fe"]]},{"id":"7b8330524ea2f4c4","type":"mqtt out","z":"103b1fd4c70bd5ad","name":"mqtt boiler","topic":"tasmota/chaudiere/cmnd/POWER","qos":"0","retain":"false","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"d7efe4ef4af81eb9","x":770,"y":360,"wires":[]},{"id":"9fabcb15eb75a432","type":"function","z":"103b1fd4c70bd5ad","name":"compute action","func":"var res = {};\nvar miss = 0;\nfor (const [key, value] of Object.entries(msg.payload)) {\n if (value.device_type == 3) {\n name = value.room_name.replace(\" \", \"_\");// + \"_\" + value.device_name.replace(\" \", \"_\");\n if (value.temp < value.setpoint) {\n if (value.room_name != 'WC')\n miss += value.setpoint - value.temp;\n }\n res[name] = { \"status\": \"off\" };\n }\n}\n\nvar action = null;\nif (miss <= 0.5) {\n action = 'OFF';\n}\nif (miss >= 1.2) {\n action = 'ON';\n for (const [key, value] of Object.entries(msg.payload)) {\n if (value.device_type == 3) {\n name = value.room_name.replace(\" \", \"_\");// + \"_\" + value.device_name.replace(\" \", \"_\")\n if (value.temp < value.setpoint && value.room_name != 'WC') {\n status = 'heat';\n } else {\n status = 'off';\n }\n res[name] = { \"status\": status };\n }\n }\n}\nreturn [ { 'payload': action, 'heat': miss }, { \"payload\": res } ];","outputs":2,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":460,"wires":[["7b8330524ea2f4c4","87831a7d8384ba61","eaa0ef6ec5828c4b"],["f1d30ee021d42cf6"]]},{"id":"3355f9d8134bb8d5","type":"split","z":"103b1fd4c70bd5ad","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":630,"y":580,"wires":[["d09de1b4a1e90b50"]]},{"id":"2ebfae9701dd6b68","type":"function","z":"103b1fd4c70bd5ad","name":"decode","func":"var res = {};\nfor (const [key, value] of Object.entries(msg.payload)) {\n if (value.device_type) {\n name = value.room_name.replace(\" \", \"_\") + \"_\" + value.device_name.replace(\" \", \"_\");\n if (!(value.device_type in res))\n res[value.device_type] = {};\n res[value.device_type][name] = value;\n }\n}\nreturn [ { \"payload\": res[1] }, { \"payload\": res[3] }, { \"payload\": res[4] }, res ];","outputs":4,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":600,"wires":[["f3a618cb9b217476"],["3355f9d8134bb8d5"],["da37c30786c72470"],[]]},{"id":"f1d30ee021d42cf6","type":"split","z":"103b1fd4c70bd5ad","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":630,"y":480,"wires":[["835b0a70c0092e13"]]},{"id":"835b0a70c0092e13","type":"function","z":"103b1fd4c70bd5ad","name":"thermostat state","func":"msg.topic = 'maxcube2mqtt/thermostat/' + msg.parts.key;\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":780,"y":480,"wires":[["f855b4166b9fe922"]]},{"id":"f3a618cb9b217476","type":"split","z":"103b1fd4c70bd5ad","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":630,"y":540,"wires":[["221d232e309d8974"]]},{"id":"da37c30786c72470","type":"split","z":"103b1fd4c70bd5ad","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":630,"y":620,"wires":[["b64957542172ae46"]]},{"id":"87831a7d8384ba61","type":"function","z":"103b1fd4c70bd5ad","name":"boiler total","func":"var msgo = {};\nmsgo.payload = msg;\nmsgo.payload.heat = msgo.payload.heat.toFixed(1)\nmsgo.topic = 'homeassistant/sensor/maxcube_heat';\nmsgo.payload.config = {}\nmsgo.payload.config[\"~\"] = msgo.topic;\nmsgo.payload.config[\"uniq_id\"] = \"maxcube_heat\";\nmsgo.payload.config[\"name\"] = \"Chaudière Total\";\nmsgo.payload.config[\"state_topic\"] = \"~/heat\";\nmsgo.payload.config[\"unit_of_measurement\"] = \"°\";\nreturn msgo;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":440,"wires":[["f855b4166b9fe922"]]},{"id":"9288a4f985382537","type":"mqtt out","z":"103b1fd4c70bd5ad","name":"mqtt","topic":"","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"d7efe4ef4af81eb9","x":1190,"y":440,"wires":[]},{"id":"f855b4166b9fe922","type":"split","z":"103b1fd4c70bd5ad","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"key","x":950,"y":440,"wires":[["9f45cc50a1240208"]]},{"id":"9f45cc50a1240208","type":"function","z":"103b1fd4c70bd5ad","name":"suffix","func":"msg.topic = msg.topic + '/' + msg.key;\ndelete msg.key;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1070,"y":440,"wires":[["9288a4f985382537"]]},{"id":"29949c9d2834f922","type":"comment","z":"103b1fd4c70bd5ad","name":"boiler","info":"boiler management.\nCompute total of missing degrees in each room and turn on the boiler if needed.","x":410,"y":420,"wires":[]},{"id":"af681e641dcfc3b7","type":"comment","z":"103b1fd4c70bd5ad","name":"mqtt receive","info":"send/receive to mqtt","x":430,"y":540,"wires":[]},{"id":"248a31587c7960fe","type":"maxcube out","z":"103b1fd4c70bd5ad","server":"9a07e5adcaeb56f7","singleMessage":true,"x":220,"y":540,"wires":[["9fabcb15eb75a432","2ebfae9701dd6b68"]]},{"id":"eaa0ef6ec5828c4b","type":"function","z":"103b1fd4c70bd5ad","name":"boiler state","func":"msg.payload = 'OFF';\nif (msg.payload == null)\n return null;\nvar msgo = {};\nmsgo.payload = {};\nmsgo.topic = 'homeassistant/binary_sensor/maxcube_state';\nmsgo.payload.state = msg.payload;\nmsgo.payload.config = {}\nmsgo.payload.config[\"~\"] = msgo.topic;\nmsgo.payload.config[\"uniq_id\"] = \"maxcube_state\";\nmsgo.payload.config[\"name\"] = \"Chaudière État\";\nmsgo.payload.config[\"state_topic\"] = \"~/state\";\nreturn msgo;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":400,"wires":[["f855b4166b9fe922"]]},{"id":"d09de1b4a1e90b50","type":"function","z":"103b1fd4c70bd5ad","name":"thermostat","func":"msg.topic = 'maxcube2mqtt/thermostat/' + msg.payload.room_name.replace(\" \", \"_\");\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":580,"wires":[["5ba40e51ea31021b"]]},{"id":"221d232e309d8974","type":"function","z":"103b1fd4c70bd5ad","name":"valve","func":"msg.topic = 'maxcube2mqtt/valve/' + msg.payload.room_name.replace(\" \", \"_\") + \"_\" + msg.payload.device_name.replace(\" \", \"_\");\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":750,"y":540,"wires":[["5ba40e51ea31021b"]]},{"id":"5ba40e51ea31021b","type":"split","z":"103b1fd4c70bd5ad","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"key","x":910,"y":580,"wires":[["f834c4de1ba53a86"]]},{"id":"f834c4de1ba53a86","type":"function","z":"103b1fd4c70bd5ad","name":"suffix","func":"msg.topic = msg.topic + '/' + msg.key;\ndelete msg.key;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1030,"y":580,"wires":[["efcb1347e477233d"]]},{"id":"b64957542172ae46","type":"function","z":"103b1fd4c70bd5ad","name":"window","func":"msg.topic = 'maxcube2mqtt/window/' + msg.payload.room_name.replace(\" \", \"_\") + \" / \" + msg.payload.device_name.replace(\" \", \"_\");\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":760,"y":620,"wires":[["5ba40e51ea31021b"]]},{"id":"3d2761b7773ae8d5","type":"inject","z":"103b1fd4c70bd5ad","name":"on start","props":[{"p":"reason","v":"start","vt":"str"}],"repeat":"3600","crontab":"","once":true,"onceDelay":"1","topic":"","x":160,"y":60,"wires":[["554700ca0a7b0288"]]},{"id":"554700ca0a7b0288","type":"maxcube out","z":"103b1fd4c70bd5ad","server":"9a07e5adcaeb56f7","singleMessage":true,"x":320,"y":60,"wires":[["262018a32e7e029b"]]},{"id":"262018a32e7e029b","type":"function","z":"103b1fd4c70bd5ad","name":"decode","func":"var res = {};\nfor (const [key, value] of Object.entries(msg.payload)) {\n if (value.device_type) {\n name = value.room_name.replace(\" \", \"_\") + \"_\" + value.device_name.replace(\" \", \"_\");\n if (!(value.device_type in res))\n res[value.device_type] = {};\n res[value.device_type][name] = value;\n }\n}\nreturn [ { \"payload\": res[1] }, { \"payload\": res[3] }, { \"payload\": res[4] }, res ];","outputs":4,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":60,"wires":[["45a48dfb50ec27a3"],["cf5b45a47dc5be43"],["1e0f3bbea406afcd"],[]]},{"id":"45a48dfb50ec27a3","type":"split","z":"103b1fd4c70bd5ad","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":650,"y":60,"wires":[["c4bef775bb3de4a4","3ec8ad146c23b99e"]]},{"id":"c4bef775bb3de4a4","type":"function","z":"103b1fd4c70bd5ad","name":"valve","func":"var res = {}\nres.topic = 'homeassistant/climate/' + msg.payload.room_name.replace(\" \", \"_\") + \"-\" + msg.payload.device_name.replace(\" \", \"_\") + '/config';\nres.payload = {}\nres.payload[\"~\"] = 'maxcube2mqtt/valve/' + msg.payload.room_name.replace(\" \", \"_\") + \"_\" + msg.payload.device_name.replace(\" \", \"_\");\nres.payload[\"unique_id\"] = \"maxcube_valve_\" + msg.parts.key.replace(\" \", \"_\");\nres.payload[\"name\"] = \"Valve \" + msg.payload.room_name + \" / \" + msg.payload.device_name;\nres.payload[\"temp_cmd_t\"] = \"~/setpoint/set\";\nres.payload[\"temp_stat_t\"] = \"~/setpoint\";\nres.payload[\"curr_temp_t\"] = \"~/temp\";\nres.payload[\"min_temp\"] = \"12\";\nres.payload[\"max_temp\"] = \"25\";\nres.payload[\"temp_step\"] = \"0.5\";\nres.payload[\"device\"] = {};\nres.payload.device[\"manufacturer\"] = \"ELV\";\nres.payload.device[\"model\"] = \"valve\";\nres.payload.device[\"name\"] = res.payload[\"name\"];\nres.payload.device[\"identifiers\"] = [ \"maxcube_\" + msg.payload.rf_address];\n// res.payload.device[\"connections\"] = [ [ \"mac\", msg.payload.rf_address ] ];\n// res.payload[\"origin\"] = {};\n// res.payload.origin[\"name\"] = \"maxcube\";\nreturn res;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":60,"wires":[["3c3e46d6fee1be7b"]]},{"id":"3c3e46d6fee1be7b","type":"mqtt out","z":"103b1fd4c70bd5ad","name":"mqtt","topic":"","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"d7efe4ef4af81eb9","x":1010,"y":60,"wires":[]},{"id":"3ec8ad146c23b99e","type":"function","z":"103b1fd4c70bd5ad","name":"valve bat","func":"var res = {}\nres.topic = 'homeassistant/sensor/' + msg.payload.room_name.replace(\" \", \"_\") + \"-\" + msg.payload.device_name.replace(\" \", \"_\") + \"_battery/config\";\nres.payload = {}\nres.payload[\"~\"] = 'maxcube2mqtt/valve/' + msg.payload.room_name.replace(\" \", \"_\") + \"_\" + msg.payload.device_name.replace(\" \", \"_\");\nres.payload[\"uniq_id\"] = \"maxcube_\" + msg.parts.key.replace(\" \", \"_\") + \"_battery\";\nres.payload[\"name\"] = \"Valve \" + msg.payload.room_name + \" / \" + msg.payload.device_name + \" Battery\";\nres.payload[\"device_class\"] = \"battery\";\nres.payload[\"entity_category\"] = \"diagnostic\";\nres.payload[\"state_class\"] = \"measurement\";\nres.payload[\"state_topic\"] = \"~/battery_low\";\nres.payload[\"unit_of_measurement\"] = \"%\";\nres.payload[\"value_template\"] = '{{ 0 if value == \"true\" else 100 }}';\nres.payload[\"device\"] = {};\nres.payload.device[\"manufacturer\"] = \"ELV\";\nres.payload.device[\"model\"] = \"valve\";\nres.payload.device[\"name\"] = res.payload[\"name\"];\nres.payload.device[\"identifiers\"] = [ \"maxcube_\" + msg.payload.rf_address];\nreturn res;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":780,"y":100,"wires":[["3c3e46d6fee1be7b"]]},{"id":"6ad662a6b39283fa","type":"function","z":"103b1fd4c70bd5ad","name":"thermostat ","func":"var res = {}\nres.topic = 'homeassistant/climate/' + msg.payload.room_name.replace(\" \", \"_\") + \"/config\";\nres.payload = {}\nres.payload[\"~\"] = 'maxcube2mqtt/thermostat/' + msg.payload.room_name.replace(\" \", \"_\");\nres.payload[\"uniq_id\"] = \"maxcube_\" + msg.payload.room_name.replace(\" \", \"_\");\nres.payload[\"name\"] = \"Thermostat \" + msg.payload.room_name;\nres.payload[\"modes\"] = [ \"heat\", \"off\" ]\nres.payload[\"mode_state_topic\"] = \"~/status\";\nres.payload[\"temp_cmd_t\"] = \"~/setpoint/set\";\nres.payload[\"temp_stat_t\"] = \"~/setpoint\";\nres.payload[\"curr_temp_t\"] = \"~/temp\";\nres.payload[\"min_temp\"] = \"12\";\nres.payload[\"max_temp\"] = \"25\";\nres.payload[\"temp_step\"] = \"0.5\";\nres.payload[\"preset_modes\"] = [ \"AUTO\", \"MANUAL\", \"BOOST\" ];\nres.payload[\"preset_mode_command_topic\"] = \"~/mode/set\";\nres.payload[\"preset_mode_state_topic\"] = \"~/mode\";\nres.payload[\"device\"] = {};\nres.payload.device[\"manufacturer\"] = \"ELV\";\nres.payload.device[\"model\"] = \"thermostat\";\nres.payload.device[\"name\"] = res.payload[\"name\"];\nres.payload.device[\"identifiers\"] = [ \"maxcube_\" + msg.payload.rf_address];\nreturn res;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":790,"y":140,"wires":[["3c3e46d6fee1be7b"]]},{"id":"794a0609769ac85c","type":"function","z":"103b1fd4c70bd5ad","name":"thermostat bat ","func":"var res = {}\nres.topic = 'homeassistant/sensor/' + msg.parts.key.replace(\" \", \"_\") + \"_battery/config\";\nres.payload = {}\nres.payload = {}\nres.payload[\"~\"] = 'maxcube2mqtt/thermostat/' + msg.payload.room_name.replace(\" \", \"_\");\nres.payload[\"uniq_id\"] = \"maxcube_\" + msg.parts.key.replace(\" \", \"_\") + \"_battery\";\nres.payload[\"name\"] = \"Thermostat \" + msg.payload.room_name + \" / \" + msg.payload.device_name + \" Battery\";\nres.payload[\"device_class\"] = \"battery\";\nres.payload[\"entity_category\"] = \"diagnostic\";\nres.payload[\"state_class\"] = \"measurement\";\nres.payload[\"state_topic\"] = \"~/battery_low\";\nres.payload[\"unit_of_measurement\"] = \"%\";\nres.payload[\"value_template\"] = '{{ 0 if value == \"true\" else 100 }}';\nres.payload[\"device\"] = {};\nres.payload.device[\"manufacturer\"] = \"ELV\";\nres.payload.device[\"model\"] = \"thermostat\";\nres.payload.device[\"name\"] = res.payload[\"name\"];\nres.payload.device[\"identifiers\"] = [ \"maxcube_\" + msg.payload.rf_address];\nreturn res;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":800,"y":180,"wires":[["3c3e46d6fee1be7b"]]},{"id":"cf5b45a47dc5be43","type":"split","z":"103b1fd4c70bd5ad","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":650,"y":140,"wires":[["6ad662a6b39283fa","794a0609769ac85c"]]},{"id":"1e3df1f548625467","type":"comment","z":"103b1fd4c70bd5ad","name":"HA discovery","info":"boiler management.\nCompute total of missing degrees in each room and turn on the boiler if needed.","x":330,"y":20,"wires":[]},{"id":"b215271d477e76a1","type":"function","z":"103b1fd4c70bd5ad","name":"window","func":"var res = {};\nres.topic = 'homeassistant/binary_sensor/' + msg.parts.key.replace(\" \", \"_\") + '/config';\nres.payload = {}\nres.payload[\"~\"] = 'maxcube2mqtt/window/' + msg.payload.room_name.replace(\" \", \"_\");\nres.payload[\"uniq_id\"] = \"maxcube_\" + msg.parts.key.replace(\" \", \"_\");\nres.payload[\"name\"] = \"Contact \" + msg.payload.room_name + \" / \" + msg.payload.device_name;\nres.payload[\"state_topic\"] = \"~/open\";\nres.payload[\"device_class\"] = \"window\";\nres.payload[\"payload_off\"] = \"false\";\nres.payload[\"payload_on\"] = \"true\";\nreturn res;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":780,"y":220,"wires":[["3c3e46d6fee1be7b"]]},{"id":"b022f80ec1f025d0","type":"function","z":"103b1fd4c70bd5ad","name":"window bat","func":"var res = {}\nres.topic = 'homeassistant/sensor/' + msg.parts.key.replace(\" \", \"_\") + \"_battery/config\";\nres.payload = {}\nres.payload[\"~\"] = 'maxcube2mqtt/window/' + msg.payload.room_name.replace(\" \", \"_\");\nres.payload[\"uniq_id\"] = \"maxcube_\" + msg.parts.key.replace(\" \", \"_\") + \"_battery\";\nres.payload[\"name\"] = \"Contact \" + msg.payload.room_name + \" / \" + msg.payload.device_name + \" Battery\";\nres.payload[\"device_class\"] = \"battery\";\nres.payload[\"entity_category\"] = \"diagnostic\";\nres.payload[\"state_class\"] = \"measurement\";\nres.payload[\"state_topic\"] = \"~/battery_low\";\nres.payload[\"unit_of_measurement\"] = \"%\";\nres.payload[\"value_template\"] = '{{ 0 if value == \"true\" else 100 }}';\nreturn res;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":790,"y":260,"wires":[["3c3e46d6fee1be7b"]]},{"id":"1e0f3bbea406afcd","type":"split","z":"103b1fd4c70bd5ad","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":650,"y":220,"wires":[["b215271d477e76a1","b022f80ec1f025d0"]]},{"id":"efcb1347e477233d","type":"mqtt out","z":"103b1fd4c70bd5ad","name":"mqtt","topic":"","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"d7efe4ef4af81eb9","x":1150,"y":580,"wires":[]},{"id":"3d3e1fea5d7df796","type":"function","z":"103b1fd4c70bd5ad","name":"decode","func":"var res = {};\nfor (const [key, value] of Object.entries(msg.payload)) {\n if (value.device_type) {\n name = value.room_name.replace(\" \", \"_\") + \"_\" + value.device_name.replace(\" \", \"_\");\n if (!(value.device_type in res))\n res[value.device_type] = {};\n res[value.device_type][name] = value;\n }\n}\nreturn [ { \"payload\": res[1] }, { \"payload\": res[3] }, { \"payload\": res[4] }, res ];","outputs":4,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":780,"wires":[[],["f9b774ccf31a5c1f"],[],[]]},{"id":"dca227a30d266fdf","type":"comment","z":"103b1fd4c70bd5ad","name":"mqtt send","info":"send/receive to mqtt","x":420,"y":720,"wires":[]},{"id":"f9b774ccf31a5c1f","type":"split","z":"103b1fd4c70bd5ad","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":590,"y":780,"wires":[["8d6bf2e8cf66f9fb"]]},{"id":"4d772a73d166d0d8","type":"mqtt in","z":"103b1fd4c70bd5ad","name":"","topic":"","qos":"2","datatype":"auto","broker":"d7efe4ef4af81eb9","nl":false,"rap":true,"rh":0,"inputs":1,"x":850,"y":780,"wires":[["b06952c575c8a5a6"]]},{"id":"8d6bf2e8cf66f9fb","type":"function","z":"103b1fd4c70bd5ad","name":"subscribe","func":"var msgo = {}\nmsgo.action = 'subscribe'\nmsgo.topic = 'maxcube2mqtt/thermostat/' + msg.payload.room_name.replace(\" \", \"_\") + \"/setpoint/set\";\nvar persist = flow.get('persist', 'file');\nif (typeof persist == 'undefined') {\n persist = {};\n}\npersist[msgo.topic] = msg.payload.rf_address;\nflow.set('persist', persist, 'file');\nreturn msgo;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":720,"y":780,"wires":[["4d772a73d166d0d8"]]},{"id":"b06952c575c8a5a6","type":"function","z":"103b1fd4c70bd5ad","name":"get_rfaddress","func":"var persist = flow.get('persist', 'file');\nreturn { \"payload\": { \"rf_address\": persist[msg.topic], \"degrees\": parseFloat(msg.payload), \"mode\": \"MANUAL\" } };","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1000,"y":780,"wires":[["1b8a19e60d1941d5"]]},{"id":"b6d09b6a82b25db2","type":"delay","z":"103b1fd4c70bd5ad","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":1300,"y":780,"wires":[["248a31587c7960fe"]]},{"id":"1b8a19e60d1941d5","type":"maxcube in","z":"103b1fd4c70bd5ad","server":"9a07e5adcaeb56f7","x":1160,"y":780,"wires":[["b6d09b6a82b25db2"]]},{"id":"7897f3ffd2481dcc","type":"inject","z":"103b1fd4c70bd5ad","name":"on start","props":[],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","x":120,"y":780,"wires":[["d0d37f63eb3c771c"]]},{"id":"d0d37f63eb3c771c","type":"maxcube out","z":"103b1fd4c70bd5ad","server":"9a07e5adcaeb56f7","singleMessage":true,"x":260,"y":780,"wires":[["3d3e1fea5d7df796"]]},{"id":"1201580fe85fe424","type":"subflow:bae136fa5a77790e","z":"103b1fd4c70bd5ad","name":"","x":160,"y":100,"wires":[["554700ca0a7b0288"]]},{"id":"d7efe4ef4af81eb9","type":"mqtt-broker","name":"MQTT","broker":"10.68.69.5","port":"1883","clientid":"nodered","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"nodered/status","birthQos":"0","birthRetain":"true","birthPayload":"online","birthMsg":{},"closeTopic":"nodered/status","closeQos":"0","closeRetain":"true","closePayload":"offline","closeMsg":{},"willTopic":"nodered/status","willQos":"0","willRetain":"true","willPayload":"timeout","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"9a07e5adcaeb56f7","type":"maxcube-server","host":"10.68.69.120","port":"62910","disabled":false}]
i noticed i also have those “timeout” in debug info, but it does not impact on system functioning.
Can i ask how your system is setup? what devices do you have (i.e. eco button? window contac? because i do not have them…)
more than this, the system never updates values or it just does not accept commands?
Thanks for your reply.
I don’t have any eco buttons nor window contacts. Only thermostatic valves (around 13 or 14 in my setup, I don’t remember exactly)
When I try to change the value, the thermostat in home assistant stays with the value I ask a few moments and then comes back to its original value. The thermostatic valve never changes.
so you do not have wall thermostats, only radiator thermostats?
well this is a difference from my setup, but it should not impact…
i have not understood if when you start home assistant (for example) the values from valve are collected correctly or not (i mean, can you see temperature, setpoint and all the rest for all rooms?)
have you tried changing something at cube level (it should change all home)
my problem in helping you is that i can’t reproduce the issue, afaik it can be linked to some “strange” config in your setup…
Yes all the values are correctly collected (almost, sometimes the cube can’t reach the furthest valves, so it comes and leaves). Changing at cube level has no effect either…
Sorry to come back here but, hey, winter is coming
I tried different debug settings but really can’t understand why it’s working okay from the valves/cube to HA, but changes in HA have no effect on the valves.
Any hints on how I could investigate more in depth?
Yours
this is not something i can reproduce (i do not have any issue), so i can’t help further if not suggestin a hard reset of the cube itself.
This means you need to set up everything up again from scratch, but this would not be the first time the cube has a strange behavior that can be fixed only with a reset…
The only other difference is that i also have wall thermostat, but i can easily change config on single radiator thermostat so…
Hey, im a bit late to the game, but acutally im switching everything (whats possible) from homebridge to ha.
Now im running in a strange problem.
I created 2 scenes, one sets the 4 of my 6 radiators to 20 degrees, and the other one switches them off.
The 20 degrees scene changes values itself. Suddenly heating mode is on auto, originally was heating, and the preset mode is comfort, was none.
So the thermostats seem to switch modes/presets themselves.
Any idea? Do you need logs? Do i need an exorcism for the thermostats?
Edit: iirc i did not have this while using homebridge scenes
nothing is changing the mode if not you. The preset mode is comfort only if your devices are configured with that temperature as comfort.
i have automations turning my thermostats from heating to off to auto when i open and close windows and doors, with schedules and leaving home or coming back, and they never decide what to do by themselves. just check what you are setting