cleaned up the code

changed GUI layout to respect current desktop layout for SDI capture
added temperature offset controls
This commit is contained in:
Lucas Pleß 2014-11-21 03:50:27 +01:00
parent 9c0c7a0fdc
commit ac890076b4
18 changed files with 383 additions and 348 deletions

View File

@ -131,6 +131,9 @@
<item class="de.psychose.ActorDisplay" icon="" removable="true" auto-create-binding="false" can-attach-label="false"> <item class="de.psychose.ActorDisplay" icon="" removable="true" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="0" /> <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="0" />
</item> </item>
<item class="de.psychose.TemperatureControl" icon="" removable="true" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="0" />
</item>
</group> </group>
</component> </component>
</project> </project>

View File

@ -1,5 +1,10 @@
you need jdk 1.7 or newer and maven2 installed
compile with compile with
mvn clean compile ideauidesigner:javac2 assembly:single mvn clean compile ideauidesigner:javac2 assembly:single
run with
java -jar psychose-X.X-jar-with-dependencies.jar

View File

@ -6,34 +6,63 @@ package de.psychose;
*/ */
public class ActorData { public class ActorData {
private String actor = "";
private String caption = "";
private PulseData pulseData = new PulseData(); private PulseData pulseData = new PulseData();
private int airflow; private int airflow;
private int ekg; private int ekg;
private int emg; private int emg;
private float temperature; private double temperature;
private double temperatureOffset;
private boolean tommyHeartbeat; private boolean tommyHeartbeat;
private long timestampPulse = 0; private long timestampPulse = 0;
private long timestampTommyPulse = 0; private long timestampHeartbeat = 0;
private long timestampOxygen = 0;
private long timestampTommyHeartbeat = 0;
private long timestampEkg = 0; private long timestampEkg = 0;
private long timestampEmg = 0; private long timestampEmg = 0;
private long timestampTemperature = 0; private long timestampTemperature = 0;
private long timestampBreath = 0; private long timestampBreath = 0;
// TODO: hier die timestamps setzen wann letztes mal geändert, public ActorData(String actor, String caption) {
// dann kann ich in ActorDisplay im Timer einfach prüfen ob differenz > timeout, dann rot setzen this.actor = actor;
this.caption = caption;
public void setTimestampPulse() {
this.timestampPulse = System.currentTimeMillis();
}
public PulseData getPulseData() {
return pulseData;
} }
public void setPulseData(PulseData pulseData) { public String getActor() {
this.pulseData = pulseData; return actor;
this.timestampPulse = System.currentTimeMillis(); }
public String getCaption() {
return caption;
}
public int getOxygen() {
return pulseData.getOxygen();
}
public void setOxygen(int oxygen) {
timestampOxygen = System.currentTimeMillis();
pulseData.setOxygen(oxygen);
}
public boolean getHeartbeat() {
return pulseData.getHeartbeat();
}
public void setHeartbeat(boolean heartbeat) {
timestampHeartbeat = System.currentTimeMillis();
pulseData.setHeartbeat(heartbeat);
}
public int getPulse() {
return pulseData.getPulse();
}
public void setPulse(int pulse) {
timestampPulse = System.currentTimeMillis();
pulseData.setPulse(pulse);
} }
public int getAirflow() { public int getAirflow() {
@ -63,11 +92,11 @@ public class ActorData {
this.timestampEmg = System.currentTimeMillis(); this.timestampEmg = System.currentTimeMillis();
} }
public float getTemperature() { public double getTemperature() {
return temperature; return temperature;
} }
public void setTemperature(float temperature) { public void setTemperature(double temperature) {
this.temperature = temperature; this.temperature = temperature;
this.timestampTemperature = System.currentTimeMillis(); this.timestampTemperature = System.currentTimeMillis();
} }
@ -78,7 +107,15 @@ public class ActorData {
public void setTommyHeartbeat(boolean tommyHeartbeat) { public void setTommyHeartbeat(boolean tommyHeartbeat) {
this.tommyHeartbeat = tommyHeartbeat; this.tommyHeartbeat = tommyHeartbeat;
this.timestampTommyPulse = System.currentTimeMillis(); this.timestampTommyHeartbeat = System.currentTimeMillis();
}
public double getTemperatureOffset() {
return temperatureOffset;
}
public void setTemperatureOffset(double temperatureOffset) {
this.temperatureOffset = temperatureOffset;
} }
public long getTimestampPulse() { public long getTimestampPulse() {
@ -100,4 +137,26 @@ public class ActorData {
public long getTimestampBreath() { public long getTimestampBreath() {
return timestampBreath; return timestampBreath;
} }
@Override
public String toString() {
return "ActorData{" +
"actor='" + actor + '\'' +
", caption='" + caption + '\'' +
", airflow=" + airflow +
", ekg=" + ekg +
", emg=" + emg +
", temperature=" + temperature +
", temperatureOffset=" + temperatureOffset +
", tommyHeartbeat=" + tommyHeartbeat +
", timestampPulse=" + timestampPulse +
", timestampHeartbeat=" + timestampHeartbeat +
", timestampOxygen=" + timestampOxygen +
", timestampTommyHeartbeat=" + timestampTommyHeartbeat +
", timestampEkg=" + timestampEkg +
", timestampEmg=" + timestampEmg +
", timestampTemperature=" + timestampTemperature +
", timestampBreath=" + timestampBreath +
'}';
}
} }

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.psychose.ActorDisplay"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.psychose.ActorDisplay">
<grid id="27dc6" binding="actorPanel" layout-manager="GridLayoutManager" row-count="9" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="9" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="4" left="6" bottom="4" right="6"/> <margin top="4" left="6" bottom="4" right="6"/>
<constraints> <constraints>
<xy x="20" y="20" width="316" height="302"/> <xy x="20" y="20" width="316" height="302"/>

View File

@ -2,7 +2,6 @@ package de.psychose;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent;
import java.text.DecimalFormat; import java.text.DecimalFormat;
/** /**
@ -10,11 +9,7 @@ import java.text.DecimalFormat;
* @date: 14.04.14 21:44 * @date: 14.04.14 21:44
*/ */
public class ActorDisplay { public class ActorDisplay {
private final Timer timer; private static final long TIMEOUT_MILLISECONDS = 2000;
private final static Color onColor = Color.WHITE;
private final static Color offColor = Color.RED;
private final static String offText = "no data";
private JLabel lblCaption; private JLabel lblCaption;
private JLabel lblHeartbeat; private JLabel lblHeartbeat;
private JLabel lblPulse; private JLabel lblPulse;
@ -23,98 +18,49 @@ public class ActorDisplay {
private JLabel lblEmg; private JLabel lblEmg;
private JLabel lblTemperature; private JLabel lblTemperature;
private JLabel lblBreath; private JLabel lblBreath;
private JPanel actorPanel; private JPanel mainPanel;
private ActorData actorData; private ActorData actorData;
private boolean showErrors = false; private boolean showErrors = false;
private DecimalFormat df = new DecimalFormat("#.0"); private DecimalFormat df = new DecimalFormat("#.0");
//TODO: die einzelnen Setter wegmachen, dafür eine setData() bauen die die daten en bloc nimmt
// die darin enthaltenen timestamps dann für rotfärbung nehmen
public void setActorData(ActorData actorData) {
this.actorData = actorData;
}
public void setCaption(String caption) {
lblCaption.setText(caption);
}
public void update() { public void update() {
lblBreath.setText(String.valueOf(actorData.getAirflow())); if (actorData == null) {
return;
lblTemperature.setText(df.format(actorData.getTemperature()));
lblEkg.setText(String.valueOf(actorData.getEkg()));
lblPulse.setText(actorData.getPulseData().getHeartbeat() == 0 ? "systole" : "diastole");
lblEmg.setText(String.valueOf(actorData.getEmg()));
lblOxy.setText(String.valueOf(actorData.getPulseData().getOxygen()));
lblHeartbeat.setText(String.valueOf(actorData.getPulseData().getPulse()));
} }
public ActorDisplay() { lblBreath.setText(String.valueOf(actorData.getAirflow()));
this.timer = new Timer(100, new AbstractAction() { lblTemperature.setText(df.format(actorData.getTemperature() + actorData.getTemperatureOffset()));
@Override lblEkg.setText(String.valueOf(actorData.getEkg()));
public void actionPerformed(ActionEvent e) { lblPulse.setText(actorData.getHeartbeat() ? "systole" : "diastole");
lblEmg.setText(String.valueOf(actorData.getEmg()));
if (actorData == null) lblOxy.setText(String.valueOf(actorData.getOxygen()));
return; lblHeartbeat.setText(String.valueOf(actorData.getPulse()));
update();
if (showErrors) { if (showErrors) {
checkTimeout(lblTemperature, actorData.getTimestampTemperature());
long timeout = System.currentTimeMillis() - 1000; checkTimeout(lblPulse, actorData.getTimestampPulse());
checkTimeout(lblOxy, actorData.getTimestampPulse());
if (actorData.getTimestampTemperature() < timeout) { checkTimeout(lblHeartbeat, actorData.getTimestampPulse());
lblTemperature.setForeground(offColor); checkTimeout(lblEkg, actorData.getTimestampEkg());
lblTemperature.setText(offText); checkTimeout(lblEmg, actorData.getTimestampEmg());
} else { checkTimeout(lblBreath, actorData.getTimestampBreath());
lblTemperature.setForeground(onColor);
}
if (actorData.getTimestampPulse() < timeout) {
lblPulse.setForeground(offColor);
lblPulse.setText(offText);
lblOxy.setForeground(offColor);
lblOxy.setText(offText);
lblHeartbeat.setForeground(offColor);
lblHeartbeat.setText(offText);
} else {
lblPulse.setForeground(onColor);
lblOxy.setForeground(onColor);
lblHeartbeat.setForeground(onColor);
}
if (actorData.getTimestampEkg() < timeout) {
lblEkg.setForeground(offColor);
lblEkg.setText(offText);
} else {
lblEkg.setForeground(onColor);
}
if (actorData.getTimestampEmg() < timeout) {
lblEmg.setForeground(offColor);
lblEmg.setText(offText);
} else {
lblEmg.setForeground(onColor);
}
if (actorData.getTimestampBreath() < timeout) {
lblBreath.setForeground(offColor);
lblBreath.setText(offText);
} else {
lblBreath.setForeground(onColor);
} }
} }
}
});
timer.setRepeats(true); public void init(ActorData actorData, final boolean showErrors) {
timer.start(); this.actorData = actorData;
} lblCaption.setText(actorData.getCaption());
public void setShowErrors(boolean showErrors) {
this.showErrors = showErrors; this.showErrors = showErrors;
} }
private void checkTimeout(final JLabel label, final long time) {
if (time < System.currentTimeMillis() - TIMEOUT_MILLISECONDS) {
label.setText("no data");
label.setForeground(Color.red);
} else {
label.setForeground(Color.white);
}
}
} }

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.psychose.ActorHeart"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.psychose.ActorHeart">
<grid id="27dc6" binding="heartPanel" layout-manager="BorderLayout" hgap="0" vgap="0"> <grid id="27dc6" binding="mainPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints> <constraints>
<xy x="20" y="20" width="789" height="299"/> <xy x="20" y="20" width="789" height="299"/>
</constraints> </constraints>

View File

@ -3,7 +3,6 @@ package de.psychose;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
@ -12,33 +11,21 @@ import java.io.IOException;
* @date: 15.11.14 21:36 * @date: 15.11.14 21:36
*/ */
public class ActorHeart { public class ActorHeart {
private JPanel heartPanel; private JPanel mainPanel;
private ActorData actorData1; private ActorData[] actorDatas;
private ActorData actorData2;
private ActorData actorData3;
private ImagePanel imagePanel; private ImagePanel imagePanel;
private Timer timer;
public ActorHeart() { public ActorHeart() {
imagePanel = new ImagePanel("/de/psychose/heart1_klein_inv.jpg", "/de/psychose/heart2_klein_inv.jpg"); imagePanel = new ImagePanel("/de/psychose/heart1_klein_inv.jpg", "/de/psychose/heart2_klein_inv.jpg");
heartPanel.add(imagePanel); mainPanel.add(imagePanel);
}
timer = new Timer(100, new AbstractAction() { public void update() {
@Override
public void actionPerformed(ActionEvent e) {
if(actorData1 != null && actorData2 != null && actorData3 != null) {
imagePanel.repaint(); imagePanel.repaint();
} }
}
});
timer.setRepeats(true);
timer.start();
}
public void setActorData(final ActorData actorData1, final ActorData actorData2, final ActorData actorData3) { public void setActorDatas(final ActorData[] actorDatas) {
this.actorData1 = actorData1; this.actorDatas = actorDatas;
this.actorData2 = actorData2;
this.actorData3 = actorData3;
} }
private class ImagePanel extends JPanel { private class ImagePanel extends JPanel {
@ -57,10 +44,13 @@ public class ActorHeart {
@Override @Override
protected void paintComponent(Graphics g) { protected void paintComponent(Graphics g) {
super.paintComponent(g); super.paintComponent(g);
if(actorData1 != null && actorData2 != null && actorData3 != null) {
g.drawImage(ActorHeart.this.actorData1.getTommyHeartbeat() ? image1 : image2, 0, 0, null, null); if (actorDatas != null) {
g.drawImage(ActorHeart.this.actorData2.getTommyHeartbeat() ? image1 : image2, 263, 0, null, null); for (int i = 0; i < actorDatas.length; i++) {
g.drawImage(ActorHeart.this.actorData3.getTommyHeartbeat() ? image1 : image2, 526, 0, null, null); if (actorDatas[i] != null) {
g.drawImage(actorDatas[i].getTommyHeartbeat() ? image1 : image2, 263 * i, 0, null, null);
}
}
} }
} }
} }

View File

@ -45,21 +45,21 @@ public class ChaOSCclient {
return changeChaoscSubscription(true); return changeChaoscSubscription(true);
} }
public void sendPulse(String actor, int heartbeat, int pulse, int oxygen) { public void sendMessage(final String address, Object... args) {
try { try {
OSCMessage subscribeMessage = new OSCMessage("/" + actor + "/heartbeat"); OSCMessage subscribeMessage = new OSCMessage(address);
subscribeMessage.addArgument(heartbeat);
subscribeMessage.addArgument(pulse); for(Object param: args) {
subscribeMessage.addArgument(oxygen); subscribeMessage.addArgument(param);
}
portOut.send(subscribeMessage); portOut.send(subscribeMessage);
} catch (IOException e) { } catch (IOException e) {
System.out.println("could not send pulse OSC Message"); System.out.println("could not send pulse OSC Message");
e.printStackTrace(); e.printStackTrace();
} }
}
}
private boolean changeChaoscSubscription(boolean subscribe) { private boolean changeChaoscSubscription(boolean subscribe) {
try { try {

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.psychose.ControlForm"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.psychose.ControlForm">
<grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <grid id="27dc6" binding="rootPanel" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="10" left="10" bottom="10" right="10"/> <margin top="10" left="10" bottom="10" right="10"/>
<constraints> <constraints>
<xy x="20" y="20" width="704" height="400"/> <xy x="20" y="20" width="704" height="400"/>
@ -25,15 +25,30 @@
</nested-form> </nested-form>
<nested-form id="c060f" form-file="de/psychose/ActorDisplay.form" binding="actor1"> <nested-form id="c060f" form-file="de/psychose/ActorDisplay.form" binding="actor1">
<constraints> <constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/> <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints> </constraints>
</nested-form> </nested-form>
<nested-form id="abfde" form-file="de/psychose/ActorDisplay.form" binding="actor2"> <nested-form id="abfde" form-file="de/psychose/ActorDisplay.form" binding="actor2">
<constraints> <constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/> <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints> </constraints>
</nested-form> </nested-form>
<nested-form id="97d21" form-file="de/psychose/ActorDisplay.form" binding="actor3"> <nested-form id="97d21" form-file="de/psychose/ActorDisplay.form" binding="actor3">
<constraints>
<grid row="2" column="2" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
</nested-form>
<nested-form id="f7ec5" form-file="de/psychose/TemperatureControl.form" binding="temp1">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
</nested-form>
<nested-form id="bcc93" form-file="de/psychose/TemperatureControl.form" binding="temp2">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
</nested-form>
<nested-form id="3726f" form-file="de/psychose/TemperatureControl.form" binding="temp3">
<constraints> <constraints>
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/> <grid row="1" column="2" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints> </constraints>

View File

@ -8,47 +8,61 @@ import java.util.Observer;
* @author: lucas * @author: lucas
* @date: 15.11.14 22:23 * @date: 15.11.14 22:23
*/ */
public class ControlForm { public class ControlForm extends JFrame {
private PulseControl pulse1; private PulseControl pulse1;
private PulseControl pulse2; private PulseControl pulse2;
private PulseControl pulse3; private PulseControl pulse3;
private JPanel mainPanel; private JPanel rootPanel;
private ActorDisplay actor1; private ActorDisplay actor1;
private ActorDisplay actor2; private ActorDisplay actor2;
private ActorDisplay actor3; private ActorDisplay actor3;
private TemperatureControl temp1;
private TemperatureControl temp2;
private TemperatureControl temp3;
private final ChaOSCclient osCclient; private final ChaOSCclient osCclient;
public JPanel getMainPanel() { public ControlForm(ChaOSCclient chaOSCclient, final ActorData[] actorData) {
return mainPanel; super("HD Control");
}
public ControlForm(ChaOSCclient chaOSCclient, final ActorData actorData1, final ActorData actorData2, final ActorData actorData3) {
this.osCclient = chaOSCclient; this.osCclient = chaOSCclient;
addActor("merle", pulse1, actor1, actorData1); setContentPane(rootPanel);
addActor("uwe", pulse2, actor2, actorData2); setResizable(false);
addActor("bjoern", pulse3, actor3, actorData3); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
actor1.setShowErrors(true); addActor(pulse1, actor1, temp1, actorData[0]);
actor2.setShowErrors(true); addActor(pulse2, actor2, temp2, actorData[1]);
actor3.setShowErrors(true); addActor(pulse3, actor3, temp3, actorData[2]);
pack();
setVisible(true);
} }
private void addActor(final String actor, PulseControl pulse, ActorDisplay display, ActorData actorData) { private void addActor(final PulseControl pulse, final ActorDisplay display, final TemperatureControl temp, final ActorData actorData) {
pulse.addObserver(new Observer() { pulse.addObserver(new Observer() {
@Override @Override
public void update(Observable o, Object arg) { public void update(Observable o, Object arg) {
if(arg instanceof PulseData) { if (arg instanceof PulseData) {
final PulseData data = (PulseData)arg; final PulseData data = (PulseData) arg;
osCclient.sendPulse(actor, data.getHeartbeat(), data.getPulse(), data.getOxygen()); osCclient.sendMessage("/" + actorData.getActor().toLowerCase() + "/heartbeat", data.getHeartbeat(),
data.getPulse(), data.getOxygen());
// TODO: delete this line, bc tommy will send the real events
osCclient.sendMessage("/" + actorData.getActor().toLowerCase() + "/tommyheartbeat");
} }
} }
}); });
display.setCaption(actor);
display.setActorData(actorData); temp.addObserver(new Observer() {
@Override
public void update(Observable o, Object arg) {
if (arg instanceof Double) {
actorData.setTemperatureOffset((double)arg);
}
}
});
display.init(actorData, true);
} }
} }

View File

@ -4,8 +4,6 @@ import com.illposed.osc.OSCListener;
import com.illposed.osc.OSCMessage; import com.illposed.osc.OSCMessage;
import javax.swing.*; import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.SocketException; import java.net.SocketException;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Date; import java.util.Date;
@ -15,26 +13,17 @@ import java.util.Date;
* @date: 25.04.14 00:23 * @date: 25.04.14 00:23
*/ */
public class Main { public class Main {
private ChaOSCclient chaOSCclient;
private ControlForm controlForm;
private MainForm mainForm;
private int totalMessageCount = 0;
private int messagesTempCounter = 0;
private long totalTraffic = 0;
private long lastTraffic = 0;
private final ActorData actorData1 = new ActorData();
private final ActorData actorData2 = new ActorData();
private final ActorData actorData3 = new ActorData();
public static void main(String[] args) { public static void main(String[] args) {
new Main(); new Main();
} }
public Main() { public Main() {
final ActorData[] actorDatas = new ActorData[3];
actorDatas[0] = new ActorData("merle", "Körper 1");
actorDatas[1] = new ActorData("uwe", "Körper 2");
actorDatas[2] = new ActorData("bjoern", "Körper 3");
try { try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
} catch (Exception e) { } catch (Exception e) {
@ -42,151 +31,99 @@ public class Main {
} }
try { try {
this.chaOSCclient = new ChaOSCclient("chaosc", 7110); final ChaOSCclient chaOSCclient = new ChaOSCclient("chaosc", 7110);
this.controlForm = new ControlForm(chaOSCclient, actorData1, actorData2, actorData3);
final JFrame cframe = new JFrame("HD Control"); for(int i = 0; i < actorDatas.length; i++) {
cframe.setContentPane(controlForm.getMainPanel()); addActorOSCListeners(chaOSCclient, actorDatas[i]);
cframe.setResizable(false);
cframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
cframe.pack();
this.mainForm = new MainForm(actorData1, actorData2, actorData3);
final JFrame frame = new JFrame("HD Main");
frame.setContentPane(mainForm.getMainPanel());
frame.setResizable(false);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(true);
frame.pack();
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
chaOSCclient.stopReceiver();
// snmp.stopRunning();
super.windowClosing(e);
} }
});
addActor("merle", actorData1);
addActor("uwe", actorData2);
addActor("bjoern", actorData3);
cframe.setVisible(true);
frame.setVisible(true);
chaOSCclient.startReceiver(); chaOSCclient.startReceiver();
new ControlForm(chaOSCclient, actorDatas);
new MainForm(actorDatas);
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
chaOSCclient.stopReceiver();
}
}));
} catch (UnknownHostException | SocketException e) { } catch (UnknownHostException | SocketException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
private void addActor(final String actor, final ActorData actorData) { private static void addActorOSCListeners(final ChaOSCclient chaOSCclient, final ActorData actorData) {
chaOSCclient.addListener("/" + actor.toLowerCase() + "/heartbeat", new OSCListener() { chaOSCclient.addListener("/" + actorData.getActor().toLowerCase() + "/heartbeat", new OSCListener() {
@Override @Override
public void acceptMessage(Date time, OSCMessage message) { public void acceptMessage(Date time, OSCMessage message) {
if (message.getArguments().length == 3) { if (message.getArguments().length == 3) {
totalMessageCount++;
if (message.getArguments()[1] instanceof Integer) {
int pulse = (int) (message.getArguments()[1]);
if (pulse > 60) { // try to skip the invalid pulserate from device
// set the heartrate
actorData.getPulseData().setPulse((int) (message.getArguments()[1]));
// set the beat ( 0 or 1 ) // set the beat ( 0 or 1 )
if (message.getArguments()[0] instanceof Integer) { if (message.getArguments()[0] instanceof Integer) {
actorData.getPulseData().setHeartbeat((int) (message.getArguments()[0])); actorData.setHeartbeat( (int)(message.getArguments()[0]) == 1);
} }
//TODO: remove this, its for testing without tommy only // set the heartrate
actorData.setTommyHeartbeat(((int) message.getArguments()[0]) == 1); if (message.getArguments()[1] instanceof Integer) {
final int pulse = (int) (message.getArguments()[1]);
if (pulse > 60) { // try to skip the invalid pulse rate from device
actorData.setPulse(pulse);
}
}
// set the oxy level // set the oxy level
if (message.getArguments()[2] instanceof Integer) { if (message.getArguments()[2] instanceof Integer) {
actorData.getPulseData().setOxygen((int) (message.getArguments()[2])); actorData.setOxygen((int) (message.getArguments()[2]));
}
actorData.setTimestampPulse();
}
} }
} }
} }
}); });
chaOSCclient.addListener("/" + actor.toLowerCase() + "/ekg", new OSCListener() { chaOSCclient.addListener("/" + actorData.getActor().toLowerCase() + "/ekg", new OSCListener() {
@Override @Override
public void acceptMessage(Date time, OSCMessage message) { public void acceptMessage(Date time, OSCMessage message) {
if (message.getArguments().length == 1) { if (message.getArguments().length == 1 && message.getArguments()[0] instanceof Integer) {
totalMessageCount++;
if (message.getArguments()[0] instanceof Integer) {
actorData.setEkg((int) (message.getArguments()[0])); actorData.setEkg((int) (message.getArguments()[0]));
} }
} }
}
}); });
chaOSCclient.addListener("/" + actor.toLowerCase() + "/emg", new OSCListener() { chaOSCclient.addListener("/" + actorData.getActor().toLowerCase() + "/emg", new OSCListener() {
@Override @Override
public void acceptMessage(Date time, OSCMessage message) { public void acceptMessage(Date time, OSCMessage message) {
if (message.getArguments().length == 1) { if (message.getArguments().length == 1 && message.getArguments()[0] instanceof Integer) {
totalMessageCount++;
if (message.getArguments()[0] instanceof Integer) {
actorData.setEmg((int) (message.getArguments()[0])); actorData.setEmg((int) (message.getArguments()[0]));
} }
} }
}
}); });
chaOSCclient.addListener("/" + actor.toLowerCase() + "/temperature", new OSCListener() { chaOSCclient.addListener("/" + actorData.getActor().toLowerCase() + "/temperature", new OSCListener() {
@Override @Override
public void acceptMessage(Date time, OSCMessage message) { public void acceptMessage(Date time, OSCMessage message) {
if (message.getArguments().length == 1) { if (message.getArguments().length == 1 && message.getArguments()[0] instanceof Float) {
totalMessageCount++;
if (message.getArguments()[0] instanceof Float) {
actorData.setTemperature((float) (message.getArguments()[0])); actorData.setTemperature((float) (message.getArguments()[0]));
} }
} }
}
}); });
chaOSCclient.addListener("/" + actor.toLowerCase() + "/airFlow", new OSCListener() { chaOSCclient.addListener("/" + actorData.getActor().toLowerCase() + "/airFlow", new OSCListener() {
@Override @Override
public void acceptMessage(Date time, OSCMessage message) { public void acceptMessage(Date time, OSCMessage message) {
if (message.getArguments().length == 1) { if (message.getArguments().length == 1 && message.getArguments()[0] instanceof Integer) {
totalMessageCount++;
if (message.getArguments()[0] instanceof Integer) {
actorData.setAirflow((int) (message.getArguments()[0])); actorData.setAirflow((int) (message.getArguments()[0]));
} }
} }
}
}); });
chaOSCclient.addListener("/" + actor.toLowerCase() + "/tommypuls", new OSCListener() { //TODO: evtl muss das oben hier noch anders
chaOSCclient.addListener("/" + actorData.getActor().toLowerCase() + "/tommyheartbeat", new OSCListener() {
@Override @Override
public void acceptMessage(Date time, OSCMessage message) { public void acceptMessage(Date time, OSCMessage message) {
if (message.getArguments().length == 1) { actorData.setTommyHeartbeat(!actorData.getTommyHeartbeat());
totalMessageCount++;
if (message.getArguments()[0] instanceof Integer) {
actorData.setTommyHeartbeat((boolean) (message.getArguments()[0]));
}
//TODO: evtl muss das oben hier noch anders
}
} }
}); });
} }
} }

View File

@ -1,16 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.psychose.MainForm"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.psychose.MainForm">
<grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="2" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/> <margin top="0" left="0" bottom="0" right="0"/>
<constraints> <constraints>
<xy x="0" y="0" width="810" height="670"/> <xy x="0" y="0" width="930" height="560"/>
</constraints> </constraints>
<properties> <properties>
<background color="-16777216"/> <background color="-16777216"/>
<foreground color="-1"/> <foreground color="-1"/>
<maximumSize width="1000" height="1000"/> <maximumSize width="1000" height="1000"/>
<minimumSize width="810" height="670"/> <minimumSize width="930" height="560"/>
<preferredSize width="810" height="670"/> <preferredSize width="950" height="570"/>
</properties> </properties>
<border type="none"/> <border type="none"/>
<children> <children>
@ -19,9 +19,9 @@
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/> <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints> </constraints>
</nested-form> </nested-form>
<nested-form id="e6dc4" form-file="de/psychose/ActorHeart.form" binding="heart1"> <nested-form id="e6dc4" form-file="de/psychose/ActorHeart.form" binding="heart">
<constraints> <constraints>
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/> <grid row="1" column="0" row-span="1" col-span="4" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints> </constraints>
</nested-form> </nested-form>
<nested-form id="18353" form-file="de/psychose/ActorDisplay.form" binding="actor2"> <nested-form id="18353" form-file="de/psychose/ActorDisplay.form" binding="actor2">
@ -36,17 +36,22 @@
</nested-form> </nested-form>
<component id="fe39c" class="javax.swing.JLabel" binding="breath"> <component id="fe39c" class="javax.swing.JLabel" binding="breath">
<constraints> <constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/> <grid row="0" column="3" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints> </constraints>
<properties> <properties>
<enabled value="true"/> <enabled value="true"/>
<font name="Serif" size="72"/> <font size="70"/>
<foreground color="-1"/> <foreground color="-1"/>
<horizontalAlignment value="0"/> <horizontalAlignment value="0"/>
<horizontalTextPosition value="0"/> <horizontalTextPosition value="0"/>
<text value="123"/> <text value="999"/>
</properties> </properties>
</component> </component>
<hspacer id="10ad8">
<constraints>
<grid row="1" column="4" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
</children> </children>
</grid> </grid>
</form> </form>

View File

@ -2,44 +2,48 @@ package de.psychose;
import javax.swing.*; import javax.swing.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.text.DecimalFormat;
/** /**
* @author: lucas * @author: lucas
* @date: 14.04.14 21:43 * @date: 14.04.14 21:43
*/ */
public class MainForm { public class MainForm extends JFrame {
private JPanel mainPanel; private JPanel mainPanel;
private ActorHeart heart1; private ActorHeart heart;
private ActorDisplay actor1; private ActorDisplay actor1;
private ActorDisplay actor2; private ActorDisplay actor2;
private ActorDisplay actor3; private ActorDisplay actor3;
private JLabel breath; private JLabel breath;
private final DecimalFormat df = new DecimalFormat("#.0");
public JPanel getMainPanel() { public MainForm(final ActorData[] actorDatas) {
return mainPanel; super("HD Main");
} setContentPane(mainPanel);
setResizable(false);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setUndecorated(true);
public MainForm(final ActorData actorData1, final ActorData actorData2, final ActorData actorData3) { actor1.init(actorDatas[0], false);
actor2.init(actorDatas[1], false);
actor3.init(actorDatas[2], false);
heart.setActorDatas(actorDatas);
actor1.setCaption("Körper 1"); // this is now our main timer to update all and everything gui related
actor2.setCaption("Körper 2"); final Timer timer = new Timer(50, new AbstractAction() {
actor3.setCaption("Körper 3");
actor1.setActorData(actorData1);
actor2.setActorData(actorData2);
actor3.setActorData(actorData3);
heart1.setActorData(actorData1, actorData2, actorData3);
final Timer timer = new Timer(100, new AbstractAction() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
breath.setText(String.valueOf(actorData1.getAirflow())); // update the breath display
breath.setText(String.valueOf(actorDatas[0].getAirflow()));
actor1.update();
actor2.update();
actor3.update();
heart.update();
} }
}); });
timer.setRepeats(true);
timer.start(); timer.start();
pack();
setVisible(true);
} }

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.psychose.PulseControl"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.psychose.PulseControl">
<grid id="27dc6" binding="pulsePanel" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/> <margin top="0" left="0" bottom="0" right="0"/>
<constraints> <constraints>
<xy x="20" y="20" width="261" height="38"/> <xy x="20" y="20" width="179" height="30"/>
</constraints> </constraints>
<properties> <properties>
<foreground color="-1"/> <foreground color="-1"/>
@ -12,29 +12,34 @@
<children> <children>
<component id="a9565" class="javax.swing.JCheckBox" binding="enableCheckBox" default-binding="true"> <component id="a9565" class="javax.swing.JCheckBox" binding="enableCheckBox" default-binding="true">
<constraints> <constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/> <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints> </constraints>
<properties> <properties>
<focusable value="false"/>
<selected value="false"/> <selected value="false"/>
<text value="Enable"/> <text value="Enable"/>
</properties> </properties>
</component> </component>
<component id="dadb" class="javax.swing.JSpinner" binding="spinner1" default-binding="true"> <component id="dadb" class="javax.swing.JSpinner" binding="spinner">
<constraints> <constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"> <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false">
<minimum-size width="50" height="-1"/> <minimum-size width="50" height="-1"/>
<preferred-size width="50" height="-1"/> <preferred-size width="50" height="-1"/>
</grid> </grid>
</constraints> </constraints>
<properties> <properties>
<background color="-16711423"/> <background color="-16711423"/>
<focusable value="false"/>
</properties> </properties>
</component> </component>
<hspacer id="dec01"> <component id="b9118" class="javax.swing.JLabel">
<constraints> <constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/> <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints> </constraints>
</hspacer> <properties>
<text value="Pulse"/>
</properties>
</component>
</children> </children>
</grid> </grid>
</form> </form>

View File

@ -14,58 +14,41 @@ import java.util.Random;
public class PulseControl extends Observable { public class PulseControl extends Observable {
private final int PULSE_WOBBLE_WIDTH = 10; private final int PULSE_WOBBLE_WIDTH = 10;
private JCheckBox enableCheckBox; private JCheckBox enableCheckBox;
private JSpinner spinner1; private JSpinner spinner;
private JPanel pulsePanel; private JPanel mainPanel;
private Timer timer; private final Timer timer;
private Random random = new Random(); private final Random random = new Random();
private int heartbeat = 0; private boolean heartbeat = false;
public PulseControl() { public PulseControl() {
enableCheckBox.setFocusable(false); spinner.setValue(110);
spinner1.setFocusable(false);
spinner1.setValue(110);
timer = new Timer(100, new AbstractAction() { timer = new Timer(500, new AbstractAction() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
heartbeat = (heartbeat+1) % 2; heartbeat = !heartbeat;
final int pulseWobbleCenter = (int)spinner1.getValue(); int pulse = (int) spinner.getValue() - PULSE_WOBBLE_WIDTH / 2 + random.nextInt(PULSE_WOBBLE_WIDTH);
int pulse = pulseWobbleCenter - PULSE_WOBBLE_WIDTH / 2 + random.nextInt(PULSE_WOBBLE_WIDTH);
if(pulse < 60) pulse = 60; if(pulse < 60) pulse = 60;
if(pulse > 230) pulse = 230; if(pulse > 230) pulse = 230;
final PulseData data = new PulseData(heartbeat, pulse, 95 + random.nextInt(4));
setChanged(); setChanged();
notifyObservers(data); notifyObservers(new PulseData(heartbeat, pulse, 95 + random.nextInt(4)));
final int delay = 60000 / pulse; timer.setDelay(60000 / pulse);
timer.setDelay(delay);
} }
}); });
timer.setRepeats(true);
enableCheckBox.addItemListener(new ItemListener() { enableCheckBox.addItemListener(new ItemListener() {
@Override @Override
public void itemStateChanged(ItemEvent e) { public void itemStateChanged(ItemEvent e) {
JCheckBox checkBox = (JCheckBox)e.getSource(); if (enableCheckBox.isSelected() && !timer.isRunning()) {
if(checkBox.isSelected()) {
if(!timer.isRunning()) {
System.out.println("starting pulsecontrol " + this);
timer.start(); timer.start();
} } else if (timer.isRunning()) {
} else {
if(timer.isRunning()) {
System.out.println("stopping pulsecontrol " + this);
timer.stop(); timer.stop();
} }
} }
}
}); });
} }
} }

View File

@ -6,7 +6,7 @@ package de.psychose;
*/ */
public class PulseData { public class PulseData {
private int heartbeat; private boolean heartbeat;
private int pulse; private int pulse;
private int oxygen; private int oxygen;
@ -14,17 +14,17 @@ public class PulseData {
} }
public PulseData(int heartbeat, int pulse, int oxygen) { public PulseData(boolean heartbeat, int pulse, int oxygen) {
this.heartbeat = heartbeat; this.heartbeat = heartbeat;
this.pulse = pulse; this.pulse = pulse;
this.oxygen = oxygen; this.oxygen = oxygen;
} }
public int getHeartbeat() { public boolean getHeartbeat() {
return heartbeat; return heartbeat;
} }
public void setHeartbeat(int heartbeat) { public void setHeartbeat(boolean heartbeat) {
this.heartbeat = heartbeat; this.heartbeat = heartbeat;
} }

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.psychose.TemperatureControl">
<grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="211" height="30"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="c685e" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Temp"/>
</properties>
</component>
<component id="f12ee" class="javax.swing.JCheckBox" binding="enableCheckBox" default-binding="true">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Enable"/>
</properties>
</component>
<component id="27ee3" class="javax.swing.JSpinner" binding="spinner1" default-binding="true">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
</children>
</grid>
</form>

View File

@ -0,0 +1,34 @@
package de.psychose;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.util.Observable;
/**
* @author: lucas
* @date: 20.11.14 23:11
*/
public class TemperatureControl extends Observable {
private static final double MIN_OFFSET = -20;
private static final double MAX_OFFSET = 20;
private static final double INCREMENT = 0.1;
private JCheckBox enableCheckBox;
private JSpinner spinner1;
private JPanel mainPanel;
public TemperatureControl() {
spinner1.setModel(new SpinnerNumberModel(0, MIN_OFFSET, MAX_OFFSET, INCREMENT));
final ChangeListener changeListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
setChanged();
notifyObservers(enableCheckBox.isSelected() ? spinner1.getValue() : 0.0);
}
};
spinner1.addChangeListener(changeListener);
enableCheckBox.addChangeListener(changeListener);
}
}