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 TypeMethodDescriptionbooleanWhether accessory and structure identifiers survive an app restart.voidcommission(int requestId, String setupPayload, String structureId, String roomId, String suggestedName, int timeoutMillis) Adds a new Matter accessory.voidcreateScene(int requestId, String structureId, String name, String[] accessoryIds, String[] serviceIds, String[] traitIds, int[] kinds, double[] numericValues, String[] stringValues, int[] unitWireIds) Creates a scene.voiddeleteScene(int requestId, String structureId, String sceneId) Deletes a scene.voiddrainChanges(int requestId) Hands over changes gathered since the last drain, throughSmartHome.deliverChangesfor each affected subscription, then answersSmartHome.deliverDrained.voidexecuteScene(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.intThe current authorization, as the ordinal of acom.codename1.home.HomeAuthorizationStatusconstant.intThe current availability, as the ordinal of acom.codename1.home.HomeAvailabilityconstant.Which backend this is:"homekit","google_home","matter_only"or"local".intHow this backend adds a new accessory, as the ordinal of acom.codename1.home.commissioning.CommissioningStyleconstant.String[]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.intThe largest number of traits this backend will read in one call, or zero for no limit.intThe largest number of traits this backend will write in one call, or zero for no limit.String[]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[]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[]The homes, one per entry:id \t name \t primary \t owner \t sceneAuthoring, where the three flags are1or0.String[]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[]The zones of one home, one per entry:id \t name \t roomId,roomId,....voidAsks an accessory to make itself known -- blink, beep.booleanWhether this backend pushes trait changes without being asked.booleanWhether this bridge can do anything at all.booleanOpens the platform's ecosystem app -- Apple Home, Google Home -- so the user can set up a home or add an accessory there.booleanOpens the system settings page where the user can change this app's smart-home access.booleanOpens wherever the user installs or updates the backend's provider -- Google Play services on Android.voidreadTraits(int requestId, String[] accessoryIds, String[] serviceIds, String[] traitIds, boolean allowCached) Reads traits.voidrefresh(int requestId) Reloads the graph from the platform.voidrequestAuthorization(int requestId) Prompts the user for access.voidstart(int requestId) Connects to the backend and loads the graph.voidstop()Disconnects, releases every platform registration, and drops any pending request without answering it.voidsubscribe(int requestId, String subscriptionId, String[] accessoryIds, String[] serviceIds, String[] traitIds) Starts watching traits.voidunsubscribe(String subscriptionId) Stops watching and releases the platform registration.voidwriteTraits(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
falsehere rather than failing every later call.Returns
truewhen the backend is present -
getAvailability
int getAvailability()The current availability, as the ordinal of a
com.codename1.home.HomeAvailabilityconstant.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.HomeConfigurationExceptioncarries, 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
truewhen 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.HomeAuthorizationStatusconstant.Returns
the status ordinal
-
requestAuthorization
void requestAuthorization(int requestId) Prompts the user for access. Answers through
SmartHome.deliverAuthorizationwhen 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
truewhen 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
truewhen the app was opened;falsewhen it is not installed -
openProviderSetup
boolean openProviderSetup()Opens wherever the user installs or updates the backend's provider -- Google Play services on Android.
Returns
truewhen something was opened -
getStructures
String[] getStructures()The homes, one per entry:
id \t name \t primary \t owner \t sceneAuthoring, where the three flags are1or0.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
-
getZones
-
getAccessories
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.roomIdandbridgeAccessoryIdare empty when absent;reachableis1or0;categoryOrdinalindexescom.codename1.home.AccessoryCategory.Parameters
structureId: the home
Returns
the encoded accessories, never
null -
getServices
-
getTraits
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
1or0; the three numbers are decimal and are ignored whenhasRangeis0;validOrdinalsCsvis empty when the accessory did not enumerate its values.A
traitIdthis 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
numericValuesorstringValuessuits its kind: a boolean as1or0, an int and an enum ordinal as themselves, a double with its unit inunitWireIds, a string instringValueswith 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'scom.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.
trueonly where the platform genuinely delivers while the app runs. A backend that answersfalsemust still acceptsubscribe(int, String, String[], String[], String[])and gather changes fordrainChanges(int).Returns
truewhen changes arrive unsolicited -
subscribe
void subscribe(int requestId, String subscriptionId, String[] accessoryIds, String[] serviceIds, String[] traitIds) Starts watching traits. Changes arrive through
SmartHome.deliverChangescarrying the samesubscriptionId.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 throughSmartHome.deliverSubscribed -
subscriptionId: the identifier to tag deliveries with -
accessoryIds: the accessories to watch -
serviceIds: the services on them -
traitIds: the traits to watch
-
-
unsubscribe
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.deliverChangesfor each affected subscription, then answersSmartHome.deliverDrained.The only way changes arrive at all where
isPushDelivery()isfalse.Parameters
requestId: the request to answer
-
getScenes
-
getSceneActions
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
-
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
-
getCommissioningStyle
int getCommissioningStyle()How this backend adds a new accessory, as the ordinal of a
com.codename1.home.commissioning.CommissioningStyleconstant.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
Asks an accessory to make itself known -- blink, beep. Answers through
SmartHome.deliverIdentifyResult.Parameters
-
requestId: the request to answer -
accessoryId: the accessory to identify
-
-