Skip to content

Commit

Permalink
[#167] Updated Notification system so that Sections are embedded in a…
Browse files Browse the repository at this point in the history
… Notification object
  • Loading branch information
susanw1 committed Oct 3, 2024
1 parent 808740e commit 3a228a6
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package net.zscript.javaclient.commandbuilder.notifications;

public interface Notification {
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@
import net.zscript.javaclient.commandbuilder.ZscriptClientException;
import net.zscript.javaclient.commandbuilder.ZscriptResponse;

public abstract class NotificationHandle {
public abstract class NotificationHandle<N extends Notification> {
@Nonnull
public abstract <T extends ZscriptResponse> NotificationSection<T> getSection(NotificationSectionId<T> response);

@Nonnull
@Deprecated
public abstract List<NotificationSection<?>> getSections();

public abstract N createNotification(@Nonnull final ResponseExecutionPath responsePath);

/**
* Creates a list of the right types of notification section content
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package net.zscript.javaclient.commandbuilder.notifications;

public abstract class NotificationId<T extends NotificationHandle> {
public abstract class NotificationId<H extends NotificationHandle<? extends Notification>> {
public abstract int getId();

public abstract Class<T> getHandleType();
public abstract Class<H> getHandleType();

public abstract T newHandle();
public abstract H newHandle();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

import net.zscript.javaclient.commandbuilder.ZscriptResponse;

public class NotificationSectionId<T extends ZscriptResponse> {
public class NotificationSectionId<R extends ZscriptResponse> {
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Individual Notification Sections, to be grouped into actual notifications. Processed separately from the actual notifications, because many Sections are
// replicated identically across multiple notifications, and would otherwise create pointless duplicates.

// Individual Notification Sections, to be grouped into actual notifications. Processed separately from the actual notifications, because many Sections are
// replicated identically across multiple notifications, and would otherwise create pointless duplicates.

{{#notificationSections}}
/** Singleton identifier for specific notification section: {{description}} */
Expand Down Expand Up @@ -44,15 +45,14 @@
}

// Notification section field accessors

{{#fields}}
{{>responseField.mustache}}
{{/fields}}
}

{{/notificationSections}}

// Notification-level classes.
// Notification-level classes.

{{#notifications}}
/** Singleton identifier for the {{notificationName}} notification: {{description}} */
Expand Down Expand Up @@ -93,8 +93,8 @@
}

/** Handle for {{#upperCamel}}{{notificationName}}{{/upperCamel}} Notifications, referencing the sections within. */
public static final class {{#upperCamel}}{{notificationName}}{{/upperCamel}}NotificationHandle extends NotificationHandle {
private final LinkedHashMap<NotificationSectionId<?>, NotificationSection<?>> sections = new LinkedHashMap<>();
public static final class {{#upperCamel}}{{notificationName}}{{/upperCamel}}NotificationHandle extends NotificationHandle<{{#upperCamel}}{{notificationName}}{{/upperCamel}}Notification> {
private final Map<NotificationSectionId<?>, NotificationSection<?>> sections = new LinkedHashMap<>();
public {{#upperCamel}}{{notificationName}}{{/upperCamel}}NotificationHandle() {
{{#sections}}
Expand All @@ -115,6 +115,38 @@
public List<NotificationSection<?>> getSections() {
return new ArrayList<>(sections.values());
}

@Nonnull
@Override
public {{#upperCamel}}{{notificationName}}{{/upperCamel}}Notification createNotification(@Nonnull final ResponseExecutionPath responsePath) {
return new {{#upperCamel}}{{notificationName}}{{/upperCamel}}Notification(this, responsePath);
}
}

/** Notification object for {{#upperCamel}}{{notificationName}}{{/upperCamel}}, with section accessors. */
public static final class {{#upperCamel}}{{notificationName}}{{/upperCamel}}Notification implements Notification {
{{#sections}}
{{#section}}
private final {{#upperCamel}}{{name}}{{/upperCamel}}NotificationSectionContent {{#lowerCamel}}{{name}}{{/lowerCamel}};
{{/section}}
{{/sections}}

{{#upperCamel}}{{notificationName}}{{/upperCamel}}Notification(final {{#upperCamel}}{{notificationName}}{{/upperCamel}}NotificationHandle handle, final ResponseExecutionPath responsePath) {
Iterator<ZscriptResponse> responseIterator = handle.buildNotificationContent(responsePath).iterator();
{{#sections}}
{{#section}}
{{#lowerCamel}}{{name}}{{/lowerCamel}} = ({{#upperCamel}}{{name}}{{/upperCamel}}NotificationSectionContent) responseIterator.next();
{{/section}}
{{/sections}}
}

{{#sections}}
{{#section}}
public {{#upperCamel}}{{name}}{{/upperCamel}}NotificationSectionContent get{{#upperCamel}}{{name}}{{/upperCamel}}Section() {
return {{#lowerCamel}}{{name}}{{/lowerCamel}};
}
{{/section}}
{{/sections}}
}
{{/notifications}}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void shouldCreateNotificationWithRequiredFields() {

final TestingModule.TestNtfBNotificationHandle handle = TestingModule.TestNtfBNotificationId.get().newHandle();

final CompleteAddressedResponse car = CompleteAddressedResponse.parse(buffer.getTokenReader());
final CompleteAddressedResponse car = CompleteAddressedResponse.parse(tokenReader);
assertThat(car.asResponse().hasAddress()).isFalse();
assertThat(car.getContent().getResponseValue()).isEqualTo(0x234);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import net.zscript.util.ByteString.ByteAppendable;
import net.zscript.util.ByteString.ByteStringBuilder;

public class ResponseSequence implements ByteAppendable {
public final class ResponseSequence implements ByteAppendable {
private final ResponseExecutionPath executionPath;

private final int echoField;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import net.zscript.javaclient.commandbuilder.commandnodes.CommandSequenceNode;
import net.zscript.javaclient.commandbuilder.commandnodes.OrSequenceNode;
import net.zscript.javaclient.commandbuilder.commandnodes.ZscriptCommandNode;
import net.zscript.javaclient.commandbuilder.notifications.Notification;
import net.zscript.javaclient.commandbuilder.notifications.NotificationHandle;
import net.zscript.javaclient.commandbuilder.notifications.NotificationId;
import net.zscript.javaclient.nodes.ZscriptNode;
Expand All @@ -34,19 +35,30 @@ public class Device {
private final ZscriptModel model;
private final ZscriptNode node;

private final Map<NotificationId<?>, NotificationHandle> handles = new HashMap<>();
private final Map<NotificationId<?>, NotificationHandle<?>> handles = new HashMap<>();

public Device(ZscriptModel model, ZscriptNode node) {
this.model = model;
this.node = node;
}

@Nonnull
public <T extends NotificationHandle> T getNotificationHandle(NotificationId<T> id) {
public <N extends Notification, H extends NotificationHandle<N>> H getNotificationHandle(NotificationId<H> id) {
return id.getHandleType().cast(handles.computeIfAbsent(id, NotificationId::newHandle));
}

public <T extends NotificationHandle> void setNotificationListener(NotificationId<T> id, Consumer<NotificationSequenceCallback> listener) {
public <N extends Notification, H extends NotificationHandle<N>> void setNotificationListener(NotificationId<H> id, Consumer<? super N> listener) {
final H notificationHandle = getNotificationHandle(id);
node.setNotificationHandler(id.getId(), respSeq -> {
final N notification = notificationHandle.createNotification(respSeq.getExecutionPath());
listener.accept(notification);
});
}

/**
* @deprecated Use {@link #setNotificationListener(NotificationId, Consumer)} instead
*/
public <N extends Notification, H extends NotificationHandle<N>> void setNotificationListener_Prev(NotificationId<H> id, Consumer<NotificationSequenceCallback> listener) {
node.setNotificationHandler(id.getId(),
respSeq -> listener.accept(NotificationSequenceCallback.from(getNotificationHandle(id).getSections(), respSeq.getExecutionPath().getResponses())));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,20 @@ private int negotiateBaud(SerialPort port, Device device, int target, String nam
if (target != -1) {
// Find the channel index for the current channel
ResponseCaptor<CoreModule.ChannelInfoCommand.ChannelInfoResponse> infoResp = ResponseCaptor.create();
int currentChannelIndex = device.sendAndWaitExpectSuccess(
CoreModule.channelInfoBuilder().capture(infoResp).build()).getResponseFor(infoResp).orElseThrow().getCurrentChannel();
int currentChannelIndex = device.sendAndWaitExpectSuccess(CoreModule.channelInfoBuilder()
.capture(infoResp)
.build())
.getResponseFor(infoResp).orElseThrow()
.getCurrentChannel();

// get the detailed info on the current channel
ResponseCaptor<UartModule.ChannelInfoCommand.ChannelInfoResponse> uartInfo = ResponseCaptor.create();
UartModule.ChannelInfoCommand.ChannelInfoResponse resp = device.sendAndWaitExpectSuccess(
UartModule.channelInfoBuilder().setChannel(currentChannelIndex).capture(uartInfo).build()).getResponseFor(uartInfo).orElseThrow();
UartModule.ChannelInfoCommand.ChannelInfoResponse resp = device.sendAndWaitExpectSuccess(UartModule.channelInfoBuilder()
.setChannel(currentChannelIndex)
.capture(uartInfo)
.build())
.getResponseFor(uartInfo).orElseThrow();

if (resp.getBitsetCapabilities().contains(UartModule.ChannelInfoCommand.ChannelInfoResponse.BitsetCapabilities.ArbitraryFrequency)) {
// if the channel supports free baud rate setting, use that to set the desired baud rate
return setBaudArbitrary(port, device, target, name, resp, currentChannelIndex);
Expand Down Expand Up @@ -173,9 +180,13 @@ private int setBaudSearchMenu(SerialPort port, Device device, int target, String
boolean hasFound = false;
for (int i = 0; i < resp.getFrequenciesSupported().orElseThrow(); i++) {
ResponseCaptor<UartModule.ChannelInfoCommand.ChannelInfoResponse> captor = ResponseCaptor.create();
node = node.andThen(UartModule.channelInfoBuilder().setChannel(currentChannelIndex).setFrequencySelection(i).capture(captor).build());
node = node.andThen(UartModule.channelInfoBuilder()
.setChannel(currentChannelIndex)
.setFrequencySelection(i).capture(captor)
.build());
captors.add(captor);
}

ResponseSequenceCallback result = device.sendAndWaitExpectSuccess(node);
// iterate the frequency options looking for an exact match
for (int i = 0; i < resp.getFrequenciesSupported().orElseThrow(); i++) {
Expand All @@ -184,7 +195,10 @@ private int setBaudSearchMenu(SerialPort port, Device device, int target, String
int baudInt = parseBaud(respEach.getBaudRate());
if (baudInt == target) {
hasFound = true;
device.sendAndWaitExpectSuccess(UartModule.channelSetupBuilder().setChannel(currentChannelIndex).setFrequencySelection(i).build());
device.sendAndWaitExpectSuccess(UartModule.channelSetupBuilder()
.setChannel(currentChannelIndex)
.setFrequencySelection(i)
.build());
port.setBaudRate(target);
break;
}
Expand All @@ -206,7 +220,11 @@ private int setBaudInteractiveMenu(SerialPort port, Device device, String name,
// send all the get commands in one batch, for fun
for (int i = 0; i < resp.getFrequenciesSupported().orElseThrow(); i++) {
ResponseCaptor<UartModule.ChannelInfoCommand.ChannelInfoResponse> captor = ResponseCaptor.create();
node = node.andThen(UartModule.channelInfoBuilder().setChannel(currentChannelIndex).setFrequencySelection(i).capture(captor).build());
node = node.andThen(UartModule.channelInfoBuilder()
.setChannel(currentChannelIndex)
.setFrequencySelection(i)
.capture(captor)
.build());
captors.add(captor);
}
int[] freqChoices = new int[resp.getFrequenciesSupported().orElseThrow()];
Expand Down Expand Up @@ -236,7 +254,11 @@ private int setBaudInteractiveMenu(SerialPort port, Device device, String name,
return 1;
}
// apply chosen frequency
device.sendAndWaitExpectSuccess(UartModule.channelSetupBuilder().setChannel(currentChannelIndex).setFrequencySelection(choice).build());
device.sendAndWaitExpectSuccess(UartModule.channelSetupBuilder()
.setChannel(currentChannelIndex)
.setFrequencySelection(choice)
.build());

port.setBaudRate(freqChoices[choice]);
return 0;
}
Expand All @@ -260,7 +282,10 @@ private int setBaudArbitrary(SerialPort port, Device device, int target, String
return 1;
}
byte[] baud = new byte[] { (byte) (actualTarget >> 16), (byte) (actualTarget >> 8), (byte) actualTarget };
device.sendAndWaitExpectSuccess(UartModule.channelSetupBuilder().setChannel(currentChannelIndex).setBaudRate(baud).build());
device.sendAndWaitExpectSuccess(UartModule.channelSetupBuilder()
.setChannel(currentChannelIndex)
.setBaudRate(baud)
.build());
port.setBaudRate(actualTarget);
return 0;
}
Expand All @@ -281,9 +306,12 @@ private int parsePin(Device device, String name, String verb, Predicate<DigitalS
throws InterruptedException {
ResponseCaptor<PinsModule.CapabilitiesCommand.CapabilitiesResponse> captor = ResponseCaptor.create();

int pinCount = device.sendAndWaitExpectSuccess(PinsModule.capabilitiesBuilder().capture(captor).build())
int pinCount = device.sendAndWaitExpectSuccess(PinsModule.capabilitiesBuilder()
.capture(captor)
.build())
.getResponseFor(captor)
.orElseThrow().getPinCount();

System.out.println(name + " has " + pinCount + " pins");
Set<Integer> pinsSupporting = new HashSet<>();
// assemble a big command sequence to check pins in batches...
Expand All @@ -297,7 +325,9 @@ private int parsePin(Device device, String name, String verb, Predicate<DigitalS
continue;
}
ResponseCaptor<DigitalSetupResponse> digitalCaptor = ResponseCaptor.create();
sequence = sequence.andThen(PinsModule.digitalSetupBuilder().setPin(i).capture(digitalCaptor).build());
sequence = sequence.andThen(PinsModule.digitalSetupBuilder()
.setPin(i).capture(digitalCaptor)
.build());
captors.add(digitalCaptor);
}
ResponseSequenceCallback resp = device.sendAndWaitExpectSuccess(sequence);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import static net.zscript.model.modules.base.PinsModule.DigitalNotificationSectionContent.Value;

import net.zscript.javaclient.commandbuilder.commandnodes.ResponseCaptor;
import net.zscript.javaclient.devices.Device;
import net.zscript.model.modules.base.OuterCoreModule;
import net.zscript.model.modules.base.PinsModule;
Expand Down Expand Up @@ -39,12 +38,18 @@ public MorseReceiver(MorseTranslator translator, Device device, long ditPeriodMa
public void startReceiving() {
try {
lastTimeNano = System.nanoTime();
ResponseCaptor<PinsModule.DigitalNotificationSectionContent> captor = ResponseCaptor.create();
device.getNotificationHandle(PinsModule.DigitalNotificationId.get())
.getSection(PinsModule.DigitalNotificationSectionId.get())
.setCaptor(captor);
device.setNotificationListener(PinsModule.DigitalNotificationId.get(), notificationSequenceCallback -> {
PinsModule.DigitalNotificationSectionContent content = notificationSequenceCallback.getResponseFor(captor).get();

// // Older notification registration system, using Captors.
// ResponseCaptor<PinsModule.DigitalNotificationSectionContent> captor = ResponseCaptor.create();
// device.getNotificationHandle(PinsModule.DigitalNotificationId.get())
// .getSection(PinsModule.DigitalNotificationSectionId.get())
// .setCaptor(captor);
// device.setNotificationListener_Prev(PinsModule.DigitalNotificationId.get(), notificationSequenceCallback -> {
// PinsModule.DigitalNotificationSectionContent content = notificationSequenceCallback.getResponseFor(captor).get();
// });

device.setNotificationListener(PinsModule.DigitalNotificationId.get(), n -> {
PinsModule.DigitalNotificationSectionContent content = n.getDigitalSection();

long current = System.nanoTime();
double time = (current - lastTimeNano) / 1000.0 / ditPeriodMaxUs;
Expand Down Expand Up @@ -75,8 +80,14 @@ public void startReceiving() {
}
lastTimeNano = current;
});
device.sendAndWaitExpectSuccess(OuterCoreModule.channelSetupBuilder().setAssignNotification().build());
device.sendAndWaitExpectSuccess(PinsModule.digitalSetupBuilder().setPin(pin).setMode(Mode.Input).setNotificationMode(NotificationMode.OnChange).build());
device.sendAndWaitExpectSuccess(OuterCoreModule.channelSetupBuilder()
.setAssignNotification()
.build());
device.sendAndWaitExpectSuccess(PinsModule.digitalSetupBuilder()
.setPin(pin)
.setMode(Mode.Input).
setNotificationMode(NotificationMode.OnChange)
.build());
exec.scheduleAtFixedRate(this::checkReceive, 100000, ditPeriodMaxUs * 4, TimeUnit.MICROSECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
Expand Down

0 comments on commit 3a228a6

Please sign in to comment.