From fcc4430bf94f4dfc681bd81938c513db471e9eca Mon Sep 17 00:00:00 2001 From: Mathias Scherer Date: Mon, 5 Apr 2021 01:10:15 +0200 Subject: [PATCH] adds basic media_player volume handling --- MMM-HomeAssistant-Touch.js | 2 + UIClasses/Cover.js | 85 +------------------------------------- UIClasses/MediaPlayer.js | 20 +++++++++ UIClasses/Slider.js | 78 ++++++++++++++++++++++++++++++++++ helpers/UIClassFactory.js | 2 + node_helper.js | 26 +++++++++--- 6 files changed, 124 insertions(+), 89 deletions(-) create mode 100644 UIClasses/MediaPlayer.js create mode 100644 UIClasses/Slider.js diff --git a/MMM-HomeAssistant-Touch.js b/MMM-HomeAssistant-Touch.js index 14d0a7d..0fadb89 100644 --- a/MMM-HomeAssistant-Touch.js +++ b/MMM-HomeAssistant-Touch.js @@ -18,9 +18,11 @@ Module.register("MMM-HomeAssistant-Touch", { return [ this.file("./helpers/UIClassFactory.js"), this.file("./UIClasses/Base.js"), + this.file("./UIClasses/Slider.js"), this.file("./UIClasses/Light.js"), this.file("./UIClasses/Switch.js"), this.file("./UIClasses/Cover.js"), + this.file("./UIClasses/MediaPlayer.js"), this.file("./UIClasses/Unsupported.js"), ]; }, diff --git a/UIClasses/Cover.js b/UIClasses/Cover.js index cb77190..fd7b0c3 100644 --- a/UIClasses/Cover.js +++ b/UIClasses/Cover.js @@ -1,93 +1,10 @@ -class Cover extends Base { - constructor(...params) { - super(...params); - this.onSliderMove = this.onSliderMove.bind(this); - this.removeSlider = this.removeSlider.bind(this); - } - - getContainer() { - const entity = super.getContainer(); - entity.onmousedown = (event) => { - this.addSlider(event.x, event.y); - }; - entity.onpointerdown = (event) => { - this.addSlider(event.x, event.y) - } - entity.onmouseup = this.removeSlider - entity.ontouchend = this.removeSlider - return entity; - } - +class Cover extends Slider { updateState(state) { this.name = (state.attributes || {}).friendly_name || this.id; this.state = state.attributes.current_position; this.render(); } - render() { - super.render(); - const container = document.getElementById(this.id); - if (container) { - container.classList.add(this.state); - } - } - - addSlider(offsetX, offsetY) { - const slider = document.createElement("div"); - slider.id = `slider-${this.id}`; - slider.classList.add("ha-slider"); - - // click location minus height minus margins - slider.style.top = `calc(${offsetY}px - 60px - 200px + calc(2px * ${this.state}))`; - // click location minus width/2 minus margins - slider.style.left = `calc(${offsetX}px - 60px - 1.5rem)`; - - const sliderFill = document.createElement("div"); - sliderFill.id = `slider-fill-${this.id}`; - sliderFill.classList.add("ha-slider-fill"); - sliderFill.style.height = `${this.state}%`; - sliderFill.innerHTML = this.state; - - slider.appendChild(sliderFill); - document.body.appendChild(slider); - - document.body.addEventListener("mouseup", this.removeSlider); - document.body.addEventListener("touchend", this.removeSlider) - document.body.addEventListener("mousemove", this.onSliderMove); - document.body.addEventListener("touchmove", this.onSliderMove); - - this.sliderStartY = offsetY; - this.sliderState = this.state; - } - - onSliderMove(event) { - let y = event.y - if(event.touches) { - y = event.touches[0].clientY - } - const sliderFill = document.getElementById(`slider-fill-${this.id}`); - if (sliderFill) { - const offset = this.sliderStartY - y; - this.sliderState = this.state + Math.round((100 / 200) * offset); - if(this.sliderState > 100) this.sliderState = 100 - if(this.sliderState < 0) this.sliderState = 0 - sliderFill.style.height = `${this.sliderState}%`; - sliderFill.innerHTML = this.sliderState; - } - } - - removeSlider() { - const slider = document.getElementById(`slider-${this.id}`); - if (slider) { - slider.remove(); - } - document.body.removeEventListener("mouseup", this.removeSlider); - document.body.removeEventListener("touchend", this.removeSlider) - document.body.removeEventListener("mousemove", this.onSliderMove); - document.body.removeEventListener("touchmove", this.onSliderMove); - this.sendNewState(); - } - sendNewState() { this.mm.sendSocketNotification("SET_COVER_POSITION", { entity: this.id, diff --git a/UIClasses/MediaPlayer.js b/UIClasses/MediaPlayer.js new file mode 100644 index 0000000..95efea0 --- /dev/null +++ b/UIClasses/MediaPlayer.js @@ -0,0 +1,20 @@ +class MediaPlayer extends Slider { + updateState(state) { + console.log(state) + this.name = (state.attributes || {}).friendly_name || this.id; + this.state = state.attributes.volume_level * 100; + this.render(); + } + + onSliderMove(event) { + super.onSliderMove(event) + this.sendNewState() + } + + sendNewState() { + this.mm.sendSocketNotification("SET_MEDIAPLAYER_VOLUME", { + entity: this.id, + volume_level: this.sliderState / 100, + }); + } +} \ No newline at end of file diff --git a/UIClasses/Slider.js b/UIClasses/Slider.js new file mode 100644 index 0000000..2167e8e --- /dev/null +++ b/UIClasses/Slider.js @@ -0,0 +1,78 @@ +class Slider extends Base { + constructor(...params) { + super(...params); + this.onSliderMove = this.onSliderMove.bind(this); + this.removeSlider = this.removeSlider.bind(this); + } + + getContainer() { + const entity = super.getContainer(); + entity.onmousedown = (event) => { + this.addSlider(event.x, event.y); + }; + entity.onpointerdown = (event) => { + this.addSlider(event.x, event.y); + }; + entity.onmouseup = this.removeSlider; + entity.ontouchend = this.removeSlider; + return entity; + } + + addSlider(offsetX, offsetY) { + const slider = document.createElement("div"); + slider.id = `slider-${this.id}`; + slider.classList.add("ha-slider"); + + // click location minus height minus margins + slider.style.top = `calc(${offsetY}px - 60px - 200px + calc(2px * ${this.state}))`; + // click location minus width/2 minus margins + slider.style.left = `calc(${offsetX}px - 60px - 1.5rem)`; + + const sliderFill = document.createElement("div"); + sliderFill.id = `slider-fill-${this.id}`; + sliderFill.classList.add("ha-slider-fill"); + sliderFill.style.height = `${this.state}%`; + sliderFill.innerHTML = this.state; + + slider.appendChild(sliderFill); + document.body.appendChild(slider); + + document.body.addEventListener("mouseup", this.removeSlider); + document.body.addEventListener("touchend", this.removeSlider); + document.body.addEventListener("mousemove", this.onSliderMove); + document.body.addEventListener("touchmove", this.onSliderMove); + + this.sliderStartY = offsetY; + this.sliderState = this.state; + } + + onSliderMove(event) { + let y = event.y; + if (event.touches) { + y = event.touches[0].clientY; + } + const sliderFill = document.getElementById(`slider-fill-${this.id}`); + if (sliderFill) { + const offset = this.sliderStartY - y; + this.sliderState = this.state + Math.round((100 / 200) * offset); + if (this.sliderState > 100) this.sliderState = 100; + if (this.sliderState < 0) this.sliderState = 0; + sliderFill.style.height = `${this.sliderState}%`; + sliderFill.innerHTML = this.sliderState; + } + } + + removeSlider() { + const slider = document.getElementById(`slider-${this.id}`); + if (slider) { + slider.remove(); + } + document.body.removeEventListener("mouseup", this.removeSlider); + document.body.removeEventListener("touchend", this.removeSlider); + document.body.removeEventListener("mousemove", this.onSliderMove); + document.body.removeEventListener("touchmove", this.onSliderMove); + this.sendNewState(); + } + + sendNewState() {} +} diff --git a/helpers/UIClassFactory.js b/helpers/UIClassFactory.js index 0e9545b..a04d0c8 100644 --- a/helpers/UIClassFactory.js +++ b/helpers/UIClassFactory.js @@ -9,6 +9,8 @@ class UIClassFactory { return Switch; case "cover": return Cover; + case "media_player": + return MediaPlayer; default: return Unsupported; } diff --git a/node_helper.js b/node_helper.js index b33bb71..0d2e62e 100644 --- a/node_helper.js +++ b/node_helper.js @@ -11,6 +11,7 @@ module.exports = NodeHelper.create({ getState, toggleState, setCoverPosition, + setMediaPlayerVolume, onStateChangedEvent, }); @@ -50,6 +51,9 @@ function socketNotificationReceived(notification, payload) { case "SET_COVER_POSITION": this.setCoverPosition(payload); break; + case "SET_MEDIAPLAYER_VOLUME": + this.setMediaPlayerVolume(payload); + break; } } @@ -89,7 +93,6 @@ async function getState(payload) { const hass = this.connections[payload.identifier].hass; const [domain, entity] = payload.entity.split("."); const response = await hass.states.get(domain, entity); - this.logger.debug(`Got state for ${payload.entity}`); this.sendSocketNotification("GOT_STATE", { identifier: payload.identifier, data: response, @@ -104,20 +107,33 @@ async function toggleState(payload) { this.logger.debug(`Toggling state for ${payload.entity}`); const hass = this.connections[payload.identifier].hass; const [domain, entity] = payload.entity.split("."); - const response = await hass.services.call("toggle", domain, entity); + await hass.services.call("toggle", domain, entity); this.getState(payload); } async function setCoverPosition(payload) { - this.logger.debug(`Setting position for cover ${payload.entity} to ${payload.position}`) + this.logger.debug( + `Setting position for cover ${payload.entity} to ${payload.position}` + ); const hass = this.connections[payload.identifier].hass; - const response = await hass.services.call("set_cover_position", 'cover', { + await hass.services.call("set_cover_position", "cover", { entity_id: payload.entity, - position: payload.position + position: payload.position, }); this.getState(payload); } +async function setMediaPlayerVolume(payload) { + this.logger.debug( + `Setting volume for media_player ${payload.entity} to ${payload.volume_level}` + ); + const hass = this.connections[payload.identifier].hass; + await hass.services.call("volume_set", "media_player", { + entity_id: payload.entity, + volume_level: payload.volume_level, + }); +} + function onStateChangedEvent(event) { //this.logger.debug(`Got state change for ${event.data.entity_id}`); for (const connection in this.connections) {