├── .gitignore ├── README.md ├── convert.py └── flower-card.js /.gitignore: -------------------------------------------------------------------------------- 1 | data/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EARLY BETA 2 | 3 |  4 | 5 | ### Instructions 6 | 7 | 1: Install card (`type: module`) 8 | 9 | 2: Get CSV database file (No. I won't tell you where) 10 | 11 | 3: Run `python3 convert.py DBFileName.csv > data.js` 12 | 13 | 4: Move `data.js` to `www/lovelace-flower-card/data/data.js` 14 | 15 | 5: Get flower images and extract to `www/lovelace-flower-card/data/Images` 16 | 17 | 6: Setup card 18 | 19 | ```yaml 20 | type: custom:flower-card 21 | entity: plant.my_plant 22 | species: "tulipa 'hollandia'" 23 | ``` 24 | 25 | To get a list of the available species run `python3 convert.py DBFilename.csv species`. The value you want is the one after the colon. Enter it exactly like it says, with quotes and all. 26 | -------------------------------------------------------------------------------- /convert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import sys 4 | import csv 5 | import json 6 | 7 | filename = sys.argv[1] 8 | 9 | data = {} 10 | with open(filename) as csvfile: 11 | reader = csv.reader(csvfile) 12 | for ln, line in enumerate(reader): 13 | if ln > 0: 14 | data[line[0]] = list(line[i] for i in [1,2,19,18,21,20,25,24,27,26]) 15 | 16 | if len(sys.argv) > 2: 17 | for k,v in data.items(): 18 | print('{}: "{}"'.format(v[1], k)) 19 | else: 20 | print("'use strict';") 21 | print("const FlowerData =") 22 | print(json.dumps(data)) 23 | print(";") 24 | print("export {FlowerData};") 25 | -------------------------------------------------------------------------------- /flower-card.js: -------------------------------------------------------------------------------- 1 | import {FlowerData} from '/local/lovelace-flower-card/data/data.js'; 2 | customElements.whenDefined('card-tools').then(() => { 3 | class FlowerCard extends cardTools.LitElement { 4 | 5 | 6 | async setConfig(config) { 7 | 8 | this.config = config; 9 | 10 | } 11 | 12 | static get styles() { 13 | return cardTools.LitCSS` 14 | ha-card { 15 | margin-top: 32px; 16 | } 17 | .attributes { 18 | white-space: nowrap; 19 | padding: 8px; 20 | } 21 | .attribute ha-icon { 22 | float: left; 23 | margin-right: 4px; 24 | } 25 | .attribute { 26 | display: inline-block; 27 | width: 50%; 28 | white-space: normal; 29 | } 30 | 31 | .header { 32 | padding-top: 8px; 33 | height: 72px; 34 | } 35 | .header > img { 36 | width: 88px; 37 | border-radius: var(--ha-card-border-radius, 2px); 38 | margin-left: 16px; 39 | margin-right: 16px; 40 | margin-top: -32px; 41 | float: left; 42 | box-shadow: var( --ha-card-box-shadow, 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2) ); 43 | } 44 | .header > #name { 45 | font-weight: bold; 46 | width: 100%; 47 | margin-top: 16px; 48 | text-transform: capitalize; 49 | display: block; 50 | } 51 | .header > #species { 52 | text-transform: capitalize; 53 | color: #8c96a5; 54 | display: block; 55 | } 56 | .meter { 57 | height: 8px; 58 | background-color: #f1f1f1; 59 | border-radius: 2px; 60 | display: inline-grid; 61 | overflow: hidden; 62 | } 63 | .meter.red { 64 | width: 10%; 65 | } 66 | .meter.green { 67 | width: 50%; 68 | } 69 | .meter > span { 70 | grid-row: 1; 71 | grid-column: 1; 72 | height: 100%; 73 | } 74 | .meter > .good { 75 | background-color: rgba(43,194,83,1); 76 | } 77 | .meter > .bad { 78 | background-color: rgba(240,163,163); 79 | } 80 | .divider { 81 | height: 1px; 82 | background-color: #727272; 83 | opacity: 0.25; 84 | margin-left: 8px; 85 | margin-right: 8px; 86 | } 87 | `; 88 | } 89 | 90 | render() { 91 | const species = this.config.species; 92 | const Flower = FlowerData[species]; 93 | if(!this.stateObj) 94 | return cardTools.LitHtml``; 95 | 96 | const attribute = (icon, val, min, max) => { 97 | const pct = 100*Math.max(0, Math.min(1, (val-min)/(max-min))); 98 | return cardTools.LitHtml` 99 |