Ejemplo n.º 1
0
 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()
Ejemplo n.º 2
0
 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)
Ejemplo n.º 3
0
 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)
Ejemplo n.º 4
0
 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()
Ejemplo n.º 5
0
 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()
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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')
Ejemplo n.º 10
0
    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
            },
        )
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
    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
Ejemplo n.º 14
0
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
Ejemplo n.º 15
0
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()
Ejemplo n.º 16
0
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
Ejemplo n.º 17
0
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
Ejemplo n.º 18
0
 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()
Ejemplo n.º 20
0
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'])
Ejemplo n.º 21
0
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
Ejemplo n.º 22
0
#!/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("--------------------------------------")
Ejemplo n.º 23
0
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
Ejemplo n.º 24
0
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)
Ejemplo n.º 25
0
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])
Ejemplo n.º 26
0
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
Ejemplo n.º 27
0
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
Ejemplo n.º 28
0
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)
Ejemplo n.º 29
0
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
Ejemplo n.º 30
0
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()