Skip to content

Conversation

@cgarwood
Copy link

@cgarwood cgarwood commented Oct 9, 2025

Adds an MQTT remote API to Companion providing live updates of all Companion variables and allows pressing buttons and setting custom variables.

I used the Ember+ module as a reference, and tried to align syntax for commands with the other modules as closely as possible.

Uses the same mqtt dependency as the Generic MQTT Companion Module

This is my first PR against Companion core. I wasn't 100% sure how to handle the yarn.lock file for the PR.

@CLAassistant
Copy link

CLAassistant commented Oct 9, 2025

CLA assistant check
All committers have signed the CLA.

Comment on lines +98 to +105
private startEventListeners(): void {
// Listen for variable changes
this.#serviceApi.on('variables_changed', this.variablesChanged)
}

private stopEventListeners(): void {
this.#serviceApi.removeListener('variables_changed', this.variablesChanged)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not keen on where these are being called from, as it makes it hard to tell when they are being called and to ensure that they are called the correct number of times.

I think it would be easier to follow if they were setup in just the constructor of the class. And teardown might not be necessary (ember+ doesnt do it), as we currently instantiate these at startup and keep them until exit.
The cost of the methods firing when there is no client connected is not enough to worry about I expect, perhaps the variablesChanged method needs a 'is connected' check too?

Comment on lines +113 to +116
if (label == 'internal' && name.startsWith('custom')) {
label = 'custom'
name = name.substring(7)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this block will do anything, while there are some internal aliases of internal:custom_* to custom:*, that is all handled at the point of reading the values, they should never be reported as being changed (I think)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now see that the ember+ service was doing this already, I shall look into removing it from there too

Comment on lines +120 to +122
if (label === 'custom') {
value = this.#serviceApi.getCustomVariableValue(name)?.toString()
if (value === undefined) return
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can skip this block. While technically more correct, its a few levels of indirection that result in the same thing as calling this.#serviceApi.getConnectionVariableValue('custom', name).

It exists primarily to allow the caller to not need to know that the label is 'custom', but you dont need to worry about that as you already have the label and name pair

if (value === undefined) return
} else {
value = this.#serviceApi.getConnectionVariableValue(label, name)?.toString()
if (value === undefined) return
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect that you don't want to do this check, as when a variable gets removes/unset then you wont be reporting that to clients.

In ember+, this would usually manifest as the node going away, but I dont think you can do the same, so should probably report the variable becomign empty

if (value === undefined) return
}

const topic = `${this.topic}/variables/${label}/${name}`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just thinking about future proofing, it might be better to do ${this.topic}/variables/${label}/${name}/value, so that the description or type or something could be added as separate properties later?

Or maybe the message should be a small json blob:

{
  "value": "abc"
}

to allow for other details to be added with it?

this.handleMessage(topic, message)
this.logger.debug(`Received MQTT message on topic ${topic}: ${message.toString()}`)
})
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should any current values be published? having to wait for them to change could be problematic at times?

@cgarwood
Copy link
Author

Thanks for the review! May be a week or so but I'll take a look and make adjustments 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants