X-Sense Security - is it possible to create an integration?

SC07-WX ISSUES/MISSING FEATURES/SUGGESTIONS

Just purchased two SC07-WX smoke/CO alarms for my small business because of the existence of this integration (thank you @theosnel and @Jarnsen!). Would like to buy more of them, start setting up automations and ditch the X-Sense app eventually. I see a few issues and missing features, some of which have already been discussed here, but I wanted to put them all together in a post for new people intending to buy this device and to use it with HA:

  • HA entities don’t get updated fast enough for an emergency device (minutes of delay!): as a workaround I set DEFAULT_SCAN_INTERVAL=15 in custom_components/xsense/const.py
  • No silence button
  • No test button and test status
  • The Alarm Status entity actually represents the presence/absence of smoke and not of a generic alarm: therefore it should probably be renamed and assigned class “Smoke”, given an appropriate icon and moved from the diagnostic to the sensors section. I tested this by triggering a CO alarm and observing the entity remaining Off (Carbon monoxide entity showing ~900ppm)
  • Testing whether the entity with the same name as the device (plug icon) represents the online/offline status: if so it should probably be named accordingly
  • Battery entity in diagnostic section?
  • No local control :smiley:

HA version is 2025.5.3

1 Like

Seeing this thread bumped reminded me. I have the SSL51 spotlights. In the app, there are options to have the lights come on when motion is detected, schedule them, etc.

But there is also a toggle to just turn the light on or off. Wondering if we could pull that over here.

I don’t know much about coding but could provide logs to help.

You can put automation together. When Alarm goes off, turn lights on, and if they are rgb lights you can make them change color and flash or flicker

I submitted a PR to fix your #4 (sensor categorizations), but it was ignored by devs. Wasn’t going to land it without approval.

1 Like

Maybe they weren’t able to run or weren’t presented with empirical tests to confirm the actual meaning of the entity. A bag tied to the exhaust of my car with the sensor inside reveals the correct meaning :smile:

@theosnel @Jarnsen Can people donate anywhere to the project?

The entity with the plug icon for the SC07-WX doesn’t seem to represent online/offline status. It is On even when the device is Offline in the X-Sense app. It only turns Off for a short while when reloading the integration. Does it only represent connection to the X-Sense cloud from HA?

And since there is no generic (smoke or CO) alarm status entity, one may be created with a simple binary sensor template such as

{{ states("binary_sensor.smoke_co_sensor_smoke") == "on" or states("sensor.smoke_co_sensor_carbon_monoxide")|float > 30 }}

This however does not represent the true alarm status, since you can have CO > 30ppm for a while before the CO alarm is triggered. In fact, there is also a “CO Alarm Precaution” state that may be entered before the actual alarm.

I’m seeing the same, can’t get XS-01WX to work with Home Assistant.

  1. HA core 2025.7.1
  2. python-xsense==0.0.16
  3. Integration version v.1.0.16

Tested with 1x and 2x connected units - authentication is OK, all devices show up in HA with all entities, but during a “real” alarm (not with a test button) the Alarm Status never changes.

X-Sense app notifications are working fine, alarm is detected.

Below are the messages recieved from MQTT (in async_event_received) - can see that alarmStatus does change from 0 to 1, but the entity in HA is not updated.

2025-07-11 18:51:32.688 ERROR (MainThread) [custom_components.xsense] // DBG data {'clientId': 'XS01-WX00540CAE', 'timestamp': 1752285092636, 'eventType': 'connected', 'sessionIdentifier': 'be919899-3f5e-420e-afbf-8d82e54b577c', 'principalIdentifier': '3a6111888a80d1271db0f50482c0696c2f944969aa916b3a4078764d722c3bd7', 'ipAddress': '73.66.231.25', 'versionNumber': 6}
2025-07-11 18:51:33.342 ERROR (MainThread) [custom_components.xsense] // DBG data {'state': {'desired': {'shadow': 'sysTime', 'stationSN': '00540CAE'}, 'reported': {'type': 'XS01-WX', 'stationSN': '00540CAE', 'deleted': '0', 'sw': 'v1.1.0', 'wifiRSSI': '-40'}}, 'clientToken': '7321'}
2025-07-11 18:51:34.633 ERROR (MainThread) [custom_components.xsense] // DBG data {'state': {'reported': {'00540CAE': {'type': 'XS01-WX', 'stationSN': '00540CAE', 'deviceSN': '00540CAE', 'dismantle': '0', 'isAlarm': '1', 'reAlarm': '0', 'time': '20250712015141'}}}, 'clientToken': '8494'}
2025-07-11 18:51:35.862 ERROR (MainThread) [custom_components.xsense] // DBG data {'state': {'reported': {'type': 'XS01-WX', '_stationSN': '00540CAE', '_deviceSN': '00540CAE', 'sw': 'v1.1.0', 'ssid': 'wifiname_EXT', 'ip': '10.0.0.192', 'mac': '68:25:DD:E9:A7:A4', 'macBT': '68:25:DD:E9:A7:A6', 'swMain': 'v1.9.0', 'ledLight': '1'}}, 'clientToken': '9722'}
2025-07-11 18:51:36.078 ERROR (MainThread) [custom_components.xsense] // DBG data {'userId': '832933a2-b0ee-4625-9140-00de837664af', 'eventType': 'alarmDispatch', 'eventTime': '20250712015135', 'eventData': {'houseId': 'BEA9B3105E7C11F089D2C7EE1B5024EF', 'stationId': '967EE5885EBC11F0B504F769F3A9408A', 'stationSn': '00540CAE', 'deviceId': '967EE5885EBC11F0B504F769F3A9408A', 'deviceSn': '00540CAE', 'deviceType': 'XS01-WX', 'isAlarm': '1', 'alarmTime': '20250712015141', 'trainAlarmed': '0', 'eventItem': {'type': 'XS01-WX', 'stationSN': '00540CAE', 'deviceSN': '00540CAE', 'dismantle': '0', 'isAlarm': '1', 'reAlarm': '0', 'time': '20250712015141', 'deviceSn': '00540CAE', 'stationSn': '00540CAE'}}}
2025-07-11 18:51:37.039 ERROR (MainThread) [custom_components.xsense] // DBG data {'state': {'reported': {'00540CAE': {'type': 'XS01-WX', 'stationSN': '00540CAE', 'wifiRssi': '-32', 'batInfo': '3', 'time': '20250712015141', 'onlineTime': '20250712015141'}}}, 'clientToken': '10953'}
2025-07-11 18:51:38.319 ERROR (MainThread) [custom_components.xsense] // DBG data {'state': {'reported': {'00540CAE': {'houseId': 'BEA9B3105E7C11F089D2C7EE1B5024EF', 'type': 'XS01-WX', 'stationSN': '00540CAE', 'wifiRssi': '-32', 'batInfo': '3', 'time': '20250712015141', 'onlineTime': '20250712015141', 'status': {'alarmStatus': '1', 'muteStatus': '1', 'time': '20250712015141'}}}}, 'clientToken': '12186'}

For others struggling with XS-01WX, got it to work with it, but it probably breaks other things/devices, my goal was to get only my XS-01WX alarmStatus to update correctly.

In /home/homeassistant/.homeassistant/custom_components/xsense/coordinator.py

    def async_event_received(self, topic: str, data_str: bytes) -> None:
        """Handle incoming data from MQTT."""
        data = json.loads(data_str.decode("utf8"))
        LOGGER.error(f"// DATA {data}")
        reported = data.get("state", {}).get("reported", {})

        for station_sn, station_data in reported.items():
            station = self._get_station_by_id(station_sn)
            if not station:
                continue

            children = station_data.pop("devs", {})

            self.xsense.parse_get_state(station, station_data)
            for k, v in children.items():
                if dev := station.get_device_by_sn(k):
                    dev.set_data(v)

        self.async_update_listeners()

In /srv/homeassistant/lib/python3.13/site-packages/xsense/base.py

    def parse_get_state(self, station: Station, data: Dict):
        if 'wifiRSSI' in data:
            station.data['wifiRSSI'] = data['wifiRSSI']
        if 'status' in data:
            status = data['status']
            if isinstance(status, dict):
                alarm_status = status.get('alarmStatus')
                if alarm_status is not None:
                    station.data['alarmStatus'] = int(alarm_status)
                if 'muteStatus' in status:
                    station.data['muteStatus'] = status['muteStatus']
                if 'time' in status:
                    station.data['statusTime'] = status['time']  # optional, for clarity

        for sn, i in data.get('devs', {}).items():
            if dev := station.get_device_by_sn(sn):
                dev.set_data(i)

Now with “real” alarm, below two messages are correctly changing alarmStatus to 1 and 0 in HA:

// example of alarmStatus=1
2025-07-12 10:18:40.852 ERROR (MainThread) [custom_components.xsense] // DATA {'state': {'reported': {'00540CAE': {'houseId': 'BEA9B3105E7C11F089D2C7EE1B5024EF', 'type': 'XS01-WX', 'stationSN': '00540CAE', 'wifiRssi': '-71', 'batInfo': '3', 'time': '20250712171843', 'onlineTime': '20250712171843', 'status': {'alarmStatus': '1', 'muteStatus': '1', 'time': '20250712171843'}}}}, 'clientToken': '12482'}

// example of alarmStatus=0
2025-07-12 10:18:52.118 ERROR (MainThread) [custom_components.xsense] // DATA {'state': {'reported': {'00540CAE': {'houseId': 'BEA9B3105E7C11F089D2C7EE1B5024EF', 'type': 'XS01-WX', 'stationSN': '00540CAE', 'wifiRssi': '-71', 'batInfo': '3', 'time': '20250712171857', 'onlineTime': '20250712171857', 'status': {'alarmStatus': '0', 'muteStatus': '1', 'time': '20250712171857'}}}}, 'clientToken': '23750'}

2 Likes

I’m still missing the armed/disarmed state of the SBS50 in the HA integration :frowning:

1 Like

Just want to say a HUGE thank you! I can see all my LoRa Sensors and their status. Brilliant work :slight_smile:

Hi Guys

I have added a (new model?) smoke alarm:

XS0B-IR

Does this look correct? I assume “Alarm Status” goes to on if the smoke alarm is triggered. Does anyone know a way to test if this is working? The standard test (pressing the self-test button on the unit) doesn’t shift this sensor.

Otherwise i’ll try burn some paper :joy:

Sorry, iam very busy the last month and also now. But i will che the repo for pushs or somthing like that.

I merged the last pull.

Its Merged now

XS0E-iR smoke detector added.
I had to modify DEFAULT_SCAN_INTERVAL as suggested by @c-gabri since the alarm notification was too much delayed.

My system has worked flawlessly for months, but has problems this morning and I fear an API change. Am getting:

Failed setup, will retry: XSense API Issue: Unable to retrieve station data: 403/{"message":"Forbidden","traceId":"50b287e2-ad1e-f24f-7662-d728c8d05cc8"}.

There appears to be nothing wrong with the X-Sense system, as my iOS app is working fine.

I tried re-pulling the integration and restarting Home Assistant. I tried deleting the X-Sense hub and reconnecting. Neither helped.

I have enabled debug logging but honestly don’t know where to find the results. Nothing in the home-assistant,log, Where should I look for more details?

Hi,

I tried to reproduce it, but so far everything seems to work here. I’ve upgraded and restarted my home-assistant and tried to run python-xsense with my dev-account, which includes several environments of others. So far no errors.

However, I am currently travelling home from my holiday and am limited in what I can test.
Would it be possible to invite [email protected] to your environment? I suspect that a certain type of device has changed. I will try to have a look this weekend.

Done.

No hurry. I’m just thrilled you do this. Please let me know if there’s anything else I can to do to help.

I had hopes that it was my smart mailbox alarm, which might be a bit unusual. But I removed that device–leaving nothing except the common SBS50 hub and a few XPOA-MR and XSOB-MR. Still giving the error.

An getting exactly the same error, just reinstalled the reintegration and switched accounts. Didn’t with it for me to be honest:

XSense Account [email protected]
Instellen mislukt, wordt opnieuw geprobeerd:
XSense API Issue: Unable to retrieve station data: 403/{"message":"Forbidden","traceId":"0d2b6602-fbe4-ba24-8797-11991aadc5ed"}

I only own XS01-M smoke detectors, using an SBS-50 hub.

Edit: in my case, the whole problem was solved after syncing time; which turned out to be 10min out of sync.