diff --git a/MMM-BoschSmartHome.js b/MMM-BoschSmartHome.js index b9fce6d..541fc3d 100644 --- a/MMM-BoschSmartHome.js +++ b/MMM-BoschSmartHome.js @@ -1,6 +1,6 @@ /*! ***************************************************************************** mmm-bosch-smart-home - Version 1.2.0 + Version 1.3.0 A client interface for the Bosch Smart Home System on the MagicMirror² platform. Please submit bugs at https://github.com/jalibu/MMM-BoschSmartHome/issues @@ -11,4 +11,4 @@ This file is auto-generated. Do not edit. ***************************************************************************** */ -!function(e){"use strict";function t(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var i=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,i.get?i:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var r=t(e);class i{static getRoomIcon(e){switch(e){case"icon_room_bathroom":return"fa-bath";case"icon_room_bedroom":return"fa-bed";case"icon_room_office":return"fa-briefcase";case"icon_room_living_room":return"fa-couch";case"icon_room_dining_room":return"fa-utensils";default:return"fa-house-user"}}static getLowBatteryDevices(e){const t=[];for(const r of e){const e=r.services.find((e=>"BatteryLevel"===e.id));e&&e.faults&&t.push(r.name)}return t}static getSwitchedOnHueDevices(e){const t=e.filter((e=>"HUE_LIGHT"===e.deviceModel)),r=[];return t.forEach((e=>{e.services.find((e=>"BinarySwitch"===e.id)).state.on&&r.indexOf(e.name)<=0&&r.push(e.name)})),r}static getOpenShutters(e){const t=e.filter((e=>"SWD"===e.deviceModel)),r=[];return t.forEach((e=>{"CLOSED"!==e.services.find((e=>"ShutterContact"===e.id)).state.value&&r.indexOf(e.profile)<=0&&r.push(e.profile)})),r}static getClimateControlService(e){const t=e.find((e=>"ROOM_CLIMATE_CONTROL"===e.deviceModel));return t?t.services.find((e=>"RoomClimateControl"===e.id)):null}static getTemperatureLevelService(e){const t=e.find((e=>"ROOM_CLIMATE_CONTROL"===e.deviceModel));return t?t.services.find((e=>"TemperatureLevel"===e.id)):null}static getAirQualityService(e){const t=e.find((e=>"TWINGUARD"===e.deviceModel));return t?t.services.find((e=>"AirQualityLevel"===e.id)):null}static getThermostatServices(e){const t=e.filter((e=>"TRV"===e.deviceModel));if(!t)return null;const r=[];return t.forEach((e=>{const t=e.services.find((e=>"TemperatureLevel"===e.id)),i=e.services.find((e=>"ValveTappet"===e.id));r.push({temperatureLevelService:t,valveTappetService:i,name:e.name})})),r}static getDishWasherService(e){const t=e.find((e=>"HOMECONNECT_DISHWASHER"===e.deviceModel));if(!t)return null;const r=t.services.find((e=>"HCDishwasher"===e.id));return r.deviceName=t.name,r}static getChartHumidityPercentage(e){return e>100?100:e}static getChartPurityPercentage(e){const t=e.state.purity/e.state.comfortZone.maxPurity*50;return t>100?100:t}static getChartTemperaturePercentage(e,t){if(!t||!e)return null;const r=e/(t.maxTemperature-(t.maxTemperature-t.minTemperature))*50;return r>100?100:r}static isHidden(e,t,r){return r.hideComponents[e.name]&&r.hideComponents[e.name].indexOf(t)>=0}}Module.register("MMM-BoschSmartHome",{defaults:{mocked:!1,debug:!1,header:null,host:"192.168.0.150",name:"MMM-BoschSmartHome",identifier:"MMM-BoschSmartHome",password:"",width:"340px",refreshIntervalInSeconds:60,displayRoomIcons:!1,hideComponents:{},airquality:{purity:"bar",humidity:"bar",temperature:"bar",preferredTemperatureProvider:"Twinguard",preferredHumidityProvider:"Twinguard"},temperatureLevel:{displayCurrentTemperature:!0,displayTargetTemperature:!0,forceRowTile:!0},thermostats:{display:!0,displayName:!1}},getStyles:()=>["font-awesome.css","MMM-BoschSmartHome.css"],getTranslations:()=>({en:"translations/en.json",de:"translations/de.json"}),getTemplate:()=>"templates/MMM-BoschSmartHome.njk",getTemplateData(){return{config:this.config,rooms:this.rooms,error:this.error,utils:i}},getHeader(){return this.config.header},start(){this.rooms=[],this.error=null,this.sendSocketNotification("BSH_CONFIG_REQUEST",this.config),this.updateDom()},socketNotificationReceived(e,t){"BSH_ROOMS_RESPONSE"===e?(this.error=null,this.rooms=t,this.updateDom(),r.log("BSH Rooms",this.rooms)):"BSH_ERROR_RESPONSE"===e&&(this.error=t,console.log(this.error),this.updateDom())}})}(Log); +!function(e){"use strict";function t(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var i=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,i.get?i:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var r=t(e);class i{static getRoomIcon(e){switch(e){case"icon_room_bathroom":return"fa-bath";case"icon_room_bedroom":return"fa-bed";case"icon_room_office":return"fa-briefcase";case"icon_room_living_room":return"fa-couch";case"icon_room_dining_room":return"fa-utensils";default:return"fa-house-user"}}static getLowBatteryDevices(e){const t=[];for(const r of e){const e=r.services.find((e=>"BatteryLevel"===e.id));e&&e.faults&&t.push(r.name)}return t}static getSwitchedOnHueDevices(e){const t=e.filter((e=>"HUE_LIGHT"===e.deviceModel)),r=[];return t.forEach((e=>{e.services.find((e=>"BinarySwitch"===e.id)).state.on&&r.indexOf(e.name)<=0&&r.push(e.name)})),r}static getOpenShutters(e){const t=e.filter((e=>"SWD"===e.deviceModel)),r=[];return t.forEach((e=>{"CLOSED"!==e.services.find((e=>"ShutterContact"===e.id)).state.value&&r.indexOf(e.profile)<=0&&r.push(e.profile)})),r}static getClimateControlService(e){const t=e.find((e=>"ROOM_CLIMATE_CONTROL"===e.deviceModel));return t?t.services.find((e=>"RoomClimateControl"===e.id)):null}static getTemperatureLevelService(e){const t=e.find((e=>"ROOM_CLIMATE_CONTROL"===e.deviceModel));return t?t.services.find((e=>"TemperatureLevel"===e.id)):null}static getAirQualityService(e){const t=e.find((e=>"TWINGUARD"===e.deviceModel));return t?t.services.find((e=>"AirQualityLevel"===e.id)):null}static getThermostatServices(e){const t=e.filter((e=>"TRV"===e.deviceModel));if(!t)return null;const r=[];return t.forEach((e=>{const t=e.services.find((e=>"TemperatureLevel"===e.id)),i=e.services.find((e=>"ValveTappet"===e.id));r.push({temperatureLevelService:t,valveTappetService:i,name:e.name})})),r}static getDishWasherService(e){const t=e.find((e=>"HOMECONNECT_DISHWASHER"===e.deviceModel));if(!t)return null;const r=t.services.find((e=>"HCDishwasher"===e.id));return r.deviceName=t.name,r}static getChartHumidityPercentage(e){return e>100?100:e}static getChartPurityPercentage(e){const t=e.state.purity/e.state.comfortZone.maxPurity*50;return t>100?100:t}static getChartTemperaturePercentage(e,t){if(!t||!e)return null;const r=e/(t.maxTemperature-(t.maxTemperature-t.minTemperature))*50;return r>100?100:r}static isHidden(e,t,r){return r.hideComponents[e.name]&&r.hideComponents[e.name].indexOf(t)>=0}}Module.register("MMM-BoschSmartHome",{defaults:{mocked:!1,debug:!1,host:"192.168.0.150",name:"MMM-BoschSmartHome",identifier:"MMM-BoschSmartHome",password:"",width:"340px",refreshIntervalInSeconds:60,displayRoomIcons:!1,roomOrder:[],hideComponents:{},airquality:{purity:"bar",humidity:"bar",temperature:"bar",preferredTemperatureProvider:"Twinguard",preferredHumidityProvider:"Twinguard"},temperatureLevel:{displayCurrentTemperature:!0,displayTargetTemperature:!0,forceRowTile:!0},thermostats:{display:!0,displayName:!1}},getStyles:()=>["font-awesome.css","MMM-BoschSmartHome.css"],getTranslations:()=>({en:"translations/en.json",de:"translations/de.json"}),getTemplate:()=>"templates/MMM-BoschSmartHome.njk",getTemplateData(){return{config:this.config,rooms:this.rooms,error:this.error,utils:i}},start(){this.rooms=[],this.error=null,this.sendSocketNotification("BSH_CONFIG_REQUEST",this.config),this.updateDom()},socketNotificationReceived(e,t){"BSH_ROOMS_RESPONSE"===e?(this.error=null,this.rooms=t,this.updateDom(),r.log("BSH Rooms",this.rooms)):"BSH_ERROR_RESPONSE"===e&&(this.error=t,console.log(this.error),this.updateDom())}})}(Log); diff --git a/README.md b/README.md index 3bb4cef..8e2d3cc 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,7 @@ Click here for the Magic Mirror [Forum Thread](https://forum.magicmirror.builder Contribution welcome. ### Support -If you like this module and want to thank, please rate this repository with a star or buy me a coffee :-) - -Buy Me A Beer +If you like this module and want to thank, please rate this repository with a star or [buy me a coffee](https://paypal.me/jalibu). ## Features @@ -63,6 +61,7 @@ If you like this module and want to thank, please rate this repository with a st width: "340px", displayRoomIcons: false, // Default: false hideComponents: {}, // See example below. Default: {} + roomOrder: [], // Manually set the room order by a list of room names, e.g. ["Livingroom", "Bedroom", "Kitchen"] airquality: { purity: "bar", // one of [tile, bar, donut, none] humidity: "bar", // one of [tile, bar, donut, none] @@ -86,7 +85,7 @@ If you like this module and want to thank, please rate this repository with a st You can hide individual components per room. Check sample for possible values: ```javascript - config: { + config: { hideComponents: { "Livingroom": ["temperature", "purity", "humidity"], "Bed Room": ["battery", "climateControl", "temperatureLevel", "hue"], diff --git a/node_helper.js b/node_helper.js index af1b974..6259e32 100644 --- a/node_helper.js +++ b/node_helper.js @@ -1,6 +1,6 @@ /*! ***************************************************************************** mmm-bosch-smart-home - Version 1.2.0 + Version 1.3.0 A client interface for the Bosch Smart Home System on the MagicMirror² platform. Please submit bugs at https://github.com/jalibu/MMM-BoschSmartHome/issues @@ -26,4 +26,4 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ -function l(e,t,i,o){return new(i||(i=Promise))((function(n,s){function r(e){try{h(o.next(e))}catch(e){s(e)}}function c(e){try{h(o.throw(e))}catch(e){s(e)}}function h(e){var t;e.done?n(e.value):(t=e.value,t instanceof i?t:new i((function(e){e(t)}))).then(r,c)}h((o=o.apply(e,t||[])).next())}))}class a{constructor(){this.client=null,this.config=null,this.cert=null,this.key=null,this.logger=null,this.rooms=null}setConfig(e){this.config=e}establishConnection(){return l(this,void 0,void 0,(function*(){this.cert=h.readFileSync(`${__dirname}/client-cert.pem`).toString(),this.key=h.readFileSync(`${__dirname}/client-key.pem`).toString(),this.logger=new c.DefaultLogger,this.logger.fine=()=>{},this.logger.info=e=>{e.indexOf("Using existing certificate")>=0||e.indexOf("Check if client with identifier")>=0||r.info(e)};const e=c.BoschSmartHomeBridgeBuilder.builder().withHost(this.config.host).withClientCert(this.cert).withClientPrivateKey(this.key).withLogger(this.logger).build();yield e.pairIfNeeded(this.config.name,this.config.identifier,this.config.password).toPromise(),this.client=e.getBshcClient(),r.info("Established connection to BSHB")}))}getRooms(){return l(this,void 0,void 0,(function*(){try{if(!this.client)try{yield this.establishConnection()}catch(e){throw Error(`Could not establish connection to BSHB: ${e.message}`)}if(!this.rooms){const{parsedResponse:e}=yield this.client.getRooms().toPromise();this.rooms=e,r.info("Retrieved rooms from BSHB.")}const{parsedResponse:e}=yield this.client.getDevices().toPromise(),{parsedResponse:t}=yield this.client.getDevicesServices().toPromise();for(const i of e)i.services=t.filter((e=>e.deviceId===i.id));for(const t of this.rooms)t.devices=e.filter((e=>e.roomId===t.id));return Promise.resolve(this.rooms)}catch(e){return r.error(e.message),Promise.reject(e)}}))}}module.exports=s.create({start(){this.client=new a,r.log(`${this.name} helper method started...`)},socketNotificationReceived(e,t){return l(this,void 0,void 0,(function*(){if("BSH_CONFIG_REQUEST"===e){const e=t;this.client.setConfig(e),this.getClientData(),this.schedule||(this.schedule=setInterval(this.getClientData.bind(this),1e3*e.refreshIntervalInSeconds))}}))},getClientData(){return l(this,void 0,void 0,(function*(){try{const e=yield this.client.getRooms();this.sendSocketNotification("BSH_ROOMS_RESPONSE",e)}catch(e){this.sendSocketNotification("BSH_ERROR_RESPONSE",{type:"WARNING",message:e.message})}}))}}); +function l(e,t,i,o){return new(i||(i=Promise))((function(n,s){function r(e){try{h(o.next(e))}catch(e){s(e)}}function c(e){try{h(o.throw(e))}catch(e){s(e)}}function h(e){var t;e.done?n(e.value):(t=e.value,t instanceof i?t:new i((function(e){e(t)}))).then(r,c)}h((o=o.apply(e,t||[])).next())}))}class d{constructor(){this.client=null,this.config=null,this.cert=null,this.key=null,this.logger=null,this.rooms=null}setConfig(e){this.config=e}establishConnection(){return l(this,void 0,void 0,(function*(){this.cert=h.readFileSync(`${__dirname}/client-cert.pem`).toString(),this.key=h.readFileSync(`${__dirname}/client-key.pem`).toString(),this.logger=new c.DefaultLogger,this.logger.fine=()=>{},this.logger.info=e=>{e.indexOf("Using existing certificate")>=0||e.indexOf("Check if client with identifier")>=0||r.info(e)};const e=c.BoschSmartHomeBridgeBuilder.builder().withHost(this.config.host).withClientCert(this.cert).withClientPrivateKey(this.key).withLogger(this.logger).build();yield e.pairIfNeeded(this.config.name,this.config.identifier,this.config.password).toPromise(),this.client=e.getBshcClient(),r.info("Established connection to BSHB")}))}getRooms(){return l(this,void 0,void 0,(function*(){try{if(!this.client)try{yield this.establishConnection()}catch(e){throw Error(`Could not establish connection to BSHB: ${e.message}`)}if(!this.rooms){const{parsedResponse:e}=yield this.client.getRooms().toPromise();this.rooms=e.sort(((e,t)=>this.config.roomOrder.indexOf(e.name)-this.config.roomOrder.indexOf(t.name))),r.info("Retrieved rooms from BSHB.")}const{parsedResponse:e}=yield this.client.getDevices().toPromise(),{parsedResponse:t}=yield this.client.getDevicesServices().toPromise();for(const i of e)i.services=t.filter((e=>e.deviceId===i.id));for(const t of this.rooms)t.devices=e.filter((e=>e.roomId===t.id));return Promise.resolve(this.rooms)}catch(e){return r.error(e.message),Promise.reject(e)}}))}}module.exports=s.create({start(){this.client=new d,r.log(`${this.name} helper method started...`)},socketNotificationReceived(e,t){return l(this,void 0,void 0,(function*(){if("BSH_CONFIG_REQUEST"===e){const e=t;this.client.setConfig(e),this.getClientData(),this.schedule||(this.schedule=setInterval(this.getClientData.bind(this),1e3*e.refreshIntervalInSeconds))}}))},getClientData(){return l(this,void 0,void 0,(function*(){try{const e=yield this.client.getRooms();this.sendSocketNotification("BSH_ROOMS_RESPONSE",e)}catch(e){this.sendSocketNotification("BSH_ERROR_RESPONSE",{type:"WARNING",message:e.message})}}))}}); diff --git a/package-lock.json b/package-lock.json index d62ed96..b937673 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mmm-bosch-smart-home", - "version": "1.2.1", + "version": "1.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mmm-bosch-smart-home", - "version": "1.2.1", + "version": "1.3.0", "license": "MIT", "dependencies": { "bosch-smart-home-bridge": "^1.0.0" diff --git a/package.json b/package.json index 30d17a3..8f649eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mmm-bosch-smart-home", - "version": "1.2.1", + "version": "1.3.0", "description": "A client interface for the Bosch Smart Home System on the MagicMirror² platform.", "main": "MMM-BoschSmartHome.js", "repository": { diff --git a/src/backend/BshClient.ts b/src/backend/BshClient.ts index bee33fe..552745b 100644 --- a/src/backend/BshClient.ts +++ b/src/backend/BshClient.ts @@ -57,7 +57,12 @@ export default class BshbClient { if (!this.rooms) { const { parsedResponse: rooms } = await this.client.getRooms().toPromise() - this.rooms = rooms + + // Change room order if configured + this.rooms = rooms.sort((a: Room, b: Room) => { + return this.config.roomOrder.indexOf(a.name) - this.config.roomOrder.indexOf(b.name) + }) + Log.info('Retrieved rooms from BSHB.') } diff --git a/src/frontend/Frontend.ts b/src/frontend/Frontend.ts index 0711ffc..0fc60f6 100644 --- a/src/frontend/Frontend.ts +++ b/src/frontend/Frontend.ts @@ -6,7 +6,6 @@ Module.register('MMM-BoschSmartHome', { defaults: { mocked: false, debug: false, - header: null, host: '192.168.0.150', name: 'MMM-BoschSmartHome', identifier: 'MMM-BoschSmartHome', @@ -14,6 +13,7 @@ Module.register('MMM-BoschSmartHome', { width: '340px', refreshIntervalInSeconds: 60, displayRoomIcons: false, + roomOrder: [], hideComponents: {}, // see README.md airquality: { purity: 'bar', // one of [tile, bar, donut, none] @@ -57,10 +57,6 @@ Module.register('MMM-BoschSmartHome', { } }, - getHeader() { - return this.config.header - }, - start() { this.rooms = [] this.error = null diff --git a/src/types/Config.ts b/src/types/Config.ts index d5869ab..f15a6b7 100644 --- a/src/types/Config.ts +++ b/src/types/Config.ts @@ -1,13 +1,13 @@ export type Config = { mocked: boolean debug: boolean - header: string host: string name: string identifier: string password: string width: string hideComponents: any + roomOrder: string[] refreshIntervalInSeconds: number displayRoomIcons: boolean temperatureLevel: TemperatureLevelConfig