Skip to content

Commit 8561dea

Browse files
committed
Update to set IEEE address in Ember NCP
Signed-off-by: Chris Jackson <[email protected]>
1 parent f6bd4bd commit 8561dea

File tree

17 files changed

+625
-217
lines changed

17 files changed

+625
-217
lines changed

com.zsmartsystems.zigbee.console.main/src/main/java/com/zsmartsystems/zigbee/console/main/ZigBeeDataStore.java

+32-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import java.io.FileOutputStream;
1515
import java.io.InputStreamReader;
1616
import java.io.OutputStreamWriter;
17-
import java.util.Collections;
1817
import java.util.HashSet;
1918
import java.util.Set;
2019
import java.util.UUID;
@@ -65,9 +64,9 @@ public ZigBeeDataStore(String networkId) {
6564
if (!file.exists() && !file.mkdirs()) {
6665
logger.error("Error creating network database folder {}", file);
6766
}
68-
file = new File(this.networkId + "/" + BACKUP);
67+
file = new File(DATABASE + BACKUP);
6968
if (!file.exists() && !file.mkdirs()) {
70-
logger.error("Error creating network database folder {}", file);
69+
logger.error("Error creating network backup folder {}", file);
7170
}
7271
}
7372

@@ -151,7 +150,6 @@ public ZigBeeNodeDao readNode(IeeeAddress address) {
151150
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), CHARSET))) {
152151
node = (ZigBeeNodeDao) stream.fromXML(reader);
153152
reader.close();
154-
logger.info("{}: ZigBee reading network state complete.", address);
155153
} catch (Exception e) {
156154
logger.error("{}: Error reading network state: ", address, e);
157155
}
@@ -167,7 +165,6 @@ public void writeNode(ZigBeeNodeDao node) {
167165
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), CHARSET))) {
168166
stream.marshal(node, new PrettyPrintWriter(writer));
169167
writer.close();
170-
logger.info("{}: ZigBee saving network state complete.", node.getIeeeAddress());
171168
} catch (Exception e) {
172169
logger.error("{}: Error writing network state: ", node.getIeeeAddress(), e);
173170
}
@@ -189,7 +186,6 @@ public void writeObject(String key, Object object) {
189186
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), CHARSET))) {
190187
stream.marshal(object, new PrettyPrintWriter(writer));
191188
writer.close();
192-
logger.info("{}: ZigBee saving key complete.", key);
193189
} catch (Exception e) {
194190
logger.error("{}: Error writing key: ", key, e);
195191
}
@@ -208,12 +204,12 @@ public boolean writeBackup(ZigBeeNetworkBackupDao backup) {
208204
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), CHARSET))) {
209205
stream.marshal(backup, new PrettyPrintWriter(writer));
210206
writer.close();
211-
logger.info("ZigBee saving network backup {} complete.", backup.getUuid());
212207
} catch (Exception e) {
213208
logger.error("Error writing network backup: ", backup.getUuid(), e);
209+
return false;
214210
}
215211

216-
return false;
212+
return true;
217213
}
218214

219215
@Override
@@ -225,7 +221,6 @@ public ZigBeeNetworkBackupDao readBackup(UUID uuid) {
225221
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), CHARSET))) {
226222
backup = (ZigBeeNetworkBackupDao) stream.fromXML(reader);
227223
reader.close();
228-
logger.info("ZigBee reading network backup {} complete.", uuid);
229224
} catch (Exception e) {
230225
logger.error("{}: Error reading network backup: ", uuid, e);
231226
}
@@ -235,6 +230,33 @@ public ZigBeeNetworkBackupDao readBackup(UUID uuid) {
235230

236231
@Override
237232
public Set<ZigBeeNetworkBackupDao> listBackups() {
238-
return Collections.emptySet();
233+
Set<ZigBeeNetworkBackupDao> backups = new HashSet<>();
234+
File dir = new File(DATABASE + BACKUP);
235+
File[] files = dir.listFiles();
236+
237+
if (files == null) {
238+
return backups;
239+
}
240+
241+
for (File file : files) {
242+
if (!file.getName().toLowerCase().endsWith(".xml")) {
243+
continue;
244+
}
245+
246+
try {
247+
String filename = file.getName();
248+
UUID uuid = UUID.fromString(filename.substring(0, filename.length() - 4));
249+
ZigBeeNetworkBackupDao backup = readBackup(uuid);
250+
for (ZigBeeNodeDao node : backup.getNodes()) {
251+
node.setEndpoints(null);
252+
node.setBindingTable(null);
253+
}
254+
backups.add(backup);
255+
} catch (IllegalArgumentException e) {
256+
logger.error("Error parsing database filename: {}", file.getName());
257+
}
258+
}
259+
260+
return backups;
239261
}
240262
}

com.zsmartsystems.zigbee.console/src/main/java/com/zsmartsystems/zigbee/console/ZigBeeConsoleNetworkBackupCommand.java

+44-8
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@
88
package com.zsmartsystems.zigbee.console;
99

1010
import java.io.PrintStream;
11+
import java.util.Map;
12+
import java.util.TreeMap;
13+
import java.util.UUID;
1114

1215
import com.zsmartsystems.zigbee.ZigBeeNetworkManager;
16+
import com.zsmartsystems.zigbee.ZigBeeStatus;
17+
import com.zsmartsystems.zigbee.database.ZigBeeNetworkBackupDao;
18+
import com.zsmartsystems.zigbee.database.ZigBeeNodeDao;
1319

1420
/**
1521
* Console command to backup the network.
@@ -47,28 +53,58 @@ public void process(ZigBeeNetworkManager networkManager, String[] args, PrintStr
4753

4854
switch (args[1].toUpperCase()) {
4955
case "LIST":
50-
listBackups();
56+
listBackups(out, networkManager);
5157
break;
5258
case "BACKUP":
53-
createBackup();
59+
createBackup(out, networkManager);
5460
break;
5561
case "RESTORE":
56-
restoreBackup();
62+
restoreBackup(out, networkManager, UUID.fromString(args[2]));
5763
break;
5864
default:
5965
throw new IllegalArgumentException("Unknown option '" + args[1] + "'");
6066
}
6167
}
6268

63-
private void listBackups() {
69+
private void listBackups(PrintStream out, ZigBeeNetworkManager networkManager) {
70+
Map<Long, ZigBeeNetworkBackupDao> sortedBackups = new TreeMap<>();
71+
for (ZigBeeNetworkBackupDao backup : networkManager.listBackups()) {
72+
sortedBackups.put(backup.getDate().getTime(), backup);
73+
}
6474

75+
out.println(
76+
"DATE UUID PANID EPANID CHANNEL COORDINATOR NODES");
77+
for (ZigBeeNetworkBackupDao backup : sortedBackups.values()) {
78+
ZigBeeNodeDao coordinator = null;
79+
for (ZigBeeNodeDao node : backup.getNodes()) {
80+
if (node.getNetworkAddress() == 0) {
81+
coordinator = node;
82+
break;
83+
}
84+
}
85+
out.println(
86+
String.format("%s %s %04X %s %s %s %d", backup.getDate().toInstant().toString(),
87+
backup.getUuid(),
88+
backup.getPan(), backup.getEpan(), backup.getChannel(),
89+
(coordinator != null ? coordinator.getIeeeAddress() : " "),
90+
backup.getNodes().size()));
91+
}
6592
}
6693

67-
private void createBackup() {
68-
94+
private void createBackup(PrintStream out, ZigBeeNetworkManager networkManager) {
95+
UUID uuid = networkManager.createBackup();
96+
if (uuid == null) {
97+
out.println("Error creating backup!!");
98+
} else {
99+
out.println("Backup created with UUID " + uuid);
100+
}
69101
}
70102

71-
private void restoreBackup() {
72-
103+
private void restoreBackup(PrintStream out, ZigBeeNetworkManager networkManager, UUID uuid) {
104+
if (networkManager.restoreBackup(uuid) == ZigBeeStatus.SUCCESS) {
105+
out.println("Backup restored from " + uuid.toString());
106+
} else {
107+
out.println("Error restoring backup " + uuid.toString());
108+
}
73109
}
74110
}

com.zsmartsystems.zigbee.dongle.ember.autocode/src/main/resources/ezsp_protocol.xml

+24-20
Original file line numberDiff line numberDiff line change
@@ -1964,26 +1964,6 @@
19641964
</response_parameters>
19651965
</command>
19661966

1967-
<command>
1968-
<name>becomeTrustCenter</name>
1969-
<id>0x77</id>
1970-
<description>This function causes a coordinator to become the Trust Center when it is operating in a network that is not using one. It will send out an updated Network Key to all devices that will indicate a transition of the network to now use a Trust Center. The Trust Center should also switch all devices to using this new network key with the appropriate API.</description>
1971-
<command_parameters>
1972-
<parameter>
1973-
<data_type>EmberKeyData</data_type>
1974-
<name>newNetworkKey</name>
1975-
<description>The key data for the Updated Network Key.</description>
1976-
</parameter>
1977-
</command_parameters>
1978-
<response_parameters>
1979-
<parameter>
1980-
<data_type>EmberStatus</data_type>
1981-
<name>status</name>
1982-
<description>The response status.</description>
1983-
</parameter>
1984-
</response_parameters>
1985-
</command>
1986-
19871967
<command>
19881968
<name>aesMmoHash</name>
19891969
<id>0x6F</id>
@@ -3916,6 +3896,30 @@
39163896
<description>A command which does nothing. The Host can use this to set the sleep mode or check the status of the NCP.</description>
39173897
</command>
39183898

3899+
<command>
3900+
<name>tokenFactoryReset</name>
3901+
<id>0x0077</id>
3902+
<description>Factory reset all configured Zigbee tokens.</description>
3903+
<command_parameters>
3904+
<parameter>
3905+
<data_type>bool</data_type>
3906+
<name>excludeOutgoingFC</name>
3907+
<description>Exclude network and APS outgoing frame counter tokens.</description>
3908+
</parameter>
3909+
<parameter>
3910+
<data_type>bool</data_type>
3911+
<name>excludeBootCounter</name>
3912+
<description>Exclude stack boot counter token.</description>
3913+
</parameter>
3914+
</command_parameters>
3915+
</command>
3916+
3917+
<command>
3918+
<name>resetNode</name>
3919+
<id>0x0104</id>
3920+
<description>Reset the node by calling halReboot.</description>
3921+
</command>
3922+
39193923
<structure>
39203924
<name>EmberCertificateData</name>
39213925
<description>The implicit certificate used in CBKE.</description>

com.zsmartsystems.zigbee.dongle.ember/src/main/java/com/zsmartsystems/zigbee/dongle/ember/EmberNcp.java

+34
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@
132132
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspSetValueResponse;
133133
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspStartScanRequest;
134134
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspStartScanResponse;
135+
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspTokenFactoryResetRequest;
136+
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspTokenFactoryResetResponse;
135137
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspVersionRequest;
136138
import com.zsmartsystems.zigbee.dongle.ember.ezsp.command.EzspVersionResponse;
137139
import com.zsmartsystems.zigbee.dongle.ember.ezsp.structure.EmberAesMmoHashContext;
@@ -1073,6 +1075,16 @@ public IeeeAddress getMfgCustomEui64() {
10731075
return new IeeeAddress(response);
10741076
}
10751077

1078+
/**
1079+
* Sets the custom EUI64 (long address) from the manufacturer information block on the NCP
1080+
*
1081+
* @param address {@link IeeeAddress} containing the custom address
1082+
* @return {@link EmberStatus}
1083+
*/
1084+
public EmberStatus setMfgCustomEui64(IeeeAddress address) {
1085+
return setMfgToken(EzspMfgTokenId.EZSP_MFG_CUSTOM_EUI_64, address.getValue());
1086+
}
1087+
10761088
/**
10771089
* Gets the install code stored in the NCP memory
10781090
*
@@ -1333,6 +1345,28 @@ public EzspStatus resetToFactoryDefaults() {
13331345
return response.getStatus();
13341346
}
13351347

1348+
/**
1349+
* Factory reset all configured Zigbee tokens.
1350+
*
1351+
* @param excludeOutgoingFC Exclude network and APS outgoing frame counter tokens.
1352+
* @param excludeBootCounter Exclude stack boot counter token.
1353+
* @return the response {@link EzspStatus}
1354+
*/
1355+
public EzspStatus tokenFactoryReset(boolean excludeOutgoingFC, boolean excludeBootCounter) {
1356+
EzspTokenFactoryResetRequest request = new EzspTokenFactoryResetRequest();
1357+
request.setExcludeOutgoingFC(excludeOutgoingFC);
1358+
request.setExcludeBootCounter(excludeBootCounter);
1359+
EzspTransaction transaction = protocolHandler
1360+
.sendEzspTransaction(
1361+
new EzspSingleResponseTransaction(request, EzspTokenFactoryResetResponse.class));
1362+
EzspTokenFactoryResetResponse response = (EzspTokenFactoryResetResponse) transaction
1363+
.getResponse();
1364+
if (response == null) {
1365+
return EzspStatus.UNKNOWN;
1366+
}
1367+
return EzspStatus.EZSP_SUCCESS;
1368+
}
1369+
13361370
private String intArrayToString(int[] payload) {
13371371
int length = payload.length;
13381372
for (int cnt = 0; cnt < length; cnt++) {

com.zsmartsystems.zigbee.dongle.ember/src/main/java/com/zsmartsystems/zigbee/dongle/ember/ZigBeeDongleEzsp.java

+33
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.zsmartsystems.zigbee.ZigBeeDeviceType;
3131
import com.zsmartsystems.zigbee.ZigBeeExecutors;
3232
import com.zsmartsystems.zigbee.ZigBeeNetworkManager;
33+
import com.zsmartsystems.zigbee.ZigBeeNetworkState;
3334
import com.zsmartsystems.zigbee.ZigBeeNodeStatus;
3435
import com.zsmartsystems.zigbee.ZigBeeNwkAddressMode;
3536
import com.zsmartsystems.zigbee.ZigBeeProfileType;
@@ -745,11 +746,43 @@ public IeeeAddress getIeeeAddress() {
745746
return ieeeAddress;
746747
}
747748

749+
@Override
750+
public boolean setIeeeAddress(IeeeAddress ieeeAddress) {
751+
EmberNcp ncp = getEmberNcp();
752+
if (ncp.getIeeeAddress().equals(ieeeAddress)) {
753+
// Don't write the IEEE address unless it's different since there are limitations on how many times this can
754+
// be changed in some firmware versions.
755+
return true;
756+
}
757+
return ncp.setMfgCustomEui64(ieeeAddress) == EmberStatus.EMBER_SUCCESS;
758+
}
759+
748760
@Override
749761
public Integer getNwkAddress() {
750762
return nwkAddress;
751763
}
752764

765+
@Override
766+
public ZigBeeStatus setNetworkState(ZigBeeNetworkState networkState) {
767+
EmberNcp ncp = getEmberNcp();
768+
switch (networkState) {
769+
case UNINITIALISED:
770+
// Reset the NCP to "factory default"
771+
// Note that tokenFactoryReset was introduced in firmware 7.3 (approx) and older versions used the same
772+
// ID for another function.
773+
// We don't check the result here for that reason.
774+
// Note that the impact of this function not working is that the IEEE address can only be written to the
775+
// token area once - subsequent writes will fail, and therefore changing IEEE address (eg from a
776+
// backup/restore) may fail.
777+
ncp.tokenFactoryReset(false, false);
778+
return ncp.leaveNetwork() == EmberStatus.EMBER_SUCCESS ? ZigBeeStatus.SUCCESS : ZigBeeStatus.FAILURE;
779+
case ONLINE:
780+
return ncp.networkInit() == EmberStatus.EMBER_SUCCESS ? ZigBeeStatus.SUCCESS : ZigBeeStatus.FAILURE;
781+
default:
782+
return ZigBeeStatus.INVALID_ARGUMENTS;
783+
}
784+
}
785+
753786
@Override
754787
public void sendCommand(final int msgTag, final ZigBeeApsFrame apsFrame) {
755788
if (!isConfigured) {

com.zsmartsystems.zigbee.dongle.ember/src/main/java/com/zsmartsystems/zigbee/dongle/ember/ezsp/EzspFrame.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ public abstract class EzspFrame {
9595
protected static final int FRAME_ID_ADD_TRANSIENT_LINK_KEY = 0xAF;
9696
protected static final int FRAME_ID_ADDRESS_TABLE_ENTRY_IS_ACTIVE = 0x5B;
9797
protected static final int FRAME_ID_AES_MMO_HASH = 0x6F;
98-
protected static final int FRAME_ID_BECOME_TRUST_CENTER = 0x77;
9998
protected static final int FRAME_ID_BINDING_IS_ACTIVE = 0x2E;
10099
protected static final int FRAME_ID_CALCULATE_SMACS = 0x9F;
101100
protected static final int FRAME_ID_CALCULATE_SMACS283K1 = 0xEA;
@@ -213,6 +212,7 @@ public abstract class EzspFrame {
213212
protected static final int FRAME_ID_REMOTE_SET_BINDING_HANDLER = 0x31;
214213
protected static final int FRAME_ID_REMOVE_DEVICE = 0xA8;
215214
protected static final int FRAME_ID_REQUEST_LINK_KEY = 0x14;
215+
protected static final int FRAME_ID_RESET_NODE = 0x104;
216216
protected static final int FRAME_ID_RESET_TO_FACTORY_DEFAULTS = 0xCC;
217217
protected static final int FRAME_ID_SCAN_COMPLETE_HANDLER = 0x1C;
218218
protected static final int FRAME_ID_SEND_BROADCAST = 0x36;
@@ -248,6 +248,7 @@ public abstract class EzspFrame {
248248
protected static final int FRAME_ID_START_SCAN = 0x1A;
249249
protected static final int FRAME_ID_STOP_SCAN = 0x1D;
250250
protected static final int FRAME_ID_SWITCH_NETWORK_KEY_HANDLER = 0x6E;
251+
protected static final int FRAME_ID_TOKEN_FACTORY_RESET = 0x77;
251252
protected static final int FRAME_ID_TRUST_CENTER_JOIN_HANDLER = 0x24;
252253
protected static final int FRAME_ID_VERSION = 0x00;
253254
protected static final int FRAME_ID_ZIGBEE_KEY_ESTABLISHMENT_HANDLER = 0x9B;
@@ -265,7 +266,6 @@ public abstract class EzspFrame {
265266
ezspHandlerMap.put(FRAME_ID_ADD_TRANSIENT_LINK_KEY, EzspAddTransientLinkKeyResponse.class);
266267
ezspHandlerMap.put(FRAME_ID_ADDRESS_TABLE_ENTRY_IS_ACTIVE, EzspAddressTableEntryIsActiveResponse.class);
267268
ezspHandlerMap.put(FRAME_ID_AES_MMO_HASH, EzspAesMmoHashResponse.class);
268-
ezspHandlerMap.put(FRAME_ID_BECOME_TRUST_CENTER, EzspBecomeTrustCenterResponse.class);
269269
ezspHandlerMap.put(FRAME_ID_BINDING_IS_ACTIVE, EzspBindingIsActiveResponse.class);
270270
ezspHandlerMap.put(FRAME_ID_CALCULATE_SMACS, EzspCalculateSmacsResponse.class);
271271
ezspHandlerMap.put(FRAME_ID_CALCULATE_SMACS283K1, EzspCalculateSmacs283k1Response.class);
@@ -383,6 +383,7 @@ public abstract class EzspFrame {
383383
ezspHandlerMap.put(FRAME_ID_REMOTE_SET_BINDING_HANDLER, EzspRemoteSetBindingHandler.class);
384384
ezspHandlerMap.put(FRAME_ID_REMOVE_DEVICE, EzspRemoveDeviceResponse.class);
385385
ezspHandlerMap.put(FRAME_ID_REQUEST_LINK_KEY, EzspRequestLinkKeyResponse.class);
386+
ezspHandlerMap.put(FRAME_ID_RESET_NODE, EzspResetNodeResponse.class);
386387
ezspHandlerMap.put(FRAME_ID_RESET_TO_FACTORY_DEFAULTS, EzspResetToFactoryDefaultsResponse.class);
387388
ezspHandlerMap.put(FRAME_ID_SCAN_COMPLETE_HANDLER, EzspScanCompleteHandler.class);
388389
ezspHandlerMap.put(FRAME_ID_SEND_BROADCAST, EzspSendBroadcastResponse.class);
@@ -418,6 +419,7 @@ public abstract class EzspFrame {
418419
ezspHandlerMap.put(FRAME_ID_START_SCAN, EzspStartScanResponse.class);
419420
ezspHandlerMap.put(FRAME_ID_STOP_SCAN, EzspStopScanResponse.class);
420421
ezspHandlerMap.put(FRAME_ID_SWITCH_NETWORK_KEY_HANDLER, EzspSwitchNetworkKeyHandler.class);
422+
ezspHandlerMap.put(FRAME_ID_TOKEN_FACTORY_RESET, EzspTokenFactoryResetResponse.class);
421423
ezspHandlerMap.put(FRAME_ID_TRUST_CENTER_JOIN_HANDLER, EzspTrustCenterJoinHandler.class);
422424
ezspHandlerMap.put(FRAME_ID_VERSION, EzspVersionResponse.class);
423425
ezspHandlerMap.put(FRAME_ID_ZIGBEE_KEY_ESTABLISHMENT_HANDLER, EzspZigbeeKeyEstablishmentHandler.class);

0 commit comments

Comments
 (0)