1# Copyright (C) 2017 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the 'License');
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an 'AS IS' BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15
16import time
17
18import vhal_consts_2_0 as c
19
20# A list of user actions as a subset of VHAL properties to simulate
21userActions = [
22    c.VEHICLEPROPERTY_HVAC_POWER_ON,
23    c.VEHICLEPROPERTY_HVAC_TEMPERATURE_SET,
24    c.VEHICLEPROPERTY_HVAC_FAN_SPEED,
25    c.VEHICLEPROPERTY_HVAC_FAN_DIRECTION,
26    c.VEHICLEPROPERTY_HVAC_AUTO_ON,
27    c.VEHICLEPROPERTY_HVAC_RECIRC_ON,
28    c.VEHICLEPROPERTY_HVAC_AC_ON,
29    c.VEHICLEPROPERTY_HVAC_DEFROSTER
30]
31
32propDesc = {
33    c.VEHICLEPROPERTY_HVAC_POWER_ON: 'HVAC_POWER_ON',
34    c.VEHICLEPROPERTY_HVAC_TEMPERATURE_SET: 'HVAC_TEMPERATURE_SET',
35    c.VEHICLEPROPERTY_HVAC_FAN_SPEED: 'HVAC_FAN_SPEED',
36    c.VEHICLEPROPERTY_HVAC_FAN_DIRECTION: 'HVAC_FAN_DIRECTION',
37    c.VEHICLEPROPERTY_HVAC_AUTO_ON: 'HVAC_AUTO_ON',
38    c.VEHICLEPROPERTY_HVAC_RECIRC_ON: 'HVAC_AUTO_RECIRC_ON',
39    c.VEHICLEPROPERTY_HVAC_AC_ON: 'HVAC_AC_ON',
40    c.VEHICLEPROPERTY_HVAC_DEFROSTER: 'HVAC_DEFROSTER'
41}
42
43SHORT_SLEEP_TIME_SEC = 2
44LONG_SLEEP_TIME_SEC = 30
45
46MIN_TEMPERATURE_C = 22
47MAX_TEMPERATURE_C = 28
48
49MIN_FAN_SPEED = 1
50MAX_FAN_SPEED = 5
51
52class ActionPropConfig(object):
53    """
54        A configuration class that parse the vhal property config message and hold the
55        configuration values
56    """
57    def __init__(self, vhalConfig):
58        self.supportedAreas = self._getSupportedAreas(vhalConfig)
59        self.areaConfigs = self._getAreaConfigs(vhalConfig, self.supportedAreas,
60                                                vhalConfig.value_type)
61
62    def _getSupportedAreas(self, vhalConfig):
63        supportedAreas = []
64        for config in vhalConfig.area_configs:
65            supportedAreas.append(config.area_id)
66
67        return supportedAreas
68
69    def _getAreaConfigs(self, vhalConfig, supportedAreas, valueType):
70        areaConfigs = {}
71        configs = vhalConfig.area_configs
72        if not configs:
73            return None
74
75        if len(configs) == 1:
76            for area in supportedAreas:
77                areaConfigs[area] = AreaConfig(configs[0], valueType)
78        else:
79            for config in configs:
80                areaConfigs[config.area_id] = AreaConfig(config, valueType)
81
82        return areaConfigs
83
84class AreaConfig(object):
85    """
86        A configuration class is representing an area config of a vhal property.
87    """
88    def __init__(self, vhalAreaConfig, valueType):
89        """
90            The class is initialized by parsing the vhal area config object
91        """
92        if valueType == c.VEHICLEPROPERTYTYPE_INT32:
93            self.min = vhalAreaConfig.min_int32_value
94            self.max = vhalAreaConfig.max_int32_value
95        elif valueType == c.VEHICLEPROPERTYTYPE_INT64:
96            self.min = vhalAreaConfig.min_int64_value
97            self.max = vhalAreaConfig.max_int64_value
98        elif valueType == c.VEHICLEPROPERTYTYPE_FLOAT:
99            self.min = vhalAreaConfig.min_float_value
100            self.max = vhalAreaConfig.max_float_value
101        else:
102            self.min = None
103            self.max = None
104
105class UserActionGenerator(object):
106    """
107        A class generate user action related vhal properties in a deterministic algorithm based on
108        pre-fetched vhal configuration
109    """
110    def __init__(self, vhal):
111        self.configs = self._getConfig(vhal)
112
113
114    def _getConfig(self, vhal):
115        """
116            Get vhal configuration for properties that need to be simulated
117        """
118        vhalConfig = {}
119        for actionProp in userActions:
120            vhal.getConfig(actionProp)
121            vhalConfig[actionProp] = ActionPropConfig(vhal.rxMsg().config[0])
122        return vhalConfig
123
124    def _adjustContinuousProperty(self, prop, begin, end, listener):
125        """
126            The method generate continuous property value from "begin" value to "end" value
127            (exclusive).
128        """
129        config = self.configs[prop]
130        for area in config.supportedAreas:
131            areaConfig = config.areaConfigs[area]
132            if begin < end:
133                begin = areaConfig.min if begin < areaConfig.min else begin
134                end = areaConfig.max if end > areaConfig.max else end
135            else:
136                begin = areaConfig.max if begin > areaConfig.max else begin
137                end = areaConfig.min if end < areaConfig.min else end
138
139            for value in self._range(begin, end):
140                listener.handle(prop, area, value, propDesc[prop])
141                time.sleep(0.2)
142
143    def _setProperty(self, prop, value, listener):
144        """
145            This method generates single property value (e.g. boolean or integer value)
146        """
147        config = self.configs[prop]
148        for area in config.supportedAreas:
149            listener.handle(prop, area, value, propDesc[prop])
150            time.sleep(1)
151
152    def _range(self, begin, end):
153        if begin < end:
154            i = begin
155            while i < end:
156                yield i
157                i += 1
158        else:
159            i = begin
160            while i > end:
161                yield i
162                i += -1
163
164    def generate(self, listener):
165        """
166            Main method that simulate user in-car actions such as HVAC
167        """
168
169        # Turn on HVAC only for front seats
170        listener.handle(c.VEHICLEPROPERTY_HVAC_POWER_ON, c.VEHICLEAREASEAT_ROW_1_LEFT,
171                        1, 'HVAC_POWER_ON')
172        listener.handle(c.VEHICLEPROPERTY_HVAC_POWER_ON, c.VEHICLEAREASEAT_ROW_1_RIGHT,
173                        1, 'HVAC_POWER_ON')
174        time.sleep(SHORT_SLEEP_TIME_SEC)
175
176        while True:
177
178            self._setProperty(c.VEHICLEPROPERTY_HVAC_AC_ON, 1, listener)
179            time.sleep(SHORT_SLEEP_TIME_SEC)
180
181            self._setProperty(c.VEHICLEPROPERTY_HVAC_FAN_DIRECTION,
182                              c.VEHICLEHVACFANDIRECTION_FACE, listener)
183            time.sleep(SHORT_SLEEP_TIME_SEC)
184
185            self._adjustContinuousProperty(c.VEHICLEPROPERTY_HVAC_TEMPERATURE_SET,
186                                           MAX_TEMPERATURE_C, MIN_TEMPERATURE_C, listener)
187            time.sleep(SHORT_SLEEP_TIME_SEC)
188
189            self._adjustContinuousProperty(c.VEHICLEPROPERTY_HVAC_FAN_SPEED,
190                                           MIN_FAN_SPEED, MAX_FAN_SPEED, listener)
191            time.sleep(LONG_SLEEP_TIME_SEC)
192
193            self._setProperty(c.VEHICLEPROPERTY_HVAC_AUTO_ON, 1, listener)
194            time.sleep(LONG_SLEEP_TIME_SEC)
195
196            self._setProperty(c.VEHICLEPROPERTY_HVAC_AUTO_ON, 0, listener)
197            time.sleep(SHORT_SLEEP_TIME_SEC)
198
199            self._setProperty(c.VEHICLEPROPERTY_HVAC_FAN_DIRECTION,
200                              c.VEHICLEHVACFANDIRECTION_FACE, listener)
201            time.sleep(LONG_SLEEP_TIME_SEC)
202
203            self._setProperty(c.VEHICLEPROPERTY_HVAC_DEFROSTER, 1, listener)
204            time.sleep(SHORT_SLEEP_TIME_SEC)
205
206            self._setProperty(c.VEHICLEPROPERTY_HVAC_FAN_DIRECTION,
207                              c.VEHICLEHVACFANDIRECTION_DEFROST, listener)
208            time.sleep(SHORT_SLEEP_TIME_SEC)
209
210            self._adjustContinuousProperty(c.VEHICLEPROPERTY_HVAC_TEMPERATURE_SET,
211                                           MIN_TEMPERATURE_C, MAX_TEMPERATURE_C, listener)
212            time.sleep(SHORT_SLEEP_TIME_SEC)
213
214            self._adjustContinuousProperty(c.VEHICLEPROPERTY_HVAC_FAN_SPEED,
215                                           MAX_FAN_SPEED, MIN_FAN_SPEED, listener)
216            time.sleep(LONG_SLEEP_TIME_SEC)
217
218            self._setProperty(c.VEHICLEPROPERTY_HVAC_AC_ON, 0, listener)
219            time.sleep(SHORT_SLEEP_TIME_SEC)
220