Skip to content

Commit

Permalink
Merge pull request #25 from korapp/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
korapp authored Feb 21, 2024
2 parents 228a32a + 96e8e3a commit 17662eb
Show file tree
Hide file tree
Showing 23 changed files with 317 additions and 318 deletions.
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ on:
push:
branches:
- master
- 'release/**'

jobs:
bump:
Expand Down
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ Add Home Assistant to your plasma desktop.
## Requirements

* Active KDE Wallet
* Qt >= 5.14, KDE Frameworks >= 5.77, KDE Plasma >= 5.19 (e.g. Kubuntu 21.04 and newer)
* KDE Plasma >= 6.0
* Home Assistant >= 2022.4
* **Qt WebSocket package installed**

Base | Required package
--|--
Debian, Ubuntu | qml-module-qtwebsockets
Arch | qt5-websockets
Fedora | qt5-qtwebsockets-devel
openSUSE | libQt5WebSockets5
NixOS | libsForQt5.qt5.qtwebsockets
Debian, Ubuntu | qml6-module-qtwebsockets
Arch | qt6-websockets
Fedora | qt6-qtwebsockets-devel
openSUSE | libQt6WebSockets6
NixOS | libsForQt6.qt6.qtwebsockets

**Please remember to restart plasma or re-login after installing the dependency.**

Expand Down Expand Up @@ -79,5 +80,5 @@ Say thank you with coffee ☕ if you'd like.
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/korapp)
[<img src="https://img.shields.io/static/v1?message=Revolut&color=FFFFFF&logo=Revolut&logoColor=000000&label=" height="30"/>](https://revolut.me/korapp)

[kdestore]: https://store.kde.org/p/2070431/
[kdestore]: https://store.kde.org/p/2131364/
[releases]: https://github.com/korapp/plasma-homeassistant/releases
13 changes: 6 additions & 7 deletions package/contents/code/model.mjs
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
const activeStates = ['on', 'open'];

function getDisplayValue({ state, domain, attribute, attributes }) {
if (domain === 'button') return ''
function getDisplayValue({ state, attribute, attributes, unit }) {
if (attribute) {
return attributes[attribute] || ''
}
if (state && state !== 'unknown') {
const unit = attributes.unit_of_measurement
return state + (unit ? (unit === '%' ? '' : ' ') + unit : '')
return state + (unit === '%' ? unit : ' ' + unit)
}
return ''
}

export function Entity({ entity_id = '', domain, name, icon, attribute = '', default_action = {} }, { state, attributes = {} } = {}) {
export function Entity({ entity_id = '', name, icon, attribute = '', unit, default_action = {} } = {}, data = {}) {
const { s: state = '', a: attributes = {} } = data
this.entity_id = entity_id
this.domain = domain
this.name = name || attributes.friendly_name || ''
this.icon = icon || attributes.icon || ''
this.unit = unit || attributes.unit_of_measurement || ''
this.attribute = attribute
this.default_action = default_action
this.active = activeStates.includes(state)
this.domain = entity_id.substring(0, entity_id.indexOf('.'))
this.state = state
this.value = getDisplayValue({ state, domain: this.domain, attribute, attributes })
this.value = getDisplayValue({ state, attribute, attributes, unit: this.unit })
}

export function ConfigEntity({ entity_id = '', name, icon, attribute, default_action, notify } = {}) {
Expand Down
4 changes: 2 additions & 2 deletions package/contents/config/config.qml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import QtQuick 2.0
import org.kde.plasma.configuration 2.0
import QtQuick
import org.kde.plasma.configuration

ConfigModel {
ConfigCategory {
Expand Down
2 changes: 1 addition & 1 deletion package/contents/lib/secrets
Submodule secrets updated 2 files
+3 −3 Exec.qml
+1 −1 Wallet.qml
29 changes: 11 additions & 18 deletions package/contents/ui/Client.qml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import QtQuick 2.0
import QtWebSockets 1.0
import QtQuick
import QtWebSockets

import "components"

BaseObject {
property string baseUrl
property string token
property var subscribeState: ws.subscribeState
property var subscribeEntities: ws.subscribeEntities
property var callService: ws.callService
property var getServices: ws.getServices
property var getStates: ws.getStates
Expand All @@ -18,8 +18,8 @@ BaseObject {

Connections {
target: ws
onError: errorString = msg
onEstablished: errorString = ""
function onError(msg) { errorString = msg }
function onEstablished() { errorString = "" }
}

readonly property QtObject ready: QtObject {
Expand Down Expand Up @@ -65,7 +65,7 @@ BaseObject {
onOpenChanged: ready = false
onReadyChanged: ready && established()

onTextMessageReceived: {
onTextMessageReceived: message => {
pingPongTimer.reset()
const msg = JSON.parse(message)
switch (msg.type) {
Expand All @@ -77,7 +77,7 @@ BaseObject {
}
}

onErrorStringChanged: errorString && error(errorString)
onErrorStringChanged: () => errorString && error(errorString)

function reconnect() {
active = false
Expand All @@ -101,23 +101,16 @@ BaseObject {

function notifyStateUpdate(msg) {
const callback = subscriptions.get(msg.id)
return callback && callback(msg.event.variables.trigger.to_state)
return callback && callback(msg.event)
}

function subscribeState(entities, callback) {
if (!callback) return
const subscription = subscribe({
"platform": "state",
"entity_id": entities
})
function subscribeEntities(entity_ids, callback) {
if (!entity_ids) return
const subscription = command({"type": "subscribe_entities", entity_ids})
subscriptions.set(subscription, callback)
return () => unsubscribe(subscription)
}

function subscribe(trigger) {
return command({"type": "subscribe_trigger", trigger})
}

function unsubscribe(subscription) {
if(!subscriptions.has(subscription)) return
return commandAsync({"type": "unsubscribe_events", subscription})
Expand Down
2 changes: 1 addition & 1 deletion package/contents/ui/ClientFactory.qml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pragma Singleton

import QtQuick 2.0
import QtQuick

import "components"

Expand Down
4 changes: 2 additions & 2 deletions package/contents/ui/CompactRepresentation.qml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import QtQuick 2.0
import QtQuick

import "./mdi"

MouseArea {
onClicked: plasmoid.expanded = !plasmoid.expanded
onClicked: root.expanded = !root.expanded

MdiIcon {
name: "home-assistant"
Expand Down
133 changes: 68 additions & 65 deletions package/contents/ui/ConfigGeneral.qml
Original file line number Diff line number Diff line change
@@ -1,88 +1,91 @@
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

import org.kde.kirigami 2.4 as Kirigami
import org.kde.kirigami as Kirigami
import org.kde.kcmutils as KCM

Kirigami.FormLayout {
KCM.SimpleKCM {
property string cfg_url
property alias cfg_flat: flat.checked

signal configurationChanged

Secrets {
id: secrets
property string token
onReady: {
restore(cfg_url)
list().then(urls => (url.model = urls))
}

function restore(entryKey) {
if (!entryKey) {
return this.token = ""
Kirigami.FormLayout {
Secrets {
id: secrets
property string token
onReady: {
restore(cfg_url)
list().then(urls => (url.model = urls))
}

function restore(entryKey) {
if (!entryKey) {
return this.token = ""
}
get(entryKey)
.then(t => this.token = t)
.catch(() => this.token = "")
}
get(entryKey)
.then(t => this.token = t)
.catch(() => this.token = "")
}
}

Item {
Kirigami.FormData.isSection: true
Kirigami.FormData.label: i18n("API")
}

ComboBox {
id: url
editable: true
onModelChanged: currentIndex = indexOfValue(cfg_url)
onActiveFocusChanged: !activeFocus && setValue(editText)
onHoveredChanged: !hovered && setValue(editText)
onEditTextChanged: editText !== cfg_url && configurationChanged()
onActivated: {
secrets.restore(editText)
setValue(editText)
Item {
Kirigami.FormData.isSection: true
Kirigami.FormData.label: i18n("API")
}
Kirigami.FormData.label: i18n("Home Assistant URL")
Layout.fillWidth: true

function setValue(value) {
cfg_url = editText = value ? value.replace(/\s+|\/+\s*$/g,'') : ''
ComboBox {
id: url
editable: true
onModelChanged: currentIndex = indexOfValue(cfg_url)
onActiveFocusChanged: !activeFocus && setValue(editText)
onHoveredChanged: !hovered && setValue(editText)
onEditTextChanged: editText !== cfg_url && configurationChanged()
onActivated: {
secrets.restore(editText)
setValue(editText)
}
Kirigami.FormData.label: i18n("Home Assistant URL")
Layout.fillWidth: true

function setValue(value) {
cfg_url = editText = value ? value.replace(/\s+|\/+\s*$/g,'') : ''
}
}
}

Label {
text: i18n("Make sure the URL includes the protocol and port. For example:\nhttp://homeassistant.local:8123\nhttps://example.duckdns.org")
}
Label {
text: i18n("Make sure the URL includes the protocol and port. For example:\nhttp://homeassistant.local:8123\nhttps://example.duckdns.org")
}

TextField {
id: token
text: secrets.token
onTextChanged: text !== secrets.token && configurationChanged()
Kirigami.FormData.label: i18n("Token")
}
TextField {
id: token
text: secrets.token
onTextChanged: text !== secrets.token && configurationChanged()
Kirigami.FormData.label: i18n("Token")
}

Label {
text: i18n("Get token from your profile page")
}
Label {
text: i18n("Get token from your profile page")
}

Label {
text: `<a href="${url.editText}/profile">${url.editText}/profile</a>`
onLinkActivated: Qt.openUrlExternally(link)
visible: url.editText
}
Label {
text: `<a href="${url.editText}/profile">${url.editText}/profile</a>`
onLinkActivated: link => Qt.openUrlExternally(link)
visible: url.editText
}

Item {
Kirigami.FormData.isSection: true
Kirigami.FormData.label: i18n("Look")
}
Item {
Kirigami.FormData.isSection: true
Kirigami.FormData.label: i18n("Look")
}

CheckBox {
id: flat
Kirigami.FormData.label: i18n("Flat entities")
CheckBox {
id: flat
Kirigami.FormData.label: i18n("Flat entities")
}
}

function saveConfig() {
secrets.set(url.editText, token.text)
}
Expand Down
Loading

0 comments on commit 17662eb

Please sign in to comment.