Skip to content
Shiny.NET
Commercial SupportGuaranteed response times on Shiny bug fixes, straight from the maintainers. Plans from US$1,500 a year.See the plans

Hubs

NuGet package Shiny.AppDeviceBridge.Hubs

The hubs bridge lets the web app host Universal Hubs: real-time hubs that other devices join over Bluetooth LE, Wi-Fi (mDNS) and Multipeer, with methods, streams, pushes and groups. The app serves them on the bridge’s own HTTP server, but the hub’s logic lives in the downloaded web app. Every call a client makes reaches the web app as the native call hub:{name}: the page while it is open, otherwise background.js. So a hub’s behavior ships with a web app update, with no new app build.

Clients are ordinary Universal Hubs clients (AddUniversalHubClient<IGameHub>) on other devices. They can’t tell a web app hub from a compiled one.

Transport Platforms
Wi-Fi (mDNS) Every head
Bluetooth LE Android, iOS and Mac Catalyst (Universal Hubs registers the platform BLE hosting there); Windows and macOS once the app calls services.AddBluetoothLeHosting()
Multipeer Apple platforms, with Shiny.UniversalHubs.Multipeer in the app

Without BLE hosting (Windows or macOS without AddBluetoothLeHosting(), and Linux), AddHubsBridge registers a fallback that reports BLE hosting as unsupported, so starting a hub on All skips BLE and runs it over Wi-Fi and Multipeer instead of failing. A transport that can’t start (Bluetooth off, no network, a transport the platform lacks) is skipped as long as another one starts. When none does, start answers 503. A host without AddHubsBridge answers 501.

Terminal window
dotnet add package Shiny.AppDeviceBridge.Hubs
builder.UseAppDeviceBridge(
bridge => bridge.AddHubsBridge(server => server
.ServiceUuid("…") // optional - clients must use the same one
.AllowDynamicHubs(o => o.ServiceTypes.Add("_myapp._tcp"))), // the mDNS types web app hubs may use
webApp => { /* … */ }
);

configure is Universal Hubs’ own AddUniversalServer builder, so compiled hubs of the app’s own can sit beside the web app’s. The service types and the hub limit are fixed here, in the app, because the platforms fix them when the app is built: iOS lists every mDNS type in NSBonjourServices. See Dynamic hubs. The hubs share the bridge’s server and never start or stop it.

Client C# TypeScript
IHubsBridge AddHubsBridgeClient() (or AddWebAppHub<THub>(), which adds it) HubsBridge

The same as any Universal Hubs host:

  • iOS and macOS: list every allowed service type in NSBonjourServices (and, for Multipeer, its _x._tcp and _x._udp), and set NSLocalNetworkUsageDescription and NSBluetoothAlwaysUsageDescription.
  • Android: the BLE permissions, plus CHANGE_WIFI_MULTICAST_STATE for mDNS.
  • Wi-Fi clients reach the hubs only when the server listens beyond loopback (http.Options.Address = IPAddress.Any). See Security.

Derive from WebAppHub and map each method by the name the clients’ contract uses. Values are read and written through source-generated JSON metadata, so there’s no reflection:

public sealed class GameHub(GameEngine engine) : WebAppHub
{
protected override void Map(WebAppHubMethods methods) => methods
.Invoke("MakeMove", GameJson.Default.Int32, GameJson.Default.MoveResult, this.MakeMove)
.Invoke("Kick", GameJson.Default.String, reason => { this.Abort(reason); return Task.CompletedTask; })
.Stream("Watch", GameJson.Default.GameState, engine.Changes);
public override Task OnConnectedAsync(HubConnectionInfo connection)
=> engine.IsFull ? throw new HubException("GameFull", "The table is full") : Task.CompletedTask;
async Task<MoveResult> MakeMove(int cell)
{
if (!engine.IsTurn(this.Connection.Id))
throw new HubException("GameRule", "Not your turn"); // the client sees GameRule
var result = engine.Move(this.Connection.Id, cell);
await this.PushAsync("StateChanged", GameJson.Default.GameState, engine.State);
return result;
}
}
Program.cs
builder.Services
.AddWebAppHostClient()
.AddWebAppHub<GameHub>(new("game", "6e400010-b5a3-f393-e0a9-e50e24dcca9e", "_myapp._tcp") { MaxClients = 6 });
// once the page is up - every time it loads
var hubs = services.GetRequiredService<WebAppHubs>();
await hubs.DefineAsync();
await hubs.StartAsync("game");
Member
WebAppHubMethods Invoke with 0–2 typed arguments, with or without a result; Stream with 0–1; and raw JsonElement overloads for anything else
Connection The caller (HubConnectionInfo: Id, Transport, Name, AppVersion, Properties, ConnectedAt)
OnConnectedAsync, OnDisconnectedAsync, OnRenamedAsync Throw from OnConnectedAsync or OnRenamedAsync to refuse
Abort(reason) Ends the caller’s session once the reply is sent
PushAsync, AddToGroupAsync, RemoveFromGroupAsync, DisconnectAsync Pushes and groups for this hub; Bridge is the IHubsBridge for anything else
WebAppHubOptions Name, CharacteristicUuid, ServiceType, MaxClients (8), AllowTunnel (false)
WebAppHubs DefineAsync() defines every registered hub and takes its calls; StartAsync(name, transports), StopAsync(name, reason)

One instance serves every call, and calls can overlap, so keep per-caller state keyed by Connection.Id. WebAppHub takes its calls through IWebAppNativeCalls (in Shiny.AppDeviceBridge.Client), which the Blazor package’s WebAppNativeCalls implements.

A page without the C# client imports hostHub from the bridge. Each function is a method, an async generator is a stream, and the on… handlers are the lifecycle:

import { hostHub, HubError } from "/_bridge/hubs/client.js";
const game = await hostHub(
{ name: "game", characteristicUuid: "6e400010-b5a3-f393-e0a9-e50e24dcca9e", serviceType: "_myapp._tcp", maxClients: 6 },
{
async MakeMove(cell) {
if (!isTurn(this.connection.id)) throw new HubError("GameRule", "Not your turn");
return { accepted: true, cell };
},
async *Watch() { for await (const state of changes()) yield state; },
Kick(reason) { this.abort(reason); },
onConnected(connection) { if (full()) throw new HubError("GameFull", "The table is full"); },
onDisconnected(connection, reason, message) { },
});
await game.start(); // or start("Http"), …
await game.push("StateChanged", [state], { groups: ["red"] });

The handle also has stop, remove, connections, disconnect, addToGroup, removeFromGroup, group and off. A TypeScript page can use HubsBridge from @shinyorg/appdevicebridge for the same routes and answer the hub:{name} calls itself.

Each call is the native call hub:{name} carrying a HubCall, answered with a HubCallReply. WebAppHub and client.js do this for you; background.js answers the same way while no page is open:

background.js
appdevicebridge.on("hub:game", call => {
if (call.kind === "Invoke" && call.method === "Ping") return { result: "pong" };
return {};
});
kind Reply
Invoke { result }, or { error: { type, message } }. abort and abortReason end the caller’s session after the reply
Stream {} once it has started. Post each item to POST /_bridge/hubs/streams/{streamId}, then POST …/{streamId}/end (with an error or without). Both answer 410 once the caller has gone, and the hubs.stream event says so too
Connected {}, or an error to refuse the client
Disconnected {}. The client’s groups are still intact
Renamed {}, or an error to refuse the new name
  • Methods not in the definition are answered HubMethodNotFound without reaching the web app.
  • Errors keep their type. A HubError (JavaScript), HubException (C#) or { error: { type, message } } reaches the client as a BleHubRemoteException with that RemoteErrorType. Anything else carries its class name.
  • No page and no background.js handler: connections are refused and calls fail with HubUnavailable.
  • Pushes go to every client, or to a target’s connections and groups, less its except. Groups exist while they have members.

The page defines its hubs every time it loads. Defining with the same characteristic, service type, MaxClients and AllowTunnel keeps the hub and its clients; only the method list may change. Changing any of those replaces the hub, and its clients are disconnected. define answers 400 for a service type the app doesn’t allow, and 409 when the name or characteristic is taken or the app’s hub limit (MaxHubs, 6 by default) is reached.

Clients are plain Universal Hubs clients with a [BleHubClient] contract whose names match the hub’s methods and events:

builder.Services.AddUniversalHubClient<IGameHub>("6e400010-b5a3-f393-e0a9-e50e24dcca9e", "_myapp._tcp");

The web app can also join hubs on other devices, compiled or dynamic, with no contract compiled in, through Universal Hubs’ dynamic hub clients. Methods and events go by name, and values cross as JSON. What the clients share (the hosts’ BLE ServiceUuid, timeouts, Multipeer) is AddHubsBridge’s second parameter:

bridge.AddHubsBridge(
server => server.AllowDynamicHubs(o => o.ServiceTypes.Add("_myapp._tcp")),
clients => clients.Multipeer("myapp-mc"));
const hubs = new HubsBridge();
const client = await hubs.createClient({ characteristicUuid: "6e400010-…", serviceType: "_myapp._tcp" });
await hubs.onHost(host => { /* host.name, host.transports (None = gone), host.rssi */ });
await hubs.onPush(push => { /* push.clientId, push.event, push.arguments */ });
await hubs.discover(client.id, { transports: "All" });
await hubs.connect(client.id, { host: "Kitchen", name: "Allan", prefer: "Http", allowed: "All" });
const { result, error } = await hubs.invoke(client.id, { method: "Send", arguments: ["hi"] });
Route
POST clients A client for a hub: { characteristicUuid, serviceType }. At most 8 at once (409 too_many_clients)
POST clients/{id}/discover Looks on transports until stopped (DELETE), the client is removed, or nothing listens to hubs.client.host. Listen first, or it answers 409 not_listening
POST clients/{id}/connect host (a discovered host’s name, 404 if unseen) or url (Wi-Fi only), plus name, prefer, allowed and properties. A refusal answers 409 refused with the host’s reason
POST clients/{id}/invoke { method, arguments }. A hub’s own failure is the result’s error ({ type, message }), not an HTTP failure. 409 not_connected before connecting
POST clients/{id}/streams The same body; items and the end arrive as hubs.client.stream. DELETE clients/{id}/streams/{streamId} stops it
POST clients/{id}/disconnect, DELETE clients/{id} Disconnect, or disconnect and forget

Events: hubs.client.host (found, changed or gone), hubs.client.push, hubs.client.status (connected or disconnected, and why) and hubs.client.stream. IHubsBridge in C# and HubsBridge in TypeScript have every route. clients is a reserved hub name. The platform setup is the same as hosting, since discovery browses the same mDNS and Multipeer types.

The sample’s Hubs page (samples/Sample.Blazor/Pages/Hubs.razor, with ChatHub.cs) does both: it serves a chat hub on the transports you tick, and joins one by a discovered host (choosing the transports to look on, Prefer and Allowed) or by address. samples/Sample.App/SampleConfiguration.cs registers AddHubsBridge with Multipeer and binds the server to IPAddress.Any. In a debug build that also puts the bridges on the network, as the sample notes.

GET/_bridge/hubs#

Every hub the web app has defined.

C#IHubsBridge.GetHubsAsyncTSHubsBridge.getHubs
Response
200 HubInfo[]
HubInfo · 8 fields
namestring
characteristicUuidstring
serviceTypestring
methodsHubMethod[]
maxClientsnumber | null
allowTunnelboolean
runningTransportsHubTransportsWhere the hub is accepting clients right now.
connectionsnumberClients connected, over every transport.
PUT/_bridge/hubs#

Defines a hub, or updates its methods. Changing its characteristic, service type, client limit or tunnel setting replaces it, disconnecting its clients. 400 for a service type the app does not allow, 409 when its name or characteristic is taken or the app's hub limit is reached.

C#IHubsBridge.DefineAsyncTSHubsBridge.define
Body
application/json · HubDefinition
HubDefinition · 6 fields
namestringLetters, digits, -, _ and ., up to 64. Calls reach the web app as the native call hub:{name}.
characteristicUuidstringThe hub's BLE characteristic, also its HTTP path. Clients use the same one.
serviceTypestringThe mDNS service type, such as _myapp._tcp: one the app allows for web app hubs.
methodsHubMethod[]Every method clients may call. Anything else is answered as not found without reaching the web app.
maxClientsnumber | nullCounted across every transport; null for no limit.
allowTunnelbooleanLet clients reach the hub through a tunnel — the public internet.
Response
200 HubInfo
HubInfo · 8 fields
namestring
characteristicUuidstring
serviceTypestring
methodsHubMethod[]
maxClientsnumber | null
allowTunnelboolean
runningTransportsHubTransportsWhere the hub is accepting clients right now.
connectionsnumberClients connected, over every transport.
Errors
400Bad request409Conflict
DELETE/_bridge/hubs/{name}#

Stops a hub on every transport, telling its clients why, and forgets it. 404 when there is none.

C#IHubsBridge.RemoveAsyncTSHubsBridge.remove
ParameterInType
namepathstringrequired
reasonquerystring | nulloptional
Response
204 No content
Errors
404Not found
POST/_bridge/hubs/{name}/start#

Starts accepting clients. 503 when no transport could start — Bluetooth off and no network, say.

C#IHubsBridge.StartAsyncTSHubsBridge.start
ParameterInType
namepathstringrequired
Body
application/json · HubStartRequest
HubStartRequest · 1 field
transportsHubTransportsWhere to accept clients. One that cannot start here is skipped as long as another does.
Response
200 HubInfo
HubInfo · 8 fields
namestring
characteristicUuidstring
serviceTypestring
methodsHubMethod[]
maxClientsnumber | null
allowTunnelboolean
runningTransportsHubTransportsWhere the hub is accepting clients right now.
connectionsnumberClients connected, over every transport.
Errors
503Unavailable
POST/_bridge/hubs/{name}/stop#

Stops accepting clients on every transport; the connected ones are told why.

C#IHubsBridge.StopAsyncTSHubsBridge.stop
ParameterInType
namepathstringrequired
Body
application/json · HubStopRequest
HubStopRequest · 1 field
reasonstring | nullTold to every connected client.
Response
200 HubInfo
HubInfo · 8 fields
namestring
characteristicUuidstring
serviceTypestring
methodsHubMethod[]
maxClientsnumber | null
allowTunnelboolean
runningTransportsHubTransportsWhere the hub is accepting clients right now.
connectionsnumberClients connected, over every transport.
GET/_bridge/hubs/{name}/connections#

The clients connected right now, over every transport.

C#IHubsBridge.GetConnectionsAsyncTSHubsBridge.getConnections
ParameterInType
namepathstringrequired
Response
200 HubConnectionInfo[]
HubConnectionInfo · 6 fields
idstringThe connection id: what pushes, groups and disconnects name it by.
transportHubTransports
namestring | null
appVersionstring | null
propertiesRecord&lt;string, string&gt;The values the client sent when it connected.
connectedAtstring
DELETE/_bridge/hubs/{name}/connections/{connectionId}#

Ends a client's session, telling it why.

C#IHubsBridge.DisconnectAsyncTSHubsBridge.disconnect
ParameterInType
namepathstringrequired
connectionIdpathstringrequired
reasonquerystring | nulloptional
Response
204 No content
POST/_bridge/hubs/{name}/push#

Raises an event on the hub's clients — all of them, or a target's.

C#IHubsBridge.PushAsyncTSHubsBridge.push
ParameterInType
namepathstringrequired
Body
application/json · HubPushRequest
HubPushRequest · 3 fields
eventstringThe event name, exactly as the clients' contract spells it.
argumentsunknown[]Each argument as JSON.
targetHubPushTarget | null
Response
204 No content
GET/_bridge/hubs/{name}/groups/{group}#

The connection ids in a group.

C#IHubsBridge.GetGroupAsyncTSHubsBridge.getGroup
ParameterInType
namepathstringrequired
grouppathstringrequired
Response
200 string[]
PUT/_bridge/hubs/{name}/groups/{group}/{connectionId}#

Adds a connection to a group. Groups exist while they have members.

C#IHubsBridge.AddToGroupAsyncTSHubsBridge.addToGroup
ParameterInType
namepathstringrequired
grouppathstringrequired
connectionIdpathstringrequired
Response
204 No content
DELETE/_bridge/hubs/{name}/groups/{group}/{connectionId}#

C#IHubsBridge.RemoveFromGroupAsyncTSHubsBridge.removeFromGroup
ParameterInType
namepathstringrequired
grouppathstringrequired
connectionIdpathstringrequired
Response
204 No content
POST/_bridge/hubs/streams/{streamId}#

Sends a streaming call's next item. 410 once its caller has gone — stop sending.

C#IHubsBridge.SendStreamItemAsyncTSHubsBridge.sendStreamItem
ParameterInType
streamIdpathstringrequired
Body
application/json · unknown
Response
204 No content
Errors
410Gone
POST/_bridge/hubs/streams/{streamId}/end#

Ends a streaming call, with an error or without. 410 once its caller has gone.

C#IHubsBridge.EndStreamAsyncTSHubsBridge.endStream
ParameterInType
streamIdpathstringrequired
Body
application/json · HubStreamEnd
HubStreamEnd · 1 field
errorHubError | nullEnds the stream with an error after the items already sent.
Response
204 No content
Errors
410Gone
GET/_bridge/hubs/clients#

The clients created so far.

C#IHubsBridge.GetClientsAsyncTSHubsBridge.getClients
Response
200 HubClientInfo[]
HubClientInfo · 6 fields
idstring
characteristicUuidstring
serviceTypestring
statusHubClientStatus
transportHubTransportsHow it is connected now; None when it is not.
hostNamestring | nullThe host it is connected to.
POST/_bridge/hubs/clients#

A client for another device's hub. It finds hosts with discover and joins one with connect.

C#IHubsBridge.CreateClientAsyncTSHubsBridge.createClient
Body
application/json · HubClientRequest
HubClientRequest · 2 fields
characteristicUuidstring
serviceTypestringThe hub's mDNS service type, browsed for over Wi-Fi.
Response
200 HubClientInfo
HubClientInfo · 6 fields
idstring
characteristicUuidstring
serviceTypestring
statusHubClientStatus
transportHubTransportsHow it is connected now; None when it is not.
hostNamestring | nullThe host it is connected to.
DELETE/_bridge/hubs/clients/{clientId}#

Disconnects a client and forgets it.

C#IHubsBridge.RemoveClientAsyncTSHubsBridge.removeClient
ParameterInType
clientIdpathstringrequired
Response
204 No content
POST/_bridge/hubs/clients/{clientId}/discover#

Looks for hosts on the transports asked for; each arrives through onHost, which must be listened to first (409 not_listening). Runs until stopped, the client is removed, or nothing listens.

C#IHubsBridge.DiscoverAsyncTSHubsBridge.discover
ParameterInType
clientIdpathstringrequired
Body
application/json · HubDiscoverRequest
HubDiscoverRequest · 1 field
transportsHubTransportsWhere to look: BLE scanning, mDNS browsing, Multipeer.
Response
204 No content
Errors
409Conflict
DELETE/_bridge/hubs/clients/{clientId}/discover#

C#IHubsBridge.StopDiscoveringAsyncTSHubsBridge.stopDiscovering
ParameterInType
clientIdpathstringrequired
Response
204 No content
POST/_bridge/hubs/clients/{clientId}/connect#

Joins a host. 404 for a host discovery has not seen; 409 refused when the host refuses, with its reason.

C#IHubsBridge.ConnectAsyncTSHubsBridge.connect
ParameterInType
clientIdpathstringrequired
Body
application/json · HubConnectRequest
HubConnectRequest · 6 fields
hoststring | nullA host's name, as discovery reported it.
urlstring | nullOr a host's address — http://192.168.1.20:5780, a tunnel's public URL — reached over Wi-Fi only.
namestring | nullThe name this client goes by on the host.
preferHubTransportsTried first when the host is reachable more than one way; the rest follow as Wi-Fi, Multipeer, BLE.
allowedHubTransportsThe only transports that may be used.
propertiesRecord&lt;string, string&gt; | nullSent to the host in the handshake.
Response
200 HubClientInfo
HubClientInfo · 6 fields
idstring
characteristicUuidstring
serviceTypestring
statusHubClientStatus
transportHubTransportsHow it is connected now; None when it is not.
hostNamestring | nullThe host it is connected to.
Errors
404Not found409Conflict
POST/_bridge/hubs/clients/{clientId}/disconnect#

C#IHubsBridge.DisconnectClientAsyncTSHubsBridge.disconnectClient
ParameterInType
clientIdpathstringrequired
Response
200 HubClientInfo
HubClientInfo · 6 fields
idstring
characteristicUuidstring
serviceTypestring
statusHubClientStatus
transportHubTransportsHow it is connected now; None when it is not.
hostNamestring | nullThe host it is connected to.
POST/_bridge/hubs/clients/{clientId}/invoke#

Calls a hub method. A hub's own failure is the result's error; 409 not_connected before connecting.

C#IHubsBridge.InvokeAsyncTSHubsBridge.invoke
ParameterInType
clientIdpathstringrequired
Body
application/json · HubInvokeRequest
HubInvokeRequest · 2 fields
methodstringThe method name, exactly as the hub's contract spells it.
argumentsunknown[]Each argument as JSON.
Response
200 HubInvokeResult
HubInvokeResult · 2 fields
resultunknown | nullThe method's result; absent for a method with none.
errorHubError | nullThe hub failed the call: the error's type and message, as the hub gave them.
Errors
409Conflict
POST/_bridge/hubs/clients/{clientId}/streams#

Starts a streaming call; its items and its end arrive through onStreamItem.

C#IHubsBridge.StreamAsyncTSHubsBridge.stream
ParameterInType
clientIdpathstringrequired
Body
application/json · HubInvokeRequest
HubInvokeRequest · 2 fields
methodstringThe method name, exactly as the hub's contract spells it.
argumentsunknown[]Each argument as JSON.
Response
200 HubClientStream
HubClientStream · 1 field
streamIdstring
DELETE/_bridge/hubs/clients/{clientId}/streams/{streamId}#

Stops a streaming call early.

C#IHubsBridge.StopStreamAsyncTSHubsBridge.stopStream
ParameterInType
clientIdpathstringrequired
streamIdpathstringrequired
Response
204 No content
EVENThubs.stream#

A streaming call's caller went away, or its hub stopped.

C#IHubsBridge.OnStreamClosedAsyncTSHubsBridge.onStreamClosed
Payload
HubStreamClosed
streamIdstring
hubstring
EVENThubs.client.host#

A host was found, changed or went away.

C#IHubsBridge.OnHostAsyncTSHubsBridge.onHost
Payload
HubHostSeen
clientIdstring
namestring
hostIdstring | null
transportsHubTransportsHow the host can be reached.
rssinumber | nullIts BLE signal, when seen over BLE.
EVENThubs.client.push#

A host raised an event on one of the clients.

C#IHubsBridge.OnPushAsyncTSHubsBridge.onPush
Payload
HubClientPush
clientIdstring
eventstring
argumentsunknown[]
EVENThubs.client.stream#

A streaming call's next item, or its end.

C#IHubsBridge.OnStreamItemAsyncTSHubsBridge.onStreamItem
Payload
HubClientStreamItem
clientIdstring
streamIdstring
itemunknown | null
endboolean
errorHubError | null

JSON property names are camelCase and enums travel as their names. A ? marks a property the payload may omit;| null one that may be null.

HubInfoobject#
namestring
characteristicUuidstring
serviceTypestring
methodsHubMethod[]
maxClientsnumber | null
allowTunnelboolean
runningTransportsHubTransportsWhere the hub is accepting clients right now.
connectionsnumberClients connected, over every transport.
HubMethodobject#
namestringThe method name clients call, exactly as their contract spells it.
kindHubMethodKind
HubMethodKindenum#
"Invoke""Stream"
HubTransportsenum#

How hub clients reach this device. Flags: a hub can run on several at once.

"None""Ble""Http""Multipeer""All"
HubDefinitionobject#

A hub the web app serves. Defining it again with the same values changes nothing.

namestringLetters, digits, -, _ and ., up to 64. Calls reach the web app as the native call hub:{name}.
characteristicUuidstringThe hub's BLE characteristic, also its HTTP path. Clients use the same one.
serviceTypestringThe mDNS service type, such as _myapp._tcp: one the app allows for web app hubs.
methodsHubMethod[]Every method clients may call. Anything else is answered as not found without reaching the web app.
maxClients?number | nullCounted across every transport; null for no limit.
allowTunnel?booleanLet clients reach the hub through a tunnel — the public internet.
HubStartRequestobject#
transports?HubTransportsWhere to accept clients. One that cannot start here is skipped as long as another does.
HubStopRequestobject#
reason?string | nullTold to every connected client.
HubConnectionInfoobject#

A client connected to a hub.

idstringThe connection id: what pushes, groups and disconnects name it by.
transportHubTransports
namestring | null
appVersionstring | null
propertiesRecord&lt;string, string&gt;The values the client sent when it connected.
connectedAtstring
HubPushRequestobject#

Raises an event on the hub's clients.

eventstringThe event name, exactly as the clients' contract spells it.
argumentsunknown[]Each argument as JSON.
target?HubPushTarget | null
HubPushTargetobject#

Who a push goes to: everyone without a target, otherwise the connections and groups named, less except.

connections?string[] | null
groups?string[] | null
except?string[] | null
HubStreamEndobject#
error?HubError | nullEnds the stream with an error after the items already sent.
HubErrorobject#
typestringThe error's type, such as an exception's name. Clients see it with the message.
messagestring
HubClientInfoobject#
idstring
characteristicUuidstring
serviceTypestring
statusHubClientStatus
transportHubTransportsHow it is connected now; None when it is not.
hostNamestring | nullThe host it is connected to.
HubClientStatusenum#
"Disconnected""Connecting""Connected""Disconnecting"
HubClientRequestobject#

A client for the hub on characteristicUuid — this app joining another device's hub.

characteristicUuidstring
serviceTypestringThe hub's mDNS service type, browsed for over Wi-Fi.
HubDiscoverRequestobject#
transports?HubTransportsWhere to look: BLE scanning, mDNS browsing, Multipeer.
HubConnectRequestobject#

Connects to a host found by discovery, or one at an address.

host?string | nullA host's name, as discovery reported it.
url?string | nullOr a host's address — http://192.168.1.20:5780, a tunnel's public URL — reached over Wi-Fi only.
name?string | nullThe name this client goes by on the host.
prefer?HubTransportsTried first when the host is reachable more than one way; the rest follow as Wi-Fi, Multipeer, BLE.
allowed?HubTransportsThe only transports that may be used.
properties?Record&lt;string, string&gt; | nullSent to the host in the handshake.
HubInvokeRequestobject#
methodstringThe method name, exactly as the hub's contract spells it.
argumentsunknown[]Each argument as JSON.
HubInvokeResultobject#
resultunknown | nullThe method's result; absent for a method with none.
errorHubError | nullThe hub failed the call: the error's type and message, as the hub gave them.
HubClientStreamobject#
streamIdstring
HubStreamClosedobject#

A stream's caller went away or the hub stopped: stop sending its items.

streamIdstring
hubstring
HubHostSeenobject#

A host found, changed or gone (transports is None), merged across transports by name.

clientIdstring
namestring
hostIdstring | null
transportsHubTransportsHow the host can be reached.
rssinumber | nullIts BLE signal, when seen over BLE.
HubClientPushobject#

The host raised an event on this client.

clientIdstring
eventstring
argumentsunknown[]
HubDisconnectReasonenum#

Why a client left. The same value the client sees.

"ClientDisconnect""ClientTimeout""ServerDisconnect""ServerShutdown""ConnectionFailed"
HubClientStreamItemobject#

An item of a stream started with clients/{id}/streams, or its end.

clientIdstring
streamIdstring
itemunknown | null
endboolean
errorHubError | null