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
Method details
isSupported
public abstract boolean isSupported()false here rather than failing every later call.Returns
true when the backend is presentgetAvailability
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
getBackendId
public abstract String getBackendId()"homekit", "google_home", "matter_only" or
"local".Returns
nullgetConfigurationProblems
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
nullareIdsPersistent
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 launchesstart
public abstract void start(int requestId)SmartHome.deliverStarted.Parameters
requestIdint- the request to answer
stop
public abstract void stop()getAuthorizationStatus
public abstract int getAuthorizationStatus()com.codename1.home.HomeAuthorizationStatus constant.Returns
requestAuthorization
public abstract void requestAuthorization(int requestId)SmartHome.deliverAuthorization when the flow finishes, whatever the
user chose.Parameters
requestIdint- the request to answer
openHomeSettings
public abstract boolean openHomeSettings()Returns
true when something was openedopenEcosystemApp
public abstract boolean openEcosystemApp()Returns
true when the app was opened; false when it is not installedopenProviderSetup
public abstract boolean openProviderSetup()Returns
true when something was openedgetStructures
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
nullgetRooms
public abstract String[] getRooms(String structureId)id \t name.Parameters
structureIdString- the home
Returns
nullgetZones
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
structureIdString- the home
Returns
nullgetAccessories
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
structureIdString- the home
Returns
nullgetServices
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
accessoryIdString- the accessory
Returns
nullgetTraits
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
accessoryIdString- the accessory
serviceIdString- the service on it
Returns
nullrefresh
public abstract void refresh(int requestId)SmartHome.deliverRefreshed; the synchronous getters above reflect the
new graph once it has.Parameters
requestIdint- the request to answer
getMaxReadBatchSize
public abstract int getMaxReadBatchSize()Returns
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
requestIdint- the request to answer
accessoryIdsString[]- the accessories to read
serviceIdsString[]- the services on them
traitIdsString[]- the traits to read
allowCachedboolean- whether the platform may answer from its own cache
getMaxWriteBatchSize
public abstract int getMaxWriteBatchSize()Returns
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
requestIdint- the request to answer
accessoryIdsString[]- the accessories to write
serviceIdsString[]- the services on them
traitIdsString[]- the traits to set
kindsint[]- the ordinal of each value’s
com.codename1.home.TraitValueKind numericValuesdouble[]- the numeric component of each value
stringValuesString[]- the text component of each value, empty where none
unitWireIdsint[]com.codename1.home.TraitUnit#getWireId()for each valueauthorizationDataString[]- 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 unsolicitedsubscribe
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
requestIdint- the request to answer through
SmartHome.deliverSubscribed subscriptionIdString- the identifier to tag deliveries with
accessoryIdsString[]- the accessories to watch
serviceIdsString[]- the services on them
traitIdsString[]- the traits to watch
unsubscribe
public abstract void unsubscribe(String subscriptionId)Parameters
subscriptionIdString- 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
requestIdint- 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
structureIdString- the home
Returns
nullgetSceneActions
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
structureIdString- the home
sceneIdString- the scene
Returns
nullexecuteScene
public abstract void executeScene(int requestId, String structureId, String sceneId)SmartHome.deliverSceneResult.Parameters
requestIdint- the request to answer
structureIdString- the home
sceneIdString- 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
requestIdint- the request to answer
structureIdString- the home to create it in
nameString- the scene’s name
accessoryIdsString[]- the accessories the scene acts on
serviceIdsString[]- the services on them
traitIdsString[]- the traits to set
kindsint[]- the ordinal of each value’s kind
numericValuesdouble[]- the numeric component of each value
stringValuesString[]- the text component of each value
unitWireIdsint[]- the unit wire id of each value
deleteScene
public abstract void deleteScene(int requestId, String structureId, String sceneId)SmartHome.deliverSceneResult.Parameters
requestIdint- the request to answer
structureIdString- the home
sceneIdString- the scene to delete
getCommissioningStyle
public abstract int getCommissioningStyle()com.codename1.home.commissioning.CommissioningStyle constant.Returns
commission
public abstract void commission(int requestId, String setupPayload, String structureId, String roomId, String suggestedName, int timeoutMillis)SmartHome.deliverCommissioningResult.Parameters
requestIdint- the request to answer
setupPayloadString- the Matter onboarding payload, or empty to let the platform’s own UI scan one
structureIdString- the home to add it to, or empty for the default
roomIdString- the room to add it to, or empty for none
suggestedNameString- a name to offer the user, or empty
timeoutMillisint- how long to allow, or zero for the platform default
identify
public abstract void identify(int requestId, String accessoryId)SmartHome.deliverIdentifyResult.Parameters
requestIdint- the request to answer
accessoryIdString- the accessory to identify