Big restructuring - repo is now a full home assistant config directory

This commit is contained in:
Martin Bauer
2019-06-30 19:37:32 +02:00
parent d35b9e132e
commit 808727ad92
79 changed files with 14378 additions and 27 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
{
"name": "state-card-custom-cover",
"version": "0.0.1",
"description": "Cover card from home assistant",
"main": "src/state-card-custom-cover.ts",
"scripts": {
"build": "webpack",
"test": "echo \"Error: no test specified\" && exit 1"
},
"private": true,
"author": "Martin Bauer",
"license": "GPLv3",
"devDependencies": {
"home-assistant-js-websocket": "^4.2.2",
"lit-element": "^2.1.0",
"ts-loader": "^6.0.2",
"typescript": "^3.5.1",
"webpack": "^4.33.0",
"webpack-cli": "^3.3.4"
}
}

View File

@@ -0,0 +1,26 @@
import {Connection, HassConfig, HassEntities, HassServices, MessageBase} from "home-assistant-js-websocket";
export interface HomeAssistant {
connection: Connection;
connected: boolean;
states: HassEntities;
services: HassServices;
config: HassConfig;
callService: (
domain: string,
service: string,
serviceData?: { [key: string]: any }
) => Promise<void>;
callApi: <T>(
method: "GET" | "POST" | "PUT" | "DELETE",
path: string,
parameters?: { [key: string]: any }
) => Promise<T>;
fetchWithAuth: (
path: string,
init?: { [key: string]: any }
) => Promise<Response>;
sendWS: (msg: MessageBase) => void;
callWS: <T>(msg: MessageBase) => Promise<T>;
}

View File

@@ -0,0 +1,208 @@
import {LitElement, html, css, customElement, property, TemplateResult, CSSResult} from "lit-element";
import {classMap} from "lit-html/directives/class-map";
import {HomeAssistant} from "./home-assistant-interface";
@customElement("room-glance-card")
export class RoomGlanceCard extends LitElement {
@property() public hass?: HomeAssistant;
@property() private _config?: any;
public setConfig(config: any) {
//if (!config || !config.entity) {
// throw new Error("Invalid configuration");
//}
console.log("Setting config", config);
this._config = config;
}
public static getCardSize(): number {
return 3;
}
protected render(): TemplateResult | void {
return html`
<ha-card>
<hui-image
class="${classMap({
clickable: true,
})}"
@ha-click="${this._handleTap}"
@ha-hold="${this._handleHold}"
.hass="${this.hass}"
image="${this._config.image}"
aspectRatio="${this._config.aspect_ratio}"
></hui-image>
<div class="box box-upper">
<div>${this._config.name}</div>
<div>
${this.renderCoverControl()}
</div>
</div>
<div class="box box-lower">
<div class="title"></div>
<div>
${this._config.scenes.map( (sceneButtonCfg) => this.renderSceneButton(sceneButtonCfg))}
<paper-icon-button
icon="mdi:close-circle"
@click=${this.serviceHandler("light", "turn_off")}
></paper-icon-button>
<paper-icon-button
icon="mdi:chevron-up"
title="Heller"
@click=${this.serviceHandler("dimmer", "dim", {offset: 30})}
></paper-icon-button>
<paper-icon-button
icon="mdi:chevron-down"
title="Dunkler"
@click=${this.serviceHandler("dimmer", "dim", {offset: -30})}
></paper-icon-button>
</div>
</div>
</ha-card>
`;
}
private renderSceneButton(buttonCfg: any) {
return html`
<paper-icon-button
icon="${buttonCfg.icon || "mdi:checkbox-blank"}"
style="color: ${buttonCfg.color || ""};"
title="${buttonCfg.name}"
@click=${this.serviceHandler("scene", "turn_on", {entity_id: buttonCfg.scene})}
></paper-icon-button>
`;
}
private renderCoverControl() {
return html`
<paper-icon-button
icon="hass:menu"
@click=${this.serviceHandler("cover_half", "set_half")}
></paper-icon-button>
<paper-icon-button
icon="hass:arrow-up"
@click=${this.serviceHandler("cover", "open_cover")}
></paper-icon-button>
<paper-icon-button
icon="hass:stop"
@click=${this.serviceHandler("cover", "stop_cover")}
></paper-icon-button>
<paper-icon-button
icon="hass:arrow-down"
@click=${this.serviceHandler("cover", "close_cover")}
></paper-icon-button>
`;
}
private serviceHandler(domain: string, service: string, serviceData: { [key: string]: any } = {})
{
const thisObj = this;
return function(ev) {
ev.stopPropagation();
thisObj.callServiceForAllEntities(domain, service, serviceData);
}
}
private callServiceForAllEntities(domain: string, service:string, serviceData: { [key: string]: any } = {}) {
if (!serviceData.hasOwnProperty('entity_id')) {
for (let entity_id of this._config!.entities) {
serviceData['entity_id'] = entity_id;
console.log("Calling service", domain, service, serviceData);
this.hass!.callService(domain, service, serviceData);
}
} else {
console.log("Calling service with given entity_id", domain, service, serviceData);
this.hass!.callService(domain, service, serviceData);
}
}
private _handleTap() {
console.log("Image tap");
}
private _handleHold() {
console.log("Image hold");
}
static get styles(): CSSResult {
return css`
ha-card {
position: relative;
min-height: 48px;
overflow: hidden;
}
hui-image.clickable {
cursor: pointer;
}
.box {
/* start paper-font-common-nowrap style */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
/* end paper-font-common-nowrap style */
position: absolute;
left: 0;
right: 0;
padding-left: 8px;
padding-right: 8px;
font-size: 16px;
line-height: 40px;
color: white;
display: flex;
justify-content: space-between;
background-color: rgba(0, 0, 0, 0.3);
}
.box-upper {
bottom: 45px;
padding-top: 4px;
padding-bottom: 0;
}
.box-lower {
bottom: 0;
padding-top: 0;
padding-bottom: 0px;
height:45px;
}
.box .title {
font-weight: 500;
margin-left: 8px;
}
ha-icon {
cursor: pointer;
padding: 8px;
color: #a9a9a9;
}
ha-icon.state-on {
color: white;
}
`;
}
}

View File

@@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "es2017",
"module": "esnext",
"moduleResolution": "node",
"lib": [
"es2017",
"dom",
"dom.iterable"
],
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"strict": true,
"noImplicitAny": false,
"skipLibCheck": true,
"resolveJsonModule": true,
"experimentalDecorators": true
}
}

View File

@@ -0,0 +1,19 @@
const path = require('path');
module.exports = {
entry: "./src/room-glance-card.ts",
output: {
filename: 'room-glance-card.js',
path: path.resolve(__dirname, 'dist')
},
resolve: {
extensions: [".tsx", ".ts", ".js", ".json"]
},
module: {
rules: [
// all files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'
{test: /\.tsx?$/, use: ["ts-loader"], exclude: /node_modules/}
]
},
mode: "production"
}