Resolves #106 Climate support
This commit is contained in:
parent
c23034688e
commit
6e604440c0
@ -298,9 +298,14 @@ class ClimateEntity extends Entity {
|
|||||||
List<String> get swingList => attributes["swing_list"] != null
|
List<String> get swingList => attributes["swing_list"] != null
|
||||||
? (attributes["swing_list"] as List).cast<String>()
|
? (attributes["swing_list"] as List).cast<String>()
|
||||||
: null;
|
: null;
|
||||||
double get temperature => _getTemperature();
|
double get temperature => _getDoubleAttributeValue('temperature');
|
||||||
double get targetHigh => _getTargetHigh();
|
double get targetHigh => _getDoubleAttributeValue('target_temp_high');
|
||||||
double get targetLow => _getTargetLow();
|
double get targetLow => _getDoubleAttributeValue('target_temp_low');
|
||||||
|
double get maxTemp => _getDoubleAttributeValue('max_temp') ?? 100.0;
|
||||||
|
double get minTemp => _getDoubleAttributeValue('min_temp') ?? -100.0;
|
||||||
|
double get targetHumidity => _getDoubleAttributeValue('humidity');
|
||||||
|
double get maxHumidity => _getDoubleAttributeValue('max_humidity');
|
||||||
|
double get minHumidity => _getDoubleAttributeValue('min_humidity');
|
||||||
String get operationMode => attributes['operation_mode'];
|
String get operationMode => attributes['operation_mode'];
|
||||||
String get fanMode => attributes['fan_mode'];
|
String get fanMode => attributes['fan_mode'];
|
||||||
String get swingMode => attributes['swing_mode'];
|
String get swingMode => attributes['swing_mode'];
|
||||||
@ -320,8 +325,8 @@ class ClimateEntity extends Entity {
|
|||||||
return ClimateControlWidget();
|
return ClimateControlWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
double _getTemperature() {
|
double _getDoubleAttributeValue(String attributeName) {
|
||||||
var temp1 = attributes['temperature'];
|
var temp1 = attributes["$attributeName"];
|
||||||
if (temp1 is int) {
|
if (temp1 is int) {
|
||||||
return temp1.toDouble();
|
return temp1.toDouble();
|
||||||
} else if (temp1 is double) {
|
} else if (temp1 is double) {
|
||||||
@ -331,27 +336,6 @@ class ClimateEntity extends Entity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double _getTargetHigh() {
|
|
||||||
var temp1 = attributes['target_temp_high'];
|
|
||||||
if (temp1 is int) {
|
|
||||||
return temp1.toDouble();
|
|
||||||
} else if (temp1 is double) {
|
|
||||||
return temp1;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double _getTargetLow() {
|
|
||||||
var temp1 = attributes['target_temp_low'];
|
|
||||||
if (temp1 is int) {
|
|
||||||
return temp1.toDouble();
|
|
||||||
} else if (temp1 is double) {
|
|
||||||
return temp1;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SelectEntity extends Entity {
|
class SelectEntity extends Entity {
|
||||||
|
@ -240,13 +240,13 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
double _tmpTemperature = 0.0;
|
double _tmpTemperature = 0.0;
|
||||||
double _tmpTargetLow = 0.0;
|
double _tmpTargetLow = 0.0;
|
||||||
double _tmpTargetHigh = 0.0;
|
double _tmpTargetHigh = 0.0;
|
||||||
|
double _tmpTargetHumidity = 0.0;
|
||||||
String _tmpOperationMode;
|
String _tmpOperationMode;
|
||||||
String _tmpFanMode;
|
String _tmpFanMode;
|
||||||
String _tmpSwingMode;
|
String _tmpSwingMode;
|
||||||
bool _tmpAwayMode = false;
|
bool _tmpAwayMode = false;
|
||||||
bool _tmpIsOff = false;
|
bool _tmpIsOff = false;
|
||||||
bool _tmpAuxHeat = false;
|
bool _tmpAuxHeat = false;
|
||||||
double _temperatureStep = 0.2;
|
|
||||||
|
|
||||||
void _resetVars(ClimateEntity entity) {
|
void _resetVars(ClimateEntity entity) {
|
||||||
_tmpTemperature = entity.temperature;
|
_tmpTemperature = entity.temperature;
|
||||||
@ -258,38 +258,39 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
_tmpAwayMode = entity.awayMode;
|
_tmpAwayMode = entity.awayMode;
|
||||||
_tmpIsOff = entity.isOff;
|
_tmpIsOff = entity.isOff;
|
||||||
_tmpAuxHeat = entity.auxHeat;
|
_tmpAuxHeat = entity.auxHeat;
|
||||||
|
_tmpTargetHumidity = entity.targetHumidity;
|
||||||
|
|
||||||
_showPending = false;
|
_showPending = false;
|
||||||
_changedHere = false;
|
_changedHere = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _temperatureUp(ClimateEntity entity) {
|
void _temperatureUp(ClimateEntity entity, double step) {
|
||||||
_tmpTemperature += _temperatureStep;
|
_tmpTemperature = ((_tmpTemperature + step) <= entity.maxTemp) ? _tmpTemperature + step : entity.maxTemp;
|
||||||
_setTemperature(entity);
|
_setTemperature(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _temperatureDown(ClimateEntity entity) {
|
void _temperatureDown(ClimateEntity entity, double step) {
|
||||||
_tmpTemperature -= _temperatureStep;
|
_tmpTemperature = ((_tmpTemperature - step) >= entity.minTemp) ? _tmpTemperature - step : entity.minTemp;
|
||||||
_setTemperature(entity);
|
_setTemperature(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _targetLowUp(ClimateEntity entity) {
|
void _targetLowUp(ClimateEntity entity, double step) {
|
||||||
_tmpTargetLow += _temperatureStep;
|
_tmpTargetLow = ((_tmpTargetLow + step) <= entity.maxTemp) ? _tmpTargetLow + step : entity.maxTemp;
|
||||||
_setTargetTemp(entity);
|
_setTargetTemp(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _targetLowDown(ClimateEntity entity) {
|
void _targetLowDown(ClimateEntity entity, double step) {
|
||||||
_tmpTargetLow -= _temperatureStep;
|
_tmpTargetLow = ((_tmpTargetLow - step) >= entity.minTemp) ? _tmpTargetLow - step : entity.minTemp;
|
||||||
_setTargetTemp(entity);
|
_setTargetTemp(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _targetHighUp(ClimateEntity entity) {
|
void _targetHighUp(ClimateEntity entity, double step) {
|
||||||
_tmpTargetHigh += _temperatureStep;
|
_tmpTargetHigh = ((_tmpTargetHigh + step) <= entity.maxTemp) ? _tmpTargetHigh + step : entity.maxTemp;
|
||||||
_setTargetTemp(entity);
|
_setTargetTemp(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _targetHighDown(ClimateEntity entity) {
|
void _targetHighDown(ClimateEntity entity, double step) {
|
||||||
_tmpTargetHigh -= _temperatureStep;
|
_tmpTargetHigh = ((_tmpTargetHigh - step) >= entity.minTemp) ? _tmpTargetHigh - step : entity.minTemp;
|
||||||
_setTargetTemp(entity);
|
_setTargetTemp(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,6 +313,15 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _setTargetHumidity(ClimateEntity entity, double value) {
|
||||||
|
setState(() {
|
||||||
|
_tmpTargetHumidity = value.roundToDouble();
|
||||||
|
_changedHere = true;
|
||||||
|
eventBus.fire(new ServiceCallEvent(entity.domain, "set_humidity", entity.entityId,{"humidity": "$_tmpTargetHumidity"}));
|
||||||
|
_resetStateTimer(entity);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void _setOperationMode(ClimateEntity entity, value) {
|
void _setOperationMode(ClimateEntity entity, value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_tmpOperationMode = value;
|
_tmpOperationMode = value;
|
||||||
@ -394,6 +404,7 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
_buildOnOffControl(entity),
|
_buildOnOffControl(entity),
|
||||||
_buildTemperatureControls(entity),
|
_buildTemperatureControls(entity),
|
||||||
|
_buildHumidityControls(entity),
|
||||||
_buildOperationControl(entity),
|
_buildOperationControl(entity),
|
||||||
_buildFanControl(entity),
|
_buildFanControl(entity),
|
||||||
_buildSwingControl(entity),
|
_buildSwingControl(entity),
|
||||||
@ -451,7 +462,7 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAuxHeatControl(ClimateEntity entity) {
|
Widget _buildAuxHeatControl(ClimateEntity entity) {
|
||||||
if (entity.supportAwayMode) {
|
if (entity.supportAuxHeat ) {
|
||||||
return Row(
|
return Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -568,96 +579,197 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
|
|
||||||
Widget _buildTemperatureControls(ClimateEntity entity) {
|
Widget _buildTemperatureControls(ClimateEntity entity) {
|
||||||
List<Widget> result = [];
|
List<Widget> result = [];
|
||||||
|
bool empty = true;
|
||||||
if (entity.supportTargetTemperature) {
|
if (entity.supportTargetTemperature) {
|
||||||
|
empty = false;
|
||||||
result.addAll(<Widget>[
|
result.addAll(<Widget>[
|
||||||
Expanded(
|
Text(
|
||||||
child: Text(
|
"$_tmpTemperature",
|
||||||
"$_tmpTemperature",
|
style: TextStyle(
|
||||||
style: TextStyle(
|
fontSize: entity.largeFontSize,
|
||||||
fontSize: entity.largeFontSize,
|
color: _showPending ? Colors.red : Colors.black
|
||||||
color: _showPending ? Colors.red : Colors.black
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.keyboard_arrow_up),
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-up')),
|
||||||
iconSize: 30.0,
|
iconSize: 30.0,
|
||||||
onPressed: () => _temperatureUp(entity),
|
onPressed: () => _temperatureUp(entity, 0.1),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.keyboard_arrow_down),
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-down')),
|
||||||
iconSize: 30.0,
|
iconSize: 30.0,
|
||||||
onPressed: () => _temperatureDown(entity),
|
onPressed: () => _temperatureDown(entity, 0.1),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: <Widget>[
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-double-up')),
|
||||||
|
iconSize: 30.0,
|
||||||
|
onPressed: () => _temperatureUp(entity, 0.5),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-double-down')),
|
||||||
|
iconSize: 30.0,
|
||||||
|
onPressed: () => _temperatureDown(entity, 0.5),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
} else if (entity.supportTargetTemperatureHigh && entity.supportTargetTemperatureLow) {
|
} else if (entity.supportTargetTemperatureHigh && entity.supportTargetTemperatureLow) {
|
||||||
|
empty = false;
|
||||||
result.addAll(<Widget>[
|
result.addAll(<Widget>[
|
||||||
Expanded(
|
Text(
|
||||||
child: Text(
|
"$_tmpTargetLow",
|
||||||
"$_tmpTargetLow",
|
style: TextStyle(
|
||||||
style: TextStyle(
|
fontSize: entity.largeFontSize,
|
||||||
fontSize: entity.largeFontSize,
|
color: _showPending ? Colors.red : Colors.black
|
||||||
color: _showPending ? Colors.red : Colors.black
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.keyboard_arrow_up),
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-up')),
|
||||||
iconSize: 30.0,
|
iconSize: 30.0,
|
||||||
onPressed: () => _targetLowUp(entity),
|
onPressed: () => _targetLowUp(entity, 0.1),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.keyboard_arrow_down),
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-down')),
|
||||||
iconSize: 30.0,
|
iconSize: 30.0,
|
||||||
onPressed: () => _targetLowDown(entity),
|
onPressed: () => _targetLowDown(entity, 0.1),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Container(width: 20.0,),
|
Column(
|
||||||
Expanded(
|
children: <Widget>[
|
||||||
child: Text(
|
IconButton(
|
||||||
"$_tmpTargetHigh",
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-double-up')),
|
||||||
style: TextStyle(
|
iconSize: 30.0,
|
||||||
fontSize: entity.largeFontSize,
|
onPressed: () => _targetLowUp(entity, 0.5),
|
||||||
color: _showPending ? Colors.red : Colors.black
|
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-double-down')),
|
||||||
|
iconSize: 30.0,
|
||||||
|
onPressed: () => _targetLowDown(entity, 0.5),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(height: 10.0),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"$_tmpTargetHigh",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: entity.largeFontSize,
|
||||||
|
color: _showPending ? Colors.red : Colors.black
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.keyboard_arrow_up),
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-up')),
|
||||||
iconSize: 30.0,
|
iconSize: 30.0,
|
||||||
onPressed: () => _targetHighUp(entity),
|
onPressed: () => _targetHighUp(entity, 0.1),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.keyboard_arrow_down),
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-down')),
|
||||||
iconSize: 30.0,
|
iconSize: 30.0,
|
||||||
onPressed: () => _targetHighDown(entity),
|
onPressed: () => _targetHighDown(entity, 0.1),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: <Widget>[
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-double-up')),
|
||||||
|
iconSize: 30.0,
|
||||||
|
onPressed: () => _targetHighUp(entity, 0.5),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-double-down')),
|
||||||
|
iconSize: 30.0,
|
||||||
|
onPressed: () => _targetHighDown(entity, 0.5),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
} else {
|
} else if (entity.supportTargetTemperatureHigh || entity.supportTargetTemperatureLow) {
|
||||||
result.add(Text("Unsupported temperature controls =("));
|
empty = false;
|
||||||
|
result.add(Text("Unsupported temperature control. Please, report an issue."));
|
||||||
}
|
}
|
||||||
return Column(
|
if (!empty) {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
return Column(
|
||||||
children: <Widget>[
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Text("Target temperature", style: TextStyle(
|
children: <Widget>[
|
||||||
fontSize: entity.stateFontSize
|
Text("Target temperature", style: TextStyle(
|
||||||
)),
|
fontSize: entity.stateFontSize
|
||||||
Row(
|
)),
|
||||||
children: result,
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: result,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container(height: 0.0, width: 0.0,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildHumidityControls(ClimateEntity entity) {
|
||||||
|
List<Widget> result = [];
|
||||||
|
bool empty = true;
|
||||||
|
if (entity.supportTargetHumidity) {
|
||||||
|
empty = false;
|
||||||
|
result.addAll(<Widget>[
|
||||||
|
Text(
|
||||||
|
"$_tmpTargetHumidity%",
|
||||||
|
style: TextStyle(fontSize: entity.largeFontSize),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Slider(
|
||||||
|
value: _tmpTargetHumidity,
|
||||||
|
max: entity.maxHumidity,
|
||||||
|
min: entity.minHumidity,
|
||||||
|
onChanged: ((double val) {
|
||||||
|
setState(() {
|
||||||
|
_changedHere = true;
|
||||||
|
_tmpTargetHumidity = val.roundToDouble();
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
onChangeEnd: (double v) => _setTargetHumidity(entity, v),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
]);
|
||||||
);
|
}
|
||||||
|
if (!empty) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(
|
||||||
|
0.0, entity.rowPadding, 0.0, entity.rowPadding),
|
||||||
|
child: Text("Target humidity", style: TextStyle(
|
||||||
|
fontSize: entity.stateFontSize
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: result,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: entity.rowPadding,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container(
|
||||||
|
width: 0.0,
|
||||||
|
height: 0.0,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ part 'card_class.dart';
|
|||||||
|
|
||||||
EventBus eventBus = new EventBus();
|
EventBus eventBus = new EventBus();
|
||||||
const String appName = "HA Client";
|
const String appName = "HA Client";
|
||||||
const appVersion = "0.2.5.35";
|
const appVersion = "0.2.5.36";
|
||||||
|
|
||||||
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.2.5+35
|
version: 0.2.5+36
|
||||||
|
|
||||||
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