Skip to content

Commit

Permalink
Add LQI/RSSI information to ApsFrame
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Jackson <[email protected]>
  • Loading branch information
cdjackson committed Mar 15, 2020
1 parent a1ccb3d commit ba8598c
Show file tree
Hide file tree
Showing 9 changed files with 228 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,9 @@ public void handlePacket(EzspFrame response) {
apsFrame.setSourceAddress(incomingMessage.getSender());
apsFrame.setSourceEndpoint(emberApsFrame.getSourceEndpoint());

apsFrame.setReceivedLqi(incomingMessage.getLastHopLqi());
apsFrame.setReceivedRssi(incomingMessage.getLastHopRssi());

apsFrame.setPayload(incomingMessage.getMessageContents());
zigbeeTransportReceive.receiveCommand(apsFrame);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2016-2020 by the respective copyright holders.
* 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 com.zsmartsystems.zigbee;

/**
* An interface that allows clients to retrieve link quality information available from a node
*
* @author Chris Jackson
*
*/
public interface ZigBeeLinkQualityStatistics {
/**
* Returns the LQI value from the last recieved packet
*
* @return the last received LQI value
*/
public Integer getLastReceivedLqi();

/**
* Returns the RSSI value from the last recieved packet
*
* @return the last received RSSI value in dBm
*/
public Integer getLastReceivedRssi();

}
Original file line number Diff line number Diff line change
Expand Up @@ -959,16 +959,27 @@ public void run() {

// Pass the command to the transaction manager for processing
// If the transaction manager wants to drop this command, it returns null
command = transactionManager.receive(command);
if (command == null) {
final ZigBeeCommand finalCommand = transactionManager.receive(command);
if (finalCommand == null) {
return;
}

// Ignore the DefaultResponse
if (command instanceof DefaultResponse) {
if (finalCommand instanceof DefaultResponse) {
return;
}

// Directly distribute commands to nodes
ZigBeeNode node = getNode(command.getSourceAddress().getAddress());
if (node != null) {
NotificationService.execute(new Runnable() {
@Override
public void run() {
node.commandReceived(finalCommand, apsFrame.getReceivedRssi(), apsFrame.getReceivedLqi());
}
});
}

// Notify the listeners
commandNotifier.notifyCommandListeners(command);
}
Expand Down Expand Up @@ -1585,7 +1596,6 @@ public void removeNode(final ZigBeeNode node) {
return;
}
networkNodes.remove(node.getIeeeAddress());
removeCommandListener(node);

synchronized (this) {
if (networkState != ZigBeeNetworkState.ONLINE) {
Expand Down Expand Up @@ -1628,7 +1638,6 @@ public void updateNode(final ZigBeeNode node) {
return;
}
networkNodes.put(node.getIeeeAddress(), node);
addCommandListener(node);

synchronized (this) {
if (networkState != ZigBeeNetworkState.ONLINE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.zsmartsystems.zigbee.database.ZigBeeEndpointDao;
import com.zsmartsystems.zigbee.database.ZigBeeNodeDao;
import com.zsmartsystems.zigbee.internal.NotificationService;
import com.zsmartsystems.zigbee.internal.ZigBeeNodeLinkQualityHandler;
import com.zsmartsystems.zigbee.transaction.ZigBeeTransactionMatcher;
import com.zsmartsystems.zigbee.zcl.ZclCluster;
import com.zsmartsystems.zigbee.zcl.ZclCommand;
Expand All @@ -53,7 +54,7 @@
* @author Chris Jackson
*
*/
public class ZigBeeNode implements ZigBeeCommandListener {
public class ZigBeeNode {
/**
* The {@link Logger}.
*/
Expand Down Expand Up @@ -143,6 +144,11 @@ public enum ZigBeeNodeState {
OFFLINE
}

/**
* A handler to manage the {@link ZigBeeLinkQualityStatistics}
*/
private ZigBeeNodeLinkQualityHandler linkQualityStatistics = new ZigBeeNodeLinkQualityHandler();

/**
* Constructor
*
Expand Down Expand Up @@ -319,13 +325,23 @@ public boolean isReducedFuntionDevice() {
return nodeDescriptor.getMacCapabilities().contains(MacCapabilitiesType.REDUCED_FUNCTION_DEVICE);
}

/**
* Returns true if the node is capable of supporting security. This tests the {@link NodeDescriptor}.
*
* @return true if the node is capable of supporting security
*/
public boolean isSecurityCapable() {
if (nodeDescriptor == null) {
return false;
}
return nodeDescriptor.getMacCapabilities().contains(MacCapabilitiesType.SECURITY_CAPABLE);
}

/**
* Returns true if the node is the primary trust centre. This tests the {@link NodeDescriptor}.
*
* @return true if the node is the primary trust centre
*/
public boolean isPrimaryTrustCenter() {
if (nodeDescriptor == null) {
return false;
Expand Down Expand Up @@ -670,8 +686,15 @@ public Date getLastUpdateTime() {
return lastUpdateTime;
}

@Override
public void commandReceived(ZigBeeCommand command) {
/**
* Incoming command handler. The node will process any commands addressed to this node ID and pass to
* the appropriate endpoint.
*
* @param command the {@link ZigBeeCommand} received
* @param rssi the Received Signal Strength Indicator of the received packet, or null
* @param lqi the Link Quality Indicator of the received packet, or null
*/
public void commandReceived(ZigBeeCommand command, Integer rssi, Integer lqi) {
// This gets called for all received commands
// Check if it's our address
if (!(command instanceof ZclCommand) || networkAddress == null
Expand All @@ -681,6 +704,9 @@ public void commandReceived(ZigBeeCommand command) {

logger.trace("{}: ZigBeeNode.commandReceived({})", ieeeAddress, command);

linkQualityStatistics.updateReceivedLqi(lqi);
linkQualityStatistics.updateReceivedRssi(rssi);

ZclCommand zclCommand = (ZclCommand) command;
ZigBeeEndpointAddress endpointAddress = (ZigBeeEndpointAddress) zclCommand.getSourceAddress();

Expand Down Expand Up @@ -888,6 +914,15 @@ public ZigBeeNodeState getNodeState() {
return nodeState;
}

/**
* Retrieves the {@link ZigBeeLinkQualityStatistics} for the node
*
* @return the {@link ZigBeeLinkQualityStatistics} for the node
*/
public ZigBeeLinkQualityStatistics getLinkQualityStatistics() {
return linkQualityStatistics;
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder(100);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ public class ZigBeeApsFrame {
*/
private int apsCounter = -1;

private Integer rssi;
private Integer lqi;

protected int fragmentSize;
protected int fragmentBase = 0;
protected int fragmentTotal = 0;
Expand Down Expand Up @@ -394,6 +397,62 @@ public int[] getPayload() {
return payload;
}

/**
* Calling this method indicates that transmission of a fragment has completed.
* It moves the fragment base and decrease outstanding fragments counter.
*/
public void oneFragmentCompleted() {
fragmentBase++;
if (fragmentOutstanding > 0) {
fragmentOutstanding--;
}
}

/**
* Calling this method indicates that a fragment has been sent. It increases outstanding fragments counter.
*/
public void oneFragmentSent() {
if (fragmentOutstanding <= fragmentTotal) {
this.fragmentOutstanding++;
}
}

/**
* Gets the RSSI from the packet. If this is unknown the method will return null
*
* @return the RSSI of the packet
*/
public Integer getReceivedRssi() {
return rssi;
}

/**
* Sets the RSSI from the packet. If this is unknown the method will return null
*
* @param the RSSI of the packet
*/
public void setReceivedRssi(int rssi) {
this.rssi = rssi;
}

/**
* Gets the LQI from the packet. If this is unknown the method will return null
*
* @return the LQI of the packet
*/
public Integer getReceivedLqi() {
return lqi;
}

/**
* Sets the LQI from the packet. If this is unknown the method will return null
*
* @param the LQI of the packet
*/
public void setReceivedLqi(int lqi) {
this.lqi = lqi;
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder(164);
Expand All @@ -413,6 +472,20 @@ public String toString() {
} else {
builder.append(String.format("%02X", apsCounter));
}

builder.append(", rssi=");
if (rssi == null) {
builder.append("--");
} else {
builder.append(rssi);
}
builder.append(", lqi=");
if (lqi == null) {
builder.append("--");
} else {
builder.append(String.format("%02X", lqi));
}

builder.append(", payload=");
if (payload != null) {
for (int c = 0; c < payload.length; c++) {
Expand All @@ -425,24 +498,4 @@ public String toString() {
builder.append(']');
return builder.toString();
}

/**
* Calling this method indicates that transmission of a fragment has completed.
* It moves the fragment base and decrease outstanding fragments counter.
*/
public void oneFragmentCompleted() {
fragmentBase++;
if (fragmentOutstanding > 0) {
fragmentOutstanding--;
}
}

/**
* Calling this method indicates that a fragment has been sent. It increases outstanding fragments counter.
*/
public void oneFragmentSent() {
if (fragmentOutstanding <= fragmentTotal) {
this.fragmentOutstanding++;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Copyright (c) 2016-2020 by the respective copyright holders.
* 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 com.zsmartsystems.zigbee.internal;

import com.zsmartsystems.zigbee.ZigBeeLinkQualityStatistics;

/**
* Handler to record and manage link quality information for a node
*
* @author Chris Jackson
*
*/
public class ZigBeeNodeLinkQualityHandler implements ZigBeeLinkQualityStatistics {
Integer lastRssi;
Integer lastLqi;

/**
* Updates the Link Quality Indicator value with the value from the latest received packet
*
* @param lqi the last received LQI value
*/
public void updateReceivedLqi(Integer lqi) {
if (lqi == null) {
return;
}
lastLqi = lqi;
}

/**
* Updates the Received Signal Strength Indicator value with the value from the latest received packet
*
* @param rssi the last received RSSI value in dBm
*/
public void updateReceivedRssi(Integer rssi) {
if (rssi == null) {
return;
}
lastRssi = rssi;
}

@Override
public Integer getLastReceivedLqi() {
return lastLqi;
}

@Override
public Integer getLastReceivedRssi() {
return lastRssi;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,8 @@ private ZigBeeCommand getZigBeeCommand(ZigBeeApsFrame apsFrame) throws Exception
TestUtilities.setField(ZigBeeNetworkManager.class, networkManager, "networkState", ZigBeeNetworkState.ONLINE);
networkManager.receiveCommand(apsFrame);
Mockito.verify(node, Mockito.timeout(TIMEOUT).times(1))
.commandReceived(ArgumentMatchers.any(ZigBeeCommand.class));
.commandReceived(ArgumentMatchers.any(ZigBeeCommand.class), ArgumentMatchers.any(),
ArgumentMatchers.any());
Awaitility.await().until(() -> commandListenerUpdated());
if (commandListenerCapture.size() == 0) {
return null;
Expand Down
Loading

0 comments on commit ba8598c

Please sign in to comment.