Bentel KYO32 Alarm System Integration

Honestly I think all is the same, take one with the latest version of ESP32 chip :wink:

Thanks, I’ll buy a new one and give it a try.
In the meantime, I created my first alarm card!
I can arm the whole system or the two areas independently. I can see the full system status, including tampering, using the chips card.
I can also see the status of every zone — whether it’s included or excluded — and whether there are any memory alarms.
It would be great to have a popup asking for a PIN when pressing the disarm button, before actually disarming the system. Any suggestions on how to implement that?
It’s still a work in progress!

1 Like

Done… i’m happy with my kyo32 card with code to disarm the alarm, maybe not the safest solution but at least is something…

pressing the disarm button opens a popup (browser mod) with a pin pad

many thanks for your fantastic work!!
now i’m waiting for the new hardware to check if i can solve the connection issue

2 Likes

Great work @firstcolle, my compliments! :clap:

(I didn’t provide in my firmware request of pin/code because the Kyo Unit serial commands doesn’t require it, but of course on lovelace side you can amost done everything)

If you want, you can prepare a YAML package and do a PR to my repo, or write to me privately, as you prefer :slight_smile:

Hello Lorenzo, your project is very close to what i was looking for and I thank you for sharing it with the world.

I was hoping that you could help me with implementing a different application of your project, that ditches entirely the esphome integration (i don’t have smart home or homeassistant) and works solely off the wemos board, that acts standalone as a web server from where i can command the alarm system trough a simple web UI.

I have extremely basic coding experience but i managed to use some AI chatbots to get some working code that mimics - i think - exactly the command logic of the bentel_kyo32.h library (bytes commands and crc) and the esphome yaml (some settings like baud rate and parity);

i confirmed multiple times that the bytes go trough the serial port by using a rs232 to usb cable/converter and checking the incoming data from the ESP board, as to say that I have done quite a lot of troubleshooting along the way!

The alarm system doesn’t seem to react to anything though, i was wondering if some start sequence is required to get the central to accept incoming traffic, at some point i was also wondering wether the firmware of the kyo was not up to date (as a side note, how do i check my FW version?)

If you could help me understand what I am missing in my approach it will be very appreciated
thank you :pray:

1 Like

I received this board to try to fix the disconnection issues (8MB version). How should I configure the directives?

https://a.aliexpress.com/_EH6c3Zg

honestly I don’t know specifically… you can found on ESPHome documentation, anyway just a rapid google search, I found this Running ESPHome on a ESP32C6 device for Home Assistant - adrianba.net

I ended up using an ESP32-S3 and it’s working great. no disconnects in 36 hours so far.

ciao ho visto che hai fatto una dashboard con la tastiera è possibile che tu possa condividere il file per creare il comando, io ci sto provandò da un pò ma ho scarse preparazione di progammazione se mi aiuteresti ti sarei grato

To create a panel with a code entry keypad, I followed a guide I found online and adapted it to my needs.
I also tried to create a file to share/distribute it, but I wasn’t able to.
Here are the steps I followed to create the keypad:

1. Create a script with the following YAML:

alias: Keypad Input
sequence:
  - data_template:
      entity_id: input_text.keypad_input
      value: >
        {% set current_value = states('input_text.keypad_input') %}
        {% if current_value != 'None' and current_value != 'unknown' %}
          {{ current_value ~ number | string }}
        {% else %}
          {{ number | string }}
        {% endif %}
    action: input_text.set_value
mode: single

2. Create the following helpers:

  • keypad_code: type input_text with password mode to hide the characters.
    You must write the disarm code here.
  • keypad_input: type input_text.
    This will store the code as it’s typed on the keypad.
  • verifica_codice: type input_boolean.
    This is used to trigger code verification.

3. Create a template sensor to mask the input:

- platform: template
  sensors:
    keypad_input_masked:
      unique_id: keypad_input_masked
      value_template: >
        {% set input_length = states('input_text.keypad_input')|length %}
        {{ '*' * input_length }}

4. Create an automation to verify the code and disarm the alarm if correct:

alias: Disarm Alarm if Code is Correct
description: ""
trigger:
  - platform: state
    entity_id: input_boolean.verifica_codice
    to: "on"
condition: []
action:
  - alias: If correct code, disarm the alarm
    if:
      - condition: template
        value_template: >
          {{ states('input_text.keypad_input') == states('input_text.keypad_code') }}
    then:
      - service: esphome.esphome_antifurto_disarm_area
        data:
          area: 1
          specific_area: 0
      - service: browser_mod.close_popup
      - service: input_text.set_value
        data:
          value: ""
        target:
          entity_id: input_text.keypad_input
    else:
      - service: input_text.set_value
        data:
          value: ""
        target:
          entity_id: input_text.keypad_input
  - service: input_boolean.turn_off
    target:
      entity_id: input_boolean.verifica_codice
mode: single

5. Create a button that opens the keypad popup:

If you want the keypad to appear as a popup, the Browser Mod 2 integration must be installed, configured, and working:
:point_right: hass-browser_mod/README.md at master ¡ thomasloven/hass-browser_mod ¡ GitHub

Use this tap_action on a button card to display the keypad popup:

tap_action:
  action: perform-action
  perform_action: browser_mod.popup
  data:
    content:
      type: vertical-stack
      cards:
        - type: entity
          entity: sensor.keypad_input_masked
          icon: mdi:dialpad
          name: Enter Code
          style: |
            ha-card { 
              --ha-card-background: none;
              border: none;
              text-align: center;
              margin-bottom: -20px
            }
        - type: grid
          columns: 3
          square: false
          cards:
            # Number buttons (1–9)
            {% for i in range(1, 10) %}
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: script.keypad_input
                service_data:
                  number: "{{ i }}"
              icon: mdi:numeric-{{ i }}
              color: "#bdbdbd"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            {% endfor %}
            # Clear (X)
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: input_text.set_value
                service_data:
                  entity_id: input_text.keypad_input
                  value: ""
              icon: mdi:alpha-x
              color: "#f87272"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            # Zero (0)
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: script.keypad_input
                service_data:
                  number: "0"
              icon: mdi:numeric-0
              color: "#bdbdbd"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            # Confirm (✓)
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: perform-action
                perform_action: input_boolean.turn_on
                target:
                  entity_id: input_boolean.verifica_codice
              icon: mdi:check
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
                icon:
                  - color: "#8dc869"
    timeout: 10000

5b.

If you are not using Browser Mod, you can create a card like this:

type: vertical-stack
cards:
        - type: entity
          entity: sensor.keypad_input_masked
          icon: mdi:dialpad
          name: Inserisci Codice
          style: |
            ha-card { 
              --ha-card-background: none;
              border: none;
              text-align: center;
              margin-bottom: -20px
            }
        - type: grid
          columns: 3
          square: false
          cards:
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: script.keypad_input
                service_data:
                  number: "1"
              icon: mdi:numeric-1
              color: "#bdbdbd"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: script.keypad_input
                service_data:
                  number: "2"
              icon: mdi:numeric-2
              color: "#bdbdbd"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: script.keypad_input
                service_data:
                  number: "3"
              icon: mdi:numeric-3
              color: "#bdbdbd"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: script.keypad_input
                service_data:
                  number: "4"
              icon: mdi:numeric-4
              color: "#bdbdbd"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: script.keypad_input
                service_data:
                  number: "5"
              icon: mdi:numeric-5
              color: "#bdbdbd"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: script.keypad_input
                service_data:
                  number: "6"
              icon: mdi:numeric-6
              color: "#bdbdbd"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: script.keypad_input
                service_data:
                  number: "7"
              icon: mdi:numeric-7
              color: "#bdbdbd"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: script.keypad_input
                service_data:
                  number: "8"
              icon: mdi:numeric-8
              color: "#bdbdbd"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: script.keypad_input
                service_data:
                  number: "9"
              icon: mdi:numeric-9
              color: "#bdbdbd"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: input_text.set_value
                service_data:
                  entity_id: input_text.keypad_input
                  value: ""
              icon: mdi:alpha-x
              color: "#f87272"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: call-service
                service: script.keypad_input
                service_data:
                  number: "0"
              icon: mdi:numeric-0
              color: "#bdbdbd"
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
            - type: custom:button-card
              show_name: false
              show_icon: true
              aspect_ratio: 1/.75
              tap_action:
                action: perform-action
                perform_action: input_boolean.turn_on
                target:
                  entity_id: input_boolean.verifica_codice
              icon: mdi:check
              size: 100%
              styles:
                card:
                  - background: none
                  - border: none
                  - "--mdc-ripple-press-opacity": 0
                icon:
                  - color: "#8dc869"

If anyone wants to create a package or a blueprint with everything needed, feel absolutely free to do so :slight_smile:

1 Like

Hello @JustARegularUser , I think you can use MQTT integration of esphome instead of Napive API, MQTT Client Component — ESPHome.

With MQTT Integration you can see sensor status with a frontend UI, but you need a MQTT Broker… honestly I suggest you to install Home Assistant on a Raspberry/NAS and use HA mobile App on smartphone/tablet, etc… quiet simple and 100% guarantee of working :wink:

1 Like

Great job @firstcolle :muscle: !

If you want to collaborate you can build a package and do a PR on my repo :slight_smile:

Great job, let me share another alternative GitHub - nielsfaber/alarmo: Easy to use alarm system integration for Home Assistant

1 Like

Yes, I also used Alarmo :slight_smile:

HI,

any idea on this error

In file included from src/main.cpp:194:
src/bentel_kyo32.h: In member function ‘virtual void Bentel_Kyo32::setup()’:
src/bentel_kyo32.h:67:25: error: ‘register_service’ was not declared in this scope
67 | register_service(&Bentel_Kyo32::arm_area, “arm_area”, {“area”, “arm_type”, “specific_area”});
| ^~~~~~~~~~~~~~~~

yes, look at my yaml example files, with ESPHome > 2025.7.x you’ve to add

api:
  custom_services: true

You’ve also take latest version of .h files from my repo :wink:

Let me know if works.

Is anyone experiencing issues with the latest ESPHome 2025.8.0 update? My UART seems to be broken—I’m no longer receiving any data.

I reverted to version 2025.7.5, and everything works like a charm. If anyone else encounters a similar issue, this add-on was a lifesaver

GitHub - khenderick/esphome-legacy-addons: ESPHome addons from previous versions. Just in case something isn’t working with the new version

Have you tried 2025.8.1 or .2?

@firstcolle I tried 2025.8.0