Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
4b6dda5a9c | |||
4099fa0c83 | |||
76057e8797 | |||
538d3603dc | |||
bc0e72ca52 | |||
f25a47beb2 | |||
cc3c6b0087 | |||
6cf80c0bfd | |||
8ce9bdb7a5 | |||
31e50150b1 |
@ -19,8 +19,8 @@ class _EntityViewPageState extends State<EntityViewPage> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_stateSubscription = eventBus.on<StateChangedEvent>().listen((event) {
|
_stateSubscription = eventBus.on<StateChangedEvent>().listen((event) {
|
||||||
Logger.d("State change event handled by entity page: ${event.entityId}");
|
|
||||||
if (event.entityId == widget.entityId) {
|
if (event.entityId == widget.entityId) {
|
||||||
|
Logger.d("State change event handled by entity page: ${event.entityId}");
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -6,14 +6,12 @@ class CameraEntity extends Entity {
|
|||||||
|
|
||||||
CameraEntity(Map rawData) : super(rawData);
|
CameraEntity(Map rawData) : super(rawData);
|
||||||
|
|
||||||
bool get supportOnOff => ((attributes["supported_features"] &
|
bool get supportOnOff => ((supportedFeatures &
|
||||||
CameraEntity.SUPPORT_ON_OFF) ==
|
CameraEntity.SUPPORT_ON_OFF) ==
|
||||||
CameraEntity.SUPPORT_ON_OFF);
|
CameraEntity.SUPPORT_ON_OFF);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget _buildAdditionalControlsForPage(BuildContext context) {
|
Widget _buildAdditionalControlsForPage(BuildContext context) {
|
||||||
return CameraControlsWidget(
|
return CameraStreamView();
|
||||||
url: '$homeAssistantWebHost/api/camera_proxy_stream/camera.demo_camera?token=${this.attributes['access_token']}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,44 +23,44 @@ class ClimateEntity extends Entity {
|
|||||||
static const SUPPORT_AUX_HEAT = 2048;
|
static const SUPPORT_AUX_HEAT = 2048;
|
||||||
static const SUPPORT_ON_OFF = 4096;
|
static const SUPPORT_ON_OFF = 4096;
|
||||||
|
|
||||||
bool get supportTargetTemperature => ((attributes["supported_features"] &
|
bool get supportTargetTemperature => ((supportedFeatures &
|
||||||
ClimateEntity.SUPPORT_TARGET_TEMPERATURE) ==
|
ClimateEntity.SUPPORT_TARGET_TEMPERATURE) ==
|
||||||
ClimateEntity.SUPPORT_TARGET_TEMPERATURE);
|
ClimateEntity.SUPPORT_TARGET_TEMPERATURE);
|
||||||
bool get supportTargetTemperatureHigh => ((attributes["supported_features"] &
|
bool get supportTargetTemperatureHigh => ((supportedFeatures &
|
||||||
ClimateEntity.SUPPORT_TARGET_TEMPERATURE_HIGH) ==
|
ClimateEntity.SUPPORT_TARGET_TEMPERATURE_HIGH) ==
|
||||||
ClimateEntity.SUPPORT_TARGET_TEMPERATURE_HIGH);
|
ClimateEntity.SUPPORT_TARGET_TEMPERATURE_HIGH);
|
||||||
bool get supportTargetTemperatureLow => ((attributes["supported_features"] &
|
bool get supportTargetTemperatureLow => ((supportedFeatures &
|
||||||
ClimateEntity.SUPPORT_TARGET_TEMPERATURE_LOW) ==
|
ClimateEntity.SUPPORT_TARGET_TEMPERATURE_LOW) ==
|
||||||
ClimateEntity.SUPPORT_TARGET_TEMPERATURE_LOW);
|
ClimateEntity.SUPPORT_TARGET_TEMPERATURE_LOW);
|
||||||
bool get supportTargetHumidity => ((attributes["supported_features"] &
|
bool get supportTargetHumidity => ((supportedFeatures &
|
||||||
ClimateEntity.SUPPORT_TARGET_HUMIDITY) ==
|
ClimateEntity.SUPPORT_TARGET_HUMIDITY) ==
|
||||||
ClimateEntity.SUPPORT_TARGET_HUMIDITY);
|
ClimateEntity.SUPPORT_TARGET_HUMIDITY);
|
||||||
bool get supportTargetHumidityHigh => ((attributes["supported_features"] &
|
bool get supportTargetHumidityHigh => ((supportedFeatures &
|
||||||
ClimateEntity.SUPPORT_TARGET_HUMIDITY_HIGH) ==
|
ClimateEntity.SUPPORT_TARGET_HUMIDITY_HIGH) ==
|
||||||
ClimateEntity.SUPPORT_TARGET_HUMIDITY_HIGH);
|
ClimateEntity.SUPPORT_TARGET_HUMIDITY_HIGH);
|
||||||
bool get supportTargetHumidityLow => ((attributes["supported_features"] &
|
bool get supportTargetHumidityLow => ((supportedFeatures &
|
||||||
ClimateEntity.SUPPORT_TARGET_HUMIDITY_LOW) ==
|
ClimateEntity.SUPPORT_TARGET_HUMIDITY_LOW) ==
|
||||||
ClimateEntity.SUPPORT_TARGET_HUMIDITY_LOW);
|
ClimateEntity.SUPPORT_TARGET_HUMIDITY_LOW);
|
||||||
bool get supportFanMode =>
|
bool get supportFanMode =>
|
||||||
((attributes["supported_features"] & ClimateEntity.SUPPORT_FAN_MODE) ==
|
((supportedFeatures & ClimateEntity.SUPPORT_FAN_MODE) ==
|
||||||
ClimateEntity.SUPPORT_FAN_MODE);
|
ClimateEntity.SUPPORT_FAN_MODE);
|
||||||
bool get supportOperationMode => ((attributes["supported_features"] &
|
bool get supportOperationMode => ((supportedFeatures &
|
||||||
ClimateEntity.SUPPORT_OPERATION_MODE) ==
|
ClimateEntity.SUPPORT_OPERATION_MODE) ==
|
||||||
ClimateEntity.SUPPORT_OPERATION_MODE);
|
ClimateEntity.SUPPORT_OPERATION_MODE);
|
||||||
bool get supportHoldMode =>
|
bool get supportHoldMode =>
|
||||||
((attributes["supported_features"] & ClimateEntity.SUPPORT_HOLD_MODE) ==
|
((supportedFeatures & ClimateEntity.SUPPORT_HOLD_MODE) ==
|
||||||
ClimateEntity.SUPPORT_HOLD_MODE);
|
ClimateEntity.SUPPORT_HOLD_MODE);
|
||||||
bool get supportSwingMode =>
|
bool get supportSwingMode =>
|
||||||
((attributes["supported_features"] & ClimateEntity.SUPPORT_SWING_MODE) ==
|
((supportedFeatures & ClimateEntity.SUPPORT_SWING_MODE) ==
|
||||||
ClimateEntity.SUPPORT_SWING_MODE);
|
ClimateEntity.SUPPORT_SWING_MODE);
|
||||||
bool get supportAwayMode =>
|
bool get supportAwayMode =>
|
||||||
((attributes["supported_features"] & ClimateEntity.SUPPORT_AWAY_MODE) ==
|
((supportedFeatures & ClimateEntity.SUPPORT_AWAY_MODE) ==
|
||||||
ClimateEntity.SUPPORT_AWAY_MODE);
|
ClimateEntity.SUPPORT_AWAY_MODE);
|
||||||
bool get supportAuxHeat =>
|
bool get supportAuxHeat =>
|
||||||
((attributes["supported_features"] & ClimateEntity.SUPPORT_AUX_HEAT) ==
|
((supportedFeatures & ClimateEntity.SUPPORT_AUX_HEAT) ==
|
||||||
ClimateEntity.SUPPORT_AUX_HEAT);
|
ClimateEntity.SUPPORT_AUX_HEAT);
|
||||||
bool get supportOnOff =>
|
bool get supportOnOff =>
|
||||||
((attributes["supported_features"] & ClimateEntity.SUPPORT_ON_OFF) ==
|
((supportedFeatures & ClimateEntity.SUPPORT_ON_OFF) ==
|
||||||
ClimateEntity.SUPPORT_ON_OFF);
|
ClimateEntity.SUPPORT_ON_OFF);
|
||||||
|
|
||||||
List<String> get operationList => attributes["operation_list"] != null
|
List<String> get operationList => attributes["operation_list"] != null
|
||||||
|
@ -11,29 +11,29 @@ class CoverEntity extends Entity {
|
|||||||
static const SUPPORT_STOP_TILT = 64;
|
static const SUPPORT_STOP_TILT = 64;
|
||||||
static const SUPPORT_SET_TILT_POSITION = 128;
|
static const SUPPORT_SET_TILT_POSITION = 128;
|
||||||
|
|
||||||
bool get supportOpen => ((attributes["supported_features"] &
|
bool get supportOpen => ((supportedFeatures &
|
||||||
CoverEntity.SUPPORT_OPEN) ==
|
CoverEntity.SUPPORT_OPEN) ==
|
||||||
CoverEntity.SUPPORT_OPEN);
|
CoverEntity.SUPPORT_OPEN);
|
||||||
bool get supportClose => ((attributes["supported_features"] &
|
bool get supportClose => ((supportedFeatures &
|
||||||
CoverEntity.SUPPORT_CLOSE) ==
|
CoverEntity.SUPPORT_CLOSE) ==
|
||||||
CoverEntity.SUPPORT_CLOSE);
|
CoverEntity.SUPPORT_CLOSE);
|
||||||
bool get supportSetPosition => ((attributes["supported_features"] &
|
bool get supportSetPosition => ((supportedFeatures &
|
||||||
CoverEntity.SUPPORT_SET_POSITION) ==
|
CoverEntity.SUPPORT_SET_POSITION) ==
|
||||||
CoverEntity.SUPPORT_SET_POSITION);
|
CoverEntity.SUPPORT_SET_POSITION);
|
||||||
bool get supportStop => ((attributes["supported_features"] &
|
bool get supportStop => ((supportedFeatures &
|
||||||
CoverEntity.SUPPORT_STOP) ==
|
CoverEntity.SUPPORT_STOP) ==
|
||||||
CoverEntity.SUPPORT_STOP);
|
CoverEntity.SUPPORT_STOP);
|
||||||
|
|
||||||
bool get supportOpenTilt => ((attributes["supported_features"] &
|
bool get supportOpenTilt => ((supportedFeatures &
|
||||||
CoverEntity.SUPPORT_OPEN_TILT) ==
|
CoverEntity.SUPPORT_OPEN_TILT) ==
|
||||||
CoverEntity.SUPPORT_OPEN_TILT);
|
CoverEntity.SUPPORT_OPEN_TILT);
|
||||||
bool get supportCloseTilt => ((attributes["supported_features"] &
|
bool get supportCloseTilt => ((supportedFeatures &
|
||||||
CoverEntity.SUPPORT_CLOSE_TILT) ==
|
CoverEntity.SUPPORT_CLOSE_TILT) ==
|
||||||
CoverEntity.SUPPORT_CLOSE_TILT);
|
CoverEntity.SUPPORT_CLOSE_TILT);
|
||||||
bool get supportStopTilt => ((attributes["supported_features"] &
|
bool get supportStopTilt => ((supportedFeatures &
|
||||||
CoverEntity.SUPPORT_STOP_TILT) ==
|
CoverEntity.SUPPORT_STOP_TILT) ==
|
||||||
CoverEntity.SUPPORT_STOP_TILT);
|
CoverEntity.SUPPORT_STOP_TILT);
|
||||||
bool get supportSetTiltPosition => ((attributes["supported_features"] &
|
bool get supportSetTiltPosition => ((supportedFeatures &
|
||||||
CoverEntity.SUPPORT_SET_TILT_POSITION) ==
|
CoverEntity.SUPPORT_SET_TILT_POSITION) ==
|
||||||
CoverEntity.SUPPORT_SET_TILT_POSITION);
|
CoverEntity.SUPPORT_SET_TILT_POSITION);
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ class Entity {
|
|||||||
String get lastUpdated => _getLastUpdatedFormatted();
|
String get lastUpdated => _getLastUpdatedFormatted();
|
||||||
bool get isHidden => attributes["hidden"] ?? false;
|
bool get isHidden => attributes["hidden"] ?? false;
|
||||||
double get doubleState => double.tryParse(state) ?? 0.0;
|
double get doubleState => double.tryParse(state) ?? 0.0;
|
||||||
|
int get supportedFeatures => attributes["supported_features"] ?? 0;
|
||||||
|
|
||||||
Entity(Map rawData) {
|
Entity(Map rawData) {
|
||||||
update(rawData);
|
update(rawData);
|
||||||
|
@ -8,13 +8,13 @@ class FanEntity extends Entity {
|
|||||||
|
|
||||||
FanEntity(Map rawData) : super(rawData);
|
FanEntity(Map rawData) : super(rawData);
|
||||||
|
|
||||||
bool get supportSetSpeed => ((attributes["supported_features"] &
|
bool get supportSetSpeed => ((supportedFeatures &
|
||||||
FanEntity.SUPPORT_SET_SPEED) ==
|
FanEntity.SUPPORT_SET_SPEED) ==
|
||||||
FanEntity.SUPPORT_SET_SPEED);
|
FanEntity.SUPPORT_SET_SPEED);
|
||||||
bool get supportOscillate => ((attributes["supported_features"] &
|
bool get supportOscillate => ((supportedFeatures &
|
||||||
FanEntity.SUPPORT_OSCILLATE) ==
|
FanEntity.SUPPORT_OSCILLATE) ==
|
||||||
FanEntity.SUPPORT_OSCILLATE);
|
FanEntity.SUPPORT_OSCILLATE);
|
||||||
bool get supportDirection => ((attributes["supported_features"] &
|
bool get supportDirection => ((supportedFeatures &
|
||||||
FanEntity.SUPPORT_DIRECTION) ==
|
FanEntity.SUPPORT_DIRECTION) ==
|
||||||
FanEntity.SUPPORT_DIRECTION);
|
FanEntity.SUPPORT_DIRECTION);
|
||||||
|
|
||||||
|
@ -10,25 +10,25 @@ class LightEntity extends Entity {
|
|||||||
static const SUPPORT_TRANSITION = 32;
|
static const SUPPORT_TRANSITION = 32;
|
||||||
static const SUPPORT_WHITE_VALUE = 128;
|
static const SUPPORT_WHITE_VALUE = 128;
|
||||||
|
|
||||||
bool get supportBrightness => ((attributes["supported_features"] &
|
bool get supportBrightness => ((supportedFeatures &
|
||||||
LightEntity.SUPPORT_BRIGHTNESS) ==
|
LightEntity.SUPPORT_BRIGHTNESS) ==
|
||||||
LightEntity.SUPPORT_BRIGHTNESS);
|
LightEntity.SUPPORT_BRIGHTNESS);
|
||||||
bool get supportColorTemp => ((attributes["supported_features"] &
|
bool get supportColorTemp => ((supportedFeatures &
|
||||||
LightEntity.SUPPORT_COLOR_TEMP) ==
|
LightEntity.SUPPORT_COLOR_TEMP) ==
|
||||||
LightEntity.SUPPORT_COLOR_TEMP);
|
LightEntity.SUPPORT_COLOR_TEMP);
|
||||||
bool get supportEffect => ((attributes["supported_features"] &
|
bool get supportEffect => ((supportedFeatures &
|
||||||
LightEntity.SUPPORT_EFFECT) ==
|
LightEntity.SUPPORT_EFFECT) ==
|
||||||
LightEntity.SUPPORT_EFFECT);
|
LightEntity.SUPPORT_EFFECT);
|
||||||
bool get supportFlash => ((attributes["supported_features"] &
|
bool get supportFlash => ((supportedFeatures &
|
||||||
LightEntity.SUPPORT_FLASH) ==
|
LightEntity.SUPPORT_FLASH) ==
|
||||||
LightEntity.SUPPORT_FLASH);
|
LightEntity.SUPPORT_FLASH);
|
||||||
bool get supportColor => ((attributes["supported_features"] &
|
bool get supportColor => ((supportedFeatures &
|
||||||
LightEntity.SUPPORT_COLOR) ==
|
LightEntity.SUPPORT_COLOR) ==
|
||||||
LightEntity.SUPPORT_COLOR);
|
LightEntity.SUPPORT_COLOR);
|
||||||
bool get supportTransition => ((attributes["supported_features"] &
|
bool get supportTransition => ((supportedFeatures &
|
||||||
LightEntity.SUPPORT_TRANSITION) ==
|
LightEntity.SUPPORT_TRANSITION) ==
|
||||||
LightEntity.SUPPORT_TRANSITION);
|
LightEntity.SUPPORT_TRANSITION);
|
||||||
bool get supportWhiteValue => ((attributes["supported_features"] &
|
bool get supportWhiteValue => ((supportedFeatures &
|
||||||
LightEntity.SUPPORT_WHITE_VALUE) ==
|
LightEntity.SUPPORT_WHITE_VALUE) ==
|
||||||
LightEntity.SUPPORT_WHITE_VALUE);
|
LightEntity.SUPPORT_WHITE_VALUE);
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ class LightEntity extends Entity {
|
|||||||
double get maxMireds => _getDoubleAttributeValue("max_mireds");
|
double get maxMireds => _getDoubleAttributeValue("max_mireds");
|
||||||
double get minMireds => _getDoubleAttributeValue("min_mireds");
|
double get minMireds => _getDoubleAttributeValue("min_mireds");
|
||||||
HSVColor get color => _getColor();
|
HSVColor get color => _getColor();
|
||||||
bool get isAdditionalControls => ((attributes["supported_features"] != null) && (attributes["supported_features"] != 0));
|
bool get isAdditionalControls => ((supportedFeatures != null) && (supportedFeatures != 0));
|
||||||
List<String> get effectList => getStringListAttributeValue("effect_list");
|
List<String> get effectList => getStringListAttributeValue("effect_list");
|
||||||
|
|
||||||
LightEntity(Map rawData) : super(rawData);
|
LightEntity(Map rawData) : super(rawData);
|
||||||
|
@ -22,53 +22,53 @@ class MediaPlayerEntity extends Entity {
|
|||||||
|
|
||||||
MediaPlayerEntity(Map rawData) : super(rawData);
|
MediaPlayerEntity(Map rawData) : super(rawData);
|
||||||
|
|
||||||
bool get supportPause => ((attributes["supported_features"] &
|
bool get supportPause => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_PAUSE) ==
|
MediaPlayerEntity.SUPPORT_PAUSE) ==
|
||||||
MediaPlayerEntity.SUPPORT_PAUSE);
|
MediaPlayerEntity.SUPPORT_PAUSE);
|
||||||
bool get supportSeek => ((attributes["supported_features"] &
|
bool get supportSeek => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_SEEK) ==
|
MediaPlayerEntity.SUPPORT_SEEK) ==
|
||||||
MediaPlayerEntity.SUPPORT_SEEK);
|
MediaPlayerEntity.SUPPORT_SEEK);
|
||||||
bool get supportVolumeSet => ((attributes["supported_features"] &
|
bool get supportVolumeSet => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_VOLUME_SET) ==
|
MediaPlayerEntity.SUPPORT_VOLUME_SET) ==
|
||||||
MediaPlayerEntity.SUPPORT_VOLUME_SET);
|
MediaPlayerEntity.SUPPORT_VOLUME_SET);
|
||||||
bool get supportVolumeMute => ((attributes["supported_features"] &
|
bool get supportVolumeMute => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_VOLUME_MUTE) ==
|
MediaPlayerEntity.SUPPORT_VOLUME_MUTE) ==
|
||||||
MediaPlayerEntity.SUPPORT_VOLUME_MUTE);
|
MediaPlayerEntity.SUPPORT_VOLUME_MUTE);
|
||||||
bool get supportPreviousTrack => ((attributes["supported_features"] &
|
bool get supportPreviousTrack => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_PREVIOUS_TRACK) ==
|
MediaPlayerEntity.SUPPORT_PREVIOUS_TRACK) ==
|
||||||
MediaPlayerEntity.SUPPORT_PREVIOUS_TRACK);
|
MediaPlayerEntity.SUPPORT_PREVIOUS_TRACK);
|
||||||
bool get supportNextTrack => ((attributes["supported_features"] &
|
bool get supportNextTrack => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_NEXT_TRACK) ==
|
MediaPlayerEntity.SUPPORT_NEXT_TRACK) ==
|
||||||
MediaPlayerEntity.SUPPORT_NEXT_TRACK);
|
MediaPlayerEntity.SUPPORT_NEXT_TRACK);
|
||||||
|
|
||||||
bool get supportTurnOn => ((attributes["supported_features"] &
|
bool get supportTurnOn => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_TURN_ON) ==
|
MediaPlayerEntity.SUPPORT_TURN_ON) ==
|
||||||
MediaPlayerEntity.SUPPORT_TURN_ON);
|
MediaPlayerEntity.SUPPORT_TURN_ON);
|
||||||
bool get supportTurnOff => ((attributes["supported_features"] &
|
bool get supportTurnOff => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_TURN_OFF) ==
|
MediaPlayerEntity.SUPPORT_TURN_OFF) ==
|
||||||
MediaPlayerEntity.SUPPORT_TURN_OFF);
|
MediaPlayerEntity.SUPPORT_TURN_OFF);
|
||||||
bool get supportPlayMedia => ((attributes["supported_features"] &
|
bool get supportPlayMedia => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_PLAY_MEDIA) ==
|
MediaPlayerEntity.SUPPORT_PLAY_MEDIA) ==
|
||||||
MediaPlayerEntity.SUPPORT_PLAY_MEDIA);
|
MediaPlayerEntity.SUPPORT_PLAY_MEDIA);
|
||||||
bool get supportVolumeStep => ((attributes["supported_features"] &
|
bool get supportVolumeStep => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_VOLUME_STEP) ==
|
MediaPlayerEntity.SUPPORT_VOLUME_STEP) ==
|
||||||
MediaPlayerEntity.SUPPORT_VOLUME_STEP);
|
MediaPlayerEntity.SUPPORT_VOLUME_STEP);
|
||||||
bool get supportSelectSource => ((attributes["supported_features"] &
|
bool get supportSelectSource => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_SELECT_SOURCE) ==
|
MediaPlayerEntity.SUPPORT_SELECT_SOURCE) ==
|
||||||
MediaPlayerEntity.SUPPORT_SELECT_SOURCE);
|
MediaPlayerEntity.SUPPORT_SELECT_SOURCE);
|
||||||
bool get supportStop => ((attributes["supported_features"] &
|
bool get supportStop => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_STOP) ==
|
MediaPlayerEntity.SUPPORT_STOP) ==
|
||||||
MediaPlayerEntity.SUPPORT_STOP);
|
MediaPlayerEntity.SUPPORT_STOP);
|
||||||
bool get supportClearPlaylist => ((attributes["supported_features"] &
|
bool get supportClearPlaylist => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_CLEAR_PLAYLIST) ==
|
MediaPlayerEntity.SUPPORT_CLEAR_PLAYLIST) ==
|
||||||
MediaPlayerEntity.SUPPORT_CLEAR_PLAYLIST);
|
MediaPlayerEntity.SUPPORT_CLEAR_PLAYLIST);
|
||||||
bool get supportPlay => ((attributes["supported_features"] &
|
bool get supportPlay => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_PLAY) ==
|
MediaPlayerEntity.SUPPORT_PLAY) ==
|
||||||
MediaPlayerEntity.SUPPORT_PLAY);
|
MediaPlayerEntity.SUPPORT_PLAY);
|
||||||
bool get supportShuffleSet => ((attributes["supported_features"] &
|
bool get supportShuffleSet => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_SHUFFLE_SET) ==
|
MediaPlayerEntity.SUPPORT_SHUFFLE_SET) ==
|
||||||
MediaPlayerEntity.SUPPORT_SHUFFLE_SET);
|
MediaPlayerEntity.SUPPORT_SHUFFLE_SET);
|
||||||
bool get supportSelectSoundMode => ((attributes["supported_features"] &
|
bool get supportSelectSoundMode => ((supportedFeatures &
|
||||||
MediaPlayerEntity.SUPPORT_SELECT_SOUND_MODE) ==
|
MediaPlayerEntity.SUPPORT_SELECT_SOUND_MODE) ==
|
||||||
MediaPlayerEntity.SUPPORT_SELECT_SOUND_MODE);
|
MediaPlayerEntity.SUPPORT_SELECT_SOUND_MODE);
|
||||||
|
|
||||||
|
175
lib/entity_widgets/common/camera_stream_view.dart
Normal file
175
lib/entity_widgets/common/camera_stream_view.dart
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
part of '../../main.dart';
|
||||||
|
|
||||||
|
class CameraStreamView extends StatefulWidget {
|
||||||
|
|
||||||
|
CameraStreamView({Key key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_CameraStreamViewState createState() => _CameraStreamViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CameraStreamViewState extends State<CameraStreamView> {
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraEntity _entity;
|
||||||
|
|
||||||
|
http.Client client;
|
||||||
|
http.StreamedResponse response;
|
||||||
|
List<int> binaryImage = [];
|
||||||
|
bool timeToStop = false;
|
||||||
|
Completer streamCompleter;
|
||||||
|
bool started = false;
|
||||||
|
bool useSVG = false;
|
||||||
|
|
||||||
|
void _connect() async {
|
||||||
|
started = true;
|
||||||
|
timeToStop = false;
|
||||||
|
String streamUrl = '$homeAssistantWebHost/api/camera_proxy_stream/${_entity.entityId}?token=${_entity.attributes['access_token']}';
|
||||||
|
client = new http.Client(); // create a client to make api calls
|
||||||
|
http.Request request = new http.Request("GET", Uri.parse(streamUrl)); // create get request
|
||||||
|
Logger.d("[Sending] ==> $streamUrl");
|
||||||
|
response = await client.send(request);
|
||||||
|
Logger.d("[Received] <== ${response.headers}");
|
||||||
|
String frameBoundary = response.headers['content-type'].split('boundary=')[1];
|
||||||
|
final int frameBoundarySize = frameBoundary.length;
|
||||||
|
List<int> primaryBuffer=[];
|
||||||
|
int imageSizeStart = 59;
|
||||||
|
int imageSizeEnd = 0;
|
||||||
|
int imageStart = 0;
|
||||||
|
int imageSize = 0;
|
||||||
|
String strBuffer = "";
|
||||||
|
String contentType = "";
|
||||||
|
streamCompleter = Completer();
|
||||||
|
response.stream.transform(
|
||||||
|
StreamTransformer.fromHandlers(
|
||||||
|
handleData: (data, sink) {
|
||||||
|
primaryBuffer.addAll(data);
|
||||||
|
imageStart = 0;
|
||||||
|
imageSizeEnd = 0;
|
||||||
|
if (primaryBuffer.length >= imageSizeStart + 10) {
|
||||||
|
contentType = utf8.decode(
|
||||||
|
primaryBuffer.sublist(frameBoundarySize+16, imageSizeStart + 10), allowMalformed: true).split("\r\n")[0];
|
||||||
|
useSVG = contentType == "image/svg+xml";
|
||||||
|
imageSizeStart = frameBoundarySize + 16 + contentType.length + 18;
|
||||||
|
for (int i = imageSizeStart; i < primaryBuffer.length - 4; i++) {
|
||||||
|
strBuffer = utf8.decode(
|
||||||
|
primaryBuffer.sublist(i, i + 4), allowMalformed: true);
|
||||||
|
if (strBuffer == "\r\n\r\n") {
|
||||||
|
imageSizeEnd = i;
|
||||||
|
imageStart = i + 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (imageSizeEnd > 0) {
|
||||||
|
imageSize = int.tryParse(utf8.decode(
|
||||||
|
primaryBuffer.sublist(imageSizeStart, imageSizeEnd),
|
||||||
|
allowMalformed: true));
|
||||||
|
//Logger.d("content-length: $imageSize");
|
||||||
|
if (imageSize != null &&
|
||||||
|
primaryBuffer.length >= imageStart + imageSize + 2) {
|
||||||
|
sink.add(
|
||||||
|
primaryBuffer.sublist(
|
||||||
|
imageStart, imageStart + imageSize));
|
||||||
|
primaryBuffer.removeRange(0, imageStart + imageSize + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (timeToStop) {
|
||||||
|
sink?.close();
|
||||||
|
streamCompleter.complete();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleError: (error, stack, sink) {
|
||||||
|
Logger.e("Error parsing MJPEG stream: $error");
|
||||||
|
},
|
||||||
|
handleDone: (sink) {
|
||||||
|
Logger.d("Camera stream finished. Reconnecting...");
|
||||||
|
sink?.close();
|
||||||
|
streamCompleter?.complete();
|
||||||
|
_reconnect();
|
||||||
|
},
|
||||||
|
)
|
||||||
|
).listen((d) {
|
||||||
|
if (!timeToStop) {
|
||||||
|
setState(() {
|
||||||
|
binaryImage = d;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _reconnect() {
|
||||||
|
disconnect().then((_){
|
||||||
|
_connect();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future disconnect() {
|
||||||
|
Completer disconF = Completer();
|
||||||
|
timeToStop = true;
|
||||||
|
if (streamCompleter != null && !streamCompleter.isCompleted) {
|
||||||
|
streamCompleter.future.then((_) {
|
||||||
|
client?.close();
|
||||||
|
disconF.complete();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
client?.close();
|
||||||
|
disconF.complete();
|
||||||
|
}
|
||||||
|
return disconF.future;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (!started) {
|
||||||
|
_entity = EntityModel
|
||||||
|
.of(context)
|
||||||
|
.entityWrapper
|
||||||
|
.entity;
|
||||||
|
_connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (binaryImage.isEmpty) {
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(20.0),
|
||||||
|
child: const CircularProgressIndicator()
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (useSVG) {
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
SvgPicture.memory(
|
||||||
|
Uint8List.fromList(binaryImage),
|
||||||
|
placeholderBuilder: (BuildContext context) =>
|
||||||
|
new Container(
|
||||||
|
padding: const EdgeInsets.all(20.0),
|
||||||
|
child: const CircularProgressIndicator()
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Image.memory(
|
||||||
|
Uint8List.fromList(binaryImage), gaplessPlayback: true),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
disconnect();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
@ -1,115 +0,0 @@
|
|||||||
part of '../../main.dart';
|
|
||||||
|
|
||||||
class CameraControlsWidget extends StatefulWidget {
|
|
||||||
|
|
||||||
final String url;
|
|
||||||
|
|
||||||
CameraControlsWidget({Key key, @required this.url}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_CameraControlsWidgetState createState() => _CameraControlsWidgetState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _CameraControlsWidgetState extends State<CameraControlsWidget> {
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_getData();
|
|
||||||
}
|
|
||||||
|
|
||||||
http.Client client;
|
|
||||||
http.StreamedResponse response;
|
|
||||||
List<int> binaryImage = [];
|
|
||||||
String cameraState = "Connecting...";
|
|
||||||
bool timeToStop = false;
|
|
||||||
Completer streamCompleter;
|
|
||||||
|
|
||||||
void _getData() async {
|
|
||||||
client = new http.Client(); // create a client to make api calls
|
|
||||||
http.Request request = new http.Request("GET", Uri.parse(widget.url)); // create get request
|
|
||||||
Logger.d("[Sending] ==> ${widget.url}");
|
|
||||||
response = await client.send(request);
|
|
||||||
setState(() {
|
|
||||||
cameraState = "Starting...";
|
|
||||||
});
|
|
||||||
Logger.d("[Received] <== ${response.headers}");
|
|
||||||
List<int> primaryBuffer=[];
|
|
||||||
final int imageSizeStart = 59;
|
|
||||||
int imageSizeEnd = 0;
|
|
||||||
int imageStart = 0;
|
|
||||||
int imageSize = 0;
|
|
||||||
String strBuffer = "";
|
|
||||||
streamCompleter = Completer();
|
|
||||||
response.stream.transform(
|
|
||||||
StreamTransformer.fromHandlers(
|
|
||||||
handleData: (data, sink) {
|
|
||||||
primaryBuffer.addAll(data);
|
|
||||||
if (primaryBuffer.length >= 66) {
|
|
||||||
for (int i = imageSizeStart; i < primaryBuffer.length - 4; i++) {
|
|
||||||
strBuffer = utf8.decode(
|
|
||||||
primaryBuffer.sublist(i, i + 4), allowMalformed: true);
|
|
||||||
if (strBuffer == "\r\n\r\n") {
|
|
||||||
imageSizeEnd = i;
|
|
||||||
imageStart = i + 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
imageSize = int.tryParse(utf8.decode(
|
|
||||||
primaryBuffer.sublist(imageSizeStart, imageSizeEnd),
|
|
||||||
allowMalformed: true));
|
|
||||||
if (imageSize != null && primaryBuffer.length >= imageStart + imageSize + 2) {
|
|
||||||
sink.add(
|
|
||||||
primaryBuffer.sublist(imageStart, imageStart + imageSize));
|
|
||||||
primaryBuffer.removeRange(0, imageStart + imageSize + 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (timeToStop) {
|
|
||||||
sink?.close();
|
|
||||||
streamCompleter.complete();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleError: (error, stack, sink) {
|
|
||||||
Logger.e("Error parsing MJPEG stream: $error");
|
|
||||||
},
|
|
||||||
handleDone: (sink) {
|
|
||||||
sink?.close();
|
|
||||||
},
|
|
||||||
)
|
|
||||||
).listen((d) {
|
|
||||||
setState(() {
|
|
||||||
binaryImage = d;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
if (binaryImage.isEmpty) {
|
|
||||||
return Column(
|
|
||||||
children: <Widget>[
|
|
||||||
Text("$cameraState")
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Column(
|
|
||||||
children: <Widget>[
|
|
||||||
Image.memory(Uint8List.fromList(binaryImage), gaplessPlayback: true),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
super.dispose();
|
|
||||||
timeToStop = true;
|
|
||||||
if (streamCompleter != null && !streamCompleter.isCompleted) {
|
|
||||||
streamCompleter.future.then((_) {
|
|
||||||
client?.close();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
client?.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,6 +15,7 @@ import 'package:http/http.dart' as http;
|
|||||||
import 'package:charts_flutter/flutter.dart' as charts;
|
import 'package:charts_flutter/flutter.dart' as charts;
|
||||||
import 'package:progress_indicators/progress_indicators.dart';
|
import 'package:progress_indicators/progress_indicators.dart';
|
||||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
|
||||||
part 'entity_class/const.dart';
|
part 'entity_class/const.dart';
|
||||||
part 'entity_class/entity.class.dart';
|
part 'entity_class/entity.class.dart';
|
||||||
@ -50,6 +51,7 @@ part 'entity_widgets/common/mode_selector.dart';
|
|||||||
part 'entity_widgets/common/universal_slider.dart';
|
part 'entity_widgets/common/universal_slider.dart';
|
||||||
part 'entity_widgets/common/flat_service_button.dart';
|
part 'entity_widgets/common/flat_service_button.dart';
|
||||||
part 'entity_widgets/common/light_color_picker.dart';
|
part 'entity_widgets/common/light_color_picker.dart';
|
||||||
|
part 'entity_widgets/common/camera_stream_view.dart';
|
||||||
part 'entity_widgets/entity_colors.class.dart';
|
part 'entity_widgets/entity_colors.class.dart';
|
||||||
part 'entity_widgets/entity_page_container.dart';
|
part 'entity_widgets/entity_page_container.dart';
|
||||||
part 'entity_widgets/history_chart/entity_history.dart';
|
part 'entity_widgets/history_chart/entity_history.dart';
|
||||||
@ -73,7 +75,6 @@ part 'entity_widgets/controls/light_controls.dart';
|
|||||||
part 'entity_widgets/controls/media_player_widgets.dart';
|
part 'entity_widgets/controls/media_player_widgets.dart';
|
||||||
part 'entity_widgets/controls/fan_controls.dart';
|
part 'entity_widgets/controls/fan_controls.dart';
|
||||||
part 'entity_widgets/controls/alarm_control_panel_controls.dart';
|
part 'entity_widgets/controls/alarm_control_panel_controls.dart';
|
||||||
part 'entity_widgets/controls/camera_controls.dart';
|
|
||||||
part 'settings.page.dart';
|
part 'settings.page.dart';
|
||||||
part 'configuration.page.dart';
|
part 'configuration.page.dart';
|
||||||
part 'home_assistant.class.dart';
|
part 'home_assistant.class.dart';
|
||||||
@ -93,8 +94,7 @@ part 'ui_widgets/card_header_widget.dart';
|
|||||||
|
|
||||||
EventBus eventBus = new EventBus();
|
EventBus eventBus = new EventBus();
|
||||||
const String appName = "HA Client";
|
const String appName = "HA Client";
|
||||||
const appVersion = "0.4.0";
|
const appVersion = "0.4.4";
|
||||||
const appBuild = "91";
|
|
||||||
|
|
||||||
String homeAssistantWebHost;
|
String homeAssistantWebHost;
|
||||||
|
|
||||||
@ -383,8 +383,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
applicationName: appName,
|
applicationName: appName,
|
||||||
applicationVersion: appVersion,
|
applicationVersion: appVersion
|
||||||
applicationLegalese: "build $appBuild",
|
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
45
pubspec.lock
45
pubspec.lock
@ -35,7 +35,7 @@ packages:
|
|||||||
name: cached_network_image
|
name: cached_network_image
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.0-alpha.2"
|
version: "0.6.0+1"
|
||||||
charcode:
|
charcode:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -49,14 +49,14 @@ packages:
|
|||||||
name: charts_common
|
name: charts_common
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.0"
|
version: "0.6.0"
|
||||||
charts_flutter:
|
charts_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: charts_flutter
|
name: charts_flutter
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.0"
|
version: "0.6.0"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -100,7 +100,7 @@ packages:
|
|||||||
name: event_bus
|
name: event_bus
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.3"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -112,7 +112,7 @@ packages:
|
|||||||
name: flutter_cache_manager
|
name: flutter_cache_manager
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.0-beta.2+1"
|
version: "0.3.0"
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -127,6 +127,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.2.0"
|
||||||
|
flutter_svg:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_svg
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.10.3"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -195,13 +202,27 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.6.2"
|
version: "1.6.2"
|
||||||
|
path_drawing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_drawing
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.0"
|
||||||
|
path_parsing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_parsing
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.3"
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.1"
|
version: "0.5.0+1"
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -248,7 +269,7 @@ packages:
|
|||||||
name: sqflite
|
name: sqflite
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.2+1"
|
version: "1.1.0+1"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -276,7 +297,7 @@ packages:
|
|||||||
name: synchronized
|
name: synchronized
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.3+2"
|
version: "2.0.2+1"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -311,7 +332,7 @@ packages:
|
|||||||
name: uuid
|
name: uuid
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.3"
|
version: "2.0.0"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -332,7 +353,7 @@ packages:
|
|||||||
name: xml
|
name: xml
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.3.1"
|
version: "3.2.5"
|
||||||
yaml:
|
yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -341,5 +362,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.15"
|
version: "2.1.15"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.0.0 <3.0.0"
|
dart: ">=2.1.0 <3.0.0"
|
||||||
flutter: ">=0.5.6 <2.0.0"
|
flutter: ">=0.7.3 <2.0.0"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
name: hass_client
|
name: hass_client
|
||||||
description: Home Assistant Android Client
|
description: Home Assistant Android Client
|
||||||
|
|
||||||
version: 0.4.0+91
|
version: 0.4.4+95
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
||||||
@ -18,6 +18,7 @@ dependencies:
|
|||||||
date_format: any
|
date_format: any
|
||||||
charts_flutter: any
|
charts_flutter: any
|
||||||
flutter_markdown: any
|
flutter_markdown: any
|
||||||
|
flutter_svg: ^0.10.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Reference in New Issue
Block a user