New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Device Support Request] NOUS E6 TS0601 _TZE200_nnrfa68v #1702
Comments
I want to check this issue but I will be away from my computer until the end of August. |
Im also really interested. Thanks for your hard work. |
The first thing to say is that my knowledge of Python is quite basic, so I recommend interpreting my comments and instructions with caution. In principle the functionality is implemented in another class: Also important, this comment: The proposed code mostly looks correct to me, but there are a couple of differences that might be worth testing. This code is not in the 'original' implementation: payload.extend(sequence_number[0].to_bytes(1, "big", signed=False))
payload.extend(sequence_number[1].to_bytes(1, "big", signed=False)) I suppose that wants to put the sequence in the response payload, but there is also a sequence in the command: self.command(TUYA_SET_TIME, payload, expect_reply=True, tsn = self.endpoint.device.application.get_sequence()) Maybe we could do without these parts (any of both). Other diference with the original is the command call. The original is like this (the self.create_catching_task(
super().command(TUYA_SET_TIME, payload, expect_reply=False)
) I would try with a more similar implementation to try to make it work (without the There are also the offsets (your code don't implement the
I suppose that the probe that code isn't working is that the device time is not synchronized. And that there is any info about it in the logs. Isn't it? |
Yeah the sequence_number was an addition by me based on some Tuya spec I've found bo it didn't work. I will check if I get the sensor to respond to my set time command. The reason why I am not using set_time_local_offset is because the base class for this request is not implementing any code to synchronize the time, so it won't make a difference, but I will try with various offsets. |
@javicalle hhmm whatever I do I seem to get the following result: |
The device is not liking the command we sent it. Could you include the full log? I want to see the device request and the response. Also you can try with this code: self.create_catching_task(
super().command(
TUYA_SET_TIME,
payload,
manufacturer=foundation.ZCLHeader.NO_MANUFACTURER_ID,
expect_reply=False
)
) |
Wow, it was the manufacturer parameter! Now it works flawlessly. How did you know? :D Here is the current version of the quirk (which additionally is able to parse temperature_sensitivity etc, I am also trying to make setting of that param work): """Tuya temp and humidity sensor with screen."""
from typing import Dict
################## clean this up
import zigpy.types as t
from zigpy.zcl import foundation
from zhaquirks.tuya import TuyaTimePayload, TuyaCommand
import datetime
from typing import Tuple, Optional, Union
##################
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import Basic, Groups, Ota, Scenes, Time, AnalogOutput
from zigpy.zcl.clusters.measurement import RelativeHumidity, TemperatureMeasurement
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
SKIP_CONFIGURATION,
)
from zhaquirks.tuya import TuyaLocalCluster, TuyaPowerConfigurationCluster2AAA
from zhaquirks.tuya.mcu import DPToAttributeMapping, TuyaDPType, TuyaMCUCluster
TUYA_SET_TIME = 0x24
# NOTES:
# The data comes in as a string on cluster, if there is nothing set up you may see these lines in the logs:
# Unknown message (b'19830100a40102000400000118') on cluster 61184: unknown endpoint or cluster id: 'No cluster ID 0xef00 on (a4:c1:38:d0:18:8b:64:aa, 1)'
# 28.0 degrees
# Unknown message (b'19840100a5020200040000022c') on cluster 61184: unknown endpoint or cluster id: 'No cluster ID 0xef00 on (a4:c1:38:d0:18:8b:64:aa, 1)'
# 55.6% humid
# Unknown message (b'19850100a60402000400000064') on cluster 61184: unknown endpoint or cluster id: 'No cluster ID 0xef00 on (a4:c1:38:d0:18:8b:64:aa, 1)'
# 100% battery
class TemperatureUnitConvert(t.enum8):
"""Tuya Temp unit convert enum."""
Celsius = 0x00
Fahrenheit = 0x01
class TuyaTemperatureMeasurement(TemperatureMeasurement, TuyaLocalCluster):
"""Tuya local TemperatureMeasurement cluster."""
attributes = TemperatureMeasurement.attributes.copy()
attributes.update(
{
0x8001: ("temp_unit_convert", t.enum8),
0x8002: ("alarm_max_temperature", t.Single),
0x8003: ("alarm_min_temperature", t.Single),
0x8004: ("temperature_sensitivity", t.Single),
}
)
class TuyaRelativeHumidity(RelativeHumidity, TuyaLocalCluster):
"""Tuya local RelativeHumidity cluster."""
class TemperatureHumidityManufCluster(TuyaMCUCluster):
"""Tuya Manufacturer Cluster with Temperature and Humidity data points."""
dp_to_attribute: Dict[int, DPToAttributeMapping] = {
1: DPToAttributeMapping(
TuyaTemperatureMeasurement.ep_attribute,
"measured_value",
dp_type=TuyaDPType.VALUE,
converter=lambda x: x * 10, # decidegree to centidegree
),
2: DPToAttributeMapping(
TuyaRelativeHumidity.ep_attribute,
"measured_value",
dp_type=TuyaDPType.VALUE,
converter=lambda x: x * 100, # 0.01 to 1.0
),
4: DPToAttributeMapping(
TuyaPowerConfigurationCluster2AAA.ep_attribute,
"battery_percentage_remaining",
dp_type=TuyaDPType.VALUE,
converter=lambda x: x * 2, # reported percentage is doubled
),
9: DPToAttributeMapping(
TuyaTemperatureMeasurement.ep_attribute,
"temp_unit_convert",
dp_type=TuyaDPType.ENUM,
converter=lambda x: TemperatureUnitConvert(x)
),
10: DPToAttributeMapping(
TuyaTemperatureMeasurement.ep_attribute,
"alarm_max_temperature",
dp_type=TuyaDPType.VALUE,
converter=lambda x: x / 10
),
11: DPToAttributeMapping(
TuyaTemperatureMeasurement.ep_attribute,
"alarm_min_temperature",
dp_type=TuyaDPType.VALUE,
converter=lambda x: x / 10
),
19: DPToAttributeMapping(
TuyaTemperatureMeasurement.ep_attribute,
"temperature_sensitivity",
dp_type=TuyaDPType.VALUE,
converter=lambda x: x / 10
)
}
set_time_offset = 1970
set_time_local_offset = 1970
data_point_handlers = {
1: "_dp_2_attr_update",
2: "_dp_2_attr_update",
4: "_dp_2_attr_update",
9: "_dp_2_attr_update",
10: "_dp_2_attr_update",
11: "_dp_2_attr_update",
19: "_dp_2_attr_update",
}
def handle_set_time_request(self, sequence_number: t.uint16_t) -> foundation.Status:
payload = TuyaTimePayload()
utc_now = datetime.datetime.utcnow()
now = datetime.datetime.now()
offset_time = datetime.datetime(self.set_time_offset, 1, 1)
offset_time_local = datetime.datetime(self.set_time_local_offset, 1, 1)
utc_timestamp = int((utc_now - offset_time).total_seconds())
local_timestamp = int((now - offset_time).total_seconds())
payload.extend(utc_timestamp.to_bytes(4, "big", signed=False))
payload.extend(local_timestamp.to_bytes(4, "big", signed=False))
self.create_catching_task(
self.command(TUYA_SET_TIME, payload, manufacturer=foundation.ZCLHeader.NO_MANUFACTURER_ID, expect_reply=False)
)
return foundation.Status.SUCCESS
class TuyaNousE6TempHumiditySensor(CustomDevice):
"""Custom device representing tuya temp and humidity sensor with a screen (NOUS E6)."""
signature = {
# <SimpleDescriptor endpoint=1, profile=260, device_type=81
# device_version=1
# input_clusters=[4, 5, 61184, 0]
# output_clusters=[25, 10]>
MODELS_INFO: [("_TZE200_nnrfa68v", "TS0601")],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.SMART_PLUG, # this is how the device reports itself
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TemperatureHumidityManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id],
}
},
}
replacement = {
SKIP_CONFIGURATION: True,
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
INPUT_CLUSTERS: [
Basic.cluster_id,
TemperatureHumidityManufCluster, # Single bus for temp, humidity, and battery
TuyaTemperatureMeasurement,
TuyaRelativeHumidity,
TuyaPowerConfigurationCluster2AAA,
],
OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id],
}
},
} |
Which param are you trying to set? And where do these attributes come from?: 0x8001: ("temp_unit_convert", t.enum8),
0x8002: ("alarm_max_temperature", t.Single),
0x8003: ("alarm_min_temperature", t.Single),
0x8004: ("temperature_sensitivity", t.Single), Any settings you want to modify must be done through the PS: you can color your code if:
|
Ummmm, I think I see what you're trying to... Add the attributes to the cluster class TemperatureHumidityManufCluster(TuyaMCUCluster):
"""Tuya Manufacturer Cluster with Temperature and Humidity data points."""
attributes = TuyaMCUCluster.attributes.copy()
attributes.update(
{
0x8001: ("temp_unit_convert", t.enum8),
0x8002: ("alarm_max_temperature", t.Single),
0x8003: ("alarm_min_temperature", t.Single),
0x8004: ("temperature_sensitivity", t.Single),
}
)
.../... Device report logs with the datapoints may be helpful. |
Hi, also i'm a senior developper i started the zigbee and homeassistant adventure only yesterday, so i apologize if i'mbeing noob. I installed the above quirk in haos 8.5 and it works thank you very much. Without you i should have returned my device. However i was wondering why did i have to go to the device and make the pairing again so it began to work. before that, the humidy and temperature where marked as unavailable. is it specific to haos ? When we edit a quirk, beside reloading haos must i always redo the pairing ? thank you again. |
If the device never have reported one attribute ZHA is not knowing it. Normal is not needed repairing device but repower can being good for most devices with Exceptions. With python you shall always deleting the generated cash folder then editing the file before restarting HA. |
Thanks a lot for the quirk, I see now correct sensor values from the NOUS E6 thermostat. Sadly I only get few updates... The temperature on the device has to get at least 0.6 °C lower or higher for device to notify HA with an updated value. Same for humidity sensor, few updates. Is there a way to configure the device regarding sensitivity ? |
Trying to configure temperature sensitivity in device management, I select "TuyaTemperatureMeasurement (Endpoint id: 1, Id: 0x0402, Type: in)" cluster, then "temperature_sensitivity (id: 0x8004)" in attributes list, set value to 0.1 but I miss the manufacturer replacing code on the next input. |
I have just tried to update the sensitivity (using the quirk from @RhavoX - great stuff, thanks!) and it works more or less fine for me. It seems not to always update after a 0.1 degree change, but much more often as can be seen in the screenshots I have now set it to 0.2 and will let let it run for a few days. |
Which value returns the cluster if you try to read the attribute again? It returns the same you set? |
Yes, I tried this for both devices. It always returns the value I have set. E.g. first I tried |
I've tried that and at least for me it does not work. It reports 0.2 in the read value but it's still at the default 0.6 if I look at the logs. Tried this as well: https://community.home-assistant.io/t/report-configuration-of-a-sleepy-device-with-zha-toolkit/384617 My service call looks like this: service: zha_toolkit.conf_report
data:
ieee: sensor.thermometer_01_temperature
endpoint: 1
cluster: 0x0402
attribute: 0
min_interval: 5
max_interval: 300
reportable_change: 10
tries: 100
event_done: zha_done |
Thanks @RhavoX for complete current version of the quirk above, works flawlessly. Thanks @spandi for the sensitivity tweak above. FWIW, it looks like humidity metrics reporting is dragging a bit too (75% -> 74% -> 72% is yet to be reported as I'm writing this). Also I don't see any automatic changes to sensitivity parameter as reported above (at least as seen from HASS). Probably different device revisions somehow? @spandi, per your comment with tests, am I missing something and there's humidity sensitivity parameter, or do you assume that temperature_sensitivity controls bove humidity and temperature? |
@markuskonojacki I have the same behaviour. I think "writing" the 0.2 value in temperature_sensitivity is just doing it locally in HA memory state for the device. When using tre "out" clusters I can see HA issuing some commands to the device, but temperature is an "in" cluster and does not send any command/attribute update ?... |
Hello, I am brand new to Home Assistant. I just manage to get things working which do work ^out of the box^. However sadly enough, this device does not :( The device seems to be developed for tuya, what is as I see it now is a bad thing (I do not like to have my home controlled from china). I have a clean install of Home Assistant without any connection which a cloud service and I would like to keep it that way. I have a ^clean^ Home Assistant system with an USB-zigbee-stick. The device is recognized on zigbee level, but does not work. So what to do:
Could some one give me a hand / explain? |
Hello @LouisAtGH , |
Thanks, but probably very stupid, but I really have no idea how to do that from the GUI :( |
@LouisAtGH Here's a guide on how to do this: https://github.com/home-assistant/home-assistant.io/pull/23884/files#diff-f6bd4d42fd2565238968333a466474a25384fb4eecddc0235902e5ff5e798c8dR422-R435 |
I was afraid of that. In general ..... the Home Assistant GUI could use ^some^ improvements. So I need SSH. I already did a first trail to se up SSH. But I am afraid that I have to do that from the command line as well. Including generating a key etc. After searching the internet, I will probably manage that, but oh oh oh oh ..... it could and should be so much simpler ... |
Well, it's not an issue of Home Assistant per se (apart from lack of docs may be) The thing is that the device in question (NOUS E6) is quite new and, on top of that, doesn't follow the standard way for communication. And obviously HA (or Hence, HA clearly (at least in from my perspective) separates between "supported" and "do-it-yourself" kind of integrations, with former being supported in GUI quite well, and the latter requering some direct tinkering with underlying configuration files. It shouldn't be hard to do by yourself, so give it a shot. The instructions above and complete quirk code from here should be enough to do that. (Sorry for a bit of off-topic everyone) |
Thanks after taking a lot of steps, I managed to get this device working. I will describe those steps in the forum as reaction on my help request today. https://community.home-assistant.io/t/how-to-define-an-unsupported-device-starting-with-a-fresh-home-assistant-install/510150. However one thing is still unclear to me that is every thing written here about "Manage Zigbee Device and clusters. I searched in the gui and on the internet .... can not find how to reach those settings .... |
So far I used #1702 (comment) but the most recent Home Assistant update (2023.3.0) seems to have broken it. Thanks to the error I got my whole ZigBee integration stopped working so I removed the quirk for now. This was the error I got: Does anyone know whats up with that? I'm using the If this is the wrong project/issue to report this in, please let me know and I'll go where-ever else is appropriate. It's just that I originally found the quirk here and it worked perfectly for so long :D |
Hi, yep got hit by that too :) """Tuya temp and humidity sensor with screen."""
from typing import Dict
################## clean this up
import zigpy.types as t
from zigpy.zcl import foundation
from zhaquirks.tuya import TuyaTimePayload, TuyaCommand, TuyaDPType
import datetime
from typing import Tuple, Optional, Union
##################
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import Basic, Groups, Ota, Scenes, Time, AnalogOutput
from zigpy.zcl.clusters.measurement import RelativeHumidity, TemperatureMeasurement
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
SKIP_CONFIGURATION,
)
from zhaquirks.tuya import TuyaLocalCluster, TuyaPowerConfigurationCluster2AAA
from zhaquirks.tuya.mcu import DPToAttributeMapping, TuyaMCUCluster
TUYA_SET_TIME = 0x24
# NOTES:
# The data comes in as a string on cluster, if there is nothing set up you may see these lines in the logs:
# Unknown message (b'19830100a40102000400000118') on cluster 61184: unknown endpoint or cluster id: 'No cluster ID 0xef00 on (a4:c1:38:d0:18:8b:64:aa, 1)'
# 28.0 degrees
# Unknown message (b'19840100a5020200040000022c') on cluster 61184: unknown endpoint or cluster id: 'No cluster ID 0xef00 on (a4:c1:38:d0:18:8b:64:aa, 1)'
# 55.6% humid
# Unknown message (b'19850100a60402000400000064') on cluster 61184: unknown endpoint or cluster id: 'No cluster ID 0xef00 on (a4:c1:38:d0:18:8b:64:aa, 1)'
# 100% battery
class TemperatureUnitConvert(t.enum8):
"""Tuya Temp unit convert enum."""
Celsius = 0x00
Fahrenheit = 0x01
class TuyaTemperatureMeasurement(TemperatureMeasurement, TuyaLocalCluster):
"""Tuya local TemperatureMeasurement cluster."""
attributes = TemperatureMeasurement.attributes.copy()
attributes.update(
{
0x8001: ("temp_unit_convert", t.enum8),
0x8002: ("alarm_max_temperature", t.Single),
0x8003: ("alarm_min_temperature", t.Single),
0x8004: ("temperature_sensitivity", t.Single),
}
)
class TuyaRelativeHumidity(RelativeHumidity, TuyaLocalCluster):
"""Tuya local RelativeHumidity cluster."""
class TemperatureHumidityManufCluster(TuyaMCUCluster):
"""Tuya Manufacturer Cluster with Temperature and Humidity data points."""
dp_to_attribute: Dict[int, DPToAttributeMapping] = {
1: DPToAttributeMapping(
TuyaTemperatureMeasurement.ep_attribute,
"measured_value",
converter=lambda x: x * 10, # decidegree to centidegree
),
2: DPToAttributeMapping(
TuyaRelativeHumidity.ep_attribute,
"measured_value",
converter=lambda x: x * 100, # 0.01 to 1.0
),
4: DPToAttributeMapping(
TuyaPowerConfigurationCluster2AAA.ep_attribute,
"battery_percentage_remaining",
converter=lambda x: x * 2, # reported percentage is doubled
),
9: DPToAttributeMapping(
TuyaTemperatureMeasurement.ep_attribute,
"temp_unit_convert",
converter=lambda x: TemperatureUnitConvert(x)
),
10: DPToAttributeMapping(
TuyaTemperatureMeasurement.ep_attribute,
"alarm_max_temperature",
converter=lambda x: x / 10
),
11: DPToAttributeMapping(
TuyaTemperatureMeasurement.ep_attribute,
"alarm_min_temperature",
converter=lambda x: x / 10
),
19: DPToAttributeMapping(
TuyaTemperatureMeasurement.ep_attribute,
"temperature_sensitivity",
converter=lambda x: x / 10
)
}
set_time_offset = 1970
set_time_local_offset = 1970
data_point_handlers = {
1: "_dp_2_attr_update",
2: "_dp_2_attr_update",
4: "_dp_2_attr_update",
9: "_dp_2_attr_update",
10: "_dp_2_attr_update",
11: "_dp_2_attr_update",
19: "_dp_2_attr_update",
}
def handle_set_time_request(self, sequence_number: t.uint16_t) -> foundation.Status:
payload = TuyaTimePayload()
utc_now = datetime.datetime.utcnow()
now = datetime.datetime.now()
offset_time = datetime.datetime(self.set_time_offset, 1, 1)
offset_time_local = datetime.datetime(self.set_time_local_offset, 1, 1)
utc_timestamp = int((utc_now - offset_time).total_seconds())
local_timestamp = int((now - offset_time).total_seconds())
payload.extend(utc_timestamp.to_bytes(4, "big", signed=False))
payload.extend(local_timestamp.to_bytes(4, "big", signed=False))
self.create_catching_task(
self.command(TUYA_SET_TIME, payload, manufacturer=foundation.ZCLHeader.NO_MANUFACTURER_ID, expect_reply=False)
)
return foundation.Status.SUCCESS
class TuyaNousE6TempHumiditySensor(CustomDevice):
"""Custom device representing tuya temp and humidity sensor with a screen (NOUS E6)."""
signature = {
# <SimpleDescriptor endpoint=1, profile=260, device_type=81
# device_version=1
# input_clusters=[4, 5, 61184, 0]
# output_clusters=[25, 10]>
MODELS_INFO: [("_TZE200_nnrfa68v", "TS0601")],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.SMART_PLUG, # this is how the device reports itself
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TemperatureHumidityManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id],
}
},
}
replacement = {
SKIP_CONFIGURATION: True,
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
INPUT_CLUSTERS: [
Basic.cluster_id,
TemperatureHumidityManufCluster, # Single bus for temp, humidity, and battery
TuyaTemperatureMeasurement,
TuyaRelativeHumidity,
TuyaPowerConfigurationCluster2AAA,
],
OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id],
}
},
} |
Wow, that was fast. It works too! Thank you 😄 |
I am using the code from 3/2/2023. Thanks very much. Everything is working fine so far. I would like to add the following information: It takes a moment for the time to appear on the display. The temperature values and humidity values are sent in Home Assistant. Only the status of the battery is still unknown. This value will hopefully be achievable in the near future. I'll wait and have a coffee first. Great work |
I, too, have my own quirk for this issue - and it addresses also #1286. I have compressed all essential changes to a single standalone script that can be used for testing: https://github.com/Any-berg/zha-device-handlers/blob/standalone/zhaquirks/nous/ts0601.py My actual fork relies on some changes and additions to Tuya scripts: https://github.com/Any-berg/zha-device-handlers Based on my own testing with a different Nous sensor, there are no remaining problems to fix. Time synchronization and device configuration through attributes works well after |
Using zigbee2mqtt I was able to change the parameter temperature_sensitivity to 0.1. Now I get updates for every little temperature changes :-) Tip: if you want to switch to zigbee2mqtt, have a look at "network_key" in "advanced" section of the configuration, this might save you some time, as the default key is not secured and changing the key requires re-pairing all devices. |
Hello, |
Thanks, certainly helped me to get my T&H sensor added in ZHA. Working like a charm now. |
Thank you so much!! works great!! |
Same here. I also tried the same but it seems there is no library for TuyaPowerConfigurationCluster3AAA. |
All tuya Power cluster si made for the MCU TRVs and adding the battery types to them. zha-device-handlers/zhaquirks/__init__.py Lines 180 to 193 in 93ca50a
|
Hi, I got one issue with the quirk. Everything works great, apart from the time. I'm UTC+1, but the device is being set to UTC-1. Could there be a sign issue? Thanks in advance! EDIT: we had winter time shift now. Turns out it's just displaying UTC, not the local time... |
There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions. |
Is your feature request related to a problem? Please describe.
The NOUS E6 Thermometer and Humidity sensor does not provide any values, as well as the time on it is not synced.
I have modified the current sensor quirk a bit and made temperature, humidity and battery level work. Whatever I do though the time synchronization has no effect. In this issue I will provide the code I have now, maybe someone will have some ideas :)
I have also checked the tuya zigbee communication spec but I didn't find anything useful there.
Describe the solution you'd like
I would like for the device to be officially supported :). And maybe additionally to suport the time sync feature.
Device signature
Diagnostic information
Additional logs
Additional context
Here is the page with the device info: https://noussmart.pl/product/e6.html
Here is the code I for the test quirk:
The text was updated successfully, but these errors were encountered: