From d3c6e52f3f5bae6054f8fc05b241a1e9b0a6ca1c Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Sat, 18 Nov 2023 13:55:55 +0100 Subject: [PATCH] Added individual LED control --- src/lib/locales/en.json | 5 ++ src/lib/locales/es.json | 5 ++ src/lib/locales/nl.json | 5 ++ src/routes/+page.svelte | 28 ++++++- src/routes/Control.svelte | 54 ++++++++++++- src/routes/Status.svelte | 32 +------- static/swagger.json | 109 ++++++++++++++++++++++----- static/{swagger.yaml => swagger.yml} | 54 ++++++++++++- 8 files changed, 237 insertions(+), 55 deletions(-) rename static/{swagger.yaml => swagger.yml} (81%) diff --git a/src/lib/locales/en.json b/src/lib/locales/en.json index a32b77b..d634291 100644 --- a/src/lib/locales/en.json +++ b/src/lib/locales/en.json @@ -62,5 +62,10 @@ "timer": { "running": "running", "stopped": "stopped" + }, + "sections": { + "control": { + "keepSameColor": "Keep same color" + } } } diff --git a/src/lib/locales/es.json b/src/lib/locales/es.json index ace51cf..c3958ae 100644 --- a/src/lib/locales/es.json +++ b/src/lib/locales/es.json @@ -62,5 +62,10 @@ "timer": { "running": "funcionando", "stopped": "detenido" + }, + "sections": { + "control": { + "keepSameColor": "Mantén el mismo color" + } } } diff --git a/src/lib/locales/nl.json b/src/lib/locales/nl.json index 7028b52..24c2396 100644 --- a/src/lib/locales/nl.json +++ b/src/lib/locales/nl.json @@ -61,5 +61,10 @@ "timer": { "running": "actief", "stopped": "gestopt" + }, + "sections": { + "control": { + "keepSameColor": "Behoud zelfde kleur" + } } } diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index d581125..28b617b 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -14,6 +14,17 @@ fgColor: "0" }); + let status = writable({ + data: ["L", "O", "A", "D", "I", "N", "G"], + espFreeHeap: 0, + espHeapSize: 0, + connectionStatus: { + "price": false, + "blocks": false + }, + leds: [] + }); + onMount(() => { fetch( PUBLIC_BASE_URL + `/api/settings`) .then((res) => res.json()) @@ -31,6 +42,19 @@ } settings.set(data); }); + + fetch(`${PUBLIC_BASE_URL}/api/status`) + .then((res) => res.json()) + .then((data) => { + status.set(data); + }); + + const evtSource = new EventSource(`${PUBLIC_BASE_URL}/events`); + + evtSource.addEventListener('status', (e) => { + let dataObj = (JSON.parse(e.data)); + status.set(dataObj); + }); }); @@ -40,8 +64,8 @@ - - + + diff --git a/src/routes/Control.svelte b/src/routes/Control.svelte index 0d97371..23b13c3 100644 --- a/src/routes/Control.svelte +++ b/src/routes/Control.svelte @@ -1,6 +1,9 @@ @@ -54,7 +89,7 @@ const forceFullRefresh = () => { - + @@ -66,7 +101,18 @@ const forceFullRefresh = () => { - + + {#if ledStatus} + {#each ledStatus as led, i } + + + + {/each} + {/if} + + + + diff --git a/src/routes/Status.svelte b/src/routes/Status.svelte index 059426a..3195ad8 100644 --- a/src/routes/Status.svelte +++ b/src/routes/Status.svelte @@ -3,36 +3,12 @@ import { onMount } from 'svelte'; import { _ } from 'svelte-i18n'; - import { writable } from 'svelte/store'; + import { writable, type Writable } from 'svelte/store'; import { Row, Input, Button, ButtonGroup, Card, CardBody, CardHeader, Col, Progress,CardTitle } from 'sveltestrap'; import Rendered from './Rendered.svelte'; export let settings; - - const status = writable({ - data: ["L", "O", "A", "D", "I", "N", "G"], - espFreeHeap: 0, - espHeapSize: 0, - connectionStatus: { - "price": false, - "blocks": false - } - }); - - onMount(() => { - fetch(`${PUBLIC_BASE_URL}/api/status`) - .then((res) => res.json()) - .then((data) => { - status.set(data); - }); - - const evtSource = new EventSource(`${PUBLIC_BASE_URL}/events`); - - evtSource.addEventListener('status', (e) => { - let dataObj = (JSON.parse(e.data)); - status.set(dataObj); - }); - }); + export let status:Writable<{}>; const toTime = (secs:Number) => { var hours = Math.floor(secs / (60 * 60)); @@ -60,11 +36,11 @@ let memoryFreePercent:number = 50; let lightMode:boolean = false; - status.subscribe((value) => { + status.subscribe((value: {}) => { memoryFreePercent = Math.round(value.espFreeHeap / value.espHeapSize * 100); }); - settings.subscribe((value) => { + settings.subscribe((value: {}) => { lightMode = value.bgColor > value.fgColor; }); diff --git a/static/swagger.json b/static/swagger.json index 83ee5ec..565e997 100644 --- a/static/swagger.json +++ b/static/swagger.json @@ -7,7 +7,7 @@ }, "servers": [ { - "url": "/api/" + "url": "http://192.168.20.231/api/" } ], "paths": { @@ -216,7 +216,37 @@ "summary": "Get LEDs status", "responses": { "200": { - "description": "successful operation" + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArrayOfLeds" + } + } + } + } + } + }, + "patch": { + "tags": [ + "lights" + ], + "summary": "Set individual LEDs", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ArrayOfLedsInput" + } + } + } + }, + "responses": { + "200": { + "description": "succesful operation" + }, + "400": { + "description": "invalid colors or wrong amount of LEDs" } } } @@ -275,24 +305,69 @@ }, "components": { "schemas": { + "RgbColorValues": { + "type": "object", + "properties": { + "red": { + "type": "integer", + "minimum": 0, + "maximum": 255, + "example": 255 + }, + "green": { + "type": "integer", + "minimum": 0, + "maximum": 255, + "example": 204 + }, + "blue": { + "type": "integer", + "minimum": 0, + "maximum": 255, + "example": 0 + } + } + }, + "RgbColorHex": { + "type": "object", + "properties": { + "hex": { + "type": "string", + "pattern": "^#(?:[0-9a-fA-F]{3}){1,2}$", + "example": "#FFCC00" + } + } + }, + "RgbColorValueAndHex": { + "allOf": [ + { + "$ref": "#/components/schemas/RgbColorValues" + }, + { + "$ref": "#/components/schemas/RgbColorHex" + } + ] + }, + "RgbColorValueOrHex": { + "oneOf": [ + { + "$ref": "#/components/schemas/RgbColorValues" + }, + { + "$ref": "#/components/schemas/RgbColorHex" + } + ] + }, "ArrayOfLeds": { "type": "array", "items": { - "type": "object", - "properties": { - "red": { - "type": "integer" - }, - "green": { - "type": "integer" - }, - "blue": { - "type": "integer" - }, - "hex": { - "type": "string" - } - } + "$ref": "#/components/schemas/RgbColorValueAndHex" + } + }, + "ArrayOfLedsInput": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RgbColorValueOrHex" } }, "Settings": { diff --git a/static/swagger.yaml b/static/swagger.yml similarity index 81% rename from static/swagger.yaml rename to static/swagger.yml index 966d614..9300f73 100644 --- a/static/swagger.yaml +++ b/static/swagger.yml @@ -4,7 +4,7 @@ info: version: '3.0' description: BTClock V3 API servers: - - url: /api/ + - url: http://192.168.20.231/api/ paths: /status: get: @@ -135,6 +135,24 @@ paths: responses: '200': description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ArrayOfLeds' + patch: + tags: + - lights + summary: Set individual LEDs + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ArrayOfLedsInput' + responses: + "200": + description: succesful operation + "400": + description: invalid colors or wrong amount of LEDs /lights/{color}: get: tags: @@ -169,19 +187,47 @@ paths: description: successful operation components: schemas: - ArrayOfLeds: - type: array - items: + RgbColorValues: type: object properties: red: type: integer + minimum: 0 + maximum: 255 + example: 255 green: type: integer + minimum: 0 + maximum: 255 + example: 204 blue: type: integer + minimum: 0 + maximum: 255 + example: 0 + RgbColorHex: + type: object + properties: hex: type: string + pattern: ^#(?:[0-9a-fA-F]{3}){1,2}$ + example: "#FFCC00" + RgbColorValueAndHex: + allOf: + - $ref: '#/components/schemas/RgbColorValues' + - $ref: '#/components/schemas/RgbColorHex' + RgbColorValueOrHex: + oneOf: + - $ref: '#/components/schemas/RgbColorValues' + - $ref: '#/components/schemas/RgbColorHex' + ArrayOfLeds: + type: array + items: + $ref: '#/components/schemas/RgbColorValueAndHex' + ArrayOfLedsInput: + type: array + items: + $ref: '#/components/schemas/RgbColorValueOrHex' Settings: type: object properties: