Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  NodesStore.swift   Sprache: unbekannt

 
Spracherkennung für: .swift vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

import Foundation
import Observation
import OSLog

struct NodeInfo: Identifiable, Codable {
    let nodeId: String
    let displayName: String?
    let platform: String?
    let version: String?
    let coreVersion: String?
    let uiVersion: String?
    let deviceFamily: String?
    let modelIdentifier: String?
    let remoteIp: String?
    let caps: [String]?
    let commands: [String]?
    let permissions: [String: Bool]?
    let paired: Bool?
    let connected: Bool?

    var id: String {
        self.nodeId
    }

    var isConnected: Bool {
        self.connected ?? false
    }

    var isPaired: Bool {
        self.paired ?? false
    }
}

private struct NodeListResponse: Codable {
    let ts: Double?
    let nodes: [NodeInfo]
}

@MainActor
@Observable
final class NodesStore {
    static let shared = NodesStore()

    var nodes: [NodeInfo] = []
    var lastError: String?
    var statusMessage: String?
    var isLoading = false

    private let logger = Logger(subsystem: "ai.openclaw", category: "nodes")
    private var task: Task<Void, Never>?
    private let interval: TimeInterval = 30
    private var startCount = 0

    func start() {
        self.startCount += 1
        guard self.startCount == 1 else { return }
        SimpleTaskSupport.startDetachedLoop(task: &self.task, interval: self.interval) { [weak self] in
            await self?.refresh()
        }
    }

    func stop() {
        guard self.startCount > 0 else { return }
        self.startCount -= 1
        guard self.startCount == 0 else { return }
        self.task?.cancel()
        self.task = nil
    }

    func refresh() async {
        if self.isLoading { return }
        self.statusMessage = nil
        self.isLoading = true
        defer { self.isLoading = false }
        do {
            let data = try await GatewayConnection.shared.requestRaw(method: "node.list", params: nil, timeoutMs: 8000)
            let decoded = try JSONDecoder().decode(NodeListResponse.self, from: data)
            self.nodes = decoded.nodes
            self.lastError = nil
            self.statusMessage = nil
        } catch {
            if Self.isCancelled(error) {
                self.logger.debug("node.list cancelled; keeping last nodes")
                if self.nodes.isEmpty {
                    self.statusMessage = "Refreshing devices…"
                }
                self.lastError = nil
                return
            }
            self.logger.error("node.list failed \(error.localizedDescription, privacy: .public)")
            self.nodes = []
            self.lastError = error.localizedDescription
            self.statusMessage = nil
        }
    }

    private static func isCancelled(_ error: Error) -> Bool {
        if error is CancellationError { return true }
        if let urlError = error as? URLError, urlError.code == .cancelled { return true }
        let nsError = error as NSError
        if nsError.domain == NSURLErrorDomain, nsError.code == NSURLErrorCancelled { return true }
        return false
    }
}

[Dauer der Verarbeitung: 0.22 Sekunden, vorverarbeitet 2026-04-27]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge