Skip to content

Commit

Permalink
Add methods to set gateway light brightness and color
Browse files Browse the repository at this point in the history
  • Loading branch information
valashko committed Oct 25, 2018
1 parent 0b49531 commit 12e1732
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 14 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugins {
}

group 'com.valashko.xaapi'
version '0.5'
version '0.6'

sourceCompatibility = 1.8

Expand Down
23 changes: 23 additions & 0 deletions src/main/java/com/valashko/xaapi/command/WriteSelfCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.valashko.xaapi.command;

import com.google.gson.JsonObject;
import com.valashko.xaapi.device.XiaomiGateway;

import java.nio.charset.StandardCharsets;

public class WriteSelfCommand implements ICommand {
private XiaomiGateway gateway;
private JsonObject data;

public WriteSelfCommand(XiaomiGateway gateway, JsonObject data, String key) {
this.gateway = gateway;
this.data = data;
data.addProperty("key", key);
}

@Override
public byte[] toBytes() {
String what = "{{\"cmd\":\"write\", \"sid\":\""+ gateway.getSid() +"\", \"data\":" + data + "}}";
return what.getBytes(StandardCharsets.US_ASCII);
}
}
15 changes: 13 additions & 2 deletions src/main/java/com/valashko/xaapi/device/BuiltinDevice.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,22 @@ public enum Type {
}

protected static JsonParser JSON_PARSER = new JsonParser();
protected XiaomiGateway gateway;
private String uid;
private Type type;

public BuiltinDevice(String uid, Type type) {
this.uid = uid;
public BuiltinDevice(XiaomiGateway gateway, Type type) {
this.gateway = gateway;
String typeSuffix = "undefined";
switch (type) {
case XiaomiGatewayLight:
typeSuffix = "light";
break;
case XiaomiGatewayIlluminationSensor:
typeSuffix = "illumination";
break;
}
this.uid = gateway.getSid() + ":" + typeSuffix;
this.type = type;
}

Expand Down
32 changes: 30 additions & 2 deletions src/main/java/com/valashko/xaapi/device/XiaomiGateway.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.Executor;

Expand Down Expand Up @@ -77,8 +78,8 @@ public Map<String, SlaveDevice> getKnownDevices() {
}

private void configureBuiltinDevices() {
builtinLight = new XiaomiGatewayLight(sid);
builtinIlluminationSensor = new XiaomiGatewayIlluminationSensor(sid);
builtinLight = new XiaomiGatewayLight(this);
builtinIlluminationSensor = new XiaomiGatewayIlluminationSensor(this);
}

private void configureCipher(String password) throws XaapiException {
Expand Down Expand Up @@ -162,6 +163,20 @@ void sendDataToDevice(SlaveDevice device, JsonObject data) throws XaapiException
}
}

void sendDataToDevice(BuiltinDevice device /* just a type marker for overloading */, JsonObject data) throws XaapiException {
assert device.gateway.equals(this);
if(key.isPresent()) {
try {
directChannel.send(new WriteSelfCommand(this, data, key.get()).toBytes());
// TODO add handling for expired key
} catch (IOException e) {
throw new XaapiException("Network error: " + e.getMessage());
}
} else {
throw new XaapiException("Unable to control device without a key. Did you forget to set a password?");
}
}

private SlaveDevice readDevice(String sid) throws XaapiException {
try {
directChannel.send(new ReadCommand(sid).toBytes());
Expand Down Expand Up @@ -263,4 +278,17 @@ private void handleGatewayHeartbeat(GatewayHeartbeat gatewayHeartbeat) throws Xa
private void handleSlaveDeviceHeartbeat(SlaveDeviceHeartbeat slaveDeviceHeartbeat) {
// TODO implement
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
XiaomiGateway that = (XiaomiGateway) o;
return Objects.equals(sid, that.sid);
}

@Override
public int hashCode() {
return Objects.hash(sid);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public class XiaomiGatewayIlluminationSensor extends BuiltinDevice {
private int illumination;
private HashMap<IInteractiveDevice.SubscriptionToken, Consumer<Integer>> illuminationChangeCallbacks = new HashMap<>();

public XiaomiGatewayIlluminationSensor(String gatewaySid) {
super(gatewaySid + ":illumination", Type.XiaomiGatewayIlluminationSensor);
public XiaomiGatewayIlluminationSensor(XiaomiGateway gateway) {
super(gateway, Type.XiaomiGatewayIlluminationSensor);
}

@Override
Expand Down
75 changes: 68 additions & 7 deletions src/main/java/com/valashko/xaapi/device/XiaomiGatewayLight.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,98 @@

import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import com.valashko.xaapi.XaapiException;

import java.awt.Color;
import java.util.HashMap;
import java.util.function.Consumer;

public class XiaomiGatewayLight extends BuiltinDevice {

private byte brightness;
private Color color;
private Color color = Color.BLACK; // TODO decide if this is an appropriate default value

public XiaomiGatewayLight(String gatewaySid) {
super(gatewaySid + ":light", Type.XiaomiGatewayLight);
private HashMap<IInteractiveDevice.SubscriptionToken, Consumer<Byte>> brightnessCallbacks = new HashMap<>();
private HashMap<IInteractiveDevice.SubscriptionToken, Consumer<Color>> colorCallbacks = new HashMap<>();

public XiaomiGatewayLight(XiaomiGateway gateway) {
super(gateway, Type.XiaomiGatewayLight);
}

@Override
void update(String data) {
try {
JsonObject o = JSON_PARSER.parse(data).getAsJsonObject();
int rgb = o.get("rgb").getAsInt();
brightness = (byte)(rgb & 0xFF000000);
byte previousBrightnessValue = brightness;
brightness = (byte)(rgb >>> 24);
Color previousColorValue = color;
color = new Color(rgb & 0x00FFFFFF);
if(brightness != previousBrightnessValue) {
notifyWithBrightnessChange(brightness);
}
if(! color.equals(previousColorValue)) {
notifyWithColorChange(color);
}
} catch (JsonSyntaxException e) {
e.printStackTrace();
}
}

public byte getBrightness() {
return brightness;
return brightness; // TODO query from device
}

public Color getColor() {
return color;
return color; // TODO query from device
}

public IInteractiveDevice.SubscriptionToken subscribeForBrightnessChange(Consumer<Byte> callback) {
IInteractiveDevice.SubscriptionToken token = new IInteractiveDevice.SubscriptionToken();
brightnessCallbacks.put(token, callback);
return token;
}

public void unsubscribeForBrightnessChange(IInteractiveDevice.SubscriptionToken token) {
brightnessCallbacks.remove(token);
}

private void notifyWithBrightnessChange(byte value) {
for(Consumer<Byte> c : brightnessCallbacks.values()) {
c.accept(value);
}
}

public IInteractiveDevice.SubscriptionToken subscribeForColorChange(Consumer<Color> callback) {
IInteractiveDevice.SubscriptionToken token = new IInteractiveDevice.SubscriptionToken();
colorCallbacks.put(token, callback);
return token;
}

// TODO implement subscription for brightness and color updates
public void unsubscribeForColorChange(IInteractiveDevice.SubscriptionToken token) {
colorCallbacks.remove(token);
}

private void notifyWithColorChange(Color value) {
for(Consumer<Color> c : colorCallbacks.values()) {
c.accept(value);
}
}

public void setBrightness(byte brightness) throws XaapiException {
writeBrightnessAndColor(brightness, this.color);
this.brightness = brightness;
}

public void setColor(Color color) throws XaapiException {
writeBrightnessAndColor(this.brightness, color);
this.color = color;
}

private void writeBrightnessAndColor(int brightness, Color color) throws XaapiException {
JsonObject rgb = new JsonObject();
int rgbValue = brightness << 24 | color.getRGB();
rgb.addProperty("rgb", rgbValue);
gateway.sendDataToDevice(this, rgb);
}
}

0 comments on commit 12e1732

Please sign in to comment.