Nexmosphere industrial quality sensors and Home Assistant

Hey! I wanted to test if https://www.nexmosphere.com/ industrial sensors, usually used for Brightsign mediaplayers would also work on home assistant. And they do!
Which is also useful for trying out the sensors before deploying them on Brightsign due you can see the raw values coming in. Or because their just cool sensors that guaranteed work out of the box.

So what I did:
XN-135 XPERIENCE CONTROLLER as main sensor interface via USB on a Raspberry Pi connected to Home Assistant. Works due pl2303 Driver for Prolific USB-to-Serial converters. (I used a RPi500+ home assistant install)

Add to configuration.yaml

sensor:
  - platform: serial
    name: "Nexmosphere Raw"
    serial_port: /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller_DZAQb106315-if00-port0
    baudrate: 115200

Than after a reboot this gives me the sensor.nexmosphere_raw
entity where all raw data comes in (when something happens).

By the way I found this serial port via HA > Settings > System > Hardware > All hardware > USB1
If it doesn’t match with your USB…

Then nexmospere has a range of sensors to buy: Products — Nexmosphere

I connected the XY-240 prescense detector and X-Eye Motion XY-320 radar to port A and B of the XN-135.
Manuals of the sensors can be found on the link above. For now their also here:

To make them work I added these sensors to configuration.yaml

template:
  # =========================
  # XY-240 (Distance / Presence)
  # =========================
  - trigger:
      - platform: state
        entity_id: sensor.nexmosphere_raw
        to: ~
    condition:
      - condition: template
        value_template: >
          {{ trigger.to_state.state.startswith('X002B[Dz=') }}
    binary_sensor:
      - name: "XY240 Presence"
        device_class: motion
        state: >
          {% set zone = trigger.to_state.state.split('Dz=')[1].replace(']', '') %}
          {{ zone != 'XX' }}
    sensor:
      - name: "XY240 Distance Zone"
        state: >
          {% set zone = trigger.to_state.state.split('Dz=')[1].replace(']', '') %}
          {% set mapping = {
            'AB': 'AirButton',
            '01': '10-25cm',
            '02': '25-50cm',
            '03': '50-75cm',
            '04': '75-100cm',
            '05': '100-125cm',
            '06': '125-150cm',
            '07': '150-175cm',
            '08': '175-200cm',
            '09': '200-225cm',
            '10': '225-250cm',
            'XX': 'Out of range'
          } %}
          {{ mapping.get(zone, zone) }}
  # =========================
  # XY-320 (Motion)
  # =========================
  - trigger:
      - platform: state
        entity_id: sensor.nexmosphere_raw
        to: ~
    condition:
      - condition: template
        value_template: >
          {{ trigger.to_state.state.startswith('X001A[') }}
    binary_sensor:
      - name: "XY320 Motion"
        device_class: motion
        state: >
          {% set amount = trigger.to_state.state.split('[')[1].replace(']', '') | int %}
          {{ amount > 0 }}
    sensor:
      - name: "XY320 Motion Amount"
        unit_of_measurement: "units"
        state: >
          {{ trigger.to_state.state.split('[')[1].replace(']', '') | int }}

After a reboot you can use the entities of these sensors.

Oh and I don’t know if its neccary but I excluded them from the recorder, because a lot of data is coming in constantly.

recorder:
  purge_keep_days: 365
  exclude:
    entities:
      - sensor.xy320_motion_amount
      - sensor.xy240_distance_zone
      - sensor.nexmosphere_raw

Talking back to change the settings of a sensor is possible like this:

shell_command:

XY-320: Size/Range of Detection Area

xy320_set_detection_area_1: ‘echo -ne “X001S[5:1]\r” > /dev/ttyUSB1’

XY-240: Range of Interest

xy240_set_roi_50: ‘echo -ne “X001S[6:50]\r” > /dev/ttyUSB1’

For your example commands:

  • Setting 6: Range of Interest → can be set via a command like X002B[RoI=X], where X = 1‑50 for XY‑240 (in units of 10 cm). Default 25 = 250 cm.
  • Setting 8: Hysteresis for distance zones → can be set via X002B[Hz=X], where X = 1‑250 cm. Default = 10 cm.
  • AirButton rangeX002B[AB=X], X = 1‑250 cm, default 10 cm.

The Reboot! And:

Use Developer Tools → Services

  1. Go to Developer Tools → Services in Home Assistant.
  2. Select the service shell_command.YOUR_COMMAND_NAME.
  3. Call each command manually, in order.

Works immediately, no scripts needed.

Since there is no feedback I don’t know if this works. Can also use Brightsign to set the value. Don’t know if it persists after reboot.

A real Nexmosphere integation made by someone would epic in this case :wink: