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