Posted on
Artificial Intelligence

Artificial Intelligence Smart Home Automation

Author
  • User
    linuxbash
    Posts by this author
    Posts by this author

AI-Powered Smart Home Automation on Linux (Bash-Friendly Guide)

Tired of cloud-only assistants that phone home, lock you in, and break when the internet hiccups? With a modest Linux box and a few open-source tools, you can run a private, fast, and extensible AI smart home—entirely on your LAN. This guide shows you how to stand up a local stack—MQTT, Home Assistant, Node-RED, and a local LLM—then wire up real automations with nothing but Bash and a few containers.

What you’ll get:

  • A local, private, low-latency AI home hub

  • Hardware control via Zigbee/Z-Wave (e.g., lights, sensors)

  • Natural-language control without the cloud

  • Reproducible, scriptable setups you can automate with Bash

Why local AI for smart homes is worth it

  • Privacy by default: Your commands, presence, and routines never leave your LAN.

  • Reliability and latency: Actions complete in milliseconds, even without internet.

  • Freedom and extensibility: Open protocols (MQTT), pluggable tools (Home Assistant, Node-RED), and local LLMs give you complete control.

  • Cost control: No subscriptions; run on spare hardware (old mini PC, Pi-class boards).

What we’ll build (architecture)

  • Mosquitto (MQTT broker): The event bus for your devices and automations.

  • Home Assistant: Device discovery, dashboards, and deep integrations.

  • Node-RED: Low-code logic and HTTP endpoints for glue/automation.

  • Zigbee2MQTT: Bridges Zigbee devices to MQTT (Z-Wave alternatives exist).

  • Ollama: Local LLM server for natural-language understanding.

We’ll run most services in containers (Podman) for portability and easy updates.


1) Prerequisites: Install base tools

Install Podman (containers), Mosquitto (MQTT), Git, curl, and jq. Pick your package manager:

  • Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y podman mosquitto mosquitto-clients git curl jq
sudo systemctl enable --now mosquitto
  • Fedora/RHEL (dnf):
sudo dnf install -y podman mosquitto mosquitto-clients git curl jq
sudo systemctl enable --now mosquitto
  • openSUSE (zypper):
sudo zypper install -y podman mosquitto git curl jq
sudo systemctl enable --now mosquitto

Optional: If your firewall blocks ports, open these:

  • Home Assistant: 8123/tcp

  • Node-RED: 1880/tcp

  • MQTT: 1883/tcp

  • Zigbee2MQTT frontend: 8080/tcp

Example (firewalld):

sudo firewall-cmd --add-port=8123/tcp --add-port=1880/tcp --add-port=1883/tcp --add-port=8080/tcp --permanent
sudo firewall-cmd --reload

Create directories to hold container data:

mkdir -p ~/containers/{homeassistant/config,nodered/data,zigbee2mqtt/data}

2) Spin up your backbone services (Home Assistant + Node-RED)

We’ll run these in Podman with host networking to make MQTT/home services simple.

  • Home Assistant (stable):
podman run -d --name homeassistant \
  --restart=always --privileged --network=host \
  -v ~/containers/homeassistant/config:/config \
  ghcr.io/home-assistant/home-assistant:stable

Access: http://localhost:8123 (first-run setup will guide you).

  • Node-RED:
podman run -d --name nodered \
  --restart=always --network=host \
  -v ~/containers/nodered/data:/data \
  docker.io/nodered/node-red:latest

Access: http://localhost:1880

Tip: In Node-RED, add the Home Assistant palette for easy service calls:

  • Menu > Manage palette > Install: node-red-contrib-home-assistant-websocket

3) Add local AI: Ollama (run LLMs on your LAN)

Install Ollama (serves models at http://localhost:11434):

curl -fsSL https://ollama.com/install.sh | sh
systemctl --user enable --now ollama || ollama serve &

Download a model that fits your hardware:

ollama pull phi3:mini     # lightweight
# or
ollama pull llama3:8b     # stronger model, needs more RAM/VRAM

Quick test:

curl -s http://localhost:11434/api/generate -d '{
  "model": "phi3:mini",
  "prompt": "In one sentence, explain what MQTT is."
}' | jq -r '.response'

4) Bridge the physical world: Zigbee2MQTT

Plug in your Zigbee coordinator (e.g., CC2652-based USB dongle) and grant serial access:

sudo usermod -aG dialout $USER
# Log out/in or reboot for group change to take effect
ls -l /dev/serial/by-id/

Create Zigbee2MQTT config:

cat > ~/containers/zigbee2mqtt/data/configuration.yaml <<'YAML'
homeassistant: true
permit_join: false
mqtt:
  base_topic: zigbee2mqtt
  server: 'mqtt://127.0.0.1:1883'
serial:
  port: '/dev/serial/by-id/usb-TI_CC2652...'
frontend:
  port: 8080
YAML

Run the container:

podman run -d --name zigbee2mqtt \
  --restart=always --network=host \
  --device /dev/ttyUSB0 \
  -v ~/containers/zigbee2mqtt/data:/app/data \
  docker.io/koenkk/zigbee2mqtt:latest

Note:

  • Prefer the stable by-id path in configuration.yaml; keep --device aligned (e.g., /dev/ttyACM0).

  • Access the Zigbee2MQTT UI at http://localhost:8080 to pair devices and see logs.


5) Real-world automations you can run today

Here are three Bash-first examples that show how to glue it all together.

A) Natural-language light control with Ollama + Home Assistant

Goal: Type “set the living room lights to warm 40%” and let the LLM turn that into a service call.

1) Create a long-lived token in Home Assistant (Profile > Create Token). Save it as HA_TOKEN.

2) Bash helper that parses natural language into JSON using Ollama, then calls HA:

#!/usr/bin/env bash
set -euo pipefail

HA_URL="http://127.0.0.1:8123"
HA_TOKEN="<PUT_YOUR_HA_TOKEN_HERE>"
MODEL="phi3:mini"

NL="$*"
if [[ -z "${NL}" ]]; then
  echo "Usage: $0 \"turn kitchen light on warm 40%\"" >&2
  exit 1
fi

SYSTEM_PROMPT='You convert home commands to strict JSON. Keys: device (string), action (on|off|toggle), brightness (0-255, optional), color_temp (153-500 mireds, optional). Only output JSON.'
USER_PROMPT="Command: ${NL}"

PAYLOAD=$(jq -n --arg sp "$SYSTEM_PROMPT" --arg up "$USER_PROMPT" \
  '{model:"'"$MODEL"'", system:$sp, prompt:$up, format:"json"}')

JSON=$(curl -s http://127.0.0.1:11434/api/generate -d "$PAYLOAD" | jq -r '.response')

DEVICE=$(jq -r '.device' <<<"$JSON")
ACTION=$(jq -r '.action' <<<"$JSON")
BRI=$(jq -r 'try .brightness // empty' <<<"$JSON")
CT=$(jq -r 'try .color_temp // empty' <<<"$JSON")

# map your device names to HA entity_ids
declare -A MAP=( ["living room"]="light.living_room" ["kitchen"]="light.kitchen" )
ENTITY="${MAP[$DEVICE]}"

if [[ -z "${ENTITY:-}" ]]; then
  echo "Unknown device: $DEVICE" >&2
  exit 1
fi

SERVICE="light/turn_${ACTION}"
BODY=$(jq -n --arg e "$ENTITY" --argjson b "${BRI:-null}" --argjson c "${CT:-null}" '
  .entity_id=$e
  | if $b != null then .brightness=$b else . end
  | if $c != null then .color_temp=$c else . end
')

curl -s -X POST "$HA_URL/api/services/$SERVICE" \
  -H "Authorization: Bearer $HA_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$BODY" | jq .

Use it:

./ai-light.sh "set the living room lights to warm 40%"

B) Quick “Goodnight” scene via MQTT (no HA call needed)

Assuming Zigbee2MQTT, publish to a specific light or group:

mosquitto_pub -h 127.0.0.1 -t zigbee2mqtt/bedroom_lamp/set -m '{"state":"OFF"}'
mosquitto_pub -h 127.0.0.1 -t zigbee2mqtt/hall_group/set -m '{"state":"OFF"}'

Wrap it with a simple LLM plan:

PLAN=$(curl -s http://127.0.0.1:11434/api/generate -d '{
  "model":"phi3:mini",
  "prompt":"Create a JSON array of MQTT commands to turn off all lights and set bedroom temperature cozy. Use topics zigbee2mqtt/<thing>/set with minimal fields."
}' | jq -r '.response')

jq -c '.[]' <<<"$PLAN" | while read -r cmd; do
  TOPIC=$(jq -r '.topic' <<<"$cmd")
  MSG=$(jq -c '.message' <<<"$cmd")
  mosquitto_pub -h 127.0.0.1 -t "$TOPIC" -m "$MSG"
done

C) Energy coach: summarize usage and post a tip

1) Create a Home Assistant sensor for energy (e.g., sensor.energy_daily).
2) Bash script pulls the value, asks the LLM for a tip, and publishes to MQTT:

#!/usr/bin/env bash
set -euo pipefail
HA_URL="http://127.0.0.1:8123"
HA_TOKEN="<PUT_YOUR_HA_TOKEN_HERE>"

VAL=$(curl -s "$HA_URL/api/states/sensor.energy_daily" \
  -H "Authorization: Bearer $HA_TOKEN" | jq -r '.state')

TIP=$(curl -s http://127.0.0.1:11434/api/generate -d "{
  \"model\":\"phi3:mini\",
  \"prompt\":\"Today's household energy use is ${VAL} kWh. In <=2 sentences, offer one specific, practical tip to reduce consumption tonight.\"
}" | jq -r '.response' | tr -s '\n' ' ')

mosquitto_pub -h 127.0.0.1 -t home/energy/tip -m "$TIP"
echo "Posted tip: $TIP"

Schedule with cron:

crontab -e
# at 21:00 daily
0 21 * * * /home/you/bin/energy-tip.sh >> /home/you/energy-tip.log 2>&1

Troubleshooting tips

  • Can’t reach MQTT from containers? Use --network=host and connect to 127.0.0.1. Make sure mosquitto is running: systemctl status mosquitto.

  • Zigbee coordinator path: Prefer the by-id path from /dev/serial/by-id/ in configuration.yaml.

  • Permissions: After adding your user to the dialout group, log out/in.

  • Performance: Try smaller models (e.g., phi3:mini) on low-RAM systems.

  • Node-RED to HA: Use the HA WebSocket nodes for easy entity discovery and service calls.


Conclusion and next steps (CTA)

You now have a private AI home hub running entirely on Linux—with device control, natural-language smarts, and portable automations you can script in Bash. Next:

  • In Home Assistant, add Assist + Piper for offline voice control.

  • In Node-RED, build flows that call Ollama for intent parsing.

  • Secure remote access via a reverse proxy and mTLS/WireGuard.

  • Back up ~/containers/* and your HA config regularly.

Share your automations and tweaks with the community, and show what Linux + local AI can do—no cloud required.