]> git.basschouten.com Git - openhab-addons.git/blob
71536c6540d678dec41d14a3d1f058e74a066ea4
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.loxone.internal.types;
14
15 import java.util.Arrays;
16 import java.util.List;
17 import java.util.stream.Collectors;
18
19 import org.openhab.core.library.types.HSBType;
20
21 /**
22  * Temperature HSB Type which acceptss a color in the form brigthness,temperature (Kelvin)
23  *
24  * @author Michael Mattan - initial contribution
25  *
26  */
27 public class LxTemperatureHSBType extends HSBType {
28
29     private static final long serialVersionUID = -2821122730407485795L;
30
31     public static HSBType fromBrightnessTemperature(String value) {
32         List<String> constituents = Arrays.stream(value.split(",")).map(in -> in.trim()).collect(Collectors.toList());
33
34         if (constituents.size() == 2) {
35             int brightness = constrain(Integer.valueOf(constituents.get(0)), 0, 100);
36             int temperature = constrain(Integer.valueOf(constituents.get(1)), 0, 65500);
37
38             int red = map(brightness, 0, 100, 0, calculateRed(temperature));
39             int green = map(brightness, 0, 100, 0, calculateGreen(temperature));
40             int blue = map(brightness, 0, 100, 0, calculateBlue(temperature));
41
42             return HSBType.fromRGB(red, green, blue);
43         } else {
44             throw new IllegalArgumentException(value + " is not a valid TemperatureHSBType syntax");
45         }
46     }
47
48     /**
49      * Re-maps a number from one range to another. That is, a value of fromLow would get mapped to toLow, a value of
50      * fromHigh to toHigh, values in-between to values in-between, etc.
51      *
52      * @param x the number to map
53      * @param fromLow the lower bound of the value's current range
54      * @param fromHigh the upper bound of the value's current range
55      * @param toLow the lower bound of the value's target range
56      * @param toHigh the upper bound of the value's target range
57      * @return the mapped value
58      */
59     private static int map(int x, int fromLow, int fromHigh, int toLow, int toHigh) {
60         return (x - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) + toLow;
61     }
62
63     /**
64      * calculates the red value based on the Kelvin temperature
65      *
66      * @param temp the Kelvin temperature
67      * @return the red value
68      */
69     private static int calculateRed(int temp) {
70         int red = 255;
71         int temperature = temp / 100;
72
73         if (temperature > 66) {
74             red = temperature - 60;
75             red = ((Long) Math.round(329.698727466 * Math.pow(red, -0.1332047592))).intValue();
76         }
77
78         return constrain(red, 0, 255);
79     }
80
81     /**
82      * calculates the green value based on the Kelvin temperature
83      *
84      * @param temp green Kelvin temperature
85      * @return the red value
86      */
87     private static int calculateGreen(int temp) {
88         int green;
89         int temperature = temp / 100;
90
91         if (temperature <= 66) {
92             green = temperature;
93             green = ((Long) Math.round((99.4708025861 * Math.log(green)) - 161.1195681661)).intValue();
94         } else {
95             green = temperature - 60;
96             green = ((Long) Math.round(288.1221695283 * Math.pow(green, -0.0755148492))).intValue();
97         }
98
99         return constrain(green, 0, 255);
100     }
101
102     /**
103      * calculates the blue value based on the Kelvin temperature
104      *
105      * @param temp the Kelvin temperature
106      * @return the blue value
107      */
108     private static int calculateBlue(int temp) {
109         int blue = 255;
110         int temperature = temp / 100;
111
112         if (temperature < 65) {
113             if (temperature <= 19) {
114                 blue = 0;
115             } else {
116                 blue = temperature - 10;
117                 blue = ((Long) Math.round((138.5177312231 * Math.log(blue)) - 305.0447927307)).intValue();
118             }
119         }
120
121         return constrain(blue, 0, 255);
122     }
123
124     /**
125      * Constrains a number to be within a range.
126      *
127      * @param x the number to constrain
128      * @param min the minimum value
129      * @param max the maximum value
130      * @return the constrained value
131      */
132     private static int constrain(int x, int min, int max) {
133         if (x >= min && x <= max) {
134             return x;
135         } else if (x < min) {
136             return min;
137         } else {
138             return max;
139         }
140     }
141 }