mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-14 00:04:15 +09:00
- update Temperature module (add all possible sensors to show);
- delete SystemKit; - update Disk module to select the disk to show; - fix interval saving in CPU, RAM and Disk modules;
This commit is contained in:
@@ -54,7 +54,7 @@
|
||||
9AA28DC1243774ED00D2B196 /* Temperature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AA28DC0243774ED00D2B196 /* Temperature.swift */; };
|
||||
9AA28DC32437752D00D2B196 /* TemperatureMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AA28DC22437752D00D2B196 /* TemperatureMenu.swift */; };
|
||||
9AA28DC52437762C00D2B196 /* TemperatureReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AA28DC42437762C00D2B196 /* TemperatureReader.swift */; };
|
||||
9AA28DCF2437884200D2B196 /* SystemKit.c in Sources */ = {isa = PBXBuildFile; fileRef = 9AA28DCE2437884200D2B196 /* SystemKit.c */; };
|
||||
9AA28DCF2437884200D2B196 /* SMC.c in Sources */ = {isa = PBXBuildFile; fileRef = 9AA28DCE2437884200D2B196 /* SMC.c */; };
|
||||
9AA28DD1243799E500D2B196 /* TemperatureWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AA28DD0243799E500D2B196 /* TemperatureWidget.swift */; };
|
||||
9AF0F31B22DA924000026AE6 /* LineChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AF0F31A22DA924000026AE6 /* LineChart.swift */; };
|
||||
9AF0F31D22DA925000026AE6 /* LineChartWithValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AF0F31C22DA925000026AE6 /* LineChartWithValue.swift */; };
|
||||
@@ -148,8 +148,8 @@
|
||||
9AA28DC22437752D00D2B196 /* TemperatureMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemperatureMenu.swift; sourceTree = "<group>"; };
|
||||
9AA28DC42437762C00D2B196 /* TemperatureReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemperatureReader.swift; sourceTree = "<group>"; };
|
||||
9AA28DC9243780C500D2B196 /* Stats.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Stats.h; sourceTree = "<group>"; };
|
||||
9AA28DCD2437884200D2B196 /* SystemKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SystemKit.h; sourceTree = "<group>"; };
|
||||
9AA28DCE2437884200D2B196 /* SystemKit.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SystemKit.c; sourceTree = "<group>"; };
|
||||
9AA28DCD2437884200D2B196 /* SMC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SMC.h; sourceTree = "<group>"; };
|
||||
9AA28DCE2437884200D2B196 /* SMC.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SMC.c; sourceTree = "<group>"; };
|
||||
9AA28DD0243799E500D2B196 /* TemperatureWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemperatureWidget.swift; sourceTree = "<group>"; };
|
||||
9AF0F31A22DA924000026AE6 /* LineChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineChart.swift; sourceTree = "<group>"; };
|
||||
9AF0F31C22DA925000026AE6 /* LineChartWithValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineChartWithValue.swift; sourceTree = "<group>"; };
|
||||
@@ -304,13 +304,13 @@
|
||||
9A5B1CBD229E78D2008B9D3C /* libs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9AA28DCD2437884200D2B196 /* SMC.h */,
|
||||
9AA28DCE2437884200D2B196 /* SMC.c */,
|
||||
9A5B1CC4229E7B40008B9D3C /* Extensions.swift */,
|
||||
9A426DB722C2B5EE00C064C4 /* MacAppUpdater.swift */,
|
||||
9A59AE55231EE02F007989D6 /* ChartMarker.swift */,
|
||||
9A2D15CF23C77BA300C4C417 /* Repeater.swift */,
|
||||
9AA28DC9243780C500D2B196 /* Stats.h */,
|
||||
9AA28DCD2437884200D2B196 /* SystemKit.h */,
|
||||
9AA28DCE2437884200D2B196 /* SystemKit.c */,
|
||||
);
|
||||
path = libs;
|
||||
sourceTree = "<group>";
|
||||
@@ -533,7 +533,7 @@
|
||||
9AA28DD1243799E500D2B196 /* TemperatureWidget.swift in Sources */,
|
||||
9A2D15FA23CE3BE600C4C417 /* Battery.swift in Sources */,
|
||||
9A54EF67232AB81800F7DC20 /* BatteryPercentageWidget.swift in Sources */,
|
||||
9AA28DCF2437884200D2B196 /* SystemKit.c in Sources */,
|
||||
9AA28DCF2437884200D2B196 /* SMC.c in Sources */,
|
||||
9AA28DC52437762C00D2B196 /* TemperatureReader.swift in Sources */,
|
||||
9A57A18522A1D26D0033E318 /* MenuBar.swift in Sources */,
|
||||
9A2D15D923CD036400C4C417 /* CPUMenu.swift in Sources */,
|
||||
|
||||
@@ -11,7 +11,6 @@ import IOKit.ps
|
||||
|
||||
class Battery: Module {
|
||||
public var name: String = "Battery"
|
||||
public var updateInterval: Double = 15
|
||||
|
||||
public var enabled: Bool = true
|
||||
public var available: Bool {
|
||||
@@ -63,7 +62,9 @@ class Battery: Module {
|
||||
}
|
||||
|
||||
public func stop() {
|
||||
(readers[0] as! BatteryReader).stop()
|
||||
if readers.count > 0 {
|
||||
(readers[0] as! BatteryReader).stop()
|
||||
}
|
||||
}
|
||||
|
||||
public func restart() {
|
||||
|
||||
@@ -36,6 +36,7 @@ class CPU: Module {
|
||||
if !self.available { return }
|
||||
|
||||
self.enabled = defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true
|
||||
self.updateInterval = defaults.object(forKey: "\(name)_interval") != nil ? defaults.double(forKey: "\(name)_interval") : self.updateInterval
|
||||
self.widget.type = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Mini
|
||||
|
||||
self.initWidget()
|
||||
|
||||
@@ -55,6 +55,7 @@ class CPUProcessReader: Reader {
|
||||
try task.run()
|
||||
} catch let error {
|
||||
print(error)
|
||||
return
|
||||
}
|
||||
|
||||
let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
|
||||
|
||||
@@ -10,7 +10,7 @@ import Cocoa
|
||||
|
||||
class Disk: Module {
|
||||
public var name: String = "SSD"
|
||||
public var updateInterval: Double = 15
|
||||
public var updateInterval: Double = 5
|
||||
|
||||
public var enabled: Bool = true
|
||||
public var available: Bool = true
|
||||
@@ -24,12 +24,16 @@ class Disk: Module {
|
||||
|
||||
internal let defaults = UserDefaults.standard
|
||||
internal var submenu: NSMenu = NSMenu()
|
||||
internal var selectedDisk: String = ""
|
||||
internal var disks: disksList = disksList()
|
||||
|
||||
init() {
|
||||
if !self.available { return }
|
||||
|
||||
self.enabled = defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true
|
||||
self.updateInterval = defaults.object(forKey: "\(name)_interval") != nil ? defaults.double(forKey: "\(name)_interval") : self.updateInterval
|
||||
self.widget.type = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Mini
|
||||
self.selectedDisk = defaults.object(forKey: "\(name)_disk") != nil ? defaults.string(forKey: "\(name)_disk")! : self.selectedDisk
|
||||
|
||||
self.initWidget()
|
||||
self.initMenu()
|
||||
@@ -60,9 +64,26 @@ class Disk: Module {
|
||||
self.start()
|
||||
}
|
||||
|
||||
private func usageUpdater(value: Double) {
|
||||
private func usageUpdater(disks: disksList) {
|
||||
if self.disks.list.count != disks.list.count && disks.list.count != 0 {
|
||||
self.disks = disks
|
||||
self.initMenu()
|
||||
}
|
||||
|
||||
if self.widget.view is Widget {
|
||||
(self.widget.view as! Widget).setValue(data: [value])
|
||||
var d: diskInfo? = disks.getDiskByBSDName(self.selectedDisk)
|
||||
if d == nil {
|
||||
d = disks.getRootDisk()
|
||||
}
|
||||
|
||||
if d != nil {
|
||||
let total = d!.totalSize
|
||||
let free = d!.freeSize
|
||||
let usedSpace = total - free
|
||||
let percentage = Double(usedSpace) / Double(total)
|
||||
|
||||
(self.widget.view as! Widget).setValue(data: [percentage])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,15 +8,67 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
struct diskInfo {
|
||||
var ID: String = "";
|
||||
|
||||
var name: String = "";
|
||||
var model: String = "";
|
||||
var path: URL?;
|
||||
var connection: String = "";
|
||||
var fileSystem: String = "";
|
||||
|
||||
var totalSize: Int64 = 0;
|
||||
var freeSize: Int64 = 0;
|
||||
|
||||
var mediaBSDName: String = "";
|
||||
var root: Bool = false;
|
||||
}
|
||||
|
||||
struct disksList {
|
||||
var list: [diskInfo] = []
|
||||
|
||||
func getDiskByBSDName(_ name: String) -> diskInfo? {
|
||||
let idx = self.list.firstIndex { $0.mediaBSDName == name }
|
||||
|
||||
if idx == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.list[idx!]
|
||||
}
|
||||
|
||||
func getDiskByName(_ name: String) -> diskInfo? {
|
||||
let idx = self.list.firstIndex { $0.name == name }
|
||||
|
||||
if idx == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.list[idx!]
|
||||
}
|
||||
|
||||
func getRootDisk() -> diskInfo? {
|
||||
let idx = self.list.firstIndex { $0.root }
|
||||
|
||||
if idx == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.list[idx!]
|
||||
}
|
||||
}
|
||||
|
||||
class DiskCapacityReader: Reader {
|
||||
public var name: String = "Capacity"
|
||||
public var enabled: Bool = true
|
||||
public var available: Bool = true
|
||||
public var optional: Bool = false
|
||||
public var initialized: Bool = false
|
||||
public var callback: (Double) -> Void = {_ in}
|
||||
public var callback: (disksList) -> Void = {_ in}
|
||||
|
||||
init(_ updater: @escaping (Double) -> Void) {
|
||||
private var disks: disksList = disksList()
|
||||
|
||||
init(_ updater: @escaping (disksList) -> Void) {
|
||||
self.callback = updater
|
||||
|
||||
if self.available {
|
||||
@@ -30,36 +82,91 @@ class DiskCapacityReader: Reader {
|
||||
if !self.enabled && self.initialized { return }
|
||||
self.initialized = true
|
||||
|
||||
let total = totalDiskSpaceInBytes()
|
||||
let free = freeDiskSpaceInBytes()
|
||||
let usedSpace = total - free
|
||||
let keys: [URLResourceKey] = [.volumeNameKey]
|
||||
let paths = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: keys)!
|
||||
if let session = DASessionCreate(kCFAllocatorDefault) {
|
||||
for url in paths {
|
||||
if url.pathComponents.count == 1 || (url.pathComponents.count > 1 && url.pathComponents[1] == "Volumes") {
|
||||
if let disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, url as CFURL) {
|
||||
let BSDName: String = String(cString: DADiskGetBSDName(disk)!)
|
||||
|
||||
if let _: diskInfo = self.disks.getDiskByBSDName(BSDName) {
|
||||
let idx = self.disks.list.firstIndex { $0.mediaBSDName == BSDName }
|
||||
self.disks.list[idx!].freeSize = freeDiskSpaceInBytes(self.disks.list[idx!].path!.absoluteString)
|
||||
continue
|
||||
}
|
||||
|
||||
self.disks.list.append(getDisk(disk))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async(execute: {
|
||||
self.callback((Double(usedSpace) / Double(total)))
|
||||
self.callback(self.disks)
|
||||
})
|
||||
}
|
||||
|
||||
private func totalDiskSpaceInBytes() -> Int64 {
|
||||
do {
|
||||
let systemAttributes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String)
|
||||
let space = (systemAttributes[FileAttributeKey.systemSize] as? NSNumber)?.int64Value
|
||||
return space!
|
||||
} catch {
|
||||
return 0
|
||||
}
|
||||
public func toggleEnable(_ value: Bool) {
|
||||
self.enabled = value
|
||||
}
|
||||
|
||||
private func freeDiskSpaceInBytes() -> Int64 {
|
||||
private func getDisk(_ disk: DADisk) -> diskInfo {
|
||||
var d: diskInfo = diskInfo()
|
||||
|
||||
if let bsdName = DADiskGetBSDName(disk) {
|
||||
d.mediaBSDName = String(cString: bsdName)
|
||||
}
|
||||
|
||||
if let diskDescription = DADiskCopyDescription(disk) {
|
||||
if let dict = diskDescription as? [String: AnyObject] {
|
||||
if let mediaName = dict[kDADiskDescriptionMediaNameKey as String] {
|
||||
d.name = mediaName as! String
|
||||
}
|
||||
if let mediaSize = dict[kDADiskDescriptionMediaSizeKey as String] {
|
||||
d.totalSize = Int64(truncating: mediaSize as! NSNumber)
|
||||
}
|
||||
if let deviceModel = dict[kDADiskDescriptionDeviceModelKey as String] {
|
||||
d.model = (deviceModel as! String).trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
if let deviceProtocol = dict[kDADiskDescriptionDeviceProtocolKey as String] {
|
||||
d.connection = deviceProtocol as! String
|
||||
}
|
||||
if let volumePath = dict[kDADiskDescriptionVolumePathKey as String] {
|
||||
let url = volumePath as? NSURL
|
||||
if url != nil {
|
||||
if url!.pathComponents!.count > 1 && url!.pathComponents![1] == "Volumes" {
|
||||
let lastPath: String = (url?.lastPathComponent)!
|
||||
if lastPath != "" {
|
||||
d.name = lastPath
|
||||
d.path = URL(string: "/Volumes/\(lastPath)")
|
||||
}
|
||||
} else if url!.pathComponents!.count == 1 {
|
||||
d.path = URL(string: "/")
|
||||
d.root = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if let volumeKind = dict[kDADiskDescriptionVolumeKindKey as String] {
|
||||
d.fileSystem = volumeKind as! String
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if d.path != nil {
|
||||
d.freeSize = freeDiskSpaceInBytes(d.path!.absoluteString)
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
private func freeDiskSpaceInBytes(_ path: String) -> Int64 {
|
||||
do {
|
||||
let systemAttributes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String)
|
||||
let systemAttributes = try FileManager.default.attributesOfFileSystem(forPath: path)
|
||||
let freeSpace = (systemAttributes[FileAttributeKey.systemFreeSize] as? NSNumber)?.int64Value
|
||||
return freeSpace!
|
||||
} catch {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
public func toggleEnable(_ value: Bool) {
|
||||
self.enabled = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,18 @@ extension Disk {
|
||||
}
|
||||
menu.target = self
|
||||
|
||||
self.disks.list.forEach { (d: diskInfo) in
|
||||
let disk = NSMenuItem(title: d.name, action: #selector(toggleDisk), keyEquivalent: "")
|
||||
if self.selectedDisk == "" && d.root {
|
||||
disk.state = NSControl.StateValue.on
|
||||
} else {
|
||||
disk.state = self.selectedDisk == d.mediaBSDName ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
}
|
||||
disk.target = self
|
||||
|
||||
submenu.addItem(disk)
|
||||
}
|
||||
|
||||
let mini = NSMenuItem(title: "Mini", action: #selector(toggleWidget), keyEquivalent: "")
|
||||
mini.state = self.widget.type == Widgets.Mini ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
mini.target = self
|
||||
@@ -28,6 +40,8 @@ extension Disk {
|
||||
barChart.state = self.widget.type == Widgets.BarChart ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
barChart.target = self
|
||||
|
||||
submenu.addItem(NSMenuItem.separator())
|
||||
|
||||
submenu.addItem(mini)
|
||||
submenu.addItem(barChart)
|
||||
|
||||
@@ -159,4 +173,27 @@ extension Disk {
|
||||
self.defaults.set(interval, forKey: "\(name)_interval")
|
||||
self.task?.reset(.seconds(interval), restart: self.task!.state.isRunning)
|
||||
}
|
||||
|
||||
@objc func toggleDisk(_ sender: NSMenuItem) {
|
||||
let name: String = sender.title
|
||||
let d: diskInfo? = self.disks.getDiskByName(name)
|
||||
if d == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if d!.mediaBSDName == self.selectedDisk {
|
||||
return
|
||||
}
|
||||
|
||||
for item in self.submenu.items {
|
||||
if self.disks.getDiskByName(item.title) != nil {
|
||||
item.state = NSControl.StateValue.off
|
||||
}
|
||||
}
|
||||
|
||||
sender.state = NSControl.StateValue.on
|
||||
self.selectedDisk = d!.mediaBSDName
|
||||
self.defaults.set(d!.mediaBSDName, forKey: "\(name)_disk")
|
||||
menuBar!.reload(name: self.name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import Charts
|
||||
|
||||
protocol Module: class {
|
||||
var name: String { get } // module name
|
||||
var updateInterval: Double { get } // module update interval
|
||||
|
||||
var enabled: Bool { get } // determine if module is enabled or disabled
|
||||
var available: Bool { get } // determine if module is available on this PC
|
||||
|
||||
@@ -36,6 +36,7 @@ class RAM: Module {
|
||||
if !self.available { return }
|
||||
|
||||
self.enabled = defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true
|
||||
self.updateInterval = defaults.object(forKey: "\(name)_interval") != nil ? defaults.double(forKey: "\(name)_interval") : self.updateInterval
|
||||
self.widget.type = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Mini
|
||||
|
||||
readers.append(RAMUsageReader(self.usageUpdater))
|
||||
|
||||
@@ -44,6 +44,7 @@ class RAMProcessReader: Reader {
|
||||
try task.run()
|
||||
} catch let error {
|
||||
print(error)
|
||||
return
|
||||
}
|
||||
|
||||
let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
|
||||
|
||||
@@ -25,17 +25,19 @@ class Temperature: Module {
|
||||
internal let defaults = UserDefaults.standard
|
||||
internal var submenu: NSMenu = NSMenu()
|
||||
|
||||
internal var cpu: String = SMC_TEMP_CPU_0_PROXIMITY
|
||||
internal var gpu: String = SMC_TEMP_GPU_0_PROXIMITY
|
||||
internal var value_1: String = "cpu_1_diode"
|
||||
internal var value_2: String = "gpu_diode"
|
||||
internal var once: Int = 0
|
||||
|
||||
init() {
|
||||
if !self.available { return }
|
||||
|
||||
self.enabled = defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true
|
||||
self.widget.type = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Temperature
|
||||
self.cpu = (defaults.object(forKey: "\(name)_cpu") != nil ? defaults.string(forKey: "\(name)_cpu") : cpu)!
|
||||
self.gpu = (defaults.object(forKey: "\(name)_gpu") != nil ? defaults.string(forKey: "\(name)_gpu") : gpu)!
|
||||
self.value_1 = (defaults.object(forKey: "\(name)_value_1") != nil ? defaults.string(forKey: "\(name)_value_1")! : value_1)
|
||||
self.value_2 = (defaults.object(forKey: "\(name)_value_2") != nil ? defaults.string(forKey: "\(name)_value_2")! : value_2)
|
||||
|
||||
self.initGroups()
|
||||
self.initWidget()
|
||||
self.initMenu()
|
||||
|
||||
@@ -65,13 +67,23 @@ class Temperature: Module {
|
||||
self.start()
|
||||
}
|
||||
|
||||
private func usageUpdater(value: TemperatureValue) {
|
||||
private func usageUpdater(value: Temperatures) {
|
||||
if self.widget.view is Widget {
|
||||
DispatchQueue.main.async(execute: {
|
||||
let cpu: Double = self.cpu == SMC_TEMP_CPU_0_DIE ? value.CPUDie : value.CPUProximity
|
||||
let gpu: Double = self.gpu == SMC_TEMP_GPU_0_DIODE ? value.GPUDie : value.GPUProximity
|
||||
var value_1: Double = 0
|
||||
var value_2: Double = 0
|
||||
|
||||
(self.widget.view as! Widget).setValue(data: [cpu, gpu])
|
||||
let v1 = value.asDictionary.first { $0.key == self.value_1 }
|
||||
let v2 = value.asDictionary.first { $0.key == self.value_2 }
|
||||
|
||||
if v1 != nil {
|
||||
value_1 = v1!.value as! Double
|
||||
}
|
||||
if v2 != nil {
|
||||
value_2 = v2!.value as! Double
|
||||
}
|
||||
|
||||
(self.widget.view as! Widget).setValue(data: [value_1, value_2])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,86 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
struct temperatureMenu {
|
||||
let name: String
|
||||
let originalName: String
|
||||
}
|
||||
|
||||
struct temperatureGroup {
|
||||
let name: String
|
||||
var value: String
|
||||
var menus: [temperatureMenu]
|
||||
|
||||
mutating func addMenu(menu: temperatureMenu) {
|
||||
self.menus.append(menu)
|
||||
}
|
||||
|
||||
func findBy(name: String) -> String {
|
||||
let menu = self.menus.first{ $0.name == name }
|
||||
if menu != nil {
|
||||
return menu!.originalName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
struct temperatureGroupsStruct {
|
||||
var list: [Int : temperatureGroup]
|
||||
|
||||
mutating func addMenuToGroup(group: String, menu: temperatureMenu) {
|
||||
let index = self.list.firstIndex{ $0.value.value == group}
|
||||
if index != nil {
|
||||
let (k, _) = self.list[index!]
|
||||
self.list[k]!.menus.append(menu)
|
||||
}
|
||||
}
|
||||
|
||||
func getOriginalNameOfSensor(name: String) -> String {
|
||||
var originalName: String = ""
|
||||
|
||||
self.list.forEach{ (key: Int, value: temperatureGroup) in
|
||||
if value.findBy(name: name) != "" {
|
||||
originalName = value.findBy(name: name)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return originalName
|
||||
}
|
||||
}
|
||||
|
||||
var temperatureGroups: temperatureGroupsStruct = temperatureGroupsStruct(list: [
|
||||
0: temperatureGroup(name: "CPU", value: "cpu", menus: []),
|
||||
1: temperatureGroup(name: "GPU", value: "gpu", menus: []),
|
||||
2: temperatureGroup(name: "Memory", value: "mem", menus: []),
|
||||
3: temperatureGroup(name: "Termal zones", value: "termal", menus: []),
|
||||
4: temperatureGroup(name: "Sensors", value: "sensor", menus: []),
|
||||
5: temperatureGroup(name: "PCI", value: "pci", menus: []),
|
||||
6: temperatureGroup(name: "Northbridge", value: "northbridge", menus: []),
|
||||
7: temperatureGroup(name: "HDD", value: "hdd", menus: []),
|
||||
8: temperatureGroup(name: "Thunderbolt", value: "thunderbolt", menus: []),
|
||||
])
|
||||
|
||||
extension Temperature {
|
||||
internal func initGroups() {
|
||||
var temperatures: Temperatures = Temperatures()
|
||||
GetTemperatures(&temperatures)
|
||||
|
||||
temperatures.asDictionary.forEach { (arg0) in
|
||||
let (key, value) = arg0
|
||||
if value as! Double != 0 {
|
||||
let group: String = String(key.split(separator: "_")[0])
|
||||
|
||||
var name = key.replacingOccurrences(of: "_", with: " ")
|
||||
if group == "sensor" || group == "termal" {
|
||||
name = name.replacingOccurrences(of: "\(group) ", with: "")
|
||||
}
|
||||
|
||||
temperatureGroups.addMenuToGroup(group: group, menu: temperatureMenu(name: name.toUpperCase(), originalName: key))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func initMenu() {
|
||||
menu = NSMenuItem(title: name, action: #selector(toggle), keyEquivalent: "")
|
||||
submenu = NSMenu()
|
||||
@@ -20,28 +99,44 @@ extension Temperature {
|
||||
}
|
||||
menu.target = self
|
||||
|
||||
let cpuDie: NSMenuItem = NSMenuItem(title: "CPU Die", action: #selector(toggleCPU), keyEquivalent: "")
|
||||
cpuDie.state = self.cpu == SMC_TEMP_CPU_0_DIE ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
cpuDie.target = self
|
||||
let sensor_1: NSMenuItem = NSMenuItem(title: "Sensor #1", action: nil, keyEquivalent: "")
|
||||
sensor_1.target = self
|
||||
sensor_1.submenu = NSMenu()
|
||||
|
||||
let cpuProximity: NSMenuItem = NSMenuItem(title: "CPU Proximity", action: #selector(toggleCPU), keyEquivalent: "")
|
||||
cpuProximity.state = self.cpu == SMC_TEMP_CPU_0_PROXIMITY ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
cpuProximity.target = self
|
||||
let sensor_2: NSMenuItem = NSMenuItem(title: "Sensor #2", action: nil, keyEquivalent: "")
|
||||
sensor_2.target = self
|
||||
sensor_2.submenu = NSMenu()
|
||||
|
||||
let gpuDie: NSMenuItem = NSMenuItem(title: "GPU Die", action: #selector(toggleGPU), keyEquivalent: "")
|
||||
gpuDie.state = self.gpu == SMC_TEMP_GPU_0_DIODE ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
gpuDie.target = self
|
||||
|
||||
let gpuProximity: NSMenuItem = NSMenuItem(title: "GPU Proximity", action: #selector(toggleGPU), keyEquivalent: "")
|
||||
gpuProximity.state = self.gpu == SMC_TEMP_GPU_0_PROXIMITY ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
gpuProximity.target = self
|
||||
|
||||
submenu.addItem(cpuProximity)
|
||||
submenu.addItem(cpuDie)
|
||||
submenu.addItem(NSMenuItem.separator())
|
||||
submenu.addItem(gpuProximity)
|
||||
submenu.addItem(gpuDie)
|
||||
for i in 0...temperatureGroups.list.count-1 {
|
||||
let group = temperatureGroups.list[i]!
|
||||
|
||||
if group.menus.count != 0 {
|
||||
sensor_1.submenu!.addItem(NSMenuItem(title: group.name, action: nil, keyEquivalent: ""))
|
||||
group.menus.forEach { (m: temperatureMenu) in
|
||||
let menuPoint: NSMenuItem = NSMenuItem(title: m.name, action: #selector(toggleValue1), keyEquivalent: "")
|
||||
menuPoint.state = m.originalName == self.value_1 ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
menuPoint.target = self
|
||||
sensor_1.submenu!.addItem(menuPoint)
|
||||
}
|
||||
sensor_1.submenu!.addItem(NSMenuItem.separator())
|
||||
|
||||
sensor_2.submenu!.addItem(NSMenuItem(title: group.name, action: nil, keyEquivalent: ""))
|
||||
group.menus.forEach { (m: temperatureMenu) in
|
||||
let menuPoint: NSMenuItem = NSMenuItem(title: m.name, action: #selector(toggleValue2), keyEquivalent: "")
|
||||
menuPoint.state = m.originalName == self.value_2 ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
menuPoint.target = self
|
||||
sensor_2.submenu!.addItem(menuPoint)
|
||||
}
|
||||
sensor_2.submenu!.addItem(NSMenuItem.separator())
|
||||
}
|
||||
}
|
||||
|
||||
if sensor_1.submenu?.items.count != 0 {
|
||||
submenu.addItem(sensor_1)
|
||||
}
|
||||
if sensor_2.submenu?.items.count != 0 {
|
||||
submenu.addItem(sensor_2)
|
||||
}
|
||||
submenu.addItem(NSMenuItem.separator())
|
||||
|
||||
if let view = self.widget.view as? Widget {
|
||||
@@ -71,55 +166,41 @@ extension Temperature {
|
||||
self.restart()
|
||||
}
|
||||
|
||||
@objc func toggleCPU(_ sender: NSMenuItem) {
|
||||
var cpu: String = sender.title
|
||||
|
||||
switch cpu {
|
||||
case "CPU Die":
|
||||
cpu = SMC_TEMP_CPU_0_DIE
|
||||
case "CPU Proximity":
|
||||
cpu = SMC_TEMP_CPU_0_PROXIMITY
|
||||
default:
|
||||
break
|
||||
@objc func toggleValue1(_ sender: NSMenuItem) {
|
||||
let val: String = sender.title
|
||||
let originalName = temperatureGroups.getOriginalNameOfSensor(name: val)
|
||||
if self.value_1 == originalName {
|
||||
return
|
||||
}
|
||||
|
||||
let state = sender.state == NSControl.StateValue.on
|
||||
for item in self.submenu.items {
|
||||
if item.title == "CPU Die" || item.title == "CPU Proximity" {
|
||||
item.state = NSControl.StateValue.off
|
||||
}
|
||||
item.state = NSControl.StateValue.off
|
||||
}
|
||||
|
||||
sender.state = state ? NSControl.StateValue.off : NSControl.StateValue.on
|
||||
self.defaults.set(cpu, forKey: "\(name)_cpu")
|
||||
self.cpu = cpu
|
||||
self.defaults.set(originalName, forKey: "\(name)_value_1")
|
||||
self.value_1 = originalName
|
||||
self.initWidget()
|
||||
self.initMenu()
|
||||
menuBar!.reload(name: self.name)
|
||||
}
|
||||
|
||||
@objc func toggleGPU(_ sender: NSMenuItem) {
|
||||
var gpu: String = sender.title
|
||||
|
||||
switch gpu {
|
||||
case "GPU Die":
|
||||
gpu = SMC_TEMP_GPU_0_DIODE
|
||||
case "GPU Proximity":
|
||||
gpu = SMC_TEMP_GPU_0_PROXIMITY
|
||||
default:
|
||||
break
|
||||
@objc func toggleValue2(_ sender: NSMenuItem) {
|
||||
let val: String = sender.title
|
||||
let originalName = temperatureGroups.getOriginalNameOfSensor(name: val)
|
||||
if self.value_2 == originalName {
|
||||
return
|
||||
}
|
||||
|
||||
let state = sender.state == NSControl.StateValue.on
|
||||
for item in self.submenu.items {
|
||||
if item.title == "GPU Die" || item.title == "GPU Proximity" {
|
||||
item.state = NSControl.StateValue.off
|
||||
}
|
||||
item.state = NSControl.StateValue.off
|
||||
}
|
||||
|
||||
sender.state = state ? NSControl.StateValue.off : NSControl.StateValue.on
|
||||
self.defaults.set(gpu, forKey: "\(name)_gpu")
|
||||
self.gpu = gpu
|
||||
self.defaults.set(originalName, forKey: "\(name)_value_2")
|
||||
self.value_2 = originalName
|
||||
self.initWidget()
|
||||
self.initMenu()
|
||||
menuBar!.reload(name: self.name)
|
||||
|
||||
@@ -9,13 +9,6 @@
|
||||
import IOKit
|
||||
import Foundation
|
||||
|
||||
struct TemperatureValue {
|
||||
var CPUDie: Double = 0
|
||||
var CPUProximity: Double = 0
|
||||
var GPUDie: Double = 0
|
||||
var GPUProximity: Double = 0
|
||||
}
|
||||
|
||||
class TemperatureReader: Reader {
|
||||
public var name: String = "Temperature"
|
||||
public var enabled: Bool = true
|
||||
@@ -23,9 +16,9 @@ class TemperatureReader: Reader {
|
||||
public var optional: Bool = false
|
||||
public var initialized: Bool = false
|
||||
|
||||
public var callback: (TemperatureValue) -> Void = {_ in}
|
||||
public var callback: (Temperatures) -> Void = {_ in}
|
||||
|
||||
init(_ updater: @escaping (TemperatureValue) -> Void) {
|
||||
init(_ updater: @escaping (Temperatures) -> Void) {
|
||||
self.callback = updater
|
||||
|
||||
if self.available {
|
||||
@@ -39,14 +32,10 @@ class TemperatureReader: Reader {
|
||||
if !self.enabled && self.initialized { return }
|
||||
self.initialized = true
|
||||
|
||||
let temp = TemperatureValue(
|
||||
CPUDie: GetTemperature(SMC_TEMP_CPU_0_DIE.UTF8CString),
|
||||
CPUProximity: GetTemperature(SMC_TEMP_CPU_0_PROXIMITY.UTF8CString),
|
||||
GPUDie: GetTemperature(SMC_TEMP_GPU_0_DIODE.UTF8CString),
|
||||
GPUProximity: GetTemperature(SMC_TEMP_GPU_0_PROXIMITY.UTF8CString)
|
||||
)
|
||||
var temperatures: Temperatures = Temperatures()
|
||||
GetTemperatures(&temperatures)
|
||||
|
||||
self.callback(temp)
|
||||
self.callback(temperatures)
|
||||
}
|
||||
|
||||
func toggleEnable(_ value: Bool) {
|
||||
|
||||
@@ -274,6 +274,13 @@ extension String {
|
||||
func matches(_ regex: String) -> Bool {
|
||||
return self.range(of: regex, options: .regularExpression, range: nil, locale: nil) != nil
|
||||
}
|
||||
|
||||
func toUpperCase() -> String {
|
||||
return prefix(1).capitalized + dropFirst()
|
||||
}
|
||||
func toLowwerCase() -> String {
|
||||
return prefix(1).lowercased() + dropFirst()
|
||||
}
|
||||
}
|
||||
|
||||
extension URL {
|
||||
@@ -287,3 +294,16 @@ class ChartsNetworkAxisFormatter: IAxisValueFormatter {
|
||||
return Units(bytes: Int64(value)).getReadableSpeed()
|
||||
}
|
||||
}
|
||||
|
||||
extension Temperatures {
|
||||
var asDictionary : [String: Any] {
|
||||
let mirror = Mirror(reflecting: self)
|
||||
|
||||
var dict: Dictionary<String, Any> = [:]
|
||||
for (_, element) in mirror.children.enumerated() {
|
||||
dict[element.label!] = element.value
|
||||
}
|
||||
|
||||
return dict
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// SystemKit.c
|
||||
// SMC.c
|
||||
// Stats
|
||||
//
|
||||
// SMC code borrowed from https://github.com/lavoiesl/osx-cpu-temp.
|
||||
@@ -8,13 +8,14 @@
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
#include <IOKit/ps/IOPowerSources.h>
|
||||
#include <IOKit/ps/IOPSKeys.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SystemKit.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include "SMC.h"
|
||||
|
||||
static io_connect_t conn;
|
||||
|
||||
@@ -151,6 +152,79 @@ double GetTemperature(char* key) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void GetTemperatures(Temperatures *list) {
|
||||
list->termal_zone_0 = GetTemperature(SMC_TEMP_TERMALZONE_0);
|
||||
list->termal_zone_1 = GetTemperature(SMC_TEMP_TERMALZONE_1);
|
||||
list->termal_ambient_0 = GetTemperature(SMC_TEMP_AMBIENT_AIR_0);
|
||||
list->termal_ambient_1 = GetTemperature(SMC_TEMP_AMBIENT_AIR_1);
|
||||
list->termal_heatpipe_0 = GetTemperature(SMC_TEMP_HEATPIPE_0);
|
||||
list->termal_heatpipe_1 = GetTemperature(SMC_TEMP_HEATPIPE_1);
|
||||
list->termal_heatpipe_2 = GetTemperature(SMC_TEMP_HEATPIPE_2);
|
||||
list->termal_heatpipe_3 = GetTemperature(SMC_TEMP_HEATPIPE_3);
|
||||
|
||||
list->cpu_0_die = GetTemperature(SMC_TEMP_CPU_0_DIE);
|
||||
list->cpu_0_diode = GetTemperature(SMC_TEMP_CPU_0_DIODE);
|
||||
list->cpu_0_heatsink = GetTemperature(SMC_TEMP_CPU_0_HEATSINK);
|
||||
list->cpu_0_proximity = GetTemperature(SMC_TEMP_CPU_0_PROXIMITY);
|
||||
list->cpu_1_die = GetTemperature(SMC_TEMP_CPU_1_DIE);
|
||||
list->cpu_1_diode = GetTemperature(SMC_TEMP_CPU_1_DIODE);
|
||||
list->cpu_1_heatsink = GetTemperature(SMC_TEMP_CPU_1_HEATSINK);
|
||||
list->cpu_1_proximity = GetTemperature(SMC_TEMP_CPU_1_PROXIMITY);
|
||||
|
||||
list->cpu_1 = GetTemperature(SMC_TEMP_CPU_CORE_1);
|
||||
list->cpu_2 = GetTemperature(SMC_TEMP_CPU_CORE_2);
|
||||
list->cpu_3 = GetTemperature(SMC_TEMP_CPU_CORE_3);
|
||||
list->cpu_4 = GetTemperature(SMC_TEMP_CPU_CORE_4);
|
||||
list->cpu_5 = GetTemperature(SMC_TEMP_CPU_CORE_5);
|
||||
list->cpu_6 = GetTemperature(SMC_TEMP_CPU_CORE_6);
|
||||
list->cpu_7 = GetTemperature(SMC_TEMP_CPU_CORE_7);
|
||||
list->cpu_8 = GetTemperature(SMC_TEMP_CPU_CORE_8);
|
||||
|
||||
list->gpu_diode = GetTemperature(SMC_TEMP_GPU_0_DIODE);
|
||||
list->gpu_heatsink = GetTemperature(SMC_TEMP_GPU_0_HEATSINK);
|
||||
list->gpu_proximity = GetTemperature(SMC_TEMP_GPU_0_PROXIMITY);
|
||||
|
||||
list->mem_proximity = GetTemperature(SMC_TEMP_MEM_SLOTS);
|
||||
list->mem_0 = GetTemperature(SMC_TEMP_MEM_SLOT_0);
|
||||
list->mem_1 = GetTemperature(SMC_TEMP_MEM_SLOT_1);
|
||||
list->mem_2 = GetTemperature(SMC_TEMP_MEM_SLOT_2);
|
||||
list->mem_3 = GetTemperature(SMC_TEMP_MEM_SLOT_3);
|
||||
|
||||
list->pci_proximity = GetTemperature(SMC_TEMP_PCI_SLOTS);
|
||||
list->pci_0 = GetTemperature(SMC_TEMP_PCI_SLOT_0);
|
||||
list->pci_1 = GetTemperature(SMC_TEMP_PCI_SLOT_1);
|
||||
list->pci_2 = GetTemperature(SMC_TEMP_PCI_SLOT_2);
|
||||
list->pci_3 = GetTemperature(SMC_TEMP_PCI_SLOT_3);
|
||||
|
||||
list->sensor_mainboard = GetTemperature(SMC_TEMP_MAINBOARD_PROXIMITY);
|
||||
list->sensor_powerboard = GetTemperature(SMC_TEMP_POWERBOARD_PROXIMITY);
|
||||
list->sensor_battery = GetTemperature(SMC_TEMP_BATTERY_PROXIMITY);
|
||||
list->sensor_airport = GetTemperature(SMC_TEMP_AIRPORT_PROXIMITY);
|
||||
list->sensor_lcd = GetTemperature(SMC_TEMP_LCD_PROXIMITY);
|
||||
list->sensor_odd = GetTemperature(SMC_TEMP_ODD_PROXIMITY);
|
||||
|
||||
list->northbridge_die = GetTemperature(SMC_TEMP_NORTHBRIDGE_DIE);
|
||||
list->northbridge_proximity = GetTemperature(SMC_TEMP_NORTHBRIDGE_PROXIMITY);
|
||||
|
||||
list->hdd_0 = GetTemperature(SMC_TEMP_HDD_0);
|
||||
list->hdd_1 = GetTemperature(SMC_TEMP_HDD_1);
|
||||
list->hdd_2 = GetTemperature(SMC_TEMP_HDD_2);
|
||||
list->hdd_3 = GetTemperature(SMC_TEMP_HDD_3);
|
||||
|
||||
list->thunderbolt_0 = GetTemperature(SMC_TEMP_THUNDERBOLT_0);
|
||||
list->thunderbolt_1 = GetTemperature(SMC_TEMP_THUNDERBOLT_1);
|
||||
list->thunderbolt_2 = GetTemperature(SMC_TEMP_THUNDERBOLT_2);
|
||||
list->thunderbolt_3 = GetTemperature(SMC_TEMP_THUNDERBOLT_3);
|
||||
}
|
||||
|
||||
void GetVoltages(Voltages *list) {
|
||||
|
||||
}
|
||||
|
||||
void GetPowers(Powers *list) {
|
||||
|
||||
}
|
||||
|
||||
float GetFanRPM(char* key) {
|
||||
SMCVal_t val;
|
||||
kern_return_t result;
|
||||
@@ -166,112 +240,16 @@ float GetFanRPM(char* key) {
|
||||
return -1.f;
|
||||
}
|
||||
|
||||
PowerManagmentInformation *GetPowerInfo() {
|
||||
PowerManagmentInformation *info = malloc(sizeof(PowerManagmentInformation));
|
||||
|
||||
CFTypeRef power_sources = IOPSCopyPowerSourcesInfo();
|
||||
CFTypeRef external_adapter = IOPSCopyExternalPowerAdapterDetails();
|
||||
|
||||
/* Get information aboud external adapter */
|
||||
if (external_adapter != NULL) {
|
||||
CFNumberRef watts = CFDictionaryGetValue(external_adapter, CFSTR(kIOPSPowerAdapterWattsKey));
|
||||
if (watts) {
|
||||
CFNumberGetValue(watts, kCFNumberDoubleType, &info->ACWatts);
|
||||
CFRelease(watts);
|
||||
}
|
||||
|
||||
CFRelease(external_adapter);
|
||||
}
|
||||
|
||||
if(power_sources == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFArrayRef list = IOPSCopyPowerSourcesList(power_sources);
|
||||
CFDictionaryRef battery = NULL;
|
||||
|
||||
if(list == NULL) {
|
||||
CFRelease(power_sources);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the battery */
|
||||
for(int i = 0; i < CFArrayGetCount(list) && battery == NULL; ++i) {
|
||||
CFDictionaryRef candidate = IOPSGetPowerSourceDescription(power_sources, CFArrayGetValueAtIndex(list, i));
|
||||
CFStringRef type;
|
||||
|
||||
if(candidate != NULL) {
|
||||
type = (CFStringRef) CFDictionaryGetValue(candidate, CFSTR(kIOPSTransportTypeKey));
|
||||
int64_t GetCPUFrequency() {
|
||||
int mib[2];
|
||||
unsigned int freq;
|
||||
size_t len;
|
||||
|
||||
if(kCFCompareEqualTo == CFStringCompare(type, CFSTR(kIOPSInternalType), 0)) {
|
||||
CFRetain(candidate);
|
||||
battery = candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_CPU_FREQ;
|
||||
len = sizeof(freq);
|
||||
sysctl(mib, 2, &freq, &len, NULL, 0);
|
||||
|
||||
if(battery != NULL) {
|
||||
CFStringRef power_state = CFDictionaryGetValue(battery, CFSTR(kIOPSPowerSourceStateKey));
|
||||
|
||||
CFNumberRef max_capacity = CFDictionaryGetValue(battery, CFSTR(kIOPSMaxCapacityKey));
|
||||
CFNumberRef design_capacity = CFDictionaryGetValue(battery, CFSTR(kIOPSDesignCapacityKey));
|
||||
CFNumberRef current_capacity = CFDictionaryGetValue(battery, CFSTR(kIOPSCurrentCapacityKey));
|
||||
|
||||
CFNumberRef amperage = CFDictionaryGetValue(battery, CFSTR(kIOPSCurrentKey));
|
||||
CFNumberRef voltage = CFDictionaryGetValue(battery, CFSTR(kIOPSVoltageKey));
|
||||
CFNumberRef temperature = CFDictionaryGetValue(battery, CFSTR(kIOPSTemperatureKey));
|
||||
|
||||
/* Determine the AC state */
|
||||
info->isCharging = kCFCompareEqualTo == CFStringCompare(power_state, CFSTR(kIOPSACPowerValue), 0);
|
||||
|
||||
/* Get capacity */
|
||||
if (max_capacity) {
|
||||
CFNumberGetValue(max_capacity, kCFNumberDoubleType, &info->maxCapacity);
|
||||
CFRelease(max_capacity);
|
||||
}
|
||||
if (design_capacity) {
|
||||
CFNumberGetValue(design_capacity, kCFNumberDoubleType, &info->designCapacity);
|
||||
CFRelease(design_capacity);
|
||||
}
|
||||
if (current_capacity) {
|
||||
CFNumberGetValue(current_capacity, kCFNumberDoubleType, &info->currentCapacity);
|
||||
CFRelease(current_capacity);
|
||||
}
|
||||
|
||||
/* Determine the level */
|
||||
if (info->currentCapacity && info->maxCapacity) {
|
||||
info->level = (info->currentCapacity * 100.0) / info->maxCapacity;
|
||||
}
|
||||
|
||||
/* Get the parameters */
|
||||
if (amperage) {
|
||||
CFNumberGetValue(amperage, kCFNumberDoubleType, &info->amperage);
|
||||
CFRelease(amperage);
|
||||
}
|
||||
if (voltage) {
|
||||
printf("2\n");
|
||||
CFNumberGetValue(voltage, kCFNumberDoubleType, &info->voltage);
|
||||
CFRelease(voltage);
|
||||
}
|
||||
if (temperature) {
|
||||
printf("3\n");
|
||||
CFNumberGetValue(temperature, kCFNumberDoubleType, &info->voltage);
|
||||
CFRelease(temperature);
|
||||
}
|
||||
|
||||
// printf("%f\n", info->amperage);
|
||||
// printf("%f\n", test);
|
||||
// printf("%f\n", info->temperature);
|
||||
// printf("\n%hhu\n", info->isCharging);
|
||||
|
||||
// printf("%u", info->level);
|
||||
|
||||
CFRelease(battery);
|
||||
}
|
||||
|
||||
CFRelease(list);
|
||||
CFRelease(power_sources);
|
||||
|
||||
free(info);
|
||||
return info;
|
||||
return freq;
|
||||
}
|
||||
273
Stats/libs/SMC.h
Normal file
273
Stats/libs/SMC.h
Normal file
@@ -0,0 +1,273 @@
|
||||
//
|
||||
// SMC.h
|
||||
// Stats
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 03/04/2020.
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
typedef struct {
|
||||
double termal_zone_0;
|
||||
double termal_zone_1;
|
||||
double termal_ambient_0;
|
||||
double termal_ambient_1;
|
||||
double termal_heatpipe_0;
|
||||
double termal_heatpipe_1;
|
||||
double termal_heatpipe_2;
|
||||
double termal_heatpipe_3;
|
||||
|
||||
double cpu_0_die;
|
||||
double cpu_0_diode;
|
||||
double cpu_0_heatsink;
|
||||
double cpu_0_proximity;
|
||||
double cpu_1_die;
|
||||
double cpu_1_diode;
|
||||
double cpu_1_heatsink;
|
||||
double cpu_1_proximity;
|
||||
|
||||
double cpu_1;
|
||||
double cpu_2;
|
||||
double cpu_3;
|
||||
double cpu_4;
|
||||
double cpu_5;
|
||||
double cpu_6;
|
||||
double cpu_7;
|
||||
double cpu_8;
|
||||
|
||||
double gpu_diode;
|
||||
double gpu_heatsink;
|
||||
double gpu_proximity;
|
||||
|
||||
double mem_proximity;
|
||||
double mem_0;
|
||||
double mem_1;
|
||||
double mem_2;
|
||||
double mem_3;
|
||||
|
||||
double pci_proximity;
|
||||
double pci_0;
|
||||
double pci_1;
|
||||
double pci_2;
|
||||
double pci_3;
|
||||
|
||||
double sensor_mainboard;
|
||||
double sensor_powerboard;
|
||||
double sensor_battery;
|
||||
double sensor_airport;
|
||||
double sensor_lcd;
|
||||
double sensor_misc;
|
||||
double sensor_odd;
|
||||
|
||||
double northbridge_die;
|
||||
double northbridge_proximity;
|
||||
|
||||
double hdd_0;
|
||||
double hdd_1;
|
||||
double hdd_2;
|
||||
double hdd_3;
|
||||
|
||||
double thunderbolt_0;
|
||||
double thunderbolt_1;
|
||||
double thunderbolt_2;
|
||||
double thunderbolt_3;
|
||||
} Temperatures;
|
||||
|
||||
typedef struct {
|
||||
} Voltages;
|
||||
|
||||
typedef struct {
|
||||
} Powers;
|
||||
|
||||
kern_return_t SMCOpen(void);
|
||||
kern_return_t SMCClose(void);
|
||||
|
||||
double GetTemperature(char* key);
|
||||
float GetFanRPM(char* key);
|
||||
|
||||
void GetTemperatures(Temperatures* list);
|
||||
void GetVoltages(Voltages* list);
|
||||
void GetPowers(Powers* list);
|
||||
|
||||
int64_t GetCPUFrequency(void);
|
||||
|
||||
#define SMC_TEMP_AMBIENT_AIR_0 "TA0P"
|
||||
#define SMC_TEMP_AMBIENT_AIR_1 "TA1P"
|
||||
#define SMC_TEMP_HEATPIPE_0 "Th0H"
|
||||
#define SMC_TEMP_HEATPIPE_1 "Th1H"
|
||||
#define SMC_TEMP_HEATPIPE_2 "Th2H"
|
||||
#define SMC_TEMP_HEATPIPE_3 "Th3H"
|
||||
#define SMC_TEMP_TERMALZONE_0 "TZ0C"
|
||||
#define SMC_TEMP_TERMALZONE_1 "TZ1C"
|
||||
|
||||
#define SMC_TEMP_CPU_0_DIE "TC0F"
|
||||
#define SMC_TEMP_CPU_0_DIODE "TC0D"
|
||||
#define SMC_TEMP_CPU_0_HEATSINK "TC0H"
|
||||
#define SMC_TEMP_CPU_0_PROXIMITY "TC0P"
|
||||
#define SMC_TEMP_CPU_1_DIE "TCAD"
|
||||
#define SMC_TEMP_CPU_1_DIODE "TC1D"
|
||||
#define SMC_TEMP_CPU_1_HEATSINK "TC1H"
|
||||
#define SMC_TEMP_CPU_1_PROXIMITY "TC1P"
|
||||
|
||||
#define SMC_TEMP_CPU_CORE_1 "TC1C"
|
||||
#define SMC_TEMP_CPU_CORE_2 "TC2C"
|
||||
#define SMC_TEMP_CPU_CORE_3 "TC3C"
|
||||
#define SMC_TEMP_CPU_CORE_4 "TC4C"
|
||||
#define SMC_TEMP_CPU_CORE_5 "TC5C"
|
||||
#define SMC_TEMP_CPU_CORE_6 "TC6C"
|
||||
#define SMC_TEMP_CPU_CORE_7 "TC7C"
|
||||
#define SMC_TEMP_CPU_CORE_8 "TC8C"
|
||||
|
||||
#define SMC_TEMP_GPU_0_DIODE "TG0D"
|
||||
#define SMC_TEMP_GPU_0_HEATSINK "TG0H"
|
||||
#define SMC_TEMP_GPU_0_PROXIMITY "TG0P"
|
||||
|
||||
#define SMC_TEMP_MEM_SLOTS "Ts0S"
|
||||
#define SMC_TEMP_MEM_SLOT_0 "TM0S"
|
||||
#define SMC_TEMP_MEM_SLOT_1 "TM1S"
|
||||
#define SMC_TEMP_MEM_SLOT_2 "TM2S"
|
||||
#define SMC_TEMP_MEM_SLOT_3 "TM3S"
|
||||
|
||||
#define SMC_TEMP_PCI_SLOTS "TS0C"
|
||||
#define SMC_TEMP_PCI_SLOT_0 "TA0S"
|
||||
#define SMC_TEMP_PCI_SLOT_1 "TA1S"
|
||||
#define SMC_TEMP_PCI_SLOT_2 "TA2S"
|
||||
#define SMC_TEMP_PCI_SLOT_3 "TA3S"
|
||||
|
||||
#define SMC_TEMP_MAINBOARD_PROXIMITY "Tm0P"
|
||||
#define SMC_TEMP_POWERBOARD_PROXIMITY "Tp0P"
|
||||
#define SMC_TEMP_BATTERY_PROXIMITY "TB1T"
|
||||
|
||||
#define SMC_TEMP_AIRPORT_PROXIMITY "TW0P"
|
||||
#define SMC_TEMP_LCD_PROXIMITY "TL0P"
|
||||
#define SMC_TEMP_ODD_PROXIMITY "TO0P"
|
||||
|
||||
#define SMC_TEMP_NORTHBRIDGE_DIE "TN0D"
|
||||
#define SMC_TEMP_NORTHBRIDGE_PROXIMITY "TN0P"
|
||||
|
||||
#define SMC_TEMP_HDD_0 "TH0P"
|
||||
#define SMC_TEMP_HDD_1 "TH1P"
|
||||
#define SMC_TEMP_HDD_2 "TH2P"
|
||||
#define SMC_TEMP_HDD_3 "TH3P"
|
||||
|
||||
#define SMC_TEMP_THUNDERBOLT_0 "TI0P"
|
||||
#define SMC_TEMP_THUNDERBOLT_1 "TI1P"
|
||||
#define SMC_TEMP_THUNDERBOLT_2 "TI2P"
|
||||
#define SMC_TEMP_THUNDERBOLT_3 "TI3P"
|
||||
|
||||
#define SMC_VOLTAGE_CPU_VRM "VS0C"
|
||||
#define SMC_VOLTAGE_CPU_CORE_0 "VC0C"
|
||||
#define SMC_VOLTAGE_CPU_CORE_1 "VC1C"
|
||||
#define SMC_VOLTAGE_CPU_CORE_2 "VC2C"
|
||||
#define SMC_VOLTAGE_CPU_CORE_3 "VC3C"
|
||||
#define SMC_VOLTAGE_CPU_CORE_4 "VC4C"
|
||||
#define SMC_VOLTAGE_CPU_CORE_5 "VC5C"
|
||||
#define SMC_VOLTAGE_CPU_CORE_6 "VC6C"
|
||||
#define SMC_VOLTAGE_CPU_CORE_7 "VC7C"
|
||||
#define SMC_VOLTAGE_CPU_CORE_8 "VC8C"
|
||||
|
||||
#define SMC_VOLTAGE_GPU "VG0C"
|
||||
#define SMC_VOLTAGE_MEMORY "VM0R"
|
||||
#define SMC_VOLTAGE_BATTERY "VBAT"
|
||||
#define SMC_VOLTAGE_CMOS "Vb0R"
|
||||
|
||||
#define SMC_VOLTAGE_MAINBOARD "VD0R"
|
||||
#define SMC_VOLTAGE_12V_RAIL "VP0R"
|
||||
#define SMC_VOLTAGE_12V_VCC "Vp0C"
|
||||
#define SMC_VOLTAGE_3V "VV2S"
|
||||
#define SMC_VOLTAGE_3_3V "VR3R"
|
||||
#define SMC_VOLTAGE_5V "VV1S"
|
||||
#define SMC_VOLTAGE_12V "VV9S"
|
||||
#define SMC_VOLTAGE_PCI_12V "VeES"
|
||||
|
||||
#define SMC_VOLTAGE_BATT0_VOLT "B0AV"
|
||||
#define SMC_CURRENT_BATT0 "B0AC"
|
||||
|
||||
#define SMC_WATT_CPU_PACKAGE_CORE "PCPC"
|
||||
#define SMC_WATT_CPU_PACKAGE_TOTAL "PCPT"
|
||||
#define SMC_WATT_IGPU_PACKAGE "PCPG"
|
||||
|
||||
#define SMC_FREQUENCY_CPU_PACKAGE_MULTI "MPkC"
|
||||
#define SMC_FREQUENCY_CPU_CORE_0_MULTI "MC0C"
|
||||
#define SMC_FREQUENCY_CPU_CORE_1_MULTI "MC1C"
|
||||
#define SMC_FREQUENCY_CPU_CORE_2_MULTI "MC2C"
|
||||
#define SMC_FREQUENCY_CPU_CORE_3_MULTI "MC3C"
|
||||
#define SMC_FREQUENCY_CPU_CORE_4_MULTI "MC4C"
|
||||
#define SMC_FREQUENCY_CPU_CORE_5_MULTI "MC5C"
|
||||
#define SMC_FREQUENCY_CPU_CORE_6_MULTI "MC6C"
|
||||
#define SMC_FREQUENCY_CPU_CORE_7_MULTI "MC7C"
|
||||
#define SMC_FREQUENCY_CPU_CORE_0 "FRC0"
|
||||
#define SMC_FREQUENCY_CPU_CORE_1 "FRC1"
|
||||
#define SMC_FREQUENCY_CPU_CORE_2 "FRC2"
|
||||
#define SMC_FREQUENCY_CPU_CORE_3 "FRC3"
|
||||
#define SMC_FREQUENCY_CPU_CORE_4 "FRC4"
|
||||
#define SMC_FREQUENCY_CPU_CORE_5 "FRC5"
|
||||
#define SMC_FREQUENCY_CPU_CORE_6 "FRC6"
|
||||
#define SMC_FREQUENCY_CPU_CORE_7 "FRC7"
|
||||
|
||||
#define SMC_FREQUENCY_GPU_0 "CG0C"
|
||||
#define SMC_FREQUENCY_GPU_1 "CG1C"
|
||||
#define SMC_FREQUENCY_GPU_0_SHADER "CG0S"
|
||||
#define SMC_FREQUENCY_GPU_1_SHADER "CG1S"
|
||||
#define SMC_FREQUENCY_GPU_0_MEMORY "CG1M"
|
||||
#define SMC_FREQUENCY_GPU_1_MEMORY "CG0M"
|
||||
|
||||
#define SMC_FAN0_RPM "F0Ac"
|
||||
|
||||
#define KERNEL_INDEX_SMC 2
|
||||
|
||||
#define SMC_CMD_READ_BYTES 5
|
||||
#define SMC_CMD_WRITE_BYTES 6
|
||||
#define SMC_CMD_READ_INDEX 8
|
||||
#define SMC_CMD_READ_KEYINFO 9
|
||||
#define SMC_CMD_READ_PLIMIT 11
|
||||
#define SMC_CMD_READ_VERS 12
|
||||
|
||||
#define DATATYPE_FPE2 "fpe2"
|
||||
#define DATATYPE_UINT8 "ui8 "
|
||||
#define DATATYPE_UINT16 "ui16"
|
||||
#define DATATYPE_UINT32 "ui32"
|
||||
#define DATATYPE_SP78 "sp78"
|
||||
|
||||
typedef char UInt32Char_t[5];
|
||||
typedef char SMCBytes_t[32];
|
||||
|
||||
typedef struct {
|
||||
UInt32Char_t key;
|
||||
UInt32 dataSize;
|
||||
UInt32Char_t dataType;
|
||||
SMCBytes_t bytes;
|
||||
} SMCVal_t;
|
||||
|
||||
typedef struct {
|
||||
char major;
|
||||
char minor;
|
||||
char build;
|
||||
char reserved[1];
|
||||
UInt16 release;
|
||||
} SMCKeyData_vers_t;
|
||||
|
||||
typedef struct {
|
||||
UInt16 version;
|
||||
UInt16 length;
|
||||
UInt32 cpuPLimit;
|
||||
UInt32 gpuPLimit;
|
||||
UInt32 memPLimit;
|
||||
} SMCKeyData_pLimitData_t;
|
||||
|
||||
typedef struct {
|
||||
UInt32 dataSize;
|
||||
UInt32 dataType;
|
||||
char dataAttributes;
|
||||
} SMCKeyData_keyInfo_t;
|
||||
|
||||
typedef struct {
|
||||
UInt32 key;
|
||||
SMCKeyData_vers_t vers;
|
||||
SMCKeyData_pLimitData_t pLimitData;
|
||||
SMCKeyData_keyInfo_t keyInfo;
|
||||
char result;
|
||||
char status;
|
||||
char data8;
|
||||
UInt32 data32;
|
||||
SMCBytes_t bytes;
|
||||
} SMCKeyData_t;
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "SystemKit.h"
|
||||
#import "SMC.h"
|
||||
|
||||
//! Project version number for SMCKit.
|
||||
FOUNDATION_EXPORT double SMCKitVersionNumber;
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
//
|
||||
// SystemKit.h
|
||||
// Stats
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 03/04/2020.
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
#define SMC_TEMP_AMBIENT_AIR_0 "TA0P"
|
||||
#define SMC_TEMP_AMBIENT_AIR_1 "TA1P"
|
||||
|
||||
#define SMC_TEMP_CPU_0_DIE "TC0F"
|
||||
#define SMC_TEMP_CPU_0_DIODE "TC0D"
|
||||
#define SMC_TEMP_CPU_0_HEATSINK "TC0H"
|
||||
#define SMC_TEMP_CPU_0_PROXIMITY "TC0P"
|
||||
|
||||
#define SMC_TEMP_ENCLOSURE_BASE_0 "TB0T"
|
||||
#define SMC_TEMP_ENCLOSURE_BASE_1 "TB1T"
|
||||
#define SMC_TEMP_ENCLOSURE_BASE_2 "TB2T"
|
||||
#define SMC_TEMP_ENCLOSURE_BASE_3 "TB3T"
|
||||
|
||||
#define SMC_TEMP_GPU_0_DIODE "TG0D"
|
||||
#define SMC_TEMP_GPU_0_HEATSINK "TG0H"
|
||||
#define SMC_TEMP_GPU_0_PROXIMITY "TG0P"
|
||||
|
||||
#define SMC_TEMP_HDD_PROXIMITY "TH0P"
|
||||
#define SMC_TEMP_LCD_PROXIMITY "TL0P"
|
||||
#define SMC_TEMP_MISC_PROXIMITY "Tm0P"
|
||||
#define SMC_TEMP_ODD_PROXIMITY "TO0P"
|
||||
|
||||
#define SMC_TEMP_HEATSINK_0 "Th0H"
|
||||
#define SMC_TEMP_HEATSINK_1 "Th1H"
|
||||
#define SMC_TEMP_HEATSINK_2 "Th2H"
|
||||
|
||||
#define SMC_TEMP_MEM_SLOT_0 "TM0S"
|
||||
#define SMC_TEMP_MEM_SLOTS_PROXIMITY "TM0P"
|
||||
|
||||
#define SMC_TEMP_NORTHBRIDGE "TN0H"
|
||||
#define SMC_TEMP_NORTHBRIDGE_DIODE "TN0D"
|
||||
#define SMC_TEMP_NORTHBRIDGE_PROXIMITY "TN0P"
|
||||
|
||||
#define SMC_TEMP_PALM_REST "Ts0P"
|
||||
#define PWR_TEMP_SUPPLY_PROXIMITY "Tp0P"
|
||||
|
||||
#define SMC_TEMP_THUNDERBOLT_0 "TI0P"
|
||||
#define SMC_TEMP_THUNDERBOLT_1 "TI1P"
|
||||
|
||||
#define SMC_FAN0_RPM "F0Ac"
|
||||
|
||||
typedef enum {
|
||||
Off_line,
|
||||
AC_Power,
|
||||
Battery_Power
|
||||
} PowerSource;
|
||||
|
||||
typedef struct {
|
||||
unsigned int level;
|
||||
Boolean isCharging;
|
||||
|
||||
double amperage;
|
||||
double voltage;
|
||||
double temperature;
|
||||
|
||||
double cycles;
|
||||
|
||||
double currentCapacity;
|
||||
double maxCapacity;
|
||||
double designCapacity;
|
||||
|
||||
double timeToEmpty;
|
||||
double timeToFull;
|
||||
|
||||
PowerSource powerSource;
|
||||
double ACWatts;
|
||||
} PowerManagmentInformation;
|
||||
|
||||
kern_return_t SMCOpen(void);
|
||||
kern_return_t SMCClose(void);
|
||||
|
||||
double GetTemperature(char* key);
|
||||
float GetFanRPM(char* key);
|
||||
//PowerManagmentInformation *GetPowerInfo(void);
|
||||
|
||||
// INTERNAL
|
||||
#define KERNEL_INDEX_SMC 2
|
||||
|
||||
#define SMC_CMD_READ_BYTES 5
|
||||
#define SMC_CMD_WRITE_BYTES 6
|
||||
#define SMC_CMD_READ_INDEX 8
|
||||
#define SMC_CMD_READ_KEYINFO 9
|
||||
#define SMC_CMD_READ_PLIMIT 11
|
||||
#define SMC_CMD_READ_VERS 12
|
||||
|
||||
#define DATATYPE_FPE2 "fpe2"
|
||||
#define DATATYPE_UINT8 "ui8 "
|
||||
#define DATATYPE_UINT16 "ui16"
|
||||
#define DATATYPE_UINT32 "ui32"
|
||||
#define DATATYPE_SP78 "sp78"
|
||||
|
||||
typedef char UInt32Char_t[5];
|
||||
typedef char SMCBytes_t[32];
|
||||
|
||||
typedef struct {
|
||||
UInt32Char_t key;
|
||||
UInt32 dataSize;
|
||||
UInt32Char_t dataType;
|
||||
SMCBytes_t bytes;
|
||||
} SMCVal_t;
|
||||
|
||||
typedef struct {
|
||||
char major;
|
||||
char minor;
|
||||
char build;
|
||||
char reserved[1];
|
||||
UInt16 release;
|
||||
} SMCKeyData_vers_t;
|
||||
|
||||
typedef struct {
|
||||
UInt16 version;
|
||||
UInt16 length;
|
||||
UInt32 cpuPLimit;
|
||||
UInt32 gpuPLimit;
|
||||
UInt32 memPLimit;
|
||||
} SMCKeyData_pLimitData_t;
|
||||
|
||||
typedef struct {
|
||||
UInt32 dataSize;
|
||||
UInt32 dataType;
|
||||
char dataAttributes;
|
||||
} SMCKeyData_keyInfo_t;
|
||||
|
||||
typedef struct {
|
||||
UInt32 key;
|
||||
SMCKeyData_vers_t vers;
|
||||
SMCKeyData_pLimitData_t pLimitData;
|
||||
SMCKeyData_keyInfo_t keyInfo;
|
||||
char result;
|
||||
char status;
|
||||
char data8;
|
||||
UInt32 data32;
|
||||
SMCBytes_t bytes;
|
||||
} SMCKeyData_t;
|
||||
Reference in New Issue
Block a user