Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ZigBeeUtcTime class and client/server #1371

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ Currently implemented extensions include -:
- IAS CIE client (`ZigBeeIasCieExtension`)
- OTA Upgrade Server (`ZigBeeOtaUpgradeExtension`)
- Basic Cluster Server (`ZigBeeBasicServerExtension`)
- Time management (`ZigBeeTimeExtension`)

These provide basic functionality and can be extended as required to meet the application needs.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public static class DataTypeMap {
dataTypeMapping.put("CHARACTER_STRING", new DataTypeMap("String", 0x42, -1, false));
dataTypeMapping.put("LONG_OCTET_STRING", new DataTypeMap("ByteArray", 0x43, -1, false));
dataTypeMapping.put("LONG_CHARACTER_STRING", new DataTypeMap("String", 0x44, -1, false));
dataTypeMapping.put("UTCTIME", new DataTypeMap("Calendar", 0xe2, 4, true, 0xffffffff));
dataTypeMapping.put("UTCTIME", new DataTypeMap("ZigBeeUtcTime", 0xe2, 4, true, 0xffffffff));
dataTypeMapping.put("ZDO_STATUS", new DataTypeMap("ZdoStatus", 0, 0, false));
dataTypeMapping.put("ZCL_STATUS", new DataTypeMap("ZclStatus", 0, 0, false));
dataTypeMapping.put("ZIGBEE_DATA_TYPE", new DataTypeMap("ZclDataType", 0, 0, false));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
<description>The DstEnd attribute indicates the DST end time in seconds. The value 0xffffffff indicates an invalid DST end time.</description>
<description>Note that the three attributes DstStart, DstEnd and DstShift are optional, but if any one of them is implemented the other two must also be implemented. Note that this attribute should be set to a new value once every year.</description>
<description>Note that this attribute should be set to a new value once every year, and should be written synchronously with the DstStart attribute. The DstEnd attribute indicates the DST end time in seconds. The value 0xffffffff indicates an invalid DST end time.</description>
<description>Note that this attribute should be set to a new value once every year, and should be written synchronously with the DstStart attribute</description>
</attribute>
<attribute code="0x0005" type="SIGNED_32_BIT_INTEGER" side="server" optional="true" writable="true" reportable="false">
<name>DST Shift</name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
import com.zsmartsystems.zigbee.console.ZigBeeConsoleSwitchLevelCommand;
import com.zsmartsystems.zigbee.console.ZigBeeConsoleSwitchOffCommand;
import com.zsmartsystems.zigbee.console.ZigBeeConsoleSwitchOnCommand;
import com.zsmartsystems.zigbee.console.ZigBeeConsoleTimeCommand;
import com.zsmartsystems.zigbee.console.ZigBeeConsoleTrustCentreCommand;
import com.zsmartsystems.zigbee.console.ZigBeeConsoleUnbindCommand;
import com.zsmartsystems.zigbee.console.ZigBeeConsoleWindowCoveringCommand;
Expand Down Expand Up @@ -206,6 +207,7 @@ public ZigBeeConsole(final ZigBeeNetworkManager networkManager, final ZigBeeTran

newCommands.put("otaupgrade", new ZigBeeConsoleOtaUpgradeCommand());
newCommands.put("channel", new ZigBeeConsoleChannelCommand());
newCommands.put("time", new ZigBeeConsoleTimeCommand());

newCommands.put("smartenergy", new ZigBeeConsoleSmartEnergyCommand());
newCommands.put("cbke", new ZigBeeConsoleCbkeCommand());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ public interface ZigBeeConsoleCommand {
* @param args the command arguments. arg[0] is the command
* @param out the output PrintStream
* @return true if the command executed successfully
* @throws IllegalArgumentException if any commands are incorrectly formatted, or the incorrect number of commands
* are provided
* @throws IllegalStateException if the network is not in a state that allows the command to be executed
* @throws InterruptedException if the command was interrupted
* @throws ExecutionException if the command failed
* @throws {@link IllegalArgumentException} if any commands are incorrectly formatted, or the incorrect number of
* commands are provided
* @throws {@link IllegalStateException} if the network is not in a state that allows the command to be executed
* @throws {@link InterruptedException} if the command was interrupted
* @throws {@link ExecutionException} if the command failed
*/
public void process(final ZigBeeNetworkManager networkManager, final String[] args, PrintStream out)
throws IllegalArgumentException, IllegalStateException, ExecutionException, InterruptedException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
package com.zsmartsystems.zigbee.console;

import java.io.PrintStream;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
Expand All @@ -20,9 +19,15 @@
import com.zsmartsystems.zigbee.security.ZigBeeCbkeProvider;
import com.zsmartsystems.zigbee.zcl.clusters.ZclMeteringCluster;
import com.zsmartsystems.zigbee.zcl.clusters.ZclPriceCluster;
import com.zsmartsystems.zigbee.zcl.clusters.metering.*;
import com.zsmartsystems.zigbee.zcl.clusters.metering.GetProfile;
import com.zsmartsystems.zigbee.zcl.clusters.metering.GetProfileResponse;
import com.zsmartsystems.zigbee.zcl.clusters.metering.GetProfileStatusEnum;
import com.zsmartsystems.zigbee.zcl.clusters.metering.IntervalPeriodEnum;
import com.zsmartsystems.zigbee.zcl.clusters.metering.RequestFastPollMode;
import com.zsmartsystems.zigbee.zcl.clusters.metering.RequestFastPollModeResponse;
import com.zsmartsystems.zigbee.zcl.clusters.price.GetCurrentPriceCommand;
import com.zsmartsystems.zigbee.zcl.clusters.price.PublishPriceCommand;
import com.zsmartsystems.zigbee.zcl.field.ZigBeeUtcTime;
import com.zsmartsystems.zigbee.zcl.protocol.ZclClusterType;

/**
Expand Down Expand Up @@ -126,7 +131,7 @@ private void getProfile(ZigBeeNetworkManager networkManager, String[] args, Prin

try {
for (int cnt = 0; cnt < repeatCycles; cnt++) {
CommandResult result = cluster.sendCommand(new GetProfile(0, Calendar.getInstance(), 1)).get();
CommandResult result = cluster.sendCommand(new GetProfile(0, ZigBeeUtcTime.now(), 1)).get();
GetProfileResponse response = (GetProfileResponse) result.getResponse();
if (response.getStatus() != 0) {
out.println(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/**
* Copyright (c) 2016-2023 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.console;

import java.io.PrintStream;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ExecutionException;

import com.zsmartsystems.zigbee.ZigBeeEndpoint;
import com.zsmartsystems.zigbee.ZigBeeEndpointAddress;
import com.zsmartsystems.zigbee.ZigBeeNetworkManager;
import com.zsmartsystems.zigbee.app.time.ZclTimeClient;
import com.zsmartsystems.zigbee.app.time.ZigBeeTimeExtension;
import com.zsmartsystems.zigbee.zcl.field.ZigBeeUtcTime;

/**
* Provides information about time servers on the network
*
* @author Chris Jackson
*
*/
public class ZigBeeConsoleTimeCommand extends ZigBeeConsoleAbstractCommand {
private static final String NOT_SET = "Not Set";
private static final String SECONDS = " seconds";
private static final String MINUTES = " minutes";

@Override
public String getCommand() {
return "time";
}

@Override
public String getDescription() {
return "Gets information about time servers";
}

@Override
public String getSyntax() {
return "[MANAGER | ENDPOINT] [POLL | GET | SET] [VALUE]";
}

@Override
public String getHelp() {
return "";
}

@Override
public void process(ZigBeeNetworkManager networkManager, String[] args, PrintStream out)
throws IllegalArgumentException, InterruptedException, ExecutionException {

ZigBeeTimeExtension extension = (ZigBeeTimeExtension) networkManager.getExtension(ZigBeeTimeExtension.class);
if (extension == null) {
throw new IllegalStateException("Time extension not found");
}

if (args.length == 1) {
ZigBeeUtcTime dstStart = extension.getDstStart();
ZigBeeUtcTime dstEnd = extension.getDstEnd();

out.println("Current Time : " + ZigBeeUtcTime.now().toString());
out.println("DST Start : " + ((dstStart == null) ? NOT_SET : dstStart.toString()));
out.println("DST Finish : " + ((dstEnd == null) ? NOT_SET : dstEnd.toString()));
out.println("DST Offset : " + extension.getDstOffset() / 60 + MINUTES);
out.println("Update delta : " + extension.getUpdateDelta() + SECONDS);
out.println("Poll period : " + extension.getPollPeriod() + SECONDS);
out.println("Master : " + extension.isMaster());
out.println("Superceding : " + extension.isSuperceding());
out.println();
showClient(out, extension);
return;
}

if (args[1].equalsIgnoreCase("manager")) {
processManagerOptions(extension, args, out);
return;
}

final ZigBeeEndpoint endpoint = getEndpoint(networkManager, args[1]);

if (args.length == 2) {
return;
}

final ZclTimeClient client = extension.getTimeClient(endpoint.getEndpointAddress());
if (client == null) {
throw new IllegalStateException(
"Time client not found for endpoint " + endpoint.getEndpointAddress().toString());
}

switch (args[2].toLowerCase()) {
case "set":
break;
case "get":
break;
default:
throw new IllegalArgumentException("Unknown endpoint command option " + args[2]);
}
}

private void processManagerOptions(ZigBeeTimeExtension extension, String[] args, PrintStream out) {
if (args.length < 4) {
throw new IllegalArgumentException("Invalid number of arguments");
}

switch (args[2].toLowerCase()) {
case "set":
processManagerSettings(extension, args, out);
break;
default:
throw new IllegalArgumentException("Unknown manager command option " + args[2]);
}
}

private void processManagerSettings(ZigBeeTimeExtension extension, String[] args, PrintStream out) {
if (args.length < 5) {
throw new IllegalArgumentException("Invalid number of arguments");
}

switch (args[3].toLowerCase()) {
case "poll":
extension.setPollPeriod(parseInteger(args[4]));
out.println("Time manager poll period set to " + extension.getPollPeriod() + SECONDS);
break;
case "delta":
extension.setUpdateDelta(parseInteger(args[4]));
out.println("Time manager update delta set to " + extension.getUpdateDelta() + SECONDS);
break;
case "master":
extension.setMaster(Boolean.parseBoolean(args[4]));
out.println("Time manager set master clock source to " + extension.isMaster());
break;
case "superceding":
extension.setSuperceding(Boolean.parseBoolean(args[4]));
out.println("Time manager set superceding clock source to " + extension.isSuperceding());
break;
default:
throw new IllegalArgumentException("Unknown manager setting option " + args[2]);
}
}

private void showClient(PrintStream out, ZigBeeTimeExtension extension) {
Map<ZigBeeEndpointAddress, ZclTimeClient> clients = new TreeMap<>();

// Provide a sorted output, sorted by address
for (ZclTimeClient client : extension.getTimeClients()) {
clients.put(client.getZigBeeAddress(), client);
}

out.println(
"Address Last Poll Dif Last Update By Delta s/24hr Valid Until DST Set Synced Master Master-DST Superceded");

for (ZclTimeClient client : clients.values()) {
ZigBeeUtcTime lastRequestedTime = client.getLastRequestedTime();
ZigBeeUtcTime lastUpdateTime = extension.getLastUpdateTime(client.getZigBeeAddress());
ZigBeeUtcTime validUntil = client.getValidUntil();
out.println(String.format(
"%-9s %-20s %3s %-20s %-6s % 2dsec %+6.1f %-20s %-5b %-5b %-5b %-5b %-5b",
client.getZigBeeAddress().toString(),
((lastRequestedTime == null) ? NOT_SET : lastRequestedTime.toString()),
((lastRequestedTime == null) ? "" : Integer.toString(client.getCurrentDelta())),
((lastUpdateTime == null) ? NOT_SET : lastUpdateTime.toString()),
extension.getLastUpdateMethod(client.getZigBeeAddress()).toString(), client.getLastDelta(),
client.getDailyDriftRate(), ((validUntil == null) ? NOT_SET : validUntil.toString()),
client.isDstSet(), client.isRemoteSynchronized(), client.isRemoteMaster(),
client.isRemoteMasterDst(), client.isRemoteSuperceding()));
}
}
}
Loading
Loading