Skip to content

Conversation

@IsmaelMartinez
Copy link
Owner

@IsmaelMartinez IsmaelMartinez commented Nov 30, 2025

Implements the core infrastructure for MQTT extended status publishing as defined in issue #1938 Phase 1a and 1b.

Changes:

  • Add generic publish() method to MQTTClient for flexible MQTT publishing
  • Create MQTTMediaStatusService following established service pattern
  • Add camera-state-changed and microphone-state-changed to IPC allowlist
  • Initialize mediaStatusService in main app when MQTT is enabled
  • Update IPC documentation with new channels (now 42 total)
  • Update research document with Phase 1a completion status
  • Phase 1b: Document configuration schema for semantic categories

What's working:

  • Call state publishing via existing call-connected/call-disconnected events
  • Infrastructure ready for camera/microphone monitoring (Phase 2)
  • Generic publish() method supports all future MQTT use cases

Next steps:

  • Phase 2: Implement WebRTC monitoring for camera/mic state detection

Related: #1938

Implements the core infrastructure for MQTT extended status publishing as defined in issue #1938 Phase 1a. Changes: - Add generic publish() method to MQTTClient for flexible MQTT publishing - Create MQTTMediaStatusService following established service pattern - Add camera-state-changed and microphone-state-changed to IPC allowlist - Initialize mediaStatusService in main app when MQTT is enabled - Update IPC documentation with new channels (now 42 total) - Update research document with Phase 1a completion status What's working: - Call state publishing via existing call-connected/call-disconnected events - Infrastructure ready for camera/microphone monitoring (Phase 2) - Generic publish() method supports all future MQTT use cases Next steps: - Phase 1b: Document configuration schema for semantic categories - Phase 2: Implement WebRTC monitoring for camera/mic state detection Related: #1938
@github-actions
Copy link
Contributor

✅ Changelog entry generated and committed to this PR:

Implement MQTT Extended Status Phase 1a - by @IsmaelMartinez (#2007) 

The file .changelog/pr-2007.txt will be included when you merge this PR.

You can edit it directly in this PR if needed.

github-actions bot added a commit that referenced this pull request Nov 30, 2025
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @IsmaelMartinez, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request implements the foundational infrastructure for publishing extended MQTT status information, specifically focusing on media and call states. It introduces a new service to handle these events and a generic MQTT publishing mechanism, laying the groundwork for future enhancements like real-time camera and microphone status monitoring.

Highlights

  • Generic MQTT Publishing: A new publish() method has been added to MQTTClient to allow flexible publishing of any payload (string or object) to specified MQTT topics with configurable retain and QoS options.
  • MQTT Media Status Service: A new MQTTMediaStatusService has been introduced to bridge IPC events (like call connected/disconnected, camera/microphone state changes) to the MQTT broker, publishing to topics such as {topicPrefix}/in-call, {topicPrefix}/camera, and {topicPrefix}/microphone.
  • IPC Channel Allowlist Expansion: The IPC allowlist in app/security/ipcValidator.js has been updated to include camera-state-changed and microphone-state-changed channels, ensuring secure communication for media status updates.
  • Main Application Integration: The main application (app/index.js) now imports and initializes the MQTTMediaStatusService when MQTT is enabled, ensuring the service starts up correctly.
  • Documentation Updates: The auto-generated IPC documentation (docs-site/docs/development/ipc-api-generated.md) has been updated to reflect the new channels, increasing the total documented channels to 42. The research document for MQTT extended status has also been updated to mark Phase 1a as complete.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request lays a solid foundation for extended MQTT status publishing by introducing a new MQTTMediaStatusService and a flexible, reusable publish method in the MQTTClient. The code is well-structured and follows existing patterns in the codebase. However, there's a critical issue with the IPC handling for call states that will prevent that part of the feature from working. Additionally, there are some minor inconsistencies in the auto-generated documentation regarding IPC channel counts that should be corrected to prevent confusion.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 30, 2025

📦 PR Build Artifacts

Build successful! Download artifacts:

View workflow run

Fix conflict where call-connected and call-disconnected IPC channels were registered with both ipcMain.handle (browserWindowManager) and ipcMain.on (mediaStatusService), which is not allowed in Electron. Solution: - browserWindowManager emits internal events after handling IPC - MQTT service listens to internal events instead of IPC channels directly Changes: - browserWindowManager now emits 'teams-call-connected' and 'teams-call-disconnected' internal events after handling IPC - mediaStatusService listens to internal events, not IPC channels - Maintains existing IPC contract (still returns boolean) - No breaking changes to renderer-side IPC callers This decouples the event handling and allows multiple listeners for the same logical event.
Move internal call state events from ipcMain to app EventEmitter to properly separate IPC channels from internal process events. Changes: - Use app.emit() instead of ipcMain.emit() for internal events - MQTT service uses app.on() instead of ipcMain.on() for internal events - Add descriptive comments above all IPC channel registrations - IPC documentation now correctly shows 40 channels (was 42) - Remove duplicate call-connected/call-disconnected entries - All channel descriptions now present This fixes the IPC documentation issues identified by review: - Eliminates duplicate channel entries - Correct channel count (38 + 2 new = 40) - Complete descriptions for all channels
@IsmaelMartinez IsmaelMartinez force-pushed the claude/mqtt-extended-status-phase-1a-01NwR55q278TNrwhymeNFKUq branch from fcee25b to 5203977 Compare November 30, 2025 09:24
@github-actions
Copy link
Contributor

✅ Changelog entry generated and committed to this PR:

Implement MQTT Extended Status Phase 1a - by @IsmaelMartinez (#2007) 

The file .changelog/pr-2007.txt will be included when you merge this PR.

You can edit it directly in this PR if needed.

@IsmaelMartinez
Copy link
Owner Author

Hello @vbartik,

The changes in this branch should add the {topicPrefix}/in-call (default is teams/in-call) that just returns a boolean for when connects and disconnects.

📦 PR Build Artifacts

Build successful! Download artifacts:

View workflow run

Can you test it? Seems to work for me. Once this is out we can look at phase 2 that is adding the mic and camera status, that might be a bit more difficult.

I still need to update the docs etc, but appreciate feedback to see if this is going to work. Thanks!

@IsmaelMartinez IsmaelMartinez changed the title Implement MQTT Extended Status Phase 1a Implement MQTT Extended Status Phase 1(a and b) Nov 30, 2025
Document new MQTT topics in configuration guide. Changes: - Add "Published Topics" table to MQTT Integration section - Document {topicPrefix}/in-call, camera, and microphone topics - Explain payload format and retained message behavior - Mark Phase 1b as complete in research document - Update overall status to "Phase 1 Complete" All MQTT topics are now documented for users setting up home automation integrations.
MDX interprets {topicPrefix} as JavaScript expressions. Escape them with backslashes to render as literal text. Fixes documentation build errors in configuration.md and mqtt-extended-status-investigation.md
@vbartik
Copy link

vbartik commented Nov 30, 2025

Hi @IsmaelMartinez ,

I did some preliminary tests. The feature, in simple scenario - "clicked" join + "clicked" leave - works.

  1. If I click on "Meet now", acknowledge a meeting name, it immediately gets me in-call = true, before "Join now" gets clicked on. If I cancel it (press "Cancel" instead of "Join now"), it stays on 'true', as 'hangup' never occurred. If I follow through with the join and the go "Leave", in-call correctly switches to false. This happens even for scheduled meetings in the calendar. In call gets triggered before actual joining happens - either before you click join, or you're waiting in a lobby.
  2. If I start the app, in-call doesn't get mqtt-published until there is a reason to go for 'true' or 'false' value.
  3. As it seems to be bound to the controls to join and leave, there might be an issue with calls, that end when creator closes the meeting and it just gets terminated for attendees without them actually leaving on their own. (This is a speculation though)
  4. I think, that the in-call should appear within the status for ease of integration to Home Assistant. But for testing purposes of the functionality itself, it doesn't really matter.
@IsmaelMartinez
Copy link
Owner Author

Hi @vbartik thanks for the testing and review. A few comments back.

Hi @IsmaelMartinez ,

I did some preliminary tests. The feature, in simple scenario - "clicked" join + "clicked" leave - works.

  1. If I click on "Meet now", acknowledge a meeting name, it immediately gets me in-call = true, before "Join now" gets clicked on. If I cancel it (press "Cancel" instead of "Join now"), it stays on 'true', as 'hangup' never occurred. If I follow through with the join and the go "Leave", in-call correctly switches to false. This happens even for scheduled meetings in the calendar. In call gets triggered before actual joining happens - either before you click join, or you're waiting in a lobby.
  2. If I start the app, in-call doesn't get mqtt-published until there is a reason to go for 'true' or 'false' value.
  3. As it seems to be bound to the controls to join and leave, there might be an issue with calls, that end when creator closes the meeting and it just gets terminated for attendees without them actually leaving on their own. (This is a speculation though)
  4. I think, that the in-call should appear within the status for ease of integration to Home Assistant. But for testing purposes of the functionality itself, it doesn't really matter.
  1. The actual events we are hooking in are call connected and disconnected, what looks like it might be a limitation. Maybe we can change the event to not be a boolean, but to have a string that mentions the status. connected, disconnected (or similar) and we can look into seeing if we can add other ones.
  2. That is a limitation with even driven systems. We could emit an "initial state" for all the events we publish, but that gets pretty messy, and would add a dependency with the mqtt client on the starting order.
  3. If teams crashes within a call, yes, you will not get a disconnected even, and the system will be out of sync until you perform an action.
  4. We need to keep them separated to make sure we can extend the system. True it might require a bit more on the other side, but you should get more granularity. For example, if a user only want to care about this in-call event, they don't need to filter all the status event changes (and the other way around)

For 2 and 3 we could add an event that triggers indicating the app has loaded (and/or crashed), and you couldn't reset the status on your side. We could add extra events but I tend to prefer to keep them separated and to not emit events without a cause-effect.

Thanks again for the test. I will think about it a bit more. Appreciate the feedback.

@vbartik
Copy link

vbartik commented Dec 1, 2025

Hi @IsmaelMartinez ,

regarding 1+2, understood.

3. If teams crashes within a call, yes, you will not get a disconnected even, and the system will be out of sync until you perform an action. 

Maybe a MQTT LWT message could work here well?

4. We need to keep them separated to make sure we can extend the system. True it might require a bit more on the other side, but you should get more granularity. For example, if a user only want to care about this in-call event, they don't need to filter all the status event changes (and the other way around) 

You're right about the granularity. It allows granular event driven flows through targeted mqtt topic subscriptions, and you then don't really have to determine what changed within one big json. 👍 Aggregating into a single topic of multiple metrics would make sense when you're for example reading multiple values from a physical sensor at once, or similar. These are decoupled.

@IsmaelMartinez
Copy link
Owner Author

sorry, what do you mean with LWT ? (and apologies as I am extremely busy so playing catchup)

@vbartik
Copy link

vbartik commented Dec 8, 2025

It is MQTT Will Message (Last Will & Testament = LWT). Basically, if a clients provides MQTT lastWill to the broker, upon the client's unexpected disconnection, the broker acts upon it by posting the lastWillMessage to the lastWillTopic. That way, you can update the status to 'disconnected' for example, even if you crash/lose connectivity/whatever unexpected happens.

Implement MQTT LWT to handle app crashes and network failures gracefully. Changes: - Configure LWT on connection: publishes connected=false if app disconnects unexpectedly - Publish connected=true when successfully connected to broker - Publish connected=false on graceful disconnect - Add {topicPrefix}/connected topic to documentation How it works: - On connect: broker stores LWT message (connected=false) - App publishes: connected=true (while running) - App crashes/network fails: broker auto-publishes LWT (connected=false) - Graceful exit: app publishes connected=false before disconnecting This allows home automation to detect stale state and invalidate in-call/camera/mic status when the app is offline. Related: #1938
Document the implementation of MQTT Last Will and Testament. Changes: - Mark Phase 1c as completed in checklist - Add implementation notes explaining LWT behavior - Include Home Assistant example for handling disconnects - Update MQTT topics list to include connected topic - Update status header to reflect complete Phase 1 Phase 1 is now complete with: - 1a: Core infrastructure - 1b: Documentation - 1c: Connection state & LWT
@IsmaelMartinez
Copy link
Owner Author

That LWT is now associated to a new topic "{topicPrefix}/connected" (teams/connected by default). Apologies but I got little time lately. Let me know if you are happy with the it and I can see if we can release this.

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

Labels

None yet

4 participants