Firebase / FCM setup

The FCM doorbell has two sides, each with its own credential:

  • The server sends wake messages → it needs a service-account key (secret).
  • The agent receives them → it needs google-services.json (not secret) + the google-services Gradle plugin.

Both are optional for basic development: with neither configured, the server logs FCM doorbell: NOT configured, ring() is a no-op, and agents simply sync over HTTP on their normal schedule. You only need this to get push wake-ups.

Server: the service-account key

Doorbell (Doorbell.kt) resolves a credential in this order:

  1. Application Default Credentials — the GOOGLE_APPLICATION_CREDENTIALS environment variable (or a GCP runtime). This is the recommended path.
  2. A local key file, by trying these relative paths in turn:
    • firebase-service-account.json
    • server/firebase-service-account.json
    • ../server/firebase-service-account.json

    Multiple candidates exist because the working directory depends on the launcher: :server:run runs from the server/ module directory, while java -jar runs from wherever you invoke it.

Generate the key

Firebase console → Project settings → Service accounts → Generate new private key. Save the JSON as server/firebase-service-account.json, or point GOOGLE_APPLICATION_CREDENTIALS at it.

Never commit this file. It’s a private key. .gitignore already excludes **/firebase-service-account.json and *-service-account.json. Don’t paste its contents anywhere, including into docs or issues.

Verify

Start the server and look for the boot log:

FCM doorbell: ready — policy changes will wake devices via push.

If you instead see NOT configured, the credential wasn’t found (or failed to initialize — any failure degrades to no-op by design, so the server never 500s on the doorbell).

Agent: google-services.json + the plugin

The agent needs Firebase client config:

  • agent/google-services.json — downloaded from the Firebase console for the agent’s application id (com.arganaemre.mdmcore). It’s not secret and is committed (unlike the service-account key). The google-services plugin processes it at build time into Firebase config resources.
  • Gradle wiring in agent/build.gradle.kts: the com.google.gms.google-services plugin, the Firebase BoM (which pins versions), and firebase-messaging (unversioned — the BoM controls it). Versions: development.md.

If google-services.json is missing, the agent build fails — the plugin requires it.

Emulator requirements

Live FCM needs Google Play services, which means an emulator created from a “Google APIs” system image (not a bare AOSP image).

This dovetails neatly with Device Owner: set-device-owner requires a device with no account added — and a Google APIs image with no account signed in satisfies both requirements at once. So: a fresh Google APIs emulator, no account, is the sweet spot for end-to-end testing.

Quick checklist

  • agent/google-services.json present (agent builds).
  • Service-account key at server/firebase-service-account.json or GOOGLE_APPLICATION_CREDENTIALS set (server logs FCM doorbell: ready).
  • Emulator from a Google APIs image, no account signed in.
  • Device Owner set (see agent.md).

Without the first two, everything still works — just without push. See troubleshooting.md when the doorbell rings but nothing happens.