Tuya Zigbee TS0202 detector de presencia integrarlo en Home Assistant

Hoy integrare un detector de movimiento Zigbee TS0202 que normalmente anda por 10 – 15€ , pero aprovechando el tema de 3 artículos de aliexpress lo he comprado aquí por 2,99€

Este seria el sensor

La verdad es que es alucinante que en una semana llegue a casa , esta es la caja que contiene el sensor de movimiento

Y este es el contenido de dicha caja

Para ponerlo en marcha abriremos la tapa trasera y quitaremos la tira que evita que consuma hasta que llegue a nuestras manos

Ahora es el turno de enlazarlo con Zigbee2MQTT ,para ello primero pondremos Zigbee2MQTT en modo join , aqui podeis encontrar mas informacion de este sensor

Pulsaremos en botón de emparejamiento del sensor durante diez segundos hasta que empiece a parpadear

En el fichero configuration.yaml nos aparecerá el nuevo dispositivo al cual le asignaremos una etiqueta en friendly_name

  '0x00158d0003993ecf':
    friendly_name: '0x00158d0003993ecf'
  '0xa4c138e7e26ebe23':
    friendly_name: 'sensor_proximidad_cocina'

Reiniciamos el docker y veremos que no nos lo detecta . este problema esta bien explicado aquí , para solventarlo haremos lo siguiente :

Grabamos el siguiente condigo en un fichero llamado ext_converter.js teniendo en cuenta los valores del log

"manufacturer":"_TZ3000_6ygjfyll","model_id":"TS0202"
const fz = require('zigbee-herdsman-converters/converters/fromZigbee');
const tz = require('zigbee-herdsman-converters/converters/toZigbee');
const exposes = require('zigbee-herdsman-converters/lib/exposes');
const reporting = require('zigbee-herdsman-converters/lib/reporting');
const extend = require('zigbee-herdsman-converters/lib/extend');
const ota = require('zigbee-herdsman-converters/lib/ota');
const tuya = require('zigbee-herdsman-converters/lib/tuya');
const e = exposes.presets;
const ea = exposes.access;

const definition = {
    fingerprint: [{modelID: 'TS0202', manufacturerName: '_TZ3000_6ygjfyll'},
        {modelID: 'TS0202', manufacturerName: '_TZ3000_6ygjfyll'},
        {modelID: 'TS0202', manufacturerName: '_TZ3000_6ygjfyll'}],
    model: 'TS0202_1',
    vendor: 'TuYa',
    description: 'Motion sensor',
    // Requires alarm_1_with_timeout https://github.com/Koenkk/zigbee2mqtt/issues/2818#issuecomment-776119586
    fromZigbee: [fz.ias_occupancy_alarm_1_with_timeout, fz.battery, fz.ignore_basic_report],
    toZigbee: [],
    exposes: [e.occupancy(), e.battery_low(), e.linkquality(), e.battery(), e.battery_voltage()],
    configure: async (device, coordinatorEndpoint, logger) => {
        const endpoint = device.getEndpoint(1);
        await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
        await reporting.batteryPercentageRemaining(endpoint);
    },
};

module.exports = definition;

y añadimos estas dos líneas al fichero configuration.yaml

external_converters:
  - ext_converter.js

Reiniciaremos el Docker y debería funcionar correctamente enviando la información y los cambios de estado por MQTT

ACTUALIZACION : En la ultima versión de zigbee2mqtt ya viene implementado este sensor directamente

Empezaremos creando en configuration.yaml nuestros sensores

  ### SENSOR MOVIMIENTO COCINA
  
    - state_topic: "zigbee2mqtt/sensor_proximidad_cocina"
      availability_topic: "zigbee2mqtt/bridge/state"
      unit_of_measurement: "mV"
      icon: "mdi:battery"
      device_class: "battery"
      value_template: "{{ (value_json.voltage | float(0)) }}"
      expire_after: 21600
      force_update: true
      name: "sensor_movimiento_cocina_voltaje"
      
    - state_topic: "zigbee2mqtt/sensor_proximidad_cocina"
      availability_topic: "zigbee2mqtt/bridge/state"
      unit_of_measurement: "%"
      icon: "mdi:battery"
      device_class: "battery"
      value_template: "{{ (value_json.battery | int(0)) }}"
      expire_after: 21600
      force_update: true
      name: "sensor_movimiento_cocina_bateria"

    - state_topic: "zigbee2mqtt/sensor_proximidad_cocina"
      availability_topic: "zigbee2mqtt/bridge/state"
      icon: "mdi:tune"
      unit_of_measurement: "lqi"
      value_template: "{{ value_json.sensitivity }}"
      name: "sensor_movimiento_cocina_sensibilidad"

    - state_topic: "zigbee2mqtt/sensor_proximidad_cocina"
      availability_topic: "zigbee2mqtt/bridge/state"
      icon: "mdi:tune"
      unit_of_measurement: "Seg."
      value_template: "{{ value_json.keep_time }}"
      name: "sensor_movimiento_cocina_mentener_tiempo"
      
    - state_topic: "zigbee2mqtt/sensor_proximidad_cocina"
      availability_topic: "zigbee2mqtt/bridge/state"
      icon: "mdi:signal"
      unit_of_measurement: "lqi"
      value_template: "{{ value_json.linkquality }}"
      name: "sensor_movimiento_cocina_estado"
  

Y nuestros binary_sensors :

    # SENSOR MOVIMIENTO COCINA
    - state_topic: "zigbee2mqtt/sensor_proximidad_cocina"
      availability_topic: "zigbee2mqtt/bridge/state"
      payload_on: true
      payload_off: false
      value_template: "{{ value_json.occupancy }}"
      device_class: "motion"   
      name: sensor_movimiento_cocina_evento      
      off_delay: 120       
   
    - state_topic: "zigbee2mqtt/sensor_proximidad_cocina"
      availability_topic: "zigbee2mqtt/bridge/state"
      payload_on: true
      payload_off: false
      value_template: "{{ value_json.battery_low }}"
      device_class: "battery"   
      name: sensor_movimiento_bateria_baja_evento      
      off_delay: 120 
   
    - state_topic: "zigbee2mqtt/sensor_proximidad_cocina"
      availability_topic: "zigbee2mqtt/bridge/state"
      payload_on: true
      payload_off: false
      value_template: "{{ value_json.tamper }}"
      device_class: "tamper"   
      name: sensor_movimiento_tamper_evento      
      off_delay: 120

Añadiremos en la sección recorder los nuevos sensores

- sensor.sensor_movimiento_cocina_estado
- sensor.sensor_movimiento_cocina_mentener_tiempo
- sensor.sensor_movimiento_cocina_sensibilidad
- sensor.sensor_movimiento_cocina_bateria
- sensor.sensor_movimiento_cocina_voltaje
- binary_sensor.sensor_movimiento_cocina_evento
- binary_sensor.sensor_movimiento_bateria_baja_evento
- binary_sensor.sensor_movimiento_tamper_evento

En el fichero customize.yaml pondremos las etiquetas a nuestro gusto

binary_sensor.sensor_movimiento_cocina_evento:
  friendly_name: Movimiento detectado
binary_sensor.sensor_movimiento_bateria_baja_evento:
  friendly_name: Bateria baja
binary_sensor.sensor_movimiento_tamper_evento:
  friendly_name: Sensor manipulación
sensor.sensor_movimiento_cocina_estado:
  friendly_name: Calidad del enlace
sensor.sensor_movimiento_cocina_mentener_tiempo:
  friendly_name: Tiempo señal activa
sensor.sensor_movimiento_cocina_sensibilidad:
  friendly_name: Sensibilidad
sensor.sensor_movimiento_cocina_bateria:
  friendly_name: Nivel de bateria 
sensor.sensor_movimiento_cocina_voltaje:
  friendly_name: Tensión de bateria

Ya nos aparece la información del sensor recientemente añadido

Crearemos las automatizaciones , por ejemplo en este caso apagar luces si no hay movimiento en la cocina durante media hora

####################################################
# Temporizadores de media hora por movimiento cocina
####################################################  

- alias: Apagado luces cocina tras media hora sin movimiento
  initial_state: 'on'
  trigger:
    platform: state
    entity_id: 
      - binary_sensor.sensor_movimiento_cocina_evento
    from: 'on'
    to: 'off'      
    for: '00:30:00'     
  condition:
    condition: state
    entity_id: input_boolean.int_luces_temporizadas
    state: 'on'    
  action: 
    - service: light.turn_off
      entity_id: light.luz_cocina 
    - service: light.turn_off
      entity_id: light.tira_led_cocina 
    - service: notify.notif_telegram_bot
      data:
        message: "\U0001f4a1  ¡¡¡ Luces *cocina* apagadas tras media hora sin movimiento !!! \U0001f4a1"  

Crearemos un sensor para que quede bien bonito el tema del nivel de batería

      sensor_movimiento_cocina_battery_level:
        friendly_name: Sencsor movimiento Cocina
        value_template: "{{ states.sensor.sensor_movimiento_cocina_bateria.state |default(-1)| int(0)  if states.sensor.sensor_movimiento_cocina_bateria is not none }}"
        unit_of_measurement: '%'
        icon_template: '{% if states.sensor.sensor_movimiento_cocina_bateria.state| int(0)   == 100 %}
                          mdi:battery
                       {% elif states.sensor.sensor_movimiento_cocina_bateria.state| int(0)   >= 90 %}
                          mdi:battery-90
                       {% elif states.sensor.sensor_movimiento_cocina_bateria.state| int(0)   >= 80 %}
                          mdi:battery-80
                       {% elif states.sensor.sensor_movimiento_cocina_bateria.state| int(0)   >= 70 %}
                          mdi:battery-70
                       {% elif states.sensor.sensor_movimiento_cocina_bateria.state| int(0)   >= 60 %}
                          mdi:battery-60
                       {% elif states.sensor.sensor_movimiento_cocina_bateria.state| int(0)   >= 50 %}
                          mdi:battery-50
                       {% elif states.sensor.sensor_movimiento_cocina_bateria.state| int(0)   >= 40 %}
                          mdi:battery-40
                       {% elif states.sensor.sensor_movimiento_cocina_bateria.state| int(0)   >= 30 %}
                          mdi:battery-30
                       {% elif states.sensor.sensor_movimiento_cocina_bateria.state| int(0)   >= 20 %}
                          mdi:battery-20
                       {% elif states.sensor.sensor_movimiento_cocina_bateria.state| int(0)   >= 10 %}
                          mdi:battery-10
                       {% else %}
                          mdi:battery-outline
                       {% endif %}'

Y con esto y un bizcocho …….