450 lines
12 KiB
Go
450 lines
12 KiB
Go
package mock
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"time"
|
|
|
|
"spore-gateway/pkg/client"
|
|
"spore-gateway/pkg/registry"
|
|
)
|
|
|
|
// GenerateMockClusterMembers generates mock cluster member data
|
|
func GenerateMockClusterMembers(nodes map[string]*NodeInfo) []client.ClusterMember {
|
|
members := make([]client.ClusterMember, 0, len(nodes))
|
|
|
|
for _, node := range nodes {
|
|
member := client.ClusterMember{
|
|
IP: node.IP,
|
|
Hostname: node.Hostname,
|
|
Status: string(node.Status),
|
|
Latency: node.Latency,
|
|
LastSeen: node.LastSeen.Unix(),
|
|
Labels: node.Labels,
|
|
Resources: map[string]interface{}{
|
|
"freeHeap": 32768 + rand.Intn(32768),
|
|
"cpuFreqMHz": 80 + rand.Intn(160),
|
|
"flashChipSize": 4194304,
|
|
},
|
|
}
|
|
members = append(members, member)
|
|
}
|
|
|
|
return members
|
|
}
|
|
|
|
// GenerateMockTaskStatus generates mock task status data
|
|
func GenerateMockTaskStatus() *client.TaskStatusResponse {
|
|
tasks := []client.TaskInfo{
|
|
{
|
|
Name: "HeartbeatTask",
|
|
Interval: 5000,
|
|
Enabled: true,
|
|
Running: true,
|
|
AutoStart: true,
|
|
},
|
|
{
|
|
Name: "SensorReadTask",
|
|
Interval: 10000,
|
|
Enabled: true,
|
|
Running: true,
|
|
AutoStart: true,
|
|
},
|
|
{
|
|
Name: "StatusUpdateTask",
|
|
Interval: 30000,
|
|
Enabled: true,
|
|
Running: false,
|
|
AutoStart: false,
|
|
},
|
|
{
|
|
Name: "CleanupTask",
|
|
Interval: 60000,
|
|
Enabled: false,
|
|
Running: false,
|
|
AutoStart: false,
|
|
},
|
|
}
|
|
|
|
activeTasks := 0
|
|
for _, task := range tasks {
|
|
if task.Running {
|
|
activeTasks++
|
|
}
|
|
}
|
|
|
|
return &client.TaskStatusResponse{
|
|
Summary: client.TaskSummary{
|
|
TotalTasks: len(tasks),
|
|
ActiveTasks: activeTasks,
|
|
},
|
|
Tasks: tasks,
|
|
System: client.SystemInfo{
|
|
FreeHeap: 32768 + int64(rand.Intn(32768)),
|
|
Uptime: int64(time.Now().Unix() - 3600*24), // 24 hours uptime
|
|
},
|
|
}
|
|
}
|
|
|
|
// GenerateMockSystemStatus generates mock system status data
|
|
func GenerateMockSystemStatus(labels map[string]string) *client.SystemStatusResponse {
|
|
return &client.SystemStatusResponse{
|
|
FreeHeap: 32768 + int64(rand.Intn(32768)),
|
|
ChipID: int64(rand.Int31()),
|
|
SDKVersion: "3.1.0",
|
|
CPUFreqMHz: 80 + rand.Intn(160),
|
|
FlashChipSize: 4194304,
|
|
Labels: labels,
|
|
}
|
|
}
|
|
|
|
// GenerateMockCapabilities generates mock API endpoint capabilities
|
|
func GenerateMockCapabilities() *client.CapabilitiesResponse {
|
|
return &client.CapabilitiesResponse{
|
|
Endpoints: []client.EndpointInfo{
|
|
{
|
|
URI: "/api/node/status",
|
|
Method: "GET",
|
|
Parameters: []client.ParameterInfo{
|
|
{
|
|
Name: "detailed",
|
|
Type: "boolean",
|
|
Required: false,
|
|
Description: "Include detailed system information",
|
|
Location: "query",
|
|
Default: "false",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
URI: "/api/cluster/members",
|
|
Method: "GET",
|
|
Parameters: []client.ParameterInfo{},
|
|
},
|
|
{
|
|
URI: "/api/tasks/status",
|
|
Method: "GET",
|
|
Parameters: []client.ParameterInfo{},
|
|
},
|
|
{
|
|
URI: "/api/node/update",
|
|
Method: "POST",
|
|
Parameters: []client.ParameterInfo{
|
|
{
|
|
Name: "firmware",
|
|
Type: "file",
|
|
Required: true,
|
|
Description: "Firmware binary file",
|
|
Location: "body",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
URI: "/api/node/config",
|
|
Method: "POST",
|
|
Parameters: []client.ParameterInfo{
|
|
{
|
|
Name: "labels",
|
|
Type: "json",
|
|
Required: true,
|
|
Description: "Node labels in JSON format",
|
|
Location: "body",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
URI: "/api/sensors/read",
|
|
Method: "GET",
|
|
Parameters: []client.ParameterInfo{
|
|
{
|
|
Name: "sensor",
|
|
Type: "string",
|
|
Required: false,
|
|
Description: "Specific sensor to read",
|
|
Location: "query",
|
|
Values: []string{"temperature", "humidity", "pressure"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// GenerateMockFirmwareList generates mock firmware registry data
|
|
func GenerateMockFirmwareList() []registry.GroupedFirmware {
|
|
return []registry.GroupedFirmware{
|
|
{
|
|
Name: "spore-firmware",
|
|
Firmware: []registry.FirmwareRecord{
|
|
{
|
|
Name: "spore-firmware",
|
|
Version: "1.0.0",
|
|
Size: 524288,
|
|
Labels: map[string]string{
|
|
"stable": "true",
|
|
"env": "production",
|
|
},
|
|
Path: "/firmware/spore-firmware/1.0.0",
|
|
},
|
|
{
|
|
Name: "spore-firmware",
|
|
Version: "1.1.0",
|
|
Size: 548864,
|
|
Labels: map[string]string{
|
|
"stable": "true",
|
|
"env": "production",
|
|
},
|
|
Path: "/firmware/spore-firmware/1.1.0",
|
|
},
|
|
{
|
|
Name: "spore-firmware",
|
|
Version: "1.2.0",
|
|
Size: 573440,
|
|
Labels: map[string]string{
|
|
"stable": "false",
|
|
"env": "beta",
|
|
},
|
|
Path: "/firmware/spore-firmware/1.2.0",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "sensor-firmware",
|
|
Firmware: []registry.FirmwareRecord{
|
|
{
|
|
Name: "sensor-firmware",
|
|
Version: "2.0.0",
|
|
Size: 262144,
|
|
Labels: map[string]string{
|
|
"stable": "true",
|
|
"type": "sensor",
|
|
},
|
|
Path: "/firmware/sensor-firmware/2.0.0",
|
|
},
|
|
{
|
|
Name: "sensor-firmware",
|
|
Version: "2.1.0",
|
|
Size: 286720,
|
|
Labels: map[string]string{
|
|
"stable": "true",
|
|
"type": "sensor",
|
|
},
|
|
Path: "/firmware/sensor-firmware/2.1.0",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// GenerateMockFirmwareBinary generates mock firmware binary data
|
|
func GenerateMockFirmwareBinary(size int) []byte {
|
|
// Generate some pseudo-random but deterministic binary data
|
|
data := make([]byte, size)
|
|
for i := range data {
|
|
data[i] = byte(i % 256)
|
|
}
|
|
return data
|
|
}
|
|
|
|
// NodeInfo is an alias to avoid import cycle
|
|
type NodeInfo struct {
|
|
IP string
|
|
Hostname string
|
|
Status string
|
|
Latency int64
|
|
LastSeen time.Time
|
|
Labels map[string]string
|
|
}
|
|
|
|
// ResourceMetrics represents resource usage metrics for a node
|
|
type ResourceMetrics struct {
|
|
Timestamp int64 `json:"timestamp"`
|
|
NodeIP string `json:"node_ip"`
|
|
Hostname string `json:"hostname"`
|
|
CPU CPUMetrics `json:"cpu"`
|
|
Memory MemoryMetrics `json:"memory"`
|
|
Network NetworkMetrics `json:"network"`
|
|
Flash FlashMetrics `json:"flash"`
|
|
Labels map[string]string `json:"labels"`
|
|
}
|
|
|
|
// CPUMetrics represents CPU usage metrics
|
|
type CPUMetrics struct {
|
|
Frequency int `json:"frequency_mhz"`
|
|
UsagePercent float64 `json:"usage_percent"`
|
|
Temperature float64 `json:"temperature_c,omitempty"`
|
|
}
|
|
|
|
// MemoryMetrics represents memory usage metrics
|
|
type MemoryMetrics struct {
|
|
Total int64 `json:"total_bytes"`
|
|
Free int64 `json:"free_bytes"`
|
|
Used int64 `json:"used_bytes"`
|
|
UsagePercent float64 `json:"usage_percent"`
|
|
}
|
|
|
|
// NetworkMetrics represents network usage metrics
|
|
type NetworkMetrics struct {
|
|
BytesSent int64 `json:"bytes_sent"`
|
|
BytesReceived int64 `json:"bytes_received"`
|
|
PacketsSent int64 `json:"packets_sent"`
|
|
PacketsRecv int64 `json:"packets_received"`
|
|
RSSI int `json:"rssi_dbm,omitempty"`
|
|
SignalQuality float64 `json:"signal_quality_percent,omitempty"`
|
|
}
|
|
|
|
// FlashMetrics represents flash storage metrics
|
|
type FlashMetrics struct {
|
|
Total int64 `json:"total_bytes"`
|
|
Used int64 `json:"used_bytes"`
|
|
Free int64 `json:"free_bytes"`
|
|
UsagePercent float64 `json:"usage_percent"`
|
|
}
|
|
|
|
// MonitoringResourcesResponse represents the monitoring resources endpoint response
|
|
type MonitoringResourcesResponse struct {
|
|
Timestamp string `json:"timestamp"`
|
|
Nodes []ResourceMetrics `json:"nodes"`
|
|
Summary ResourceSummary `json:"summary"`
|
|
}
|
|
|
|
// ResourceSummary provides aggregate statistics across all nodes
|
|
type ResourceSummary struct {
|
|
TotalNodes int `json:"total_nodes"`
|
|
AvgCPUUsage float64 `json:"avg_cpu_usage_percent"`
|
|
AvgMemoryUsage float64 `json:"avg_memory_usage_percent"`
|
|
AvgFlashUsage float64 `json:"avg_flash_usage_percent"`
|
|
TotalBytesSent int64 `json:"total_bytes_sent"`
|
|
TotalBytesRecv int64 `json:"total_bytes_received"`
|
|
}
|
|
|
|
// GenerateMockMonitoringResources generates meaningful mock monitoring data for all nodes
|
|
func GenerateMockMonitoringResources(nodes map[string]*NodeInfo) *MonitoringResourcesResponse {
|
|
now := time.Now()
|
|
metrics := make([]ResourceMetrics, 0, len(nodes))
|
|
|
|
var totalCPU, totalMemoryPercent, totalFlash float64
|
|
var totalBytesSent, totalBytesRecv int64
|
|
|
|
for _, node := range nodes {
|
|
// Generate realistic resource usage based on node characteristics
|
|
cpuFreq := 80 + rand.Intn(160)
|
|
cpuUsage := 15.0 + rand.Float64()*45.0 // 15-60% usage
|
|
|
|
// Memory metrics
|
|
nodeMemoryTotal := int64(65536 + rand.Intn(65536)) // 64-128KB
|
|
freeMemory := int64(32768 + rand.Intn(32768)) // 32-64KB free
|
|
usedMemory := nodeMemoryTotal - freeMemory
|
|
memoryUsagePercent := float64(usedMemory) / float64(nodeMemoryTotal) * 100
|
|
|
|
// Flash metrics
|
|
flashTotal := int64(4194304) // 4MB
|
|
flashUsed := int64(1048576 + rand.Intn(2097152)) // 1-3MB used
|
|
flashFree := flashTotal - flashUsed
|
|
flashUsagePercent := float64(flashUsed) / float64(flashTotal) * 100
|
|
|
|
// Network metrics (simulating accumulated traffic)
|
|
bytesSent := int64(1000000 + rand.Intn(5000000)) // 1-6MB
|
|
bytesRecv := int64(2000000 + rand.Intn(8000000)) // 2-10MB
|
|
packetsSent := int64(10000 + rand.Intn(50000))
|
|
packetsRecv := int64(15000 + rand.Intn(75000))
|
|
|
|
// WiFi signal metrics
|
|
rssi := -30 - rand.Intn(60) // -30 to -90 dBm
|
|
signalQuality := float64(100+rssi+90) / 60.0 * 100 // Convert RSSI to quality percentage
|
|
if signalQuality < 0 {
|
|
signalQuality = 0
|
|
} else if signalQuality > 100 {
|
|
signalQuality = 100
|
|
}
|
|
|
|
metric := ResourceMetrics{
|
|
Timestamp: now.Unix(),
|
|
NodeIP: node.IP,
|
|
Hostname: node.Hostname,
|
|
CPU: CPUMetrics{
|
|
Frequency: cpuFreq,
|
|
UsagePercent: cpuUsage,
|
|
Temperature: 45.0 + rand.Float64()*20.0, // 45-65°C
|
|
},
|
|
Memory: MemoryMetrics{
|
|
Total: nodeMemoryTotal,
|
|
Free: freeMemory,
|
|
Used: usedMemory,
|
|
UsagePercent: memoryUsagePercent,
|
|
},
|
|
Network: NetworkMetrics{
|
|
BytesSent: bytesSent,
|
|
BytesReceived: bytesRecv,
|
|
PacketsSent: packetsSent,
|
|
PacketsRecv: packetsRecv,
|
|
RSSI: rssi,
|
|
SignalQuality: signalQuality,
|
|
},
|
|
Flash: FlashMetrics{
|
|
Total: flashTotal,
|
|
Used: flashUsed,
|
|
Free: flashFree,
|
|
UsagePercent: flashUsagePercent,
|
|
},
|
|
Labels: node.Labels,
|
|
}
|
|
|
|
metrics = append(metrics, metric)
|
|
|
|
// Accumulate for summary
|
|
totalCPU += cpuUsage
|
|
totalMemoryPercent += memoryUsagePercent
|
|
totalFlash += flashUsagePercent
|
|
totalBytesSent += bytesSent
|
|
totalBytesRecv += bytesRecv
|
|
}
|
|
|
|
// Calculate averages
|
|
nodeCount := len(nodes)
|
|
var avgCPU, avgMemory, avgFlash float64
|
|
if nodeCount > 0 {
|
|
avgCPU = totalCPU / float64(nodeCount)
|
|
avgMemory = totalMemoryPercent / float64(nodeCount)
|
|
avgFlash = totalFlash / float64(nodeCount)
|
|
}
|
|
|
|
return &MonitoringResourcesResponse{
|
|
Timestamp: now.Format(time.RFC3339),
|
|
Nodes: metrics,
|
|
Summary: ResourceSummary{
|
|
TotalNodes: nodeCount,
|
|
AvgCPUUsage: avgCPU,
|
|
AvgMemoryUsage: avgMemory,
|
|
AvgFlashUsage: avgFlash,
|
|
TotalBytesSent: totalBytesSent,
|
|
TotalBytesRecv: totalBytesRecv,
|
|
},
|
|
}
|
|
}
|
|
|
|
// GenerateMockProxyResponse generates a mock response for proxy calls
|
|
func GenerateMockProxyResponse(method, uri string) map[string]interface{} {
|
|
switch uri {
|
|
case "/api/sensors/read":
|
|
return map[string]interface{}{
|
|
"temperature": 22.5 + rand.Float64()*5,
|
|
"humidity": 45.0 + rand.Float64()*20,
|
|
"pressure": 1013.0 + rand.Float64()*10,
|
|
"timestamp": time.Now().Unix(),
|
|
}
|
|
case "/api/led/control":
|
|
return map[string]interface{}{
|
|
"status": "success",
|
|
"message": "LED state updated",
|
|
"state": "on",
|
|
}
|
|
default:
|
|
return map[string]interface{}{
|
|
"status": "success",
|
|
"message": fmt.Sprintf("Mock response for %s %s", method, uri),
|
|
"data": map[string]interface{}{"mock": true},
|
|
}
|
|
}
|
|
}
|