|
51 | 51 | 'mist_modes': ['humidity', 'sleep', 'manual'], |
52 | 52 | 'mist_levels': list(range(1, 10)), |
53 | 53 | 'warm_mist_levels': list(range(4)) |
54 | | - }, |
| 54 | + }, |
| 55 | + 'OASISMIST1000S': { |
| 56 | + 'module': 'VeSyncHumid1000S', |
| 57 | + 'models': ['LUH-M101S-WUS'], |
| 58 | + 'features': [], |
| 59 | + 'mist_modes': ['auto', 'sleep', 'manual'], |
| 60 | + 'mist_levels': list(range(1, 10)) |
| 61 | + } |
55 | 62 | } |
56 | 63 |
|
57 | 64 |
|
@@ -2001,3 +2008,262 @@ def set_display(self, mode: bool) -> bool: |
2001 | 2008 | return True |
2002 | 2009 | logger.debug("Error toggling 200S display - %s", self.device_name) |
2003 | 2010 | return False |
| 2011 | + |
| 2012 | + |
| 2013 | +class VeSyncHumid1000S(VeSyncHumid200300S): |
| 2014 | + """Levoit OasisMist 1000S Specific class.""" |
| 2015 | + |
| 2016 | + def __init__(self, details, manager): |
| 2017 | + """Initialize levoit 1000S device class.""" |
| 2018 | + super().__init__(details, manager) |
| 2019 | + self.connection_status: str = details.get('deviceProp', {}).get( |
| 2020 | + 'connectionStatus', None) |
| 2021 | + |
| 2022 | + self._api_modes = ['getHumidifierStatus', 'setAutoStopSwitch', |
| 2023 | + 'setSwitch', 'setVirtualLevel', 'setTargetHumidity', |
| 2024 | + 'setHumidityMode', 'setDisplay'] |
| 2025 | + |
| 2026 | + def build_humid_dict(self, dev_dict: Dict[str, str]) -> None: |
| 2027 | + """Build humidifier status dictionary.""" |
| 2028 | + super().build_humid_dict(dev_dict) |
| 2029 | + self.device_status = 'off' if dev_dict.get('powerSwitch', 0) == 0 else 'on' |
| 2030 | + self.details['mist_virtual_level'] = dev_dict.get( |
| 2031 | + 'virtualLevel', 0) |
| 2032 | + self.details['mist_level'] = dev_dict.get('mistLevel', 0) |
| 2033 | + self.details['mode'] = dev_dict.get('workMode', 'manual') |
| 2034 | + self.details['water_lacks'] = bool(dev_dict.get('waterLacksState', 0)) |
| 2035 | + self.details['humidity_high'] = bool(int(dev_dict.get('targetHumidity', 0)) < |
| 2036 | + int(dev_dict.get('humidity', 0))) |
| 2037 | + self.details['water_tank_lifted'] = bool(dev_dict.get( |
| 2038 | + 'waterTankLifted', 0)) |
| 2039 | + self.details['automatic_stop_reach_target'] = bool(dev_dict.get( |
| 2040 | + 'autoStopState', 1 |
| 2041 | + )) |
| 2042 | + self.details['display'] = bool(dev_dict['screenState']) |
| 2043 | + |
| 2044 | + def build_config_dict(self, conf_dict): |
| 2045 | + """Build configuration dict for humidifier.""" |
| 2046 | + self.config['auto_target_humidity'] = conf_dict.get( |
| 2047 | + 'targetHumidity', 0) |
| 2048 | + self.config['display'] = bool(conf_dict.get('screenSwitch', 0)) |
| 2049 | + self.config['automatic_stop'] = bool(conf_dict.get('autoStopSwitch', 1)) |
| 2050 | + |
| 2051 | + def get_details(self) -> None: |
| 2052 | + """Build Humidifier details dictionary.""" |
| 2053 | + head = Helpers.bypass_header() |
| 2054 | + body = Helpers.bypass_body_v2(self.manager) |
| 2055 | + body['cid'] = self.cid |
| 2056 | + body['configModule'] = self.config_module |
| 2057 | + body['payload'] = { |
| 2058 | + 'method': 'getHumidifierStatus', |
| 2059 | + 'source': 'APP', |
| 2060 | + 'data': {} |
| 2061 | + } |
| 2062 | + |
| 2063 | + r, _ = Helpers.call_api( |
| 2064 | + '/cloud/v2/deviceManaged/bypassV2', |
| 2065 | + method='post', |
| 2066 | + headers=head, |
| 2067 | + json_object=body, |
| 2068 | + ) |
| 2069 | + if r is None or not isinstance(r, dict): |
| 2070 | + logger.debug("Error getting status of %s ", self.device_name) |
| 2071 | + return |
| 2072 | + outer_result = r.get('result', {}) |
| 2073 | + inner_result = None |
| 2074 | + |
| 2075 | + if outer_result is not None: |
| 2076 | + inner_result = r.get('result', {}).get('result') |
| 2077 | + if inner_result is not None and Helpers.code_check(r): |
| 2078 | + if outer_result.get('code') == 0: |
| 2079 | + self.connection_status = 'online' |
| 2080 | + self.build_humid_dict(inner_result) |
| 2081 | + self.build_config_dict(inner_result) |
| 2082 | + else: |
| 2083 | + logger.debug('error in inner result dict from humidifier') |
| 2084 | + elif r.get('code') == -11300030: |
| 2085 | + logger.debug('%s device offline', self.device_name) |
| 2086 | + self.connection_status = 'offline' |
| 2087 | + self.device_status = 'off' |
| 2088 | + else: |
| 2089 | + logger.debug('Error in humidifier response') |
| 2090 | + |
| 2091 | + def set_display(self, mode: bool) -> bool: |
| 2092 | + """Toggle display on/off.""" |
| 2093 | + if not isinstance(mode, bool): |
| 2094 | + logger.debug("Mode must be True or False") |
| 2095 | + return False |
| 2096 | + |
| 2097 | + head, body = self.build_api_dict('setDisplay') |
| 2098 | + |
| 2099 | + body['payload']['data'] = { |
| 2100 | + 'screenSwitch': int(mode) |
| 2101 | + } |
| 2102 | + |
| 2103 | + r, _ = Helpers.call_api( |
| 2104 | + '/cloud/v2/deviceManaged/bypassV2', |
| 2105 | + method='post', |
| 2106 | + headers=head, |
| 2107 | + json_object=body, |
| 2108 | + ) |
| 2109 | + |
| 2110 | + if r is not None and Helpers.code_check(r): |
| 2111 | + return True |
| 2112 | + logger.debug("Error toggling purifier display - %s", |
| 2113 | + self.device_name) |
| 2114 | + return False |
| 2115 | + |
| 2116 | + def set_humidity_mode(self, mode: str) -> bool: |
| 2117 | + """Set humidifier mode - sleep, auto or manual.""" |
| 2118 | + if mode.lower() not in self.mist_modes: |
| 2119 | + logger.debug('Invalid humidity mode used - %s', |
| 2120 | + mode) |
| 2121 | + logger.debug('Proper modes for this device are - %s', |
| 2122 | + str(self.mist_modes)) |
| 2123 | + return False |
| 2124 | + head, body = self.build_api_dict('setHumidityMode') |
| 2125 | + if not head and not body: |
| 2126 | + return False |
| 2127 | + body['payload']['data'] = { |
| 2128 | + 'workMode': mode.lower() |
| 2129 | + } |
| 2130 | + |
| 2131 | + r, _ = Helpers.call_api( |
| 2132 | + '/cloud/v2/deviceManaged/bypassV2', |
| 2133 | + method='post', |
| 2134 | + headers=head, |
| 2135 | + json_object=body, |
| 2136 | + ) |
| 2137 | + |
| 2138 | + if r is not None and Helpers.code_check(r): |
| 2139 | + return True |
| 2140 | + logger.debug('Error setting humidity mode') |
| 2141 | + return False |
| 2142 | + |
| 2143 | + def set_sleep_mode(self): |
| 2144 | + """Set humifier to manual mode with 1 mist level.""" |
| 2145 | + return self.set_humidity_mode('sleep') |
| 2146 | + |
| 2147 | + def set_mist_level(self, level) -> bool: |
| 2148 | + """Set humidifier mist level with int.""" |
| 2149 | + try: |
| 2150 | + level = int(level) |
| 2151 | + except ValueError: |
| 2152 | + level = str(level) |
| 2153 | + if level not in self.mist_levels: |
| 2154 | + logger.debug('Humidifier mist level out of range') |
| 2155 | + return False |
| 2156 | + |
| 2157 | + head, body = self.build_api_dict('setVirtualLevel') |
| 2158 | + if not head and not body: |
| 2159 | + return False |
| 2160 | + |
| 2161 | + body['payload']['data'] = { |
| 2162 | + 'levelIdx': 0, |
| 2163 | + 'virtualLevel': level, |
| 2164 | + 'levelType': 'mist' |
| 2165 | + } |
| 2166 | + |
| 2167 | + r, _ = Helpers.call_api( |
| 2168 | + '/cloud/v2/deviceManaged/bypassV2', |
| 2169 | + method='post', |
| 2170 | + headers=head, |
| 2171 | + json_object=body, |
| 2172 | + ) |
| 2173 | + |
| 2174 | + if r is not None and Helpers.code_check(r): |
| 2175 | + return True |
| 2176 | + logger.debug('Error setting mist level') |
| 2177 | + return False |
| 2178 | + |
| 2179 | + def toggle_switch(self, toggle: bool) -> bool: |
| 2180 | + """Toggle humidifier on/off.""" |
| 2181 | + if not isinstance(toggle, bool): |
| 2182 | + logger.debug('Invalid toggle value for humidifier switch') |
| 2183 | + return False |
| 2184 | + |
| 2185 | + head = Helpers.bypass_header() |
| 2186 | + body = Helpers.bypass_body_v2(self.manager) |
| 2187 | + body['cid'] = self.cid |
| 2188 | + body['configModule'] = self.config_module |
| 2189 | + body['payload'] = { |
| 2190 | + 'data': { |
| 2191 | + 'powerSwitch': int(toggle), |
| 2192 | + 'switchIdx': 0 |
| 2193 | + }, |
| 2194 | + 'method': 'setSwitch', |
| 2195 | + 'source': 'APP' |
| 2196 | + } |
| 2197 | + |
| 2198 | + r, _ = Helpers.call_api( |
| 2199 | + '/cloud/v2/deviceManaged/bypassV2', |
| 2200 | + method='post', |
| 2201 | + headers=head, |
| 2202 | + json_object=body, |
| 2203 | + ) |
| 2204 | + |
| 2205 | + if r is not None and Helpers.code_check(r): |
| 2206 | + if toggle: |
| 2207 | + self.device_status = 'on' |
| 2208 | + else: |
| 2209 | + self.device_status = 'off' |
| 2210 | + |
| 2211 | + return True |
| 2212 | + logger.debug("Error toggling humidifier - %s", self.device_name) |
| 2213 | + return False |
| 2214 | + |
| 2215 | + def set_humidity(self, humidity: int) -> bool: |
| 2216 | + """Set target Humidifier humidity.""" |
| 2217 | + if humidity < 30 or humidity > 80: |
| 2218 | + logger.debug("Humidity value must be set between 30 and 80") |
| 2219 | + return False |
| 2220 | + head, body = self.build_api_dict('setTargetHumidity') |
| 2221 | + |
| 2222 | + if not head and not body: |
| 2223 | + return False |
| 2224 | + |
| 2225 | + body['payload']['data'] = { |
| 2226 | + 'targetHumidity': humidity |
| 2227 | + } |
| 2228 | + |
| 2229 | + r, _ = Helpers.call_api( |
| 2230 | + '/cloud/v2/deviceManaged/bypassV2', |
| 2231 | + method='post', |
| 2232 | + headers=head, |
| 2233 | + json_object=body, |
| 2234 | + ) |
| 2235 | + |
| 2236 | + if r is not None and Helpers.code_check(r): |
| 2237 | + return True |
| 2238 | + logger.debug('Error setting humidity') |
| 2239 | + return False |
| 2240 | + |
| 2241 | + def set_automatic_stop(self, mode: bool) -> bool: |
| 2242 | + """Set Humidifier to automatic stop.""" |
| 2243 | + if mode not in (True, False): |
| 2244 | + logger.debug( |
| 2245 | + 'Invalid mode passed to set_automatic_stop - %s', mode) |
| 2246 | + return False |
| 2247 | + |
| 2248 | + head, body = self.build_api_dict('setAutoStopSwitch') |
| 2249 | + if not head and not body: |
| 2250 | + return False |
| 2251 | + |
| 2252 | + body['payload']['data'] = { |
| 2253 | + 'autoStopSwitch': int(mode) |
| 2254 | + } |
| 2255 | + |
| 2256 | + r, _ = Helpers.call_api( |
| 2257 | + '/cloud/v2/deviceManaged/bypassV2', |
| 2258 | + method='post', |
| 2259 | + headers=head, |
| 2260 | + json_object=body, |
| 2261 | + ) |
| 2262 | + |
| 2263 | + if r is not None and Helpers.code_check(r): |
| 2264 | + return True |
| 2265 | + if isinstance(r, dict): |
| 2266 | + logger.debug('Error toggling automatic stop') |
| 2267 | + else: |
| 2268 | + logger.debug('Error in api return json for %s', self.device_name) |
| 2269 | + return False |
0 commit comments