Skip to content
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

Smoke sensors are not seen as binary_sensors #43

Open
samuellazea opened this issue Feb 26, 2025 · 1 comment
Open

Smoke sensors are not seen as binary_sensors #43

samuellazea opened this issue Feb 26, 2025 · 1 comment

Comments

@samuellazea
Copy link

samuellazea commented Feb 26, 2025

Hello @jvitkauskas and @epoplavskis ,

I noticed that you are the authors and the maintainers for the https://pypi.org/project/pyit600/ . First of all I want to say that you guys done an amazing job and this helps me ( and other people :) ) lots. It's really appreciated.

Now the problem I see. I have homeassistant and I have installed the https://github.com/jvitkauskas/homeassistant_salus.
It all worked well for like a month. I have in there a gateway, some thermostats, some door sensors and some smoke sensors.

Now my problem, since a few days ( install was like a month ago ) I started to miss the smoke sensors. In HA they became unavailable. So I started to dig into it and wanted to see what was happening. I have to mention that the smoke sensors are online and available in the salus app.

So during my debugging I installed the pyit600 library ( had to do few minor changes to make it work. You can see #42 if you want ;) ) and then I started to debug to see what is going on. Here is part of the output:

`
root@32f54c65cdfe:/app/pyit600# python main.py --host 192.168.150.185 --euid xxxx--debug
DEBUG:pyit600:Trying to connect to gateway at 192.168.150.185
DEBUG:pyit600:Gateway request: POST http://192.168.150.185:80/deviceid/read
{"requestAttr": "readall"}

DEBUG:pyit600:Gateway response:
{
"id": [
{
"data": {
"DeviceType": 100,
"Endpoint": 1,
"UniID": "xxxx"
},
"sGenSche": {
"UpdateGenScheStatus": 0
},
"DeviceL": {
"DeviceType": 100,
"getModelIdentifierFlag_i": 1,
"DeviceSubType": 1026,
"UnquieID": "xxxx",
"ClusterIDList_i": "xxxx#",
"AttributeList": "xxxx",
"ModelIdentifier_i": "SmokeSensor-EM",
"DeviceEndpointNum_i": 1
},
"sZDO": {
"ProtocalType_i": 2,
"FirmwareVersion": "00000014",
"ShortID_d": xxxx,
"MACAddress": "xxxx",
"LeaveNetwork": 0,
"LeaveRequest_d": 0,
"DeviceName": "{"deviceName":"Senzor Fum Dormitor","ShortID_d":xxxx}"
},
"sBasicS": {
"ManufactureName": "HEIMAN",
"PowerSource": 3,
"ModelIdentifier": "SmokeSensor-EM",
"StackVersion_d": 2,
"ApplicationVersion_d": 20,
"HardwareVersion": "16"
},
"sEndpt": {
"DeviceType": 1026,
"Endpoint_i": 1
},
"sZDOInfo": {
"JoinConfigEnd": 0,
"OnlineStatus_i": 1
},
"sOTA": {
"OTAStatus_d": 0
},
"sPowerS": {
"BatteryVoltage_x10": 30
}
},
{
"data": {
"DeviceType": 100,
"Endpoint": 1,
"UniID": "xxxx"
},
"sGenSche": {
"UpdateGenScheStatus": 0
},
"DeviceL": {
"DeviceType": 100,
"getModelIdentifierFlag_i": 1,
"DeviceSubType": 1026,
"UnquieID": "xxxx",
"ClusterIDList_i": "xxxx#",
"AttributeList": "xxxx",
"ModelIdentifier_i": "SW600",
"DeviceEndpointNum_i": 1
},
"sZDO": {
"JoinConfigVersion_i": "240329",
"ProtocalType_i": 2,
"FirmwareVersion": "20240103",
"ShortID_d": xxxx,
"MACAddress": "xxxx",
"LeaveNetwork": 0,
"LeaveRequest_d": 0,
"DeviceName": "{"deviceName":"Usa Depozitare","ShortID_d":xxxx}"
},
"sBasicS": {
"ManufactureName": "SALUS",
"PowerSource": 3,
"ModelIdentifier": "SW600",
"ApplicationVersion_d": 1,
"HardwareVersion": "0"
},
"sEndpt": {
"DeviceType": 1026,
"Endpoint_i": 1
},
"sZDOInfo": {
"JoinConfigEnd": 1,
"zigbeeOTAFailDebugCode_i": 2304,
"OnlineStatus_i": 1,
"zigbeeOTArespond_i": 0,
"zigbeeOTATimeout_i": 4800
},
"sOTA": {
"OTAStatus_d": 0,
"OTAFirmwareURL_d": "xxxx"
},
"sIASZS": {
"ZoneStatus_d": 0,
"ErrorIASZSTrouble": 0,
"ErrorIASZSTampered": 0,
"ErrorIASZSAlarmed1": 0,
"ErrorIASZSLowBattery": 0,
"ErrorIASZSAlarmed2": 0,
"ErrorIASZSACFault": 0,
"ZoneState_d": 1
},
"sPowerS": {
"BatteryVoltage_x10": 29,
"BatteryVolThreshold3_x10_d": 25,
"ErrorPowerSLowBattery": 0,
"ErrorBatteryAlarmState_d": 0,
"BatteryVolThreshold_x10_d": 21,
"BatteryAlarmMask_d": 0,
"BatteryVolThreshold1_x10_d": 22,
"BatteryVolThreshold2_x10_d": 23
},
"sTempS": {
"MeasuredValue_x100": 2495
}
},

...................................................................

All binary sensor devices:
{'xxxx': BinarySensorDevice(available=True, name='Usa Depozitare', unique_id='xxxx', is_on=False, device_class='window', data={'DeviceType': 100, 'Endpoint': 1, 'UniID': 'xxxx'}, manufacturer='SALUS', model='SW600', sw_version='20240103'), 'xxxx': BinarySensorDevice(available=True, name='Usa Living', unique_id='xxxx', is_on=False, device_class='window', data={'DeviceType': 100, 'Endpoint': 1, 'UniID': 'xxxx'}, manufacturer='SALUS', model='SW600', sw_version='20240103'), 'xxxx': BinarySensorDevice(available=True, name='Usa Dormitor', unique_id='xxxx', is_on=False, device_class='window', data={'DeviceType': 100, 'Endpoint': 1, 'UniID': 'xxxx'}, manufacturer='SALUS', model='SW600', sw_version='20240103')}
Binary sensor device xxxx status:
BinarySensorDevice(available=True, name='Usa Depozitare', unique_id='xxxx', is_on=False, device_class='window', data={'DeviceType': 100, 'Endpoint': 1, 'UniID': 'xxxx'}, manufacturer='SALUS', model='SW600', sw_version='20240103')
'Usa Depozitare' is on: False

.............................

`

Now I tried to find out why is this happening. Looking at the gateway code I see this

`
async def _refresh_binary_sensor_devices(self, devices: List[Any], send_callback=False):
local_devices = {}

    if devices:
        status = await self._make_encrypted_request(
            "read",
            {
                "requestAttr": "deviceid",
                "id": [{"data": device["data"]} for device in devices]
            }
        )

        for device_status in status["id"]:
            unique_id = device_status.get("data", {}).get("UniID", None)

            if unique_id is None:
                continue

            try:
                model: Optional[str] = device_status.get("DeviceL", {}).get("ModelIdentifier_i", None)
                if model in ["it600MINITRV", "it600Receiver"]:
                    is_on: Optional[bool] = device_status.get("sIT600I", {}).get("RelayStatus", None)
                else:
                    is_on: Optional[bool] = device_status.get("sIASZS", {}).get("ErrorIASZSAlarmed1", None)

.............................................................................................................................................................................

    try:
        binary_sensors = list(
            filter(lambda x: "sIASZS" in x or
                             ("sBasicS" in x and
                              "ModelIdentifier" in x["sBasicS"] and
                              x["sBasicS"]["ModelIdentifier"] in ["it600MINITRV", "it600Receiver"]), all_devices["id"])
        )

............................................................................................................................................................................................

`

In my case based on the output of the debug call from above my you can see that the smoke sensor doesn't have the "sIASZS" and in "sBasicS" the ModelIdentifier is not part of ["it600MINITRV", "it600Receiver"]. This means that my smoke sensor doesn't meet the criteria and it's excluded from start.

In order to add it in there I had to add the smoke sensor in the ModelIdentifier list like so:

try: binary_sensors = list( filter(lambda x: "sIASZS" in x or ("sBasicS" in x and "ModelIdentifier" in x["sBasicS"] and x["sBasicS"]["ModelIdentifier"] in ["it600MINITRV", "it600Receiver", "SmokeSensor-EM"]), all_devices["id"]) )

So now we are a step further cause he sees them in the _refresh_binary_sensor_devices

async def _refresh_binary_sensor_devices(self, devices: List[Any], send_callback=False): local_devices = {} _LOGGER.debug(f"!!!!!!! _refresh_binary_sensor_devices: {devices}")

But it's still excluded because of this

try: model: Optional[str] = device_status.get("DeviceL", {}).get("ModelIdentifier_i", None) if model in ["it600MINITRV", "it600Receiver"]: is_on: Optional[bool] = device_status.get("sIT600I", {}).get("RelayStatus", None) elif model == "SmokeSensor-EM": is_on = 0 # temporary indicates the alarm state else: is_on: Optional[bool] = device_status.get("sIASZS", {}).get("ErrorIASZSAlarmed1", None)

After adding the
elif model == "SmokeSensor-EM":
is_on = 0 # temporary indicates the alarm state

I get the smoke sensors in the list. Please note that is_on = 0 is just temporary to test why the smoke sensors were not in the list. At this moment I don't have physical access to the smoke sensors to trigger one and see what data I get in the response so I can track the correct alarm state.
The moment I can trigger one I will update here the issue.

Hopefully I made myself understood from all of this digging and debugging.
Please let me know if there is anything else I can do or do so we can get this fixed somehow ( of course if you guys agree with my above tryouts ;) )

Thank you and looking forward for your feedback

@samuellazea
Copy link
Author

As promised I come back with more debugging info.
I have managed to trigger a smoke sensor and then the info I got is this

`

"data": {
"DeviceType": 100,
"Endpoint": 1,
"UniID": "xxx"
},
"sGenSche": {
"UpdateGenScheStatus": 0
},
"DeviceL": {
"DeviceType": 100,
"getModelIdentifierFlag_i": 1,
"DeviceSubType": 1026,
"UnquieID": "xxx",
"ClusterIDList_i": "xxx#",
"AttributeList": "xxx",
"ModelIdentifier_i": "SmokeSensor-EM",
"DeviceEndpointNum_i": 1
},
"status": "success",
"sZDO": {
"ProtocalType_i": 2,
"FirmwareVersion": "00000014",
"ShortID_d": xxx,
"MACAddress": "xxx",
"LeaveNetwork": 0,
"LeaveRequest_d": 0,
"DeviceName": "{"deviceName":"Senzor Fum Bucatarie","ShortID_d":xxx}"
},
"sBasicS": {
"ManufactureName": "HEIMAN",
"PowerSource": 3,
"ModelIdentifier": "SmokeSensor-EM",
"StackVersion_d": 2,
"ApplicationVersion_d": 20,
"HardwareVersion": "16"
},
"sEndpt": {
"DeviceType": 1026,
"Endpoint_i": 1
},
"sZDOInfo": {
"JoinConfigEnd": 0,
"OnlineStatus_i": 1
},
"sOTA": {
"OTAStatus_d": 0
},
"sPowerS": {
"BatteryVoltage_x10": 30
},
"sIASZS": {
"ZoneStatus_d": 32,
"ErrorIASZSTampered": 0,
"ErrorIASZSTrouble": 0,
"ErrorIASZSAlarmed1": 0,
"ErrorIASZSLowBattery": 0,
"ErrorIASZSAlarmed2": 0,
"ErrorIASZSACFault": 0
}
},

`

Basically here you can see a difference between a smoke sensor that was not triggered and one that was triggered

Image

So I went ahead and changed to this in my code

`

            try:
                model: Optional[str] = device_status.get("DeviceL", {}).get("ModelIdentifier_i", None)
                if model in ["it600MINITRV", "it600Receiver"]:
                    is_on: Optional[bool] = device_status.get("sIT600I", {}).get("RelayStatus", None)
                **elif model == "SmokeSensor-EM":
                    # First try to get the standard alarm attribute
                    is_on = Optional[bool] = device_status.get("sIASZS", {}).get("ErrorIASZSAlarmed1", None)
                    # If it doesn't exist, default to 0 (not alarmed)
                    if is_on is None:
                        is_on = 0**
                else:
                    is_on: Optional[bool] = device_status.get("sIASZS", {}).get("ErrorIASZSAlarmed1", None)
                if is_on is None:
                    continue
                if model == "SB600":
                    continue  # Skip button
                device = BinarySensorDevice(
                    available=True if device_status.get("sZDOInfo", {}).get("OnlineStatus_i", 1) == 1 else False,

`

Please let me know what you think about this and if you agree with this I would be happy to create a PR for this. Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant