Implementation of level and color data types
This commit is contained in:
parent
a89b418350
commit
234125bc35
30 changed files with 664 additions and 113 deletions
|
|
@ -18,8 +18,8 @@ subprojects {
|
||||||
apply plugin: 'java-library'
|
apply plugin: 'java-library'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'se.koc:zutil:1.0.311'
|
//implementation 'se.koc:zutil:1.0.312'
|
||||||
//implementation 'se.koc:zutil:1.0.0-SNAPSHOT'
|
implementation 'se.koc:zutil:1.0.0-SNAPSHOT'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
testImplementation 'org.hamcrest:hamcrest-core:2.2'
|
testImplementation 'org.hamcrest:hamcrest-core:2.2'
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
<td>
|
<td>
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<input type="hidden" name="action" value="modify">
|
<input type="hidden" name="action" value="modify">
|
||||||
<input type="hidden" name="action_id" value="{{event.getId()}}">
|
<input type="hidden" name="action-id" value="{{event.getId()}}">
|
||||||
|
|
||||||
<div class="btn-toolbar pull-left">
|
<div class="btn-toolbar pull-left">
|
||||||
<input class="toggle-switch" type="checkbox" name="enabled"
|
<input class="toggle-switch" type="checkbox" name="enabled"
|
||||||
|
|
|
||||||
|
|
@ -13,26 +13,6 @@
|
||||||
<th class="col-md-2">Last Update</th>
|
<th class="col-md-2">Last Update</th>
|
||||||
<th class="col-md-2 text-right">Actions</th>
|
<th class="col-md-2 text-right">Actions</th>
|
||||||
</thead>
|
</thead>
|
||||||
{{#events}}
|
|
||||||
<tr data-device-id="{{.getId()}}">
|
|
||||||
<td><a href="?id={{.getId()}}">{{.getName()}}</a></td>
|
|
||||||
<td>{{.getDeviceConfig().getClass().getSimpleName()}}</td>
|
|
||||||
<td>{{.getDeviceData()}}</td>
|
|
||||||
<td class="timestamp">{{.getDeviceData().getTimestamp()}}</td>
|
|
||||||
<td>
|
|
||||||
<form method="POST">
|
|
||||||
<input type="hidden" name="action" value="modify">
|
|
||||||
<input type="hidden" name="action_id" value="{{.getId()}}">
|
|
||||||
|
|
||||||
<div class="btn-toolbar pull-right">
|
|
||||||
<input class="toggle-switch" type="checkbox" name="enabled"
|
|
||||||
data-on-color="danger"
|
|
||||||
{{#.getDeviceData().getData()}}checked{{/.getDeviceData().getData()}} >
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{/events}}
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -45,24 +25,70 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateDevices();
|
||||||
|
|
||||||
// Auto update
|
// Auto update
|
||||||
|
|
||||||
setInterval(function() {
|
setInterval(function() {
|
||||||
|
updateDevices();
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
function updateDevices() {
|
||||||
fetch('/api/event')
|
fetch('/api/event')
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
var table = document.getElementById('event-device-table');
|
var table = document.getElementById('event-device-table');
|
||||||
|
|
||||||
for (const row of table.rows) {
|
for (const deviceData of data) {
|
||||||
var dataItem = data.find(item => item.id == row.dataset.deviceId);
|
var row = Array.from(table.rows).find(row => row.dataset.deviceId == deviceData.id);
|
||||||
|
|
||||||
if (dataItem) {
|
if (!row) {
|
||||||
row.cells[2].innerHTML = dataItem.data?.valueStr;
|
row = table.insertRow();
|
||||||
row.cells[3].innerHTML = dataItem.data?.timestamp;
|
row.insertCell(0);
|
||||||
$(row.cells[3]).relTimestamp();
|
row.insertCell(1);
|
||||||
$(row.cells[4].querySelector('[type="checkbox"]')).bootstrapSwitch('state', dataItem.data?.value === 1, true);
|
row.insertCell(2);
|
||||||
|
row.insertCell(3);
|
||||||
|
row.insertCell(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update Cells
|
||||||
|
|
||||||
|
row.dataset.deviceId = deviceData.id
|
||||||
|
row.cells[0].innerHTML = deviceData.name;
|
||||||
|
row.cells[1].innerHTML = deviceData.config?.typeConfig;
|
||||||
|
row.cells[2].innerHTML = deviceData.data?.valueStr;
|
||||||
|
|
||||||
|
row.cells[3].innerHTML = deviceData.data?.timestamp;
|
||||||
|
$(row.cells[3]).relTimestamp();
|
||||||
|
|
||||||
|
var actionHtml = "";
|
||||||
|
switch (deviceData.config?.typeData) {
|
||||||
|
case "ColorEventData":
|
||||||
|
actionHtml =
|
||||||
|
'<input type="hidden" name="type" value="color">' +
|
||||||
|
'<input type="color" name="data" onchange="this.form.submit()" value="' + deviceData.data?.valueStr + '">';
|
||||||
|
break;
|
||||||
|
case "LevelEventData":
|
||||||
|
actionHtml =
|
||||||
|
'<input type="hidden" name="type" value="level">' +
|
||||||
|
'<input type="range" name="data" min="0" max="100" step="10" onchange="this.form.submit()" value="' + (deviceData.data?.value * 100) + '">';
|
||||||
|
break;
|
||||||
|
case "OnOffEventData":
|
||||||
|
actionHtml =
|
||||||
|
'<input type="hidden" name="type" value="on-off">' +
|
||||||
|
'<input class="toggle-switch" type="checkbox" name="data" data-on-color="danger" onchange="this.form.submit()" ' + (deviceData.data?.valueStr=="ON" ? "checked" : "") + '>';
|
||||||
|
//$(row.cells[4].querySelector('[type="checkbox"]')).bootstrapSwitch('state', deviceData.data?.value === 1, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
row.cells[4].innerHTML = '<form method="POST">' +
|
||||||
|
'<input type="hidden" name="action" value="modify">' +
|
||||||
|
'<input type="hidden" name="action-id" value="' + deviceData.id + '">' +
|
||||||
|
'<div class="btn-toolbar pull-right">' + actionHtml + '</div>';
|
||||||
|
|
||||||
|
$(".toggle-switch").bootstrapSwitch({inverse: true, size: "mini"});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, 3000);
|
}
|
||||||
</script>
|
</script>
|
||||||
1
hal-core/resources/web/js/hal_alert.js
vendored
1
hal-core/resources/web/js/hal_alert.js
vendored
|
|
@ -58,6 +58,7 @@ function updateAlerts() {
|
||||||
.then(data => {
|
.then(data => {
|
||||||
data.forEach(alert => {
|
data.forEach(alert => {
|
||||||
var alertElement = $("#alert-id-" + alert.id);
|
var alertElement = $("#alert-id-" + alert.id);
|
||||||
|
|
||||||
if (alertElement.length <= 0) {
|
if (alertElement.length <= 0) {
|
||||||
alertElement = $(alertTemplate[alert.level]);
|
alertElement = $(alertTemplate[alert.level]);
|
||||||
$("#" + alertDivId).append(alertElement);
|
$("#" + alertDivId).append(alertElement);
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,11 @@
|
||||||
var table = document.getElementById('sensor-device-table');
|
var table = document.getElementById('sensor-device-table');
|
||||||
|
|
||||||
for (const row of table.rows) {
|
for (const row of table.rows) {
|
||||||
var dataItem = data.find(item => item.id == row.dataset.deviceId);
|
var deviceData = data.find(item => item.id == row.dataset.deviceId);
|
||||||
|
|
||||||
if (dataItem) {
|
if (deviceData) {
|
||||||
row.cells[2].innerHTML = dataItem.data?.valueStr;
|
row.cells[2].innerHTML = deviceData.data?.valueStr;
|
||||||
row.cells[3].innerHTML = dataItem.data?.timestamp;
|
row.cells[3].innerHTML = deviceData.data?.timestamp;
|
||||||
|
|
||||||
$(row.cells[3]).relTimestamp();
|
$(row.cells[3]).relTimestamp();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,11 @@ package se.hal.page;
|
||||||
|
|
||||||
import se.hal.EventControllerManager;
|
import se.hal.EventControllerManager;
|
||||||
import se.hal.HalContext;
|
import se.hal.HalContext;
|
||||||
|
import se.hal.intf.HalEventData;
|
||||||
import se.hal.intf.HalWebPage;
|
import se.hal.intf.HalWebPage;
|
||||||
import se.hal.struct.Event;
|
import se.hal.struct.Event;
|
||||||
|
import se.hal.struct.devicedata.ColorEventData;
|
||||||
|
import se.hal.struct.devicedata.LevelEventData;
|
||||||
import se.hal.struct.devicedata.OnOffEventData;
|
import se.hal.struct.devicedata.OnOffEventData;
|
||||||
import se.hal.util.DeviceNameComparator;
|
import se.hal.util.DeviceNameComparator;
|
||||||
import se.hal.util.HistoryDataListSqlResult;
|
import se.hal.util.HistoryDataListSqlResult;
|
||||||
|
|
@ -41,24 +44,40 @@ public class EventOverviewWebPage extends HalWebPage {
|
||||||
|
|
||||||
DBConnection db = HalContext.getDB();
|
DBConnection db = HalContext.getDB();
|
||||||
|
|
||||||
if (request.containsKey("action")) {
|
if ("modify".equals(request.get("action"))) {
|
||||||
int id = (ObjectUtil.isEmpty(request.get("action_id")) ? -1 : Integer.parseInt(request.get("action_id")));
|
int id = (ObjectUtil.isEmpty(request.get("action-id")) ? -1 : Integer.parseInt(request.get("action-id")));
|
||||||
|
|
||||||
// change event data
|
// change event data
|
||||||
OnOffEventData eventData = new OnOffEventData();
|
HalEventData eventData = null;
|
||||||
if (request.containsKey("enabled") && "on".equals(request.get("enabled")))
|
|
||||||
eventData.setOn();
|
|
||||||
else
|
|
||||||
eventData.setOff();
|
|
||||||
|
|
||||||
logger.info("Modifying Event(" + id + ") state: " + eventData.toString());
|
switch (request.get("type")) {
|
||||||
Event event = Event.getEvent(db, id);
|
case "level":
|
||||||
EventControllerManager.getInstance().send(event, eventData);
|
eventData = new LevelEventData(Integer.parseInt(request.get("data")) / 100.0, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "color":
|
||||||
|
eventData = new ColorEventData(request.get("data"), 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "on-off":
|
||||||
|
eventData = new OnOffEventData("on".equals(request.get("data")), 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventData != null) {
|
||||||
|
logger.info("Modifying Event(" + id + ") state: " + eventData.toString());
|
||||||
|
Event event = Event.getEvent(db, id);
|
||||||
|
EventControllerManager.getInstance().send(event, eventData);
|
||||||
|
} else {
|
||||||
|
logger.warning("Unable to process event change request, data type most likely not supported: " + request.get("type"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int id = (ObjectUtil.isEmpty(request.get("id")) ? -1 : Integer.parseInt(request.get("id")));
|
int id = (ObjectUtil.isEmpty(request.get("id")) ? -1 : Integer.parseInt(request.get("id")));
|
||||||
|
|
||||||
// Save new input
|
// --------------------------------------
|
||||||
|
// Detailed page
|
||||||
|
// --------------------------------------
|
||||||
if (id >= 0) {
|
if (id >= 0) {
|
||||||
Event event = Event.getEvent(db, id);
|
Event event = Event.getEvent(db, id);
|
||||||
|
|
||||||
|
|
@ -74,6 +93,9 @@ public class EventOverviewWebPage extends HalWebPage {
|
||||||
tmpl.set("history", history);
|
tmpl.set("history", history);
|
||||||
return tmpl;
|
return tmpl;
|
||||||
}
|
}
|
||||||
|
// --------------------------------------
|
||||||
|
// Overview page
|
||||||
|
// --------------------------------------
|
||||||
else {
|
else {
|
||||||
List<Event> events = Event.getLocalEvents(db);
|
List<Event> events = Event.getLocalEvents(db);
|
||||||
Collections.sort(events, DeviceNameComparator.getInstance());
|
Collections.sort(events, DeviceNameComparator.getInstance());
|
||||||
|
|
|
||||||
131
hal-core/src/se/hal/struct/devicedata/ColorEventData.java
Normal file
131
hal-core/src/se/hal/struct/devicedata/ColorEventData.java
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Ziver
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.hal.struct.devicedata;
|
||||||
|
|
||||||
|
import se.hal.intf.HalEventData;
|
||||||
|
import zutil.ColorUtil;
|
||||||
|
import zutil.converter.Converter;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.color.ColorSpace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a color based event.
|
||||||
|
*/
|
||||||
|
public class ColorEventData extends HalEventData {
|
||||||
|
private static final ColorSpace cieXYZ = ColorSpace.getInstance(ColorSpace.CS_CIEXYZ);
|
||||||
|
|
||||||
|
private int red;
|
||||||
|
private int green;
|
||||||
|
private int blue;
|
||||||
|
|
||||||
|
|
||||||
|
public ColorEventData() { }
|
||||||
|
/**
|
||||||
|
* Create object based on sRGB.
|
||||||
|
*/
|
||||||
|
public ColorEventData(String hex, long timestamp) {
|
||||||
|
int[] rgb = ColorUtil.getRgbFromHexString(hex);
|
||||||
|
this.red = rgb[0];
|
||||||
|
this.green = rgb[1];
|
||||||
|
this.blue = rgb[2];
|
||||||
|
this.setTimestamp(timestamp);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create object based on sRGB.
|
||||||
|
*/
|
||||||
|
public ColorEventData(int red, int green, int blue, long timestamp) {
|
||||||
|
this.red = red;
|
||||||
|
this.green = green;
|
||||||
|
this.blue = blue;
|
||||||
|
this.setTimestamp(timestamp);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create object based on CIE XYZ.
|
||||||
|
*/
|
||||||
|
public static ColorEventData createFromCieXYZ(float x, float y, float z, long timestamp) {
|
||||||
|
float[] rgb = cieXYZ.toRGB(new float[]{x, y, z});
|
||||||
|
return new ColorEventData((int) rgb[0], (int) rgb[0], (int) rgb[0], timestamp);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create object based on HLS.
|
||||||
|
*/
|
||||||
|
public static ColorEventData createFromHLS(float h, float l, float s, long timestamp) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getRed() {
|
||||||
|
return red;
|
||||||
|
}
|
||||||
|
public int getGreen() {
|
||||||
|
return green;
|
||||||
|
}
|
||||||
|
public int getBlue() {
|
||||||
|
return blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHue() {
|
||||||
|
return ColorUtil.getHue(red, green, blue);
|
||||||
|
}
|
||||||
|
public double getSaturation() {
|
||||||
|
return ColorUtil.getSaturation(red, green, blue);
|
||||||
|
}
|
||||||
|
public double getLightness() {
|
||||||
|
return ColorUtil.getLightness(red, green, blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float[] getCieXYZ() {
|
||||||
|
return cieXYZ.fromRGB(new float[]{red, green, blue});
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHex() {
|
||||||
|
return ColorUtil.getHexString(red, green, blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return "Red: " + red + ", Green: " + green + ", Blue: " + blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// Storage methods
|
||||||
|
// ----------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getData() {
|
||||||
|
int rgb = 0;
|
||||||
|
rgb |= 0xFF0000 & (red << 16);
|
||||||
|
rgb |= 0x00FF00 & (green << 8);
|
||||||
|
rgb |= 0x0000FF & (blue);
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setData(double data) {
|
||||||
|
int rgb = (int) data;
|
||||||
|
red = 0xFF & (rgb >> 16);
|
||||||
|
green = 0xFF & (rgb >> 8);
|
||||||
|
blue = 0xFF & (rgb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* The MIT License (MIT)
|
* Copyright (c) 2015 Ziver
|
||||||
*
|
|
||||||
* Copyright (c) 2020 Ziver Koc
|
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -22,38 +20,40 @@
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package se.hal.plugin.mqtt.device;
|
package se.hal.struct.devicedata;
|
||||||
|
|
||||||
import se.hal.intf.HalEventData;
|
import se.hal.intf.HalEventData;
|
||||||
import zutil.StringUtil;
|
|
||||||
import zutil.log.LogUtil;
|
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
/**
|
||||||
|
* Represents a percentage based level event.
|
||||||
|
*/
|
||||||
|
public class LevelEventData extends HalEventData {
|
||||||
|
|
||||||
public class HalMqttDeviceData extends HalEventData {
|
private double percent;
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
|
||||||
|
|
||||||
private double data;
|
|
||||||
|
|
||||||
|
|
||||||
public HalMqttDeviceData(byte[] byteData) {
|
public LevelEventData() { }
|
||||||
String str = new String(byteData);
|
public LevelEventData(double percent, long timestamp) {
|
||||||
|
setData(percent);
|
||||||
if (StringUtil.isDecimalNumber(str)) {
|
this.setTimestamp(timestamp);
|
||||||
data = Double.parseDouble(str);
|
|
||||||
} else {
|
|
||||||
logger.warning("Received non numeric MQTT data.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return Math.floor(percent * 100) + "%";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// Storage methods
|
||||||
|
// ----------------------------------------
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getData() {
|
public double getData() {
|
||||||
return data;
|
return percent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setData(double data) {
|
public void setData(double data) {
|
||||||
this.data = data;
|
this.percent = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -24,7 +24,9 @@ package se.hal.struct.devicedata;
|
||||||
|
|
||||||
import se.hal.intf.HalEventData;
|
import se.hal.intf.HalEventData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a 'ON' or 'OFF' state based event.
|
||||||
|
*/
|
||||||
public class OnOffEventData extends HalEventData {
|
public class OnOffEventData extends HalEventData {
|
||||||
|
|
||||||
private boolean isOn;
|
private boolean isOn;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@ package se.hal.struct.devicedata;
|
||||||
import se.hal.intf.HalEventData;
|
import se.hal.intf.HalEventData;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an 'Opened' or 'Closed' state based event.
|
||||||
|
*/
|
||||||
public class OpenClosedEventData extends HalEventData {
|
public class OpenClosedEventData extends HalEventData {
|
||||||
|
|
||||||
private boolean isOpen;
|
private boolean isOpen;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package se.hal.struct.devicedata;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class ColorEventDataTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getData() {
|
||||||
|
assertEquals(0.0, new ColorEventData(0, 0, 0, 0).getData(), 0);
|
||||||
|
assertEquals(6553600.0, new ColorEventData(100, 0, 0, 0).getData(), 0);
|
||||||
|
assertEquals(25600.0, new ColorEventData(0, 100, 0, 0).getData(), 0);
|
||||||
|
assertEquals(100.0, new ColorEventData(0, 0, 100, 0).getData(), 0);
|
||||||
|
assertEquals(16777215.0, new ColorEventData(255, 255, 255, 0).getData(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setData() {
|
||||||
|
ColorEventData colorData = new ColorEventData();
|
||||||
|
colorData.setData(0);
|
||||||
|
assertEquals(0, colorData.getRed());
|
||||||
|
assertEquals(0, colorData.getGreen());
|
||||||
|
assertEquals(0, colorData.getBlue());
|
||||||
|
|
||||||
|
colorData.setData(6553600.0);
|
||||||
|
assertEquals(100, colorData.getRed());
|
||||||
|
assertEquals(0, colorData.getGreen());
|
||||||
|
assertEquals(0, colorData.getBlue());
|
||||||
|
|
||||||
|
colorData.setData(25600.0);
|
||||||
|
assertEquals(0, colorData.getRed());
|
||||||
|
assertEquals(100, colorData.getGreen());
|
||||||
|
assertEquals(0, colorData.getBlue());
|
||||||
|
|
||||||
|
colorData.setData(100.0);
|
||||||
|
assertEquals(0, colorData.getRed());
|
||||||
|
assertEquals(0, colorData.getGreen());
|
||||||
|
assertEquals(100, colorData.getBlue());
|
||||||
|
|
||||||
|
colorData.setData(16777215.0);
|
||||||
|
assertEquals(255, colorData.getRed());
|
||||||
|
assertEquals(255, colorData.getGreen());
|
||||||
|
assertEquals(255, colorData.getBlue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,15 +27,14 @@ package se.hal.plugin.mqtt;
|
||||||
import se.hal.daemon.HalMulticastDnsDaemon;
|
import se.hal.daemon.HalMulticastDnsDaemon;
|
||||||
import se.hal.intf.*;
|
import se.hal.intf.*;
|
||||||
import se.hal.plugin.mqtt.device.HalMqttDeviceConfig;
|
import se.hal.plugin.mqtt.device.HalMqttDeviceConfig;
|
||||||
import se.hal.plugin.mqtt.device.HalMqttDeviceData;
|
|
||||||
import zutil.InetUtil;
|
import zutil.InetUtil;
|
||||||
import zutil.log.LogUtil;
|
import zutil.log.LogUtil;
|
||||||
import zutil.net.dns.MulticastDnsServer;
|
|
||||||
import zutil.net.mqtt.MqttBroker;
|
import zutil.net.mqtt.MqttBroker;
|
||||||
import zutil.net.mqtt.MqttSubscriptionListener;
|
import zutil.net.mqtt.MqttSubscriptionListener;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
@ -47,7 +46,7 @@ public class HalMqttController implements HalAutostartController, MqttSubscripti
|
||||||
|
|
||||||
private MqttBroker mqttBroker;
|
private MqttBroker mqttBroker;
|
||||||
|
|
||||||
private HashMap<String, HalMqttDeviceConfig> topics = new HashMap<>();
|
private HashMap<String, List<HalMqttDeviceConfig>> topics = new HashMap<>();
|
||||||
private List<HalDeviceReportListener> deviceListeners = new CopyOnWriteArrayList<>();
|
private List<HalDeviceReportListener> deviceListeners = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
// --------------------------
|
// --------------------------
|
||||||
|
|
@ -67,6 +66,7 @@ public class HalMqttController implements HalAutostartController, MqttSubscripti
|
||||||
|
|
||||||
logger.info("Starting up MQTT Server");
|
logger.info("Starting up MQTT Server");
|
||||||
mqttBroker = new MqttBroker();
|
mqttBroker = new MqttBroker();
|
||||||
|
mqttBroker.addGlobalSubscriber(this);
|
||||||
mqttBroker.start();
|
mqttBroker.start();
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
@ -96,14 +96,16 @@ public class HalMqttController implements HalAutostartController, MqttSubscripti
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dataPublished(String topic, byte[] data) {
|
public void dataPublished(String topic, byte[] data) {
|
||||||
HalMqttDeviceConfig eventConfig = topics.get(topic);
|
List<HalMqttDeviceConfig> devices = topics.get(topic);
|
||||||
|
|
||||||
if (eventConfig != null && data.length > 0) {
|
if (devices != null && data.length > 0) {
|
||||||
HalMqttDeviceData eventData = new HalMqttDeviceData(data);
|
for (HalMqttDeviceConfig deviceConfig : devices) {
|
||||||
|
HalDeviceData deviceData = deviceConfig.getDeviceData(data);
|
||||||
|
|
||||||
if (deviceListeners != null) {
|
if (deviceListeners != null) {
|
||||||
for (HalDeviceReportListener deviceListener : deviceListeners) {
|
for (HalDeviceReportListener deviceListener : deviceListeners) {
|
||||||
deviceListener.reportReceived(eventConfig, eventData);
|
deviceListener.reportReceived(deviceConfig, deviceData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -121,7 +123,10 @@ public class HalMqttController implements HalAutostartController, MqttSubscripti
|
||||||
public void register(HalDeviceConfig deviceConfig) {
|
public void register(HalDeviceConfig deviceConfig) {
|
||||||
if (deviceConfig instanceof HalMqttDeviceConfig) {
|
if (deviceConfig instanceof HalMqttDeviceConfig) {
|
||||||
HalMqttDeviceConfig mqttEvent = (HalMqttDeviceConfig) deviceConfig;
|
HalMqttDeviceConfig mqttEvent = (HalMqttDeviceConfig) deviceConfig;
|
||||||
topics.put(mqttEvent.getTopic(), mqttEvent);
|
|
||||||
|
if (!topics.containsKey(mqttEvent.getTopic()))
|
||||||
|
topics.put(mqttEvent.getTopic(), new ArrayList<>());
|
||||||
|
topics.get(mqttEvent.getTopic()).add(mqttEvent);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Device config is not an instance of " + HalMqttDeviceConfig.class + ": " + deviceConfig.getClass());
|
"Device config is not an instance of " + HalMqttDeviceConfig.class + ": " + deviceConfig.getClass());
|
||||||
|
|
@ -132,7 +137,8 @@ public class HalMqttController implements HalAutostartController, MqttSubscripti
|
||||||
public void deregister(HalDeviceConfig deviceConfig) {
|
public void deregister(HalDeviceConfig deviceConfig) {
|
||||||
if (deviceConfig instanceof HalMqttDeviceConfig) {
|
if (deviceConfig instanceof HalMqttDeviceConfig) {
|
||||||
HalMqttDeviceConfig mqttEvent = (HalMqttDeviceConfig) deviceConfig;
|
HalMqttDeviceConfig mqttEvent = (HalMqttDeviceConfig) deviceConfig;
|
||||||
topics.remove(mqttEvent.getTopic());
|
if (topics.containsKey(mqttEvent.getTopic()))
|
||||||
|
topics.get(mqttEvent.getTopic()).remove(deviceConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,7 +153,11 @@ public class HalMqttController implements HalAutostartController, MqttSubscripti
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return topics.size();
|
int size = 0;
|
||||||
|
for (List<HalMqttDeviceConfig> devices : topics.values()) {
|
||||||
|
size += devices.size();
|
||||||
|
}
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -48,23 +48,34 @@
|
||||||
|
|
||||||
package se.hal.plugin.mqtt.device;
|
package se.hal.plugin.mqtt.device;
|
||||||
|
|
||||||
import se.hal.intf.HalEventConfig;
|
import se.hal.intf.HalDeviceData;
|
||||||
import se.hal.intf.HalEventController;
|
import se.hal.intf.HalEventController;
|
||||||
import se.hal.intf.HalEventData;
|
import se.hal.intf.HalEventData;
|
||||||
|
import se.hal.intf.HalSensorConfig;
|
||||||
import se.hal.plugin.mqtt.HalMqttController;
|
import se.hal.plugin.mqtt.HalMqttController;
|
||||||
|
import zutil.ui.conf.Configurator;
|
||||||
|
|
||||||
public class HalMqttDeviceConfig implements HalEventConfig {
|
public abstract class HalMqttDeviceConfig implements HalSensorConfig {
|
||||||
private final String topic;
|
@Configurator.Configurable(value = "MQTT Topic")
|
||||||
|
private String topic;
|
||||||
|
@Configurator.Configurable(value = "JSON Path", description = "If the value of the topic is a JSON then this parameter can be used to specify the path to the e.g. temperature value." +
|
||||||
public HalMqttDeviceConfig(String topic) {
|
"<br>THe parameter uses the JSON-Path syntax where it always starts with $ and object fields can be accessed by .<key> and a array element by [index]")
|
||||||
this.topic = topic;
|
private String jsonPath;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getTopic() {
|
public String getTopic() {
|
||||||
return topic;
|
return topic;
|
||||||
}
|
}
|
||||||
|
public void setTopic(String topic) {
|
||||||
|
this.topic = topic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJsonPath() {
|
||||||
|
return jsonPath;
|
||||||
|
}
|
||||||
|
public void setJsonPath(String jsonPath) {
|
||||||
|
this.jsonPath = jsonPath;
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------
|
// --------------------------
|
||||||
// Hal Methods
|
// Hal Methods
|
||||||
|
|
@ -75,15 +86,25 @@ public class HalMqttDeviceConfig implements HalEventConfig {
|
||||||
return HalMqttController.class;
|
return HalMqttController.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public Class<? extends HalEventData> getDeviceDataClass() {
|
* @param data the data published to the MQTT topic.
|
||||||
return HalMqttDeviceData.class;
|
* @return a new data object instance containing the device data based on the input data.
|
||||||
}
|
*/
|
||||||
|
public abstract HalDeviceData getDeviceData(byte[] data);
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
// Java Methods
|
||||||
|
// --------------------------
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj instanceof HalMqttDeviceConfig)
|
if (obj instanceof HalMqttDeviceConfig)
|
||||||
return topic.equals(((HalMqttDeviceConfig) obj).topic);
|
return topic.equals(((HalMqttDeviceConfig) obj).topic) && jsonPath.equals(((HalMqttDeviceConfig) obj).jsonPath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Topic: " + topic + ", JSON Path: " + jsonPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Ziver Koc
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Ziver Koc
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.hal.plugin.mqtt.device;
|
||||||
|
|
||||||
|
import se.hal.intf.HalDeviceData;
|
||||||
|
import se.hal.intf.HalEventController;
|
||||||
|
import se.hal.plugin.mqtt.HalMqttController;
|
||||||
|
import se.hal.struct.devicedata.TemperatureSensorData;
|
||||||
|
import zutil.ObjectUtil;
|
||||||
|
import zutil.converter.Converter;
|
||||||
|
import zutil.parser.DataNode;
|
||||||
|
import zutil.parser.DataNodePath;
|
||||||
|
import zutil.parser.json.JSONParser;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class HalMqttParticularMatterDeviceConfig extends HalMqttDeviceConfig {
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
// Hal Methods
|
||||||
|
// --------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends HalEventController> getDeviceControllerClass() {
|
||||||
|
return HalMqttController.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends HalDeviceData> getDeviceDataClass() {
|
||||||
|
return TemperatureSensorData.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HalDeviceData getDeviceData(byte[] data) {
|
||||||
|
if (!ObjectUtil.isEmpty(getJsonPath())) {
|
||||||
|
String dataStr = new String(data, StandardCharsets.UTF_8);
|
||||||
|
DataNode json = JSONParser.read(dataStr);
|
||||||
|
DataNode deviceDataValue = DataNodePath.search(getJsonPath(), json);
|
||||||
|
|
||||||
|
if (deviceDataValue != null)
|
||||||
|
return new TemperatureSensorData(deviceDataValue.getDouble(), System.currentTimeMillis());
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new TemperatureSensorData(Converter.toInt(data), System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AggregationMethod getAggregationMethod() {
|
||||||
|
return AggregationMethod.AVERAGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
"interfaces": [
|
"interfaces": [
|
||||||
{"se.hal.intf.HalAutostartController": "se.hal.plugin.mqtt.HalMqttController"},
|
{"se.hal.intf.HalAutostartController": "se.hal.plugin.mqtt.HalMqttController"},
|
||||||
|
|
||||||
|
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.mqtt.device.HalMqttParticularMatterDeviceConfig"},
|
||||||
|
|
||||||
{"se.hal.intf.HalWebPage": "se.hal.plugin.mqtt.page.MqttOverviewPage"}
|
{"se.hal.intf.HalWebPage": "se.hal.plugin.mqtt.page.MqttOverviewPage"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
dependencies {
|
dependencies {
|
||||||
def ZIGBEE_LIB_VERSION = "1.3.8"
|
def ZIGBEE_LIB_VERSION = "1.4.11"
|
||||||
|
|
||||||
implementation project(':hal-core')
|
implementation project(':hal-core')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,19 @@
|
||||||
<div class="panel panel-default drop-shadow">
|
<div class="panel panel-default drop-shadow">
|
||||||
<!-- NODE -->
|
<!-- NODE -->
|
||||||
|
|
||||||
<div class="panel-heading">
|
<div class="panel-heading clearfix">
|
||||||
<a href="#a" data-toggle="collapse" data-target="#node-{{.getIeeeAddress()}}">
|
<a href="#a" class="pull-left" data-toggle="collapse" data-target="#node-{{.getIeeeAddress()}}">
|
||||||
Node: {{.getIeeeAddress()}}
|
Node: {{.getIeeeAddress()}}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<div class="btn-toolbar pull-right">
|
||||||
|
<form method="POST">
|
||||||
|
<input type="hidden" name="nodeAddress" value="{{.getIeeeAddress()}}">
|
||||||
|
<button type="submit" class="btn btn-danger btn-xs" name="action" value="node_remove">
|
||||||
|
<small class="glyphicon glyphicon-trash"></small>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="node-{{.getIeeeAddress()}}" class="panel-body collapse">
|
<div id="node-{{.getIeeeAddress()}}" class="panel-body collapse">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
|
@ -122,6 +131,7 @@
|
||||||
<thead>
|
<thead>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
|
<th>Type</th>
|
||||||
<th>Last Value</th>
|
<th>Last Value</th>
|
||||||
<th>Last Report Time</th>
|
<th>Last Report Time</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
|
|
@ -130,6 +140,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.getId()}}</td>
|
<td>{{.getId()}}</td>
|
||||||
<td>{{.getName()}}</td>
|
<td>{{.getName()}}</td>
|
||||||
|
<td>{{.getDataType()}}</td>
|
||||||
<td>{{.getLastValue()}}</td>
|
<td>{{.getLastValue()}}</td>
|
||||||
<td><span class="timestamp">{{.getLastReportTime().getTimeInMillis()}}</span></td>
|
<td><span class="timestamp">{{.getLastReportTime().getTimeInMillis()}}</span></td>
|
||||||
<td>
|
<td>
|
||||||
|
|
@ -168,6 +179,7 @@
|
||||||
<thead>
|
<thead>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
|
<th>Type</th>
|
||||||
<th>Last Value</th>
|
<th>Last Value</th>
|
||||||
<th>Last Report Time</th>
|
<th>Last Report Time</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
|
|
@ -176,6 +188,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.getId()}}</td>
|
<td>{{.getId()}}</td>
|
||||||
<td>{{.getName()}}</td>
|
<td>{{.getName()}}</td>
|
||||||
|
<td>{{.getDataType()}}</td>
|
||||||
<td>{{.getLastValue()}}</td>
|
<td>{{.getLastValue()}}</td>
|
||||||
<td><span class="timestamp">{{.getLastReportTime().getTimeInMillis()}}</span></td>
|
<td><span class="timestamp">{{.getLastReportTime().getTimeInMillis()}}</span></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,10 @@ public class ZigbeeController implements HalSensorController,
|
||||||
// Zigbee Node Methods
|
// Zigbee Node Methods
|
||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
|
|
||||||
|
public void unPairNode(ZigBeeNode node) {
|
||||||
|
networkManager.leave(node.getNetworkAddress(), node.getIeeeAddress(), true);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deviceStatusUpdate(ZigBeeNodeStatus deviceStatus, Integer networkAddress, IeeeAddress ieeeAddress) {
|
public void deviceStatusUpdate(ZigBeeNodeStatus deviceStatus, Integer networkAddress, IeeeAddress ieeeAddress) {
|
||||||
logger.fine("New device connected to network: " + ieeeAddress + "(" + deviceStatus + ")");
|
logger.fine("New device connected to network: " + ieeeAddress + "(" + deviceStatus + ")");
|
||||||
|
|
@ -402,7 +406,7 @@ public class ZigbeeController implements HalSensorController,
|
||||||
public void attributeUpdated(ZclAttribute attribute, Object value) {
|
public void attributeUpdated(ZclAttribute attribute, Object value) {
|
||||||
logger.finer("[Node: " + endpoint.getIeeeAddress() + ", Endpoint: " + endpoint.getEndpointId() + ", Cluster: " + attribute.getCluster().getId() + "] Attribute " + config.getClass().getSimpleName() + " updated: id=" + attribute.getId() + ", attribute_name=" + attribute.getName() + ", value=" + attribute.getLastValue());
|
logger.finer("[Node: " + endpoint.getIeeeAddress() + ", Endpoint: " + endpoint.getEndpointId() + ", Cluster: " + attribute.getCluster().getId() + "] Attribute " + config.getClass().getSimpleName() + " updated: id=" + attribute.getId() + ", attribute_name=" + attribute.getName() + ", value=" + attribute.getLastValue());
|
||||||
|
|
||||||
HalDeviceData data = config.getDeviceData(attribute);
|
HalDeviceData data = config.getDeviceData(endpoint, attribute);
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
for (HalDeviceReportListener deviceListener : deviceListeners) {
|
for (HalDeviceReportListener deviceListener : deviceListeners) {
|
||||||
deviceListener.reportReceived(config, data);
|
deviceListener.reportReceived(config, data);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
package se.hal.plugin.zigbee.device;
|
||||||
|
|
||||||
|
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
|
||||||
|
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
||||||
|
import com.zsmartsystems.zigbee.zcl.ZclCluster;
|
||||||
|
import com.zsmartsystems.zigbee.zcl.ZclCommand;
|
||||||
|
import com.zsmartsystems.zigbee.zcl.clusters.ZclColorControlCluster;
|
||||||
|
import com.zsmartsystems.zigbee.zcl.clusters.colorcontrol.MoveToColorCommand;
|
||||||
|
import se.hal.intf.HalDeviceData;
|
||||||
|
import se.hal.intf.HalEventConfig;
|
||||||
|
import se.hal.intf.HalEventData;
|
||||||
|
import se.hal.struct.devicedata.ColorEventData;
|
||||||
|
import zutil.log.LogUtil;
|
||||||
|
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A device configuration for a specific endpoint on a Zigbee device.
|
||||||
|
*/
|
||||||
|
public class ZigbeeColorConfig extends ZigbeeHalEventDeviceConfig implements HalEventConfig {
|
||||||
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
// Zigbee Methods
|
||||||
|
// --------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(ZclCluster cluster) {
|
||||||
|
if (! (cluster instanceof ZclColorControlCluster))
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ZclAttribute attribute = cluster.getAttribute(ZclColorControlCluster.ATTR_CURRENTHUE);
|
||||||
|
attribute.setReporting(1, 900).get();
|
||||||
|
attribute.readValue(60);
|
||||||
|
|
||||||
|
attribute = cluster.getAttribute(ZclColorControlCluster.ATTR_CURRENTSATURATION);
|
||||||
|
attribute.setReporting(1, 900).get();
|
||||||
|
attribute.readValue(60);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.WARNING, "Was unable to initialize cluster reporting rate.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
|
||||||
|
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
|
||||||
|
(zclAttribute.getId() == ZclColorControlCluster.ATTR_CURRENTHUE ||
|
||||||
|
zclAttribute.getId() == ZclColorControlCluster.ATTR_CURRENTSATURATION)) {
|
||||||
|
|
||||||
|
ZclCluster cluster = endpoint.getInputCluster(zclAttribute.getClusterType().getId());
|
||||||
|
float hue = (Integer) cluster.getAttribute(ZclColorControlCluster.ATTR_CURRENTHUE).getLastValue();
|
||||||
|
float saturation = (Integer) cluster.getAttribute(ZclColorControlCluster.ATTR_CURRENTSATURATION).getLastValue();
|
||||||
|
return ColorEventData.createFromHLS(
|
||||||
|
hue, 0.5f, saturation,
|
||||||
|
zclAttribute.getLastReportTime().getTimeInMillis());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getZigbeeClusterId() {
|
||||||
|
return ZclColorControlCluster.CLUSTER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ZclCommand getZigbeeCommandObject(HalEventData data) {
|
||||||
|
if (! (data instanceof ColorEventData))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
float[] cieXYZ = ((ColorEventData) data).getCieXYZ();
|
||||||
|
return new MoveToColorCommand((int) cieXYZ[0], (int) cieXYZ[1], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
// Hal Methods
|
||||||
|
// --------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends HalDeviceData> getDeviceDataClass() {
|
||||||
|
return ColorEventData.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -66,10 +66,11 @@ public abstract class ZigbeeHalDeviceConfig implements HalDeviceConfig {
|
||||||
public void initialize(ZclCluster cluster) {}
|
public void initialize(ZclCluster cluster) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param endpoint
|
||||||
* @param zclAttribute is the object that should be mapped to a HalDeviceFata object.
|
* @param zclAttribute is the object that should be mapped to a HalDeviceFata object.
|
||||||
* @return a HalDeviceData object containing the same value representation as the endpoint or null if this attribute is not translatable.
|
* @return a HalDeviceData object containing the same value representation as the endpoint or null if this attribute is not translatable.
|
||||||
*/
|
*/
|
||||||
public abstract HalDeviceData getDeviceData(ZclAttribute zclAttribute);
|
public abstract HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the cluster ID that is supported by this device config class
|
* @return the cluster ID that is supported by this device config class
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,10 @@ public class ZigbeeHalDeviceFactory {
|
||||||
|
|
||||||
private static final HashMap<Integer, Class<? extends ZigbeeHalDeviceConfig>> clusterDeviceMap = new HashMap<>();
|
private static final HashMap<Integer, Class<? extends ZigbeeHalDeviceConfig>> clusterDeviceMap = new HashMap<>();
|
||||||
static {
|
static {
|
||||||
|
clusterDeviceMap.put(new ZigbeeColorConfig().getZigbeeClusterId(), ZigbeeColorConfig.class);
|
||||||
clusterDeviceMap.put(new ZigbeeHumidityConfig().getZigbeeClusterId(), ZigbeeHumidityConfig.class);
|
clusterDeviceMap.put(new ZigbeeHumidityConfig().getZigbeeClusterId(), ZigbeeHumidityConfig.class);
|
||||||
clusterDeviceMap.put(new ZigbeeIlluminanceConfig().getZigbeeClusterId(), ZigbeeIlluminanceConfig.class);
|
clusterDeviceMap.put(new ZigbeeIlluminanceConfig().getZigbeeClusterId(), ZigbeeIlluminanceConfig.class);
|
||||||
|
clusterDeviceMap.put(new ZigbeeLevelConfig().getZigbeeClusterId(), ZigbeeLevelConfig.class);
|
||||||
clusterDeviceMap.put(new ZigbeeOccupancyConfig().getZigbeeClusterId(), ZigbeeOccupancyConfig.class);
|
clusterDeviceMap.put(new ZigbeeOccupancyConfig().getZigbeeClusterId(), ZigbeeOccupancyConfig.class);
|
||||||
clusterDeviceMap.put(new ZigbeeOnOffConfig().getZigbeeClusterId(), ZigbeeOnOffConfig.class);
|
clusterDeviceMap.put(new ZigbeeOnOffConfig().getZigbeeClusterId(), ZigbeeOnOffConfig.class);
|
||||||
clusterDeviceMap.put(new ZigbeePressureConfig().getZigbeeClusterId(), ZigbeePressureConfig.class);
|
clusterDeviceMap.put(new ZigbeePressureConfig().getZigbeeClusterId(), ZigbeePressureConfig.class);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package se.hal.plugin.zigbee.device;
|
package se.hal.plugin.zigbee.device;
|
||||||
|
|
||||||
|
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
|
||||||
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
||||||
import com.zsmartsystems.zigbee.zcl.clusters.ZclRelativeHumidityMeasurementCluster;
|
import com.zsmartsystems.zigbee.zcl.clusters.ZclRelativeHumidityMeasurementCluster;
|
||||||
import se.hal.intf.HalDeviceData;
|
import se.hal.intf.HalDeviceData;
|
||||||
import se.hal.intf.HalSensorConfig;
|
import se.hal.intf.HalSensorConfig;
|
||||||
import se.hal.struct.devicedata.HumiditySensorData;
|
import se.hal.struct.devicedata.HumiditySensorData;
|
||||||
import se.hal.struct.devicedata.TemperatureSensorData;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A device configuration for a specific endpoint on a Zigbee device.
|
* A device configuration for a specific endpoint on a Zigbee device.
|
||||||
|
|
@ -17,8 +17,8 @@ public class ZigbeeHumidityConfig extends ZigbeeHalDeviceConfig implements HalSe
|
||||||
// --------------------------
|
// --------------------------
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
|
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
|
||||||
if (zclAttribute.getCluster().getId() == getZigbeeClusterId() &&
|
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
|
||||||
zclAttribute.getId() == ZclRelativeHumidityMeasurementCluster.ATTR_MEASUREDVALUE)
|
zclAttribute.getId() == ZclRelativeHumidityMeasurementCluster.ATTR_MEASUREDVALUE)
|
||||||
return new HumiditySensorData(
|
return new HumiditySensorData(
|
||||||
((int) zclAttribute.getLastValue()) / 100.0,
|
((int) zclAttribute.getLastValue()) / 100.0,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package se.hal.plugin.zigbee.device;
|
package se.hal.plugin.zigbee.device;
|
||||||
|
|
||||||
|
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
|
||||||
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
||||||
import com.zsmartsystems.zigbee.zcl.clusters.ZclIlluminanceMeasurementCluster;
|
import com.zsmartsystems.zigbee.zcl.clusters.ZclIlluminanceMeasurementCluster;
|
||||||
import se.hal.intf.HalDeviceData;
|
import se.hal.intf.HalDeviceData;
|
||||||
|
|
@ -16,8 +17,8 @@ public class ZigbeeIlluminanceConfig extends ZigbeeHalDeviceConfig implements Ha
|
||||||
// --------------------------
|
// --------------------------
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
|
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
|
||||||
if (zclAttribute.getCluster().getId() == getZigbeeClusterId() &&
|
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
|
||||||
zclAttribute.getId() == ZclIlluminanceMeasurementCluster.ATTR_MEASUREDVALUE)
|
zclAttribute.getId() == ZclIlluminanceMeasurementCluster.ATTR_MEASUREDVALUE)
|
||||||
return new IlluminanceSensorData(
|
return new IlluminanceSensorData(
|
||||||
(int) zclAttribute.getLastValue(),
|
(int) zclAttribute.getLastValue(),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package se.hal.plugin.zigbee.device;
|
||||||
|
|
||||||
|
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
|
||||||
|
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
||||||
|
import com.zsmartsystems.zigbee.zcl.ZclCluster;
|
||||||
|
import com.zsmartsystems.zigbee.zcl.ZclCommand;
|
||||||
|
import com.zsmartsystems.zigbee.zcl.clusters.ZclLevelControlCluster;
|
||||||
|
import com.zsmartsystems.zigbee.zcl.clusters.levelcontrol.MoveToLevelCommand;
|
||||||
|
import se.hal.intf.HalDeviceData;
|
||||||
|
import se.hal.intf.HalEventConfig;
|
||||||
|
import se.hal.intf.HalEventData;
|
||||||
|
import se.hal.struct.devicedata.LevelEventData;
|
||||||
|
import zutil.log.LogUtil;
|
||||||
|
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A device configuration for a specific endpoint on a Zigbee device.
|
||||||
|
*/
|
||||||
|
public class ZigbeeLevelConfig extends ZigbeeHalEventDeviceConfig implements HalEventConfig {
|
||||||
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
// Zigbee Methods
|
||||||
|
// --------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(ZclCluster cluster) {
|
||||||
|
if (! (cluster instanceof ZclLevelControlCluster))
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ZclAttribute attribute = cluster.getAttribute(ZclLevelControlCluster.ATTR_CURRENTLEVEL);
|
||||||
|
attribute.setReporting(1, 900).get();
|
||||||
|
attribute.readValue(60);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.WARNING, "Was unable to initialize cluster reporting rate.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
|
||||||
|
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
|
||||||
|
zclAttribute.getId() == ZclLevelControlCluster.ATTR_CURRENTLEVEL)
|
||||||
|
return new LevelEventData(
|
||||||
|
(Integer) zclAttribute.getLastValue(),
|
||||||
|
zclAttribute.getLastReportTime().getTimeInMillis());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getZigbeeClusterId() {
|
||||||
|
return ZclLevelControlCluster.CLUSTER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ZclCommand getZigbeeCommandObject(HalEventData data) {
|
||||||
|
if (! (data instanceof LevelEventData))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new MoveToLevelCommand((int) (data.getData() * 255), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------
|
||||||
|
// Hal Methods
|
||||||
|
// --------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends HalDeviceData> getDeviceDataClass() {
|
||||||
|
return LevelEventData.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package se.hal.plugin.zigbee.device;
|
package se.hal.plugin.zigbee.device;
|
||||||
|
|
||||||
|
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
|
||||||
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
||||||
import com.zsmartsystems.zigbee.zcl.ZclCluster;
|
import com.zsmartsystems.zigbee.zcl.ZclCluster;
|
||||||
import com.zsmartsystems.zigbee.zcl.clusters.ZclOccupancySensingCluster;
|
import com.zsmartsystems.zigbee.zcl.clusters.ZclOccupancySensingCluster;
|
||||||
|
|
@ -37,8 +38,8 @@ public class ZigbeeOccupancyConfig extends ZigbeeHalEventDeviceConfig implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
|
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
|
||||||
if (zclAttribute.getCluster().getId() == getZigbeeClusterId() &&
|
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
|
||||||
zclAttribute.getId() == ZclOccupancySensingCluster.ATTR_OCCUPANCY)
|
zclAttribute.getId() == ZclOccupancySensingCluster.ATTR_OCCUPANCY)
|
||||||
return new OccupancyEventData(
|
return new OccupancyEventData(
|
||||||
(boolean) zclAttribute.getLastValue(),
|
(boolean) zclAttribute.getLastValue(),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package se.hal.plugin.zigbee.device;
|
package se.hal.plugin.zigbee.device;
|
||||||
|
|
||||||
|
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
|
||||||
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
||||||
import com.zsmartsystems.zigbee.zcl.ZclCluster;
|
import com.zsmartsystems.zigbee.zcl.ZclCluster;
|
||||||
import com.zsmartsystems.zigbee.zcl.ZclCommand;
|
import com.zsmartsystems.zigbee.zcl.ZclCommand;
|
||||||
|
|
@ -40,8 +41,8 @@ public class ZigbeeOnOffConfig extends ZigbeeHalEventDeviceConfig implements Hal
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
|
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
|
||||||
if (zclAttribute.getCluster().getId() == getZigbeeClusterId() &&
|
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
|
||||||
zclAttribute.getId() == ZclOnOffCluster.ATTR_ONOFF)
|
zclAttribute.getId() == ZclOnOffCluster.ATTR_ONOFF)
|
||||||
return new OnOffEventData(
|
return new OnOffEventData(
|
||||||
(boolean) zclAttribute.getLastValue(),
|
(boolean) zclAttribute.getLastValue(),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package se.hal.plugin.zigbee.device;
|
package se.hal.plugin.zigbee.device;
|
||||||
|
|
||||||
|
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
|
||||||
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
||||||
import com.zsmartsystems.zigbee.zcl.clusters.ZclTemperatureMeasurementCluster;
|
import com.zsmartsystems.zigbee.zcl.clusters.ZclTemperatureMeasurementCluster;
|
||||||
import se.hal.intf.HalDeviceData;
|
import se.hal.intf.HalDeviceData;
|
||||||
|
|
@ -16,8 +17,8 @@ public class ZigbeePressureConfig extends ZigbeeHalDeviceConfig implements HalSe
|
||||||
// --------------------------
|
// --------------------------
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
|
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
|
||||||
if (zclAttribute.getCluster().getId() == getZigbeeClusterId() &&
|
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
|
||||||
zclAttribute.getId() == ZclTemperatureMeasurementCluster.ATTR_MEASUREDVALUE)
|
zclAttribute.getId() == ZclTemperatureMeasurementCluster.ATTR_MEASUREDVALUE)
|
||||||
return new PressureSensorData(
|
return new PressureSensorData(
|
||||||
(int) zclAttribute.getLastValue(),
|
(int) zclAttribute.getLastValue(),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package se.hal.plugin.zigbee.device;
|
package se.hal.plugin.zigbee.device;
|
||||||
|
|
||||||
|
import com.zsmartsystems.zigbee.ZigBeeEndpoint;
|
||||||
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
import com.zsmartsystems.zigbee.zcl.ZclAttribute;
|
||||||
import com.zsmartsystems.zigbee.zcl.clusters.ZclTemperatureMeasurementCluster;
|
import com.zsmartsystems.zigbee.zcl.clusters.ZclTemperatureMeasurementCluster;
|
||||||
import se.hal.intf.HalDeviceData;
|
import se.hal.intf.HalDeviceData;
|
||||||
|
|
@ -17,8 +18,8 @@ public class ZigbeeTemperatureConfig extends ZigbeeHalDeviceConfig implements Ha
|
||||||
// --------------------------
|
// --------------------------
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HalDeviceData getDeviceData(ZclAttribute zclAttribute) {
|
public HalDeviceData getDeviceData(ZigBeeEndpoint endpoint, ZclAttribute zclAttribute) {
|
||||||
if (zclAttribute.getCluster().getId() == getZigbeeClusterId() &&
|
if (zclAttribute.getClusterType().getId() == getZigbeeClusterId() &&
|
||||||
zclAttribute.getId() == ZclTemperatureMeasurementCluster.ATTR_MEASUREDVALUE)
|
zclAttribute.getId() == ZclTemperatureMeasurementCluster.ATTR_MEASUREDVALUE)
|
||||||
return new TemperatureSensorData(
|
return new TemperatureSensorData(
|
||||||
((int) zclAttribute.getLastValue()) / 100.0,
|
((int) zclAttribute.getLastValue()) / 100.0,
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,11 @@ public class ZigbeeNetworkPage extends HalWebPage {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (request.get("action")) {
|
switch (request.get("action")) {
|
||||||
|
case "node_remove":
|
||||||
|
if (node != null)
|
||||||
|
controller.unPairNode(node);
|
||||||
|
break;
|
||||||
|
|
||||||
case "refresh":
|
case "refresh":
|
||||||
if (attribute != null)
|
if (attribute != null)
|
||||||
attribute.readValue(0);
|
attribute.readValue(0);
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,11 @@
|
||||||
"interfaces": [
|
"interfaces": [
|
||||||
{"se.hal.intf.HalDatabaseUpgrader": "se.hal.plugin.zigbee.db.ZigbeeHalDatabaseUpgrader"},
|
{"se.hal.intf.HalDatabaseUpgrader": "se.hal.plugin.zigbee.db.ZigbeeHalDatabaseUpgrader"},
|
||||||
|
|
||||||
|
{"se.hal.intf.HalEventConfig": "se.hal.plugin.zigbee.device.ZigbeeColorConfig"},
|
||||||
{"se.hal.intf.HalEventConfig": "se.hal.plugin.zigbee.device.ZigbeeOnOffConfig"},
|
{"se.hal.intf.HalEventConfig": "se.hal.plugin.zigbee.device.ZigbeeOnOffConfig"},
|
||||||
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeeHumidityConfig"},
|
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeeHumidityConfig"},
|
||||||
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeeIlluminanceConfig"},
|
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeeIlluminanceConfig"},
|
||||||
|
{"se.hal.intf.HalEventConfig": "se.hal.plugin.zigbee.device.ZigbeeLevelConfig"},
|
||||||
{"se.hal.intf.HalEventConfig": "se.hal.plugin.zigbee.device.ZigbeeOccupancyConfig"},
|
{"se.hal.intf.HalEventConfig": "se.hal.plugin.zigbee.device.ZigbeeOccupancyConfig"},
|
||||||
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeePressureConfig"},
|
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeePressureConfig"},
|
||||||
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeeTemperatureConfig"},
|
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.zigbee.device.ZigbeeTemperatureConfig"},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue