Guide macOS M1 and Home Assistant including ZWave

Home Assistant on M1 Mac is not well documented. I hope we can change that.

Please criticize and improve this method.
No warranties, make backups, expect everything.
My user is called “server”, change accordingly.

Why this method

  • Docker on macOS can’t use USB/Serial devices.
  • M1 Macs use virtual machines in emulation mode which is not efficient (25 % CPU with UTM on idle)
  • Raspberry Pi and similar devices can’t offer the flexibility and power of an existing Mac.

:white_check_mark: Install Node.JS LTS for macOS

:white_check_mark: Install Homebrew

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

:white_check_mark: Install Python3 on macOS

brew install python3

:white_check_mark: Install libjpeg-turbo

brew install jpeg-turbo

:white_check_mark: Install make - required since 2023.12 uses make to install zlib-ng

brew install make

:white_check_mark: Install python virtual environment (venv) and Home Assistant

pip3 install virtualenv
cd ~/
python3 -m venv homeassistant
source homeassistant/bin/activate
pip3 install homeassistant
deactivate

Config is saved in ~/.homeassistant

:white_check_mark: Install Yarn compiler

npm install --global yarn

:white_check_mark: Compile ZWaveJS2MQTT for M1

git clone https://github.com/zwave-js/zwavejs2mqtt
cd zwavejs2mqtt
yarn install
yarn run build

:white_check_mark: Manual start or restart (optional)

cd ~/zwavejs2mqtt
yarn start

source ~/homeassistant/bin/activate
~/homeassistant/bin/hass

:white_check_mark: Run Home Assistant and ZWaveJS2MQTT as services at startup

start service
launchctl load /Users/server/Library/LaunchAgents/org.homeassistant.plist
launchctl load /Users/server/Library/LaunchAgents/org.zwavejs2mqtt.plist

stop service
launchctl unload /Users/server/Library/LaunchAgents/org.homeassistant.plist
launchctl unload /Users/server/Library/LaunchAgents/org.zwavejs2mqtt.plist

manual start
launchctl start org.homeassistant
launchctl start org.zwavejs2mqtt

manual stop
launchctl stop org.homeassistant
launchctl stop org.zwavejs2mqtt

Make
~/Library/LaunchAgents/org.homeassistant.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>AbandonProcessGroup</key>
	<false/>
	<key>EnvironmentVariables</key>
	<dict>
		<key>LC_CTYPE</key>
		<string>UTF-8</string>
		<key>PATH</key>
		<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH</string>
	</dict>
	<key>KeepAlive</key>
	<dict>
		<key>SuccessfulExit</key>
		<false/>
	</dict>
	<key>Label</key>
	<string>org.homeassistant</string>
	<key>Program</key>
	<string>/Users/server/.homeassistant/scripts/ha_agent.sh</string>
	<key>RunAtLoad</key>
	<true/>
</dict>
</plist>

Make
~/Library/LaunchAgents/org.zwavejs2mqtt.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>AbandonProcessGroup</key>
	<false/>
	<key>EnvironmentVariables</key>
	<dict>
		<key>LC_CTYPE</key>
		<string>UTF-8</string>
		<key>PATH</key>
		<string>/usr/local/bin/:/usr/bin:/usr/sbin:/sbin:$PATH</string>
	</dict>
	<key>KeepAlive</key>
	<dict>
		<key>SuccessfulExit</key>
		<false/>
	</dict>
	<key>Label</key>
	<string>org.zwavejs2mqtt</string>
	<key>ProgramArguments</key>
  	<array>
		<string>bash</string>
		<string>-c</string>
		<string>cd /Users/server/zwavejs2mqtt; yarn start</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
</dict>
</plist>

Make
~/.homeassistant/scripts/ha_agent.sh

#!/bin/bash
sleep 60
source /Users/server/homeassistant/bin/activate
/Users/server/homeassistant/bin/hass

Make it executable:
chmod 711 ~/.homeassistant/scripts/ha_agent.sh

:white_check_mark: Backup procedure
Make sure to backup these folders regularly:

~/.homeassistant
~/homeassistant
~/zwavejs2mqtt

Or automate it:

caffeinate rsync -E -a --delete "/Users/server/homeassistant" "/Volumes/Backup/server"
caffeinate rsync -E -a --delete "/Users/server/.homeassistant" "/Volumes/Backup/server"
caffeinate rsync -E -a --delete "/Users/server/zwavejs2mqtt" "/Volumes/Backup/server"

:white_check_mark: Update procedures

Update Homebrew and all its packages (including Python3) and clean caches

brew update
brew upgrade
brew autoremove
brew cleanup --prune=all

Update Node.JS and npm

sudo npm install --global yarn
sudo npm install -g npm@latest
sudo npm cache clean -f
sudo npm install -g n
sudo n stable

Stop services

launchctl stop org.homeassistant

Update Python virtual environment (venv)

pip3 install --upgrade pip
pip3 install virtualenv
python3 -m venv ~/homeassistant

Install Home Assistant Core

rm -rf ~/homeassistant_old
mv ~/homeassistant ~/homeassistant_old
cd ~/
python3 -m venv homeassistant
source homeassistant/bin/activate
pip3 install --upgrade pip
pip3 install homeassistant
deactivate

Update ZWaveJsMQTT

rm -rf ~/zwavejs2mqtt_old
cp ~/zwavejs2mqtt ~/zwavejs2mqtt_old
cd ~/
#sudo npm install --global yarn
git clone https://github.com/zwave-js/zwavejs2mqtt
cd ~/zwavejs2mqtt
yarn install
yarn run build

Update custom addons

~/.homeassistant/custom_components

Automation example - be very careful and adapt

rm -rf ~/Desktop/tmp
mkdir ~/Desktop/tmp
cd ~/Desktop/tmp
curl -L  "https://github.com/USER/REPOSITORY/archive/refs/heads/NAME.zip" >file.zip
unzip file.zip
rm file.zip
mv * git_tmp
mv git_tmp/custom_components/*/ ~/Desktop/ha_tmp
rm -rf ~/Desktop/tmp

rm -rf ~/.homeassistant/custom_components/REPOSITORY
mv ~/Desktop/ha_tmp/* ~/.homeassistant/custom_components
rm -rf  ~/Desktop/ha_tmp

Restart Services after update or restart macOS

launchctl stop org.homeassistant
launchctl start org.homeassistant
launchctl stop org.zwavejs2mqtt
launchctl start org.zwavejs2mqtt

Quirks with macOS
Add this code to configuration YAML for video support on HomeKit

ffmpeg:
  ffmpeg_bin: /opt/homebrew/bin/ffmpeg

:bulb:
PLEASE report any bugs or improvements that I could do. I will add all improvements to this page. :slightly_smiling_face:

6 Likes

Big update above - please review and comment

Finally got it working, big thank you!

Btw, I had some trouble configuring the plist for the launch agents and sh script, until i realised the user was server. Maybe it would be clearer if there was an indication that it has to be replaced by your username.

Nice, that was the plan. Glad it helped you.

I did mention it, but an example would probably help.

I am constantly improving the method. If you find any improvements or issues come back to this thread.

Awesome tutorial. I used it without the Z-Wave part as I’m using zigbee. But I wondered if anyone was able to make HACS working.

HACS if needed

brew install wget
wget -O - https://get.hacs.xyz | bash -

Updated some installation and update routines.

Excellent work. Is this accessible to other applications on the Mac? Can I point them to 127.0.0.1:8123 or locahhost:8123?

Thank you :slight_smile:

Yes it is. You can also access any path on your Mac as well and you can use shell scripts to interact with the OS.

Awesome I have it running on my mac, however it does not start automatically. I have both .plist files in ~/Library/LaunchAgents/ and I have changed server to my username.

Any ideas?

Make sure your shell script is executable.
chmod 711 ~/.homeassistant/scripts/ha_agent.sh

Also use the full paths in the script and in the plist.

Run these commands if you change anything:

launchctl unload /Users/server/Library/LaunchAgents/org.homeassistant.plist
launchctl load /Users/server/Library/LaunchAgents/org.homeassistant.plist

Having trouble at this point, cant update PIP

error: can’t find Rust compiler

If you are using an outdated pip version, it is possible a prebuilt wheel is available for this package but pip is not able to install from it. Installing from the wheel would avoid the need for a Rust compiler.

To update pip, run:

  pip install --upgrade pip

and then retry package installation.

If you did intend to build this package from source, try installing a Rust compiler from your system package manager and ensure it is on the PATH during installation. Alternatively, rustup (available at https://rustup.rs) is the recommended way to download and update the Rust compiler toolchain.

This package requires Rust >=1.41.0.

Thanks for putting all this together!

Because of network issues with docker on mac/windows, I’ve been reading into this and have HA setup this way for testing purposes. My current setup in use is HA OS on a rpi 4b.

I haven’t implemented everything you’ve documented here, but it doesn’t look like it addresses one thing I’ve noticed while I’ve been testing the venv environment — when restarting from HA (config >> settings >> server controls >> restart), HA needs to be manually restarted from the venv, is that the case in your setup too?

Also, I appreciate the instructions for zwave, but there are a bunch more other add-ons that I use with my rpi4b setup and Im not really sure how to go about implementing. I understand this is supposed to be a more advanced method of running HA but I gotta say, there’s hardly any info other than running HA alone … which is obviously doesn’t help a newb like me.

Things I’m looking to integrate: mqtt (I came across this but have not attempted yet), esphome dashboard (haven’t been able to find any info on this), adguard (although not end of world if not running in this environment), nginx+duckdns, grafana+influx (maybe this last combo might be better done outside of venv? Not sure how to integrate back into HA)

It will restart automatically.

Not sure about the components you are using. But custom_components are easy to install and I covered the update procedure above. You could even install HACS if that is easier for you.

Zwavejs2mqtt includes MQTT, but I don’t use it yet. Take a look at this first, maybe it already helps.

Hmm… I wonder what could be wrong with my setup that it would not restart …

Yeah, I followed your post above for HACS and have all the custom components I need installed.
This is however different from the supervisor add-ons though.

As for zwavejs2mqtt, that is meant for exposing the zwave service to a MQTT broker if I’m not mistaken. That goes for things like zigbee2mqtt, etc. as well and so the MQTT broker needs to be setup separately. I’m with you on this, I like my zwave on it’s own and I don’t run my devices through MQTT so I’ve never used it before.

I’ve managed to get the MQTT Broker installed today from the link I included above. The broker starts as a separate service, similar to what you have provided the write-up for the zwave part and I am able to add the integration into Home Assistant.

After some digging, I’ve been able to manually start up Home Assistant, esphome and mosquitto MQTT broker … each from their own terminal window.

Now I’m trying to implement them as services per your instructions above (at least for HA itself).
I put in the plist (changing “server”), created the shell script and chmod it.
Then I tried to manually start it just to make sure it works (before turning it into a service); none of the below work:

launchctl start org.homeassistant
launchctl start ~/Library/LaunchAgents/org.homeassistant.plist
launchctl start /Users/MYUSERNAME/Library/LaunchAgents/org.homeassistant.plist

Is there a log somewhere that I can check to see why it may not be starting up?

Edit: Found this in the console, but have not been able to figure out how to fix:

Program specified by service is not a Mach-O executable file
Service exited with abnormal code: 78

executing the shell file works, so maybe it’s something in the .plist?
What exactly is happening in this line here:
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH</string>
I’m wondering if maybe my folder structure doesn’t quite look like whatever this is trying to do??

This line defines the paths that can be used by the script directly. For example that it can run python3 instead of /path/to/python3.

<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH</string>

Try this command and check for errors.

launchctl unload /Users/server/Library/LaunchAgents/org.homeassistant.plist
launchctl load /Users/server/Library/LaunchAgents/org.homeassistant.plist

I think I’m in the same boat as you - seems to be able to launch directly through Terminal, but the plist/script doesn’t seem to be running anything.
Did you have any luck figuring your issue out?

I did actually get everything running, but to be honest, I wasn’t even sure what it was that I did that made things work.

If I had to do this all over again, I would probably first start with unloading all the associated .plist files in the ~/User/Library/LaunchAgents. So from terminal use “launchctl unload <<path of .plist>>” Then remove them from that folder and then restart the computer.

Once restarted, load them in one by one and monitor from the Console app (look at the sys.log at the bottom left) to find what the error is that showed up and diganose them one by one. Sometimes it might just be that the .plist is referring to something with the wrong path.

Suggest updating the above to #!/bin/bash