Caddx Binding Widget

Alarm Control Binding based on the CADDX Binding

Caddx Widget V6c

Makes use of:
UI Widget: Keypad by Yannick Schaus. Used for the Keypad functionality and was the starting point for the entire project
[OH3 Harmony Widget] () by Craig B. Used for the GUI basis. Used to get the basics of the graphical front end.

Tried to keep the graphics of the widget as similar as I am capable of to the look of the NX-148e keypad. Though had to make some exceptions for functionality.

Received extensive help on the forum with ideas, syntax etc.

The Widget is made up of the Main Graphical Front End (laid out to fit an Android Phone in Portrait Mode), with two additional Widgets to format the Bypass Zones and Faulted Zones display popups. The widget also relies on an underlying set of rules to send actions to the binding etc. The rules in my setup are TEXT based, however these could be recreated into the UI if required I beleive (easier to share this way too).

The two display widgets could be replaced with a “actionGroupPopupItem” action. However I did not like the display and there do not seem to be any options for formatting the display at all.

The Widget Offers the following settings via the Widget Props:

Partiton Selection Proxy Item - this is a proxy STRING item used to process the Partiton Selection to allow the switching between Partitons within the Widget.
Alarm Feedback Item - used to provide feedback from rules etc in the widget. This item should have the Expire Metadata set to a suitable time with the “Update State” to set state to “-”.
Show Tooltips in Widget - enable or disable Tootips when the widget is running. Nice to have when starting and an easy place to give details, but not required for daily operation.
Mask Character - as per the original Keypad, just a character to mask the CHaracters being entered.

In order to make use of the PROPS, there is a requirement for a standard name convention. I used PartitonX_. There are groups that must comply to this as well. Difficult to list all of them, however a staring point would be:

Groups:
	<PartitionX>	_Doors			Door Contacts	/ MAG
			        _MotionSensors	Motions Sensors / PIR
			        _Zones			All Zones in a partition
			        _Bypass_Group	Group of all Zone Bypass channel links on each Zone Thing. (Switch, All OFF then OFF, else ON)

Items:
	<PartitionX>	_Pin_Number		     Used to carry/activate the disarm function which requires PIN
			        _Armed			     Switch Item linked in Binding
			        _ReadyToArm		     Switch item linked in Binding
			        _ErrorBeepTripleBeep Switch item linked in Binding
			        _EntryGuard		     Switch item linked in Binding
			        _Stay			     Switch to toggle Entry Guard/Stay 
			        _ChimeModeOn         Switch item linked in Binding
			        _Chime			     Switch to toggle Chime 
			        _Exit1			     Switch item linked in Binding
			        _Exit			     Switch to toggle Exit Mode Arming
			        _Pin_Number		     String Item to hold the entered Pin Number

The PartitionX could be changed - would however require editing the Widget Code to replace the Selection actionOptions from Partiton1=1,Partiton2=2,Partiton3=3,Partiton4=4. Additional Partitons could also be added the same way.

As you will notice some of the buttons show a “Not yet Active” tooltips - this is either because I do not have the equipment / configuration or the feature is not yet available in the binding.

I would have liked to play audio on “Triple Beep” error. However Main UI does not at this stage support WebAudio, so had to go with and LED option (ERROR)

I disabled the * and # on keypad. They gave me an error in widget and I don’t think they are required for functionality. Could be removed if required.

The PIN number details need to be filtered from the logs - via the log4j2.xml with REGEX expressions.

To Do list:

  • Combine the two step process to select partition into a single click.
  • Implement Audio Feedback.
  • Make a responsive layout. Found that different devices do not have the same layout. So what looks good on my Android might not look as good on a PC with a Chrome browser.
  • Add missing buttons actions when possible.
  • Integrate the Faulted Zones and Bypass Zones widgets back into main widget.

Issues:
See errors as follows in the logs. These are intermittent and do not seem to cause issues. Have not been able to determine what the cause is.

2021-04-30 15:10:42.027 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: undefined<Item Suffix>

CaddxFaultedCard.txt (818 Bytes) CaddxBypassCard.txt (899 Bytes)
caddx_graphic_portrait_V1.txt (21.8 KB)
EDIT: Forgot to include .rules file - you will need to replace with your Bridge ID.
Partition1.txt (3.1 KB)

EDIT: Fixed error on ARMED and BYPASS buttons - not using vars for Partiton Selection. Code replaced

EDIT 06/05/2021 Added V2:
caddx_graphic_portrait_V2.txt (26.5 KB)

EDIT 13/07/2021 Added V5:
caddx_graphic_portrait_V5.txt (33.2 KB)

Uses % for layout
Built in Logs, Bypass Zones, Faulted Zones - Toggle with READY, BYPASS and DOWN_ARROW
Only external items is the Feedback item.
EDIT 22/07/2021 Added V6
caddx_graphic_portrait_V6.txt (28.1 KB)
Made some enhancements based on the suggestions by @jossuar . Fully self contained now - no external rules required

EDIT 16/12/2022 Added V6c
Sadly my Caddx system has failed so I will be replacing and no longer making changes to this widget. Hopefully it helps someone out there.
Will be changing to a Paradox EVO setup and have started a similar widget. Binding does not look as complete however, so going to miss by Caddx.

Changelog

Version 6c

Make the widget self contained with no external rules requirements, Added Fixed Popup Size

Issues:

See errors as follows occasionally when opening widget (items do exist):

2021-10-04 15:11:24.912 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: PIR Cottage Lounge 22

Resources

uid: caddx_graphic_portrait_V6c
tags: []
props:
  parameters:
    - context: item
      description: Alarm Feedback Item
      label: Alarm Feedback Item
      name: alarmFeedback
      required: false
      type: TEXT
    - context: item
      description: Send Command Item
      label: Send Command Item
      name: sendCommand
      required: true
      type: TEXT
    - default: Partition1
      description: Default (Fallback) Partition
      label: Default (Fallback) Partition
      name: selectedPartitionC
      required: false
      type: TEXT
    - description: Show Tooltips in Widget
      label: Show Tooltips in Widget
      name: tooltipEnable
      required: false
      type: BOOLEAN
    - description: Replace pincode characters with this string, leave blank to show it as-is
      label: Mask character
      name: mask
      required: false
  parameterGroups: []
timestamp: Dec 14, 2022, 7:55:27 AM
component: f7-page
config:
  style:
    --f7-bars-translucent-blur: none
    --f7-bars-translucent-opacity: none
    --f7-card-margin-horizontal: 0px
    --f7-navbar-bg-color: transparent
    --f7-navbar-border-color: transparent
    --f7-navbar-font-size: 15px
    --f7-navbar-height: 35px
    --f7-navbar-link-color: white
    --f7-navbar-shadow-image: none
    --f7-navbar-text-color: white
    --f7-popup-tablet-width: 40px
    background-color: rgb(220,220,220)
    border-radius: 20px
    height: 720px
    left: 0px
    text-overflow: ellipsis
    top: 0px
    width: 360px
slots:
  default:
    - component: Label
      config:
        style:
          color: white
          font-size: 25px
          left: 30%
          line-height: 32px
          overflow: hidden
          position: absolute
          text-overflow: ellipsis
          text-shadow: -1px 1px 1px hsl(0,0%,66%)
          top: 0%
          white-space: nowrap
        text: ="Caddx Control"
    - component: oh-button
      config:
        bgColor: gray
        clearVariable: selectedPartitionC
        large: true
        popupClose: .modal-in
        style:
          color: white
          height: 55px
          left: 6.0%
          position: absolute
          top: 5%
          width: 40px
        tooltip: '=!(props.tooltipEnable) ? false : "Close Popup"'
        tooltip-trigger: hover
      slots:
        default:
          - component: f7-icon
            config:
              color: white
              f7: clear_fill
              style:
                color: black
                font-size: 25px
                left: 20%
                overflow: hidden
                position: absolute
                top: 30%
    - component: f7-badge
      config:
        bgColor: gray
        style:
          border-radius: 0px
          height: 55px
          left: 20%
          position: absolute
          top: 5%
          width: 60%
    - component: oh-link
      config:
        bgColor: gray
        large: true
        raised: true
        style:
          left: 20%
          position: absolute
          top: 5.5%
          width: 60%
        text: '=(vars.selectedPartitionC  === NULL) ? "Select Partition" : vars.selectedPartitionC '
        textColor: white
        tooltip: '=!(props.tooltipEnable) ? false : "Selected Partition"'
        tooltip-trigger: hover
    - component: oh-link
      config:
        bgColor: gray
        large: true
        raised: true
        style:
          left: 20%
          position: absolute
          top: 5.5%
          width: 60%
          z-index: 999
        text: '=(items[props.alarmFeedback].state  === "-") ? "" : (items[props.alarmFeedback].state) '
        textColor: white
    - component: oh-link
      config:
        bgColor: gray
        large: true
        raised: true
        style:
          left: 25%
          position: absolute
          top: 9%
          width: 50%
          z-index: 0
        text: "=(props.mask && vars.pincode) ? props.mask.repeat(vars.pincode.length || 0) : vars.pincode"
        textColor: white
    - component: oh-button
      config:
        action: variable
        actionVariable: showLogs
        actionVariableValue: '=(vars.showLogs == "null") ? true : !(vars.showLogs)'
        bgColor: gray
        iconColor: black
        iconF7: arrowtriangle_up_fill
        iconSize: 20
        style:
          color: white
          position: absolute
          right: 6.8%
          top: 5.0%
        tooltip: '=!(props.tooltipEnable) ? false : "Show Alarm Logs Drop Down"'
        tooltip-trigger: hover
    - component: oh-button
      config:
        action: variable
        actionVariable: Faulted
        actionVariableValue: '=(vars.Faulted == "null") ? true : !(vars.Faulted)'
        bgColor: gray
        iconColor: black
        iconF7: arrowtriangle_down_fill
        iconSize: 20
        style:
          border-radius: 5px
          color: white
          position: absolute
          right: 6.8%
          top: 9.0%
        tooltip: '=!(props.tooltipEnable) ? false : "Show Faulted Zones"'
        tooltip-trigger: hover
    - component: f7-badge
      config:
        bgColor: '=(items[vars.selectedPartitionC + "_Armed"].state === "ON") ? "red" : "gray"'
        style:
          border-radius: 12px
          height: 20px
          left: 5%
          position: absolute
          top: 15%
          width: 60px
        tooltip: '=!(props.tooltipEnable) ? false : "Partition Armed"'
        tooltip-trigger: hover
      slots:
        default:
          - component: Label
            config:
              text: ARMED
    - component: f7-badge
      config:
        bgColor: '=(items[vars.selectedPartitionC + "_ReadyToArm"].state === "ON") ? "green" : "gray"'
        style:
          border-radius: 12px
          height: 20px
          left: 30%
          position: absolute
          top: 15%
          width: 60px
        tooltip: '=!(props.tooltipEnable) ? false : "Partiton ready or faulted?"'
        tooltip-trigger: hover
      slots:
        default:
          - component: Label
            config:
              text: READY
    - component: f7-badge
      config:
        bgColor: gray
        style:
          border-radius: 12px
          height: 20px
          left: 55%
          position: absolute
          top: 15%
          width: 60px
        tooltip: '=!(props.tooltipEnable) ? false : "Not yet Active"'
        tooltip-trigger: hover
      slots:
        default:
          - component: Label
            config:
              text: FIRE
    - component: f7-badge
      config:
        bgColor: '=(items.Panel_ACPowerOn.state === "ON") ? "green" : "gray"'
        style:
          border-radius: 12px
          height: 20px
          left: 80%
          position: absolute
          top: 15%
          width: 60px
        tooltip: '=!(props.tooltipEnable) ? false : "Panel has AC Power (Green)"'
        tooltip-trigger: hover
      slots:
        default:
          - component: Label
            config:
              text: POWER
    - component: oh-button
      config:
        bgColor: '=(items[vars.selectedPartitionC + "_ErrorBeepTripleBeep"].state === "ON") ? "red" : "gray"'
        style:
          border-radius: 12px
          color: white
          left: 5%
          position: absolute
          top: 20%
        text: ERROR
        tooltip: '=!(props.tooltipEnable) ? false : "Indicates Tripple Beep Error"'
        tooltip-trigger: hover
    - component: oh-button
      config:
        action: variable
        actionVariable: pincode
        actionVariableValue: "=(vars.pincode) ? vars.pincode + '1' : '1'"
        bgColor: gray
        large: false
        raised: true
        style:
          border-radius: 12px
          left: 25%
          position: absolute
          top: 20%
        text: "1"
        textColor: white
    - component: oh-button
      config:
        action: variable
        actionVariable: pincode
        actionVariableValue: "=(vars.pincode) ? vars.pincode + '2' : '2'"
        bgColor: gray
        large: false
        raised: true
        style:
          border-radius: 12px
          left: 42%
          position: absolute
          top: 20%
        text: "2"
        textColor: white
    - component: oh-button
      config:
        action: variable
        actionVariable: pincode
        actionVariableValue: "=(vars.pincode) ? vars.pincode + '3' : '3'"
        bgColor: gray
        large: false
        raised: true
        style:
          border-radius: 12px
          left: 60%
          position: absolute
          top: 20%
        text: "3"
        textColor: white
    - component: f7-badge
      config:
        bgColor: '=(items[vars.selectedPartitionC + "_EntryGuard"].state === "ON") ? "green" : "gray"'
        style:
          border-radius: 12px
          height: 12px
          left: 71%
          position: absolute
          top: 21%
          width: 25px
        text: StayLED
    - component: oh-button
      config:
        action: command
        actionCommand: '="partition_secondary_command|0," + (1 << (((vars.selectedPartitionC === NULL) ? props.selectedPartitionC : vars.selectedPartitionC).substr(-1) - 1))'
        actionItem: =props.sendCommand
        bgColor: gray
        iconF7: person_2_square_stack_fill
        iconSize: 20
        style:
          border-radius: 12px
          left: 79%
          position: absolute
          top: 20%
          width: 12%
        textColor: white
        tooltip: '=!(props.tooltipEnable) ? false : "Arm in STAY Mode"'
        tooltip-trigger: hover
    - component: oh-button
      config:
        action: command
        actionCommand: ="partition_secondary_command|4,1"
        actionItem: =props.sendCommand
        bgColor: gray
        iconColor: red
        iconF7: flame
        iconSize: 20
        style:
          border-radius: 12px
          color: white
          left: 6%
          position: absolute
          top: 27%
        tooltip: '=!(props.tooltipEnable) ? false : "Fire Panic"'
        tooltip-trigger: hover
    - component: oh-button
      config:
        action: variable
        actionVariable: pincode
        actionVariableValue: "=(vars.pincode) ? vars.pincode + '4' : '4'"
        bgColor: gray
        large: false
        raised: true
        style:
          border-radius: 12px
          left: 25%
          position: absolute
          top: 27%
        text: "4"
        textColor: white
    - component: oh-button
      config:
        action: variable
        actionVariable: pincode
        actionVariableValue: "=(vars.pincode) ? vars.pincode + '5' : '5'"
        bgColor: gray
        large: false
        raised: true
        style:
          border-radius: 12px
          left: 42%
          position: absolute
          top: 27%
        text: "5"
        textColor: white
    - component: oh-button
      config:
        action: variable
        actionVariable: pincode
        actionVariableValue: "=(vars.pincode) ? vars.pincode + '6' : '6'"
        bgColor: gray
        large: false
        raised: true
        style:
          border-radius: 12px
          left: 60%
          position: absolute
          top: 27%
        text: "6"
        textColor: white
    - component: f7-badge
      config:
        bgColor: '=(items[vars.selectedPartitionC + "_ChimeModeOn"].state === "ON") ? "green" : "gray"'
        style:
          border-radius: 12px
          height: 12px
          left: 71%
          position: absolute
          top: 28%
          width: 25px
        text: ChimeLED
    - component: oh-button
      config:
        action: command
        actionCommand: '="partition_secondary_command|1," + (1 << (((vars.selectedPartitionC === NULL) ? props.selectedPartitionC : vars.selectedPartitionC).substr(-1) - 1))'
        actionItem: =props.sendCommand
        bgColor: gray
        iconF7: music_note_2
        iconSize: 20
        style:
          border-radius: 12px
          left: 79%
          position: absolute
          top: 27%
          width: 12%
        textColor: white
        tooltip: '=!(props.tooltipEnable) ? false : "Toggle CHIME Mode"'
        tooltip-trigger: hover
    - component: oh-button
      config:
        action: command
        actionCommand: ="partition_secondary_command|5,1"
        actionItem: =props.sendCommand
        bgColor: gray
        iconColor: green
        iconF7: plus
        iconSize: 28
        style:
          border-radius: 12px
          color: white
          left: 6%
          position: absolute
          top: 37%
        tooltip: '=!(props.tooltipEnable) ? false : "Medical Panic"'
        tooltip-trigger: hover
    - component: oh-button
      config:
        action: variable
        actionVariable: pincode
        actionVariableValue: "=(vars.pincode) ? vars.pincode + '7' : '7'"
        bgColor: gray
        large: false
        raised: true
        style:
          border-radius: 12px
          left: 25%
          position: absolute
          top: 34%
        text: "7"
        textColor: white
    - component: oh-button
      config:
        action: variable
        actionVariable: pincode
        actionVariableValue: "=(vars.pincode) ? vars.pincode + '8' : '8'"
        bgColor: gray
        large: false
        raised: true
        style:
          border-radius: 12px
          left: 42%
          position: absolute
          top: 34%
        text: "8"
        textColor: white
    - component: oh-button
      config:
        action: variable
        actionVariable: pincode
        actionVariableValue: "=(vars.pincode) ? vars.pincode + '9' : '9'"
        bgColor: gray
        large: false
        raised: true
        style:
          border-radius: 12px
          left: 60%
          position: absolute
          top: 34%
        text: "9"
        textColor: white
    - component: f7-badge
      config:
        bgColor: '=(items[vars.selectedPartitionC + "_Exit1"].state === "ON") ? "green" : "gray"'
        style:
          border-radius: 12px
          height: 12px
          left: 71%
          position: absolute
          top: 35%
          width: 25px
        text: ExitLED
    - component: oh-button
      config:
        action: command
        actionCommand: '="partition_secondary_command|2," + (1 << (((vars.selectedPartitionC === NULL) ? props.selectedPartitionC : vars.selectedPartitionC).substr(-1) - 1))'
        actionItem: =props.sendCommand
        bgColor: gray
        iconF7: house_alt
        iconSize: 20
        style:
          border-radius: 12px
          left: 79%
          position: absolute
          top: 34%
          width: 12%
        textColor: white
        tooltip: '=!(props.tooltipEnable) ? false : "Arm in EXIT Mode"'
        tooltip-trigger: hover
    - component: oh-button
      config:
        bgColor: gray
        large: false
        raised: true
        style:
          border-radius: 12px
          left: 25%
          position: absolute
          top: 41%
        text: "*"
        textColor: white
        tooltip: '=!(props.tooltipEnable) ? false : "Not yet Active"'
        tooltip-trigger: hover
    - component: oh-button
      config:
        action: variable
        actionVariable: pincode
        actionVariableValue: "=(vars.pincode) ? vars.pincode + '0' : '0'"
        bgColor: gray
        large: false
        raised: true
        style:
          border-radius: 12px
          left: 42%
          position: absolute
          top: 41%
        text: "0"
        textColor: white
    - component: oh-button
      config:
        bgColor: gray
        large: false
        raised: true
        style:
          border-radius: 12px
          left: 60%
          position: absolute
          top: 41%
        text: "#"
        textColor: white
        tooltip: '=!(props.tooltipEnable) ? false : "Not yet Active"'
        tooltip-trigger: hover
    - component: f7-badge
      config:
        bgColor: '=(items[vars.selectedPartitionC + "_Bypass_Group"].state === "ON") ? "green" : "gray"'
        style:
          border-radius: 12px
          height: 12px
          left: 71%
          position: absolute
          top: 42%
          width: 25px
        text: BypassLED
    - component: oh-button
      config:
        action: variable
        actionVariable: Bypass
        actionVariableValue: '=(vars.Bypass == "null") ? true : !(vars.Bypass)'
        bgColor: gray
        iconF7: arrow_branch
        iconSize: 20
        style:
          border-radius: 12px
          left: 79%
          position: absolute
          top: 41%
          width: 12%
        textColor: white
        tooltip: '=!(props.tooltipEnable) ? false : "Allow Zone Bypass via Popup"'
        tooltip-trigger: hover
    - component: oh-button
      config:
        action: command
        actionCommand: ="partition_secondary_command|6,1"
        actionItem: =props.sendCommand
        bgColor: gray
        iconColor: blue
        iconF7: shield_fill
        iconSize: 24
        style:
          border-radius: 12px
          color: white
          left: 6%
          position: absolute
          top: 48%
        tooltip: '=!(props.tooltipEnable) ? false : "Police Panic"'
        tooltip-trigger: hover
    - component: oh-button
      config:
        action: variable
        actionVariable: pincode
        actionVariableValue: ""
        bgColor: gray
        iconColor: white
        iconF7: trash
        iconSize: 19
        style:
          border-radius: 12px
          color: white
          left: 24.5%
          position: absolute
          top: 48%
    - component: oh-button
      config:
        action: command
        actionCommand: '="partition_primary_command_with_pin|0x" + (vars.pincode).substr(1,1) + (vars.pincode).substr(0,1) + ",0x" + (vars.pincode).substr(3,1) + (vars.pincode).substr(2,1) + ",0x" + (vars.pincode+"00").substr(4,1) + (vars.pincode+"00").substr(4,1) + "," + ((items[((vars.selectedPartition === NULL) ? props.selectedPartition : vars.selectedPartition) + "_Armed"].state === "ON") ? "1" : "2") + "," + (1 << (((vars.selectedPartition === NULL) ? props.selectedPartition : vars.selectedPartition).substr(-1) - 1))'
        actionItem: =props.sendCommand
        bgColor: gray
        clearVariable: pincode
        closePopup: =props.closePopup
        disabled: =!vars.pincode
        iconColor: white
        iconF7: hand_thumbsup
        iconSize: 19
        style:
          border-radius: 12px
          color: white
          left: 41.5%
          position: absolute
          top: 48%
    - component: oh-button
      config:
        action: variable
        actionVariable: pincode
        actionVariableValue: '=(vars.pincode) ? vars.pincode.substring(0, vars.pincode.length - 1) : ""'
        bgColor: gray
        iconColor: white
        iconF7: delete_left
        iconSize: 19
        style:
          border-radius: 12px
          color: white
          left: 59%
          position: absolute
          top: 48%
    - component: f7-badge
      config:
        bgColor: '=(items[vars.selectedPartitionC + "_Cancel"].state === "ON") ? "green" : "gray"'
        style:
          border-radius: 12px
          height: 12px
          left: 71%
          position: absolute
          top: 49%
          width: 25px
        text: CancelLED
    - component: oh-button
      config:
        action: command
        actionCommand: ON
        actionItem: =(vars.selectedPartitionC) + '_Cancel'
        bgColor: gray
        iconF7: xmark_circle
        iconSize: 19
        style:
          border-radius: 12px
          left: 79%
          position: absolute
          top: 48%
          width: 12%
        textColor: white
        tooltip: '=!(props.tooltipEnable) ? false : "Not yet Active"'
        tooltip-trigger: hover
    - component: f7-list
      config:
        class:
          - padding-bottom
        style:
          --f7-list-border-color: transparent
          background: rgb(235, 232, 232)
          left: 20%
          opacity: 80%
          position: absolute
          top: 16%
          width: 60%
        visible: =(vars.Faulted) == true
      slots:
        default:
          - component: Label
            config:
              style:
                background: rgb(191, 189, 189)
                font-size: 75%
                font-weight: 500
                line-height: 20px
                padding-left: 20px
              text: Zones Faulted
          - component: oh-repeater
            config:
              for: item
              fragment: true
              groupItem: =(vars.selectedPartitionC) + '_Zones'
              sourceType: itemsInGroup
            slots:
              default:
                - component: oh-list-item
                  config:
                    color: '=(items[loop.item.name].state == "ON") ? "red" : "gray"'
                    item: =loop.item.name
                    style:
                      --f7-list-item-border-color: transparent
                      --f7-list-item-min-height: 14px
                      --f7-list-item-padding-vertical: 1px
                      backgroundColor: rgb(235, 232, 232)
                      font-size: 70%
                    title: =loop.item.label
                    visible: =items[loop.item.name].state == "OPEN"
    - component: f7-list
      config:
        class:
          - padding-bottom
          - big-toggles
        style:
          --f7-list-border-color: transparent
          left: 20%
          opacity: 80%
          position: absolute
          top: 16%
          width: 60%
        visible: =(vars.Bypass) == true
      slots:
        default:
          - component: Label
            config:
              style:
                backgroundColor: rgb(191, 189, 189)
                font-size: 75%
                font-weight: 500
                line-height: 20px
                padding-left: 20px
              text: Zones Bypassed
          - component: oh-repeater
            config:
              for: item
              fragment: true
              groupItem: =(vars.selectedPartitionC) + '_Bypass_Group'
              sourceType: itemsInGroup
            slots:
              default:
                - component: oh-toggle-item
                  config:
                    color: '=(items[loop.item.name].state == "ON") ? "green" : "gray"'
                    item: =loop.item.name
                    style:
                      --f7-list-item-border-color: transparent
                      --f7-list-item-min-height: 14px
                      --f7-list-item-padding-vertical: 1px
                      --f7-toggle-height: 10px
                      --f7-toggle-width: 35px
                      backgroundColor: rgb(235, 232, 232)
                      font-size: 70%
                    title: =loop.item.label
    - component: f7-list
      config:
        class:
          - padding-bottom
        noChevron: false
        style:
          --f7-list-border-color: transparent
          background: rgb(235, 232, 232)
          left: 20%
          opacity: 80%
          position: absolute
          top: 16%
          width: 60%
        visible: =(vars.showLogs) == true
      slots:
        default:
          - component: Label
            config:
              style:
                backgroundColor: rgb(191, 189, 189)
                font-size: 80%
                font-weight: 500
                line-height: 150%
                padding-left: 1%
              text: Alarm Logs
          - component: f7-list-item
            config:
              accordionItem: true
              style:
                --f7-list-item-border-color: transparent
                --f7-list-item-min-height: 14px
                --f7-list-item-padding-horizontal: 10px
                --f7-list-item-title-line-height: 100%
                backgroundColor: rgb(235, 232, 232)
                color: black
                font-size: 75%
              title: =items.Panel_LogMessage10.state
            slots:
              default:
                - component: f7-accordion-content
                  slots:
                    default:
                      - component: f7-list-item
                        config:
                          style:
                            font-size: 75%
                            z-index: 1
                          title: =items.Panel_LogMessage9.state
                      - component: f7-list-item
                        config:
                          style:
                            font-size: 75%
                          title: =items.Panel_LogMessage8.state
                      - component: f7-list-item
                        config:
                          style:
                            font-size: 75%
                          title: =items.Panel_LogMessage7.state
                      - component: f7-list-item
                        config:
                          style:
                            font-size: 75%
                          title: =items.Panel_LogMessage6.state
                      - component: f7-list-item
                        config:
                          style:
                            font-size: 75%
                          title: =items.Panel_LogMessage5.state
                      - component: f7-list-item
                        config:
                          style:
                            font-size: 75%
                          title: =items.Panel_LogMessage4.state
                      - component: f7-list-item
                        config:
                          style:
                            font-size: 75%
                          title: =items.Panel_LogMessage3.state
                      - component: f7-list-item
                        config:
                          style:
                            font-size: 75%
                          title: =items.Panel_LogMessage2.state
                      - component: f7-list-item
                        config:
                          style:
                            font-size: 75%
                          title: =items.Panel_LogMessage1.state
    - component: f7-block
      config:
        class:
          - padding
        style:
          --f7-button-bg-color: var(--f7-card-bg-color)
          --f7-button-text-color: var(--f7-text-color)
          --f7-theme-color-rgb: var(--f7-color-blue-rgb)
          position: absolute
          top: 85%
          width: 100%
          z-index: 999
      slots:
        default:
          - component: f7-row
            config:
              class: no-gap
              style:
                --f7-button-bg-color: transparent
                --f7-theme-color: var(--f7-color-blue)
            slots:
              default:
                - component: oh-repeater
                  config:
                    for: partition
                    fragment: true
                    in:
                      - 1
                      - 2
                      - 3
                      - 4
                      - 5
                      - 6
                      - 7
                      - 8
                  slots:
                    default:
                      - component: f7-row
                        config:
                          width: "10"
                        slots:
                          default:
                            - component: oh-button
                              config:
                                action: variable
                                actionVariable: selectedPartitionC
                                actionVariableValue: ='Partition' + loop.partition
                                bgColor: '=(items["Partition" + loop.partition + "_Armed"].state === "-") ? "gray" : (items["Partition" + loop.partition + "_Armed"].state === "ON") ? "red" : "green"'
                                disabled: '=(items["Partition" + loop.partition + "_Armed"].state === "-") ? true : false'
                                fill: true
                                raised: false
                                style:
                                  --f7-button-hover-bg-color: var(--f7-color-blue-tint)
                                  --f7-button-pressed-bg-color: var(--f7-color-blue-tint)
                                  border-radius: 12px
                                  overflow: hidden
                                  text-overflow: ellipsis
                                  white-space: nowrap
                                  z-index: 999
                                text: =["P" + loop.partition]
                                textColor: white
                                tooltip: '=!(props.tooltipEnable) ? false : "Apply Partition to current run"'
                                tooltip-trigger: hover

Called as a POPUP from an oh-cell as follows:

component: oh-cell
config:
  title: Alarm
slots:
  background:
    - component: f7-block
      config:
        bgColor: none
        style:
          height: 40%
          left: 0%
          position: absolute
          top: 60%
          width: 100%
      slots:
        default:
          - component: oh-button
            config:
              popupOpen: .caddx-pop
              style:
                height: 100%
                width: 100%
              text: OPEN
    - component: f7-popup
      config:
        class: caddx-pop
        style:
          background-color: rgb(220,220,220)
          border-radius: 30px
          height: 720px
          text-overflow: ellipsis
          width: 360px
      slots:
        default:
          - component: widget:caddx_graphic_portrait_V6c
            config:
              alarmFeedback: Alarm_Feedback
              popupClose: .caddx-pop
              selectedPartition: =["Partition1"]
              sendCommand: CaddxBridge_SendCommand
              tooltipEnable: true
  header:
    - component: f7-list
      config:
        mediaList: true
      slots:
        default:
          - component: f7-list-item
            config:
              title: Alarm
            slots:
              title:
                - component: f7-chip
                  config:
                    color: '=(items.Partition1_Armed.state === "ON") ? "red" : "green"'
                    text: 1
                - component: f7-chip
                  config:
                    color: '=(items.Partition2_Armed.state === "ON") ? "red" : "green"'
                    text: 2
                - component: f7-chip
                  config:
                    color: '=(items.Partition3_Armed.state === "ON") ? "red" : "green"'
                    text: 3
                - component: f7-chip
                  config:
                    color: '=(items.Partition4_Armed.state === "ON") ? "red" : "green"'
                    text: 4

3 Likes

Spacer

Well done, looks really great!

1 Like

Hi @Mark_VG,

i did use your widget as an input and simplified it, a bit.
It does not need external rules. It only relies on the items having the default names.
It is responsive and renders correctly also on phones, etc.

It consists of the following two widgets:
caddxKeypad.txt (17.5 KB)
caddxZoneBypass.txt (1.8 KB)

Can you give it a try, to test if it works on a multi partition setup.
Thanks

Hi Georgios

Gave it a try, but cannot get the alarm to disarm. Looks very good though.

I had updated to more responsive and all into one (excluding rules)

Also using variables instead of items for the pincode

Can you explain:

                                action: command
                                actionItem: CaddxBridge_SendCommand
                                actionCommand: ="partition_secondary_command|4,1"

Also, when selecting the Partition seems to light the incorrect status lights (Armed, Ready, Fire, Power)

Cheers
Mark

EDIT: I have updated my initial post above with my latest version.

EDIT: Managed to get the ARM/DISARM to work. Had to link CaddxBridge_SendCommand Still not sure about the actionCommand though? Also, the Pin does not clear .

EDIT: Looks like Item for PIN is not required in Props? Using variable

Hi @Mark_VG,

i was sure you would figure it out.

The SendCommand channel is nowhere documented. My bad. I have to amend the documentation.
You can send commands to the panel by writing a special formulated string in this channel.
The string consists of two parts separated with a pipe “|”. The first part is the command and the second part is the data of the command. Using this channel you do not need an item for the PIN, you can just send the command directly to the panel.

The most interest is in the following partition commands:

partition_primary_command_with_pin|0x<digit2><digit1>,0x<digit4><digit3>,0x<digit6><digit5>,<pfunction>,<partition_mask>
digit1: Pin digit 1
digit2: Pin digit 2
digit3: Pin digit 3
digit4: Pin digit 4
digit5: Pin digit 5 (0 if the system has a 4 digit pin)
digit6: Pin digit 6 (0 if the system has a 4 digit pin)
pfunction: Primary function
   0: Turn off any sounder or alarm
   1: Disarm
   2: Arm in away mode
   3: Arm in stay mode
   4: Cancel
   5: Initiate auto-arm
   6: Start walk-test mode
   7: Stop walk-test mode
partition_mask: Partition mask (number resulting from the addition of the below)
   1: Partition 1
   2: Partition 2
   4: Partition 3
   8: Partition 4
  16: Partition 5
  32: Partition 6
  64: Partition 7
 128: Partition 8

partition_secondary_command|<sfunction>,<partition_mask>
sfunction: Secondary function
   0: Stay (1 button arm / toggle interiors)
   1: Chime (toggle chime mode)
   2: Exit (1 button arm / toggle instant)
   3: Bypass interiors
   4: Fire panic
   5: Medical panic
   6: Police panic
   7: Smoke detector reset
   8: Auto callback download
   9: Manual pickup download
  10: Enable silent exit (for this arm cycle)
  11: Perform test
  12: Group bypass
  13: Auxiliary function 1, 
  14: Auxiliary function 2, 
  15: Start keypad sounder
partition_mask: See above

Examples:

Instant arm Partition 3: partition_secondary_command|2,4
Fire panic on partition 5: partition_secondary_command|4,16
Disarm all partitions (4 digit PIN 5789): partition_primary_command_with_pin|0x75,0x98,0x00,1,255
Arm partition 3 in stay mode (4 digit PIN 5789): partition_primary_command_with_pin|0x75,0x98,0x00,3,4

With the above info and looking at the widget i posted above, i think you can amend and make your widget more powerful.

Thanks Georgios. Have started to include some of the ideas. Makes sense now.

@jossuar Hi Georgios

Please can you explain this expression to me?

actionCommand: '="partition_secondary_command|1," + (1 << (((vars.selectedPartition === NULL) ? props.selectedPartition : vars.selectedPartition).substr(-1) - 1))'

also need help with the disarm one?

actionCommand: '="partition_primary_command_with_pin|0x" + (vars.pincode).substr(1,1) + (vars.pincode).substr(0,1) + ",0x" + (vars.pincode).substr(3,1) + (vars.pincode).substr(2,1) + ",0x" + (vars.pincode+"00").substr(4,1) + (vars.pincode+"00").substr(4,1) + "," + ((items[((vars.selectedPartition === NULL) ? props.selectedPartition : vars.selectedPartition) + "_Armed"].state === "ON") ? "1" : "2") + "," + (1 << (((vars.selectedPartition === NULL) ? props.selectedPartition : vars.selectedPartition).substr(-1) - 1))'

Thanks
Mark

Hello @Mark_VG,

for the 1st expression:
the property props.selectedPartition has the default selected partition.
the variable vars.selectedPartition holds the actual selected partition by the user.

Both have one of the following values: “Partition1”, “Partition2” … “Partition8”

The following returns the default if no partition is selected by the user.

(vars.selectedPartition === NULL) ? props.selectedPartition : vars.selectedPartition

The following returns one character from the right of selectedPartition var or prop. Its a value from “1” to “8”:

selectedPartition.substr(-1)

The following returns a number from 0 to 7:

selectedPartition.substr(-1) -1

The (1<<num) is a left shift bit wise operation it shifts the 1 by “num” places to the left.

1<<0 = 1
1<<1 = 2
1<<2 = 4
1<<3 = 8
1<<4 = 16
1<<5 = 32
1<<6 = 64
1<<7 = 128

So the expression is:

'="partition_secondary_command|1," + (1 << (selectedPartition.substr(-1) - 1))'

which in the end will evaluate for Partition1 to the string:

"partition_secondary_command|1,1"

and for Partition3 to the string:

"partition_secondary_command|1,4"

If you look at the previous post for the partition_secondary_command the “1” toggles the chime mode and the 4 is the partition mask.

For more info about the disarm i will get back tomorrow. Its getting late here.

Thank you for the great explanation. Makes it easier to understand. Was a bit confused by the props value as did not seem to be used. Makes sense now though. I have included the Default back into my version as well :slight_smile:

Would appreciate the info about the more complex disarm expression.

Hi @Mark_VG.

Caddx
A pin code in Caddx can be configured to have a length of 4 or a length of 6 digits.
The command always receives 6 digits. In case of a 4 digit ping digits 5 and 6 are “0”.

Javascript
Only the substr function is used you can find the definition below:
https://www.w3schools.com/jsref/jsref_substr.asp

Command
The string that you can send to the SendCommand channel has the following general format:

command|byte,byte,byte,byte,...

The bytes can be written in decimal notation like 17 or in hexadecimal notation like 0x11 (also 17).

A partition primary command has the following format:

Arm/Disarm command analysis
vars.pincode contains the digits entered by the user on the widget.
Say the pincode is “6789” (4 digit pin) then digit1 = “6”, digit2 = “7”, digit3 = “8”, digit4 = “9”
vars.selectedPartition contains “Partition1”, “Partition2”, … “Partition8” according to the selected partition.

"partition_primary_command_with_pin|" +

is the command to be sent followed by the pipe.

"0x" + (vars.pincode).substr(1,1) + (vars.pincode).substr(0,1) + "," +

contains 0x<digit2><digit1>,
The manual states that in the 8 bits of the first byte, we must set the two first digits of the pin.
More specifically the first digit in the lower 4 bits and the second digit in the upper 4 bits.
A byte in hexdeximal notation is written 0xab where “a” are the upper 4 bits and “b” the lower 4 bits.

"0x" + (vars.pincode).substr(3,1) + (vars.pincode).substr(2,1) + "," +

contains 0x<digit4><digit3>,
The same as above for digits 3 and 4.

"0x" + (vars.pincode+"00").substr(5,1) + (vars.pincode+"00").substr(4,1) + "," + 

The same as above for digits 5 and 6.
In case the pincode is only 4 digits long, then the expression (vars.pincode).substr(4,1) would yield an error because substr(4,1) gets the fifth digit. To overcome this condition “00” is added at the end of the pincode, converting it to a 6-digit pin like it is expected by the command.

((items[((vars.selectedPartition === NULL) ? props.selectedPartition : vars.selectedPartition) + "_Armed"].state === "ON") ? "1" : "2") + "," + 

or simpler

((items[vars.selectedPartition + "_Armed"].state === "ON") ? "1" : "2") + "," + 

This calculates the <primary function> to be send to the panel.
If the item “Partition1_Armed” is ON then “1” (Disarm) is sent to the panel.
If the item “Partition1_Armed” is OFF then “2” (Arm in away mode) is sent to the panel.

(1 << (((vars.selectedPartition === NULL) ? props.selectedPartition : vars.selectedPartition).substr(-1) - 1))'

This calculates the partition mask like in the previous post.

Thanks Georgios.

I have uploaded by latest version in the initial post. Thanks for all the support etc.