Skip to content

Commit

Permalink
Add brightness to group switch case
Browse files Browse the repository at this point in the history
  • Loading branch information
amberstarlight committed Oct 13, 2024
1 parent 069dd66 commit 36d7c12
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 13 deletions.
14 changes: 5 additions & 9 deletions packages/api/routes/groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import express, { Request, Response, Router } from "express";
import { Zigbee2MqttService } from "../zigbee2mqttService";
import { ApiError } from "./api";
import { range } from "../utils";
import { nextUnused, range } from "../utils";
import { type Group, Scene } from "@starlight/types";

const router = express.Router();
Expand Down Expand Up @@ -277,14 +277,10 @@ export function groupsRouter(zigbee2mqttService: Zigbee2MqttService): Router {
return res.status(404).json({ error: ApiError.NameInUse });
}

let sceneId: number = 0;
const idRange = range(0, 255);

if (group.group.scenes.length !== 0) {
const usedIds = new Set(group.group.scenes.map((scene) => scene.id));
const feasibleIds = idRange.filter((value) => !usedIds.has(value));
sceneId = Math.min(...feasibleIds);
}
let sceneId = nextUnused(
group.group.scenes.map((scene) => scene.id),
range(0, 255),
);

// transition on scenes can only be set with 'scene_add', so if we have the
// property in the body we should first call createOrUpdateScene with just
Expand Down
12 changes: 12 additions & 0 deletions packages/api/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,15 @@ export function range(
.fill(start)
.map((_, index) => start + index * step);
}

export function nextUnused(items: Array<number>, range: Array<number>): number {
let nextUnused: number = 0;

if (items.length !== 0) {
const usedNumbers = new Set(items);
const feasibleNumbers = range.filter((value) => !usedNumbers.has(value));
nextUnused = Math.min(...feasibleNumbers);
}

return nextUnused;
}
52 changes: 50 additions & 2 deletions packages/ui/src/components/GroupSettings/GroupSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

import { useState, useEffect } from "react";
import { useLocation } from "wouter";

import {
mqttStateToBoolean,
booleanToMqttState,
updateGroupState,
percentage,
} from "../../utils/deviceUtilities";
import LoadingSpinner from "../LoadingSpinner/LoadingSpinner";
import Button from "../Button/Button";
import EditableText from "../EditableText/EditableText";
import LoadingSpinner from "../LoadingSpinner/LoadingSpinner";
import Slider from "../Slider/Slider";
import Toggle from "../Toggle/Toggle";

const backend = import.meta.env.VITE_API_URL ?? "";
Expand All @@ -26,15 +30,36 @@ function GroupSettings(props) {
.then((data) => setGroupSettingsState(data.data));
};

const [location, navigate] = useLocation();

useEffect(() => {
fetchGroupState();
}, []);

const deleteButton = (
<Button
text={"❌ Remove Group"}
onClick={() => {
const request = new Request(`${backend}/api/groups/${props.group.id}`, {
method: "DELETE",
});
fetch(request)
.then((res) => res.json())
.then((data) => console.log(data))
.finally(() => navigate("/groups"));
// we also want to refresh the groups list but this works for now
}}
/>
);

if (!groupSettingsState) return <LoadingSpinner />;

const groupSettingsGenerator = (groupSettingsState, callback) => {
const settingComponents = [];

// the API doesn't give us data yet about how we should transform the state
// values, so to get this working initially we can hardcode what we expect

for (const setting in groupSettingsState) {
switch (setting) {
case "state":
Expand All @@ -51,11 +76,32 @@ function GroupSettings(props) {
/>,
);
break;
case "brightness":
settingComponents.push(
<Slider
key={"brightness"}
label={"Brightness"}
min={1}
max={254}
step={1}
value={groupSettingsState[setting]}
displayUnit={"%"}
displayValue={percentage(groupSettingsState[setting], 254)}
onChange={(event) => {
const newMqttValue = event.target.value;
updateGroupState(props.group.id, setting, newMqttValue).then(
callback,
);
}}
/>,
);
default:
break;
}
}
return settingComponents;

// i want "State" to be first, so here's a tiny hack
return settingComponents.reverse();
};

return (
Expand All @@ -75,8 +121,10 @@ function GroupSettings(props) {
// );
// }}
/>
<p>{`${props.group.members.length} devices`}</p>
</div>
<div>{groupSettingsGenerator(groupSettingsState, fetchGroupState)}</div>
<div>{deleteButton}</div>
</>
);
}
Expand Down
3 changes: 3 additions & 0 deletions packages/ui/src/utils/deviceUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,6 @@ export const stringTidy = (string) => {
.map((word) => word[0].toUpperCase() + word.slice(1).toLowerCase())
.join(" ");
};

export const percentage = (value, maxValue) =>
Math.floor((value / maxValue) * 100);
3 changes: 1 addition & 2 deletions packages/ui/src/utils/transformers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ import {
miredToKelvin,
stringTidy,
updateDeviceState,
percentage,
} from "./deviceUtilities";

const percentage = (value, maxValue) => Math.floor((value / maxValue) * 100);

export const numericTransformer = (
feature,
device,
Expand Down

0 comments on commit 36d7c12

Please sign in to comment.