Home

Awesome

GitHub tag (latest SemVer) GitHub GitHub Workflow Status

Description

Moonraker Tuya Generic HTTP Service

This is a simple service to be used with the Moonraker API server for Klipper 3D printing. It provides an API for the Moonraker Generic HTTP power plugin to control Tuya/Smart Life smart wifi electrical outlets locally.

Tuya do not make it easy to control your devices locally, and you will have to jump through a few hoops to get this running.

This service makes use of the tinytuya python library to interact with your devices. You will need to use some of their guides in order to get required information for your devices.

This service is intended to run as a docker container (easiest), but you can also run it directly by cloning the repository if you prefer. I recommend setting up a venv. The command to launch the service is uvicorn main:app --host 0.0.0.0 inside the app directory.

Initial Setup

I strongly recommend assigning static IP addresses for each device that you want to control with this service. You can do this via static DHCP mapping on your DHCP server or router.

Ensure that you add your devices to either the Tuya App or the Smart Life App and that you have a Tuya account.

Follow Step 3 of the section "Setup Wizard - Getting Local Keys" in this document to create a Tuya IoT developer account. This account is different to your Tuya/Smart Life App account. Link your Tuya/Smart Life App account into your Tuya Iot cloud project. Search this document for your country to determine what data center your account is associated with.

You will need the following information from the developer account:

From the Devices tab of your cloud project, copy one of the device IDs for one of your devices, it doesn't matter which one. If you don't see any Devices, check that you have linked your Tuya/Smart Life App account.

Run the wizard command from the directory where you will put the docker-compose.yml, or specify the full path instead of ./config: docker run --rm -it -v ./config:/app/config ghcr.io/teejo75/mtghs /app/tinytuya.sh wizard and enter the details from your Tuya IoT project. The tinytuya.sh script is just a shortcut to running python -m tinytuya so all options it supports are available. Run it with -h for more information.

This will create devices.json based on your devices listed in your Tuya/Smart Life App. I strongly recommend that you also allow the wizard to poll all the devices. This will create snapshot.json that contains more information than devices.json If you add new devices, or remove and re-add devices to your Tuya/Smart Life App, you will need to re-run the wizard command.

If the wizard is unable to find any devices on your network, add the parameter -force 192.168.0.0/24 or whatever your local network subnet is to the wizard command.

Once the devices.json exists in the config directory, create names.json by copying names-example.json and editing as required. If snapshot.json exists, the ip key in names.json will be ignored, so you can leave it as a blank string or remove it entirely. Add as many entries as you require. Only the devices listed in names.json will be controllable.

The service requires names.json and devices.json, however if snapshot.json exists, devices.json will be ignored.

On start up, the service will generate an api key and save it to config.json. Use the api key within the moonraker config to query this service. To generate a new key, either edit config.json and input your own key, then restart the service, or delete config.json then restart the service, and a new key will be generated. Check the console logs docker compose logs or get the new key from config.json.

Use the following simple docker-compose.yml to bring the service up.

version: "3.9"
services:
  mtghs:
    image: ghcr.io/teejo75/mtghs:latest
    ports:
      - 8000:80
    volumes:
      - ./config:/app/config
    restart: unless-stopped

To bring the service up, run docker compose up. This will bring the service up with the logs in the console. Verify that the service is starting and not throwing an error. If you're getting an error, it's probably because one of names.json, devices.json, snapshot.json is missing. If you're happy that it starts up properly, kill it with ctrl+c then bring it up in the background with docker compose up -d. Note: If you see duplicated log entries, it's because of the number of workers. Two workers start by default, so you will see two log entries initially.

If you call the service URL directly, http://<service>:8000/ you will get a json doc with the available devices.

Moonraker Config

Add the generated api key to moonraker.secrets, this file lives in the moonraker data_path. If you don't know where this is, check the top of moonraker.log. Be sure to add a [secrets] section to the moonraker.conf file so that the secrets file will be loaded.

moonraker.secrets:

[mtghs]
api_key: <your generated key goes here>

moonraker.conf:

#  Add as many sections as needed for the devices you want to control.
[power tuyaoutlet]
type: http
#  In the below urls, <name> should be replaced with your device name per names.json, devices.json/snapshot.json
#  <service> should be replaced with the hostname and port of the service.
on_url: http://<service>/on/<name>
off_url: http://<service>/off/<name>
status_url: http://<service>/status/<name>
request_template:
    {% if command in ["on", "off"] %}
        {% do http_request.set_method("PUT") %}
        {% do http_request.add_header("api_key", "%s" % secrets.mtghs.api_key) %}
        {% do http_request.set_body({}) %}
    {% endif %}
    {% do http_request.send() %}
response_template:
  {% set resp = http_request.last_response().json() %}
  {resp["status"]}
# This enables a power button in mainsail.
bound_services: klipper  # You can remove this line for non printer power sources where you don't need Klipper to restart.

Building your own image

Clone the repository: git clone https://github.com/teejo75/mtghs.git. Inside the cloned respository, run docker build -t teejo75/mtghs .