-
-
Save m33x/62f6e8f6eab546e4b3a854695ea8c3a8 to your computer and use it in GitHub Desktop.
| let widget = await createWidget(); | |
| if (!config.runsInWidget) { | |
| await widget.presentSmall(); | |
| } | |
| Script.setWidget(widget); | |
| Script.complete(); | |
| async function createWidget(items) { | |
| /* Get data from API */ | |
| const tempImg = await getImage('temperature.png'); | |
| const humidImg = await getImage('humidity.png'); | |
| const logoImg = await getImage('hass-favicon.png'); | |
| let req = new Request("https://<HASS IP>/api/states") | |
| req.headers = { "Authorization": "Bearer <HASS Long-Lived Access Token at https://<HASS IP>/profile", "content-type": "application/json" } | |
| let json = await req.loadJSON(); | |
| /* Parse data received from API */ | |
| let data = {outdoor: {}, child: {}, office: {}, bedroom: {}, livingroom: {}, kitchen: {}, hallway: {}, bathroom: {}, wc: {}} | |
| data.outdoor = addData(json, data.outdoor, ['sensor.ble_temperature_aabbccddeeff', 'sensor.ble_humidity_aabbccddeeff']); | |
| data.child = addData(json, data.child, ['sensor.ble_temperature_aabbccddeeff', 'sensor.ble_humidity_aabbccddeeff']); | |
| data.office = addData(json, data.office, ['sensor.ble_temperature_aabbccddeeff', 'sensor.ble_humidity_aabbccddeeff']); | |
| data.bedroom = addData(json, data.bedroom, ['sensor.ble_temperature_aabbccddeeff', 'sensor.ble_humidity_aabbccddeeff']); | |
| data.livingroom = addData(json, data.livingroom, ['sensor.ble_temperature_aabbccddeeff', 'sensor.ble_humidity_aabbccddeeff']); | |
| data.kitchen = addData(json, data.kitchen, ['sensor.ble_temperature_aabbccddeeff', 'sensor.ble_humidity_aabbccddeeff']); | |
| data.hallway = addData(json, data.hallway, ['sensor.ble_temperature_aabbccddeeff', 'sensor.ble_humidity_aabbccddeeff']); | |
| data.bathroom = addData(json, data.bathroom, ['sensor.ble_temperature_aabbccddeeff', 'sensor.ble_humidity_aabbccddeeff']); | |
| data.wc = addData(json, data.wc, ['sensor.ble_temperature_aabbccddeeff', 'sensor.ble_humidity_aabbccddeeff']); | |
| /* Create the widget */ | |
| const widget = new ListWidget(); | |
| widget.backgroundColor = new Color("#03a9f4", 1.0); | |
| /* Design the widget header */ | |
| let headerStack = widget.addStack(); | |
| const logoStack = headerStack.addStack(); | |
| headerStack.addSpacer(2); | |
| const titleStack = headerStack.addStack(); | |
| headerStack.addSpacer(7); | |
| const tempImageStack = headerStack.addStack(); | |
| headerStack.addSpacer(14); | |
| const humidImageStack = headerStack.addStack(); | |
| /* Add a logo icon */ | |
| logoStack.backgroundColor = new Color("#03a9f4", 1.0) | |
| logoStack.cornerRadius = 1 | |
| const wimgLogo = logoStack.addImage(logoImg) | |
| wimgLogo.imageSize = new Size(20, 20) | |
| wimgLogo.rightAlignImage() | |
| /* Add the name of this Home Assistant */ | |
| const titleLabel = titleStack.addText("HA42"); | |
| titleStack.setPadding(2, 0, 0, 0); | |
| titleLabel.font = Font.heavyMonospacedSystemFont(12); | |
| titleLabel.textColor = Color.black(); | |
| /* Add a temperature icon */ | |
| tempImageStack.backgroundColor = new Color("#03a9f4", 1.0) | |
| tempImageStack.cornerRadius = 1 | |
| const wimgTemp = tempImageStack.addImage(tempImg) | |
| wimgTemp.imageSize = new Size(20, 20) | |
| wimgTemp.rightAlignImage() | |
| /* Add a humid icon */ | |
| humidImageStack.backgroundColor = new Color("#03a9f4", 1.0) | |
| humidImageStack.cornerRadius = 1 | |
| const wimgHumid = humidImageStack.addImage(humidImg) | |
| wimgHumid.imageSize = new Size(20, 20) | |
| wimgHumid.rightAlignImage() | |
| widget.addSpacer(5) | |
| /* Add the sensor entries */ | |
| const bodyStack = widget.addStack(); | |
| /* First, the label column */ | |
| const labelStack = bodyStack.addStack(); | |
| labelStack.setPadding(0, 0, 0, 0); | |
| labelStack.borderWidth = 0; | |
| labelStack.layoutVertically(); | |
| addLabel(labelStack, " Outdoor:") | |
| addLabel(labelStack, " Child:") | |
| addLabel(labelStack, " Office:") | |
| addLabel(labelStack, " Bedroom:") | |
| addLabel(labelStack, " Living:") | |
| addLabel(labelStack, " Kitchen:") | |
| addLabel(labelStack, " Hallway:") | |
| addLabel(labelStack, " Bathroom:") | |
| addLabel(labelStack, " WC:") | |
| /* Second, the temperature column */ | |
| const tempStack = bodyStack.addStack(); | |
| tempStack.setPadding(0, 3, 0, 0); | |
| tempStack.borderWidth = 0; | |
| tempStack.layoutVertically(); | |
| addTemp(tempStack, data.outdoor) | |
| addTemp(tempStack, data.child) | |
| addTemp(tempStack, data.office) | |
| addTemp(tempStack, data.bedroom) | |
| addTemp(tempStack, data.livingroom) | |
| addTemp(tempStack, data.kitchen) | |
| addTemp(tempStack, data.hallway) | |
| addTemp(tempStack, data.bathroom) | |
| addTemp(tempStack, data.wc) | |
| /* Third, the humidity column */ | |
| const humidStack = bodyStack.addStack(); | |
| humidStack.setPadding(0, 5, 0, 0); | |
| humidStack.borderWidth = 0; | |
| humidStack.layoutVertically(); | |
| addHumid(humidStack, data.outdoor) | |
| addHumid(humidStack, data.child) | |
| addHumid(humidStack, data.office) | |
| addHumid(humidStack, data.bedroom) | |
| addHumid(humidStack, data.livingroom) | |
| addHumid(humidStack, data.kitchen) | |
| addHumid(humidStack, data.hallway) | |
| addHumid(humidStack, data.bathroom) | |
| addHumid(humidStack, data.wc) | |
| /* Done: Widget is now ready to be displayed */ | |
| return widget; | |
| } | |
| /* Adds the entries to the label column */ | |
| async function addLabel(labelStack, label) { | |
| const mytext = labelStack.addText(label); | |
| mytext.font = Font.semiboldSystemFont(10); | |
| mytext.textColor = Color.black(); | |
| } | |
| /* Adds the entries to the temperature column */ | |
| async function addTemp(tempStack, data) { | |
| const mytext = tempStack.addText(data.temp + "°C"); | |
| mytext.font = Font.heavyMonospacedSystemFont(10); | |
| mytext.textColor = Color.white(); | |
| } | |
| /* Adds the entries to the humidity column */ | |
| async function addHumid(humidStack, data) { | |
| const mytext = humidStack.addText("(" + data.humid + "%)"); | |
| mytext.font = Font.mediumMonospacedSystemFont(10); | |
| mytext.textColor = Color.white(); | |
| mytext.textOpacity = 0.8; | |
| } | |
| /* | |
| The following function is "borrowed" from: | |
| https://gist.github.com/marco79cgn/23ce08fd8711ee893a3be12d4543f2d2 | |
| Retrieves the image from the local file store or downloads it once | |
| */ | |
| async function getImage(image) { | |
| let fm = FileManager.local() | |
| let dir = fm.documentsDirectory() | |
| let path = fm.joinPath(dir, image) | |
| if (fm.fileExists(path)) { | |
| return fm.readImage(path) | |
| } else { | |
| // download once | |
| let imageUrl | |
| switch (image) { | |
| case 'temperature.png': | |
| imageUrl = "https://<YOU NEED TO HOST THIS>/temperature.png" | |
| break | |
| case 'humidity.png': | |
| imageUrl = "https://<YOU NEED TO HOST THIS>/humidity.png" | |
| break | |
| case 'hass-favicon.png': | |
| imageUrl = "https://<HASS IP>/static/icons/favicon-192x192.png" | |
| break | |
| default: | |
| console.log(`Sorry, couldn't find ${image}.`); | |
| } | |
| let iconImage = await loadImage(imageUrl) | |
| fm.writeImage(path, iconImage) | |
| return iconImage | |
| } | |
| } | |
| /* | |
| The following function is "borrowed" from: | |
| https://gist.github.com/marco79cgn/23ce08fd8711ee893a3be12d4543f2d2 | |
| Downloads an image from a given URL | |
| */ | |
| async function loadImage(imgUrl) { | |
| const req = new Request(imgUrl) | |
| return await req.loadImage() | |
| } | |
| /* Searches for the respective sensor values ('state') in the API response of Home Assistant */ | |
| function addData(json, room, sensors) { | |
| room.temp = "N/A"; | |
| room.humid = "N/A"; | |
| var i; | |
| for (i = 0; i < json.length; i++) { | |
| if (json[i]['entity_id'] == sensors[0]) { | |
| room.temp = Math.round(json[i]['state']); | |
| } | |
| if (json[i]['entity_id'] == sensors[1]) { | |
| room.humid = Math.round(json[i]['state']); | |
| } | |
| } | |
| return room; | |
| } |
How often does it update the values?
I could not find any constant refresh interval, looks like, it is updated on-demand and depends on how often you look at your home screen.
10.0.0.110 - - [18/Feb/2022:09:36:42 +0100] "GET /api/states HTTP/1.1" 200 27597 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:09:41:50 +0100] "GET /api/states HTTP/1.1" 200 27591 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:09:47:00 +0100] "GET /api/states HTTP/1.1" 200 27567 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:10:00:02 +0100] "GET /api/states HTTP/1.1" 200 27618 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:10:15:20 +0100] "GET /api/states HTTP/1.1" 200 27590 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:10:47:44 +0100] "GET /api/states HTTP/1.1" 200 27607 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:10:53:14 +0100] "GET /api/states HTTP/1.1" 200 27644 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:11:14:55 +0100] "GET /api/states HTTP/1.1" 200 27766 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:11:29:51 +0100] "GET /api/states HTTP/1.1" 200 27811 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:11:35:19 +0100] "GET /api/states HTTP/1.1" 200 27767 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:12:00:06 +0100] "GET /api/states HTTP/1.1" 200 27762 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:12:15:31 +0100] "GET /api/states HTTP/1.1" 200 27740 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:12:45:03 +0100] "GET /api/states HTTP/1.1" 200 27764 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:13:00:05 +0100] "GET /api/states HTTP/1.1" 200 27731 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
10.0.0.110 - - [18/Feb/2022:13:14:53 +0100] "GET /api/states HTTP/1.1" 200 27742 "-" "ScriptableWidgetExtension/187 CFNetwork/1329 Darwin/21.3.0"
I am having trouble getting the widget to load.
How do I add individual text like „km“ or „min“ after each sensor data? I do not want to add „%“ to the whole column.
ext like „km“ or „min“ after each sensor data? I do not want to add „%“ to the whole column.
for example i wanted to return the produce of my solar panels.
let valueLabel = mainStack.addText(${result.value}W);
This is based on the gauge script on this gist.
the "W" is like you want or km or min.
see my full script an example of a forked (edited) version from gauge script m33x
https://gist.github.com/malosaa/c2611c8e490d6e0af1b5366577b5e2ba
Thank you very much !