Skip to content

Commit

Permalink
validate hex colors on input
Browse files Browse the repository at this point in the history
v0.5.1
  • Loading branch information
AlCalzone committed Oct 28, 2017
1 parent 0eb70f4 commit fd089e7
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 18 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ The result object `ret` looks as follows:

## Changelog

#### 0.5.0 (2017-10-28)
#### 0.5.1 (2017-10-28)
* (AlCalzone) Support virtual groups
* (AlCalzone) Validate hex colors on input

#### 0.4.5 (2017-10-20)
* (AlCalzone) RGB and connection fixes.
Expand Down
2 changes: 2 additions & 0 deletions build/lib/colors.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/** Normalizes any input that might represent a hex color. Returns undefined if no match was found */
export declare function normalizeHexColor(color: string): string;
13 changes: 13 additions & 0 deletions build/lib/colors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// accept a bunch of stuff that follows 2 rules
// 1. ends with 6 hex digits
// 2. the remainder does not contain letters or digits
const hexColorRegex = /^[^a-zA-Z0-9]*([a-fA-F0-9]{6})$/;
/** Normalizes any input that might represent a hex color. Returns undefined if no match was found */
function normalizeHexColor(color) {
const match = hexColorRegex.exec(color);
if (match && match.length > 1)
return match[1];
}
exports.normalizeHexColor = normalizeHexColor;
44 changes: 37 additions & 7 deletions build/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const virtual_group_1 = require("./lib/virtual-group");
// Adapter-Utils laden
const utils_1 = require("./lib/utils");
// Adapter-Module laden
const colors_1 = require("./lib/colors");
const custom_subscriptions_1 = require("./modules/custom-subscriptions");
const gateway_1 = require("./modules/gateway");
const groups_1 = require("./modules/groups");
Expand Down Expand Up @@ -192,7 +193,18 @@ let adapter = utils_1.default.adapter({
sceneId: val,
}));
}
else if (/\.(colorTemperature|color|hue|saturation)$/.test(id)) {
else if (id.endsWith(".color")) {
val = colors_1.normalizeHexColor(val);
if (val != null) {
state.val = val;
yield operations_1.operateVirtualGroup(group, {
color: val,
transitionTime: yield getTransitionDuration(group),
});
wasAcked = true;
}
}
else if (/\.(colorTemperature|hue|saturation)$/.test(id)) {
// color change is only supported manually, so we operate
// the virtual state of this group
yield operations_1.operateVirtualGroup(group, {
Expand All @@ -214,6 +226,7 @@ let adapter = utils_1.default.adapter({
// find the virtual group instance
const vGroup = gateway_1.gateway.virtualGroups[rootObj.native.instanceId];
let operation;
let wasAcked = false;
if (id.endsWith(".state")) {
operation = {
onOff: val,
Expand All @@ -225,21 +238,34 @@ let adapter = utils_1.default.adapter({
transitionTime: yield getTransitionDuration(vGroup),
};
}
else if (/\.(colorTemperature|color|hue|saturation)$/.test(id)) {
else if (id.endsWith(".color")) {
val = colors_1.normalizeHexColor(val);
if (val != null) {
state.val = val;
operation = {
dimmer: val,
transitionTime: yield getTransitionDuration(vGroup),
};
}
}
else if (/\.(colorTemperature|hue|saturation)$/.test(id)) {
operation = {
[id.substr(id.lastIndexOf(".") + 1)]: val,
transitionTime: yield getTransitionDuration(vGroup),
};
}
else if (id.endsWith(".transitionDuration")) {
// No operation here, since this is part of another one
wasAcked = true;
}
// update all lightbulbs in this group
if (operation != null) {
operations_1.operateVirtualGroup(vGroup, operation);
wasAcked = true;
}
// and ack the state change
adapter.$setState(id, state, true);
if (wasAcked)
adapter.$setState(id, state, true);
return;
}
default: {
Expand Down Expand Up @@ -267,10 +293,14 @@ let adapter = utils_1.default.adapter({
// might already have "color" states for white spectrum bulbs
// in the future, we create different states for white and RGB bulbs
if (light.spectrum === "rgb") {
wasAcked = !(yield operations_1.operateLight(accessory, {
color: val,
transitionTime: yield getTransitionDuration(accessory),
}));
val = colors_1.normalizeHexColor(val);
if (val != null) {
state.val = val;
wasAcked = !(yield operations_1.operateLight(accessory, {
color: val,
transitionTime: yield getTransitionDuration(accessory),
}));
}
}
else if (light.spectrum === "white") {
wasAcked = !(yield operations_1.operateLight(accessory, {
Expand Down
4 changes: 2 additions & 2 deletions io-package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"common": {
"name": "tradfri",
"version": "0.5.0",
"version": "0.5.1",
"news": {
"0.5.0": {
"0.5.1": {
"en": "Support of virtual groups",
"de": "Unterstützung virtueller Gruppen"
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "iobroker.tradfri",
"version": "0.5.0",
"version": "0.5.1",
"description": "ioBroker tradfri Adapter",
"author": {
"name": "AlCalzone",
Expand Down
34 changes: 34 additions & 0 deletions src/lib/colors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { expect } from "chai";
import { normalizeHexColor } from "./colors";
// tslint:disable:no-unused-expression

describe.only("lib/colors => normalizeHexColor() =>", () => {

it("should not change valid hex colors without #", () => {
const sampleColors = [
"000000", "0a0a0a", "A5A5A5", "FFEEDD", "abcdef",
];
for (const hex of sampleColors) {
expect(normalizeHexColor(hex)).to.equal(hex);
}
});

it("should strip the prefix off strings that might represent hex colors", () => {
const sampleColors = [
"#000000", ".,-0a0a0a", "####A5A5A5", "%FFEEDD", "$$$abcdef",
];
for (const hex of sampleColors) {
expect(normalizeHexColor(hex)).to.equal(hex.substr(-6));
}
});

it("should return undefined for stuff that's not almost a hex string", () => {
const sampleColors = [
"A000000", "Z0a0a0a", "6A5A5A5", "aFFEEDD", "a_abcdef",
];
for (const hex of sampleColors) {
expect(normalizeHexColor(hex)).to.be.undefined;
}
});

});
9 changes: 9 additions & 0 deletions src/lib/colors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// accept a bunch of stuff that follows 2 rules
// 1. ends with 6 hex digits
// 2. the remainder does not contain letters or digits
const hexColorRegex = /^[^a-zA-Z0-9]*([a-fA-F0-9]{6})$/;
/** Normalizes any input that might represent a hex color. Returns undefined if no match was found */
export function normalizeHexColor(color: string): string {
const match = hexColorRegex.exec(color);
if (match && match.length > 1) return match[1];
}
41 changes: 34 additions & 7 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { VirtualGroup } from "./lib/virtual-group";
import utils from "./lib/utils";

// Adapter-Module laden
import { normalizeHexColor } from "./lib/colors";
import { applyCustomObjectSubscriptions, applyCustomStateSubscriptions, subscribeStates } from "./modules/custom-subscriptions";
import { gateway as gw, GroupInfo } from "./modules/gateway";
import { calcGroupId, calcGroupName, extendGroup, updateGroupStates, updateMultipleGroupStates } from "./modules/groups";
Expand Down Expand Up @@ -202,7 +203,17 @@ let adapter: ExtendedAdapter = utils.adapter({
onOff: true,
sceneId: val,
});
} else if (/\.(colorTemperature|color|hue|saturation)$/.test(id)) {
} else if (id.endsWith(".color")) {
val = normalizeHexColor(val);
if (val != null) {
state.val = val;
await operateVirtualGroup(group, {
color: val,
transitionTime: await getTransitionDuration(group),
});
wasAcked = true;
}
} else if (/\.(colorTemperature|hue|saturation)$/.test(id)) {
// color change is only supported manually, so we operate
// the virtual state of this group
await operateVirtualGroup(group, {
Expand All @@ -225,6 +236,7 @@ let adapter: ExtendedAdapter = utils.adapter({
const vGroup = gw.virtualGroups[rootObj.native.instanceId];

let operation: LightOperation;
let wasAcked: boolean = false;

if (id.endsWith(".state")) {
operation = {
Expand All @@ -235,22 +247,33 @@ let adapter: ExtendedAdapter = utils.adapter({
dimmer: val,
transitionTime: await getTransitionDuration(vGroup),
};
} else if (/\.(colorTemperature|color|hue|saturation)$/.test(id)) {
} else if (id.endsWith(".color")) {
val = normalizeHexColor(val);
if (val != null) {
state.val = val;
operation = {
dimmer: val,
transitionTime: await getTransitionDuration(vGroup),
};
}
} else if (/\.(colorTemperature|hue|saturation)$/.test(id)) {
operation = {
[id.substr(id.lastIndexOf(".") + 1)]: val,
transitionTime: await getTransitionDuration(vGroup),
};
} else if (id.endsWith(".transitionDuration")) {
// No operation here, since this is part of another one
wasAcked = true;
}

// update all lightbulbs in this group
if (operation != null) {
operateVirtualGroup(vGroup, operation);
wasAcked = true;
}

// and ack the state change
adapter.$setState(id, state, true);
if (wasAcked) adapter.$setState(id, state, true);
return;
}

Expand Down Expand Up @@ -279,10 +302,14 @@ let adapter: ExtendedAdapter = utils.adapter({
// might already have "color" states for white spectrum bulbs
// in the future, we create different states for white and RGB bulbs
if (light.spectrum === "rgb") {
wasAcked = !await operateLight(accessory, {
color: val,
transitionTime: await getTransitionDuration(accessory),
});
val = normalizeHexColor(val);
if (val != null) {
state.val = val;
wasAcked = !await operateLight(accessory, {
color: val,
transitionTime: await getTransitionDuration(accessory),
});
}
} else if (light.spectrum === "white") {
wasAcked = !await operateLight(accessory, {
colorTemperature: val,
Expand Down

0 comments on commit fd089e7

Please sign in to comment.