[zb4osgi-changeset] [scm] ZigBee 4 OSGi repository change: r461 - /projects/zb4osgi/sandbox/manlio.bacco/org.aaloa.osgi.zigbee.basedriver/src/main/java/it/cnr/isti/zigbee/basedriver/discovery/DeviceBuilderThread.java
scm-notify at zb4osgi.aaloa.org
scm-notify at zb4osgi.aaloa.org
Mon Sep 24 17:24:29 CEST 2012
Author: manlio.bacco
Date: Mon Sep 24 17:24:29 2012
New Revision: 461
Log:
management of devices not correctly instantiated
Modified:
projects/zb4osgi/sandbox/manlio.bacco/org.aaloa.osgi.zigbee.basedriver/src/main/java/it/cnr/isti/zigbee/basedriver/discovery/DeviceBuilderThread.java
Modified: projects/zb4osgi/sandbox/manlio.bacco/org.aaloa.osgi.zigbee.basedriver/src/main/java/it/cnr/isti/zigbee/basedriver/discovery/DeviceBuilderThread.java
==============================================================================
--- projects/zb4osgi/sandbox/manlio.bacco/org.aaloa.osgi.zigbee.basedriver/src/main/java/it/cnr/isti/zigbee/basedriver/discovery/DeviceBuilderThread.java (original)
+++ projects/zb4osgi/sandbox/manlio.bacco/org.aaloa.osgi.zigbee.basedriver/src/main/java/it/cnr/isti/zigbee/basedriver/discovery/DeviceBuilderThread.java Mon Sep 24 17:24:29 2012
@@ -18,7 +18,7 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-*/
+ */
package it.cnr.isti.zigbee.basedriver.discovery;
@@ -36,6 +36,11 @@
import it.cnr.isti.zigbee.util.IEEEAddress;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
@@ -63,267 +68,320 @@
public class DeviceBuilderThread implements Stoppable{
private static final Logger logger = LoggerFactory.getLogger(DeviceBuilderThread.class);
-
+
private final ImportingQueue queue;
- private final ArrayList<ZigBeeDeviceReference> failedDevice = new ArrayList<ZigBeeDeviceReference>();
-
+ private final List<ZigBeeDeviceReference> failedDevice = new ArrayList<ZigBeeDeviceReference>();
+
+ private Map<ZigBeeDeviceReference, Integer> failedAttempts = new HashMap<ZigBeeDeviceReference, Integer>();
+ private final int maxRetriesFailedDevices = 5;
+
+ private Map<ZigBeeDeviceReference, Long> delayedReattempts = new HashMap<ZigBeeDeviceReference, Long>();
+ private final long delay = 30000;
+
private final SimpleDriver driver;
private boolean end;
- private long nextInspectionSlot = 0;
-
+ private long nextInspectionSlot = 0;
+ private ZigBeeNodeAddress dev;
+
private class ZigBeeDeviceReference{
ZigBeeNode node;
byte endPoint;
-
+
ZigBeeDeviceReference(ZigBeeNode node, byte endPoint) {
super();
this.node = node;
this.endPoint = endPoint;
}
}
-
+
public DeviceBuilderThread(ImportingQueue queue, SimpleDriver driver) {
this.queue = queue;
this.driver = driver;
}
-
private ZDO_ACTIVE_EP_RSP doInspectDeviceOfNode(final int nwkAddress, final ZigBeeNode node){
//TODO Move into SimpleDriver?!?!?
logger.info("Inspecting device on node #{} by issuing ZDO_ACTIVE_EP_REQ", nwkAddress);
-
+
int i = 0;
ZDO_ACTIVE_EP_RSP result = null;
-
+
while (i < Activator.getCurrentConfiguration().getMessageRetryCount()) {
- result = driver.sendZDOActiveEndPointRequest(
- new ZDO_ACTIVE_EP_REQ(nwkAddress)
- );
+ result = driver.sendZDOActiveEndPointRequest(new ZDO_ACTIVE_EP_REQ(nwkAddress));
+
if( result == null ){
+
final long waiting = Activator.getCurrentConfiguration().getMessageRetryDelay();
logger.debug(
"Inspecting device on node {} failed during it {}-nth attempt. " +
- "Waiting for {}ms before retrying",
- new Object[]{node, i, waiting}
- );
+ "Waiting for {}ms before retrying",
+ new Object[]{node, i, waiting}
+ );
ThreadUtils.waitNonPreemptive(waiting);
i++;
- } else {
+ }
+ else
break;
- }
- }
-
+ }
+
return result;
}
-
- private void inspectDeviceOfNode(final int nwkAddress, final ZigBeeNode node) {
-
+
+ private boolean inspectDeviceOfNode(final int nwkAddress, final ZigBeeNode node) {
+
final ZDO_ACTIVE_EP_RSP result = doInspectDeviceOfNode(nwkAddress, node);
if( result == null ){
logger.warn("ZDO_ACTIVE_EP_REQ FAILED on {}", node);
- return;
- }
-
+ return false;
+ }
+
byte[] endPoints = result.getActiveEndPointList();
logger.info("ZDO_ACTIVE_EP_REQ SUCCESS with {} from {}", endPoints.length, node);
for (int i = 0; i < endPoints.length; i++) {
doCreateZigBeeDeviceService(node, endPoints[i]);
}
+
+ return true;
}
private void doCreateZigBeeDeviceService(ZigBeeNode node, byte ep) {
- final ZigBeeNetwork network = AFLayer.getAFLayer(driver).getZigBeeNetwork();
- synchronized (network) {
- if( network.containsDevice(node.getIEEEAddress(), ep) ){
- logger.info(
- "Skipping service creation for endpoint {} on node {} it is already registered as a Service", ep, node
- );
- return ;
- }else{
- logger.info(
- "Creating {} service for endpoint {} on node {}",
- new Object[]{ ZigBeeDevice.class, ep, node }
- );
- }
-
- }
+
+ final ZigBeeNetwork network = AFLayer.getAFLayer(driver).getZigBeeNetwork();
+ synchronized (network) {
+ if( network.containsDevice(node.getIEEEAddress(), ep) ){
+ logger.info(
+ "Skipping service creation for endpoint {} on node {} it is already registered as a Service", ep, node
+ );
+ return ;
+ }
+ else{
+ logger.info(
+ "Creating {} service for endpoint {} on node {}",
+ new Object[]{ ZigBeeDevice.class, ep, node }
+ );
+ }
+ }
try {
ZigBeeDeviceImpl device = new ZigBeeDeviceImpl(driver, node, ep);
if ( network.addDevice(device) ) {
- ServiceRegistration registration = Activator.getBundleContext().registerService(
- ZigBeeDevice.class.getName(),
- device,
- device.getDescription()
- );
- ArrayList<ServiceRegistration> list;
- synchronized ( Activator.devices ) {
- final String ieee = node.getIEEEAddress();
- list = Activator.devices.get( ieee );
- if ( list == null ) {
- list = new ArrayList<ServiceRegistration>();
- Activator.devices.put( ieee, list );
- }
- }
- synchronized ( list ) {
- list.add( registration );
- }
- } else {
- logger.error( "Failed to add endpoint {} to the network map for node {}", ep, node );
- }
- } catch (ZigBeeBasedriverException e) {
- logger.error("Error building the device:",e);
- failedDevice.add(new ZigBeeDeviceReference(node, ep));
+ ServiceRegistration registration = Activator.getBundleContext().registerService(
+ ZigBeeDevice.class.getName(),
+ device,
+ device.getDescription()
+ );
+ queue.deviceCorrectlyDiscovered(dev.getNetworkAddress(), dev.getIEEEAddress());
+ ArrayList<ServiceRegistration> list;
+ synchronized ( Activator.devices ) {
+ final String ieee = node.getIEEEAddress();
+ list = Activator.devices.get( ieee );
+ if ( list == null ) {
+ list = new ArrayList<ServiceRegistration>();
+ Activator.devices.put( ieee, list );
+ }
+ }
+ synchronized ( list ) {
+ list.add( registration );
+ }
+ }
+ else
+ logger.error( "Failed to add endpoint {} to the network map for node {}", ep, node );
+ }
+ catch (ZigBeeBasedriverException e) {
+ logger.error("Error building the device: {}", node, e);
+
+ ZigBeeDeviceReference last = new ZigBeeDeviceReference(node, ep);
+ if(!failedAttempts.containsKey(last))
+ failedAttempts.put(last, 0);
+ else if(failedAttempts.get(last)+1 < maxRetriesFailedDevices)
+ failedAttempts.put(last, failedAttempts.get(last)+1);
+ else{
+ logger.debug("Too many attempts failed, device {}:{} adding delayed of {} ms", new Object[]{node, ep, delay});
+ failedDevice.remove(last);
+ delayedReattempts.put(last, delay);
+ }
}
}
private void inspectNode(ZToolAddress16 nwkAddress, ZToolAddress64 ieeeAddress) {
+
int nwk = nwkAddress.get16BitValue();
final String ieee = IEEEAddress.toString(ieeeAddress.getLong());
ZigBeeNodeImpl node = null;
- boolean isNew = false;
+ boolean isNew = false, correctlyInspected = false;
final ZigBeeNetwork network = AFLayer.getAFLayer(driver).getZigBeeNetwork();
synchronized (network) {
node = network.containsNode(ieee);
if( node == null ){
node = new ZigBeeNodeImpl(nwk, ieeeAddress);
isNew = true;
- network.addNode(node);
- logger.debug( "Created node object for {} that was not available on the network", node );
+ network.addNode(node);
+ logger.debug( "Created node object for {} that was not available on the network", node );
}
- }
- if( isNew ){
- inspectDeviceOfNode(nwk, node);
- } else if( node.getNetworkAddress() != nwk ) {
- logger.warn(
- "The device {} has been found again with a new network address {} ",
- node, nwkAddress.get16BitValue()
- );
- if ( ! changedNetworkAddress( node, nwk ) ) {
- /*
- * No previous device inspection completed successfully, so we should try to inspect
- * the device agagin
- */
- inspectDeviceOfNode( nwk, new ZigBeeNodeImpl( nwk, node.getIEEEAddress() ) );
- }
- node.setNetworkAddress( nwk );
- }
+
+ if( isNew ){
+ logger.info("Creating a new set of services for ZigBee Node {} ({})", nwk, ieee);
+ correctlyInspected = inspectDeviceOfNode(nwk, node);
+
+ if(correctlyInspected)
+ return;
+ else{
+ // if you don't remove node with devices not yet inspected from network, you won't be able to re-inspect them later
+ // maybe device is sleeping and you have to wait for a non-sleeping period
+ logger.debug("Node {} removed from network because attempts to instantiate devices on it are failed", node);
+ network.removeNode(node);
+ }
+ }
+ else if( node.getNetworkAddress() != nwk ) {
+ logger.warn(
+ "The device {} has been found again with a new network address {} ",
+ node, nwkAddress.get16BitValue()
+ );
+ if ( ! changedNetworkAddress( node, nwk ) ) {
+ /*
+ * No previous device inspection completed successfully, so we should try to inspect
+ * the device agagin
+ */
+ inspectDeviceOfNode( nwk, new ZigBeeNodeImpl( nwk, node.getIEEEAddress() ) );
+ }
+ node.setNetworkAddress( nwk );
+
+ return;
+ }
+ }
}
/**
* This method updates the network address on all the device belonging the node<br>
* with the change network address<br>
*
- * @param node {@link ZigBeeNodeImpl} the old node with the obsoleted network address
- * @param nwk the new network address of the node
- * @return if at least a device has been updated
- * @since 0.6.0 - Revision 74
- */
- private boolean changedNetworkAddress( ZigBeeNodeImpl node, int nwk ) {
- /*
- * This may happen either for two reason:
- * A - Device has re-joined the network, it may happen either in end-user or
- * ZigBee developer environment
- * B - Device has been re-programmed and it joins as new device on the network,
- * it could happen only on ZigBee developer environment
- * The actual code handle only the case A
- */
- final ArrayList<ServiceRegistration> registrations;
- synchronized ( Activator.devices ) {
- registrations = Activator.devices.get( node.getIEEEAddress() );
- }
- if ( registrations == null ) {
- logger.info( "No registered service to updated even if we identified a network address changing" );
- return false;
- }
- boolean changed = false;
- /*
- * //TODO For covering case B: we should compare the content of "registrations"
- * with the actual list of End Point on the node
- */
- for ( ServiceRegistration registration : registrations ) {
- final ZigBeeDeviceImpl device =
- (ZigBeeDeviceImpl) Activator.getBundleContext().getService( registration.getReference() );
- if ( device.setPhysicalNode( new ZigBeeNodeImpl( nwk, node.getIEEEAddress() ) ) ) {
- changed = true;
- registration.setProperties( device.getDescription() );
- }
- }
-
- return changed;
- }
-
-
- private void inspectNewlyDevice(){
- logger.info("Trying to register a node extracted from ImportingQueue");
- final ZigBeeNodeAddress dev = queue.pop();
- final ZToolAddress16 nwk = dev.getNetworkAddress();
- final ZToolAddress64 ieee = dev.getIEEEAddress();
- logger.info("Creating a new set of services for ZigBee Node {} ({})",nwk,ieee);
- nextInspectionSlot = Activator.getCurrentConfiguration().getDeviceInspectionPeriod() + System.currentTimeMillis();
- inspectNode(nwk, ieee);
- }
-
+ * @param node {@link ZigBeeNodeImpl} the old node with the obsoleted network address
+ * @param nwk the new network address of the node
+ * @return if at least a device has been updated
+ * @since 0.6.0 - Revision 74
+ */
+ private boolean changedNetworkAddress( ZigBeeNodeImpl node, int nwk ) {
+ /*
+ * This may happen either for two reason:
+ * A - Device has re-joined the network, it may happen either in end-user or
+ * ZigBee developer environment
+ * B - Device has been re-programmed and it joins as new device on the network,
+ * it could happen only on ZigBee developing environment
+ * The actual code handle only the case A
+ */
+ final ArrayList<ServiceRegistration> registrations;
+ synchronized ( Activator.devices ) {
+ registrations = Activator.devices.get( node.getIEEEAddress() );
+ }
+ if ( registrations == null ) {
+ logger.info( "No registered service to updated even if we identified a network address changing" );
+ return false;
+ }
+ boolean changed = false;
+ /*
+ * //TODO For covering case B: we should compare the content of "registrations"
+ * with the actual list of End Point on the node
+ */
+ for ( ServiceRegistration registration : registrations ) {
+ final ZigBeeDeviceImpl device =
+ (ZigBeeDeviceImpl) Activator.getBundleContext().getService( registration.getReference() );
+ if ( device.setPhysicalNode( new ZigBeeNodeImpl( nwk, node.getIEEEAddress() ) ) ) {
+ changed = true;
+ registration.setProperties( device.getDescription() );
+ }
+ }
+ return changed;
+ }
+
+ private void inspectNewlyDevice(){
+
+ logger.info("Trying to register a node extracted from ImportingQueue");
+ nextInspectionSlot = Activator.getCurrentConfiguration().getDeviceInspectionPeriod() + System.currentTimeMillis();
+
+ if(queue != null && !queue.isEmpty()){
+ dev = queue.pop();
+ final ZToolAddress16 nwk = dev.getNetworkAddress();
+ final ZToolAddress64 ieee = dev.getIEEEAddress();
+
+ inspectNode(nwk, ieee);
+ }
+ else{
+ nextInspectionSlot = System.currentTimeMillis() + Activator.getCurrentConfiguration().getNetworkBrowsingPeriod()*2;
+ logger.debug("Devices inspection completed, waiting until {}", nextInspectionSlot);
+ }
+ }
+
private void inspectFailedDevice(){
- //TODO We should add a statistical history for removing a device when we tried it too many times
- logger.info("Trying to register a node extracted from FailedQueue");
- final ZigBeeDeviceReference failed = failedDevice.remove(0);
- nextInspectionSlot = Activator.getCurrentConfiguration().getDeviceInspectionPeriod() + System.currentTimeMillis();
- doCreateZigBeeDeviceService(failed.node, failed.endPoint);
- }
-
+ //TODO We should add a statistical history for removing a device when we tried it too many times
+ logger.info("Trying to register a node extracted from FailedQueue");
+ final ZigBeeDeviceReference failed = failedDevice.get(0);
+ nextInspectionSlot = Activator.getCurrentConfiguration().getDeviceInspectionPeriod() + System.currentTimeMillis();
+ doCreateZigBeeDeviceService(failed.node, failed.endPoint);
+ }
+
/**
* @return the number of Node waiting for inspection
* @since 0.6.0 - Revision 71
*/
public int getPendingNodes() {
- return queue.size();
- }
-
- /**
- * @return the number of Node waiting for inspection
- * @since 0.6.0 - Revision 71
- */
- public int getPendingDevices() {
- return failedDevice.size();
- }
-
+ return queue.size();
+ }
+
+ /**
+ * @return the number of Node waiting for inspection
+ * @since 0.6.0 - Revision 71
+ */
+ public int getPendingDevices() {
+ return failedDevice.size();
+ }
+
public void run() {
+
logger.info("{} STARTED Successfully", Thread.currentThread().getName() );
-
+
while(!isEnd()){
try{
- ThreadUtils.waitingUntil( nextInspectionSlot );
-
- if ( queue.size() > 0 && failedDevice.size() > 0 ){
- double sel = Math.random();
- if( sel > 0.6 ) {
- inspectFailedDevice();
- } else {
- inspectNewlyDevice();
- }
- } else if ( queue.size() == 0 && failedDevice.size() > 0 ){
- inspectFailedDevice();
- } else if ( queue.size() > 0 && failedDevice.size() == 0 ){
- inspectNewlyDevice();
- } else if ( queue.size() == 0 && failedDevice.size() == 0 ){
- inspectNewlyDevice();
- }
-
+ if(!delayedReattempts.isEmpty()){
+ Iterator<Entry<ZigBeeDeviceReference, Long>> iterator = delayedReattempts.entrySet().iterator();
+ while(iterator.hasNext()){
+ Entry<ZigBeeDeviceReference, Long> device = iterator.next();
+ if((device.getValue() + delay) >= System.currentTimeMillis()){
+ failedDevice.add(device.getKey());
+ logger.debug("EP {} of node {} has been readded to queue for inspection after {} ms",
+ new Object[]{device.getKey().endPoint, device.getKey().node, System.currentTimeMillis() - device.getValue()});
+ }
+ }
+ }
+ ThreadUtils.waitingUntil( nextInspectionSlot );
+
+ if ( queue.size() > 0 && failedDevice.size() > 0 ){
+ double sel = Math.random();
+ if( sel > 0.6 ) {
+ inspectFailedDevice();
+ } else {
+ inspectNewlyDevice();
+ }
+ } else if ( queue.size() == 0 && failedDevice.size() > 0 ){
+ inspectFailedDevice();
+ } else if ( queue.size() > 0 && failedDevice.size() == 0 ){
+ inspectNewlyDevice();
+ } else if ( queue.size() == 0 && failedDevice.size() == 0 ){
+ inspectNewlyDevice();
+ }
+
}catch(Exception e){
e.printStackTrace();
}
}
-
+
logger.info("{} TERMINATED Successfully", Thread.currentThread().getName());
}
public synchronized boolean isEnd() {
return end;
}
-
+
public synchronized void end() {
end = true;
- }
-
-}
+ }
+}
More information about the Commit
mailing list