home-assistant-js-websocket
Advanced tools
Comparing version 2.0.1 to 3.0.0-rc2
@@ -1,1 +0,2 @@ | ||
function auth(a){return{type:'auth',api_password:a}}function authAccessToken(a){return{type:'auth',access_token:a}}function states(){return{type:'get_states'}}function config(){return{type:'get_config'}}function services(){return{type:'get_services'}}function panels(){return{type:'get_panels'}}function callService(a,b,c){var d={type:'call_service',domain:a,service:b};return c&&(d.service_data=c),d}function subscribeEvents(a){var b={type:'subscribe_events'};return a&&(b.event_type=a),b}function unsubscribeEvents(a){return{type:'unsubscribe_events',subscription:a}}function ping(){return{type:'ping'}}function error(a,b){return{type:'result',success:!1,error:{code:a,message:b}}}var ERR_CANNOT_CONNECT=1,ERR_INVALID_AUTH=2,ERR_CONNECTION_LOST=3,MSG_TYPE_AUTH_REQUIRED='auth_required',MSG_TYPE_AUTH_INVALID='auth_invalid',MSG_TYPE_AUTH_OK='auth_ok',MSG_TYPE_EVENT='event',MSG_TYPE_RESULT='result',MSG_TYPE_PONG='pong';function getSocket(a,b){function c(d,e,f){var g=new WebSocket(a),h=!1,i=function(){if(g.removeEventListener('close',i),h)return void f(ERR_INVALID_AUTH);if(0===d)return void f(ERR_CANNOT_CONNECT);var a=-1===d?-1:d-1;setTimeout(function(){return c(a,e,f)},1e3)},j=function(a){var c=JSON.parse(a.data);switch(c.type){case MSG_TYPE_AUTH_REQUIRED:b.authToken?g.send(JSON.stringify(auth(b.authToken))):b.accessToken?g.send(JSON.stringify(authAccessToken(b.accessToken))):(h=!0,g.close());break;case MSG_TYPE_AUTH_INVALID:h=!0,g.close();break;case MSG_TYPE_AUTH_OK:g.removeEventListener('message',j),g.removeEventListener('close',i),g.removeEventListener('error',i),e(g);break;default:}};g.addEventListener('message',j),g.addEventListener('close',i),g.addEventListener('error',i)}return new Promise(function(a,d){return c(b.setupRetry||0,a,d)})}function extractResult(a){return a.result}var Connection=function(a,b){this.url=a,this.options=b||{},this.commandId=1,this.commands={},this.eventListeners={},this.closeRequested=!1,this._handleMessage=this._handleMessage.bind(this),this._handleClose=this._handleClose.bind(this)};Connection.prototype.setSocket=function(a){var b=this,c=this.socket;if(this.socket=a,a.addEventListener('message',this._handleMessage),a.addEventListener('close',this._handleClose),c){var d=this.commands;this.commandId=1,this.commands={},Object.keys(d).forEach(function(a){var c=d[a];c.eventType&&b.subscribeEvents(c.eventCallback,c.eventType).then(function(a){c.unsubscribe=a})}),this.fireEvent('ready')}},Connection.prototype.addEventListener=function(a,b){var c=this.eventListeners[a];c||(c=this.eventListeners[a]=[]),c.push(b)},Connection.prototype.removeEventListener=function(a,b){var c=this.eventListeners[a];if(c){var d=c.indexOf(b);-1!==d&&c.splice(d,1)}},Connection.prototype.fireEvent=function(a,b){var c=this;(this.eventListeners[a]||[]).forEach(function(a){return a(c,b)})},Connection.prototype.close=function(){this.closeRequested=!0,this.socket.close()},Connection.prototype.getStates=function(){return this.sendMessagePromise(states()).then(extractResult)},Connection.prototype.getServices=function(){return this.sendMessagePromise(services()).then(extractResult)},Connection.prototype.getPanels=function(){return this.sendMessagePromise(panels()).then(extractResult)},Connection.prototype.getConfig=function(){return this.sendMessagePromise(config()).then(extractResult)},Connection.prototype.callService=function(a,b,c){return this.sendMessagePromise(callService(a,b,c))},Connection.prototype.subscribeEvents=function(a,b){var c=this;return this.sendMessagePromise(subscribeEvents(b)).then(function(d){var e={eventCallback:a,eventType:b,unsubscribe:function(){return c.sendMessagePromise(unsubscribeEvents(d.id)).then(function(){delete c.commands[d.id]})}};return c.commands[d.id]=e,function(){return e.unsubscribe()}})},Connection.prototype.ping=function(){return this.sendMessagePromise(ping())},Connection.prototype.sendMessage=function(a){this.socket.send(JSON.stringify(a))},Connection.prototype.sendMessagePromise=function(a){var b=this;return new Promise(function(c,d){b.commandId+=1;var e=b.commandId;a.id=e,b.commands[e]={resolve:c,reject:d},b.sendMessage(a)})},Connection.prototype._handleMessage=function(a){var b=JSON.parse(a.data);switch(b.type){case MSG_TYPE_EVENT:this.commands[b.id].eventCallback(b.event);break;case MSG_TYPE_RESULT:b.success?this.commands[b.id].resolve(b):this.commands[b.id].reject(b.error),delete this.commands[b.id];break;case MSG_TYPE_PONG:break;default:}},Connection.prototype._handleClose=function(){var a=this;if(Object.keys(this.commands).forEach(function(b){var c=a.commands[b],d=c.reject;d&&d(error(ERR_CONNECTION_LOST,'Connection lost'))}),!this.closeRequested){this.fireEvent('disconnected');var b=Object.assign({},this.options,{setupRetry:0}),c=function(d){setTimeout(function(){getSocket(a.url,b).then(function(b){return a.setSocket(b)},function(b){return b===ERR_INVALID_AUTH?a.fireEvent('reconnect-error',b):c(d+1)})},1e3*Math.min(d,5))};c(0)}};function createConnection(a,b){return void 0===b&&(b={}),getSocket(a,b).then(function(c){var d=new Connection(a,b);return d.setSocket(c),d})}function subscribeConfig(a,b){return a._subscribeConfig?a._subscribeConfig(b):new Promise(function(c,d){var e=null,f=null,g=[],h=null;b&&g.push(b);var i=function(a){e=Object.assign({},e,a);for(var b=0;b<g.length;b++)g[b](e)},j=function(a,b){var c;return i({services:Object.assign({},e.services,(c={},c[a]=b,c))})},k=function(a){if(null!==e){var b=Object.assign({},e.core,{components:e.core.components.concat(a.data.component)});i({core:b})}},l=function(a){var b;if(null!==e){var c=a.data,d=c.domain,f=c.service,g=Object.assign({},e.services[d]||{},(b={},b[f]={description:'',fields:{}},b));j(d,g)}},m=function(a){if(null!==e){var b=a.data,c=b.domain,d=b.service,f=e.services[c];if(f&&d in f){var g={};Object.keys(f).forEach(function(a){a!==d&&(g[a]=f[a])}),j(c,g)}}},n=function(){return Promise.all([a.getConfig(),a.getPanels(),a.getServices()]).then(function(a){var b=a[0],c=a[1],d=a[2];i({core:b,panels:c,services:d})})},o=function(a){a&&g.splice(g.indexOf(a),1),0===g.length&&f()};a._subscribeConfig=function(a){return a&&(g.push(a),null!==e&&a(e)),h.then(function(){return function(){return o(a)}})},h=Promise.all([a.subscribeEvents(k,'component_loaded'),a.subscribeEvents(l,'service_registered'),a.subscribeEvents(m,'service_removed'),n()]),h.then(function(d){var e=d[0],g=d[1],h=d[2];f=function(){a.removeEventListener('ready',n),e(),g(),h()},a.addEventListener('ready',n),c(function(){return o(b)})},function(){return d()})})}function getEntities(a){for(var b,c={},d=0;d<a.length;d++)b=a[d],c[b.entity_id]=b;return c}function updateState(a,b){var c=Object.assign({},a);return c[b.entity_id]=b,c}function removeState(a,b){var c=Object.assign({},a);return delete c[b],c}function subscribeEntities(a,b){return a._subscribeEntities?a._subscribeEntities(b):new Promise(function(c,d){function e(a){if(null!==h){var b=a.data,c=b.entity_id,d=b.new_state;h=d?updateState(h,d):removeState(h,c);for(var e=0;e<j.length;e++)j[e](h)}}function f(){return a.getStates().then(function(a){h=getEntities(a);for(var b=0;b<j.length;b++)j[b](h)})}function g(b){b&&j.splice(j.indexOf(b),1),0===j.length&&(i(),a.removeEventListener('ready',f),a._subscribeEntities=null)}var h=null,i=null,j=[],k=null;b&&j.push(b),a._subscribeEntities=function(a){return a&&(j.push(a),null!==h&&a(h)),k.then(function(){return function(){return g(a)}})},k=Promise.all([a.subscribeEvents(e,'state_changed'),f()]),k.then(function(d){var e=d[0];i=e,a.addEventListener('ready',f),c(function(){return g(b)})},function(){return d()})})}export{ERR_CANNOT_CONNECT,ERR_INVALID_AUTH,ERR_CONNECTION_LOST,createConnection,subscribeConfig,subscribeEntities}; | ||
function e(e,t,n,r){return new(n||(n=Promise))(function(s,i){function o(e){try{a(r.next(e))}catch(e){i(e)}}function c(e){try{a(r.throw(e))}catch(e){i(e)}}function a(e){e.done?s(e.value):new n(function(t){t(e.value)}).then(o,c)}a((r=r.apply(e,t||[])).next())})}function t(e,t){var n,r,s,i,o={label:0,sent:function(){if(1&s[0])throw s[1];return s[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(i){return function(c){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;o;)try{if(n=1,r&&(s=2&i[0]?r.return:i[0]?r.throw||((s=r.return)&&s.call(r),0):r.next)&&!(s=s.call(r,i[1])).done)return s;switch(r=0,s&&(i=[2&i[0],s.value]),i[0]){case 0:case 1:s=i;break;case 4:return o.label++,{value:i[1],done:!1};case 5:o.label++,r=i[1],i=[0];continue;case 7:i=o.ops.pop(),o.trys.pop();continue;default:if(!(s=(s=o.trys).length>0&&s[s.length-1])&&(6===i[0]||2===i[0])){o=0;continue}if(3===i[0]&&(!s||i[1]>s[0]&&i[1]<s[3])){o.label=i[1];break}if(6===i[0]&&o.label<s[1]){o.label=s[1],s=i;break}if(s&&o.label<s[2]){o.label=s[2],o.ops.push(i);break}s[2]&&o.ops.pop(),o.trys.pop();continue}i=t.call(e,o)}catch(e){i=[6,e],r=0}finally{n=s=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,c])}}}var n=1,r=2,s=3,i=4,o="auth_required",c="auth_invalid",a="auth_ok",u="auth_callback";function h(){return location.protocol+"//"+location.host+"/"}function f(e,t){var n=location.protocol+"//"+location.host+location.pathname+location.search;n+=n.includes("?")?"&":"?",n+=u+"=1",document.location.href=function(e,t,n,r){var s=e+"/auth/authorize?response_type=code&client_id="+encodeURIComponent(t)+"&redirect_uri="+encodeURIComponent(n);return r&&(s+="&state="+encodeURIComponent(r)),s}(e,h(),n,t)}function l(n,r,s){return e(this,void 0,void 0,function(){var e,i,o;return t(this,function(t){switch(t.label){case 0:return(e=new FormData).append("client_id",r),Object.keys(s).forEach(function(t){e.append(t,s[t])}),[4,fetch(n+"/auth/token",{method:"POST",body:e})];case 1:if(!(i=t.sent()).ok)throw new Error("Unable to fetch tokens");return[4,i.json()];case 2:return(o=t.sent()).hassUrl=n,o.expires=1e3*o.expires_in+Date.now(),[2,o]}})})}var d=function(){function n(e,t){this.data=e,this._saveCache=t}return Object.defineProperty(n.prototype,"wsUrl",{get:function(){return"ws"+this.data.hassUrl.substr(4)+"/api/websocket"},enumerable:!0,configurable:!0}),Object.defineProperty(n.prototype,"accessToken",{get:function(){return this.data.access_token},enumerable:!0,configurable:!0}),Object.defineProperty(n.prototype,"expired",{get:function(){return Date.now()>this.data.expires-1e4},enumerable:!0,configurable:!0}),n.prototype.refreshAccessToken=function(){return e(this,void 0,void 0,function(){var e;return t(this,function(t){switch(t.label){case 0:return e=this,[4,(n=this.data.hassUrl,r=h(),s=this.data.refresh_token,l(n,r,{grant_type:"refresh_token",refresh_token:s}))];case 1:return e.data=t.sent(),this._saveCache&&this._saveCache(this.data),[2]}var n,r,s})})},n}();function v(n){var r=void 0===n?{}:n,s=r.hassUrl,o=r.loadCache,c=r.saveCache;return e(this,void 0,void 0,function(){var e,n,r;return t(this,function(t){switch(t.label){case 0:if(!("auth_callback"in(e=function(e){for(var t={},n=e.split("&"),r=0;r<n.length;r++){var s=n[r].split("="),i=decodeURIComponent(s[0]),o=s.length>1?decodeURIComponent(s[1]):void 0;t[i]=o}return t}(location.search.substr(1)))))return[3,4];r=JSON.parse(atob(e.state)),t.label=1;case 1:return t.trys.push([1,3,,4]),[4,function(e,t,n){return l(e,t,{code:n,grant_type:"authorization_code"})}(r.hassUrl,h(),e.code)];case 2:return n=t.sent(),c&&c(n),[3,4];case 3:return t.sent(),[3,4];case 4:return n||!o?[3,6]:[4,o()];case 5:n=t.sent(),t.label=6;case 6:if(!n&&s)return f(s,function(e){return btoa(JSON.stringify(e))}({hassUrl:s})),[2,new Promise(function(){})];if(n)return[2,new d(n,c)];throw i}})})}var p=function(){function n(e,t){this.options=t,this.commandId=1,this.commands={},this.eventListeners={},this.closeRequested=!1,this._handleClose=this._handleClose.bind(this),this.setSocket(e)}return n.prototype.setSocket=function(e){var t=this,n=this.socket;if(this.socket=e,e.addEventListener("message",function(e){return t._handleMessage(e)}),e.addEventListener("close",this._handleClose),n){var r=this.commands;this.commandId=1,this.commands={},Object.keys(r).forEach(function(e){var n=r[e];n.eventType&&t.subscribeEvents(n.eventCallback,n.eventType).then(function(e){n.unsubscribe=e})}),this.fireEvent("ready")}},n.prototype.addEventListener=function(e,t){var n=this.eventListeners[e];n||(n=this.eventListeners[e]=[]),n.push(t)},n.prototype.removeEventListener=function(e,t){var n=this.eventListeners[e];if(n){var r=n.indexOf(t);-1!==r&&n.splice(r,1)}},n.prototype.fireEvent=function(e,t){var n=this;(this.eventListeners[e]||[]).forEach(function(e){return e(n,t)})},n.prototype.close=function(){this.closeRequested=!0,this.socket.close()},n.prototype.getStates=function(){return this.sendMessagePromise({type:"get_states"})},n.prototype.getServices=function(){return this.sendMessagePromise({type:"get_services"})},n.prototype.getConfig=function(){return this.sendMessagePromise({type:"get_config"})},n.prototype.callService=function(e,t,n){return this.sendMessagePromise(function(e,t,n){var r={type:"call_service",domain:e,service:t};return n&&(r.service_data=n),r}(e,t,n))},n.prototype.subscribeEvents=function(n,r){return e(this,void 0,void 0,function(){var s,i,o=this;return t(this,function(c){switch(c.label){case 0:return s=this._genCmdId(),[4,this.sendMessagePromise(function(e){var t={type:"subscribe_events"};return e&&(t.event_type=e),t}(r),s)];case 1:return c.sent(),this.commands[s]=i={eventCallback:n,eventType:r,unsubscribe:function(){return e(o,void 0,void 0,function(){return t(this,function(e){switch(e.label){case 0:return[4,this.sendMessagePromise((t=s,{type:"unsubscribe_events",subscription:t}))];case 1:return e.sent(),delete this.commands[s],[2]}var t})})}},[2,function(){return i.unsubscribe()}]}})})},n.prototype.ping=function(){return this.sendMessagePromise({type:"ping"})},n.prototype.sendMessage=function(e,t){t||(t=this._genCmdId()),e.id=t,this.socket.send(JSON.stringify(e))},n.prototype.sendMessagePromise=function(e,t){var n=this;return new Promise(function(r,s){t||(t=n._genCmdId()),n.commands[t]={resolve:r,reject:s},n.sendMessage(e,t)})},n.prototype._handleMessage=function(e){var t=JSON.parse(e.data);switch(t.type){case"event":this.commands[t.id].eventCallback(t.event);break;case"result":t.id in this.commands&&(1==t.success?this.commands[t.id].resolve(t.result):this.commands[t.id].reject(t.error),delete this.commands[t.id])}},n.prototype._handleClose=function(){var n=this;if(Object.keys(this.commands).forEach(function(e){var t=n.commands[e].reject;t&&t({type:"result",success:!1,error:{code:3,message:"Connection lost"}})}),!this.closeRequested){this.fireEvent("disconnected");var s=Object.assign({},this.options,{setupRetry:0}),i=function(o){setTimeout(function(){return e(n,void 0,void 0,function(){var e,n;return t(this,function(t){switch(t.label){case 0:t.label=1;case 1:return t.trys.push([1,3,,4]),[4,s.createSocket(s)];case 2:return e=t.sent(),this.setSocket(e),[3,4];case 3:return(n=t.sent())===r?this.fireEvent("reconnect-error",n):i(o+1),[3,4];case 4:return[2]}})})},1e3*Math.min(o,5))};i(0)}},n.prototype._genCmdId=function(){return this.commandId+=1,this.commandId},n}(),b={setupRetry:0,createSocket:function(s){var i=s.auth,u=i.wsUrl;return new Promise(function(h,f){return function s(h,f,l){var d=this,v=new WebSocket(u),p=!1,b=function(){if(v.removeEventListener("close",b),p)l(r);else if(0!==h){var e=-1===h?-1:h-1;setTimeout(function(){return s(e,f,l)},1e3)}else l(n)},m=function(n){return e(d,void 0,void 0,function(){return t(this,function(e){switch(e.label){case 0:switch(JSON.parse(n.data).type){case o:return[3,1];case c:return[3,6];case a:return[3,7]}return[3,8];case 1:return e.trys.push([1,4,,5]),i.expired?[4,i.refreshAccessToken()]:[3,3];case 2:e.sent(),e.label=3;case 3:return v.send(JSON.stringify({type:"auth",access_token:i.accessToken})),[3,5];case 4:return e.sent(),p=!0,v.close(),[3,5];case 5:return[3,9];case 6:return p=!0,v.close(),[3,9];case 7:return v.removeEventListener("message",m),v.removeEventListener("close",b),v.removeEventListener("error",b),f(v),[3,9];case 8:e.label=9;case 9:return[2]}})})};v.addEventListener("message",m),v.addEventListener("close",b),v.addEventListener("error",b)}(s.setupRetry,h,f)})}};function m(n){return e(this,void 0,void 0,function(){var e,r;return t(this,function(t){switch(t.label){case 0:return[4,(e=Object.assign({},b,n)).createSocket(e)];case 1:return r=t.sent(),[2,new p(r,e)]}})})}var y=function(){function e(e){this._noSub=e,this.listeners=[]}return e.prototype.action=function(e){var t=this,n=function(e){return t.setState(e,!1)};return function(){for(var r=[],s=0;s<arguments.length;s++)r[s]=arguments[s];var i=e.apply(void 0,[t.state].concat(r));if(null!=i)return"then"in i?i.then(n):n(i)}},e.prototype.setState=function(e,t){this.state=t?e:Object.assign({},this.state,e);for(var n=this.listeners,r=0;r<n.length;r++)n[r](this.state)},e.prototype.subscribe=function(e){var t=this;return this.listeners.push(e),void 0!==this.state&&e(this.state),function(){t.unsubscribe(e)}},e.prototype.unsubscribe=function(e){for(var t=e,n=[],r=this.listeners,s=0;s<r.length;s++)r[s]===t?t=null:n.push(r[s]);this.listeners=n,0===n.length&&this._noSub()},e}();function g(n,r,s,i,o){if(n in i)return i[n](o);var c,a=new y(function(){c.then(function(e){return e()}),i.removeEventListener("ready",u),delete i[n]});function u(){return e(this,void 0,void 0,function(){var e,n;return t(this,function(t){switch(t.label){case 0:return n=(e=a).setState,[4,r(i)];case 1:return n.apply(e,[t.sent(),!0]),[2]}})})}return i[n]=a.subscribe,c=s(i,a),i.addEventListener("ready",u),u(),a.subscribe(o)}function _(e,t){return void 0===e?null:{components:e.components.concat(t.data.component)}}var w=function(e){return e.getConfig()},k=function(e,t){return e.subscribeEvents(t.action(_),"component_loaded")};function E(e,t){return g("_cnf",w,k,e,t)}function S(e,t){var n,r;if(void 0===e)return null;var s=t.data,i=s.domain,o=Object.assign({},e[i],((n={})[s.service]={description:"",fields:{}},n));return(r={})[i]=o,r}function C(e,t){var n;if(void 0===e)return null;var r=t.data,s=r.domain,i=r.service,o=e[s];if(!(o&&i in o))return null;var c={};return Object.keys(o).forEach(function(e){e!==i&&(c[e]=o[e])}),(n={})[s]=c,n}var O=function(e){return e.getServices()},L=function(e,t){return Promise.all([e.subscribeEvents(t.action(S),"service_registered"),e.subscribeEvents(t.action(C),"service_removed")]).then(function(e){return function(){return e.forEach(function(e){return e()})}})};function P(e,t){return g("_srv",O,L,e,t)}function j(n){return e(this,void 0,void 0,function(){var e,r,s,i;return t(this,function(t){switch(t.label){case 0:return[4,n.getStates()];case 1:for(e=t.sent(),r={},s=0;s<e.length;s++)r[(i=e[s]).entity_id]=i;return[2,r]}})})}var U=function(e,t){return e.subscribeEvents(function(e){return function(e,t){var n,r=e.state;if(void 0!==r){var s=t.data,i=s.entity_id,o=s.new_state;if(o)e.setState(((n={})[o.entity_id]=o,n));else{var c=Object.assign({},r);delete c[i],e.setState(c,!0)}}}(t,e)},"state_changed")};function I(e,t){return g("_ent",j,U,e,t)}export{n as ERR_CANNOT_CONNECT,r as ERR_INVALID_AUTH,s as ERR_CONNECTION_LOST,i as ERR_HASS_HOST_REQUIRED,v as getAuth,m as createConnection,E as subscribeConfig,P as subscribeServices,I as subscribeEntities}; | ||
//# sourceMappingURL=haws.es.js.map |
@@ -1,1 +0,2 @@ | ||
(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?b(exports):'function'==typeof define&&define.amd?define(['exports'],b):b(a.HAWS={})})(this,function(a){'use strict';function b(a){return{type:'auth',api_password:a}}function c(a){return{type:'auth',access_token:a}}function d(){return{type:'get_states'}}function e(){return{type:'get_config'}}function f(){return{type:'get_services'}}function g(){return{type:'get_panels'}}function h(a,b,c){var d={type:'call_service',domain:a,service:b};return c&&(d.service_data=c),d}function i(a){var b={type:'subscribe_events'};return a&&(b.event_type=a),b}function j(a){return{type:'unsubscribe_events',subscription:a}}function k(){return{type:'ping'}}function l(a,b){return{type:'result',success:!1,error:{code:a,message:b}}}function m(a,d){function e(f,g,h){var i=new WebSocket(a),j=!1,k=function(){if(i.removeEventListener('close',k),j)return void h(s);if(0===f)return void h(r);var a=-1===f?-1:f-1;setTimeout(function(){return e(a,g,h)},1e3)},l=function(a){var e=JSON.parse(a.data);switch(e.type){case u:d.authToken?i.send(JSON.stringify(b(d.authToken))):d.accessToken?i.send(JSON.stringify(c(d.accessToken))):(j=!0,i.close());break;case v:j=!0,i.close();break;case w:i.removeEventListener('message',l),i.removeEventListener('close',k),i.removeEventListener('error',k),g(i);break;default:}};i.addEventListener('message',l),i.addEventListener('close',k),i.addEventListener('error',k)}return new Promise(function(a,b){return e(d.setupRetry||0,a,b)})}function n(a){return a.result}function o(a){for(var b,c={},d=0;d<a.length;d++)b=a[d],c[b.entity_id]=b;return c}function p(a,b){var c=Object.assign({},a);return c[b.entity_id]=b,c}function q(a,b){var c=Object.assign({},a);return delete c[b],c}var r=1,s=2,t=3,u='auth_required',v='auth_invalid',w='auth_ok',x=function(a,b){this.url=a,this.options=b||{},this.commandId=1,this.commands={},this.eventListeners={},this.closeRequested=!1,this._handleMessage=this._handleMessage.bind(this),this._handleClose=this._handleClose.bind(this)};x.prototype.setSocket=function(a){var b=this,c=this.socket;if(this.socket=a,a.addEventListener('message',this._handleMessage),a.addEventListener('close',this._handleClose),c){var d=this.commands;this.commandId=1,this.commands={},Object.keys(d).forEach(function(a){var c=d[a];c.eventType&&b.subscribeEvents(c.eventCallback,c.eventType).then(function(a){c.unsubscribe=a})}),this.fireEvent('ready')}},x.prototype.addEventListener=function(a,b){var c=this.eventListeners[a];c||(c=this.eventListeners[a]=[]),c.push(b)},x.prototype.removeEventListener=function(a,b){var c=this.eventListeners[a];if(c){var d=c.indexOf(b);-1!==d&&c.splice(d,1)}},x.prototype.fireEvent=function(a,b){var c=this;(this.eventListeners[a]||[]).forEach(function(a){return a(c,b)})},x.prototype.close=function(){this.closeRequested=!0,this.socket.close()},x.prototype.getStates=function(){return this.sendMessagePromise(d()).then(n)},x.prototype.getServices=function(){return this.sendMessagePromise(f()).then(n)},x.prototype.getPanels=function(){return this.sendMessagePromise(g()).then(n)},x.prototype.getConfig=function(){return this.sendMessagePromise(e()).then(n)},x.prototype.callService=function(a,b,c){return this.sendMessagePromise(h(a,b,c))},x.prototype.subscribeEvents=function(a,b){var c=this;return this.sendMessagePromise(i(b)).then(function(d){var e={eventCallback:a,eventType:b,unsubscribe:function(){return c.sendMessagePromise(j(d.id)).then(function(){delete c.commands[d.id]})}};return c.commands[d.id]=e,function(){return e.unsubscribe()}})},x.prototype.ping=function(){return this.sendMessagePromise(k())},x.prototype.sendMessage=function(a){this.socket.send(JSON.stringify(a))},x.prototype.sendMessagePromise=function(a){var b=this;return new Promise(function(c,d){b.commandId+=1;var e=b.commandId;a.id=e,b.commands[e]={resolve:c,reject:d},b.sendMessage(a)})},x.prototype._handleMessage=function(a){var b=JSON.parse(a.data);switch(b.type){case'event':this.commands[b.id].eventCallback(b.event);break;case'result':b.success?this.commands[b.id].resolve(b):this.commands[b.id].reject(b.error),delete this.commands[b.id];break;case'pong':break;default:}},x.prototype._handleClose=function(){var a=this;if(Object.keys(this.commands).forEach(function(b){var c=a.commands[b],d=c.reject;d&&d(l(t,'Connection lost'))}),!this.closeRequested){this.fireEvent('disconnected');var b=Object.assign({},this.options,{setupRetry:0}),c=function(d){setTimeout(function(){m(a.url,b).then(function(b){return a.setSocket(b)},function(b){return b===s?a.fireEvent('reconnect-error',b):c(d+1)})},1e3*Math.min(d,5))};c(0)}},a.ERR_CANNOT_CONNECT=r,a.ERR_INVALID_AUTH=s,a.ERR_CONNECTION_LOST=t,a.createConnection=function(a,b){return void 0===b&&(b={}),m(a,b).then(function(c){var d=new x(a,b);return d.setSocket(c),d})},a.subscribeConfig=function(a,b){return a._subscribeConfig?a._subscribeConfig(b):new Promise(function(c,d){var e=null,f=null,g=[],h=null;b&&g.push(b);var i=function(a){e=Object.assign({},e,a);for(var b=0;b<g.length;b++)g[b](e)},j=function(a,b){var c;return i({services:Object.assign({},e.services,(c={},c[a]=b,c))})},k=function(a){if(null!==e){var b=Object.assign({},e.core,{components:e.core.components.concat(a.data.component)});i({core:b})}},l=function(a){var b;if(null!==e){var c=a.data,d=c.domain,f=c.service,g=Object.assign({},e.services[d]||{},(b={},b[f]={description:'',fields:{}},b));j(d,g)}},m=function(a){if(null!==e){var b=a.data,c=b.domain,d=b.service,f=e.services[c];if(f&&d in f){var g={};Object.keys(f).forEach(function(a){a!==d&&(g[a]=f[a])}),j(c,g)}}},n=function(){return Promise.all([a.getConfig(),a.getPanels(),a.getServices()]).then(function(a){var b=a[0],c=a[1],d=a[2];i({core:b,panels:c,services:d})})},o=function(a){a&&g.splice(g.indexOf(a),1),0===g.length&&f()};a._subscribeConfig=function(a){return a&&(g.push(a),null!==e&&a(e)),h.then(function(){return function(){return o(a)}})},h=Promise.all([a.subscribeEvents(k,'component_loaded'),a.subscribeEvents(l,'service_registered'),a.subscribeEvents(m,'service_removed'),n()]),h.then(function(d){var e=d[0],g=d[1],h=d[2];f=function(){a.removeEventListener('ready',n),e(),g(),h()},a.addEventListener('ready',n),c(function(){return o(b)})},function(){return d()})})},a.subscribeEntities=function(a,b){return a._subscribeEntities?a._subscribeEntities(b):new Promise(function(c,d){function e(a){if(null!==h){var b=a.data,c=b.entity_id,d=b.new_state;h=d?p(h,d):q(h,c);for(var e=0;e<j.length;e++)j[e](h)}}function f(){return a.getStates().then(function(a){h=o(a);for(var b=0;b<j.length;b++)j[b](h)})}function g(b){b&&j.splice(j.indexOf(b),1),0===j.length&&(i(),a.removeEventListener('ready',f),a._subscribeEntities=null)}var h=null,i=null,j=[],k=null;b&&j.push(b),a._subscribeEntities=function(a){return a&&(j.push(a),null!==h&&a(h)),k.then(function(){return function(){return g(a)}})},k=Promise.all([a.subscribeEvents(e,'state_changed'),f()]),k.then(function(d){var e=d[0];i=e,a.addEventListener('ready',f),c(function(){return g(b)})},function(){return d()})})},Object.defineProperty(a,'__esModule',{value:!0})}); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.homeAssistantJsWebsocket={})}(this,function(e){function t(e,t,n,r){return new(n||(n=Promise))(function(s,i){function o(e){try{a(r.next(e))}catch(e){i(e)}}function c(e){try{a(r.throw(e))}catch(e){i(e)}}function a(e){e.done?s(e.value):new n(function(t){t(e.value)}).then(o,c)}a((r=r.apply(e,t||[])).next())})}function n(e,t){var n,r,s,i,o={label:0,sent:function(){if(1&s[0])throw s[1];return s[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(i){return function(c){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;o;)try{if(n=1,r&&(s=2&i[0]?r.return:i[0]?r.throw||((s=r.return)&&s.call(r),0):r.next)&&!(s=s.call(r,i[1])).done)return s;switch(r=0,s&&(i=[2&i[0],s.value]),i[0]){case 0:case 1:s=i;break;case 4:return o.label++,{value:i[1],done:!1};case 5:o.label++,r=i[1],i=[0];continue;case 7:i=o.ops.pop(),o.trys.pop();continue;default:if(!(s=(s=o.trys).length>0&&s[s.length-1])&&(6===i[0]||2===i[0])){o=0;continue}if(3===i[0]&&(!s||i[1]>s[0]&&i[1]<s[3])){o.label=i[1];break}if(6===i[0]&&o.label<s[1]){o.label=s[1],s=i;break}if(s&&o.label<s[2]){o.label=s[2],o.ops.push(i);break}s[2]&&o.ops.pop(),o.trys.pop();continue}i=t.call(e,o)}catch(e){i=[6,e],r=0}finally{n=s=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,c])}}}var r=1,s=2,i=4,o="auth_required",c="auth_invalid",a="auth_ok",u="auth_callback";function h(){return location.protocol+"//"+location.host+"/"}function f(e,t){var n=location.protocol+"//"+location.host+location.pathname+location.search;n+=n.includes("?")?"&":"?",n+=u+"=1",document.location.href=function(e,t,n,r){var s=e+"/auth/authorize?response_type=code&client_id="+encodeURIComponent(t)+"&redirect_uri="+encodeURIComponent(n);return r&&(s+="&state="+encodeURIComponent(r)),s}(e,h(),n,t)}function d(e,r,s){return t(this,void 0,void 0,function(){var t,i,o;return n(this,function(n){switch(n.label){case 0:return(t=new FormData).append("client_id",r),Object.keys(s).forEach(function(e){t.append(e,s[e])}),[4,fetch(e+"/auth/token",{method:"POST",body:t})];case 1:if(!(i=n.sent()).ok)throw new Error("Unable to fetch tokens");return[4,i.json()];case 2:return(o=n.sent()).hassUrl=e,o.expires=1e3*o.expires_in+Date.now(),[2,o]}})})}var l=function(){function e(e,t){this.data=e,this._saveCache=t}return Object.defineProperty(e.prototype,"wsUrl",{get:function(){return"ws"+this.data.hassUrl.substr(4)+"/api/websocket"},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"accessToken",{get:function(){return this.data.access_token},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"expired",{get:function(){return Date.now()>this.data.expires-1e4},enumerable:!0,configurable:!0}),e.prototype.refreshAccessToken=function(){return t(this,void 0,void 0,function(){var e;return n(this,function(t){switch(t.label){case 0:return e=this,[4,(n=this.data.hassUrl,r=h(),s=this.data.refresh_token,d(n,r,{grant_type:"refresh_token",refresh_token:s}))];case 1:return e.data=t.sent(),this._saveCache&&this._saveCache(this.data),[2]}var n,r,s})})},e}();var v=function(){function e(e,t){this.options=t,this.commandId=1,this.commands={},this.eventListeners={},this.closeRequested=!1,this._handleClose=this._handleClose.bind(this),this.setSocket(e)}return e.prototype.setSocket=function(e){var t=this,n=this.socket;if(this.socket=e,e.addEventListener("message",function(e){return t._handleMessage(e)}),e.addEventListener("close",this._handleClose),n){var r=this.commands;this.commandId=1,this.commands={},Object.keys(r).forEach(function(e){var n=r[e];n.eventType&&t.subscribeEvents(n.eventCallback,n.eventType).then(function(e){n.unsubscribe=e})}),this.fireEvent("ready")}},e.prototype.addEventListener=function(e,t){var n=this.eventListeners[e];n||(n=this.eventListeners[e]=[]),n.push(t)},e.prototype.removeEventListener=function(e,t){var n=this.eventListeners[e];if(n){var r=n.indexOf(t);-1!==r&&n.splice(r,1)}},e.prototype.fireEvent=function(e,t){var n=this;(this.eventListeners[e]||[]).forEach(function(e){return e(n,t)})},e.prototype.close=function(){this.closeRequested=!0,this.socket.close()},e.prototype.getStates=function(){return this.sendMessagePromise({type:"get_states"})},e.prototype.getServices=function(){return this.sendMessagePromise({type:"get_services"})},e.prototype.getConfig=function(){return this.sendMessagePromise({type:"get_config"})},e.prototype.callService=function(e,t,n){return this.sendMessagePromise(function(e,t,n){var r={type:"call_service",domain:e,service:t};return n&&(r.service_data=n),r}(e,t,n))},e.prototype.subscribeEvents=function(e,r){return t(this,void 0,void 0,function(){var s,i,o=this;return n(this,function(c){switch(c.label){case 0:return s=this._genCmdId(),[4,this.sendMessagePromise(function(e){var t={type:"subscribe_events"};return e&&(t.event_type=e),t}(r),s)];case 1:return c.sent(),this.commands[s]=i={eventCallback:e,eventType:r,unsubscribe:function(){return t(o,void 0,void 0,function(){return n(this,function(e){switch(e.label){case 0:return[4,this.sendMessagePromise((t=s,{type:"unsubscribe_events",subscription:t}))];case 1:return e.sent(),delete this.commands[s],[2]}var t})})}},[2,function(){return i.unsubscribe()}]}})})},e.prototype.ping=function(){return this.sendMessagePromise({type:"ping"})},e.prototype.sendMessage=function(e,t){t||(t=this._genCmdId()),e.id=t,this.socket.send(JSON.stringify(e))},e.prototype.sendMessagePromise=function(e,t){var n=this;return new Promise(function(r,s){t||(t=n._genCmdId()),n.commands[t]={resolve:r,reject:s},n.sendMessage(e,t)})},e.prototype._handleMessage=function(e){var t=JSON.parse(e.data);switch(t.type){case"event":this.commands[t.id].eventCallback(t.event);break;case"result":t.id in this.commands&&(1==t.success?this.commands[t.id].resolve(t.result):this.commands[t.id].reject(t.error),delete this.commands[t.id])}},e.prototype._handleClose=function(){var e=this;if(Object.keys(this.commands).forEach(function(t){var n=e.commands[t].reject;n&&n({type:"result",success:!1,error:{code:3,message:"Connection lost"}})}),!this.closeRequested){this.fireEvent("disconnected");var r=Object.assign({},this.options,{setupRetry:0}),i=function(o){setTimeout(function(){return t(e,void 0,void 0,function(){var e,t;return n(this,function(n){switch(n.label){case 0:n.label=1;case 1:return n.trys.push([1,3,,4]),[4,r.createSocket(r)];case 2:return e=n.sent(),this.setSocket(e),[3,4];case 3:return(t=n.sent())===s?this.fireEvent("reconnect-error",t):i(o+1),[3,4];case 4:return[2]}})})},1e3*Math.min(o,5))};i(0)}},e.prototype._genCmdId=function(){return this.commandId+=1,this.commandId},e}(),p={setupRetry:0,createSocket:function(e){var i=e.auth,u=i.wsUrl;return new Promise(function(h,f){return function e(h,f,d){var l=this,v=new WebSocket(u),p=!1,b=function(){if(v.removeEventListener("close",b),p)d(s);else if(0!==h){var t=-1===h?-1:h-1;setTimeout(function(){return e(t,f,d)},1e3)}else d(r)},m=function(e){return t(l,void 0,void 0,function(){return n(this,function(t){switch(t.label){case 0:switch(JSON.parse(e.data).type){case o:return[3,1];case c:return[3,6];case a:return[3,7]}return[3,8];case 1:return t.trys.push([1,4,,5]),i.expired?[4,i.refreshAccessToken()]:[3,3];case 2:t.sent(),t.label=3;case 3:return v.send(JSON.stringify({type:"auth",access_token:i.accessToken})),[3,5];case 4:return t.sent(),p=!0,v.close(),[3,5];case 5:return[3,9];case 6:return p=!0,v.close(),[3,9];case 7:return v.removeEventListener("message",m),v.removeEventListener("close",b),v.removeEventListener("error",b),f(v),[3,9];case 8:t.label=9;case 9:return[2]}})})};v.addEventListener("message",m),v.addEventListener("close",b),v.addEventListener("error",b)}(e.setupRetry,h,f)})}};var b=function(){function e(e){this._noSub=e,this.listeners=[]}return e.prototype.action=function(e){var t=this,n=function(e){return t.setState(e,!1)};return function(){for(var r=[],s=0;s<arguments.length;s++)r[s]=arguments[s];var i=e.apply(void 0,[t.state].concat(r));if(null!=i)return"then"in i?i.then(n):n(i)}},e.prototype.setState=function(e,t){this.state=t?e:Object.assign({},this.state,e);for(var n=this.listeners,r=0;r<n.length;r++)n[r](this.state)},e.prototype.subscribe=function(e){var t=this;return this.listeners.push(e),void 0!==this.state&&e(this.state),function(){t.unsubscribe(e)}},e.prototype.unsubscribe=function(e){for(var t=e,n=[],r=this.listeners,s=0;s<r.length;s++)r[s]===t?t=null:n.push(r[s]);this.listeners=n,0===n.length&&this._noSub()},e}();function m(e,r,s,i,o){if(e in i)return i[e](o);var c,a=new b(function(){c.then(function(e){return e()}),i.removeEventListener("ready",u),delete i[e]});function u(){return t(this,void 0,void 0,function(){var e,t;return n(this,function(n){switch(n.label){case 0:return t=(e=a).setState,[4,r(i)];case 1:return t.apply(e,[n.sent(),!0]),[2]}})})}return i[e]=a.subscribe,c=s(i,a),i.addEventListener("ready",u),u(),a.subscribe(o)}function y(e,t){return void 0===e?null:{components:e.components.concat(t.data.component)}}var g=function(e){return e.getConfig()},_=function(e,t){return e.subscribeEvents(t.action(y),"component_loaded")};function k(e,t){var n,r;if(void 0===e)return null;var s=t.data,i=s.domain,o=Object.assign({},e[i],((n={})[s.service]={description:"",fields:{}},n));return(r={})[i]=o,r}function w(e,t){var n;if(void 0===e)return null;var r=t.data,s=r.domain,i=r.service,o=e[s];if(!(o&&i in o))return null;var c={};return Object.keys(o).forEach(function(e){e!==i&&(c[e]=o[e])}),(n={})[s]=c,n}var E=function(e){return e.getServices()},S=function(e,t){return Promise.all([e.subscribeEvents(t.action(k),"service_registered"),e.subscribeEvents(t.action(w),"service_removed")]).then(function(e){return function(){return e.forEach(function(e){return e()})}})};function C(e){return t(this,void 0,void 0,function(){var t,r,s,i;return n(this,function(n){switch(n.label){case 0:return[4,e.getStates()];case 1:for(t=n.sent(),r={},s=0;s<t.length;s++)r[(i=t[s]).entity_id]=i;return[2,r]}})})}var O=function(e,t){return e.subscribeEvents(function(e){return function(e,t){var n,r=e.state;if(void 0!==r){var s=t.data,i=s.entity_id,o=s.new_state;if(o)e.setState(((n={})[o.entity_id]=o,n));else{var c=Object.assign({},r);delete c[i],e.setState(c,!0)}}}(t,e)},"state_changed")};e.ERR_CANNOT_CONNECT=r,e.ERR_INVALID_AUTH=s,e.ERR_CONNECTION_LOST=3,e.ERR_HASS_HOST_REQUIRED=i,e.getAuth=function(e){var r=void 0===e?{}:e,s=r.hassUrl,o=r.loadCache,c=r.saveCache;return t(this,void 0,void 0,function(){var e,t,r;return n(this,function(n){switch(n.label){case 0:if(!("auth_callback"in(e=function(e){for(var t={},n=e.split("&"),r=0;r<n.length;r++){var s=n[r].split("="),i=decodeURIComponent(s[0]),o=s.length>1?decodeURIComponent(s[1]):void 0;t[i]=o}return t}(location.search.substr(1)))))return[3,4];r=JSON.parse(atob(e.state)),n.label=1;case 1:return n.trys.push([1,3,,4]),[4,function(e,t,n){return d(e,t,{code:n,grant_type:"authorization_code"})}(r.hassUrl,h(),e.code)];case 2:return t=n.sent(),c&&c(t),[3,4];case 3:return n.sent(),[3,4];case 4:return t||!o?[3,6]:[4,o()];case 5:t=n.sent(),n.label=6;case 6:if(!t&&s)return f(s,function(e){return btoa(JSON.stringify(e))}({hassUrl:s})),[2,new Promise(function(){})];if(t)return[2,new l(t,c)];throw i}})})},e.createConnection=function(e){return t(this,void 0,void 0,function(){var t,r;return n(this,function(n){switch(n.label){case 0:return[4,(t=Object.assign({},p,e)).createSocket(t)];case 1:return r=n.sent(),[2,new v(r,t)]}})})},e.subscribeConfig=function(e,t){return m("_cnf",g,_,e,t)},e.subscribeServices=function(e,t){return m("_srv",E,S,e,t)},e.subscribeEntities=function(e,t){return m("_ent",C,O,e,t)}}); | ||
//# sourceMappingURL=haws.umd.js.map |
{ | ||
"name": "home-assistant-js-websocket", | ||
"sideEffects": false, | ||
"version": "2.0.1", | ||
"version": "3.0.0-rc2", | ||
"description": "Home Assistant websocket client", | ||
"source": "lib/index.ts", | ||
"types": "dist/index.d.ts", | ||
"main": "dist/haws.umd.js", | ||
@@ -13,7 +15,5 @@ "module": "dist/haws.es.js", | ||
"scripts": { | ||
"watch": "rollup -c --watch --sourcemap inline", | ||
"build": "rollup -c --environment NODE_ENV:production", | ||
"lint": "eslint lib test", | ||
"test": "mocha", | ||
"test-watch": "mocha --watch" | ||
"watch": "microbundle watch", | ||
"build": "microbundle", | ||
"test": "mocha" | ||
}, | ||
@@ -23,17 +23,25 @@ "author": "Paulus Schoutsen <paulus@paulusschoutsen.nl>", | ||
"devDependencies": { | ||
"eslint": "^4.19.1", | ||
"eslint-config-airbnb-base": "^12.1.0", | ||
"eslint-plugin-import": "^2.2.0", | ||
"husky": "^1.0.0-rc.13", | ||
"lint-staged": "^7.2.0", | ||
"microbundle": "^0.5.1", | ||
"mocha": "^5.1.1", | ||
"prettier": "1.14.0", | ||
"reify": "^0.15.1", | ||
"rollup": "^0.59.1", | ||
"rollup-plugin-babel-minify": "^4.0.0", | ||
"rollup-plugin-babili": "^3.1.1", | ||
"rollup-plugin-buble": "^0.19.2", | ||
"rollup-plugin-replace": "^2.0.0", | ||
"rollup-watch": "^4.3.1" | ||
"ts-node": "^7.0.0" | ||
}, | ||
"files": [ | ||
"dist" | ||
] | ||
], | ||
"dependencies": {}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged" | ||
} | ||
}, | ||
"lint-staged": { | ||
"*.{ts,js,json,css,md}": [ | ||
"prettier --write", | ||
"git add" | ||
] | ||
} | ||
} |
178
README.md
# :aerial_tramway: JavaScript websocket client for Home Assistant | ||
This is a websocket client written in JavaScript that communicates with the Home Assistant websocket API. It can be used to integrate Home Assistant into your apps. It has 0 dependencies. | ||
This 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. | ||
```javascript | ||
import { createConnection, subscribeEntities } from 'home-assistant-js-websocket'; | ||
## Trying it out | ||
function stateChanged(event) { | ||
console.log('state changed', event); | ||
} | ||
We've included an [example client](https://github.com/home-assistant/home-assistant-js-websocket/blob/master/example.html) based on this lib so that it's easy to try it out: | ||
createConnection('ws://localhost:8123/api/websocket').then( | ||
(conn) => { | ||
console.log('Connection established!'); | ||
subscribeEntities(conn, entities => console.log('New entities!', entities)); | ||
}, | ||
err => console.error('Connection failed with code', err) | ||
) | ||
```bash | ||
yarn build | ||
npx http-server -o | ||
# A browser will open, navigate to example.html | ||
``` | ||
[Try it on JSFiddle.](https://jsfiddle.net/balloob/9w3oyswa/) | ||
## Usage | ||
@@ -27,4 +19,38 @@ | ||
Connections to the websocket API are initiated by calling `createConnection(url[, options])`. `createConnection` will return a promise that will resolve to either a `Connection` object or rejects with an error code. | ||
To 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 ask the url of their instance. | ||
```js | ||
// Example connect code | ||
import { | ||
getAuth, | ||
createConnection, | ||
subscribeEntities, | ||
ERR_HASS_HOST_REQUIRED | ||
} from "home-assistant-js-websocket"; | ||
async function connect() { | ||
let auth; | ||
try { | ||
auth = await getAuth(); | ||
} catch (err) { | ||
if (err === ERR_HASS_HOST_REQUIRED) { | ||
const hassUrl = prompt( | ||
"What host to connect to?", | ||
"http://localhost:8123" | ||
); | ||
auth = await getAuth({ hassUrl }); | ||
} else { | ||
alert(`Unknown error: ${err}`); | ||
return; | ||
} | ||
} | ||
const connection = await createConnection({ auth }); | ||
subscribeEntities(connection, ent => console.log(ent)); | ||
} | ||
connect(); | ||
``` | ||
Connections to the websocket API are initiated by calling `createConnection(options)`. This method will return a promise that will resolve to either a `Connection` object or rejects with error codes `ERR_INVALID_AUTH` or `ERR_CANNOT_CONNECT`. | ||
#### Available options | ||
@@ -34,6 +60,6 @@ | ||
| Option | Description | | ||
| ------ | ----------- | | ||
| authToken | Auth token to use to validate with Home Assistant. | ||
| setupRetry | Number of times to retry initial connection when it fails. -1 means infinite. | ||
| Option | Description | | ||
| ------------ | -------------------------------------------------------------------------------------------------------------------- | | ||
| setupRetry | Number of times to retry initial connection when it fails. Set to -1 for infinite retries. Default is 0 (no retries) | | ||
| createSocket | Override the createSocket method with your own. `(auth, options) => Promise<WebSocket>` | | ||
@@ -44,6 +70,8 @@ #### Possible error codes | ||
| Error | Description | | ||
| ----- | ----------- | | ||
| ERR_CANNOT_CONNECT | If the client was unable to connect to the websocket API. | ||
| ERR_INVALID_AUTH | If the supplied authentication was invalid. | ||
| Error | Description | | ||
| ---------------------- | ----------------------------------------------------------------------- | | ||
| ERR_CANNOT_CONNECT | If the client was unable to connect to the websocket API. | | ||
| ERR_INVALID_AUTH | If the supplied authentication was invalid. | | ||
| ERR_CONNECTION_LOST | Raised if connection closed while waiting for a message to be returned. | | ||
| ERR_HASS_HOST_REQUIRED | If the authentication requires a host to be defined. | | ||
@@ -53,3 +81,6 @@ You can import them into your code as follows: | ||
```javascript | ||
import { ERR_CANNOT_CONNECT, ERR_INVALID_AUTH } from 'home-assistant-js-websocket'; | ||
import { | ||
ERR_CANNOT_CONNECT, | ||
ERR_INVALID_AUTH | ||
} from "home-assistant-js-websocket"; | ||
``` | ||
@@ -63,7 +94,7 @@ | ||
| Event | Data | Description | | ||
| ----- | ---- | ----------- | | ||
| ready | - | Fired when authentication is successful and the connection is ready to take commands. | ||
| disconnected | - | Fired when the connection is lost. | ||
| reconnect-error | Error code | Fired when we encounter a fatal error when trying to reconnect. Currently limited to `ERR_INVALID_AUTH`. | ||
| Event | Data | Description | | ||
| --------------- | ---------- | -------------------------------------------------------------------------------------------------------- | | ||
| ready | - | Fired when authentication is successful and the connection is ready to take commands. | | ||
| disconnected | - | Fired when the connection is lost. | | ||
| reconnect-error | Error code | Fired when we encounter a fatal error when trying to reconnect. Currently limited to `ERR_INVALID_AUTH`. | | ||
@@ -74,7 +105,7 @@ You can attach and remove listeners as follows: | ||
function eventHandler(connection, data) { | ||
console.log('Connection has been established again'); | ||
console.log("Connection has been established again"); | ||
} | ||
conn.addEventListener('ready', eventHandler); | ||
conn.removeEventListener('ready', eventHandler); | ||
conn.addEventListener("ready", eventHandler); | ||
conn.removeEventListener("ready", eventHandler); | ||
``` | ||
@@ -86,10 +117,10 @@ | ||
The function `subscribeEntities` will return a promise that resolves to an unsubscribe function. | ||
The function `subscribeEntities` will return an unsubscribe function. | ||
```javascript | ||
import { subscribeEntities } from 'home-assistant-js-websocket'; | ||
import { subscribeEntities } from "home-assistant-js-websocket"; | ||
// conn is the connection from earlier. | ||
subscribeEntities(conn, entities => console.log('New entities!', entities)); | ||
subscribeEntities(conn, entities => console.log("New entities!", entities)); | ||
``` | ||
@@ -99,61 +130,26 @@ | ||
You can subscribe to the config of Home Assistant. Config can change when either a component gets loaded or a new service gets registered. | ||
You can subscribe to the config of Home Assistant. Config can change when either a component gets loaded. | ||
The function `subscribeConfig` will return a promise that resolves to an unsubscribe function. | ||
The function `subscribeConfig` will return an unsubscribe function. | ||
```javascript | ||
import { subscribeConfig } from 'home-assistant-js-websocket'; | ||
import { subscribeConfig } from "home-assistant-js-websocket"; | ||
// conn is the connection from earlier. | ||
subscribeConfig(conn, config => console.log('New config!', config)); | ||
subscribeConfig(conn, config => console.log("New config!", config)); | ||
``` | ||
### Managing entities | ||
### Services | ||
A few helper methods are included to help display the returned entities. | ||
You can subscribe to the available services of Home Assistant. Services can change when a new service gets registered or removed. | ||
#### getGroupEntities(entities, group) | ||
The function `subscribeServices` will return an unsubscribe function. | ||
Returns an object with only the entities referenced by `group`. | ||
#### splitByGroups(entities) | ||
Split `entities` into the groups that are contained in `entities` and a collection of entities that do not belong to a group. Groups will be returned sorted by order. | ||
```json5 | ||
{ | ||
groups: [ | ||
{ entity_id: 'group.example_1', state: … }, | ||
{ entity_id: 'group.example_2', state: … }, | ||
], | ||
ungrouped: { | ||
'sensor.temperature': { entity_id: … }, | ||
'sensor.humidity': { entity_id: … }, | ||
} | ||
} | ||
``` | ||
#### getViewEntities(entities, view) | ||
Returns an object containing all the entities from `entities` that are needed to render this view. | ||
#### extractViews(entities) | ||
Returns an ordered list of available views in `entities`. | ||
#### extractDomain(entityId) | ||
Returns the domain of `entityId`. | ||
```javascript | ||
extractDomain('light.kitchen') # 'light' | ||
``` | ||
import { subscribeServices } from "home-assistant-js-websocket"; | ||
#### extractObjectId(entityId) | ||
// conn is the connection from earlier. | ||
Returns the object id of `entityId`. | ||
```javascript | ||
extractObjectId('light.kitchen') # 'kitchen' | ||
subscribeServices(conn, services => console.log("New services!", services)); | ||
``` | ||
@@ -171,6 +167,2 @@ | ||
##### `conn.getPanels()` | ||
Get the Home Assistant panel config. Returns a promise that will resolve to the result of querying the server for all the panels config. | ||
##### `conn.getConfig()` | ||
@@ -199,16 +191,6 @@ | ||
```js | ||
const WebSocket = require('ws'); | ||
const WebSocket = require("ws"); | ||
global.WebSocket = WebSocket; | ||
const HAWS = require("home-assistant-js-websocket"); | ||
``` | ||
const getWsUrl = haUrl => `ws://${haUrl}/api/websocket`; | ||
HAWS.createConnection(getWsUrl('localhost:8123')).then(conn => { | ||
HAWS.subscribeEntities(conn, logEntities); | ||
}); | ||
function logEntities(entities) { | ||
Object.keys(entities).forEach(key => console.log(`${key}: ${entities[key].state}`)); | ||
console.log('') | ||
} | ||
``` | ||
You'll also need to instantiate your own Auth object. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
63305
7
22
370
2
187
4