1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.android.car.kitchensink.hvac; 18 19 import static java.lang.Integer.toHexString; 20 21 import android.car.hardware.CarPropertyConfig; 22 import android.car.hardware.CarPropertyValue; 23 import android.car.hardware.hvac.CarHvacManager; 24 import android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat; 25 import android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow; 26 import android.hardware.automotive.vehicle.V2_0.VehicleUnit; 27 import android.os.Bundle; 28 import android.os.Handler; 29 import android.util.Log; 30 import android.view.LayoutInflater; 31 import android.view.View; 32 import android.view.ViewGroup; 33 import android.widget.Button; 34 import android.widget.RadioButton; 35 import android.widget.RadioGroup; 36 import android.widget.TextView; 37 import android.widget.Toast; 38 import android.widget.ToggleButton; 39 40 import androidx.fragment.app.Fragment; 41 42 import com.google.android.car.kitchensink.KitchenSinkActivity; 43 import com.google.android.car.kitchensink.R; 44 45 import java.util.List; 46 47 public class HvacTestFragment extends Fragment { 48 private final boolean DBG = true; 49 private final String TAG = "HvacTestFragment"; 50 private static final float TEMP_STEP = 0.5f; 51 private RadioButton mRbFanPositionFace; 52 private RadioButton mRbFanPositionFloor; 53 private RadioButton mRbFanPositionFaceAndFloor; 54 private RadioButton mRbFanPositionDefrost; 55 private RadioButton mRbFanPositionDefrostAndFloor; 56 private ToggleButton mTbAc; 57 private ToggleButton mTbAuto; 58 private ToggleButton mTbDefrostFront; 59 private ToggleButton mTbDefrostRear; 60 private ToggleButton mTbDual; 61 private ToggleButton mTbMaxAc; 62 private ToggleButton mTbMaxDefrost; 63 private ToggleButton mTbRecirc; 64 private ToggleButton mTbAutoRecirc; 65 private ToggleButton mTbTempDisplayUnit; 66 private ToggleButton mTbPower; 67 private Button mTbPowerAndAc; 68 private TextView mTvFanSpeed; 69 private TextView mTvDTemp; 70 private TextView mTvPTemp; 71 private TextView mTvOutsideTemp; 72 private int mCurFanSpeed; 73 private int mMinFanSpeed; 74 private int mMaxFanSpeed; 75 private float mCurDTemp; 76 private float mCurPTemp; 77 private float mMinDTemp; 78 private float mMinPTemp; 79 private float mMaxDTemp; 80 private float mMaxPTemp; 81 private CarHvacManager mCarHvacManager; 82 private int mZoneForAcOn; 83 private int mZoneForSetTempD; 84 private int mZoneForSetTempP; 85 private int mZoneForFanSpeed; 86 private int mZoneForFanPosition; 87 private List<CarPropertyConfig> mCarPropertyConfigs; 88 private View mHvacView; 89 90 private final CarHvacManager.CarHvacEventCallback mHvacCallback = 91 new CarHvacManager.CarHvacEventCallback() { 92 @Override 93 public void onChangeEvent(final CarPropertyValue value) { 94 int zones = value.getAreaId(); 95 switch (value.getPropertyId()) { 96 case CarHvacManager.ID_OUTSIDE_AIR_TEMP: 97 mTvOutsideTemp.setText(String.valueOf(value.getValue())); 98 break; 99 case CarHvacManager.ID_ZONED_DUAL_ZONE_ON: 100 mTbDual.setChecked((boolean) value.getValue()); 101 break; 102 case CarHvacManager.ID_ZONED_AC_ON: 103 mTbAc.setChecked((boolean) value.getValue()); 104 break; 105 case CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON: 106 mTbAuto.setChecked((boolean) value.getValue()); 107 break; 108 case CarHvacManager.ID_ZONED_FAN_DIRECTION: 109 switch ((int) value.getValue()) { 110 case CarHvacManager.FAN_DIRECTION_FACE: 111 mRbFanPositionFace.setChecked(true); 112 break; 113 case CarHvacManager.FAN_DIRECTION_FLOOR: 114 mRbFanPositionFloor.setChecked(true); 115 break; 116 case (CarHvacManager.FAN_DIRECTION_FACE | 117 CarHvacManager.FAN_DIRECTION_FLOOR): 118 mRbFanPositionFaceAndFloor.setChecked(true); 119 break; 120 case CarHvacManager.FAN_DIRECTION_DEFROST: 121 mRbFanPositionDefrost.setChecked(true); 122 break; 123 case (CarHvacManager.FAN_DIRECTION_DEFROST | 124 CarHvacManager.FAN_DIRECTION_FLOOR): 125 mRbFanPositionDefrostAndFloor.setChecked(true); 126 break; 127 default: 128 if (DBG) { 129 Log.e(TAG, "Unknown fan position: " + value.getValue()); 130 } 131 break; 132 } 133 break; 134 case CarHvacManager.ID_ZONED_MAX_AC_ON: 135 mTbMaxAc.setChecked((boolean) value.getValue()); 136 break; 137 case CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON: 138 mTbRecirc.setChecked((boolean) value.getValue()); 139 break; 140 case CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT: 141 if ((zones & mZoneForFanSpeed) == mZoneForFanSpeed) { 142 mCurFanSpeed = (int) value.getValue(); 143 mTvFanSpeed.setText(String.valueOf(mCurFanSpeed)); 144 } 145 break; 146 case CarHvacManager.ID_ZONED_TEMP_SETPOINT: 147 if ((zones & mZoneForSetTempD) == mZoneForSetTempD) { 148 mCurDTemp = (float) value.getValue(); 149 mTvDTemp.setText(String.valueOf(mCurDTemp)); 150 } 151 if ((zones & mZoneForSetTempP) == mZoneForSetTempP) { 152 mCurPTemp = (float) value.getValue(); 153 mTvPTemp.setText(String.valueOf(mCurPTemp)); 154 } 155 break; 156 case CarHvacManager.ID_ZONED_MAX_DEFROST_ON: 157 mTbMaxDefrost.setChecked((boolean) value.getValue()); 158 break; 159 case CarHvacManager.ID_WINDOW_DEFROSTER_ON: 160 if ((zones & VehicleAreaWindow.FRONT_WINDSHIELD) 161 == VehicleAreaWindow.FRONT_WINDSHIELD) { 162 mTbDefrostFront.setChecked((boolean) value.getValue()); 163 } 164 if ((zones & VehicleAreaWindow.REAR_WINDSHIELD) 165 == VehicleAreaWindow.REAR_WINDSHIELD) { 166 mTbDefrostRear.setChecked((boolean) value.getValue()); 167 } 168 break; 169 case CarHvacManager.ID_ZONED_HVAC_AUTO_RECIRC_ON: 170 mTbAutoRecirc.setChecked((boolean) value.getValue()); 171 break; 172 case CarHvacManager.ID_TEMPERATURE_DISPLAY_UNITS: 173 mTbTempDisplayUnit.setChecked( 174 ((Integer) value.getValue()).equals(VehicleUnit.FAHRENHEIT)); 175 break; 176 case CarHvacManager.ID_ZONED_HVAC_POWER_ON: 177 mTbPower.setChecked((boolean) value.getValue()); 178 break; 179 default: 180 Log.d(TAG, "onChangeEvent(): unknown property id = " + value 181 .getPropertyId()); 182 } 183 } 184 185 @Override 186 public void onErrorEvent(final int propertyId, final int zone) { 187 Log.w(TAG, "Error: propertyId=0x" + toHexString(propertyId) 188 + ", zone=0x" + toHexString(zone)); 189 } 190 }; 191 192 @Override onCreate(Bundle savedInstanceState)193 public void onCreate(Bundle savedInstanceState) { 194 195 super.onCreate(savedInstanceState); 196 197 } 198 199 @Override onDestroy()200 public void onDestroy() { 201 super.onDestroy(); 202 mCarHvacManager.unregisterCallback(mHvacCallback); 203 } 204 205 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance)206 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) { 207 mHvacView = inflater.inflate(R.layout.hvac_test, container, false); 208 final Runnable r = () -> { 209 mCarHvacManager = ((KitchenSinkActivity) getActivity()).getHvacManager(); 210 mCarHvacManager.registerCallback(mHvacCallback); 211 mCarPropertyConfigs = mCarHvacManager.getPropertyList(); 212 for (CarPropertyConfig prop : mCarPropertyConfigs) { 213 int propId = prop.getPropertyId(); 214 215 if (DBG) { 216 Log.d(TAG, prop.toString()); 217 } 218 219 switch (propId) { 220 case CarHvacManager.ID_OUTSIDE_AIR_TEMP: 221 configureOutsideTemp(mHvacView, prop); 222 break; 223 case CarHvacManager.ID_ZONED_DUAL_ZONE_ON: 224 configureDualOn(mHvacView, prop); 225 break; 226 case CarHvacManager.ID_ZONED_AC_ON: 227 configureAcOn(mHvacView, prop); 228 break; 229 case CarHvacManager.ID_ZONED_FAN_DIRECTION: 230 configureFanPosition(mHvacView, prop); 231 break; 232 case CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT: 233 configureFanSpeed(mHvacView, prop); 234 break; 235 case CarHvacManager.ID_ZONED_TEMP_SETPOINT: 236 configureTempSetpoint(mHvacView, prop); 237 break; 238 case CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON: 239 configureAutoModeOn(mHvacView, prop); 240 break; 241 case CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON: 242 configureRecircOn(mHvacView, prop); 243 break; 244 case CarHvacManager.ID_ZONED_MAX_AC_ON: 245 configureMaxAcOn(mHvacView, prop); 246 break; 247 case CarHvacManager.ID_ZONED_MAX_DEFROST_ON: 248 configureMaxDefrostOn(mHvacView, prop); 249 break; 250 case CarHvacManager.ID_WINDOW_DEFROSTER_ON: 251 configureDefrosterOn(mHvacView, prop); 252 break; 253 case CarHvacManager.ID_ZONED_HVAC_AUTO_RECIRC_ON: 254 configureAutoRecircOn(mHvacView, prop); 255 break; 256 case CarHvacManager.ID_TEMPERATURE_DISPLAY_UNITS: 257 configureTempDisplayUnit(mHvacView, prop); 258 break; 259 case CarHvacManager.ID_ZONED_HVAC_POWER_ON: 260 configurePowerOn(mHvacView, prop); 261 configurePowerAndAcOn(mHvacView, prop); 262 break; 263 default: 264 Log.w(TAG, "propertyId " + propId + " is not handled"); 265 break; 266 } 267 } 268 269 mTvFanSpeed = (TextView) mHvacView.findViewById(R.id.tvFanSpeed); 270 mTvFanSpeed.setText(String.valueOf(mCurFanSpeed)); 271 mTvDTemp = (TextView) mHvacView.findViewById(R.id.tvDTemp); 272 mTvDTemp.setText(String.valueOf(mCurDTemp)); 273 mTvPTemp = (TextView) mHvacView.findViewById(R.id.tvPTemp); 274 mTvPTemp.setText(String.valueOf(mCurPTemp)); 275 mTvOutsideTemp = (TextView) mHvacView.findViewById(R.id.tvOutsideTemp); 276 mTvOutsideTemp.setText("N/A"); 277 }; 278 279 ((KitchenSinkActivity) getActivity()).requestRefreshManager(r, 280 new Handler(getContext().getMainLooper())); 281 282 if (DBG) { 283 Log.d(TAG, "Starting HvacTestFragment"); 284 } 285 286 return mHvacView; 287 } 288 configureOutsideTemp(View v, CarPropertyConfig prop)289 private void configureOutsideTemp(View v, CarPropertyConfig prop) { 290 // Do nothing 291 } 292 configureDualOn(View v, CarPropertyConfig prop)293 private void configureDualOn(View v, CarPropertyConfig prop) { 294 int temp = prop.getFirstAndOnlyAreaId(); 295 mTbDual = (ToggleButton) v.findViewById(R.id.tbDual); 296 mTbDual.setEnabled(true); 297 298 mTbDual.setOnClickListener(view -> { 299 // TODO handle zone properly 300 setBooleanProperty(CarHvacManager.ID_ZONED_DUAL_ZONE_ON, temp, mTbDual.isChecked()); 301 }); 302 } 303 configureAcOn(View v, CarPropertyConfig prop)304 private void configureAcOn(View v, CarPropertyConfig prop) { 305 mZoneForAcOn = prop.getFirstAndOnlyAreaId(); 306 mTbAc = (ToggleButton) v.findViewById(R.id.tbAc); 307 mTbAc.setEnabled(true); 308 309 mTbAc.setOnClickListener(view -> { 310 // TODO handle zone properly 311 setBooleanProperty(CarHvacManager.ID_ZONED_AC_ON, mZoneForAcOn, mTbAc.isChecked()); 312 }); 313 } 314 configureAutoModeOn(View v, CarPropertyConfig prop)315 private void configureAutoModeOn(View v, CarPropertyConfig prop) { 316 int temp = prop.getFirstAndOnlyAreaId(); 317 mTbAuto = (ToggleButton) v.findViewById(R.id.tbAuto); 318 mTbAuto.setEnabled(true); 319 320 mTbAuto.setOnClickListener(view -> { 321 // TODO handle zone properly 322 setBooleanProperty(CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON, temp, 323 mTbAuto.isChecked()); 324 }); 325 } 326 configureFanPosition(View v, CarPropertyConfig prop)327 private void configureFanPosition(View v, CarPropertyConfig prop) { 328 mZoneForFanPosition = prop.getFirstAndOnlyAreaId(); 329 RadioGroup rg = (RadioGroup) v.findViewById(R.id.rgFanPosition); 330 rg.setOnCheckedChangeListener((group, checkedId) -> { 331 int position; 332 switch (checkedId) { 333 case R.id.rbPositionFace: 334 position = CarHvacManager.FAN_DIRECTION_FACE; 335 break; 336 case R.id.rbPositionFloor: 337 position = CarHvacManager.FAN_DIRECTION_FLOOR; 338 break; 339 case R.id.rbPositionFaceAndFloor: 340 position = (CarHvacManager.FAN_DIRECTION_FACE | 341 CarHvacManager.FAN_DIRECTION_FLOOR); 342 break; 343 case R.id.rbPositionDefrost: 344 position = CarHvacManager.FAN_DIRECTION_DEFROST; 345 break; 346 case R.id.rbPositionDefrostAndFloor: 347 position = (CarHvacManager.FAN_DIRECTION_DEFROST | 348 CarHvacManager.FAN_DIRECTION_FLOOR); 349 break; 350 default: 351 throw new IllegalStateException("Unexpected fan position: " + checkedId); 352 } 353 try { 354 if (mCarHvacManager.isPropertyAvailable(CarHvacManager.ID_ZONED_FAN_DIRECTION, 355 mZoneForFanSpeed)) { 356 mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_DIRECTION, 357 mZoneForFanPosition, 358 position); 359 } 360 } catch (IllegalStateException e) { 361 Log.e(TAG, "Failed to set HVAC integer property", e); 362 Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); 363 } 364 }); 365 366 mRbFanPositionFace = (RadioButton) v.findViewById(R.id.rbPositionFace); 367 mRbFanPositionFace.setClickable(true); 368 mRbFanPositionFloor = (RadioButton) v.findViewById(R.id.rbPositionFloor); 369 mRbFanPositionFloor.setClickable(true); 370 mRbFanPositionFaceAndFloor = (RadioButton) v.findViewById(R.id.rbPositionFaceAndFloor); 371 mRbFanPositionFaceAndFloor.setClickable(true); 372 mRbFanPositionDefrost = (RadioButton) v.findViewById(R.id.rbPositionDefrost); 373 mRbFanPositionDefrost.setClickable(true); 374 mRbFanPositionDefrostAndFloor = (RadioButton) v.findViewById( 375 R.id.rbPositionDefrostAndFloor); 376 mRbFanPositionDefrostAndFloor.setClickable(true); 377 } 378 configureFanSpeed(View v, CarPropertyConfig prop)379 private void configureFanSpeed(View v, CarPropertyConfig prop) { 380 381 mZoneForFanSpeed = prop.getFirstAndOnlyAreaId(); 382 mMaxFanSpeed = (Integer) prop.getMaxValue(mZoneForFanSpeed); 383 mMinFanSpeed = (Integer) prop.getMinValue(mZoneForFanSpeed); 384 385 try { 386 mCurFanSpeed = mCarHvacManager.getIntProperty( 387 CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT, 388 mZoneForFanSpeed); 389 } catch (IllegalStateException e) { 390 Log.e(TAG, "Failed to get HVAC int property", e); 391 } 392 393 Button btnFanSpeedUp = (Button) v.findViewById(R.id.btnFanSpeedUp); 394 btnFanSpeedUp.setEnabled(true); 395 btnFanSpeedUp.setOnClickListener(view -> changeFanSpeed(1)); 396 397 Button btnFanSpeedDn = (Button) v.findViewById(R.id.btnFanSpeedDn); 398 btnFanSpeedDn.setEnabled(true); 399 btnFanSpeedDn.setOnClickListener(view -> changeFanSpeed(-1)); 400 } 401 changeFanSpeed(int change)402 private void changeFanSpeed(int change) { 403 int targetSpeed = mCurFanSpeed + change; 404 if (mMinFanSpeed < targetSpeed && targetSpeed < mMaxFanSpeed) { 405 mCurFanSpeed = targetSpeed; 406 mTvFanSpeed.setText(String.valueOf(mCurFanSpeed)); 407 try { 408 if (mCarHvacManager.isPropertyAvailable( 409 CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT, mZoneForFanSpeed)) { 410 mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT, 411 mZoneForFanSpeed, mCurFanSpeed); 412 } 413 } catch (IllegalStateException e) { 414 Log.e(TAG, "Failed to set HVAC int property", e); 415 Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); 416 } 417 } 418 } 419 configureTempSetpoint(View v, CarPropertyConfig prop)420 private void configureTempSetpoint(View v, CarPropertyConfig prop) { 421 422 mZoneForSetTempD = 0; 423 if (prop.hasArea(VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_2_LEFT 424 | VehicleAreaSeat.ROW_2_CENTER)) { 425 mZoneForSetTempD = VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_2_LEFT 426 | VehicleAreaSeat.ROW_2_CENTER; 427 } 428 mZoneForSetTempP = 0; 429 if (prop.hasArea(VehicleAreaSeat.ROW_1_RIGHT | VehicleAreaSeat.ROW_2_RIGHT)) { 430 mZoneForSetTempP = VehicleAreaSeat.ROW_1_RIGHT | VehicleAreaSeat.ROW_2_RIGHT; 431 } 432 int[] areas = prop.getAreaIds(); 433 if (mZoneForSetTempD == 0 && areas.length > 1) { 434 mZoneForSetTempD = areas[0]; 435 } 436 if (mZoneForSetTempP == 0 && areas.length > 2) { 437 mZoneForSetTempP = areas[1]; 438 } 439 Button btnDTempUp = (Button) v.findViewById(R.id.btnDTempUp); 440 if (mZoneForSetTempD != 0) { 441 mMaxDTemp = (Float) prop.getMaxValue(mZoneForSetTempD); 442 mMinDTemp = (Float) prop.getMinValue(mZoneForSetTempD); 443 444 445 try { 446 mCurDTemp = mCarHvacManager.getFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT, 447 mZoneForSetTempD); 448 if (mCurDTemp < mMinDTemp) { 449 mCurDTemp = mMinDTemp; 450 } else if (mCurDTemp > mMaxDTemp) { 451 mCurDTemp = mMaxDTemp; 452 } 453 } catch (IllegalStateException e) { 454 Log.e(TAG, "Failed to get HVAC zoned temp property", e); 455 } 456 btnDTempUp.setEnabled(true); 457 btnDTempUp.setOnClickListener(view -> changeDriverTemperature(TEMP_STEP)); 458 459 Button btnDTempDn = (Button) v.findViewById(R.id.btnDTempDn); 460 btnDTempDn.setEnabled(true); 461 btnDTempDn.setOnClickListener(view -> changeDriverTemperature(-TEMP_STEP)); 462 } else { 463 btnDTempUp.setEnabled(false); 464 } 465 466 Button btnPTempUp = (Button) v.findViewById(R.id.btnPTempUp); 467 if (mZoneForSetTempP != 0) { 468 mMaxPTemp = (Float) prop.getMaxValue(mZoneForSetTempP); 469 mMinPTemp = (Float) prop.getMinValue(mZoneForSetTempP); 470 471 try { 472 mCurPTemp = mCarHvacManager.getFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT, 473 mZoneForSetTempP); 474 if (mCurPTemp < mMinPTemp) { 475 mCurPTemp = mMinPTemp; 476 } else if (mCurPTemp > mMaxPTemp) { 477 mCurPTemp = mMaxPTemp; 478 } 479 } catch (IllegalStateException e) { 480 Log.e(TAG, "Failed to get HVAC zoned temp property", e); 481 } 482 btnPTempUp.setEnabled(true); 483 btnPTempUp.setOnClickListener(view -> changePassengerTemperature(TEMP_STEP)); 484 485 Button btnPTempDn = (Button) v.findViewById(R.id.btnPTempDn); 486 btnPTempDn.setEnabled(true); 487 btnPTempDn.setOnClickListener(view -> changePassengerTemperature(-TEMP_STEP)); 488 } else { 489 btnPTempUp.setEnabled(false); 490 } 491 492 Button btnATempUp = (Button) v.findViewById(R.id.btnATempUp); 493 if (mZoneForSetTempD != 0 && mZoneForSetTempP != 0) { 494 btnATempUp.setEnabled(true); 495 btnATempUp.setOnClickListener(view -> { 496 changeDriverTemperature(TEMP_STEP); 497 changePassengerTemperature(TEMP_STEP); 498 }); 499 500 Button btnATempDn = (Button) v.findViewById(R.id.btnATempDn); 501 btnATempDn.setEnabled(true); 502 btnATempDn.setOnClickListener(view -> { 503 changeDriverTemperature(-TEMP_STEP); 504 changePassengerTemperature(-TEMP_STEP); 505 }); 506 } else { 507 btnATempUp.setEnabled(false); 508 } 509 } 510 changeDriverTemperature(float tempStep)511 private void changeDriverTemperature(float tempStep) { 512 float targetTemp = mCurDTemp + tempStep; 513 if (mMinDTemp < targetTemp && targetTemp < mMaxDTemp) { 514 mCurDTemp = targetTemp; 515 mTvDTemp.setText(String.valueOf(mCurDTemp)); 516 setFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT, mZoneForSetTempD, mCurDTemp); 517 } 518 } 519 changePassengerTemperature(float tempStep)520 private void changePassengerTemperature(float tempStep) { 521 float targetTemp = mCurPTemp + tempStep; 522 if (mMinPTemp < targetTemp && targetTemp < mMaxPTemp) { 523 mCurPTemp = targetTemp; 524 mTvPTemp.setText(String.valueOf(mCurPTemp)); 525 setFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT, mZoneForSetTempP, mCurPTemp); 526 } 527 } 528 configureDefrosterOn(View v, CarPropertyConfig prop1)529 private void configureDefrosterOn(View v, CarPropertyConfig prop1) { 530 if (prop1.hasArea(VehicleAreaWindow.FRONT_WINDSHIELD)) { 531 mTbDefrostFront = (ToggleButton) v.findViewById(R.id.tbDefrostFront); 532 mTbDefrostFront.setEnabled(true); 533 mTbDefrostFront.setOnClickListener(view -> { 534 setBooleanProperty(CarHvacManager.ID_WINDOW_DEFROSTER_ON, 535 VehicleAreaWindow.FRONT_WINDSHIELD, mTbDefrostFront.isChecked()); 536 }); 537 } 538 if (prop1.hasArea(VehicleAreaWindow.REAR_WINDSHIELD)) { 539 mTbDefrostRear = (ToggleButton) v.findViewById(R.id.tbDefrostRear); 540 mTbDefrostRear.setEnabled(true); 541 mTbDefrostRear.setOnClickListener(view -> { 542 setBooleanProperty(CarHvacManager.ID_WINDOW_DEFROSTER_ON, 543 VehicleAreaWindow.REAR_WINDSHIELD, mTbDefrostRear.isChecked()); 544 }); 545 } 546 } 547 configureRecircOn(View v, CarPropertyConfig prop)548 private void configureRecircOn(View v, CarPropertyConfig prop) { 549 int temp = prop.getFirstAndOnlyAreaId(); 550 mTbRecirc = (ToggleButton) v.findViewById(R.id.tbRecirc); 551 mTbRecirc.setEnabled(true); 552 553 mTbRecirc.setOnClickListener(view -> { 554 // TODO handle zone properly 555 setBooleanProperty(CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON, temp, 556 mTbRecirc.isChecked()); 557 }); 558 } 559 configureMaxAcOn(View v, CarPropertyConfig prop)560 private void configureMaxAcOn(View v, CarPropertyConfig prop) { 561 int temp = prop.getFirstAndOnlyAreaId(); 562 mTbMaxAc = (ToggleButton) v.findViewById(R.id.tbMaxAc); 563 mTbMaxAc.setEnabled(true); 564 565 mTbMaxAc.setOnClickListener(view -> { 566 // TODO handle zone properly 567 setBooleanProperty(CarHvacManager.ID_ZONED_MAX_AC_ON, temp, mTbMaxAc.isChecked()); 568 }); 569 } 570 configureMaxDefrostOn(View v, CarPropertyConfig prop)571 private void configureMaxDefrostOn(View v, CarPropertyConfig prop) { 572 int temp = prop.getFirstAndOnlyAreaId(); 573 mTbMaxDefrost = (ToggleButton) v.findViewById(R.id.tbMaxDefrost); 574 mTbMaxDefrost.setEnabled(true); 575 576 mTbMaxDefrost.setOnClickListener(view -> { 577 // TODO handle zone properly 578 setBooleanProperty(CarHvacManager.ID_ZONED_MAX_DEFROST_ON, temp, 579 mTbMaxDefrost.isChecked()); 580 }); 581 } 582 configureAutoRecircOn(View v, CarPropertyConfig prop)583 private void configureAutoRecircOn(View v, CarPropertyConfig prop) { 584 // TODO handle areaId properly 585 int areaId = prop.getFirstAndOnlyAreaId(); 586 mTbAutoRecirc = (ToggleButton) v.findViewById(R.id.tbAutoRecirc); 587 mTbAutoRecirc.setEnabled(true); 588 589 mTbAutoRecirc.setOnClickListener(view -> { 590 setBooleanProperty(CarHvacManager.ID_ZONED_HVAC_AUTO_RECIRC_ON, areaId, 591 mTbAutoRecirc.isChecked()); 592 }); 593 } 594 configureTempDisplayUnit(View v, CarPropertyConfig prop)595 private void configureTempDisplayUnit(View v, CarPropertyConfig prop) { 596 int areaId = prop.getFirstAndOnlyAreaId(); 597 mTbTempDisplayUnit = (ToggleButton) v.findViewById(R.id.tbTempDisplayUnit); 598 mTbTempDisplayUnit.setEnabled(true); 599 600 mTbTempDisplayUnit.setOnClickListener(view -> { 601 int unit = 602 (mTbTempDisplayUnit.isChecked() ? VehicleUnit.FAHRENHEIT : VehicleUnit.CELSIUS); 603 setIntProperty(CarHvacManager.ID_TEMPERATURE_DISPLAY_UNITS, areaId, unit); 604 }); 605 } 606 configurePowerOn(View v, CarPropertyConfig prop)607 private void configurePowerOn(View v, CarPropertyConfig prop) { 608 // TODO handle areaId properly 609 int areaId = prop.getFirstAndOnlyAreaId(); 610 mTbPower = (ToggleButton) v.findViewById(R.id.tbPower); 611 mTbPower.setEnabled(true); 612 613 mTbPower.setOnClickListener(view -> { 614 setBooleanProperty(CarHvacManager.ID_ZONED_HVAC_POWER_ON, areaId, mTbPower.isChecked()); 615 }); 616 } 617 configurePowerAndAcOn(View v, CarPropertyConfig prop)618 private void configurePowerAndAcOn(View v, CarPropertyConfig prop) { 619 // TODO handle areaId properly 620 int areaId = prop.getFirstAndOnlyAreaId(); 621 mTbPowerAndAc = (Button) v.findViewById(R.id.tbPowerAndAc); 622 mTbPowerAndAc.setEnabled(true); 623 624 mTbPowerAndAc.setOnClickListener(view -> { 625 setBooleanProperty(CarHvacManager.ID_ZONED_HVAC_POWER_ON, areaId, true); 626 setBooleanProperty(CarHvacManager.ID_ZONED_AC_ON, areaId, true); 627 }); 628 } 629 setBooleanProperty(int propertyId, int areaId, boolean value)630 private void setBooleanProperty(int propertyId, int areaId, boolean value) { 631 try { 632 mCarHvacManager.setBooleanProperty(propertyId, areaId, value); 633 } catch (IllegalStateException e) { 634 Log.e(TAG, "Failed to set boolean property", e); 635 Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); 636 } 637 } 638 setIntProperty(int propertyId, int areaId, int value)639 private void setIntProperty(int propertyId, int areaId, int value) { 640 try { 641 mCarHvacManager.setIntProperty(propertyId, areaId, value); 642 } catch (IllegalStateException e) { 643 Log.e(TAG, "Failed to set int property", e); 644 Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); 645 } 646 } 647 setFloatProperty(int propertyId, int areaId, float value)648 private void setFloatProperty(int propertyId, int areaId, float value) { 649 try { 650 mCarHvacManager.setFloatProperty(propertyId, areaId, value); 651 } catch (IllegalStateException e) { 652 Log.e(TAG, "Failed to set float property", e); 653 Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); 654 } 655 } 656 } 657