Mac2mqtt — control volume on macOS via MQTT

Yes, I would like to add something like this (not sure that i completely agree with the names & syntax).

What do you think about the ability to run any command? You just publish command to some mqtt topic and it is executed on the mac? Will you use it? Or do you want the ability to explicitly specified the list of allowed commands?

Any names and syntax would be great - I was just trying to illustrate the idea.

I’m not sure I understand exactly what you mean by “command” in your question, but what I want to do is to trigger my iMac screen to wake up (opposite of pmset displaysleepnow) which for me includes inputting a password. This is not a single command, but rather a bunch of stuff that includes grabbing the password from the keychain and then simulating typing it in. I have an applescript that does it, so if I could have mac2mqtt run that applescript, I would have what I need.

That whole thing also made me think about the idea of other more complicated automations I might want to have HA trigger on my Mac in the future and that’s the idea of being able to run arbitrary applescripts - to allow arbitrary, perhaps multi-step automations on the mac to run in response to mqtt messages published by HA.

I love that this can sleep the display and all I need now is a wake display option. I’ve done it in the past with caffeinate -u -t 2 via ssh.

Could this be added to the app?

I’ve never written any go code before but I hacked the mac2mqtt source and added the ability to run my wake up applescript into it.

@bessarabov what I ended up doing inside there was creating a new func commandWake into which I just put:

runCommand("/usr/bin/osascript", path/to/my/applescript)

I set it up so mac2mqtt is watching another topic called prefix/command/wake and looking for the string wake, basically just the same as how you have it already coded for command/displaysleep.

I thought about your idea of being able to publish arbitrary commands to a command topic and I can see how it would be easy to do that, but in my opinion that’s too big a security hole to create. Anyone or anything that could publish to the mqtt broker would be able to run arbitrary commands on a mac that was running mac2mqtt. To me it seems better to keep it locked down to specific commands that you want to be able to run.

@dax333 it would be very simple to add your wake display command.

this is super, super cool, it looks like it can evolve into IOTLink for Mac!

mac2mqtt 1.3.1 running on 11.5.2 doesn’t launch on boot even with KeepAlive and RunAtLoad enabled in /Library/LaunchDaemons/com.bessarabov.mac2mqtt.plist. It doesn’t run unless i manually run launchctl load /Library/LaunchDaemons/com.bessarabov.mac2mqtt.plist after every boot.

Also, Console gives me this every minute: Aug 31 11:02:45 Mac com.apple.xpc.launchd[1] (com.bessarabov.mac2mqtt[2581]): Service exited with abnormal code: 2

What else can I check? Thanks.

For some reason I cannot get this to work with a .plist

I am not sure what goes wrong… here are a couple of infos that should help:
1: If I follow the README.md and name it ‘mac2mqtt’ the file will not run when ./mac2mqtt. Terminal returns:

./mac2mqtt: line 1: package: command not found

./mac2mqtt: line 3: syntax error near unexpected token `newline’

./mac2mqtt: line 3: `import (’

If I then change the mac2mqtt to mac2mqtt.go and instead of ./mac2mqtt.go execute: go run . everything works:

2021/10/18 19:10:17 Started

2021/10/18 19:10:19 Connected to MQTT

2021/10/18 19:10:19 Sending ‘true’ to topic: mac2mqtt/Glenns-MacBook-Pro/status/alive

Everything good, but… I want to run it all the time on boot…

Now this is my .plist (where user is username on macOS):

<?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>Label</key>
        <string>com.user.mac2mqtt</string>
        <key>ProgramArguments</key>
        <array>
        <string>/Users/user/mac2mqtt/mac2mqtt.go</string>
        </array>
        <key>WorkingDirectory</key>
        <string>/Users/user/mac2mqtt/</string>
        <key>RunAtLoad</key>
        <true/>
        <key>KeepAlive</key>
        <true/>
        <key>StandardOutPath</key>
        <string>/Users/user/mac2mqtt/myjob.log</string>
        <key>StandardErrorPath</key>
        <string>/Users/user/mac2mqtt/myjob.log</string>
        <key>Debug</key>
        <true/>
    </dict>
</plist>

If I then load it by:

launchctl load /Library/LaunchDaemons/com.user.mac2mqtt.plist

I again get the same return as in first scenario.

Is there an obvious mistake somewhere I cannot find?

Edit: had a brain fart and responded with incorrect info! :frowning: Apologies!

Can you share it? :smiley:

Edit: hang on, I got confused - I thought this was regarding glances - not mac2mqtt! My bad!

Apologies!! I only slept like 2 hours last night lol!

I’d try deleting the mac2mqtt.go file entirely and creating a brand new file using the code here: https://github.com/bessarabov/mac2mqtt/blob/ece79452a91c10027043e81077d9674b1cf6b655/mac2mqtt.go

I think I created my file using nano on Terminal, pasted in the code from the URL above, saved it simply as mac2mqtt and then made it executable by command ‘chmod +x mac2mqtt
Then update your plist file to remove the ‘.go’ from the end of the mac2mqtt and hopefully it should work?

Still doesn’t work when I launch it by:
launchctl load /Library/LaunchDaemons/com.glennherping.mac2mqtt.plist

I’m afraid I’m not sure why :frowning:

You took the mac2mqtt.go file containing the go source code, dropped the .go extension and changed its priviliges to include “execute”. That doesn’t make it directly executable (at least it doesn’t on my system) unless you invoke the go interpreter:
go run mac2mqtt

In my experience, that also failed because the source code references two external modules (that aren’t included in the default installation of go).

What I did was leave the file name as mac2mqtt.go and compile it into executable code with go build. The result of that process is an executable mac2mqtt file which can be executed from the command line.

However, to get to that stage, I first had to install and configure the development environment for go and then install the two external modules referenced by the mac2mqtt.go source code.

Being completely new to go, it was a longer journey than I had expected but I ultimately got it to work after a fair bit of searching/reading. I also had to remove the code dealing with battery level because when I ran it on an iMac it aborted with an error.

After I got it working, it does everything as described. However, I am not using it because it’s a bit too chatty (it works by polling and publishes status every 2 seconds to ensure prompt updates).

Anyway, it was an educational experience.