diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Buttons/AC.dart | 124 | ||||
-rw-r--r-- | lib/Buttons/ac_on_face.dart | 145 | ||||
-rw-r--r-- | lib/Buttons/ac_on_foot.dart | 146 | ||||
-rw-r--r-- | lib/Buttons/auto.dart | 116 | ||||
-rw-r--r-- | lib/Buttons/defrost_recirculate.dart | 178 | ||||
-rw-r--r-- | lib/Buttons/fresh_air.dart | 110 | ||||
-rw-r--r-- | lib/config.dart | 111 | ||||
-rw-r--r-- | lib/home_page.dart | 181 | ||||
-rw-r--r-- | lib/kuksa-server/intial_connection.dart | 44 | ||||
-rw-r--r-- | lib/kuksa-server/on_boarding_page.dart | 65 | ||||
-rw-r--r-- | lib/kuksa-server/vehicle-class.dart | 53 | ||||
-rw-r--r-- | lib/kuksa-server/vehicle-provider.dart | 47 | ||||
-rw-r--r-- | lib/kuksa-server/vehicle_config.dart | 39 | ||||
-rw-r--r-- | lib/kuksa-server/vehicle_methods.dart | 97 | ||||
-rw-r--r-- | lib/kuksa-server/vehicle_server_path.dart | 36 | ||||
-rw-r--r-- | lib/main.dart | 23 | ||||
-rw-r--r-- | lib/provider.dart | 37 | ||||
-rw-r--r-- | lib/size.dart | 50 | ||||
-rw-r--r-- | lib/slider/Climate_slider.dart | 38 | ||||
-rw-r--r-- | lib/slider/Right_climate_slider.dart | 36 | ||||
-rw-r--r-- | lib/slider/slider.dart | 44 | ||||
-rw-r--r-- | lib/widgets/Right_climate.dart | 115 | ||||
-rw-r--r-- | lib/widgets/left_climate.dart | 112 |
23 files changed, 1947 insertions, 0 deletions
diff --git a/lib/Buttons/AC.dart b/lib/Buttons/AC.dart new file mode 100644 index 0000000..e0c610a --- /dev/null +++ b/lib/Buttons/AC.dart @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle-provider.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle_methods.dart'; + +import '../size.dart'; + +class AC extends ConsumerStatefulWidget { + WebSocket socket; + String serverPath; + AC({ + Key? key, + required this.serverPath, + required this.socket, + }) : super(key: key); + + @override + _ACState createState() => _ACState(); +} + +class _ACState extends ConsumerState<AC> with SingleTickerProviderStateMixin { + late AnimationController _controller; + late bool isAcActive; + late Animation<Color?> _colorAnimation; + + @override + void initState() { + super.initState(); + + _controller = AnimationController( + duration: Duration(milliseconds: 500), + vsync: this, + ); + + _colorAnimation = + ColorTween(begin: Colors.lightBlueAccent, end: Colors.green) + .animate(_controller); + + _controller.addListener(() { + + }); + + _controller.addStatusListener((status) { + if (status == AnimationStatus.completed) { + VISS.set(widget.socket, ref,widget.serverPath, isAcActive.toString()); + } + if (status == AnimationStatus.dismissed) { + VISS.set(widget.socket, ref,widget.serverPath, isAcActive.toString()); + } + }); + } + + // dismiss the animation when widget exits screen + @override + void dispose() { + super.dispose(); + _controller.dispose(); + } + + @override + Widget build(BuildContext context) { + isAcActive = ref.watch(vehicleProvider).isAcActive; + return AnimatedBuilder( + animation: _controller, + builder: (BuildContext context, _) { + return InkWell( + child: AnimatedContainer( + constraints: BoxConstraints( + maxHeight: SizeConfig.screenHeight*0.10, + maxWidth: SizeConfig.screenWidth*0.15, + ), + + + decoration: BoxDecoration( + gradient: isAcActive + ? RadialGradient( + colors: [Colors.black, Colors.lightBlue], + radius: 2, + ) + : null, + + + border: Border.all( + color: Colors.white, + width: 2, + ), + borderRadius: BorderRadius.circular(SizeConfig.blockSizeVertical*2), + ), + duration: Duration(seconds: 1), + child: AnimatedContainer( + duration: Duration(milliseconds: 100), + margin: EdgeInsets.all(SizeConfig.blockSizeVertical*2), + child: Container( + width: SizeConfig.screenWidth*0.15, + height: SizeConfig.screenHeight*0.10, + child: FittedBox( + fit: BoxFit.fill, + child: Text( + 'A/C', + style: TextStyle( + color: _colorAnimation.value, + fontWeight: FontWeight.w700, + + ), + ), + ), + ), + ), + ), + onTap: () { + isAcActive ? _controller.reverse() : _controller.forward(); + ref + .read(vehicleProvider.notifier) + .update(isAcActive: !isAcActive); + }, + ); + + }); + } +} diff --git a/lib/Buttons/ac_on_face.dart b/lib/Buttons/ac_on_face.dart new file mode 100644 index 0000000..f0c0f41 --- /dev/null +++ b/lib/Buttons/ac_on_face.dart @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg_provider/flutter_svg_provider.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle-provider.dart'; + +import '../kuksa-server/vehicle-class.dart'; +import '../kuksa-server/vehicle_methods.dart'; +import '../size.dart'; + +class AcOnFace extends ConsumerStatefulWidget { + final String img; + WebSocket socket; + AcOnFace({ + Key? key, + required this.img, + required this.socket, + }) : super(key: key); + + @override + _AcOnFaceState createState() => _AcOnFaceState(); +} + +class _AcOnFaceState extends ConsumerState<AcOnFace> + with SingleTickerProviderStateMixin { + late AnimationController _controller; + late Animation<Color?> _colorAnimation; + + @override + void initState() { + super.initState(); + + _controller = AnimationController( + duration: Duration(milliseconds: 500), + vsync: this, + ); + + _colorAnimation = + ColorTween(begin: Colors.lightBlueAccent, end: Colors.green) + .animate(_controller); + + _controller.addListener(() {}); + + _controller.addStatusListener((status) { + if (status == AnimationStatus.completed) { + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row1.Left.AirDistribution", 'up'); + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row1.Right.AirDistribution", 'up'); + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row2.Left.AirDistribution", 'up'); + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row2.Right.AirDistribution", 'up'); + } + + if (status == AnimationStatus.dismissed) { + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row1.Left.AirDistribution", 'middle'); + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row1.Right.AirDistribution", 'middle'); + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row2.Left.AirDistribution", 'middle'); + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row2.Right.AirDistribution", 'middle'); + } + }); + } + + // dismiss the animation when widget exits screen + @override + void dispose() { + super.dispose(); + _controller.dispose(); + } + + @override + Widget build(BuildContext context) { + vehicle vehicledata = ref.watch(vehicleProvider); + if (vehicledata.isAcDirectionUp == false) { + _controller.reverse(); + } + + return AnimatedBuilder( + animation: _controller, + builder: (BuildContext context, _) { + return InkWell( + child: AnimatedContainer( + constraints: BoxConstraints( + maxHeight: SizeConfig.screenHeight*0.10, + maxWidth: SizeConfig.screenWidth*0.15, + ), + + + decoration: BoxDecoration( + gradient: vehicledata.isAcDirectionUp + ? RadialGradient( + colors: [Colors.black, Colors.lightBlue], + radius: 2, + ) + : null, + + + border: Border.all( + color: Colors.white, + width: 2, + ), + borderRadius: BorderRadius.circular(SizeConfig.safeBlockVertical*2), + ), + duration: const Duration(milliseconds: 500), + child: AnimatedContainer( + duration: Duration(milliseconds: 100), + margin: const EdgeInsets.all(10), + child: Image( + width: SizeConfig.screenWidth*0.15, + height: SizeConfig.screenHeight*0.10, + image: Svg(widget.img), + color: _colorAnimation.value, + ), + ), + ), + onTap: () { + if (vehicledata.isAcDirectionDown) { + ref + .watch(vehicleProvider.notifier) + .update(isAcDirectionDown: !vehicledata.isAcDirectionDown); + } + Future.delayed(Duration(milliseconds: 500),(){ + vehicledata.isAcDirectionUp + ? _controller.reverse() + : _controller.forward(); + + ref.watch(vehicleProvider.notifier).update( + isAcDirectionUp: !vehicledata.isAcDirectionUp, + ); + }); + + }, + ); + + }); + } +} diff --git a/lib/Buttons/ac_on_foot.dart b/lib/Buttons/ac_on_foot.dart new file mode 100644 index 0000000..41e2569 --- /dev/null +++ b/lib/Buttons/ac_on_foot.dart @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg_provider/flutter_svg_provider.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle-provider.dart'; + +import '../kuksa-server/vehicle-class.dart'; +import '../kuksa-server/vehicle_methods.dart'; +import '../size.dart'; + +class AcOnFoot extends ConsumerStatefulWidget { + final String img; + WebSocket socket; + AcOnFoot({ + Key? key, + required this.img, + required this.socket, + }) : super(key: key); + + @override + _AcOnFootState createState() => _AcOnFootState(); +} + +class _AcOnFootState extends ConsumerState<AcOnFoot> + with SingleTickerProviderStateMixin { + late AnimationController _controller; + late Animation<Color?> _colorAnimation; + + @override + void initState() { + super.initState(); + + _controller = AnimationController( + duration: Duration(milliseconds: 500), + vsync: this, + ); + + _colorAnimation = + ColorTween(begin: Colors.lightBlueAccent, end: Colors.green) + .animate(_controller); + + _controller.addListener(() {}); + + _controller.addStatusListener((status) { + if (status == AnimationStatus.completed) { + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row1.Left.AirDistribution", 'down'); + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row1.Right.AirDistribution", 'down'); + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row2.Left.AirDistribution", 'down'); + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row2.Right.AirDistribution", 'down'); + + } + + if (status == AnimationStatus.dismissed) { + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row1.Left.AirDistribution", 'middle'); + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row1.Right.AirDistribution", 'middle'); + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row2.Left.AirDistribution", 'middle'); + VISS.set(widget.socket,ref, + "Vehicle.Cabin.HVAC.Station.Row2.Right.AirDistribution", 'middle'); + } + }); + } + + // dismiss the animation when widget exits screen + @override + void dispose() { + super.dispose(); + _controller.dispose(); + } + + @override + Widget build(BuildContext context) { + vehicle vehicledata = ref.watch(vehicleProvider); + if (vehicledata.isAcDirectionDown == false) { + _controller.reverse(); + } + + return AnimatedBuilder( + animation: _controller, + builder: (BuildContext context, _) { + return InkWell( + child: AnimatedContainer( + constraints: BoxConstraints( + maxHeight: SizeConfig.screenHeight*0.10, + maxWidth: SizeConfig.screenWidth*0.15, + ), + + + decoration: BoxDecoration( + gradient: vehicledata.isAcDirectionDown + ? RadialGradient( + colors: [Colors.black, Colors.lightBlue], + radius: 2, + ) + : null, + + + border: Border.all( + color: Colors.white, + width: 2, + ), + borderRadius: BorderRadius.circular(SizeConfig.safeBlockVertical*2), + ), + duration: const Duration(milliseconds: 500), + child: AnimatedContainer( + duration: Duration(milliseconds: 100), + margin: const EdgeInsets.all(10), + child: Image( + width: SizeConfig.screenWidth*0.15, + height: SizeConfig.screenHeight*0.10, + image: Svg(widget.img), + color: _colorAnimation.value, + ), + ), + ), + onTap: () { + if (vehicledata.isAcDirectionUp == true) { + ref + .watch(vehicleProvider.notifier) + .update(isAcDirectionUp: !vehicledata.isAcDirectionUp); + } + Future.delayed(Duration(milliseconds: 500),(){ + vehicledata.isAcDirectionDown + ? _controller.reverse() + : _controller.forward(); + + ref.watch(vehicleProvider.notifier).update( + isAcDirectionDown: !vehicledata.isAcDirectionDown, + ); + }); + + }, + ); + + }); + } +} diff --git a/lib/Buttons/auto.dart b/lib/Buttons/auto.dart new file mode 100644 index 0000000..536a117 --- /dev/null +++ b/lib/Buttons/auto.dart @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle-provider.dart'; + +import '../size.dart'; + +class Auto extends ConsumerStatefulWidget { + WebSocket socket; + String serverPath; + Auto({ + Key? key, + required this.serverPath, + required this.socket, + }) : super(key: key); + + @override + _AutoState createState() => _AutoState(); +} + +class _AutoState extends ConsumerState<Auto> with SingleTickerProviderStateMixin { + late AnimationController _controller; + late bool isAutoActive; + late Animation<Color?> _colorAnimation; + + @override + void initState() { + super.initState(); + + _controller = AnimationController( + duration: Duration(milliseconds: 500), + vsync: this, + ); + + _colorAnimation = + ColorTween(begin: Colors.lightBlueAccent, end: Colors.green) + .animate(_controller); + + _controller.addListener(() { + + }); + + + } + + // dismiss the animation when widget exits screen + @override + void dispose() { + super.dispose(); + _controller.dispose(); + } + + @override + Widget build(BuildContext context) { + isAutoActive = ref.watch(vehicleProvider).isAutoActive; + return AnimatedBuilder( + animation: _controller, + builder: (BuildContext context, _) { + return InkWell( + child: AnimatedContainer( + constraints: BoxConstraints( + maxHeight: SizeConfig.screenHeight*0.10, + maxWidth: SizeConfig.screenWidth*0.15, + ), + + + decoration: BoxDecoration( + gradient: isAutoActive + ? RadialGradient( + colors: [Colors.black, Colors.lightBlue], + radius: 2, + ) + : null, + + + border: Border.all( + color: Colors.white, + width: 2, + ), + borderRadius: BorderRadius.circular(SizeConfig.safeBlockVertical*2), + ), + duration: Duration(seconds: 1), + child: AnimatedContainer( + duration: Duration(milliseconds: 100), + margin: EdgeInsets.all(SizeConfig.blockSizeVertical*2), + child: Container( + width: SizeConfig.screenWidth*0.15, + height: SizeConfig.screenHeight*0.10, + child: FittedBox( + fit: BoxFit.fill, + child: Text( + 'AUTO', + style: TextStyle( + color: _colorAnimation.value, + fontWeight: FontWeight.w700, + // fontSize: SizeConfig.fontsize*4, + ), + ), + ), + ), + ), + ), + onTap: () { + isAutoActive ? _controller.reverse() : _controller.forward(); + ref + .read(vehicleProvider.notifier) + .update(isAutoActive: !isAutoActive); + }, + ); + + }); + } +} diff --git a/lib/Buttons/defrost_recirculate.dart b/lib/Buttons/defrost_recirculate.dart new file mode 100644 index 0000000..30ac40d --- /dev/null +++ b/lib/Buttons/defrost_recirculate.dart @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg_provider/flutter_svg_provider.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle-class.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle-provider.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle_methods.dart'; +import 'package:flutter_hvac/size.dart'; + +class CaustomButton extends ConsumerStatefulWidget { + WebSocket socket; + String serverPath; + String img; + String type; + CaustomButton({ + Key? key, + required this.serverPath, + required this.socket, + required this.img, + required this.type, + }) : super(key: key); + + @override + _CaustomButtonState createState() => _CaustomButtonState(); +} + +class _CaustomButtonState extends ConsumerState<CaustomButton> + with SingleTickerProviderStateMixin { + late AnimationController _controller; + late vehicle vehicledata; + late Animation<Color?> _colorAnimation; + + @override + void initState() { + super.initState(); + + _controller = AnimationController( + duration: Duration(milliseconds: 500), + vsync: this, + ); + + _colorAnimation = + ColorTween(begin: Colors.blue, end: Colors.green) + .animate(_controller); + + _controller.addListener(() { + + }); + + _controller.addStatusListener((status) { + if (status == AnimationStatus.completed) { + if (widget.type == 'Front_defrost') { + VISS.set(widget.socket,ref, widget.serverPath, + vehicledata.isFrontDefrosterActive.toString()); + } + if (widget.type == "Rear_defrost") { + VISS.set(widget.socket,ref, widget.serverPath, + vehicledata.isRearDefrosterActive.toString()); + } + if (widget.type == "Recirculation") { + VISS.set(widget.socket,ref, widget.serverPath, + vehicledata.isRecirculationActive.toString()); + } + + + + } + if (status == AnimationStatus.dismissed) { + if (widget.type == 'Front_defrost') { + VISS.set(widget.socket, ref,widget.serverPath, + vehicledata.isFrontDefrosterActive.toString()); + } + if (widget.type == "Rear_defrost") { + VISS.set(widget.socket, ref,widget.serverPath, + vehicledata.isRearDefrosterActive.toString()); + } + if (widget.type == "Recirculation") { + VISS.set(widget.socket, ref,widget.serverPath, + vehicledata.isRecirculationActive.toString()); + } + } + }); + } + + // dismiss the animation when widget exits screen + @override + void dispose() { + super.dispose(); + _controller.dispose(); + } + + @override + Widget build(BuildContext context) { + vehicledata = ref.watch(vehicleProvider); + return AnimatedBuilder( + animation: _controller, + builder: (BuildContext context, _) { + return InkWell( + child: AnimatedContainer( + constraints: BoxConstraints( + maxHeight: SizeConfig.screenHeight*0.10, + maxWidth: SizeConfig.screenWidth*0.15, + ), + + + decoration: BoxDecoration( + gradient: widget.type == "Front_defrost" + ? vehicledata.isFrontDefrosterActive + ? RadialGradient( + colors: [Colors.black, Colors.lightBlue], + radius: 2, + ) + : null + : widget.type == "Rear_defrost" + ? vehicledata.isRearDefrosterActive + ? RadialGradient( + colors: [Colors.black, Colors.lightBlue], + radius: 2, + ) + : null + : vehicledata.isRecirculationActive + ? RadialGradient( + colors: [Colors.black, Colors.lightBlue], + radius: 2, + ) + : null, + + + border: Border.all( + color: Colors.white, + width: 2, + ), + borderRadius: BorderRadius.circular(SizeConfig.safeBlockVertical*2), + ), + duration: Duration(milliseconds: 100), + child: AnimatedContainer( + duration: Duration(milliseconds: 100), + margin: EdgeInsets.all(SizeConfig.blockSizeVertical), + child: Image( + width: SizeConfig.screenWidth*0.15, + height: SizeConfig.screenHeight*0.10, + image: Svg(widget.img), + color: _colorAnimation.value, + ), + ), + ), + onTap: () { + if (widget.type == "Front_defrost") { + vehicledata.isFrontDefrosterActive + ? _controller.reverse() + : _controller.forward(); + ref.read(vehicleProvider.notifier).update( + isFrontDefrosterActive: + !vehicledata.isFrontDefrosterActive); + } + if (widget.type == "Rear_defrost") { + vehicledata.isRearDefrosterActive + ? _controller.reverse() + : _controller.forward(); + ref.read(vehicleProvider.notifier).update( + isRearDefrosterActive: !vehicledata.isRearDefrosterActive); + } + if (widget.type == "Recirculation") { + vehicledata.isRecirculationActive + ? _controller.reverse() + : _controller.forward(); + ref.read(vehicleProvider.notifier).update( + isRecirculationActive: !vehicledata.isRecirculationActive); + } + }, + ); + + }); + } +} diff --git a/lib/Buttons/fresh_air.dart b/lib/Buttons/fresh_air.dart new file mode 100644 index 0000000..3858cba --- /dev/null +++ b/lib/Buttons/fresh_air.dart @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg_provider/flutter_svg_provider.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle-provider.dart'; + +import '../size.dart'; + +class FreshAir extends ConsumerStatefulWidget { + WebSocket socket; + String serverPath; + String img; + FreshAir({ + Key? key, + required this.serverPath, + required this.socket, + required this.img, + }) : super(key: key); + + @override + _FreshAirState createState() => _FreshAirState(); +} + +class _FreshAirState extends ConsumerState<FreshAir> with SingleTickerProviderStateMixin { + late AnimationController _controller; + late bool isFreshAirCirculateActive; + late Animation<Color?> _colorAnimation; + + @override + void initState() { + super.initState(); + + _controller = AnimationController( + duration: Duration(milliseconds: 500), + vsync: this, + ); + + _colorAnimation = + ColorTween(begin: Colors.lightBlueAccent, end: Colors.green) + .animate(_controller); + + _controller.addListener(() { + + }); + + + } + + // dismiss the animation when widget exits screen + @override + void dispose() { + super.dispose(); + _controller.dispose(); + } + + @override + Widget build(BuildContext context) { + isFreshAirCirculateActive = ref.watch(vehicleProvider).isFreshAirCirculateActive; + return AnimatedBuilder( + animation: _controller, + builder: (BuildContext context, _) { + return InkWell( + child: AnimatedContainer( + constraints: BoxConstraints( + maxHeight: SizeConfig.screenHeight*0.10, + maxWidth: SizeConfig.screenWidth*0.15, + ), + + + decoration: BoxDecoration( + gradient: isFreshAirCirculateActive + ? RadialGradient( + colors: [Colors.black, Colors.lightBlue], + radius: 2, + ) + : null, + + // color: _colorAnimation2.value, + border: Border.all( + color: Colors.white, + width: 2, + ), + borderRadius: BorderRadius.circular(SizeConfig.safeBlockVertical*2), + ), + duration: const Duration(milliseconds: 500), + child: AnimatedContainer( + duration: Duration(milliseconds: 100), + margin: const EdgeInsets.all(10), + child: Image( + width: SizeConfig.screenWidth*0.15, + height: SizeConfig.screenHeight*0.10, + image: Svg(widget.img), + color: _colorAnimation.value, + ), + ), + ), + onTap: () { + isFreshAirCirculateActive ? _controller.reverse() : _controller.forward(); + ref + .read(vehicleProvider.notifier) + .update(isFreshAirCirculateActive: !isFreshAirCirculateActive); + }, + ); + + }); + } +} diff --git a/lib/config.dart b/lib/config.dart new file mode 100644 index 0000000..db7266e --- /dev/null +++ b/lib/config.dart @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:flutter_hvac/kuksa-server/intial_connection.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:yaml/yaml.dart'; + + +class GetConfig extends ConsumerStatefulWidget { + const GetConfig({Key? key, required this.client}) : super(key: key); + final HttpClient client; + + @override + ConsumerState<GetConfig> createState() => _GetConfigState(); +} + +class _GetConfigState extends ConsumerState<GetConfig> { + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + final configStateProvider = ref.read(ConfigStateprovider.notifier); + + String configFilePath = '/etc/xdg/AGL/HVAC_config.yaml'; + + + final configFile = File(configFilePath); + configFile.readAsString().then((content) { + final dynamic yamlMap = loadYaml(content); + configStateProvider.update( + hostname: yamlMap['hostname'], + port: yamlMap['port'], + kuksaAuthToken: yamlMap['kuskaAuthToken'], + ); + }); + }); + } + + @override + Widget build(BuildContext context) { + final config = ref.watch(ConfigStateprovider); + if (config.hostname == "" || + config.port == 0 || + config.kuksaAuthToken == "" + ) { + return Scaffold( + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: const [ + Text("ERROR", + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), + Text( + "Something Wrong with config file! Check config.yaml file and restart"), + ], + )), + ); + } + return InitialScreen(client: widget.client); + } +} + +class Config { + Config({ + required this.hostname, + required this.port, + required this.kuksaAuthToken, + + }); + final String hostname; + final int port; + final String kuksaAuthToken; + + Config copywith({ + String? hostname, + int? port, + String? kuksaAuthToken, + String? mapboxAccessToken, + }) => + Config( + hostname: hostname ?? this.hostname, + port: port ?? this.port, + kuksaAuthToken: kuksaAuthToken ?? this.kuksaAuthToken, + ); +} + +final ConfigStateprovider = +StateNotifierProvider<ConfigStateNotifier, Config>( + (ref) => ConfigStateNotifier()); + +class ConfigStateNotifier extends StateNotifier<Config> { + ConfigStateNotifier() : super(_initialValue); + static final Config _initialValue = Config( + hostname: "", + port: 0, + kuksaAuthToken: "", + ); + void update({ + String? hostname, + int? port, + String? kuksaAuthToken, + }) { + state = state.copywith( + hostname: hostname, + port: port, + kuksaAuthToken: kuksaAuthToken, + ); + } +} diff --git a/lib/home_page.dart b/lib/home_page.dart new file mode 100644 index 0000000..481fef0 --- /dev/null +++ b/lib/home_page.dart @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: Apache-2.0 + + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_hvac/Buttons/fresh_air.dart'; +import 'package:flutter_svg_provider/flutter_svg_provider.dart'; +import 'package:flutter_hvac/Buttons/AC.dart'; +import 'package:flutter_hvac/Buttons/ac_on_face.dart'; +import 'package:flutter_hvac/Buttons/ac_on_foot.dart'; +import 'package:flutter_hvac/Buttons/defrost_recirculate.dart'; +import 'package:flutter_hvac/size.dart'; +import 'package:flutter_hvac/slider/Climate_slider.dart'; +import 'package:flutter_hvac/slider/Right_climate_slider.dart'; + +import 'Buttons/auto.dart'; +import 'widgets/Right_climate.dart'; +import 'widgets/left_climate.dart'; +import 'slider/slider.dart'; + +class MyHome_Page extends StatelessWidget { + final WebSocket socket; + MyHome_Page({Key? key, required this.socket}) : super(key: key); + + @override + Widget build(BuildContext context) { + SizeConfig().init(context); + + return Scaffold( + backgroundColor: Colors.black54, + body: Flex(direction: Axis.vertical, + children: [ + Flexible( + flex: 4, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Row( + children: [ + + ClimateSliderControlLeft(), + SizedBox(width: SizeConfig.blockSizeHorizontal*4,), + + + Column( + children: [ + Text( + 'L CLIMATE', + style: TextStyle( + fontSize: SizeConfig.fontsize*4, + fontWeight: FontWeight.w700, + color: Colors.lightBlueAccent, + ), + ), + + SizedBox( + height: SizeConfig.screenHeight/10, + width: SizeConfig.screenWidth/10, + child: Image.asset('images/left_climate.PNG')), + + ScrollContainerLeft( + socket: socket, + ), + ], + ), + + + ], + ), + Row( + // mainAxisAlignment: MainAxisAlignment.end, + children: [ + + Column( + children: [ + Text( + 'R CLIMATE', + style: TextStyle( + fontSize: SizeConfig.fontsize*4, + fontWeight: FontWeight.w700, + color: Colors.lightBlueAccent, + ), + ), + SizedBox( + height: SizeConfig.screenHeight/10, + width: SizeConfig.screenWidth/10, + child: Image.asset('images/right_climate.PNG')), + + ScrollContainerRight( + socket: socket, + ), + ], + ), + SizedBox(width: SizeConfig.blockSizeHorizontal*4,), + + ClimateSliderControlRight(), + ], + ), + + ], + )), + Flexible( + flex: 2, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image( + width: SizeConfig.screenWidth*0.20, + height: SizeConfig.screenHeight*0.25, + image: Svg('images/fan.svg'), + color: Colors.lightBlueAccent, + ), + SliderControl( + socket: socket, + ) + ], + )), + Flexible( + flex: 3, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + AC( + socket: socket, + serverPath: 'Vehicle.Cabin.HVAC.IsAirConditioningActive'), + SizedBox(height: SizeConfig.safeBlockVertical,), + + AcOnFoot( + img: 'images/ac_on_foot.svg', + socket: socket, + ), + SizedBox(height: SizeConfig.safeBlockVertical,), + + AcOnFace( + img: 'images/ac_on_face.svg', + socket: socket, + ), + ], + ), + Row( + children: [ + Auto(serverPath: '', socket: socket), + SizedBox(width: SizeConfig.safeBlockHorizontal,), + FreshAir(serverPath: '', socket: socket, img: 'images/wind_in.svg'), + ], + ), + Column( + children: [ + CaustomButton( + serverPath: 'Vehicle.Cabin.HVAC.IsRecirculationActive', + socket: socket, + img: 'images/in_out.svg', + type: 'Recirculation'), + SizedBox(height: SizeConfig.safeBlockVertical,), + CaustomButton( + serverPath: 'Vehicle.Cabin.HVAC.IsRearDefrosterActive', + socket: socket, + img: 'images/rear_ws.svg', + type: 'Rear_defrost'), + SizedBox(height: SizeConfig.safeBlockVertical,), + + CaustomButton( + serverPath: 'Vehicle.Cabin.HVAC.IsFrontDefrosterActive', + socket: socket, + img: 'images/wind_shield.svg', + type: 'Front_defrost'), + ], + ), + ], + )), + ], + + + ), + ); + } +} diff --git a/lib/kuksa-server/intial_connection.dart b/lib/kuksa-server/intial_connection.dart new file mode 100644 index 0000000..0ba4e9f --- /dev/null +++ b/lib/kuksa-server/intial_connection.dart @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle_config.dart'; + +import 'on_boarding_page.dart'; + +class InitialScreen extends ConsumerWidget { + InitialScreen({Key? key, required this.client}) : super(key: key); + final HttpClient client; + late WebSocket socket; + + @override + Widget build(BuildContext context, ref) { + final sockConnect = ref.watch(sockConnectprovider(client)); + + return sockConnect.when( + data: (socket) { + this.socket = socket; + this.socket.pingInterval = const Duration(seconds: 2); + return OnBoardingPage(client: client, socket: this.socket); + }, + error: (e, stk) { + print(e); + ref.refresh(sockConnectprovider(client)); + return const Scaffold( + backgroundColor: Colors.black, + body: Center( + child: Text( + 'error', + style: TextStyle(color: Colors.white), + )), + ); + }, + loading: () => const Scaffold( + backgroundColor: Colors.black, + body: Center( + child: Text('loading', style: TextStyle(color: Colors.white))), + ), + ); + } +} diff --git a/lib/kuksa-server/on_boarding_page.dart b/lib/kuksa-server/on_boarding_page.dart new file mode 100644 index 0000000..a14145c --- /dev/null +++ b/lib/kuksa-server/on_boarding_page.dart @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:async'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle_config.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle_methods.dart'; + +import '../home_page.dart'; + +class OnBoardingPage extends ConsumerStatefulWidget { + const OnBoardingPage({Key? key, required this.client, required this.socket}) + : super(key: key); + final WebSocket socket; + final HttpClient client; + + @override + ConsumerState<OnBoardingPage> createState() => _OnBoardingPageState(); +} + +class _OnBoardingPageState extends ConsumerState<OnBoardingPage> { + late Timer _timer; + late WebSocket _socket; + + + @override + void initState() { + super.initState(); + _socket = widget.socket; + VISS.init(widget.socket,ref); + _timer = Timer.periodic(const Duration(seconds: 2), (timer) { + + if (widget.socket.readyState == 3) { + ref.refresh(sockConnectprovider(widget.client)); + } + }); + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + widget.socket.listen( + (data) { + + }, + onError: (e, stk) { + print(e.toString()); + ref.refresh(sockConnectprovider(widget.client)); + }, + ); + }); + } + + @override + void dispose() { + super.dispose(); + _timer.cancel(); + widget.socket.close(786887, "Connection lost with server!"); + } + + @override + Widget build(BuildContext context) { + return MyHome_Page( + socket: _socket, + ); + } +} diff --git a/lib/kuksa-server/vehicle-class.dart b/lib/kuksa-server/vehicle-class.dart new file mode 100644 index 0000000..a04ad90 --- /dev/null +++ b/lib/kuksa-server/vehicle-class.dart @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: Apache-2.0 + +class vehicle { + late bool isAcActive; + late bool isFrontDefrosterActive; + late bool isRearDefrosterActive; + late bool isAcDirectionUp; + late bool isAcDirectionDown; + late bool isAcDirectionMiddle; + late bool isRecirculationActive; + late bool isAutoActive; + late bool isFreshAirCirculateActive; + + vehicle({ + required this.isAcActive, + required this.isAcDirectionDown, + required this.isAcDirectionMiddle, + required this.isAcDirectionUp, + required this.isFrontDefrosterActive, + required this.isRearDefrosterActive, + required this.isRecirculationActive, + required this.isAutoActive, + required this.isFreshAirCirculateActive, + }); + + vehicle copywith({ + bool? isAcActive, + bool? isAcDirectionDown, + bool? isAcDirectionMiddle, + bool? isAcDirectionUp, + bool? isFrontDefrosterActive, + bool? isRearDefrosterActive, + bool? isRecirculationActive, + bool? isAutoActive, + bool? isFreshAirCirculateActive, + }) { + return vehicle( + isAcActive: isAcActive ?? this.isAcActive, + isAcDirectionDown: isAcDirectionDown ?? this.isAcDirectionDown, + isAcDirectionMiddle: isAcDirectionMiddle ?? this.isAcDirectionMiddle, + isAcDirectionUp: isAcDirectionUp ?? this.isAcDirectionUp, + isFrontDefrosterActive: + isFrontDefrosterActive ?? this.isFrontDefrosterActive, + isRearDefrosterActive: + isRearDefrosterActive ?? this.isRearDefrosterActive, + isRecirculationActive: + isRecirculationActive ?? this.isRecirculationActive, + isAutoActive: isAutoActive ?? this.isAutoActive, + isFreshAirCirculateActive: isFreshAirCirculateActive ?? this.isFreshAirCirculateActive, + + ); + } +} diff --git a/lib/kuksa-server/vehicle-provider.dart b/lib/kuksa-server/vehicle-provider.dart new file mode 100644 index 0000000..f070a53 --- /dev/null +++ b/lib/kuksa-server/vehicle-provider.dart @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle-class.dart'; + +final vehicleProvider = StateNotifierProvider<VehicleSignal, vehicle>( + (ref) => VehicleSignal(), +); + +class VehicleSignal extends StateNotifier<vehicle> { + static vehicle intial_value = vehicle( + isAcActive: false, + isAcDirectionDown: false, + isAcDirectionMiddle: false, + isAcDirectionUp: false, + isFrontDefrosterActive: false, + isRearDefrosterActive: false, + isRecirculationActive: false, + isAutoActive: false, + isFreshAirCirculateActive : false, + ); + VehicleSignal() : super(intial_value); + + void update({ + bool? isAcActive, + bool? isAcDirectionDown, + bool? isAcDirectionUp, + bool? isAcDirectionMiddle, + bool? isFrontDefrosterActive, + bool? isRearDefrosterActive, + bool? isRecirculationActive, + bool? isAutoActive, + bool? isFreshAirCirculateActive, + }) { + state = state.copywith( + isAcActive: isAcActive, + isAcDirectionDown: isAcDirectionDown, + isAcDirectionMiddle: isAcDirectionMiddle, + isAcDirectionUp: isAcDirectionUp, + isFrontDefrosterActive: isFrontDefrosterActive, + isRearDefrosterActive: isRearDefrosterActive, + isRecirculationActive: isRecirculationActive, + isAutoActive : isAutoActive, + isFreshAirCirculateActive : isFreshAirCirculateActive, + ); + } +} diff --git a/lib/kuksa-server/vehicle_config.dart b/lib/kuksa-server/vehicle_config.dart new file mode 100644 index 0000000..6eff800 --- /dev/null +++ b/lib/kuksa-server/vehicle_config.dart @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: Apache-2.0 + + +import 'dart:io'; +import 'package:flutter_hvac/config.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:http/http.dart' as http; + + + +final sockConnectprovider = FutureProvider.family<WebSocket, HttpClient>( + (ref, client) => connect(client,ref)); + + + +// load certificates and set context and returns http client +Future<HttpClient> initializeClient() async { + + + SecurityContext ctx = SecurityContext.defaultContext; + + HttpClient client = HttpClient(context: ctx) + ..findProxy = null + ..badCertificateCallback = (cert, host, port) { + return true; + }; + return client; +} + + + +Future<WebSocket> connect(HttpClient client, ref) async { + final config = ref.read(ConfigStateprovider); + WebSocket socket = await WebSocket.connect( + "wss://${config.hostname}:${config.port}", + customClient: client); + return socket; +} + diff --git a/lib/kuksa-server/vehicle_methods.dart b/lib/kuksa-server/vehicle_methods.dart new file mode 100644 index 0000000..2dda79f --- /dev/null +++ b/lib/kuksa-server/vehicle_methods.dart @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter_hvac/config.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle_server_path.dart'; + + +class VISS { + static const requestId = "test-id"; + static void init(WebSocket socket,WidgetRef ref) { + authorize(socket,ref); + + subscribe(socket,ref, VSPath.vehicleFrontLeftTier); + subscribe(socket,ref, VSPath.vehicleFrontRightTier); + subscribe(socket,ref, VSPath.vehicleRearLeftTier); + subscribe(socket,ref, VSPath.vehicleRearRightTier); + subscribe(socket,ref, VSPath.vehicleIsChildLockActiveLeft); + subscribe(socket,ref, VSPath.vehicleIsChildLockActiveRight); + subscribe(socket,ref, VSPath.vehicleCurrentLatitude); + subscribe(socket,ref, VSPath.vehicleCurrentLongitude); + subscribe(socket,ref, VSPath.vehicleInsideTemperature); + subscribe(socket,ref, VSPath.vehicleAmbientAirTemperature); + } + + static void update(WebSocket socket,WidgetRef ref) { + get(socket,ref, VSPath.vehicleAmbientAirTemperature); + get(socket,ref, VSPath.vehicleTrunkLocked); + get(socket, ref,VSPath.vehicleTrunkOpen); + + get(socket,ref, VSPath.vehicleFrontLeftTier); + get(socket,ref, VSPath.vehicleFrontRightTier); + get(socket,ref, VSPath.vehicleRearLeftTier); + get(socket,ref, VSPath.vehicleRearRightTier); + get(socket,ref, VSPath.vehicleIsChildLockActiveLeft); + get(socket,ref, VSPath.vehicleIsChildLockActiveRight); + get(socket,ref, VSPath.vehicleCurrentLatitude); + get(socket,ref, VSPath.vehicleCurrentLongitude); + get(socket,ref, VSPath.vehicleInsideTemperature); + } + + static void authorize(WebSocket socket,WidgetRef ref) { + final config = ref.read(ConfigStateprovider); + Map<String, dynamic> map = { + "action": "authorize", + "tokens": config.kuksaAuthToken, + "requestId": requestId + }; + socket.add(jsonEncode(map)); + } + + static void get(WebSocket socket,WidgetRef ref ,String path) { + final config = ref.read(ConfigStateprovider); + + Map<String, dynamic> map = { + "action": "get", + "tokens": config.kuksaAuthToken, + "path": path, + "requestId": requestId + }; + socket.add(jsonEncode(map)); + } + + static void set( + WebSocket socket, + WidgetRef ref, + String path, + String value, + ) { + final config = ref.read(ConfigStateprovider); + + Map<String, dynamic> map = { + "action": "set", + "tokens": config.kuksaAuthToken, + "path": path, + "requestId": requestId, + "value": value + }; + socket.add(jsonEncode(map)); + } + + static void subscribe(WebSocket socket,WidgetRef ref, String path) { + final config = ref.read(ConfigStateprovider); + + Map<String, dynamic> map = { + "action": "subscribe", + "tokens": config.kuksaAuthToken, + "path": path, + "requestId": requestId + }; + socket.add(jsonEncode(map)); + } + + +} diff --git a/lib/kuksa-server/vehicle_server_path.dart b/lib/kuksa-server/vehicle_server_path.dart new file mode 100644 index 0000000..c61c3ca --- /dev/null +++ b/lib/kuksa-server/vehicle_server_path.dart @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 + + +class VSPath { + + + static const String vehicleTrunkLocked = "Vehicle.Body.Trunk.IsLocked"; + static const String vehicleTrunkOpen = "Vehicle.Body.Trunk.IsOpen"; + + + static const String vehicleAmbientAirTemperature = + "Vehicle.AmbientAirTemperature"; + + static const String vehicleFrontLeftTier = + "Vehicle.Chassis.Axle.Row1.Wheel.Left.Tire.Pressure"; + static const String vehicleFrontRightTier = + "Vehicle.Chassis.Axle.Row1.Wheel.Right.Tire.Pressure"; + static const String vehicleRearLeftTier = + "Vehicle.Chassis.Axle.Row2.Wheel.Left.Tire.Pressure"; + + static const String vehicleRearRightTier = + "Vehicle.Chassis.Axle.Row2.Wheel.Right.Tire.Pressure"; + static const String vehicleIsChildLockActiveLeft = + "Vehicle.Cabin.Door.Row2.Left.IsChildLockActive"; + static const String vehicleIsChildLockActiveRight = + "Vehicle.Cabin.Door.Row2.Right.IsChildLockActive"; + static const String vehicleCurrentLongitude = + "Vehicle.CurrentLocation.Longitude"; + static const String vehicleCurrentLatitude = + "Vehicle.CurrentLocation.Latitude"; + + static const String vehicleInsideTemperature = + "Vehicle.Cabin.HVAC.AmbientAirTemperature"; + static const String vehicleFrontLeftAc = + "Vehicle.Cabin.HVAC.Station.Row1.Left.AirDistribution"; +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..b2758de --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_hvac/config.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'kuksa-server/vehicle_config.dart'; + + + +Future<void> main() async { + WidgetsFlutterBinding.ensureInitialized(); + HttpClient client = await initializeClient(); + + runApp( + ProviderScope( + child: MaterialApp( + home: GetConfig(client: client), + ), + ), + ); +} diff --git a/lib/provider.dart b/lib/provider.dart new file mode 100644 index 0000000..c933fdd --- /dev/null +++ b/lib/provider.dart @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final LeftSlider = StateNotifierProvider<leftclimate, int>( + (ref) => leftclimate(), +); + +class leftclimate extends StateNotifier<int> { + leftclimate() : super(0); + + Future<void> update(value) async { + state = value; + } +} + +final RightSlider = StateNotifierProvider<Rightclimate, int>( + (ref) => Rightclimate(), +); + +class Rightclimate extends StateNotifier<int> { + Rightclimate() : super(0); + + Future<void> update(value) async { + state = value; + } +} + +final fanSpeedProvider = + StateNotifierProvider<fanslider, int>((ref) => fanslider()); + +class fanslider extends StateNotifier<int> { + fanslider() : super(30); + void update(value) { + state = value; + } +} diff --git a/lib/size.dart b/lib/size.dart new file mode 100644 index 0000000..a572ad2 --- /dev/null +++ b/lib/size.dart @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +class SizeConfig { + static late MediaQueryData _mediaQueryData; + static late double screenWidth; + static late double screenHeight; + static late double blockSizeHorizontal; + static late double blockSizeVertical; + static late double _safeAreaHorizontal; + static late double _safeAreaVertical; + static late double safeBlockHorizontal; + static late double safeBlockVertical; + static late double fontsize; + static late TextStyle normalfont; + static late TextStyle smallnormalfont; + static late TextStyle smallnormalfont2; + + void init(BuildContext context) { + _mediaQueryData = MediaQuery.of(context); + screenWidth = _mediaQueryData.size.width; + screenHeight = _mediaQueryData.size.height; + blockSizeHorizontal = screenWidth / 100; + blockSizeVertical = screenHeight / 100; + _safeAreaHorizontal = + _mediaQueryData.padding.left + _mediaQueryData.padding.right; + _safeAreaVertical = + _mediaQueryData.padding.top + _mediaQueryData.padding.bottom; + safeBlockHorizontal = (screenWidth - _safeAreaHorizontal) / 100; + safeBlockVertical = (screenHeight - _safeAreaVertical) / 100; + fontsize = screenHeight * screenWidth * 0.01 * 0.01 * 0.1; + // fontsize= blockSizeVertical*2; + normalfont = TextStyle( + fontSize: fontsize, + fontWeight: FontWeight.w700, + color: Colors.white, + ); + smallnormalfont = TextStyle( + fontSize: fontsize / 2, + fontWeight: FontWeight.w700, + color: Colors.white, + ); + smallnormalfont2 = TextStyle( + fontSize: fontsize * 0.4, + color: Colors.white, + ); + } +} diff --git a/lib/slider/Climate_slider.dart b/lib/slider/Climate_slider.dart new file mode 100644 index 0000000..b0a0d6f --- /dev/null +++ b/lib/slider/Climate_slider.dart @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_hvac/provider.dart'; + +import '../size.dart'; + +class ClimateSliderControlLeft extends ConsumerWidget { + const ClimateSliderControlLeft({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context,ref) { + int val = ref.watch(LeftSlider).toInt(); + + return SizedBox( + height: SizeConfig.screenHeight*0.35, + width: SizeConfig.blockSizeHorizontal*3, + child: RotatedBox( + quarterTurns: 3, + child: Slider( + min: 0, + max: 15, + value: val.toDouble(), + divisions: 15, + onChanged: (value) { + ref.read(LeftSlider.notifier).update(value.toInt()); + }, + activeColor: Colors.green, + inactiveColor: Colors.white, + thumbColor: Colors.grey, + ), + + ), + ); + + } +} diff --git a/lib/slider/Right_climate_slider.dart b/lib/slider/Right_climate_slider.dart new file mode 100644 index 0000000..536d11c --- /dev/null +++ b/lib/slider/Right_climate_slider.dart @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_hvac/provider.dart'; + +import '../size.dart'; + +class ClimateSliderControlRight extends ConsumerWidget { + const ClimateSliderControlRight({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context, ref) { + int val = ref.watch(RightSlider).toInt(); + return SizedBox( + height: SizeConfig.screenHeight*0.35, + width: SizeConfig.blockSizeHorizontal*3, + child: RotatedBox( + quarterTurns: 3, + child: Slider( + min: 0, + max: 15, + value: val.toDouble(), + divisions: 15, + onChanged: (value) { + ref.read(RightSlider.notifier).update(value.toInt()); + }, + activeColor: Colors.green, + inactiveColor: Colors.white, + thumbColor: Colors.grey, + ), + + ), + ); + } +} diff --git a/lib/slider/slider.dart b/lib/slider/slider.dart new file mode 100644 index 0000000..1d2de82 --- /dev/null +++ b/lib/slider/slider.dart @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_hvac/provider.dart'; + +import '../kuksa-server/vehicle_methods.dart'; +import '../size.dart'; + +class SliderControl extends ConsumerWidget { + WebSocket socket; + SliderControl({Key? key, required this.socket}) : super(key: key); + + @override + Widget build(BuildContext context, ref) { + return SizedBox( + height: SizeConfig.safeBlockVertical*2, + width: SizeConfig.screenWidth*0.5, + + child: Slider( + value: ref.watch(fanSpeedProvider).toDouble(), + onChanged: (value) { + ref.read(fanSpeedProvider.notifier).update(value.toInt()); + VISS.set(socket, ref,'Vehicle.Cabin.HVAC.Station.Row1.Left.FanSpeed', + value.toInt().toString()); + VISS.set(socket, ref,'Vehicle.Cabin.HVAC.Station.Row1.Right.FanSpeed', + value.toInt().toString()); + VISS.set(socket, ref,'Vehicle.Cabin.HVAC.Station.Row2.Left.FanSpeed', + value.toInt().toString()); + VISS.set(socket,ref, 'Vehicle.Cabin.HVAC.Station.Row2.Right.FanSpeed', + value.toInt().toString()); + }, + min: 0, + max: 100, + activeColor: Colors.green, + inactiveColor: Colors.white70, + thumbColor: Colors.grey, + label: 'fan speed', + ), + ); + } +} diff --git a/lib/widgets/Right_climate.dart b/lib/widgets/Right_climate.dart new file mode 100644 index 0000000..d47a659 --- /dev/null +++ b/lib/widgets/Right_climate.dart @@ -0,0 +1,115 @@ + +// SPDX-License-Identifier: Apache-2.0 + + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; +import 'package:flutter_hvac/kuksa-server/vehicle_methods.dart'; +import 'package:flutter_hvac/provider.dart'; +import 'package:flutter_hvac/size.dart'; + +class ScrollContainerRight extends ConsumerWidget { + WebSocket socket; + ScrollContainerRight({Key? key, required this.socket}) : super(key: key); + + List<int> mylist = [ + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + ]; + + + final ItemScrollController itemScrollController = ItemScrollController(); + final ItemPositionsListener itemPositionsListener = + ItemPositionsListener.create(); + + @override + Widget build(BuildContext context, ref) { + int val = ref.watch(RightSlider).toInt(); + + VISS.set(socket,ref, 'Vehicle.Cabin.HVAC.Station.Row1.Right.Temperature', + mylist[val].toString()); + VISS.set(socket, ref,'Vehicle.Cabin.HVAC.Station.Row2.Right.Temperature', + mylist[val].toString()); + + if (itemScrollController.isAttached) { + itemScrollController.scrollTo( + index: val.toInt()+2, + duration: Duration(milliseconds: 500), + curve: Curves.easeInOutCubic, + alignment: 1); + } + + + return SingleChildScrollView( + child: SizedBox( + height: SizeConfig.screenHeight*0.30, + width: SizeConfig.screenWidth*0.25, + child: AnimatedContainer( + // color: Colors.red, + duration: Duration(milliseconds: 300), + decoration: BoxDecoration( + border: Border.all( + color: Colors.white, + width: 2, + ), + borderRadius: BorderRadius.circular(12), + ), + child: ScrollablePositionedList.builder( + physics: NeverScrollableScrollPhysics(), + scrollDirection: Axis.vertical, + itemCount: mylist.length, + itemScrollController: itemScrollController, + itemPositionsListener: itemPositionsListener, + itemBuilder: (context, index) { + return Container( + decoration: BoxDecoration( + + gradient: index == val + ? RadialGradient( + colors: [Colors.white54, Colors.black], radius: SizeConfig.safeBlockVertical*0.7) + : null, + ), + child: ListTile( + subtitle: Center( + child: Text( + '' + mylist[index].toString() + '°', + style: index == val ? TextStyle( + color: Colors.lightBlueAccent, + fontWeight: FontWeight.w700, + fontSize: SizeConfig.fontsize*4, + ):TextStyle( + color: Colors.white54, + fontWeight: FontWeight.w700, + fontSize: SizeConfig.fontsize*4, + ), + ), + ), + + minVerticalPadding: 5, + + ), + ); + }), + ), + ), + ); + } +} diff --git a/lib/widgets/left_climate.dart b/lib/widgets/left_climate.dart new file mode 100644 index 0000000..2fb30a0 --- /dev/null +++ b/lib/widgets/left_climate.dart @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: Apache-2.0 + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; +import 'package:flutter_hvac/provider.dart'; +import 'dart:io'; + +import '../kuksa-server/vehicle_methods.dart'; +import '../size.dart'; + +class ScrollContainerLeft extends ConsumerWidget { + WebSocket socket; + ScrollContainerLeft({Key? key, required this.socket}) : super(key: key); + + List<int> mylist = [ + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32 + ]; + + + final ItemScrollController itemScrollController = ItemScrollController(); + final ItemPositionsListener itemPositionsListener = + ItemPositionsListener.create(); + @override + Widget build(BuildContext context, ref) { + int val = ref.watch(LeftSlider).toInt(); + + VISS.set(socket,ref, 'Vehicle.Cabin.HVAC.Station.Row1.Left.Temperature', + mylist[val].toString()); + VISS.set(socket,ref, 'Vehicle.Cabin.HVAC.Station.Row2.Left.Temperature', + mylist[val].toString()); + + + if (itemScrollController.isAttached) { + itemScrollController.scrollTo( + index: val.toInt() + 2, + duration: Duration(milliseconds: 500), + curve: Curves.easeInOutCubic, + alignment: 1); + } + + return SingleChildScrollView( + child: SizedBox( + height: SizeConfig.screenHeight*0.30, + width: SizeConfig.screenWidth*0.25, + child: AnimatedContainer( + // color: Colors.red, + duration: Duration(milliseconds: 500), + decoration: BoxDecoration( + border: Border.all( + color: Colors.white, + width: 2, + ), + borderRadius: BorderRadius.circular(12), + ), + child: ScrollablePositionedList.builder( + physics: NeverScrollableScrollPhysics(), + scrollDirection: Axis.vertical, + itemCount: mylist.length, + itemScrollController: itemScrollController, + itemPositionsListener: itemPositionsListener, + itemBuilder: (context, index) { + return Container( + decoration: BoxDecoration( + + gradient: index == val + ? RadialGradient( + colors: [Colors.white54, Colors.black], radius: SizeConfig.safeBlockVertical*0.7) + : null, + ), + child: ListTile( + subtitle: Center( + child: Text( + '' + mylist[index].toString() + '°', + style: index == val ? TextStyle( + color: Colors.lightBlueAccent, + fontWeight: FontWeight.w700, + fontSize: SizeConfig.fontsize*4, + ):TextStyle( + color: Colors.white54, + fontWeight: FontWeight.w700, + fontSize: SizeConfig.fontsize*4, + ), + ), + ), + // tileColor: Colors.red, + minVerticalPadding: 5, + // selectedTileColor: , + ), + ); + }), + ), + ), + ); + } +} |