Light type detection and filter for device list

"Extended color light" isn't used anymore for all devices without thinking about it. It will now automatically differentiate between Color and Dimmable light by the following logic: 
1. If it's  Philips Hue passthru look at the state: if it contains the attribute "colormode" it's a Extended color light, otherwise it's a Dimmable light.
2. If it's no passthru it's a dimmable light if the colorUrl has no content. 

I didn't use On/Off light because i disovered that a) the hue app treats these exactly the same as dimmable light, you can still "change the brightness" and b) the amazon echo doesn't find these lights without the skill

I also enhanced the filter options in the web ui.
You have a textbox "Show devices visible to". You can fill in an ip-address and there will only be devices displayed that a) have the ip address in the requesterFilter or b) don't filter by requester.
If you tick the checkbox "Must contain filter" option b isn't used. This means also if you check the box with no ip address in the textbox only devices without request filter will be shown.
Also there is a filter by device type.
All these 3 filter options will be remembered as long as the browser tab is closed.
This commit is contained in:
Florian Förderreuther
2017-08-02 07:34:06 +02:00
parent 95c342b548
commit ce79fb4b82
8 changed files with 100 additions and 44 deletions

View File

@@ -105,26 +105,19 @@ public class DeviceResponse {
response.setName(device.getName());
response.setUniqueid(device.getUniqueid());
//if (device.getColorUrl() == null || device.getColorUrl().trim().equals("")) {
// if (device.getDimUrl() == null || device.getDimUrl().trim().equals("")) {
// response.setType("On/Off light");
// response.setModelid("Plug - LIGHTIFY");
// response.setManufacturername("OSRAM");
// response.setSwversion("V1.04.12");
// } else {
// response.setManufacturername("Philips");
// response.setType("Dimmable light");
// response.setModelid("LWB007");
// response.setSwversion("66012040");
// }
//} else {
response.setManufacturername("Philips");
response.setManufacturername("Philips");
if (device.isColorDevice()) {
response.setType("Extended color light");
response.setModelid("LCT010");
response.setSwversion("1.15.2_r19181");
response.setSwconfigid("F921C859");
response.setProductid("Philips-LCT010-1-A19ECLv4");
//}
} else {
response.setType("Dimmable light");
response.setModelid("LWB007");
response.setSwversion("66012040");
}
response.setLuminaireuniqueid(null);

View File

@@ -9,11 +9,11 @@ import java.util.List;
public class DeviceState {
private boolean on;
private int bri;
private int hue;
private int sat;
private Integer hue;
private Integer sat;
private String effect;
private List<Double> xy;
private int ct;
private Integer ct;
private String alert;
private String colormode;
private boolean reachable;
@@ -37,7 +37,7 @@ public class DeviceState {
}
public int getHue() {
return hue;
return hue != null ? hue.intValue() : 0;
}
public void setHue(int hue) {
@@ -46,7 +46,7 @@ public class DeviceState {
}
public int getSat() {
return sat;
return sat != null ? sat.intValue() : 0;
}
public void setSat(int sat) {
@@ -63,7 +63,7 @@ public class DeviceState {
}
public int getCt() {
return ct;
return ct != null ? ct.intValue() : 0;
}
public void setCt(int ct) {
@@ -111,23 +111,28 @@ public class DeviceState {
// this.transitiontime = transitiontime;
// }
public static DeviceState createDeviceState() {
public static DeviceState createDeviceState(boolean color) {
DeviceState newDeviceState = new DeviceState();
newDeviceState.fillIn();
newDeviceState.setColormode("ct");
newDeviceState.setCt(200);
ArrayList<Double> doubleArray = new ArrayList<Double>();
doubleArray.add(new Double(0));
doubleArray.add(new Double(0));
newDeviceState.setXy(doubleArray);
newDeviceState.fillIn(color);
if (color) {
newDeviceState.setColormode("xy");
newDeviceState.setHue(0);
newDeviceState.setSat(0);
newDeviceState.setCt(153);
ArrayList<Double> doubleArray = new ArrayList<Double>();
doubleArray.add(0.3146);
doubleArray.add(0.3303);
newDeviceState.setXy(doubleArray);
}
return newDeviceState;
}
public void fillIn() {
public void fillIn(boolean color) {
if(this.getAlert() == null)
this.setAlert("none");
if(this.getEffect() == null)
this.setEffect("none");
if (color) {
if(this.getEffect() == null)
this.setEffect("none");
}
this.setReachable(true);
}
@Override

View File

@@ -82,7 +82,7 @@ public class GroupResponse {
i++;
}
GroupResponse theResponse = new GroupResponse();
theResponse.setAction(DeviceState.createDeviceState());
theResponse.setAction(DeviceState.createDeviceState(true));
theResponse.setState(new GroupState(all_on, any_on));
theResponse.setName("Group 0");
theResponse.setLights(theList);

View File

@@ -219,7 +219,7 @@ public class DeviceDescriptor{
public DeviceState getDeviceState() {
if(deviceState == null)
deviceState = DeviceState.createDeviceState();
deviceState = DeviceState.createDeviceState(this.isColorDevice());
return deviceState;
}
@@ -299,4 +299,16 @@ public class DeviceDescriptor{
return false;
}
public boolean isColorDevice() {
boolean color = true;
if ((deviceType == null || !deviceType.trim().equals("passthru")) && (colorUrl == null || colorUrl.trim().equals(""))) {
color = false;
} else if (deviceType != null && deviceType.trim().equals("passthru")) {
if (deviceState != null && (deviceState.getColormode() == null || deviceState.getColormode().equals(""))) {
color = false;
}
}
return color;
}
}

View File

@@ -90,7 +90,7 @@ public class GroupDescriptor{
public DeviceState getAction() {
if(action == null)
action = DeviceState.createDeviceState();
action = DeviceState.createDeviceState(true);
return action;
}

View File

@@ -1073,7 +1073,7 @@ public class HueMulator {
state = device.getDeviceState();
if (state == null)
state = DeviceState.createDeviceState();
state = DeviceState.createDeviceState(device.isColorDevice());
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, device.isOffState());
device.setDeviceState(state);
@@ -1127,7 +1127,7 @@ public class HueMulator {
state = device.getDeviceState();
if (state == null) {
state = DeviceState.createDeviceState();
state = DeviceState.createDeviceState(device.isColorDevice());
device.setDeviceState(state);
}
@@ -1248,7 +1248,7 @@ public class HueMulator {
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, device.isOffState());
device.setDeviceState(state);
} else {
DeviceState dummyState = DeviceState.createDeviceState();
DeviceState dummyState = DeviceState.createDeviceState(device.isColorDevice());
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, dummyState, targetBri, targetBriInc, device.isOffState());
}
}
@@ -1309,7 +1309,7 @@ public class HueMulator {
state = group.getAction();
if (state == null) {
state = DeviceState.createDeviceState();
state = DeviceState.createDeviceState(true);
group.setAction(state);
}
}

View File

@@ -134,7 +134,8 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
this.state = {base: "./api/devices", bridgelocation: ".", systemsbase: "./system", huebase: "./api", configs: [], backups: [], devices: [], device: {},
mapandid: [], type: "", settings: [], myToastMsg: [], logMsgs: [], loggerInfo: [], mapTypes: [], olddevicename: "", logShowAll: false,
isInControl: false, showVera: false, showHarmony: false, showNest: false, showHue: false, showHal: false, showMqtt: false, showHass: false,
showDomoticz: false, showSomfy: false, showLifx: false, habridgeversion: {}, viewDevId: "", queueDevId: "", securityInfo: {}, filterDevicesByIpAddress: null};
showDomoticz: false, showSomfy: false, showLifx: false, habridgeversion: {}, viewDevId: "", queueDevId: "", securityInfo: {}, filterDevicesByIpAddress: null,
filterDevicesOnlyFiltered: false, filterDeviceType: null};
this.displayWarn = function(errorTitle, error) {
var toastContent = errorTitle;
@@ -3463,13 +3464,39 @@ app.filter('configuredSomfyDevices', function (bridgeService) {
});
app.filter('filterDevicesByRequester', function () {
return function(input,search) {
return function(input,search,mustContain,deviceType) {
var out = [];
if(input === undefined || input === null || input.length === undefined)
return out;
var pattern = new RegExp(search);
var patternType = new RegExp(deviceType);
for (var i = 0; i < input.length; i++) {
if(pattern.test(input[i].requesterAddress) || !input[i].requesterAddress || input[i].requesterAddress.length === 0){
var pushRequester = false;
var pushType = false;
// Check filter by requester
if (!search || search.trim().length === 0) { // if search is empty and mustContain == true push only unfiltered devices
if (mustContain) {
if (!input[i].requesterAddress || input[i].requesterAddress.length === 0) {
pushRequester = true;
}
} else {
pushRequester = true;
}
} else {
if(pattern.test(input[i].requesterAddress) || !mustContain && (!input[i].requesterAddress || input[i].requesterAddress.length === 0)){
pushRequester = true;
}
}
// Check filter by deviceType
if (deviceType) {
pushType = patternType.test(input[i].deviceType);
} else {
pushType = true;
}
if (pushRequester && pushType) {
out.push(input[i]);
}
}

View File

@@ -37,6 +37,25 @@
<label for="device-ip-filter">Show devices visible to: </label>
<input type="text" id="device-ip-filter" style="width:150px"
ng-model="bridge.state.filterDevicesByIpAddress" placeholder="">
<input type="checkbox" id="device-ip-filter-mode" ng-model="bridge.state.filterDevicesOnlyFiltered" ng-true-value=true ng-false-value=false style="margin-right: 3px">Must contain filter
<label for="device-type-filter" style="margin-left:50px">Filter device type: </label>
<select name="device-type" id="device-type-filter"
ng-model="bridge.state.filterDeviceType">
<option value="">---No Filter---</option>
<!-- not selected / blank option -->
<option value="custom">Custom</option>
<option value="UDP">UDP</option>
<option value="TCP">TCP</option>
<option value="exec">Execute Script/Program</option>
<option value="switch">Switch</option>
<option value="scene">Scene</option>
<option value="macro">Macro</option>
<option value="group">Group</option>
<option value="activity">Activity</option>
<option value="button">Button</option>
<option value="thermo">Thermo</option>
<option value="passthru">Pass Thru</option>
</select>
</div>
<scrollable-table watch="bridge.devices">
@@ -55,7 +74,7 @@
<th>Actions</th>
</tr>
</thead>
<tr ng-repeat="device in bridge.devices | orderBy:'name' | filterDevicesByRequester:bridge.state.filterDevicesByIpAddress" row-id="{{device.id}}" ng-class="{info: bridge.viewDevId == device.id}" >
<tr ng-repeat="device in bridge.devices | orderBy:'name' | filterDevicesByRequester:bridge.state.filterDevicesByIpAddress:bridge.state.filterDevicesOnlyFiltered:bridge.state.filterDeviceType" row-id="{{device.id}}" ng-class="{info: bridge.viewDevId == device.id}" >
<td>{{$index+1}}</td>
<td>{{device.id}}</td>
<td>{{device.name}}</td>