ISC Kea lease hook script

Posted on Jan 17, 2023

This is just an update for MQTT based presence detection, but using the ISC Kea lease hook library to send MQTT messages.

The script

First, the shell script I’m using. It’s more or less stolen from the ISC Kea documentation, but I’ve added a : in each empty function to avoid syntax errors. :-)

#!/bin/bash

unknown_handle() {
    echo "Unhandled function call ${*}"
    exit 123
}

publish_mqtt () {
    MAC=$1
    STATE=$2
    HOSTNAME=$3
    UNIQUE_ID=$(echo "$MAC" | tr -d ":")
    TIME=$(date +%s)
    JSON=$(jq -n --arg mac "$MAC" --arg state "$STATE" --arg time "$TIME" --arg hostname "$HOSTNAME" '{mac: $mac, state: $state, update: $time, hostname: $hostname }' )
    AUTO_DISCOVERY=$(jq -n --arg state_topic "location/${MAC}/state"\
                           --arg name "${HOSTNAME}" \
                           --arg payload_home "home"\
                           --arg payload_not_home "not_home"\
                           --arg source_type "router"\
                           '{state_topic: $state_topic, name: $name, payload_home: $payload_home, payload_not_home: $payload_not_home, source_type: $source_type }')

    mosquitto_pub -h {{ dnsmasq_mqtt_address }} -u {{ dnsmasq_mqtt_username }} -P {{ dnsmasq_mqtt_password }} -t "homeassistant/device_tracker/${UNIQUE_ID}/config" -m "$AUTO_DISCOVERY"
    mosquitto_pub -h {{ dnsmasq_mqtt_address }} -u {{ dnsmasq_mqtt_username }} -P {{ dnsmasq_mqtt_password }} -t "location/$MAC/attributes" -m "$JSON"
    mosquitto_pub -h {{ dnsmasq_mqtt_address }} -u {{ dnsmasq_mqtt_username }} -P {{ dnsmasq_mqtt_password }} -t "location/$MAC/state" -m "$STATE"
}

lease4_renew () {
    publish_mqtt "$LEASE4_HWADDR" "home" "$LEASE4_HOSTNAME"
}

lease4_expire () {
    publish_mqtt "$LEASE4_HWADDR" "not_home" "$LEASE4_HOSTNAME"
}

lease4_recover () {
    publish_mqtt "$LEASE4_HWADDR" "home" "$LEASE4_HOSTNAME"
}

leases4_committed () {
    :
}


lease4_release () {
    publish_mqtt "$LEASE4_HWADDR" "not_home" "$LEASE4_HOSTNAME"
}

lease4_decline () {
    :
}

lease6_renew () {
    :
}

lease6_rebind () {
    :
}

lease6_expire () {
    :
}

lease6_recover () {
    :
}

leases6_committed () {
    :
}

lease6_release () {
    :
}

lease6_decline () {
    :
}

case "$1" in
    "lease4_renew")
        lease4_renew
        ;;
    "lease4_expire")
        lease4_expire
        ;;
    "lease4_recover")
        lease4_recover
        ;;
    "leases4_committed")
        leases4_committed
        ;;
    "lease4_release")
        lease4_release
        ;;
    "lease4_decline")
        lease4_decline
        ;;
    "lease6_renew")
        lease6_renew
        ;;
    "lease6_rebind")
        lease6_rebind
        ;;
    "lease6_expire")
        lease6_expire
        ;;
    "lease6_recover")
        lease6_recover
        ;;
    "leases6_committed")
        leases6_committed
        ;;
    "lease6_release")
        lease6_release
        ;;
    "lease6_decline")
        lease6_decline
        ;;
    *)
        unknown_handle "${@}"
        ;;
esac

Nothing interesting, just using the same script and jq to generate the json payload. Just remember to make the script executable, and have mosquitto, bash & jq installed.

ISC Kea configuration

And for the final configuration in ISC Kea:

{
    "hooks-libraries": [
        {
            "library": "/usr/local/lib/libdhcp_run_script.so",
            "parameters": {
                "name": "/full_path_to/script_name.sh",
                "sync": false
            }
        }
    ]
}

That’s it, now your ISC Kea will send a MQTT message for when new leases are handed out, and when old ones expires. I’m using this as a device tracker in Home Assistant.

Home Assistant configuration

I used to manually setup these device trackers in Home Assistant as it was quite easy:

# Before using autodiscovery
device_tracker:
  - name: "Oscar iPhone"
    state_topic: !secret oscar_iphone_attributes_topic
    value_template: "{{ value_json.state }}"
    source_type: "router"

…but I’ve now taken the approx. 2 minutes needed to read the auto discovery documentation, and implement it in my lease script above.