MBTEK Apollo (MC6) Thermostat

Thermostat Integration in Home Assistant for MBTEK Apollo (MC6)

Step-by-Step Guide

This guide assists in integrating the MBTEK Apollo thermostat (which is an MC6 under the hood) with Home Assistant. The MBTEK Apollo should have the right firmware out of the box. By following these steps, you will set up a virtual MQTT thermostat to talk to the modbus interface on the thermostat.

Also consult mc6 thread: MC6 Thermostat
And my code is based on this defunct guide: Termostato MC6 – Integración en Home Assistant – Domaray

Putting the Thermostat into Modbus Mode

To integrate the MBTEK Apollo thermostat with Home Assistant, you need to enable Modbus mode. Follow these steps to activate Modbus mode on the MC6 thermostat:

  1. Configure Modbus on Apollo:

    • Go to the thermostat’s display.
    • Navigate to the settings menu (gear icon).
    • Select “access level”
  2. Unlock the Communications Config Screen:

    • Click on “Screen Lock.”
    • Enter the code 3036.
    • Click on the lock icon to unlock the screen.
  3. Enable Modbus TCP:

    • Select “WiFi Modbus TCP.”
    • An information screen will appear, and the relay will begin to activate and deactivate.
    • Click “Exit,” and the device will restart.
  4. Configure Network Settings:

    • After the device restarts, go back to the Settings menu.
    • Click on “Network settings.”
    • Fill in the following fields:
      • AP SSID: Enter the SSID of your WiFi router.
      • AP Password: Enter the password for your WiFi.
      • Gateway: Enter your router’s IP address.
      • NetMask: Enter the network mask.
      • IP: Assign a static IP address to your MC6 thermostat.
      • Port: Set to 502 (default Modbus port).
  5. Save and Restart:

    • Save the settings and allow the thermostat to restart.

Note: Activating Modbus will disable the mobile app functionality of the thermostat.

Install the Mosquitto MQTT Add-on

  1. Navigate to the Supervisor tab in Home Assistant.
  2. Click on the Add-on Store.
  3. Search for “Mosquitto broker” and install it.
  4. Start the Mosquitto broker after installation.

Enable Modbus Add-on in Node-RED

Ensure the Modbus add-on is enabled in Node-RED:

  1. Go to the Node-RED add-on in Home Assistant.
  2. Start Node-RED and go to the Palette Manager.
  3. Search for “node-red-contrib-modbus” and install it.

Import Node-RED Flow

  1. Go to the Node-RED interface.
  2. Click on the hamburger menu (three horizontal lines) and select Import.
  3. Paste the following Node-RED flow and click Import:
[{"id":"c7ae10d2.116ce","type":"mqtt out","z":"56deb452.46025c","name":"Get Current Temperature","topic":"home/termostato/current_temperature/state","qos":"0","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"99ab3ff6.4455d","x":1750,"y":432,"wires":[]},{"id":"64a0672c.6b54c8","type":"mqtt in","z":"56deb452.46025c","name":"Set Temperature Setpoint","topic":"home/termostato/temperature_setpoint/set","qos":"0","datatype":"auto-detect","broker":"99ab3ff6.4455d","nl":false,"rap":false,"inputs":0,"x":1330,"y":1240,"wires":[["13520fdf.ee69a"]]},{"id":"967c846b.4ec788","type":"modbus-write","z":"56deb452.46025c","name":"Set Temperature Setpoint","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"","dataType":"MHoldingRegisters","adr":"64","quantity":"1","server":"36e9f5f4.01499a","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":2070,"y":1240,"wires":[[],[]]},{"id":"a4fd90ac.9d17b","type":"mqtt out","z":"56deb452.46025c","name":"Get Temperature Setpoint","topic":"home/termostato/temperature_setpoint/state","qos":"0","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"99ab3ff6.4455d","x":1750,"y":592,"wires":[]},{"id":"582f3cd6.0433b4","type":"json","z":"56deb452.46025c","name":"","property":"payload","action":"","pretty":false,"x":1870,"y":1240,"wires":[["967c846b.4ec788"]]},{"id":"13520fdf.ee69a","type":"function","z":"56deb452.46025c","name":"","func":"msg.payload*=10;\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1560,"y":1240,"wires":[["bf5397e8.9daf18"]]},{"id":"bf5397e8.9daf18","type":"template","z":"56deb452.46025c","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"[{{ payload }}]","output":"str","x":1720,"y":1240,"wires":[["582f3cd6.0433b4"]]},{"id":"93c8a67f.ff0818","type":"mqtt out","z":"56deb452.46025c","name":"Get Current Mode","topic":"home/termostato/mode/mode","qos":"0","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"99ab3ff6.4455d","x":2010,"y":660,"wires":[]},{"id":"cbde474c.988668","type":"mqtt out","z":"56deb452.46025c","name":"Get Current Mode","topic":"home/termostato/status/state","qos":"0","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"99ab3ff6.4455d","x":1730,"y":700,"wires":[]},{"id":"1e7e7c1a.ced034","type":"mqtt out","z":"56deb452.46025c","name":"Get Current Humidity","topic":"home/termostato/humidity/state","qos":"0","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"99ab3ff6.4455d","x":1740,"y":512,"wires":[]},{"id":"1b9065ba.078dfa","type":"modbus-flex-getter","z":"56deb452.46025c","name":"","showStatusActivities":false,"showErrors":false,"showWarnings":true,"logIOActivities":false,"server":"36e9f5f4.01499a","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":1150,"y":740,"wires":[["c57738f6.fa7538","5db36dd8.ca6654","b7d029fb.83d3c8","cd0f13e3.29767","efaf078c.272528","31702aeb72712b58","b209f42e78567e36"],[]]},{"id":"5d5a96ab.394ab8","type":"function","z":"56deb452.46025c","name":"Prepare Request","func":"var newMsg = { payload: msg.payload.length,\n                topic: \"\"\n};\nvar ts = new Date();\n\nnewMsg.payload = {\n    'value': ts.getTime(),\n    'fc': 3,\n    'unitid': 1,\n    'address': 0,\n    'quantity': 86\n};\n\nreturn newMsg;\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1110,"y":460,"wires":[["1b9065ba.078dfa"]]},{"id":"e372074b.8e3c48","type":"inject","z":"56deb452.46025c","name":"Read","props":[{"p":"payload"}],"repeat":"10","crontab":"","once":true,"onceDelay":"5","topic":"","payload":"","payloadType":"num","x":850,"y":420,"wires":[["5d5a96ab.394ab8"]]},{"id":"c57738f6.fa7538","type":"function","z":"56deb452.46025c","name":"Get Temperature Setpoint","func":"const register = 64;\nmsg.payload = msg.payload[register]; \nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1450,"y":592,"wires":[["a4fd90ac.9d17b"]]},{"id":"5db36dd8.ca6654","type":"function","z":"56deb452.46025c","name":"Get Current Temperature","func":"const register = 0;\nmsg.payload = msg.payload[register]; \nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1450,"y":432,"wires":[["c7ae10d2.116ce"]]},{"id":"b7d029fb.83d3c8","type":"function","z":"56deb452.46025c","name":"Get Current Humidity","func":"const register = 2;\nmsg.payload = msg.payload[register]; \nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1440,"y":512,"wires":[["1e7e7c1a.ced034"]]},{"id":"cd0f13e3.29767","type":"function","z":"56deb452.46025c","name":"Get Current Mode","func":"const register = 62;\nmsg.payload = msg.payload[register]; \nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1430,"y":660,"wires":[["cbde474c.988668","2ad7f0fc.1f337"]]},{"id":"efaf078c.272528","type":"function","z":"56deb452.46025c","name":"Get Action Status","func":"const register = 4;  //was 9 \nmsg.payload = msg.payload[register]; \nif(msg.payload == 0){\n        msg.payload = \"Idle\";\n} else {\n        msg.payload = \"Cool\";\n}\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1430,"y":860,"wires":[["1da278e0.f0bf57"]]},{"id":"1da278e0.f0bf57","type":"mqtt out","z":"56deb452.46025c","name":"Get Action","topic":"home/termostato/action/state","qos":"0","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"99ab3ff6.4455d","x":1710,"y":860,"wires":[]},{"id":"2ad7f0fc.1f337","type":"change","z":"56deb452.46025c","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"1","fromt":"num","to":"heat","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"2","fromt":"num","to":"cool","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"3","fromt":"num","to":"fan_only","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"4","fromt":"num","to":"dehumidify","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"5","fromt":"num","to":"auto","tot":"str"},{"t":"set","p":"savedMode","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1720,"y":660,"wires":[["93c8a67f.ff0818"]]},{"id":"fan_speed_set","type":"mqtt in","z":"56deb452.46025c","name":"Set Fan Mode","topic":"home/termostato/fan_mode/set","qos":"0","datatype":"auto-detect","broker":"99ab3ff6.4455d","nl":false,"rap":true,"rh":0,"inputs":0,"x":1290,"y":1340,"wires":[["fan_speed_convert"]]},{"id":"fan_speed_convert","type":"function","z":"56deb452.46025c","name":"Convert Fan Mode","func":"if (!msg.payload || typeof msg.payload !== 'string') {\n    node.error(\"Payload is not a string: \" + typeof msg.payload);\n    return null; // Stop the flow if payload is not valid\n}\n\nconst speed = msg.payload.toLowerCase();\nlet modbusValue;\n\nswitch(speed) {\n    case 'high':\n        modbusValue = \"0\";\n        break;\n    case 'medium':\n        modbusValue = \"1\";\n        break;\n    case 'low':\n        modbusValue = \"2\";\n        break;\n    case 'auto':\n        modbusValue = \"3\";\n        break;\n    default:\n        node.warn('Invalid fan speed: ' + speed);\n        return null;\n}\n\nmsg.payload = modbusValue;\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1830,"y":1340,"wires":[["0c6aa9d636748ad1"]]},{"id":"859502bc48cbb8b1","type":"mqtt out","z":"56deb452.46025c","name":"Get Current Fan Status","topic":"home/termostato/fan_mode/state","qos":"0","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"99ab3ff6.4455d","x":1750,"y":360,"wires":[]},{"id":"31702aeb72712b58","type":"function","z":"56deb452.46025c","name":"Get Current Fan Mode","func":"const register = 63;\nmsg.payload = msg.payload[register]; \nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1440,"y":360,"wires":[["859502bc48cbb8b1","f3245d050175dba5"]]},{"id":"0c6aa9d636748ad1","type":"modbus-write","z":"56deb452.46025c","name":"Set Status","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"","dataType":"MHoldingRegisters","adr":"63","quantity":"1","server":"36e9f5f4.01499a","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":2070,"y":1340,"wires":[[],[]]},{"id":"b209f42e78567e36","type":"function","z":"56deb452.46025c","name":"Get On/Off Status","func":"const register = 61\nmsg.payload = msg.payload[register]; \nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1430,"y":760,"wires":[["fdc0f6621b4e660d"]]},{"id":"fdc0f6621b4e660d","type":"mqtt out","z":"56deb452.46025c","name":"Get On/Off Status","topic":"home/termostato/onoff/state","qos":"0","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"99ab3ff6.4455d","x":1730,"y":760,"wires":[]},{"id":"f3245d050175dba5","type":"change","z":"56deb452.46025c","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"0","fromt":"num","to":"high","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"1","fromt":"num","to":"medium","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"2","fromt":"num","to":"low","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"3","fromt":"num","to":"auto","tot":"str"},{"t":"set","p":"savedFanMode","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1720,"y":320,"wires":[["f8552a6ed3f07a6b"]]},{"id":"f8552a6ed3f07a6b","type":"mqtt out","z":"56deb452.46025c","name":"Get Current Fan Mode","topic":"home/termostato/fan_mode/mode","qos":"0","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"99ab3ff6.4455d","x":1960,"y":320,"wires":[]},{"id":"8cbe39de04565ae6","type":"mqtt in","z":"56deb452.46025c","name":"Set Mode","topic":"home/termostato/mode/set","qos":"0","datatype":"auto-detect","broker":"99ab3ff6.4455d","nl":false,"rap":true,"rh":0,"inputs":0,"x":1280,"y":1520,"wires":[["4a0c662259317d6d"]]},{"id":"4a0c662259317d6d","type":"function","z":"56deb452.46025c","name":"Convert Mode","func":"if (!msg.payload || typeof msg.payload !== 'string') {\n    node.error(\"Payload is not a string: \" + typeof msg.payload);\n    return null; // Stop the flow if payload is not valid\n}\n\nconst speed = msg.payload.toLowerCase();\nlet modbusValue;\n\nswitch(speed) {\n    case 'heat':\n        modbusValue = \"0\";\n        break;\n    case 'cool':\n        modbusValue = \"1\";\n        break;\n    case 'fan_only':\n        modbusValue = \"2\";\n        break;\n    case 'dehumidify':\n        modbusValue = \"3\";\n        break;\n    case 'auto':\n        modbusValue = \"4\";\n        break;\n    default:\n        node.warn('Invalid mode: ' + speed);\n        return null;\n}\n\nmsg.payload = modbusValue;\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1840,"y":1520,"wires":[["92482b81b3077544"]]},{"id":"92482b81b3077544","type":"modbus-write","z":"56deb452.46025c","name":"Set Mode","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"","dataType":"MHoldingRegisters","adr":"62","quantity":"1","server":"36e9f5f4.01499a","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":2060,"y":1520,"wires":[[],[]]},{"id":"861d0968.494578","type":"mqtt in","z":"56deb452.46025c","name":"Set On/Off","topic":"home/termostato/onoff/set","qos":"0","datatype":"auto-detect","broker":"99ab3ff6.4455d","nl":false,"rap":false,"inputs":0,"x":1280,"y":1140,"wires":[["5257703f.d5da3"]]},{"id":"5257703f.d5da3","type":"template","z":"56deb452.46025c","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"[{{ payload }}]","output":"str","x":1520,"y":1140,"wires":[["8685cea6.1935c"]]},{"id":"8685cea6.1935c","type":"json","z":"56deb452.46025c","name":"","property":"payload","action":"","pretty":false,"x":1670,"y":1140,"wires":[["940d1c82.2b838"]]},{"id":"940d1c82.2b838","type":"modbus-write","z":"56deb452.46025c","name":"Set Status","showStatusActivities":false,"showErrors":false,"showWarnings":true,"unitid":"","dataType":"MHoldingRegisters","adr":"61","quantity":"1","server":"36e9f5f4.01499a","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":1910,"y":1140,"wires":[[],[]]},{"id":"527f2f054560cb64","type":"complete","z":"56deb452.46025c","name":"Read After Write","scope":["967c846b.4ec788","0c6aa9d636748ad1","92482b81b3077544","940d1c82.2b838"],"uncaught":false,"x":860,"y":560,"wires":[["5d5a96ab.394ab8"]]},{"id":"99ab3ff6.4455d","type":"mqtt-broker","name":"MQTT HA Server","broker":"localhost","port":"1883","tls":"","clientid":"","autoConnect":true,"usetls":false,"compatmode":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"36e9f5f4.01499a","type":"modbus-client","name":"Termostato","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"192.168.1.89","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"","unit_id":"1","commandDelay":"200","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true,"showErrors":true,"showWarnings":true,"showLogs":true}]
  1. Open the Configuration Menu (three horizontal lines or a hamburger icon).
  2. Navigate to the Termostato Node
  3. Edit “IP Address” and “Port”. Recommend making IP static on your router. Port should be 502.
  4. Deploy Changes - “Deploy” button is usually located in the top right corner.

Modify configuration.yaml

# MQTT Broker Configuration
mqtt:

    # MQTT Climate Configuration
    climate:
      - name: apollo
        modes:
          - "cool"
          - "fan_only"
        fan_modes:
          - "low"
          - "medium"
          - "high"
          - "auto"
        fan_mode_command_topic: "home/termostato/fan_mode/set"
        fan_mode_state_topic: "home/termostato/fan_mode/mode"
        #fan_mode_state_template: "{{ value_json }}"  # Modify as needed
        temperature_command_topic: "home/termostato/temperature_setpoint/set"
        temperature_state_topic: "home/termostato/temperature_setpoint/state"
        temperature_state_template: "{{ value_json|float / 10 }}"
        current_temperature_topic: "home/termostato/current_temperature/state"
        current_temperature_template: "{{ value_json|float / 10 }}"
        mode_state_topic: "home/termostato/mode/mode"
        mode_command_topic: "home/termostato/mode/set"
        temperature_unit: f
        max_temp: 90
        min_temp: 65
        temp_step: 1
        retain: true

    # MQTT Switch Configuration
    switch: 
      - name: "Apollo On/Off"
        state_topic: "home/termostato/onoff/state"
        command_topic: "home/termostato/onoff/set"
        value_template: "{{ value_json }}"
        payload_on: "1"
        payload_off: "0"
        qos: 0
        retain: true
        icon: mdi:power

    # MQTT Sensor Configuration
    sensor:
    - name: "Apollo Humidity"
      state_topic: "home/termostato/humidity/state"
      value_template: "{{ value_json|int }}"
      device_class: humidity
      unit_of_measurement: '%'  # Specify the unit of measurement as percentage

    - name: "Apollo Temperature"
      state_topic: "home/termostato/current_temperature/state"
      value_template: "{{ value_json|float / 10 }}"
      device_class: temperature
      unit_of_measurement: '°F'

Modify the Lovelace Interface

  1. Navigate to the Home Assistant dashboard.
  2. Click on the “Configure UI” button (usually found in the top right corner).
  3. Click on the “Add Card” button at the bottom right.
  4. Select “Manual” from the card picker.
  5. Copy and paste the following configuration into the card configuration:
square: false
type: grid
columns: 1
cards:
  - type: thermostat
    entity: climate.apollo
    features:
      - style: icons
        hvac_modes:
          - cool
          - fan_only
        type: climate-hvac-modes
      - style: icons
        fan_modes:
          - low
          - medium
          - high
          - auto
        type: climate-fan-modes
    show_current_as_primary: false
  - type: entities
    entities:
      - entity: switch.apollo_on_off
      - entity: sensor.apollo_temperature
      - entity: sensor.apollo_humidity
    show_header_toggle: false
    state_color: true

Other Lock Code PINS

8657 Master key
5209 Set lock pin
0907 Installer
1976 MQTT Setup [MBTEK claims to be working on this]
3036 Communications Config Screen

Just a thought, if you want you can get direct modbus connection to the mc6 from HA native modbus integration. This avoid the hassle if setup and config node red.
In the mc6 thread there’s a post I made with the details, it needs to be adapted to the new standard modbus integration that has changed a bit to fix some errors.

HA should now have fixed the issue of the fan mode setting.

1 Like