summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHritik Chouhan <hritikc3961@gmail.com>2022-09-01 19:15:56 +0200
committerHritik Chouhan <hritikc3961@gmail.com>2022-09-16 17:25:01 +0200
commit5559cdb261cfd3e69daa2349906f071dc2491c0d (patch)
tree12a530a7ab6b8f5fc758f228bf1729e733db9aa8
parentb7ba5e78b0ca5245cd9c09313d40561e75d0b120 (diff)
Upload Flutter-HVAC application for IVI
Flutter hvac app which sets value to KUKSA.VAL like Fan speed,left and right zone climate temperature, AC vent direction, Air circulation,Front and Rear Wind shield defrost. Update UI and removed Unused code. Bug-AGL: SPEC-4546 Change-Id: I57f7a9a2954520f4bb781a5ec02be612d72cf404 Signed-off-by: Hritik Chouhan <hritikc3961@gmail.com>
-rw-r--r--.gitreview5
-rw-r--r--License.md201
-rw-r--r--images/ac_on_face.svg52
-rw-r--r--images/ac_on_foot.svg52
-rw-r--r--images/face_foot.svg76
-rw-r--r--images/fan.svg1
-rw-r--r--images/in_out.svg85
-rw-r--r--images/left_climate.PNGbin0 -> 26668 bytes
-rw-r--r--images/rear_ws.svg61
-rw-r--r--images/right_climate.PNGbin0 -> 27493 bytes
-rw-r--r--images/wind_in.svg81
-rw-r--r--images/wind_shield.svg67
-rw-r--r--lib/Buttons/AC.dart124
-rw-r--r--lib/Buttons/ac_on_face.dart145
-rw-r--r--lib/Buttons/ac_on_foot.dart146
-rw-r--r--lib/Buttons/auto.dart116
-rw-r--r--lib/Buttons/defrost_recirculate.dart178
-rw-r--r--lib/Buttons/fresh_air.dart110
-rw-r--r--lib/config.dart111
-rw-r--r--lib/home_page.dart181
-rw-r--r--lib/kuksa-server/intial_connection.dart44
-rw-r--r--lib/kuksa-server/on_boarding_page.dart65
-rw-r--r--lib/kuksa-server/vehicle-class.dart53
-rw-r--r--lib/kuksa-server/vehicle-provider.dart47
-rw-r--r--lib/kuksa-server/vehicle_config.dart39
-rw-r--r--lib/kuksa-server/vehicle_methods.dart97
-rw-r--r--lib/kuksa-server/vehicle_server_path.dart36
-rw-r--r--lib/main.dart23
-rw-r--r--lib/provider.dart37
-rw-r--r--lib/size.dart50
-rw-r--r--lib/slider/Climate_slider.dart38
-rw-r--r--lib/slider/Right_climate_slider.dart36
-rw-r--r--lib/slider/slider.dart44
-rw-r--r--lib/widgets/Right_climate.dart115
-rw-r--r--lib/widgets/left_climate.dart112
-rw-r--r--pubspec.yaml95
36 files changed, 2723 insertions, 0 deletions
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..6f9dc04
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,5 @@
+[gerrit]
+host=gerrit.automotivelinux.org
+port=29418
+project=apps/flutter-hvac
+defaultbranch=master
diff --git a/License.md b/License.md
new file mode 100644
index 0000000..a0b7d15
--- /dev/null
+++ b/License.md
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [2022] [Hritik Chouhan]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/images/ac_on_face.svg b/images/ac_on_face.svg
new file mode 100644
index 0000000..3ab2d40
--- /dev/null
+++ b/images/ac_on_face.svg
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 454.521 454.521" style="enable-background:new 0 0 454.521 454.521;" xml:space="preserve">
+<g>
+ <path d="M360.778,127.298L360.778,127.298c-13.676-3.736-27.988-1.925-40.3,5.104c-12.313,7.028-21.151,18.43-24.888,32.104
+ l-27.318,99.971H165.363c-3.979,0-7.794,1.58-10.606,4.394l-95.048,95.048c-10.024,10.024-15.546,23.353-15.546,37.529
+ s5.521,27.505,15.546,37.529s23.353,15.545,37.529,15.545s27.505-5.521,37.528-15.545l68.352-68.352h86.295
+ c35.266,0,66.387-23.759,75.682-57.775l32.891-120.364c3.736-13.676,1.925-27.987-5.103-40.3
+ C385.854,139.874,374.453,131.035,360.778,127.298z M289.413,340.625h-92.508c-3.979,0-7.794,1.58-10.606,4.394l-72.746,72.745
+ c-4.357,4.358-10.151,6.758-16.314,6.758s-11.958-2.399-16.316-6.758s-6.759-10.153-6.759-16.316s2.4-11.957,6.759-16.315
+ l90.654-90.655h108.147c6.762,0,12.688-4.523,14.47-11.046l30.337-111.018c3.353-12.273,16.063-19.531,28.341-16.176h-0.001
+ c12.273,3.354,19.53,16.067,16.176,28.34l-32.891,120.365C330.415,325.951,311.194,340.625,289.413,340.625z"/>
+ <path d="M352.856,115.006c31.707,0,57.503-25.796,57.503-57.503S384.563,0,352.856,0s-57.503,25.796-57.503,57.503
+ S321.149,115.006,352.856,115.006z M352.856,30c15.165,0,27.503,12.338,27.503,27.503s-12.338,27.503-27.503,27.503
+ s-27.503-12.338-27.503-27.503S337.691,30,352.856,30z"/>
+ <path d="M93.468,73.292H214.89c0.115,0,0.226-0.015,0.34-0.017v18.417c0,6.919,8.365,10.384,13.257,5.492l33.427-33.427
+ c3.033-3.033,3.033-7.95,0-10.983l-33.427-33.427c-4.892-4.893-13.257-1.427-13.257,5.491v18.472
+ c-0.114-0.002-0.225-0.017-0.34-0.017H93.468c-8.284,0-15,6.716-15,15S85.184,73.292,93.468,73.292z"/>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/images/ac_on_foot.svg b/images/ac_on_foot.svg
new file mode 100644
index 0000000..29425aa
--- /dev/null
+++ b/images/ac_on_foot.svg
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 454.521 454.521" style="enable-background:new 0 0 454.521 454.521;" xml:space="preserve">
+<g>
+ <path d="M402.126,127.298L402.126,127.298c-28.227-7.713-57.473,8.978-65.188,37.208l-27.317,99.971H206.712
+ c-3.979,0-7.794,1.58-10.606,4.394l-95.048,95.048c-10.024,10.024-15.546,23.353-15.546,37.529s5.521,27.505,15.545,37.529
+ c10.024,10.024,23.353,15.545,37.529,15.545s27.505-5.521,37.529-15.545l68.352-68.352h86.294
+ c35.265,0,66.387-23.758,75.683-57.775l32.89-120.364c3.736-13.676,1.925-27.987-5.103-40.3
+ C427.203,139.874,415.801,131.035,402.126,127.298z M238.254,340.625c-3.979,0-7.794,1.58-10.606,4.394l-72.745,72.745
+ c-8.998,8.996-23.638,8.996-32.632,0c-8.997-8.997-8.997-23.636,0-32.632l90.654-90.655h108.147c6.762,0,12.688-4.523,14.47-11.046
+ l30.336-111.017c3.354-12.272,16.065-19.527,28.341-16.177c5.944,1.625,10.901,5.468,13.957,10.819
+ c3.055,5.354,3.843,11.575,2.218,17.521l-32.89,120.364c-5.741,21.01-24.963,35.684-46.743,35.684H238.254z"/>
+ <path d="M394.205,115.006c31.707,0,57.503-25.796,57.503-57.503S425.912,0,394.205,0c-31.708,0-57.504,25.796-57.504,57.503
+ S362.497,115.006,394.205,115.006z M394.205,30c15.165,0,27.503,12.338,27.503,27.503s-12.338,27.503-27.503,27.503
+ c-15.166,0-27.504-12.338-27.504-27.503S379.039,30,394.205,30z"/>
+ <path d="M133.06,277.247c4.289,0,7.766-3.477,7.766-7.766v-47.273c0-6.919-8.365-10.384-13.257-5.492l-13.062,13.062
+ c-0.079-0.082-0.147-0.171-0.228-0.252L28.42,143.668c-5.857-5.857-15.355-5.857-21.213,0c-5.858,5.857-5.858,15.355,0,21.213
+ l85.858,85.858c0.081,0.081,0.17,0.149,0.252,0.228L80.295,263.99c-4.892,4.892-1.427,13.257,5.491,13.257H133.06z"/>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/images/face_foot.svg b/images/face_foot.svg
new file mode 100644
index 0000000..e2bee93
--- /dev/null
+++ b/images/face_foot.svg
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<g>
+ <g>
+ <path style="fill:#34485C;" d="M507.586,44.138c0,24.373-19.765,44.138-44.138,44.138c-24.373,0-44.138-19.765-44.138-44.138
+ S439.075,0,463.448,0C487.821,0,507.586,19.765,507.586,44.138"/>
+ <path style="fill:#34485C;" d="M367.802,151.257l-48.87,141.639c-3.24,9.384-12.57,15.263-22.44,14.124l-89.538-10.284
+ c-8.766-1.095-16.993,4.414-19.315,12.932l-58.73,170.178c-2.18,7.998-0.468,16.87,5.411,22.713
+ c17.373,17.276,41.498,8.925,47.289-9.613l49.646-121.706c2.622-8.404,11.008-13.603,19.694-12.235l133.438,18.22
+ c10.037,1.368,19.633-4.555,22.908-14.133l60.646-177.443c9.869-28.866-6.638-60.072-36.043-68.167l0,0
+ C404.966,110.068,376.912,124.854,367.802,151.257"/>
+ </g>
+ <polygon style="fill:#74B73E;" points="313.379,79.448 233.931,0 233.931,44.138 92.69,44.138 92.69,114.759 233.931,114.759
+ 233.931,158.897 "/>
+ <path style="fill:#94CAFF;" d="M189.793,264.827L189.793,264.827c-60.195-11.847-119.305-11.697-176.552,0l0,0l-8.828-88.276
+ c54.175-11.794,141.506-11.75,194.207,0L189.793,264.827z"/>
+ <g>
+ <path style="fill:#4897F7;" d="M136.827,335.447c-2.348,0-4.687-0.927-6.426-2.772c-3.337-3.549-3.178-9.137,0.371-12.482
+ c3.858-3.637,14.883-16.746,14.883-28.884c0-6.126-3.046-12.332-5.738-17.805c-0.927-1.88-1.792-3.646-2.463-5.226
+ c-0.115-0.291-0.23-0.583-0.318-0.874c-0.477-1.05-1.033-2.18-1.615-3.381c-3.169-6.497-7.521-15.413-7.521-25.679
+ c0-10.266,4.343-19.165,7.521-25.662c0.759-1.545,1.457-2.975,2.013-4.273c1.898-4.484,7.071-6.594,11.573-4.67
+ c4.484,1.907,6.577,7.089,4.67,11.573c-0.653,1.554-1.492,3.275-2.392,5.12c-2.684,5.5-5.729,11.732-5.729,17.911
+ c0,6.188,3.046,12.429,5.729,17.938c0.9,1.845,1.739,3.566,2.392,5.111c0.124,0.291,0.23,0.574,0.318,0.865
+ c0.494,1.077,1.059,2.233,1.668,3.46c3.178,6.479,7.548,15.351,7.548,25.591c0,22.237-19.597,40.951-20.427,41.737
+ C141.179,334.653,138.999,335.447,136.827,335.447"/>
+ <path style="fill:#4897F7;" d="M92.69,335.447c-2.348,0-4.687-0.927-6.426-2.772c-3.337-3.549-3.178-9.137,0.371-12.482
+ c3.858-3.637,14.883-16.746,14.883-28.884c0-6.126-3.046-12.332-5.738-17.805c-0.927-1.88-1.792-3.646-2.463-5.226
+ c-0.115-0.291-0.23-0.583-0.318-0.874c-0.477-1.05-1.033-2.18-1.615-3.381c-3.169-6.497-7.521-15.413-7.521-25.679
+ c0-10.266,4.343-19.165,7.521-25.662c0.75-1.545,1.457-2.975,2.013-4.273c1.898-4.484,7.08-6.594,11.573-4.67
+ c4.484,1.907,6.577,7.089,4.67,11.573c-0.653,1.554-1.492,3.275-2.392,5.12c-2.684,5.5-5.729,11.732-5.729,17.911
+ c0,6.188,3.046,12.429,5.729,17.938c0.9,1.845,1.739,3.566,2.392,5.111c0.124,0.291,0.23,0.574,0.318,0.865
+ c0.494,1.077,1.059,2.233,1.668,3.46c3.178,6.479,7.548,15.351,7.548,25.591c0,22.237-19.597,40.951-20.427,41.737
+ C97.042,334.653,94.861,335.447,92.69,335.447"/>
+ <path style="fill:#4897F7;" d="M48.552,335.447c-2.348,0-4.687-0.927-6.426-2.772c-3.337-3.549-3.178-9.137,0.371-12.482
+ c3.858-3.637,14.883-16.746,14.883-28.884c0-6.126-3.046-12.332-5.738-17.805c-0.927-1.88-1.792-3.646-2.463-5.226
+ c-0.115-0.291-0.23-0.583-0.318-0.874c-0.477-1.05-1.033-2.18-1.615-3.381c-3.169-6.497-7.521-15.413-7.521-25.679
+ c0-10.266,4.343-19.165,7.521-25.662c0.75-1.545,1.457-2.975,2.013-4.273c1.898-4.484,7.071-6.594,11.573-4.67
+ c4.484,1.907,6.577,7.089,4.67,11.573c-0.653,1.554-1.492,3.275-2.392,5.12c-2.684,5.5-5.729,11.732-5.729,17.911
+ c0,6.188,3.046,12.429,5.729,17.938c0.9,1.845,1.739,3.566,2.392,5.111c0.124,0.291,0.23,0.574,0.318,0.865
+ c0.494,1.077,1.059,2.233,1.668,3.46c3.178,6.479,7.548,15.351,7.548,25.591c0,22.237-19.597,40.951-20.427,41.737
+ C52.904,334.653,50.723,335.447,48.552,335.447"/>
+ </g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/images/fan.svg b/images/fan.svg
new file mode 100644
index 0000000..4f0d6c0
--- /dev/null
+++ b/images/fan.svg
@@ -0,0 +1 @@
+<svg class="svg-icon" style="width: 1em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M457.085 459.284c1.929-1.916 19.923-21.075 26.705-27.66 14.06-13.655 27.832-24.354 43.571-32.82 19.096-10.27 36.569-30.294 46.56-52.11 4.225-9.226 6.559-17.722 6.855-23.683-15.19-10.698-38.455-18.393-61.105-19.65-25.435-1.413-45.52 5.208-56.305 18.15-13.068 15.682-20.816 45.463-20.13 78.19 0.525 25.07 6.072 47.618 13.277 60.148 0.188-0.184 0.378-0.372 0.572-0.565z m-17.67-157.732c38.406-46.087 125.21-32.103 165.034 0 22.53 18.162-7.576 95.266-62.32 124.71-54.743 29.444-73.753 91.316-102.714 62.355-33.394-33.394-39.538-139.62 0-187.065z m125.3 155.533c1.917 1.929 21.076 19.923 27.662 26.705 13.654 14.06 24.353 27.832 32.819 43.571 10.27 19.096 30.294 36.569 52.11 46.56 9.226 4.225 17.722 6.559 23.683 6.855 10.698-15.19 18.393-38.455 19.65-61.105 1.413-25.435-5.208-45.52-18.15-56.305-15.682-13.068-45.463-20.816-78.19-20.13-25.07 0.525-47.618 6.072-60.148 13.277 0.184 0.188 0.372 0.378 0.565 0.572z m157.733-17.67c46.087 38.406 32.103 125.21 0 165.034-18.162 22.53-95.266-7.576-124.71-62.32-29.444-54.743-91.316-73.753-62.355-102.714 33.394-33.394 139.62-39.538 187.065 0z m-155.533 125.3c-1.929 1.917-19.923 21.076-26.705 27.662-14.06 13.654-27.832 24.353-43.571 32.819-19.096 10.27-36.569 30.294-46.56 52.11-4.225 9.226-6.559 17.722-6.855 23.683 15.19 10.698 38.455 18.393 61.105 19.65 25.435 1.413 45.52-5.208 56.305-18.15 13.068-15.682 20.816-45.463 20.13-78.19-0.525-25.07-6.072-47.618-13.277-60.148-0.188 0.184-0.378 0.372-0.572 0.565z m17.67 157.733c-38.406 46.087-125.21 32.103-165.034 0-22.53-18.162 7.576-95.266 62.32-124.71 54.743-29.444 73.753-91.316 102.714-62.355 33.394 33.394 39.538 139.62 0 187.065z m-125.3-155.533c-1.917-1.929-21.076-19.923-27.662-26.705-13.654-14.06-24.353-27.832-32.819-43.571-10.27-19.096-30.294-36.569-52.11-46.56-9.226-4.225-17.722-6.559-23.683-6.855-10.698 15.19-18.393 38.455-19.65 61.105-1.413 25.435 5.208 45.52 18.15 56.305 15.682 13.068 45.463 20.816 78.19 20.13 25.07-0.525 47.618-6.072 60.148-13.277a142.54 142.54 0 0 0-0.565-0.572z m-157.733 17.67c-46.087-38.406-32.103-125.21 0-165.034 18.162-22.53 95.266 7.576 124.71 62.32 29.444 54.743 91.316 73.753 62.355 102.714-33.394 33.394-139.62 39.538-187.065 0z" /></svg> \ No newline at end of file
diff --git a/images/in_out.svg b/images/in_out.svg
new file mode 100644
index 0000000..eac2657
--- /dev/null
+++ b/images/in_out.svg
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 295.239 295.239" style="enable-background:new 0 0 295.239 295.239;" xml:space="preserve">
+<g>
+ <g>
+ <g>
+ <path d="M66.667,247.62c-7.876,0-14.286,6.41-14.286,14.286c0,7.876,6.41,14.286,14.286,14.286
+ c7.876,0,14.286-6.41,14.286-14.286C80.952,254.03,74.543,247.62,66.667,247.62z M66.667,266.668
+ c-2.629,0-4.762-2.133-4.762-4.762c0-2.629,2.133-4.762,4.762-4.762c2.629,0,4.762,2.133,4.762,4.762
+ C71.429,264.535,69.295,266.668,66.667,266.668z"/>
+ <path d="M280.953,266.668c11.805,0,14.286-7.771,14.286-14.286v-38.095c0-12.095-6.481-22.852-16.919-28.071l-0.967-0.357
+ c-0.171-0.043-17.2-4.486-25.614-16.833l-14.148-28.295c-5.81-11.629-18.624-16.919-28.067-16.919h-59.786
+ c7.733-12.686,12.167-27.471,12.167-42.857h-9.524c0,26.805-15.062,51.605-38.095,63.9v-16.281h-9.524v28.571h28.571v-9.524
+ h-5.51c5.662-4.09,10.729-8.914,15.148-14.286h66.552c6.824,0,15.729,4.005,19.548,11.652l14.286,28.571l0.3,0.51
+ c9.586,14.376,27.343,19.91,30.81,20.876c6.952,3.671,11.248,11.038,11.248,19.343v38.095c0,4.09-0.671,4.762-4.762,4.762
+ h-19.429c-2.324-16.124-16.195-28.571-32.952-28.571c-16.757,0-30.629,12.448-32.952,28.571h-96
+ c-2.324-16.124-16.195-28.571-32.952-28.571c-16.757,0-30.629,12.448-32.952,28.571H19.048c-5.071,0-9.524-4.452-9.524-9.524
+ v-33.333c0-11.781,7.881-17.614,15.067-19.114l28.724-4.79c6.219-1.248,11.281-4.557,17.162-11.338l20-26.662h-9.524
+ c-26.805,0-51.605-15.062-63.9-38.095h16.281v-9.524H4.762v28.571h9.524v-5.543c13.367,18.505,34.395,30.976,57.533,33.6
+ l-8.748,11.676c-4.276,4.924-7.538,7.162-11.471,7.952l-28.762,4.795C9.181,188.658,0,200.1,0,214.287v33.333
+ c0,10.324,8.724,19.048,19.048,19.048h14.667c2.324,16.124,16.195,28.571,32.952,28.571h90.476v-9.524H89.948
+ c5.114-5.005,8.605-11.638,9.671-19.048h96c1.067,7.41,4.557,14.043,9.671,19.048h-19.576v9.524h109.524v-9.524h-43.386
+ c5.119-5.004,8.605-11.638,9.672-19.047H280.953z M66.667,285.715c-13.129,0-23.81-10.681-23.81-23.81
+ c0-13.129,10.681-23.81,23.81-23.81c13.129,0,23.81,10.681,23.81,23.81C90.477,275.033,79.795,285.715,66.667,285.715z
+ M228.572,285.715c-13.129,0-23.81-10.682-23.81-23.81c0-13.129,10.681-23.81,23.81-23.81c13.129,0,23.81,10.681,23.81,23.81
+ C252.382,275.035,241.701,285.715,228.572,285.715z"/>
+ <path d="M228.571,247.62c-7.876,0-14.286,6.41-14.286,14.286c0,7.876,6.41,14.286,14.286,14.286
+ c7.876,0,14.286-6.41,14.286-14.286C242.857,254.03,236.448,247.62,228.571,247.62z M228.571,266.668
+ c-2.629,0-4.762-2.133-4.762-4.762c0-2.629,2.133-4.762,4.762-4.762c2.629,0,4.762,2.133,4.762,4.762
+ C233.333,264.535,231.2,266.668,228.571,266.668z"/>
+ <rect x="166.667" y="285.715" width="9.524" height="9.524"/>
+ <rect x="23.81" y="285.715" width="9.524" height="9.524"/>
+ <rect x="4.762" y="285.715" width="9.524" height="9.524"/>
+ <path d="M223.81,195.238v-4.762c0-13.129-10.681-23.81-23.81-23.81h-61.905c-13.129,0-23.81,10.681-23.81,23.81h9.524
+ c0-7.876,6.41-14.286,14.286-14.286H200c7.876,0,14.286,6.41,14.286,14.286v4.762c0,7.876-6.41,14.286-14.286,14.286h-45.648
+ l10.919-10.919l-6.733-6.733l-22.414,22.414l22.414,22.414l6.733-6.733l-10.919-10.919H200
+ C213.129,219.048,223.81,208.368,223.81,195.238z"/>
+ <path d="M47.619,17.053v16.281h9.524V4.763H28.571v9.524h5.51C13.176,29.396,0,54.311,0,80.953h9.524
+ C9.524,54.149,24.586,29.349,47.619,17.053z"/>
+ <path d="M144.852,47.62h-16.281v9.524h28.571V28.572h-9.524v5.51C132.51,13.177,107.595,0.001,80.952,0.001v9.524
+ C107.757,9.525,132.557,24.587,144.852,47.62z"/>
+ <polygon points="52.381,52.382 52.381,57.482 45.381,53.105 40.333,61.181 46.671,65.139 41.352,66.915 44.362,75.944
+ 57.143,71.686 71.967,80.953 57.143,90.22 44.362,85.962 41.352,94.991 46.671,96.767 40.333,100.725 45.381,108.801
+ 52.381,104.425 52.381,109.525 61.905,109.525 61.905,98.472 76.19,89.543 76.19,98.415 62.857,116.191 70.476,121.905
+ 76.19,114.282 76.19,128.572 85.714,128.572 85.714,114.282 91.429,121.905 99.048,116.191 85.714,98.415 85.714,89.543
+ 100,98.472 100,109.525 109.524,109.525 109.524,104.425 116.524,108.801 121.571,100.725 115.233,96.767 120.552,94.991
+ 117.543,85.962 104.762,90.22 89.938,80.953 104.762,71.686 117.543,75.944 120.552,66.915 115.233,65.139 121.571,61.181
+ 116.524,53.105 109.524,57.482 109.524,52.382 100,52.382 100,63.434 85.714,72.363 85.714,63.491 99.048,45.715 91.429,40.001
+ 85.714,47.625 85.714,33.334 76.19,33.334 76.19,47.625 70.476,40.001 62.857,45.715 76.19,63.491 76.19,72.363 61.905,63.434
+ 61.905,52.382 "/>
+ </g>
+ </g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/images/left_climate.PNG b/images/left_climate.PNG
new file mode 100644
index 0000000..ad1e6ba
--- /dev/null
+++ b/images/left_climate.PNG
Binary files differ
diff --git a/images/rear_ws.svg b/images/rear_ws.svg
new file mode 100644
index 0000000..d246ec1
--- /dev/null
+++ b/images/rear_ws.svg
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:svg="http://www.w3.org/2000/svg" id="svg2" viewBox="0 0 81.786 59.286" version="1.1">
+ <g id="layer1" transform="translate(-175.59 -219.84)">
+ <rect id="rect4577" style="color:#000000" rx="1.3393" ry="1.0714" height="34.464" width="66.786" stroke="#327dc8" stroke-linecap="round" y="227.34" x="183.09" stroke-width="5" fill="none"/>
+ <g id="g5273">
+ <g id="g5228" transform="translate(.22628)">
+ <g id="g5224" stroke="#327dc8">
+ <path id="path5216" stroke-width="5" fill="none" d="m218.14 244.22c-6.9199 8.9459 3.4253 17.17 1.014 24.731-0.28791 0.90275-0.7577 1.796-1.4605 2.68"/>
+ <path id="path5222" stroke-width="1px" stroke-linecap="round" fill="#327dc8" d="m216.17 236.18-5.1786 11.071h10.268z"/>
+ </g>
+ </g>
+ <g id="g5228-1" transform="translate(15.539)">
+ <g id="g5224-5" stroke="#327dc8">
+ <path id="path5216-4" stroke-width="5" fill="none" d="m218.14 244.22c-6.9199 8.9459 3.4253 17.17 1.014 24.731-0.28791 0.90275-0.7577 1.796-1.4605 2.68"/>
+ <path id="path5222-2" stroke-width="1px" stroke-linecap="round" fill="#327dc8" d="m216.17 236.18-5.1786 11.071h10.268z"/>
+ </g>
+ </g>
+ <g id="g5228-0" transform="translate(-15.086)">
+ <g id="g5224-9" stroke="#327dc8">
+ <path id="path5216-7" stroke-width="5" fill="none" d="m218.14 244.22c-6.9199 8.9459 3.4253 17.17 1.014 24.731-0.28791 0.90275-0.7577 1.796-1.4605 2.68"/>
+ <path id="path5222-3" stroke-width="1px" stroke-linecap="round" fill="#327dc8" d="m216.17 236.18-5.1786 11.071h10.268z"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ <metadata>
+ <rdf:RDF>
+ <cc:Work>
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ <cc:license rdf:resource="http://creativecommons.org/licenses/publicdomain/"/>
+ <dc:publisher>
+ <cc:Agent rdf:about="http://openclipart.org/">
+ <dc:title>Openclipart</dc:title>
+ </cc:Agent>
+ </dc:publisher>
+ <dc:title>rear window heating</dc:title>
+ <dc:date>2013-05-07T09:13:11</dc:date>
+ <dc:description>Icon for rear window heating like found in cars</dc:description>
+ <dc:source>http://openclipart.org/detail/177851/rear-window-heating-by-dblade82-177851</dc:source>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>DBlade82</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>car</rdf:li>
+ <rdf:li>icon</rdf:li>
+ <rdf:li>rear window heating</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ </cc:Work>
+ <cc:License rdf:about="http://creativecommons.org/licenses/publicdomain/">
+ <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
+ <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
+ <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/images/right_climate.PNG b/images/right_climate.PNG
new file mode 100644
index 0000000..410d160
--- /dev/null
+++ b/images/right_climate.PNG
Binary files differ
diff --git a/images/wind_in.svg b/images/wind_in.svg
new file mode 100644
index 0000000..5608ff1
--- /dev/null
+++ b/images/wind_in.svg
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 512.853 512.853" style="enable-background:new 0 0 512.853 512.853;" xml:space="preserve">
+<g transform="translate(1 1)">
+ <g>
+ <path d="M471.747,217.88c-22.187-1.707-40.107-11.947-50.347-28.16l-2.56-4.267c-13.653-23.04-38.4-36.693-64.853-36.693H242.2
+ c-21.333,0-41.813,9.387-56.32,25.6l-11.947,11.947c-7.787,8.686-16.524,16.315-26.019,22.751
+ c-28.247-21.901-46.514-56.134-46.514-94.431c0-5.12-3.413-8.533-8.533-8.533c-5.12,0-8.533,3.413-8.533,8.533
+ c0,41.337,18.623,78.532,47.888,103.624c-13.526,6.763-28.206,11.307-43.621,13.283l-52.053,6.827
+ C15.213,241.773-1,259.693-1,281.027v38.4c0,23.893,18.773,42.667,42.667,42.667H76.53c4.095,24.134,25.217,42.667,50.47,42.667
+ s46.375-18.533,50.47-42.667h172.127c4.095,24.134,25.217,42.667,50.47,42.667c25.253,0,46.375-18.533,50.47-42.667h17.797
+ c23.893,0,42.667-18.773,43.52-41.813v-59.733C511.853,238.36,493.933,219.587,471.747,217.88z M127,387.693
+ c-18.773,0-34.133-15.36-34.133-34.133c0-18.773,15.36-34.133,34.133-34.133c18.773,0,34.133,15.36,34.133,34.133
+ C161.133,372.333,145.773,387.693,127,387.693z M400.067,387.693c-18.773,0-34.133-15.36-34.133-34.133
+ c0-18.773,15.36-34.133,34.133-34.133c18.773,0,34.133,15.36,34.133,34.133C434.2,372.333,418.84,387.693,400.067,387.693z
+ M493.933,319.427c0,14.507-11.093,25.6-25.6,25.6h-17.797c-2.881-16.98-14.192-31.177-29.444-38.106
+ c-0.338-0.155-0.674-0.314-1.017-0.462c-0.214-0.092-0.432-0.175-0.648-0.264c-0.553-0.229-1.109-0.453-1.672-0.662
+ c-0.152-0.056-0.306-0.108-0.459-0.163c-0.625-0.226-1.256-0.442-1.893-0.644c-0.138-0.044-0.276-0.085-0.415-0.127
+ c-0.648-0.199-1.302-0.387-1.962-0.56c-0.146-0.038-0.292-0.076-0.439-0.113c-0.648-0.164-1.301-0.316-1.96-0.455
+ c-0.166-0.035-0.331-0.071-0.497-0.104c-0.636-0.128-1.277-0.242-1.922-0.346c-0.191-0.031-0.381-0.064-0.573-0.093
+ c-0.621-0.093-1.248-0.17-1.877-0.24c-0.213-0.024-0.425-0.052-0.639-0.074c-0.629-0.062-1.263-0.107-1.899-0.146
+ c-0.21-0.013-0.417-0.033-0.628-0.043c-0.837-0.041-1.68-0.065-2.529-0.065c-0.849,0-1.692,0.024-2.529,0.065
+ c-0.21,0.01-0.418,0.03-0.628,0.043c-0.636,0.039-1.27,0.084-1.899,0.146c-0.214,0.021-0.426,0.05-0.639,0.074
+ c-0.629,0.07-1.256,0.148-1.877,0.24c-0.192,0.029-0.382,0.062-0.574,0.093c-0.645,0.104-1.285,0.218-1.921,0.345
+ c-0.167,0.034-0.332,0.069-0.498,0.104c-0.658,0.139-1.311,0.291-1.959,0.455c-0.146,0.037-0.293,0.074-0.439,0.113
+ c-0.66,0.174-1.314,0.361-1.962,0.561c-0.138,0.042-0.276,0.083-0.414,0.127c-0.638,0.202-1.268,0.418-1.894,0.644
+ c-0.152,0.055-0.305,0.107-0.457,0.163c-0.564,0.21-1.121,0.434-1.675,0.664c-0.215,0.089-0.432,0.172-0.645,0.263
+ c-0.343,0.148-0.68,0.308-1.019,0.463c-15.25,6.93-26.561,21.126-29.441,38.105H177.47c-2.881-16.979-14.19-31.174-29.439-38.104
+ c-0.34-0.156-0.677-0.316-1.021-0.464c-0.213-0.091-0.43-0.174-0.645-0.263c-0.554-0.229-1.111-0.453-1.675-0.664
+ c-0.151-0.056-0.305-0.108-0.457-0.163c-0.626-0.226-1.257-0.442-1.894-0.644c-0.137-0.043-0.276-0.084-0.414-0.127
+ c-0.648-0.199-1.302-0.387-1.962-0.561c-0.146-0.038-0.292-0.076-0.439-0.113c-0.648-0.164-1.301-0.316-1.96-0.455
+ c-0.166-0.035-0.331-0.071-0.497-0.104c-0.636-0.128-1.277-0.242-1.922-0.346c-0.191-0.031-0.381-0.064-0.573-0.093
+ c-0.621-0.093-1.248-0.17-1.877-0.24c-0.213-0.024-0.425-0.052-0.639-0.074c-0.629-0.062-1.263-0.107-1.899-0.146
+ c-0.21-0.013-0.417-0.033-0.628-0.043c-0.837-0.041-1.68-0.065-2.529-0.065c-0.849,0-1.692,0.024-2.529,0.065
+ c-0.21,0.01-0.418,0.03-0.628,0.043c-0.636,0.039-1.27,0.084-1.899,0.146c-0.214,0.021-0.426,0.05-0.639,0.074
+ c-0.629,0.07-1.256,0.148-1.877,0.24c-0.192,0.029-0.382,0.062-0.573,0.093c-0.645,0.104-1.286,0.218-1.922,0.346
+ c-0.166,0.033-0.332,0.069-0.497,0.104c-0.659,0.139-1.312,0.291-1.96,0.455c-0.146,0.037-0.293,0.074-0.439,0.113
+ c-0.66,0.174-1.313,0.361-1.962,0.56c-0.138,0.042-0.277,0.083-0.415,0.127c-0.637,0.202-1.267,0.418-1.893,0.644
+ c-0.153,0.055-0.307,0.107-0.459,0.163c-0.563,0.21-1.119,0.433-1.672,0.662c-0.216,0.089-0.434,0.172-0.648,0.264
+ c-0.342,0.148-0.678,0.307-1.017,0.462c-15.252,6.929-26.563,21.126-29.444,38.106H41.667c-14.507,0-25.6-11.093-25.6-25.6v-38.4
+ c0-12.8,9.387-23.893,22.187-24.747l52.053-6.827c20.828-2.367,40.602-8.941,58.31-19.128
+ c20.99,13.186,45.769,20.835,72.25,20.835h30.72l-19.627,19.627c-3.413,3.413-3.413,8.533,0,11.947
+ c1.707,1.707,3.413,2.56,5.973,2.56s4.267-0.853,5.973-2.56l32.673-32.673c2.51-1.395,4.02-4.034,4.02-7.434
+ s-1.511-6.038-4.02-7.434l-32.673-32.673c-3.413-3.413-8.533-3.413-11.947,0s-3.413,8.533,0,11.947l19.627,19.627h-30.72
+ c-20.371,0-39.592-5.171-56.42-14.26c8.048-6.099,15.52-13.027,22.287-20.727l11.947-13.653
+ c11.093-12.8,26.453-19.627,43.52-19.627h111.787c20.48,0,39.253,11.093,49.493,27.307l2.56,4.267
+ c12.8,21.333,36.693,34.987,64,36.693c13.653,0.853,23.893,11.947,23.893,25.6V319.427z"/>
+ </g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/images/wind_shield.svg b/images/wind_shield.svg
new file mode 100644
index 0000000..bca6032
--- /dev/null
+++ b/images/wind_shield.svg
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 490.001 490.001" style="enable-background:new 0 0 490.001 490.001;" xml:space="preserve">
+<g>
+ <path d="M485.607,150.221c-31.245-31.245-67.633-55.777-108.154-72.916c-41.959-17.747-86.523-26.746-132.452-26.746
+ c-45.93,0-90.494,8.999-132.454,26.746c-40.521,17.14-76.909,41.673-108.154,72.918c-4.85,4.851-5.792,12.373-2.288,18.27
+ l116,195.195c2.704,4.549,7.604,7.337,12.895,7.337h14.386c1.864,6.991,4.364,13.725,6.786,20.24
+ c2.314,6.224,4.5,12.103,5.995,17.789c1.464,5.566,2.175,10.6,2.175,15.388c0,8.284,6.716,15,15,15s15-6.716,15-15
+ c0-7.397-1.034-14.927-3.162-23.016c-1.872-7.122-4.423-13.982-6.89-20.616c-1.247-3.354-2.453-6.606-3.538-9.785l46.124,0
+ c1.862,6.987,4.363,13.724,6.786,20.241c2.314,6.224,4.5,12.103,5.995,17.788c1.464,5.568,2.175,10.603,2.175,15.389
+ c0,8.284,6.716,15,15,15c8.284,0,15-6.716,15-15c0-7.396-1.034-14.924-3.162-23.016c-1.872-7.122-4.423-13.982-6.89-20.616
+ c-1.248-3.355-2.454-6.607-3.538-9.786l46.124,0c1.862,6.988,4.363,13.725,6.786,20.241c2.313,6.222,4.499,12.099,5.995,17.788
+ c1.464,5.568,2.175,10.603,2.175,15.389c0,8.284,6.716,15,15,15s15-6.716,15-15c0-7.396-1.034-14.924-3.162-23.017
+ c-1.874-7.126-4.424-13.983-6.89-20.615c-1.248-3.355-2.454-6.607-3.538-9.786H359c5.292,0,10.191-2.788,12.895-7.337l116-195.196
+ C491.4,162.594,490.457,155.072,485.607,150.221z M327.544,341.024c0.356-2.797,0.927-5.704,1.736-8.778
+ c1.494-5.684,3.68-11.563,5.995-17.788c2.466-6.632,5.016-13.489,6.89-20.616c2.127-8.092,3.162-15.62,3.162-23.016
+ c0-7.395-1.034-14.923-3.162-23.017c-0.958-3.643-2.094-7.216-3.304-10.726h12.42c5.694,0,8.546-6.884,4.519-10.911l-27.511-27.511
+ c-2.496-2.496-6.543-2.496-9.039,0l-27.511,27.511c-4.026,4.026-1.175,10.911,4.519,10.911h10.719
+ c0.062,0.188,0.109,0.379,0.179,0.566c2.314,6.224,4.5,12.102,5.995,17.787c1.464,5.569,2.176,10.604,2.176,15.389
+ c0,4.786-0.711,9.82-2.175,15.388c-1.497,5.69-3.682,11.567-5.995,17.789c-2.467,6.635-5.019,13.497-6.89,20.616
+ c-1.498,5.699-2.443,11.115-2.877,16.405l-47.335,0c0.356-2.797,0.927-5.704,1.736-8.779c1.494-5.684,3.68-11.563,5.995-17.788
+ c2.467-6.634,5.018-13.494,6.89-20.616c2.127-8.092,3.162-15.62,3.162-23.016c0-7.395-1.034-14.923-3.162-23.016
+ c-0.957-3.642-2.093-7.215-3.304-10.727h11.143c5.694,0,8.546-6.884,4.519-10.911l-27.511-27.511c-2.496-2.496-6.543-2.496-9.039,0
+ l-27.511,27.511c-4.026,4.026-1.175,10.911,4.519,10.911h11.996c0.062,0.188,0.109,0.379,0.179,0.566
+ c2.315,6.226,4.501,12.105,5.995,17.787c1.464,5.569,2.176,10.604,2.176,15.389c0,4.786-0.711,9.82-2.175,15.389
+ c-1.495,5.686-3.681,11.563-5.995,17.788c-2.467,6.635-5.019,13.497-6.89,20.616c-1.498,5.699-2.443,11.116-2.877,16.406l-47.335,0
+ c0.356-2.797,0.927-5.704,1.735-8.778c1.496-5.688,3.681-11.566,5.995-17.789c2.467-6.634,5.018-13.494,6.89-20.615
+ c2.127-8.09,3.162-15.619,3.162-23.017c0-7.396-1.034-14.926-3.162-23.016c-0.957-3.642-2.093-7.215-3.304-10.727h9.866
+ c5.694,0,8.546-6.884,4.519-10.911l-27.511-27.511c-2.496-2.496-6.543-2.496-9.039,0l-27.511,27.511
+ c-4.026,4.026-1.175,10.911,4.519,10.911h13.272c0.062,0.188,0.109,0.379,0.179,0.566c2.315,6.226,4.501,12.105,5.995,17.788
+ c1.464,5.567,2.175,10.601,2.175,15.388c0,4.788-0.711,9.821-2.175,15.389c-1.495,5.686-3.681,11.563-5.995,17.788
+ c-2.466,6.633-5.017,13.491-6.89,20.616c-1.498,5.699-2.443,11.116-2.877,16.406h-2.87L33.964,163.378
+ c57.552-53.497,132.041-82.819,211.038-82.819c78.995,0,153.482,29.321,211.035,82.817L350.466,341.024H327.544z"/>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
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: ,
+ ),
+ );
+ }),
+ ),
+ ),
+ );
+ }
+}
diff --git a/pubspec.yaml b/pubspec.yaml
new file mode 100644
index 0000000..5f0b20e
--- /dev/null
+++ b/pubspec.yaml
@@ -0,0 +1,95 @@
+name: flutter_hvac
+description: A new Flutter project.
+
+# The following line prevents the package from being accidentally published to
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+# The following defines the version and build number for your application.
+# A version number is three numbers separated by dots, like 1.2.43
+# followed by an optional build number separated by a +.
+# Both the version and the builder number may be overridden in flutter
+# build by specifying --build-name and --build-number, respectively.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
+# Read more about iOS versioning at
+# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
+version: 1.0.0+1
+
+environment:
+ sdk: ">=2.12.0 <3.0.0"
+
+# Dependencies specify other packages that your package needs in order to work.
+# To automatically upgrade your package dependencies to the latest versions
+# consider running `flutter pub upgrade --major-versions`. Alternatively,
+# dependencies can be manually updated by changing the version numbers below to
+# the latest version available on pub.dev. To see which dependencies have newer
+# versions available, run `flutter pub outdated`.
+dependencies:
+ flutter:
+ sdk: flutter
+
+
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+ cupertino_icons: ^1.0.2
+ flutter_svg_provider: ^1.0.3
+ flutter_hooks: ^0.18.3
+ slider_controller: ^0.0.3
+ scrollable_positioned_list: ^0.3.1
+ flutter_riverpod: ^1.0.3
+ yaml: ^3.1.1
+
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+ # The "flutter_lints" package below contains a set of recommended lints to
+ # encourage good coding practices. The lint set provided by the package is
+ # activated in the `analysis_options.yaml` file located at the root of your
+ # package. See that file for information about deactivating specific lint
+ # rules and activating additional ones.
+ flutter_lints: ^1.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter.
+flutter:
+
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
+
+ # To add assets to your application, add an assets section, like this:
+ assets:
+ - images/
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware.
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/assets-and-images/#from-packages
+
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/custom-fonts/#from-packages