Home | History | Annotate | Download | only in hvac
      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 com.google.android.car.kitchensink.KitchenSinkActivity;
     22 import com.google.android.car.kitchensink.R;
     23 
     24 import android.car.CarNotConnectedException;
     25 import android.car.hardware.CarPropertyConfig;
     26 import android.car.hardware.CarPropertyValue;
     27 import android.car.hardware.hvac.CarHvacManager;
     28 import android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow;
     29 import android.hardware.automotive.vehicle.V2_0.VehicleAreaZone;
     30 import android.os.Bundle;
     31 import android.support.v4.app.Fragment;
     32 import android.util.Log;
     33 import android.view.LayoutInflater;
     34 import android.view.View;
     35 import android.view.ViewGroup;
     36 import android.widget.Button;
     37 import android.widget.RadioButton;
     38 import android.widget.RadioGroup;
     39 import android.widget.TextView;
     40 import android.widget.ToggleButton;
     41 
     42 import java.util.ArrayList;
     43 import java.util.List;
     44 
     45 public class HvacTestFragment extends Fragment {
     46     private final boolean DBG = true;
     47     private final String TAG = "HvacTestFragment";
     48     private RadioButton mRbFanPositionFace;
     49     private RadioButton mRbFanPositionFloor;
     50     private RadioButton mRbFanPositionFaceAndFloor;
     51     private RadioButton mRbFanPositionDefrost;
     52     private RadioButton mRbFanPositionDefrostAndFloor;
     53     private ToggleButton mTbAc;
     54     private ToggleButton mTbAuto;
     55     private ToggleButton mTbDefrostFront;
     56     private ToggleButton mTbDefrostRear;
     57     private ToggleButton mTbDual;
     58     private ToggleButton mTbMaxAc;
     59     private ToggleButton mTbMaxDefrost;
     60     private ToggleButton mTbRecirc;
     61     private TextView mTvFanSpeed;
     62     private TextView mTvDTemp;
     63     private TextView mTvPTemp;
     64     private TextView mTvOutsideTemp;
     65     private int mCurFanSpeed;
     66     private int mMinFanSpeed;
     67     private int mMaxFanSpeed;
     68     private float mCurDTemp;
     69     private float mCurPTemp;
     70     private float mMinTemp;
     71     private float mMaxTemp;
     72     private float mTempStep;
     73     private CarHvacManager mCarHvacManager;
     74     private int mZoneForAcOn;
     75     private int mZoneForSetTempD;
     76     private int mZoneForSetTempP;
     77     private int mZoneForFanSpeed;
     78     private int mZoneForFanPosition;
     79 
     80     private final CarHvacManager.CarHvacEventCallback mHvacCallback =
     81             new CarHvacManager.CarHvacEventCallback () {
     82                 @Override
     83                 public void onChangeEvent(final CarPropertyValue value) {
     84                     int zones = value.getAreaId();
     85                     switch(value.getPropertyId()) {
     86                         case CarHvacManager.ID_OUTSIDE_AIR_TEMP:
     87                             mTvOutsideTemp.setText(String.valueOf(value.getValue()));
     88                             break;
     89                         case CarHvacManager.ID_ZONED_DUAL_ZONE_ON:
     90                             mTbDual.setChecked((boolean)value.getValue());
     91                             break;
     92                         case CarHvacManager.ID_ZONED_AC_ON:
     93                             mTbAc.setChecked((boolean)value.getValue());
     94                             break;
     95                         case CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON:
     96                             mTbAuto.setChecked((boolean)value.getValue());
     97                             break;
     98                         case CarHvacManager.ID_ZONED_FAN_POSITION:
     99                             switch((int)value.getValue()) {
    100                                 case CarHvacManager.FAN_POSITION_FACE:
    101                                     mRbFanPositionFace.setChecked(true);
    102                                     break;
    103                                 case CarHvacManager.FAN_POSITION_FLOOR:
    104                                     mRbFanPositionFloor.setChecked(true);
    105                                     break;
    106                                 case CarHvacManager.FAN_POSITION_FACE_AND_FLOOR:
    107                                     mRbFanPositionFaceAndFloor.setChecked(true);
    108                                     break;
    109                                 case CarHvacManager.FAN_POSITION_DEFROST:
    110                                     mRbFanPositionDefrost.setChecked(true);
    111                                     break;
    112                                 case CarHvacManager.FAN_POSITION_DEFROST_AND_FLOOR:
    113                                     mRbFanPositionDefrostAndFloor.setChecked(true);
    114                                     break;
    115                                 default:
    116                                     if (DBG) {
    117                                         Log.e(TAG, "Unknown fan position: " + value.getValue());
    118                                     }
    119                                     break;
    120                             }
    121                             break;
    122                         case CarHvacManager.ID_ZONED_MAX_AC_ON:
    123                             mTbMaxAc.setChecked((boolean)value.getValue());
    124                             break;
    125                         case CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON:
    126                             mTbRecirc.setChecked((boolean)value.getValue());
    127                             break;
    128                         case CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT:
    129                             if ((zones & mZoneForFanSpeed) != 0) {
    130                                 mCurFanSpeed = (int)value.getValue();
    131                                 mTvFanSpeed.setText(String.valueOf(mCurFanSpeed));
    132                             }
    133                             break;
    134                         case CarHvacManager.ID_ZONED_TEMP_SETPOINT:
    135                             if ((zones & mZoneForSetTempD) != 0) {
    136                                 mCurDTemp = (float)value.getValue();
    137                                 mTvDTemp.setText(String.valueOf(mCurDTemp));
    138                             }
    139                             if ((zones & mZoneForSetTempP) != 0) {
    140                                 mCurPTemp = (float)value.getValue();
    141                                 mTvPTemp.setText(String.valueOf(mCurPTemp));
    142                             }
    143                             break;
    144                         case CarHvacManager.ID_ZONED_MAX_DEFROST_ON:
    145                             mTbMaxDefrost.setChecked((boolean)value.getValue());
    146                             break;
    147                         case CarHvacManager.ID_WINDOW_DEFROSTER_ON:
    148                             if((zones & VehicleAreaWindow.FRONT_WINDSHIELD) ==
    149                                     VehicleAreaWindow.FRONT_WINDSHIELD) {
    150                                 mTbDefrostFront.setChecked((boolean)value.getValue());
    151                             }
    152                             if((zones & VehicleAreaWindow.REAR_WINDSHIELD) ==
    153                                     VehicleAreaWindow.REAR_WINDSHIELD) {
    154                                 mTbDefrostRear.setChecked((boolean)value.getValue());
    155                             }
    156                             break;
    157                         default:
    158                             Log.d(TAG, "onChangeEvent(): unknown property id = " + value
    159                                     .getPropertyId());
    160                     }
    161                 }
    162 
    163                 @Override
    164                 public void onErrorEvent(final int propertyId, final int zone) {
    165                     Log.w(TAG, "Error:  propertyId=0x" + toHexString(propertyId)
    166                             + ", zone=0x" + toHexString(zone));
    167                 }
    168             };
    169 
    170     @Override
    171     public void onCreate(Bundle savedInstanceState) {
    172         mCarHvacManager = ((KitchenSinkActivity)getActivity()).getHvacManager();
    173         super.onCreate(savedInstanceState);
    174         try {
    175             mCarHvacManager.registerCallback(mHvacCallback);
    176         } catch (CarNotConnectedException e) {
    177             Log.e(TAG, "Car is not connected!");
    178         }
    179     }
    180 
    181     @Override
    182     public void onDestroy() {
    183         super.onDestroy();
    184         mCarHvacManager.unregisterCallback(mHvacCallback);
    185     }
    186 
    187     @Override
    188     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) {
    189         View v = inflater.inflate(R.layout.hvac_test, container, false);
    190 
    191         List<CarPropertyConfig> props;
    192         try {
    193             props = mCarHvacManager.getPropertyList();
    194         } catch (CarNotConnectedException e) {
    195             Log.e(TAG, "Failed to get list of properties", e);
    196             props = new ArrayList<>();
    197         }
    198 
    199         for(CarPropertyConfig prop : props) {
    200             int propId = prop.getPropertyId();
    201 
    202             if(DBG) {
    203                 Log.d(TAG, prop.toString());
    204             }
    205 
    206             switch(propId) {
    207                 case CarHvacManager.ID_OUTSIDE_AIR_TEMP:
    208                     configureOutsideTemp(v, prop);
    209                     break;
    210                 case CarHvacManager.ID_ZONED_DUAL_ZONE_ON:
    211                     configureDualOn(v, prop);
    212                     break;
    213                 case CarHvacManager.ID_ZONED_AC_ON:
    214                     configureAcOn(v, prop);
    215                     break;
    216                 case CarHvacManager.ID_ZONED_FAN_POSITION:
    217                     configureFanPosition(v, prop);
    218                     break;
    219                 case CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT:
    220                     configureFanSpeed(v, prop);
    221                     break;
    222                 case CarHvacManager.ID_ZONED_TEMP_SETPOINT:
    223                     configureTempSetpoint(v, prop);
    224                     break;
    225                 case CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON:
    226                     configureAutoModeOn(v, prop);
    227                     break;
    228                 case CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON:
    229                     configureRecircOn(v, prop);
    230                     break;
    231                 case CarHvacManager.ID_ZONED_MAX_AC_ON:
    232                     configureMaxAcOn(v, prop);
    233                     break;
    234                 case CarHvacManager.ID_ZONED_MAX_DEFROST_ON:
    235                     configureMaxDefrostOn(v, prop);
    236                     break;
    237                 case CarHvacManager.ID_WINDOW_DEFROSTER_ON:
    238                     configureDefrosterOn(v, prop);
    239                     break;
    240                 default:
    241                     Log.w(TAG, "propertyId " + propId + " is not handled");
    242                     break;
    243             }
    244         }
    245 
    246         mTvFanSpeed = (TextView) v.findViewById(R.id.tvFanSpeed);
    247         mTvFanSpeed.setText(String.valueOf(mCurFanSpeed));
    248         mTvDTemp = (TextView) v.findViewById(R.id.tvDTemp);
    249         mTvDTemp.setText(String.valueOf(mCurDTemp));
    250         mTvPTemp = (TextView) v.findViewById(R.id.tvPTemp);
    251         mTvPTemp.setText(String.valueOf(mCurPTemp));
    252         mTvOutsideTemp = (TextView) v.findViewById(R.id.tvOutsideTemp);
    253         mTvOutsideTemp.setText("N/A");
    254 
    255         if(DBG) {
    256             Log.d(TAG, "Starting HvacTestFragment");
    257         }
    258 
    259         return v;
    260     }
    261 
    262     private void configureOutsideTemp(View v, CarPropertyConfig prop) {
    263         // Do nothing
    264     }
    265 
    266     private void configureDualOn(View v, CarPropertyConfig prop) {
    267         int temp = prop.getFirstAndOnlyAreaId();
    268         mTbDual = (ToggleButton)v.findViewById(R.id.tbDual);
    269         mTbDual.setEnabled(true);
    270 
    271         mTbDual.setOnClickListener(view -> {
    272             // TODO handle zone properly
    273             try {
    274                 mCarHvacManager.setBooleanProperty(CarHvacManager.ID_ZONED_DUAL_ZONE_ON,temp,
    275                         mTbDual.isChecked());
    276             } catch (CarNotConnectedException e) {
    277                 Log.e(TAG, "Failed to set HVAC boolean property", e);
    278             }
    279         });
    280     }
    281 
    282     private void configureAcOn(View v, CarPropertyConfig prop) {
    283         mZoneForAcOn = prop.getFirstAndOnlyAreaId();
    284         mTbAc = (ToggleButton)v.findViewById(R.id.tbAc);
    285         mTbAc.setEnabled(true);
    286 
    287         mTbAc.setOnClickListener(view -> {
    288             // TODO handle zone properly
    289             try {
    290                 mCarHvacManager.setBooleanProperty(CarHvacManager.ID_ZONED_AC_ON, mZoneForAcOn,
    291                         mTbAc.isChecked());
    292             } catch (CarNotConnectedException e) {
    293                 Log.e(TAG, "Failed to set HVAC boolean property", e);
    294             }
    295         });
    296     }
    297 
    298     private void configureAutoModeOn(View v, CarPropertyConfig prop) {
    299         int temp = prop.getFirstAndOnlyAreaId();
    300         mTbAuto = (ToggleButton)v.findViewById(R.id.tbAuto);
    301         mTbAuto.setEnabled(true);
    302 
    303         mTbAuto.setOnClickListener(view -> {
    304             // TODO handle zone properly
    305             try {
    306                 mCarHvacManager.setBooleanProperty(CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON,temp,
    307                         mTbAuto.isChecked());
    308             } catch (CarNotConnectedException e) {
    309                 Log.e(TAG, "Failed to set HVAC boolean property", e);
    310             }
    311         });
    312     }
    313 
    314     private void configureFanPosition(View v, CarPropertyConfig prop) {
    315         mZoneForFanPosition = prop.getFirstAndOnlyAreaId();
    316         RadioGroup rg = (RadioGroup)v.findViewById(R.id.rgFanPosition);
    317         rg.setOnCheckedChangeListener((group, checkedId) -> {
    318             int position;
    319             switch(checkedId) {
    320                 case R.id.rbPositionFace:
    321                     position = CarHvacManager.FAN_POSITION_FACE;
    322                     break;
    323                 case R.id.rbPositionFloor:
    324                     position = CarHvacManager.FAN_POSITION_FLOOR;
    325                     break;
    326                 case R.id.rbPositionFaceAndFloor:
    327                     position = CarHvacManager.FAN_POSITION_FACE_AND_FLOOR;
    328                     break;
    329                 case R.id.rbPositionDefrost:
    330                     position = CarHvacManager.FAN_POSITION_DEFROST;
    331                     break;
    332                 case R.id.rbPositionDefrostAndFloor:
    333                     position = CarHvacManager.FAN_POSITION_DEFROST_AND_FLOOR;
    334                     break;
    335                 default:
    336                     throw new IllegalStateException("Unexpected fan position: " + checkedId);
    337             }
    338             try {
    339                 mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_POSITION,
    340                         mZoneForFanPosition,
    341                         position);
    342             } catch (CarNotConnectedException e) {
    343                 Log.e(TAG, "Failed to set HVAC integer property", e);
    344             }
    345         });
    346 
    347         mRbFanPositionFace = (RadioButton)v.findViewById(R.id.rbPositionFace);
    348         mRbFanPositionFace.setClickable(true);
    349         mRbFanPositionFloor = (RadioButton)v.findViewById(R.id.rbPositionFloor);
    350         mRbFanPositionFloor.setClickable(true);
    351         mRbFanPositionFaceAndFloor = (RadioButton)v.findViewById(R.id.rbPositionFaceAndFloor);
    352         mRbFanPositionFaceAndFloor.setClickable(true);
    353         mRbFanPositionDefrost = (RadioButton)v.findViewById(R.id.rbPositionDefrost);
    354         mRbFanPositionDefrost.setClickable(true);
    355         mRbFanPositionDefrostAndFloor = (RadioButton)v.findViewById(R.id.rbPositionDefrostAndFloor);
    356         mRbFanPositionDefrostAndFloor.setClickable(true);
    357     }
    358 
    359     private void configureFanSpeed(View v, CarPropertyConfig prop) {
    360         mMinFanSpeed = ((Integer)prop.getMinValue()).intValue();
    361         mMaxFanSpeed = ((Integer)prop.getMaxValue()).intValue();
    362         mZoneForFanSpeed = prop.getFirstAndOnlyAreaId();
    363         try {
    364             mCurFanSpeed = mCarHvacManager.getIntProperty(
    365                     CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT,
    366                     mZoneForFanSpeed);
    367         } catch (CarNotConnectedException e) {
    368             Log.e(TAG, "Failed to get HVAC int property", e);
    369         }
    370 
    371         Button btnFanSpeedUp = (Button) v.findViewById(R.id.btnFanSpeedUp);
    372         btnFanSpeedUp.setEnabled(true);
    373         btnFanSpeedUp.setOnClickListener(view -> {
    374             if (mCurFanSpeed < mMaxFanSpeed) {
    375                 mCurFanSpeed++;
    376                 mTvFanSpeed.setText(String.valueOf(mCurFanSpeed));
    377                 try {
    378                     mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT,
    379                             mZoneForFanSpeed, mCurFanSpeed);
    380                 } catch (CarNotConnectedException e) {
    381                     Log.e(TAG, "Failed to set HVAC int property", e);
    382                 }
    383             }
    384         });
    385 
    386         Button btnFanSpeedDn = (Button) v.findViewById(R.id.btnFanSpeedDn);
    387         btnFanSpeedDn.setEnabled(true);
    388         btnFanSpeedDn.setOnClickListener(view -> {
    389             if (mCurFanSpeed > mMinFanSpeed) {
    390                 mCurFanSpeed--;
    391                 mTvFanSpeed.setText(String.valueOf(mCurFanSpeed));
    392                 try {
    393                     mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT,
    394                             mZoneForFanSpeed, mCurFanSpeed);
    395                 } catch (CarNotConnectedException e) {
    396                     Log.e(TAG, "Failed to set HVAC fan speed property", e);
    397                 }
    398             }
    399         });
    400     }
    401 
    402     private void configureTempSetpoint(View v, CarPropertyConfig prop) {
    403         mMinTemp = ((Float)prop.getMinValue()).floatValue();
    404         mMaxTemp = ((Float)prop.getMaxValue()).floatValue();
    405 
    406         if (mMaxTemp > 50) {
    407             // Assume it's Fahrenheit
    408             mTempStep = 1.0f;
    409         } else {
    410             // Assume it's Celsius
    411             mTempStep = 0.5f;
    412         }
    413         mZoneForSetTempD = 0;
    414         if (prop.hasArea(VehicleAreaZone.ROW_1_LEFT)) {
    415             mZoneForSetTempD = VehicleAreaZone.ROW_1_LEFT;
    416         }
    417         mZoneForSetTempP = 0;
    418         if (prop.hasArea(VehicleAreaZone.ROW_1_RIGHT)) {
    419             mZoneForSetTempP = VehicleAreaZone.ROW_1_RIGHT;
    420         }
    421         int[] areas = prop.getAreaIds();
    422         if (mZoneForSetTempD == 0 && areas.length > 1) {
    423             mZoneForSetTempD = areas[0];
    424         }
    425         if (mZoneForSetTempP == 0 && areas.length > 2) {
    426             mZoneForSetTempP = areas[1];
    427         }
    428         Button btnDTempUp = (Button) v.findViewById(R.id.btnDTempUp);
    429         if (mZoneForSetTempD != 0) {
    430             try {
    431                 mCurDTemp = mCarHvacManager.getFloatProperty(
    432                         CarHvacManager.ID_ZONED_TEMP_SETPOINT,
    433                         mZoneForSetTempD);
    434                 if (mCurDTemp < mMinTemp) {
    435                     mCurDTemp = mMinTemp;
    436                 } else if (mCurDTemp > mMaxTemp) {
    437                     mCurDTemp = mMaxTemp;
    438                 }
    439             } catch (CarNotConnectedException e) {
    440                 Log.e(TAG, "Failed to get HVAC zoned temp property", e);
    441             }
    442             btnDTempUp.setEnabled(true);
    443             btnDTempUp.setOnClickListener(view -> {
    444                 if(mCurDTemp < mMaxTemp) {
    445                     mCurDTemp += mTempStep;
    446                     mTvDTemp.setText(String.valueOf(mCurDTemp));
    447                     try {
    448                         mCarHvacManager.setFloatProperty(
    449                                 CarHvacManager.ID_ZONED_TEMP_SETPOINT,
    450                                 mZoneForSetTempD, mCurDTemp);
    451                     } catch (CarNotConnectedException e) {
    452                         Log.e(TAG, "Failed to set HVAC zoned temp property", e);
    453                     }
    454                 }
    455             });
    456 
    457             Button btnDTempDn = (Button) v.findViewById(R.id.btnDTempDn);
    458             btnDTempDn.setEnabled(true);
    459             btnDTempDn.setOnClickListener(view -> {
    460                 if(mCurDTemp > mMinTemp) {
    461                     mCurDTemp -= mTempStep;
    462                     mTvDTemp.setText(String.valueOf(mCurDTemp));
    463                     try {
    464                         mCarHvacManager.setFloatProperty(
    465                                 CarHvacManager.ID_ZONED_TEMP_SETPOINT,
    466                                 mZoneForSetTempD, mCurDTemp);
    467                     } catch (CarNotConnectedException e) {
    468                         Log.e(TAG, "Failed to set HVAC zoned temp property", e);
    469                     }
    470                 }
    471             });
    472         } else {
    473             btnDTempUp.setEnabled(false);
    474         }
    475 
    476         Button btnPTempUp = (Button) v.findViewById(R.id.btnPTempUp);
    477         if (mZoneForSetTempP !=0 ) {
    478             try {
    479                 mCurPTemp = mCarHvacManager.getFloatProperty(
    480                         CarHvacManager.ID_ZONED_TEMP_SETPOINT,
    481                         mZoneForSetTempP);
    482                 if (mCurPTemp < mMinTemp) {
    483                     mCurPTemp = mMinTemp;
    484                 } else if (mCurPTemp > mMaxTemp) {
    485                     mCurPTemp = mMaxTemp;
    486                 }
    487             } catch (CarNotConnectedException e) {
    488                 Log.e(TAG, "Failed to get HVAC zoned temp property", e);
    489             }
    490             btnPTempUp.setEnabled(true);
    491             btnPTempUp.setOnClickListener(view -> {
    492                 if (mCurPTemp < mMaxTemp) {
    493                     mCurPTemp += mTempStep;
    494                     mTvPTemp.setText(String.valueOf(mCurPTemp));
    495                     try {
    496                         mCarHvacManager.setFloatProperty(
    497                                 CarHvacManager.ID_ZONED_TEMP_SETPOINT,
    498                                 mZoneForSetTempP, mCurPTemp);
    499                     } catch (CarNotConnectedException e) {
    500                         Log.e(TAG, "Failed to set HVAC zoned temp property", e);
    501                     }
    502                 }
    503             });
    504 
    505             Button btnPTempDn = (Button) v.findViewById(R.id.btnPTempDn);
    506             btnPTempDn.setEnabled(true);
    507             btnPTempDn.setOnClickListener(view -> {
    508                 if (mCurPTemp > mMinTemp) {
    509                     mCurPTemp -= mTempStep;
    510                     mTvPTemp.setText(String.valueOf(mCurPTemp));
    511                     try {
    512                         mCarHvacManager.setFloatProperty(
    513                                 CarHvacManager.ID_ZONED_TEMP_SETPOINT,
    514                                 mZoneForSetTempP, mCurPTemp);
    515                     } catch (CarNotConnectedException e) {
    516                         Log.e(TAG, "Failed to set HVAC zoned temp property", e);
    517                     }
    518                 }
    519             });
    520         } else {
    521             btnPTempUp.setEnabled(false);
    522         }
    523     }
    524 
    525     private void configureDefrosterOn(View v, CarPropertyConfig prop1) {
    526         if (prop1.hasArea(VehicleAreaWindow.FRONT_WINDSHIELD)) {
    527             mTbDefrostFront = (ToggleButton) v.findViewById(R.id.tbDefrostFront);
    528             mTbDefrostFront.setEnabled(true);
    529             mTbDefrostFront.setOnClickListener(view -> {
    530                 try {
    531                     mCarHvacManager.setBooleanProperty(CarHvacManager.ID_WINDOW_DEFROSTER_ON,
    532                             VehicleAreaWindow.FRONT_WINDSHIELD,
    533                             mTbDefrostFront.isChecked());
    534                 } catch (CarNotConnectedException e) {
    535                     Log.e(TAG, "Failed to set HVAC window defroster property", e);
    536                 }
    537             });
    538         }
    539         if (prop1.hasArea(VehicleAreaWindow.REAR_WINDSHIELD)) {
    540             mTbDefrostRear = (ToggleButton) v.findViewById(R.id.tbDefrostRear);
    541             mTbDefrostRear.setEnabled(true);
    542             mTbDefrostRear.setOnClickListener(view -> {
    543                 try {
    544                     mCarHvacManager.setBooleanProperty(CarHvacManager.ID_WINDOW_DEFROSTER_ON,
    545                             VehicleAreaWindow.REAR_WINDSHIELD,
    546                             mTbDefrostRear.isChecked());
    547                 } catch (CarNotConnectedException e) {
    548                     Log.e(TAG, "Failed to set HVAC window defroster property", e);
    549                 }
    550             });
    551         }
    552     }
    553 
    554     private void configureRecircOn(View v, CarPropertyConfig prop) {
    555         int temp = prop.getFirstAndOnlyAreaId();
    556         mTbRecirc = (ToggleButton)v.findViewById(R.id.tbRecirc);
    557         mTbRecirc.setEnabled(true);
    558 
    559         mTbRecirc.setOnClickListener(view -> {
    560             // TODO handle zone properly
    561             try {
    562                 mCarHvacManager.setBooleanProperty(CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON,
    563                         temp, mTbRecirc.isChecked());
    564             } catch (CarNotConnectedException e) {
    565                 Log.e(TAG, "Failed to set HVAC boolean property", e);
    566             }
    567         });
    568     }
    569 
    570     private void configureMaxAcOn(View v, CarPropertyConfig prop) {
    571         int temp = prop.getFirstAndOnlyAreaId();
    572         mTbMaxAc = (ToggleButton)v.findViewById(R.id.tbMaxAc);
    573         mTbMaxAc.setEnabled(true);
    574 
    575         mTbMaxAc.setOnClickListener(view -> {
    576             // TODO handle zone properly
    577             try {
    578                 mCarHvacManager.setBooleanProperty(CarHvacManager.ID_ZONED_MAX_AC_ON,temp,
    579                         mTbMaxAc.isChecked());
    580             } catch (CarNotConnectedException e) {
    581                 Log.e(TAG, "Failed to set HVAC boolean property", e);
    582             }
    583         });
    584     }
    585 
    586     private void configureMaxDefrostOn(View v, CarPropertyConfig prop) {
    587         int temp = prop.getFirstAndOnlyAreaId();
    588         mTbMaxDefrost = (ToggleButton)v.findViewById(R.id.tbMaxDefrost);
    589         mTbMaxDefrost.setEnabled(true);
    590 
    591         mTbMaxDefrost.setOnClickListener(view -> {
    592             // TODO handle zone properly
    593             try {
    594                 mCarHvacManager.setBooleanProperty(CarHvacManager.ID_ZONED_MAX_DEFROST_ON,temp,
    595                         mTbMaxDefrost.isChecked());
    596             } catch (CarNotConnectedException e) {
    597                 Log.e(TAG, "Failed to set HVAC boolean property", e);
    598             }
    599         });
    600     }
    601 }
    602