async def test_get_plug_by_index(dev: SmartStrip): assert dev.get_plug_by_index(0) == dev.plugs[0] with pytest.raises(SmartDeviceException): dev.get_plug_by_index(-1) with pytest.raises(SmartDeviceException): dev.get_plug_by_index(len(dev.plugs))
def power_get(host, port, index): assert port is None index = int(index) strip = SmartStrip(host) asyncio.run(strip.update()) assert (len(strip.children) > index), "Trying to access non-existant plug socket on strip" return strip.children[index].is_on
def try_connect(self): try: from kasa import SmartStrip self.strip = SmartStrip(self.plug_address) asyncio.run(self.strip.update()) self.output_setup = True except Exception as e: self.logger.error( "Output was unable to be setup: {err}".format(err=e))
async def connect(self): try: self.strip = SmartStrip(self.address) await self.strip.update() return 0, f'Strip {self.strip.alias}: {self.strip.hw_info}' except Exception: return 1, str(traceback.print_exc())
async def kill(self, ctx): if not await self.isOnCooldown(ctx) and not await self.voteInEffect(ctx ): print('vote started...') self.start_vote = True dev = SmartStrip("192.168.0.165") await dev.update() await ctx.send(f'Kill vote started, type !y or !n in chat!') #vote delay await asyncio.sleep(self.vote_delay) print('vote ended...') #handle pass/fail and reset vote bool if (self.ycount > self.ncount): await ctx.send(f'Vote passed!') print(self.cooldown_end) self.cooldown_end = time.time() + self.kill_delay #reboot plug1 await dev.children[0].turn_off() await asyncio.sleep(1) await dev.children[0].turn_on() print('on cooldown...') await self.kill_wait() print('off cooldown...') else: await ctx.send(f'Vote failed!') self.ycount = 0 self.ncount = 0 self.voter_list = [] self.start_vote = False print('reset!')
class TpLinkHandlerSmartStrip(SmartDeviceException): def __init__(self, address): self.worker = ThreadedWorker() self.device = SmartStrip(address) def update(self): asyncio.run(self.device.update()) def update_two(self): asyncio.create_task(self.device.update()) def update_three(self): future = asyncio.run_coroutine_threadsafe(self.device.update(), self.worker.loop) result = future.result() def shutdown_btn(self, settings): if settings.get(["navButton", "deviceOne"]): asyncio.create_task(self.device.children[0].turn_off()) if settings.get(["navButton", "deviceTwo"]): asyncio.create_task(self.device.children[1].turn_off()) if settings.get(["navButton", "deviceThree"]): asyncio.create_task(self.device.children[2].turn_off()) return "shutdown" def turnOn_btn(self, settings): if settings.get(["navButton", "deviceOne"]): asyncio.create_task(self.device.children[0].turn_on()) if settings.get(["navButton", "deviceTwo"]): asyncio.create_task(self.device.children[1].turn_on()) if settings.get(["navButton", "deviceThree"]): asyncio.create_task(self.device.children[2].turn_on()) return "Turning on" def turn_on(self, plugNumber): asyncio.run(self.device.children[plugNumber].turn_on()) def shutdown(self, plugNumber): asyncio.run(self.device.children[plugNumber].turn_off()) def get_plug_information(self): return self.device.hw_info def __repr__(self): pass
async def _power_set(host, port, index, value): """We embed the coroutines in an `async` function to minimise calls to `asyncio.run`""" assert port is None index = int(index) strip = SmartStrip(host) await strip.update() assert (len(strip.children) > index), "Trying to access non-existant plug socket on strip" if value is True: await strip.children[index].turn_on() elif value is False: await strip.children[index].turn_off()
async def cli(ctx, host, alias, target, debug, bulb, plug, lightstrip, strip, klap, user, password): """A tool for controlling TP-Link smart home devices.""" # noqa if debug: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.INFO) if ctx.invoked_subcommand == "discover": return if alias is not None and host is None: click.echo(f"Alias is given, using discovery to find host {alias}") host = await find_host_from_alias(alias=alias, target=target) if host: click.echo(f"Found hostname is {host}") else: click.echo(f"No device with name {alias} found") return if password != "" and user == "": click.echo("Using a password requires a username") return if klap or user != "": authentication = Auth(user=user, password=password) else: authentication = None if host is None: click.echo("No host name given, trying discovery..") await ctx.invoke(discover) return else: if not bulb and not plug and not strip and not lightstrip: click.echo("No --strip nor --bulb nor --plug given, discovering..") dev = await Discover.discover_single(host, authentication) elif bulb: dev = SmartBulb(host) elif plug: dev = SmartPlug(host, authentication) elif strip: dev = SmartStrip(host) elif lightstrip: dev = SmartLightStrip(host) else: click.echo( "Unable to detect type, use --strip or --bulb or --plug!") return ctx.obj = dev if ctx.invoked_subcommand is None: await ctx.invoke(state)
def start(self): LOGGER.debug(f'{self.pfx} start') self.dev = SmartStrip(self.host) super(SmartStripNode, self).start() self.update() self.check_st() LOGGER.info(f'{self.pfx} {self.dev.alias} has {len(self.dev.children)+1} children') for pnum in range(len(self.dev.children)): naddress = "{}{:02d}".format(self.address,pnum+1) nname = self.dev.children[pnum].alias LOGGER.info(f"{self.pfx} adding plug num={pnum} address={naddress} name={nname}") self.nodes.append(self.controller.addNode(SmartStripPlugNode(self.controller, self, naddress, nname, self.dev.children[pnum]))) self.ready = True LOGGER.debug(f'{self.pfx} done')
async def change_outlet_state(self, channel, state): from kasa import SmartStrip self.strip = SmartStrip(self.plug_address) await self.strip.update() if state: msg = await self.strip.children[channel].turn_on() self.output_states[channel] = True else: msg = await self.strip.children[channel].turn_off() self.output_states[channel] = False await self.strip.update() return msg
async def try_connect(self): from kasa import SmartStrip lf = LockFile() if lf.lock_acquire(self.lock_file, timeout=self.lock_timeout): try: self.strip = SmartStrip(self.plug_address) await self.strip.update() self.logger.debug( f'Strip {self.strip.alias}: {self.strip.hw_info}') self.output_setup = True except Exception as err: self.logger.error(f"Output was unable to be setup: {err}") finally: time.sleep(self.switch_wait) lf.lock_release(self.lock_file)
def _load_hardware(self): # Input format should be either: # - [IP],[POWER_SWITCH_NR] # Use an internal caching for speeding things up. self.__state_cache = terrariumCache() self._async = terrariumAsync() address = self._address if len(address) == 1: self._device['device'] = SmartPlug(address[0]) self._device['switch'] = 0 else: self._device['device'] = SmartStrip(address[0]) self._device['switch'] = int(address[1])-1 return self._device['device']
async def connect(self): self.logger.debug("try_connect") from kasa import SmartStrip try: self.strip = SmartStrip(self.plug_address) await self.strip.update() self.logger.debug( f'Connected to {self.strip.alias}: {self.strip.hw_info}') self.output_setup = True self.failed_connect_count = 0 except Exception as err: self.logger.error(f"Output was unable to be setup: {err}") self.failed_connect_count += 1 wait_timer = time.time() if self.failed_connect_count > 19: if self.failed_connect_count == 20: self.logger.error( "Failed to connect 20 times. Increasing reconnect attempt interval to 300 seconds." ) while wait_timer > time.time() - 300 and self.running: time.sleep(1) elif self.failed_connect_count > 4: if self.failed_connect_count == 5: self.logger.error( "Failed to connect 5 times. Increasing reconnect attempt interval to 60 seconds." ) while wait_timer > time.time() - 60 and self.running: time.sleep(1) else: self.logger.error("Failed to connect. Retrying in 5 seconds.") while wait_timer > time.time() - 5 and self.running: time.sleep(1) if self.first_connect and self.output_setup: self.first_connect = False for channel in channels_dict: if channel not in self.output_states: self.output_states[channel] = None if self.options_channels['state_startup'][channel] == 1: await self.strip.children[channel].turn_on() elif self.options_channels['state_startup'][channel] == 0: await self.strip.children[channel].turn_off() self.logger.debug( f'Strip children: {self.strip.children[channel]}')
async def cli(ctx, host, alias, target, debug, bulb, plug, strip): """A cli tool for controlling TP-Link smart home plugs.""" # noqa if debug: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.INFO) if ctx.invoked_subcommand == "discover": return if alias is not None and host is None: click.echo(f"Alias is given, using discovery to find host {alias}") host = await find_host_from_alias(alias=alias, target=target) if host: click.echo(f"Found hostname is {host}") else: click.echo(f"No device with name {alias} found") return if host is None: click.echo("No host name given, trying discovery..") await ctx.invoke(discover) return else: if not bulb and not plug and not strip: click.echo("No --strip nor --bulb nor --plug given, discovering..") dev = await Discover.discover_single(host) elif bulb: dev = SmartBulb(host) elif plug: dev = SmartPlug(host) elif strip: dev = SmartStrip(host) else: click.echo( "Unable to detect type, use --strip or --bulb or --plug!") return ctx.obj = dev if ctx.invoked_subcommand is None: await ctx.invoke(state)
async def get_status(self): from kasa import SmartStrip lf = LockFile() if lf.lock_acquire(self.lock_file, timeout=self.lock_timeout): try: self.strip = SmartStrip(self.plug_address) await self.strip.update() for channel in channels_dict: if self.strip.children[channel].is_on: self.output_states[channel] = True else: self.output_states[channel] = False except Exception as err: self.logger.error( f"get_status() raised an exception when taking a reading: {err}" ) return 'error', err finally: time.sleep(self.switch_wait) lf.lock_release(self.lock_file)
def load_hardware(self): address = self.__get_address() if len(address) == 2: self._device = SmartStrip(address[0]) else: self._device = SmartPlug(address[0])
class OutputModule(AbstractOutput): """An output support class that operates an output.""" def __init__(self, output, testing=False): super().__init__(output, testing=testing, name=__name__) self.strip = None self.outlet_switching = False self.status_thread = None self.outlet_status_checking = False self.timer_status_check = time.time() self.first_connect = True self.plug_address = None self.status_update_period = None self.setup_custom_options(OUTPUT_INFORMATION['custom_options'], output) output_channels = db_retrieve_table_daemon(OutputChannel).filter( OutputChannel.output_id == self.output.unique_id).all() self.options_channels = self.setup_custom_channel_options_json( OUTPUT_INFORMATION['custom_channel_options'], output_channels) def initialize(self): self.setup_output_variables(OUTPUT_INFORMATION) if not self.plug_address: self.logger.error("Plug address must be set") return try: self.try_connect() self.status_thread = threading.Thread(target=self.status_update) self.status_thread.start() if self.output_setup: self.logger.debug('Strip setup: {}'.format(self.strip.hw_info)) for channel in channels_dict: if self.options_channels['state_startup'][channel] == 1: self.output_switch("on", output_channel=channel) elif self.options_channels['state_startup'][channel] == 0: self.output_switch("off", output_channel=channel) self.logger.debug('Strip children: {}'.format( self.strip.children[channel])) except Exception as e: self.logger.error("initialize() Error: {err}".format(err=e)) def try_connect(self): try: from kasa import SmartStrip self.strip = SmartStrip(self.plug_address) asyncio.run(self.strip.update()) self.output_setup = True except Exception as e: if self.first_connect: self.first_connect = False self.logger.error( "Output was unable to be setup: {err}".format(err=e)) else: self.logger.debug( "Output was unable to be setup: {err}".format(err=e)) def output_switch(self, state, output_type=None, amount=None, output_channel=None): if not self.is_setup(): msg = "Error 101: Device not set up. See https://kizniche.github.io/Mycodo/Error-Codes#error-101 for more info." self.logger.error(msg) return msg while self.outlet_status_checking and self.running: time.sleep(0.1) try: self.outlet_switching = True if state == 'on': asyncio.run(self.strip.children[output_channel].turn_on()) self.output_states[output_channel] = True elif state == 'off': asyncio.run(self.strip.children[output_channel].turn_off()) self.output_states[output_channel] = False msg = 'success' except Exception as e: msg = "State change error: {}".format(e) self.logger.error(msg) self.output_setup = False finally: self.outlet_switching = False return msg def is_on(self, output_channel=None): if self.is_setup(): if output_channel is not None and output_channel in self.output_states: return self.output_states[output_channel] else: return self.output_states def is_setup(self): return self.output_setup def stop_output(self): """Called when Output is stopped.""" if self.is_setup(): for channel in channels_dict: if self.options_channels['state_shutdown'][channel] == 1: self.output_switch('on', output_channel=channel) elif self.options_channels['state_shutdown'][channel] == 0: self.output_switch('off', output_channel=channel) self.running = False def status_update(self): while self.running: if self.timer_status_check < time.time(): while self.timer_status_check < time.time(): self.timer_status_check += self.status_update_period while self.outlet_switching and self.running: time.sleep(0.1) self.outlet_status_checking = True self.logger.debug("Checking state of outlets") if not self.output_setup: self.try_connect() if not self.output_setup: self.logger.debug("Could not connect to power strip") try: if self.output_setup: asyncio.run(self.strip.update()) for channel in channels_dict: if self.strip.children[channel].is_on: self.output_states[channel] = True else: self.output_states[channel] = False except Exception as e: self.logger.debug( "Could not query power strip status: {}".format(e)) self.output_setup = False finally: self.outlet_status_checking = False time.sleep(1)
def __init__(self, address): self.worker = ThreadedWorker() self.device = SmartStrip(address)
async def test_get_plug_by_name(dev: SmartStrip): name = dev.plugs[0].alias assert dev.get_plug_by_name(name) == dev.plugs[0] with pytest.raises(SmartDeviceException): dev.get_plug_by_name("NONEXISTING NAME")
if bulb: asyncio.run(bulb.update()) asyncio.run(bulb.set_brightness(30)) def bulb_brightness_100(): if bulb: asyncio.run(bulb.update()) asyncio.run(bulb.set_brightness(100)) ### TPLINK KASA HS300 ### Change the ip addresss accordingly print('LOADING SMART-STRIP <--- HS300') strip = SmartStrip("192.168.1.22") # Plug1 def on_plug_0(): strip.turn_on(index=0) def off_plug_0(): strip.turn_off(index=0) # Plug2 def on_plug_1(): strip.turn_on(index=1)
import asyncio import logging from time import sleep from kasa import SmartStrip LOG = logging.getLogger(__name__) STRIPS = [SmartStrip("192.168.0.123"), SmartStrip("192.168.0.194")] def reboot_plug(plug): LOG.info("rebooting plug %s", plug.alias) asyncio.run(plug.turn_off()) sleep(3) asyncio.run(plug.turn_on()) def find_plug(plug_name): return_value = None for strip in STRIPS: asyncio.run(strip.update()) for plug in strip.children: if plug_name in plug.alias: return_value = plug return return_value