// // readers.swift // Sensors // // Created by Serhiy Mytrovtsiy on 17/06/2020. // Using Swift 5.0. // Running on macOS 10.15. // // Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved. // import Cocoa import Kit import IOKit.hid internal class SensorsReader: Reader<[Sensor_p]> { internal var list: [Sensor_p] = [] } internal class x86_SensorsReader: SensorsReader { init() { super.init() var available: [String] = SMC.shared.getAllKeys() var list: [Sensor] = [] if let count = SMC.shared.getValue("FNum") { debug("Found \(Int(count)) fans", log: self.log) for i in 0.. Bool in switch key.prefix(1) { case "T", "V", "P": return true default: return false } }) SensorsList.forEach { (s: Sensor) in if let idx = available.firstIndex(where: { $0 == s.key }) { list.append(s) available.remove(at: idx) } } SensorsList.filter{ $0.key.contains("%") }.forEach { (s: Sensor) in var index = 1 for i in 0..<10 { let key = s.key.replacingOccurrences(of: "%", with: "\(i)") if available.firstIndex(where: { $0 == key }) != nil { var sensor = s.copy() sensor.key = key sensor.name = s.name.replacingOccurrences(of: "%", with: "\(index)") list.append(sensor) index += 1 } } } for sensor in list { if let newValue = SMC.shared.getValue(sensor.key) { if let idx = list.firstIndex(where: { $0.key == sensor.key }) { list[idx].value = newValue } } } self.list += list.filter({ (s: Sensor) -> Bool in if s.type == .temperature && s.value > 110 { return false } return true }) } public override func read() { for i in 0.. FanMode { let fansMode: Int = Int(SMC.shared.getValue("FS! ") ?? 0) var mode: FanMode = .automatic if fansMode == 0 { mode = .automatic } else if fansMode == 3 { mode = .forced } else if fansMode == 1 && id == 0 { mode = .forced } else if fansMode == 2 && id == 1 { mode = .forced } return mode } } internal class AppleSilicon_SensorsReader: SensorsReader { private let types: [SensorType] = [.temperature, .current, .voltage] init() { super.init() for type in types { self.fetch(type: type) } self.list = self.list.filter({ (s: Sensor_p) -> Bool in switch s.type { case .temperature: return s.value < 110 && s.value >= 0 case .voltage: return s.value < 300 && s.value >= 0 case .current: return s.value < 100 && s.value >= 0 default: return true } }) self.list = self.list.sorted { $0.name.lowercased() < $1.name.lowercased() } } public override func read() { for type in types { self.fetch(type: type) } self.callback(self.list) } private func fetch(type: SensorType) { var page: Int32 = 0 var usage: Int32 = 0 var eventType: Int32 = kIOHIDEventTypeTemperature // usagePage: // kHIDPage_AppleVendor = 0xff00, // kHIDPage_AppleVendorTemperatureSensor = 0xff05, // kHIDPage_AppleVendorPowerSensor = 0xff08, // kHIDPage_GenericDesktop // // usage: // kHIDUsage_AppleVendor_TemperatureSensor = 0x0005, // kHIDUsage_AppleVendorPowerSensor_Current = 0x0002, // kHIDUsage_AppleVendorPowerSensor_Voltage = 0x0003, // kHIDUsage_GD_Keyboard // switch type { case .temperature: page = 0xff00 usage = 0x0005 eventType = kIOHIDEventTypeTemperature case .current: page = 0xff08 usage = 0x0003 eventType = kIOHIDEventTypePower case .voltage: page = 0xff08 usage = 0x0002 eventType = kIOHIDEventTypePower case .power: break case .fan: break } if let list = AppleSiliconSensors(page, usage, eventType) { list.forEach { (key, value) in if let name = key as? String, let value = value as? Double { if let idx = self.list.firstIndex(where: { $0.name == name }) { self.list[idx].value = value } else { self.list.append(Sensor( key: name, name: name, value: value, group: .system, type: type )) } } } } return } private func createDeviceMatchingDictionary(usagePage: Int, usage: Int) -> CFMutableDictionary { let dict = [ kIOHIDPrimaryUsageKey: usage, kIOHIDPrimaryUsagePageKey: usagePage ] as NSDictionary return dict.mutableCopy() as! NSMutableDictionary } }