Replaced the IOHID and SMC interfaces. Replaced the sensors window.
This commit is contained in:
@@ -7,27 +7,43 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
05221E62266FD5BD007246FF /* AppleSilicon.m in Sources */ = {isa = PBXBuildFile; fileRef = 05221E61266FD5BD007246FF /* AppleSilicon.m */; };
|
||||
05221E8626700772007246FF /* DictionaryIsEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05221E8526700772007246FF /* DictionaryIsEmpty.swift */; };
|
||||
05221E88267009A8007246FF /* SensorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05221E87267009A8007246FF /* SensorViewController.swift */; };
|
||||
05221E8B26700A57007246FF /* SensorViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05221E8926700A57007246FF /* SensorViewController.xib */; };
|
||||
052FBC34251ECA8600C4322E /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 052FBC33251ECA8600C4322E /* IOKit.framework */; };
|
||||
052FBC38251ECB8B00C4322E /* SMC.c in Sources */ = {isa = PBXBuildFile; fileRef = 052FBC37251ECB8B00C4322E /* SMC.c */; };
|
||||
052FBCA3251EE43B00C4322E /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 052FBCA2251EE43B00C4322E /* PreferencesWindowController.swift */; };
|
||||
052FBCA7251EE46700C4322E /* PreferencesWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 052FBCA5251EE46700C4322E /* PreferencesWindowController.xib */; };
|
||||
052FBCD4251F842C00C4322E /* SpeedTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 052FBCCF251F842C00C4322E /* SpeedTemplate.pdf */; };
|
||||
052FBCD5251F842C00C4322E /* CPUTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 052FBCD1251F842C00C4322E /* CPUTemplate.pdf */; };
|
||||
052FBCD6251F842C00C4322E /* TemperatureTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 052FBCD2251F842C00C4322E /* TemperatureTemplate.pdf */; };
|
||||
052FBCD7251F842C00C4322E /* SchedulerTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 052FBCD3251F842C00C4322E /* SchedulerTemplate.pdf */; };
|
||||
05566A082990F85200E7A5F1 /* SensorIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669EA2990F85200E7A5F1 /* SensorIcon.swift */; };
|
||||
05566A092990F85200E7A5F1 /* SensorsWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669EB2990F85200E7A5F1 /* SensorsWindowController.swift */; };
|
||||
05566A0A2990F85200E7A5F1 /* VoltageTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 055669ED2990F85200E7A5F1 /* VoltageTemplate.pdf */; };
|
||||
05566A0B2990F85200E7A5F1 /* CurrentTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 055669EE2990F85200E7A5F1 /* CurrentTemplate.pdf */; };
|
||||
05566A0C2990F85200E7A5F1 /* ThermalTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 055669EF2990F85200E7A5F1 /* ThermalTemplate.pdf */; };
|
||||
05566A0D2990F85200E7A5F1 /* SensorValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669F02990F85200E7A5F1 /* SensorValue.swift */; };
|
||||
05566A0E2990F85200E7A5F1 /* SensorHistoryData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669F12990F85200E7A5F1 /* SensorHistoryData.swift */; };
|
||||
05566A0F2990F85200E7A5F1 /* ArrayIsNotEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669F22990F85200E7A5F1 /* ArrayIsNotEmpty.swift */; };
|
||||
05566A102990F85200E7A5F1 /* SensorItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669F32990F85200E7A5F1 /* SensorItem.swift */; };
|
||||
05566A112990F85200E7A5F1 /* SensorItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = 055669F42990F85200E7A5F1 /* SensorItem.xib */; };
|
||||
05566A122990F85200E7A5F1 /* SensorsWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 055669F62990F85200E7A5F1 /* SensorsWindowController.xib */; };
|
||||
05566A132990F85200E7A5F1 /* ArrayIsEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669F82990F85200E7A5F1 /* ArrayIsEmpty.swift */; };
|
||||
05566A142990F85200E7A5F1 /* SensorGraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669F92990F85200E7A5F1 /* SensorGraphView.swift */; };
|
||||
05566A152990F85200E7A5F1 /* NSImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669FA2990F85200E7A5F1 /* NSImage.swift */; };
|
||||
05566A162990F85200E7A5F1 /* Sensors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669FB2990F85200E7A5F1 /* Sensors.swift */; };
|
||||
05566A172990F85200E7A5F1 /* Synchronizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669FC2990F85200E7A5F1 /* Synchronizable.swift */; };
|
||||
05566A182990F85200E7A5F1 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055669FD2990F85200E7A5F1 /* Colors.swift */; };
|
||||
05566A192990F85200E7A5F1 /* IOHIDData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05566A012990F85200E7A5F1 /* IOHIDData.swift */; };
|
||||
05566A1A2990F85200E7A5F1 /* IOHID.m in Sources */ = {isa = PBXBuildFile; fileRef = 05566A022990F85200E7A5F1 /* IOHID.m */; };
|
||||
05566A1B2990F85200E7A5F1 /* SMC.m in Sources */ = {isa = PBXBuildFile; fileRef = 05566A042990F85200E7A5F1 /* SMC.m */; };
|
||||
05566A1C2990F85200E7A5F1 /* SMCData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05566A052990F85200E7A5F1 /* SMCData.swift */; };
|
||||
055A9320252778C10070F771 /* InfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055A931F252778C10070F771 /* InfoViewController.swift */; };
|
||||
055A9323252778D00070F771 /* InfoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 055A9321252778D00070F771 /* InfoViewController.xib */; };
|
||||
055A932525277E9E0070F771 /* IntegerToString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055A932425277E9E0070F771 /* IntegerToString.swift */; };
|
||||
055A932725277F6E0070F771 /* TemperatureToString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055A932625277F6E0070F771 /* TemperatureToString.swift */; };
|
||||
055A932925277F990070F771 /* PercentToString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055A932825277F990070F771 /* PercentToString.swift */; };
|
||||
055A932B252780FD0070F771 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055A932A252780FD0070F771 /* GraphView.swift */; };
|
||||
057BA11728884BCD00324D16 /* CurrentTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 057BA11328884BCD00324D16 /* CurrentTemplate.pdf */; };
|
||||
057BA11828884BCD00324D16 /* ThermalTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 057BA11528884BCD00324D16 /* ThermalTemplate.pdf */; };
|
||||
057BA11928884BCD00324D16 /* VoltageTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 057BA11628884BCD00324D16 /* VoltageTemplate.pdf */; };
|
||||
057F8B00251D22360048F1E1 /* StatusIconTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 057F8AFF251D22360048F1E1 /* StatusIconTemplate.pdf */; };
|
||||
057F8B0C251D273E0048F1E1 /* AboutWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 057F8B0B251D273E0048F1E1 /* AboutWindowController.swift */; };
|
||||
057F8B11251D274C0048F1E1 /* NSApplication+LaunchServices.m in Sources */ = {isa = PBXBuildFile; fileRef = 057F8B10251D274C0048F1E1 /* NSApplication+LaunchServices.m */; };
|
||||
@@ -35,20 +51,6 @@
|
||||
057F8B1B251D2A970048F1E1 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 057F8B1A251D2A970048F1E1 /* Icon.icns */; };
|
||||
057F8B65251D2D5F0048F1E1 /* GitHubUpdates.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 057F8B5C251D2D510048F1E1 /* GitHubUpdates.framework */; };
|
||||
057F8B67251D2D680048F1E1 /* GitHubUpdates.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 057F8B5C251D2D510048F1E1 /* GitHubUpdates.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
05A012C226FB9AEB00D3F6B6 /* SensorIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A012B026FB9AEB00D3F6B6 /* SensorIcon.swift */; };
|
||||
05A012C326FB9AEB00D3F6B6 /* SensorData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A012B126FB9AEB00D3F6B6 /* SensorData.swift */; };
|
||||
05A012C426FB9AEB00D3F6B6 /* SensorsWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A012B226FB9AEB00D3F6B6 /* SensorsWindowController.swift */; };
|
||||
05A012C626FB9AEB00D3F6B6 /* SensorValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A012B526FB9AEB00D3F6B6 /* SensorValue.swift */; };
|
||||
05A012C826FB9AEB00D3F6B6 /* ArrayIsNotEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A012B726FB9AEB00D3F6B6 /* ArrayIsNotEmpty.swift */; };
|
||||
05A012C926FB9AEB00D3F6B6 /* SensorItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A012B826FB9AEB00D3F6B6 /* SensorItem.swift */; };
|
||||
05A012CA26FB9AEB00D3F6B6 /* ArrayIsEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A012BA26FB9AEB00D3F6B6 /* ArrayIsEmpty.swift */; };
|
||||
05A012CB26FB9AEB00D3F6B6 /* SensorGraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A012BB26FB9AEB00D3F6B6 /* SensorGraphView.swift */; };
|
||||
05A012CC26FB9AEB00D3F6B6 /* NSImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A012BC26FB9AEB00D3F6B6 /* NSImage.swift */; };
|
||||
05A012CD26FB9AEB00D3F6B6 /* Synchronizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A012BD26FB9AEB00D3F6B6 /* Synchronizable.swift */; };
|
||||
05A012CE26FB9AEB00D3F6B6 /* Sensors.m in Sources */ = {isa = PBXBuildFile; fileRef = 05A012BE26FB9AEB00D3F6B6 /* Sensors.m */; };
|
||||
05A012CF26FB9AEB00D3F6B6 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A012BF26FB9AEB00D3F6B6 /* Colors.swift */; };
|
||||
05A012D626FB9B8B00D3F6B6 /* SensorItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05A012D226FB9B8B00D3F6B6 /* SensorItem.xib */; };
|
||||
05A012D726FB9B8B00D3F6B6 /* SensorsWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05A012D426FB9B8B00D3F6B6 /* SensorsWindowController.xib */; };
|
||||
05AA407A251CF3D200106CEA /* ApplicationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05AA4079251CF3D200106CEA /* ApplicationDelegate.swift */; };
|
||||
05AA407F251CF3D600106CEA /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05AA407D251CF3D600106CEA /* MainMenu.xib */; };
|
||||
05AA408D251CFA0600106CEA /* ThermalLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05AA408C251CFA0600106CEA /* ThermalLog.swift */; };
|
||||
@@ -102,29 +104,47 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
05221E60266FD5BD007246FF /* AppleSilicon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleSilicon.h; sourceTree = "<group>"; };
|
||||
05221E61266FD5BD007246FF /* AppleSilicon.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppleSilicon.m; sourceTree = "<group>"; };
|
||||
05221E8526700772007246FF /* DictionaryIsEmpty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryIsEmpty.swift; sourceTree = "<group>"; };
|
||||
05221E87267009A8007246FF /* SensorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SensorViewController.swift; sourceTree = "<group>"; };
|
||||
05221E8A26700A57007246FF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SensorViewController.xib; sourceTree = "<group>"; };
|
||||
052FBC32251EC69B00C4322E /* SMC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SMC.h; sourceTree = "<group>"; };
|
||||
052FBC33251ECA8600C4322E /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
|
||||
052FBC37251ECB8B00C4322E /* SMC.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SMC.c; sourceTree = "<group>"; };
|
||||
052FBCA2251EE43B00C4322E /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = "<group>"; };
|
||||
052FBCA6251EE46700C4322E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PreferencesWindowController.xib; sourceTree = "<group>"; };
|
||||
052FBCCF251F842C00C4322E /* SpeedTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = SpeedTemplate.pdf; sourceTree = "<group>"; };
|
||||
052FBCD1251F842C00C4322E /* CPUTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = CPUTemplate.pdf; sourceTree = "<group>"; };
|
||||
052FBCD2251F842C00C4322E /* TemperatureTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = TemperatureTemplate.pdf; sourceTree = "<group>"; };
|
||||
052FBCD3251F842C00C4322E /* SchedulerTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = SchedulerTemplate.pdf; sourceTree = "<group>"; };
|
||||
055669EA2990F85200E7A5F1 /* SensorIcon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorIcon.swift; sourceTree = "<group>"; };
|
||||
055669EB2990F85200E7A5F1 /* SensorsWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorsWindowController.swift; sourceTree = "<group>"; };
|
||||
055669ED2990F85200E7A5F1 /* VoltageTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = VoltageTemplate.pdf; sourceTree = "<group>"; };
|
||||
055669EE2990F85200E7A5F1 /* CurrentTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = CurrentTemplate.pdf; sourceTree = "<group>"; };
|
||||
055669EF2990F85200E7A5F1 /* ThermalTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = ThermalTemplate.pdf; sourceTree = "<group>"; };
|
||||
055669F02990F85200E7A5F1 /* SensorValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorValue.swift; sourceTree = "<group>"; };
|
||||
055669F12990F85200E7A5F1 /* SensorHistoryData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorHistoryData.swift; sourceTree = "<group>"; };
|
||||
055669F22990F85200E7A5F1 /* ArrayIsNotEmpty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayIsNotEmpty.swift; sourceTree = "<group>"; };
|
||||
055669F32990F85200E7A5F1 /* SensorItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorItem.swift; sourceTree = "<group>"; };
|
||||
055669F52990F85200E7A5F1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SensorItem.xib; sourceTree = "<group>"; };
|
||||
055669F72990F85200E7A5F1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SensorsWindowController.xib; sourceTree = "<group>"; };
|
||||
055669F82990F85200E7A5F1 /* ArrayIsEmpty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayIsEmpty.swift; sourceTree = "<group>"; };
|
||||
055669F92990F85200E7A5F1 /* SensorGraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorGraphView.swift; sourceTree = "<group>"; };
|
||||
055669FA2990F85200E7A5F1 /* NSImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSImage.swift; sourceTree = "<group>"; };
|
||||
055669FB2990F85200E7A5F1 /* Sensors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sensors.swift; sourceTree = "<group>"; };
|
||||
055669FC2990F85200E7A5F1 /* Synchronizable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Synchronizable.swift; sourceTree = "<group>"; };
|
||||
055669FD2990F85200E7A5F1 /* Colors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = "<group>"; };
|
||||
055669FF2990F85200E7A5F1 /* IOHID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOHID.h; sourceTree = "<group>"; };
|
||||
05566A002990F85200E7A5F1 /* IOHID-Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IOHID-Internal.h"; sourceTree = "<group>"; };
|
||||
05566A012990F85200E7A5F1 /* IOHIDData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IOHIDData.swift; sourceTree = "<group>"; };
|
||||
05566A022990F85200E7A5F1 /* IOHID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IOHID.m; sourceTree = "<group>"; };
|
||||
05566A042990F85200E7A5F1 /* SMC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMC.m; sourceTree = "<group>"; };
|
||||
05566A052990F85200E7A5F1 /* SMCData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SMCData.swift; sourceTree = "<group>"; };
|
||||
05566A062990F85200E7A5F1 /* SMC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMC.h; sourceTree = "<group>"; };
|
||||
05566A072990F85200E7A5F1 /* SMC-Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SMC-Internal.h"; sourceTree = "<group>"; };
|
||||
055A931F252778C10070F771 /* InfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoViewController.swift; sourceTree = "<group>"; };
|
||||
055A9322252778D00070F771 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/InfoViewController.xib; sourceTree = "<group>"; };
|
||||
055A932425277E9E0070F771 /* IntegerToString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegerToString.swift; sourceTree = "<group>"; };
|
||||
055A932625277F6E0070F771 /* TemperatureToString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemperatureToString.swift; sourceTree = "<group>"; };
|
||||
055A932825277F990070F771 /* PercentToString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PercentToString.swift; sourceTree = "<group>"; };
|
||||
055A932A252780FD0070F771 /* GraphView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = "<group>"; };
|
||||
057BA11328884BCD00324D16 /* CurrentTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = CurrentTemplate.pdf; sourceTree = "<group>"; };
|
||||
057BA11528884BCD00324D16 /* ThermalTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = ThermalTemplate.pdf; sourceTree = "<group>"; };
|
||||
057BA11628884BCD00324D16 /* VoltageTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = VoltageTemplate.pdf; sourceTree = "<group>"; };
|
||||
057F8AFF251D22360048F1E1 /* StatusIconTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = StatusIconTemplate.pdf; sourceTree = "<group>"; };
|
||||
057F8B0B251D273E0048F1E1 /* AboutWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutWindowController.swift; sourceTree = "<group>"; };
|
||||
057F8B0E251D274C0048F1E1 /* Hot-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Hot-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
@@ -179,22 +199,6 @@
|
||||
057F8B53251D2C840048F1E1 /* ccache.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ccache.sh; sourceTree = "<group>"; };
|
||||
057F8B54251D2C840048F1E1 /* Debug - zld.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Debug - zld.xcconfig"; sourceTree = "<group>"; };
|
||||
057F8B56251D2D510048F1E1 /* GitHubUpdates.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GitHubUpdates.xcodeproj; path = Submodules/GitHubUpdates/GitHubUpdates.xcodeproj; sourceTree = "<group>"; };
|
||||
05A012B026FB9AEB00D3F6B6 /* SensorIcon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorIcon.swift; sourceTree = "<group>"; };
|
||||
05A012B126FB9AEB00D3F6B6 /* SensorData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorData.swift; sourceTree = "<group>"; };
|
||||
05A012B226FB9AEB00D3F6B6 /* SensorsWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorsWindowController.swift; sourceTree = "<group>"; };
|
||||
05A012B426FB9AEB00D3F6B6 /* Sensors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sensors.h; sourceTree = "<group>"; };
|
||||
05A012B526FB9AEB00D3F6B6 /* SensorValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorValue.swift; sourceTree = "<group>"; };
|
||||
05A012B726FB9AEB00D3F6B6 /* ArrayIsNotEmpty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayIsNotEmpty.swift; sourceTree = "<group>"; };
|
||||
05A012B826FB9AEB00D3F6B6 /* SensorItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorItem.swift; sourceTree = "<group>"; };
|
||||
05A012B926FB9AEB00D3F6B6 /* IOHID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOHID.h; sourceTree = "<group>"; };
|
||||
05A012BA26FB9AEB00D3F6B6 /* ArrayIsEmpty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayIsEmpty.swift; sourceTree = "<group>"; };
|
||||
05A012BB26FB9AEB00D3F6B6 /* SensorGraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorGraphView.swift; sourceTree = "<group>"; };
|
||||
05A012BC26FB9AEB00D3F6B6 /* NSImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSImage.swift; sourceTree = "<group>"; };
|
||||
05A012BD26FB9AEB00D3F6B6 /* Synchronizable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Synchronizable.swift; sourceTree = "<group>"; };
|
||||
05A012BE26FB9AEB00D3F6B6 /* Sensors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sensors.m; sourceTree = "<group>"; };
|
||||
05A012BF26FB9AEB00D3F6B6 /* Colors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = "<group>"; };
|
||||
05A012D326FB9B8B00D3F6B6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SensorItem.xib; sourceTree = "<group>"; };
|
||||
05A012D526FB9B8B00D3F6B6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SensorsWindowController.xib; sourceTree = "<group>"; };
|
||||
05AA4076251CF3D200106CEA /* Hot.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Hot.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
05AA4079251CF3D200106CEA /* ApplicationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationDelegate.swift; sourceTree = "<group>"; };
|
||||
05AA407E251CF3D600106CEA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
@@ -226,13 +230,64 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
055669E92990F85200E7A5F1 /* SensorsWindow */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
055669EA2990F85200E7A5F1 /* SensorIcon.swift */,
|
||||
055669EB2990F85200E7A5F1 /* SensorsWindowController.swift */,
|
||||
055669EC2990F85200E7A5F1 /* Images */,
|
||||
055669F02990F85200E7A5F1 /* SensorValue.swift */,
|
||||
055669F12990F85200E7A5F1 /* SensorHistoryData.swift */,
|
||||
055669F22990F85200E7A5F1 /* ArrayIsNotEmpty.swift */,
|
||||
055669F32990F85200E7A5F1 /* SensorItem.swift */,
|
||||
055669F42990F85200E7A5F1 /* SensorItem.xib */,
|
||||
055669F62990F85200E7A5F1 /* SensorsWindowController.xib */,
|
||||
055669F82990F85200E7A5F1 /* ArrayIsEmpty.swift */,
|
||||
055669F92990F85200E7A5F1 /* SensorGraphView.swift */,
|
||||
055669FA2990F85200E7A5F1 /* NSImage.swift */,
|
||||
055669FB2990F85200E7A5F1 /* Sensors.swift */,
|
||||
055669FC2990F85200E7A5F1 /* Synchronizable.swift */,
|
||||
055669FD2990F85200E7A5F1 /* Colors.swift */,
|
||||
);
|
||||
path = SensorsWindow;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
055669EC2990F85200E7A5F1 /* Images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
055669ED2990F85200E7A5F1 /* VoltageTemplate.pdf */,
|
||||
055669EE2990F85200E7A5F1 /* CurrentTemplate.pdf */,
|
||||
055669EF2990F85200E7A5F1 /* ThermalTemplate.pdf */,
|
||||
);
|
||||
path = Images;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
055669FE2990F85200E7A5F1 /* IOHID */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
055669FF2990F85200E7A5F1 /* IOHID.h */,
|
||||
05566A002990F85200E7A5F1 /* IOHID-Internal.h */,
|
||||
05566A012990F85200E7A5F1 /* IOHIDData.swift */,
|
||||
05566A022990F85200E7A5F1 /* IOHID.m */,
|
||||
);
|
||||
path = IOHID;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05566A032990F85200E7A5F1 /* SMC */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05566A042990F85200E7A5F1 /* SMC.m */,
|
||||
05566A052990F85200E7A5F1 /* SMCData.swift */,
|
||||
05566A062990F85200E7A5F1 /* SMC.h */,
|
||||
05566A072990F85200E7A5F1 /* SMC-Internal.h */,
|
||||
);
|
||||
path = SMC;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
057F8AFE251D22360048F1E1 /* Images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05AD458F29092B8400A791C8 /* BatteryTemplate.pdf */,
|
||||
057BA11328884BCD00324D16 /* CurrentTemplate.pdf */,
|
||||
057BA11528884BCD00324D16 /* ThermalTemplate.pdf */,
|
||||
057BA11628884BCD00324D16 /* VoltageTemplate.pdf */,
|
||||
05AD459129092CEB00A791C8 /* TCalTemplate.pdf */,
|
||||
05B0DFA8267150F40068FF9B /* TCXCTemplate.pdf */,
|
||||
05B0DFA326714A830068FF9B /* eAccTemplate.pdf */,
|
||||
@@ -382,36 +437,6 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05A012AF26FB9AEB00D3F6B6 /* Sensors */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05A012BA26FB9AEB00D3F6B6 /* ArrayIsEmpty.swift */,
|
||||
05A012B726FB9AEB00D3F6B6 /* ArrayIsNotEmpty.swift */,
|
||||
05A012BF26FB9AEB00D3F6B6 /* Colors.swift */,
|
||||
05A012B926FB9AEB00D3F6B6 /* IOHID.h */,
|
||||
05A012B226FB9AEB00D3F6B6 /* SensorsWindowController.swift */,
|
||||
05A012BC26FB9AEB00D3F6B6 /* NSImage.swift */,
|
||||
05A012B126FB9AEB00D3F6B6 /* SensorData.swift */,
|
||||
05A012BB26FB9AEB00D3F6B6 /* SensorGraphView.swift */,
|
||||
05A012B026FB9AEB00D3F6B6 /* SensorIcon.swift */,
|
||||
05A012B826FB9AEB00D3F6B6 /* SensorItem.swift */,
|
||||
05A012B426FB9AEB00D3F6B6 /* Sensors.h */,
|
||||
05A012BE26FB9AEB00D3F6B6 /* Sensors.m */,
|
||||
05A012B526FB9AEB00D3F6B6 /* SensorValue.swift */,
|
||||
05A012BD26FB9AEB00D3F6B6 /* Synchronizable.swift */,
|
||||
);
|
||||
path = Sensors;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05A012D126FB9B8B00D3F6B6 /* Sensors */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05A012D226FB9B8B00D3F6B6 /* SensorItem.xib */,
|
||||
05A012D426FB9B8B00D3F6B6 /* SensorsWindowController.xib */,
|
||||
);
|
||||
path = Sensors;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05AA406D251CF3D200106CEA = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -447,7 +472,9 @@
|
||||
05AA4088251CF3F400106CEA /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05A012AF26FB9AEB00D3F6B6 /* Sensors */,
|
||||
055669FE2990F85200E7A5F1 /* IOHID */,
|
||||
055669E92990F85200E7A5F1 /* SensorsWindow */,
|
||||
05566A032990F85200E7A5F1 /* SMC */,
|
||||
057F8B0B251D273E0048F1E1 /* AboutWindowController.swift */,
|
||||
05AA4079251CF3D200106CEA /* ApplicationDelegate.swift */,
|
||||
05221E87267009A8007246FF /* SensorViewController.swift */,
|
||||
@@ -460,10 +487,6 @@
|
||||
057F8B10251D274C0048F1E1 /* NSApplication+LaunchServices.m */,
|
||||
055A932825277F990070F771 /* PercentToString.swift */,
|
||||
052FBCA2251EE43B00C4322E /* PreferencesWindowController.swift */,
|
||||
052FBC37251ECB8B00C4322E /* SMC.c */,
|
||||
052FBC32251EC69B00C4322E /* SMC.h */,
|
||||
05221E60266FD5BD007246FF /* AppleSilicon.h */,
|
||||
05221E61266FD5BD007246FF /* AppleSilicon.m */,
|
||||
055A932625277F6E0070F771 /* TemperatureToString.swift */,
|
||||
05BA0BA926F342DA00AA7BFC /* PressureToString.swift */,
|
||||
05AA408C251CFA0600106CEA /* ThermalLog.swift */,
|
||||
@@ -475,7 +498,6 @@
|
||||
05AA4089251CF3FC00106CEA /* UI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05A012D126FB9B8B00D3F6B6 /* Sensors */,
|
||||
057F8B13251D27650048F1E1 /* AboutWindowController.xib */,
|
||||
057F8AFE251D22360048F1E1 /* Images */,
|
||||
055A9321252778D00070F771 /* InfoViewController.xib */,
|
||||
@@ -571,28 +593,28 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
057BA11728884BCD00324D16 /* CurrentTemplate.pdf in Resources */,
|
||||
052FBCD4251F842C00C4322E /* SpeedTemplate.pdf in Resources */,
|
||||
05BA0BAD26F347A500AA7BFC /* PressureTemplate.pdf in Resources */,
|
||||
052FBCD6251F842C00C4322E /* TemperatureTemplate.pdf in Resources */,
|
||||
057F8B00251D22360048F1E1 /* StatusIconTemplate.pdf in Resources */,
|
||||
057F8B1B251D2A970048F1E1 /* Icon.icns in Resources */,
|
||||
052FBCD5251F842C00C4322E /* CPUTemplate.pdf in Resources */,
|
||||
05566A0C2990F85200E7A5F1 /* ThermalTemplate.pdf in Resources */,
|
||||
05221E8B26700A57007246FF /* SensorViewController.xib in Resources */,
|
||||
05AD459229092CEB00A791C8 /* TCalTemplate.pdf in Resources */,
|
||||
05A012D626FB9B8B00D3F6B6 /* SensorItem.xib in Resources */,
|
||||
05AD458C2908505900A791C8 /* SelectSensorsWindowController.xib in Resources */,
|
||||
055A9323252778D00070F771 /* InfoViewController.xib in Resources */,
|
||||
05B0DFA526714A830068FF9B /* UnknownTemplate.pdf in Resources */,
|
||||
05A012D726FB9B8B00D3F6B6 /* SensorsWindowController.xib in Resources */,
|
||||
05566A112990F85200E7A5F1 /* SensorItem.xib in Resources */,
|
||||
05566A0B2990F85200E7A5F1 /* CurrentTemplate.pdf in Resources */,
|
||||
05AD459029092B8400A791C8 /* BatteryTemplate.pdf in Resources */,
|
||||
057BA11828884BCD00324D16 /* ThermalTemplate.pdf in Resources */,
|
||||
057BA11928884BCD00324D16 /* VoltageTemplate.pdf in Resources */,
|
||||
057F8B15251D27650048F1E1 /* AboutWindowController.xib in Resources */,
|
||||
052FBCA7251EE46700C4322E /* PreferencesWindowController.xib in Resources */,
|
||||
05AA407F251CF3D600106CEA /* MainMenu.xib in Resources */,
|
||||
052FBCD7251F842C00C4322E /* SchedulerTemplate.pdf in Resources */,
|
||||
05B0DFA626714A830068FF9B /* eAccTemplate.pdf in Resources */,
|
||||
05566A0A2990F85200E7A5F1 /* VoltageTemplate.pdf in Resources */,
|
||||
05566A122990F85200E7A5F1 /* SensorsWindowController.xib in Resources */,
|
||||
05B0DFAA267150F40068FF9B /* TCXCTemplate.pdf in Resources */,
|
||||
05B0DFA426714A830068FF9B /* pAccTemplate.pdf in Resources */,
|
||||
);
|
||||
@@ -626,34 +648,36 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
05566A0E2990F85200E7A5F1 /* SensorHistoryData.swift in Sources */,
|
||||
055A932525277E9E0070F771 /* IntegerToString.swift in Sources */,
|
||||
05566A172990F85200E7A5F1 /* Synchronizable.swift in Sources */,
|
||||
055A932725277F6E0070F771 /* TemperatureToString.swift in Sources */,
|
||||
05A012CD26FB9AEB00D3F6B6 /* Synchronizable.swift in Sources */,
|
||||
05566A0D2990F85200E7A5F1 /* SensorValue.swift in Sources */,
|
||||
05566A1C2990F85200E7A5F1 /* SMCData.swift in Sources */,
|
||||
05566A192990F85200E7A5F1 /* IOHIDData.swift in Sources */,
|
||||
05566A152990F85200E7A5F1 /* NSImage.swift in Sources */,
|
||||
05221E8626700772007246FF /* DictionaryIsEmpty.swift in Sources */,
|
||||
05A012C626FB9AEB00D3F6B6 /* SensorValue.swift in Sources */,
|
||||
05A012C326FB9AEB00D3F6B6 /* SensorData.swift in Sources */,
|
||||
052FBCA3251EE43B00C4322E /* PreferencesWindowController.swift in Sources */,
|
||||
055A932B252780FD0070F771 /* GraphView.swift in Sources */,
|
||||
05A012CC26FB9AEB00D3F6B6 /* NSImage.swift in Sources */,
|
||||
05221E62266FD5BD007246FF /* AppleSilicon.m in Sources */,
|
||||
05221E88267009A8007246FF /* SensorViewController.swift in Sources */,
|
||||
05A012C426FB9AEB00D3F6B6 /* SensorsWindowController.swift in Sources */,
|
||||
057F8B11251D274C0048F1E1 /* NSApplication+LaunchServices.m in Sources */,
|
||||
05A012C926FB9AEB00D3F6B6 /* SensorItem.swift in Sources */,
|
||||
057F8B0C251D273E0048F1E1 /* AboutWindowController.swift in Sources */,
|
||||
05A012CA26FB9AEB00D3F6B6 /* ArrayIsEmpty.swift in Sources */,
|
||||
055A9320252778C10070F771 /* InfoViewController.swift in Sources */,
|
||||
05A012CB26FB9AEB00D3F6B6 /* SensorGraphView.swift in Sources */,
|
||||
05A012CF26FB9AEB00D3F6B6 /* Colors.swift in Sources */,
|
||||
05566A162990F85200E7A5F1 /* Sensors.swift in Sources */,
|
||||
05566A102990F85200E7A5F1 /* SensorItem.swift in Sources */,
|
||||
05566A082990F85200E7A5F1 /* SensorIcon.swift in Sources */,
|
||||
05566A182990F85200E7A5F1 /* Colors.swift in Sources */,
|
||||
05566A092990F85200E7A5F1 /* SensorsWindowController.swift in Sources */,
|
||||
05AD458829084FEF00A791C8 /* SelectSensorsWindowController.swift in Sources */,
|
||||
05566A1A2990F85200E7A5F1 /* IOHID.m in Sources */,
|
||||
05566A0F2990F85200E7A5F1 /* ArrayIsNotEmpty.swift in Sources */,
|
||||
05AA408D251CFA0600106CEA /* ThermalLog.swift in Sources */,
|
||||
055A932925277F990070F771 /* PercentToString.swift in Sources */,
|
||||
05566A132990F85200E7A5F1 /* ArrayIsEmpty.swift in Sources */,
|
||||
05AA407A251CF3D200106CEA /* ApplicationDelegate.swift in Sources */,
|
||||
05BA0BAA26F342DA00AA7BFC /* PressureToString.swift in Sources */,
|
||||
05A012C226FB9AEB00D3F6B6 /* SensorIcon.swift in Sources */,
|
||||
05A012CE26FB9AEB00D3F6B6 /* Sensors.m in Sources */,
|
||||
052FBC38251ECB8B00C4322E /* SMC.c in Sources */,
|
||||
05A012C826FB9AEB00D3F6B6 /* ArrayIsNotEmpty.swift in Sources */,
|
||||
05566A1B2990F85200E7A5F1 /* SMC.m in Sources */,
|
||||
05566A142990F85200E7A5F1 /* SensorGraphView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -684,6 +708,22 @@
|
||||
name = PreferencesWindowController.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
055669F42990F85200E7A5F1 /* SensorItem.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
055669F52990F85200E7A5F1 /* Base */,
|
||||
);
|
||||
name = SensorItem.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
055669F62990F85200E7A5F1 /* SensorsWindowController.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
055669F72990F85200E7A5F1 /* Base */,
|
||||
);
|
||||
name = SensorsWindowController.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
055A9321252778D00070F771 /* InfoViewController.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
@@ -700,22 +740,6 @@
|
||||
name = AboutWindowController.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05A012D226FB9B8B00D3F6B6 /* SensorItem.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
05A012D326FB9B8B00D3F6B6 /* Base */,
|
||||
);
|
||||
name = SensorItem.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05A012D426FB9B8B00D3F6B6 /* SensorsWindowController.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
05A012D526FB9B8B00D3F6B6 /* Base */,
|
||||
);
|
||||
name = SensorsWindowController.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05AA407D251CF3D600106CEA /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @file AppleSilicon.m
|
||||
* @copyright (c) 2021, Jean-David Gadina - www.xs-labs.com
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* LICENSE NOTICE
|
||||
*
|
||||
* The private IOKit calls used in the following code have been derived
|
||||
* from the https://github.com/fermion-star/apple_sensors project, which itself
|
||||
* has been derived from the https://github.com/freedomtan/sensors project,
|
||||
* by Koan-Sin Tan. As this might be considered as a derivative work, here are
|
||||
* the original license terms:
|
||||
*
|
||||
* BSD 3-Clause License
|
||||
*
|
||||
* Copyright (c) 2016-2018, "freedom" Koan-Sin Tan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
******************************************************************************/
|
||||
|
||||
#import "AppleSilicon.h"
|
||||
#import "IOHID.h"
|
||||
#import <IOKit/hidsystem/IOHIDEventSystemClient.h>
|
||||
#import <IOKit/hidsystem/IOHIDServiceClient.h>
|
||||
|
||||
static IOHIDEventSystemClientRef client = nil;
|
||||
|
||||
NSDictionary< NSString *, NSNumber * > * ReadAppleSiliconSensors( void )
|
||||
{
|
||||
if( client == nil )
|
||||
{
|
||||
client = IOHIDEventSystemClientCreate( kCFAllocatorDefault );
|
||||
|
||||
NSDictionary * filter =
|
||||
@{
|
||||
@"PrimaryUsagePage" : [ NSNumber numberWithLongLong: IOHIDPageAppleVendor ],
|
||||
@"PrimaryUsage" : [ NSNumber numberWithLongLong: IOHIDUsageAppleVendorTemperatureSensor ]
|
||||
};
|
||||
|
||||
IOHIDEventSystemClientSetMatching( client, ( __bridge CFDictionaryRef )filter );
|
||||
}
|
||||
|
||||
NSArray * services = CFBridgingRelease( IOHIDEventSystemClientCopyServices( client ) );
|
||||
NSMutableDictionary< NSString *, NSNumber * > * values = [ NSMutableDictionary new ];
|
||||
|
||||
for( id o in services )
|
||||
{
|
||||
IOHIDServiceClientRef service = ( __bridge IOHIDServiceClientRef )o;
|
||||
NSString * name = CFBridgingRelease( IOHIDServiceClientCopyProperty( service, CFSTR( "Product" ) ) );
|
||||
CFTypeRef event = IOHIDServiceClientCopyEvent( service, IOHIDEventTypeTemperature, 0, 0 );
|
||||
|
||||
if( name != nil && event != nil )
|
||||
{
|
||||
values[ name ] = [ NSNumber numberWithDouble: IOHIDEventGetFloatValue( event, 0x000F0000 ) ];
|
||||
}
|
||||
|
||||
if( event != nil )
|
||||
{
|
||||
CFRelease( event );
|
||||
}
|
||||
}
|
||||
|
||||
return [ values copy ];
|
||||
}
|
||||
@@ -407,7 +407,7 @@ class ApplicationDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate
|
||||
|
||||
func windowWillClose( _ notification: Notification )
|
||||
{
|
||||
self.sensorsWindowController?.stop()
|
||||
self.sensorsWindowController?.stop( completion: nil )
|
||||
|
||||
self.sensorsWindowController = nil
|
||||
}
|
||||
|
||||
@@ -24,5 +24,4 @@
|
||||
|
||||
#import "NSApplication+LaunchServices.h"
|
||||
#import "SMC.h"
|
||||
#import "AppleSilicon.h"
|
||||
#import "Sensors.h"
|
||||
#import "IOHID.h"
|
||||
|
||||
@@ -120,6 +120,14 @@ typedef NS_ENUM( int64_t, IOHIDEvent )
|
||||
IOHIDEventTypeReset = 0x1D
|
||||
};
|
||||
|
||||
#define IOHIDEventFieldBase( _type_ ) ( _type_ << 16 )
|
||||
|
||||
typedef NS_ENUM( int64_t, IOHIDEventField )
|
||||
{
|
||||
IOHIDEventFieldTemperatureLevel = IOHIDEventFieldBase( IOHIDEventTypeTemperature ),
|
||||
IOHIDEventFieldPowerMeasurement = IOHIDEventFieldBase( IOHIDEventTypePower )
|
||||
};
|
||||
|
||||
extern IOHIDEventSystemClientRef IOHIDEventSystemClientCreate( CFAllocatorRef );
|
||||
extern void IOHIDEventSystemClientSetMatching( IOHIDEventSystemClientRef, CFDictionaryRef );
|
||||
extern CFTypeRef IOHIDServiceClientCopyEvent( IOHIDServiceClientRef, IOHIDEvent, int64_t, int64_t );
|
||||
@@ -1,18 +1,18 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2022 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -24,15 +24,18 @@
|
||||
|
||||
@import Foundation;
|
||||
|
||||
@class IOHIDData;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class SensorData;
|
||||
@interface IOHID: NSObject
|
||||
|
||||
@interface Sensors: NSObject
|
||||
@property( class, nonatomic, readonly ) IOHID * shared;
|
||||
|
||||
@property( atomic, readwrite, strong ) NSArray< SensorData * > * data;
|
||||
|
||||
- ( void )stop: ( void ( ^ _Nullable )( void ) )completion;
|
||||
- ( instancetype )init;
|
||||
- ( NSArray< IOHIDData * > * )readTemperatureSensors;
|
||||
- ( NSArray< IOHIDData * > * )readVoltageSensors;
|
||||
- ( NSArray< IOHIDData * > * )readCurrentSensors;
|
||||
|
||||
@end
|
||||
|
||||
132
Hot/Classes/IOHID/IOHID.m
Normal file
132
Hot/Classes/IOHID/IOHID.m
Normal file
@@ -0,0 +1,132 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#import "IOHID.h"
|
||||
#import "IOHID-Internal.h"
|
||||
#import "Hot-Swift.h"
|
||||
#import <IOKit/hidsystem/IOHIDEventSystemClient.h>
|
||||
#import <IOKit/hidsystem/IOHIDServiceClient.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface IOHID()
|
||||
|
||||
@property( nonatomic, readwrite, assign, nullable ) IOHIDEventSystemClientRef client;
|
||||
|
||||
- ( NSArray< IOHIDData * > * )read: ( long long )page usage: ( int64_t )usage eventType: ( int64_t )eventType eventField: ( int64_t )eventField;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@implementation IOHID
|
||||
|
||||
+ ( IOHID * )shared
|
||||
{
|
||||
static dispatch_once_t once;
|
||||
static IOHID * instance;
|
||||
|
||||
dispatch_once
|
||||
(
|
||||
&once,
|
||||
^( void )
|
||||
{
|
||||
instance = [ IOHID new ];
|
||||
}
|
||||
);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
- ( instancetype )init
|
||||
{
|
||||
if( ( self = [ super init ] ) )
|
||||
{
|
||||
self.client = IOHIDEventSystemClientCreate( kCFAllocatorDefault );
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- ( oneway void )dealloc
|
||||
{
|
||||
CFRelease( self.client );
|
||||
}
|
||||
|
||||
- ( NSArray< IOHIDData * > * )readTemperatureSensors
|
||||
{
|
||||
return [ self read: IOHIDPageAppleVendor usage: IOHIDUsageAppleVendorTemperatureSensor eventType: IOHIDEventTypeTemperature eventField: IOHIDEventFieldTemperatureLevel ];
|
||||
}
|
||||
|
||||
- ( NSArray< IOHIDData * > * )readVoltageSensors
|
||||
{
|
||||
return [ self read: IOHIDPageAppleVendorPowerSensor usage: IOHIDUsageAppleVendorPowerSensorVoltage eventType: IOHIDEventTypePower eventField: IOHIDEventFieldPowerMeasurement ];
|
||||
}
|
||||
|
||||
- ( NSArray< IOHIDData * > * )readCurrentSensors
|
||||
{
|
||||
return [ self read: IOHIDPageAppleVendorPowerSensor usage: IOHIDUsageAppleVendorPowerSensorCurrent eventType: IOHIDEventTypePower eventField: IOHIDEventFieldPowerMeasurement ];
|
||||
}
|
||||
|
||||
- ( NSArray< IOHIDData * > * )read: ( long long )page usage: ( int64_t )usage eventType: ( int64_t )eventType eventField: ( int64_t )eventField
|
||||
{
|
||||
if( self.client == nil )
|
||||
{
|
||||
return @[];
|
||||
}
|
||||
|
||||
NSDictionary * filter =
|
||||
@{
|
||||
@"PrimaryUsagePage" : [ NSNumber numberWithLongLong: page ],
|
||||
@"PrimaryUsage" : [ NSNumber numberWithLongLong: usage ]
|
||||
};
|
||||
|
||||
IOHIDEventSystemClientSetMatching( self.client, ( __bridge CFDictionaryRef )filter );
|
||||
|
||||
NSArray * services = CFBridgingRelease( IOHIDEventSystemClientCopyServices( ( IOHIDEventSystemClientRef )( self.client ) ) );
|
||||
NSMutableDictionary< NSString *, IOHIDData * > * values = [ NSMutableDictionary new ];
|
||||
|
||||
for( id o in services )
|
||||
{
|
||||
IOHIDServiceClientRef service = ( __bridge IOHIDServiceClientRef )o;
|
||||
NSString * name = CFBridgingRelease( IOHIDServiceClientCopyProperty( service, CFSTR( "Product" ) ) );
|
||||
NSArray * keys = @[ @"IOClass", @"IOProviderClass", @"IONameMatch", @"Product", @"DeviceUsagePairs" ];
|
||||
NSDictionary * properties = CFBridgingRelease( IOHIDServiceClientCopyProperties( service, ( __bridge CFArrayRef )keys ) );
|
||||
CFTypeRef event = IOHIDServiceClientCopyEvent( service, eventType, 0, 0 );
|
||||
|
||||
if( name != nil && event != nil )
|
||||
{
|
||||
values[ name ] = [ [ IOHIDData alloc ] initWithName: name value: IOHIDEventGetFloatValue( event, eventField ) properties: properties ];
|
||||
}
|
||||
|
||||
if( event != nil )
|
||||
{
|
||||
CFRelease( event );
|
||||
}
|
||||
}
|
||||
|
||||
return [ values allValues ];
|
||||
}
|
||||
|
||||
@end
|
||||
41
Hot/Classes/IOHID/IOHIDData.swift
Normal file
41
Hot/Classes/IOHID/IOHIDData.swift
Normal file
@@ -0,0 +1,41 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc
|
||||
public class IOHIDData: NSObject
|
||||
{
|
||||
@objc public dynamic var name: String
|
||||
@objc public dynamic var value: Double
|
||||
@objc public dynamic var properties: [ AnyHashable: Any ]
|
||||
|
||||
@objc
|
||||
public init( name: String, value: Double, properties: [ AnyHashable: Any ] )
|
||||
{
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.properties = properties
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @file SMC.c
|
||||
* @copyright (c) 2020, Jean-David Gadina - www.xs-labs.com
|
||||
*/
|
||||
|
||||
#include "SMC.h"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wfour-char-constants"
|
||||
|
||||
/* Reference: https://logi.wiki/index.php/SMC_Sensor_Codes */
|
||||
uint32_t SMCKeyTCXC = 'TCXC';
|
||||
uint32_t SMCKeyCUS1 = 'CUS1';
|
||||
uint32_t SMCKeyTC0D = 'TC0D';
|
||||
uint32_t SMCKeyTC0C = 'TC0C';
|
||||
uint32_t SMCKeyTCAD = 'TCAD';
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
/*
|
||||
* Reference:
|
||||
* - https://opensource.apple.com/source/IOKitUser/
|
||||
* - https://opensource.apple.com/source/IOKitUser/IOKitUser-647.6/pwr_mgt.subproj/IOPMLibPrivate.c
|
||||
*/
|
||||
|
||||
IOReturn SMCReadKey( uint32_t key, uint8_t * buf, IOByteCount * maxSize )
|
||||
{
|
||||
SMCParamStruct input;
|
||||
SMCParamStruct output;
|
||||
IOReturn ret;
|
||||
|
||||
if( key == 0 || buf == NULL )
|
||||
{
|
||||
return kIOReturnCannotWire;
|
||||
}
|
||||
|
||||
memset( buf, 0, *( maxSize ) );
|
||||
memset( &input, 0, sizeof( SMCParamStruct ) );
|
||||
memset( &output, 0, sizeof( SMCParamStruct ) );
|
||||
|
||||
input.data8 = kSMCGetKeyInfo;
|
||||
input.key = key;
|
||||
|
||||
SMCCallFunction( kSMCHandleYPCEvent, &input, &output );
|
||||
|
||||
if( output.result == kSMCKeyNotFound )
|
||||
{
|
||||
return kIOReturnNotFound;
|
||||
}
|
||||
else if( output.result != kSMCSuccess )
|
||||
{
|
||||
return kIOReturnInternalError;
|
||||
}
|
||||
|
||||
input.data8 = kSMCReadKey;
|
||||
input.key = key;
|
||||
input.keyInfo.dataSize = output.keyInfo.dataSize;
|
||||
|
||||
memset( &output, 0, sizeof( SMCParamStruct ) );
|
||||
|
||||
ret = SMCCallFunction( kSMCHandleYPCEvent, &input, &output );
|
||||
|
||||
if( output.result == kSMCKeyNotFound )
|
||||
{
|
||||
return kIOReturnNotFound;
|
||||
}
|
||||
else if( output.result != kSMCSuccess )
|
||||
{
|
||||
return kIOReturnInternalError;
|
||||
}
|
||||
|
||||
if( *( maxSize ) > input.keyInfo.dataSize )
|
||||
{
|
||||
*( maxSize ) = input.keyInfo.dataSize;
|
||||
}
|
||||
|
||||
for( IOByteCount i = 0; i < *( maxSize ); i++ )
|
||||
{
|
||||
buf[ i ] = output.bytes[ i ];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
IOReturn SMCCallFunction( uint32_t function, SMCParamStruct * input, SMCParamStruct * output )
|
||||
{
|
||||
io_connect_t connection;
|
||||
io_service_t smc;
|
||||
IOReturn result;
|
||||
|
||||
smc = IOServiceGetMatchingService( kIOMasterPortDefault, IOServiceMatching( "AppleSMC" ) );
|
||||
|
||||
if( smc == IO_OBJECT_NULL )
|
||||
{
|
||||
return kIOReturnNotFound;
|
||||
}
|
||||
|
||||
result = IOServiceOpen( smc, mach_task_self(), 1, &connection );
|
||||
|
||||
if( result != kIOReturnSuccess || connection == IO_OBJECT_NULL )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = IOConnectCallMethod( connection, kSMCUserClientOpen, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL );
|
||||
|
||||
if( result != kIOReturnSuccess )
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
{
|
||||
size_t outputSize;
|
||||
|
||||
outputSize = sizeof( SMCParamStruct );
|
||||
result = IOConnectCallStructMethod( connection, function, input, sizeof( SMCParamStruct ), output, &outputSize );
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if( connection != IO_OBJECT_NULL )
|
||||
{
|
||||
IOConnectCallMethod( connection, kSMCUserClientClose, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL );
|
||||
IOServiceClose( connection );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SMCGetCPUTemperature( uint32_t key, double * valueOut )
|
||||
{
|
||||
uint8_t bytes[ 2 ];
|
||||
IOByteCount size;
|
||||
|
||||
memset( &bytes, 0, sizeof( bytes ) );
|
||||
|
||||
size = sizeof( bytes );
|
||||
|
||||
if( SMCReadKey( key, ( uint8_t * )&bytes, &size ) != kIOReturnSuccess || size != 2 )
|
||||
{
|
||||
if( valueOut )
|
||||
{
|
||||
*( valueOut ) = 0.0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
double t1;
|
||||
double t2;
|
||||
|
||||
t1 = bytes[ 0 ] & 0x7F;
|
||||
t2 = bytes[ 1 ];
|
||||
t2 /= 1 << 8;
|
||||
|
||||
if( valueOut )
|
||||
{
|
||||
*( valueOut ) = t1 + t2;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2022 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -22,34 +22,29 @@
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @header SMC.h
|
||||
* @copyright (c) 2020, Jean-David Gadina - www.xs-labs.com
|
||||
*/
|
||||
|
||||
#ifndef SMC_H
|
||||
#define SMC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
@import IOKit;
|
||||
|
||||
/*
|
||||
* Reference:
|
||||
* - https://github.com/apple-oss-distributions/IOKitUser
|
||||
* - https://opensource.apple.com/source/IOKitUser/
|
||||
* - https://opensource.apple.com/source/IOKitUser/IOKitUser-647.6/pwr_mgt.subproj/IOPMLibPrivate.c
|
||||
*/
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
enum
|
||||
{
|
||||
kSMCKeyNotFound = 0x84
|
||||
};
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
enum
|
||||
{
|
||||
kSMCSuccess = 0,
|
||||
kSMCError = 1
|
||||
kSMCSuccess = 0,
|
||||
kSMCError = 1
|
||||
};
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
enum
|
||||
{
|
||||
kSMCUserClientOpen = 0,
|
||||
@@ -62,6 +57,7 @@ enum
|
||||
kSMCGetKeyInfo = 9
|
||||
};
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char major;
|
||||
@@ -72,6 +68,7 @@ typedef struct
|
||||
}
|
||||
SMCVersion;
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t version;
|
||||
@@ -82,14 +79,16 @@ typedef struct
|
||||
}
|
||||
SMCPLimitData;
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
typedef struct
|
||||
{
|
||||
IOByteCount dataSize;
|
||||
uint32_t dataType;
|
||||
uint8_t dataAttributes;
|
||||
uint32_t dataSize;
|
||||
uint32_t dataType;
|
||||
uint8_t dataAttributes;
|
||||
}
|
||||
SMCKeyInfoData;
|
||||
|
||||
/* Do not modify - defined by AppleSMC.kext */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t key;
|
||||
@@ -104,14 +103,5 @@ typedef struct
|
||||
}
|
||||
SMCParamStruct;
|
||||
|
||||
extern uint32_t SMCKeyTCXC;
|
||||
extern uint32_t SMCKeyCUS1;
|
||||
extern uint32_t SMCKeyTC0D;
|
||||
extern uint32_t SMCKeyTC0C;
|
||||
extern uint32_t SMCKeyTCAD;
|
||||
|
||||
IOReturn SMCReadKey( uint32_t key, uint8_t * buf, IOByteCount * maxSize );
|
||||
IOReturn SMCCallFunction( uint32_t function, SMCParamStruct * input, SMCParamStruct * output );
|
||||
bool SMCGetCPUTemperature( uint32_t key, double * valueOut );
|
||||
|
||||
#endif /* SMC_H */
|
||||
extern const uint32_t kSMCKeyNKEY;
|
||||
extern const uint32_t kSMCKeyACID;
|
||||
@@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com
|
||||
* Copyright (c) 2022 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,15 +22,19 @@
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @header AppleSilicon.h
|
||||
* @copyright (c) 2021, Jean-David Gadina - www.xs-labs.com
|
||||
*/
|
||||
|
||||
@import Foundation;
|
||||
|
||||
@class SMCData;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NSDictionary< NSString *, NSNumber * > * ReadAppleSiliconSensors( void );
|
||||
@interface SMC: NSObject
|
||||
|
||||
@property( class, nonatomic, readonly ) SMC * shared;
|
||||
|
||||
- ( instancetype )init;
|
||||
- ( NSArray< SMCData * > * )readAllKeys;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
405
Hot/Classes/SMC/SMC.m
Normal file
405
Hot/Classes/SMC/SMC.m
Normal file
@@ -0,0 +1,405 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#import "SMC.h"
|
||||
#import "SMC-Internal.h"
|
||||
#import "Hot-Swift.h"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wfour-char-constants"
|
||||
|
||||
const uint32_t kSMCKeyNKEY = '#KEY';
|
||||
const uint32_t kSMCKeyACID = 'ACID';
|
||||
|
||||
#pragma clang diagnostic push
|
||||
|
||||
@import IOKit;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface SMC()
|
||||
|
||||
@property( nonatomic, readwrite, assign ) io_connect_t connection;
|
||||
@property( nonatomic, readwrite, strong ) NSMutableArray< NSNumber * > * keys;
|
||||
@property( nonatomic, readwrite, strong ) NSMutableDictionary< NSNumber *, NSValue * > * keyInfoCache;
|
||||
|
||||
+ ( NSError * )errorWithTitle: ( NSString * )title message: ( NSString * )message code: ( NSInteger )code;
|
||||
- ( BOOL )callSMCFunction: ( uint32_t )function input: ( const SMCParamStruct * )input output: ( SMCParamStruct * )output;
|
||||
- ( BOOL )readSMCKeyInfo: ( SMCKeyInfoData * )info forKey: ( uint32_t )key;
|
||||
- ( BOOL )readSMCKey: ( uint32_t * )key atIndex: ( uint32_t )index;
|
||||
- ( BOOL )readSMCKey: ( uint32_t )key buffer: ( uint8_t * )buffer maxSize: ( uint32_t * )maxSize keyInfo: ( SMCKeyInfoData * _Nullable )keyInfo;
|
||||
- ( uint32_t )readSMCKeyCount;
|
||||
- ( uint32_t )readInteger: ( uint8_t * )data size: ( uint32_t )size;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@implementation SMC
|
||||
|
||||
+ ( SMC * )shared
|
||||
{
|
||||
static dispatch_once_t once;
|
||||
static SMC * instance;
|
||||
|
||||
dispatch_once
|
||||
(
|
||||
&once,
|
||||
^( void )
|
||||
{
|
||||
instance = [ SMC new ];
|
||||
}
|
||||
);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
+ ( NSError * )errorWithTitle: ( NSString * )title message: ( NSString * )message code: ( NSInteger )code
|
||||
{
|
||||
NSDictionary * info =
|
||||
@{
|
||||
NSLocalizedDescriptionKey: title,
|
||||
NSLocalizedRecoverySuggestionErrorKey: message
|
||||
};
|
||||
|
||||
return [ [ NSError alloc ] initWithDomain: NSCocoaErrorDomain code: code userInfo: info ];
|
||||
}
|
||||
|
||||
- ( instancetype )init
|
||||
{
|
||||
if( ( self = [ super init ] ) )
|
||||
{
|
||||
self.keys = [ NSMutableArray new ];
|
||||
self.keyInfoCache = [ NSMutableDictionary new ];
|
||||
|
||||
[ self open: nil ];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- ( oneway void )dealloc
|
||||
{
|
||||
[ self close ];
|
||||
}
|
||||
|
||||
- ( NSArray< SMCData * > * )readAllKeys
|
||||
{
|
||||
if( self.connection == IO_OBJECT_NULL )
|
||||
{
|
||||
return @[];
|
||||
}
|
||||
|
||||
if( self.keys.count == 0 )
|
||||
{
|
||||
uint32_t count = [ self readSMCKeyCount ];
|
||||
|
||||
for( uint32_t i = 0; i < count; i++ )
|
||||
{
|
||||
uint32_t key = 0;
|
||||
|
||||
if( [ self readSMCKey: &key atIndex: i ] == NO )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( key != 0 )
|
||||
{
|
||||
[ self.keys addObject: [ NSNumber numberWithUnsignedInt: key ] ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSMutableArray< SMCData * > * items = [ [ NSMutableArray alloc ] initWithCapacity: self.keys.count ];
|
||||
|
||||
for( NSNumber * key in self.keys )
|
||||
{
|
||||
SMCKeyInfoData info;
|
||||
uint8_t data[ 32 ];
|
||||
uint32_t size = sizeof( data );
|
||||
|
||||
if( [ self readSMCKey: key.unsignedIntValue buffer: data maxSize: &size keyInfo: &info ] == NO )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
SMCData * item = [ [ SMCData alloc ] initWithKey: key.unsignedIntValue type: info.dataType data: [ NSData dataWithBytes: data length: size ] ];
|
||||
|
||||
[ items addObject: item ];
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
- ( BOOL )open: ( NSError * _Nullable __autoreleasing * )error
|
||||
{
|
||||
if( self.connection != IO_OBJECT_NULL )
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
io_service_t smc = IOServiceGetMatchingService( kIOMasterPortDefault, IOServiceMatching( "AppleSMC" ) );
|
||||
|
||||
if( smc == IO_OBJECT_NULL )
|
||||
{
|
||||
if( error )
|
||||
{
|
||||
*( error ) = [ SMC errorWithTitle: @"Cannot Open SMC" message: @"Unable to retrieve the SMC service." code: -1 ];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
io_connect_t connection = IO_OBJECT_NULL;
|
||||
kern_return_t result = IOServiceOpen( smc, mach_task_self(), 0, &connection );
|
||||
|
||||
if( result != kIOReturnSuccess || connection == IO_OBJECT_NULL )
|
||||
{
|
||||
if( error )
|
||||
{
|
||||
*( error ) = [ SMC errorWithTitle: @"Cannot Open SMC" message: @"Unable to open the SMC service." code: -1 ];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
self.connection = connection;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- ( BOOL )close
|
||||
{
|
||||
if( self.connection == IO_OBJECT_NULL )
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
if( IOServiceClose( self.connection ) != kIOReturnSuccess )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
self.connection = IO_OBJECT_NULL;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- ( BOOL )callSMCFunction: ( uint32_t )function input: ( const SMCParamStruct * )input output: ( SMCParamStruct * )output
|
||||
{
|
||||
size_t inputSize = sizeof( SMCParamStruct );
|
||||
size_t outputSize = sizeof( SMCParamStruct );
|
||||
kern_return_t result = IOConnectCallMethod( self.connection, kSMCUserClientOpen, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL );
|
||||
|
||||
if( result != kIOReturnSuccess )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
result = IOConnectCallStructMethod( self.connection, function, input, inputSize, output, &outputSize );
|
||||
|
||||
IOConnectCallMethod( self.connection, kSMCUserClientClose, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL );
|
||||
|
||||
return result == kIOReturnSuccess;
|
||||
}
|
||||
|
||||
- ( BOOL )readSMCKeyInfo: ( SMCKeyInfoData * )info forKey: ( uint32_t )key
|
||||
{
|
||||
if( info == NULL || key == 0 )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
{
|
||||
NSValue * cached = self.keyInfoCache[ [ NSNumber numberWithUnsignedInt: key ] ];
|
||||
|
||||
if( cached != nil )
|
||||
{
|
||||
*( info ) = *( ( SMCKeyInfoData * )( cached.pointerValue ) );
|
||||
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
SMCParamStruct input;
|
||||
SMCParamStruct output;
|
||||
|
||||
bzero( &input, sizeof( SMCParamStruct ) );
|
||||
bzero( &output, sizeof( SMCParamStruct ) );
|
||||
|
||||
input.data8 = kSMCGetKeyInfo;
|
||||
input.key = key;
|
||||
|
||||
if( [ self callSMCFunction: kSMCHandleYPCEvent input: &input output: &output ] == NO )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
if( output.result != kSMCSuccess )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
*( info ) = output.keyInfo;
|
||||
|
||||
{
|
||||
SMCKeyInfoData * cached = calloc( sizeof( SMCKeyInfoData ), 1 );
|
||||
|
||||
if( cached != NULL )
|
||||
{
|
||||
*( cached ) = output.keyInfo;
|
||||
self.keyInfoCache[ [ NSNumber numberWithUnsignedInt: key ] ] = [ NSValue valueWithPointer: cached ];
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- ( BOOL )readSMCKey: ( uint32_t * )key atIndex: ( uint32_t )index
|
||||
{
|
||||
if( key == NULL )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
SMCParamStruct input;
|
||||
SMCParamStruct output;
|
||||
|
||||
bzero( &input, sizeof( SMCParamStruct ) );
|
||||
bzero( &output, sizeof( SMCParamStruct ) );
|
||||
|
||||
input.data8 = kSMCGetKeyFromIndex;
|
||||
input.data32 = index;
|
||||
|
||||
if( [ self callSMCFunction: kSMCHandleYPCEvent input: &input output: &output ] == NO )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
if( output.result != kSMCSuccess )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
*( key ) = output.key;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- ( BOOL )readSMCKey: ( uint32_t )key buffer: ( uint8_t * )buffer maxSize: ( uint32_t * )maxSize keyInfo: ( SMCKeyInfoData * _Nullable )keyInfo
|
||||
{
|
||||
if( key == 0 || buffer == NULL || maxSize == NULL )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
SMCKeyInfoData info;
|
||||
|
||||
if( [ self readSMCKeyInfo: &info forKey: key ] == NO )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
SMCParamStruct input;
|
||||
SMCParamStruct output;
|
||||
|
||||
bzero( &input, sizeof( SMCParamStruct ) );
|
||||
bzero( &output, sizeof( SMCParamStruct ) );
|
||||
|
||||
input.key = key;
|
||||
input.data8 = kSMCReadKey;
|
||||
input.keyInfo.dataSize = info.dataSize;
|
||||
|
||||
if( [ self callSMCFunction: kSMCHandleYPCEvent input: &input output: &output ] == NO )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
if( output.result != kSMCSuccess )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
if( *( maxSize ) < info.dataSize )
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
if( keyInfo != NULL )
|
||||
{
|
||||
*( keyInfo ) = info;
|
||||
}
|
||||
|
||||
*( maxSize ) = info.dataSize;
|
||||
|
||||
bzero( buffer, *( maxSize ) );
|
||||
|
||||
for( uint32_t i = 0; i < info.dataSize; i++ )
|
||||
{
|
||||
if( key == kSMCKeyACID )
|
||||
{
|
||||
buffer[ i ] = output.bytes[ i ];
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[ i ] = output.bytes[ info.dataSize - ( i + 1 ) ];
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- ( uint32_t )readSMCKeyCount
|
||||
{
|
||||
uint8_t data[ 8 ];
|
||||
uint32_t size = sizeof( data );
|
||||
|
||||
bzero( data, size );
|
||||
|
||||
if( [ self readSMCKey: kSMCKeyNKEY buffer: data maxSize: &size keyInfo: NULL ] == NO )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return [ self readInteger: data size: size ];
|
||||
}
|
||||
|
||||
- ( uint32_t )readInteger: ( uint8_t * )data size: ( uint32_t )size
|
||||
{
|
||||
uint32_t n = 0;
|
||||
|
||||
if( size > sizeof( uint32_t ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for( uint32_t i = 0; i < size; i++ )
|
||||
{
|
||||
n |= ( uint32_t )( data[ i ] ) << ( i * 8 );
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@end
|
||||
180
Hot/Classes/SMC/SMCData.swift
Normal file
180
Hot/Classes/SMC/SMCData.swift
Normal file
@@ -0,0 +1,180 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc
|
||||
public class SMCData: NSObject
|
||||
{
|
||||
@objc public dynamic var key: UInt32
|
||||
@objc public dynamic var type: UInt32
|
||||
@objc public dynamic var data: Data
|
||||
@objc public dynamic var value: Any?
|
||||
|
||||
@objc public var keyName: String
|
||||
{
|
||||
SMCData.fourCC( value: self.key )
|
||||
}
|
||||
|
||||
@objc public var typeName: String
|
||||
{
|
||||
SMCData.fourCC( value: self.type )
|
||||
}
|
||||
|
||||
@objc
|
||||
public init( key: UInt32, type: UInt32, data: Data )
|
||||
{
|
||||
self.key = key
|
||||
self.type = type
|
||||
self.data = data
|
||||
self.value = SMCData.value( for: data, type: type )
|
||||
}
|
||||
|
||||
private class func fourCC( value: UInt32 ) -> String
|
||||
{
|
||||
let c1 = UInt8( ( value >> 24 ) & 0xFF )
|
||||
let c2 = UInt8( ( value >> 16 ) & 0xFF )
|
||||
let c3 = UInt8( ( value >> 8 ) & 0xFF )
|
||||
let c4 = UInt8( ( value >> 0 ) & 0xFF )
|
||||
|
||||
return String( format: "%c%c%c%c", c1, c2, c3, c4 )
|
||||
}
|
||||
|
||||
private class func value( for data: Data, type: UInt32 ) -> Any?
|
||||
{
|
||||
switch self.fourCC( value: type )
|
||||
{
|
||||
case "si8 ": return self.sint8( data: data ).byteSwapped
|
||||
case "ui8 ": return self.uint8( data: data ).byteSwapped
|
||||
case "si16": return self.sint16( data: data ).byteSwapped
|
||||
case "ui16": return self.uint16( data: data ).byteSwapped
|
||||
case "si32": return self.sint32( data: data ).byteSwapped
|
||||
case "ui32": return self.uint32( data: data ).byteSwapped
|
||||
case "si64": return self.sint64( data: data ).byteSwapped
|
||||
case "ui64": return self.uint64( data: data ).byteSwapped
|
||||
case "flt ": return self.float32( data: data )
|
||||
case "ioft": return self.ioFloat( data: data )
|
||||
case "sp78": return self.sp78( data: data )
|
||||
case "flag": return data[ 0 ] == 1 ? "True" : "False"
|
||||
case "ch8*": return String( data: Data( data.reversed() ), encoding: .utf8 )
|
||||
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
private class func sint8( data: Data ) -> Int8
|
||||
{
|
||||
Int8( bitPattern: self.uint8( data: data ) )
|
||||
}
|
||||
|
||||
private class func sint16( data: Data ) -> Int16
|
||||
{
|
||||
Int16( bitPattern: self.uint16( data: data ) )
|
||||
}
|
||||
|
||||
private class func sint32( data: Data ) -> Int32
|
||||
{
|
||||
Int32( bitPattern: self.uint32( data: data ) )
|
||||
}
|
||||
|
||||
private class func sint64( data: Data ) -> Int64
|
||||
{
|
||||
Int64( bitPattern: self.uint64( data: data ) )
|
||||
}
|
||||
|
||||
private class func uint8( data: Data ) -> UInt8
|
||||
{
|
||||
UInt8( data[ 0 ] )
|
||||
}
|
||||
|
||||
private class func uint16( data: Data ) -> UInt16
|
||||
{
|
||||
let u1 = UInt16( data[ 0 ] ) << 8
|
||||
let u2 = UInt16( data[ 1 ] ) << 0
|
||||
|
||||
return u1 | u2
|
||||
}
|
||||
|
||||
private class func uint32( data: Data ) -> UInt32
|
||||
{
|
||||
let u1 = UInt32( data[ 0 ] ) << 24
|
||||
let u2 = UInt32( data[ 1 ] ) << 16
|
||||
let u3 = UInt32( data[ 2 ] ) << 8
|
||||
let u4 = UInt32( data[ 3 ] ) << 0
|
||||
|
||||
return u1 | u2 | u3 | u4
|
||||
}
|
||||
|
||||
private class func uint64( data: Data ) -> UInt64
|
||||
{
|
||||
let u1 = UInt64( data[ 0 ] ) << 56
|
||||
let u2 = UInt64( data[ 1 ] ) << 48
|
||||
let u3 = UInt64( data[ 2 ] ) << 40
|
||||
let u4 = UInt64( data[ 3 ] ) << 32
|
||||
let u5 = UInt64( data[ 4 ] ) << 24
|
||||
let u6 = UInt64( data[ 5 ] ) << 16
|
||||
let u7 = UInt64( data[ 6 ] ) << 8
|
||||
let u8 = UInt64( data[ 7 ] ) << 0
|
||||
|
||||
return u1 | u2 | u3 | u4 | u5 | u6 | u7 | u8
|
||||
}
|
||||
|
||||
private class func float32( data: Data ) -> Float32
|
||||
{
|
||||
Float32( bitPattern: self.uint32( data: data ) )
|
||||
}
|
||||
|
||||
private class func float64( data: Data ) -> Float64
|
||||
{
|
||||
Float64( bitPattern: self.uint64( data: data ) )
|
||||
}
|
||||
|
||||
private class func ioFloat( data: Data ) -> Double
|
||||
{
|
||||
if data.count != 8
|
||||
{
|
||||
return 0
|
||||
}
|
||||
|
||||
let u64 = self.uint64( data: data )
|
||||
let integral = Double( u64 >> 16 )
|
||||
let mask = pow( 2.0, 16.0 ) - 1
|
||||
let fractional = Double( u64 & UInt64( mask ) ) / Double( 1 << 16 )
|
||||
|
||||
return integral + fractional
|
||||
}
|
||||
|
||||
private class func sp78( data: Data ) -> Double
|
||||
{
|
||||
if data.count != 2
|
||||
{
|
||||
return 0
|
||||
}
|
||||
|
||||
let b1 = Double( data[ 1 ] & 0x7F )
|
||||
let b2 = Double( data[ 0 ] ) / Double( 1 << 8 )
|
||||
|
||||
return b1 + b2
|
||||
}
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#import "Sensors.h"
|
||||
#import "Hot-Swift.h"
|
||||
#import "IOHID.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface Sensors()
|
||||
|
||||
@property( nonatomic, readwrite, strong ) NSMutableDictionary< NSString *, SensorData * > * sensors;
|
||||
@property( atomic, readwrite, strong, nullable ) void ( ^ completion )( void );
|
||||
@property( atomic, readwrite, assign ) BOOL shouldRun;
|
||||
|
||||
- ( void )run;
|
||||
- ( void )readSensors: ( NSTimer * )timer;
|
||||
- ( void )readSensors: ( SensorDataKind )kind page: ( IOHIDPage )page usage: ( NSInteger )usage event: ( IOHIDEvent )eventType client: ( IOHIDEventSystemClientRef )client;
|
||||
- ( void )addSensorData: ( double )value name: ( NSString * )name kind: ( SensorDataKind )kind properties: ( nullable NSDictionary * )properties;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@implementation Sensors
|
||||
|
||||
- ( instancetype )init
|
||||
{
|
||||
if( ( self = [ super init ] ) )
|
||||
{
|
||||
self.sensors = [ NSMutableDictionary new ];
|
||||
self.data = [ NSArray new ];
|
||||
self.shouldRun = YES;
|
||||
|
||||
dispatch_async
|
||||
(
|
||||
dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ),
|
||||
^( void )
|
||||
{
|
||||
[ self run ];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- ( void )stop: ( void ( ^ _Nullable )( void ) )completion
|
||||
{
|
||||
if( self.shouldRun == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self.completion = completion;
|
||||
self.shouldRun = false;
|
||||
}
|
||||
|
||||
- ( void )run
|
||||
{
|
||||
IOHIDEventSystemClientRef client = IOHIDEventSystemClientCreate( kCFAllocatorDefault );
|
||||
NSDictionary * info = @{ @"Client" : [ NSValue valueWithPointer: client ] };
|
||||
NSTimer * timer = [ NSTimer timerWithTimeInterval: 1 target: self selector: @selector( readSensors: ) userInfo: info repeats: YES ];
|
||||
|
||||
[ self readSensors: timer ];
|
||||
[ [ NSRunLoop currentRunLoop ] addTimer: timer forMode: NSDefaultRunLoopMode ];
|
||||
|
||||
while( self.shouldRun )
|
||||
{
|
||||
[ [ NSRunLoop currentRunLoop ] runUntilDate: [ NSDate dateWithTimeIntervalSinceNow: 5 ] ];
|
||||
}
|
||||
|
||||
void ( ^ completion )( void ) = self.completion;
|
||||
self.completion = nil;
|
||||
|
||||
if( completion != nil )
|
||||
{
|
||||
completion();
|
||||
}
|
||||
}
|
||||
|
||||
- ( void )readSensors: ( NSTimer * )timer
|
||||
{
|
||||
IOHIDEventSystemClientRef client = ( ( NSValue * )( timer.userInfo[ @"Client" ] ) ).pointerValue;
|
||||
|
||||
if( client != nil )
|
||||
{
|
||||
[ self readSensors: SensorDataKindThermal page: IOHIDPageAppleVendor usage: IOHIDUsageAppleVendorTemperatureSensor event: IOHIDEventTypeTemperature client: client ];
|
||||
[ self readSensors: SensorDataKindVoltage page: IOHIDPageAppleVendorPowerSensor usage: IOHIDUsageAppleVendorPowerSensorVoltage event: IOHIDEventTypePower client: client ];
|
||||
[ self readSensors: SensorDataKindCurrent page: IOHIDPageAppleVendorPowerSensor usage: IOHIDUsageAppleVendorPowerSensorCurrent event: IOHIDEventTypePower client: client ];
|
||||
|
||||
dispatch_async
|
||||
(
|
||||
dispatch_get_main_queue(),
|
||||
^( void )
|
||||
{
|
||||
self.data = self.sensors.allValues;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
- ( void )readSensors: ( SensorDataKind )kind page: ( IOHIDPage )page usage: ( NSInteger )usage event: ( IOHIDEvent )eventType client: ( IOHIDEventSystemClientRef )client
|
||||
{
|
||||
NSDictionary * filter =
|
||||
@{
|
||||
@"PrimaryUsagePage" : [ NSNumber numberWithLongLong: page ],
|
||||
@"PrimaryUsage" : [ NSNumber numberWithLongLong: usage ]
|
||||
};
|
||||
|
||||
IOHIDEventSystemClientSetMatching( client, ( __bridge CFDictionaryRef )filter );
|
||||
|
||||
{
|
||||
NSArray * services = CFBridgingRelease( IOHIDEventSystemClientCopyServices( client ) );
|
||||
|
||||
for( id o in services )
|
||||
{
|
||||
IOHIDServiceClientRef service = ( __bridge IOHIDServiceClientRef )o;
|
||||
CFTypeRef event = IOHIDServiceClientCopyEvent( service, eventType, 0, 0 );
|
||||
NSString * name = CFBridgingRelease( IOHIDServiceClientCopyProperty( service, CFSTR( "Product" ) ) );
|
||||
NSArray * keys = @[ @"IOClass", @"IOProviderClass", @"IONameMatch", @"Product", @"DeviceUsagePairs" ];
|
||||
NSDictionary * properties = CFBridgingRelease( IOHIDServiceClientCopyProperties( service, ( __bridge CFArrayRef )keys ) );
|
||||
|
||||
if( name != nil && event != nil )
|
||||
{
|
||||
[ self addSensorData: IOHIDEventGetFloatValue( event, eventType << 16 ) name: name kind: kind properties: properties ];
|
||||
}
|
||||
|
||||
if( event != nil )
|
||||
{
|
||||
CFRelease( event );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- ( void )addSensorData: ( double )value name: ( NSString * )name kind: ( SensorDataKind )kind properties: ( nullable NSDictionary * )properties
|
||||
{
|
||||
NSString * key = [ NSString stringWithFormat: @"%llu.%@", ( uint64_t )kind, name ];
|
||||
SensorData * data = [ self.sensors objectForKey: key ];
|
||||
|
||||
if( data == nil )
|
||||
{
|
||||
data = [ [ SensorData alloc ] initWithKind: kind name: name properties: properties ];
|
||||
|
||||
[ self.sensors setObject: data forKey: key ];
|
||||
}
|
||||
|
||||
dispatch_async
|
||||
(
|
||||
dispatch_get_main_queue(),
|
||||
^( void )
|
||||
{
|
||||
[ data addValue: value ];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19162" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19162"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="SensorsWindowController" customModule="Hot" customModuleProvider="target">
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="SensorsWindowController" customModule="Sensors" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="arrayController" destination="k4f-4o-be4" id="F6X-Lo-Fc0"/>
|
||||
<outlet property="collectionView" destination="d8j-id-ziA" id="tbm-Yo-sK6"/>
|
||||
@@ -19,7 +19,7 @@
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="800" height="515"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1025"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1710" height="1069"/>
|
||||
<value key="minSize" type="size" width="800" height="515"/>
|
||||
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="800" height="515"/>
|
||||
@@ -113,6 +113,26 @@
|
||||
<binding destination="-2" name="value" keyPath="self.showCurrent" id="McY-1z-eLE"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AZ7-l5-9da">
|
||||
<rect key="frame" x="481" y="21" width="62" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="IOHID" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="B30-xT-MxH">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.showIOHID" id="BgH-kZ-wRG"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="wQZ-5m-sLD">
|
||||
<rect key="frame" x="549" y="21" width="55" height="18"/>
|
||||
<buttonCell key="cell" type="check" title="SMC" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="lBw-Xe-W5E">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.showSMC" id="vG2-nh-ynR"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="wh8-P7-8p4">
|
||||
<rect key="frame" x="610" y="22" width="79" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Graph Style:" id="6Ty-8X-UI6">
|
||||
@@ -142,12 +162,14 @@
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="0b0-bM-ppa" firstAttribute="leading" secondItem="X4f-ON-Yh7" secondAttribute="leading" constant="20" symbolic="YES" id="7Hg-zM-lO0"/>
|
||||
<constraint firstItem="wh8-P7-8p4" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="DL0-ry-nBa" secondAttribute="trailing" constant="8" symbolic="YES" id="AMf-YL-aMc"/>
|
||||
<constraint firstItem="AZ7-l5-9da" firstAttribute="centerY" secondItem="DL0-ry-nBa" secondAttribute="centerY" id="95S-Ic-EYV"/>
|
||||
<constraint firstItem="YH9-KV-isM" firstAttribute="centerY" secondItem="CWx-dr-5aC" secondAttribute="centerY" id="DiY-62-WNM"/>
|
||||
<constraint firstItem="0b0-bM-ppa" firstAttribute="top" secondItem="X4f-ON-Yh7" secondAttribute="top" constant="20" symbolic="YES" id="MLt-9Q-NWw"/>
|
||||
<constraint firstItem="wQZ-5m-sLD" firstAttribute="leading" secondItem="AZ7-l5-9da" secondAttribute="trailing" constant="8" symbolic="YES" id="TAj-3M-Ri4"/>
|
||||
<constraint firstItem="wh8-P7-8p4" firstAttribute="centerY" secondItem="DL0-ry-nBa" secondAttribute="centerY" id="TS8-6H-T7P"/>
|
||||
<constraint firstItem="DL0-ry-nBa" firstAttribute="centerY" secondItem="YH9-KV-isM" secondAttribute="centerY" id="UFB-Be-d69"/>
|
||||
<constraint firstItem="b2Z-bC-lIL" firstAttribute="leading" secondItem="wh8-P7-8p4" secondAttribute="trailing" constant="8" symbolic="YES" id="V4o-Be-jIe"/>
|
||||
<constraint firstItem="AZ7-l5-9da" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="DL0-ry-nBa" secondAttribute="trailing" constant="8" symbolic="YES" id="guo-9T-pSR"/>
|
||||
<constraint firstItem="CWx-dr-5aC" firstAttribute="leading" secondItem="X4f-ON-Yh7" secondAttribute="leading" constant="20" symbolic="YES" id="kHN-fy-wU3"/>
|
||||
<constraint firstItem="DL0-ry-nBa" firstAttribute="leading" secondItem="YH9-KV-isM" secondAttribute="trailing" constant="8" symbolic="YES" id="kXC-gz-rYd"/>
|
||||
<constraint firstItem="b2Z-bC-lIL" firstAttribute="top" secondItem="0b0-bM-ppa" secondAttribute="bottom" constant="20" symbolic="YES" id="nmc-VG-jfo"/>
|
||||
@@ -156,7 +178,8 @@
|
||||
<constraint firstAttribute="trailing" secondItem="0b0-bM-ppa" secondAttribute="trailing" constant="20" symbolic="YES" id="vhy-3U-orM"/>
|
||||
<constraint firstAttribute="trailing" secondItem="b2Z-bC-lIL" secondAttribute="trailing" constant="20" symbolic="YES" id="vmq-Sh-oFu"/>
|
||||
<constraint firstItem="b2Z-bC-lIL" firstAttribute="centerY" secondItem="wh8-P7-8p4" secondAttribute="centerY" id="wRu-AK-pi5"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="DL0-ry-nBa" secondAttribute="trailing" constant="20" symbolic="YES" id="yDe-dg-UV7"/>
|
||||
<constraint firstItem="wh8-P7-8p4" firstAttribute="leading" secondItem="wQZ-5m-sLD" secondAttribute="trailing" constant="8" symbolic="YES" id="ywZ-bR-CBb"/>
|
||||
<constraint firstItem="wQZ-5m-sLD" firstAttribute="centerY" secondItem="AZ7-l5-9da" secondAttribute="centerY" id="zw8-PQ-uUL"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="self.sensors.data" id="oYT-Hj-xEu">
|
||||
@@ -26,7 +26,7 @@ import Cocoa
|
||||
|
||||
public class Colors
|
||||
{
|
||||
public class func color( for kind: SensorData.Kind ) -> NSColor
|
||||
public class func color( for kind: SensorHistoryData.Kind ) -> NSColor
|
||||
{
|
||||
switch kind
|
||||
{
|
||||
@@ -35,48 +35,36 @@ public class SensorGraphView: NSView
|
||||
case bars
|
||||
}
|
||||
|
||||
@objc public dynamic var sensor: SensorData?
|
||||
@objc public dynamic var sensor: SensorHistoryData?
|
||||
|
||||
private var graphStyleObserver: NSKeyValueObservation?
|
||||
private var defaultsObserver: Any?
|
||||
|
||||
public override init( frame: NSRect )
|
||||
{
|
||||
super.init( frame: frame )
|
||||
UserDefaults.standard.addObserver( self, forKeyPath: "graphStyle", options: .new, context: nil )
|
||||
|
||||
self.defaultsObserver = NotificationCenter.default.addObserver( forName: UserDefaults.didChangeNotification, object: nil, queue: nil )
|
||||
{
|
||||
[ weak self ] _ in self?.needsDisplay = true
|
||||
}
|
||||
}
|
||||
|
||||
required init?( coder: NSCoder )
|
||||
{
|
||||
super.init( coder: coder )
|
||||
UserDefaults.standard.addObserver( self, forKeyPath: "graphStyle", options: .new, context: nil )
|
||||
}
|
||||
|
||||
deinit
|
||||
{
|
||||
UserDefaults.standard.removeObserver( self, forKeyPath: "graphStyle" )
|
||||
}
|
||||
|
||||
public override func observeValue( forKeyPath keyPath: String?, of object: Any?, change: [ NSKeyValueChangeKey: Any ]?, context: UnsafeMutableRawPointer? )
|
||||
{
|
||||
if let keyPath = keyPath, keyPath == "graphStyle", let object = object as? UserDefaults, object == UserDefaults.standard
|
||||
self.defaultsObserver = NotificationCenter.default.addObserver( forName: UserDefaults.didChangeNotification, object: nil, queue: nil )
|
||||
{
|
||||
self.needsDisplay = true
|
||||
[ weak self ] _ in self?.needsDisplay = true
|
||||
}
|
||||
else
|
||||
{
|
||||
super.observeValue( forKeyPath: keyPath, of: object, change: change, context: context )
|
||||
}
|
||||
}
|
||||
|
||||
private var graphStyle: GraphStyle
|
||||
{
|
||||
GraphStyle( rawValue: UserDefaults.standard.integer( forKey: "graphStyle" ) ) ?? .gradient
|
||||
}
|
||||
|
||||
public override func draw( _ rect: NSRect )
|
||||
{
|
||||
self.drawBorder( in: rect )
|
||||
self.drawBackground( in: rect )
|
||||
let style = GraphStyle( rawValue: UserDefaults.standard.integer( forKey: "sensorsWindowGraphStyle" ) ) ?? .bars
|
||||
|
||||
self.drawBorder( in: rect, style: style )
|
||||
self.drawBackground( in: rect, style: style )
|
||||
|
||||
guard let sensor = self.sensor, sensor.values.count >= 2
|
||||
else
|
||||
@@ -94,7 +82,7 @@ public class SensorGraphView: NSView
|
||||
max = 100
|
||||
}
|
||||
|
||||
if self.graphStyle == .bars
|
||||
if style == .bars
|
||||
{
|
||||
self.drawBars(
|
||||
in: rect,
|
||||
@@ -113,14 +101,15 @@ public class SensorGraphView: NSView
|
||||
values: values,
|
||||
min: min,
|
||||
max: max,
|
||||
color: Colors.color( for: sensor.kind )
|
||||
color: Colors.color( for: sensor.kind ),
|
||||
style: style
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private func drawBorder( in rect: NSRect )
|
||||
private func drawBorder( in rect: NSRect, style: GraphStyle )
|
||||
{
|
||||
if self.graphStyle == .bars
|
||||
if style == .bars
|
||||
{
|
||||
return
|
||||
}
|
||||
@@ -132,9 +121,9 @@ public class SensorGraphView: NSView
|
||||
border.stroke()
|
||||
}
|
||||
|
||||
private func drawBackground( in rect: NSRect )
|
||||
private func drawBackground( in rect: NSRect, style: GraphStyle )
|
||||
{
|
||||
if self.graphStyle == .bars
|
||||
if style == .bars
|
||||
{
|
||||
let c = 15
|
||||
let h = rect.size.height / CGFloat( c )
|
||||
@@ -160,7 +149,7 @@ public class SensorGraphView: NSView
|
||||
}
|
||||
}
|
||||
|
||||
private func drawGraph( in rect: NSRect, kind: SensorData.Kind, values: [ CGFloat ], min: CGFloat, max: CGFloat, color: NSColor )
|
||||
private func drawGraph( in rect: NSRect, kind: SensorHistoryData.Kind, values: [ CGFloat ], min: CGFloat, max: CGFloat, color: NSColor, style: GraphStyle )
|
||||
{
|
||||
let p1 = NSBezierPath()
|
||||
let p2 = NSBezierPath()
|
||||
@@ -201,13 +190,13 @@ public class SensorGraphView: NSView
|
||||
p2.line( to: NSPoint( x: rect.origin.x, y: rect.origin.y - 3 ) )
|
||||
p2.close()
|
||||
|
||||
if self.graphStyle == .gradient
|
||||
if style == .gradient
|
||||
{
|
||||
let gradient = NSGradient( colors: [ color.withAlphaComponent( 0.25 ), color.withAlphaComponent( 0 ) ] )
|
||||
|
||||
gradient?.draw( in: p2, angle: -90 )
|
||||
}
|
||||
else if self.graphStyle == .fill
|
||||
else if style == .fill
|
||||
{
|
||||
color.setFill()
|
||||
p2.fill()
|
||||
@@ -217,7 +206,7 @@ public class SensorGraphView: NSView
|
||||
p1.stroke()
|
||||
}
|
||||
|
||||
private func drawBars( in rect: NSRect, kind: SensorData.Kind, values: [ CGFloat ], min: CGFloat, max: CGFloat, color: NSColor )
|
||||
private func drawBars( in rect: NSRect, kind: SensorHistoryData.Kind, values: [ CGFloat ], min: CGFloat, max: CGFloat, color: NSColor )
|
||||
{
|
||||
let c = 15
|
||||
let h = rect.size.height / CGFloat( c )
|
||||
@@ -25,9 +25,9 @@
|
||||
import Foundation
|
||||
|
||||
@objc
|
||||
public class SensorData: NSObject
|
||||
public class SensorHistoryData: NSObject, Synchronizable
|
||||
{
|
||||
@objc( SensorDataKind )
|
||||
@objc( SensorHistoryDataKind )
|
||||
public enum Kind: Int, CustomStringConvertible
|
||||
{
|
||||
case thermal
|
||||
@@ -45,53 +45,83 @@ public class SensorData: NSObject
|
||||
}
|
||||
}
|
||||
|
||||
@objc( SensorHistoryDataSource )
|
||||
public enum Source: Int, CustomStringConvertible
|
||||
{
|
||||
case hid
|
||||
case smc
|
||||
|
||||
public var description: String
|
||||
{
|
||||
switch self
|
||||
{
|
||||
case .hid: return "IOHID"
|
||||
case .smc: return "SMC"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc public private( set ) dynamic var source: Source
|
||||
@objc public private( set ) dynamic var kind: Kind
|
||||
@objc public private( set ) dynamic var name: String
|
||||
@objc public private( set ) dynamic var properties: [ String: Any ]?
|
||||
@objc public private( set ) dynamic var properties: [ AnyHashable: Any ]?
|
||||
|
||||
private var data: [ Double ] = []
|
||||
|
||||
@objc public dynamic var values: [ NSNumber ]
|
||||
{
|
||||
self.data.map { NSNumber( floatLiteral: $0 ) }
|
||||
return self.synchronized
|
||||
{
|
||||
return self.data.map { NSNumber( floatLiteral: $0 ) }
|
||||
}
|
||||
}
|
||||
|
||||
@objc public dynamic var min: NSNumber?
|
||||
{
|
||||
guard let max = self.data.min()
|
||||
else
|
||||
return self.synchronized
|
||||
{
|
||||
return nil
|
||||
}
|
||||
guard let max = self.data.min()
|
||||
else
|
||||
{
|
||||
return nil
|
||||
}
|
||||
|
||||
return NSNumber( floatLiteral: max )
|
||||
return NSNumber( floatLiteral: max )
|
||||
}
|
||||
}
|
||||
|
||||
@objc public dynamic var max: NSNumber?
|
||||
{
|
||||
guard let min = self.data.max()
|
||||
else
|
||||
return self.synchronized
|
||||
{
|
||||
return nil
|
||||
}
|
||||
guard let min = self.data.max()
|
||||
else
|
||||
{
|
||||
return nil
|
||||
}
|
||||
|
||||
return NSNumber( floatLiteral: min )
|
||||
return NSNumber( floatLiteral: min )
|
||||
}
|
||||
}
|
||||
|
||||
@objc public dynamic var last: NSNumber?
|
||||
{
|
||||
guard let last = self.data.last
|
||||
else
|
||||
return self.synchronized
|
||||
{
|
||||
return nil
|
||||
}
|
||||
guard let last = self.data.last
|
||||
else
|
||||
{
|
||||
return nil
|
||||
}
|
||||
|
||||
return NSNumber( floatLiteral: last )
|
||||
return NSNumber( floatLiteral: last )
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
public init( kind: Kind, name: String, properties: [ String: Any ]? )
|
||||
public init( source: Source, kind: Kind, name: String, properties: [ AnyHashable: Any ]? )
|
||||
{
|
||||
self.source = source
|
||||
self.kind = kind
|
||||
self.name = name
|
||||
self.properties = properties
|
||||
@@ -100,21 +130,24 @@ public class SensorData: NSObject
|
||||
@objc( addValue: )
|
||||
public func add( value: Double )
|
||||
{
|
||||
var data = self.data
|
||||
self.synchronized
|
||||
{
|
||||
var data = self.data
|
||||
|
||||
data.append( value )
|
||||
data.append( value )
|
||||
|
||||
self.willChangeValue( for: \.values )
|
||||
self.willChangeValue( for: \.min )
|
||||
self.willChangeValue( for: \.max )
|
||||
self.willChangeValue( for: \.last )
|
||||
self.willChangeValue( for: \.values )
|
||||
self.willChangeValue( for: \.min )
|
||||
self.willChangeValue( for: \.max )
|
||||
self.willChangeValue( for: \.last )
|
||||
|
||||
self.data = data.suffix( 50 )
|
||||
self.data = data.suffix( 50 )
|
||||
|
||||
self.didChangeValue( for: \.values )
|
||||
self.didChangeValue( for: \.min )
|
||||
self.didChangeValue( for: \.max )
|
||||
self.didChangeValue( for: \.last )
|
||||
self.didChangeValue( for: \.values )
|
||||
self.didChangeValue( for: \.min )
|
||||
self.didChangeValue( for: \.max )
|
||||
self.didChangeValue( for: \.last )
|
||||
}
|
||||
}
|
||||
|
||||
public override var description: String
|
||||
@@ -39,7 +39,7 @@ public class SensorIcon: ValueTransformer
|
||||
|
||||
public override func transformedValue( _ value: Any? ) -> Any?
|
||||
{
|
||||
guard let data = value as? SensorData
|
||||
guard let data = value as? SensorHistoryData
|
||||
else
|
||||
{
|
||||
return nil
|
||||
@@ -26,7 +26,7 @@ import Cocoa
|
||||
|
||||
public class SensorItem: NSCollectionViewItem
|
||||
{
|
||||
@objc public dynamic var sensor: SensorData?
|
||||
@objc public dynamic var sensor: SensorHistoryData?
|
||||
{
|
||||
didSet
|
||||
{
|
||||
145
Hot/Classes/SensorsWindow/Sensors.swift
Normal file
145
Hot/Classes/SensorsWindow/Sensors.swift
Normal file
@@ -0,0 +1,145 @@
|
||||
/*******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the Software), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
import Cocoa
|
||||
|
||||
@objc
|
||||
public class Sensors: NSObject
|
||||
{
|
||||
@objc public private( set ) dynamic var data = [ SensorHistoryData ]()
|
||||
@objc private dynamic var sensors = [ String: SensorHistoryData ]()
|
||||
|
||||
private var shouldRun = true
|
||||
private var completion: ( () -> Void )?
|
||||
|
||||
public override init()
|
||||
{
|
||||
super.init()
|
||||
|
||||
DispatchQueue.global( qos: .background ).async
|
||||
{
|
||||
self.run()
|
||||
}
|
||||
}
|
||||
|
||||
public func stop( completion: ( () -> Void )? )
|
||||
{
|
||||
if self.shouldRun == false
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
self.completion = completion
|
||||
self.shouldRun = false
|
||||
}
|
||||
|
||||
private func run()
|
||||
{
|
||||
let timer = Timer.scheduledTimer( withTimeInterval: 1, repeats: true )
|
||||
{
|
||||
_ in self.readSensors()
|
||||
}
|
||||
|
||||
self.readSensors()
|
||||
RunLoop.current.add( timer, forMode: .default )
|
||||
|
||||
while self.shouldRun
|
||||
{
|
||||
RunLoop.current.run( until: Date( timeIntervalSinceNow: 5 ) )
|
||||
}
|
||||
|
||||
let completion = self.completion
|
||||
self.completion = nil
|
||||
|
||||
completion?()
|
||||
}
|
||||
|
||||
private func readSensors()
|
||||
{
|
||||
self.readIOHIDSensors()
|
||||
self.readSMCSensors()
|
||||
|
||||
let sensors = self.sensors
|
||||
|
||||
DispatchQueue.main.async
|
||||
{
|
||||
self.data = [ SensorHistoryData ]( sensors.values )
|
||||
}
|
||||
}
|
||||
|
||||
private func readIOHIDSensors()
|
||||
{
|
||||
IOHID.shared.readTemperatureSensors().forEach { self.addSensorHistoryData( data: $0, kind: .thermal ) }
|
||||
IOHID.shared.readVoltageSensors().forEach { self.addSensorHistoryData( data: $0, kind: .voltage ) }
|
||||
IOHID.shared.readCurrentSensors().forEach { self.addSensorHistoryData( data: $0, kind: .current ) }
|
||||
}
|
||||
|
||||
private func readSMCSensors()
|
||||
{
|
||||
let all = SMC.shared.readAllKeys()
|
||||
|
||||
all.filter { $0.keyName.hasPrefix( "T" ) }.forEach { self.addSensorHistoryData( data: $0, kind: .thermal ) }
|
||||
all.filter { $0.keyName.hasPrefix( "V" ) }.forEach { self.addSensorHistoryData( data: $0, kind: .voltage ) }
|
||||
all.filter { $0.keyName.hasPrefix( "I" ) }.forEach { self.addSensorHistoryData( data: $0, kind: .current ) }
|
||||
}
|
||||
|
||||
private func addSensorHistoryData( data: IOHIDData, kind: SensorHistoryData.Kind )
|
||||
{
|
||||
let key = String( format: "IOHID.%llu.%@", kind.rawValue, data.name )
|
||||
|
||||
if self.sensors[ key ] == nil
|
||||
{
|
||||
self.sensors[ key ] = SensorHistoryData( source: .hid, kind: kind, name: data.name, properties: data.properties )
|
||||
}
|
||||
|
||||
self.sensors[ key ]?.add( value: data.value )
|
||||
}
|
||||
|
||||
private func addSensorHistoryData( data: SMCData, kind: SensorHistoryData.Kind )
|
||||
{
|
||||
let value: Double
|
||||
|
||||
if let f = data.value as? Double
|
||||
{
|
||||
value = f
|
||||
}
|
||||
else if let f = data.value as? Float32
|
||||
{
|
||||
value = Double( f )
|
||||
}
|
||||
else
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
let key = String( format: "SMC.%llu.%@", kind.rawValue, data.keyName )
|
||||
|
||||
if self.sensors[ key ] == nil
|
||||
{
|
||||
self.sensors[ key ] = SensorHistoryData( source: .smc, kind: kind, name: data.keyName, properties: [ : ] )
|
||||
}
|
||||
|
||||
self.sensors[ key ]?.add( value: value )
|
||||
}
|
||||
}
|
||||
@@ -26,9 +26,9 @@ import Cocoa
|
||||
|
||||
public class SensorsWindowController: NSWindowController
|
||||
{
|
||||
@objc private dynamic var sensors: Sensors? = Sensors()
|
||||
@objc private dynamic var sensors = Sensors()
|
||||
|
||||
@objc private dynamic var showTemperature = UserDefaults.standard.bool( forKey: "sensorsWindowShowTemperature" )
|
||||
@objc private dynamic var showTemperature = UserDefaults.standard.object( forKey: "sensorsWindowShowTemperature" ) as? Bool ?? true
|
||||
{
|
||||
didSet
|
||||
{
|
||||
@@ -37,7 +37,7 @@ public class SensorsWindowController: NSWindowController
|
||||
}
|
||||
}
|
||||
|
||||
@objc private dynamic var showVoltage = UserDefaults.standard.bool( forKey: "sensorsWindowShowVoltage" )
|
||||
@objc private dynamic var showVoltage = UserDefaults.standard.object( forKey: "sensorsWindowShowVoltage" ) as? Bool ?? true
|
||||
{
|
||||
didSet
|
||||
{
|
||||
@@ -46,7 +46,7 @@ public class SensorsWindowController: NSWindowController
|
||||
}
|
||||
}
|
||||
|
||||
@objc private dynamic var showCurrent = UserDefaults.standard.bool( forKey: "sensorsWindowShowCurrent" )
|
||||
@objc private dynamic var showCurrent = UserDefaults.standard.object( forKey: "sensorsWindowShowCurrent" ) as? Bool ?? true
|
||||
{
|
||||
didSet
|
||||
{
|
||||
@@ -55,16 +55,34 @@ public class SensorsWindowController: NSWindowController
|
||||
}
|
||||
}
|
||||
|
||||
@objc private dynamic var showIOHID = UserDefaults.standard.object( forKey: "sensorsWindowShowIOHID" ) as? Bool ?? true
|
||||
{
|
||||
didSet
|
||||
{
|
||||
self.updateFilters()
|
||||
UserDefaults.standard.set( self.showIOHID, forKey: "sensorsWindowShowIOHID" )
|
||||
}
|
||||
}
|
||||
|
||||
@objc private dynamic var showSMC = UserDefaults.standard.object( forKey: "sensorsWindowShowSMC" ) as? Bool ?? true
|
||||
{
|
||||
didSet
|
||||
{
|
||||
self.updateFilters()
|
||||
UserDefaults.standard.set( self.showSMC, forKey: "sensorsWindowShowSMC" )
|
||||
}
|
||||
}
|
||||
|
||||
@objc private dynamic var searchText: String?
|
||||
{
|
||||
didSet { self.updateFilters() }
|
||||
}
|
||||
|
||||
@objc private dynamic var graphStyle = UserDefaults.standard.integer( forKey: "graphStyle" )
|
||||
@objc private dynamic var graphStyle = UserDefaults.standard.integer( forKey: "sensorsWindowGraphStyle" )
|
||||
{
|
||||
didSet
|
||||
{
|
||||
UserDefaults.standard.set( self.graphStyle, forKey: "graphStyle" )
|
||||
UserDefaults.standard.set( self.graphStyle, forKey: "sensorsWindowGraphStyle" )
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,20 +97,15 @@ public class SensorsWindowController: NSWindowController
|
||||
public override func windowDidLoad()
|
||||
{
|
||||
super.windowDidLoad()
|
||||
self.updateFilters()
|
||||
|
||||
self.arrayController.sortDescriptors = [ NSSortDescriptor( key: "name", ascending: true, selector: #selector( NSString.localizedCaseInsensitiveCompare( _: ) ) ) ]
|
||||
|
||||
self.updateFilters()
|
||||
}
|
||||
|
||||
public func stop()
|
||||
public func stop( completion: ( () -> Void )? )
|
||||
{
|
||||
self.sensors?.stop
|
||||
{
|
||||
DispatchQueue.main.async
|
||||
{
|
||||
self.sensors = nil
|
||||
}
|
||||
}
|
||||
self.sensors.stop( completion: completion )
|
||||
}
|
||||
|
||||
private func updateFilters()
|
||||
@@ -101,17 +114,27 @@ public class SensorsWindowController: NSWindowController
|
||||
|
||||
if self.showTemperature == false
|
||||
{
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorData )?.kind != .thermal } )
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorHistoryData )?.kind != .thermal } )
|
||||
}
|
||||
|
||||
if self.showVoltage == false
|
||||
{
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorData )?.kind != .voltage } )
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorHistoryData )?.kind != .voltage } )
|
||||
}
|
||||
|
||||
if self.showCurrent == false
|
||||
{
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorData )?.kind != .current } )
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorHistoryData )?.kind != .current } )
|
||||
}
|
||||
|
||||
if self.showIOHID == false
|
||||
{
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorHistoryData )?.source != .hid } )
|
||||
}
|
||||
|
||||
if self.showSMC == false
|
||||
{
|
||||
predicates.append( NSPredicate { o, i in ( o as? SensorHistoryData )?.source != .smc } )
|
||||
}
|
||||
|
||||
if let search = self.searchText, search.count > 0
|
||||
@@ -139,14 +162,14 @@ extension SensorsWindowController: NSCollectionViewDataSource
|
||||
|
||||
public func collectionView( _ collectionView: NSCollectionView, numberOfItemsInSection section: Int ) -> Int
|
||||
{
|
||||
( self.arrayController.arrangedObjects as? [ SensorData ] )?.count ?? 0
|
||||
( self.arrayController.arrangedObjects as? [ SensorHistoryData ] )?.count ?? 0
|
||||
}
|
||||
|
||||
public func collectionView( _ itemForRepresentedObjectAtcollectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath ) -> NSCollectionViewItem
|
||||
{
|
||||
let item = self.collectionView.makeItem( withIdentifier: NSUserInterfaceItemIdentifier( rawValue: "SensorItem" ), for: indexPath )
|
||||
|
||||
if let item = item as? SensorItem, let sensors = self.arrayController.arrangedObjects as? [ SensorData ]
|
||||
if let item = item as? SensorItem, let sensors = self.arrayController.arrangedObjects as? [ SensorHistoryData ]
|
||||
{
|
||||
if sensors.count > indexPath.item
|
||||
{
|
||||
@@ -47,11 +47,11 @@ public class ThermalLog: NSObject
|
||||
#if arch( arm64 )
|
||||
|
||||
return Dictionary( uniqueKeysWithValues:
|
||||
ReadAppleSiliconSensors().map
|
||||
IOHID.shared.readTemperatureSensors().map
|
||||
{
|
||||
let isCPU = $0.key.hasPrefix( "pACC" ) || $0.key.hasPrefix( "eACC" )
|
||||
let isCPU = $0.name.hasPrefix( "pACC" ) || $0.name.hasPrefix( "eACC" )
|
||||
|
||||
return ( $0.key, ( temperature: $0.value.doubleValue, isCPU: isCPU ) )
|
||||
return ( $0.name, ( temperature: $0.value, isCPU: isCPU ) )
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user