Refactoring: Entity classes by action type. Wntity widget building in
entity
This commit is contained in:
parent
4b4fc338f6
commit
067ccfde02
@ -1,6 +1,13 @@
|
||||
part of 'main.dart';
|
||||
|
||||
class Entity {
|
||||
static Map<String, Color> stateIconColors = {
|
||||
"on": Colors.amber,
|
||||
"off": Color.fromRGBO(68, 115, 158, 1.0),
|
||||
"unavailable": Colors.black12,
|
||||
"unknown": Colors.black12,
|
||||
"playing": Colors.amber
|
||||
};
|
||||
Map _attributes;
|
||||
String _domain;
|
||||
String _entityId;
|
||||
@ -43,4 +50,123 @@ class Entity {
|
||||
_state = rawData["state"];
|
||||
}
|
||||
|
||||
Widget buildWidget() {
|
||||
return SizedBox(
|
||||
height: 34.0,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(8.0, 0.0, 12.0, 0.0),
|
||||
child: MaterialDesignIcons.createIconWidgetFromEntityData(this, 28.0, Entity.stateIconColors[_state] ?? Colors.blueGrey),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"${this.displayName}",
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: false,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0
|
||||
),
|
||||
),
|
||||
),
|
||||
_buildActionWidget()
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildActionWidget() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 0.0, 14.0, 0.0),
|
||||
child: Text(
|
||||
"${_state}${this.unitOfMeasurement}",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontSize: 16.0,
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SwitchEntity extends Entity {
|
||||
|
||||
SwitchEntity(Map rawData) : super(rawData);
|
||||
|
||||
@override
|
||||
Widget _buildActionWidget() {
|
||||
return Switch(
|
||||
value: this.isOn,
|
||||
onChanged: ((switchState) {
|
||||
eventBus.fire(new ServiceCallEvent(_domain, switchState ? "turn_on" : "turn_off", entityId, null));
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ButtonEntity extends Entity {
|
||||
|
||||
ButtonEntity(Map rawData) : super(rawData);
|
||||
|
||||
@override
|
||||
Widget _buildActionWidget() {
|
||||
return FlatButton(
|
||||
onPressed: (() {
|
||||
eventBus.fire(new ServiceCallEvent(_domain, "turn_on", _entityId, null));
|
||||
}),
|
||||
child: Text(
|
||||
"EXECUTE",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(fontSize: 16.0, color: Colors.blue),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class InputEntity extends Entity {
|
||||
|
||||
InputEntity(Map rawData) : super(rawData);
|
||||
|
||||
@override
|
||||
Widget _buildActionWidget() {
|
||||
if (this.isSlider) {
|
||||
return Container(
|
||||
width: 200.0,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Slider(
|
||||
min: this.minValue*10,
|
||||
max: this.maxValue*10,
|
||||
value: this.doubleState*10,
|
||||
divisions: this.getValueDivisions(),
|
||||
onChanged: (value) {
|
||||
eventBus.fire(new StateChangedEvent(_entityId, (value.roundToDouble() / 10).toString(), true));
|
||||
},
|
||||
onChangeEnd: (value) {
|
||||
eventBus.fire(new ServiceCallEvent(_domain, "set_value", _entityId,{"value": "${_state}"}));
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 16.0),
|
||||
child: Text(
|
||||
"${_state}${this.unitOfMeasurement}",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontSize: 16.0,
|
||||
)
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
//TODO draw box instead of slider
|
||||
return Text("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -26,6 +26,30 @@ class EntityCollection {
|
||||
});
|
||||
}
|
||||
|
||||
Entity _createEntityInstance(rawEntityData) {
|
||||
switch (rawEntityData["entity_id"].split(".")[0]) {
|
||||
case "automation":
|
||||
case "input_boolean ":
|
||||
case "switch":
|
||||
case "light": {
|
||||
return SwitchEntity(rawEntityData);
|
||||
}
|
||||
|
||||
case "script":
|
||||
case "scene": {
|
||||
return ButtonEntity(rawEntityData);
|
||||
}
|
||||
|
||||
case "input_number": {
|
||||
return InputEntity(rawEntityData);
|
||||
}
|
||||
|
||||
default: {
|
||||
return Entity(rawEntityData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateState(Map rawStateData) {
|
||||
if (isExist(rawStateData["entity_id"])) {
|
||||
updateFromRaw(rawStateData["new_state"] ?? rawStateData["old_state"]);
|
||||
@ -39,7 +63,7 @@ class EntityCollection {
|
||||
}
|
||||
|
||||
Entity addFromRaw(Map rawEntityData) {
|
||||
Entity entity = Entity(rawEntityData);
|
||||
Entity entity = _createEntityInstance(rawEntityData);
|
||||
_entities[entity.entityId] = entity;
|
||||
return entity;
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ class HomeAssistant {
|
||||
void _handleEntityStateChange(Map eventData) {
|
||||
TheLogger.log("Debug", "Parsing new state for ${eventData['entity_id']}");
|
||||
_entities.updateState(eventData);
|
||||
eventBus.fire(new StateChangedEvent(eventData["entity_id"]));
|
||||
eventBus.fire(new StateChangedEvent(eventData["entity_id"], null, false));
|
||||
}
|
||||
|
||||
void _parseConfig(Map data) {
|
||||
|
161
lib/main.dart
161
lib/main.dart
@ -85,14 +85,9 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
|
||||
String _lastErrorMessage = "";
|
||||
StreamSubscription _stateSubscription;
|
||||
StreamSubscription _settingsSubscription;
|
||||
StreamSubscription _serviceCallSubscription;
|
||||
bool _isLoading = true;
|
||||
Map<String, Color> _stateIconColors = {
|
||||
"on": Colors.amber,
|
||||
"off": Color.fromRGBO(68, 115, 158, 1.0),
|
||||
"unavailable": Colors.black12,
|
||||
"unknown": Colors.black12,
|
||||
"playing": Colors.amber
|
||||
};
|
||||
|
||||
Map<String, Color> _badgeColors = {
|
||||
"default": Color.fromRGBO(223, 76, 30, 1.0),
|
||||
"binary_sensor": Color.fromRGBO(3, 155, 229, 1.0)
|
||||
@ -146,9 +141,17 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
|
||||
if (_stateSubscription != null) _stateSubscription.cancel();
|
||||
_stateSubscription = eventBus.on<StateChangedEvent>().listen((event) {
|
||||
setState(() {
|
||||
_entities = _homeAssistant.entities;
|
||||
if (event.setToCollection) {
|
||||
_entities
|
||||
.get(event.entityId)
|
||||
.state = event.newState;
|
||||
}
|
||||
});
|
||||
});
|
||||
if (_serviceCallSubscription != null) _serviceCallSubscription.cancel();
|
||||
_serviceCallSubscription = eventBus.on<ServiceCallEvent>().listen((event) {
|
||||
_callService(event.domain, event.service, event.entityId, event.additionalParams);
|
||||
});
|
||||
}
|
||||
|
||||
_refreshData() async {
|
||||
@ -384,151 +387,18 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
|
||||
List<Widget> _buildCardBody(List ids) {
|
||||
List<Widget> entities = [];
|
||||
ids.forEach((id) {
|
||||
var data = _entities.get(id);
|
||||
if (data != null) {
|
||||
var entity = _entities.get(id);
|
||||
if (entity != null) {
|
||||
entities.add(
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
|
||||
child: SizedBox(
|
||||
height: 34.0,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(8.0, 0.0, 12.0, 0.0),
|
||||
child: MaterialDesignIcons.createIconWidgetFromEntityData(data, 28.0, _stateIconColors[data.state] ?? Colors.blueGrey),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"${data.displayName}",
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: false,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0
|
||||
),
|
||||
),
|
||||
),
|
||||
_buildEntityActionWidget(data)
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
/*new ListTile(
|
||||
leading: MaterialDesignIcons.createIconWidgetFromEntityData(data, 28.0, _stateIconColors[data.state] ?? Colors.blueGrey),
|
||||
//subtitle: Text("${data['entity_id']}"),
|
||||
trailing: _buildEntityActionWidget(data),
|
||||
title: Text(
|
||||
"${data.displayName}",
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: false,
|
||||
),
|
||||
)*/);
|
||||
child: entity.buildWidget(),
|
||||
));
|
||||
}
|
||||
});
|
||||
return entities;
|
||||
}
|
||||
|
||||
Widget _buildEntityActionWidget(Entity entity) {
|
||||
String entityId = entity.entityId;
|
||||
Widget result;
|
||||
switch (entity.domain) {
|
||||
case "automation":
|
||||
case "input_boolean":
|
||||
case "switch":
|
||||
case "light": {
|
||||
result = Switch(
|
||||
value: entity.isOn,
|
||||
onChanged: ((state) {
|
||||
_callService(
|
||||
entity.domain, state ? "turn_on" : "turn_off", entityId, null
|
||||
);
|
||||
//TODO remove after checking if state will chenge without setState but after socket event
|
||||
/*setState(() {
|
||||
_entities[entityId]["state"] = state ? "on" : "off";
|
||||
});*/
|
||||
}),
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case "script":
|
||||
case "scene": {
|
||||
result = FlatButton(
|
||||
onPressed: (() {
|
||||
_callService(entity.domain, "turn_on", entityId, null);
|
||||
}),
|
||||
child: Text(
|
||||
"EXECUTE",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(fontSize: 16.0, color: Colors.blue),
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case "input_number": {
|
||||
if (entity.isSlider) {
|
||||
result = Container(
|
||||
width: 200.0,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Slider(
|
||||
min: entity.minValue*10,
|
||||
max: entity.maxValue*10,
|
||||
value: entity.doubleState*10,
|
||||
divisions: entity.getValueDivisions(),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
entity.state = (value.roundToDouble() / 10).toString();
|
||||
});
|
||||
},
|
||||
onChangeEnd: (value) {
|
||||
_callService(entity.domain, "set_value", entityId,
|
||||
{"value": "${entity.state}"});
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 16.0),
|
||||
child: Text(
|
||||
"${entity.state}${entity.unitOfMeasurement}",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontSize: 16.0,
|
||||
)
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
//TODO draw box instead of slider
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
result = Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 0.0, 14.0, 0.0),
|
||||
child: Text(
|
||||
"${entity.state}${entity.unitOfMeasurement}",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontSize: 16.0,
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*return SizedBox(
|
||||
width: 60.0,
|
||||
// height: double.infinity,
|
||||
child: result
|
||||
);*/
|
||||
return result;
|
||||
}
|
||||
|
||||
List<Tab> buildUIViewTabs() {
|
||||
List<Tab> result = [];
|
||||
if ((_entities != null) && (!_homeAssistant.uiBuilder.isEmpty)) {
|
||||
@ -731,6 +601,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
if (_stateSubscription != null) _stateSubscription.cancel();
|
||||
if (_settingsSubscription != null) _settingsSubscription.cancel();
|
||||
if (_serviceCallSubscription != null) _serviceCallSubscription.cancel();
|
||||
_homeAssistant.closeConnection();
|
||||
super.dispose();
|
||||
}
|
||||
|
@ -44,12 +44,23 @@ class haUtils {
|
||||
|
||||
class StateChangedEvent {
|
||||
String entityId;
|
||||
String newState;
|
||||
bool setToCollection;
|
||||
|
||||
StateChangedEvent(this.entityId);
|
||||
StateChangedEvent(this.entityId, this.newState, this.setToCollection);
|
||||
}
|
||||
|
||||
class SettingsChangedEvent {
|
||||
bool reconnect;
|
||||
|
||||
SettingsChangedEvent(this.reconnect);
|
||||
}
|
||||
|
||||
class ServiceCallEvent {
|
||||
String domain;
|
||||
String service;
|
||||
String entityId;
|
||||
Map<String, String> additionalParams;
|
||||
|
||||
ServiceCallEvent(this.domain, this.service, this.entityId, this.additionalParams);
|
||||
}
|
Reference in New Issue
Block a user