def start(self): LOGGER.info('Started VeSync NodeServer') self.removeNoticesAll() if self.check_params(): self.removeNoticesAll() self.vesync = VeSync(self.email, self.password) self.vesync.login() self.vesync.update() self.discover()
def setUp(self): self.vesync_1 = VeSync('*****@*****.**', 'password', 'America/New_York') self.vesync_2 = VeSync('*****@*****.**', 'password') self.vesync_3 = VeSync('*****@*****.**', 'password', None) self.vesync_4 = VeSync('*****@*****.**', 'password') self.vesync_5 = VeSync('', '') self.vesync_6 = VeSync(None, None, None) self.vesync_7 = VeSync(None, 'password') self.vesync_8 = VeSync('*****@*****.**', None) self.vesync_9 = VeSync('*****@*****.**', 'password', 1)
def setUp(self): """Setup VeSync argument cases.""" self.vesync_1 = VeSync('*****@*****.**', 'password', 'America/New_York') self.vesync_2 = VeSync('*****@*****.**', 'password') self.vesync_3 = VeSync('*****@*****.**', 'password', None) self.vesync_4 = VeSync('*****@*****.**', 'password') self.vesync_5 = VeSync('', '') self.vesync_6 = VeSync(None, None, None) self.vesync_7 = VeSync(None, 'password') self.vesync_8 = VeSync('*****@*****.**', None) self.vesync_9 = VeSync('*****@*****.**', 'password', 1)
def api_mock(self, caplog): self.mock_api_call = patch('pyvesync.helpers.Helpers.call_api') self.mock_api = self.mock_api_call.start() self.mock_api.create_autospect() self.mock_api.return_value.ok = True self.vesync_obj = VeSync('*****@*****.**', 'pass') self.vesync_obj.enabled = True self.vesync_obj.login = True self.vesync_obj.token = 'sample_tk' self.vesync_obj.account_id = 'sample_actid' caplog.set_level(logging.DEBUG) yield self.mock_api_call.stop()
def api_mock(self, caplog): """Mock call_api() and initialize VeSync object.""" self.mock_api_call = patch.object(pyvesync.helpers.Helpers, 'call_api') self.mock_api = self.mock_api_call.start() self.mock_api.create_autospect() self.mock_api.return_value.ok = True self.vesync_obj = VeSync('*****@*****.**', 'pass') self.vesync_obj.enabled = True self.vesync_obj.login = True self.vesync_obj.tk = 'sample_tk' self.vesync_obj.account_id = 'sample_actid' caplog.set_level(logging.DEBUG) yield self.mock_api_call.stop()
async def async_setup_entry(hass, config_entry): """Set up Vesync as config entry.""" username = config_entry.data[CONF_USERNAME] password = config_entry.data[CONF_PASSWORD] time_zone = str(hass.config.time_zone) manager = VeSync(username, password, time_zone) login = await hass.async_add_executor_job(manager.login) if not login: _LOGGER.error("Unable to login to the VeSync server") return False device_dict = await async_process_devices(hass, manager) forward_setup = hass.config_entries.async_forward_entry_setup hass.data[DOMAIN] = {} hass.data[DOMAIN][VS_MANAGER] = manager switches = hass.data[DOMAIN][VS_SWITCHES] = [] hass.data[DOMAIN][VS_DISPATCHERS] = [] if device_dict[VS_SWITCHES]: switches.extend(device_dict[VS_SWITCHES]) hass.async_create_task(forward_setup(config_entry, "switch")) async def async_new_device_discovery(service): """Discover if new devices should be added.""" manager = hass.data[DOMAIN][VS_MANAGER] switches = hass.data[DOMAIN][VS_SWITCHES] dev_dict = await async_process_devices(hass, manager) switch_devs = dev_dict.get(VS_SWITCHES, []) switch_set = set(switch_devs) new_switches = list(switch_set.difference(switches)) if new_switches and switches: switches.extend(new_switches) async_dispatcher_send(hass, VS_DISCOVERY.format(VS_SWITCHES), new_switches) return if new_switches and not switches: switches.extend(new_switches) hass.async_create_task(forward_setup(config_entry, "switch")) hass.services.async_register(DOMAIN, SERVICE_UPDATE_DEVS, async_new_device_discovery) return True
def refreshList(): manager = VeSync(account['email'], account['password'], time_zone=account['timezone']) manager.login() manager.update() firstRun = 0 dd.clear() de.clear() for device in manager.outlets: dd.append(device.displayJSON()['Device Name']) de.append(device.displayJSON()['Status']) return manager
def SwitchOff(): manager = VeSync("*****@*****.**", "Ge1234") manager.login() manager.update() my_switch = manager.outlets[0] # Turn on the first switch my_switch.turn_off() time.sleep(2) # Turn off the first switch my_switch.turn_on() # Get energy usage data # manager.update_energy() # Display outlet device information # for device in manager.outlets: # device.display() pass
def set_light_state(power_on: bool) -> None: """ Turns the VeSync power outlet on or off, which controls the "busy" light. :param power_on: Should the light be powered on? """ manager = VeSync(VESYNC_EMAIL, VESYNC_PASSWORD) manager.login() manager.update() my_switch = manager.outlets[0] if power_on: my_switch.turn_on() logger.info('Turning light on') else: my_switch.turn_off() logger.info('Turning light off')
async def async_step_user(self, user_input=None): """Handle a flow start.""" if configured_instances(self.hass): return self.async_abort(reason="already_setup") if not user_input: return self._show_form() self._username = user_input[CONF_USERNAME] self._password = user_input[CONF_PASSWORD] manager = VeSync(self._username, self._password) login = await self.hass.async_add_executor_job(manager.login) if not login: return self._show_form(errors={"base": "invalid_login"}) return self.async_create_entry( title=self._username, data={ CONF_USERNAME: self._username, CONF_PASSWORD: self._password }, )
def __init__(self, vesync_name, duration=None, states=["on", "off"], **kwargs): BaseModule.__init__(self, **kwargs) self.vesync_name = vesync_name self.duration = duration self.next_idx = 0 self.states = states if not VeSyncOutlet.manager: VeSyncOutlet.manager = VeSync(os.environ['VESYNC_USERNAME'], os.environ['VESYNC_PASSWORD']) VeSyncOutlet.manager.login() VeSyncOutlet.manager.update() self.device = next( filter(lambda x: x.device_name == vesync_name, VeSyncOutlet.manager.outlets), None) if self.device is None: raise Exception("Unable to find VeSync device " + vesync_name)
async def async_step_user(self, user_input=None): """Handle a flow start.""" if self._async_current_entries(): return self.async_abort(reason="single_instance_allowed") if not user_input: return self._show_form() self._username = user_input[CONF_USERNAME] self._password = user_input[CONF_PASSWORD] manager = VeSync(self._username, self._password) login = await self.opp.async_add_executor_job(manager.login) if not login: return self._show_form(errors={"base": "invalid_auth"}) return self.async_create_entry( title=self._username, data={ CONF_USERNAME: self._username, CONF_PASSWORD: self._password }, )
class App: MQTT_ROOT_TOPIC = os.environ["MQTT_ROOT_TOPIC"] _manager = VeSync _purifier = Any _auto_mode = False _publishing = False _run = True def __init__(self): self.main() def main(self): # Connect to MQTT broker client = mqtt.Client() client.on_connect = self.on_connect client.on_message = self.on_message print("Connecting to MQTT broker...") client.username_pw_set(os.environ["MQTT_USER"], os.environ["MQTT_PASS"]) client.connect(os.environ["MQTT_HOST"], port=int(os.environ["MQTT_PORT"]), keepalive=60) client.subscribe(f"{self.MQTT_ROOT_TOPIC}/power_state") client.subscribe(f"{self.MQTT_ROOT_TOPIC}/auto_mode") # client.subscribe(f"{self.MQTT_ROOT_TOPIC}/sleep_mode") client.subscribe(f"{self.MQTT_ROOT_TOPIC}/fan_speed") client.subscribe(f"{self.MQTT_ROOT_TOPIC}/air_quality") client.subscribe(f"{self.MQTT_ROOT_TOPIC}/filter_life") # Connect to VeSync API print("Connecting to VeSync API...") attempts = 3 self._manager = VeSync(os.environ["VESYNC_USER"], os.environ["VESYNC_PASS"], os.environ["TZ"]) while not self._manager.login() and attempts > 0: print(f"Could not connect. Attempts remaining: {attempts}.") attempts -= 1 time.sleep(1000) self._manager.update() self._purifier = self._manager.fans[0] # Start loop client.loop_start() while self._run: try: # Get readings from API self._purifier.update() power_state = self._purifier.device_status fan_speed = self._purifier.fan_level # If the fan is in auto mode, the value will be returned as None if fan_speed == None: fan_speed = 0 air_quality = self._purifier.air_quality filter_life = self._purifier.filter_life self._auto_mode = self._purifier.mode == "auto" # print(f"state: {power_state}, speed: {fan_speed}, AQ: {air_quality}, life: {filter_life}, auto: {self._auto_mode}") self._publishing = True client.publish("smarthome/air-purifier/power_state", power_state.upper()) client.publish("smarthome/air-purifier/auto_mode", "ON" if self._auto_mode else "OFF") client.publish("smarthome/air-purifier/fan_speed", fan_speed) client.publish("smarthome/air-purifier/air_quality", air_quality) client.publish("smarthome/air-purifier/filter_life", filter_life) time.sleep(0.5) self._publishing = False time.sleep(5) except KeyboardInterrupt: self._run = False print("Stopping application...") client.loop_stop() def on_connect(self, client, userdata, flags, rc): print(f"MQTT connection returned result: {mqtt.connack_string(rc)}") def on_message(self, client, userdata, message): # Don't listen to own messages > prevent message recursion if self._publishing: return decoded_payload = message.payload.decode("utf-8") print(f"Received {message.topic}: {decoded_payload}") if message.topic == f"{self.MQTT_ROOT_TOPIC}/power_state": if decoded_payload == "ON": self._purifier.turn_on() elif decoded_payload == "OFF": self._purifier.turn_off() if message.topic == f"{self.MQTT_ROOT_TOPIC}/auto_mode": if decoded_payload == "ON": self._purifier.auto_mode() self._auto_mode = True elif decoded_payload == "OFF": self._purifier.manual_mode() self._auto_mode = False if message.topic == f"{self.MQTT_ROOT_TOPIC}/fan_speed": try: value = int(decoded_payload) if value not in [1, 2, 3]: return if self._auto_mode: self._purifier.manual_mode() self._auto_mode = False self._purifier.change_fan_speed(value) except ValueError: pass
class TestVeSyncBulbESL100: @pytest.fixture() def api_mock(self, caplog): self.mock_api_call = patch('pyvesync.helpers.Helpers.call_api') self.mock_api = self.mock_api_call.start() self.mock_api.create_autospect() self.mock_api.return_value.ok = True self.vesync_obj = VeSync('*****@*****.**', 'pass') self.vesync_obj.enabled = True self.vesync_obj.login = True self.vesync_obj.token = 'sample_tk' self.vesync_obj.account_id = 'sample_actid' caplog.set_level(logging.DEBUG) yield self.mock_api_call.stop() def test_esl100_conf(self, api_mock): """Tests that Wall Switch is instantiated properly""" self.mock_api.return_value = DEV_LIST devices = self.vesync_obj.get_devices() bulbs = devices[3] assert len(bulbs) == 1 bulb = bulbs[0] assert isinstance(bulb, VeSyncBulbESL100) assert bulb.device_name == "Etekcity Soft White Bulb" assert bulb.device_type == "ESL100" assert bulb.cid == "ESL100-CID" assert bulb.uuid == "UUID" def test_esl100_details(self, api_mock): """Test WS get_details() """ self.mock_api.return_value = DEVICE_DETAILS bulb = VeSyncBulbESL100(DEV_LIST_DETAIL, self.vesync_obj) bulb.get_details() dev_details = bulb.details assert bulb.device_status == 'on' assert isinstance(dev_details, dict) assert bulb.connection_status == 'online' def test_esl100_no_details(self, caplog, api_mock): """Test no device details for disconnected bulb""" self.mock_api.return_value = ({'code': 5}, 200) bulb = VeSyncBulbESL100(DEV_LIST_DETAIL, self.vesync_obj) bulb.update() assert len(caplog.records) == 2 def test_esl100_onoff(self, caplog, api_mock): """Test power toggle for ESL100 bulb""" self.mock_api.return_value = ({'code': 0}, 200) bulb = VeSyncBulbESL100(DEV_LIST_DETAIL, self.vesync_obj) assert bulb.turn_off() assert bulb.turn_on() def test_brightness(self, api_mock): self.mock_api.return_value = ({'code': 0}, 200) bulb = VeSyncBulbESL100(DEV_LIST_DETAIL, self.vesync_obj) assert bulb.set_brightness(50) def test_invalid_brightness(self, caplog, api_mock): bulb = VeSyncBulbESL100(DEV_LIST_DETAIL, self.vesync_obj) assert not bulb.set_brightness(5000) def test_features(self, api_mock): bulb = VeSyncBulbESL100(DEV_LIST_DETAIL, self.vesync_obj) assert bulb.dimmable_feature assert not bulb.bulb_temp_feature assert not bulb.color_change_feature
class TestVesyncWallSwitch(object): @pytest.fixture() def api_mock(self, caplog): self.mock_api_call = patch('pyvesync.helpers.Helpers.call_api') self.mock_api = self.mock_api_call.start() self.mock_api.create_autospect() self.mock_api.return_value.ok = True self.vesync_obj = VeSync('*****@*****.**', 'pass') self.vesync_obj.enabled = True self.vesync_obj.login = True self.vesync_obj.token = 'sample_tk' self.vesync_obj.account_id = 'sample_actid' caplog.set_level(logging.DEBUG) yield self.mock_api_call.stop() def test_ws_conf(self, api_mock): """Tests that Wall Switch is instantiated properly""" self.mock_api.return_value = CORRECT_WS_LIST devices = self.vesync_obj.get_devices() switch = devices[1] assert len(switch) == 1 wswitch = switch[0] assert isinstance(wswitch, VeSyncWallSwitch) assert wswitch.device_name == "Name Wall Switch" assert wswitch.device_type == "ESWL01" assert wswitch.cid == "WS-CID" assert wswitch.uuid == "UUID" def test_ws_details(self, api_mock): """Test WS get_details() """ self.mock_api.return_value = CORRECT_WS_DETAILS wswitch = VeSyncWallSwitch(DEV_LIST_DETAIL, self.vesync_obj) wswitch.get_details() dev_details = wswitch.details assert wswitch.device_status == 'on' assert type(dev_details) == dict assert dev_details['active_time'] == 1 assert wswitch.connection_status == 'online' def test_ws_details_fail(self, caplog, api_mock): """Test WS get_details with Code>0""" self.mock_api.return_value = BAD_LIST vswitch15a = VeSyncWallSwitch(DEV_LIST_DETAIL, self.vesync_obj) vswitch15a.get_details() assert len(caplog.records) == 2 assert 'details' in caplog.text def test_ws_onoff(self, caplog, api_mock): """Test 15A Device On/Off Methods""" self.mock_api.return_value = ({"code": 0}, 200) wswitch = VeSyncWallSwitch(DEV_LIST_DETAIL, self.vesync_obj) head = helpers.req_headers(self.vesync_obj) body = helpers.req_body(self.vesync_obj, 'devicestatus') body['status'] = 'on' body['uuid'] = wswitch.uuid on = wswitch.turn_on() self.mock_api.assert_called_with( '/inwallswitch/v1/device/devicestatus', 'put', headers=head, json=body) assert on off = wswitch.turn_off() body['status'] = 'off' self.mock_api.assert_called_with( '/inwallswitch/v1/device/devicestatus', 'put', headers=head, json=body) assert off def test_ws_onoff_fail(self, api_mock): """Test ws On/Off Fail with Code>0""" self.mock_api.return_value = ({"code": 1}, 400) vswitch15a = VeSyncWallSwitch(DEV_LIST_DETAIL, self.vesync_obj) assert not vswitch15a.turn_on() assert not vswitch15a.turn_off()
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Set up Vesync as config entry.""" username = config_entry.data[CONF_USERNAME] password = config_entry.data[CONF_PASSWORD] time_zone = str(hass.config.time_zone) manager = VeSync(username, password, time_zone) login = await hass.async_add_executor_job(manager.login) if not login: _LOGGER.error("Unable to login to the VeSync server") return False device_dict = await async_process_devices(hass, manager) forward_setup = hass.config_entries.async_forward_entry_setup hass.data[DOMAIN] = {} hass.data[DOMAIN][VS_MANAGER] = manager switches = hass.data[DOMAIN][VS_SWITCHES] = [] fans = hass.data[DOMAIN][VS_FANS] = [] lights = hass.data[DOMAIN][VS_LIGHTS] = [] sensors = hass.data[DOMAIN][VS_SENSORS] = [] if device_dict[VS_SWITCHES]: switches.extend(device_dict[VS_SWITCHES]) hass.async_create_task(forward_setup(config_entry, Platform.SWITCH)) if device_dict[VS_FANS]: fans.extend(device_dict[VS_FANS]) hass.async_create_task(forward_setup(config_entry, Platform.FAN)) if device_dict[VS_LIGHTS]: lights.extend(device_dict[VS_LIGHTS]) hass.async_create_task(forward_setup(config_entry, Platform.LIGHT)) if device_dict[VS_SENSORS]: sensors.extend(device_dict[VS_SENSORS]) hass.async_create_task(forward_setup(config_entry, Platform.SENSOR)) async def async_new_device_discovery(service: ServiceCall) -> None: """Discover if new devices should be added.""" manager = hass.data[DOMAIN][VS_MANAGER] switches = hass.data[DOMAIN][VS_SWITCHES] fans = hass.data[DOMAIN][VS_FANS] lights = hass.data[DOMAIN][VS_LIGHTS] sensors = hass.data[DOMAIN][VS_SENSORS] dev_dict = await async_process_devices(hass, manager) switch_devs = dev_dict.get(VS_SWITCHES, []) fan_devs = dev_dict.get(VS_FANS, []) light_devs = dev_dict.get(VS_LIGHTS, []) sensor_devs = dev_dict.get(VS_SENSORS, []) switch_set = set(switch_devs) new_switches = list(switch_set.difference(switches)) if new_switches and switches: switches.extend(new_switches) async_dispatcher_send(hass, VS_DISCOVERY.format(VS_SWITCHES), new_switches) return if new_switches and not switches: switches.extend(new_switches) hass.async_create_task(forward_setup(config_entry, Platform.SWITCH)) fan_set = set(fan_devs) new_fans = list(fan_set.difference(fans)) if new_fans and fans: fans.extend(new_fans) async_dispatcher_send(hass, VS_DISCOVERY.format(VS_FANS), new_fans) return if new_fans and not fans: fans.extend(new_fans) hass.async_create_task(forward_setup(config_entry, Platform.FAN)) light_set = set(light_devs) new_lights = list(light_set.difference(lights)) if new_lights and lights: lights.extend(new_lights) async_dispatcher_send(hass, VS_DISCOVERY.format(VS_LIGHTS), new_lights) return if new_lights and not lights: lights.extend(new_lights) hass.async_create_task(forward_setup(config_entry, Platform.LIGHT)) sensor_set = set(sensor_devs) new_sensors = list(sensor_set.difference(sensors)) if new_sensors and sensors: sensors.extend(new_sensors) async_dispatcher_send(hass, VS_DISCOVERY.format(VS_SENSORS), new_sensors) return if new_sensors and not sensors: sensors.extend(new_sensors) hass.async_create_task(forward_setup(config_entry, Platform.SENSOR)) hass.services.async_register(DOMAIN, SERVICE_UPDATE_DEVS, async_new_device_discovery) return True
async def async_setup_entry(opp, config_entry): """Set up Vesync as config entry.""" username = config_entry.data[CONF_USERNAME] password = config_entry.data[CONF_PASSWORD] time_zone = str(opp.config.time_zone) manager = VeSync(username, password, time_zone) login = await opp.async_add_executor_job(manager.login) if not login: _LOGGER.error("Unable to login to the VeSync server") return False device_dict = await async_process_devices(opp, manager) forward_setup = opp.config_entries.async_forward_entry_setup opp.data[DOMAIN] = {} opp.data[DOMAIN][VS_MANAGER] = manager switches = opp.data[DOMAIN][VS_SWITCHES] = [] fans = opp.data[DOMAIN][VS_FANS] = [] lights = opp.data[DOMAIN][VS_LIGHTS] = [] opp.data[DOMAIN][VS_DISPATCHERS] = [] if device_dict[VS_SWITCHES]: switches.extend(device_dict[VS_SWITCHES]) opp.async_create_task(forward_setup(config_entry, "switch")) if device_dict[VS_FANS]: fans.extend(device_dict[VS_FANS]) opp.async_create_task(forward_setup(config_entry, "fan")) if device_dict[VS_LIGHTS]: lights.extend(device_dict[VS_LIGHTS]) opp.async_create_task(forward_setup(config_entry, "light")) async def async_new_device_discovery(service): """Discover if new devices should be added.""" manager = opp.data[DOMAIN][VS_MANAGER] switches = opp.data[DOMAIN][VS_SWITCHES] fans = opp.data[DOMAIN][VS_FANS] lights = opp.data[DOMAIN][VS_LIGHTS] dev_dict = await async_process_devices(opp, manager) switch_devs = dev_dict.get(VS_SWITCHES, []) fan_devs = dev_dict.get(VS_FANS, []) light_devs = dev_dict.get(VS_LIGHTS, []) switch_set = set(switch_devs) new_switches = list(switch_set.difference(switches)) if new_switches and switches: switches.extend(new_switches) async_dispatcher_send(opp, VS_DISCOVERY.format(VS_SWITCHES), new_switches) return if new_switches and not switches: switches.extend(new_switches) opp.async_create_task(forward_setup(config_entry, "switch")) fan_set = set(fan_devs) new_fans = list(fan_set.difference(fans)) if new_fans and fans: fans.extend(new_fans) async_dispatcher_send(opp, VS_DISCOVERY.format(VS_FANS), new_fans) return if new_fans and not fans: fans.extend(new_fans) opp.async_create_task(forward_setup(config_entry, "fan")) light_set = set(light_devs) new_lights = list(light_set.difference(lights)) if new_lights and lights: lights.extend(new_lights) async_dispatcher_send(opp, VS_DISCOVERY.format(VS_LIGHTS), new_lights) return if new_lights and not lights: lights.extend(new_lights) opp.async_create_task(forward_setup(config_entry, "light")) opp.services.async_register(DOMAIN, SERVICE_UPDATE_DEVS, async_new_device_discovery) return True
def _get_plug(self): manager = VeSync(self.email, self.password, self.time_zone) manager.login() manager.update() return manager.outlets[self.index]
with open('config.yaml', 'r') as f: config = yaml.safe_load(f.read()) logging.config.dictConfig(config['Logging']) logging.info("Starting VeSync monitoring daemon") influx_client = InfluxDBClient(url=config['InfluxDB']['url'], token=config['InfluxDB']['token'], org=config['InfluxDB']['org']) influx_writer = influx_client.write_api(write_options=SYNCHRONOUS) vesync_client = VeSync(config['VeSync']['email'], config['VeSync']['password'], time_zone='America/New_York') if not vesync_client.login(): logging.critical("Could not login to VeSync") sys.exit(1) while True: influx_payload = [] try: logging.info("Updating energy information") vesync_client.update() vesync_client.update_energy() now = datetime.utcnow().isoformat()
VESYNCAPIPATH = config['DEFAULT']['VESYNCAPIPATH'] POWERTHRESHOLD = float(config['DEFAULT']['PowerThreshold']) InfluxDBIP = str(config['DEFAULT']['InfluxDBIP']) UserName = config['DEFAULT']['UserName'] Password = config['DEFAULT']['Password'] botoclient = boto3.client( "sns", aws_access_key_id=config['DEFAULT']['aws_access_key_id'], aws_secret_access_key=config['DEFAULT']['aws_secret_access_key'], region_name=config['DEFAULT']['region_name']) OutletsToProcess = config['DEFAULT']['OutletsToProcess'].split(",") sys.path.insert(0, VESYNCAPIPATH) from pyvesync import VeSync manager = VeSync(UserName, Password, time_zone=DEFAULT_TZ) manager.login() manager.update() # Get energy usage data manager.update_energy() client = InfluxDBClient(InfluxDBIP, 8086, '', '', 'EnergyMonitor') # Display outlet device information for device in manager.outlets: ret = device.displayJSON() print("Checking if array contians " + ret['Device Name']) if (ret['Device Name'] in OutletsToProcess): currentValue = float(ret['Power'])
class TestVesyncAirPurifier: """Air purifier tests.""" @pytest.fixture() def api_mock(self, caplog): """Mock call_api and initialize VeSync object.""" self.mock_api_call = patch('pyvesync.helpers.Helpers.call_api') self.mock_api = self.mock_api_call.start() self.mock_api.create_autospect() self.mock_api.return_value.ok = True self.vesync_obj = VeSync('*****@*****.**', 'pass') self.vesync_obj.enabled = True self.vesync_obj.login = True self.vesync_obj.token = 'sample_tk' self.vesync_obj.account_id = 'sample_actid' caplog.set_level(logging.DEBUG) yield self.mock_api_call.stop() def test_airpur_conf(self, api_mock): """Tests that 15A Outlet is instantiated properly.""" self.mock_api.return_value = CORRECT_LIST self.vesync_obj.get_devices() fans = self.vesync_obj.fans assert len(fans) == 1 fan = fans[0] assert isinstance(fan, VeSyncAir131) assert fan.device_name == 'Name Air Purifier' assert fan.device_type == 'LV-PUR131S' assert fan.cid == 'AIRPUR-CID' assert fan.uuid == 'UUID' def test_airpur_details(self, api_mock): """Test 15A get_details().""" self.mock_api.return_value = CORRECT_DETAILS fan = VeSyncAir131(DEV_LIST_DETAIL, self.vesync_obj) fan.get_details() dev_details = fan.details assert fan.device_status == 'on' assert isinstance(dev_details, dict) assert dev_details['active_time'] == 1 assert fan.filter_life == 100 assert dev_details['screen_status'] == 'on' assert fan.mode == 'manual' assert dev_details['level'] == 1 assert fan.fan_level == 1 assert dev_details['air_quality'] == 'excellent' assert fan.air_quality == 'excellent' def test_airpur_details_fail(self, caplog, api_mock): """Test Air Purifier get_details with Code>0.""" self.mock_api.return_value = BAD_LIST fan = VeSyncAir131(DEV_LIST_DETAIL, self.vesync_obj) fan.get_details() assert len(caplog.records) == 1 assert 'details' in caplog.text def test_airpur_onoff(self, caplog, api_mock): """Test Air Purifier Device On/Off Methods.""" self.mock_api.return_value = ({'code': 0}, 200) fan = VeSyncAir131(DEV_LIST_DETAIL, self.vesync_obj) head = helpers.req_headers(self.vesync_obj) body = helpers.req_body(self.vesync_obj, 'devicestatus') fan.device_status = 'off' body['status'] = 'on' body['uuid'] = fan.uuid on = fan.turn_on() self.mock_api.assert_called_with( '/131airPurifier/v1/device/deviceStatus', 'put', json_object=body, headers=head) call_args = self.mock_api.call_args_list[0][0] assert call_args[0] == '/131airPurifier/v1/device/deviceStatus' assert call_args[1] == 'put' assert on fan.device_status = 'on' off = fan.turn_off() body['status'] = 'off' self.mock_api.assert_called_with( '/131airPurifier/v1/device/deviceStatus', 'put', json_object=body, headers=head) assert off def test_airpur_onoff_fail(self, api_mock): """Test Air Purifier On/Off Fail with Code>0.""" self.mock_api.return_value = ({'code': 1}, 400) vsfan = VeSyncAir131(DEV_LIST_DETAIL, self.vesync_obj) assert not vsfan.turn_on() assert not vsfan.turn_off() def test_airpur_fanspeed(self, caplog, api_mock): """Test changing fan speed of.""" self.mock_api.return_value = ({'code': 0}, 200) fan = VeSyncAir131(DEV_LIST_DETAIL, self.vesync_obj) fan.details['level'] = 1 b = fan.change_fan_speed() assert fan.fan_level == 2 b = fan.change_fan_speed() assert fan.fan_level == 3 b = fan.change_fan_speed() assert fan.fan_level == 1 assert b b = fan.change_fan_speed(2) assert b assert fan.fan_level == 2 def test_mode_toggle(self, caplog, api_mock): """Test changing modes on air purifier.""" self.mock_api.return_value = ({'code': 0}, 200) fan = VeSyncAir131(DEV_LIST_DETAIL, self.vesync_obj) f = fan.auto_mode() assert f assert fan.mode == 'auto' f = fan.manual_mode() assert fan.mode == 'manual' assert f f = fan.sleep_mode() assert fan.mode == 'sleep' assert f
#!/usr/bin/env python3 import os from pyvesync import VeSync EMAIL = os.getenv('EMAIL') PASSWORD = os.getenv('PASSWORD') TZ = os.getenv('TZ', 'America/New_York') manager = VeSync(EMAIL, PASSWORD, time_zone=TZ) manager.login() manager.update() for device in manager.outlets: device.display() print("--------------------------------------")
class TestVesync15ASwitch(object): @pytest.fixture() def api_mock(self, caplog): self.mock_api_call = patch('pyvesync.helpers.Helpers.call_api') self.mock_api = self.mock_api_call.start() self.mock_api.create_autospect() self.mock_api.return_value.ok = True self.vesync_obj = VeSync('*****@*****.**', 'pass') self.vesync_obj.enabled = True self.vesync_obj.login = True self.vesync_obj.token = 'sample_tk' self.vesync_obj.account_id = 'sample_actid' caplog.set_level(logging.DEBUG) yield self.mock_api_call.stop() def test_15aswitch_conf(self, api_mock): """Tests that 15A Outlet is instantiated properly""" self.mock_api.return_value = CORRECT_15A_LIST outlets = self.vesync_obj.get_devices() outlets = outlets[0] assert len(outlets) == 1 vswitch15a = outlets[0] assert isinstance(vswitch15a, VeSyncOutlet15A) assert vswitch15a.device_name == "Name 15A Outlet" assert vswitch15a.device_type == "ESW15-USA" assert vswitch15a.cid == "15A-CID" assert vswitch15a.uuid == "UUID" def test_15a_details(self, api_mock): """Test 15A get_details() """ self.mock_api.return_value = CORRECT_15A_DETAILS vswitch15a = VeSyncOutlet15A(DEV_LIST_DETAIL, self.vesync_obj) vswitch15a.get_details() dev_details = vswitch15a.details assert vswitch15a.device_status == 'on' assert type(dev_details) == dict assert dev_details['active_time'] == 1 assert dev_details['energy'] == 1 assert dev_details['power'] == '1' assert dev_details['voltage'] == '1' assert vswitch15a.power == 1 assert vswitch15a.voltage == 1 assert vswitch15a.active_time == 1 assert vswitch15a.energy_today == 1 def test_15a_details_fail(self, caplog, api_mock): """Test 15A get_details with Code>0""" self.mock_api.return_value = BAD_15A_LIST vswitch15a = VeSyncOutlet15A(DEV_LIST_DETAIL, self.vesync_obj) vswitch15a.get_details() assert len(caplog.records) == 1 assert 'details' in caplog.text def test_15a_no_details(self, caplog, api_mock): """Test 15A details return with no details and code=0""" bad_15a_details = {"code": 0, "deviceStatus": "on"} self.mock_api.return_value = (bad_15a_details, 200) vswitch15a = VeSyncOutlet15A(DEV_LIST_DETAIL, self.vesync_obj) vswitch15a.get_details() assert len(caplog.records) == 2 def test_15a_onoff(self, caplog, api_mock): """Test 15A Device On/Off Methods""" self.mock_api.return_value = ({"code": 0}, 200) vswitch15a = VeSyncOutlet15A(DEV_LIST_DETAIL, self.vesync_obj) head = helpers.req_headers(self.vesync_obj) body = helpers.req_body(self.vesync_obj, 'devicestatus') body['status'] = 'on' body['uuid'] = vswitch15a.uuid on = vswitch15a.turn_on() self.mock_api.assert_called_with('/15a/v1/device/devicestatus', 'put', headers=head, json=body) assert on off = vswitch15a.turn_off() body['status'] = 'off' self.mock_api.assert_called_with('/15a/v1/device/devicestatus', 'put', headers=head, json=body) assert off def test_15a_onoff_fail(self, api_mock): """Test 15A On/Off Fail with Code>0""" self.mock_api.return_value = ({"code": 1}, 400) vswitch15a = VeSyncOutlet15A(DEV_LIST_DETAIL, self.vesync_obj) assert not vswitch15a.turn_on() assert not vswitch15a.turn_off() def test_15a_weekly(self, api_mock): """Test 15A get_weekly_energy""" self.mock_api.return_value = ENERGY_HISTORY vswitch15a = VeSyncOutlet15A(DEV_LIST_DETAIL, self.vesync_obj) vswitch15a.get_weekly_energy() body = helpers.req_body(self.vesync_obj, 'energy_week') body['uuid'] = vswitch15a.uuid self.mock_api.assert_called_with('/15a/v1/device/energyweek', 'post', headers=helpers.req_headers( self.vesync_obj), json=body) energy_dict = vswitch15a.energy['week'] assert energy_dict['energy_consumption_of_today'] == 1 assert energy_dict['cost_per_kwh'] == 1 assert energy_dict['max_energy'] == 1 assert energy_dict['total_energy'] == 1 assert energy_dict['data'] == [1, 1] assert vswitch15a.weekly_energy_total == 1 def test_15a_monthly(self, api_mock): """Test 15A get_monthly_energy""" self.mock_api.return_value = ENERGY_HISTORY vswitch15a = VeSyncOutlet15A(DEV_LIST_DETAIL, self.vesync_obj) vswitch15a.get_monthly_energy() body = helpers.req_body(self.vesync_obj, 'energy_month') body['uuid'] = vswitch15a.uuid self.mock_api.assert_called_with('/15a/v1/device/energymonth', 'post', headers=helpers.req_headers( self.vesync_obj), json=body) energy_dict = vswitch15a.energy['month'] assert energy_dict['energy_consumption_of_today'] == 1 assert energy_dict['cost_per_kwh'] == 1 assert energy_dict['max_energy'] == 1 assert energy_dict['total_energy'] == 1 assert energy_dict['data'] == [1, 1] assert vswitch15a.monthly_energy_total == 1 def test_15a_yearly(self, api_mock): """Test 15A get_yearly_energy""" self.mock_api.return_value = ENERGY_HISTORY vswitch15a = VeSyncOutlet15A(DEV_LIST_DETAIL, self.vesync_obj) vswitch15a.get_yearly_energy() body = helpers.req_body(self.vesync_obj, 'energy_year') body['uuid'] = vswitch15a.uuid self.mock_api.assert_called_with('/15a/v1/device/energyyear', 'post', headers=helpers.req_headers( self.vesync_obj), json=body) energy_dict = vswitch15a.energy['year'] assert energy_dict['energy_consumption_of_today'] == 1 assert energy_dict['cost_per_kwh'] == 1 assert energy_dict['max_energy'] == 1 assert energy_dict['total_energy'] == 1 assert energy_dict['data'] == [1, 1] assert vswitch15a.yearly_energy_total == 1 def test_history_fail(self, caplog, api_mock): """Test 15A energy failure""" bad_history = {"code": 1} self.mock_api.return_value = (bad_history, 200) vswitch15a = VeSyncOutlet15A(DEV_LIST_DETAIL, self.vesync_obj) vswitch15a.update_energy() assert len(caplog.records) == 2 assert 'weekly' in caplog.text caplog.clear() vswitch15a.get_monthly_energy() assert len(caplog.records) == 2 assert 'monthly' in caplog.text caplog.clear() vswitch15a.get_yearly_energy() assert len(caplog.records) == 2 assert 'yearly' in caplog.text
class TestVesync(unittest.TestCase): def setUp(self): self.vesync_1 = VeSync('*****@*****.**', 'password', 'America/New_York') self.vesync_2 = VeSync('*****@*****.**', 'password') self.vesync_3 = VeSync('*****@*****.**', 'password', None) self.vesync_4 = VeSync('*****@*****.**', 'password') self.vesync_5 = VeSync('', '') self.vesync_6 = VeSync(None, None, None) self.vesync_7 = VeSync(None, 'password') self.vesync_8 = VeSync('*****@*****.**', None) self.vesync_9 = VeSync('*****@*****.**', 'password', 1) def tearDown(self): pass def test_instance(self): self.assertIsInstance(self.vesync_1, VeSync) def test_username(self): self.assertEqual(self.vesync_1.username, '*****@*****.**') self.assertEqual(self.vesync_5.username, '') self.assertEqual(self.vesync_6.username, None) self.vesync_1.username = '******' self.assertEqual(self.vesync_1.username, '*****@*****.**') def test_password(self): self.assertEqual(self.vesync_1.password, 'password') self.assertEqual(self.vesync_5.password, '') self.assertEqual(self.vesync_6.password, None) self.vesync_1.password = '******' self.assertEqual(self.vesync_1.password, 'other') def test_hash_password(self): self.assertEqual(Helpers.hash_password(self.vesync_1.password), '5f4dcc3b5aa765d61d8327deb882cf99') self.assertEqual(Helpers.hash_password(self.vesync_5.password), 'd41d8cd98f00b204e9800998ecf8427e') with self.assertRaises(AttributeError): Helpers.hash_password(self.vesync_6.password) def test_time_zone(self): self.assertEqual(self.vesync_1.time_zone, 'America/New_York') self.assertEqual(self.vesync_2.time_zone, 'America/New_York') self.assertEqual(self.vesync_3.time_zone, 'America/New_York') self.assertEqual(self.vesync_9.time_zone, 'America/New_York') self.vesync_1.time_zone = 'America/East' self.assertEqual(self.vesync_1.time_zone, 'America/East') def test_login(self): mock_vesync = mock.Mock() mock_vesync.login.return_value = True self.assertTrue(mock_vesync.login()) mock_vesync.login.return_value = False self.assertFalse(mock_vesync.login()) with patch('pyvesync.helpers.Helpers.call_api') as mocked_post: d = { "result": { "accountID": "12346536", "userType": "1", "token": "somevaluehere" }, "code": 0 } mocked_post.return_value = (d, 200) data = self.vesync_1.login() body = Helpers.req_body(self.vesync_1, 'login') body['email'] = self.vesync_1.username body['password'] = Helpers.hash_password(self.vesync_1.password) mocked_post.assert_called_with('/cloud/v1/user/login', 'post', json=body) self.assertTrue(data)
import datetime from pyvesync import VeSync import pandas as pd import sys print(str(datetime.datetime.now()) + ": Libraries loaded & script starting.") config = pd.read_csv("/home/jacobrozran/ecobee/vesync.config") manager = VeSync(config.email[0], config.password[0]) manager.login() manager.update() print( str(datetime.datetime.now()) + ": Connected to VeSync. Figuring out what to do for " + sys.argv[1]) for out in range(len(manager.outlets)): if sys.argv[1] in str.lower(str(manager.outlets[out])): name = out switch = manager.outlets[name] if 'status: on' in str.lower(str(switch)): status = 'on' else: status = 'off' print( str(datetime.datetime.now()) + ": " + sys.argv[1] + " outlet is " + status + " and needs to be " + sys.argv[2])
class TestVesync10ASwitch(object): """Test class for 10A outlets.""" @pytest.fixture() def api_mock(self, caplog): """Mock call_api() method and initialize VeSync object.""" self.mock_api_call = patch('pyvesync.helpers.Helpers.call_api') self.mock_api = self.mock_api_call.start() self.mock_api.create_autospect() self.mock_api.return_value.ok = True self.vesync_obj = VeSync('*****@*****.**', 'pass') self.vesync_obj.enabled = True self.vesync_obj.login = True self.vesync_obj.token = 'sample_tk' self.vesync_obj.account_id = 'sample_actid' caplog.set_level(logging.DEBUG) yield self.mock_api_call.stop() @pytest.mark.parametrize('mock_return, devtype', [(CORRECT_10AEU_LIST, 'ESW01-EU'), (CORRECT_10AUS_LIST, 'ESW03-USA')]) def test_10a_conf(self, mock_return, devtype, api_mock): """Tests that 10A US & EU Outlet is instantiated properly.""" self.mock_api.return_value = mock_return outlets = self.vesync_obj.get_devices() outlets = outlets[0] assert len(outlets) == 1 outlet = outlets[0] assert isinstance(outlet, VeSyncOutlet10A) assert outlet.device_name == "Name 10A Outlet" assert outlet.device_type == devtype assert outlet.cid == "10A-CID" assert outlet.uuid == "UUID" def test_10a_details(self, api_mock): """Test 10A get_details().""" self.mock_api.return_value = CORRECT_10A_DETAILS outlet = VeSyncOutlet10A(DEV_LIST_DETAIL_US, self.vesync_obj) outlet.get_details() dev_details = outlet.details assert outlet.device_status == 'on' assert type(dev_details) == dict assert dev_details['active_time'] == 1 assert dev_details['energy'] == 1 assert dev_details['power'] == '1' assert dev_details['voltage'] == '1' assert outlet.power == 1 assert outlet.voltage == 1 def test_10a_details_fail(self, caplog, api_mock): """Test 10A get_details with Code>0.""" self.mock_api.return_value = BAD_10A_LIST out = VeSyncOutlet10A(DEV_LIST_DETAIL_EU, self.vesync_obj) out.get_details() assert len(caplog.records) == 1 assert 'details' in caplog.text def test_10a_onoff(self, caplog, api_mock): """Test 10A Device On/Off Methods.""" self.mock_api.return_value = ({"code": 0}, 200) out = VeSyncOutlet10A(DEV_LIST_DETAIL_EU, self.vesync_obj) head = helpers.req_headers(self.vesync_obj) body = helpers.req_body(self.vesync_obj, 'devicestatus') body['status'] = 'on' body['uuid'] = out.uuid on = out.turn_on() self.mock_api.assert_called_with('/10a/v1/device/devicestatus', 'put', headers=head, json=body) assert on off = out.turn_off() body['status'] = 'off' self.mock_api.assert_called_with('/10a/v1/device/devicestatus', 'put', headers=head, json=body) assert off def test_10a_onoff_fail(self, api_mock): """Test 10A On/Off Fail with Code>0.""" self.mock_api.return_value = ({"code": 1}, 400) out = VeSyncOutlet10A(DEV_LIST_DETAIL_US, self.vesync_obj) assert not out.turn_on() assert not out.turn_off() def test_10a_weekly(self, api_mock): """Test 10A get_weekly_energy.""" self.mock_api.return_value = ENERGY_HISTORY out = VeSyncOutlet10A(DEV_LIST_DETAIL_EU, self.vesync_obj) out.get_weekly_energy() body = helpers.req_body(self.vesync_obj, 'energy_week') body['uuid'] = out.uuid self.mock_api.assert_called_with('/10a/v1/device/energyweek', 'post', headers=helpers.req_headers( self.vesync_obj), json=body) energy_dict = out.energy['week'] assert energy_dict['energy_consumption_of_today'] == 1 assert energy_dict['cost_per_kwh'] == 1 assert energy_dict['max_energy'] == 1 assert energy_dict['total_energy'] == 1 assert energy_dict['data'] == [1, 1] assert out.weekly_energy_total == 1 def test_10a_monthly(self, api_mock): """Test 10A get_monthly_energy.""" self.mock_api.return_value = ENERGY_HISTORY out = VeSyncOutlet10A(DEV_LIST_DETAIL_EU, self.vesync_obj) out.get_monthly_energy() body = helpers.req_body(self.vesync_obj, 'energy_month') body['uuid'] = out.uuid self.mock_api.assert_called_with('/10a/v1/device/energymonth', 'post', headers=helpers.req_headers( self.vesync_obj), json=body) energy_dict = out.energy['month'] assert energy_dict['energy_consumption_of_today'] == 1 assert energy_dict['cost_per_kwh'] == 1 assert energy_dict['max_energy'] == 1 assert energy_dict['total_energy'] == 1 assert energy_dict['data'] == [1, 1] assert out.monthly_energy_total == 1 def test_10a_yearly(self, api_mock): """Test 10A get_yearly_energy.""" self.mock_api.return_value = ENERGY_HISTORY out = VeSyncOutlet10A(DEV_LIST_DETAIL_US, self.vesync_obj) out.get_yearly_energy() body = helpers.req_body(self.vesync_obj, 'energy_year') body['uuid'] = out.uuid self.mock_api.assert_called_with('/10a/v1/device/energyyear', 'post', headers=helpers.req_headers( self.vesync_obj), json=body) energy_dict = out.energy['year'] assert energy_dict['energy_consumption_of_today'] == 1 assert energy_dict['cost_per_kwh'] == 1 assert energy_dict['max_energy'] == 1 assert energy_dict['total_energy'] == 1 assert energy_dict['data'] == [1, 1] assert out.yearly_energy_total == 1 def test_history_fail(self, caplog, api_mock): """Test 15A energy failure.""" bad_history = {"code": 1} self.mock_api.return_value = (bad_history, 200) out = VeSyncOutlet10A(DEV_LIST_DETAIL_US, self.vesync_obj) out.update_energy() assert len(caplog.records) == 1 assert 'weekly' in caplog.text caplog.clear() out.get_monthly_energy() assert len(caplog.records) == 1 assert 'monthly' in caplog.text caplog.clear() out.get_yearly_energy() assert len(caplog.records) == 1 assert 'yearly' in caplog.text
class TestVesync7ASwitch(object): """Test 7A outlet API.""" @pytest.fixture() def api_mock(self, caplog): """Mock call_api() and initialize VeSync object.""" self.mock_api_call = patch.object(pyvesync.helpers.Helpers, 'call_api') self.mock_api = self.mock_api_call.start() self.mock_api.create_autospect() self.mock_api.return_value.ok = True self.vesync_obj = VeSync('*****@*****.**', 'pass') self.vesync_obj.enabled = True self.vesync_obj.login = True self.vesync_obj.tk = 'sample_tk' self.vesync_obj.account_id = 'sample_actid' caplog.set_level(logging.DEBUG) yield self.mock_api_call.stop() def test_7aswitch_conf(self, api_mock): """Test inizialization of 7A outlet.""" self.mock_api.return_value = CORRECT_7A_LIST devs = self.vesync_obj.get_devices() assert len(devs) == 4 vswitch7a = devs[0][0] assert isinstance(vswitch7a, VeSyncOutlet7A) assert vswitch7a.device_name == "Name 7A Outlet" assert vswitch7a.device_type == "wifi-switch-1.3" assert vswitch7a.cid == "7A-CID" assert vswitch7a.is_on def test_7a_details(self, api_mock): """Test get_details() method for 7A outlet.""" self.mock_api.return_value = CORRECT_7A_DETAILS vswitch7a = VeSyncOutlet7A(DEV_LIST_DETAIL, self.vesync_obj) vswitch7a.get_details() dev_details = vswitch7a.details assert vswitch7a.device_status == 'on' assert type(dev_details) == dict assert dev_details['active_time'] == 1 assert dev_details['energy'] == 1 assert vswitch7a.power == 1 assert vswitch7a.voltage == 1 def test_7a_no_devstatus(self, caplog, api_mock): """Test 7A outlet details response with no device status key.""" bad_7a_details = { "deviceImg": "", "activeTime": 1, "energy": 1, "power": "1A:1A", "voltage": "1A:1A" } self.mock_api.return_value = (bad_7a_details, 200) vswitch7a = VeSyncOutlet7A(DEV_LIST_DETAIL, self.vesync_obj) vswitch7a.get_details() assert len(caplog.records) == 1 assert 'details' in caplog.text def test_7a_no_details(self, caplog, api_mock): """Test 7A outlet details response with unknown keys.""" bad_7a_details = { "wrongdetails": "on" } self.mock_api.return_value = (bad_7a_details, 200) vswitch7a = VeSyncOutlet7A(DEV_LIST_DETAIL, self.vesync_obj) vswitch7a.get_details() assert len(caplog.records) == 1 def test_7a_onoff(self, caplog, api_mock): """Test 7A outlet on/off methods.""" self.mock_api.return_value = ("response", 200) vswitch7a = VeSyncOutlet7A(DEV_LIST_DETAIL, self.vesync_obj) on = vswitch7a.turn_on() head = helpers.req_headers(self.vesync_obj) self.mock_api.assert_called_with( '/v1/wifi-switch-1.3/' + vswitch7a.cid + '/status/on', 'put', headers=head) assert on off = vswitch7a.turn_off() self.mock_api.assert_called_with( '/v1/wifi-switch-1.3/' + vswitch7a.cid + '/status/off', 'put', headers=head) assert off def test_7a_onoff_fail(self, api_mock): """Test 7A outlet on/off methods that fail.""" self.mock_api.return_value = ('response', 400) vswitch7a = VeSyncOutlet7A(DEV_LIST_DETAIL, self.vesync_obj) assert not vswitch7a.turn_on() assert not vswitch7a.turn_off() def test_7a_weekly(self, api_mock): """Test 7A outlet weekly energy API call and energy dict.""" self.mock_api.return_value = ENERGY_HISTORY vswitch7a = VeSyncOutlet7A(DEV_LIST_DETAIL, self.vesync_obj) vswitch7a.get_weekly_energy() self.mock_api.assert_called_with( '/v1/device/' + vswitch7a.cid + '/energy/week', 'get', headers=helpers.req_headers(self.vesync_obj)) energy_dict = vswitch7a.energy['week'] assert energy_dict['energy_consumption_of_today'] == 1 assert energy_dict['cost_per_kwh'] == 1 assert energy_dict['max_energy'] == 1 assert energy_dict['total_energy'] == 1 assert energy_dict['data'] == [1, 1] def test_7a_monthly(self, api_mock): """Test 7A outlet monthly energy API call and energy dict.""" self.mock_api.return_value = ENERGY_HISTORY vswitch7a = VeSyncOutlet7A(DEV_LIST_DETAIL, self.vesync_obj) vswitch7a.get_monthly_energy() self.mock_api.assert_called_with( '/v1/device/' + vswitch7a.cid + '/energy/month', 'get', headers=helpers.req_headers(self.vesync_obj)) energy_dict = vswitch7a.energy['month'] assert energy_dict['energy_consumption_of_today'] == 1 assert energy_dict['cost_per_kwh'] == 1 assert energy_dict['max_energy'] == 1 assert energy_dict['total_energy'] == 1 assert energy_dict['data'] == [1, 1] def test_7a_yearly(self, api_mock): """Test 7A outlet yearly energy API call and energy dict.""" self.mock_api.return_value = ENERGY_HISTORY vswitch7a = VeSyncOutlet7A(DEV_LIST_DETAIL, self.vesync_obj) vswitch7a.get_yearly_energy() self.mock_api.assert_called_with( '/v1/device/' + vswitch7a.cid + '/energy/year', 'get', headers=helpers.req_headers(self.vesync_obj)) energy_dict = vswitch7a.energy['year'] assert energy_dict['energy_consumption_of_today'] == 1 assert energy_dict['cost_per_kwh'] == 1 assert energy_dict['max_energy'] == 1 assert energy_dict['total_energy'] == 1 assert energy_dict['data'] == [1, 1] def test_history_fail(self, caplog, api_mock): """Test handling of energy update failure.""" bad_history = {"code": 1} self.mock_api.return_value = (bad_history, 200) vswitch7a = VeSyncOutlet7A(DEV_LIST_DETAIL, self.vesync_obj) vswitch7a.update_energy() assert len(caplog.records) == 1 assert 'weekly' in caplog.text caplog.clear() vswitch7a.get_monthly_energy() assert len(caplog.records) == 1 assert 'monthly' in caplog.text caplog.clear() vswitch7a.get_yearly_energy() assert len(caplog.records) == 1 assert 'yearly' in caplog.text
class TestVesync(unittest.TestCase): """Test VeSync object initialization.""" def setUp(self): """Setup VeSync argument cases.""" self.vesync_1 = VeSync('*****@*****.**', 'password', 'America/New_York') self.vesync_2 = VeSync('*****@*****.**', 'password') self.vesync_3 = VeSync('*****@*****.**', 'password', None) self.vesync_4 = VeSync('*****@*****.**', 'password') self.vesync_5 = VeSync('', '') self.vesync_6 = VeSync(None, None, None) self.vesync_7 = VeSync(None, 'password') self.vesync_8 = VeSync('*****@*****.**', None) self.vesync_9 = VeSync('*****@*****.**', 'password', 1) def tearDown(self): """Clean up test.""" pass def test_instance(self): """Test VeSync object is successfully initialized.""" self.assertIsInstance(self.vesync_1, VeSync) def test_imports(self): """Test that __all__ contains only names that are actually exported.""" modules = [ 'pyvesync.vesyncfan', 'pyvesync.vesyncbulb', 'pyvesync.vesyncoutlet', 'pyvesync.vesyncswitch' ] for mod in modules: import_mod = importlib.import_module(mod) missing = set(n for n in import_mod.__all__ if getattr(import_mod, n, None) is None) self.assertFalse(missing, msg="__all__ contains unresolved names: %s" % (", ".join(missing), )) def test_username(self): """Test invalid username arguments.""" self.assertEqual(self.vesync_1.username, '*****@*****.**') self.assertEqual(self.vesync_5.username, '') self.assertEqual(self.vesync_6.username, None) self.vesync_1.username = '******' self.assertEqual(self.vesync_1.username, '*****@*****.**') def test_password(self): """Test invalid password arguments.""" self.assertEqual(self.vesync_1.password, 'password') self.assertEqual(self.vesync_5.password, '') self.assertEqual(self.vesync_6.password, None) self.vesync_1.password = '******' self.assertEqual(self.vesync_1.password, 'other') def test_hash_password(self): """Test password hash method.""" self.assertEqual( Helpers.hash_password(self.vesync_1.password), '5f4dcc3b5aa765d61d8327deb882cf99', ) self.assertEqual( Helpers.hash_password(self.vesync_5.password), 'd41d8cd98f00b204e9800998ecf8427e', ) with self.assertRaises(AttributeError): Helpers.hash_password(self.vesync_6.password) def test_time_zone(self): """Test time zone argument handling.""" self.assertEqual(self.vesync_1.time_zone, 'America/New_York') self.assertEqual(self.vesync_2.time_zone, 'America/New_York') self.assertEqual(self.vesync_3.time_zone, 'America/New_York') self.assertEqual(self.vesync_9.time_zone, 'America/New_York') self.vesync_1.time_zone = 'America/East' self.assertEqual(self.vesync_1.time_zone, 'America/East') def test_login(self): """Test login method.""" mock_vesync = mock.Mock() mock_vesync.login.return_value = True self.assertTrue(mock_vesync.login()) mock_vesync.login.return_value = False self.assertFalse(mock_vesync.login()) with patch('pyvesync.helpers.Helpers.call_api') as mocked_post: d = { 'result': { 'accountID': '12346536', 'userType': '1', 'token': 'somevaluehere', }, 'code': 0, } mocked_post.return_value = (d, 200) data = self.vesync_1.login() body = Helpers.req_body(self.vesync_1, 'login') body['email'] = self.vesync_1.username body['password'] = Helpers.hash_password(self.vesync_1.password) mocked_post.assert_called_with('/cloud/v1/user/login', 'post', json_object=body) self.assertTrue(data)
class TestVesyncOutdoorPlug: """Test class for outdoor outlet.""" @pytest.fixture() def api_mock(self, caplog): """Mock call_api and initialize VeSync object.""" self.mock_api_call = patch('pyvesync.helpers.Helpers.call_api') self.mock_api = self.mock_api_call.start() self.mock_api.create_autospec() self.mock_api.return_value.ok = True self.vesync_obj = VeSync('*****@*****.**', 'pass') self.vesync_obj.enabled = True self.vesync_obj.login = True self.vesync_obj.token = 'sample_tk' self.vesync_obj.account_id = 'sample_actid' caplog.set_level(logging.DEBUG) yield self.mock_api_call.stop() def test_outdoor_conf(self, api_mock): """Tests outdoor outlet is instantiated properly.""" self.mock_api.return_value = CORRECT_OUTDOOR_LIST self.vesync_obj.get_devices() outlets = self.vesync_obj.outlets assert len(outlets) == 2 outdoor_outlet = outlets[0] assert isinstance(outdoor_outlet, VeSyncOutdoorPlug) assert outdoor_outlet.device_type == 'ESO15-TB' assert outdoor_outlet.uuid == 'UUID' def test_outdoor_details(self, api_mock): """Tests retrieving outdoor outlet details.""" self.mock_api.return_value = CORRECT_OUTDOOR_DETAILS outdoor_outlet = VeSyncOutdoorPlug(DEV_LIST_DETAIL, self.vesync_obj) outdoor_outlet.get_details() dev_details = outdoor_outlet.details assert outdoor_outlet.device_status == 'on' assert isinstance(outdoor_outlet, VeSyncOutdoorPlug) assert dev_details['active_time'] == 1 def test_outdoor_details_fail(self, caplog, api_mock): """Test outdoor outlet get_details response.""" self.mock_api.return_value = BAD_OUTDOOR_LIST outdoor_outlet = VeSyncOutdoorPlug(DEV_LIST_DETAIL, self.vesync_obj) outdoor_outlet.get_details() assert len(caplog.records) == 1 assert 'details' in caplog.text def test_outdoor_outlet_onoff(self, caplog, api_mock): """Test Outdoor Outlet Device On/Off Methods.""" self.mock_api.return_value = ({'code': 0}, 200) outdoor_outlet = VeSyncOutdoorPlug(DEV_LIST_DETAIL, self.vesync_obj) head = helpers.req_headers(self.vesync_obj) body = helpers.req_body(self.vesync_obj, 'devicestatus') body['status'] = 'on' body['uuid'] = outdoor_outlet.uuid body['switchNo'] = outdoor_outlet.sub_device_no on = outdoor_outlet.turn_on() self.mock_api.assert_called_with( '/outdoorsocket15a/v1/device/devicestatus', 'put', headers=head, json_object=body ) assert on off = outdoor_outlet.turn_off() body['status'] = 'off' self.mock_api.assert_called_with( '/outdoorsocket15a/v1/device/devicestatus', 'put', headers=head, json_object=body ) assert off def test_outdoor_outlet_onoff_fail(self, api_mock): """Test outdoor outlet On/Off Fail with Code>0.""" self.mock_api.return_value = ({'code': 1}, 400) outdoor_outlet = VeSyncOutdoorPlug(DEV_LIST_DETAIL, self.vesync_obj) assert not outdoor_outlet.turn_on() assert not outdoor_outlet.turn_off() def test_outdoor_outlet_weekly(self, api_mock): """Test outdoor outlet get_weekly_energy.""" self.mock_api.return_value = ENERGY_HISTORY outdoor_outlet = VeSyncOutdoorPlug(DEV_LIST_DETAIL, self.vesync_obj) outdoor_outlet.get_weekly_energy() body = helpers.req_body(self.vesync_obj, 'energy_week') body['uuid'] = outdoor_outlet.uuid self.mock_api.assert_called_with( '/outdoorsocket15a/v1/device/energyweek', 'post', headers=helpers.req_headers(self.vesync_obj), json_object=body, ) energy_dict = outdoor_outlet.energy['week'] assert energy_dict['energy_consumption_of_today'] == 1 assert energy_dict['cost_per_kwh'] == 1 assert energy_dict['max_energy'] == 1 assert energy_dict['total_energy'] == 1 assert energy_dict['data'] == [1, 1] assert outdoor_outlet.weekly_energy_total == 1 def test_outdoor_outlet_monthly(self, api_mock): """Test outdoor outlet get_monthly_energy.""" self.mock_api.return_value = ENERGY_HISTORY outdoor_outlet = VeSyncOutdoorPlug(DEV_LIST_DETAIL, self.vesync_obj) outdoor_outlet.get_monthly_energy() body = helpers.req_body(self.vesync_obj, 'energy_month') body['uuid'] = outdoor_outlet.uuid self.mock_api.assert_called_with( '/outdoorsocket15a/v1/device/energymonth', 'post', headers=helpers.req_headers(self.vesync_obj), json_object=body, ) energy_dict = outdoor_outlet.energy['month'] assert energy_dict['energy_consumption_of_today'] == 1 assert energy_dict['cost_per_kwh'] == 1 assert energy_dict['max_energy'] == 1 assert energy_dict['total_energy'] == 1 assert energy_dict['data'] == [1, 1] assert outdoor_outlet.monthly_energy_total == 1 def test_outdoor_outlet_yearly(self, api_mock): """Test outdoor outlet get_yearly_energy.""" self.mock_api.return_value = ENERGY_HISTORY outdoor_outlet = VeSyncOutdoorPlug(DEV_LIST_DETAIL, self.vesync_obj) outdoor_outlet.get_yearly_energy() body = helpers.req_body(self.vesync_obj, 'energy_year') body['uuid'] = outdoor_outlet.uuid self.mock_api.assert_called_with( '/outdoorsocket15a/v1/device/energyyear', 'post', headers=helpers.req_headers(self.vesync_obj), json_object=body, ) energy_dict = outdoor_outlet.energy['year'] assert energy_dict['energy_consumption_of_today'] == 1 assert energy_dict['cost_per_kwh'] == 1 assert energy_dict['max_energy'] == 1 assert energy_dict['total_energy'] == 1 assert energy_dict['data'] == [1, 1] assert outdoor_outlet.yearly_energy_total == 1 def test_history_fail(self, caplog, api_mock): """Test outdoor outlet energy failure.""" bad_history = {'code': 1} self.mock_api.return_value = (bad_history, 200) outdoor_outlet = VeSyncOutdoorPlug(DEV_LIST_DETAIL, self.vesync_obj) outdoor_outlet.update_energy() assert len(caplog.records) == 1 assert 'weekly' in caplog.text caplog.clear() outdoor_outlet.get_monthly_energy() assert len(caplog.records) == 1 assert 'monthly' in caplog.text caplog.clear() outdoor_outlet.get_yearly_energy() assert len(caplog.records) == 1 assert 'yearly' in caplog.text
from pyvesync import VeSync import os import time VESYNC_PASS = os.environ.get('VESYNC_PASS') manager = VeSync("*****@*****.**", VESYNC_PASS, time_zone='America/New_York') manager.login() manager.update() my_switch = manager.outlets[0] my_switch.turn_on() time.sleep(5) my_switch.turn_off()