1010import java .util .ArrayList ;
1111import java .util .Arrays ;
1212import java .util .Collections ;
13+ import java .util .Date ;
1314import java .util .List ;
1415import java .util .Random ;
1516import java .util .concurrent .CountDownLatch ;
@@ -131,6 +132,11 @@ public class ZclOtaUpgradeServer implements ZigBeeApplication, ZclCommandListene
131132 */
132133 private ZigBeeOtaServerStatus status ;
133134
135+ /**
136+ * The time of the last image update request
137+ */
138+ private Date lastImageRequestTime = null ;
139+
134140 /**
135141 * The parameter is part of Image Notify Command sent by the upgrade server. The parameter indicates
136142 * whether the client receiving Image Notify Command should send in Query Next Image Request
@@ -220,7 +226,7 @@ public class ZclOtaUpgradeServer implements ZigBeeApplication, ZclCommandListene
220226 /**
221227 * The sleep time before trying to request the current firmware version
222228 */
223- private static final long CURRENT_FW_VERSION_REQUEST_DELAY = 10000 ;
229+ private static final long CURRENT_FW_VERSION_REQUEST_DELAY = 1500 ;
224230
225231 /**
226232 * Field control value of 0x01 (bit 0 set) means that the client’s IEEE address is included in the payload. This
@@ -279,6 +285,24 @@ public ZigBeeOtaServerStatus getServerStatus() {
279285 return status ;
280286 }
281287
288+ /**
289+ * Gets the time the last image update request was received
290+ *
291+ * @return the {@link Date} of the last received image request
292+ */
293+ public Date getLastImageRequestTime () {
294+ return lastImageRequestTime ;
295+ }
296+
297+ /**
298+ * Gets the percentage complete when an update is in progress. Returns null if not upgrade is in progress.
299+ *
300+ * @return the percentage complete, or null if not upgrade is in progress.
301+ */
302+ public Integer getPercentageComplete () {
303+ return status == ZigBeeOtaServerStatus .OTA_UNINITIALISED ? null : percentComplete ;
304+ }
305+
282306 /**
283307 * Cancels any upgrade transfers that are in progress and removes the current file. If a transfer is currently in
284308 * progress, then the listeners are notified.
@@ -455,7 +479,7 @@ public void run() {
455479 }
456480 ImageUpgradeStatus status = ImageUpgradeStatus .getStatus (statusValue );
457481 if (status != ImageUpgradeStatus .DOWNLOAD_COMPLETE
458- && status != ImageUpgradeStatus .WAITING_TO_UPGRADE ) {
482+ && status != ImageUpgradeStatus .WAITING_TO_UPGRADE && status != ImageUpgradeStatus . NORMAL ) {
459483 // Client is not in correct state to end upgrade
460484 switch (status ) {
461485 case COUNT_DOWN :
@@ -467,22 +491,22 @@ public void run() {
467491 case WAIT_FOR_MORE :
468492 updateStatus (ZigBeeOtaServerStatus .OTA_WAITING );
469493 break ;
470- case NORMAL :
471494 case UNKNOWN :
472495 default :
496+ logger .debug ("{}: Unexpected remote transfer status {} - OTA failed." ,
497+ status , cluster .getZigBeeAddress ());
473498 updateStatus (ZigBeeOtaServerStatus .OTA_UPGRADE_FAILED );
474499 break ;
475500 }
476501 return ;
477502 }
478503
479- updateStatus (ZigBeeOtaServerStatus .OTA_UPGRADE_FIRMWARE_RESTARTING );
480-
481504 UpgradeEndResponse upgradeEndResponse = new UpgradeEndResponse (otaFile .getManufacturerCode (),
482505 otaFile .getImageType (), otaFile .getFileVersion (), 0 , 0 );
506+ upgradeEndResponse .setDisableDefaultResponse (true );
483507
484508 // If we received a UpgradeEndCommand then send the UpgradeEndResponse as a response. Otherwise send
485- // it as a commands
509+ // it as a command
486510 CommandResult response ;
487511 if (command != null ) {
488512 response = cluster .sendResponse (command , upgradeEndResponse ).get ();
@@ -491,9 +515,11 @@ public void run() {
491515 }
492516
493517 if (!(response .isSuccess () || response .isTimeout ())) {
518+ logger .debug ("{}: Failed to send UpgradeEnd - OTA failed." , cluster .getZigBeeAddress ());
494519 updateStatus (ZigBeeOtaServerStatus .OTA_UPGRADE_FAILED );
495520 return ;
496521 }
522+ updateStatus (ZigBeeOtaServerStatus .OTA_UPGRADE_FIRMWARE_RESTARTING );
497523
498524 // Attempt to get the current firmware version. As the device will be restarting, which could take
499525 // some time to complete, we retry this a few times.
@@ -526,6 +552,9 @@ public void run() {
526552 if (fileVersion .equals (otaFile .getFileVersion ())) {
527553 updateStatus (ZigBeeOtaServerStatus .OTA_UPGRADE_COMPLETE );
528554 return ;
555+ } else {
556+ updateStatus (ZigBeeOtaServerStatus .OTA_UPGRADE_FAILED );
557+ return ;
529558 }
530559 } else if (attributesResponse .getRecords ().get (0 )
531560 .getStatus () == ZclStatus .UNSUPPORTED_ATTRIBUTE ) {
@@ -695,6 +724,8 @@ public void run() {
695724 * @return true if the handler has, or will send a response to this command
696725 */
697726 private boolean handleQueryNextImageCommand (QueryNextImageCommand command ) {
727+ lastImageRequestTime = new Date ();
728+
698729 if (otaFile == null ) {
699730 logger .debug ("{} OTA Server: No file set in QueryNextImageCommand." ,
700731 cluster .getZigBeeAddress ());
@@ -756,7 +787,7 @@ private boolean handleQueryNextImageCommand(QueryNextImageCommand command) {
756787 }
757788
758789 // Update the state as we're starting
759- updateStatus (ZigBeeOtaServerStatus .OTA_TRANSFER_IN_PROGRESS );
790+ updateStatus (ZigBeeOtaServerStatus .OTA_STARTED );
760791 startTransferTimer ();
761792
762793 cluster .sendResponse (command , new QueryNextImageResponse (
@@ -766,6 +797,8 @@ private boolean handleQueryNextImageCommand(QueryNextImageCommand command) {
766797 otaFile .getFileVersion (),
767798 otaFile .getImageSize ()));
768799
800+ updateStatus (ZigBeeOtaServerStatus .OTA_TRANSFER_IN_PROGRESS );
801+
769802 return true ;
770803 }
771804
@@ -894,7 +927,15 @@ private boolean handleUpgradeEndCommand(UpgradeEndCommand command) {
894927 && status != ZigBeeOtaServerStatus .OTA_TRANSFER_COMPLETE ) {
895928 logger .debug ("{} OTA Error: Invalid server state {} when handling UpgradeEndCommand." ,
896929 cluster .getZigBeeAddress (), status );
897- cluster .sendDefaultResponse (command , ZclStatus .UNKNOWN );
930+
931+ UpgradeEndResponse upgradeEndResponse = new UpgradeEndResponse (command .getManufacturerCode (),
932+ command .getImageType (), command .getFileVersion (), 0 , 0 );
933+ try {
934+ cluster .sendCommand (upgradeEndResponse ).get ();
935+ } catch (InterruptedException e ) {
936+ } catch (ExecutionException e ) {
937+ }
938+
898939 return true ;
899940 }
900941
@@ -987,6 +1028,8 @@ public boolean commandReceived(final ZclCommand command) {
9871028 private ZigBeeOtaFile notifyUpdateRequestReceived (final QueryNextImageCommand command ) {
9881029 CountDownLatch latch ;
9891030 List <ZigBeeOtaFile > otaFiles = new ArrayList <>();
1031+ logger .debug ("{}: ZigBeeOtaServer.notifyUpdateRequestReceived ({} listeners)" , cluster .getZigBeeAddress (),
1032+ statusListeners .size ());
9901033
9911034 synchronized (this ) {
9921035 // Notify the listeners
@@ -1043,7 +1086,7 @@ public void run() {
10431086
10441087 @ Override
10451088 public String toString () {
1046- return "ZigBeeOtaServer [status=" + status + ", cluster=" + cluster + ", otaFile=" + otaFile + "]" ;
1089+ return "ZigBeeOtaServer [status=" + status + ", listeners=" + statusListeners .size () + ", otaFile=" + otaFile
1090+ + "]" ;
10471091 }
1048-
10491092}
0 commit comments