Files
sless/examples/IOT
Naeel 1e53766c46 feat(iot): Этапы 2-7 — MQTT auth, IoT API, EMQX, mqtt-bridge, E2E demo
Этап 2+4: internal/api/handler/iot_device_handler.go
  - MQTTAuth: POST /internal/mqtt/auth (без JWT, для EMQX)
  - CreateIoTDevice, ListIoTDevices, GetIoTDevice (c password), DeleteIoTDevice, UpdateIoTDevice
  - crypto/subtle.ConstantTimeCompare против timing attacks

Этап 4: internal/api/router.go
  - /v1/namespaces/{ns}/iot/devices CRUD
  - /internal/mqtt/auth (без JWT middleware)

Этап 3: deployments/k8s/emqx.yaml
  - EMQX 5.5.1, emqx.conf (HOCON) с HTTP auth backend
  - Сервис exposure: 1883 (MQTT), 8083 (WS), 18083 (Dashboard)

Этап 3: iot/cmd/mqtt-bridge/main.go
  - paho.mqtt.golang: подписка на +/telemetry/+
  - amqp091-go: publish в iot.{namespace}.telemetry
  - deployments/k8s/iot-mqtt-bridge.yaml

Этап 7: examples/IOT/ — E2E demo (main.tf, handler.py, README.md)

go.mod: добавлен github.com/eclipse/paho.mqtt.golang v1.5.1
go build ./... — ошибок нет
2026-04-04 09:45:23 +03:00
..

IoT MVP — E2E Demo

Что делает этот пример

Показывает полную цепочку:

IoT Device (mosquitto_pub)
  → MQTT PUBLISH → EMQX (HTTP auth → sless-operator)
    → [iot-mqtt-bridge подписан на "+/telemetry/+"]
      → RabbitMQ queue "iot.{namespace}.telemetry"
        → event-dispatcher
          → POST → serverless function (handler.py)

Предусловия

  1. EMQX запущен: kubectl apply -f deployments/k8s/emqx.yaml
  2. iot-mqtt-bridge запущен: kubectl apply -f deployments/k8s/iot-mqtt-bridge.yaml
  3. event-dispatcher запущен (уже должен работать)

Запуск

# Установить переменные
export API_TOKEN="your-jwt-token"
export NAMESPACE="sless-abc123def456"  # твой namespace

# Инициализировать
terraform init
terraform apply \
  -var="namespace=${NAMESPACE}" \
  -var="api_token=${API_TOKEN}"

# Получить credentials
MQTT_USER=$(terraform output -raw mqtt_username)
MQTT_PASS=$(terraform output -raw mqtt_password)
MQTT_TOPIC=$(terraform output -raw mqtt_topic)

echo "MQTT user: ${MQTT_USER}"
echo "MQTT topic: ${MQTT_TOPIC}"

Отправить тестовое сообщение

# Через mosquitto_pub (из пода внутри кластера)
kubectl run mqtt-test --rm -i --image=eclipse-mosquitto --restart=Never -- \
  mosquitto_pub \
  -h emqx.sless.svc \
  -p 1883 \
  -u "${MQTT_USER}" \
  -P "${MQTT_PASS}" \
  -t "${MQTT_TOPIC}" \
  -m '{"temperature": 22.5, "humidity": 65, "unit": "celsius"}'

Проверить что функция вызвалась

# Логи event-dispatcher
kubectl logs -n sless deployment/event-dispatcher -f

# Логи функции (через invocations API)
curl -H "Authorization: Bearer ${API_TOKEN}" \
  https://sless.kube5s.ru/v1/namespaces/${NAMESPACE}/functions/iot-telemetry-handler/invocations

Структура файлов

examples/IOT/
  main.tf      # Terraform: function + trigger + iot_device
  handler.py   # Python обработчик телеметрии
  README.md    # Этот файл

Известные ограничения MVP

  • sless_iot_device Terraform ресурс требует реализации в terraform-provider-sless (Этап 6)
  • EMQX TLS отключён — включить для prod (настроить cert-manager secret)
  • iot-mqtt-bridge credentials создаются вручную (автоматизировать в будущем)
  • Нет обратного канала: Cloud → Device команды (Device Shadow — вне MVP)