├── 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 |
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 |
19 |
--------------------------------------------------------------------------------
/source/Power Monitor/AppIcon.icon/Assets/l3.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | [](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 |
--------------------------------------------------------------------------------