├── source ├── README.md ├── .gitattributes ├── Shared │ ├── IOPMLibPrivate.h │ └── Classes │ │ ├── MTModifyData.m │ │ ├── MTModifyData.h │ │ ├── MTPowerMeasurement.m │ │ ├── MTPowerMeasurementArray.h │ │ ├── MTPowerMeasurementWriter.h │ │ ├── MTElectricityPrice.h │ │ ├── MTPowerMeasurementReader.h │ │ ├── MTElectricityPrice.m │ │ ├── MTPowerMeasurement.h │ │ ├── MTPowerMeasurementArray.m │ │ └── MTSystemInfo.h ├── Power Monitor │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── AppIcon-128.png │ │ │ ├── AppIcon-16.png │ │ │ ├── AppIcon-256.png │ │ │ ├── AppIcon-32.png │ │ │ ├── AppIcon-512.png │ │ │ ├── AppIcon-64.png │ │ │ ├── AppIcon-1024.png │ │ │ └── Contents.json │ │ ├── StatusItem.imageset │ │ │ ├── StatusItem-16.png │ │ │ ├── StatusItem-32.png │ │ │ └── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── GraphFillColor.colorset │ │ │ └── Contents.json │ │ ├── CarbonFootprintColor.colorset │ │ │ └── Contents.json │ │ ├── GraphAverageLineColor.colorset │ │ │ └── Contents.json │ │ ├── GraphDayMarkerColor.colorset │ │ │ └── Contents.json │ │ ├── GraphPowerNapFillColor.colorset │ │ │ └── Contents.json │ │ └── GraphPositionLineColor.colorset │ │ │ └── Contents.json │ ├── Power Monitor.entitlements │ ├── Classes │ │ ├── MTSidebarItem.m │ │ ├── MTHourTextField.h │ │ ├── MTJournalTableView.h │ │ ├── MTToolbarItem.h │ │ ├── MTStatusItemMenu.h │ │ ├── MTMainWindowController.h │ │ ├── MTMainWindowController.m │ │ ├── MTSegmentedControl.h │ │ ├── MTPowerGraphTooltip.h │ │ ├── MTWeekdayTextField.h │ │ ├── MTToolbarItem.m │ │ ├── MTJournalTableView.m │ │ ├── MTSidebarItem.h │ │ ├── MTSegmentedControl.m │ │ ├── MTWeekdayTextField.m │ │ ├── MTHourTextField.m │ │ ├── MTCarbonAPIKey.h │ │ ├── MTElectricityMapsAPI.h │ │ ├── MTDaemonConnection.h │ │ ├── MTCarbonFootprint.h │ │ └── MTElectricityMapsAPI.m │ ├── AppDelegate.h │ ├── View Controllers │ │ ├── MTAssertionsController.h │ │ ├── MTLogController.h │ │ ├── MTLogDetailsController.h │ │ ├── MTMainViewController.h │ │ ├── MTPowerInfoController.h │ │ ├── MTDescriptionController.h │ │ ├── MTSettingsCarbonController.h │ │ ├── MTSettingsGeneralController.h │ │ ├── MTSettingsJournalController.h │ │ ├── MTTabViewController.h │ │ ├── MTSettingsPowerNapController.h │ │ ├── MTCredentialsController.h │ │ ├── MTJournalSplitViewController.h │ │ ├── MTSettingsCostsController.h │ │ ├── MTSettingsViewOptionsController.h │ │ ├── MTSidebarController.h │ │ ├── MTGraphSplitViewController.h │ │ ├── MTConsoleSplitViewController.h │ │ ├── MTJournalInspectorController.h │ │ ├── MTPowerGraphInspectorController.h │ │ ├── MTSavePanelAccessoryController.h │ │ ├── MTJournalSplitViewController.m │ │ ├── MTLogDetailsController.m │ │ ├── MTJournalController.h │ │ ├── MTSavePanelAccessoryController.m │ │ ├── MTAssertionsController.m │ │ ├── MTDescriptionController.m │ │ ├── MTTabViewController.m │ │ ├── MTConsoleSplitViewController.m │ │ ├── MTPowerGraphController.h │ │ ├── MTGraphSplitViewController.m │ │ └── MTSettingsViewOptionsController.m │ ├── main.m │ ├── corp.sap.PowerMonitorDaemon.plist │ ├── de.lproj │ │ └── Credits.rtf │ ├── Base.lproj │ │ └── Credits.rtf │ ├── Value Transformers │ │ ├── MTColorTransformer.m │ │ ├── MTColorTransformer.h │ │ ├── MTUsageConsumptionValueTransformer.h │ │ ├── MTButtonTitleTransformer.m │ │ ├── MTButtonTitleTransformer.h │ │ ├── MTUsagePriceTextTransformer.m │ │ ├── MTUsagePeriodTextTransformer.m │ │ ├── MTUsageConsumptionTextTransformer.m │ │ ├── MTUsagePeriodTextTransformer.h │ │ ├── MTLogLevelValueTransformer.h │ │ ├── MTUsagePriceTextTransformer.h │ │ ├── MTUsageConsumptionTextTransformer.h │ │ ├── MTUsageConsumptionValueTransformer.m │ │ └── MTLogLevelValueTransformer.m │ ├── Info.plist │ ├── AppIcon.icon │ │ ├── Assets │ │ │ ├── l1.svg │ │ │ ├── l2.svg │ │ │ └── l3.svg │ │ └── icon.json │ └── InfoPlist.xcstrings ├── Power Monitor.xcodeproj │ ├── .DS_Store │ ├── xcuserdata │ │ └── .DS_Store │ ├── xcshareddata │ │ ├── .DS_Store │ │ └── xcschemes │ │ │ ├── PowerMonitorDaemon.xcscheme │ │ │ └── Power Monitor.xcscheme │ └── project.xcworkspace │ │ ├── .DS_Store │ │ ├── xcuserdata │ │ └── .DS_Store │ │ └── contents.xcworkspacedata ├── PowerMonitorXPC │ ├── Info.plist │ ├── PowerMonitorXPC.h │ ├── PowerMonitorXPCProtocol.h │ ├── main.m │ └── PowerMonitorXPC.m └── PowerMonitorDaemon │ ├── PowerMonitorDaemon-Info.plist │ ├── Classes │ ├── MTPowerMonitorDaemon.h │ ├── MTPowerEvent.m │ ├── MTPowerEvent.h │ └── MTSleepWatcher.h │ └── main.m ├── readme_images ├── power_monitor_launched.png ├── power_monitor_background.png ├── power_monitor_settings_costs.png ├── power_monitor_settings_view.png ├── powermonitor_banner_github.png ├── power_monitor_settings_carbon.png ├── power_monitor_settings_general.png ├── power_monitor_settings_journal.png └── power_monitor_settings_powernap.png ├── REUSE.toml ├── example_jamf_pro_extension_attribute └── example_jamf_pro_extension_attribute.sh ├── CONTRIBUTING.md └── README.md /source/README.md: -------------------------------------------------------------------------------- 1 | # PowerMonitor 2 | Source code for the Power Monitor app 3 | -------------------------------------------------------------------------------- /source/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /source/Shared/IOPMLibPrivate.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Shared/IOPMLibPrivate.h -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /readme_images/power_monitor_launched.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/readme_images/power_monitor_launched.png -------------------------------------------------------------------------------- /source/Power Monitor.xcodeproj/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor.xcodeproj/.DS_Store -------------------------------------------------------------------------------- /readme_images/power_monitor_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/readme_images/power_monitor_background.png -------------------------------------------------------------------------------- /readme_images/power_monitor_settings_costs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/readme_images/power_monitor_settings_costs.png -------------------------------------------------------------------------------- /readme_images/power_monitor_settings_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/readme_images/power_monitor_settings_view.png -------------------------------------------------------------------------------- /readme_images/powermonitor_banner_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/readme_images/powermonitor_banner_github.png -------------------------------------------------------------------------------- /readme_images/power_monitor_settings_carbon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/readme_images/power_monitor_settings_carbon.png -------------------------------------------------------------------------------- /readme_images/power_monitor_settings_general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/readme_images/power_monitor_settings_general.png -------------------------------------------------------------------------------- /readme_images/power_monitor_settings_journal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/readme_images/power_monitor_settings_journal.png -------------------------------------------------------------------------------- /readme_images/power_monitor_settings_powernap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/readme_images/power_monitor_settings_powernap.png -------------------------------------------------------------------------------- /source/Power Monitor.xcodeproj/xcuserdata/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor.xcodeproj/xcuserdata/.DS_Store -------------------------------------------------------------------------------- /source/Power Monitor.xcodeproj/xcshareddata/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor.xcodeproj/xcshareddata/.DS_Store -------------------------------------------------------------------------------- /source/Power Monitor.xcodeproj/project.xcworkspace/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor.xcodeproj/project.xcworkspace/.DS_Store -------------------------------------------------------------------------------- /source/Power Monitor.xcodeproj/project.xcworkspace/xcuserdata/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor.xcodeproj/project.xcworkspace/xcuserdata/.DS_Store -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-128.png -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-64.png -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/StatusItem.imageset/StatusItem-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor/Assets.xcassets/StatusItem.imageset/StatusItem-16.png -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/StatusItem.imageset/StatusItem-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/power-monitoring-tool-for-macos/HEAD/source/Power Monitor/Assets.xcassets/StatusItem.imageset/StatusItem-32.png -------------------------------------------------------------------------------- /source/Power Monitor.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /source/PowerMonitorXPC/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | XPCService 6 | 7 | JoinExistingSession 8 | 9 | ServiceType 10 | Application 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /REUSE.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | SPDX-PackageName = "power-monitoring-tool-for-macos" 3 | SPDX-PackageSupplier = "SAP Mac Open Source Security macatsap-opensource-security@sap.com" 4 | SPDX-PackageDownloadLocation = "https://github.com/SAP/power-monitoring-tool-for-macos" 5 | 6 | [[annotations]] 7 | path = "**" 8 | precedence = "aggregate" 9 | SPDX-FileCopyrightText = "2023-2025 SAP SE or an SAP affiliate company and Script2Pkg contributors." 10 | SPDX-License-Identifier = "Apache-2.0" 11 | -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/StatusItem.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "StatusItem-16.png", 5 | "idiom" : "mac", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "StatusItem-32.png", 10 | "idiom" : "mac", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "author" : "xcode", 16 | "version" : 1 17 | }, 18 | "properties" : { 19 | "template-rendering-intent" : "template" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/Power Monitor/Power Monitor.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.temporary-exception.files.absolute-path.read-write 6 | 7 | /Users/Shared/ 8 | 9 | com.apple.security.temporary-exception.sbpl 10 | 11 | (allow iokit-open) 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /source/PowerMonitorDaemon/PowerMonitorDaemon-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | corp.sap.PowerMonitorDaemon 7 | CFBundleInfoDictionaryVersion 8 | 6.0 9 | CFBundleName 10 | PowerMonitorDaemon 11 | CFBundleShortVersionString 12 | $(MARKETING_VERSION) 13 | CFBundleVersion 14 | $(CURRENT_PROJECT_VERSION) 15 | NSHumanReadableCopyright 16 | Copyright © 2023-2025 SAP SE. All rights reserved. 17 | 18 | 19 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTSidebarItem.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTSidebarItem.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTSidebarItem.h" 19 | 20 | @implementation MTSidebarItem 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTHourTextField.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTHourTextField.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTHourTextField : NSTextField 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | AppDelegate.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface AppDelegate : NSObject 21 | 22 | @end 23 | 24 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTJournalTableView.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTJournalTableView.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTJournalTableView : NSTableView 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTAssertionsController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTAssertionsController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTAssertionsController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTLogController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTLogController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTLogController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTLogDetailsController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTLogDetailsController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTLogDetailsController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTMainViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTMainViewController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTMainViewController : NSViewController 21 | 22 | @end 23 | 24 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTPowerInfoController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPowerInfoController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTPowerInfoController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTDescriptionController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTDescriptionController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTDescriptionController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTToolbarItem.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTToolbarItem.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTToolbarItem : NSToolbarItem 21 | 22 | @property (weak) IBOutlet NSButton *button; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTSettingsCarbonController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSettingsCarbonController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTSettingsCarbonController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTSettingsGeneralController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSettingsGeneralController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTSettingsGeneralController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTSettingsJournalController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSettingsJournalController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTSettingsJournalController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTTabViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTTabViewController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTTabViewController : NSTabViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTSettingsPowerNapController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSettingsPowerNapController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTSettingsPowerNapController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTCredentialsController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTCredentialsController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTCredentialsController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTJournalSplitViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTJournalSplitViewController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTJournalSplitViewController : NSSplitViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTSettingsCostsController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSettingsCostsController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTSettingsCostsController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTSettingsViewOptionsController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSettingsViewOptionsController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTSettingsViewOptionsController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "211", 9 | "green" : "143", 10 | "red" : "0" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "255", 27 | "green" : "170", 28 | "red" : "15" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /source/Power Monitor/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | main.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | int main(int argc, const char * argv[]) 21 | { 22 | @autoreleasepool { 23 | 24 | } 25 | 26 | return NSApplicationMain(argc, argv); 27 | } 28 | -------------------------------------------------------------------------------- /source/PowerMonitorXPC/PowerMonitorXPC.h: -------------------------------------------------------------------------------- 1 | /* 2 | PowerMonitorXPC.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "PowerMonitorXPCProtocol.h" 20 | 21 | @interface PowerMonitorXPC : NSObject 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/GraphFillColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "38", 9 | "green" : "139", 10 | "red" : "52" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "28", 27 | "green" : "184", 28 | "red" : "79" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTSidebarController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSidebarController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTSidebarController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/CarbonFootprintColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "38", 9 | "green" : "139", 10 | "red" : "52" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "28", 27 | "green" : "184", 28 | "red" : "79" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/GraphAverageLineColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "24", 9 | "green" : "54", 10 | "red" : "188" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0", 27 | "green" : "85", 28 | "red" : "227" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/GraphDayMarkerColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "211", 9 | "green" : "143", 10 | "red" : "0" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "255", 27 | "green" : "170", 28 | "red" : "15" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTGraphSplitViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTGraphSplitViewController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTGraphSplitViewController : NSSplitViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTConsoleSplitViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTConsoleSplitViewController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTConsoleSplitViewController : NSSplitViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/GraphPowerNapFillColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.000", 9 | "green" : "0.671", 10 | "red" : "0.941" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.000", 27 | "green" : "0.686", 28 | "red" : "1.000" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /source/Power Monitor/corp.sap.PowerMonitorDaemon.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MachServices 6 | 7 | corp.sap.PowerMonitor.xpc 8 | 9 | 10 | Label 11 | corp.sap.PowerMonitorDaemon 12 | Program 13 | /Applications/Power Monitor.app/Contents/MacOS/PowerMonitorDaemon 14 | AssociatedBundleIdentifiers 15 | corp.sap.PowerMonitor 16 | SpawnConstraint 17 | 18 | team-identifier 19 | 7R5ZEU67FQ 20 | signing-identifier 21 | corp.sap.PowerMonitorDaemon 22 | 23 | RunAtLoad 24 | 25 | KeepAlive 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/GraphPositionLineColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0x6E", 9 | "green" : "0x00", 10 | "red" : "0x83" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "display-p3", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.517", 27 | "green" : "0.000", 28 | "red" : "0.818" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /source/Power Monitor/de.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf2758 2 | \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 SFPro-Regular;} 3 | {\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red0\green0\blue0;} 4 | {\*\expandedcolortbl;;\cssrgb\c0\c0\c0\c49804\cname secondaryLabelColor;\csgray\c0\c0;} 5 | \paperw11900\paperh16840\vieww20740\viewh8340\viewkind0 6 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc\partightenfactor0 7 | 8 | \f0\fs20 \cf2 \cb3 \ 9 | Idee, Design & Entwicklung\ 10 | Marc Thielemann\ 11 | \ 12 | \pard\pardeftab720\qc\partightenfactor0 13 | \cf2 \expnd0\expndtw0\kerning0 14 | Diese Anwendung kann unter der\ 15 | \pard\pardeftab720\qc\partightenfactor0 16 | {\field{\*\fldinst{HYPERLINK "http://www.apache.org/licenses/LICENSE-2.0"}}{\fldrslt \cf2 \kerning1\expnd0\expndtw0 Apache Lizenz, Version 2.0}}\ 17 | weitergegeben und modifiziert werden.\ 18 | } -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTJournalInspectorController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTJournalInspectorController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTJournalController.h" 20 | 21 | @interface MTJournalInspectorController : NSViewController 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTPowerGraphInspectorController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPowerGraphInspectorController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTPowerGraphController.h" 20 | 21 | @interface MTPowerGraphInspectorController : NSViewController 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /source/Power Monitor/Base.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf2758 2 | \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 SFPro-Regular;} 3 | {\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red0\green0\blue0;} 4 | {\*\expandedcolortbl;;\cssrgb\c0\c0\c0\c49804\cname secondaryLabelColor;\csgray\c0\c0;} 5 | \paperw11900\paperh16840\vieww20740\viewh8340\viewkind0 6 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc\partightenfactor0 7 | 8 | \f0\fs20 \cf2 \cb3 \ 9 | Idea, Design & Engineering\ 10 | Marc Thielemann\ 11 | \ 12 | \pard\pardeftab720\qc\partightenfactor0 13 | \cf2 \expnd0\expndtw0\kerning0 14 | This application can be redistributed\ 15 | and modified under \kerning1\expnd0\expndtw0 the\ 16 | \pard\pardeftab720\qc\partightenfactor0 17 | {\field{\*\fldinst{HYPERLINK "http://www.apache.org/licenses/LICENSE-2.0"}}{\fldrslt \cf2 Apache License, Version 2.0}}\expnd0\expndtw0\kerning0 18 | \ 19 | } -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTStatusItemMenu.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTStatusItemMenu.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTStatusItemMenu 22 | @abstract This class defines the menu for the status item. 23 | */ 24 | 25 | @interface MTStatusItemMenu : NSMenu 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTColorTransformer.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTColorTransformer.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTColorTransformer.h" 19 | 20 | @implementation MTColorTransformer 21 | 22 | + (NSArray*)allowedTopLevelClasses 23 | { 24 | return [NSArray arrayWithObject:[NSColor class]]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTColorTransformer.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTColorTransformer.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTColorTransformer 22 | @abstract A transformer that allows to store NSColor in NSUserDefaults 23 | */ 24 | 25 | @interface MTColorTransformer : NSSecureUnarchiveFromDataTransformer 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTSavePanelAccessoryController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSavePanelAccessoryController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTSavePanelAccessoryController : NSViewController 21 | 22 | @property (assign) BOOL hasSelection; 23 | @property (assign) BOOL exportSelected; 24 | @property (assign) NSCalendarUnit summarizeType; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTMainWindowController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTMainWindowController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTMainWindowController 22 | @abstract A sublass of NSWindowController that terminates the app as soon as the 23 | window controller's window has been closed. 24 | */ 25 | @interface MTMainWindowController : NSWindowController 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTUsageConsumptionValueTransformer.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTUsageConsumptionValueTransformer.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTUsageConsumptionValueTransformer 22 | @abstract A value transformer that returns the formatted power consumption string from a given value. 23 | */ 24 | 25 | @interface MTUsageConsumptionValueTransformer : NSValueTransformer 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTMainWindowController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTMainWindowController.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTMainWindowController.h" 19 | #import "Constants.h" 20 | 21 | @implementation MTMainWindowController 22 | 23 | - (void)windowWillClose:(NSNotification *)notification 24 | { 25 | if (![[NSUserDefaults standardUserDefaults] boolForKey:kMTDefaultsRunInBackgroundKey]) { 26 | [NSApp terminate:self]; 27 | } 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTButtonTitleTransformer.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTButtonTitleTransformer.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTButtonTitleTransformer.h" 19 | 20 | @implementation MTButtonTitleTransformer 21 | 22 | + (BOOL)allowsReverseTransformation 23 | { 24 | return NO; 25 | } 26 | 27 | - (id)transformedValue:(id)value 28 | { 29 | return (value) ? NSLocalizedString(@"clearButtonTitle", nil) : NSLocalizedString(@"importButtonTitle", nil); 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTButtonTitleTransformer.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTButtonTitleTransformer.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTButtonTitleTransformer 22 | @abstract A value transformer that returns the localized string "clearButtonTitle" if the given 23 | value is nil. Otherwise it returns the localized string "importButtonTitle". 24 | */ 25 | 26 | @interface MTButtonTitleTransformer : NSValueTransformer 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTUsagePriceTextTransformer.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTUsagePriceTextTransformer.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTUsagePriceTextTransformer.h" 19 | 20 | @implementation MTUsagePriceTextTransformer 21 | 22 | + (BOOL)allowsReverseTransformation 23 | { 24 | return NO; 25 | } 26 | 27 | - (id)transformedValue:(id)value 28 | { 29 | return ([value boolValue]) ? NSLocalizedString(@"usagePriceTodayText", nil) : NSLocalizedString(@"usagePriceText", nil); 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTUsagePeriodTextTransformer.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTUsagePeriodTextTransformer.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTUsagePeriodTextTransformer.h" 19 | 20 | @implementation MTUsagePeriodTextTransformer 21 | 22 | + (BOOL)allowsReverseTransformation 23 | { 24 | return NO; 25 | } 26 | 27 | - (id)transformedValue:(id)value 28 | { 29 | return ([value boolValue]) ? NSLocalizedString(@"usagePeriodTodayText", nil) : NSLocalizedString(@"usagePeriodText", nil); 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTSegmentedControl.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSegmentedControl.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTSegmentedControl : NSSegmentedControl 21 | 22 | /*! 23 | @method setSelectedSegmentsWithArray: 24 | @abstract Selects the specified segments. 25 | @param selected An array of NSNumber objects representing the indexes of the segments that should be selected. 26 | */ 27 | - (void)setSelectedSegmentsWithArray:(NSArray*)selected; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTUsageConsumptionTextTransformer.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTUsagePriceTextTransformer.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTUsageConsumptionTextTransformer.h" 19 | 20 | @implementation MTUsageConsumptionTextTransformer 21 | 22 | + (BOOL)allowsReverseTransformation 23 | { 24 | return NO; 25 | } 26 | 27 | - (id)transformedValue:(id)value 28 | { 29 | return ([value boolValue]) ? NSLocalizedString(@"usageConsumptionTodayText", nil) : NSLocalizedString(@"usageConsumptionText", nil); 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTUsagePeriodTextTransformer.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTUsagePeriodTextTransformer.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTUsagePeriodTextTransformer 22 | @abstract A value transformer that returns the localized string "usagePeriodTodayText" if the bool value 23 | of the given value is YES. Otherwise it returns the localized string "usagePeriodText". 24 | */ 25 | 26 | @interface MTUsagePeriodTextTransformer : NSValueTransformer 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTModifyData.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTModifyData.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTModifyData.h" 19 | 20 | @implementation NSData (MTModifyData) 21 | 22 | - (void)replaceMappedBytesInRange:(NSRange)range withBytes:(const void *)bytes 23 | { 24 | void *dataPtr = (void*)[self bytes]; 25 | NSUInteger finalLength = range.location + range.length; 26 | 27 | if (finalLength <= [self length]) { 28 | dataPtr = dataPtr + range.location; 29 | memcpy(dataPtr, bytes, range.length); 30 | } 31 | } 32 | 33 | @end 34 | 35 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTLogLevelValueTransformer.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTLogLevelValueTransformer.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTLogLevelValueTransformer 22 | @abstract A value transformer that returns an image of a filled yellow circle 23 | if the given OSLogEntryLog is of level OSLogEntryLogLevelError 24 | or an image of a filled red circle if the given OSLogEntryLog is of 25 | level OSLogEntryLogLevelFault. 26 | */ 27 | 28 | @interface MTLogLevelValueTransformer : NSValueTransformer 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTUsagePriceTextTransformer.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTUsagePriceTextTransformer.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTUsagePriceTextTransformer 22 | @abstract A value transformer that returns the localized string "usagePriceTodayText" if the bool 23 | value of the given value is YES and the double value of the current electricity price is 24 | greater than 0. Otherwise it returns the localized string "usagePriceText". 25 | */ 26 | 27 | @interface MTUsagePriceTextTransformer : NSValueTransformer 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTUsageConsumptionTextTransformer.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTUsagePriceTextTransformer.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTUsagePriceTextTransformer 22 | @abstract A value transformer that returns the localized string "usageConsumptionTodayText" if the bool 23 | value of the given value is YES and the double value of the current electricity price is greater 24 | than 0. Otherwise it returns the localized string "usageConsumptionText". 25 | */ 26 | 27 | @interface MTUsageConsumptionTextTransformer : NSValueTransformer 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTPowerGraphTooltip.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPowerGraphTooltip.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTPowerMeasurement.h" 20 | 21 | /*! 22 | @class MTPowerGraphTooltip 23 | @abstract This class defines a floating tooltip window for the power graph. 24 | */ 25 | 26 | @interface MTPowerGraphTooltip : NSWindow 27 | 28 | /*! 29 | @method setMeasurement: 30 | @abstract Set the measurement for the power graph's tooltip. 31 | @param measurement The MTPowerMeasurement object that should be displayed as the tooltip. 32 | */ 33 | - (void)setMeasurement:(MTPowerMeasurement*)measurement; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /source/PowerMonitorXPC/PowerMonitorXPCProtocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | PowerMonitorXPCProtocol.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @protocol PowerMonitorXPCProtocol 22 | @abstract Defines the protocol implemented by the xpc service and 23 | called by Power Monitor. 24 | */ 25 | 26 | @protocol PowerMonitorXPCProtocol 27 | 28 | /*! 29 | @method connectWithDaemonEndpointReply: 30 | @abstract Returns an endpoint that's connected to the daemon. 31 | @param reply The reply block to call when the request is complete. 32 | */ 33 | - (void)connectWithDaemonEndpointReply:(void(^)(NSXPCListenerEndpoint *endpoint))reply; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTWeekdayTextField.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTWeekdayTextField.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTWeekdayTextField : NSTextField 21 | 22 | /*! 23 | @method dayOfTheWeekForElementWithID: 24 | @abstract Returns the day of the week for the element with the given id. 25 | @param elementID An integer specifying the id of the element. 26 | @discussion Would return 0 on U.S. systems for the element with the id 1, because there the first day of the week is Sunday (0). 27 | On a German system it would return 1, because there the week starts on Monday (1). Returns the day of the week 28 | as an integer or -1 if an error occurred. 29 | */ 30 | + (NSInteger)dayOfTheWeekForElementWithID:(NSInteger)elementID; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /source/Power Monitor/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDocumentTypes 6 | 7 | 8 | CFBundleTypeIconSystemGenerated 9 | 1 10 | CFBundleTypeName 11 | Power Monitor Data File 12 | CFBundleTypeRole 13 | Viewer 14 | LSHandlerRank 15 | Owner 16 | LSItemContentTypes 17 | 18 | corp.sap.PowerMonitor.data 19 | 20 | NSDocumentClass 21 | NSDocument 22 | 23 | 24 | LSHasLocalizedDisplayName 25 | 26 | UTExportedTypeDeclarations 27 | 28 | 29 | UTTypeConformsTo 30 | 31 | public.data 32 | 33 | UTTypeDescription 34 | Power Monitor Data File 35 | UTTypeIcons 36 | 37 | UTTypeIdentifier 38 | corp.sap.PowerMonitor.data 39 | UTTypeTagSpecification 40 | 41 | public.filename-extension 42 | 43 | pwrdata 44 | 45 | public.mime-type 46 | 47 | application/octet-stream 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTJournalSplitViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTJournalSplitViewController.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTJournalSplitViewController.h" 19 | #import "MTJournalController.h" 20 | #import "MTJournalInspectorController.h" 21 | #import "Constants.h" 22 | 23 | @implementation MTJournalSplitViewController 24 | 25 | - (void)viewDidLoad 26 | { 27 | [super viewDidLoad]; 28 | 29 | NSSplitViewItem *contentItem = [[self splitViewItems] firstObject]; 30 | NSSplitViewItem *inspectorItem = [[self splitViewItems] lastObject]; 31 | 32 | // set a delegate so we can pass data to our inspector 33 | MTJournalController *contentController = (MTJournalController*)[contentItem viewController]; 34 | MTJournalInspectorController *inspectorController = (MTJournalInspectorController*)[inspectorItem viewController]; 35 | [contentController setDelegate:inspectorController]; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /source/Power Monitor/AppIcon.icon/Assets/l1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /source/Power Monitor/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "AppIcon-16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "AppIcon-32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "AppIcon-32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "AppIcon-64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "AppIcon-128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "AppIcon-256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "AppIcon-256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "AppIcon-512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "AppIcon-512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "AppIcon-1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /source/PowerMonitorDaemon/Classes/MTPowerMonitorDaemon.h: -------------------------------------------------------------------------------- 1 | /* 2 | PowerMonitorDaemon.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTSleepWatcher.h" 20 | #import "PowerMonitorDaemonProtocol.h" 21 | 22 | /*! 23 | @class MTPowerMonitorDaemon 24 | @abstract This class defines the power monitor daemon. 25 | */ 26 | 27 | @interface MTPowerMonitorDaemon : NSObject 28 | 29 | /*! 30 | @method startMonitoring 31 | @abstract Starts power monitoring. 32 | @discussion Returns YES if the measurement file could be opened for writing, mapped into memory 33 | and power monitoring started successfully, otherwise returns NO. 34 | */ 35 | - (BOOL)startMonitoring; 36 | 37 | /*! 38 | @method stopMonitoring 39 | @abstract Stops power monitoring. 40 | @discussion Returns YES if power monitoring has been stopped, otherwise returns NO. 41 | */ 42 | - (BOOL)stopMonitoring; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTToolbarItem.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTToolbarItem.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTToolbarItem.h" 19 | 20 | @implementation MTToolbarItem 21 | 22 | - (void)validate 23 | { 24 | BOOL enabled = YES; 25 | 26 | // get the content controller… 27 | NSSplitViewController *consoleSplitViewController = (NSSplitViewController*)[[[self view] window] contentViewController]; 28 | 29 | if (consoleSplitViewController && [consoleSplitViewController respondsToSelector:@selector(validateToolbarItem:)]) { 30 | 31 | NSInvocationOperation *invocation = [[NSInvocationOperation alloc] initWithTarget:consoleSplitViewController 32 | selector:@selector(validateToolbarItem:) 33 | object:self 34 | ]; 35 | [invocation start]; 36 | [[invocation result] getValue:&enabled]; 37 | 38 | [self setEnabled:enabled]; 39 | } 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTModifyData.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTModifyData.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @abstract This extends the NSData class with the method replaceMappedBytesInRange:withBytes: to allow 22 | the modification of memory-mapped data. 23 | */ 24 | 25 | @interface NSData (MTModifyData) 26 | 27 | /*! 28 | @method replaceMappedBytesInRange:withBytes: 29 | @abstract Replaces with a given set of bytes a given range within the contents of the receiver. 30 | @param range The range within the receiver's contents to replace with bytes. The range must not exceed the bounds of the receiver. 31 | @param bytes The data to insert into the receiver's contents. 32 | @discussion If the location of range isn’t within the receiver’s range of bytes, an NSRangeException is raised. 33 | The receiver is resized to accommodate the new bytes, if necessary. 34 | */ 35 | - (void)replaceMappedBytesInRange:(NSRange)range withBytes:(const void *)bytes; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /source/PowerMonitorXPC/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | main.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "PowerMonitorXPC.h" 20 | 21 | @interface ServiceDelegate : NSObject 22 | @end 23 | 24 | @implementation ServiceDelegate 25 | 26 | - (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection 27 | { 28 | [newConnection setExportedInterface:[NSXPCInterface interfaceWithProtocol:@protocol(PowerMonitorXPCProtocol)]]; 29 | [newConnection setExportedObject:[[PowerMonitorXPC alloc] init]]; 30 | [newConnection resume]; 31 | 32 | return YES; 33 | } 34 | 35 | @end 36 | 37 | int main(int argc, const char *argv[]) 38 | { 39 | #pragma unused(argc) 40 | #pragma unused(argv) 41 | 42 | ServiceDelegate *delegate = [[ServiceDelegate alloc] init]; 43 | 44 | // set up the NSXPCListener 45 | NSXPCListener *listener = [NSXPCListener serviceListener]; 46 | [listener setDelegate:delegate]; 47 | [listener resume]; 48 | 49 | return EXIT_SUCCESS; 50 | } 51 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTJournalTableView.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTJournalTableView.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTJournalTableView.h" 19 | 20 | @implementation MTJournalTableView 21 | 22 | - (NSMenu *)menuForEvent:(NSEvent *)event 23 | { 24 | [super menuForEvent:event]; 25 | 26 | NSInteger clickedRow = [self clickedRow]; 27 | 28 | // add an item for deleting one or more journal entries 29 | NSMenuItem *removeItem = [[self menu] itemWithTag:1000]; 30 | 31 | if (clickedRow >= 0) { 32 | 33 | if ([[self selectedRowIndexes] containsIndex:clickedRow] && [[self selectedRowIndexes] count] > 1) { 34 | [removeItem setTitle:NSLocalizedString(@"deleteJournalMultipleMenuEntry", nil)]; 35 | } else { 36 | [removeItem setTitle:NSLocalizedString(@"deleteJournalOneMenuEntry", nil)]; 37 | } 38 | 39 | [removeItem setHidden:NO]; 40 | 41 | } else { 42 | 43 | [removeItem setHidden:YES]; 44 | } 45 | 46 | return [self menu]; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTSidebarItem.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSidebarItem.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTSidebarItem 22 | @abstract This class specifies a sidebar item. 23 | */ 24 | 25 | @interface MTSidebarItem : NSObject 26 | 27 | /*! 28 | @property label 29 | @abstract A property to specify the text label of a sidebar item. 30 | @discussion The value of this property is NSString. 31 | */ 32 | @property (nonatomic, strong, readwrite) NSString *label; 33 | 34 | /*! 35 | @property image 36 | @abstract A property to specify the image of a sidebar item. 37 | @discussion The value of this property is NSImage. 38 | */ 39 | @property (nonatomic, strong, readwrite) NSImage *image; 40 | 41 | /*! 42 | @property targetViewControllerIdentifier 43 | @abstract A property to specify the identifier of the target view controller to be called when 44 | the sidebar item is clicked. 45 | @discussion The value of this property is NSString. 46 | */ 47 | @property (nonatomic, strong, readwrite) NSString *targetViewControllerIdentifier; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTUsageConsumptionValueTransformer.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTUsageConsumptionValueTransformer.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTUsageConsumptionValueTransformer.h" 19 | #import "Constants.h" 20 | 21 | @implementation MTUsageConsumptionValueTransformer 22 | 23 | + (BOOL)allowsReverseTransformation 24 | { 25 | return NO; 26 | } 27 | 28 | - (id)transformedValue:(id)value 29 | { 30 | NSNumber *measuredValue = (NSNumber*)value; 31 | 32 | NSMeasurement *powerConsumption = [[NSMeasurement alloc] initWithDoubleValue:[measuredValue doubleValue] unit:[NSUnitEnergy joules]]; 33 | powerConsumption = [powerConsumption measurementByConvertingToUnit:[NSUnitEnergy kilowattHours]]; 34 | 35 | NSMeasurementFormatter *powerFormatter = [[NSMeasurementFormatter alloc] init]; 36 | [[powerFormatter numberFormatter] setMinimumFractionDigits:3]; 37 | [[powerFormatter numberFormatter] setMaximumFractionDigits:3]; 38 | [powerFormatter setUnitOptions:NSMeasurementFormatterUnitOptionsNaturalScale | NSMeasurementFormatterUnitOptionsProvidedUnit]; 39 | 40 | NSString *returnValue = [powerFormatter stringFromMeasurement:powerConsumption]; 41 | 42 | return returnValue; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTLogDetailsController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTLogDetailsController.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTLogDetailsController.h" 19 | #import "Constants.h" 20 | 21 | @interface MTLogDetailsController () 22 | @property (weak) IBOutlet NSTextView *logDetailsView; 23 | @end 24 | 25 | @implementation MTLogDetailsController 26 | 27 | - (void)viewDidLoad 28 | { 29 | [super viewDidLoad]; 30 | 31 | [_logDetailsView setFont:[NSFont monospacedSystemFontOfSize:11 weight:NSFontWeightRegular]]; 32 | 33 | // register for notifications 34 | [[NSNotificationCenter defaultCenter] addObserver:self 35 | selector:@selector(updateDetailView:) 36 | name:kMTNotificationNameLogMessage 37 | object:nil 38 | ]; 39 | } 40 | 41 | - (void)updateDetailView:(NSNotification*)notification 42 | { 43 | NSDictionary *userInfo = [notification userInfo]; 44 | 45 | if (userInfo) { 46 | 47 | NSString *logMessage = [userInfo objectForKey:kMTNotificationKeyLogMessage]; 48 | if (logMessage) { [self.logDetailsView setString:logMessage]; } 49 | } 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /source/Power Monitor/AppIcon.icon/icon.json: -------------------------------------------------------------------------------- 1 | { 2 | "fill" : "automatic", 3 | "groups" : [ 4 | { 5 | "layers" : [ 6 | { 7 | "fill-specializations" : [ 8 | { 9 | "appearance" : "tinted", 10 | "value" : { 11 | "solid" : "extended-gray:0.75000,1.00000" 12 | } 13 | } 14 | ], 15 | "glass-specializations" : [ 16 | { 17 | "appearance" : "tinted", 18 | "value" : false 19 | } 20 | ], 21 | "image-name" : "l3.svg", 22 | "name" : "l3" 23 | }, 24 | { 25 | "fill-specializations" : [ 26 | { 27 | "appearance" : "tinted", 28 | "value" : { 29 | "solid" : "extended-gray:0.50000,1.00000" 30 | } 31 | } 32 | ], 33 | "image-name" : "l2.svg", 34 | "name" : "l2" 35 | }, 36 | { 37 | "fill-specializations" : [ 38 | { 39 | "value" : "none" 40 | }, 41 | { 42 | "appearance" : "tinted", 43 | "value" : { 44 | "solid" : "extended-gray:0.25000,1.00000" 45 | } 46 | } 47 | ], 48 | "image-name" : "l1.svg", 49 | "name" : "l1" 50 | } 51 | ], 52 | "position" : { 53 | "scale" : 1.24, 54 | "translation-in-points" : [ 55 | 0, 56 | 0 57 | ] 58 | }, 59 | "shadow" : { 60 | "kind" : "neutral", 61 | "opacity" : 0.5 62 | }, 63 | "specular" : false, 64 | "translucency" : { 65 | "enabled" : false, 66 | "value" : 0.5 67 | } 68 | } 69 | ], 70 | "supported-platforms" : { 71 | "squares" : [ 72 | "macOS" 73 | ] 74 | } 75 | } -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTJournalController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTJournalController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @class MTJournalController; 21 | /*! 22 | @protocol MTJournalControllerDelegate 23 | @abstract Defines an interface for delegates of MTJournalController to be notified if specific aspects of the journal have changed. 24 | */ 25 | @protocol MTJournalControllerDelegate 26 | @optional 27 | 28 | /*! 29 | @method journalControllerSelectionDidChange: 30 | @abstract Called whenever the selection of the journal array controller changed. 31 | @param controller A reference to the NSArrayController instance. 32 | @discussion Delegates receive this message whenever the selection of the journal array controller changed. 33 | */ 34 | - (void)journalControllerSelectionDidChange:(NSArrayController*)controller; 35 | 36 | @end 37 | 38 | @interface MTJournalController : NSViewController 39 | 40 | /*! 41 | @property delegate 42 | @abstract The receiver's delegate. 43 | @discussion The value of this property is an object conforming to the MTJournalControllerDelegate protocol. 44 | */ 45 | @property (weak) id delegate; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTSegmentedControl.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTSegmentedControl.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTSegmentedControl.h" 19 | 20 | @implementation MTSegmentedControl 21 | 22 | - (instancetype)init 23 | { 24 | self = [super init]; 25 | 26 | if (self) { 27 | 28 | [self setUpControl]; 29 | } 30 | 31 | return self; 32 | } 33 | 34 | - (instancetype)initWithCoder:(NSCoder *)coder 35 | { 36 | self = [super initWithCoder:coder]; 37 | 38 | if (self) { 39 | 40 | [self setUpControl]; 41 | } 42 | 43 | return self; 44 | } 45 | 46 | - (void)setUpControl 47 | { 48 | [self setSelectedSegment:-1]; 49 | [self setToolTip:NSLocalizedString(@"altScheduleToolTip", nil)]; 50 | [self setAccessibilityChildren:nil]; 51 | } 52 | 53 | - (void)setSelectedSegmentsWithArray:(NSArray*)selected 54 | { 55 | [self setSelectedSegment:-1]; 56 | 57 | for (NSNumber *index in selected) { 58 | 59 | NSInteger selectedIndex = [index integerValue]; 60 | NSInteger numberOfSegments = [self segmentCount]; 61 | 62 | if (selectedIndex >= 0 && selectedIndex < numberOfSegments) { 63 | [self setSelected:YES forSegment:selectedIndex]; 64 | } 65 | } 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTWeekdayTextField.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTWeekdayTextField.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTWeekdayTextField.h" 19 | 20 | @implementation MTWeekdayTextField 21 | 22 | - (instancetype)init 23 | { 24 | self = [super init]; 25 | 26 | if (self) { 27 | 28 | [self setUpControl]; 29 | } 30 | 31 | return self; 32 | } 33 | 34 | - (instancetype)initWithCoder:(NSCoder *)coder 35 | { 36 | self = [super initWithCoder:coder]; 37 | 38 | if (self) { 39 | 40 | [self setUpControl]; 41 | } 42 | 43 | return self; 44 | } 45 | 46 | - (void)setUpControl 47 | { 48 | NSInteger index = [MTWeekdayTextField dayOfTheWeekForElementWithID:[self tag]]; 49 | 50 | if (index >= 0) { 51 | [self setStringValue:[NSString stringWithFormat:@"%@:", [[[NSCalendar currentCalendar] weekdaySymbols] objectAtIndex:index]]]; 52 | } 53 | } 54 | 55 | + (NSInteger)dayOfTheWeekForElementWithID:(NSInteger)elementID 56 | { 57 | NSInteger index = -1; 58 | 59 | // weekday numbers start from 1 (first day of the week) 60 | if (elementID >= 1 && elementID <= 7) { 61 | 62 | index = (elementID - 1 + [[NSCalendar currentCalendar] firstWeekday] - 1) % 7; 63 | } 64 | 65 | return index; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTHourTextField.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTHourTextField.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTHourTextField.h" 19 | #import "MTElectricityPrice.h" 20 | 21 | @implementation MTHourTextField 22 | 23 | - (instancetype)init 24 | { 25 | self = [super init]; 26 | 27 | if (self) { 28 | 29 | [self setUpControl]; 30 | } 31 | 32 | return self; 33 | } 34 | 35 | - (instancetype)initWithCoder:(NSCoder *)coder 36 | { 37 | self = [super initWithCoder:coder]; 38 | 39 | if (self) { 40 | 41 | [self setUpControl]; 42 | } 43 | 44 | return self; 45 | } 46 | 47 | - (void)setUpControl 48 | { 49 | NSInteger hour = [self tag]; 50 | 51 | if (hour >= 0 && hour <= 23) { 52 | 53 | NSDateComponents *components = [[NSDateComponents alloc] init]; 54 | [components setHour:hour]; 55 | [components setMinute:0]; 56 | 57 | NSDateFormatter *timeFormatter = [[NSDateFormatter alloc] init]; 58 | timeFormatter.timeStyle = NSDateFormatterShortStyle; 59 | timeFormatter.dateStyle = NSDateFormatterNoStyle; 60 | 61 | NSCalendar *calendar = [NSCalendar currentCalendar]; 62 | NSString *hourString = [timeFormatter stringFromDate:[calendar dateFromComponents:components]]; 63 | 64 | [self setStringValue:hourString]; 65 | } 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTPowerMeasurement.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTPowerMeasurement.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTPowerMeasurement.h" 19 | 20 | @implementation MTPowerMeasurement 21 | 22 | - (instancetype)initWithPowerValue:(double)powerValue 23 | { 24 | self = [super initWithDoubleValue:powerValue unit:[NSUnitPower watts]]; 25 | 26 | return self; 27 | } 28 | 29 | + (MeasurementFileHeader)headerWithFilePath:(NSString*)path 30 | { 31 | MeasurementFileHeader buffer = (MeasurementFileHeader){ 0 }; 32 | 33 | int fd = open([path UTF8String], O_RDONLY); 34 | 35 | if (fd >= 0) { 36 | 37 | size_t headerSize = read(fd, &buffer, sizeof(MeasurementFileHeader)); 38 | close(fd); 39 | 40 | if (headerSize != sizeof(MeasurementFileHeader)) { 41 | buffer = (MeasurementFileHeader){ 0 }; 42 | } 43 | } 44 | 45 | return buffer; 46 | } 47 | 48 | - (NSString*)state 49 | { 50 | NSString *stateString = NSLocalizedString(@"tooltipSleep", nil); 51 | 52 | if ([self doubleValue] > 0) { 53 | 54 | if ([self darkWake]) { 55 | 56 | stateString = NSLocalizedString(@"tooltipPowerNap", nil); 57 | 58 | } else { 59 | 60 | stateString = NSLocalizedString(@"tooltipAwake", nil); 61 | } 62 | } 63 | 64 | return stateString; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /source/Power Monitor/InfoPlist.xcstrings: -------------------------------------------------------------------------------- 1 | { 2 | "sourceLanguage" : "en", 3 | "strings" : { 4 | "CFBundleDisplayName" : { 5 | "comment" : "the localized app name", 6 | "extractionState" : "extracted_with_value", 7 | "localizations" : { 8 | "de" : { 9 | "stringUnit" : { 10 | "state" : "translated", 11 | "value" : "Leistungsanzeige" 12 | } 13 | }, 14 | "en" : { 15 | "stringUnit" : { 16 | "state" : "new", 17 | "value" : "Power Monitor" 18 | } 19 | } 20 | } 21 | }, 22 | "CFBundleName" : { 23 | "comment" : "Bundle name", 24 | "extractionState" : "extracted_with_value", 25 | "localizations" : { 26 | "de" : { 27 | "stringUnit" : { 28 | "state" : "translated", 29 | "value" : "Leistungsanzeige" 30 | } 31 | }, 32 | "en" : { 33 | "stringUnit" : { 34 | "state" : "new", 35 | "value" : "Power Monitor" 36 | } 37 | } 38 | } 39 | }, 40 | "NSHumanReadableCopyright" : { 41 | "comment" : "the copyright string (for the application's info window in Finder)", 42 | "extractionState" : "extracted_with_value", 43 | "localizations" : { 44 | "de" : { 45 | "stringUnit" : { 46 | "state" : "translated", 47 | "value" : "Copyright © 2023-2025 SAP SE. Alle Rechte vorbehalten." 48 | } 49 | }, 50 | "en" : { 51 | "stringUnit" : { 52 | "state" : "new", 53 | "value" : "Copyright © 2023-2025 SAP SE. All rights reserved." 54 | } 55 | } 56 | } 57 | }, 58 | "Power Monitor Data File" : { 59 | "comment" : "the localized document type", 60 | "localizations" : { 61 | "de" : { 62 | "stringUnit" : { 63 | "state" : "translated", 64 | "value" : "Power Monitor Datei" 65 | } 66 | } 67 | } 68 | } 69 | }, 70 | "version" : "1.0" 71 | } -------------------------------------------------------------------------------- /source/Power Monitor/Value Transformers/MTLogLevelValueTransformer.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTLogLevelValueTransformer.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTLogLevelValueTransformer.h" 19 | #import 20 | 21 | @implementation MTLogLevelValueTransformer 22 | 23 | + (BOOL)allowsReverseTransformation 24 | { 25 | return NO; 26 | } 27 | 28 | - (id)transformedValue:(id)value 29 | { 30 | NSImage *levelIndicator = nil; 31 | 32 | if (value && [value isKindOfClass:[OSLogEntryLog class]]) { 33 | 34 | OSLogEntryLog *entry = (OSLogEntryLog*)value; 35 | 36 | if ([entry level] == OSLogEntryLogLevelError) { 37 | 38 | NSImageSymbolConfiguration *config = [NSImageSymbolConfiguration configurationWithHierarchicalColor:[NSColor systemYellowColor]]; 39 | 40 | levelIndicator = [[NSImage imageWithSystemSymbolName:@"circlebadge.fill" accessibilityDescription:nil] imageWithSymbolConfiguration:config]; 41 | 42 | } else if ([entry level] == OSLogEntryLogLevelFault) { 43 | 44 | NSImageSymbolConfiguration *config = [NSImageSymbolConfiguration configurationWithHierarchicalColor:[NSColor systemRedColor]]; 45 | 46 | levelIndicator = [[NSImage imageWithSystemSymbolName:@"circlebadge.fill" accessibilityDescription:nil] imageWithSymbolConfiguration:config]; 47 | } 48 | } 49 | 50 | return levelIndicator; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTSavePanelAccessoryController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTSavePanelAccessoryController.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTSavePanelAccessoryController.h" 19 | #import "Constants.h" 20 | #import 21 | 22 | @implementation MTSavePanelAccessoryController 23 | 24 | - (void)viewDidLoad 25 | { 26 | [super viewDidLoad]; 27 | 28 | self.summarizeType = [self summarizeTypeForTag:[[NSUserDefaults standardUserDefaults] integerForKey:kMTDefaultsJournalExportSummarizeKey]]; 29 | } 30 | 31 | - (NSCalendarUnit)summarizeTypeForTag:(NSInteger)tag 32 | { 33 | NSCalendarUnit type = 0; 34 | 35 | switch (tag) { 36 | 37 | case 1: 38 | type = NSCalendarUnitWeekOfYear; 39 | break; 40 | 41 | case 2: 42 | type = NSCalendarUnitMonth; 43 | break; 44 | 45 | case 3: 46 | type = NSCalendarUnitYear; 47 | break; 48 | 49 | default: 50 | type = 0; 51 | break; 52 | } 53 | 54 | return type; 55 | } 56 | 57 | - (IBAction)selectExportFileType:(id)sender 58 | { 59 | NSSavePanel *savePanel = (NSSavePanel*)[sender window]; 60 | [savePanel setAllowedContentTypes:[NSArray arrayWithObject:([sender selectedTag] == 1) ? UTTypeJSON : UTTypeCommaSeparatedText]]; 61 | } 62 | 63 | - (IBAction)setSummarizing:(id)sender 64 | { 65 | self.summarizeType = [self summarizeTypeForTag:[sender selectedTag]]; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /source/PowerMonitorDaemon/Classes/MTPowerEvent.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTPowerEvent.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTPowerEvent.h" 19 | #import "IOPMLibPrivate.h" 20 | 21 | @interface MTPowerEvent () 22 | @property (nonatomic, strong, readwrite) NSDate *startDate; 23 | @property (nonatomic, strong, readwrite) NSDate *endDate; 24 | @end 25 | 26 | @implementation MTPowerEvent 27 | 28 | - (instancetype)init 29 | { 30 | self = [super init]; 31 | 32 | if (self) { 33 | _startDate = [NSDate date]; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (void)endEvent 40 | { 41 | _endDate = [NSDate date]; 42 | } 43 | 44 | - (NSTimeInterval)duration 45 | { 46 | NSDate *endDate = (_endDate) ? _endDate : [NSDate date]; 47 | NSTimeInterval eventDuration = [endDate timeIntervalSinceDate:_startDate]; 48 | 49 | return eventDuration; 50 | } 51 | 52 | - (BOOL)didEnd 53 | { 54 | return (_endDate) ? YES : NO; 55 | } 56 | 57 | + (MTPowerEventType)eventTypeWithCapabilities:(IOPMSystemPowerStateCapabilities)capabilities 58 | { 59 | MTPowerEventType eventType = MTPowerEventTypeNone; 60 | 61 | if (IOPMIsASleep(capabilities)) { 62 | 63 | eventType = MTPowerEventTypeSleep; 64 | 65 | } else if (IOPMIsADarkWake(capabilities)) { 66 | 67 | eventType = MTPowerEventTypeDarkWake; 68 | 69 | } else if (IOPMIsAUserWake(capabilities)) { 70 | 71 | eventType = MTPowerEventTypeUserWake; 72 | } 73 | 74 | return eventType; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /source/Power Monitor/AppIcon.icon/Assets/l2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /source/Power Monitor/AppIcon.icon/Assets/l3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTAssertionsController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTAssertionsController.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTAssertionsController.h" 19 | #import "MTSystemInfo.h" 20 | #import "Constants.h" 21 | 22 | @interface MTAssertionsController () 23 | @property (nonatomic, strong, readwrite) NSMutableArray *assertionEntries; 24 | 25 | @property (weak) IBOutlet NSTableView *assertionsTableView; 26 | @property (weak) IBOutlet NSArrayController *assertionsController; 27 | @end 28 | 29 | @implementation MTAssertionsController 30 | 31 | - (void)viewDidLoad 32 | { 33 | [super viewDidLoad]; 34 | 35 | [_assertionsTableView setAccessibilityLabel:NSLocalizedString(@"accessiblilityLabelAssertionsTableView", nil)]; 36 | 37 | _assertionEntries = [[NSMutableArray alloc] init]; 38 | NSSortDescriptor *initialSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"Process Name" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]; 39 | [self.assertionsController setSortDescriptors:[NSArray arrayWithObject:initialSortDescriptor]]; 40 | 41 | [self updateProcessList]; 42 | } 43 | 44 | - (void)updateProcessList 45 | { 46 | NSArray *processList = [MTSystemInfo processesPreventingSleep]; 47 | 48 | if (processList) { 49 | self.assertionEntries = [NSMutableArray arrayWithArray:processList]; 50 | } 51 | } 52 | 53 | - (IBAction)updateContent:(id)sender 54 | { 55 | [self updateProcessList]; 56 | } 57 | 58 | #pragma mark NSToolbarItemValidation 59 | 60 | - (BOOL)enableToolbarItem:(NSToolbarItem *)item 61 | { 62 | BOOL enable = NO; 63 | 64 | if (item) { 65 | 66 | if ([[item itemIdentifier] isEqualToString:MTToolbarConsoleReloadItemIdentifier]) { 67 | 68 | enable = YES; 69 | } 70 | } 71 | 72 | return enable; 73 | } 74 | 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTDescriptionController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTDescriptionController.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTDescriptionController.h" 19 | #import "Constants.h" 20 | 21 | @interface MTDescriptionController () 22 | @property (weak) IBOutlet NSTextField *powerDescription; 23 | @end 24 | 25 | @implementation MTDescriptionController 26 | 27 | - (void)viewDidLoad 28 | { 29 | [super viewDidLoad]; 30 | 31 | NSMeasurement *measurementInterval = [[NSMeasurement alloc] initWithDoubleValue:kMTMeasurementInterval 32 | unit:[NSUnitDuration seconds] 33 | ]; 34 | 35 | NSMeasurement *measurementPeriod = [[NSMeasurement alloc] initWithDoubleValue:kMTMeasurementTimePeriod 36 | unit:[NSUnitDuration hours] 37 | ]; 38 | 39 | NSMeasurementFormatter *timeFormatter = [[NSMeasurementFormatter alloc] init]; 40 | [[timeFormatter numberFormatter] setMaximumFractionDigits:0]; 41 | [timeFormatter setUnitStyle:NSFormattingUnitStyleLong]; 42 | [timeFormatter setUnitOptions:NSMeasurementFormatterUnitOptionsNaturalScale]; 43 | 44 | NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; 45 | [numberFormatter setMaximumFractionDigits:0]; 46 | [numberFormatter setNumberStyle:NSNumberFormatterPercentStyle]; 47 | 48 | [_powerDescription setStringValue:[NSString localizedStringWithFormat:NSLocalizedString(@"powerDescription", nil), 49 | [timeFormatter stringFromMeasurement:measurementInterval], 50 | [timeFormatter stringFromMeasurement:measurementPeriod], 51 | [numberFormatter stringFromNumber:[NSNumber numberWithFloat:.1]] 52 | ] 53 | ]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTTabViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTTabViewController.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTTabViewController.h" 19 | #import "Constants.h" 20 | 21 | @interface MTTabViewController () 22 | @property (assign) BOOL skipSelection; 23 | @end 24 | 25 | @implementation MTTabViewController 26 | 27 | - (id)initWithCoder:(NSCoder *)coder 28 | { 29 | self = [super initWithCoder:coder]; 30 | 31 | if (self) { 32 | 33 | _skipSelection = YES; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (void)viewDidLoad 40 | { 41 | [super viewDidLoad]; 42 | 43 | // select the last tab the user selected 44 | NSInteger selectedTabIndex = [[NSUserDefaults standardUserDefaults] integerForKey:kMTDefaultsSettingsSelectedTabKey]; 45 | 46 | if (selectedTabIndex >= 0 && selectedTabIndex < [[self tabViewItems] count]) { 47 | [self setSelectedTabViewItemIndex:selectedTabIndex]; 48 | } else { 49 | [self setSelectedTabViewItemIndex:0]; 50 | } 51 | } 52 | 53 | - (void)viewWillAppear 54 | { 55 | [super viewWillAppear]; 56 | [self updateWindowTitle]; 57 | } 58 | 59 | - (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem 60 | { 61 | [super tabView:tabView didSelectTabViewItem:tabViewItem]; 62 | [self updateWindowTitle]; 63 | 64 | // we skip the initial tab selection (the one we had to define in Xcode) 65 | if (_skipSelection) { 66 | 67 | _skipSelection = NO; 68 | 69 | } else { 70 | 71 | [[NSUserDefaults standardUserDefaults] setInteger:[tabView indexOfTabViewItem:[tabView selectedTabViewItem]] forKey:kMTDefaultsSettingsSelectedTabKey]; 72 | } 73 | } 74 | 75 | - (void)updateWindowTitle 76 | { 77 | // set the window title to the label of the selected tab 78 | NSTabViewItem *selectedItem = [[self tabView] selectedTabViewItem]; 79 | [[[self tabView] window] setTitle:[selectedItem label]]; 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /example_jamf_pro_extension_attribute/example_jamf_pro_extension_attribute.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This Jamf Pro Extension Attribute gets the carbon average power value 4 | # and the current country code from the Power Monitor app, then uses 5 | # static information (see end of the script) to calculate the carbon 6 | # footprint. Script returns the carbon footprint as an integer value 7 | # in gCO2eq/h or -1 if an error occurred. 8 | 9 | appPath="/Applications/Power Monitor.app/Contents/MacOS/Power Monitor" 10 | 11 | ########## nothing to change below this line ########## 12 | 13 | carbonFootprint=-1 14 | 15 | if [[ -x "$appPath" ]]; then 16 | 17 | pmOut=$("$appPath" --noGUI & /bin/sleep 2 && kill $! >/dev/null 2>&1) 18 | 19 | if [[ -n "$pmOut" ]]; then 20 | 21 | averagePower=$(/usr/bin/sed -n 's/^Average[^:]*: \([0-9\.]*\).*$/\1/p' <<< "$pmOut") 22 | countryCode=$(/usr/bin/sed -n 's/^Country[^:]*: \([A-Z]*\).*$/\1/p' <<< "$pmOut") 23 | 24 | if [[ "$averagePower" =~ ^[0-9\.]+$ && -n "$countryCode" ]]; then 25 | 26 | carbonIntensity=$(/usr/bin/sed "1,/########## carbon intensity data ##########/d" "$0" | /usr/bin/sed -n "s/^$countryCode;\(.*\)/\1/p") 27 | 28 | if [[ "$carbonIntensity" =~ ^[0-9]+$ ]]; then 29 | 30 | # calculate footprint 31 | calculatedFootprint=$(/usr/bin/bc -l <<< "($averagePower / 1000) * $carbonIntensity") 32 | 33 | # round footprint 34 | calculatedFootprint=$(echo "scale=0;($calculatedFootprint+0.5)/1" | /usr/bin/bc) 35 | 36 | if [[ "$calculatedFootprint" =~ ^[0-9]+$ && $calculatedFootprint -ge 0 ]]; then 37 | carbonFootprint="$calculatedFootprint" 38 | fi 39 | 40 | fi 41 | fi 42 | 43 | fi 44 | fi 45 | 46 | echo "$carbonFootprint" 47 | 48 | exit 0 49 | 50 | 51 | ########## carbon intensity data ########## 52 | 53 | AE;162 54 | AR;196 55 | AU;246 56 | AT;157 57 | AZ;210 58 | BE;126 59 | BD;203 60 | BG;196 61 | BY;194 62 | BR;140 63 | CA;141 64 | CH;117 65 | CL;185 66 | CN;262 67 | CO;172 68 | CY;255 69 | CZ;208 70 | DE;192 71 | DK;159 72 | DZ;257 73 | EC;195 74 | EG;237 75 | ES;150 76 | EE;159 77 | FI;117 78 | FR;117 79 | GB;174 80 | GR;192 81 | HK;130 82 | HR;178 83 | HU;172 84 | ID;268 85 | IN;275 86 | IE;215 87 | IR;221 88 | IQ;315 89 | IS;58 90 | IL;187 91 | IT;186 92 | JP;217 93 | KZ;350 94 | KR;176 95 | KW;220 96 | LK;196 97 | LT;198 98 | LU;199 99 | LV;172 100 | MA;266 101 | MX;216 102 | MK;236 103 | MY;220 104 | NL;146 105 | NO;72 106 | NZ;145 107 | OM;194 108 | PK;214 109 | PE;169 110 | PH;265 111 | PL;266 112 | PT;154 113 | QA;179 114 | RO;204 115 | RU;202 116 | SA;224 117 | SG;34 118 | SK;179 119 | SI;167 120 | SE;57 121 | TH;196 122 | TM;186 123 | TT;212 124 | TR;235 125 | TW;205 126 | UA;218 127 | US;194 128 | UZ;222 129 | VE;141 130 | VN;272 131 | ZA;315 132 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTCarbonAPIKey.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTCarbonAPIKey.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTCarbonFootprint.h" 20 | 21 | /*! 22 | @class MTCarbonAPIKey 23 | @abstract This class provides methods to store API keys in Keychain (and also to retrieve and delete them). 24 | */ 25 | 26 | @interface MTCarbonAPIKey : NSObject 27 | 28 | /*! 29 | @method init 30 | @discussion The init method is not available. Please use initWithAPIType: instead. 31 | */ 32 | - (instancetype)init NS_UNAVAILABLE; 33 | 34 | /*! 35 | @method initWithAPIType: 36 | @abstract Initialize a MTCarbonAPIKey object with a given api type. 37 | @param type The type of the api. 38 | @discussion Returns an initialized object for the specified api type. 39 | */ 40 | - (instancetype)initWithAPIType:(MTCarbonAPIType)type NS_DESIGNATED_INITIALIZER; 41 | 42 | /*! 43 | @method storeKey:completionHandler: 44 | @abstract Store the given key in the user's login keychain. 45 | @param key The key that should be stored. 46 | @param completionHandler The completion handler to call when the request is complete. 47 | @discussion Returns a reference to the keychain item (may be nil) and the status of the operation. 48 | */ 49 | - (void)storeKey:(NSString*)key completionHandler:(void(^)(OSStatus status, CFTypeRef item))completionHandler; 50 | 51 | /*! 52 | @method getKeyWithCompletionHandler: 53 | @abstract Retrieve the api key from the user's login keychain. 54 | @param completionHandler The completion handler to call when the request is complete. 55 | @discussion Returns the key or nil if an error occurred. 56 | */ 57 | - (void)getKeyWithCompletionHandler:(void(^)(NSString *key))completionHandler; 58 | 59 | /*! 60 | @method deleteKeyWithCompletionHandler: 61 | @abstract Delete the api key from the user's login keychain. 62 | @param completionHandler The completion handler to call when the request is complete. 63 | @discussion Returns YES if the key has been successfully deleted, otherwise returns NO. 64 | */ 65 | - (void)deleteKeyWithCompletionHandler:(void(^)(BOOL success))completionHandler; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTPowerMeasurementArray.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPowerMeasurementArray.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTPowerMeasurement.h" 20 | 21 | /*! 22 | @abstract This extends the NSArray class with some convenience methods used by arrays of MTPowerMeasurement objects. 23 | */ 24 | 25 | @interface NSArray (MTPowerMeasurementArray) 26 | 27 | /*! 28 | @method minimumPower 29 | @abstract Returns the minimum power value. 30 | @discussion Returns an MTPowerMeasurement object representing the minimum power value of the array. 31 | */ 32 | - (MTPowerMeasurement*)minimumPower; 33 | 34 | /*! 35 | @method averagePower 36 | @abstract Returns the average power value. 37 | @discussion Returns an MTPowerMeasurement object representing the average power value of the array. 38 | */ 39 | - (MTPowerMeasurement*)averagePower; 40 | 41 | /*! 42 | @method maximumPower 43 | @abstract Returns the maximum power value. 44 | @discussion Returns an MTPowerMeasurement object representing the maximum power value of the array. 45 | */ 46 | - (MTPowerMeasurement*)maximumPower; 47 | 48 | /*! 49 | @method awakeMeasurements 50 | @abstract Returns only the measurements taken while the device was awake. 51 | @discussion Returns an NSArray of MTPowerMeasurement objects. 52 | */ 53 | - (NSArray*)awakeMeasurements; 54 | 55 | /*! 56 | @method powerNapMeasurements 57 | @abstract Returns only the measurements taken while the device took a power nap. 58 | @discussion Returns an NSArray of MTPowerMeasurement objects. 59 | */ 60 | - (NSArray*)powerNapMeasurements; 61 | 62 | /*! 63 | @method totalTime 64 | @abstract Returns the total time covered by the taken measurements. 65 | @discussion Returns an NSTimeInterval object. 66 | */ 67 | - (NSTimeInterval)totalTime; 68 | 69 | /*! 70 | @method measurementsGroupedByDay 71 | @abstract Returns the measurement data grouped by day. 72 | @discussion Returns an NSDictionary with timestamps as keys and NSArrays of MTPowerMeasurement 73 | objects as values. 74 | */ 75 | - (NSDictionary*)measurementsGroupedByDay; 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Code of Conduct 4 | 5 | All members of the project community must abide by the [SAP Open Source Code of Conduct](https://github.com/SAP/.github/blob/main/CODE_OF_CONDUCT.md). 6 | Only by respecting each other we can develop a productive, collaborative community. 7 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting [a project maintainer](.reuse/dep5). 8 | 9 | ## Engaging in Our Project 10 | 11 | We use GitHub to manage reviews of pull requests. 12 | 13 | * If you are a new contributor, see: [Steps to Contribute](#steps-to-contribute) 14 | 15 | * Before implementing your change, create an issue that describes the problem you would like to solve or the code that should be enhanced. Please note that you are willing to work on that issue. 16 | 17 | * The team will review the issue and decide whether it should be implemented as a pull request. In that case, they will assign the issue to you. If the team decides against picking up the issue, the team will post a comment with an explanation. 18 | 19 | ## Steps to Contribute 20 | 21 | Should you wish to work on an issue, please claim it first by commenting on the GitHub issue that you want to work on. This is to prevent duplicated efforts from other contributors on the same issue. 22 | 23 | If you have questions about one of the issues, please comment on them, and one of the maintainers will clarify. 24 | 25 | ## Contributing Code or Documentation 26 | 27 | You are welcome to contribute code in order to fix a bug or to implement a new feature that is logged as an issue. 28 | 29 | The following rule governs code contributions: 30 | 31 | * Contributions must be licensed under the [Apache 2.0 License](./LICENSE) 32 | * Due to legal reasons, contributors will be asked to accept a Developer Certificate of Origin (DCO) when they create the first pull request to this project. This happens in an automated fashion during the submission process. SAP uses [the standard DCO text of the Linux Foundation](https://developercertificate.org/). 33 | 34 | ## Contributing with AI-generated code 35 | As artificial intelligence evolves, AI-generated code is becoming valuable for many software projects, including open-source initiatives. While we recognize the potential benefits of incorporating AI-generated content into our open-source projects there are certain requirements that need to be reflected and adhered to when making contributions. 36 | 37 | Please see our [guideline for AI-generated code contributions to SAP Open Source Software Projects](https://github.com/SAP/.github/blob/main/CONTRIBUTING_USING_GENAI.md) for these requirements.![image] 38 | 39 | ## Issues and Planning 40 | 41 | * We use GitHub issues to track bugs and enhancement requests. 42 | 43 | * Please provide as much context as possible when you open an issue. The information you provide must be comprehensive enough to reproduce that issue for the assignee. 44 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTElectricityMapsAPI.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTElectricityMapsAPI.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import 20 | 21 | /*! 22 | @class MTElectricityMapsAPI 23 | @abstract This class provides methods to retrieve carbon data using the Electricity Maps API (https://www.electricitymaps.com). 24 | */ 25 | 26 | @interface MTElectricityMapsAPI : NSObject 27 | 28 | /*! 29 | @method init 30 | @discussion The init method is not available. Please use initWithAPIKey: instead. 31 | */ 32 | - (instancetype)init NS_UNAVAILABLE; 33 | 34 | /*! 35 | @method initWithAPIKey: 36 | @abstract Initialize a MTElectricityMapsAPI object with the given API key. 37 | @param key The API key.. 38 | @discussion Returns an initialized MTElectricityMapsAPI object. 39 | */ 40 | - (instancetype)initWithAPIKey:(NSString*)key NS_DESIGNATED_INITIALIZER; 41 | 42 | /*! 43 | @method requestCarbonDataForLocation:completionHandler: 44 | @abstract Get the Mac's carbon data for the given location. 45 | @param location The location object. 46 | @param completionHandler The completion handler to call when the request is complete. 47 | @discussion Returns the carbon value in gCO2eq/kWh. If an error occurred, the NSError object might 48 | provide information about the error that caused the operation to fail. 49 | */ 50 | - (void)requestCarbonDataForLocation:(CLLocation*)location 51 | completionHandler:(void (^) (NSNumber *gramsCO2eqkWh, NSError *error))completionHandler; 52 | 53 | /*! 54 | @method requestCarbonDataForCountry:completionHandler: 55 | @abstract Get the Mac's carbon data for the given country. 56 | @param country The country code. 57 | @param completionHandler The completion handler to call when the request is complete. 58 | @discussion Returns the carbon value in gCO2eq/kWh. If an error occurred, the NSError object might 59 | provide information about the error that caused the operation to fail. 60 | */ 61 | - (void)requestCarbonDataForCountry:(NSString*)country 62 | completionHandler:(void (^) (NSNumber *gramsCO2eqkWh, NSError *error))completionHandler; 63 | @end 64 | -------------------------------------------------------------------------------- /source/PowerMonitorXPC/PowerMonitorXPC.m: -------------------------------------------------------------------------------- 1 | /* 2 | PowerMonitorXPC.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "PowerMonitorXPC.h" 19 | #import "PowerMonitorDaemonProtocol.h" 20 | #import "Constants.h" 21 | #import 22 | 23 | @interface PowerMonitorXPC () 24 | @property (atomic, strong, readwrite) NSXPCConnection *daemonConnection; 25 | @end 26 | 27 | @implementation PowerMonitorXPC 28 | 29 | - (void)connectToDaemon 30 | { 31 | if (!_daemonConnection) { 32 | 33 | _daemonConnection = [[NSXPCConnection alloc] initWithMachServiceName:kMTDaemonMachServiceName 34 | options:NSXPCConnectionPrivileged]; 35 | [_daemonConnection setRemoteObjectInterface:[NSXPCInterface interfaceWithProtocol:@protocol(PowerMonitorDaemonProtocol)]]; 36 | 37 | #pragma clang diagnostic push 38 | #pragma clang diagnostic ignored "-Warc-retain-cycles" 39 | [_daemonConnection setInvalidationHandler:^{ 40 | 41 | [self->_daemonConnection setInvalidationHandler:nil]; 42 | dispatch_async(dispatch_get_main_queue(), ^{ 43 | os_log(OS_LOG_DEFAULT, "SAPCorp: Daemon connection invalidated"); 44 | self->_daemonConnection = nil; 45 | }); 46 | }]; 47 | 48 | [_daemonConnection setInterruptionHandler:^{ 49 | 50 | [self->_daemonConnection setInterruptionHandler:nil]; 51 | dispatch_async(dispatch_get_main_queue(), ^{ 52 | os_log(OS_LOG_DEFAULT, "SAPCorp: Daemon connection interrupted"); 53 | self->_daemonConnection = nil; 54 | }); 55 | }]; 56 | #pragma clang diagnostic pop 57 | 58 | [_daemonConnection resume]; 59 | } 60 | } 61 | 62 | - (void)connectWithDaemonEndpointReply:(void(^)(NSXPCListenerEndpoint *endpoint))reply 63 | { 64 | [self connectToDaemon]; 65 | [[_daemonConnection remoteObjectProxyWithErrorHandler:^(NSError *error) { 66 | 67 | os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_FAULT, "SAPCorp: Failed to connect to daemon: %{public}@", error); 68 | reply(nil); 69 | 70 | }] connectWithEndpointReply:^(NSXPCListenerEndpoint *endpoint) { 71 | 72 | reply(endpoint); 73 | }]; 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTConsoleSplitViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTConsoleSplitViewController.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTConsoleSplitViewController.h" 19 | 20 | @interface MTConsoleSplitViewController () 21 | 22 | @end 23 | 24 | @implementation MTConsoleSplitViewController 25 | 26 | - (void)viewDidLoad 27 | { 28 | [super viewDidLoad]; 29 | } 30 | 31 | - (BOOL)validateToolbarItem:(NSToolbarItem *)item 32 | { 33 | BOOL enable = NO; 34 | 35 | // we always enable the toggle sidebar item 36 | if ([[item itemIdentifier] isEqualToString:NSToolbarToggleSidebarItemIdentifier]) { 37 | 38 | // call super to make sure the item's tooltip 39 | // reflects the current state of the sidebar 40 | [super validateToolbarItem:item]; 41 | enable = YES; 42 | 43 | } else { 44 | 45 | // get our content view's last view controller 46 | id contentViewController = [[self childViewControllers] lastObject]; 47 | 48 | // if the object itself is a split view, get the 49 | // split view's first view controller 50 | if ([contentViewController isKindOfClass:[NSSplitViewController class]]) { 51 | contentViewController = [[contentViewController childViewControllers] firstObject]; 52 | } 53 | 54 | // check if the view controller responds to the selector enableToolbarItem: 55 | // and if so, call the selector with our toolbar item and enable the toolbar 56 | // item depending on the result 57 | SEL selector = NSSelectorFromString(@"enableToolbarItem:"); 58 | if (contentViewController && [contentViewController respondsToSelector:selector]) { 59 | 60 | NSInvocationOperation *invocation = [[NSInvocationOperation alloc] initWithTarget:contentViewController 61 | selector:selector 62 | object:item 63 | ]; 64 | [invocation start]; 65 | [[invocation result] getValue:&enable]; 66 | 67 | [item setTarget:contentViewController]; 68 | } 69 | } 70 | 71 | return enable; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTPowerMeasurementWriter.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPowerMeasurementWriter.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTModifyData.h" 20 | #import "MTPowerMeasurement.h" 21 | 22 | /*! 23 | @class MTPowerMeasurementWriter 24 | @abstract This class provides methods to write power measurement data to a file. 25 | */ 26 | 27 | @interface MTPowerMeasurementWriter : NSObject 28 | 29 | /*! 30 | @property measurementData 31 | @abstract The memory-mapped data from the given file. 32 | @discussion The value of this property is NSData. 33 | */ 34 | @property (nonatomic, strong, readwrite) NSData *measurementData; 35 | 36 | /*! 37 | @method init 38 | @discussion The init method is not available. Please use initWithFileAtPath:maximumMeasurements: instead. 39 | */ 40 | - (instancetype)init NS_UNAVAILABLE; 41 | 42 | /*! 43 | @method initWithFileAtPath:maximumMeasurements: 44 | @abstract Initialize a MTPowerMeasurementWriter object with a data file at the given path and the given maximum number of measurements. 45 | @param path The path to the data file. 46 | @param maximumMeasurements An integer specifying the maximum number of measurements the data file should be able to hold. 47 | @discussion Returns an initialized MTPowerMeasurementWriter object with the given data file 48 | mapped into memory (writeable). If the data file already exists and can exactly hold 49 | the specified number of measurements, the file is used. Otherwise a new file will be 50 | created. This method returns nil if an error occurred. 51 | */ 52 | - (instancetype)initWithFileAtPath:(NSString*)path maximumMeasurements:(NSInteger)maximumMeasurements NS_DESIGNATED_INITIALIZER; 53 | 54 | /*! 55 | @method currentBufferIndex 56 | @abstract Return the current position in our buffer. 57 | @discussion As our data file is actually a ring buffer, this method returns the current position within this buffer. 58 | */ 59 | - (NSInteger)currentBufferIndex; 60 | 61 | /*! 62 | @method invalidate 63 | @abstract Invalidates the receiver. 64 | @discussion Unmaps the measurement file from memory, closes the file handle and invalidates 65 | the receiver. 66 | */ 67 | - (void)invalidate; 68 | 69 | @end 70 | 71 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTElectricityPrice.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTElectricityPrice.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTPowerMeasurement.h" 20 | 21 | @interface MTElectricityPrice : NSObject 22 | 23 | /*! 24 | @method init: 25 | @discussion The init method is not available. Please use initWithRegularPrice:alternativePrice:schedule: instead. 26 | */ 27 | - (instancetype)init NS_UNAVAILABLE; 28 | 29 | /*! 30 | @method initWithRegularPrice:alternativePrice:schedule: 31 | @abstract Initialize a MTElectricityPrice object with the given values. 32 | @param regular The regular electricity price per kWh. 33 | @param alternative The alternative electricity price per kWh. 34 | @param schedule A dictionary that contains a key for each day of the week, where the number 35 | 0 stands for Sunday, 1 for Monday, and so on. The corresponding value is of type array 36 | and contains integers for each hour of the day during which the alternative electricity tariff 37 | is to apply (0-23). 38 | @discussion Returns a MTElectricityPrice object initialized with the given values. 39 | */ 40 | - (instancetype)initWithRegularPrice:(double)regular 41 | alternativePrice:(double)alternative 42 | schedule:(NSDictionary*)schedule NS_DESIGNATED_INITIALIZER; 43 | 44 | /*! 45 | @method priceAtDate: 46 | @abstract Returns the electricity price for the given date and time. 47 | @param date The date and time for which the electricity price is to be returned. 48 | @discussion Returns the electricity price or -1 if an error occurred. 49 | */ 50 | - (double)priceAtDate:(NSDate*)date; 51 | 52 | /*! 53 | @method measurementsInRegularTariffWithArray: 54 | @abstract Takes an array of measurements and returns only the measurements taken while the regular electricity tariff was active. 55 | @discussion Returns an NSArray of MTPowerMeasurement objects. 56 | */ 57 | - (NSArray*)measurementsInRegularTariffWithArray:(NSArray*)measurements; 58 | 59 | /*! 60 | @method measurementsInAltTariffWithArray: 61 | @abstract Takes an array of measurements and returns only the measurements taken while the alternative electricity tariff was active. 62 | @discussion Returns an NSArray of MTPowerMeasurement objects. 63 | */ 64 | - (NSArray*)measurementsInAltTariffWithArray:(NSArray*)measurements; 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTPowerGraphController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPowerGraphController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTPowerGraphView.h" 20 | 21 | @class MTPowerGraphController; 22 | /*! 23 | @protocol MTPowerGraphControllerDelegate 24 | @abstract Defines an interface for delegates of MTPowerGraphController to be notified if specific aspects of the view have changed. 25 | */ 26 | @protocol MTPowerGraphControllerDelegate 27 | @optional 28 | 29 | /*! 30 | @method graphView:didSelectMeasurement: 31 | @abstract Called whenever the position line selected a new measurement. 32 | @param view A reference to the MTPowerGraphView instance. 33 | @param measurement A reference to the MTPowerMeasurement that has been selected. 34 | @discussion Delegates receive this message whenever the position line selected a new measurement. 35 | */ 36 | - (void)graphView:(MTPowerGraphView*)view didSelectMeasurement:(MTPowerMeasurement*)measurement; 37 | 38 | /*! 39 | @method graphView:didChangePinning: 40 | @abstract Called whenever the pinning of the view has changed. 41 | @param view A reference to the MTPowerGraphView instance. 42 | @param isPinned Returns YES if there's a value pinned, otherwise returns NO. 43 | @discussion Delegates receive this message whenever pinning changed. 44 | */ 45 | - (void)graphView:(MTPowerGraphView*)view didChangePinning:(BOOL)isPinned; 46 | 47 | /*! 48 | @method mouseEnteredGraphView: 49 | @abstract Called whenever the mouse pointer enters the view. 50 | @param view A reference to the MTPowerGraphView instance. 51 | @discussion Delegates receive this message whenever the mouse pointer enters the view. 52 | */ 53 | - (void)mouseEnteredGraphView:(MTPowerGraphView*)view; 54 | 55 | /*! 56 | @method mouseExitedGraphView: 57 | @abstract Called whenever the mouse pointer exited the view. 58 | @param view A reference to the MTPowerGraphView instance. 59 | @discussion Delegates receive this message whenever the mouse pointer exited the view. 60 | */ 61 | - (void)mouseExitedGraphView:(MTPowerGraphView*)view; 62 | 63 | @end 64 | 65 | @interface MTPowerGraphController : NSViewController 66 | 67 | /*! 68 | @property delegate 69 | @abstract The receiver's delegate. 70 | @discussion The value of this property is an object conforming to the MTPowerGraphControllerDelegate protocol. 71 | */ 72 | @property (weak) id delegate; 73 | 74 | @end 75 | 76 | -------------------------------------------------------------------------------- /source/PowerMonitorDaemon/Classes/MTPowerEvent.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPowerEvent.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "IOPMLibPrivate.h" 20 | 21 | /*! 22 | @class MTPowerEvent 23 | @abstract This class defines a power event. 24 | */ 25 | 26 | @interface MTPowerEvent : NSObject 27 | 28 | /*! 29 | @enum MTPowerEventType 30 | @abstract Specifies a power measurement, containing of the measured value and a timestamp. 31 | @constant MTPowerEventTypeNone 32 | @constant MTPowerEventTypeSleep Specifies a sleep event. 33 | @constant MTPowerEventTypeDarkWake Specifies a dark wake event. 34 | @constant MTPowerEventTypeUserWake Specifies a user wake event. 35 | */ 36 | typedef enum { 37 | MTPowerEventTypeNone = 0, 38 | MTPowerEventTypeSleep = 1, 39 | MTPowerEventTypeDarkWake = 2, 40 | MTPowerEventTypeUserWake = 3 41 | } MTPowerEventType; 42 | 43 | /*! 44 | @property type 45 | @abstract A property to store event type. 46 | @discussion The value of this property is MTPowerEventType. 47 | */ 48 | @property (assign) MTPowerEventType type; 49 | 50 | /*! 51 | @property startDate 52 | @abstract A property to store the event's start date. 53 | @discussion The value of this property is NSDate. 54 | */ 55 | @property (nonatomic, strong, readonly) NSDate *startDate; 56 | 57 | /*! 58 | @property type 59 | @abstract A property to store the event's end date. 60 | @discussion The value of this property is NSDate. 61 | */ 62 | @property (nonatomic, strong, readonly) NSDate *endDate; 63 | 64 | /*! 65 | @method endEvent 66 | @abstract End the event by setting the receiver's end date. 67 | */ 68 | - (void)endEvent; 69 | 70 | /*! 71 | @method duration 72 | @abstract Returns the durantion of the event. 73 | @discussion If the event is still active, the time interval between the event start date and the current date 74 | is returned, otherwise the time interval between start and end date is returned. 75 | */ 76 | - (NSTimeInterval)duration; 77 | 78 | /*! 79 | @method didEnd 80 | @abstract Returns if an event has ended or not. 81 | @discussion Returns YES if the event has ended, otherwise returns NO. 82 | */ 83 | - (BOOL)didEnd; 84 | 85 | /*! 86 | @method eventTypeWithCapabilities: 87 | @abstract Returns the MTPowerEventType for the given IOPMSystemPowerStateCapabilities. 88 | @param capabilities The IOPMSystemPowerStateCapabilities. 89 | */ 90 | + (MTPowerEventType)eventTypeWithCapabilities:(IOPMSystemPowerStateCapabilities)capabilities; 91 | 92 | @end 93 | 94 | -------------------------------------------------------------------------------- /source/PowerMonitorDaemon/Classes/MTSleepWatcher.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSleepWatcher.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTPowerEvent.h" 20 | 21 | /*! 22 | @protocol MTSleepWatcherDelegate 23 | @abstract Defines an interface for delegates of MTSleepWatcher to be notified about power events. 24 | */ 25 | @protocol MTSleepWatcherDelegate 26 | @optional 27 | 28 | /*! 29 | @method powerEventDidStart: 30 | @abstract Called if a new power event has started. 31 | @param event A reference to the MTPowerEvent instance that has started. 32 | */ 33 | - (void)powerEventDidStart:(MTPowerEvent*)event; 34 | 35 | /*! 36 | @method powerEventDidEnd: 37 | @abstract Called if a power event has ended. 38 | @param event A reference to the MTPowerEvent instance that has ended. 39 | */ 40 | - (void)powerEventDidEnd:(MTPowerEvent*)event; 41 | 42 | /*! 43 | @method powerEvent:willChangeType: 44 | @abstract Called if the type of a power event will change. 45 | @param event A reference to the MTPowerEvent instance that will change. 46 | @param type The new type of the power event. 47 | */ 48 | - (void)powerEvent:(MTPowerEvent*)event willChangeType:(MTPowerEventType)type; 49 | 50 | @end 51 | 52 | /*! 53 | @class MTSleepWatcher 54 | @abstract This class defines a power event. 55 | */ 56 | 57 | @interface MTSleepWatcher : NSObject 58 | 59 | /*! 60 | @method init 61 | @discussion The init method is not available. Please use initWithDelegate: instead. 62 | */ 63 | - (instancetype)init NS_UNAVAILABLE; 64 | 65 | /*! 66 | @method initWithDelegate: 67 | @abstract Initialize a MTSleepWatcher object with a given delegate. 68 | @param delegate The receiver's delegate. The value of this property is an object 69 | conforming to the MTSleepWatcherDelegate protocol. 70 | @discussion Returns an initialized MTSleepWatcher object. 71 | */ 72 | - (instancetype)initWithDelegate:(id)delegate NS_DESIGNATED_INITIALIZER; 73 | 74 | /*! 75 | @method startWatching 76 | @abstract Starts watching for sleep/wake events. 77 | @discussion Returns YES if watching has been started successfully, otherwise returns NO. 78 | */ 79 | - (BOOL)startWatching; 80 | 81 | /*! 82 | @method stopWatching 83 | @abstract Stops watching for sleep/wake events. 84 | @discussion Returns YES if watching has been stopped successfully, otherwise returns NO. 85 | */ 86 | - (BOOL)stopWatching; 87 | 88 | /*! 89 | @method currentEvent 90 | @abstract Returns the current event. 91 | */ 92 | - (MTPowerEvent*)currentEvent; 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /source/Power Monitor.xcodeproj/xcshareddata/xcschemes/PowerMonitorDaemon.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 44 | 46 | 52 | 53 | 54 | 55 | 58 | 59 | 60 | 61 | 67 | 69 | 75 | 76 | 77 | 78 | 80 | 81 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTGraphSplitViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTGraphSplitViewController.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTGraphSplitViewController.h" 19 | #import "MTPowerGraphController.h" 20 | #import "MTPowerGraphInspectorController.h" 21 | #import "Constants.h" 22 | 23 | @implementation MTGraphSplitViewController 24 | 25 | - (void)viewDidLoad 26 | { 27 | [super viewDidLoad]; 28 | 29 | NSSplitViewItem *contentItem = [[self splitViewItems] firstObject]; 30 | NSSplitViewItem *inspectorItem = [[self splitViewItems] lastObject]; 31 | 32 | // set a delegate so we can pass data to our inspector 33 | MTPowerGraphController *contentController = (MTPowerGraphController*)[contentItem viewController]; 34 | MTPowerGraphInspectorController *inspectorController = (MTPowerGraphInspectorController*)[inspectorItem viewController]; 35 | [contentController setDelegate:inspectorController]; 36 | 37 | // set the minimum width for the inspector 38 | [inspectorItem setMinimumThickness:150]; 39 | } 40 | 41 | - (IBAction)showOrHideInspector:(id)sender; 42 | { 43 | // we could get all of this for free in macOS 14+ but as we 44 | // also support macOS 13, we have to build this by ourselves… 45 | NSSplitViewItem *inspectorItem = [[self splitViewItems] lastObject]; 46 | [[inspectorItem animator] setCollapsed:![inspectorItem isCollapsed]]; 47 | } 48 | 49 | #pragma mark NSToolbarItemValidation 50 | 51 | - (BOOL)validateToolbarItem:(NSToolbarItem *)item 52 | { 53 | BOOL enable = NO; 54 | 55 | // we always enable the toggle sidebar item 56 | if ([[item itemIdentifier] isEqualToString:@"MTToolbarGraphInspectorItem"]) { 57 | 58 | [item setTarget:self]; 59 | enable = YES; 60 | 61 | } else { 62 | 63 | // get our content view's first view controller 64 | id contentViewController = [[self childViewControllers] firstObject]; 65 | 66 | // check if the view controller responds to the selector enableToolbarItem: 67 | // and if so, call the selector with our toolbar item and enable the toolbar 68 | // item depending on the result 69 | SEL selector = NSSelectorFromString(@"enableToolbarItem:"); 70 | if (contentViewController && [contentViewController respondsToSelector:selector]) { 71 | 72 | NSInvocationOperation *invocation = [[NSInvocationOperation alloc] initWithTarget:contentViewController 73 | selector:selector 74 | object:item 75 | ]; 76 | [invocation start]; 77 | [[invocation result] getValue:&enable]; 78 | 79 | [item setTarget:contentViewController]; 80 | } 81 | } 82 | 83 | return enable; 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTPowerMeasurementReader.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPowerMeasurementReader.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTPowerMeasurement.h" 20 | 21 | /*! 22 | @class MTPowerMeasurementReader 23 | @abstract This class provides methods to read power measurement data from file. 24 | */ 25 | 26 | @interface MTPowerMeasurementReader : NSObject 27 | 28 | /*! 29 | @method init 30 | @discussion The init method is not available. Please use initWithContentsOfFile: instead. 31 | */ 32 | - (instancetype)init NS_UNAVAILABLE; 33 | 34 | /*! 35 | @method initWithContentsOfFile: 36 | @abstract Initialize a MTPowerMeasurementReader object with a data file at the given path. 37 | @param path The path to the data file. 38 | @discussion Returns an initialized MTPowerMeasurementReader object with the given data file 39 | mapped into memory (read-only). Returns nil if an error occurred. 40 | */ 41 | - (instancetype)initWithContentsOfFile:(NSString*)path; 42 | 43 | /*! 44 | @method initWithData: 45 | @abstract Initialize a MTPowerMeasurementReader object with the given data. 46 | @param data A reference to the data object. 47 | @discussion Returns an initialized MTPowerMeasurementReader object with the given data. Returns nil if an error occurred. 48 | */ 49 | - (instancetype)initWithData:(NSData*)data; 50 | 51 | /*! 52 | @method allMeasurements 53 | @abstract Return all measurement data. 54 | @discussion Returns an array of MTPowerMeasurement objects. This represents all data that are 55 | currently stored in the given data file. 56 | */ 57 | - (NSArray*)allMeasurements; 58 | 59 | /*! 60 | @method allMeasurementsSinceDate: 61 | @abstract Return all measurement data starting with the given date 62 | @param date The date from which measured values should be returned 63 | @discussion Returns an array of MTPowerMeasurement objects. This represents all data with a 64 | timestamp after the given date that are currently stored in the given data file. 65 | */ 66 | - (NSArray*)allMeasurementsSinceDate:(NSDate*)date; 67 | 68 | /*! 69 | @method currentBufferIndex 70 | @abstract Return the current position in our buffer. 71 | @discussion As our data file is actually a ring buffer, this method returns the current position within this buffer. 72 | */ 73 | - (NSInteger)currentBufferIndex; 74 | 75 | /*! 76 | @method currentPower 77 | @abstract Returns the current system power. 78 | @discussion Returns a MTPowerMeasurement object representing the current system power. 79 | */ 80 | - (MTPowerMeasurement*)currentPower; 81 | 82 | /*! 83 | @method invalidate 84 | @abstract Invalidates the receiver. 85 | @discussion Unmaps the measurement file from memory, closes the file handle and invalidates 86 | the receiver. 87 | */ 88 | - (void)invalidate; 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTElectricityPrice.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTElectricityPrice.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTElectricityPrice.h" 19 | 20 | @interface MTElectricityPrice () 21 | @property (nonatomic, strong, readwrite) NSDictionary *savedSchedule; 22 | @property (assign) double regularPrice; 23 | @property (assign) double altPrice; 24 | @end 25 | 26 | @implementation MTElectricityPrice 27 | 28 | - (instancetype)initWithRegularPrice:(double)regular 29 | alternativePrice:(double)alternative 30 | schedule:(NSDictionary*)schedule 31 | { 32 | self = [super init]; 33 | 34 | if (self) { 35 | 36 | _regularPrice = regular; 37 | _altPrice = alternative; 38 | _savedSchedule = schedule; 39 | } 40 | 41 | return self; 42 | } 43 | 44 | - (double)priceAtDate:(NSDate*)date 45 | { 46 | double pricePerKWh = -1; 47 | 48 | if (date) { 49 | pricePerKWh = ([self isAlternatePriceWithDate:date]) ? _altPrice : _regularPrice; 50 | } 51 | 52 | return pricePerKWh; 53 | } 54 | 55 | - (BOOL)isAlternatePriceWithDate:(NSDate*)date 56 | { 57 | BOOL isAlternate = NO; 58 | 59 | // check if the given date lies in one of the alternative price ranges 60 | if (_savedSchedule) { 61 | 62 | NSCalendar *calendar = [NSCalendar currentCalendar]; 63 | NSInteger dayOfTheWeek = [calendar component:NSCalendarUnitWeekday fromDate:date]; 64 | NSInteger index = dayOfTheWeek - 1; 65 | 66 | NSArray *idxSet = [_savedSchedule objectForKey:[NSString stringWithFormat:@"%ld", index]]; 67 | NSDateComponents *timeComponents = [calendar components:NSCalendarUnitHour fromDate:date]; 68 | 69 | isAlternate = ([idxSet containsObject:[NSNumber numberWithInteger:[timeComponents hour]]]); 70 | } 71 | 72 | return isAlternate; 73 | } 74 | 75 | - (NSArray*)measurementsInAltTariffWithArray:(NSArray*)measurements 76 | { 77 | NSMutableArray *usingAltTariff = [[NSMutableArray alloc] init]; 78 | 79 | for (MTPowerMeasurement *pM in measurements) { 80 | 81 | if ([self isAlternatePriceWithDate:[NSDate dateWithTimeIntervalSince1970:[pM timeStamp]]]) { 82 | [usingAltTariff addObject:pM]; 83 | } 84 | } 85 | 86 | return usingAltTariff; 87 | } 88 | 89 | - (NSArray*)measurementsInRegularTariffWithArray:(NSArray*)measurements 90 | { 91 | NSMutableArray *usingRegularTariff = [[NSMutableArray alloc] init]; 92 | 93 | for (MTPowerMeasurement *pM in measurements) { 94 | 95 | if (![self isAlternatePriceWithDate:[NSDate dateWithTimeIntervalSince1970:[pM timeStamp]]]) { 96 | [usingRegularTariff addObject:pM]; 97 | } 98 | } 99 | 100 | return usingRegularTariff; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /source/Power Monitor.xcodeproj/xcshareddata/xcschemes/Power Monitor.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 16 | 17 | 18 | 24 | 30 | 31 | 32 | 33 | 34 | 40 | 41 | 51 | 53 | 59 | 60 | 61 | 62 | 65 | 66 | 67 | 68 | 74 | 76 | 82 | 83 | 84 | 85 | 87 | 88 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTDaemonConnection.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTDaemonConnection.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "PowerMonitorXPCProtocol.h" 20 | #import "PowerMonitorDaemonProtocol.h" 21 | #import 22 | #import 23 | 24 | /*! 25 | @protocol MTDaemonConnectionDelegate 26 | @abstract Defines an interface for delegates of MTDaemonConnection to be notified if 27 | the connection to the daemon failed. 28 | */ 29 | @protocol MTDaemonConnectionDelegate 30 | @optional 31 | 32 | /*! 33 | @method connection:didFailWithError: 34 | @abstract Called if the connection to the daemon failed. 35 | @param connection A reference to the NSXPCConnection instance that failed. 36 | @param error The error that caused the xpc connection to fail. 37 | @discussion Delegates receive this message if the connection to the daemon failed. 38 | */ 39 | - (void)connection:(NSXPCConnection*)connection didFailWithError:(NSError*)error; 40 | 41 | @end 42 | 43 | /*! 44 | @class MTDaemonConnection 45 | @abstract A class that provides an easy way to connect to a daemon (via xpc service). 46 | */ 47 | 48 | @interface MTDaemonConnection : NSObject 49 | 50 | /*! 51 | @property delegate 52 | @abstract The receiver's connection delegate. 53 | @discussion The value of this property is an object conforming to the MTDaemonConnectionDelegate protocol. 54 | */ 55 | @property (weak) id delegate; 56 | 57 | /*! 58 | @property connection 59 | @abstract A property to store the connection object. 60 | @discussion The value of this property is NSXPCConnection. 61 | */ 62 | @property (atomic, strong, readonly) NSXPCConnection *connection; 63 | 64 | /*! 65 | @property remoteObjectProxy 66 | @abstract A property to store the connection's remote object proxy. 67 | @discussion The value of this property is id. 68 | */ 69 | @property (atomic, strong, readonly) id remoteObjectProxy; 70 | 71 | /*! 72 | @method connectToXPCServiceWithRemoteObjectProxyReply: 73 | @abstract Returns a proxy for the xpc service. 74 | @param reply The reply block to call when the request is complete. 75 | @discussion Returns a proxy for the xpc service or nil if an error occurred. In case of an error 76 | the error object might contain information about the error that caused the operation 77 | to fail. 78 | */ 79 | - (void)connectToXPCServiceWithRemoteObjectProxyReply:(void (^)(id remoteObjectProxy, NSError *error))reply; 80 | 81 | /*! 82 | @method connectToDaemonWithExportedObject:andExecuteCommandBlock: 83 | @abstract Connects to the daemon and executes the given command block. 84 | @param exportedObject The object you want to export to the daemon. May be nil. 85 | @param commandBlock The command block that should be executed after the connection has been established. 86 | */ 87 | - (void)connectToDaemonWithExportedObject:(id)exportedObject 88 | andExecuteCommandBlock:(void(^)(void))commandBlock; 89 | 90 | /*! 91 | @method invalidate 92 | @abstract Invalidates the connection to the daemon (and xpc service). 93 | */ 94 | - (void)invalidate; 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTPowerMeasurement.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPowerMeasurement.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTPowerMeasurement 22 | @abstract This class defines a power measurement. 23 | */ 24 | 25 | @interface MTPowerMeasurement : NSMeasurement 26 | 27 | /*! 28 | @struct MeasurementFileHeader 29 | @abstract Specifies the header of a measurement file. 30 | @discussion The measurement file format looks like this: 31 | @code 32 | +00 7B magic number (0x70777264617461) 33 | +07 1B reserved (0x0) 34 | +08 1B length of header (0xA) 35 | +09 1B version number (0x2) 36 | +10 XX [data] 37 | */ 38 | typedef struct __attribute__((packed)) { 39 | 40 | /// The signature of the file. 41 | char signature[8]; 42 | /// The size of the header 43 | uint8_t size; 44 | /// The file format version. 45 | uint8_t version; 46 | 47 | } MeasurementFileHeader; 48 | 49 | /*! 50 | @struct MeasurementStruct 51 | @abstract Specifies a power measurement, containing of the measured value and a timestamp. 52 | */ 53 | typedef struct __attribute__((packed)) { 54 | 55 | /// The timestamp of the measurement. 56 | time_t timestamp; 57 | /// The measurement value. 58 | uint32_t value; 59 | /// A boolean specifying if the Mac is in dark wake mode. 60 | Boolean darkwake; 61 | 62 | } MeasurementStruct; 63 | 64 | /*! 65 | @property timeStamp 66 | @abstract A property to store the timestamp of a measurement. 67 | @discussion The value of this property is time_t. 68 | */ 69 | @property (assign) time_t timeStamp; 70 | 71 | /*! 72 | @property darkWake 73 | @abstract A property to store if the measurement was done while the Mac was in dark wake mode. 74 | @discussion The value of this boolean. 75 | */ 76 | @property (assign) BOOL darkWake; 77 | 78 | /*! 79 | @method initWithDoubleValue:unit: 80 | @discussion The init method is not available. Please use initWithPowerValue: instead. 81 | */ 82 | - (instancetype)initWithDoubleValue:(double)doubleValue unit:(NSUnit *)unit NS_UNAVAILABLE; 83 | 84 | /*! 85 | @method initWithPowerValue: 86 | @abstract Initialize a MTPowerMeasurement object with a given power value. 87 | @param powerValue The double-precision floating-point measurement value. 88 | @discussion Returns a measurement initialized to have the specified value in watts. 89 | */ 90 | - (instancetype)initWithPowerValue:(double)powerValue NS_DESIGNATED_INITIALIZER; 91 | 92 | /*! 93 | @method state 94 | @abstract Get the power state of a measurement (awake, power nap, sleep). 95 | @discussion Returns a localized string for the power state of the measurement. 96 | */ 97 | - (NSString*)state; 98 | 99 | /*! 100 | @method headerWithFilePath: 101 | @abstract Read a pwrdata file's header and return the relevant data in a MeasurementFileHeader struct. 102 | @param path The path to the pwrdata file. 103 | @discussion Returns a MeasurementFileHeader struct with the values read from file. 104 | */ 105 | + (MeasurementFileHeader)headerWithFilePath:(NSString*)path; 106 | 107 | @end 108 | 109 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTCarbonFootprint.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTCarbonFootprint.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import 20 | 21 | /*! 22 | @class MTCarbonFootprint 23 | @abstract This class provides methods to determine the carbon footprint. 24 | */ 25 | 26 | @interface MTCarbonFootprint : NSObject 27 | 28 | /*! 29 | @enum MTCarbonAPIType 30 | @abstract Specifies the type of the carbon API. 31 | @constant MTCarbonAPITypeElectricityMaps Specifies the Electricity Maps API. 32 | */ 33 | typedef enum { 34 | MTCarbonAPITypeElectricityMaps = 1 35 | } MTCarbonAPIType; 36 | 37 | /*! 38 | @property allowUserInteraction 39 | @abstract A property to specify if user interaction is allowed or not. 40 | @discussion If set to YES, the user might be asked if the location of the Mac can be used to determine the correct carbon 41 | footprint. If set to NO, the user is not prompted and another but less accurate method is used to determine 42 | the approximate location of the Mac. The value of this property is boolean. 43 | */ 44 | @property (assign) BOOL allowUserInteraction; 45 | 46 | /*! 47 | @property apiType 48 | @abstract A property to specify which API should be used. 49 | @discussion The value of this property is MTCarbonAPIType. 50 | */ 51 | @property (assign) MTCarbonAPIType apiType; 52 | 53 | /*! 54 | @method init 55 | @discussion The init method is not available. Please use initWithAPIKey: instead. 56 | */ 57 | - (instancetype)init NS_UNAVAILABLE; 58 | 59 | /*! 60 | @method initWithAPIKey: 61 | @abstract Initialize a MTCarbonFootprint object with the given API key. 62 | @param key The API key.. 63 | @discussion Returns an initialized MTCarbonFootprint object. 64 | */ 65 | - (instancetype)initWithAPIKey:(NSString *)key NS_DESIGNATED_INITIALIZER; 66 | 67 | /*! 68 | @method currentLocationWithCompletionHandler: 69 | @abstract Get the Macs current location. 70 | @param completionHandler The completion handler to call when the request is complete. 71 | @discussion Returns the Mac's current location together with a boolean that indicates if the location 72 | is precise (location services) or not (MapKit). 73 | */ 74 | - (void)currentLocationWithCompletionHandler:(void (^) (CLLocation *location, BOOL preciseLocation))completionHandler; 75 | 76 | /*! 77 | @method footprintWithLocation:completionHandler: 78 | @abstract Get the Mac's carbon footprint at the given location. 79 | @param location The location object. 80 | @param completionHandler The completion handler to call when the request is complete. 81 | @discussion Returns the carbon value in gCO2eq/kWh. If an error occurred, the NSError object might 82 | provide information about the error that caused the operation to fail. 83 | */ 84 | - (void)footprintWithLocation:(CLLocation*)location completionHandler:(void (^) (NSNumber *gramsCO2eqkWh, NSError *error))completionHandler; 85 | 86 | /*! 87 | @method countryCodeWithLocation:completionHandler: 88 | @abstract Get the country code for the given location. 89 | @param location The location object. 90 | @param completionHandler The completion handler to call when the request is complete. 91 | @discussion Returns country code for the given location or nil, if the location could not be determined. 92 | */ 93 | - (void)countryCodeWithLocation:(CLLocation*)location completionHandler:(void (^) (NSString *countryCode))completionHandler; 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTPowerMeasurementArray.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTPowerMeasurementArray.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTPowerMeasurementArray.h" 19 | #import "MTElectricityPrice.h" 20 | #import "Constants.h" 21 | 22 | @implementation NSArray (MTPowerMeasurementArray) 23 | 24 | - (MTPowerMeasurement*)minimumPower 25 | { 26 | NSNumber *minimum = 0; 27 | 28 | if ([self count] > 0) { 29 | minimum = [self valueForKeyPath:@"@min.doubleValue"]; 30 | } 31 | 32 | MTPowerMeasurement *measurement = [[MTPowerMeasurement alloc] initWithPowerValue:[minimum doubleValue]]; 33 | 34 | return measurement; 35 | } 36 | 37 | - (MTPowerMeasurement*)averagePower 38 | { 39 | NSNumber *average = 0; 40 | 41 | if ([self count] > 0) { 42 | average = [self valueForKeyPath:@"@avg.doubleValue"]; 43 | } 44 | 45 | MTPowerMeasurement *measurement = [[MTPowerMeasurement alloc] initWithPowerValue:[average doubleValue]]; 46 | 47 | return measurement; 48 | } 49 | 50 | - (MTPowerMeasurement*)maximumPower 51 | { 52 | NSNumber *maximum = 0; 53 | 54 | if ([self count] > 0) { 55 | maximum = [self valueForKeyPath:@"@max.doubleValue"]; 56 | } 57 | 58 | MTPowerMeasurement *measurement = [[MTPowerMeasurement alloc] initWithPowerValue:[maximum doubleValue]]; 59 | 60 | return measurement; 61 | } 62 | 63 | - (NSArray*)awakeMeasurements 64 | { 65 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"darkWake == %@", [NSNumber numberWithBool:NO]]; 66 | NSArray *awakeMeasurements = [self filteredArrayUsingPredicate:predicate]; 67 | 68 | return awakeMeasurements; 69 | } 70 | 71 | - (NSArray*)powerNapMeasurements 72 | { 73 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"darkWake == %@", [NSNumber numberWithBool:YES]]; 74 | NSArray *powerNapMeasurements = [self filteredArrayUsingPredicate:predicate]; 75 | 76 | return powerNapMeasurements; 77 | } 78 | 79 | - (NSTimeInterval)totalTime 80 | { 81 | NSTimeInterval total = [self count] * kMTMeasurementInterval; 82 | 83 | return total; 84 | } 85 | 86 | - (NSDictionary*)measurementsGroupedByDay 87 | { 88 | NSDate *anchorDate = [NSDate distantPast]; 89 | NSMutableDictionary *groupedDict = [[NSMutableDictionary alloc] init]; 90 | NSMutableArray *groupedEntries = [[NSMutableArray alloc] init]; 91 | 92 | for (MTPowerMeasurement *pM in self) { 93 | 94 | NSDate *measurementDate = [NSDate dateWithTimeIntervalSince1970:[pM timeStamp]]; 95 | 96 | if ([[NSCalendar currentCalendar] compareDate:anchorDate 97 | toDate:measurementDate 98 | toUnitGranularity:NSCalendarUnitDay] != NSOrderedSame) { 99 | 100 | if ([groupedEntries count] > 0) { 101 | 102 | [groupedDict setObject:groupedEntries forKey:[NSString stringWithFormat:@"%.0lf", [anchorDate timeIntervalSince1970]]]; 103 | groupedEntries = [[NSMutableArray alloc] init]; 104 | } 105 | 106 | anchorDate = [[NSCalendar currentCalendar] startOfDayForDate:measurementDate]; 107 | } 108 | 109 | [groupedEntries addObject:pM]; 110 | } 111 | 112 | if ([groupedEntries count] > 0) { 113 | 114 | [groupedDict setObject:groupedEntries forKey:[NSString stringWithFormat:@"%.0lf", [anchorDate timeIntervalSince1970]]]; 115 | } 116 | 117 | return groupedDict; 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /source/Power Monitor/Classes/MTElectricityMapsAPI.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTElectricityMapsAPI.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTElectricityMapsAPI.h" 19 | #import "Constants.h" 20 | 21 | @interface MTElectricityMapsAPI () 22 | @property (nonatomic, strong, readwrite) NSString* apiKey; 23 | @end 24 | 25 | @implementation MTElectricityMapsAPI 26 | 27 | - (instancetype)initWithAPIKey:(NSString *)key 28 | { 29 | self = [super init]; 30 | 31 | if (self) { 32 | _apiKey= key; 33 | } 34 | 35 | return self; 36 | } 37 | 38 | - (void)requestCarbonDataForLocation:(CLLocation*)location completionHandler:(void (^) (NSNumber *gramsCO2eqkWh, NSError *error))completionHandler 39 | { 40 | [self requestCarbonDataForCountry:nil 41 | location:location 42 | completionHandler:completionHandler 43 | ]; 44 | } 45 | 46 | - (void)requestCarbonDataForCountry:(NSString*)country completionHandler:(void (^) (NSNumber *gramsCO2eqkWh, NSError *error))completionHandler 47 | { 48 | [self requestCarbonDataForCountry:country 49 | location:nil 50 | completionHandler:completionHandler 51 | ]; 52 | } 53 | 54 | - (void)requestCarbonDataForCountry:(NSString*)country location:(CLLocation*)location completionHandler:(void (^) (NSNumber *gramsCO2eqkWh, NSError *error))completionHandler 55 | { 56 | NSString *apiURLString = @"https://api.electricitymap.org/v3/carbon-intensity/latest?"; 57 | 58 | if (country) { 59 | 60 | apiURLString = [apiURLString stringByAppendingFormat:@"zone=%@", country]; 61 | 62 | } else { 63 | 64 | CLLocationCoordinate2D coordinate = [location coordinate]; 65 | apiURLString = [apiURLString stringByAppendingFormat:@"lon=%f&lat=%f", coordinate.longitude, coordinate.latitude]; 66 | } 67 | 68 | NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:apiURLString]]; 69 | [request addValue:_apiKey forHTTPHeaderField:@"auth-token"]; 70 | 71 | NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration ephemeralSessionConfiguration]; 72 | NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:nil delegateQueue:nil]; 73 | 74 | NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request 75 | completionHandler:^(NSData* data, NSURLResponse* response, NSError* error) { 76 | 77 | NSNumber *gramsCO2eqkWh = 0; 78 | NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; 79 | NSError *httpError = nil; 80 | 81 | if ([httpResponse statusCode] == 200 && data) { 82 | 83 | NSDictionary *carbonDict = [NSJSONSerialization JSONObjectWithData:data 84 | options:kNilOptions 85 | error:&error 86 | ]; 87 | 88 | gramsCO2eqkWh = [carbonDict valueForKeyPath:@"carbonIntensity"]; 89 | 90 | } else { 91 | 92 | NSDictionary *errorDetail = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"Request failed with error: %ld", [httpResponse statusCode]], NSLocalizedDescriptionKey, nil]; 93 | httpError = [NSError errorWithDomain:kMTErrorDomain code:0 userInfo:errorDetail]; 94 | } 95 | 96 | if (completionHandler) { completionHandler(gramsCO2eqkWh, httpError); } 97 | }]; 98 | 99 | [dataTask resume]; 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /source/Power Monitor/View Controllers/MTSettingsViewOptionsController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTSettingsViewOptionsController.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTSettingsViewOptionsController.h" 19 | #import "Constants.h" 20 | 21 | @interface MTSettingsViewOptionsController () 22 | @property (nonatomic, strong, readwrite) NSUserDefaults *userDefaults; 23 | 24 | @property (weak) IBOutlet NSButton *showAverageCheckbox; 25 | @property (weak) IBOutlet NSButton *showDayMarkersCheckbox; 26 | @property (weak) IBOutlet NSButton *markPowerNapsCheckbox; 27 | @property (weak) IBOutlet NSColorWell *graphColorWell; 28 | @property (weak) IBOutlet NSColorWell *graphPowerNapColorWell; 29 | @property (weak) IBOutlet NSColorWell *averageColorWell; 30 | @property (weak) IBOutlet NSColorWell *dayMarkersColorWell; 31 | @property (weak) IBOutlet NSColorWell *positionLineColorWell; 32 | @property (weak) IBOutlet NSButton *resetColorsButton; 33 | @end 34 | 35 | @implementation MTSettingsViewOptionsController 36 | 37 | - (void)viewDidLoad 38 | { 39 | [super viewDidLoad]; 40 | 41 | _userDefaults = [NSUserDefaults standardUserDefaults]; 42 | 43 | [self defaultsChanged]; 44 | 45 | [[NSNotificationCenter defaultCenter] addObserver:self 46 | selector:@selector(defaultsChanged) 47 | name:NSUserDefaultsDidChangeNotification 48 | object:nil 49 | ]; 50 | } 51 | 52 | - (void)defaultsChanged 53 | { 54 | dispatch_async(dispatch_get_main_queue(), ^{ 55 | 56 | // options 57 | [self->_showAverageCheckbox setEnabled:![self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphShowAverageKey]]; 58 | [self->_showDayMarkersCheckbox setEnabled:![self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphShowDayMarkersKey]]; 59 | [self->_markPowerNapsCheckbox setEnabled:![self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphMarkPowerNapsKey]]; 60 | 61 | // color wells 62 | [self->_graphColorWell setEnabled:![self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphFillColorKey]]; 63 | [self->_graphPowerNapColorWell setEnabled:![self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphPowerNapFillColorKey]]; 64 | [self->_averageColorWell setEnabled:![self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphAverageColorKey]]; 65 | [self->_dayMarkersColorWell setEnabled:![self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphDayMarkerColorKey]]; 66 | [self->_positionLineColorWell setEnabled:![self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphPositionLineColorKey]]; 67 | 68 | // button 69 | [self->_resetColorsButton setEnabled:!([self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphFillColorKey] && 70 | [self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphPowerNapFillColorKey] && 71 | [self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphAverageColorKey] && 72 | [self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphDayMarkerColorKey] && 73 | [self->_userDefaults objectIsForcedForKey:kMTDefaultsGraphPositionLineColorKey])]; 74 | }); 75 | } 76 | 77 | - (IBAction)resetGraphColors:(id)sender 78 | { 79 | [_userDefaults removeObjectForKey:kMTDefaultsGraphFillColorKey]; 80 | [_userDefaults removeObjectForKey:kMTDefaultsGraphPowerNapFillColorKey]; 81 | [_userDefaults removeObjectForKey:kMTDefaultsGraphAverageColorKey]; 82 | [_userDefaults removeObjectForKey:kMTDefaultsGraphDayMarkerColorKey]; 83 | [_userDefaults removeObjectForKey:kMTDefaultsGraphPositionLineColorKey]; 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | # Power Monitor 6 | 7 | [![REUSE status](https://api.reuse.software/badge/github.com/SAP/power-monitoring-tool-for-macos)](https://api.reuse.software/info/github.com/SAP/power-monitoring-tool-for-macos) 8 | 9 | _Power Monitor_ is a powerful open-source tool that provides real-time insights into your device's energy consumption and carbon footprint, linked to your location. Here's how it can help you: 10 | 11 | 🔌 Measure Energy Consumption: Track how much energy your Mac consumes, helping you understand the environmental impact of your device usage. 12 | 13 | 🌍 Location-Based Carbon Footprint: See the carbon footprint generated by your device, taking into account your location. Make informed choices for a greener future. 14 | 15 | 📈 Data-Driven Decisions: With data measured every 5 seconds and storage of maximum values from the last 24 hours, pinpoint energy hogs and optimize your usage for efficiency. 16 | 17 | 🌟 Technical Accuracy: While it's not possible to measure exact wattage directly on the Mac, _Power Monitor_ provides a reliable estimate based on external power meter tests. 18 | 19 | **_Power Monitor_ supports the following macOS versions:** 20 | 21 | * macOS 26.x 22 | * macOS 15.x 23 | * macOS 14.x 24 | * macOS 13.x 25 | 26 |
27 | 28 | **Make a positive impact, reduce energy waste, and contribute to sustainability with _Power Monitor_!** 29 | 30 |
31 | 32 | # Demo 33 | 34 | _Power Monitor_ is a new native Mac solution to monitor, report and visualize your Mac’s power consumption. 35 | 36 | 37 | 38 | # Documentation 39 | 40 | To learn more about _Power Monitor_ features, make sure to take a look at our [wiki](https://github.com/SAP/power-monitoring-tool-for-macos/wiki) or the links below: 41 | 42 | * [Installation](https://github.com/SAP/power-monitoring-tool-for-macos/wiki/Installation) 43 | * [Uninstallation](https://github.com/SAP/power-monitoring-tool-for-macos/wiki/Uninstallation) 44 | * [Using _Power Monitor_](https://github.com/SAP/power-monitoring-tool-for-macos/wiki/Using-Power-Monitor) 45 | * [Managing _Power Monitor_](https://github.com/SAP/power-monitoring-tool-for-macos/wiki/Managing-Power-Monitor) 46 | * [FAQ](https://github.com/SAP/power-monitoring-tool-for-macos/wiki/Frequently-Asked-Questions) 47 | 48 |
49 | 50 | # Articles 51 | 52 | See who's talking about _Power Monitor_… 53 | 54 | 2025 55 | * [Computerworld: Apple should Sherlock SAP’s open-source energy management app](https://www.computerworld.com/article/4012412/apple-should-sherlock-saps-open-source-energy-management-app.html) 56 | 57 |
58 | 59 | # Support 60 | 61 | This project is 'as-is' with no support, no changes being made. You are welcome to make changes to improve it but we are not available for questions or support of any kind. 62 | 63 |
64 | 65 | # Security / Disclosure 66 | If you find any bug that may be a security problem, please follow our instructions at [in our security policy](https://github.com/SAP/power-monitoring-tool-for-macos/security/policy) on how to report it. Please do not create GitHub issues for security-related doubts or problems. 67 | 68 |
69 | 70 | # Feedback and Contributing 71 | 72 | This project is open to feature requests/suggestions, bug reports etc. via [GitHub issues](https://github.com/SAP/power-monitoring-tool-for-macos/issues). Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our [Contribution Guidelines](CONTRIBUTING.md). 73 | 74 |
75 | 76 | # Code of Conduct 77 | 78 | We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. By participating in this project, you agree to abide by its [Code of Conduct](https://github.com/SAP/.github/blob/main/CODE_OF_CONDUCT.md) at all times. 79 | 80 |
81 | 82 | # License 83 | 84 | Copyright 2023-2025 SAP SE or an SAP affiliate company and Power Monitor contributors. Please see our [LICENSE](LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/SAP/power-monitoring-tool-for-macos). 85 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTSystemInfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSystemInfo.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTSystemInfo 22 | @abstract This class provides methods to get some system information. 23 | */ 24 | 25 | @interface MTSystemInfo : NSObject 26 | 27 | /*! 28 | @method processList 29 | @abstract Returns a list of all running processes. 30 | @discussion Returns an array containing the complete paths to all running processes 31 | or nil, if an error occurred. 32 | */ 33 | + (NSArray*)processList; 34 | 35 | /*! 36 | @method rawSystemPower 37 | @abstract Returns the Mac's current power value. 38 | */ 39 | + (float)rawSystemPower; 40 | 41 | /*! 42 | @method deviceSupportsPowerNap 43 | @abstract Returns if the device supports Power Nap or not. 44 | @discussion Returns YES if Power Nap is supported, otherwise returns NO. 45 | */ 46 | + (BOOL)deviceSupportsPowerNap; 47 | 48 | /*! 49 | @method powerNapStatusWithCompletionHandler: 50 | @abstract Returns the Mac's current Power Nap settings. 51 | @param completionHandler The completion handler to call when the request is complete. 52 | @discussion Returns a boolean indicating if Power Nap is enabled and another boolean indicating 53 | if it's only enabled while on ac power. 54 | */ 55 | + (void)powerNapStatusWithCompletionHandler:(void (^) (BOOL enabled, BOOL aconly))completionHandler; 56 | 57 | /*! 58 | @method enablePowerNap:acPowerOnly: 59 | @abstract Enables or disables Power Nap. 60 | @param enable If set to YES, Power Naps are allowed, otherwise not 61 | @param aconly If set to YES, Power Naps are only allowed if ac power is connected 62 | @discussion Returns YES on success, otherwise returns NO. 63 | */ 64 | + (BOOL)enablePowerNap:(BOOL)enable acPowerOnly:(BOOL)aconly; 65 | 66 | /*! 67 | @method hasBattery 68 | @abstract Returns if the device has a battery or not. 69 | @discussion Returns YES if the device has a battery, otherwise returns NO. 70 | */ 71 | + (BOOL)hasBattery; 72 | 73 | /*! 74 | @method processesPreventingSleep 75 | @abstract Returns a list of processes currently preventing sleep mode. 76 | @discussion Returns an NSArray containing dictionaries with information about all processes currently 77 | preventing sleep mode or nil if an error occurred. 78 | */ 79 | + (NSArray*)processesPreventingSleep; 80 | 81 | /*! 82 | @method loginItemEnabled 83 | @abstract Returns if the current application is registered to be opened at login. 84 | @discussion Returns YES if the current application is registered as login item and 85 | is eligible to run. Otherwise returns NO. 86 | */ 87 | + (BOOL)loginItemEnabled; 88 | 89 | /*! 90 | @method enableLoginItem: 91 | @abstract Registers the current application to be opened at login. 92 | @discussion Returns YES if the current application has been successfully registered as login item and 93 | is eligible to run. Otherwise returns NO. 94 | */ 95 | + (BOOL)enableLoginItem:(BOOL)enable; 96 | 97 | /*! 98 | @method externalPowerAdapterDetails 99 | @abstract Returns a NSDictionary that describes the attached (AC) external power adapter (if any external power adapter is attached). 100 | @discussion Returns a NSDictionary on success. Returns nil if no adapter is attached, or if an error occurred. Use the kIOPSPowerAdapter... 101 | keys described in IOPSKeys.h to interpret the returned dictionary. 102 | */ 103 | + (NSDictionary*)externalPowerAdapterDetails; 104 | 105 | /*! 106 | @method powerSourcesInfo 107 | @abstract Returns a NSArray of power source information, each of type NSDictionary. 108 | @discussion Returns a NSArray on success, otherwise returns nil. See the C-strings defined in IOPSKeys.h for specific keys into the dictionary. 109 | Don't expect all keys to be present in any dictionary. 110 | */ 111 | + (NSArray*)powerSourcesInfo; 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /source/PowerMonitorDaemon/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | main.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTSystemInfo.h" 20 | #import "MTPowerMonitorDaemon.h" 21 | #import "Constants.h" 22 | 23 | @interface Main : NSObject 24 | @property (nonatomic, strong, readwrite) MTPowerMonitorDaemon *powerMonitorDaemon; 25 | @property (nonatomic, strong, readwrite) NSUserDefaults *userDefaults; 26 | @property (nonatomic, strong, readwrite) NSArray *keysToObserve; 27 | @end 28 | 29 | @implementation Main 30 | 31 | - (int)run 32 | { 33 | _userDefaults = [NSUserDefaults standardUserDefaults]; 34 | 35 | // define the keys in our prefs we need to observe 36 | _keysToObserve = [[NSArray alloc] initWithObjects: 37 | (NSString*)kMTPrefsEnableJournalKey, 38 | (NSString*)kMTPrefsJournalAutoDeleteKey, 39 | (NSString*)kMTPrefsIgnorePowerNapsKey, 40 | (NSString*)kMTPrefsUseAltPriceKey, 41 | (NSString*)kMTPrefsAltPriceScheduleKey, 42 | nil 43 | ]; 44 | 45 | // start observing our preferences to make sure we'll get notified as soon as 46 | // something changes (e.g. a configuration profile has been installed). 47 | for (NSString *aKey in _keysToObserve) { 48 | 49 | [_userDefaults addObserver:self 50 | forKeyPath:aKey 51 | options:NSKeyValueObservingOptionNew 52 | context:nil 53 | ]; 54 | } 55 | 56 | BOOL success = [_powerMonitorDaemon startMonitoring]; 57 | 58 | if (success) { 59 | 60 | signal(SIGTERM, SIG_IGN); 61 | 62 | dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 63 | dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGTERM, 0, queue); 64 | 65 | if (source) { 66 | 67 | dispatch_source_set_event_handler(source, ^{ 68 | 69 | [self->_powerMonitorDaemon stopMonitoring]; 70 | self->_powerMonitorDaemon = nil; 71 | os_log(OS_LOG_DEFAULT, "SAPCorp: Exiting"); 72 | 73 | exit(0); 74 | }); 75 | 76 | // start processing signals 77 | dispatch_resume(source); 78 | } 79 | 80 | // never return 81 | CFRunLoopRun(); 82 | } 83 | 84 | return EXIT_FAILURE; 85 | } 86 | 87 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 88 | { 89 | if (object == _userDefaults && [_keysToObserve containsObject:keyPath]) { 90 | 91 | [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kMTNotificationNameDaemonConfigDidChange 92 | object:nil 93 | userInfo:[NSDictionary dictionaryWithObject:keyPath forKey:kMTNotificationKeyPreferenceChanged] 94 | options:NSNotificationDeliverImmediately | NSNotificationPostToAllSessions 95 | ]; 96 | } 97 | } 98 | 99 | @end 100 | 101 | 102 | int main(int argc, const char * argv[]) 103 | { 104 | #pragma unused(argc) 105 | #pragma unused(argv) 106 | 107 | int exitCode = EXIT_SUCCESS; 108 | 109 | @autoreleasepool { 110 | 111 | NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:[MTSystemInfo processList]]; 112 | 113 | if ([countedSet countForObject:@"PowerMonitorDaemon"] > 1) { 114 | 115 | fprintf(stderr, "ERROR! Another instance of this daemon is already running\n"); 116 | exitCode = EXIT_FAILURE; 117 | 118 | } else { 119 | 120 | Main *m = [[Main alloc] init]; 121 | m.powerMonitorDaemon = [[MTPowerMonitorDaemon alloc] init]; 122 | exitCode = [m run]; 123 | } 124 | } 125 | 126 | return exitCode; 127 | } 128 | --------------------------------------------------------------------------------