MacOS Content Caching is rarely talked about, but a useful technology to have on your home network if your household uses Apple devices. It’s built into MacOS and caches app downloads, OS updates, Apple TV data, and the contents of your iCloud account. For those with millions of pictures in the Apple Photos app, or who stream content to Apple TVs, this can reduce load times and save you a good amount of bandwidth.
Let’s say you have 7 iOS devices in your household all needing an upgrade to iSO 15. Instead of downloading 1.5GB x 7, you’ll download once, and serve the update from your cache service. This blog post that describes some of the recent additions, like iBooks, OS recovery software downloads, and more that is now being included in the cache.
I have an old Mac Mini that I use for content caching, and I often remote into it to check on how much data I’ve saved. I wanted that data in HA, so made some webhook-based sensors which can receive the that data from a MacOS box.
A number of sensors are defined using the new-ish template format:
template:
- trigger:
- platform: webhook
webhook_id: macos_caching_hook_<some-random-text>
sensor:
- name: "MacOS Cache: Actual Cache Used"
state: "{{ (trigger.json.result.ActualCacheUsed|int / 1024 / 1024) }}"
unit_of_measurement: "MB"
- name: "MacOS Cache: Cache Free"
state: "{{ (trigger.json.result.CacheFree|int / 1024 / 1024) }}"
unit_of_measurement: "MB"
- name: "MacOS Cache: Cache Used"
state: "{{ trigger.json.result.CacheUsed|int / 1024 / 1024 }}"
unit_of_measurement: "MB"
- name: "MacOS Cache: Cache (iCloud)"
state: "{{ trigger.json.result.CacheDetails.iCloud|int / 1024 / 1024 }}"
unit_of_measurement: "MB"
- name: "MacOS Cache: Cache (iOS Software)"
state: "{{ trigger.json.result.CacheDetails['iOS Software']|int / 1024 / 1024 }}"
unit_of_measurement: "MB"
- name: "MacOS Cache: Cache (Mac Software)"
state: "{{ trigger.json.result.CacheDetails['Mac Software']|int / 1024 / 1024 }}"
unit_of_measurement: "MB"
- name: "MacOS Cache: Cache (Other)"
state: "{{ trigger.json.result.CacheDetails.Other|int / 1024 / 1024 }}"
unit_of_measurement: "MB"
- name: "MacOS Cache: Maximum Pressure (past hour)"
state: "{{ trigger.json.result.MaxCachePressureLast1Hour }}"
unit_of_measurement: "%"
- name: "MacOS Cache: Stored From Origin"
state: "{{ trigger.json.result.TotalBytesStoredFromOrigin|int / 1024 / 1024 }}"
unit_of_measurement: "MB"
- name: "MacOS Cache: Served to Clients"
state: "{{ trigger.json.result.TotalBytesReturnedToClients|int / 1024 / 1024 }}"
unit_of_measurement: "MB"
- name: "MacOS Cache: Dropped"
state: "{{ trigger.json.result.TotalBytesDropped|int / 1024 / 1024 }}"
unit_of_measurement: "MB"
binary_sensor:
- name: "MacOS Cache"
state: "{{ trigger.json.result.Active }}"
After HA knows to expect these values, all you need to do from your MacOS machine is run the following:
AssetCacheManagerUtil status -j | curl -H "Content-Type: application/json" -X POST --data-binary @- https://your.home_assistant.url/api/webhook/macos_caching_hook_<some-random-text>
Easy to test from terminal, but in order to keep the sensors up-to-date you’ll need to use launchd
to run this command every couple minutes. launchd
is like the Mac version of crontab
. You can author your own plist files to make recurring commands, or you can be lazy like me and use an app like Lingon (or Scheduler) to do that for you. One thing to look out for is that launchd
treats any job that finished quicker than 10 seconds as a failure. This means you have to add a pointless 10 second sleep before the command you run every N minutes. For example:
sleep 10 && AssetCacheManagerUtil status -j | curl -H "Content-Type: application/json" -X POST --data-binary @- https://your.home_assistant.url/api/webhook/macos_caching_hook_<some-random-text>
Bit of a niche sensor, but if you’ve got an old mac laying around, this is a really nice use for it!