def switch(request): if request.method == 'POST': post_data = json.loads(request.body.decode("utf-8")) plug_name = post_data.get('name', None) try: switch = get_switch(plug_name) except ValueError: return JsonResponse({'error': 'invalid name'}) command = post_data.get('command', None) if command == 'on': if switch.is_on: return JsonResponse({'error': 'already on'}) asyncio.run(switch.turn_on()) return JsonResponse({'success': f"{plug_name} turned on"}) elif command == 'off': if not switch.is_on: return JsonResponse({'error': 'already off'}) asyncio.run(switch.turn_off()) return JsonResponse({'success': f"{plug_name} turned off"}) else: print(command) if request.method == 'GET': switches = get_all_switches() if not switches: switches = [] for s in SWITCHES: switch = SmartPlug(s['ip']) asyncio.run(switch.update()) switches.append(switch) switches = [{'name': switch.alias, 'is_on': switch.is_on} for switch in switches] return JsonResponse({'switches': switches})
class PlugDevice: def __init__(self, config, mqtt): self.mqtt = mqtt self.plug = SmartPlug(config['host']) self.device_id = config['device_id'] def update(self): asyncio.run(self._update()) def subscribe(self, mqtt): mqtt.subscribe(f"{self.device_id}/states/switch_on") def on_message(self, msg): value = msg.strip().lower() if value == "true" or value == "yes": print('Turning on ' + self.device_id) asyncio.run(self.plug.turn_on()) self.update() elif value == "false" or value == "no": print('Turning off ' + self.device_id) asyncio.run(self.plug.turn_off()) self.update() async def _update(self): await self.plug.update() print(self.plug.alias) print(self.plug.is_on) self.mqtt.publish(f"{self.device_id}/values/is_on", str(self.plug.is_on).lower(), 1)
def get_switch(switch_name: str): found_devices = asyncio.run(Discover.discover()) device = [ dev for addr, dev in found_devices.items() if dev.alias == switch_name ] if len(device) != 1: if switch_name not in [s['alias'] for s in SWITCHES]: raise ValueError("Invalid Name") s = [s for s in SWITCHES if s['alias'] == switch_name][0] switch = SmartPlug(s['ip']) asyncio.run(switch.update()) return switch return device[0]
async def connectSwitchPlug(alias): host = await findHostFromAlias(alias) p = SmartPlug(host) await p.update() print("") return p
def initial(): with open('conf.json') as json_file: data = json.load(json_file) plug = SmartPlug(data["kasa_ip"]) waittime = int(data["timebeforshutdown"]) heatermaxtemp = int(data["maxheatertemp"]) printer = DWA.DuetWebAPI("http://"+data["duet_ip"]) check(waittime,heatermaxtemp,plug,printer)
def _turn_on(): """Turn the smart plug on. Raises: Exception: If we fail to communicate with the smart plug. """ BatteryController._ping_plug() asyncio.run(SmartPlug(BatteryController._PLUG_IP_ADDRESS).turn_on())
async def init_the_plugs(): global plug1, plug2 global plug1_error_state, plug2_error_state try: plug1 = SmartPlug(plug1_ip) await plug1.update() except: plug1_error_state = True else: plug1_error_state = False try: plug2 = SmartPlug(plug2_ip) await plug2.update() except: plug2_error_state = True else: plug2_error_state = False
def get_power_state(self): if self.device_type in [self.PLUG, self.BULB]: device = (SmartPlug(self.ip) if self.device_type in [self.PLUG] else SmartBulb(self.ip)) asyncio.run(device.update()) return device.is_on return False
def get_device(self): if self.device_type in [self.PLUG, self.BULB]: device = (SmartPlug(self.ip) if self.device_type in [self.PLUG] else SmartBulb(self.ip)) asyncio.run(device.update()) return device else: return self
def scan(): """Check whether the smart plug is on. After checking the smart plug, we perform a poll operation, as in ``poll()``. Normally, we rely on the contents of the state file to determine whether the smart plug is on. However, this assumes that only ``BatteryController`` turns it on and off. If something else turns it on or off, we should call ``scan()`` to ensure that ``BatteryController`` picks up the change. """ BatteryController._ping_plug() plug = SmartPlug(BatteryController._PLUG_IP_ADDRESS) asyncio.run(plug.update()) with BatteryController._lock(): status = BatteryController._read_state() status['currentState'] = plug.is_on BatteryController._poll(status)
async def discover(self): connected = False devices = await Discover.discover() for ipAddr, device in devices.items(): if device.alias == self.deviceAlias: print("Found device at " + ipAddr + ": " + device.alias) self.device = SmartPlug(ipAddr) connected = True print(devices) return connected
async def turn_off_plug(): """turn off plug""" try: p = SmartPlug(settings["smart_plug_ip"]) await p.update() logging.debug('Plug Turned Off') await p.turn_off() except: logging.error(traceback.format_exc())
async def main(ctx, address,period): """Main monitoring loop""" global gv_plug_address, gv_monitoring_period gv_plug_address=address gv_monitoring_period=period plug = SmartPlug(address) print( f'"Timestamp","Voltage (V)", "Current (A)", "Power (kW)", "Energy (kWh)"') while True: reading = await getReading(plug) print(reading) time.sleep(period - (time.time() % period))
def create_device_from_ip_or_scan(ip, device_name): """Tries to create a kasa SmartDevice object either from a given IP address or by scanning the network.""" device = None if ip: try: device = SmartPlug(ip) asyncio.run(device.update()) except exceptions.SmartDeviceException: print( "Unable to connect to device at provided IP. Attempting scan.") # If unable to create device from ip, or ip is not given, scan the network. if not device: devices = asyncio.run(Discover.discover()) for _, dev in devices.items(): if dev.alias == device_name: asyncio.run(dev.update()) device = dev return device
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)
class TpLinkHandler(SmartDeviceException): def __init__(self, address): self.device = SmartPlug(address) def update(self): asyncio.run(self.device.update()) def update_two(self): asyncio.create_task(self.device.update()) def shutdown_btn(self): asyncio.create_task(self.device.turn_off()) return "shutdown" def turnOn_btn(self): asyncio.create_task(self.device.turn_on()) return "Turning on" def shutdown(self): asyncio.run(self.device.turn_off()) return "shutdown" def turnOn(self): asyncio.run(self.device.turn_on()) return "Turning on" def get_plug_information(self): return self.device.hw_info def __repr__(self): pass
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']
def set_power_state(self, power): if self.device_type in [self.PLUG, self.BULB]: device = (SmartPlug(self.ip) if self.device_type in [self.PLUG] else SmartBulb(self.ip)) if power: asyncio.run(device.turn_on()) else: asyncio.run(device.turn_off()) asyncio.run(device.update()) elif self.device_type in [self.PI, self.LINUX]: stdin = b'' stdout = b'' stderr = b'' if not power: client = SSHClient() client.set_missing_host_key_policy(AutoAddPolicy()) client.connect(self.ip, port=22, username=self.username, password=self.password) stdin_model, stdout_model, stderr_model = client.exec_command( 'sudo -S shutdown -h now') stdin_model.write('%s\n' % self.password) stderr_model.flush() # print the results if stdin_model.readable(): stdin = stdin_model.read() if stdout_model.readable(): stdout = stdout_model.read() if stderr_model.readable(): stderr = stderr_model.read() client.close() return (stdin, stdout, stderr) elif self.device_type in [self.ROKU]: roku = Roku(self.ip) roku.select() return (None, None, None)
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)
def switch_plug(): p = SmartPlug("192.168.0.51") try: asyncio.run(p.update()) except SmartDeviceException as e: logging.error("Could not reach smart plug...") sys.exit(e) if p.is_on: asyncio.run(p.turn_off()) else: asyncio.run(p.turn_on()) asyncio.run(p.update()) print("The plug is on: ", p.is_on)
def discover(self): devices = asyncio.run(Discover.discover()) for addr,dev in devices.items(): asyncio.run(dev.update()) devices.update({addr:dev}) devices = self.sortdevices(devices) for addr, dev in devices.items(): if dev.is_plug: asyncio.run(dev.update()) notexisting = False if not self.plugs.get(addr,False): notexisting = True plug = self.plugs.get(addr,SmartPlug(addr)) is_on = False powerupdate = False if not notexisting: is_on = plug.is_on if plug.model.startswith("HS110"): powerupdate = True asyncio.run(plug.update()) if notexisting or powerupdate or is_on != plug.is_on: self.updateview.append(addr) self.plugs.update({addr:plug})
class TpLinkHandlerSmartPlug(SmartDeviceException): def __init__(self, address): self.device = SmartPlug(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): asyncio.create_task(self.device.turn_off()) return "shutdown" def turnOn_btn(self, settings): asyncio.create_task(self.device.turn_on()) return "Turning on" def shutdown(self): asyncio.run(self.device.turn_off()) return "shutdown" def turnOn(self): asyncio.run(self.device.turn_on()) return "Turning on" def get_plug_information(self): return self.device.hw_info def __repr__(self): pass
def __init__(self, address): self.device = SmartPlug(address)
def off(): plug = SmartPlug("192.168.178.23") asyncio.run(plug.update()) asyncio.run(plug.turn_off()) return redirect("/")
def status(): plug = SmartPlug("192.168.178.23") asyncio.run(plug.update()) return {'host': plug.host, 'state': plug.is_on}
total = R + G + B if R == 0: firstPos = 0 else: firstPos = R / total if G == 0: secondPos = 0 else: secondPos = G / total return [firstPos, secondPos] ikealicht = SmartPlug("192.168.86.155") biglight = Bridge('192.168.86.26') biglight.connect() async def Ikealicht(onoff): await ikealicht.update() if (onoff): await ikealicht.turn_on() else: await ikealicht.turn_off() async def Biglight(onoff, brightness, color): light_name = 'Deckenlicht' if (onoff): biglight.set_light(light_name, 'on', True) biglight.set_light(light_name, 'bri', brightness)
async def get_device(): f = open("device-ip.txt", "r") device = SmartPlug(f.read()) await device.update() await device.turn_off()
def __init__(self, config, mqtt): self.mqtt = mqtt self.plug = SmartPlug(config['host']) self.device_id = config['device_id']
async def main(ctx, config, plug_address, inverter, solar_monitor_url, check_interval, min_power, min_off, min_on): """Main control loop""" global gv_smartcontrol gv_smartcontrol.plug_address = plug_address gv_smartcontrol.check_interval = check_interval gv_smartcontrol.min_power = min_power gv_smartcontrol.min_on = min_on gv_smartcontrol.min_off = min_off gv_smartcontrol.switch_count = 0 gv_smartcontrol.default_min_power = min_power gv_smartcontrol.default_min_off = min_off gv_smartcontrol.default_min_on = min_on plug = SmartPlug(plug_address) last_ontime = time.time() last_offtime = last_ontime # Main check / control loop (run indefinitely) while True: try: action_string = "" gv_smartcontrol.current_time = time.time() await plug.update() # Get plug status (on or off) gv_smartcontrol.is_on = plug.is_on # Check if plug has an energy meter - if not assume consumption is min_power if plug.has_emeter: plugRealtime = await plug.get_emeter_realtime() gv_smartcontrol.plug_consumption = plugRealtime[ "power_mw"] / 1000 else: if gv_smartcontrol.is_on: gv_smartcontrol.plug_consumption = gv_smartcontrol.min_power else: gv_smartcontrol.plug_consumption = 0 # Suppress warnings requests.packages.urllib3.disable_warnings( category=InsecureRequestWarning) # Get current net Solar export from Enphase monitor API r = requests.get(solar_monitor_url, timeout=3, verify=False) solar_json = r.json() if inverter == "enphase": gv_smartcontrol.overall_production = ( solar_json["production"][1]["wNow"]) gv_smartcontrol.overall_consumption = ( solar_json["consumption"][0]["wNow"]) else: gv_smartcontrol.overall_production = ( solar_json["result"]["0199-xxxxxC06"]["6100_40463600"]["1"] [0]["val"]) gv_smartcontrol.overall_consumption = ( solar_json["result"]["0199-xxxxxC06"]["6100_40463700"]["1"] [0]["val"]) gv_smartcontrol.overall_net = gv_smartcontrol.overall_production - gv_smartcontrol.overall_consumption time_since_off = gv_smartcontrol.current_time - last_offtime time_since_on = gv_smartcontrol.current_time - last_ontime # Decide whether to turn the plug off / on based on: # - Current state # - Current power available # - Expected power usage # - On / off grace periods if (gv_smartcontrol.is_smartcontrol_enabled): if (gv_smartcontrol.is_on): if ((gv_smartcontrol.overall_net + gv_smartcontrol.plug_consumption) >= gv_smartcontrol.min_power): threshold_string = "Overall is above minimum." action_string = "Leaving on." else: threshold_string = "Overall is under minimum." if (time_since_on < gv_smartcontrol.min_on): action_string = "Leaving on." else: action_string = "Turning off." await plug.turn_off() last_offtime = gv_smartcontrol.current_time gv_smartcontrol.switch_count += 1 else: if ((gv_smartcontrol.overall_net + gv_smartcontrol.plug_consumption) >= gv_smartcontrol.min_power): threshold_string = "Overall is above minimum." if (time_since_off < gv_smartcontrol.min_off): action_string = "Leaving off." else: action_string = "Turning on." last_ontime = gv_smartcontrol.current_time await plug.turn_on() gv_smartcontrol.switch_count += 1 else: threshold_string = "Overall is under minimum." action_string = "Leaving off." else: threshold_string = "Smart control disabled." if (gv_smartcontrol.is_on): action_string = "Leaving on." else: action_string = "Leaving Off." # Print log messages to console gv_smartcontrol.message = f'{threshold_string} {action_string}' print( f'[{int(gv_smartcontrol.current_time)}] {gv_smartcontrol.is_smartcontrol_enabled}, Overall W: {int(gv_smartcontrol.overall_net):5},Min power W:{int(gv_smartcontrol.min_power):5}, Plug W: {int(gv_smartcontrol.plug_consumption):5}, Secs since on: {int(time_since_on):5}, Secs since off: {int(time_since_off):5}, Switch count: {gv_smartcontrol.switch_count:5}, Plug on?: {gv_smartcontrol.is_on:5} ==> {threshold_string} {action_string}' ) # Print errors and keep trying if the plug times out or goes offline except SmartDeviceException as ex: print( f'[{int(gv_smartcontrol.current_time)}] Plug communication error ({ex}). Has it been disconnected?' ) except requests.exceptions.Timeout: print('HTTP Timeout exception... will retry next cycle.') except requests.exceptions.ConnectionError: print('HTTP Connection Error... will retry next cycle.') # Wait additional time until the next check cycle time.sleep(gv_smartcontrol.check_interval - (time.time() % gv_smartcontrol.check_interval))
import asyncio import logging import threading from kasa import SmartPlug from kasa.exceptions import SmartDeviceException pump = SmartPlug('192.168.0.51') def update_pump_status(): threading.Timer(5, update_pump_status).start() try: asyncio.run(pump.update()) except SmartDeviceException as e: logging.error("Unable to update pump... trying again in 5 seconds") logging.error(f"exception: {e}") print(pump.is_on) if __name__ == "__main__": update_pump_status()