Constructor
new BrainClient(opts)
Create a new BrainClient.
Note this does not initate connection to the brain. Use BrainClient#connectToBrain to connect
(await
the promise, of course).
For more customization of the setup, you can use BrainClient#prepareConnection in order to bypass the setup in BrainClient#setupConnection and do your own setup.
Example
const bc1 = new BrainClient(); // default opts
const bc2 = new BrainClient({
reconnectWaitTime: 500 // change reconnect wait time to 500ms
});
Parameters
Options for configuring the client, all optional, documented below
Data structure from nebula-web-ui for Remote Control via cloud
Time to wait to try to reconnect a socket on disconnect or error in milliseconds (default to 1000
milliseconds)
Timeout value for requests internally to the Brain. If the Brain takes longer than this parameter, the request will fail with a timeout. Defaults to 1000
milliseconds.
Set to true to disable analytics collection via Google Analytics (defaults to false
)
Properties
Default port for Brain (8000
)
Classes
Methods
(static) getBrainClient(ipAddress, opts)
Static method to retrieve/create a BrainClient
instance. The ipAddress
is used as the cache key - if no client exists for that IP,
then a new one will be created and initalized. However, if an existing client is found, that client will be returned as-is.
The client is initalized using the BrainClient#connectToBrain method.
Note that this static method is intentionally designed to NOT be async - in otherwords, it is guaranteed to return a BrainClient instance right away. The BrainClient#connectToBrain method is NOT called right away (on a new instance) - it is delayed until the next clock tick. This is done so that callers can attach event listeners, for example, to cach communication failures on connection.
Example
const bc1 = BrainClient.getBrainClient('127.0.0.1:8000');
const bc2 = BrainClient.getBrainClient('127.0.0.1:8000');
console.log("Caching worked? ", (bc1 === bc2) ? true : false);
Auto mode
If you pass an object like { auto: true }
as the ipAddress
, BrainClient will check the window query string for brainIp=<whatever>
, and if not found, will use the origin host/port as brain IP.
If you pass an object like { auto: true, default: "some.host:8000" }
, BrainClient will still check the query string, but it will fallback to "some.host:8000" instead of the origin.
If you pass an object like { param: "someParam", default: "some.host:8000" }
, BrainClient will check for someParam=<whatever>
instead of "brainIp", and fallback to the value given in "default" if not found.
NOTE: Auto mode will not work server-side (e.g. from Node, etc) - it is designed specifically
for use client-side. If you try to use { auto: true }
or { param: ... }
on Node,
your program will likely fail with an exception.
In all cases, default is optional. If "auto" or "param" given and "default" not specified, it will fallback to the window origin (e.g. the host/port that the page using BrainClient was served from.) This "origin" mode is only really useful if you are taking advantage of the "bundle upload" mode in the Kramer UI of the SL brains to serve your custom javascript from the Brain's built-in webserver at the /bundle/
URL.
Parameters
IP and optional port to connect to. Example: 10.0.1.123:8000
. Note: If you pass an object like { auto: true, default: 'something' }
, BrainClient will check the window querystring for 'brainIp=default
param or origin host/port as brain IP if no default
param given. You can also specify param: "someOtherParam"
instead of auto: true
to use a different query string param other than "brainIp".
If true
, BrainClient will check the window query string for brainIp=<whatever>
, and if not found, will use the origin host/port as brain IP. Not supported server-side, only useful when using BrainClient in a browser.
BrainClient will use the param
value to check the query string for an IP address (this will set .auto
to true). Not supported server-side, only useful when using BrainClient in a browser.
If you use .auto
or .param
to turn on auto mode, and no IP is found in the query string, then BrainCient will fallback to .default
. If .default
is not given and .auto
or .param
is given, then BrainClient will instead fallback to the origin host/port serving the page. Not supported server-side, only useful when using BrainClient in a browser.
Options to pass to the BrainClient constructor. See the constructor for all options honored. However, one option the constructor doesn't consume is the pin
option, below.
PIN string or callback function to get PIN. Callback will only be executed if the Brain indicates a PIN is required. See BrainClient#setupConnection for more notes on the callback.
String containing a JWT token to authenticate with the brain instead of using a PIN code.
asObservable():Observable
Get an RxJS Observable object. This method is provided to simplify integration of BrainClient
into Angluar applications.
This observable is created using a Subject object, allowing the same event from this client to be multicast to any observers attached.
This observable will contain every event emitted by this client. For example, using event listeners, you might do:
bc.on(BrainClient.EVENTS.CONNECTION_STATUS_CHANGED, ({status}) => console.log("Status:", status));
bc.on(BrainClient.PIN_REQUIRED, () => bc.submitPin(prompt("PIN?")));
Using the Observable
returned from this method, you can instead do:
bc.asObservable().subscribe(({ event, ...data }) => {
switch(event) {
case BrainClient.EVENTS.CONNECTION_STATUS_CHANGED:
console.log("Status:", data.status);
break;
case BrainClient.EVENTS.PIN_REQUIRED:
bc.submitPin(prompt("PIN?"));
break;
default:
break;
}
})
The shape of the message emitted by the Observable from this method looks like:
const message = {
event: "",
...data
}
The event
field above is always and only one of the values from BrainClient.EVENTS.
The data
spread operator above indicates that all other fields from the event (e.g. the args
that would be passed to your event callback if you used the on
method to attach callbacks)
are spread into the message
, so you receive a single flat-ish object.
That means that the message
you would receive from the observable for the CONNECTION_STATUS_CHANGED
event would look like:
const message = {
event: BrainClient.EVENTS.CONNECTION_STATUS_CHANGED,
status: BrainClient.CONNECTION_ACTIVE // for example...
}
It is useful to note that you can listen for BrainClient.EVENTS.WS_MESSAGE
to receive ALL events (WebSocket messages) from the brain, unfiltered and unprocessed by the BrainClient
.
You can also listen for just BrainClient.EVENTS.BRAIN_EVENT
to listen only for events from the brain that are not handled internally by logic inside the BrainClient
.
Returns
- Type
- :Observable
RxJS Observable object - see RxJS Observable docs for API docs.
(async) brainId():string|null
Retrieve the ID of the connected brain. Promise returned will not resolve until brain is connected in some fashion.
Returns
- Type
- :string|null
Promise of a brainId or null
if BrainClient#connectToBrain or BrainClient#prepareConnection not called yet.
(async) brainInfo():BrainInfo
Get the brain information (the "general" API route)
Throws
- Type
- :Error
Throws an error if there is a problem talking to the brain
Returns
- Type
- :BrainInfo
A BrainInfo object describing the currently connected brain
(async) connectToBrain(ipAddress, pin, auth)
Connect the client to the brain. await
this function to ensure the connection is setup
before calling other methods. See BrainClient#setupConnection for further notes
on connection setup if this method is too opaque for your needs.
Example usage:
const bc = new BrainClient();
await bc.connectToBrain("127.0.0.1");
Parameters
IP address of Brain to connect to, with optional port, like "127.0.0.1:8000" - port defaults to 8000 if not specified
PIN string or callback function to get PIN. Callback will only be executed if the Brain indicates a PIN is required. See BrainClient#setupConnection for more notes on the callback.
Optional, JWT token to use to auth with brain instead of using the PIN
Throws
- Type
- :Error
May throw errors from BrainClient#setupConnection - see that method for Errors that could be thrown.
disconnect()
Disconnect the WebSocket, if connected, closing all communication with the brain.
getConnectionStatus():string
Get the current connection status of the Brain Client. For possible states, please see BrainClient.CONNECTION.
When the connection status of the client changes, the event BrainClient.EVENTS.CONNECTION_STATUS_CHANGED
will be emitted by the client as well.
Returns
- Type
- :string
One of the possible states enumerated in BrainClient.CONNECTION
(async) getDevice(deviceNameOrId):BrainDevice|null
Retrieve a BrainDevice based on name or ID of the device
Parameters
Name or ID of the device to retrieve
Returns
- Type
- :BrainDevice|null
Returns BrainDevice instance if deviceNameOrId
found, or null
if no matching device found.
(async) getDevices():object|null
Return a hash of deviceId
=> BrainDevice
instances for this Brain's devices, allowing you to retrieve/watch states
and execute commands.
Returns
- Type
- :object|null
Returns hash with keys being deviceId
s and values being BrainDevice instances, or null
if BrainClient#connectToBrain or BrainClient#prepareConnection not called yet.
getHandsetLayout(handsetId)
Get the layout for a specific handset from the brain and notify the Brain of the selected handset.
NOTE: Response to this query is returned as a separate event via the WebSocket
Parameters
ID of the handset to requeset
(async) getSystemDevice():BrainDevice|null
Find and return the BrainDevice
instance for this Brain's System Device, which will provide states and commands for things like time, weather, and custom states created in the KC Builder.
Returns
- Type
- :BrainDevice|null
BrainDevice instance for the System device on the Brain, or null
if not found or null
if BrainClient#connectToBrain or BrainClient#prepareConnection not called yet.
(async) isAuthorized():boolean
Returns a flag indicating if the client has cleanly authorized with the Brain in order to communicate with this space.
Returns
- Type
- :boolean
Promised true
/false
indicating if the client has completed authorization or null
if BrainClient#connectToBrain or BrainClient#prepareConnection not called yet.
(async) isExpressModeEnabled():boolean
Returns a flag indicating if express mode has been enabled in the Manager for the space provisioned to this Brain.
NOTE: Without Express Mode enabled, the client will not be able to control this space via the WebSocket. However, some basic REST APIs will still work to retrieve information about the space.
Returns
- Type
- :boolean
Promised true
/false
indicating if express mode has been enabled or null
if BrainClient#connectToBrain or BrainClient#prepareConnection not called yet.
(async) isLoginNeeded():boolean
Returns a flag indicating if authentication is required for this space.
Use BrainClient#submitPin to send PIN to the Brain, then await
BrainClient#isAuthorized to be notified when BrainClient
ready for use. You can also listen for BrainClient.EVENTS.AUTHORIZED
instead of await
ing isAuthorized
.
NOTE: You can also be notified of the need for a PIN by listening for the BrainClient.EVENTS.PIN_REQUIRED
event. See BrainClient.EVENTS for discussion of that event.
Returns
- Type
- :boolean
Promised true
/false
indicating if the Brain requires a PIN or null
if BrainClient#connectToBrain or BrainClient#prepareConnection not called yet.
(async) isProvisioned():boolean
Returns a flag indicating if any space has been provisioned to the brain. Without a space provisioned to the brain, there is nothing to control.
Returns
- Type
- :boolean
Promised true
/false
indicating if the Brain has been provisioned or null
if BrainClient#connectToBrain or BrainClient#prepareConnection not called yet.
off(event, callback)
Remove an event attached with BrainClient#on. Inherited from the core node module EventEmitter - see that class for more complete on
/off
documentation. Included here for documentation purposes and to link to BrainClient.EVENTS for event names.
Parameters
Name of the event to disconnect from. See BrainClient.EVENTS for defined event names availale on BrainClient
previously-attached callback
on(event, callback)
Attach listeners to events. Inherited from the core node module EventEmitter - see that class for more complete on
/off
documentation. Included here for documentation purposes and to link to BrainClient.EVENTS for event names.
Remove event listeners with BrainClient#off
Parameters
Name of the event to listen to. See BrainClient.EVENTS for defined event names availale on BrainClient
Your callback to call when the event is triggered
(async) prepareConnection(ipAddress):Promise
Prepare the BrainClient
to connect to a brain by setting up REST client and WebSocket connections.
You usually will not need to call this. Instead, we recommend await
ing BrainClient#connectToBrain instead. However, if you wish to reimplement BrainClient#setupConnection (which connectToBrain
uses internally to bootstrap the client), then you should NOT call connectToBrain
. Instead, create your client and call prepareConnection
then implement whatever connection steps you want to use.
NOTE: You can/should await
this method if you call it to ensure the Brain connection works. This method WILL throw an Error
of undetermined type if there is a problem connecting with the Brain.
Example usage:
const bc = new BrainClient();
await bc.prepareConnection("10.0.1.138:8000");
if(await bc.isLoginNeeded()) {
const pin = prompt("Please enter your PIN to connect to the Brain")
bc.submitPin(pin);
}
await bc.isAuthorized();
const sys = bc.getSystemDevice();
// ...
Parameters
IP with optional port specified
Throws
- Type
- :Error
Error if trouble connecting to Brain specified
Returns
- Type
- :Promise
Promise that will resolve once the WebSocket is connected
queryExpressModeEnabled()
Query to see if express mode is enabled.
For more a user-friendly interface to this information, see BrainClient#isExpressModeEnabled.
NOTE: Response to this query is returned as a separate event via the WebSocket
queryHandsets()
Query handsets from the brain
NOTE: Response to this query is returned as a separate event via the WebSocket
queryProvisionedInfo()
Request the brain's provisioning status.
For more a user-friendly interface to this information, see BrainClient#isProvisioned.
NOTE: Response to this query is returned as a separate event via the WebSocket
queryStatus()
Request the brain's gateway status.
For more a user-friendly interface to similar information, see BrainClient#brainInfo and BrainInfo.
NOTE: Response to this query is returned as a separate event via the WebSocket
sendAction()
Send a UI action from the handset layout to the Brain. This function deals with prebuilt layouts from the Builder.
NOTE: To send actions/commands from specific devices, see BrainDevice.
sendData(data)
Send the string or object over the WebSocket to the brain as-is, no checking/changes.
Parameters
String or JSON object to send to the Brain
sendRemoteAuthorization(auth)
Send a prebuilt authorization structure to the Brain
Parameters
(async) setupConnection(pin):BrainInfo
This method promise
s to return only when the client is completely
setup and free of any obvious error states, such is not being
provisioned or not having express mode enabled.
It's important to note that consumers of BrainClient can implement all the checks/steps of this setup routine themselves - for example, to prompt for a PIN code interactively.
However, note that you CAN supply a function as the pin
argument,
which will be used as a callback if the brain requires a non-blank
PIN. This function will be await
ed. That means you could use still
this method in a UI and simply provide a callback arg to pop up a
dialog, for example.
A creative user of BrainClient
could decide to not use setupConnection
at all, and instead implement each of the steps that setupConnection
does
in their own code.
setupConnection
does not use any private data,
it just reuses accessors from BrainClient
and packages them
in the form of an easy-to-use and simple await
able method. setupConnection
will work for the majority of users that use BrainClient
as-is.
However, if you find yourself needing more control over the init process
of the connection, just call BrainClient#prepareConnection after constructing your
BrainClient
instance and then setup the connection however you would like.
Parameters
Express mode PIN code, only needed if not left blank in KC Manager. NOTE: an async
function can be supplied for the pin
instead of a string, which will only be called if the pin is actually required for connection.
Throws
- Type
- :Error
Throws BrainClient.ErrorNotProvisioned, BrainClient.ErrorExpressModeDisabled, or BrainClient.ErrorClientNotInitalized.
Returns
- Type
- :BrainInfo
An object describing the current brain. See BrainInfo for fields.
submitAuthorization(authorization)
Send the Authorization token to the brain
Once you submit the token, you can await
BrainClient#isAuthorized or listen for BrainClient.EVENTS.AUTHORIZED
to be notified when the authorization succeeeds.
If the token submitted fails, the BrainClient.EVENTS.PIN_REQUIRED
event will be emitted again, but the connection status will not change.
NOTE: Response returned as a separate event via the WebSocket
Parameters
submitPin(pin)
Send the PIN to the brain
Once you submit the pin, you can await
BrainClient#isAuthorized or listen for BrainClient.EVENTS.AUTHORIZED
to be notified when the authorization succeeeds.
If the pin submitted fails, the BrainClient.EVENTS.PIN_REQUIRED
event will be emitted again, but the connection status will not change.
NOTE: Response returned as a separate event via the WebSocket
Parameters
watchStates(device_id, states, unwatch)
Inform the Brain that this client wants to receive notifications of changes to a device's states via the WebSocket.
NOTE: This function is not designed for direct user access, although you can call if it desired, no ill side effects.
However, a more user-friendly way of watching for state changes would be to get the BrainDevice instance you want to work with and calling BrainDevice#on, for example:
device.on(BrainDevice.STATE_CHANGED, myCallback)
When you attach a listener to the STATE_CHANGED
event, BrainDevice#on will automatically notify the Brain to send state changes using this method.
Parameters
Required, device ID of the device on the Brain to watch
Optional array of states, currently unused in the latest Brain software versions
[unwatch=false] Defaults to false. If true, client will tell the brain to unsubscribe this client from state changes for the given device.
Type Definitions
CONNECTION
The BrainClient.CONNECTION_*
properties define the various connection states that the BrainClient
can be in. To get the current connection state, see BrainClient#getConnectionStatus. You cannot directly
set the Brain Client's connectionStatus
.
Example usage:
const bc = new BrainClient();
const state = bc.getConnectionStatus();
Properties
- Client starts in this state and goes to this state when it's reconnecting
- Client encountered a failure in communication, either on initial connection or lost connection to the Brain
- Client has become disconnected from the Brain, either via BrainClient#disconnect or due to network issues
- Client has become disconnected and now is waiting to try to reconnect. The time the client waits to reconnect can be set by passing the
reconnectWaitTime
option to the BrainClient's constructor
- Client has connected to the Brain and is attempting to authorize the connection. NOTE: The client will attempt to authorize using an empty passcode first, and that may succeeed. If that succeeds, the client will go to
BrainClient.CONNECTION_ACTIVE
. However, if an empty passcode does not succeed, the client will transition toCONNECTION_UNAUTHORIZED
and the client will emit the eventBrainClient.EVENTS.PIN_REQUIRED
. In that case, you will need to supply the passcode to the client to use using BrainClient#submitPin. Once it succeeds, the client will transition toCONNECTION_ACTIVE
. If the pin submitted fails, theBrainClient.EVENTS.PIN_REQUIRED
event will be emitted again, but the connection status will not change.
- If the client's default empty passcode attempt fails or if the PIN you submit via
submitPin()
fails, the client will transition toCONNECTION_UNAUTHORIZED
until something else happens.
- Once the client is online, authorized, and ready to use, it will transition to this state.
- When you "Publish" a space via the KC Builder or make changes via the KC Manager, or the Brain synchronizes for some other reason, the client will enter this
CONNECTION_SYNCHRONIZING
state
EVENTS
The BrainClient.EVENTS
object holds keys that function as the event names
for various events emitted by the BrainClient.
It's important to note
that BrainDevice also emits it's own events when states change. See: BrainDevice and STATE_CHANGED
property.
Use these properties below in conjunction with BrainClient#on to attach listeners.
Example usage:
const bc = new BrainClient();
bc.on(BrainClient.EVENTS.STATUS_MESSAGE, data => console.log(data));
Properties
Emitted when the Brain's WebSocket connects
Emitted when the Brain's WebSocket is closed
Emitted when reconnecting timer is started, indicating the client will soon attempt to automatically reconnect
Emitted when the BrainClient is informed by the Brain that a PIN is required. The BrainClient will have already tried the default "empty" PIN (""
) when this event is emitted. Use BrainClient#submitPin to submit the PIN to the Brain. You can then await
BrainClient#isAuthorized (or listen for the AUTHORIZED
event). An alternative to listening for the PIN_REQUIRED
event is to await
BrainClient#isLoginNeeded and then call BrainClient#submitPin if isLoginNeeded
resolves to true
.
Emitted when the client receives the response from the Brain indicating if express mode is enabled or not. The payload provided an object with a single boolean key, enabled
. A value of true
for enabled
indicates that express mode IS enabled, and false
, of course, indicating that express mode is disabled on the provisioned space.
Emitted when BrainClient is completely authorized and ready to be used.
Emitted when the Brain's connection status changed. The current connection state will be included in the event payload as an object with a single key status
, like: { status: "" }
. The current connection status can retrieved from the client via BrainClient#getConnectionStatus. See BrainClient.CONNECTION for documentation on the connection states possible - these are the values that will be used for the status
field of the event payload mentioned previously.
Emitted when any of the handset_*
events are received from the Brain, for example, in response to BrainClient#queryHandsets or BrainClient#getHandsetLayout.
Emitted when an event is received by the brain that is NOT handled internally by the BrainClient. This is ONLY emitted for events NOT covered elsewhere in this list.
Emitted when a new WebSocket message is received from the brain with the contents of the message as the payload. Note that this event is emitted for EVERY WebSocket message containing the raw message, making this a good generic event if you want to handle ALL interaction with the brain directly.
Emitted when a new status message is received from the Brain
Emitted when a Brain color message is received