Deploy Shelly Configuration to all devices from Home Assistant

I’ve managed to put together a way to more easily make sure all my shelly devices have the same configuration via Home Assistant and make deployment easier.

This assumes:

  • Shelly device is setup in HA already via Shelly integration
  • All Shelly devices will have the same password set in secrets.yaml
  • username is admin

On all devices it will:

  • Enable MQTT and set auth per config
  • Disable Cloud
  • Disable Bluetooth
  • Disable AP
  • Set Shelly Device Name to match the HA Entity name
  • Set timezone to Europe/London (you can change this of course)
  • Set NTP server to time.cloudflare.com (you can change this in secrets.yaml)
  • Set a password on the shelly device if not already set
  • Reboot the Shelly Device (to apply all changes)

Please feel free to chip in if anything can be done better,

Add to configuration.yaml:

command_line:
  - sensor:
      name: shelly_inventory
      command: "cat /config/shelly_inventory.json"
      # Keep state short so it never exceeds 255 chars
      value_template: "{{ value_json.devices | length }}"
      json_attributes:
        - devices
      scan_interval: 3600

rest_command:
  shelly_rpc_post:
    url: "http://{{ ip }}/rpc/{{ rpc_method }}"
    method: post
    headers:
      Content-Type: "application/json"
    payload: "{{ payload }}"
    authentication: digest
    username: !secret shelly_admin_user
    password: !secret shelly_admin_password

template:
    - sensor:
      - name: "Shelly Admin User"
        unique_id: shelly_admin_user
        state: !secret shelly_admin_user
      - name: "Shelly Admin Password"
        unique_id: shelly_admin_password
        state: !secret shelly_admin_password

      - name: "Shelly MQTT Host"
        unique_id: shelly_mqtt_host
        state: !secret shelly_mqtt_host
      - name: "Shelly MQTT Port"
        unique_id: shelly_mqtt_port
        state: !secret shelly_mqtt_port
      - name: "Shelly MQTT User"
        unique_id: shelly_mqtt_user
        state: !secret shelly_mqtt_user
      - name: "Shelly MQTT Pass"
        unique_id: shelly_mqtt_pass
        state: !secret shelly_mqtt_pass

      - name: "Shelly NTP Server"
        unique_id: shelly_ntp_server
        state: !secret shelly_ntp_server
        

Add to secrets.yaml:

shelly_mqtt_port: '1883'
shelly_mqtt_user: 'your-shelly-mqtt-username'
shelly_mqtt_pass: 'your-shelly-mqtt-password'
shelly_mqtt_host: 'your-mqtt-host'

shelly_admin_user: 'admin'
shelly_admin_password: 'your-shelly-device-password'

shelly_ntp_server: 'time.cloudflare.com'

CREATE new file in /config/ called ‘shelly_inventory.json’ - This is the easiest way to quickly add devices so the script knows what’s what and tie it all together:

{
    "devices": [
      {
        "ip": "192.168.107.16",
        "ha_entity": "light.kitchen_spotlights",
        "shelly_id": "shellydimmerg3-e4b123"
      },
      {
        "ip": "192.168.107.24",
        "ha_entity": "switch.heating",
        "shelly_id": "shelly1pmminig3-e4b0123"
      },
      {
        "ip": "192.168.107.11",
        "ha_entity": "light.bedroom_light",
        "shelly_id": "shellydimmerg3-b0123"
      },
      {
        "ip": "192.168.107.19",
        "ha_entity": "switch.patio_lights",
        "shelly_id": "shelly1pmminig3-e4123"
      },
      {
        "ip": "192.168.107.12",
        "ha_entity": "light.office_light",
        "shelly_id": "shellydimmerg3-e123"
      },
      {
        "ip": "192.168.107.18",
        "ha_entity": "light.guest_room",
        "shelly_id": "shellydimmerg3-e123"
      }
    ]
}

This assumes you’ve already got the devices all setup and configured in Home Assistant, the link enables the script to pull the ha_entity name and set it on the shelly device. The shelly_id is needed to connect to the Shelly API.

The script - Copy and paste this into Script in your HA:

alias: Shelly Admin - Provision All Gen3
mode: single
sequence:
  - variables:
      dry_run: "{{ is_state('input_boolean.shelly_dry_run','on') }}"
      user: "{{ states('sensor.shelly_admin_user') }}"
      password: "{{ states('sensor.shelly_admin_password') }}"
      mqtt_host: "{{ states('sensor.shelly_mqtt_host') }}"
      mqtt_port: "{{ states('sensor.shelly_mqtt_port') | int }}"
      mqtt_user: "{{ states('sensor.shelly_mqtt_user') }}"
      mqtt_pass: "{{ states('sensor.shelly_mqtt_pass') }}"
      ntp_server: "{{ states('sensor.shelly_ntp_server') }}"
      inventory: "{{ state_attr('sensor.shelly_inventory', 'devices') or [] }}"
  - repeat:
      for_each: "{{ inventory }}"
      sequence:
        - variables:
            ip: "{{ repeat.item.ip }}"
            ha_entity: "{{ repeat.item.ha_entity }}"
            shelly_id: "{{ repeat.item.shelly_id }}"
            desired_name: |
              {{ state_attr(ha_entity,'friendly_name') or ha_entity }}
            ha1: "{{ ('admin:' ~ shelly_id ~ ':' ~ password) | sha256 }}"
            payload_mqtt: >
              {{ {"config":{"enable":true,"server":mqtt_host ~ ":" ~
              mqtt_port,"user":mqtt_user,"pass":mqtt_pass}} | tojson }}
            payload_cloud: |
              {{ {"config":{"enable":false}} | tojson }}
            payload_wifi: |
              {{ {"config":{"ap":{"enable":false}}} | tojson }}
            payload_sys: >
              {{
              {"config":{"device":{"name":desired_name},"location":{"tz":"Europe/London"},"sntp":{"server":ntp_server}}}
              | tojson }}
            payload_auth: |
              {{ {"user":"admin","realm":shelly_id,"ha1":ha1} | tojson }}
        - choose:
            - conditions:
                - condition: template
                  value_template: "{{ dry_run }}"
              sequence:
                - data:
                    name: Shelly Admin
                    message: DRY RUN provisioning {{ ip }}
                  action: logbook.log
          default:
            - data:
                ip: "{{ ip }}"
                rpc_method: MQTT.SetConfig
                user: "{{ user }}"
                password: "{{ password }}"
                payload: "{{ payload_mqtt }}"
              action: rest_command.shelly_rpc_post
            - delay: "00:00:01"
            - data:
                ip: "{{ ip }}"
                rpc_method: Cloud.SetConfig
                user: "{{ user }}"
                password: "{{ password }}"
                payload: "{{ payload_cloud }}"
              action: rest_command.shelly_rpc_post
            - delay: "00:00:01"
            - data:
                ip: "{{ ip }}"
                rpc_method: WiFi.SetConfig
                user: "{{ user }}"
                password: "{{ password }}"
                payload: "{{ payload_wifi }}"
              action: rest_command.shelly_rpc_post
            - delay: "00:00:01"
            - data:
                ip: "{{ ip }}"
                rpc_method: Sys.SetConfig
                user: "{{ user }}"
                password: "{{ password }}"
                payload: "{{ payload_sys }}"
              action: rest_command.shelly_rpc_post
            - delay: "00:00:01"
            - data:
                ip: "{{ ip }}"
                rpc_method: Shelly.SetAuth
                user: "{{ user }}"
                password: "{{ password }}"
                payload: "{{ payload_auth }}"
              action: rest_command.shelly_rpc_post
            - delay: "00:00:01"
            - data:
                ip: "{{ ip }}"
                rpc_method: Shelly.Reboot
                user: "{{ user }}"
                password: "{{ password }}"
                payload: "{}"
              action: rest_command.shelly_rpc_post
description: ""

DO NOT COME AT ME IF THIS BREAKS ANYTHING :sweat_smile: I did have to reset one of my devices when it messed up the password while I was debugging :sweat_smile: