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 17package com.google.android.car.kitchensink.hvac; 18 19import static java.lang.Integer.toHexString; 20 21import android.car.CarNotConnectedException; 22import android.car.hardware.CarPropertyConfig; 23import android.car.hardware.CarPropertyValue; 24import android.car.hardware.hvac.CarHvacManager; 25import android.car.hardware.hvac.CarHvacManager.HvacPropertyId; 26import android.os.Bundle; 27import android.support.v4.app.Fragment; 28import android.util.Log; 29import android.view.LayoutInflater; 30import android.view.View; 31import android.view.ViewGroup; 32import android.widget.Button; 33import android.widget.RadioButton; 34import android.widget.RadioGroup; 35import android.widget.TextView; 36import android.widget.ToggleButton; 37 38import com.google.android.car.kitchensink.R; 39 40import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleHvacFanDirection; 41import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleWindow; 42import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleZone; 43 44import java.util.ArrayList; 45import java.util.List; 46 47public class HvacTestFragment extends Fragment { 48 private final boolean DBG = true; 49 private final String TAG = "HvacTestFragment"; 50 private RadioButton mRbFanPositionFace; 51 private RadioButton mRbFanPositionFloor; 52 private RadioButton mRbFanPositionFaceAndFloor; 53 private ToggleButton mTbAc; 54 private ToggleButton mTbDefrostFront; 55 private ToggleButton mTbDefrostRear; 56 private TextView mTvFanSpeed; 57 private TextView mTvDTemp; 58 private TextView mTvPTemp; 59 private int mCurFanSpeed = 1; 60 private float mCurDTemp = 23; 61 private float mCurPTemp = 23; 62 private CarHvacManager mCarHvacManager; 63 private int mZoneForAcOn; 64 private int mZoneForSetTempD; 65 private int mZoneForSetTempP; 66 private int mZoneForFanSpeed; 67 private int mZoneForFanPosition; 68 69 private final CarHvacManager.CarHvacEventListener mHvacListener = 70 new CarHvacManager.CarHvacEventListener () { 71 @Override 72 public void onChangeEvent(final CarPropertyValue value) { 73 int zones = value.getAreaId(); 74 switch(value.getPropertyId()) { 75 case HvacPropertyId.ZONED_AC_ON: 76 mTbAc.setChecked((boolean)value.getValue()); 77 break; 78 case HvacPropertyId.ZONED_FAN_POSITION: 79 switch((int)value.getValue()) { 80 case VehicleHvacFanDirection.VEHICLE_HVAC_FAN_DIRECTION_FACE: 81 mRbFanPositionFace.setChecked(true); 82 break; 83 case VehicleHvacFanDirection.VEHICLE_HVAC_FAN_DIRECTION_FLOOR: 84 mRbFanPositionFloor.setChecked(true); 85 break; 86 case VehicleHvacFanDirection. 87 VEHICLE_HVAC_FAN_DIRECTION_FACE_AND_FLOOR: 88 mRbFanPositionFaceAndFloor.setChecked(true); 89 break; 90 default: 91 if (DBG) { 92 Log.e(TAG, "Unknown fan position: " + value.getValue()); 93 } 94 break; 95 } 96 break; 97 case HvacPropertyId.ZONED_FAN_SPEED_SETPOINT: 98 if ((zones & mZoneForFanSpeed) != 0) { 99 mCurFanSpeed = (int)value.getValue(); 100 mTvFanSpeed.setText(String.valueOf(mCurFanSpeed)); 101 } 102 break; 103 case HvacPropertyId.ZONED_TEMP_SETPOINT: 104 if ((zones & mZoneForSetTempD) != 0) { 105 mCurDTemp = (float)value.getValue(); 106 mTvDTemp.setText(String.valueOf(mCurDTemp)); 107 } 108 if ((zones & mZoneForSetTempP) != 0) { 109 mCurPTemp = (float)value.getValue(); 110 mTvPTemp.setText(String.valueOf(mCurPTemp)); 111 } 112 break; 113 case HvacPropertyId.WINDOW_DEFROSTER_ON: 114 if((zones & VehicleWindow.VEHICLE_WINDOW_FRONT_WINDSHIELD) == 115 VehicleWindow.VEHICLE_WINDOW_FRONT_WINDSHIELD) { 116 mTbDefrostFront.setChecked((boolean)value.getValue()); 117 } 118 if((zones & VehicleWindow.VEHICLE_WINDOW_REAR_WINDSHIELD) == 119 VehicleWindow.VEHICLE_WINDOW_REAR_WINDSHIELD) { 120 mTbDefrostRear.setChecked((boolean)value.getValue()); 121 } 122 break; 123 default: 124 Log.d(TAG, "onChangeEvent(): unknown property id = " + value 125 .getPropertyId()); 126 } 127 } 128 129 @Override 130 public void onErrorEvent(final int propertyId, final int zone) { 131 Log.w(TAG, "Error: propertyId=0x" + toHexString(propertyId) 132 + ", zone=0x" + toHexString(zone)); 133 } 134 }; 135 136 @Override 137 public void onCreate(Bundle savedInstanceState) { 138 super.onCreate(savedInstanceState); 139 try { 140 mCarHvacManager.registerListener(mHvacListener); 141 } catch (CarNotConnectedException e) { 142 Log.e(TAG, "Car is not connected!"); 143 } 144 } 145 146 @Override 147 public void onDestroy() { 148 super.onDestroy(); 149 try { 150 mCarHvacManager.unregisterListener(mHvacListener); 151 } catch (CarNotConnectedException e) { 152 Log.e(TAG, "Failed to unregister listener", e); 153 } 154 } 155 156 @Override 157 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) { 158 View v = inflater.inflate(R.layout.hvac_test, container, false); 159 160 List<CarPropertyConfig> props; 161 try { 162 props = mCarHvacManager.getPropertyList(); 163 } catch (CarNotConnectedException e) { 164 Log.e(TAG, "Failed to get list of properties", e); 165 props = new ArrayList<>(); 166 } 167 168 for(CarPropertyConfig prop : props) { 169 int propId = prop.getPropertyId(); 170 171 if(DBG) { 172 Log.d(TAG, prop.toString()); 173 } 174 175 switch(propId) { 176 case HvacPropertyId.ZONED_AC_ON: 177 configureAcOn(v, prop); 178 break; 179 case HvacPropertyId.ZONED_FAN_POSITION: 180 configureFanPosition(v, prop); 181 break; 182 case HvacPropertyId.ZONED_FAN_SPEED_SETPOINT: 183 configureFanSpeed(v, prop); 184 break; 185 case HvacPropertyId.ZONED_TEMP_SETPOINT: 186 configureTempSetpoint(v, prop); 187 break; 188 case HvacPropertyId.WINDOW_DEFROSTER_ON: 189 configureDefrosterOn(v, prop); 190 break; 191 default: 192 Log.w(TAG, "propertyId " + propId + " is not handled"); 193 break; 194 } 195 } 196 197 mTvFanSpeed = (TextView) v.findViewById(R.id.tvFanSpeed); 198 mTvFanSpeed.setText(String.valueOf(mCurFanSpeed)); 199 mTvDTemp = (TextView) v.findViewById(R.id.tvDTemp); 200 mTvDTemp.setText(String.valueOf(mCurDTemp)); 201 mTvPTemp = (TextView) v.findViewById(R.id.tvPTemp); 202 mTvPTemp.setText(String.valueOf(mCurPTemp)); 203 204 if(DBG) { 205 Log.d(TAG, "Starting HvacTestFragment"); 206 } 207 208 return v; 209 } 210 211 public void setHvacManager(CarHvacManager hvacManager) { 212 Log.d(TAG, "setHvacManager()"); 213 mCarHvacManager = hvacManager; 214 } 215 216 private void configureAcOn(View v, CarPropertyConfig prop) { 217 mZoneForAcOn = prop.getFirstAndOnlyAreaId(); 218 mTbAc = (ToggleButton)v.findViewById(R.id.tbAc); 219 mTbAc.setEnabled(true); 220 221 mTbAc.setOnClickListener(view -> { 222 // TODO handle zone properly 223 try { 224 mCarHvacManager.setBooleanProperty(HvacPropertyId.ZONED_AC_ON, mZoneForAcOn, 225 mTbAc.isChecked()); 226 } catch (CarNotConnectedException e) { 227 Log.e(TAG, "Failed to set HVAC boolean property", e); 228 } 229 }); 230 } 231 232 private void configureFanPosition(View v, CarPropertyConfig prop) { 233 mZoneForFanPosition = prop.getFirstAndOnlyAreaId(); 234 RadioGroup rg = (RadioGroup)v.findViewById(R.id.rgFanPosition); 235 rg.setOnCheckedChangeListener((group, checkedId) -> { 236 int position; 237 switch(checkedId) { 238 case R.id.rbPositionFace: 239 position = VehicleHvacFanDirection.VEHICLE_HVAC_FAN_DIRECTION_FACE; 240 break; 241 case R.id.rbPositionFloor: 242 position = VehicleHvacFanDirection.VEHICLE_HVAC_FAN_DIRECTION_FLOOR; 243 break; 244 case R.id.rbPositionFaceAndFloor: 245 position = VehicleHvacFanDirection.VEHICLE_HVAC_FAN_DIRECTION_FACE_AND_FLOOR; 246 break; 247 default: 248 throw new IllegalStateException("Unexpected fan position: " + checkedId); 249 } 250 try { 251 mCarHvacManager.setIntProperty(HvacPropertyId.ZONED_FAN_POSITION, 252 mZoneForFanPosition, 253 position); 254 } catch (CarNotConnectedException e) { 255 Log.e(TAG, "Failed to set HVAC integer property", e); 256 } 257 }); 258 259 mRbFanPositionFace = (RadioButton)v.findViewById(R.id.rbPositionFace); 260 mRbFanPositionFace.setClickable(true); 261 mRbFanPositionFloor = (RadioButton)v.findViewById(R.id.rbPositionFloor); 262 mRbFanPositionFaceAndFloor = (RadioButton)v.findViewById(R.id.rbPositionFaceAndFloor); 263 mRbFanPositionFaceAndFloor.setClickable(true); 264 mRbFanPositionFloor.setClickable(true); 265 } 266 267 private void configureFanSpeed(View v, CarPropertyConfig prop) { 268 mZoneForFanSpeed = prop.getFirstAndOnlyAreaId(); 269 try { 270 mCurFanSpeed = mCarHvacManager.getIntProperty( 271 HvacPropertyId.ZONED_FAN_SPEED_SETPOINT, 272 mZoneForFanSpeed); 273 } catch (CarNotConnectedException e) { 274 Log.e(TAG, "Failed to get HVAC int property", e); 275 } 276 277 Button btnFanSpeedUp = (Button) v.findViewById(R.id.btnFanSpeedUp); 278 btnFanSpeedUp.setEnabled(true); 279 btnFanSpeedUp.setOnClickListener(view -> { 280 if (mCurFanSpeed < 7) { 281 mCurFanSpeed++; 282 mTvFanSpeed.setText(String.valueOf(mCurFanSpeed)); 283 try { 284 mCarHvacManager.setIntProperty(HvacPropertyId.ZONED_FAN_SPEED_SETPOINT, 285 mZoneForFanSpeed, mCurFanSpeed); 286 } catch (CarNotConnectedException e) { 287 Log.e(TAG, "Failed to set HVAC int property", e); 288 } 289 } 290 }); 291 292 Button btnFanSpeedDn = (Button) v.findViewById(R.id.btnFanSpeedDn); 293 btnFanSpeedDn.setEnabled(true); 294 btnFanSpeedDn.setOnClickListener(view -> { 295 if (mCurFanSpeed > 1) { 296 mCurFanSpeed--; 297 mTvFanSpeed.setText(String.valueOf(mCurFanSpeed)); 298 try { 299 mCarHvacManager.setIntProperty(HvacPropertyId.ZONED_FAN_SPEED_SETPOINT, 300 mZoneForFanSpeed, mCurFanSpeed); 301 } catch (CarNotConnectedException e) { 302 Log.e(TAG, "Failed to set HVAC fan speed property", e); 303 } 304 } 305 }); 306 } 307 308 private void configureTempSetpoint(View v, CarPropertyConfig prop) { 309 mZoneForSetTempD = 0; 310 if (prop.hasArea(VehicleZone.VEHICLE_ZONE_ROW_1_LEFT)) { 311 mZoneForSetTempD = VehicleZone.VEHICLE_ZONE_ROW_1_LEFT; 312 } 313 mZoneForSetTempP = 0; 314 if (prop.hasArea(VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT)) { 315 mZoneForSetTempP = VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT; 316 } 317 int[] areas = prop.getAreaIds(); 318 if (mZoneForSetTempD == 0 && areas.length > 1) { 319 mZoneForSetTempD = areas[0]; 320 } 321 if (mZoneForSetTempP == 0 && areas.length > 2) { 322 mZoneForSetTempP = areas[1]; 323 } 324 Button btnDTempUp = (Button) v.findViewById(R.id.btnDTempUp); 325 if (mZoneForSetTempD != 0) { 326 try { 327 mCurDTemp = mCarHvacManager.getFloatProperty( 328 HvacPropertyId.ZONED_TEMP_SETPOINT, 329 mZoneForSetTempD); 330 } catch (CarNotConnectedException e) { 331 Log.e(TAG, "Failed to get HVAC zoned temp property", e); 332 } 333 btnDTempUp.setEnabled(true); 334 btnDTempUp.setOnClickListener(view -> { 335 if(mCurDTemp < 29.5) { 336 mCurDTemp += 0.5; 337 mTvDTemp.setText(String.valueOf(mCurDTemp)); 338 try { 339 mCarHvacManager.setFloatProperty( 340 HvacPropertyId.ZONED_TEMP_SETPOINT, 341 mZoneForSetTempD, mCurDTemp); 342 } catch (CarNotConnectedException e) { 343 Log.e(TAG, "Failed to set HVAC zoned temp property", e); 344 } 345 } 346 }); 347 348 Button btnDTempDn = (Button) v.findViewById(R.id.btnDTempDn); 349 btnDTempDn.setEnabled(true); 350 btnDTempDn.setOnClickListener(view -> { 351 if(mCurDTemp > 15.5) { 352 mCurDTemp -= 0.5; 353 mTvDTemp.setText(String.valueOf(mCurDTemp)); 354 try { 355 mCarHvacManager.setFloatProperty( 356 HvacPropertyId.ZONED_TEMP_SETPOINT, 357 mZoneForSetTempD, mCurDTemp); 358 } catch (CarNotConnectedException e) { 359 Log.e(TAG, "Failed to set HVAC zoned temp property", e); 360 } 361 } 362 }); 363 } else { 364 btnDTempUp.setEnabled(false); 365 } 366 367 Button btnPTempUp = (Button) v.findViewById(R.id.btnPTempUp); 368 if (mZoneForSetTempP !=0 ) { 369 try { 370 mCurPTemp = mCarHvacManager.getFloatProperty( 371 HvacPropertyId.ZONED_TEMP_SETPOINT, 372 mZoneForSetTempP); 373 } catch (CarNotConnectedException e) { 374 Log.e(TAG, "Failed to get HVAC zoned temp property", e); 375 } 376 btnPTempUp.setEnabled(true); 377 btnPTempUp.setOnClickListener(view -> { 378 if (mCurPTemp < 29.5) { 379 mCurPTemp += 0.5; 380 mTvPTemp.setText(String.valueOf(mCurPTemp)); 381 try { 382 mCarHvacManager.setFloatProperty( 383 HvacPropertyId.ZONED_TEMP_SETPOINT, 384 mZoneForSetTempP, mCurPTemp); 385 } catch (CarNotConnectedException e) { 386 Log.e(TAG, "Failed to set HVAC zoned temp property", e); 387 } 388 } 389 }); 390 391 Button btnPTempDn = (Button) v.findViewById(R.id.btnPTempDn); 392 btnPTempDn.setEnabled(true); 393 btnPTempDn.setOnClickListener(view -> { 394 if (mCurPTemp > 15.5) { 395 mCurPTemp -= 0.5; 396 mTvPTemp.setText(String.valueOf(mCurPTemp)); 397 try { 398 mCarHvacManager.setFloatProperty( 399 HvacPropertyId.ZONED_TEMP_SETPOINT, 400 mZoneForSetTempP, mCurPTemp); 401 } catch (CarNotConnectedException e) { 402 Log.e(TAG, "Failed to set HVAC zoned temp property", e); 403 } 404 } 405 }); 406 } else { 407 btnPTempUp.setEnabled(false); 408 } 409 } 410 411 private void configureDefrosterOn(View v, CarPropertyConfig prop1) { 412 if (prop1.hasArea(VehicleWindow.VEHICLE_WINDOW_FRONT_WINDSHIELD)) { 413 mTbDefrostFront = (ToggleButton) v.findViewById(R.id.tbDefrostFront); 414 mTbDefrostFront.setEnabled(true); 415 mTbDefrostFront.setOnClickListener(view -> { 416 try { 417 mCarHvacManager.setBooleanProperty(HvacPropertyId.WINDOW_DEFROSTER_ON, 418 VehicleWindow.VEHICLE_WINDOW_FRONT_WINDSHIELD, 419 mTbDefrostFront.isChecked()); 420 } catch (CarNotConnectedException e) { 421 Log.e(TAG, "Failed to set HVAC window defroster property", e); 422 } 423 }); 424 } 425 if (prop1.hasArea(VehicleWindow.VEHICLE_WINDOW_REAR_WINDSHIELD)) { 426 mTbDefrostRear = (ToggleButton) v.findViewById(R.id.tbDefrostRear); 427 mTbDefrostRear.setEnabled(true); 428 mTbDefrostRear.setOnClickListener(view -> { 429 try { 430 mCarHvacManager.setBooleanProperty(HvacPropertyId.WINDOW_DEFROSTER_ON, 431 VehicleWindow.VEHICLE_WINDOW_REAR_WINDSHIELD, 432 mTbDefrostRear.isChecked()); 433 } catch (CarNotConnectedException e) { 434 Log.e(TAG, "Failed to set HVAC window defroster property", e); 435 } 436 }); 437 } 438 } 439} 440