Resolves #204 Alarm panel card support

This commit is contained in:
estevez-dev 2019-01-29 15:00:15 +02:00
parent 24c7675fa4
commit 5e814e8109
8 changed files with 219 additions and 34 deletions

View File

@ -5,6 +5,8 @@ class AlarmControlPanelEntity extends Entity {
@override @override
Widget _buildAdditionalControlsForPage(BuildContext context) { Widget _buildAdditionalControlsForPage(BuildContext context) {
return AlarmControlPanelControlsWidget(); return AlarmControlPanelControlsWidget(
extended: false,
);
} }
} }

View File

@ -2,6 +2,11 @@ part of '../../main.dart';
class AlarmControlPanelControlsWidget extends StatefulWidget { class AlarmControlPanelControlsWidget extends StatefulWidget {
final bool extended;
final List states;
const AlarmControlPanelControlsWidget({Key key, @required this.extended, this.states: const ["arm_home", "arm_away"]}) : super(key: key);
@override @override
_AlarmControlPanelControlsWidgetWidgetState createState() => _AlarmControlPanelControlsWidgetWidgetState(); _AlarmControlPanelControlsWidgetWidgetState createState() => _AlarmControlPanelControlsWidgetWidgetState();
@ -20,23 +25,59 @@ class _AlarmControlPanelControlsWidgetWidgetState extends State<AlarmControlPane
}); });
} }
void _pinPadHandler(value) {
setState(() {
code += "$value";
});
}
void _pinPadClear() {
setState(() {
code = "";
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final entityModel = EntityModel.of(context); final entityModel = EntityModel.of(context);
final AlarmControlPanelEntity entity = entityModel.entityWrapper.entity; final AlarmControlPanelEntity entity = entityModel.entityWrapper.entity;
List<Widget> buttons = []; List<Widget> buttons = [];
if (entity.state == EntityState.alarm_disarmed) { if (entity.state == EntityState.alarm_disarmed) {
buttons.addAll(<Widget>[ if (widget.states.contains("arm_home")) {
buttons.add(
RaisedButton( RaisedButton(
onPressed: () => _callService(entity, "alarm_arm_home"), onPressed: () => _callService(entity, "alarm_arm_home"),
child: Text("ARM HOME"), child: Text("ARM HOME"),
),
RaisedButton(
onPressed: () => _callService(entity, "alarm_arm_away"),
child: Text("ARM AWAY"),
) )
] );
); }
if (widget.states.contains("arm_away")) {
buttons.add(
RaisedButton(
onPressed: () => _callService(entity, "alarm_arm_away"),
child: Text("ARM AWAY"),
)
);
}
if (widget.extended) {
if (widget.states.contains("arm_night")) {
buttons.add(
RaisedButton(
onPressed: () => _callService(entity, "alarm_arm_night"),
child: Text("ARM NIGHT"),
)
);
}
if (widget.states.contains("arm_custom_bypass")) {
buttons.add(
RaisedButton(
onPressed: () =>
_callService(entity, "alarm_arm_custom_bypass"),
child: Text("ARM CUSTOM BYPASS"),
)
);
}
}
} else { } else {
buttons.add( buttons.add(
RaisedButton( RaisedButton(
@ -45,33 +86,119 @@ class _AlarmControlPanelControlsWidgetWidgetState extends State<AlarmControlPane
) )
); );
} }
Widget pinPad;
if (widget.extended) {
pinPad = Padding(
padding: EdgeInsets.only(bottom: Sizes.rowPadding),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Wrap(
spacing: 5.0,
children: <Widget>[
RaisedButton(
onPressed: () => _pinPadHandler("1"),
child: Text("1"),
),
RaisedButton(
onPressed: () => _pinPadHandler("2"),
child: Text("2"),
),
RaisedButton(
onPressed: () => _pinPadHandler("3"),
child: Text("3"),
)
],
),
Wrap(
spacing: 5.0,
children: <Widget>[
RaisedButton(
onPressed: () => _pinPadHandler("4"),
child: Text("4"),
),
RaisedButton(
onPressed: () => _pinPadHandler("5"),
child: Text("5"),
),
RaisedButton(
onPressed: () => _pinPadHandler("6"),
child: Text("6"),
)
],
),
Wrap(
spacing: 5.0,
children: <Widget>[
RaisedButton(
onPressed: () => _pinPadHandler("7"),
child: Text("7"),
),
RaisedButton(
onPressed: () => _pinPadHandler("8"),
child: Text("8"),
),
RaisedButton(
onPressed: () => _pinPadHandler("9"),
child: Text("9"),
)
],
),
Wrap(
spacing: 5.0,
alignment: WrapAlignment.end,
children: <Widget>[
RaisedButton(
onPressed: () => _pinPadHandler("0"),
child: Text("0"),
),
RaisedButton(
onPressed: () => _pinPadClear(),
child: Text("CLEAR"),
)
],
)
],
)
);
} else {
pinPad = Container();
}
Widget inputWrapper = Container(
width: 150.0,
child: TextField(
decoration: InputDecoration(
labelText: "Alarm Code"
),
//focusNode: _focusNode,
obscureText: true,
controller: new TextEditingController.fromValue(
new TextEditingValue(
text: code,
selection:
new TextSelection.collapsed(offset: code.length)
)
),
onChanged: (value) {
code = value;
}
)
);
Widget buttonsWrapper = Padding(
padding: EdgeInsets.symmetric(vertical: Sizes.rowPadding),
child: Wrap(
alignment: WrapAlignment.center,
spacing: 15.0,
runSpacing: Sizes.rowPadding,
children: buttons
)
);
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Container( widget.extended ? buttonsWrapper : inputWrapper,
width: 150.0, widget.extended ? inputWrapper : buttonsWrapper,
child: TextField( pinPad
//focusNode: _focusNode,
obscureText: true,
controller: new TextEditingController.fromValue(
new TextEditingValue(
text: code,
selection:
new TextSelection.collapsed(offset: code.length)
)
),
onChanged: (value) {
code = value;
}
)
),
Wrap(
alignment: WrapAlignment.center,
spacing: 10.0,
runSpacing: 1.0,
children: buttons
)
] ]
); );

View File

@ -23,6 +23,15 @@ class EntityColor {
"cool": Colors.lightBlue, "cool": Colors.lightBlue,
EntityState.unavailable: Colors.black26, EntityState.unavailable: Colors.black26,
EntityState.unknown: Colors.black26, EntityState.unknown: Colors.black26,
EntityState.alarm_disarmed: Colors.green,
EntityState.alarm_armed_away: Colors.redAccent,
EntityState.alarm_armed_custom_bypass: Colors.redAccent,
EntityState.alarm_armed_home: Colors.redAccent,
EntityState.alarm_armed_night: Colors.redAccent,
EntityState.alarm_triggered: Colors.redAccent,
EntityState.alarm_arming: Colors.amber,
EntityState.alarm_disarming: Colors.amber,
EntityState.alarm_pending: Colors.amber,
}; };
static Color stateColor(String state) { static Color stateColor(String state) {

View File

@ -457,6 +457,7 @@ class HomeAssistant {
: rawCard['show_state'] ?? true, : rawCard['show_state'] ?? true,
showEmpty: rawCard['show_empty'] ?? true, showEmpty: rawCard['show_empty'] ?? true,
stateFilter: rawCard['state_filter'] ?? [], stateFilter: rawCard['state_filter'] ?? [],
states: rawCard['states'],
content: rawCard['content'] content: rawCard['content']
); );
if (rawCard["cards"] != null) { if (rawCard["cards"] != null) {

View File

@ -29,7 +29,7 @@ class MaterialDesignIcons {
"alarm_control_panel.armed_home" : "mdi:bell-plus", "alarm_control_panel.armed_home" : "mdi:bell-plus",
"alarm_control_panel.armed_away" : "mdi:bell", "alarm_control_panel.armed_away" : "mdi:bell",
"alarm_control_panel.armed_night" : "mdi:bell-sleep", "alarm_control_panel.armed_night" : "mdi:bell-sleep",
"alarm_control_panel.armed_custom_bypass" : "mdi:bell-sleep", "alarm_control_panel.armed_custom_bypass" : "mdi:bell",
"alarm_control_panel.triggered" : "mdi:bell-ring", "alarm_control_panel.triggered" : "mdi:bell-ring",
"alarm_control_panel" : "mdi:bell" "alarm_control_panel" : "mdi:bell"
}; };

View File

@ -12,6 +12,7 @@ class HACard {
bool showEmpty; bool showEmpty;
int columnsCount; int columnsCount;
List stateFilter; List stateFilter;
List states;
String content; String content;
HACard({ HACard({
@ -24,6 +25,7 @@ class HACard {
this.stateFilter: const [], this.stateFilter: const [],
this.showEmpty: true, this.showEmpty: true,
this.content, this.content,
this.states,
@required this.type @required this.type
}); });

View File

@ -3,14 +3,18 @@ part of '../main.dart';
class CardHeaderWidget extends StatelessWidget { class CardHeaderWidget extends StatelessWidget {
final String name; final String name;
final Widget trailing;
final Widget subtitle;
const CardHeaderWidget({Key key, this.name}) : super(key: key); const CardHeaderWidget({Key key, this.name, this.trailing, this.subtitle}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var result; var result;
if ((name != null) && (name.trim().length > 0)) { if ((name != null) && (name.trim().length > 0)) {
result = new ListTile( result = new ListTile(
trailing: trailing,
subtitle: subtitle,
title: Text("$name", title: Text("$name",
textAlign: TextAlign.left, textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,

View File

@ -37,6 +37,10 @@ class CardWidget extends StatelessWidget {
return _buildMarkdownCard(context); return _buildMarkdownCard(context);
} }
case CardType.alarmPanel: {
return _buildAlarmPanelCard(context);
}
case CardType.horizontalStack: { case CardType.horizontalStack: {
if (card.childCards.isNotEmpty) { if (card.childCards.isNotEmpty) {
List<Widget> children = []; List<Widget> children = [];
@ -128,6 +132,42 @@ class CardWidget extends StatelessWidget {
); );
} }
Widget _buildAlarmPanelCard(BuildContext context) {
if (card.linkedEntityWrapper == null || card.linkedEntityWrapper.entity == null) {
return Container(width: 0, height: 0,);
} else {
List<Widget> body = [];
body.add(CardHeaderWidget(
name: card.name ?? "",
subtitle: Text("${card.linkedEntityWrapper.entity.displayState}",
style: TextStyle(
color: Colors.grey
),
),
trailing: EntityIcon(
iconSize: 50.0,
),
));
body.add(
AlarmControlPanelControlsWidget(
extended: true,
states: card.states,
)
);
return Card(
child: EntityModel(
entityWrapper: card.linkedEntityWrapper,
handleTap: null,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: body
)
)
);
}
}
Widget _buildGlanceCard(BuildContext context) { Widget _buildGlanceCard(BuildContext context) {
List<EntityWrapper> entitiesToShow = card.getEntitiesToShow(); List<EntityWrapper> entitiesToShow = card.getEntitiesToShow();
if (entitiesToShow.isEmpty && !card.showEmpty) { if (entitiesToShow.isEmpty && !card.showEmpty) {