Cargando ahora

APIs para pantallas LED baratas

pantallas led

En mi casa tengo varias pantallas LED a las que me conecto una por una para cambiarles el Texto, otras simplemente cargan información del tiempo o de la cotización en bolsa de valores o el precio del Bitcoin.

Vamos a hacer que una IA las controle y que la información que muestren sea totalmente dinámica.

Como primer paso vamos a crear una API general para que las pantallas pregunten que información deben cargar.

Esta API va a ser la que luego controle nuestra IA y lo vamos a desplegar en nuestro servidor casero en un container


Descripción General

  • Objetivo: Crear una API REST que reciba un parámetro de identificación de dispositivo y responda con un JSON que contenga todos los textos a mostrar y el número de segundos de cada texto.
  • Tecnologías Utilizadas:
    • Go (Golang)
    • Gin Web Framework
    • SQLite3

Código Fuente

1. main.go

package main

import (
    "database/sql"
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
    _ "github.com/mattn/go-sqlite3"
)

// Estructura para representar los datos de respuesta
type ResponseData struct {
    Text    string `json:"text"`
    Seconds int    `json:"seconds"`
}

func main() {
    // Iniciar el router de Gin
    router := gin.Default()

    // Conexión a la base de datos SQLite
    db, err := sql.Open("sqlite3", "./devices.db")
    if err != nil {
        log.Fatalf("Error al conectar con la base de datos: %v", err)
    }
    defer db.Close()

    // Crear tabla si no existe
    createTable(db)

    // Ruta para manejar las solicitudes GET
    router.GET("/api/device", func(c *gin.Context) {
        deviceID := c.Query("device_id")
        if deviceID == "" {
            c.JSON(http.StatusBadRequest, gin.H{"error": "El parámetro device_id es requerido"})
            return
        }

        data, err := getData(db, deviceID)
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": "Error al obtener los datos"})
            return
        }

        c.JSON(http.StatusOK, data)
    })

    // Ejecutar el servidor en el puerto 8080
    router.Run(":8080")
}

// Función para crear la tabla en SQLite si no existe
func createTable(db *sql.DB) {
    query := `
    CREATE TABLE IF NOT EXISTS device_texts (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        device_id TEXT NOT NULL,
        text TEXT NOT NULL,
        seconds INTEGER NOT NULL
    );
    `
    _, err := db.Exec(query)
    if err != nil {
        log.Fatalf("Error al crear la tabla: %v", err)
    }
}

// Función para obtener los datos de la base de datos
func getData(db *sql.DB, deviceID string) ([]ResponseData, error) {
    query := `SELECT text, seconds FROM device_texts WHERE device_id = ?`
    rows, err := db.Query(query, deviceID)
    if err != nil {
        return nil, err
    }
    defer rows.Close()

    var data []ResponseData
    for rows.Next() {
        var item ResponseData
        if err := rows.Scan(&item.Text, &item.Seconds); err != nil {
            return nil, err
        }
        data = append(data, item)
    }
    return data, nil
}

Explicación del Código

  • Importaciones:
    • ​github.com/gin-gonic/gin​​: Framework web para manejar rutas y solicitudes HTTP.
    • ​database/sql​​ y github.com/mattn/go-sqlite3​​: Paquetes para interactuar con la base de datos SQLite.
  • Estructura ResponseData​​:
    • Representa cada entrada de texto y segundos que se enviará en la respuesta JSON.
  • Función main​​:
    • Inicializa el router de Gin.
    • Conecta a la base de datos SQLite.
    • Define la ruta /api/device​​ que maneja las solicitudes GET.
    • Llama a las funciones createTable​​ y getData​​ para preparar y obtener datos de la base de datos.
  • Función createTable​​:
    • Crea la tabla device_texts​​ si no existe.
  • Función getData​​:
    • Ejecuta una consulta para obtener los textos y segundos asociados al device_id​​ proporcionado.
    • Devuelve una slice de ResponseData​​.

Instrucciones para Ejecutar la Aplicación

1. Configurar el Entorno

  • Asegúrate de tener instalado Go en tu sistema. Puedes descargarlo desde golang.org.

2. Inicializar el Módulo

go mod init your_module_name

3. Descargar Dependencias

go get github.com/gin-gonic/gin
go get github.com/mattn/go-sqlite3

4. Ejecutar la Aplicación

go run main.go

La aplicación estará escuchando en http://localhost:8080​​.

5. Probar la API

Puedes probar la API utilizando curl​​ o cualquier herramienta como Postman:

curl "http://localhost:8080/api/device?device_id=your_device_id"

Insertar Datos de Prueba

Para probar la API, necesitarás insertar algunos datos en la base de datos. Puedes hacerlo agregando la siguiente función en tu código y llamándola en main​​ después de createTable(db)​​:

// Función para insertar datos de prueba
func insertSampleData(db *sql.DB) {
    query := `INSERT INTO device_texts (device_id, text, seconds) VALUES (?, ?, ?)`
    _, err := db.Exec(query, "device123", "Mensaje de prueba", 10)
    if err != nil {
        log.Fatalf("Error al insertar datos de prueba: %v", err)
    }
}

Luego, llama a insertSampleData(db)​​ en el main​​:

createTable(db)
insertSampleData(db)

Crear el Contenedor Docker

1. Dockerfile

Crea un archivo llamado Dockerfile​​ en el mismo directorio con el siguiente contenido:

# Etapa de compilación
FROM golang:1.20-alpine AS builder

# Establecer el directorio de trabajo
WORKDIR /app

# Copiar el código fuente
COPY . .

# Descargar dependencias
RUN go mod download

# Compilar la aplicación
RUN go build -o server main.go

# Etapa final
FROM alpine:latest

# Crear directorio de trabajo
WORKDIR /root/

# Copiar el binario compilado desde la etapa anterior
COPY --from=builder /app/server .

# Copiar la base de datos si es necesario
COPY --from=builder /app/devices.db .

# Exponer el puerto
EXPOSE 8080

# Comando para ejecutar la aplicación
CMD ["./server"]

2. Construir la Imagen

docker build -t your_image_name .

3. Ejecutar el Contenedor

docker run -d -p 8080:8080 your_image_name

Notas Adicionales

  • Persistencia de Datos:
    • Si deseas que los datos de la base de datos persistan, considera montar un volumen en Docker o utilizar una base de datos externa.
  • Manejo de Errores:
    • El código incluye manejo básico de errores, pero en un entorno de producción podrías querer mejorar el manejo y registro de errores.
  • Variables de Entorno:
    • Para mayor flexibilidad, puedes utilizar variables de entorno para configurar parámetros como el puerto o la ruta de la base de datos.

Conclusión

Este código proporciona una base sólida para tu API REST utilizando Go y SQLite. Es eficiente y ligero, ideal para ejecutarse en un contenedor Docker. Puedes expandir y modificar este código según tus necesidades específicas.


Si tienes alguna pregunta o necesitas más ayuda, ¡no dudes en preguntar!

Share this content:

Publicar comentario

Puede que te hayas perdido