APIs para pantallas LED baratas
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