WIP #120 History widget improvements
This commit is contained in:
parent
6e038b0685
commit
e16338c3f2
@ -1,14 +1,39 @@
|
|||||||
part of '../main.dart';
|
part of '../main.dart';
|
||||||
|
|
||||||
class Entity {
|
class EntityColors {
|
||||||
static const STATE_ICONS_COLORS = {
|
static const _stateColors = {
|
||||||
"on": Colors.amber,
|
"on": Colors.amber,
|
||||||
|
"auto": Colors.amber,
|
||||||
|
"idle": Colors.amber,
|
||||||
"off": Color.fromRGBO(68, 115, 158, 1.0),
|
"off": Color.fromRGBO(68, 115, 158, 1.0),
|
||||||
"default": Color.fromRGBO(68, 115, 158, 1.0),
|
"default": Color.fromRGBO(68, 115, 158, 1.0),
|
||||||
"unavailable": Colors.black12,
|
"heat": Colors.redAccent,
|
||||||
"unknown": Colors.black12,
|
"cool": Colors.lightBlue,
|
||||||
"playing": Colors.amber
|
"unavailable": Colors.black26,
|
||||||
|
"unknown": Colors.black26,
|
||||||
|
"playing": Colors.amber,
|
||||||
|
"above_horizon": Colors.amber,
|
||||||
|
"home": Colors.amber,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Color stateColor(String state) {
|
||||||
|
return _stateColors[state] ?? _stateColors["default"];
|
||||||
|
}
|
||||||
|
|
||||||
|
static charts.Color historyStateColor(String state) {
|
||||||
|
Color c = stateColor(state);
|
||||||
|
return charts.Color(
|
||||||
|
r: c.red,
|
||||||
|
g: c.green,
|
||||||
|
b: c.blue,
|
||||||
|
a: c.alpha
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Entity {
|
||||||
|
|
||||||
static const badgeColors = {
|
static const badgeColors = {
|
||||||
"default": Color.fromRGBO(223, 76, 30, 1.0),
|
"default": Color.fromRGBO(223, 76, 30, 1.0),
|
||||||
"binary_sensor": Color.fromRGBO(3, 155, 229, 1.0)
|
"binary_sensor": Color.fromRGBO(3, 155, 229, 1.0)
|
||||||
|
@ -1,217 +0,0 @@
|
|||||||
part of '../main.dart';
|
|
||||||
|
|
||||||
class EntityHistoryWidgetType {
|
|
||||||
static const int simplest = 0;
|
|
||||||
static const int valueToTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
class EntityHistoryWidget extends StatefulWidget {
|
|
||||||
|
|
||||||
final int type;
|
|
||||||
|
|
||||||
const EntityHistoryWidget({Key key, @required this.type}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_EntityHistoryWidgetState createState() {
|
|
||||||
return new _EntityHistoryWidgetState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _EntityHistoryWidgetState extends State<EntityHistoryWidget> {
|
|
||||||
|
|
||||||
List _history;
|
|
||||||
bool _needToUpdateHistory;
|
|
||||||
DateTime _selectionTimeStart;
|
|
||||||
DateTime _selectionTimeEnd;
|
|
||||||
Map<String, String> _selectionData;
|
|
||||||
int _selectedId = -1;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_needToUpdateHistory = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _loadHistory(HomeAssistant ha, String entityId) {
|
|
||||||
ha.getHistory(entityId).then((history){
|
|
||||||
setState(() {
|
|
||||||
_history = history.isNotEmpty ? history[0] : [];
|
|
||||||
_needToUpdateHistory = false;
|
|
||||||
});
|
|
||||||
}).catchError((e) {
|
|
||||||
TheLogger.error("Error loading $entityId history: $e");
|
|
||||||
setState(() {
|
|
||||||
_history = [];
|
|
||||||
_needToUpdateHistory = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final HomeAssistantModel homeAssistantModel = HomeAssistantModel.of(context);
|
|
||||||
final EntityModel entityModel = EntityModel.of(context);
|
|
||||||
final Entity entity = entityModel.entity;
|
|
||||||
if (!_needToUpdateHistory) {
|
|
||||||
_needToUpdateHistory = true;
|
|
||||||
} else {
|
|
||||||
_loadHistory(homeAssistantModel.homeAssistant, entity.entityId);
|
|
||||||
}
|
|
||||||
return _buildChart();
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildChart() {
|
|
||||||
List<Widget> children = [];
|
|
||||||
if (_selectionTimeStart != null) {
|
|
||||||
children.add(
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(right: 10.0),
|
|
||||||
child: Text(
|
|
||||||
"${_selectionData["State"]}",
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: _selectionData["State"] == "on" ? Colors.green : Colors.red
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
children: <Widget>[
|
|
||||||
Text("${formatDate(_selectionTimeStart, [M, ' ', d, ', ', HH, ':', nn, ':', ss])}"),
|
|
||||||
Text("${formatDate(_selectionTimeEnd ?? _selectionTimeStart, [M, ' ', d, ', ', HH, ':', nn, ':', ss])}"),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
children.add(
|
|
||||||
Container(height: 32.0,)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (_history == null) {
|
|
||||||
children.add(
|
|
||||||
Text("Loading history...")
|
|
||||||
);
|
|
||||||
} else if (_history.isEmpty) {
|
|
||||||
children.add(
|
|
||||||
Text("No history for last 24h")
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
children.add(
|
|
||||||
SizedBox(
|
|
||||||
height: 70.0,
|
|
||||||
child: charts.TimeSeriesChart(
|
|
||||||
_createHistoryData(),
|
|
||||||
animate: false,
|
|
||||||
dateTimeFactory: const charts.LocalDateTimeFactory(),
|
|
||||||
primaryMeasureAxis: charts.NumericAxisSpec(
|
|
||||||
renderSpec: charts.NoneRenderSpec()
|
|
||||||
),
|
|
||||||
selectionModels: [
|
|
||||||
new charts.SelectionModelConfig(
|
|
||||||
type: charts.SelectionModelType.info,
|
|
||||||
listener: _onSelectionChanged,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
behaviors: [
|
|
||||||
charts.PanAndZoomBehavior(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
children.add(Divider());
|
|
||||||
return Padding(
|
|
||||||
padding: EdgeInsets.fromLTRB(0.0, Entity.rowPadding, 0.0, Entity.rowPadding),
|
|
||||||
child: Column(
|
|
||||||
children: children,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onSelectionChanged(charts.SelectionModel model) {
|
|
||||||
final selectedDatum = model.selectedDatum;
|
|
||||||
|
|
||||||
DateTime timeStart;
|
|
||||||
DateTime timeEnd;
|
|
||||||
int selectedId;
|
|
||||||
final measures = <String, String>{};
|
|
||||||
|
|
||||||
if ((selectedDatum.isNotEmpty) &&(selectedDatum.first.datum.endTime != null)) {
|
|
||||||
timeStart = selectedDatum.first.datum.startTime;
|
|
||||||
timeEnd = selectedDatum.first.datum.endTime;
|
|
||||||
selectedId = selectedDatum.first.datum.id;
|
|
||||||
TheLogger.debug("Selected datum length is ${selectedDatum.length}");
|
|
||||||
selectedDatum.forEach((charts.SeriesDatum datumPair) {
|
|
||||||
measures[datumPair.series.displayName] = datumPair.datum.state;
|
|
||||||
});
|
|
||||||
setState(() {
|
|
||||||
_selectionTimeStart = timeStart;
|
|
||||||
_selectionTimeEnd = timeEnd;
|
|
||||||
_selectionData = measures;
|
|
||||||
_selectedId = selectedId;
|
|
||||||
_needToUpdateHistory = false;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setState(() {
|
|
||||||
_needToUpdateHistory = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
List<charts.Series<EntityStateHistoryMoment, DateTime>> _createHistoryData() {
|
|
||||||
List<EntityStateHistoryMoment> data = [];
|
|
||||||
DateTime now = DateTime.now();
|
|
||||||
for (var i = 0; i < _history.length; i++) {
|
|
||||||
var stateData = _history[i];
|
|
||||||
DateTime startTime = DateTime.tryParse(stateData["last_updated"])?.toLocal();
|
|
||||||
DateTime endTime;
|
|
||||||
if (i < (_history.length - 1)) {
|
|
||||||
endTime = DateTime.tryParse(_history[i+1]["last_updated"])?.toLocal();
|
|
||||||
} else {
|
|
||||||
endTime = now;
|
|
||||||
}
|
|
||||||
data.add(EntityStateHistoryMoment(stateData["state"], startTime, endTime, i));
|
|
||||||
}
|
|
||||||
data.add(EntityStateHistoryMoment(data.last.state, now, null, _history.length));
|
|
||||||
return [
|
|
||||||
new charts.Series<EntityStateHistoryMoment, DateTime>(
|
|
||||||
id: 'State',
|
|
||||||
strokeWidthPxFn: (EntityStateHistoryMoment historyMoment, __) => (historyMoment.id == _selectedId) ? 70.0 : 40.0,
|
|
||||||
colorFn: ((EntityStateHistoryMoment historyMoment, __) {
|
|
||||||
if (historyMoment.state == "on") {
|
|
||||||
if (historyMoment.id == _selectedId) {
|
|
||||||
return charts.MaterialPalette.green.makeShades(2)[0];
|
|
||||||
} else {
|
|
||||||
return charts.MaterialPalette.green.makeShades(2)[1];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (historyMoment.id == _selectedId) {
|
|
||||||
return charts.MaterialPalette.red.makeShades(2)[0];
|
|
||||||
} else {
|
|
||||||
return charts.MaterialPalette.red.makeShades(2)[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
domainFn: (EntityStateHistoryMoment historyMoment, _) => historyMoment.startTime,
|
|
||||||
measureFn: (EntityStateHistoryMoment historyMoment, _) => 0,
|
|
||||||
data: data,
|
|
||||||
)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class EntityStateHistoryMoment {
|
|
||||||
final DateTime startTime;
|
|
||||||
final DateTime endTime;
|
|
||||||
final String state;
|
|
||||||
final int id;
|
|
||||||
|
|
||||||
EntityStateHistoryMoment(this.state, this.startTime, this.endTime, this.id);
|
|
||||||
}
|
|
@ -11,8 +11,8 @@ class EntityIcon extends StatelessWidget {
|
|||||||
child: MaterialDesignIcons.createIconWidgetFromEntityData(
|
child: MaterialDesignIcons.createIconWidgetFromEntityData(
|
||||||
entityModel.entity,
|
entityModel.entity,
|
||||||
Entity.iconSize,
|
Entity.iconSize,
|
||||||
Entity.STATE_ICONS_COLORS[entityModel.entity.state] ??
|
EntityColors.stateColor(entityModel.entity.state)
|
||||||
Entity.STATE_ICONS_COLORS["default"]),
|
),
|
||||||
),
|
),
|
||||||
onTap: () => entityModel.handleTap
|
onTap: () => entityModel.handleTap
|
||||||
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
|
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
|
||||||
|
86
lib/entity_widgets/history_chart/entity_history.dart
Normal file
86
lib/entity_widgets/history_chart/entity_history.dart
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
part of '../../main.dart';
|
||||||
|
|
||||||
|
class EntityHistoryWidgetType {
|
||||||
|
static const int simplest = 0;
|
||||||
|
static const int valueToTime = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
class EntityHistoryWidget extends StatefulWidget {
|
||||||
|
|
||||||
|
final int type;
|
||||||
|
|
||||||
|
const EntityHistoryWidget({Key key, @required this.type}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_EntityHistoryWidgetState createState() {
|
||||||
|
return new _EntityHistoryWidgetState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EntityHistoryWidgetState extends State<EntityHistoryWidget> {
|
||||||
|
|
||||||
|
List _history;
|
||||||
|
bool _needToUpdateHistory;
|
||||||
|
int _selectedId = -1;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_needToUpdateHistory = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _loadHistory(HomeAssistant ha, String entityId) {
|
||||||
|
ha.getHistory(entityId).then((history){
|
||||||
|
setState(() {
|
||||||
|
_history = history.isNotEmpty ? history[0] : [];
|
||||||
|
_needToUpdateHistory = false;
|
||||||
|
});
|
||||||
|
}).catchError((e) {
|
||||||
|
TheLogger.error("Error loading $entityId history: $e");
|
||||||
|
setState(() {
|
||||||
|
_history = [];
|
||||||
|
_needToUpdateHistory = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final HomeAssistantModel homeAssistantModel = HomeAssistantModel.of(context);
|
||||||
|
final EntityModel entityModel = EntityModel.of(context);
|
||||||
|
final Entity entity = entityModel.entity;
|
||||||
|
if (!_needToUpdateHistory) {
|
||||||
|
_needToUpdateHistory = true;
|
||||||
|
} else {
|
||||||
|
_loadHistory(homeAssistantModel.homeAssistant, entity.entityId);
|
||||||
|
}
|
||||||
|
return _buildChart();
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildChart() {
|
||||||
|
List<Widget> children = [];
|
||||||
|
if (_history == null) {
|
||||||
|
children.add(
|
||||||
|
Text("Loading history...")
|
||||||
|
);
|
||||||
|
} else if (_history.isEmpty) {
|
||||||
|
children.add(
|
||||||
|
Text("No history for last 24h")
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
children.add(
|
||||||
|
SimpleStateHistoryChartWidget(
|
||||||
|
rawHistory: _history
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
children.add(Divider());
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(0.0, Entity.rowPadding, 0.0, Entity.rowPadding),
|
||||||
|
child: Column(
|
||||||
|
children: children,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
197
lib/entity_widgets/history_chart/simple_state_history_chart.dart
Normal file
197
lib/entity_widgets/history_chart/simple_state_history_chart.dart
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
part of '../../main.dart';
|
||||||
|
|
||||||
|
class SimpleStateHistoryChartWidget extends StatefulWidget {
|
||||||
|
final rawHistory;
|
||||||
|
|
||||||
|
const SimpleStateHistoryChartWidget({Key key, this.rawHistory}) : super(key: key);
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() {
|
||||||
|
return new _SimpleStateHistoryChartWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SimpleStateHistoryChartWidgetState extends State<SimpleStateHistoryChartWidget> {
|
||||||
|
|
||||||
|
int _selectedId = -1;
|
||||||
|
List<charts.Series<SimpleEntityStateHistoryMoment, DateTime>> _parsedHistory;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
_parsedHistory = _parseHistory();
|
||||||
|
DateTime selectedTimeStart;
|
||||||
|
DateTime selectedTimeEnd;
|
||||||
|
String selectedState;
|
||||||
|
if ((_selectedId > -1) && (_parsedHistory != null) && (_parsedHistory.first.data.length >= (_selectedId + 1))) {
|
||||||
|
selectedTimeStart = _parsedHistory.first.data[_selectedId].startTime;
|
||||||
|
selectedTimeEnd = _parsedHistory.first.data[_selectedId].endTime;
|
||||||
|
selectedState = _parsedHistory.first.data[_selectedId].state;
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
HistoryControlWidget(
|
||||||
|
selectedTimeStart: selectedTimeStart,
|
||||||
|
selectedTimeEnd: selectedTimeEnd,
|
||||||
|
selectedState: selectedState,
|
||||||
|
onPrevTap: () => _selectPrev(),
|
||||||
|
onNextTap: () => _selectNext(),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 70.0,
|
||||||
|
child: charts.TimeSeriesChart(
|
||||||
|
_parsedHistory,
|
||||||
|
animate: false,
|
||||||
|
dateTimeFactory: const charts.LocalDateTimeFactory(),
|
||||||
|
primaryMeasureAxis: charts.NumericAxisSpec(
|
||||||
|
renderSpec: charts.NoneRenderSpec()
|
||||||
|
),
|
||||||
|
selectionModels: [
|
||||||
|
new charts.SelectionModelConfig(
|
||||||
|
type: charts.SelectionModelType.info,
|
||||||
|
listener: (model) => _onSelectionChanged(model),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
behaviors: [
|
||||||
|
charts.PanAndZoomBehavior(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<charts.Series<SimpleEntityStateHistoryMoment, DateTime>> _parseHistory() {
|
||||||
|
List<SimpleEntityStateHistoryMoment> data = [];
|
||||||
|
DateTime now = DateTime.now();
|
||||||
|
for (var i = 0; i < widget.rawHistory.length; i++) {
|
||||||
|
var stateData = widget.rawHistory[i];
|
||||||
|
DateTime startTime = DateTime.tryParse(stateData["last_updated"])?.toLocal();
|
||||||
|
DateTime endTime;
|
||||||
|
if (i < (widget.rawHistory.length - 1)) {
|
||||||
|
endTime = DateTime.tryParse(widget.rawHistory[i+1]["last_updated"])?.toLocal();
|
||||||
|
} else {
|
||||||
|
endTime = now;
|
||||||
|
}
|
||||||
|
data.add(SimpleEntityStateHistoryMoment(stateData["state"], startTime, endTime, i));
|
||||||
|
}
|
||||||
|
data.add(SimpleEntityStateHistoryMoment(data.last.state, now, null, widget.rawHistory.length));
|
||||||
|
return [
|
||||||
|
new charts.Series<SimpleEntityStateHistoryMoment, DateTime>(
|
||||||
|
id: 'State',
|
||||||
|
strokeWidthPxFn: (SimpleEntityStateHistoryMoment historyMoment, __) => (historyMoment.id == _selectedId) ? 70.0 : 40.0,
|
||||||
|
colorFn: (SimpleEntityStateHistoryMoment historyMoment, __) => EntityColors.historyStateColor(historyMoment.state),
|
||||||
|
domainFn: (SimpleEntityStateHistoryMoment historyMoment, _) => historyMoment.startTime,
|
||||||
|
measureFn: (SimpleEntityStateHistoryMoment historyMoment, _) => 0,
|
||||||
|
data: data,
|
||||||
|
)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
void _selectPrev() {
|
||||||
|
if (_selectedId > 0) {
|
||||||
|
setState(() {
|
||||||
|
_selectedId -= 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _selectNext() {
|
||||||
|
if (_selectedId < (_parsedHistory.first.data.length - 2)) {
|
||||||
|
setState(() {
|
||||||
|
_selectedId += 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onSelectionChanged(charts.SelectionModel model) {
|
||||||
|
final selectedDatum = model.selectedDatum;
|
||||||
|
|
||||||
|
int selectedId;
|
||||||
|
|
||||||
|
if ((selectedDatum.isNotEmpty) &&(selectedDatum.first.datum.endTime != null)) {
|
||||||
|
selectedId = selectedDatum.first.datum.id;
|
||||||
|
setState(() {
|
||||||
|
_selectedId = selectedId;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HistoryControlWidget extends StatelessWidget {
|
||||||
|
|
||||||
|
final Function onPrevTap;
|
||||||
|
final Function onNextTap;
|
||||||
|
final DateTime selectedTimeStart;
|
||||||
|
final DateTime selectedTimeEnd;
|
||||||
|
final String selectedState;
|
||||||
|
|
||||||
|
const HistoryControlWidget({Key key, this.onPrevTap, this.onNextTap, this.selectedTimeStart, this.selectedTimeEnd, this.selectedState}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (selectedTimeStart != null) {
|
||||||
|
return
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.chevron_left),
|
||||||
|
padding: EdgeInsets.all(0.0),
|
||||||
|
iconSize: 40.0,
|
||||||
|
onPressed: onPrevTap,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(right: 10.0),
|
||||||
|
child: Text(
|
||||||
|
"$selectedState",
|
||||||
|
textAlign: TextAlign.right,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: EntityColors.stateColor(selectedState),
|
||||||
|
fontSize: 22.0
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Text("${formatDate(selectedTimeStart, [M, ' ', d, ', ', HH, ':', nn, ':', ss])}", textAlign: TextAlign.left,),
|
||||||
|
Text("${formatDate(selectedTimeEnd ?? selectedTimeStart, [M, ' ', d, ', ', HH, ':', nn, ':', ss])}", textAlign: TextAlign.left,),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.chevron_right),
|
||||||
|
padding: EdgeInsets.all(0.0),
|
||||||
|
iconSize: 40.0,
|
||||||
|
onPressed: onNextTap,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return Container(height: 32.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class SimpleEntityStateHistoryMoment {
|
||||||
|
final DateTime startTime;
|
||||||
|
final DateTime endTime;
|
||||||
|
final String state;
|
||||||
|
final int id;
|
||||||
|
|
||||||
|
SimpleEntityStateHistoryMoment(this.state, this.startTime, this.endTime, this.id);
|
||||||
|
}
|
@ -477,7 +477,6 @@ class HomeAssistant {
|
|||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
//String endTime = formatDate(now, [yyyy, '-', mm, '-', dd, 'T', HH, ':', nn, ':', ss, z]);
|
//String endTime = formatDate(now, [yyyy, '-', mm, '-', dd, 'T', HH, ':', nn, ':', ss, z]);
|
||||||
String startTime = formatDate(now.subtract(Duration(hours: 24)), [yyyy, '-', mm, '-', dd, 'T', HH, ':', nn, ':', ss, z]);
|
String startTime = formatDate(now.subtract(Duration(hours: 24)), [yyyy, '-', mm, '-', dd, 'T', HH, ':', nn, ':', ss, z]);
|
||||||
TheLogger.debug( "$startTime");
|
|
||||||
String url = "$homeAssistantWebHost/api/history/period/$startTime?&filter_entity_id=$entityId";
|
String url = "$homeAssistantWebHost/api/history/period/$startTime?&filter_entity_id=$entityId";
|
||||||
TheLogger.debug( "$url");
|
TheLogger.debug( "$url");
|
||||||
http.Response historyResponse;
|
http.Response historyResponse;
|
||||||
@ -494,7 +493,7 @@ class HomeAssistant {
|
|||||||
}
|
}
|
||||||
var history = json.decode(historyResponse.body);
|
var history = json.decode(historyResponse.body);
|
||||||
if (history is List) {
|
if (history is List) {
|
||||||
TheLogger.debug( "${history.toString()}");
|
TheLogger.debug( "Got ${history.first.length} history recors");
|
||||||
return history;
|
return history;
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
|
@ -35,7 +35,8 @@ part 'entity_widgets/last_updated.dart';
|
|||||||
part 'entity_widgets/mode_swicth.dart';
|
part 'entity_widgets/mode_swicth.dart';
|
||||||
part 'entity_widgets/mode_selector.dart';
|
part 'entity_widgets/mode_selector.dart';
|
||||||
part 'entity_widgets/entity_page_container.dart';
|
part 'entity_widgets/entity_page_container.dart';
|
||||||
part 'entity_widgets/entity_history.dart';
|
part 'entity_widgets/history_chart/entity_history.dart';
|
||||||
|
part 'entity_widgets/history_chart/simple_state_history_chart.dart';
|
||||||
part 'entity_widgets/state/switch_state.dart';
|
part 'entity_widgets/state/switch_state.dart';
|
||||||
part 'entity_widgets/state/slider_state.dart';
|
part 'entity_widgets/state/slider_state.dart';
|
||||||
part 'entity_widgets/state/text_input_state.dart';
|
part 'entity_widgets/state/text_input_state.dart';
|
||||||
@ -65,7 +66,7 @@ part 'ui_widgets/media_control_card.dart';
|
|||||||
|
|
||||||
EventBus eventBus = new EventBus();
|
EventBus eventBus = new EventBus();
|
||||||
const String appName = "HA Client";
|
const String appName = "HA Client";
|
||||||
const appVersion = "0.3.3.47";
|
const appVersion = "0.3.3.48";
|
||||||
|
|
||||||
String homeAssistantWebHost;
|
String homeAssistantWebHost;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
name: hass_client
|
name: hass_client
|
||||||
description: Home Assistant Android Client
|
description: Home Assistant Android Client
|
||||||
|
|
||||||
version: 0.3.3+47
|
version: 0.3.3+48
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
||||||
|
Reference in New Issue
Block a user