Water Level in My Tank (ME201WZ Zigbee Sensor)

Hi everyone, I’m Sigalou! I wanted to share my hands-on experience with the Moray ME201WZ Zigbee ultrasonic water level sensor, which I’ve been using to monitor the water level in my underground tank. I’ve integrated it with Zigbee2MQTT and Home Assistant, and I thought it might interest some of you here.

citerneok
As usual, I’m sharing a detailed write-up of my experience with this product and how I set it up.

I’m over the moon! For less than €50, I now have a fully autonomous system that monitors my tank’s water level, running on Zigbee and seamlessly integrated into my home automation setup.

It’s perfect!

Feel free to reach out if you have any questions or need help with your setup.

7 Likes

Hey Sigalou, thanks for taking the time to review the unit and for the photos on how to install it.

We have this same unit at work and it’s currently compatible with ZHA, using HA core V 2025.4.3
I’ll come back and update on how well it functions after testing for a few days.

1 Like

Hi Luthia04

Does it really works in ZHA ? I didn’t find anything about this in zigbee.blakadder.com
(but it is in zigbee2mqtt ME201WZ

What ZHA quirk does it use?

How do you setup the Installation height / Liquid depth max ?

I can report that I just connected this device successfully to ZHA - see below. The steep drop in liquid depth is from not having it on the tank after successfully pairing. Look to the right and you can see a subtle slope. That’s me opening a bunch of consumers to see if the level updates.

After a few minutes it looks like the depth is work, the fill % maybe not. Settings show up in the device’s UI. The two distance settings are called “Water Tank Sensor Height from sensor to liquid level” and “Water Tank Sensor Height from sensor to tank bottom”. Once I make the first number be larger than the second number the percentage changes from 100%. My hunch is now that the first config option is just mislabeled and that one of the measures is sensor height from bottom and the other is max water height from bottom.

I had the toughest time getting the device into pairing mode. The initial blink when connection power is slow. Simply holding the button for 5 seconds didn’t make it a fast blink. I found instructions to “press once, then light will dim, then hold for 5s”. I tried that… Didn’t seem to work. In the end, I feel like I was just tapping slow and fast and suddenly got a fast blink and by HA immediately picked it up…

2 Likes

Hi There,

today I installed the very same sensor.
It shows values but they don’t seem to really change when the level rises or falls.

Can you confirm the mislabeling and show your values? I don’t see the full name in your screenshot.

Thanks in advance

I can confirm they are mislabeled.

This device is weird. It was working when the values were switched up. I did a few power cycles and deleting from the network and re-adding it etc but NOW it is no longer needed to switch up the values. No idea why, it’s just weird.

I was struggling with the level value always showing up 100 percent. Once I switched the values it shows up correctly.

I do however get quite a few errors in the logs because of this device. It’s not particularly far away from the next Router or Controller. Maybe 10m the most.

Logger: homeassistant
Source: /usr/src/homeassistant/homeassistant/runner.py:112
First occurred: June 7, 2025 at 9:25:29 PM (364 occurrences)
Last logged: 10:38:01 AM

Error doing job: Task exception was never retrieved (None)
Traceback (most recent call last):
File “/usr/local/lib/python3.13/site-packages/zigpy_znp/api.py”, line 1120, in request_callback_rsp
return await callback_rsp
^^^^^^^^^^^^^^^^^^
asyncio.exceptions.CancelledError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File “/usr/local/lib/python3.13/site-packages/zigpy_znp/api.py”, line 1117, in request_callback_rsp
async with asyncio_timeout(timeout):
~~~~~~~~~~~~~~~^^^^^^^^^
File “/usr/local/lib/python3.13/asyncio/timeouts.py”, line 116, in aexit
raise TimeoutError from exc_val
TimeoutError

Or this one:

Logger: zigpy.zcl
Source: runner.py:154
First occurred: June 7, 2025 at 10:09:09 PM (13 occurrences)
Last logged: 10:35:57 AM

[0x57BC:1:0xef00] Traceback (most recent call last): File “/usr/local/lib/python3.13/site-packages/zigpy_znp/zigbee/application.py”, line 829, in _send_request_raw response = await asyncio.shield( ^^^^^^^^^^^^^^^^^^^^^ …<13 lines>… ) ^ asyncio.exceptions.CancelledError The above exception was the direct cause of the following exception: Traceback (most recent call last): File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 127, in _limit_concurrency yield File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 373, in request await send_request() File “/usr/local/lib/python3.13/site-packages/zigpy/application.py”, line 844, in request await self.send_packet( …<14 lines>… ) File “/usr/local/lib/python3.13/site-packages/zigpy_znp/zigbee/application.py”, line 933, in send_packet await self._send_request_raw( …<11 lines>… ) File “/usr/local/lib/python3.13/site-packages/zigpy_znp/zigbee/application.py”, line 822, in _send_request_raw async with asyncio_timeout( ~~~~~~~~~~~~~~~^ EXTENDED_DATA_CONFIRM_TIMEOUT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ if extended_timeout ^^^^^^^^^^^^^^^^^^^ else DATA_CONFIRM_TIMEOUT ^^^^^^^^^^^^^^^^^^^^^^^^^ ): ^ File “/usr/local/lib/python3.13/asyncio/timeouts.py”, line 116, in aexit raise TimeoutError from exc_val TimeoutError During handling of the above exception, another exception occurred: Traceback (most recent call last): File “/usr/local/lib/python3.13/site-packages/zigpy/zcl/init.py”, line 425, in reply return await self._endpoint.reply( ^^^^^^^^^^^^^^^^^^^^^^^^^^^ …<9 lines>… ) ^ File “/usr/local/lib/python3.13/site-packages/zigpy/endpoint.py”, line 304, in reply return await self.device.reply( ^^^^^^^^^^^^^^^^^^^^^^^^ …<11 lines>… ) ^ File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 558, in reply return await self.request( ^^^^^^^^^^^^^^^^^^^ …<11 lines>… ) ^ File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 371, in request async with self._limit_concurrency(priority=priority): ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^ File “/usr/local/lib/python3.13/contextlib.py”, line 235, in aexit await self.gen.athrow(value) File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 120, in _limit_concurrency async with self._concurrent_requests_semaphore(priority=priority): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^ File “/usr/local/lib/python3.13/site-packages/zigpy/datastructures.py”, line 32, in aexit await self.context_manager.aexit(exc_type, exc, traceback) File “/usr/local/lib/python3.13/site-packages/zigpy/datastructures.py”, line 184, in aexit self.release() ~~~~~~~~~~~~^^ File “/usr/local/lib/python3.13/site-packages/zigpy/datastructures.py”, line 160, in release raise ValueError(“Semaphore released too many times”) ValueError: Semaphore released too many times
[0x57BC:1:0xef00] Traceback (most recent call last): File “/usr/local/lib/python3.13/site-packages/zigpy/zcl/init.py”, line 425, in reply return await self._endpoint.reply( ^^^^^^^^^^^^^^^^^^^^^^^^^^^ …<9 lines>… ) ^ File “/usr/local/lib/python3.13/site-packages/zigpy/endpoint.py”, line 304, in reply return await self.device.reply( ^^^^^^^^^^^^^^^^^^^^^^^^ …<11 lines>… ) ^ File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 558, in reply return await self.request( ^^^^^^^^^^^^^^^^^^^ …<11 lines>… ) ^ File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 371, in request async with self._limit_concurrency(priority=priority): ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^ File “/usr/local/lib/python3.13/contextlib.py”, line 221, in aexit await anext(self.gen) File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 120, in _limit_concurrency async with self._concurrent_requests_semaphore(priority=priority): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^ File “/usr/local/lib/python3.13/site-packages/zigpy/datastructures.py”, line 32, in aexit await self.context_manager.aexit(exc_type, exc, traceback) File “/usr/local/lib/python3.13/site-packages/zigpy/datastructures.py”, line 184, in aexit self.release() ~~~~~~~~~~~~^^ File “/usr/local/lib/python3.13/site-packages/zigpy/datastructures.py”, line 160, in release raise ValueError(“Semaphore released too many times”) ValueError: Semaphore released too many times
[0x57BC:1:0x0000] Traceback (most recent call last): File “/usr/local/lib/python3.13/site-packages/zigpy/zcl/init.py”, line 425, in reply return await self._endpoint.reply( ^^^^^^^^^^^^^^^^^^^^^^^^^^^ …<9 lines>… ) ^ File “/usr/local/lib/python3.13/site-packages/zigpy/endpoint.py”, line 304, in reply return await self.device.reply( ^^^^^^^^^^^^^^^^^^^^^^^^ …<11 lines>… ) ^ File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 558, in reply return await self.request( ^^^^^^^^^^^^^^^^^^^ …<11 lines>… ) ^ File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 371, in request async with self._limit_concurrency(priority=priority): ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^ File “/usr/local/lib/python3.13/contextlib.py”, line 221, in aexit await anext(self.gen) File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 120, in _limit_concurrency async with self._concurrent_requests_semaphore(priority=priority): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^ File “/usr/local/lib/python3.13/site-packages/zigpy/datastructures.py”, line 32, in aexit await self.context_manager.aexit(exc_type, exc, traceback) File “/usr/local/lib/python3.13/site-packages/zigpy/datastructures.py”, line 184, in aexit self.release() ~~~~~~~~~~~~^^ File “/usr/local/lib/python3.13/site-packages/zigpy/datastructures.py”, line 160, in release raise ValueError(“Semaphore released too many times”) ValueError: Semaphore released too many times
[0x57BC:1:0x0000] Traceback (most recent call last): File “/usr/local/lib/python3.13/site-packages/zigpy_znp/zigbee/application.py”, line 829, in _send_request_raw response = await asyncio.shield( ^^^^^^^^^^^^^^^^^^^^^ …<13 lines>… ) ^ asyncio.exceptions.CancelledError The above exception was the direct cause of the following exception: Traceback (most recent call last): File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 127, in _limit_concurrency yield File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 373, in request await send_request() File “/usr/local/lib/python3.13/site-packages/zigpy/application.py”, line 844, in request await self.send_packet( …<14 lines>… ) File “/usr/local/lib/python3.13/site-packages/zigpy_znp/zigbee/application.py”, line 933, in send_packet await self._send_request_raw( …<11 lines>… ) File “/usr/local/lib/python3.13/site-packages/zigpy_znp/zigbee/application.py”, line 822, in _send_request_raw async with asyncio_timeout( ~~~~~~~~~~~~~~~^ EXTENDED_DATA_CONFIRM_TIMEOUT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ if extended_timeout ^^^^^^^^^^^^^^^^^^^ else DATA_CONFIRM_TIMEOUT ^^^^^^^^^^^^^^^^^^^^^^^^^ ): ^ File “/usr/local/lib/python3.13/asyncio/timeouts.py”, line 116, in aexit raise TimeoutError from exc_val TimeoutError During handling of the above exception, another exception occurred: Traceback (most recent call last): File “/usr/local/lib/python3.13/site-packages/zigpy/zcl/init.py”, line 425, in reply return await self._endpoint.reply( ^^^^^^^^^^^^^^^^^^^^^^^^^^^ …<9 lines>… ) ^ File “/usr/local/lib/python3.13/site-packages/zigpy/endpoint.py”, line 304, in reply return await self.device.reply( ^^^^^^^^^^^^^^^^^^^^^^^^ …<11 lines>… ) ^ File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 558, in reply return await self.request( ^^^^^^^^^^^^^^^^^^^ …<11 lines>… ) ^ File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 371, in request async with self._limit_concurrency(priority=priority): ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^ File “/usr/local/lib/python3.13/contextlib.py”, line 235, in aexit await self.gen.athrow(value) File “/usr/local/lib/python3.13/site-packages/zigpy/device.py”, line 120, in _limit_concurrency async with self._concurrent_requests_semaphore(priority=priority): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^ File “/usr/local/lib/python3.13/site-packages/zigpy/datastructures.py”, line 32, in aexit await self.context_manager.aexit(exc_type, exc, traceback) File “/usr/local/lib/python3.13/site-packages/zigpy/datastructures.py”, line 184, in aexit self.release() ~~~~~~~~~~~~^^ File “/usr/local/lib/python3.13/site-packages/zigpy/datastructures.py”, line 160, in release raise ValueError(“Semaphore released too many times”) ValueError: Semaphore released too many times