First RPC Version
parent
d9a08dfeeb
commit
8cf002e648
|
@ -0,0 +1,24 @@
|
||||||
|
package org.hwo.pulscounter;
|
||||||
|
|
||||||
|
public interface IPulsCounter {
|
||||||
|
|
||||||
|
public String[] getDeviceName();
|
||||||
|
|
||||||
|
public int getChannels();
|
||||||
|
|
||||||
|
public String getChannelName(Integer channel);
|
||||||
|
public void setChannelName(Integer channel,String name);
|
||||||
|
|
||||||
|
public int[] getChannelCounters();
|
||||||
|
public void setChannelCounter(Integer channel,Integer count);
|
||||||
|
|
||||||
|
public int[] getChannelOffsets();
|
||||||
|
public void setChannelOffset(Integer channel,Integer offset);
|
||||||
|
|
||||||
|
public String getPhysicalInterfaceName();
|
||||||
|
public void setPhysicalInterfaceName(String interfaceName);
|
||||||
|
|
||||||
|
public String[] getPhysicalInterfaceNames();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,230 @@
|
||||||
|
package org.hwo.pulscounter;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.hwo.io.SerialPort;
|
||||||
|
import org.hwo.io.servicelink.ServiceLink;
|
||||||
|
import org.hwo.io.servicelink.ServiceLinkException;
|
||||||
|
import org.hwo.io.servicelink.ServiceLinkRequestFailedException;
|
||||||
|
|
||||||
|
public class NewPulsCounterDevice implements IPulsCounter {
|
||||||
|
private ServiceLink serviceLink;
|
||||||
|
private Properties chprop;
|
||||||
|
|
||||||
|
public NewPulsCounterDevice()
|
||||||
|
{
|
||||||
|
this.chprop = new Properties();
|
||||||
|
File pf = new File("chnames.prop");
|
||||||
|
|
||||||
|
try {
|
||||||
|
chprop.load(new FileInputStream(pf));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
String defaultPort = chprop.getProperty("io.port", "COM1");
|
||||||
|
System.err.println("Default Port: " + defaultPort);
|
||||||
|
|
||||||
|
setPhysicalInterfaceName(defaultPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized public void reset(int ch)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized public void reset()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
synchronized public void update()
|
||||||
|
{
|
||||||
|
System.err.println(String.format("BRKVAL: 0x%04x", serviceLink.getServiceRegisterCache().getCachedInteger((byte)0, (byte)0, (short)0x200)));
|
||||||
|
System.err.println(String.format("SPLIM : 0x%04x", serviceLink.getServiceRegisterCache().getCachedInteger((byte)0, (byte)0, (short)0x201)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveProps(){
|
||||||
|
File pf = new File("chnames.prop");
|
||||||
|
try {
|
||||||
|
chprop.store(new FileOutputStream(pf), "");
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkOpen(){
|
||||||
|
if (!serviceLink.isOpen())
|
||||||
|
try {
|
||||||
|
serviceLink.open();
|
||||||
|
} catch (ServiceLinkException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getDeviceName()
|
||||||
|
{
|
||||||
|
return new String[]{"PulsCounter Board","0.1","alpha"};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDeviceTime()
|
||||||
|
{
|
||||||
|
return new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerialPort getSerialPort() {
|
||||||
|
return serviceLink.getSerialPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSerialPort(SerialPort serialPort) throws ServiceLinkException {
|
||||||
|
|
||||||
|
if (this.serviceLink == null)
|
||||||
|
this.serviceLink = new ServiceLink(serialPort);
|
||||||
|
|
||||||
|
if (this.serviceLink.isOpen())
|
||||||
|
this.serviceLink.close();
|
||||||
|
|
||||||
|
this.serviceLink.setSerialPort(serialPort);;
|
||||||
|
this.serviceLink.open();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.serviceLink.readInt((byte)0, (byte)0, 0);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.err.println("BRKVAL: " + this.serviceLink.getServiceRegisterCache().getCachedInteger(13, 0, 0x0020));
|
||||||
|
System.err.println("SPLIM: " + this.serviceLink.getServiceRegisterCache().getCachedInteger(13, 0, 0x0021));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannelName(Integer channel) {
|
||||||
|
return chprop.getProperty(String.format("channel.%d", channel),String.format("Kanal %d",channel+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChannelName(Integer channel, String name) {
|
||||||
|
|
||||||
|
chprop.setProperty(String.format("channel.%d", channel), name);
|
||||||
|
|
||||||
|
saveProps();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getChannelCounters() {
|
||||||
|
|
||||||
|
checkOpen();
|
||||||
|
|
||||||
|
int nch = getChannels();
|
||||||
|
int[] counters = new int[ nch ];
|
||||||
|
|
||||||
|
for (int i=0;i<nch;i++) {
|
||||||
|
counters[i] = serviceLink.getServiceRegisterCache().getCachedInteger(13, 0, 0x1000 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return counters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChannelCounter(Integer channel, Integer count) {
|
||||||
|
|
||||||
|
checkOpen();
|
||||||
|
|
||||||
|
try {
|
||||||
|
serviceLink.writeInt((byte)13, (byte)0, 0x1000 + channel, count);
|
||||||
|
} catch (ServiceLinkRequestFailedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ServiceLinkException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getChannelOffsets() {
|
||||||
|
|
||||||
|
checkOpen();
|
||||||
|
|
||||||
|
int nch = getChannels();
|
||||||
|
int[] offsets = new int[ nch ];
|
||||||
|
|
||||||
|
for (int i=0;i<nch;i++) {
|
||||||
|
offsets[i] = serviceLink.getServiceRegisterCache().getCachedInteger(13, 0, 0x1100 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return offsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChannelOffset(Integer channel, Integer offset) {
|
||||||
|
|
||||||
|
checkOpen();
|
||||||
|
|
||||||
|
try {
|
||||||
|
serviceLink.writeInt((byte)13, (byte)0, 0x1100 + channel, offset);
|
||||||
|
} catch (ServiceLinkRequestFailedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ServiceLinkException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChannels() {
|
||||||
|
checkOpen();
|
||||||
|
|
||||||
|
System.err.println("BRKVAL: " + this.serviceLink.getServiceRegisterCache().getCachedInteger(13, 0, 0x0020));
|
||||||
|
System.err.println("SPLIM: " + this.serviceLink.getServiceRegisterCache().getCachedInteger(13, 0, 0x0021));
|
||||||
|
|
||||||
|
return serviceLink.getServiceRegisterCache().getCachedInteger(13, 0, 0x0400 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPhysicalInterfaceName() {
|
||||||
|
|
||||||
|
checkOpen();
|
||||||
|
|
||||||
|
return serviceLink.getSerialPort().getPortName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPhysicalInterfaceName(String interfaceName) {
|
||||||
|
try {
|
||||||
|
chprop.setProperty("io.port", interfaceName);
|
||||||
|
saveProps();
|
||||||
|
|
||||||
|
SerialPort sport = SerialPort.newInstance();
|
||||||
|
sport.setPortName(interfaceName);
|
||||||
|
setSerialPort(sport);
|
||||||
|
|
||||||
|
} catch (ServiceLinkException sle){
|
||||||
|
sle.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getPhysicalInterfaceNames() {
|
||||||
|
return SerialPort.getPortNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,13 +1,42 @@
|
||||||
package org.hwo.pulscounter;
|
package org.hwo.pulscounter;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.prefs.Preferences;
|
||||||
|
|
||||||
|
import org.hwo.beacon.Beacon;
|
||||||
import org.hwo.os.OsDetect;
|
import org.hwo.os.OsDetect;
|
||||||
import org.hwo.os.OsDetect.OsType;
|
import org.hwo.os.OsDetect.OsType;
|
||||||
|
import org.hwo.rpc.json.RPCAdapter;
|
||||||
|
import org.hwo.rpc.simple.SimpleRPCServer;
|
||||||
|
|
||||||
public class PulsCounter {
|
public class PulsCounter {
|
||||||
|
|
||||||
|
static private Preferences prefs;
|
||||||
|
public static Preferences getPrefs() {
|
||||||
|
return prefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static private IPulsCounter deviceConnection;
|
||||||
|
public static IPulsCounter getDeviceConnection() {
|
||||||
|
return deviceConnection;
|
||||||
|
}
|
||||||
|
public static void setDeviceConnection(IPulsCounter deviceConnection) {
|
||||||
|
PulsCounter.deviceConnection = deviceConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Beacon beacon;
|
||||||
|
public static Beacon getBeacon() {
|
||||||
|
return beacon;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean serverMode;
|
||||||
|
|
||||||
|
|
||||||
public static void main(String args[])
|
public static void main(String args[])
|
||||||
{
|
{
|
||||||
|
@ -17,6 +46,8 @@ public class PulsCounter {
|
||||||
System.err.println("Current Directory: " + cwd.getAbsolutePath());
|
System.err.println("Current Directory: " + cwd.getAbsolutePath());
|
||||||
System.err.println("Library Path: " + System.getProperty("java.library.path"));
|
System.err.println("Library Path: " + System.getProperty("java.library.path"));
|
||||||
|
|
||||||
|
prefs = Preferences.userRoot();
|
||||||
|
|
||||||
if (OsDetect.getOperatingSystem() == OsType.LINUX)
|
if (OsDetect.getOperatingSystem() == OsType.LINUX)
|
||||||
{
|
{
|
||||||
System.err.println("Linux erkannt. Patche java.library.path");
|
System.err.println("Linux erkannt. Patche java.library.path");
|
||||||
|
@ -43,11 +74,42 @@ public class PulsCounter {
|
||||||
System.err.println("Library Path: " + System.getProperty("java.library.path"));
|
System.err.println("Library Path: " + System.getProperty("java.library.path"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Iterator<String> options = Arrays.asList(args).iterator();
|
||||||
|
|
||||||
PulsCounterWindow window = new PulsCounterWindow();
|
while (options.hasNext()) {
|
||||||
window.setVisible(true);
|
String no = options.next();
|
||||||
|
|
||||||
|
if (no.equals("-s")) {
|
||||||
|
serverMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceConnection = null;
|
||||||
|
|
||||||
|
beacon = new Beacon(44556);
|
||||||
|
beacon.getProperties().setProperty("rpc.simple.interfaces", "org.hwo.pulsecounter");
|
||||||
|
beacon.getProperties().setProperty("rpc.simple.port", "44352");
|
||||||
|
beacon.setServerOnly(serverMode);
|
||||||
|
beacon.start();
|
||||||
|
|
||||||
|
try {
|
||||||
|
NewPulsCounterDevice device = new NewPulsCounterDevice();
|
||||||
|
|
||||||
|
SimpleRPCServer rpcserver = new SimpleRPCServer(InetAddress.getByName("0.0.0.0"), 44352);
|
||||||
|
rpcserver.registerObject(IPulsCounter.class, device);
|
||||||
|
rpcserver.start();
|
||||||
|
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!serverMode) {
|
||||||
|
PulsCounterWindow window = new PulsCounterWindow();
|
||||||
|
window.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.hwo.pulscounter;
|
||||||
|
|
||||||
import java.awt.EventQueue;
|
import java.awt.EventQueue;
|
||||||
|
|
||||||
|
import javax.swing.DesktopManager;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
|
@ -13,16 +14,22 @@ import java.awt.BorderLayout;
|
||||||
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
|
|
||||||
|
import java.awt.Desktop;
|
||||||
import java.awt.GridBagLayout;
|
import java.awt.GridBagLayout;
|
||||||
import java.awt.GridBagConstraints;
|
import java.awt.GridBagConstraints;
|
||||||
|
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
|
|
||||||
|
import org.hwo.beacon.Beacon;
|
||||||
|
import org.hwo.beacon.Beacon.BeaconSender;
|
||||||
import org.hwo.csv.CSV;
|
import org.hwo.csv.CSV;
|
||||||
import org.hwo.io.SerialPort;
|
import org.hwo.io.SerialPort;
|
||||||
import org.hwo.models.TableMapper.AbstractTableMapperListener;
|
import org.hwo.models.TableMapper.AbstractTableMapperListener;
|
||||||
import org.hwo.models.TableMapper.TableMapper;
|
import org.hwo.models.TableMapper.TableMapper;
|
||||||
|
import org.hwo.pulscounter.ui.NetworkSelectorDialog;
|
||||||
|
import org.hwo.rpc.simple.SimpleRPCService;
|
||||||
|
import org.hwo.ui.JObjectSelector;
|
||||||
import org.hwo.ui.MousePopupListener;
|
import org.hwo.ui.MousePopupListener;
|
||||||
|
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
@ -58,13 +65,14 @@ import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
import org.hwo.datetime.JTimeOfDay;
|
import org.hwo.datetime.JTimeOfDay;
|
||||||
|
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
|
|
||||||
public class PulsCounterWindow extends JFrame{
|
public class PulsCounterWindow extends JFrame{
|
||||||
private JComboBox cbInterfaces;
|
|
||||||
private JTable tCounter;
|
private JTable tCounter;
|
||||||
|
|
||||||
private TableMapper tmCounter;
|
private TableMapper tmCounter;
|
||||||
|
@ -91,6 +99,7 @@ public class PulsCounterWindow extends JFrame{
|
||||||
private JTextField tfWorkDir;
|
private JTextField tfWorkDir;
|
||||||
|
|
||||||
private String workingDirectory;
|
private String workingDirectory;
|
||||||
|
private JTextField tfPhysicalInterface;
|
||||||
|
|
||||||
public PulsCounterWindow() {
|
public PulsCounterWindow() {
|
||||||
addWindowListener(new WindowAdapter() {
|
addWindowListener(new WindowAdapter() {
|
||||||
|
@ -133,42 +142,87 @@ public class PulsCounterWindow extends JFrame{
|
||||||
gbc_panel_1.gridy = 0;
|
gbc_panel_1.gridy = 0;
|
||||||
panel.add(panel_1, gbc_panel_1);
|
panel.add(panel_1, gbc_panel_1);
|
||||||
GridBagLayout gbl_panel_1 = new GridBagLayout();
|
GridBagLayout gbl_panel_1 = new GridBagLayout();
|
||||||
gbl_panel_1.columnWidths = new int[]{0, 0, 0};
|
gbl_panel_1.columnWidths = new int[]{0, 0, 0, 0};
|
||||||
gbl_panel_1.rowHeights = new int[]{0, 0};
|
gbl_panel_1.rowHeights = new int[]{0, 0, 0};
|
||||||
gbl_panel_1.columnWeights = new double[]{0.0, 1.0, Double.MIN_VALUE};
|
gbl_panel_1.columnWeights = new double[]{0.0, 1.0, 0.0, Double.MIN_VALUE};
|
||||||
gbl_panel_1.rowWeights = new double[]{0.0, Double.MIN_VALUE};
|
gbl_panel_1.rowWeights = new double[]{0.0, 0.0, Double.MIN_VALUE};
|
||||||
panel_1.setLayout(gbl_panel_1);
|
panel_1.setLayout(gbl_panel_1);
|
||||||
|
|
||||||
|
JButton btnNetzwerk = new JButton("Netzwerk...");
|
||||||
|
btnNetzwerk.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent arg0) {
|
||||||
|
BeaconSender sender = NetworkSelectorDialog.show(PulsCounter.getBeacon());
|
||||||
|
if (sender != null){
|
||||||
|
|
||||||
|
int port = Integer.decode(sender.getProperties().getProperty("rpc.simple.port"));
|
||||||
|
|
||||||
|
SimpleRPCService service = new SimpleRPCService(sender.getInetAddress(), port);
|
||||||
|
IPulsCounter ipc = service.createProxy(IPulsCounter.class);
|
||||||
|
|
||||||
|
counterChannels.clear();
|
||||||
|
|
||||||
|
changeDeviceConnection(ipc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
GridBagConstraints gbc_btnNetzwerk = new GridBagConstraints();
|
||||||
|
gbc_btnNetzwerk.insets = new Insets(0, 0, 5, 5);
|
||||||
|
gbc_btnNetzwerk.gridx = 0;
|
||||||
|
gbc_btnNetzwerk.gridy = 0;
|
||||||
|
panel_1.add(btnNetzwerk, gbc_btnNetzwerk);
|
||||||
|
|
||||||
|
JButton btnLokal = new JButton("Lokal");
|
||||||
|
btnLokal.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
try {
|
||||||
|
SimpleRPCService service;
|
||||||
|
service = new SimpleRPCService(InetAddress.getLocalHost(), 44352);
|
||||||
|
IPulsCounter ipc = service.createProxy(IPulsCounter.class);
|
||||||
|
|
||||||
|
counterChannels.clear();
|
||||||
|
|
||||||
|
changeDeviceConnection(ipc);
|
||||||
|
} catch (UnknownHostException e1) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
GridBagConstraints gbc_btnLokal = new GridBagConstraints();
|
||||||
|
gbc_btnLokal.insets = new Insets(0, 0, 5, 0);
|
||||||
|
gbc_btnLokal.gridx = 2;
|
||||||
|
gbc_btnLokal.gridy = 0;
|
||||||
|
panel_1.add(btnLokal, gbc_btnLokal);
|
||||||
|
|
||||||
JLabel lblNewLabel = new JLabel("Schnittstelle:");
|
JLabel lblNewLabel = new JLabel("Schnittstelle:");
|
||||||
GridBagConstraints gbc_lblNewLabel = new GridBagConstraints();
|
GridBagConstraints gbc_lblNewLabel = new GridBagConstraints();
|
||||||
|
gbc_lblNewLabel.anchor = GridBagConstraints.EAST;
|
||||||
gbc_lblNewLabel.insets = new Insets(0, 0, 0, 5);
|
gbc_lblNewLabel.insets = new Insets(0, 0, 0, 5);
|
||||||
gbc_lblNewLabel.gridx = 0;
|
gbc_lblNewLabel.gridx = 0;
|
||||||
gbc_lblNewLabel.gridy = 0;
|
gbc_lblNewLabel.gridy = 1;
|
||||||
panel_1.add(lblNewLabel, gbc_lblNewLabel);
|
panel_1.add(lblNewLabel, gbc_lblNewLabel);
|
||||||
|
|
||||||
cbInterfaces = new JComboBox();
|
tfPhysicalInterface = new JTextField();
|
||||||
GridBagConstraints gbc_cbInterfaces = new GridBagConstraints();
|
tfPhysicalInterface.setEditable(false);
|
||||||
gbc_cbInterfaces.fill = GridBagConstraints.HORIZONTAL;
|
GridBagConstraints gbc_tfPhysicalInterface = new GridBagConstraints();
|
||||||
gbc_cbInterfaces.gridx = 1;
|
gbc_tfPhysicalInterface.insets = new Insets(0, 0, 0, 5);
|
||||||
gbc_cbInterfaces.gridy = 0;
|
gbc_tfPhysicalInterface.anchor = GridBagConstraints.NORTH;
|
||||||
panel_1.add(cbInterfaces, gbc_cbInterfaces);
|
gbc_tfPhysicalInterface.fill = GridBagConstraints.HORIZONTAL;
|
||||||
cbInterfaces.addActionListener(new ActionListener() {
|
gbc_tfPhysicalInterface.gridx = 1;
|
||||||
public void actionPerformed(ActionEvent arg0) {
|
gbc_tfPhysicalInterface.gridy = 1;
|
||||||
|
panel_1.add(tfPhysicalInterface, gbc_tfPhysicalInterface);
|
||||||
|
tfPhysicalInterface.setColumns(10);
|
||||||
|
|
||||||
System.err.println("Save Pref PORT");
|
JButton btnWhlen = new JButton("w\u00E4hlen...");
|
||||||
|
btnWhlen.addActionListener(new ActionListener() {
|
||||||
prefs.put("io.port", cbInterfaces.getSelectedItem().toString());
|
public void actionPerformed(ActionEvent e) {
|
||||||
try
|
selectPhysicalInterface();
|
||||||
{
|
|
||||||
prefs.sync();
|
|
||||||
} catch (Exception e)
|
|
||||||
{
|
|
||||||
System.err.println("Exception: " + e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
setSerialPort();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
GridBagConstraints gbc_btnWhlen = new GridBagConstraints();
|
||||||
|
gbc_btnWhlen.gridx = 2;
|
||||||
|
gbc_btnWhlen.gridy = 1;
|
||||||
|
panel_1.add(btnWhlen, gbc_btnWhlen);
|
||||||
|
|
||||||
JPanel panel_2 = new JPanel();
|
JPanel panel_2 = new JPanel();
|
||||||
panel_2.setBorder(new TitledBorder(null, "Einstellungen", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
panel_2.setBorder(new TitledBorder(null, "Einstellungen", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||||
|
@ -291,17 +345,11 @@ public class PulsCounterWindow extends JFrame{
|
||||||
gbc_btnNewButton.gridy = 0;
|
gbc_btnNewButton.gridy = 0;
|
||||||
panel_3.add(btnNewButton, gbc_btnNewButton);
|
panel_3.add(btnNewButton, gbc_btnNewButton);
|
||||||
|
|
||||||
JButton btnTagesdateiSchreiben = new JButton("Kanalbezeichnungen speichern...");
|
|
||||||
GridBagConstraints gbc_btnTagesdateiSchreiben = new GridBagConstraints();
|
|
||||||
gbc_btnTagesdateiSchreiben.insets = new Insets(0, 0, 0, 5);
|
|
||||||
gbc_btnTagesdateiSchreiben.gridx = 2;
|
|
||||||
gbc_btnTagesdateiSchreiben.gridy = 0;
|
|
||||||
panel_3.add(btnTagesdateiSchreiben, gbc_btnTagesdateiSchreiben);
|
|
||||||
|
|
||||||
JButton btnAlle = new JButton("Alle 0");
|
JButton btnAlle = new JButton("Alle 0");
|
||||||
btnAlle.addActionListener(new ActionListener() {
|
btnAlle.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent arg0) {
|
public void actionPerformed(ActionEvent arg0) {
|
||||||
pulsCounterDevice.reset();
|
|
||||||
|
resetAllChannels();
|
||||||
|
|
||||||
synchronized (threadUpdater) {
|
synchronized (threadUpdater) {
|
||||||
threadUpdater.notifyAll();
|
threadUpdater.notifyAll();
|
||||||
|
@ -312,11 +360,6 @@ public class PulsCounterWindow extends JFrame{
|
||||||
gbc_btnAlle.gridx = 3;
|
gbc_btnAlle.gridx = 3;
|
||||||
gbc_btnAlle.gridy = 0;
|
gbc_btnAlle.gridy = 0;
|
||||||
panel_3.add(btnAlle, gbc_btnAlle);
|
panel_3.add(btnAlle, gbc_btnAlle);
|
||||||
btnTagesdateiSchreiben.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent arg0) {
|
|
||||||
saveChannelNames();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
btnNewButton.addActionListener(new ActionListener() {
|
btnNewButton.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent arg0) {
|
public void actionPerformed(ActionEvent arg0) {
|
||||||
synchronized (threadUpdater) {
|
synchronized (threadUpdater) {
|
||||||
|
@ -503,30 +546,15 @@ public class PulsCounterWindow extends JFrame{
|
||||||
|
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
applicationExiting = false;
|
applicationExiting = false;
|
||||||
pulsCounterDevice = new PulsCounterDevice();
|
|
||||||
|
|
||||||
prefs = Preferences.userRoot();
|
prefs = Preferences.userRoot();
|
||||||
|
|
||||||
String defaultPort = prefs.get("io.port", "COM1");
|
|
||||||
|
|
||||||
workingDirectory = prefs.get("file.directory", (new File(".")).getAbsolutePath());
|
workingDirectory = prefs.get("file.directory", (new File(".")).getAbsolutePath());
|
||||||
tfWorkDir.setText(workingDirectory);
|
tfWorkDir.setText(workingDirectory);
|
||||||
|
|
||||||
for (String portName:SerialPort.getPortNames())
|
counterChannels = new ArrayList<CounterChannel>();
|
||||||
cbInterfaces.addItem(portName);
|
|
||||||
|
|
||||||
// cbInterfaces.addItem("dummy:");
|
|
||||||
|
|
||||||
System.err.println("Default Port: " + defaultPort);
|
|
||||||
|
|
||||||
for (int i=0;i < cbInterfaces.getItemCount();i++)
|
|
||||||
{
|
|
||||||
if (cbInterfaces.getItemAt(i).equals(defaultPort))
|
|
||||||
cbInterfaces.setSelectedIndex(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
tmCounter = new TableMapper(CounterChannel.class, tCounter);
|
tmCounter = new TableMapper(CounterChannel.class, tCounter);
|
||||||
tmCounter.setRows(pulsCounterDevice.getChannels());
|
|
||||||
tmCounter.getColumnInfo().get(0).setReadOnly(true);
|
tmCounter.getColumnInfo().get(0).setReadOnly(true);
|
||||||
tmCounter.getColumnInfo().get(2).setReadOnly(true);
|
tmCounter.getColumnInfo().get(2).setReadOnly(true);
|
||||||
tmCounter.getColumnInfo().get(4).setReadOnly(true);
|
tmCounter.getColumnInfo().get(4).setReadOnly(true);
|
||||||
|
@ -534,9 +562,14 @@ public class PulsCounterWindow extends JFrame{
|
||||||
tmCounter.addTableMapperListener(new AbstractTableMapperListener() {
|
tmCounter.addTableMapperListener(new AbstractTableMapperListener() {
|
||||||
@Override
|
@Override
|
||||||
public void ValueChanged(int row, int column) {
|
public void ValueChanged(int row, int column) {
|
||||||
if (column == 2)
|
switch (column)
|
||||||
{
|
{
|
||||||
|
case 1:
|
||||||
|
saveChannelName(row);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
saveCorrection(row);
|
saveCorrection(row);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,7 +589,8 @@ public class PulsCounterWindow extends JFrame{
|
||||||
CounterChannel cc = (CounterChannel)tmCounter.getSelectedRow();
|
CounterChannel cc = (CounterChannel)tmCounter.getSelectedRow();
|
||||||
if (cc != null)
|
if (cc != null)
|
||||||
{
|
{
|
||||||
pulsCounterDevice.reset(cc.getChannel()-1);
|
PulsCounter.getDeviceConnection().setChannelCounter(cc.getChannel(), 0);
|
||||||
|
|
||||||
synchronized (threadUpdater) {
|
synchronized (threadUpdater) {
|
||||||
threadUpdater.notifyAll();
|
threadUpdater.notifyAll();
|
||||||
}
|
}
|
||||||
|
@ -576,8 +610,6 @@ public class PulsCounterWindow extends JFrame{
|
||||||
tmTBChannels.getColumnInfo().get(1).setReadOnly(true);
|
tmTBChannels.getColumnInfo().get(1).setReadOnly(true);
|
||||||
tmTBChannels.getColumnInfo().get(3).setReadOnly(true);
|
tmTBChannels.getColumnInfo().get(3).setReadOnly(true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
threadUpdater = new Thread(new Runnable() {
|
threadUpdater = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -591,7 +623,7 @@ public class PulsCounterWindow extends JFrame{
|
||||||
threadUpdater.wait();
|
threadUpdater.wait();
|
||||||
}
|
}
|
||||||
updateCounter();
|
updateCounter();
|
||||||
updateLiveFile();
|
// updateLiveFile();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -614,26 +646,45 @@ public class PulsCounterWindow extends JFrame{
|
||||||
});
|
});
|
||||||
updateTimer.setRepeats(true);
|
updateTimer.setRepeats(true);
|
||||||
updateTimer.start();
|
updateTimer.start();
|
||||||
|
|
||||||
loadChannelNames();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCounter()
|
private void updateCounter()
|
||||||
{
|
{
|
||||||
lActivity.setText("Werte aktualisieren...");
|
lActivity.setText("Werte aktualisieren...");
|
||||||
|
System.err.println("Werte aktualisieren...");
|
||||||
|
|
||||||
pulsCounterDevice.update();
|
if (counterChannels == null)
|
||||||
|
|
||||||
lDeviceType.setText(pulsCounterDevice.getDeviceName());
|
|
||||||
lDeviceTime.setText(pulsCounterDevice.getDeviceTime().toLocaleString());
|
|
||||||
|
|
||||||
if (cbTimeBarriers.getItemCount()==0)
|
|
||||||
{
|
{
|
||||||
for (TimeBarrier tb: pulsCounterDevice.getTimeBarriers())
|
tmCounter.setRows(counterChannels);
|
||||||
{
|
}
|
||||||
cbTimeBarriers.addItem(tb);
|
|
||||||
|
IPulsCounter ipc = PulsCounter.getDeviceConnection();
|
||||||
|
|
||||||
|
if (ipc == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int nch = ipc.getChannels();
|
||||||
|
|
||||||
|
System.err.println(String.format("GUI: updateCounter(): Channel Array Size: %d / %d",nch,counterChannels.size()));
|
||||||
|
|
||||||
|
|
||||||
|
if (nch != counterChannels.size()){
|
||||||
|
counterChannels.clear();
|
||||||
|
|
||||||
|
for (int i=0;i<nch;i++){
|
||||||
|
counterChannels.add(new CounterChannel(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadChannelNames();
|
||||||
|
loadChannelOffsets();
|
||||||
|
|
||||||
|
tmCounter.setRows(counterChannels);
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] counters = ipc.getChannelCounters();
|
||||||
|
|
||||||
|
for (CounterChannel channel: counterChannels){
|
||||||
|
channel.setValue(counters[channel.getChannel()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
lActivity.setText("warten...");
|
lActivity.setText("warten...");
|
||||||
|
@ -643,60 +694,47 @@ public class PulsCounterWindow extends JFrame{
|
||||||
private void saveCorrection(int row)
|
private void saveCorrection(int row)
|
||||||
{
|
{
|
||||||
System.err.println(String.format("Korrekturwert fŸr Kanal %d = %d",row + 1,tmCounter.getRow(row,CounterChannel.class).getCorrect()));
|
System.err.println(String.format("Korrekturwert fŸr Kanal %d = %d",row + 1,tmCounter.getRow(row,CounterChannel.class).getCorrect()));
|
||||||
|
PulsCounter.getDeviceConnection().setChannelOffset(row, tmCounter.getRow(row,CounterChannel.class).getCorrect());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSerialPort()
|
private void saveChannelName(int channel)
|
||||||
{
|
{
|
||||||
String serialPortName = cbInterfaces.getSelectedItem().toString();
|
PulsCounter.getDeviceConnection().setChannelName(channel, counterChannels.get(channel).getBezeichnung());
|
||||||
SerialPort sport = SerialPort.newInstance();
|
|
||||||
sport.setPortName(serialPortName);
|
|
||||||
pulsCounterDevice.setSerialPort(sport);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveChannelNames()
|
|
||||||
{
|
|
||||||
Properties chprop = new Properties();
|
|
||||||
|
|
||||||
for (CounterChannel ch:pulsCounterDevice.getChannels())
|
|
||||||
chprop.put(String.format("channel.%d", ch.getChannel()), ch.getBezeichnung());
|
|
||||||
|
|
||||||
File pf = new File("chnames.prop");
|
|
||||||
|
|
||||||
try {
|
|
||||||
chprop.store(new FileOutputStream(pf), "");
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
private void loadChannelNames()
|
private void loadChannelNames()
|
||||||
{
|
{
|
||||||
Properties chprop = new Properties();
|
for (CounterChannel channel: counterChannels){
|
||||||
|
channel.setBezeichnung(PulsCounter.getDeviceConnection().getChannelName(channel.getChannel()));
|
||||||
File pf = new File("chnames.prop");
|
|
||||||
|
|
||||||
try {
|
|
||||||
chprop.load(new FileInputStream(pf));
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadChannelOffsets() {
|
||||||
|
|
||||||
for (CounterChannel ch:pulsCounterDevice.getChannels())
|
int[] offsets = PulsCounter.getDeviceConnection().getChannelOffsets();
|
||||||
ch.setBezeichnung( chprop.getProperty(String.format("channel.%d", ch.getChannel())));
|
|
||||||
|
|
||||||
|
if (offsets.length != counterChannels.size()) {
|
||||||
|
System.err.println(String.format("GUI: loadChannelOffsets(): offset list size differs: %d != %d",offsets.length,counterChannels.size()));
|
||||||
|
}
|
||||||
|
for (CounterChannel channel: counterChannels){
|
||||||
|
channel.setCorrect(offsets[channel.getChannel()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetAllChannels() {
|
||||||
|
for (CounterChannel channel: counterChannels){
|
||||||
|
PulsCounter.getDeviceConnection().setChannelCounter(channel.getChannel(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeDeviceConnection(IPulsCounter ipc){
|
||||||
|
PulsCounter.setDeviceConnection(ipc);
|
||||||
|
|
||||||
|
tfPhysicalInterface.setText(ipc.getPhysicalInterfaceName());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void updateTimeBarrierView()
|
public void updateTimeBarrierView()
|
||||||
{
|
{
|
||||||
TimeBarrier tb = (TimeBarrier)cbTimeBarriers.getSelectedItem();
|
TimeBarrier tb = (TimeBarrier)cbTimeBarriers.getSelectedItem();
|
||||||
|
@ -732,4 +770,10 @@ public class PulsCounterWindow extends JFrame{
|
||||||
csv.saveToFile(String.format("%s/live.csv",workingDirectory));
|
csv.saveToFile(String.format("%s/live.csv",workingDirectory));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void selectPhysicalInterface(){
|
||||||
|
String pn = (String)JObjectSelector.execute(PulsCounter.getDeviceConnection().getPhysicalInterfaceNames());
|
||||||
|
PulsCounter.getDeviceConnection().setPhysicalInterfaceName(pn);
|
||||||
|
tfPhysicalInterface.setText(pn);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
package org.hwo.pulscounter.ui;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.FlowLayout;
|
||||||
|
|
||||||
|
import javax.swing.DefaultListModel;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JDialog;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
|
||||||
|
import javax.swing.JList;
|
||||||
|
|
||||||
|
import org.hwo.beacon.Beacon;
|
||||||
|
import org.hwo.beacon.Beacon.BeaconSender;
|
||||||
|
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.Dialog.ModalExclusionType;
|
||||||
|
import java.awt.Dialog.ModalityType;
|
||||||
|
|
||||||
|
public class NetworkSelectorDialog extends JDialog {
|
||||||
|
|
||||||
|
private final JPanel contentPanel = new JPanel();
|
||||||
|
private BeaconSender selectedSender;
|
||||||
|
|
||||||
|
private Beacon beacon;
|
||||||
|
private JList lSenders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the dialog.
|
||||||
|
*/
|
||||||
|
public NetworkSelectorDialog(Beacon beacon) {
|
||||||
|
setTitle("Netzwerk Anschluss w\u00E4hlen...");
|
||||||
|
setModalityType(ModalityType.APPLICATION_MODAL);
|
||||||
|
setModalExclusionType(ModalExclusionType.APPLICATION_EXCLUDE);
|
||||||
|
setModal(true);
|
||||||
|
setBounds(100, 100, 450, 300);
|
||||||
|
getContentPane().setLayout(new BorderLayout());
|
||||||
|
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
|
getContentPane().add(contentPanel, BorderLayout.CENTER);
|
||||||
|
GridBagLayout gbl_contentPanel = new GridBagLayout();
|
||||||
|
gbl_contentPanel.columnWidths = new int[]{0, 0};
|
||||||
|
gbl_contentPanel.rowHeights = new int[]{0, 0};
|
||||||
|
gbl_contentPanel.columnWeights = new double[]{1.0, Double.MIN_VALUE};
|
||||||
|
gbl_contentPanel.rowWeights = new double[]{1.0, Double.MIN_VALUE};
|
||||||
|
contentPanel.setLayout(gbl_contentPanel);
|
||||||
|
{
|
||||||
|
lSenders = new JList();
|
||||||
|
GridBagConstraints gbc_lSenders = new GridBagConstraints();
|
||||||
|
gbc_lSenders.fill = GridBagConstraints.BOTH;
|
||||||
|
gbc_lSenders.gridx = 0;
|
||||||
|
gbc_lSenders.gridy = 0;
|
||||||
|
contentPanel.add(lSenders, gbc_lSenders);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
JPanel buttonPane = new JPanel();
|
||||||
|
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
|
||||||
|
getContentPane().add(buttonPane, BorderLayout.SOUTH);
|
||||||
|
{
|
||||||
|
JButton okButton = new JButton("OK");
|
||||||
|
okButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (lSenders.getSelectedValue() != null) {
|
||||||
|
selectedSender = (BeaconSender)lSenders.getSelectedValue();
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
okButton.setActionCommand("OK");
|
||||||
|
buttonPane.add(okButton);
|
||||||
|
getRootPane().setDefaultButton(okButton);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
JButton cancelButton = new JButton("Cancel");
|
||||||
|
cancelButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
selectedSender = null;
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cancelButton.setActionCommand("Cancel");
|
||||||
|
buttonPane.add(cancelButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.beacon = beacon;
|
||||||
|
|
||||||
|
this.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialize()
|
||||||
|
{
|
||||||
|
DefaultListModel lm = new DefaultListModel();
|
||||||
|
|
||||||
|
for (BeaconSender sender: this.beacon.getBeaconSenders().values())
|
||||||
|
{
|
||||||
|
lm.addElement(sender);
|
||||||
|
}
|
||||||
|
lSenders.setModel(lm);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BeaconSender show(Beacon beacon)
|
||||||
|
{
|
||||||
|
NetworkSelectorDialog dlg = new NetworkSelectorDialog(beacon);
|
||||||
|
dlg.setVisible(true);
|
||||||
|
return dlg.getSelectedSender();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeaconSender getSelectedSender() {
|
||||||
|
return selectedSender;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue