Ademco/Honeywell/Vista ESPHome custom component with an esp32/esp8266

Yes, the esp32-s2 will work fine (any esp32 is preferred over an esp8266). You can use any pin that is not defined as needed for boot, etc. Your suggested pins of 9,8,37 should work fine. The pins you use need to be configured in the yaml config from the project. I’ve never had issues with needing an external antenna as the esp32’s have good range but it all depends on how far your wifi gateway is.

Updated all code and components to compile under framework: esp-idf as well as optimized memory use. Code available in “dev” branch. Will update “master” when things have been tested a bit longer and no issues crop up.

1 Like

Question about the stable branch. I periodically get log entries saying the MAC address was unavailable:

I thought this meant that the Wifi has flaking out, but even in the “unavailable” state I keep getting status update (see picture) even before it returns to available. What do these mean?

I’m asking because I designed a PCB I was going to put on Github but wanted to make sure its actually working reliably before I post something broken.

Sorry, not sure what that mac address issue is. Looks to be an HA thing. Not related the the alarm code.

I’ve setup a PCB on my system and can read status changes (which works great), but I’m struggling to actually set the alarm. I can send the arm home command to partition 1, I see the device logs respond, and monitoring on an oscilloscope I see the voltage jump up to +12V on the green line:

But only a few edges are present, and the alarm system doesn’t respond to them. I suspect more than 4 edges should be sent?

Here is my schematic:

And here is my YAML: #for documentation see project at https://github.com/Dilbert66/esphome-VistaECP - Pastebin.com

Running the stable branch. Any ideas what I am doing wrong?

I can’t see anything obvious. Did you activate keypad 17 in program *190? If it’s not active, the panel will ignore the cmds.

@Dilbert66,

I have absolutely been loving this project. I have a little bit of programming skills, but haven’t gotten that far.

I did find a bug, though, in the zone expander fault logic in vista.cpp. For this setup, in the YAML file, zone expander address 10 is enabled to allow virtual control of zones 33-40. Zone 33 is set up on my test panel for an entry/exit sensor.

The problem I found is if I called setExpFault(33, false) but there wasn’t already a fault, the zone would randomly fault, which is not intended behavior.

I tracked it down to this line (roughly line 645, but I had made some edits):
_expFaultBits = fault ? _expFaultBits | (0x80 >> z) : _expFaultBits ^ (0x80 >> z); // setup bit fields for return response with fault values for each zone

The issue is doing an XOR on the calculated bit mask. If fault is false, then it XORs a 1 in that fault bit position, meaning if the zone wasn’t faulted already, it queues in a fault.

Instead it needs to AND the NOT of the bitmask so it explicitly clears the bit whether it was set or not:

_expFaultBits = fault ? _expFaultBits | (0x80 >> z) : _expFaultBits & ~(0x80 >> z);

Now, as a side question, where does the code actually initialize between all these files? I’m new to ESP and mapping YAML parameters to #defines is new to me. I’m trying to write a sub-component that runs in “parallel” between bus data interrupt events, such as a WiFi setup UI to make this more complete.

You are correct about that bug. Thank you. Surprised it hasnt been found before. I’ve corrected and will push updates soon. Im in the middle of doing a lot of updates to support the upcoming 2026.1.xx version of esphome.

As to how everything is initialized, look at the init.py file. That converts all the yaml configs into c++ calls to the library.

Luckysorr, as to why your panel is not responding to cmds, as noted before, it can be for many reasons:

1: you need to make sure you have activated the keypad address in the panel programming. I’m not sure about the vista48d but assume it’s the same as the vista20. Also ensure it’s entered in the keypadaddr line in the yaml
2. make sure you have the correct pin set for the txpin (double check where you have wired it)
3. make sure your wiring connections are correct to the optocoupler and ensure it is wired to the panel correctly. It could also be a faulty optocoupler but that is rare.

Did you set keypad address 20 as active in the panel program *193 ?

Yes, as per the installer manual instructions, in any case in the meantime I solved it, it was a problem with the control unit that on the +12 connector did not supply voltage because the section was burnt, in fact I changed the connection and now the commands are sent, I need to understand how the macro keys are configured and then I should have solved it, thanks always for these precious projects.
Ths

Reminder:

1 Like

I’m sorry, for the next posts I will follow the rules, sorry again.

1 Like

You should be able to edit the posts.

1 Like

Glad you solved it. That was a different issue than others have reported. Good to know. As to the macros, they are represented by the letters ‘A’, ‘B’,‘C’ and ‘D’ so if you send those keys as a command, they will execute the associated macros A,B,C and D

With the changes to the ‘template’ platform, I get a reminder that my code/syntax needs to be updated. Using the sample from the GitHub

alarm_control_panel:
  - platform: template
    panels:
      safe_alarm_panel:
        name: "Alarm Panel"
        value_template: "{{states('sensor.vistaalarm_system_status')}}"
        code_arm_required: false
        
        arm_away:
           action: esphome.vistaalarm_alarm_arm_away
                  
        arm_home:
          action: esphome.vistaalarm_alarm_arm_home
          
        arm_night:
          action: esphome.vistaalarm_alarm_arm_night
            data_template:
              code: '{{code}}' #if you didnt set it in the yaml, then send the code here
          
        disarm:
           action: esphome.vistaalarm_alarm_disarm
            data_template:
              code: '{{code}}'                    

I’ve tried to revise the code (after reading through the template migration sample) like below, but the alarm_control_panel.safe_alarm_panel no longer exists as defined above. Looking for some pointers for where I’ve misunderstood the migration instructions.

template:

  - alarm_control_panel:
  
    - default_entity_id: alarm_control_panel.safe_alarm_panel
      name: "Alarm Panel"
      value_template: "{{states('sensor.vistaalarm_system_status')}}"
      code_arm_required: false

      arm_away:
        action: esphome.vistaalarm_alarm_arm_away
                  
      arm_home:
        action: esphome.vistaalarm_alarm_arm_home
          
      arm_night:
        action: esphome.vistaalarm_alarm_arm_night
          data_template:
            code: '{{code}}' #if you didnt set it in the yaml, then send the code

      disarm:
        action: esphome.vistaalarm_alarm_disarm
          data_template:
              code: '{{code}}'                    

Here’s my working template for reference.

- alarm_control_panel:
  - name: Vista20P Alarm Panel
    code_arm_required: false
    arm_away:
    - data:
        partition: 1
      action: esphome.vista20p_alarm_arm_away
    arm_home:
    - data:
        partition: 1
      action: esphome.vista20p_alarm_arm_home
    arm_night:
    - data_template:
        partition: 1
        code: 1234
      action: esphome.vista20p_alarm_arm_night
    disarm:
    - data_template:
        partition: 1
        code: '{{ code }}'
      action: esphome.vista20p_alarm_disarm
    code_format: number
    default_entity_id: alarm_control_panel.vista_alarm_panel
    state: '{{states(''sensor.vista20p_ss_1'')}}'

thanks a ton for the quick reply!
Changing my “value_template” to “state” fixed it!

Is the library capable of tracking external relay modules like it can external zone expanders? I can only get it to display binary statuses for relays that are emulated by the library.

The 4229 zone expanders have two relays, unlike the 4219s that are expanders only. I am curious as to whether they use the same messages for the relays, except only use channel 1 and 2, but to a zone expander address. Presumably I could specify to listen to address 11 on a 4229 and channel 1. That doesn’t work in my setup on real hardware, nor does listening to a 4204 relay module set to address 12, but emulating a 4204 in the microcontroller at address 13 yields a successful status change in a binary sensor.

I have both a 4229 and a 4204 relay module if you need dumps, and and other hardware, like an AUI keypad.

The code is most likely not capturing physical devices correctly. I don’t have any physical expanders to test with on the vista so went by logs for writing the emulation code. If you can provide logs of activity with real 4229 and 4204’s I can modify the code to handle those properly. Please create an issue on my github page and post your logs there: GitHub · Where software is built.

The commands to look for look like this:

[I][CMD:960]: [2026-02-08 08:30] FA 01 80 25 F1 6F                              
[I][EXT:960]: [2026-02-08 08:30] FA 0D F1 00 00 00                              
[I][RAW:960]: [2026-02-08 08:30] 0D 31 00 00 C2                                 
[I][CMD:960]: [2026-02-08 08:30] FA 01 01 02 20 F1 F1                           
[I][EXT:960]: [2026-02-08 08:30] FA 0E F1 00 00 00                              
[I][RAW:960]: [2026-02-08 08:30] 0D 34 00 00 BF   

The cmd:960 is the panel poll request to the expander, the EXT:960 is the response from the expander. (decoded ), The RAW:960 is the actual response from the module before decoding. The CMD from the panel determines how the response is decoded.