Dilbert66 / esphome-dsckeybus

Esphome custom configuration for interfacing to a DSC POWERSERIES alarm system
187 stars 34 forks source link

Zones Not Setting/Clearing Faults #74

Closed abishur closed 1 year ago

abishur commented 1 year ago

I'm using ESPHome v2022.12.3 and HA 2022.12.8 and did a pull of the "new" esphome-dsckeybus this morning.

I just finished setting up my system tonight and noticed that most my zones using the emulated expander weren't responding. I could get responses on zones 9, 10, 17, and 18, but nothing from 11-16. I thought maybe zones 11-16 were reserved by my pc1616 board so I moved zones 11-16 to 19-24, but now none of my zones above 10 respond to the set zone fault command.

I've made sure to enable all the zones from 1-24 using *8-[Installer_code]-202/203/204 and making sure all 8 options were enabled in each area. Is there a compatibility issue with the latest version of ESPHome?

I've attached my current code, maybe I entered a setting wrong.

#for documentation see project at https://github.com/Dilbert66/esphome-dsckeybus

#Zones:
  # Zones built into security panel (there are 8 possible, but only 6 physically present)
    # Zone 1: Front Door
    # Zone 2: Garage Door
    # Zone 3: Fire Alarm (Planned)
    # Zone 4: Unused
    # Zone 5: Unused
    # Zone 6: Motion Detector
    # Zone 7: Not Populated
    # Zone 8: Not Populated
  # Virtual Zones
    # Zone 9: Rear Door
    # Zone 10: Front Room Windows
    # Zone 11: Kitchen Windows
    # Zone 12: Living Room Windows
    # Zone 13: Master Bedroom Windows
    # Zone 14: Master Bathroom Window
    # Zone 15: Office Window
    # Zone 16: Red Room Windows
    # Zone 17: Eden's Windows
    # Zone 18: Boys' Room Window

substitutions:
  # change the name to suit your needs. This is what esphome will use as the friendly name for your component.
  # also used as a prefix for all fields
  systemName: "dscalarm" 

  #you can enter a list of user codes mapped to their names for display in armed/disarmed event messages
  userCodes: "1:Matthew,2:Amy,33:Hostage" 

  #Only comes into effect if a password prompt occurs when arming eg. night mode
  accessCode: !secret access_code 

  #used to select the default partition associated with the alarm panel messages
  defaultPartition: "1" 

  #zone expander addresses:
  # 9  - zones 9-16
  # 10 - zones 17-24
  # 11 - zones 25-32
  # 12 - zones 33-40 (for systems with 64 zone support)
  # 13 - zones 41-48 (for systems with 64 zone support)
  # 14 - zones 49-56 (for systems with 64 zone support)
  # 16 - zones 57-64 (for systems with 64 zone support)  
  expanderAddr1: "9" # 1st zone expander emulator address to use . Set to 0 to disable. 
  expanderAddr2: "10" # 2nd expander emulator address to use . Set to 0 to disable. 

  #ESP32 Pins
  dscClockPin: "22"
  dscReadPin: "21"
  dscWritePin: "18"

  #ESP8266 Pins
  #dscClockPin: "5"
  #dscReadPin: "4"
  #dscWritePin: "15"  

  maxZones: "32" # maximum amount of zones your system supports

esphome:
  name: $systemName
  platform: ESP32
  board: nodemcu-32s
  #platform: ESP8266
  #board: nodemcuv2

  includes:
    # subdirectory path where custom component *.h and *.cpp files are located
    - dscKeybusInterface/

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: 192.168.14.3
    gateway: 192.168.15.1
    subnet: 255.255.254.0

  ap:
    ssid: "$systemName"
    password: !secret wifi_password

logger:
  baud_rate: 115200
  level: DEBUG

##API communications - ensure the mqtt: section is commented if using this protocol
api:
   password: !secret api_password  
   #encryption:         
     #key: !secret encryption_key

##MQTT communications - ensure the api: section is commented if using this protocol
#mqtt:
  #broker: xxx.xxx.xxx.xxx #your mqtt broker address
  #port: 1883  
  #username: mqttuser #your mqtt user name
  #password: !secret mqtt_password #your mqtt user pass

ota:
   password: !secret ota_password
   safe_mode: True
   on_begin:
    then:
      - switch.turn_off: connection_status_switch   

status_led:
  pin:
    number: GPIO2
    inverted: no

#comment if using ESP8266 to conserve memory    
time:
 - platform: sntp
   id: sntp_time

custom_component:
 - id: dsckeybus
   lambda: |-
    auto DSCkeybus = new DSCkeybushome($dscClockPin,$dscReadPin,$dscWritePin);
    DSCkeybus->accessCode="$accessCode";
    DSCkeybus->userCodes="$userCodes";
    DSCkeybus->maxZones=$maxZones;
    DSCkeybus->defaultPartition=$defaultPartition;
    DSCkeybus->debug=2; // 0 = off, 1 = minimal, 2 = all packets shown on console  3 =  + serial port debugging
    DSCkeybus->expanderAddr1=$expanderAddr1; //zone expander
    DSCkeybus->expanderAddr2=$expanderAddr2;
    DSCkeybus->onSystemStatusChange([&](std::string statusCode) {
       id(system_status).publish_state(statusCode);
    });

    // if you only have one partition, remove the case 2 and corresponding p2 sensor. You can also add more partitions if needed
    DSCkeybus->onPartitionStatusChange([&](std::string statusCode, int partition) {
       switch(partition) {
         case 1: id(p1).publish_state(statusCode); break;
         case 2: id(p2).publish_state(statusCode); break;
      } 
    });

    DSCkeybus->onPartitionMsgChange([&](std::string msg,uint8_t partition) {
       switch(partition) {
         case 1: id(m1).publish_state(msg); break;
         case 2: id(m2).publish_state(msg); break;
      } // if you only have one partition, remove the case 2 statement  and corresponding p2 sensor. You can also add more partitions if needed
    });    

    DSCkeybus->onPanelStatusChange([&](panelStatus ps,bool open,int partition) {
      switch (partition) {
        case 0: // all partitions hardware statuses
          switch(ps) {
            case trStatus: id(tr).publish_state(open);break;
            case batStatus: id(bat).publish_state(open);break;
            case acStatus: id(ac).publish_state(open);break;
            case panicStatus: id(panic).publish_state(open);break;
            default: break;
          };break;  
        case 1: //partition 1 armed/ready
          switch(ps) {
            case rdyStatus: id(rdy).publish_state(open);break;
            case armStatus: id(arm).publish_state(open);break;
            default: break;
          };break;
        case 2: //partition 2 armed/ready
          switch(ps) {        
            case rdyStatus: id(rdy_2).publish_state(open);break;
            case armStatus: id(arm_2).publish_state(open);break;
            default: break;
          };break;

      };
    });

    DSCkeybus->onZoneMsgStatus([&](std::string msg) {
            id(zone_status).publish_state(msg);
    });

    DSCkeybus->onLine1Display([&](std::string msg,int partition) {
        switch(partition) {
            case 1: id(line1).publish_state(msg);break;
            case 2: id(line1_2).publish_state(msg);break;            
        }
    });

    DSCkeybus->onLine2Display([&](std::string msg,int partition) {
        switch(partition) {    
           case 1: id(line2).publish_state(msg);break;
           case 2: id(line2_2).publish_state(msg);break;           
        }            
    });
    DSCkeybus->onEventInfo([&](std::string msg) {
            id(event).publish_state(msg);
    });  

    DSCkeybus->onBeeps([&](std::string beep,int partition) {
        switch(partition) {    
            case 1: id(beeps).publish_state(beep);break; 
            case 2: id(beeps_2).publish_state(beep);break;            
        }
    });    

    DSCkeybus->onFireStatusChange([&](bool open,int partition) {
      switch (partition) {
          case 1: id(f1).publish_state(open); break;
          case 2: id(f2).publish_state(open); break;          
      }
    }); 

    DSCkeybus->onTroubleMsgStatus([&](std::string msg) {
            id(tr_msg).publish_state(msg); //non partition specific trouble messages
    });

    DSCkeybus->onZoneStatusChange([&](uint8_t zone, bool open) {
      switch (zone) {
        case 1: id(z1).publish_state(open); break;
        case 2: id(z2).publish_state(open); break;
        case 3: id(z3).publish_state(open); break;
        case 6: id(z6).publish_state(open); break;
        case 9: id(z9).publish_state(open); break;
        case 10: id(z10).publish_state(open); break;
        case 17: id(z17).publish_state(open); break;
        case 18: id(z18).publish_state(open); break;
        case 19: id(z19).publish_state(open); break;
        case 20: id(z20).publish_state(open); break;
        case 21: id(z21).publish_state(open); break;
        case 22: id(z22).publish_state(open); break;
        case 23: id(z23).publish_state(open); break;
        case 24: id(z24).publish_state(open); break;
      } // add or delete any zone you need above. Add the coresponding sensor id in the binary_sensor section
    });

    DSCkeybus->onRelayChannelChange([&](uint8_t channel, bool state) {
      switch (channel) {
        case 1: id(r1).publish_state(state); break;
        case 2: id(r2).publish_state(state); break;
        case 3: id(r3).publish_state(state); break;
        case 4: id(r4).publish_state(state); break;
        case 5: id(r5).publish_state(state); break;
        case 6: id(r6).publish_state(state); break;
        case 7: id(r7).publish_state(state); break;
        case 8: id(r8).publish_state(state); break;
      }
    });

    return {DSCkeybus};

#ESP32 only .  Calls a public function within the custom component above. In this case syncs the time   
interval:
  - interval: 3600s
    then:
      - lambda: |-
          static_cast< DSCkeybushome*> (id(dsckeybus).get_component(0))->set_panel_time();  

# add or remove any zone you need. Please ensure you also add/remove the corresonponding case statement above
# change the name to match your own zone configurations
# if you don't want to delete a zone, you can also comment out the name: field to hide it from home assistant
binary_sensor:
    #zone status open/close for each zone 
  - platform: template
    id: z1
    name: "Front door (z1)"
    device_class: door
  - platform: template
    id: z2
    name: "Garage door (z2)"
    device_class: door
  - platform: template
    id: z3
    name: "Fire Alarm (z3)"
    device_class: safety
  - platform: template
    id: z6
    name: "Motion Detector (z6)"
    device_class: motion
  - platform: template
    id: z9
    name: "Rear Door (z9)"
    device_class: door
  - platform: template
    id: z10
    name: "Front Room Windows (z10)"
    device_class: window
  - platform: template
    id: z17
    name: "Eden's Windows (z17)"
    device_class: window
  - platform: template
    id: z18
    name: "Boys' Room Window (z18)"
    device_class: window
  - platform: template
    id: z19
    name: "Kitchen Windows (z19)"
    device_class: window
  - platform: template
    id: z20
    name: "Living Room Windows (z20)"
    device_class: window
  - platform: template
    id: z21
    name: "Master Bedroom Windows (z21)"
    device_class: window
  - platform: template
    id: z22
    name: "Master Bathroom Window (z22)"
    device_class: window
  - platform: template
    id: z23
    name: "Office Window (z23)"
    device_class: window
  - platform: template
    id: z24
    name: "Red Room Windows (z24)"
    device_class: window

  - platform: template
    id: rdy
    name: "$systemName Partition 1 Ready"

  - platform: template
    id: arm
    name: "$systemName Partition 1 Armed"

  - platform: template
    id: rdy_2
    name: "$systemName Partition 2 Ready"

  - platform: template
    id: arm_2
    name: "$systemName Partition 2 Armed"    

    #panel trouble status on/off
  - platform: template
    id: tr
    name: "$systemName Trouble Status"
    device_class: problem

    #battery status ok/low
  - platform: template
    id: bat
    name: "$systemName Battery Status"
    device_class: problem

    #AC power status ok/no power
  - platform: template
    id: ac
    name: "$systemName AC Status"
    device_class: plug

    #panic alarm on/off
  - platform: template
    id: panic
    name: "$systemName Panic Status"
    device_class: safety

    #fire alarm on/off
  - platform: template
    id: f1
    device_class: safety
    name: "$systemName Fire partition 1 Status"  

  - platform: template
    id: f2
    device_class: safety
    name: "$systemName Fire partition 2 Status"    

#relay PGM channels. Will show the state of the activate relay channel on/off
#uncomment the name: field if you wish to see it in home assistant
  - platform: template
    id: r1
    name: "$systemName PGM 1"
  - platform: template
    id: r2
    name: "$systemName PGM 2"
  - platform: template
    id: r3
    name: "$systemName PGM 3"
  - platform: template
    id: r4
    name: "$systemName PGM 4"
  - platform: template
    id: r5
    #name: "$systemName PGM 5"
  - platform: template
    id: r6
    #name: "$systemName PGM 6"
  - platform: template
    id: r7
    #name: "$systemName PGM 7"
  - platform: template
    id: r8
    #name: "$systemName PGM 8"

# this sensor below is optional - example use of pin d8 as a zone trigger pin for the emulated zone expander  
# this emulates the hardware connection for a pc5108 board. Use a pull down/pull up resistor.  Adjust logic accordingly for the correct logic output. ie invert
 # - platform: gpio  
 #   pin: D8
 #   id: f1
 #   device_class: safety
 #   on_press:       #pin high=on(open), pin low=off(closed)
 #     - lambda: |-
 #         dsc.setZoneFault(17,1);  #set zone 17 as open
 #   on_release:
 #     - lambda: |-
 #         dsc.setZoneFault(17,0);  #set zone 17 as closed

text_sensor:
    #general system status online/disconnected 
  - platform: template
    id: system_status
    name: "$systemName System Status"
    icon: "mdi:shield"
    #battery level status for wireless channels, tamper , in alarm, etc for individual zones
  - platform: template
    id: zone_status
    name: "$systemName zone status "
    icon: "mdi:shield"  
    # partition status ie read/unavailable, in alarm, etc
  - platform: template
    id: p1
    name: "$systemName Partition 1 Status "
    icon: "mdi:shield"
  - platform: template
    id: p2
    name: "$systemName Partition 2 Status " # uncomment to show in home assistant.  
    icon: "mdi:shield"  
    # more verbose message regarding the partition status. ie zones open, bypassed, etc

  - platform: template
    id: m1
    name: "$systemName Partition 1 Msg "
    icon: "mdi:alert-box"
  - platform: template
    id: m2
    name: "$systemName Partition 2 Msg " # uncomment to show in home assistant
    icon: "mdi:alert-box"

  - platform: template
    id: line1
    name: "$systemName line1"
    icon: "mdi:alert-box"
  - platform: template
    id: line2
    name: "$systemName line2"
    icon: "mdi:alert-box"  
  - platform: template
    id: line1_2
    name: "$systemName line1 partition 2"
    icon: "mdi:alert-box"
  - platform: template
    id: line2_2
    name: "$systemName line2 partition 2"
    icon: "mdi:alert-box" 

  - platform: template
    id: event
    name: "$systemName event"
    icon: "mdi:alert-box"  

  - platform: template
    id: beeps
    name: "$systemName beeps"
    icon: "mdi:alert-box" 
  - platform: template
    id: beeps_2
    name: "$systemName partition 2 beeps"
    icon: "mdi:alert-box"   

  - platform: template
    id: tr_msg
    name: "$systemName Trouble Msg " # uncomment to show in home assistant
    icon: "mdi:alert-box"

switch:
    #shows status of connection status to panel.  You can disconnect before upload using the switch.
  - platform: template
    name: "$systemName Connection"
    id: connection_status_switch
    lambda: |-
      return dsc.keybusConnected;
    icon: "mdi:shield-link-variant"
    turn_on_action:
      - switch.toggle: restart_switch
    turn_off_action:
      - lambda: |-
          disconnectKeybus();
  - platform: restart
    id: restart_switch
Dilbert66 commented 1 year ago

You need to configure this section for your system. You'll need to add your zones 11,12,13,14,15,16, etc. I just had a samples there configured to my own test system. You'll also need to add the corresponding zone switch destinations.

DSCkeybus->onZoneStatusChange([&](uint8_t zone, bool open) {
      switch (zone) {
        case 1: id(z1).publish_state(open); break;
        case 2: id(z2).publish_state(open); break;
        case 3: id(z3).publish_state(open); break;
        case 6: id(z6).publish_state(open); break;
        case 9: id(z9).publish_state(open); break;
        case 10: id(z10).publish_state(open); break;
        case 17: id(z17).publish_state(open); break;
        case 18: id(z18).publish_state(open); break;
        case 19: id(z19).publish_state(open); break;
        case 20: id(z20).publish_state(open); break;
        case 21: id(z21).publish_state(open); break;
        case 22: id(z22).publish_state(open); break;
        case 23: id(z23).publish_state(open); break;
        case 24: id(z24).publish_state(open); break;
      } // add or delete any zone you need above. Add the coresponding sensor id in the binary_sensor section
    });
abishur commented 1 year ago

Okay, I've added in all the missing case sections, so I now have entries for case 1 (z1) through case 24 (z24).

I've also set up some place holders for all the zones in the binary_sensor section

And I've added them both in my programming section 202-205 (active zones in Partition 1) and set up the delay types in section 001 and 002 for my zone definitions, but I'm getting the same behavior.

Sometimes I can set it, but then it won't clear and everything gets stuck. For instance, right now I'm getting this message: [10:03:08][D][text_sensor:067]: 'dscalarm zone status ': Sending state 'OP:10,OP:11,OP:12,OP:18,OP:19,OP:20'

And if I try to clear zone 19 I'll see this in the logs:

[10:03:54][D][Debug:496]: Setting Zone Fault: 19,0
[10:03:54][I][Moduledata::971]: 05: FF 01 FF FF DF FF FF FF FF FF 01 00 00 00 00 00 

But it will still say it's open a moment later

[10:04:08][D][text_sensor:067]: 'dscalarm zone status ': Sending state 'OP:10,OP:11,OP:12,OP:18,OP:19,OP:20'

Dilbert66 commented 1 year ago

Sorry, I have no idea what the issue can be. All works fine on my system. Hard to guess.

Dilbert66 commented 1 year ago

One thing I know though is that the pc16 can only support 1 zone expander. You had two enabled in your config above. Only use the 09 one. Set the other to 0

abishur commented 1 year ago

Okay so I've set it to only use one zone expander, I had misunderstood the documentation, but I'm on the same page now.

I've set my max zones to 16, expanderaddr1 to 9, expanderaddr2 to 0. I went through and disabled the zones above 16 in the dsc device itself through programming sections 204/205 and section 202 by removing their zone definitions.

When I uploaded I could set and unset zone 9, 10, 15, and 16 as much as I wanted UNTIL I tried to mess with any zone 11-14. Once I did that all the zones in the emulated expander locked up, but the hard wired zones (zones 1-6) continued to work with no issue. I can see in the logs it's receiving my command to set and unset zones, it just doesn't do it.

Here's the bit from the log immediately following my command to set the fault for zone 11

[11:36:54][D][text_sensor:067]: 'dscalarm line1': Sending state 'System is Ready'
[11:36:54][D][text_sensor:067]: 'dscalarm line2': Sending state 'Ready to Arm <>'
[11:36:54][D][text_sensor:067]: 'dscalarm Partition 1 Msg ': Sending state '02: Stay zones open'
[11:36:54][D][Debug:496]: Setting Zone Fault: 11,1
[11:36:54][I][Moduledata::971]: 05: FF 01 FF FF BF FF FF FF FF FF 01 00 00 00 00 00 
[11:36:54][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:36:54][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:36:54][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:36:54][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:36:55][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:37:00][I][Paneldata: :971]: 27: 27 00 D5 02 10 C7 00 D5 00 00 00 00 00 00 00 00 
[11:37:00][D][info:1773]: status 02, last status 02,line2status 00,selection 01,partition=1,skip=0
[11:37:00][D][text_sensor:067]: 'dscalarm line1': Sending state 'System is Ready'
[11:37:00][D][text_sensor:067]: 'dscalarm line2': Sending state 'Ready to Arm <>'
[11:37:00][D][binary_sensor:036]: 'Motion Detector (z6)': Sending state OFF
[11:37:00][D][text_sensor:067]: 'dscalarm zone status ': Sending state 'OK'
[11:37:00][I][Paneldata: :971]: 05: 05 00 D5 01 10 C7 10 C7 10 C7 01 00 00 00 00 00 

This happens every time I try to set one of the zones from 11-14.

Here's the messages I get right after setting zone 10 (A Zone that Works):

[12:05:27][D][Debug:496]: Setting Zone Fault: 10,1
[12:05:27][I][Moduledata::971]: 05: FF 01 FF FF BF FF FF FF FF FF 01 00 00 00 00 00 
[12:05:27][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[12:05:27][I][Moduledata::971]: 28: FF 01 5D 00 FF FF 2F 00 00 00 00 00 00 00 00 00 
[12:05:27][I][Paneldata: :971]: 2D: 2D 00 D5 02 10 C7 02 DD 00 00 00 00 00 00 00 00 
[12:05:27][D][info:1773]: status 02, last status 02,line2status 00,selection 01,partition=1,skip=0
[12:05:27][D][text_sensor:067]: 'dscalarm line1': Sending state 'System is Ready'
[12:05:27][D][text_sensor:067]: 'dscalarm line2': Sending state 'Ready to Arm <>'
[12:05:27][D][binary_sensor:036]: 'Front Room Windows (z10)': Sending state ON

And Zone 11:

[11:47:08][D][Debug:496]: Setting Zone Fault: 11,0
[11:47:08][I][Moduledata::971]: 05: FF 01 FF FF BF FF FF FF FF FF 01 00 00 00 00 00 
[11:47:09][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:47:09][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 

Zone 12:

[11:50:18][D][Debug:496]: Setting Zone Fault: 12,1
[11:50:18][I][Paneldata: :971]: 05: 05 00 D5 01 10 C7 10 C7 10 C7 01 00 00 00 00 00 
[11:50:18][D][info:1773]: status 01, last status 02,line2status 00,selection 01,partition=1,skip=0
[11:50:18][D][text_sensor:067]: 'dscalarm line1': Sending state 'System is Ready'
[11:50:18][D][text_sensor:067]: 'dscalarm line2': Sending state 'Ready to Arm <>'
[11:50:18][D][text_sensor:067]: 'dscalarm Partition 1 Msg ': Sending state '01: Ready'
[11:50:18][I][Moduledata::971]: 05: FF 01 FF FF BF FF FF FF FF FF 01 00 00 00 00 00 
[11:50:18][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Paneldata: :971]: 28: 28 00 FF FF FF FF FF 00 00 00 00 00 00 00 00 00 
[11:50:18][I][Moduledata::971]: 28: FF 01 FF FF 55 55 FF 00 00 00 00 00 00 00 00 00 
[11:50:20][I][Paneldata: :971]: 27: 27 00 D5 01 10 C7 20 F4 00 00 00 00 00 00 00 00 

Zone 13:

[11:52:43][D][Debug:496]: Setting Zone Fault: 13,1
[11:52:44][I][Moduledata::971]: 05: FF 01 FF FF BF FF FF FF FF FF 01 00 00 00 00 00 

Zone 14:

[12:02:43][D][Debug:496]: Setting Zone Fault: 14,1
[12:02:43][I][Moduledata::971]: 05: FF 01 FF FF BF FF FF FF FF FF 01 00 00 00 00 00 
[12:02:47][I][Paneldata: :971]: 27: 27 00 D5 02 10 C7 00 D5 00 00 00 00 00 00 00 00 

And here's the code I'm working with now. I've deleted out references to partition 2 and I even tried deleting out any reference to the second expander address, but the didn't change any of the behavior so I put it back in and set it to zero.

#for documentation see project at https://github.com/Dilbert66/esphome-dsckeybus

#Zones:
  # Zones built into security panel (there are 8 possible, but only 6 physically present)
    # Zone 1: Front Door
    # Zone 2: Garage Door
    # Zone 3: Fire Alarm (Planned)
    # Zone 4: Unused
    # Zone 5: Unused
    # Zone 6: Motion Detector
    # Zone 7: Not Populated
    # Zone 8: Not Populated
  # Virtual Zones
    # Zone 9: Rear Door
    # Zone 10: Front Room Windows
    # Zone 11: Kitchen Windows
    # Zone 12: Living Room Windows
    # Zone 13: Master Bedroom Windows
    # Zone 14: Master Bathroom Window
    # Zone 15: Red Room Windows
    # Zone 16: Eden's Windows

substitutions:
  # change the name to suit your needs. This is what esphome will use as the friendly name for your component.
  # also used as a prefix for all fields
  systemName: "dscalarm" 

  #you can enter a list of user codes mapped to their names for display in armed/disarmed event messages
  userCodes: "1:Matthew,2:Amy,33:Hostage" 

  #Only comes into effect if a password prompt occurs when arming eg. night mode
  accessCode: !secret access_code 

  #used to select the default partition associated with the alarm panel messages
  defaultPartition: "1" 

  #zone expander addresses:
  # 9  - zones 9-16
  # 10 - zones 17-24
  # 11 - zones 25-32
  # 12 - zones 33-40 (for systems with 64 zone support)
  # 13 - zones 41-48 (for systems with 64 zone support)
  # 14 - zones 49-56 (for systems with 64 zone support)
  # 16 - zones 57-64 (for systems with 64 zone support)  
  expanderAddr1: "9" # 1st zone expander emulator address to use . Set to 0 to disable. 
  expanderAddr2: "0" # 1st zone expander emulator address to use . Set to 0 to disable. 

  #ESP32 Pins
  dscClockPin: "22"
  dscReadPin: "21"
  dscWritePin: "18"

  #ESP8266 Pins
  #dscClockPin: "5"
  #dscReadPin: "4"
  #dscWritePin: "15"  

  maxZones: "16" # maximum amount of zones your system supports

esphome:
  name: $systemName
  platform: ESP32
  board: nodemcu-32s
  #platform: ESP8266
  #board: nodemcuv2

  includes:
    # subdirectory path where custom component *.h and *.cpp files are located
    - esphome-dsckeybus/dscKeybusInterface/

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: 192.168.14.3
    gateway: 192.168.15.1
    subnet: 255.255.254.0

  ap:
    ssid: "$systemName"
    password: !secret wifi_password

logger:
  baud_rate: 115200
  level: DEBUG

##API communications - ensure the mqtt: section is commented if using this protocol
api:
   password: !secret api_password  
   #encryption:         
     #key: !secret encryption_key

##MQTT communications - ensure the api: section is commented if using this protocol
#mqtt:
  #broker: xxx.xxx.xxx.xxx #your mqtt broker address
  #port: 1883  
  #username: mqttuser #your mqtt user name
  #password: !secret mqtt_password #your mqtt user pass

ota:
   password: !secret ota_password
   safe_mode: True
   on_begin:
    then:
      - switch.turn_off: connection_status_switch   

status_led:
  pin:
    number: GPIO2
    inverted: no

#comment if using ESP8266 to conserve memory    
time:
 - platform: sntp
   id: sntp_time

custom_component:
 - id: dsckeybus
   lambda: |-
    auto DSCkeybus = new DSCkeybushome($dscClockPin,$dscReadPin,$dscWritePin);
    DSCkeybus->accessCode="$accessCode";
    DSCkeybus->userCodes="$userCodes";
    DSCkeybus->maxZones=$maxZones;
    DSCkeybus->defaultPartition=$defaultPartition;
    DSCkeybus->debug=2; // 0 = off, 1 = minimal, 2 = all packets shown on console  3 =  + serial port debugging
    DSCkeybus->expanderAddr1=$expanderAddr1; //zone expander
    DSCkeybus->expanderAddr2=$expanderAddr2;
    DSCkeybus->onSystemStatusChange([&](std::string statusCode) {
       id(system_status).publish_state(statusCode);
    });

    // if you only have one partition, remove the case 2 and corresponding p2 sensor. You can also add more partitions if needed
    DSCkeybus->onPartitionStatusChange([&](std::string statusCode, int partition) {
       switch(partition) {
         case 1: id(p1).publish_state(statusCode); break;
      } 
    });

    DSCkeybus->onPartitionMsgChange([&](std::string msg,uint8_t partition) {
       switch(partition) {
         case 1: id(m1).publish_state(msg); break;
      } // if you only have one partition, remove the case 2 statement  and corresponding p2 sensor. You can also add more partitions if needed
    });    

    DSCkeybus->onPanelStatusChange([&](panelStatus ps,bool open,int partition) {
      switch (partition) {
        case 0: // all partitions hardware statuses
          switch(ps) {
            case trStatus: id(tr).publish_state(open);break;
            case batStatus: id(bat).publish_state(open);break;
            case acStatus: id(ac).publish_state(open);break;
            case panicStatus: id(panic).publish_state(open);break;
            default: break;
          };break;  
        case 1: //partition 1 armed/ready
          switch(ps) {
            case rdyStatus: id(rdy).publish_state(open);break;
            case armStatus: id(arm).publish_state(open);break;
            default: break;
          };break;
      };
    });

    DSCkeybus->onZoneMsgStatus([&](std::string msg) {
            id(zone_status).publish_state(msg);
    });

    DSCkeybus->onLine1Display([&](std::string msg,int partition) {
        switch(partition) {
            case 1: id(line1).publish_state(msg);break;        
        }
    });

    DSCkeybus->onLine2Display([&](std::string msg,int partition) {
        switch(partition) {    
           case 1: id(line2).publish_state(msg);break;         
        }            
    });
    DSCkeybus->onEventInfo([&](std::string msg) {
            id(event).publish_state(msg);
    });  

    DSCkeybus->onBeeps([&](std::string beep,int partition) {
        switch(partition) {    
            case 1: id(beeps).publish_state(beep);break; 
            case 2: id(beeps_2).publish_state(beep);break;            
        }
    });    

    DSCkeybus->onFireStatusChange([&](bool open,int partition) {
      switch (partition) {
          case 1: id(f1).publish_state(open); break;      
      }
    }); 

    DSCkeybus->onTroubleMsgStatus([&](std::string msg) {
            id(tr_msg).publish_state(msg); //non partition specific trouble messages
    });

    DSCkeybus->onZoneStatusChange([&](uint8_t zone, bool open) {
      switch (zone) {
        case 1: id(z1).publish_state(open); break;
        case 2: id(z2).publish_state(open); break;
        case 3: id(z3).publish_state(open); break;
        case 4: id(z4).publish_state(open); break;
        case 5: id(z5).publish_state(open); break;
        case 6: id(z6).publish_state(open); break;
        case 7: id(z7).publish_state(open); break;
        case 8: id(z8).publish_state(open); break;
        case 9: id(z9).publish_state(open); break;
        case 10: id(z10).publish_state(open); break;
        case 11: id(z11).publish_state(open); break;
        case 12: id(z12).publish_state(open); break;
        case 13: id(z13).publish_state(open); break;
        case 14: id(z14).publish_state(open); break;
        case 15: id(z15).publish_state(open); break;
        case 16: id(z16).publish_state(open); break;
      } // add or delete any zone you need above. Add the coresponding sensor id in the binary_sensor section
    });

    DSCkeybus->onRelayChannelChange([&](uint8_t channel, bool state) {
      switch (channel) {
        case 1: id(r1).publish_state(state); break;
        case 2: id(r2).publish_state(state); break;
      }
    });

    return {DSCkeybus};

#ESP32 only .  Calls a public function within the custom component above. In this case syncs the time   
interval:
  - interval: 3600s
    then:
      - lambda: |-
          static_cast< DSCkeybushome*> (id(dsckeybus).get_component(0))->set_panel_time();  

# add or remove any zone you need. Please ensure you also add/remove the corresonponding case statement above
# change the name to match your own zone configurations
# if you don't want to delete a zone, you can also comment out the name: field to hide it from home assistant
binary_sensor:
    #zone status open/close for each zone 
  - platform: template
    id: z1
    name: "Front door (z1)"
    device_class: door
  - platform: template
    id: z2
    name: "Garage door (z2)"
    device_class: door
  - platform: template
    id: z3
    name: "Fire Alarm (z3)"
    device_class: safety
  - platform: template
    id: z4
    name: "Garage door (z4)"
    device_class: window
  - platform: template
    id: z5
    name: "Garage door (z5)"
    device_class: window
  - platform: template
    id: z6
    name: "Motion Detector (z6)"
    device_class: motion
  - platform: template
    id: z7
    name: "Garage door (z7)"
    device_class: window
  - platform: template
    id: z8
    name: "Garage door (z8)"
    device_class: window
  - platform: template
    id: z9
    name: "Rear Door (z9)"
    device_class: door
  - platform: template
    id: z10
    name: "Front Room Windows (z10)"
    device_class: window
  - platform: template
    id: z11
    name: "Kitchen Windows (z11)"
    device_class: window
  - platform: template
    id: z12
    name: "Living Room Windows (z12)"
    device_class: window
  - platform: template
    id: z13
    name: "Master Bedroom Windows (z13)"
    device_class: window
  - platform: template
    id: z14
    name: "Master Bathroom Window (z14)"
    device_class: window
  - platform: template
    id: z15
    name: "Red Room Windows (z15)"
    device_class: window
  - platform: template
    id: z16
    name: "Eden's Windows (z16)"
    device_class: window

  - platform: template
    id: rdy
    name: "$systemName Partition 1 Ready"

  - platform: template
    id: arm
    name: "$systemName Partition 1 Armed"

    #panel trouble status on/off
  - platform: template
    id: tr
    name: "$systemName Trouble Status"
    device_class: problem

    #battery status ok/low
  - platform: template
    id: bat
    name: "$systemName Battery Status"
    device_class: problem

    #AC power status ok/no power
  - platform: template
    id: ac
    name: "$systemName AC Status"
    device_class: plug

    #panic alarm on/off
  - platform: template
    id: panic
    name: "$systemName Panic Status"
    device_class: safety

    #fire alarm on/off
  - platform: template
    id: f1
    device_class: safety
    name: "$systemName Fire partition 1 Status"

#relay PGM channels. Will show the state of the activate relay channel on/off
#uncomment the name: field if you wish to see it in home assistant
  - platform: template
    id: r1
    name: "$systemName PGM 1"
  - platform: template
    id: r2
    name: "$systemName PGM 2"

# this sensor below is optional - example use of pin d8 as a zone trigger pin for the emulated zone expander  
# this emulates the hardware connection for a pc5108 board. Use a pull down/pull up resistor.  Adjust logic accordingly for the correct logic output. ie invert
 # - platform: gpio  
 #   pin: D8
 #   id: f1
 #   device_class: safety
 #   on_press:       #pin high=on(open), pin low=off(closed)
 #     - lambda: |-
 #         dsc.setZoneFault(17,1);  #set zone 17 as open
 #   on_release:
 #     - lambda: |-
 #         dsc.setZoneFault(17,0);  #set zone 17 as closed

text_sensor:
    #general system status online/disconnected 
  - platform: template
    id: system_status
    name: "$systemName System Status"
    icon: "mdi:shield"
    #battery level status for wireless channels, tamper , in alarm, etc for individual zones
  - platform: template
    id: zone_status
    name: "$systemName zone status "
    icon: "mdi:shield"  
    # partition status ie read/unavailable, in alarm, etc
  - platform: template
    id: p1
    name: "$systemName Partition 1 Status "
    icon: "mdi:shield"

    # more verbose message regarding the partition status. ie zones open, bypassed, etc

  - platform: template
    id: m1
    name: "$systemName Partition 1 Msg "
    icon: "mdi:alert-box"

  - platform: template
    id: line1
    name: "$systemName line1"
    icon: "mdi:alert-box"
  - platform: template
    id: line2
    name: "$systemName line2"
    icon: "mdi:alert-box"  

  - platform: template
    id: event
    name: "$systemName event"
    icon: "mdi:alert-box"  

  - platform: template
    id: beeps
    name: "$systemName beeps"
    icon: "mdi:alert-box" 
  - platform: template
    id: beeps_2
    name: "$systemName partition 2 beeps"
    icon: "mdi:alert-box"   

  - platform: template
    id: tr_msg
    name: "$systemName Trouble Msg " # uncomment to show in home assistant
    icon: "mdi:alert-box"

switch:
    #shows status of connection status to panel.  You can disconnect before upload using the switch.
  - platform: template
    name: "$systemName Connection"
    id: connection_status_switch
    lambda: |-
      return dsc.keybusConnected;
    icon: "mdi:shield-link-variant"
    turn_on_action:
      - switch.toggle: restart_switch
    turn_off_action:
      - lambda: |-
          disconnectKeybus();
  - platform: restart
    id: restart_switch
Dilbert66 commented 1 year ago

Edit: Deleted. I hadnt read your post correctly. I'll double check my logic to see if there is bug.

Dilbert66 commented 1 year ago

yes, it's a bug. I'll correct and push

abishur commented 1 year ago

Cool! Glad to help (also if it makes any difference the answer to your initial question is it looks like my system was set up for normally closed loops with single end of line resistors)

Dilbert66 commented 1 year ago

ok, I did find the issue. Chksum was not being calculated correctly for the response. I've pushed an update.

abishur commented 1 year ago

Thanks! That did it and now I can trigger all of the emulated zones. It's even working for zones on the second expander address.

Dilbert66 commented 1 year ago

Awesome! Glad it's doing the job,!