{"id":13588859,"url":"https://github.com/home-assistant/home-assistant-js-websocket","last_synced_at":"2025-05-14T19:09:50.299Z","repository":{"id":13686130,"uuid":"74852367","full_name":"home-assistant/home-assistant-js-websocket","owner":"home-assistant","description":":aerial_tramway: JavaScript websocket client for Home Assistant","archived":false,"fork":false,"pushed_at":"2025-04-29T11:43:34.000Z","size":2267,"stargazers_count":326,"open_issues_count":14,"forks_count":92,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-05-10T10:36:32.859Z","etag":null,"topics":["home-assistant","home-automation","internet-of-things","javascript","websocket"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/home-assistant.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"custom":"https://www.openhomefoundation.org"}},"created_at":"2016-11-26T21:48:25.000Z","updated_at":"2025-04-29T11:43:30.000Z","dependencies_parsed_at":"2023-11-28T03:27:35.282Z","dependency_job_id":"7624c1ce-dad7-48fc-b9f5-904b440f5212","html_url":"https://github.com/home-assistant/home-assistant-js-websocket","commit_stats":{"total_commits":567,"total_committers":24,"mean_commits":23.625,"dds":0.4991181657848325,"last_synced_commit":"ffa945270303b753721828f377278a63cbbab4c5"},"previous_names":[],"tags_count":82,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/home-assistant%2Fhome-assistant-js-websocket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/home-assistant%2Fhome-assistant-js-websocket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/home-assistant%2Fhome-assistant-js-websocket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/home-assistant%2Fhome-assistant-js-websocket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/home-assistant","download_url":"https://codeload.github.com/home-assistant/home-assistant-js-websocket/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254209859,"owners_count":22032897,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["home-assistant","home-automation","internet-of-things","javascript","websocket"],"created_at":"2024-08-01T15:06:59.489Z","updated_at":"2025-05-14T19:09:48.599Z","avatar_url":"https://github.com/home-assistant.png","language":"TypeScript","funding_links":["https://www.openhomefoundation.org"],"categories":["TypeScript"],"sub_categories":[],"readme":"# :aerial_tramway: JavaScript websocket client for Home Assistant\n\nThis is a websocket client written in JavaScript that allows retrieving authentication tokens and communicate with the Home Assistant websocket API. It can be used to integrate Home Assistant into your apps. It has 0 dependencies.\n\n## Trying it out\n\nCheck [the demo](https://hass-auth-demo.glitch.me/). The repository also includes an [example client](https://github.com/home-assistant/home-assistant-js-websocket/blob/master/example.html):\n\nClone this repository, then go to home-assistant-js-websocket folder and run the following commands:\n\n```bash\nyarn install\nyarn build\nnpx http-server -o\n# A browser will open, navigate to example.html\n```\n\n## Installation\n\n```bash\n# With npm\nnpm i home-assistant-js-websocket\n\n# With yarn\nyarn add home-assistant-js-websocket\n```\n\n## Usage\n\nTo initialize a connection, you need an authentication token for the instance that you want to connect to. This library implements the necessary steps to guide the user to authenticate your website with their Home Assistant instance and give you a token. All you need from the user is the url of their instance.\n\n```js\n// Example connect code\nimport {\n  getAuth,\n  createConnection,\n  subscribeEntities,\n  ERR_HASS_HOST_REQUIRED,\n} from \"home-assistant-js-websocket\";\n\nasync function connect() {\n  let auth;\n  try {\n    // Try to pick up authentication after user logs in\n    auth = await getAuth();\n  } catch (err) {\n    if (err === ERR_HASS_HOST_REQUIRED) {\n      const hassUrl = prompt(\n        \"What host to connect to?\",\n        \"http://localhost:8123\",\n      );\n      // Redirect user to log in on their instance\n      auth = await getAuth({ hassUrl });\n    } else {\n      alert(`Unknown error: ${err}`);\n      return;\n    }\n  }\n  const connection = await createConnection({ auth });\n  subscribeEntities(connection, (ent) =\u003e console.log(ent));\n}\n\nconnect();\n```\n\n### `getAuth()`\n\nUse this method to get authentication from a server via OAuth2. This method will handle redirecting to an instance and fetching the token after the user successful logs in.\n\nYou can pass options using the syntax:\n\n```js\ngetAuth({ hassUrl: \"http://localhost:8123\" });\n```\n\n| Option            | Description                                                                                                                                                                                              |\n| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| hassUrl           | The url where the Home Assistant instance can be reached. This option is needed so we know where to redirect the user for authentication. Once redirected back, it is not needed to pass this option in. |\n| clientId          | Client ID to use. Client IDs for Home Assistant is the url of your application. Defaults to domain of current page. Pass `null` if you are making requests on behalf of a system user.                   |\n| redirectUrl       | The url to redirect back to when the user has logged in. Defaults to current page.                                                                                                                       |\n| saveTokens        | Function to store an object containing the token information.                                                                                                                                            |\n| loadTokens        | Function that returns a promise that resolves to previously stored token information object or undefined if no info available.                                                                           |\n| authCode          | If you have an auth code received via other means, you can pass it in and it will be used to fetch tokens instead of going through the OAuth2 flow.                                                      |\n| limitHassInstance | If set to true, allow only authentication credentials for the passed in `hassUrl` and `clientId`. Defaults to false.                                                                                     |\n\nIn certain instances `getAuth` will raise an error. These errors can be imported from the package:\n\n```js\n// When bundling your application\nimport {\n  ERR_HASS_HOST_REQUIRED,\n  ERR_INVALID_AUTH,\n} from \"home-assistant-js-websocket\";\n\n// When using the UMD build\nHAWS.ERR_HASS_HOST_REQUIRED;\n```\n\n| Error                       | Description                                                                                                                                                                                                                                                                                                                                             |\n| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `ERR_HASS_HOST_REQUIRED`    | You need to pass in `hassUrl` to `getAuth` to continue getting auth. This option is not needed when the user is redirected back after successfully logging in.                                                                                                                                                                                          |\n| `ERR_INVALID_AUTH`          | This error will be raised if the url contains an authorization code that is no longer valid.                                                                                                                                                                                                                                                            |\n| `ERR_INVALID_HTTPS_TO_HTTP` | This error is raised if your code is being run from a secure context (hosted via https) and you're trying to fetch tokens from a Home Assistant instance via a non secure context (http). This is called [mixed active content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content#Mixed_active_content) and the browser forbids this. |\n| `ERR_INVALID_AUTH_CALLBACK` | This error is raised if only credentials for the specified Home Assistant instance are allowed and the client ID or hassURL in the auth callback state do not match the expected ones.                                                                                                                                                                  |\n| Other errors                | Unknown error!                                                                                                                                                                                                                                                                                                                                          |\n\n### `createConnection()`\n\nYou need to either provide `auth` or `createSocket` as options to createConnection:\n\n```js\ncreateConnection({ auth });\n```\n\n| Option       | Description                                                                                                                                    |\n| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |\n| auth         | Auth object to use to create a connection.                                                                                                     |\n| createSocket | Override the createSocket method with your own. `(options) =\u003e Promise\u003cWebSocket\u003e`. Needs to return a connection that is already authenticated. |\n| setupRetry   | Number of times to retry initial connection when it fails. Set to -1 for infinite retries. Default is 0 (no retries)                           |\n\nCurrently the following error codes can be raised by createConnection:\n\n| Error              | Description                                               |\n| ------------------ | --------------------------------------------------------- |\n| ERR_CANNOT_CONNECT | If the client was unable to connect to the websocket API. |\n| ERR_INVALID_AUTH   | If the supplied authentication was invalid.               |\n\nYou can import them into your code as follows:\n\n```javascript\nimport {\n  ERR_CANNOT_CONNECT,\n  ERR_INVALID_AUTH,\n} from \"home-assistant-js-websocket\";\n```\n\n### Automatic reconnecting\n\nThe connection object will automatically try to reconnect to the server when the connection gets lost. On reconnect, it will automatically resubscribe the event listeners.\n\n#### Suspend reconnection\n\nIf you don't want to automatically try to reconnect to the server when the connection is lost, you can pass a promise to wait for. The connection will try to reconnect after the promise is resolved.\n\n```javascript\nconnection.suspendReconnectUntil(\n  new Promise((resolve) =\u003e {\n    // When you want to try to reconnect again, resolve the promise.\n    resolve();\n  }),\n);\n```\n\nWhen the suspend promise resolves until the connection is re-established, all messages being send will be delayed until the connection is established. If the first reconnect fails, the queued messages will be rejected.\n\n#### Suspend connection\n\nYou can also actively close the connection and wait for a promise to resolve to reconnect again. This promise can be passed either with `suspendReconnectUntil` or with the `suspend` command itself.\n\nIf you don't provide a promise with either of these functions, an error will be thrown.\n\n```javascript\nconnection.suspendReconnectUntil(\n  new Promise((resolve) =\u003e {\n    // When you want to try to reconnect again, resolve the promise.\n    resolve();\n  }),\n);\nconnection.suspend();\n```\n\nor\n\n```javascript\nconnection.suspend(\n  new Promise((resolve) =\u003e {\n    // When you want to try to reconnect again, resolve the promise.\n    resolve();\n  }),\n);\n```\n\n#### Close connection\n\nYou can also close the connection, without any reconnect, with `connection.close()`.\n\n#### Events\n\nThe `Connection` object implements three events related to the reconnecting logic.\n\n| Event           | Data       | Description                                                                                              |\n| --------------- | ---------- | -------------------------------------------------------------------------------------------------------- |\n| ready           | -          | Fired when authentication is successful and the connection is ready to take commands.                    |\n| disconnected    | -          | Fired when the connection is lost.                                                                       |\n| reconnect-error | Error code | Fired when we encounter a fatal error when trying to reconnect. Currently limited to `ERR_INVALID_AUTH`. |\n\nYou can attach and remove listeners as follows:\n\n```javascript\nfunction eventHandler(connection, data) {\n  console.log(\"Connection has been established again\");\n}\n\nconn.addEventListener(\"ready\", eventHandler);\nconn.removeEventListener(\"ready\", eventHandler);\n```\n\n### Entities\n\nYou can subscribe to the entities of Home Assistant. Your callback will be called when the entities are first loaded and on every change to the state of any of the entities after that. The callback will be called with a single object that contains the entities keyed by entity_id.\n\nThe function `subscribeEntities` will return an unsubscribe function.\n\n```javascript\nimport { subscribeEntities } from \"home-assistant-js-websocket\";\n\n// conn is the connection from earlier.\nsubscribeEntities(conn, (entities) =\u003e console.log(\"New entities!\", entities));\n```\n\nYou can also import the collection:\n\n```javascript\nimport { entitiesColl } from \"home-assistant-js-websocket\";\n\n// conn is the connection from earlier.\nconst coll = entitiesColl(connection);\nconsole.log(coll.state);\nawait coll.refresh();\ncoll.subscribe((entities) =\u003e console.log(entities));\n```\n\n### Config\n\nYou can subscribe to the config of Home Assistant. Config can change when either a component gets loaded.\n\nThe function `subscribeConfig` will return an unsubscribe function.\n\n```javascript\nimport { subscribeConfig } from \"home-assistant-js-websocket\";\n\n// conn is the connection from earlier.\nsubscribeConfig(conn, (config) =\u003e console.log(\"New config!\", config));\n```\n\nYou can also import the collection:\n\n```javascript\nimport { configColl } from \"home-assistant-js-websocket\";\n\n// conn is the connection from earlier.\nconst coll = configColl(connection);\nconsole.log(coll.state);\nawait coll.refresh();\ncoll.subscribe((config) =\u003e console.log(config));\n```\n\n### Services\n\nYou can subscribe to the available services of Home Assistant. Services can change when a new service gets registered or removed.\n\nThe function `subscribeServices` will return an unsubscribe function.\n\n```javascript\nimport { subscribeServices } from \"home-assistant-js-websocket\";\n\n// conn is the connection from earlier.\nsubscribeServices(conn, (services) =\u003e console.log(\"New services!\", services));\n```\n\nYou can also import the collection:\n\n```javascript\nimport { servicesColl } from \"home-assistant-js-websocket\";\n\n// conn is the connection from earlier.\nconst coll = servicesColl(connection);\nconsole.log(coll.state);\nawait coll.refresh();\ncoll.subscribe((services) =\u003e console.log(services));\n```\n\n### Collections\n\nBesides entities, config and services you might want to create your own collections. A collection has the following features:\n\n- Fetch a full data set on initial creation and on reconnect\n- Subscribe to events to keep collection up to date\n- Share subscription between multiple listeners\n- Unsubscribe when no listeners\n- Manually trigger a refresh\n\n```typescript\n// Will only initialize one collection per connection.\ngetCollection\u003cState\u003e(\n  conn: Connection,\n  key: string,\n  fetchCollection: (conn: Connection) =\u003e Promise\u003cState\u003e,\n  subscribeUpdates: (\n    conn: Connection,\n    store: Store\u003cState\u003e\n  ) =\u003e Promise\u003cUnsubscribeFunc\u003e,\n): Collection\u003cState\u003e\n\n// Returns object with following type\nclass Collection\u003cState\u003e {\n  state: State;\n  async refresh(): Promise\u003cvoid\u003e;\n  subscribe(subscriber: (state: State) =\u003e void): UnsubscribeFunc;\n}\n```\n\n- `conn` is the connection to subscribe to.\n- `key` a unique key for the collection\n- `fetchCollection` needs to return a Promsise that resolves to the full state\n- `subscribeUpdates` needs to subscribe to the updates and update the store. Returns a promise that resolves to an unsubscribe function.\n\n#### Collection Example\n\n```javascript\nimport { getCollection } from \"home-assistant-js-websocket\";\n\nfunction panelRegistered(state, event) {\n  // Returning null means no change.\n  if (state === undefined) return null;\n\n  // This will be merged with the existing state.\n  return {\n    panels: state.panels.concat(event.data.panel),\n  };\n}\n\nconst fetchPanels = (conn) =\u003e conn.sendMessagePromise({ type: \"get_panels\" });\nconst subscribeUpdates = (conn, store) =\u003e\n  conn.subscribeEvents(store.action(panelRegistered), \"panel_registered\");\n\nconst panelsColl = getCollection(conn, \"_pnl\", fetchPanels, subscribeUpdates);\n\n// Now use collection\nconsole.log(panelsColl.state);\nawait panelsColl.refresh();\npanelsColl.subscribe((panels) =\u003e console.log(\"New panels!\", panels));\n```\n\nCollections are useful to define if data is needed for initial data load. You can create a collection and have code on your page call it before you start rendering the UI. By the time UI is loaded, the data will be available to use.\n\n## Connection API Reference\n\nA connection object is obtained by calling [`createConnection()`](#createconnection).\n\n##### `conn.haVersion`\n\nString containing the current version of Home Assistant. Examples:\n\n- `0.107.0`\n- `0.107.0b1`\n- `0.107.0.dev0`\n- `2021.3.0`\n\n##### `conn.subscribeEvents(eventCallback[, eventType])`\n\nSubscribe to all or specific events on the Home Assistant bus. Calls `eventCallback` for each event that gets received.\n\nReturns a promise that will resolve to a function that will cancel the subscription once called.\n\nSubscription will be automatically re-established after a reconnect.\n\nUses `conn.subscribeMessage` under the hood.\n\n##### `conn.addEventListener(eventType, listener)`\n\nListen for events on the connection. [See docs.](#automatic-reconnecting)\n\n##### `conn.sendMessagePromise(message)`\n\nSend a message to the server. Returns a promise that resolves or rejects based on the result of the server. Special case rejection is `ERR_CONNECTION_LOST` if the connection is lost while the command is in progress.\n\n##### `conn.subscribeMessage(callback, subscribeMessage[, options])`\n\nCall an endpoint in Home Assistant that creates a subscription. Calls `callback` for each item that gets received.\n\nReturns a promise that will resolve to a function that will cancel the subscription once called.\n\nSubscription will be automatically re-established after a reconnect unless `options.resubscribe` is false.\n\n| Option      | Description                                     |\n| ----------- | ----------------------------------------------- |\n| resubscribe | Re-established a subscription after a reconnect |\n\n## Auth API Reference\n\nAn instance of Auth is returned from the `getAuth` method. It has the following properties:\n\n- `wsUrl`: the websocket url of the instance\n- `accessToken`: the access token\n- `expired`: boolean that indicates if the access token has expired\n\n##### `auth.refreshAccessToken()`\n\nFetches a new access token from the server.\n\n##### `auth.revoke()`\n\nMakes a request to the server to revoke the refresh and all related access token. Returns a promise that resolves when the request is finished.\n\n**Note:** If you support storing and retrieving tokens, the returned auth object might load tokens from your cache that are no longer valid. If this happens, the promise returned by `createConnection` will reject with `ERR_INVALID_AUTH`. If that happens, clear your tokens with `storeTokens(null`) and call `getAuth` again. This will pick up the auth flow without relying on stored tokens.\n\n## Error Reference\n\n| Error constant            | Error number |\n| ------------------------- | ------------ |\n| ERR_CANNOT_CONNECT        | 1            |\n| ERR_INVALID_AUTH          | 2            |\n| ERR_CONNECTION_LOST       | 3            |\n| ERR_HASS_HOST_REQUIRED    | 4            |\n| ERR_INVALID_HTTPS_TO_HTTP | 5            |\n\n## Other methods\n\nThe library also contains a few helper method that you can use to ineract with the API.\n\n- `getUser(connection) -\u003e Promise\u003cHassUser\u003e`\n- `callService(connection, domain, service, serviceData?, target?) -\u003e Promise` (Support for `target` was added in Home Assistant Core 2021.3)\n\nThe following are also available, but it's recommended that you use the subscribe methods documented above.\n\n- `getStates(connection) -\u003e Promise\u003cHassEntity[]\u003e`\n- `getServices(connection) -\u003e Promise\u003cHassEntity[]\u003e`\n- `getConfig(connection) -\u003e Promise\u003cHassEntity[]\u003e`\n\n## Using this with long-lived access tokens\n\nIf you are in a browser, you should prefer to use the `getAuth()` flow. This will use the more secure refresh/access token pair. If that is not possible, you can ask the user to create a long-lived access token.\n\nYou will need to create your own auth object if you want to use this library with a long-lived access token.\n\n```js\nimport {\n  Auth,\n  createConnection,\n  subscribeEntities,\n  createLongLivedTokenAuth,\n} from \"home-assistant-js-websocket\";\n\n(async () =\u003e {\n  const auth = createLongLivedTokenAuth(\n    \"http://localhost:8123\",\n    \"YOUR ACCESS TOKEN\",\n  );\n\n  const connection = await createConnection({ auth });\n  subscribeEntities(connection, (entities) =\u003e console.log(entities));\n})();\n```\n\n## Using this in NodeJS\n\nNodeJS does not have a WebSocket client built-in, but there are some good ones on NPM. We recommend ws. The easiest way to enable WebSocket is to polyfill it into the global namespace.\nLook at https://github.com/keesschollaart81/vscode-home-assistant/blob/master/src/language-service/src/home-assistant/socket.ts as an example using ws.\n\nIf using TypeScript, you will need to install `@types/ws` as well.\n\n```js\nglobalThis.WebSocket = require(\"ws\");\n```\n\nor in TypeScript:\n\n```ts\nconst wnd = globalThis;\nwnd.WebSocket = require(\"ws\");\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhome-assistant%2Fhome-assistant-js-websocket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhome-assistant%2Fhome-assistant-js-websocket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhome-assistant%2Fhome-assistant-js-websocket/lists"}