Thanks, Rene. I fixed my original post - apologies for the poor formatting. Also, thanks for all the work you do and all the replies on the forums; I’ve seen you helping a lot, and we all appreciate it.
I started over with a fresh copy of basealarm (grabbed from gitrepo at: https://github.com/home-assistant/appdaemon.git).
I copied the basealarm folder into /config/appdaemon/custom_widgets, and renamed it to alarm_cust.
I copied the alarm.yaml file into /config/appdaemon/custom_widgets folder and renamed it to alarm_cust.
I then renamed all of the files from basealarm.ext to alarm_cust.ext and did a find/replace on all instances of basealarm, changing it to alarm_cust. In my dashboard, I changed the widget_type from alarm to alarm_cust.
Aside from find/replace and renaming the files, I haven’t done anything else to the files - just trying to get to the point where it is working properly before I modify the code.
Code:
/config/appdaemon/dashboards/Alarm.dash:
##
## Main arguments, all optional
##
title: Alarm Panel
skin: zen
widget_dimensions: [120, 120]
widget_margins: [5, 5]
widget_size: [1, 1]
columns: 5
global_parameters:
use_comma: 0
precision: 1
use_hass_icon: 1
home_label:
widget_type: label
title: Home
widget_style: "background: transparent; vertical-align: top; padding-right: 10px"
title_style: "text-align: left; font-size: 42px; vertical-align: top; margin-top: -20px"
clock:
widget_type: clock
title_style: "text-align: right; font-size: 42px; vertical-align: top; margin-top: -50px"
### Alarm ###
alarm_control_panel:
entity: alarm_control_panel.home_alarm
widget_type: alarm_cust
title: Alarm Keypad
widget_style: "background-color: #fff;"
garage_door_sensor:
widget_type: binary_sensor
entity: binary_sensor.garage
title: Garage Door
icon_on: mdi-locker
icon_off: mdi-locker
slider_door_sensor:
widget_type: binary_sensor
entity: binary_sensor.slider
title: Slider
icon_on: mdi-locker
icon_off: mdi-locker
front_door_sensor:
widget_type: binary_sensor
entity: binary_sensor.front
title: Front Door
icon_on: mdi-locker
icon_off: mdi-locker
livingroom_motion:
widget_type: binary_sensor
title: Living Room
icon_on: mdi-eye-outline
icon_off: mdi-eye-off-outline
entity: binary_sensor.living_room
diningroom_motion:
widget_type: binary_sensor
title: Dining Room
icon_on: mdi-eye-outline
icon_off: mdi-eye-off-outline
entity: binary_sensor.dining_room
### Climate ###
downstairs_thermostat:
widget_type: climate
entity: climate.downstairs
title: Downstairs
units: "°F"
upstairs_thermostat:
widget_type: climate
entity: climate.upstairs
title: Upstairs
units: "°F"
### Lighting ###
living_room_lights:
entity: light.honeywell_39351__zw3005_inwall_smart_dimmer_level
title: Living Room
widget_type: input_slider
layout:
- clock.clock(2x1), alarm_control_panel
- garage_door_sensor, front_door_sensor, slider_door_sensor, livingroom_motion, diningroom_motion
- downstairs_thermostat, upstairs_thermostat
/config/appdaemon/custom_widgets/alarm_cust.yaml:
widget_type: alarm_cust
entity: "{{entity}}"
initial_string: "Enter Code"
post_service_ah:
service: alarm_control_panel/alarm_arm_home
entity_id: "{{entity}}"
post_service_aa:
service: alarm_control_panel/alarm_arm_away
entity_id: "{{entity}}"
post_service_da:
service: alarm_control_panel/alarm_disarm
entity_id: "{{entity}}"
post_service_tr:
service: alarm_control_panel/alarm_trigger
entity_id: "{{entity}}"
state_map:
pending: Pending
armed_home: Armed Home
armed_away: Armed Away
disarmed: Disarmed
triggered: Triggered
fields:
title: "{{title}}"
title2: "{{title2}}"
state: ""
code: ""
static_css:
title_style: $alarm_title_style
title2_style: $alarm_title2_style
state_style: $alarm_state_style
widget_style: $alarm_widget_style
panel_state_style: $alarm_panel_state_style
panel_code_style: $alarm_panel_code_style
panel_background_style: $alarm_panel_background_style
panel_button_style: $alarm_panel_button_style
css: []
icons: []
static_icons: []
/config/appdaemon/custom_widgets/alarm_cust.css
/*noinspection ALL*/
.widget-alarm_cust-{{id}} .state {
display: inline-block;
vertical-align: middle;
}
/*noinspection ALL*/
.widget-alarm_cust-{{id}} .title {
position: absolute;
top: 5px;
width: 100%;
}
/*noinspection ALL*/
.widget-alarm_cust-{{id}} .title2 {
position: absolute;
top: 23px;
width: 100%;
}
/*noinspection ALL*/
.widget-alarm_cust-{{id}} .code {
width: 100%;
}
/*noinspection ALL*/
.widget-alarm_cust-{{id}} .toggle-area {
z-index: 10;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/*noinspection ALL*/
.widget-alarm_cust-{{id}} .container {
width: 275px;
display: inline-block;
}
/*noinspection ALL*/
.widget-alarm_cust-{{id}} .panel-state {
font-size: 100%;
}
/*noinspection ALL*/
.widget-alarm_cust-{{id}} .block {
display: inline-block;
width: 75px;
height: 75px;
margin: 5px;
float: top;
font-size: 175%;
text-align: center;
vertical-align: middle;
line-height: 75px;
}
/*noinspection ALL*/
.widget-alarm_cust-{{id}} .block2 {
width: 165px;
}
/*noinspection ALL*/
.widget-alarm_cust-{{id}} .block3 {
width: 255px;
}
/config/appdaemon/custom_widgets/alarm_cust/alarm_cust.html
<span class="toggle-area" id="switch"></span>
<h1 class="title" data-bind="text: title, attr:{ style: title_style}"></h1>
<h1 class="title2" data-bind="text: title2, attr:{ style: title2_style}"></h1>
<h2 class="value" data-bind="text: state, attr:{ style: state_style}"></h2>
<div id="Dialog" class="modalDialog">
<div data-bind="attr:{style: panel_background_style}">
<h2 id="close" class="modalDialogCloseButton">X</h2>
<h2 class="panel-state" data-bind="text: state, attr:{style: panel_state_style}"></h2>
<h2 class="panel-state" data-bind="text: code, attr:{style: panel_code_style}"></h2>
<div class="container">
<span data-bind="attr:{style: panel_button_style}" class="block" id="1">1</span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block" id="2">2</span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block" id="3">3</span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block" id="4">4</span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block" id="5">5</span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block" id="6">6</span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block" id="7">7</span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block" id="8">8</span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block" id="9">9</span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block block2" id="0">0</span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block mdi mdi-keyboard-backspace" id="BS"></span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block mdi mdi-home" id="AH" ></span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block mdi mdi-home-outline" id="AA"></span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block fa fa-power-off" id="DA"></span class="block">
<span data-bind="attr:{style: panel_button_style}" class="block block3" id="TR">Trigger</span class="block">
</div>
</div>
</div>
/config/appdaemon/custom_widgets/alarm_cust/alarm_cust.js
function alarm_cust(widget_id, url, skin, parameters)
{
// Will be using "self" throughout for the various flavors of "this"
// so for consistency ...
self = this
// Initialization
self.widget_id = widget_id
// Parameters may come in useful later on
self.parameters = parameters
self.OnButtonClick = OnButtonClick
self.OnCloseClick = OnCloseClick
self.OnDigitClick = OnDigitClick
self.OnArmHomeClick = OnArmHomeClick
self.OnArmAwayClick = OnArmAwayClick
self.OnDisarmClick = OnDisarmClick
self.OnTriggerClick = OnTriggerClick
var callbacks =
[
{"selector": '#' + widget_id + ' > span', "action": "click", "callback": self.OnButtonClick},
{"selector": '#' + widget_id + ' #close', "action": "click", "callback": self.OnCloseClick},
{"selector": '#' + widget_id + ' #0', "action": "click", "callback": self.OnDigitClick, "parameters": {"digit" : "0"}},
{"selector": '#' + widget_id + ' #1', "action": "click", "callback": self.OnDigitClick, "parameters": {"digit" : "1"}},
{"selector": '#' + widget_id + ' #2', "action": "click", "callback": self.OnDigitClick, "parameters": {"digit" : "2"}},
{"selector": '#' + widget_id + ' #3', "action": "click", "callback": self.OnDigitClick, "parameters": {"digit" : "3"}},
{"selector": '#' + widget_id + ' #4', "action": "click", "callback": self.OnDigitClick, "parameters": {"digit" : "4"}},
{"selector": '#' + widget_id + ' #5', "action": "click", "callback": self.OnDigitClick, "parameters": {"digit" : "5"}},
{"selector": '#' + widget_id + ' #6', "action": "click", "callback": self.OnDigitClick, "parameters": {"digit" : "6"}},
{"selector": '#' + widget_id + ' #7', "action": "click", "callback": self.OnDigitClick, "parameters": {"digit" : "7"}},
{"selector": '#' + widget_id + ' #8', "action": "click", "callback": self.OnDigitClick, "parameters": {"digit" : "8"}},
{"selector": '#' + widget_id + ' #9', "action": "click", "callback": self.OnDigitClick, "parameters": {"digit" : "9"}},
{"selector": '#' + widget_id + ' #BS', "action": "click", "callback": self.OnDigitClick, "parameters": {"digit" : "BS"}},
{"selector": '#' + widget_id + ' #AH', "action": "click", "callback": self.OnArmHomeClick},
{"selector": '#' + widget_id + ' #AA', "action": "click", "callback": self.OnArmAwayClick},
{"selector": '#' + widget_id + ' #DA', "action": "click", "callback": self.OnDisarmClick},
{"selector": '#' + widget_id + ' #TR', "action": "click", "callback": self.OnTriggerClick},
]
// Define callbacks for entities - this model allows a widget to monitor multiple entities if needed
// Initial will be called when the dashboard loads and state has been gathered for the entity
// Update will be called every time an update occurs for that entity
self.OnStateAvailable = OnStateAvailable
self.OnStateUpdate = OnStateUpdate
if ("entity" in parameters)
{
var monitored_entities =
[
{"entity": parameters.entity, "initial": self.OnStateAvailable, "update": self.OnStateUpdate}
]
}
else
{
var monitored_entities = []
}
// Finally, call the parent constructor to get things moving
WidgetBase.call(self, widget_id, url, skin, parameters, monitored_entities, callbacks)
self.set_view = set_view
// Function Definitions
// The StateAvailable function will be called when
// self.state[<entity>] has valid information for the requested entity
// state is the initial state
// Methods
function OnStateAvailable(self, state)
{
self.set_field(self, "state", self.map_state(self, state.state))
}
function OnStateUpdate(self, state)
{
self.set_field(self, "state", self.map_state(self, state.state))
}
function OnButtonClick(self)
{
self.code = self.parameters.initial_string
self.set_view(self)
$('#' + widget_id + ' > #Dialog').removeClass("modalDialogClose")
$('#' + widget_id + ' > #Dialog').addClass("modalDialogOpen")
}
function OnCloseClick(self)
{
$('#' + widget_id + ' > #Dialog').removeClass("modalDialogOpen")
$('#' + widget_id + ' > #Dialog').addClass("modalDialogClose")
}
function OnDigitClick(self, parameters)
{
if (parameters.digit == "BS")
{
if (self.code != self.parameters.initial_string)
{
if (self.code.length == 1)
{
self.code = self.parameters.initial_string
}
else
{
self.code = self.code.substring(0, self.code.length - 1);
}
}
}
else
{
if (self.code == self.parameters.initial_string)
{
self.code = parameters.digit
}
else
{
self.code = self.code + parameters.digit
}
}
self.set_view(self)
}
function OnArmHomeClick(self)
{
args = self.parameters.post_service_ah
args["code"] = self.code
self.call_service(self, args)
self.code = self.parameters.initial_string
self.set_view(self)
}
function OnArmAwayClick(self)
{
args = self.parameters.post_service_aa
args["code"] = self.code
self.call_service(self, args)
self.code = self.parameters.initial_string
self.set_view(self)
}
function OnDisarmClick(self)
{
args = self.parameters.post_service_da
args["code"] = self.code
self.call_service(self, args)
self.code = self.parameters.initial_string
self.set_view(self)
}
function OnTriggerClick(self)
{
args = self.parameters.post_service_tr
args["code"] = self.code
self.call_service(self, args)
self.code = self.parameters.initial_string
self.set_view(self)
}
function set_view(self)
{
self.set_field(self, "code", self.code)
}
}
Screenshots:
Before copying basealarm into custom_widgets and renaming/updating the files:
After copying basealarm into custom_widgets and renaming/updating the files: