mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-14 00:04:15 +09:00
- remove removable disks (dmg) from disk list;
- rename Temperature module to Sensors; - fix ordering in temperature sensors list; - rewrote SMC from C to Swift; - now sensors list load automatically; - removed all C code;
This commit is contained in:
@@ -12,6 +12,7 @@ import LaunchAtLogin
|
||||
|
||||
let updater = macAppUpdater(user: "exelban", repo: "stats")
|
||||
var menuBar: MenuBar?
|
||||
let smc = SMCService()
|
||||
|
||||
@NSApplicationMain
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
@@ -20,7 +21,12 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
private let popover = NSPopover()
|
||||
|
||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||
SMCOpen();
|
||||
let res = smc.open()
|
||||
if res != kIOReturnSuccess {
|
||||
print("ERROR open SMC")
|
||||
NSApp.terminate(nil)
|
||||
return
|
||||
}
|
||||
|
||||
guard let menuBarButton = self.menuBarItem.button else {
|
||||
NSApp.terminate(nil)
|
||||
@@ -42,7 +48,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ aNotification: Notification) {
|
||||
SMCClose()
|
||||
// SMCClose()
|
||||
menuBar?.destroy()
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import ServiceManagement
|
||||
Class keeps a status bar item and has the main function for updating widgets.
|
||||
*/
|
||||
class MenuBar {
|
||||
public let modules: [Module] = [CPU(), RAM(), Temperature(), Disk(), Battery(), Network()]
|
||||
public let modules: [Module] = [CPU(), RAM(), Sensors(), Disk(), Battery(), Network()]
|
||||
|
||||
private let menuBarItem: NSStatusItem
|
||||
private var menuBarButton: NSButton = NSButton()
|
||||
|
||||
@@ -96,7 +96,9 @@ class DiskCapacityReader: Reader {
|
||||
continue
|
||||
}
|
||||
|
||||
self.disks.list.append(getDisk(disk))
|
||||
if let d = getDisk(disk) {
|
||||
self.disks.list.append(d)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,7 +113,7 @@ class DiskCapacityReader: Reader {
|
||||
self.enabled = value
|
||||
}
|
||||
|
||||
private func getDisk(_ disk: DADisk) -> diskInfo {
|
||||
private func getDisk(_ disk: DADisk) -> diskInfo? {
|
||||
var d: diskInfo = diskInfo()
|
||||
|
||||
if let bsdName = DADiskGetBSDName(disk) {
|
||||
@@ -120,6 +122,12 @@ class DiskCapacityReader: Reader {
|
||||
|
||||
if let diskDescription = DADiskCopyDescription(disk) {
|
||||
if let dict = diskDescription as? [String: AnyObject] {
|
||||
if let removable = dict[kDADiskDescriptionMediaRemovableKey as String] {
|
||||
if removable as! Bool {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if let mediaName = dict[kDADiskDescriptionMediaNameKey as String] {
|
||||
d.name = mediaName as! String
|
||||
}
|
||||
|
||||
@@ -20,16 +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
|
||||
if self.disks.list.count > 1 {
|
||||
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)
|
||||
}
|
||||
disk.target = self
|
||||
|
||||
submenu.addItem(disk)
|
||||
}
|
||||
|
||||
let mini = NSMenuItem(title: "Mini", action: #selector(toggleWidget), keyEquivalent: "")
|
||||
|
||||
@@ -74,8 +74,8 @@ extension Module {
|
||||
switch self.widget.type {
|
||||
case Widgets.Mini:
|
||||
widget = Mini()
|
||||
case Widgets.Temperature:
|
||||
widget = TemperatureWidget()
|
||||
case Widgets.Sensors:
|
||||
widget = SensorsWidget()
|
||||
case Widgets.Chart:
|
||||
widget = Chart()
|
||||
case Widgets.ChartWithValue:
|
||||
|
||||
@@ -59,7 +59,9 @@ extension Network {
|
||||
marker.chartView = self.chart
|
||||
self.chart.marker = marker
|
||||
|
||||
let download = LineChartDataSet(label: "Download")
|
||||
var downloadLineChartEntry = [ChartDataEntry]()
|
||||
downloadLineChartEntry.append(ChartDataEntry(x: 0, y: 0))
|
||||
let download = LineChartDataSet(entries: downloadLineChartEntry, label: "Download")
|
||||
download.drawCirclesEnabled = false
|
||||
download.mode = .cubicBezier
|
||||
download.cubicIntensity = 0.1
|
||||
@@ -67,7 +69,9 @@ extension Network {
|
||||
download.fillColor = downloadGradientColor
|
||||
download.drawFilledEnabled = true
|
||||
|
||||
let upload = LineChartDataSet(label: "Upload")
|
||||
var uploadLineChartEntry = [ChartDataEntry]()
|
||||
uploadLineChartEntry.append(ChartDataEntry(x: 0, y: 0))
|
||||
let upload = LineChartDataSet(entries: uploadLineChartEntry, label: "Upload")
|
||||
upload.drawCirclesEnabled = false
|
||||
upload.mode = .cubicBezier
|
||||
upload.cubicIntensity = 0.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Temperature.swift
|
||||
// Sensors.swift
|
||||
// Stats
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 03/04/2020.
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
class Temperature: Module {
|
||||
public var name: String = "Temperature"
|
||||
class Sensors: Module {
|
||||
public var name: String = "Sensors"
|
||||
public var updateInterval: Double = 1
|
||||
|
||||
public var enabled: Bool = true
|
||||
@@ -25,66 +25,73 @@ class Temperature: Module {
|
||||
internal let defaults = UserDefaults.standard
|
||||
internal var submenu: NSMenu = NSMenu()
|
||||
|
||||
internal var value_1: String = "cpu_1_diode"
|
||||
internal var value_2: String = "gpu_diode"
|
||||
internal var value_1: String = "TC0P"
|
||||
internal var value_2: String = "TG0D"
|
||||
internal var once: Int = 0
|
||||
|
||||
internal var sensors: Sensors_t = Sensors_t()
|
||||
|
||||
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.widget.type = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Sensors
|
||||
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()
|
||||
|
||||
readers.append(TemperatureReader(self.usageUpdater))
|
||||
|
||||
if self.enabled {
|
||||
self.update()
|
||||
}
|
||||
|
||||
self.task = Repeater.init(interval: .seconds(self.updateInterval), observer: { _ in
|
||||
self.readers.forEach { reader in
|
||||
reader.read()
|
||||
if self.enabled {
|
||||
self.update()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func start() {
|
||||
public func start() {
|
||||
if self.task != nil && self.task!.state.isRunning == false {
|
||||
self.task!.start()
|
||||
}
|
||||
}
|
||||
|
||||
func stop() {
|
||||
public func stop() {
|
||||
if self.task!.state.isRunning {
|
||||
self.task?.pause()
|
||||
}
|
||||
}
|
||||
|
||||
func restart() {
|
||||
public func restart() {
|
||||
self.stop()
|
||||
self.start()
|
||||
}
|
||||
|
||||
private func usageUpdater(value: Temperatures) {
|
||||
if self.widget.view is Widget {
|
||||
DispatchQueue.main.async(execute: {
|
||||
var value_1: Double = 0
|
||||
var value_2: Double = 0
|
||||
|
||||
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])
|
||||
})
|
||||
private func update() {
|
||||
var value_1: Double = 0
|
||||
var value_2: Double = 0
|
||||
|
||||
var sensor_1: Sensor_t? = self.sensors.find(byKey: self.value_1)
|
||||
var sensor_2: Sensor_t? = self.sensors.find(byKey: self.value_2)
|
||||
|
||||
if sensor_1 != nil {
|
||||
sensor_1!.update()
|
||||
if sensor_1!.value != nil {
|
||||
value_1 = sensor_1!.value!
|
||||
}
|
||||
}
|
||||
if sensor_2 != nil {
|
||||
sensor_2!.update()
|
||||
if sensor_2!.value != nil {
|
||||
value_2 = sensor_2!.value!
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async(execute: {
|
||||
(self.widget.view as! Widget).setValue(data: [value_1, value_2])
|
||||
})
|
||||
}
|
||||
}
|
||||
151
Stats/Modules/Sensors/SensorsMenu.swift
Normal file
151
Stats/Modules/Sensors/SensorsMenu.swift
Normal file
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// SensorsMenu.swift
|
||||
// Stats
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 03/04/2020.
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
extension Sensors {
|
||||
public func initMenu() {
|
||||
menu = NSMenuItem(title: name, action: #selector(toggle), keyEquivalent: "")
|
||||
submenu = NSMenu()
|
||||
|
||||
if defaults.object(forKey: name) != nil {
|
||||
menu.state = defaults.bool(forKey: name) ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
} else {
|
||||
menu.state = NSControl.StateValue.on
|
||||
}
|
||||
menu.target = self
|
||||
|
||||
let sensor_1: NSMenuItem = NSMenuItem(title: "Sensor #1", action: nil, keyEquivalent: "")
|
||||
sensor_1.target = self
|
||||
sensor_1.submenu = NSMenu()
|
||||
addSensorsMennu(sensor_1.submenu!, value: self.value_1, action: #selector(toggleValue1))
|
||||
|
||||
let sensor_2: NSMenuItem = NSMenuItem(title: "Sensor #2", action: nil, keyEquivalent: "")
|
||||
sensor_2.target = self
|
||||
sensor_2.submenu = NSMenu()
|
||||
addSensorsMennu(sensor_2.submenu!, value: self.value_2, action: #selector(toggleValue2))
|
||||
|
||||
submenu.addItem(sensor_1)
|
||||
submenu.addItem(sensor_2)
|
||||
|
||||
submenu.addItem(NSMenuItem.separator())
|
||||
|
||||
if let view = self.widget.view as? Widget {
|
||||
for widgetMenu in view.menus {
|
||||
submenu.addItem(widgetMenu)
|
||||
}
|
||||
}
|
||||
|
||||
if self.enabled {
|
||||
menu.submenu = submenu
|
||||
}
|
||||
}
|
||||
|
||||
private func addSensorsMennu(_ menu: NSMenu, value: String, action: Selector?) {
|
||||
var sensorsMenu: NSMenuItem? = generateSensorsMenu(type: SensorType.Temperature, value: value, action: action)
|
||||
if sensorsMenu != nil {
|
||||
menu.addItem(sensorsMenu!)
|
||||
}
|
||||
sensorsMenu = generateSensorsMenu(type: SensorType.Voltage, value: value, action: action)
|
||||
if sensorsMenu != nil {
|
||||
menu.addItem(sensorsMenu!)
|
||||
}
|
||||
sensorsMenu = generateSensorsMenu(type: SensorType.Power, value: value, action: action)
|
||||
if sensorsMenu != nil {
|
||||
menu.addItem(sensorsMenu!)
|
||||
}
|
||||
}
|
||||
|
||||
private func generateSensorsMenu(type: SensorType, value: String, action: Selector?) -> NSMenuItem? {
|
||||
let list: [Sensor_t] = self.sensors.list.filter{ $0.type == type.rawValue }
|
||||
if list.isEmpty {
|
||||
return nil
|
||||
}
|
||||
|
||||
let mainItem: NSMenuItem = NSMenuItem(title: type.rawValue, action: nil, keyEquivalent: "")
|
||||
mainItem.target = self
|
||||
mainItem.submenu = NSMenu()
|
||||
|
||||
var groups: [SensorGroup_t] = []
|
||||
list.forEach { (s: Sensor_t) in
|
||||
if !groups.contains(s.group) {
|
||||
groups.append(s.group)
|
||||
}
|
||||
}
|
||||
groups.sort()
|
||||
|
||||
groups.forEach { (g: SensorGroup_t) in
|
||||
mainItem.submenu!.addItem(NSMenuItem(title: g, action: nil, keyEquivalent: ""))
|
||||
|
||||
list.filter{ $0.group == g }.forEach { (s: Sensor_t) in
|
||||
let menuPoint: NSMenuItem = NSMenuItem(title: s.name, action: action, keyEquivalent: "")
|
||||
menuPoint.state = s.key == value ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
menuPoint.target = self
|
||||
menuPoint.extraString = s.key
|
||||
|
||||
mainItem.submenu!.addItem(menuPoint)
|
||||
}
|
||||
|
||||
mainItem.submenu!.addItem(NSMenuItem.separator())
|
||||
}
|
||||
|
||||
return mainItem
|
||||
}
|
||||
|
||||
@objc func toggle(_ sender: NSMenuItem) {
|
||||
let state = sender.state != NSControl.StateValue.on
|
||||
sender.state = sender.state == NSControl.StateValue.on ? NSControl.StateValue.off : NSControl.StateValue.on
|
||||
self.defaults.set(state, forKey: name)
|
||||
self.enabled = state
|
||||
menuBar!.reload(name: self.name)
|
||||
|
||||
if !state {
|
||||
menu.submenu = nil
|
||||
} else {
|
||||
menu.submenu = submenu
|
||||
}
|
||||
|
||||
self.restart()
|
||||
}
|
||||
|
||||
@objc func toggleValue1(_ sender: NSMenuItem) {
|
||||
let val: String = sender.extraString
|
||||
if self.value_1 == val {
|
||||
return
|
||||
}
|
||||
|
||||
let state = sender.state == NSControl.StateValue.on
|
||||
for item in self.submenu.items {
|
||||
item.state = NSControl.StateValue.off
|
||||
}
|
||||
|
||||
sender.state = state ? NSControl.StateValue.off : NSControl.StateValue.on
|
||||
self.defaults.set(val, forKey: "\(name)_value_1")
|
||||
self.value_1 = val
|
||||
self.initWidget()
|
||||
self.initMenu()
|
||||
menuBar!.reload(name: self.name)
|
||||
}
|
||||
|
||||
@objc func toggleValue2(_ sender: NSMenuItem) {
|
||||
let val: String = sender.extraString
|
||||
if self.value_2 == val {
|
||||
return
|
||||
}
|
||||
|
||||
let state = sender.state == NSControl.StateValue.on
|
||||
for item in self.submenu.items {
|
||||
item.state = NSControl.StateValue.off
|
||||
}
|
||||
|
||||
sender.state = state ? NSControl.StateValue.off : NSControl.StateValue.on
|
||||
self.defaults.set(val, forKey: "\(name)_value_2")
|
||||
self.value_2 = val
|
||||
self.initWidget()
|
||||
self.initMenu()
|
||||
menuBar!.reload(name: self.name)
|
||||
}
|
||||
}
|
||||
151
Stats/Modules/Sensors/SensorsType.swift
Normal file
151
Stats/Modules/Sensors/SensorsType.swift
Normal file
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// SensorsType.swift
|
||||
// Stats
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 06/04/2020.
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
typealias SensorGroup_t = String
|
||||
enum SensorGroup: SensorGroup_t {
|
||||
case CPU = "CPU"
|
||||
case GPU = "GPU"
|
||||
case System = "Systems"
|
||||
case Sensor = "Sensors"
|
||||
}
|
||||
|
||||
typealias SensorType_t = String
|
||||
enum SensorType: SensorType_t {
|
||||
case Temperature = "Temperature"
|
||||
case Voltage = "Voltage"
|
||||
case Power = "Power"
|
||||
}
|
||||
|
||||
struct Sensor_t {
|
||||
var name: String
|
||||
var key: String = ""
|
||||
|
||||
var group: SensorGroup_t
|
||||
var type: SensorType_t
|
||||
|
||||
var value: Double? = nil
|
||||
|
||||
public mutating func update() {
|
||||
self.value = smc.getValue(self.key)
|
||||
}
|
||||
}
|
||||
|
||||
struct Sensors_t {
|
||||
var list: [Sensor_t] = []
|
||||
|
||||
init() {
|
||||
var available: [String] = smc.getAllKeys()
|
||||
var sensor: Sensor_t? = nil
|
||||
|
||||
available = available.filter({ (key: String) -> Bool in
|
||||
switch key.prefix(1) {
|
||||
case "T", "V", "P": return SensorsDict[key] != nil
|
||||
default: return false
|
||||
}
|
||||
})
|
||||
|
||||
available.forEach { (key: String) in
|
||||
sensor = SensorsDict[key]
|
||||
if sensor != nil {
|
||||
sensor!.value = smc.getValue(key)
|
||||
if sensor!.value != nil {
|
||||
sensor!.key = key
|
||||
self.list.append(sensor!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func find(byKey key: String) -> Sensor_t? {
|
||||
return self.list.first{ $0.key == key}
|
||||
}
|
||||
}
|
||||
|
||||
// List of keys: https://github.com/acidanthera/VirtualSMC/blob/master/Docs/SMCSensorKeys.txt
|
||||
let SensorsDict: [String: Sensor_t] = [
|
||||
/// Temperature
|
||||
"TA0P": Sensor_t(name: "Ambient 1", group: SensorGroup.Sensor.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TA1P": Sensor_t(name: "Ambient 2", group: SensorGroup.Sensor.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"Th0H": Sensor_t(name: "Heatpipe 1", group: SensorGroup.Sensor.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"Th1H": Sensor_t(name: "Heatpipe 2", group: SensorGroup.Sensor.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"Th2H": Sensor_t(name: "Heatpipe 3", group: SensorGroup.Sensor.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"Th3H": Sensor_t(name: "Heatpipe 4", group: SensorGroup.Sensor.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TZ0C": Sensor_t(name: "Termal zone 1", group: SensorGroup.Sensor.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TZ1C": Sensor_t(name: "Termal zone 2", group: SensorGroup.Sensor.rawValue, type: SensorType.Temperature.rawValue),
|
||||
|
||||
"TC0F": Sensor_t(name: "CPU die", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TC0H": Sensor_t(name: "CPU heatsink", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TC0P": Sensor_t(name: "CPU proximity", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TC1C": Sensor_t(name: "CPU core 1", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TC2C": Sensor_t(name: "CPU core 2", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TC3C": Sensor_t(name: "CPU core 3", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TC4C": Sensor_t(name: "CPU core 4", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TC5C": Sensor_t(name: "CPU core 5", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TC6C": Sensor_t(name: "CPU core 6", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TC7C": Sensor_t(name: "CPU core 7", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TC8C": Sensor_t(name: "CPU core 8", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
|
||||
"TCGC": Sensor_t(name: "GPU Intel Graphics", group: SensorGroup.GPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TG0D": Sensor_t(name: "GPU die", group: SensorGroup.GPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TG0H": Sensor_t(name: "GPU heatsink", group: SensorGroup.GPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TG0P": Sensor_t(name: "GPU proximity", group: SensorGroup.GPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
|
||||
"Tm0P": Sensor_t(name: "Mainboard", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"Tp0P": Sensor_t(name: "Powerboard", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TB1T": Sensor_t(name: "Battery", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TW0P": Sensor_t(name: "Airport", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TL0P": Sensor_t(name: "Display", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TI0P": Sensor_t(name: "Thunderbold 1", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TI1P": Sensor_t(name: "Thunderbold 2", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TI2P": Sensor_t(name: "Thunderbold 3", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TI3P": Sensor_t(name: "Thunderbold 4", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
|
||||
"TN0D": Sensor_t(name: "Northbridge die", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TN0H": Sensor_t(name: "Northbridge heatsink", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
"TN0P": Sensor_t(name: "Northbridge proximity", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
|
||||
/// Voltage
|
||||
"VCAC": Sensor_t(name: "CPU IA", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VCSC": Sensor_t(name: "CPU System Agent", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VC0C": Sensor_t(name: "CPU Core 1", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VC1C": Sensor_t(name: "CPU Core 2", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VC2C": Sensor_t(name: "CPU Core 3", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VC3C": Sensor_t(name: "CPU Core 4", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VC4C": Sensor_t(name: "CPU Core 5", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VC5C": Sensor_t(name: "CPU Core 6", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VC6C": Sensor_t(name: "CPU Core 7", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VC7C": Sensor_t(name: "CPU Core 8", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
|
||||
"VCTC": Sensor_t(name: "GPU Intel Graphics", group: SensorGroup.GPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VG0C": Sensor_t(name: "GPU", group: SensorGroup.GPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
|
||||
"VM0R": Sensor_t(name: "Memory", group: SensorGroup.System.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VBAT": Sensor_t(name: "Battery", group: SensorGroup.System.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"Vb0R": Sensor_t(name: "CMOS", group: SensorGroup.System.rawValue, type: SensorType.Voltage.rawValue),
|
||||
|
||||
"VD0R": Sensor_t(name: "DC In", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VP0R": Sensor_t(name: "12V rail", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"Vp0C": Sensor_t(name: "12V vcc", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VV2S": Sensor_t(name: "3V", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VR3R": Sensor_t(name: "3.3V", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VV1S": Sensor_t(name: "5V", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VV9S": Sensor_t(name: "12V", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
"VeES": Sensor_t(name: "PCI 12V", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
|
||||
/// Power
|
||||
"PCPC": Sensor_t(name: "CPU Package", group: SensorGroup.CPU.rawValue, type: SensorType.Power.rawValue),
|
||||
"PCPT": Sensor_t(name: "CPU Package total", group: SensorGroup.CPU.rawValue, type: SensorType.Power.rawValue),
|
||||
"PC0R": Sensor_t(name: "CPU Computing high side", group: SensorGroup.CPU.rawValue, type: SensorType.Power.rawValue),
|
||||
|
||||
"PCPG": Sensor_t(name: "GPU Intel Graphics", group: SensorGroup.GPU.rawValue, type: SensorType.Power.rawValue),
|
||||
"PG0R": Sensor_t(name: "GPU", group: SensorGroup.GPU.rawValue, type: SensorType.Power.rawValue),
|
||||
|
||||
"PPBR": Sensor_t(name: "Battery", group: SensorGroup.Sensor.rawValue, type: SensorType.Power.rawValue),
|
||||
"PDTR": Sensor_t(name: "DC In", group: SensorGroup.Sensor.rawValue, type: SensorType.Power.rawValue),
|
||||
"PSTR": Sensor_t(name: "System total", group: SensorGroup.Sensor.rawValue, type: SensorType.Power.rawValue),
|
||||
]
|
||||
@@ -1,208 +0,0 @@
|
||||
//
|
||||
// TemperatureMenu.swift
|
||||
// Stats
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 03/04/2020.
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
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()
|
||||
|
||||
if defaults.object(forKey: name) != nil {
|
||||
menu.state = defaults.bool(forKey: name) ? NSControl.StateValue.on : NSControl.StateValue.off
|
||||
} else {
|
||||
menu.state = NSControl.StateValue.on
|
||||
}
|
||||
menu.target = self
|
||||
|
||||
let sensor_1: NSMenuItem = NSMenuItem(title: "Sensor #1", action: nil, keyEquivalent: "")
|
||||
sensor_1.target = self
|
||||
sensor_1.submenu = NSMenu()
|
||||
|
||||
let sensor_2: NSMenuItem = NSMenuItem(title: "Sensor #2", action: nil, keyEquivalent: "")
|
||||
sensor_2.target = self
|
||||
sensor_2.submenu = NSMenu()
|
||||
|
||||
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 {
|
||||
for widgetMenu in view.menus {
|
||||
submenu.addItem(widgetMenu)
|
||||
}
|
||||
}
|
||||
|
||||
if self.enabled {
|
||||
menu.submenu = submenu
|
||||
}
|
||||
}
|
||||
|
||||
@objc func toggle(_ sender: NSMenuItem) {
|
||||
let state = sender.state != NSControl.StateValue.on
|
||||
sender.state = sender.state == NSControl.StateValue.on ? NSControl.StateValue.off : NSControl.StateValue.on
|
||||
self.defaults.set(state, forKey: name)
|
||||
self.enabled = state
|
||||
menuBar!.reload(name: self.name)
|
||||
|
||||
if !state {
|
||||
menu.submenu = nil
|
||||
} else {
|
||||
menu.submenu = submenu
|
||||
}
|
||||
|
||||
self.restart()
|
||||
}
|
||||
|
||||
@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 {
|
||||
item.state = NSControl.StateValue.off
|
||||
}
|
||||
|
||||
sender.state = state ? NSControl.StateValue.off : NSControl.StateValue.on
|
||||
self.defaults.set(originalName, forKey: "\(name)_value_1")
|
||||
self.value_1 = originalName
|
||||
self.initWidget()
|
||||
self.initMenu()
|
||||
menuBar!.reload(name: self.name)
|
||||
}
|
||||
|
||||
@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 {
|
||||
item.state = NSControl.StateValue.off
|
||||
}
|
||||
|
||||
sender.state = state ? NSControl.StateValue.off : NSControl.StateValue.on
|
||||
self.defaults.set(originalName, forKey: "\(name)_value_2")
|
||||
self.value_2 = originalName
|
||||
self.initWidget()
|
||||
self.initMenu()
|
||||
menuBar!.reload(name: self.name)
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
//
|
||||
// TemperatureReader.swift
|
||||
// Stats
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 03/04/2020.
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
import IOKit
|
||||
import Foundation
|
||||
|
||||
class TemperatureReader: Reader {
|
||||
public var name: String = "Temperature"
|
||||
public var enabled: Bool = true
|
||||
public var available: Bool = true
|
||||
public var optional: Bool = false
|
||||
public var initialized: Bool = false
|
||||
|
||||
public var callback: (Temperatures) -> Void = {_ in}
|
||||
|
||||
init(_ updater: @escaping (Temperatures) -> Void) {
|
||||
self.callback = updater
|
||||
|
||||
if self.available {
|
||||
DispatchQueue.global(qos: .default).async {
|
||||
self.read()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func read() {
|
||||
if !self.enabled && self.initialized { return }
|
||||
self.initialized = true
|
||||
|
||||
var temperatures: Temperatures = Temperatures()
|
||||
GetTemperatures(&temperatures)
|
||||
|
||||
self.callback(temperatures)
|
||||
}
|
||||
|
||||
func toggleEnable(_ value: Bool) {
|
||||
self.enabled = value
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// DoubleRow.swift
|
||||
// Sensors.swift
|
||||
// Stats
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 03/04/2020.
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
class TemperatureWidget: NSView, Widget {
|
||||
public var name: String = "Temperature"
|
||||
class SensorsWidget: NSView, Widget {
|
||||
public var name: String = "Sensors"
|
||||
public var menus: [NSMenuItem] = []
|
||||
|
||||
private var value: [Double] = []
|
||||
@@ -84,10 +84,10 @@ class TemperatureWidget: NSView, Widget {
|
||||
func setValue(data: [Double]) {
|
||||
if self.value != data && data.count == 2 {
|
||||
self.value = data
|
||||
|
||||
|
||||
self.topValueView.stringValue = "\(Int(self.value[0]))°"
|
||||
self.bottomValueView.stringValue = "\(Int(self.value[1]))°"
|
||||
|
||||
|
||||
self.topValueView.textColor = self.value[0].temperatureColor(color: self.color)
|
||||
self.bottomValueView.textColor = self.value[1].temperatureColor(color: self.color)
|
||||
}
|
||||
@@ -23,7 +23,7 @@ protocol Widget {
|
||||
typealias WidgetType = Float
|
||||
struct Widgets {
|
||||
static let Mini: WidgetType = 0.0
|
||||
static let Temperature: WidgetType = 0.1
|
||||
static let Sensors: WidgetType = 0.1
|
||||
|
||||
static let Chart: WidgetType = 1.0
|
||||
static let ChartWithValue: WidgetType = 1.1
|
||||
|
||||
@@ -295,15 +295,48 @@ class ChartsNetworkAxisFormatter: IAxisValueFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
public extension FourCharCode {
|
||||
init(fromString str: String) {
|
||||
precondition(str.count == 4)
|
||||
|
||||
self = str.utf8.reduce(0) { sum, character in
|
||||
return sum << 8 | UInt32(character)
|
||||
}
|
||||
}
|
||||
|
||||
func toString() -> String {
|
||||
return String(describing: UnicodeScalar(self >> 24 & 0xff)!) +
|
||||
String(describing: UnicodeScalar(self >> 16 & 0xff)!) +
|
||||
String(describing: UnicodeScalar(self >> 8 & 0xff)!) +
|
||||
String(describing: UnicodeScalar(self & 0xff)!)
|
||||
}
|
||||
}
|
||||
|
||||
extension UInt32 {
|
||||
init(bytes: (UInt8, UInt8, UInt8, UInt8)) {
|
||||
self = UInt32(bytes.0) << 24 | UInt32(bytes.1) << 16 | UInt32(bytes.2) << 8 | UInt32(bytes.3)
|
||||
}
|
||||
}
|
||||
|
||||
extension FloatingPoint {
|
||||
init?(_ bytes: [UInt8]) {
|
||||
self = bytes.withUnsafeBytes {
|
||||
return $0.load(fromByteOffset: 0, as: Self.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NSMenuItem {
|
||||
private static var _extraString = [String:String]()
|
||||
|
||||
var extraString: String {
|
||||
get {
|
||||
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
|
||||
return NSMenuItem._extraString[tmpAddress] ?? ""
|
||||
}
|
||||
set(newValue) {
|
||||
let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
|
||||
NSMenuItem._extraString[tmpAddress] = newValue
|
||||
}
|
||||
|
||||
return dict
|
||||
}
|
||||
}
|
||||
|
||||
255
Stats/libs/SMC.c
255
Stats/libs/SMC.c
@@ -1,255 +0,0 @@
|
||||
//
|
||||
// SMC.c
|
||||
// Stats
|
||||
//
|
||||
// SMC code borrowed from https://github.com/lavoiesl/osx-cpu-temp.
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 03/04/2020.
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include "SMC.h"
|
||||
|
||||
static io_connect_t conn;
|
||||
|
||||
UInt32 _strtoul(char* str, int size, int base) {
|
||||
UInt32 total = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (base == 16)
|
||||
total += str[i] << (size - 1 - i) * 8;
|
||||
else
|
||||
total += (unsigned char)(str[i] << (size - 1 - i) * 8);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
void _ultostr(char* str, UInt32 val) {
|
||||
str[0] = '\0';
|
||||
sprintf(str, "%c%c%c%c",
|
||||
(unsigned int)val >> 24,
|
||||
(unsigned int)val >> 16,
|
||||
(unsigned int)val >> 8,
|
||||
(unsigned int)val);
|
||||
}
|
||||
|
||||
void t(void * refcon,
|
||||
io_service_t service,
|
||||
uint32_t messageType,
|
||||
void * messageArgument) {
|
||||
printf("Hmmmm");
|
||||
}
|
||||
|
||||
kern_return_t SMCOpen(void) {
|
||||
kern_return_t result;
|
||||
io_iterator_t iterator;
|
||||
io_object_t device;
|
||||
|
||||
CFMutableDictionaryRef matchingDictionary = IOServiceMatching("AppleSMC");
|
||||
result = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &iterator);
|
||||
if (result != kIOReturnSuccess) {
|
||||
printf("Error: IOServiceGetMatchingServices() = %08x\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
device = IOIteratorNext(iterator);
|
||||
IOObjectRelease(iterator);
|
||||
if (device == 0) {
|
||||
printf("Error: no SMC found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
result = IOServiceOpen(device, mach_task_self(), 0, &conn);
|
||||
IOObjectRelease(device);
|
||||
if (result != kIOReturnSuccess) {
|
||||
printf("Error: IOServiceOpen() = %08x\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return kIOReturnSuccess;
|
||||
}
|
||||
|
||||
kern_return_t SMCClose(void) {
|
||||
return IOServiceClose(conn);
|
||||
}
|
||||
|
||||
kern_return_t SMCCall(int index, SMCKeyData_t* inputStructure, SMCKeyData_t* outputStructure) {
|
||||
size_t structureInputSize;
|
||||
size_t structureOutputSize;
|
||||
|
||||
structureInputSize = sizeof(SMCKeyData_t);
|
||||
structureOutputSize = sizeof(SMCKeyData_t);
|
||||
|
||||
#if MAC_OS_X_VERSION_10_5
|
||||
return IOConnectCallStructMethod(conn, index,
|
||||
// inputStructure
|
||||
inputStructure, structureInputSize,
|
||||
// ouputStructure
|
||||
outputStructure, &structureOutputSize);
|
||||
#else
|
||||
return IOConnectMethodStructureIStructureO(conn, index,
|
||||
structureInputSize, /* structureInputSize */
|
||||
&structureOutputSize, /* structureOutputSize */
|
||||
inputStructure, /* inputStructure */
|
||||
outputStructure); /* ouputStructure */
|
||||
#endif
|
||||
}
|
||||
|
||||
kern_return_t SMCReadKey(UInt32Char_t key, SMCVal_t* val) {
|
||||
kern_return_t result;
|
||||
SMCKeyData_t inputStructure;
|
||||
SMCKeyData_t outputStructure;
|
||||
|
||||
memset(&inputStructure, 0, sizeof(SMCKeyData_t));
|
||||
memset(&outputStructure, 0, sizeof(SMCKeyData_t));
|
||||
memset(val, 0, sizeof(SMCVal_t));
|
||||
|
||||
inputStructure.key = _strtoul(key, 4, 16);
|
||||
inputStructure.data8 = SMC_CMD_READ_KEYINFO;
|
||||
|
||||
result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
|
||||
if (result != kIOReturnSuccess)
|
||||
return result;
|
||||
|
||||
val->dataSize = outputStructure.keyInfo.dataSize;
|
||||
_ultostr(val->dataType, outputStructure.keyInfo.dataType);
|
||||
inputStructure.keyInfo.dataSize = val->dataSize;
|
||||
inputStructure.data8 = SMC_CMD_READ_BYTES;
|
||||
|
||||
result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
|
||||
if (result != kIOReturnSuccess)
|
||||
return result;
|
||||
|
||||
memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes));
|
||||
|
||||
return kIOReturnSuccess;
|
||||
}
|
||||
|
||||
double GetTemperature(char* key) {
|
||||
SMCVal_t val;
|
||||
kern_return_t result;
|
||||
|
||||
result = SMCReadKey(key, &val);
|
||||
if (result == kIOReturnSuccess) {
|
||||
if (val.dataSize > 0) {
|
||||
if (strcmp(val.dataType, DATATYPE_SP78) == 0) {
|
||||
int intValue = val.bytes[0] * 256 + (unsigned char)val.bytes[1];
|
||||
return intValue / 256.0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("Error: SMCReadKey() = %08x\n", result);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
result = SMCReadKey(key, &val);
|
||||
if (result == kIOReturnSuccess) {
|
||||
if (val.dataSize > 0) {
|
||||
if (strcmp(val.dataType, DATATYPE_FPE2) == 0) {
|
||||
return ntohs(*(UInt16*)val.bytes) / 4.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1.f;
|
||||
}
|
||||
|
||||
|
||||
int64_t GetCPUFrequency() {
|
||||
int mib[2];
|
||||
unsigned int freq;
|
||||
size_t len;
|
||||
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_CPU_FREQ;
|
||||
len = sizeof(freq);
|
||||
sysctl(mib, 2, &freq, &len, NULL, 0);
|
||||
|
||||
return freq;
|
||||
}
|
||||
273
Stats/libs/SMC.h
273
Stats/libs/SMC.h
@@ -1,273 +0,0 @@
|
||||
//
|
||||
// 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;
|
||||
254
Stats/libs/SMC.swift
Normal file
254
Stats/libs/SMC.swift
Normal file
@@ -0,0 +1,254 @@
|
||||
//
|
||||
// SMC.swift
|
||||
// Stats
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 05/04/2020.
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
import IOKit
|
||||
|
||||
enum SMCDataType: String {
|
||||
case UI32 = "ui32"
|
||||
case SP78 = "sp78"
|
||||
case SP87 = "sp87"
|
||||
case FLT = "flt "
|
||||
case FPE2 = "fpe2"
|
||||
}
|
||||
|
||||
enum SMCKeys: UInt8 {
|
||||
case KERNEL_INDEX = 2
|
||||
case READ_BYTES = 5
|
||||
case WRITE_BYTES = 6
|
||||
case READ_INDEX = 8
|
||||
case READ_KEYINFO = 9
|
||||
case READ_PLIMIT = 11
|
||||
case READ_VERS = 12
|
||||
}
|
||||
|
||||
struct SMCKeyData_t {
|
||||
typealias SMCBytes_t = (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
|
||||
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
|
||||
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
|
||||
UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8,
|
||||
UInt8, UInt8, UInt8, UInt8)
|
||||
|
||||
struct vers_t {
|
||||
var major: CUnsignedChar = 0
|
||||
var minor: CUnsignedChar = 0
|
||||
var build: CUnsignedChar = 0
|
||||
var reserved: CUnsignedChar = 0
|
||||
var release: CUnsignedShort = 0
|
||||
}
|
||||
|
||||
struct LimitData_t {
|
||||
var version: UInt16 = 0
|
||||
var length: UInt16 = 0
|
||||
var cpuPLimit: UInt32 = 0
|
||||
var gpuPLimit: UInt32 = 0
|
||||
var memPLimit: UInt32 = 0
|
||||
}
|
||||
|
||||
struct keyInfo_t {
|
||||
var dataSize: IOByteCount = 0
|
||||
var dataType: UInt32 = 0
|
||||
var dataAttributes: UInt8 = 0
|
||||
}
|
||||
|
||||
var key: UInt32 = 0
|
||||
var vers = vers_t()
|
||||
var pLimitData = LimitData_t()
|
||||
var keyInfo = keyInfo_t()
|
||||
var padding: UInt16 = 0
|
||||
var result: UInt8 = 0
|
||||
var status: UInt8 = 0
|
||||
var data8: UInt8 = 0
|
||||
var data32: UInt32 = 0
|
||||
|
||||
var bytes: SMCBytes_t = (UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
|
||||
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
|
||||
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
|
||||
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
|
||||
UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0), UInt8(0),
|
||||
UInt8(0), UInt8(0))
|
||||
}
|
||||
|
||||
struct SMCVal_t {
|
||||
var key: String
|
||||
var dataSize: UInt32 = 0
|
||||
var dataType: String = ""
|
||||
var bytes: [UInt8] = Array(repeating: 0, count: 32)
|
||||
|
||||
init(_ key: String) {
|
||||
self.key = key
|
||||
}
|
||||
}
|
||||
|
||||
class SMCService {
|
||||
private var conn: io_connect_t = 0;
|
||||
|
||||
init() {
|
||||
|
||||
}
|
||||
|
||||
public func open() -> kern_return_t {
|
||||
var result: kern_return_t
|
||||
var iterator: io_iterator_t = 0
|
||||
let device: io_object_t
|
||||
|
||||
let matchingDictionary: CFMutableDictionary = IOServiceMatching("AppleSMC")
|
||||
result = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &iterator)
|
||||
if (result != kIOReturnSuccess) {
|
||||
print("Error IOServiceGetMatchingServices(): " + (String(cString: mach_error_string(result), encoding: String.Encoding.ascii) ?? "unknown error"))
|
||||
return result
|
||||
}
|
||||
|
||||
device = IOIteratorNext(iterator)
|
||||
IOObjectRelease(iterator)
|
||||
if (device == 0) {
|
||||
print("Error IOIteratorNext(): " + (String(cString: mach_error_string(result), encoding: String.Encoding.ascii) ?? "unknown error"))
|
||||
return kIOReturnError
|
||||
}
|
||||
|
||||
result = IOServiceOpen(device, mach_task_self_, 0, &conn)
|
||||
IOObjectRelease(device)
|
||||
if (result != kIOReturnSuccess) {
|
||||
print("Error IOServiceOpen(): " + (String(cString: mach_error_string(result), encoding: String.Encoding.ascii) ?? "unknown error"))
|
||||
return result
|
||||
}
|
||||
|
||||
return kIOReturnSuccess
|
||||
}
|
||||
|
||||
public func close() -> kern_return_t{
|
||||
return IOServiceClose(conn)
|
||||
}
|
||||
|
||||
public func getValue(_ key: String) -> Double? {
|
||||
var result: kern_return_t = 0
|
||||
var val: SMCVal_t = SMCVal_t(key)
|
||||
|
||||
result = read(&val)
|
||||
if result != kIOReturnSuccess {
|
||||
print("Error read(): " + (String(cString: mach_error_string(result), encoding: String.Encoding.ascii) ?? "unknown error"))
|
||||
return nil
|
||||
}
|
||||
|
||||
if (val.dataSize > 0) {
|
||||
if val.bytes.first(where: { $0 != 0}) == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch val.dataType {
|
||||
case SMCDataType.UI32.rawValue:
|
||||
return Double(UInt32(bytes: (val.bytes[0], val.bytes[1], val.bytes[2], val.bytes[3])))
|
||||
case SMCDataType.SP78.rawValue, SMCDataType.SP87.rawValue:
|
||||
let intValue: Double = Double(Int(val.bytes[0]) * 256 + Int(val.bytes[1]))
|
||||
return Double(intValue / 256.0)
|
||||
case SMCDataType.FLT.rawValue:
|
||||
let value: Float? = Float(val.bytes)
|
||||
if value != nil {
|
||||
return Double(value!)
|
||||
}
|
||||
return nil
|
||||
case SMCDataType.FPE2.rawValue:
|
||||
// ntohs(*(UInt16*)val.bytes) / 4.0;
|
||||
print("FPE2")
|
||||
break
|
||||
default:
|
||||
print("unsupported data type \(val.dataType)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
private func read(_ value: UnsafeMutablePointer<SMCVal_t>) -> kern_return_t {
|
||||
var result: kern_return_t = 0
|
||||
var input = SMCKeyData_t()
|
||||
var output = SMCKeyData_t()
|
||||
|
||||
input.key = FourCharCode(fromString: value.pointee.key)
|
||||
input.data8 = SMCKeys.READ_KEYINFO.rawValue
|
||||
|
||||
result = call(SMCKeys.KERNEL_INDEX.rawValue, input: &input, output: &output)
|
||||
if result != kIOReturnSuccess {
|
||||
print("Error call(READ_KEYINFO): " + (String(cString: mach_error_string(result), encoding: String.Encoding.ascii) ?? "unknown error"))
|
||||
return result
|
||||
}
|
||||
|
||||
value.pointee.dataSize = output.keyInfo.dataSize
|
||||
value.pointee.dataType = output.keyInfo.dataType.toString()
|
||||
input.keyInfo.dataSize = output.keyInfo.dataSize
|
||||
input.data8 = SMCKeys.READ_BYTES.rawValue
|
||||
|
||||
result = call(SMCKeys.KERNEL_INDEX.rawValue, input: &input, output: &output)
|
||||
if result != kIOReturnSuccess {
|
||||
print("Error call(READ_BYTES): " + (String(cString: mach_error_string(result), encoding: String.Encoding.ascii) ?? "unknown error"))
|
||||
return result
|
||||
}
|
||||
|
||||
memcpy(&value.pointee.bytes, &output.bytes, Int(value.pointee.dataSize))
|
||||
|
||||
return kIOReturnSuccess;
|
||||
}
|
||||
|
||||
private func call(_ index: UInt8, input: inout SMCKeyData_t, output: inout SMCKeyData_t) -> kern_return_t {
|
||||
let inputSize = MemoryLayout<SMCKeyData_t>.stride
|
||||
var outputSize = MemoryLayout<SMCKeyData_t>.stride
|
||||
|
||||
return IOConnectCallStructMethod(
|
||||
conn,
|
||||
UInt32(index),
|
||||
&input,
|
||||
inputSize,
|
||||
&output,
|
||||
&outputSize
|
||||
)
|
||||
}
|
||||
|
||||
public func getAllKeys() -> [String] {
|
||||
var list: [String] = []
|
||||
|
||||
let keysNum: Double? = smc.getValue("#KEY")
|
||||
if keysNum == nil {
|
||||
print("ERROR no keys count found")
|
||||
return list
|
||||
}
|
||||
|
||||
var result: kern_return_t = 0
|
||||
var input: SMCKeyData_t = SMCKeyData_t()
|
||||
var output: SMCKeyData_t = SMCKeyData_t()
|
||||
|
||||
for i in 0...Int(keysNum!) {
|
||||
input = SMCKeyData_t()
|
||||
output = SMCKeyData_t()
|
||||
|
||||
input.data8 = SMCKeys.READ_INDEX.rawValue
|
||||
input.data32 = UInt32(i)
|
||||
|
||||
result = call(SMCKeys.KERNEL_INDEX.rawValue, input: &input, output: &output)
|
||||
if result != kIOReturnSuccess {
|
||||
continue
|
||||
}
|
||||
|
||||
list.append(output.key.toString())
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
//int64_t GetCPUFrequency() {
|
||||
// int mib[2];
|
||||
// unsigned int freq;
|
||||
// size_t len;
|
||||
//
|
||||
// mib[0] = CTL_HW;
|
||||
// mib[1] = HW_CPU_FREQ;
|
||||
// len = sizeof(freq);
|
||||
// sysctl(mib, 2, &freq, &len, NULL, 0);
|
||||
//
|
||||
// return freq;
|
||||
//}
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "SMC.h"
|
||||
|
||||
//! Project version number for SMCKit.
|
||||
FOUNDATION_EXPORT double SMCKitVersionNumber;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user