diff --git a/Kit/plugins/Remote.swift b/Kit/plugins/Remote.swift index 60c64ce5..c0ed70bc 100644 --- a/Kit/plugins/Remote.swift +++ b/Kit/plugins/Remote.swift @@ -12,6 +12,10 @@ import Foundation import Cocoa +public protocol RemoteType { + func remote() -> Data? +} + public class Remote { public static let shared = Remote() static public var host = URL(string: "http://localhost:8008")! // https://api.system-stats.com http://localhost:8008 @@ -83,9 +87,9 @@ public class Remote { NotificationCenter.default.post(name: .remoteState, object: nil, userInfo: ["auth": self.isAuthorized]) } - public func send(key: String, value: Codable) { - guard self.monitoring && self.isAuthorized, let blobData = try? JSONEncoder().encode(value) else { return } - self.ws.send(key: key, data: blobData) + public func send(key: String, value: Any) { + guard self.monitoring && self.isAuthorized, let v = value as? RemoteType, let data = v.remote() else { return } + self.ws.send(key: key, data: data) } @objc private func successLogin() { @@ -462,9 +466,6 @@ class WebSocketManager: NSObject { } public func send(key: String, data: Data) { - if key != "details" && !key.contains("CPU@") && !key.contains("GPU@") && !key.contains("RAM@") && !key.contains("Network@") && !key.contains("Sensors@") { - return - } if !self.isConnected { return } let message = WebSocketMessage(name: key, data: data) guard let messageData = try? JSONEncoder().encode(message) else { return } diff --git a/Modules/CPU/main.swift b/Modules/CPU/main.swift index 13afb2e9..065f58d3 100644 --- a/Modules/CPU/main.swift +++ b/Modules/CPU/main.swift @@ -10,7 +10,7 @@ import Cocoa import Kit import WidgetKit -public struct CPU_Load: Codable { +public struct CPU_Load: Codable, RemoteType { var totalUsage: Double = 0 var usagePerCore: [Double] = [] var usageECores: Double? = nil @@ -19,6 +19,26 @@ public struct CPU_Load: Codable { var systemLoad: Double = 0 var userLoad: Double = 0 var idleLoad: Double = 0 + + public func remote() -> Data? { + var string = "1,1,\(self.totalUsage),\(self.usagePerCore.count)," + for c in self.usagePerCore { + string += "\(c)," + } + string += "$" + return string.data(using: .utf8) + } +} + +public struct CPU_Frequency: Codable, RemoteType { + var value: Double = 0 + var eCore: Double = 0 + var pCore: Double = 0 + + public func remote() -> Data? { + let string = "1,1,\(self.value)$" + return string.data(using: .utf8) + } } public struct CPU_Limit: Codable { diff --git a/Modules/CPU/popup.swift b/Modules/CPU/popup.swift index 8aa22517..0a65018f 100644 --- a/Modules/CPU/popup.swift +++ b/Modules/CPU/popup.swift @@ -421,9 +421,8 @@ internal class Popup: PopupWrapper { }) } - public func frequencyCallback(_ value: [Double]?) { + public func frequencyCallback(_ value: CPU_Frequency?) { guard let value else { return } - guard !value.filter({ $0 != 0 }).isEmpty else { return } DispatchQueue.main.async(execute: { if !self.initializedFrequency { @@ -436,37 +435,19 @@ internal class Popup: PopupWrapper { } if (self.window?.isVisible ?? false) || !self.initializedFrequency { - if value.count == 1 { - let freq = value.first ?? 0 - if freq > self.maxFreq { - self.maxFreq = freq - } - self.coresFreqField?.stringValue = "\(Int(freq)) MHz" - if let circle = self.frequencyCircle { - circle.setValue((100*freq)/self.maxFreq) - circle.setText("\((freq/1000).rounded(toPlaces: 2))") - circle.toolTip = "\(localizedString("CPU frequency")): \(Int(freq)) MHz - \(((100*freq)/self.maxFreq).rounded(toPlaces: 2))%" - } - } else if value.count == 2 { - let e = value.first ?? 0 - let p = value.last ?? 0 - self.eCoresFreqField?.stringValue = "\(Int(e)) MHz" - self.pCoresFreqField?.stringValue = "\(Int(p)) MHz" - - if let eCoreCount = SystemKit.shared.device.info.cpu?.eCores, let pCoreCount = SystemKit.shared.device.info.cpu?.pCores { - let freq = ((e * Double(eCoreCount)) + (p * Double(pCoreCount))) / Double(eCoreCount + pCoreCount) - if freq > self.maxFreq { - self.maxFreq = freq - } - self.coresFreqField?.stringValue = "\(Int(freq)) MHz" - if let circle = self.frequencyCircle { - circle.setValue((100*freq)/self.maxFreq) - circle.setText("\((freq/1000).rounded(toPlaces: 2))") - circle.toolTip = "\(localizedString("CPU frequency")): \(Int(freq)) MHz - \(((100*freq)/self.maxFreq).rounded(toPlaces: 2))%" - } - } + if value.value > self.maxFreq { + self.maxFreq = value.value } + self.coresFreqField?.stringValue = "\(Int(value.value)) MHz" + if let circle = self.frequencyCircle { + circle.setValue((100*value.value)/self.maxFreq) + circle.setText("\((value.value/1000).rounded(toPlaces: 2))") + circle.toolTip = "\(localizedString("CPU frequency")): \(Int(value.value)) MHz - \(((100*value.value)/self.maxFreq).rounded(toPlaces: 2))%" + } + self.eCoresFreqField?.stringValue = "\(Int(value.eCore)) MHz" + self.pCoresFreqField?.stringValue = "\(Int(value.pCore)) MHz" + self.initializedFrequency = true } }) diff --git a/Modules/CPU/readers.swift b/Modules/CPU/readers.swift index 0385e563..8851b571 100644 --- a/Modules/CPU/readers.swift +++ b/Modules/CPU/readers.swift @@ -292,9 +292,11 @@ public class TemperatureReader: Reader { } // inspired by https://github.com/shank03/StatsBar/blob/e175aa71c914ce882ce2e90163f3eb18262a8e25/StatsBar/Service/IOReport.swift -public class FrequencyReader: Reader<[Double]> { +public class FrequencyReader: Reader { private var eCoreFreqs: [Int32] = [] private var pCoreFreqs: [Int32] = [] + private var eCoreCount: Double = 0 + private var pCoreCount: Double = 0 private var channels: CFMutableDictionary? = nil private var subscription: IOReportSubscriptionRef? = nil @@ -314,6 +316,8 @@ public class FrequencyReader: Reader<[Double]> { public override func setup() { self.eCoreFreqs = SystemKit.shared.device.info.cpu?.eCoreFrequencies ?? [] self.pCoreFreqs = SystemKit.shared.device.info.cpu?.pCoreFrequencies ?? [] + self.eCoreCount = Double(SystemKit.shared.device.info.cpu?.eCores ?? 0) + self.pCoreCount = Double(SystemKit.shared.device.info.cpu?.pCores ?? 0) self.channels = self.getChannels() var dict: Unmanaged? self.subscription = IOReportCreateSubscription(nil, self.channels, &dict, 0, nil) @@ -352,8 +356,9 @@ public class FrequencyReader: Reader<[Double]> { let eFreq: Double = eCores.reduce(0, { $0 + $1 }) / Double(self.measurementCount) let pFreq: Double = pCores.reduce(0, { $0 + $1 }) / Double(self.measurementCount) + let value: Double = ((eFreq * self.eCoreCount) + (pFreq * self.pCoreCount)) / (self.eCoreCount + self.pCoreCount) - self.callback([eFreq, pFreq]) + self.callback(CPU_Frequency(value: value, eCore: eFreq, pCore: pFreq)) self.isReading = false } } diff --git a/Modules/Disk/main.swift b/Modules/Disk/main.swift index 29428a62..ca9cabc3 100644 --- a/Modules/Disk/main.swift +++ b/Modules/Disk/main.swift @@ -64,9 +64,13 @@ public struct drive: Codable { public var popupState: Bool { Store.shared.bool(key: "Disk_\(self.uuid)_popup", defaultValue: true) } + + public func remote() -> String { + return "\(self.uuid),\(self.size),\(self.size-self.free),\(self.free),\(self.activity.read),\(self.activity.write)" + } } -public class Disks: Codable { +public class Disks: Codable, RemoteType { private var queue: DispatchQueue = DispatchQueue(label: "eu.exelban.Stats.Disk.SynchronizedArray") private var _array: [drive] = [] public var array: [drive] { @@ -156,6 +160,18 @@ public class Disks: Codable { func updateSMARTData(_ idx: Int, smart: smart_t?) { self.array[idx].smart = smart } + + public func remote() -> Data? { + var string = "\(self.array.count)," + for (i, v) in self.array.enumerated() { + string += v.remote() + if i != self.array.count { + string += "," + } + } + string += "$" + return string.data(using: .utf8) + } } public struct Disk_process: Process_p, Codable { diff --git a/Modules/GPU/main.swift b/Modules/GPU/main.swift index 9d781b17..b6d9fd6c 100644 --- a/Modules/GPU/main.swift +++ b/Modules/GPU/main.swift @@ -52,9 +52,17 @@ public struct GPU_Info: Codable { self.renderUtilization = render self.tilerUtilization = tiler } + + public func remote() -> String { + var id = self.id + if self.id.isEmpty { + id = "0" + } + return "\(id),1,\(self.utilization ?? 0),\(self.renderUtilization ?? 0),\(self.tilerUtilization ?? 0),," + } } -public class GPUs: Codable { +public class GPUs: Codable, RemoteType { private var queue: DispatchQueue = DispatchQueue(label: "eu.exelban.Stats.GPU.SynchronizedArray") private var _list: [GPU_Info] = [] @@ -82,6 +90,18 @@ public class GPUs: Codable { internal func active() -> [GPU_Info] { return self.list.filter{ $0.state && $0.utilization != nil }.sorted{ $0.utilization ?? 0 > $1.utilization ?? 0 } } + + public func remote() -> Data? { + var string = "\(self.list.count)," + for (i, v) in self.list.enumerated() { + string += v.remote() + if i != self.list.count { + string += "," + } + } + string += "$" + return string.data(using: .utf8) + } } public class GPU: Module { diff --git a/Modules/Net/main.swift b/Modules/Net/main.swift index cacb6ef6..67ae4994 100644 --- a/Modules/Net/main.swift +++ b/Modules/Net/main.swift @@ -68,7 +68,7 @@ public struct Bandwidth: Codable { var download: Int64 = 0 } -public struct Network_Usage: Codable { +public struct Network_Usage: Codable, RemoteType { var bandwidth: Bandwidth = Bandwidth() var total: Bandwidth = Bandwidth() @@ -92,6 +92,12 @@ public struct Network_Usage: Codable { self.wifiDetails.reset() } + + public func remote() -> Data? { + let addr = "\(self.laddr.v4 ?? ""),\(self.laddr.v6 ?? ""),\(self.raddr.v4 ?? ""),\(self.raddr.v6 ?? "")" + let string = "1,\(self.interface?.BSDName ?? ""),1,\(self.bandwidth.download),\(self.bandwidth.upload),\(addr)$" + return string.data(using: .utf8) + } } public struct Network_Connectivity: Codable { diff --git a/Modules/RAM/main.swift b/Modules/RAM/main.swift index e2b96d0d..f4b8d5b2 100644 --- a/Modules/RAM/main.swift +++ b/Modules/RAM/main.swift @@ -13,7 +13,7 @@ import Cocoa import Kit import WidgetKit -public struct RAM_Usage: Codable { +public struct RAM_Usage: Codable, RemoteType { var total: Double var used: Double var free: Double @@ -35,6 +35,11 @@ public struct RAM_Usage: Codable { public var usage: Double { get { Double((self.total - self.free) / self.total) } } + + public func remote() -> Data? { + let string = "\(self.total),\(self.used),\(self.pressure.level),\(self.swap.used)$" + return string.data(using: .utf8) + } } public struct Swap: Codable {