kadoma


Namekadoma JSON
Version 0.0.2 PyPI version JSON
download
home_pageNone
SummaryControl Daikin BRC1H units over BLE (forked from pymadoka)
upload_time2025-06-18 11:16:41
maintainerNone
docs_urlNone
authorNone
requires_python>=3.13
licenseNone
keywords automation ble bluetooth home-assistant homeautomation mqtt thermostat
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Kadoma

Library to control the thermostat Daikin BRC1H family.

Based on PyMadoka

Original README included until a new one is written.

# PyMadoka

This library has been written to control the thermostat Daikin BRC1H family without the need to use the mobile Madoka apps.

The code is based on the previous work by Benjamin Lafois (both [reverse engineering](https://github.com/blafois/Daikin-Madoka-BRC1H-BLE-Reverse) and [OpenHAB add-on](https://github.com/openhab/openhab-addons/tree/main/bundles/org.openhab.binding.bluetooth.daikinmadoka/src/main/java/org/openhab/binding/bluetooth/daikinmadoka)).

What does it provide?

* A Python library that can be used to integrate it with home automation systems (HomeAssistant)
* CLI tool to control the device (pymadoka)
* CLI tool to bridge the device with MQTT (pymadoka-mqtt)


# Installation
```
pip install pymadoka
```
# Requirements

The library has been developed and tested on Linux Python 3.

Once the thermostat has been paired and connected to a client, it is not available during a devices scan. Therefore, the library usually enforces a "disconnect" of the current client so it can be listed and become available for connection. I have not been able to find the way to do it using the [BLE library](https://github.com/hbldh/bleak) so it relays on `bluetoothctl` to do it.

However, this `bluetoothctl` dependency results in a lack of compatibility with other operating systems, so only Linux is supported at the moment. Nevertheless, the "force disconnect" might be only required on Linux and can be disabled when testing other operating systems.

**No other client must be connected to the device (even using the same Bluetooth adapter).** 

**This library has been designed to operate exclusively with the device and messages coming as a response of commands issued to the device from other clients may interfer with the behaviour.**


# Pairing the device

As previously noted, the device has to be paired in order to work and it requires code confirmation on the screen. The best way to achieve it is to follow this steps:

* Disconnect the BRC1H from any other device by accessing the setup menu and pressing the "forget bluetooth connection" button
* Execute `bluetoothctl`
* `agent off` to disable default bluetooth agent
* `agent KeyboardDisplay` to enable bluetooth agent for pairing
* `scan on` and wait 5s. The device MAC should be listed 
* `scan off`
* `pair <MAC_ADDRESS>`. You will be prompted to confirm the code. After typing yes, you will have to confirm on the BRC1H screen.


# Command line usage

## pymadoka 

The package provides a stand-alone CLI tool (pymadoka) that can be used to control the device. It outputs all the results in a convenient JSON format and can be configured using the following switches:

```
$ pymadoka

Usage: pymadoka [OPTIONS] COMMAND [ARGS]...

Options:
  -a, --address TEXT              Bluetooth MAC address of the thermostat
                                  [required]

  -d, --adapter TEXT              Name of the Bluetooth adapter to be used for
                                  the connection  [default: hci0]

  --force-disconnect / --not-force-disconnect
                                  Should disconnect the device to ensure it is
                                  recognized (recommended)  [default: True]

  -t, --device-discovery-timeout INTEGER
                                  Timeout for Bluetooth device scan in seconds
                                  [default: 5]

  -o, --log-output PATH           Path to the log output file
  --debug                         Enable debug logging
  --verbose                       Enable versbose logging
  --version                       Show the version and exit.
  --help                          Show this message and exit.

Commands:
  get-clean-filter-indicator
  get-fan-speed
  get-operation-mode
  get-power-state
  get-set-point
  get-status
  get-temperatures
  set-fan-speed
  set-operation-mode
  set-set-point
```
Output example:

```
{"cooling_fan_speed": "HIGH", "heating_fan_speed": "LOW"}
```

## pymadoka-mqtt

This tool is intended to be used as a daemon. It helps to integrate the library into home automation systems that support MQTT climate devices. It requires a configuration file to specify all the MQTT supported features:

```yaml
mqtt:
    host: "localhost"
    port: 1883
    username: "myuser"
    password: "mypassword"
    ssl: False
    friendly_name: "MyMadoka" # This is only used to report to HomeAssistant
    root_topic: "/my_root_topic" # Default root topic is /madoka
    root_topic_only: False # If False, don't append the device name to the root_topic
    # Optional. If this field exist, a discovery message will be sent to this topic after the device is connected for the first time.
    # <device_topic> tag will be replaced with /root_topic/XX_XX_XX_XX_XX_XX (unless root_topic_only is set)
    discovery_topic: "/homeassistant/climate/<device_topic>/config" 
daemon:
    update_interval: 15 # Query the device at this interval (seconds)
```

This is an example of the data sent with each status message:

```json

$ docker run -it -p 1883:1883 -p 9001:9001 eclipse-mosquitto
$ docker run -it -p 1883:1883 -p 9001:9001 eclipse-mosquitto
$ mosquitto_sub -t "#"

{"fan_speed": {"cooling_fan_speed": "LOW", "heating_fan_speed": "LOW"}, "operation_mode": {"operation_mode": "AUTO"}, "power_state": {"turn_on": false}, "set_point": {"cooling_set_point": 17, "heating_set_point": 17}, "temperatures": {"indoor": 20, "outdoor": null}, "clean_filter_indicator": {"clean_filter_indicator": false}}

```
Usage:

```
$ pymadoka-mqtt --help
Usage: pymadoka-mqtt [OPTIONS]

Options:
  -a, --address TEXT              Bluetooth MAC address of the thermostat
                                  [required]

  -c, --config PATH               MQTT config file  [required]
  -d, --adapter TEXT              Name of the Bluetooth adapter to be used for
                                  the connection  [default: hci0]

  --force-disconnect / --not-force-disconnect
                                  Should disconnect the device to ensure it is
                                  recognized (recommended)  [default: True]

  -t, --device-discovery-timeout INTEGER
                                  Timeout for Bluetooth device scan in seconds
                                  [default: 5]

  -o, --log-output PATH           Path to the log output file
  --debug                         Enable debug logging
  --verbose                       Enable versbose logging
  --version                       Show the version and exit.
  --help                          Show this message and exit.
```

# Library usage

The main class is Controller. The Controller contains features that are used to control different aspects of the device such as: set point, fan speed, operation mode and others.

Each feature has two methods (when available):

* Query: query the device for the information related to the feature
* Update: update the device with the new feature status

Check the examples folder for more details.

# Supporting new features

This library has been implemented to cover the basics of the HVAC. The official Madoka app seems to offer different GUIs according to the features of the HVAC model being controlled and mine doesn't seem to be as complex as others are. However, in the case you are interested in supporting other features, you can contribute by reverse engineering the Bluetooth messages required to control those features. 

There are several ways to do it but one of the easiest is to snoop on the Bluetooth interface and capture all the traffic:
* [Android bluetooth debugging](https://source.android.com/devices/bluetooth/verifying_debugging). By the end of the chapter, it explains how to enable Bluetooth Snoop logs 
* [iOS bluetooth debugging](https://www.bluetooth.com/blog/a-new-way-to-debug-iosbluetooth-applications/). 

Also, it is important to check the `btmon` utility as it can help with the message debugging on Linux. 

Search for sent/received messages
```
$ sudo btmon | grep -C 5 ACL
```

# Troubleshooting

* **My device is not listed when I scan for devices using `bluetoothctl`**

Check that the BR1CH is not connected to any other device. Go to BR1CH screen, tap on the menu and look for the Bluetooth settings. Tap on disconnect.

* **My client keeps disconnecting some seconds after connecting**

Check that your devices are correctly paired (`bluetoothctl paired-devices`). If your device is not listed and you are not able to pair after several tries, it may be due to a failure on DBUS-Bluez service. You can try to restart the service by issuing:

```
$ sudo systemctl restart dbus-org.bluez.service
```

* **It takes several seconds to execute each command**

The execution of a single command takes some time as it has to follow several steps before it can write the command:

1. Disconnect 
2. Discover devices/list services
3. Connect
4. Issue command
5. Wait for response

* **Setting the device set-point does not respect cooling/heating paremeters**

Apparently, some devices like mine don't support separate set-point values and only the last set-point value sent in a command is used. Therefore, if you use the CLI or the library, be aware that the thermostat may set both set-points to the heating set-point. I have tested this behaviour by removing the heating set-point in the command implementation and it works like a charm. However, if I send both cooling followed by heating values, only heating set-point is used. 

# TODO

1. Implement a BLE emulator or a Frida script to activate the app features not shown for the device

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "kadoma",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.13",
    "maintainer_email": "\"L. L\u00f3pez\" <luis@cuarentaydos.com>",
    "keywords": "automation, ble, bluetooth, home-assistant, homeautomation, mqtt, thermostat",
    "author": null,
    "author_email": "\"L. L\u00f3pez\" <luis@cuarentaydos.com>",
    "download_url": "https://files.pythonhosted.org/packages/d0/7b/099a94cf47b917bca2474e08cef6f41a0a00b551a01d3b2524607770d1b8/kadoma-0.0.2.tar.gz",
    "platform": null,
    "description": "# Kadoma\n\nLibrary to control the thermostat Daikin BRC1H family.\n\nBased on PyMadoka\n\nOriginal README included until a new one is written.\n\n# PyMadoka\n\nThis library has been written to control the thermostat Daikin BRC1H family without the need to use the mobile Madoka apps.\n\nThe code is based on the previous work by Benjamin Lafois (both [reverse engineering](https://github.com/blafois/Daikin-Madoka-BRC1H-BLE-Reverse) and [OpenHAB add-on](https://github.com/openhab/openhab-addons/tree/main/bundles/org.openhab.binding.bluetooth.daikinmadoka/src/main/java/org/openhab/binding/bluetooth/daikinmadoka)).\n\nWhat does it provide?\n\n* A Python library that can be used to integrate it with home automation systems (HomeAssistant)\n* CLI tool to control the device (pymadoka)\n* CLI tool to bridge the device with MQTT (pymadoka-mqtt)\n\n\n# Installation\n```\npip install pymadoka\n```\n# Requirements\n\nThe library has been developed and tested on Linux Python 3.\n\nOnce the thermostat has been paired and connected to a client, it is not available during a devices scan. Therefore, the library usually enforces a \"disconnect\" of the current client so it can be listed and become available for connection. I have not been able to find the way to do it using the [BLE library](https://github.com/hbldh/bleak) so it relays on `bluetoothctl` to do it.\n\nHowever, this `bluetoothctl` dependency results in a lack of compatibility with other operating systems, so only Linux is supported at the moment. Nevertheless, the \"force disconnect\" might be only required on Linux and can be disabled when testing other operating systems.\n\n**No other client must be connected to the device (even using the same Bluetooth adapter).** \n\n**This library has been designed to operate exclusively with the device and messages coming as a response of commands issued to the device from other clients may interfer with the behaviour.**\n\n\n# Pairing the device\n\nAs previously noted, the device has to be paired in order to work and it requires code confirmation on the screen. The best way to achieve it is to follow this steps:\n\n* Disconnect the BRC1H from any other device by accessing the setup menu and pressing the \"forget bluetooth connection\" button\n* Execute `bluetoothctl`\n* `agent off` to disable default bluetooth agent\n* `agent KeyboardDisplay` to enable bluetooth agent for pairing\n* `scan on` and wait 5s. The device MAC should be listed \n* `scan off`\n* `pair <MAC_ADDRESS>`. You will be prompted to confirm the code. After typing yes, you will have to confirm on the BRC1H screen.\n\n\n# Command line usage\n\n## pymadoka \n\nThe package provides a stand-alone CLI tool (pymadoka) that can be used to control the device. It outputs all the results in a convenient JSON format and can be configured using the following switches:\n\n```\n$ pymadoka\n\nUsage: pymadoka [OPTIONS] COMMAND [ARGS]...\n\nOptions:\n  -a, --address TEXT              Bluetooth MAC address of the thermostat\n                                  [required]\n\n  -d, --adapter TEXT              Name of the Bluetooth adapter to be used for\n                                  the connection  [default: hci0]\n\n  --force-disconnect / --not-force-disconnect\n                                  Should disconnect the device to ensure it is\n                                  recognized (recommended)  [default: True]\n\n  -t, --device-discovery-timeout INTEGER\n                                  Timeout for Bluetooth device scan in seconds\n                                  [default: 5]\n\n  -o, --log-output PATH           Path to the log output file\n  --debug                         Enable debug logging\n  --verbose                       Enable versbose logging\n  --version                       Show the version and exit.\n  --help                          Show this message and exit.\n\nCommands:\n  get-clean-filter-indicator\n  get-fan-speed\n  get-operation-mode\n  get-power-state\n  get-set-point\n  get-status\n  get-temperatures\n  set-fan-speed\n  set-operation-mode\n  set-set-point\n```\nOutput example:\n\n```\n{\"cooling_fan_speed\": \"HIGH\", \"heating_fan_speed\": \"LOW\"}\n```\n\n## pymadoka-mqtt\n\nThis tool is intended to be used as a daemon. It helps to integrate the library into home automation systems that support MQTT climate devices. It requires a configuration file to specify all the MQTT supported features:\n\n```yaml\nmqtt:\n    host: \"localhost\"\n    port: 1883\n    username: \"myuser\"\n    password: \"mypassword\"\n    ssl: False\n    friendly_name: \"MyMadoka\" #\u00a0This is only used to report to HomeAssistant\n    root_topic: \"/my_root_topic\" #\u00a0Default root topic is /madoka\n    root_topic_only: False #\u00a0If False, don't append the device name to the root_topic\n    #\u00a0Optional. If this field exist, a discovery message will be sent to this topic after the device is connected for the first time.\n    # <device_topic> tag will be replaced with /root_topic/XX_XX_XX_XX_XX_XX (unless root_topic_only is set)\n    discovery_topic: \"/homeassistant/climate/<device_topic>/config\" \ndaemon:\n    update_interval: 15 #\u00a0Query the device at this interval (seconds)\n```\n\nThis is an example of the data sent with each status message:\n\n```json\n\n$ docker run -it -p 1883:1883 -p 9001:9001 eclipse-mosquitto\n$ docker run -it -p 1883:1883 -p 9001:9001 eclipse-mosquitto\n$ mosquitto_sub -t \"#\"\n\n{\"fan_speed\": {\"cooling_fan_speed\": \"LOW\", \"heating_fan_speed\": \"LOW\"}, \"operation_mode\": {\"operation_mode\": \"AUTO\"}, \"power_state\": {\"turn_on\": false}, \"set_point\": {\"cooling_set_point\": 17, \"heating_set_point\": 17}, \"temperatures\": {\"indoor\": 20, \"outdoor\": null}, \"clean_filter_indicator\": {\"clean_filter_indicator\": false}}\n\n```\nUsage:\n\n```\n$ pymadoka-mqtt --help\nUsage: pymadoka-mqtt [OPTIONS]\n\nOptions:\n  -a, --address TEXT              Bluetooth MAC address of the thermostat\n                                  [required]\n\n  -c, --config PATH               MQTT config file  [required]\n  -d, --adapter TEXT              Name of the Bluetooth adapter to be used for\n                                  the connection  [default: hci0]\n\n  --force-disconnect / --not-force-disconnect\n                                  Should disconnect the device to ensure it is\n                                  recognized (recommended)  [default: True]\n\n  -t, --device-discovery-timeout INTEGER\n                                  Timeout for Bluetooth device scan in seconds\n                                  [default: 5]\n\n  -o, --log-output PATH           Path to the log output file\n  --debug                         Enable debug logging\n  --verbose                       Enable versbose logging\n  --version                       Show the version and exit.\n  --help                          Show this message and exit.\n```\n\n# Library usage\n\nThe main class is Controller. The Controller contains features that are used to control different aspects of the device such as: set point, fan speed, operation mode and others.\n\nEach feature has two methods (when available):\n\n* Query: query the device for the information related to the feature\n* Update: update the device with the new feature status\n\nCheck the examples folder for more details.\n\n# Supporting new features\n\nThis library has been implemented to cover the basics of the HVAC. The official Madoka app seems to offer different GUIs according to the features of the HVAC model being controlled and mine doesn't seem to be as complex as others are. However, in the case you are interested in supporting other features, you can contribute by reverse engineering the Bluetooth messages required to control those features. \n\nThere are several ways to do it but one of the easiest is to snoop on the Bluetooth interface and capture all the traffic:\n* [Android bluetooth debugging](https://source.android.com/devices/bluetooth/verifying_debugging). By the end of the chapter, it explains how to enable Bluetooth Snoop logs \n* [iOS bluetooth debugging](https://www.bluetooth.com/blog/a-new-way-to-debug-iosbluetooth-applications/). \n\nAlso, it is important to check the `btmon` utility as it can help with the message debugging on Linux. \n\nSearch for sent/received messages\n```\n$ sudo btmon | grep -C 5 ACL\n```\n\n# Troubleshooting\n\n* **My device is not listed when I scan for devices using `bluetoothctl`**\n\nCheck that the BR1CH is not connected to any other device. Go to BR1CH screen, tap on the menu and look for the Bluetooth settings. Tap on disconnect.\n\n* **My client keeps disconnecting some seconds after connecting**\n\nCheck that your devices are correctly paired (`bluetoothctl paired-devices`). If your device is not listed and you are not able to pair after several tries, it may be due to a failure on DBUS-Bluez service. You can try to restart the service by issuing:\n\n```\n$ sudo systemctl restart dbus-org.bluez.service\n```\n\n* **It takes several seconds to execute each command**\n\nThe execution of a single command takes some time as it has to follow several steps before it can write the command:\n\n1. Disconnect \n2. Discover devices/list services\n3. Connect\n4. Issue command\n5. Wait for response\n\n* **Setting the device set-point does not respect cooling/heating paremeters**\n\nApparently, some devices like mine don't support separate set-point values and only the last set-point value sent in a command is used. Therefore, if you use the CLI or the library, be aware that the thermostat may set both set-points to the heating set-point. I have tested this behaviour by removing the heating set-point in the command implementation and it works like a charm. However, if I send both cooling followed by heating values, only heating set-point is used. \n\n# TODO\n\n1. Implement a BLE emulator or a Frida script to activate the app features not shown for the device\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Control Daikin BRC1H units over BLE (forked from pymadoka)",
    "version": "0.0.2",
    "project_urls": {
        "Homepage": "https://github.com/ldotlopez/kadoma",
        "Issues": "https://github.com/ldotlopez/kadoma/issues",
        "Repository": "https://github.com/ldotlopez/kadoma"
    },
    "split_keywords": [
        "automation",
        " ble",
        " bluetooth",
        " home-assistant",
        " homeautomation",
        " mqtt",
        " thermostat"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b7c94415e1d03f327c79859f196109299ac5b708894f1fba236172137e48ddec",
                "md5": "c85da329ac8aac15ba204ccaaaebb36f",
                "sha256": "b25977a56bf630629dedab496bd95daa28ff12a18403dad680b874f405bb9bcb"
            },
            "downloads": -1,
            "filename": "kadoma-0.0.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "c85da329ac8aac15ba204ccaaaebb36f",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.13",
            "size": 21208,
            "upload_time": "2025-06-18T11:16:40",
            "upload_time_iso_8601": "2025-06-18T11:16:40.619819Z",
            "url": "https://files.pythonhosted.org/packages/b7/c9/4415e1d03f327c79859f196109299ac5b708894f1fba236172137e48ddec/kadoma-0.0.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d07b099a94cf47b917bca2474e08cef6f41a0a00b551a01d3b2524607770d1b8",
                "md5": "f66776c3af8ce85ec9c9d96829f71313",
                "sha256": "551ccc0731c55d5b8ff3d496aefb360839a3a7b999c8088dfa828e78df6bb1a8"
            },
            "downloads": -1,
            "filename": "kadoma-0.0.2.tar.gz",
            "has_sig": false,
            "md5_digest": "f66776c3af8ce85ec9c9d96829f71313",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.13",
            "size": 19560,
            "upload_time": "2025-06-18T11:16:41",
            "upload_time_iso_8601": "2025-06-18T11:16:41.499650Z",
            "url": "https://files.pythonhosted.org/packages/d0/7b/099a94cf47b917bca2474e08cef6f41a0a00b551a01d3b2524607770d1b8/kadoma-0.0.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-06-18 11:16:41",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "ldotlopez",
    "github_project": "kadoma",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "kadoma"
}
        
Elapsed time: 0.48155s