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.

Methods

public abstract boolean isSupported()Whether this bridge can do anything at all.
public abstract int getAvailability()The current availability, as the ordinal of a com.codename1.home.HomeAvailability constant.
public abstract String getBackendId()Which backend this is: "homekit", "google_home", "matter_only" or "local".
public abstract 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.
public abstract boolean areIdsPersistent()Whether accessory and structure identifiers survive an app restart.
public abstract void start(int requestId)Connects to the backend and loads the graph.
public abstract void stop()Disconnects, releases every platform registration, and drops any pending request without answering it.
public abstract int getAuthorizationStatus()The current authorization, as the ordinal of a com.codename1.home.HomeAuthorizationStatus constant.
public abstract void requestAuthorization(int requestId)Prompts the user for access.
public abstract boolean openHomeSettings()Opens the system settings page where the user can change this app’s smart-home access.
public abstract 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.
public abstract boolean openProviderSetup()Opens wherever the user installs or updates the backend’s provider – Google Play services on Android.
public abstract String[] getStructures()The homes, one per entry: id \t name \t primary \t owner \t sceneAuthoring, where the three flags are 1 or 0.
public abstract String[] getRooms(String structureId)The rooms of one home, one per entry: id \t name.
public abstract String[] getZones(String structureId)The zones of one home, one per entry: id \t name \t roomId,roomId,....
public abstract 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.
public abstract String[] getServices(String accessoryId)The services of one accessory, one per entry: id \t name \t serviceTypeOrdinal \t primary.
public abstract 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.
public abstract void refresh(int requestId)Reloads the graph from the platform.
public abstract int getMaxReadBatchSize()The largest number of traits this backend will read in one call, or zero for no limit.
public abstract void readTraits(int requestId, String[] accessoryIds, String[] serviceIds, String[] traitIds, boolean allowCached)Reads traits.
public abstract int getMaxWriteBatchSize()The largest number of traits this backend will write in one call, or zero for no limit.
public abstract void writeTraits(int requestId, String[] accessoryIds, String[] serviceIds, String[] traitIds, int[] kinds, double[] numericValues, String[] stringValues, int[] unitWireIds, String[] authorizationData)Writes traits.
public abstract boolean isPushDelivery()Whether this backend pushes trait changes without being asked.
public abstract void subscribe(int requestId, String subscriptionId, String[] accessoryIds, String[] serviceIds, String[] traitIds)Starts watching traits.
public abstract void unsubscribe(String subscriptionId)Stops watching and releases the platform registration.
public abstract void drainChanges(int requestId)Hands over changes gathered since the last drain, through SmartHome.deliverChanges for each affected subscription, then answers SmartHome.deliverDrained.
public abstract String[] getScenes(String structureId)The scenes of one home, one per entry: id \t name \t typeOrdinal \t executable.
public abstract 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.
public abstract void executeScene(int requestId, String structureId, String sceneId)Runs a scene.
public abstract 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.
public abstract void deleteScene(int requestId, String structureId, String sceneId)Deletes a scene.
public abstract int getCommissioningStyle()How this backend adds a new accessory, as the ordinal of a com.codename1.home.commissioning.CommissioningStyle constant.
public abstract void commission(int requestId, String setupPayload, String structureId, String roomId, String suggestedName, int timeoutMillis)Adds a new Matter accessory.
public abstract void identify(int requestId, String accessoryId)Asks an accessory to make itself known – blink, beep.

Method details

isSupported

public abstract 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

public abstract 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

public abstract String getBackendId()
Which backend this is: "homekit", "google_home", "matter_only" or "local".

Returns

the backend token, never null

getConfigurationProblems

public abstract 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

public abstract 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

public abstract void start(int requestId)
Connects to the backend and loads the graph. Answers through SmartHome.deliverStarted.

Parameters

requestId int
the request to answer

stop

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

getAuthorizationStatus

public abstract int getAuthorizationStatus()
The current authorization, as the ordinal of a com.codename1.home.HomeAuthorizationStatus constant.

Returns

the status ordinal

requestAuthorization

public abstract void requestAuthorization(int requestId)
Prompts the user for access. Answers through SmartHome.deliverAuthorization when the flow finishes, whatever the user chose.

Parameters

requestId int
the request to answer

openHomeSettings

public abstract 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

public abstract 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

public abstract 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

public abstract 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

public abstract String[] getRooms(String structureId)
The rooms of one home, one per entry: id \t name.

Parameters

structureId String
the home

Returns

the encoded rooms, never null

getZones

public abstract 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 String
the home

Returns

the encoded zones, never null

getAccessories

public abstract 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 String
the home

Returns

the encoded accessories, never null

getServices

public abstract 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 String
the accessory

Returns

the encoded services, never null

getTraits

public abstract 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 String
the accessory
serviceId String
the service on it

Returns

the encoded traits, never null

refresh

public abstract 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 int
the request to answer

getMaxReadBatchSize

public abstract 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

public abstract 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 int
the request to answer
accessoryIds String[]
the accessories to read
serviceIds String[]
the services on them
traitIds String[]
the traits to read
allowCached boolean
whether the platform may answer from its own cache

getMaxWriteBatchSize

public abstract 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

public abstract 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 int
the request to answer
accessoryIds String[]
the accessories to write
serviceIds String[]
the services on them
traitIds String[]
the traits to set
kinds int[]
the ordinal of each value’s com.codename1.home.TraitValueKind
numericValues double[]
the numeric component of each value
stringValues String[]
the text component of each value, empty where none
unitWireIds int[]
com.codename1.home.TraitUnit#getWireId() for each value
authorizationData String[]
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

public abstract 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 and gather changes for drainChanges(int).

Returns

true when changes arrive unsolicited

subscribe

public abstract 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 int
the request to answer through SmartHome.deliverSubscribed
subscriptionId String
the identifier to tag deliveries with
accessoryIds String[]
the accessories to watch
serviceIds String[]
the services on them
traitIds String[]
the traits to watch

unsubscribe

public abstract void unsubscribe(String subscriptionId)
Stops watching and releases the platform registration. Idempotent, and silent about an identifier it does not know.

Parameters

subscriptionId String
the subscription to end

drainChanges

public abstract 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 int
the request to answer

getScenes

public abstract 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 String
the home

Returns

the encoded scenes, never null

getSceneActions

public abstract 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 String
the home
sceneId String
the scene

Returns

the encoded actions, never null

executeScene

public abstract void executeScene(int requestId, String structureId, String sceneId)
Runs a scene. Answers through SmartHome.deliverSceneResult.

Parameters

requestId int
the request to answer
structureId String
the home
sceneId String
the scene to run

createScene

public abstract 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.

Parameters

requestId int
the request to answer
structureId String
the home to create it in
name String
the scene’s name
accessoryIds String[]
the accessories the scene acts on
serviceIds String[]
the services on them
traitIds String[]
the traits to set
kinds int[]
the ordinal of each value’s kind
numericValues double[]
the numeric component of each value
stringValues String[]
the text component of each value
unitWireIds int[]
the unit wire id of each value

deleteScene

public abstract void deleteScene(int requestId, String structureId, String sceneId)
Deletes a scene. Answers through SmartHome.deliverSceneResult.

Parameters

requestId int
the request to answer
structureId String
the home
sceneId String
the scene to delete

getCommissioningStyle

public abstract 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

public abstract 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 int
the request to answer
setupPayload String
the Matter onboarding payload, or empty to let the platform’s own UI scan one
structureId String
the home to add it to, or empty for the default
roomId String
the room to add it to, or empty for none
suggestedName String
a name to offer the user, or empty
timeoutMillis int
how long to allow, or zero for the platform default

identify

public abstract void identify(int requestId, String accessoryId)
Asks an accessory to make itself known – blink, beep. Answers through SmartHome.deliverIdentifyResult.

Parameters

requestId int
the request to answer
accessoryId String
the accessory to identify