# Interface HomeBridge

public interface HomeBridge

Internal service-provider interface implemented by each platform port to back `com.codename1.home.SmartHome` with HomeKit, the Google Home APIs, or a local simulated home.

Application code never touches this; see the package documentation.

##### Primitives and flat strings only

Nothing here takes or returns an object from `com.codename1.home`. The graph crosses as arrays of tab-delimited strings and values cross as parallel primitive arrays, so an Objective-C implementation never has to construct a Java object -- which under ParparVM means no allocation, no class lookup, and no question about which thread built it. The same discipline `com.codename1.wearable.spi.WearableBridge` follows, for the same reasons.

The cost is that the encoding is a contract, written out below and shared with `com.codename1.impl.home.HomeWire`, which does the decoding.

##### Identifiers

Three separate opaque strings, never an index and never a composite the other side has to parse:

- structureId -- unique within the bridge. HomeKit: `HMHome.uniqueIdentifier`. Google: the structure id.
- accessoryId -- unique within the bridge, not merely within its structure, so a read or a write needs only two of the three. HomeKit: `HMAccessory.uniqueIdentifier`. Matter: the fabric device id.
- serviceId -- unique within its accessory. HomeKit: `HMService.uniqueIdentifier`. Matter: the endpoint number as decimal.

A traitId is always the canonical token from `com.codename1.home.Trait#getId()`. A port maps it to its own platform identifier on its own side; no `HMCharacteristicType` string and no Matter cluster id ever crosses into Java.

##### Asynchrony

Every method taking a `requestId` returns immediately and answers later through the matching static on `com.codename1.home.SmartHome`. Those statics accept calls from any thread and marshal onto the EDT themselves, which matters here specifically because `HMHomeManagerDelegate` and `HMAccessoryDelegate` callbacks arrive on the Objective-C main queue and that is not the Codename One EDT.

Request ids are allocated by the framework, are positive, and are never reused while in flight. Zero is reserved for unsolicited deliveries.

##### Error encoding

Wherever a method's answer can fail, the error crosses as `<HomeError name>\t<platform message>`, or `null` or empty for success. The name, never the ordinal: a port built against a different version of the enum would otherwise map every error past an inserted constant onto the wrong one, and a mis-mapped authorization failure is indistinguishable from a mis-mapped timeout to everything downstream.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `boolean`
  `areIdsPersistent()`
  Whether accessory and structure identifiers survive an app restart.
  `void`
  `commission(int requestId, String setupPayload, String structureId, String roomId, String suggestedName, int timeoutMillis)`
  Adds a new Matter accessory.
  `void`
  `createScene(int requestId, String structureId, String name, String[] accessoryIds, String[] serviceIds, String[] traitIds, int[] kinds, double[] numericValues, String[] stringValues, int[] unitWireIds)`
  Creates a scene.
  `void`
  `deleteScene(int requestId, String structureId, String sceneId)`
  Deletes a scene.
  `void`
  `drainChanges(int requestId)`
  Hands over changes gathered since the last drain, through `SmartHome.deliverChanges` for each affected subscription, then answers `SmartHome.deliverDrained`.
  `void`
  `executeScene(int requestId, String structureId, String sceneId)`
  Runs a scene.
  `String[]`
  `getAccessories(String structureId)`
  The accessories of one home, one per entry: `id \t name \t roomId \t categoryOrdinal \t manufacturer \t model \t firmware \t reachable \t bridgeAccessoryId`.
  `int`
  `getAuthorizationStatus()`
  The current authorization, as the ordinal of a `com.codename1.home.HomeAuthorizationStatus` constant.
  `int`
  `getAvailability()`
  The current availability, as the ordinal of a `com.codename1.home.HomeAvailability` constant.
  `String`
  `getBackendId()`
  Which backend this is: `"homekit"`, `"google_home"`, `"matter_only"` or `"local"`.
  `int`
  `getCommissioningStyle()`
  How this backend adds a new accessory, as the ordinal of a `com.codename1.home.commissioning.CommissioningStyle` constant.
  `String[]`
  `getConfigurationProblems()`
  Build configuration this backend needs and does not have -- a missing entitlement, a missing Google Cloud project id -- one human-readable sentence per problem, each naming the build hint that fixes it.
  `int`
  `getMaxReadBatchSize()`
  The largest number of traits this backend will read in one call, or zero for no limit.
  `int`
  `getMaxWriteBatchSize()`
  The largest number of traits this backend will write in one call, or zero for no limit.
  `String[]`
  `getRooms(String structureId)`
  The rooms of one home, one per entry: `id \t name`.
  `String[]`
  `getSceneActions(String structureId, String sceneId)`
  What one scene does, one action per entry: `accessoryId \t serviceId \t traitId \t kindOrdinal \t numericValue \t stringValue \t unitWireId`.
  `String[]`
  `getScenes(String structureId)`
  The scenes of one home, one per entry: `id \t name \t typeOrdinal \t executable`.
  `String[]`
  `getServices(String accessoryId)`
  The services of one accessory, one per entry: `id \t name \t serviceTypeOrdinal \t primary`.
  `String[]`
  `getStructures()`
  The homes, one per entry: `id \t name \t primary \t owner \t sceneAuthoring`, where the three flags are `1` or `0`.
  `String[]`
  `getTraits(String accessoryId, String serviceId)`
  The traits of one service, one per entry: `traitId \t readable \t writable \t notifies \t hasRange \t min \t max \t step \t validOrdinalsCsv`.
  `String[]`
  `getZones(String structureId)`
  The zones of one home, one per entry: `id \t name \t roomId,roomId,...`.
  `void`
  `identify(int requestId, String accessoryId)`
  Asks an accessory to make itself known -- blink, beep.
  `boolean`
  `isPushDelivery()`
  Whether this backend pushes trait changes without being asked.
  `boolean`
  `isSupported()`
  Whether this bridge can do anything at all.
  `boolean`
  `openEcosystemApp()`
  Opens the platform's ecosystem app -- Apple Home, Google Home -- so the user can set up a home or add an accessory there.
  `boolean`
  `openHomeSettings()`
  Opens the system settings page where the user can change this app's smart-home access.
  `boolean`
  `openProviderSetup()`
  Opens wherever the user installs or updates the backend's provider -- Google Play services on Android.
  `void`
  `readTraits(int requestId, String[] accessoryIds, String[] serviceIds, String[] traitIds, boolean allowCached)`
  Reads traits.
  `void`
  `refresh(int requestId)`
  Reloads the graph from the platform.
  `void`
  `requestAuthorization(int requestId)`
  Prompts the user for access.
  `void`
  `start(int requestId)`
  Connects to the backend and loads the graph.
  `void`
  `stop()`
  Disconnects, releases every platform registration, and drops any pending request without answering it.
  `void`
  `subscribe(int requestId, String subscriptionId, String[] accessoryIds, String[] serviceIds, String[] traitIds)`
  Starts watching traits.
  `void`
  `unsubscribe(String subscriptionId)`
  Stops watching and releases the platform registration.
  `void`
  `writeTraits(int requestId, String[] accessoryIds, String[] serviceIds, String[] traitIds, int[] kinds, double[] numericValues, String[] stringValues, int[] unitWireIds, String[] authorizationData)`
  Writes traits.

- ## Method Details

  - ### isSupported

    boolean isSupported()

    Whether this bridge can do anything at all. A port that compiles the smart-home code but finds the platform missing at runtime answers `false` here rather than failing every later call.

    ###### Returns

    `true` when the backend is present

  - ### getAvailability

    int getAvailability()

    The current availability, as the ordinal of a `com.codename1.home.HomeAvailability` constant.

    May be called before `start(int)` and must answer without blocking.

    ###### Returns

    the availability ordinal

  - ### getBackendId

    String getBackendId()

    Which backend this is: `"homekit"`, `"google_home"`, `"matter_only"` or `"local"`.

    ###### Returns

    the backend token, never `null`

  - ### getConfigurationProblems

    String[] getConfigurationProblems()

    Build configuration this backend needs and does not have -- a missing entitlement, a missing Google Cloud project id -- one human-readable sentence per problem, each naming the build hint that fixes it.

    Empty when nothing is missing. This is what `com.codename1.home.HomeConfigurationException` carries, so the text is read by a developer, not by a user.

    ###### Returns

    the problems, never `null`

  - ### areIdsPersistent

    boolean areIdsPersistent()

    Whether accessory and structure identifiers survive an app restart.

    Both shipping backends answer `true`; a local or test bridge that regenerates its graph does not, and an app persisting a favourite should ask.

    ###### Returns

    `true` when identifiers are stable across launches

  - ### start

    void start(int requestId)

    Connects to the backend and loads the graph. Answers through `SmartHome.deliverStarted`.

    ###### Parameters

    - `requestId`: the request to answer

  - ### stop

    void stop()
    Disconnects, releases every platform registration, and drops any pending request without answering it. Idempotent.

  - ### getAuthorizationStatus

    int getAuthorizationStatus()

    The current authorization, as the ordinal of a `com.codename1.home.HomeAuthorizationStatus` constant.

    ###### Returns

    the status ordinal

  - ### requestAuthorization

    void requestAuthorization(int requestId)

    Prompts the user for access. Answers through `SmartHome.deliverAuthorization` when the flow finishes, whatever the user chose.

    ###### Parameters

    - `requestId`: the request to answer

  - ### openHomeSettings

    boolean openHomeSettings()

    Opens the system settings page where the user can change this app's smart-home access.

    ###### Returns

    `true` when something was opened

  - ### openEcosystemApp

    boolean openEcosystemApp()

    Opens the platform's ecosystem app -- Apple Home, Google Home -- so the user can set up a home or add an accessory there.

    ###### Returns

    `true` when the app was opened; `false` when it is not installed

  - ### openProviderSetup

    boolean openProviderSetup()

    Opens wherever the user installs or updates the backend's provider -- Google Play services on Android.

    ###### Returns

    `true` when something was opened

  - ### getStructures

    String[] getStructures()

    The homes, one per entry: `id \t name \t primary \t owner \t sceneAuthoring`, where the three flags are `1` or `0`.

    Synchronous, and must not block: the bridge caches the platform's model and this reads the cache. `refresh(int)` is what reloads it.

    ###### Returns

    the encoded homes, never `null`

  - ### getRooms

    String[] getRooms(String structureId)

    The rooms of one home, one per entry: `id \t name`.

    ###### Parameters

    - `structureId`: the home

    ###### Returns

    the encoded rooms, never `null`

  - ### getZones

    String[] getZones(String structureId)

    The zones of one home, one per entry: `id \t name \t roomId,roomId,...`.

    Empty on every backend but HomeKit, which is the only one with zones.

    ###### Parameters

    - `structureId`: the home

    ###### Returns

    the encoded zones, never `null`

  - ### getAccessories

    String[] getAccessories(String structureId)

    The accessories of one home, one per entry: `id \t name \t roomId \t categoryOrdinal \t manufacturer \t model \t firmware \t reachable \t bridgeAccessoryId`.

    `roomId` and `bridgeAccessoryId` are empty when absent; `reachable` is `1` or `0`; `categoryOrdinal` indexes `com.codename1.home.AccessoryCategory`.

    ###### Parameters

    - `structureId`: the home

    ###### Returns

    the encoded accessories, never `null`

  - ### getServices

    String[] getServices(String accessoryId)

    The services of one accessory, one per entry: `id \t name \t serviceTypeOrdinal \t primary`.

    `serviceTypeOrdinal` indexes `com.codename1.home.ServiceType`; `primary` is `1` or `0`.

    ###### Parameters

    - `accessoryId`: the accessory

    ###### Returns

    the encoded services, never `null`

  - ### getTraits

    String[] getTraits(String accessoryId, String serviceId)

    The traits of one service, one per entry: `traitId \t readable \t writable \t notifies \t hasRange \t min \t max \t step \t validOrdinalsCsv`.

    The four flags are `1` or `0`; the three numbers are decimal and are ignored when `hasRange` is `0`; `validOrdinalsCsv` is empty when the accessory did not enumerate its values.

    A `traitId` this build does not know is skipped by the decoder rather than failing the row, so a newer port degrades gracefully.

    ###### Parameters

    - `accessoryId`: the accessory

    - `serviceId`: the service on it

    ###### Returns

    the encoded traits, never `null`

  - ### refresh

    void refresh(int requestId)

    Reloads the graph from the platform. Answers through `SmartHome.deliverRefreshed`; the synchronous getters above reflect the new graph once it has.

    ###### Parameters

    - `requestId`: the request to answer

  - ### getMaxReadBatchSize

    int getMaxReadBatchSize()

    The largest number of traits this backend will read in one call, or zero for no limit. The framework splits larger requests and recombines the answers.

    ###### Returns

    the batch limit, or zero

  - ### readTraits

    void readTraits(int requestId, String[] accessoryIds, String[] serviceIds, String[] traitIds, boolean allowCached)

    Reads traits. Answers through `SmartHome.deliverReadings`.

    The three arrays are positionally aligned and of equal length.

    ###### Parameters

    - `requestId`: the request to answer

    - `accessoryIds`: the accessories to read

    - `serviceIds`: the services on them

    - `traitIds`: the traits to read

    - `allowCached`: whether the platform may answer from its own cache

  - ### getMaxWriteBatchSize

    int getMaxWriteBatchSize()

    The largest number of traits this backend will write in one call, or zero for no limit.

    ###### Returns

    the batch limit, or zero

  - ### writeTraits

    void writeTraits(int requestId, String[] accessoryIds, String[] serviceIds, String[] traitIds, int[] kinds, double[] numericValues, String[] stringValues, int[] unitWireIds, String[] authorizationData)

    Writes traits. Answers through `SmartHome.deliverWriteResults`.

    All the arrays are positionally aligned and of equal length. Each value is carried in whichever of `numericValues` or `stringValues` suits its kind: a boolean as `1` or `0`, an int and an enum ordinal as themselves, a double with its unit in `unitWireIds`, a string in `stringValues` with the numeric slot ignored.

    ###### Parameters

    - `requestId`: the request to answer

    - `accessoryIds`: the accessories to write

    - `serviceIds`: the services on them

    - `traitIds`: the traits to set

    - `kinds`: the ordinal of each value's `com.codename1.home.TraitValueKind`

    - `numericValues`: the numeric component of each value

    - `stringValues`: the text component of each value, empty where none

    - `unitWireIds`: `com.codename1.home.TraitUnit#getWireId()` for each value

    - `authorizationData`: the credential each write needs -- a door-lock PIN -- empty where none. Positionally aligned like every other array rather than one value for the batch: a batch can hold two locks with different PINs, and a single slot would silently send one lock the other's credential. Must not be logged.

  - ### isPushDelivery

    boolean isPushDelivery()

    Whether this backend pushes trait changes without being asked.

    `true` only where the platform genuinely delivers while the app runs. A backend that answers `false` must still accept `subscribe(int, String, String[], String[], String[])` and gather changes for `drainChanges(int)`.

    ###### Returns

    `true` when changes arrive unsolicited

  - ### subscribe

    void subscribe(int requestId, String subscriptionId, String[] accessoryIds, String[] serviceIds, String[] traitIds)

    Starts watching traits. Changes arrive through `SmartHome.deliverChanges` carrying the same `subscriptionId`.

    Coalescing is not the bridge's job: the framework applies the caller's window before anything reaches the EDT, so a port should deliver what the platform gives it.

    ###### Parameters

    - `requestId`: the request to answer through `SmartHome.deliverSubscribed`

    - `subscriptionId`: the identifier to tag deliveries with

    - `accessoryIds`: the accessories to watch

    - `serviceIds`: the services on them

    - `traitIds`: the traits to watch

  - ### unsubscribe

    void unsubscribe(String subscriptionId)

    Stops watching and releases the platform registration. Idempotent, and silent about an identifier it does not know.

    ###### Parameters

    - `subscriptionId`: the subscription to end

  - ### drainChanges

    void drainChanges(int requestId)

    Hands over changes gathered since the last drain, through `SmartHome.deliverChanges` for each affected subscription, then answers `SmartHome.deliverDrained`.

    The only way changes arrive at all where `isPushDelivery()` is `false`.

    ###### Parameters

    - `requestId`: the request to answer

  - ### getScenes

    String[] getScenes(String structureId)

    The scenes of one home, one per entry: `id \t name \t typeOrdinal \t executable`.

    `typeOrdinal` indexes `com.codename1.home.SceneType`; `executable` is `1` or `0`.

    ###### Parameters

    - `structureId`: the home

    ###### Returns

    the encoded scenes, never `null`

  - ### getSceneActions

    String[] getSceneActions(String structureId, String sceneId)

    What one scene does, one action per entry: `accessoryId \t serviceId \t traitId \t kindOrdinal \t numericValue \t stringValue \t unitWireId`.

    Empty where the backend will run a scene but not enumerate it, which is a real answer rather than an empty scene.

    ###### Parameters

    - `structureId`: the home

    - `sceneId`: the scene

    ###### Returns

    the encoded actions, never `null`

  - ### executeScene

    void executeScene(int requestId, String structureId, String sceneId)

    Runs a scene. Answers through `SmartHome.deliverSceneResult`.

    ###### Parameters

    - `requestId`: the request to answer

    - `structureId`: the home

    - `sceneId`: the scene to run

  - ### createScene

    void createScene(int requestId, String structureId, String name, String[] accessoryIds, String[] serviceIds, String[] traitIds, int[] kinds, double[] numericValues, String[] stringValues, int[] unitWireIds)

    Creates a scene. Answers through `SmartHome.deliverSceneResult`, whose scene id is the new scene's.

    The value arrays are encoded exactly as in `writeTraits(int, String[], String[], String[], int[], double[], String[], int[], String[])`.

    ###### Parameters

    - `requestId`: the request to answer

    - `structureId`: the home to create it in

    - `name`: the scene's name

    - `accessoryIds`: the accessories the scene acts on

    - `serviceIds`: the services on them

    - `traitIds`: the traits to set

    - `kinds`: the ordinal of each value's kind

    - `numericValues`: the numeric component of each value

    - `stringValues`: the text component of each value

    - `unitWireIds`: the unit wire id of each value

  - ### deleteScene

    void deleteScene(int requestId, String structureId, String sceneId)

    Deletes a scene. Answers through `SmartHome.deliverSceneResult`.

    ###### Parameters

    - `requestId`: the request to answer

    - `structureId`: the home

    - `sceneId`: the scene to delete

  - ### getCommissioningStyle

    int getCommissioningStyle()

    How this backend adds a new accessory, as the ordinal of a `com.codename1.home.commissioning.CommissioningStyle` constant.

    ###### Returns

    the style ordinal

  - ### commission

    void commission(int requestId, String setupPayload, String structureId, String roomId, String suggestedName, int timeoutMillis)

    Adds a new Matter accessory. Answers through `SmartHome.deliverCommissioningResult`.

    ###### Parameters

    - `requestId`: the request to answer

    - `setupPayload`: the Matter onboarding payload, or empty to let the platform's own UI scan one

    - `structureId`: the home to add it to, or empty for the default

    - `roomId`: the room to add it to, or empty for none

    - `suggestedName`: a name to offer the user, or empty

    - `timeoutMillis`: how long to allow, or zero for the platform default

  - ### identify

    void identify(int requestId, String accessoryId)

    Asks an accessory to make itself known -- blink, beep. Answers through `SmartHome.deliverIdentifyResult`.

    ###### Parameters

    - `requestId`: the request to answer

    - `accessoryId`: the accessory to identify