Add IP field, ping service, status endpoint and UI; update README
This commit is contained in:
@ -27,6 +27,7 @@ func InitDB() (*DB, error) {
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
mac TEXT NOT NULL UNIQUE,
|
||||
ip TEXT NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);`
|
||||
@ -36,13 +37,19 @@ func InitDB() (*DB, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Füge IP-Spalte hinzu, falls sie nicht existiert
|
||||
_, err = db.Exec("ALTER TABLE pcs ADD COLUMN ip TEXT DEFAULT ''")
|
||||
if err != nil {
|
||||
// Spalte existiert bereits, ignorieren
|
||||
}
|
||||
|
||||
log.Println("Datenbank erfolgreich initialisiert")
|
||||
return &DB{db}, nil
|
||||
}
|
||||
|
||||
// GetAllPCs holt alle PCs aus der Datenbank
|
||||
func (db *DB) GetAllPCs() ([]models.PC, error) {
|
||||
rows, err := db.Query("SELECT id, name, mac, created_at, updated_at FROM pcs ORDER BY name")
|
||||
rows, err := db.Query("SELECT id, name, mac, ip, created_at, updated_at FROM pcs ORDER BY name")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -51,7 +58,7 @@ func (db *DB) GetAllPCs() ([]models.PC, error) {
|
||||
var pcs []models.PC
|
||||
for rows.Next() {
|
||||
var pc models.PC
|
||||
err := rows.Scan(&pc.ID, &pc.Name, &pc.MAC, &pc.CreatedAt, &pc.UpdatedAt)
|
||||
err := rows.Scan(&pc.ID, &pc.Name, &pc.MAC, &pc.IP, &pc.CreatedAt, &pc.UpdatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -62,11 +69,11 @@ func (db *DB) GetAllPCs() ([]models.PC, error) {
|
||||
}
|
||||
|
||||
// CreatePC erstellt einen neuen PC-Eintrag
|
||||
func (db *DB) CreatePC(name, mac string) (*models.PC, error) {
|
||||
func (db *DB) CreatePC(name, mac, ip string) (*models.PC, error) {
|
||||
now := time.Now()
|
||||
result, err := db.Exec(
|
||||
"INSERT INTO pcs (name, mac, created_at, updated_at) VALUES (?, ?, ?, ?)",
|
||||
name, mac, now, now,
|
||||
"INSERT INTO pcs (name, mac, ip, created_at, updated_at) VALUES (?, ?, ?, ?, ?)",
|
||||
name, mac, ip, now, now,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -81,17 +88,18 @@ func (db *DB) CreatePC(name, mac string) (*models.PC, error) {
|
||||
ID: int(id),
|
||||
Name: name,
|
||||
MAC: mac,
|
||||
IP: ip,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdatePC aktualisiert einen bestehenden PC-Eintrag
|
||||
func (db *DB) UpdatePC(id int, name, mac string) (*models.PC, error) {
|
||||
func (db *DB) UpdatePC(id int, name, mac, ip string) (*models.PC, error) {
|
||||
now := time.Now()
|
||||
_, err := db.Exec(
|
||||
"UPDATE pcs SET name = ?, mac = ?, updated_at = ? WHERE id = ?",
|
||||
name, mac, now, id,
|
||||
"UPDATE pcs SET name = ?, mac = ?, ip = ?, updated_at = ? WHERE id = ?",
|
||||
name, mac, ip, now, id,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -101,6 +109,7 @@ func (db *DB) UpdatePC(id int, name, mac string) (*models.PC, error) {
|
||||
ID: id,
|
||||
Name: name,
|
||||
MAC: mac,
|
||||
IP: ip,
|
||||
UpdatedAt: now,
|
||||
}, nil
|
||||
}
|
||||
@ -115,9 +124,9 @@ func (db *DB) DeletePC(id int) error {
|
||||
func (db *DB) GetPCByID(id int) (*models.PC, error) {
|
||||
var pc models.PC
|
||||
err := db.QueryRow(
|
||||
"SELECT id, name, mac, created_at, updated_at FROM pcs WHERE id = ?",
|
||||
"SELECT id, name, mac, ip, created_at, updated_at FROM pcs WHERE id = ?",
|
||||
id,
|
||||
).Scan(&pc.ID, &pc.Name, &pc.MAC, &pc.CreatedAt, &pc.UpdatedAt)
|
||||
).Scan(&pc.ID, &pc.Name, &pc.MAC, &pc.IP, &pc.CreatedAt, &pc.UpdatedAt)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@ -3,6 +3,7 @@ package handlers
|
||||
import (
|
||||
"medi-wol/internal/database"
|
||||
"medi-wol/internal/models"
|
||||
"medi-wol/internal/ping"
|
||||
"medi-wol/internal/wol"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@ -12,15 +13,17 @@ import (
|
||||
|
||||
// PCHandler verwaltet die HTTP-Anfragen für PC-Operationen
|
||||
type PCHandler struct {
|
||||
db *database.DB
|
||||
wolService *wol.Service
|
||||
db *database.DB
|
||||
wolService *wol.Service
|
||||
pingService *ping.PingService
|
||||
}
|
||||
|
||||
// NewPCHandler erstellt einen neuen PC-Handler
|
||||
func NewPCHandler(db *database.DB, wolService *wol.Service) *PCHandler {
|
||||
return &PCHandler{
|
||||
db: db,
|
||||
wolService: wolService,
|
||||
db: db,
|
||||
wolService: wolService,
|
||||
pingService: ping.NewPingService(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +72,7 @@ func (h *PCHandler) CreatePC(c *gin.Context) {
|
||||
}
|
||||
|
||||
// PC erstellen
|
||||
pc, err := h.db.CreatePC(req.Name, req.MAC)
|
||||
pc, err := h.db.CreatePC(req.Name, req.MAC, req.IP)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, models.PCResponse{
|
||||
Success: false,
|
||||
@ -116,7 +119,7 @@ func (h *PCHandler) UpdatePC(c *gin.Context) {
|
||||
}
|
||||
|
||||
// PC aktualisieren
|
||||
pc, err := h.db.UpdatePC(id, req.Name, req.MAC)
|
||||
pc, err := h.db.UpdatePC(id, req.Name, req.MAC, req.IP)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, models.PCResponse{
|
||||
Success: false,
|
||||
@ -196,3 +199,33 @@ func (h *PCHandler) WakePC(c *gin.Context) {
|
||||
Message: "Wake-on-LAN Paket erfolgreich gesendet an " + pc.Name,
|
||||
})
|
||||
}
|
||||
|
||||
// GetPCStatus gibt den Online-Status aller PCs zurück
|
||||
func (h *PCHandler) GetPCStatus(c *gin.Context) {
|
||||
pcs, err := h.db.GetAllPCs()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, models.PCResponse{
|
||||
Success: false,
|
||||
Message: "Fehler beim Laden der PCs: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Online-Status für alle PCs überprüfen
|
||||
var statusList []models.PCStatus
|
||||
for _, pc := range pcs {
|
||||
online := h.pingService.IsOnline(pc.IP)
|
||||
statusList = append(statusList, models.PCStatus{
|
||||
ID: pc.ID,
|
||||
Name: pc.Name,
|
||||
MAC: pc.MAC,
|
||||
IP: pc.IP,
|
||||
Online: online,
|
||||
})
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"status": statusList,
|
||||
})
|
||||
}
|
||||
|
||||
@ -9,7 +9,8 @@ type PC struct {
|
||||
ID int `json:"id" db:"id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
MAC string `json:"mac" db:"mac"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
IP string `json:"ip" db:"ip"`
|
||||
CreatedAt time.Time `json:"created_at" db:"updated_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
}
|
||||
|
||||
@ -17,12 +18,14 @@ type PC struct {
|
||||
type CreatePCRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
MAC string `json:"mac" binding:"required"`
|
||||
IP string `json:"ip" binding:"required"`
|
||||
}
|
||||
|
||||
// UpdatePCRequest repräsentiert die Anfrage zum Aktualisieren eines PCs
|
||||
type UpdatePCRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
MAC string `json:"mac" binding:"required"`
|
||||
IP string `json:"ip" binding:"required"`
|
||||
}
|
||||
|
||||
// PCResponse repräsentiert die Antwort für PC-Operationen
|
||||
@ -32,3 +35,12 @@ type PCResponse struct {
|
||||
PC *PC `json:"pc,omitempty"`
|
||||
PCs []PC `json:"pcs,omitempty"`
|
||||
}
|
||||
|
||||
// PCStatus repräsentiert den Online-Status eines PCs
|
||||
type PCStatus struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
MAC string `json:"mac"`
|
||||
IP string `json:"ip"`
|
||||
Online bool `json:"online"`
|
||||
}
|
||||
|
||||
81
internal/ping/ping.go
Normal file
81
internal/ping/ping.go
Normal file
@ -0,0 +1,81 @@
|
||||
package ping
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
// PingService bietet Funktionen zum Überprüfen des Online-Status von PCs
|
||||
type PingService struct{}
|
||||
|
||||
// NewPingService erstellt eine neue Instanz des Ping-Services
|
||||
func NewPingService() *PingService {
|
||||
return &PingService{}
|
||||
}
|
||||
|
||||
// IsOnline überprüft, ob ein PC online ist
|
||||
func (ps *PingService) IsOnline(ip string) bool {
|
||||
if ip == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Verwende system-spezifischen Ping-Befehl
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
return ps.pingWindows(ip)
|
||||
case "linux", "darwin":
|
||||
return ps.pingUnix(ip)
|
||||
default:
|
||||
return ps.pingGeneric(ip)
|
||||
}
|
||||
}
|
||||
|
||||
// pingWindows führt einen Ping unter Windows aus
|
||||
func (ps *PingService) pingWindows(ip string) bool {
|
||||
cmd := exec.Command("ping", "-n", "1", "-w", "1000", ip)
|
||||
err := cmd.Run()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// pingUnix führt einen Ping unter Unix-Systemen aus
|
||||
func (ps *PingService) pingUnix(ip string) bool {
|
||||
cmd := exec.Command("ping", "-c", "1", "-W", "1", ip)
|
||||
err := cmd.Run()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// pingGeneric ist eine plattformunabhängige Alternative
|
||||
func (ps *PingService) pingGeneric(ip string) bool {
|
||||
// Versuche TCP-Verbindung auf Port 80 (HTTP)
|
||||
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:80", ip), 2*time.Second)
|
||||
if err != nil {
|
||||
// Versuche TCP-Verbindung auf Port 22 (SSH)
|
||||
conn, err = net.DialTimeout("tcp", fmt.Sprintf("%s:22", ip), 2*time.Second)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
defer conn.Close()
|
||||
return true
|
||||
}
|
||||
|
||||
// CheckAllPCs überprüft den Online-Status aller PCs
|
||||
func (ps *PingService) CheckAllPCs(pcs []interface{}) map[int]bool {
|
||||
results := make(map[int]bool)
|
||||
|
||||
for _, pc := range pcs {
|
||||
// Type assertion für PC-Interface
|
||||
if pcMap, ok := pc.(map[string]interface{}); ok {
|
||||
if id, ok := pcMap["id"].(float64); ok {
|
||||
if ip, ok := pcMap["ip"].(string); ok {
|
||||
results[int(id)] = ps.IsOnline(ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
Reference in New Issue
Block a user