Giter Site home page Giter Site logo

flavio-fernandes / mqtt2kasa Goto Github PK

View Code? Open in Web Editor NEW
29.0 4.0 14.0 38 KB

Python-based project that provides wrapper to python-kasa for MQTT access

License: MIT License

Shell 11.97% Python 87.48% Dockerfile 0.55%
mqtt kasa tplink tplink-kasa smarthome asyncio smartbulb smartplug python3

mqtt2kasa's Introduction

mqtt2kasa

Python-based project that provides wrapper to python-kasa for MQTT access

This repo provides an MQTT interface to the awesome python-kasa library. With that, one can use MQTT clients to turn on/off any compatible TP-Link device. Conversely, by subscribing to specific MQTT topics, users can be notified about state changes to any device configured.

The TP-Link / Kasa devices managed are kept in an easy to edit YAML file that looks like this:

mqtt:
    # ip/dns for the mqtt broker
    host: 192.168.1.250
    username: <optional mqtt username>
    password: <optional mqtt password>
    # retain: false
    # qos: 0
globals:
    # every location will be managed using a unique mqtt topic
    # unless explicitly specified, this format will be used
    topic_format: /{}/switch
    # kasa will monitor the current state of the device every
    # poll interval, in seconds. You can override on a per device
    poll_interval: 11
    # if devices support metering (aka emeter), use this poll
    # interval to publish it. You can override on a per device
    # emeter_poll_interval: 600
locations:
    # coffee maker. To turn it on, use mqtt publish
    # topic: /coffee_maker/switch payload: on
    # subscribe to /coffee_maker/switch to know its state
    coffee_maker:
        host: 192.168.1.21
    # toaster is similar to the coffee maker, except it relies on
    # kasa discovery in order to locate the device via its alias.
    toaster:
        alias: toaster
    # example where topic is explicitly provided for a given device
    kitchen lights:
        host: 192.168.1.22
        topic: /kitchen/light_switch
    # example where we indicate a specific poll intervals
    pantry:
        alias: storage
        poll_interval: 120
        emeter_poll_interval: 1800

Devices are connected via host or discovered by Kasa via alias. There are more attributes for further customizations, shown in the data/config.yaml file.

Starting this project can be done by setting up a service (see mqtt2kasa.service as reference), or doing the following steps:

$ ./mqtt2kasa/bin/create-env.sh && \
  source ./env/bin/activate && \
  export PYTHONPATH=${PWD}

$ python3 mqtt2kasa/main.py ./data/config.yaml

Granted the config properly refers to the TP-Link devices in the network, use regular MQTT tools for controlling and monitoring. Example below.

Controlling the devices via MQTT via publish:

  • turning on/off
$ MQTT=192.168.1.250 && \
  mosquitto_pub -h $MQTT -t /kitchen/light_switch -m off
  • setting brightness to 50%
$ MQTT=192.168.1.250 && \
  mosquitto_pub -h $MQTT -t /kitchen/light_switch/brightness -m 50

Subscribe to see changes to devices, regardless on how they were controlled:

$ MQTT=192.168.1.250 && \
  mosquitto_sub -F '@Y-@m-@dT@H:@M:@S@z : %q : %t : %p' -h $MQTT -t '/+/switch' -t /kitchen/light_switch

2021-02-18T10:16:19-0500 : 0 : /kitchen/light_switch : on
2021-02-18T10:16:26-0500 : 0 : /kitchen/light_switch : off
2021-01-30T21:43:03-0500 : 0 : /toaster/switch : on

NOTE on Metering: If metering is supported by device and emeter_poll_interval was provided, it will be published via topics that end with "emeter":

$ mosquitto_sub -h $MQTT -t '/+/switch/emeter' -t '/+/switch/emeter/#'

In order to damper endless on/off cycles, this implementation sets an async throttle for each device. If there is a need to tweak that, the attributes are located in kasa_wrapper.py.

NOTE: Use python 3.7 or newer, as this project requires a somewhat recent implementation of asyncio.

Docker

There is a docker image ghcr.io/flavio-fernandes/mqtt2kasa. Please see docker-compose.yaml for usage examples.

TODO

mqtt2kasa's People

Contributors

aderesh avatar flavio-fernandes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

mqtt2kasa's Issues

Add authentication support

Hello,

Newer device started to use a new protocol and now require an authentication to be used. In python-kasa, we can either set KASA_USERNAME and KASA_PASSWORD so it's used globally or specify --username and --password on the command line to specify it.

Exemple is KS240 device that require it.

Thank you

feature request: publish EmeterStatus

What's really missing: mqtt2kasa does not publish the EmeterStatus, which is reported by kasa.

Output of kasa --host hs110 --type plug
== Current State == <EmeterStatus power=0.952 voltage=234.378 current=0.015 total=0.482>

Question: brightness support

Hi

Before anything, thanks for library/module!

My understanding, this library/module uses 'kasa-python' internally which supports setting brightness "kasa --host 192.168.0.15 brightness 50". Does the library/module support setting brightness via mqtt? If not, any tips how to add the support (files to update, commands etc)?

Thanks!

MQTT publishing retain flag after polling

Currently the publish handler uses the default retain payload flag of the mqtt library which is "false". This should be configurable either globally or per device.

I retain payloads for all my kasa switches when publishing to the topic. However, if I directly turn the device on or off from the switch, when mqtt2kasa polls the devices it will see the changed state and publish to the topic with retain = false.

Since I retain for all devices, I manually modified mqtt.py to publish with retain = true as a workaround. Additionally the qos value could be configurable the same way.

Multiple and alternating messages.

I am getting strange repeated messages which are alternating on/off. Not quite sure what is going on.

This is the output from whening running the script in the foreground.

Any ideas?

When I restart the script the problem goes.

Device dehumidifier is too busy to take request to be set as on Device dehumidifier is too busy to take request to be set as off Device dehumidifier is too busy to take request to be set as on Device dehumidifier is too busy to take request to be set as off Device dehumidifier is too busy to take request to be set as on Device dehumidifier is too busy to take request to be set as off Device dehumidifier is too busy to take request to be set as on Device dehumidifier is too busy to take request to be set as off Device dehumidifier is too busy to take request to be set as on Device dehumidifier is too busy to take request to be set as off Device dehumidifier is too busy to take request to be set as on Device dehumidifier is too busy to take request to be set as off Device dehumidifier is too busy to take request to be set as on Device dehumidifier is too busy to take request to be set as off Device dehumidifier is too busy to take request to be set as on Device dehumidifier is too busy to take request to be set as off Device dehumidifier is too busy to take request to be set as on Device dehumidifier is too busy to take request to be set as off Device dehumidifier is too busy to take request to be set as on Device dehumidifier is too busy to take request to be set as off Device dehumidifier is too busy to take request to be set as on Device dehumidifier is too busy to take request to be set as off Device dehumidifier is too busy to take request to be set as on

TypeError: 'type' object is not subscriptable

When running as documented I see the following error...

Traceback (most recent call last):
File "mqtt2kasa/main.py", line 12, in
from mqtt2kasa.keep_alive import (
File "/home/pi/kasa/mqtt2kasa/mqtt2kasa/keep_alive.py", line 76, in
kasas: dict[str, Kasa], kas: dict[str, KeepAlive], mqtt_send_q: asyncio.Queue
TypeError: 'type' object is not subscriptable

My configuration looks like this...


knobs:
# Note: normally you don't set these... here just to show how to
# devel and debug
# log_to_console: false
# log_level_debug: false
mqtt:
# ip/dns for the mqtt broker
host: 192.168.35.90
globals:
# every location will be managed using a unique mqtt topic
# unless explicitly specified, this format will be used
topic_format: /{}/switch
# kasa will monitor the current state of the device every
# poll interval, in seconds. You can override on a per device
poll_interval: 11
locations:
# coffee maker. To turn it on, use mqtt publish
# topic: /coffee_maker/switch payload: on
# subscribe to /coffee_maker/switch to know its state
living_room_lights
host: 192.168.35.103
desk_lights:
host: 192.168.35.120

Any help would be appreciated.

'type' object is not subscriptable

Getting this error. Any suggesstions?

(env) pi@home-assistant-pi4:~/sh/kasa/mqtt2kasa $ python3 mqtt2kasa/main.py ./data/config.yaml
Traceback (most recent call last):
File "mqtt2kasa/main.py", line 12, in
from mqtt2kasa.keep_alive import (
File "/home/pi/sh/kasa/mqtt2kasa/mqtt2kasa/keep_alive.py", line 76, in
kasas: dict[str, Kasa], kas: dict[str, KeepAlive], mqtt_send_q: asyncio.Queue
TypeError: 'type' object is not subscriptable

Help: source ./env/bin/activate not found

Not sure how to get this running. Attempted the instructions but hitting issues with the source command of create-env.sh

$ ./mqtt2kasa/bin/create-env.sh && \
>   source ./env/bin/activate && \
>   export PYTHONPATH=${PWD}
++ dirname ./mqtt2kasa/bin/create-env.sh
+ cd ./mqtt2kasa/bin
+ BIN_DIR=/home/pi/mqtt2kasa/mqtt2kasa/bin
+ PROG_DIR=/home/pi/mqtt2kasa/mqtt2kasa
+ TOP_DIR=/home/pi/mqtt2kasa
+ pushd /home/pi/mqtt2kasa
~/mqtt2kasa ~/mqtt2kasa/mqtt2kasa/bin
+ '[' '!' -e ./env ']'
+ source ./env/bin/activate
./mqtt2kasa/bin/create-env.sh: line 15: ./env/bin/activate: No such file or directory

Not sure what how to get this file...

Add support for child device

Hello,

python-kasa just introduce the notion of child device for device like the KS240. It is required to be able to control each switch in a multi-device device. It would be great if it was added.

Thank you!

Exception: Invalid files: /run/systemd/journal/syslog, /var/run/syslog, /device/log

I am installing it on a Ubuntu server (Ubuntu 22.04.2 LTS).

During the first install I got the same error as : #5

Second install I get an exception raised due to invalid files. Not sure what is gong on, but I think that there is a problem somewhere.

(env) gck@emonpi:~/mqtt2kasa$ python3 mqtt2kasa/main.py ./data/config.yaml Traceback (most recent call last): File "/home/gck/mqtt2kasa/mqtt2kasa/main.py", line 263, in <module> log.initLogger() File "/home/gck/mqtt2kasa/mqtt2kasa/log.py", line 28, in initLogger logHandlerAddress = _log_handler_address( File "/home/gck/mqtt2kasa/mqtt2kasa/log.py", line 16, in _log_handler_address raise Exception("Invalid files: %s" % ", ".join(files)) Exception: Invalid files: /run/systemd/journal/syslog, /var/run/syslog, /device/log (env) gck@emonpi:~/mqtt2kasa$

emeter output is not usable

I have tried to use the emeter output, but it has a couple of issues:

  • it is surrounded by <>
  • all the different parameters are within a single payload

I have edited the code to remove the <> send multiple messages. Can this be incorporated in the standard code?

`async def handle_emeter_event_kasa(
kasa_emeter: KasaEmeterEvent, run_state: RunState, mqtt_send_q: asyncio.Queue
):
kasa = run_state.kasas.get(kasa_emeter.name)
if not kasa:
logger.warning(
f"Unable to find device with name {kasa_emeter.name}. Ignoring kasa emeter event"
)
return
topic = f"{kasa.topic}/emeter"
payload = kasa_emeter.emeter_status
payload = payload.replace('<', '')
payload = payload.replace('>', '')
logger.info(
f"Kasa emeter event requesting mqtt for {kasa_emeter.name} to publish"
f" {topic} as {payload}"
)
await mqtt_send_q.put(MqttMsgEvent(topic=topic, payload=payload))

myList = payload.split()
print(myList)

for item in myList:
    print( item )
    topic = f"{kasa.topic}/emeter/" + item.split('=')[0]
    print( 'topic =' + topic)
    payload =  item.partition("=")[2]
    await mqtt_send_q.put(MqttMsgEvent(topic=topic, payload=payload))

`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.