/**
* Copyright (c) 2010-2016, openHAB.org and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.fatekplc.items;
import java.awt.Color;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.openhab.core.items.Item;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.model.item.binding.BindingConfigParseException;
import org.simplify4u.jfatek.FatekException;
import org.simplify4u.jfatek.FatekPLC;
import org.simplify4u.jfatek.FatekReadMixDataCmd;
import org.simplify4u.jfatek.FatekWriteMixDataCmd;
import org.simplify4u.jfatek.io.FatekIOException;
import org.simplify4u.jfatek.registers.Reg;
import org.simplify4u.jfatek.registers.RegValue;
import org.simplify4u.jfatek.registers.UnknownRegNameException;
/**
* Color item implementation.
*
* @author Slawomir Jaranowski
* @since 1.9.0
*
*/
public class FatekColorItem extends FatekPLCItem {
private Reg reg2;
private Reg reg3;
private Reg reg4;
private boolean isColorRGB;
private final int step;
public FatekColorItem(Item item, List<String> confItems)
throws BindingConfigParseException {
super(item, confItems);
step = getParamsFromConfAsInt(confItems, "step", 5);
if (confItems.size() < 3 || confItems.size() > 5) {
throw new BindingConfigParseException(
"Incorrect binding for color item - should be: plcName:R1:R2:R3[:R4][:RGB|HSB]");
}
try {
reg1 = Reg.parse(confItems.get(0));
reg2 = Reg.parse(confItems.get(1));
reg3 = Reg.parse(confItems.get(2));
} catch (UnknownRegNameException e) {
throw new BindingConfigParseException(e.getMessage());
}
if (confItems.size() == 4) {
try {
reg4 = Reg.parse(confItems.get(3));
} catch (UnknownRegNameException e) {
// try color mode
initColorMode(confItems.get(3));
}
}
if (confItems.size() == 5) {
try {
reg4 = Reg.parse(confItems.get(3));
} catch (UnknownRegNameException e) {
throw new BindingConfigParseException(e.getMessage());
}
initColorMode(confItems.get(4));
}
if (reg1.isDiscrete() || reg2.isDiscrete() || reg3.isDiscrete()) {
throw new BindingConfigParseException(
"Please use data reg for color item");
}
}
private void initColorMode(String colorMode)
throws BindingConfigParseException {
if ("RGB".equalsIgnoreCase(colorMode)) {
isColorRGB = true;
} else if ("HSB".equalsIgnoreCase(colorMode)) {
isColorRGB = false;
} else {
throw new BindingConfigParseException("Invalid color mode value");
}
}
@Override
public Collection<? extends Reg> getRegs() {
if (reg4 != null) {
return Arrays.asList(reg1, reg2, reg3, reg4);
} else {
return Arrays.asList(reg1, reg2, reg3);
}
}
@Override
public State getState(Map<Reg, RegValue> response) {
if (reg4 != null) {
boolean isOn = response.get(reg4).boolValue();
if (!isOn) {
return HSBType.BLACK;
}
}
return reg2HSB(response.get(reg1), response.get(reg2),
response.get(reg3));
}
@Override
public void command(FatekPLC fatekPLC, Command command)
throws CommandException {
try {
final HSBType val;
if (command instanceof OnOffType) {
val = valueForOnOff(fatekPLC, command);
} else if (command instanceof IncreaseDecreaseType) {
val = valueForIncreaseDecrease(fatekPLC, command);
} else if (command instanceof HSBType) {
val = (HSBType) command;
} else {
throw new UnsupportedCommandException(this, command);
}
if (val != null) {
int v1;
int v2;
int v3;
if (isColorRGB) {
Color c = val.toColor();
v1 = c.getRed();
v2 = c.getGreen();
v3 = c.getBlue();
} else {
v1 = val.getHue().intValue();
v2 = val.getSaturation().intValue();
v3 = val.getBrightness().intValue();
}
FatekWriteMixDataCmd cmd = new FatekWriteMixDataCmd(fatekPLC);
cmd.addReg(reg1, v1);
cmd.addReg(reg2, v2);
cmd.addReg(reg3, v3);
cmd.send();
}
} catch (FatekIOException | FatekException e) {
throw new CommandException(this, command, e);
}
}
private HSBType reg2HSB(RegValue r1, RegValue r2, RegValue r3) {
int v1 = r1.intValueUnsigned();
int v2 = r2.intValueUnsigned();
int v3 = r3.intValueUnsigned();
if (isColorRGB) {
v1 = Math.min(v1, 255);
v2 = Math.min(v2, 255);
v3 = Math.min(v3, 255);
return new HSBType(new Color(v1, v2, v3));
} else {
v1 = Math.min(v1, 360);
v2 = Math.min(v2, 100);
v3 = Math.min(v3, 100);
return new HSBType(new DecimalType(v1), new PercentType(v2),
new PercentType(v3));
}
}
private HSBType valueForOnOff(FatekPLC fatekPLC, Command command)
throws CommandException {
HSBType val = null;
try {
if (OnOffType.ON.equals(command)) {
if (reg4 != null) {
new FatekWriteMixDataCmd(fatekPLC).addReg(reg4, true).send();
} else {
val = HSBType.WHITE;
}
} else if (OnOffType.OFF.equals(command)) {
if (reg4 != null) {
new FatekWriteMixDataCmd(fatekPLC).addReg(reg4, false).send();
} else {
val = HSBType.BLACK;
}
}
} catch (FatekIOException | FatekException e) {
throw new CommandException(this, command, e);
}
return val;
}
private HSBType valueForIncreaseDecrease(FatekPLC fatekPLC, Command command)
throws CommandException {
HSBType val = null;
try {
// first read current state
Map<Reg, RegValue> regVal = new FatekReadMixDataCmd(fatekPLC, reg1,
reg2, reg3).send();
HSBType currentVal = reg2HSB(regVal.get(reg1), regVal.get(reg1),
regVal.get(reg3));
int b = currentVal.getBrightness().intValue();
if (IncreaseDecreaseType.INCREASE.equals(command)) {
b = Math.min(b + step, 100);
} else if (IncreaseDecreaseType.DECREASE.equals(command)) {
b = Math.max(b - step, 0);
} else {
throw new CommandException(this, command,
"Unknown IncreaseDecrease type");
}
if (b != currentVal.getBrightness().intValue()) {
val = new HSBType(currentVal.getHue(),
currentVal.getSaturation(), new PercentType(b));
}
} catch (FatekIOException | FatekException e) {
throw new CommandException(this, command, e);
}
return val;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName()).append("[");
sb.append("slave=").append(getSlaveName());
sb.append(", name=").append(getItemName());
sb.append(", step=").append(step);
if (isColorRGB) {
sb.append(", R=").append(reg1);
sb.append(", G=").append(reg2);
sb.append(", B=").append(reg3);
} else {
sb.append(", H=").append(reg1);
sb.append(", S=").append(reg2);
sb.append(", B=").append(reg3);
}
sb.append("]");
return sb.toString();
}
}