package ch.elexis.connect.sysmex;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import ch.elexis.connect.sysmex.packages.AbstractData;
import ch.elexis.connect.sysmex.packages.KX21Data;
import ch.elexis.connect.sysmex.packages.KX21NData;
import ch.elexis.connect.sysmex.packages.PackageException;
import ch.elexis.connect.sysmex.packages.PocH100iData;
import ch.elexis.connect.sysmex.ui.Preferences;
import ch.elexis.connect.sysmex.ui.WhichPatientDialog;
import ch.elexis.core.data.activator.CoreHub;
import ch.elexis.core.data.events.ElexisEventDispatcher;
import ch.elexis.core.ui.Hub;
import ch.elexis.core.ui.UiDesk;
import ch.elexis.core.ui.dialogs.KontaktSelektor;
import ch.elexis.core.ui.importer.div.rs232.AbstractConnection;
import ch.elexis.core.ui.importer.div.rs232.AbstractConnection.ComPortListener;
import ch.elexis.core.ui.util.Log;
import ch.elexis.core.ui.util.SWTHelper;
import ch.elexis.data.LabItem;
import ch.elexis.data.Labor;
import ch.elexis.data.Patient;
public class SysmexAction extends Action implements ComPortListener {
AbstractConnection _ctrl;
Labor _myLab;
Logger _rs232log;
Log _elexislog = Log.get("SysmexAction"); //$NON-NLS-1$
Thread msgDialogThread;
Patient selectedPatient;
boolean background = false;
private ShutdownThread shutdownThread = null;
// Declare filename to the log for test only!! for production must be null!
String simulate = null; // "C:\\tmp\\sysmex.log";
private class ShutdownThread extends Thread {
private boolean shouldShutdown = false;
public void startSequence(){
_elexislog.log("Start sysmex shutdown sequence", Log.DEBUGMSG);
shouldShutdown = true;
}
public void stopSequence(){
_elexislog.log("Stop sysmex shutdown sequence", Log.DEBUGMSG);
shouldShutdown = false;
}
public void run(){
try {
while (true) {
_elexislog.log("Waiting for sysmex shutdown..", Log.DEBUGMSG);
while (!shouldShutdown) {
// Wait till sequence started
}
_elexislog.log("Sysmex shutdown sequence started (5 sec)..", Log.DEBUGMSG);
Thread.sleep(5000);
_elexislog.log("Sysmex shutdown sequence over. Should shutdown sysmex="
+ shouldShutdown, Log.DEBUGMSG);
if (shouldShutdown) {
_elexislog.log("Shutdown", Log.INFOS); //$NON-NLS-1$
close();
}
}
} catch (Exception ex) {
// Do nothing
}
}
};
public SysmexAction(){
super(Messages.getString("SysmexAction.ButtonName"), AS_CHECK_BOX); //$NON-NLS-1$
setToolTipText(Messages.getString("SysmexAction.ToolTip")); //$NON-NLS-1$
setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(
"ch.elexis.connect.sysmex", "icons/sysmex.png")); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Serielle Verbindung wird initialisiert
*/
private void initConnection(){
if (_ctrl != null && _ctrl.isOpen()) {
_ctrl.close();
}
_ctrl =
new SysmexConnection(Messages.getString("SysmexAction.ConnectionName"), //$NON-NLS-1$
CoreHub.localCfg.get(Preferences.PORT,
Messages.getString("SysmexAction.DefaultPort")), CoreHub.localCfg.get( //$NON-NLS-1$
Preferences.PARAMS, Messages.getString("SysmexAction.DefaultParams")), //$NON-NLS-1$
this);
}
private void initPreferences(){
if (CoreHub.localCfg.get(Preferences.LOG, "n").equalsIgnoreCase("y")) { //$NON-NLS-1$ //$NON-NLS-2$
try {
_rs232log = new Logger(System.getProperty("user.home") + File.separator + "elexis" //$NON-NLS-1$ //$NON-NLS-2$
+ File.separator + "sysmex.log"); //$NON-NLS-1$
} catch (FileNotFoundException e) {
SWTHelper.showError(Messages.getString("SysmexAction.LogError.Title"), //$NON-NLS-1$
Messages.getString("SysmexAction.LogError.Text")); //$NON-NLS-1$
_rs232log = new Logger();
}
} else {
_rs232log = new Logger(false);
}
background = CoreHub.localCfg.get(Preferences.BACKGROUND, "n") //$NON-NLS-1$
.equalsIgnoreCase("y"); //$NON-NLS-1$
}
@Override
public void run(){
if (isChecked()) {
initPreferences();
if (simulate == null) {
initConnection();
String msg = _ctrl.connect();
if (msg == null) {
String timeoutStr =
CoreHub.localCfg.get(Preferences.TIMEOUT,
Messages.getString("SysmexAction.DefaultTimeout")); //$NON-NLS-1$
int timeout = 20;
try {
timeout = Integer.parseInt(timeoutStr);
} catch (NumberFormatException e) {
// Do nothing. Use default value
}
_ctrl
.awaitFrame(
UiDesk.getTopShell(),
Messages.getString("SysmexAction.WaitMsg"), 1, 4, 0, timeout, background, true); //$NON-NLS-1$
return;
} else {
_rs232log.log("Error"); //$NON-NLS-1$
SWTHelper.showError(Messages.getString("SysmexAction.RS232.Error.Title"), //$NON-NLS-1$
msg);
}
} else {
SWTHelper.showInfo("Simulating!!!", simulate);
// test only
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(simulate);
int test = inputStream.read();
while (test != -1) {
if (test == Logger.STX) {
test = inputStream.read();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (test != -1 && test != Logger.ETX) {
baos.write(test);
test = inputStream.read();
}
byte[] data = baos.toByteArray();
gotData(null, data);
while (test != -1 && test != Logger.STX) {
test = inputStream.read();
}
}
} catch (FileNotFoundException fne) {
fne.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
} else {
if (_ctrl.isOpen()) {
_ctrl.sendBreak();
_ctrl.close();
}
}
setChecked(false);
}
/**
* Eine Standard-Fehlermeldung asynchron im UI-Thread zeigen
*/
private static void showError(final String title, final String message){
UiDesk.getDisplay().asyncExec(new Runnable() {
public void run(){
Shell shell = UiDesk.getTopShell();
MessageDialog.openError(shell, title, message);
}
});
}
/**
* Unterbruche wird von serieller Schnittstelle geschickt.
*/
public void gotBreak(final AbstractConnection connection){
connection.close();
setChecked(false);
_elexislog.log("Break", Log.INFOS); //$NON-NLS-1$
SWTHelper.showError(Messages.getString("SysmexAction.RS232.Break.Title"), Messages //$NON-NLS-1$
.getString("SysmexAction.RS232.Break.Text")); //$NON-NLS-1$
}
/**
* Einzelne Probe wird verarbeitet
*
* @param probe
*/
private void processProbe(final AbstractData probe){
UiDesk.getDisplay().syncExec(new Runnable() {
public void run(){
UiDesk.getDisplay().syncExec(new Runnable() {
public void run(){
Patient suggestedPatient = findSuggestedPatient(probe.getPatientId());
// only open selection dialog if there is a suggestion available
if (suggestedPatient != null) {
WhichPatientDialog wpDialog =
new WhichPatientDialog(UiDesk.getTopShell(), suggestedPatient);
wpDialog.open();
selectedPatient = wpDialog.getPatient();
}
// case no patient selection was orcould be made yet
if (selectedPatient == null) {
KontaktSelektor ksl = new KontaktSelektor(Hub.getActiveShell(),
Patient.class, Messages.getString("SysmexAction.Patient.Title"), //$NON-NLS-1$
Messages.getString("SysmexAction.Patient.Text"), //$NON-NLS-1$
Patient.DEFAULT_SORT);
ksl.create();
ksl.getShell()
.setText(Messages.getString("SysmexAction.Patient.Title")); //$NON-NLS-1$
if (ksl.open() == org.eclipse.jface.dialogs.Dialog.OK) {
selectedPatient = (Patient) ksl.getSelection();
} else {
selectedPatient = null;
}
}
}
});
if (selectedPatient != null) {
try {
probe.write(selectedPatient);
} catch (PackageException e) {
showError(
Messages.getString("SysmexAction.ProbeError.Title"), e.getMessage()); //$NON-NLS-1$
}
} else {
showError(Messages.getString("SysmexAction.Patient.Title"), //$NON-NLS-1$
Messages.getString("SysmexAction.NoPatientMsg")); //$NON-NLS-1$
}
}
});
}
/**
* Finds potential suggestion of a patient.<br>
* Tries to resolve Sysmex sent patient number first and alternatively tries to resolve
* currently selected patient.
*
* @param sysmexPatId
* @return The patient sent via the Sysmex device. If SysmexPatient is can't be resolved the
* currently selected patient is used. NULL if neither SysmexPatient or ActivePatient
* could be resolved.
*/
private Patient findSuggestedPatient(String sysmexPatId){
if (sysmexPatId == null || sysmexPatId.isEmpty()) {
return ElexisEventDispatcher.getSelectedPatient();
}
Patient suggestedPatient = Patient.loadByPatientID(sysmexPatId);
if (suggestedPatient == null) {
return ElexisEventDispatcher.getSelectedPatient();
}
return suggestedPatient;
}
/**
* Daten werden von der Seriellen Schnittstelle geliefert
*/
public void gotData(final AbstractConnection connection, final byte[] data){
stopShutdownSequence();
String content = new String(data);
if (connection != null) {
_rs232log.logSTX();
_rs232log.log(content);
}
AbstractData analysisData = null;
String model = CoreHub.localCfg.get(Preferences.MODEL, Preferences.MODEL_KX21);
if (Preferences.MODEL_KX21N.equals(model)) {
analysisData = new KX21NData();
} else if (Preferences.MODEL_POCH.equals(model)) {
analysisData = new PocH100iData();
} else {
analysisData = new KX21Data();
}
if (content.length() == analysisData.getSize()) {
analysisData.parse(content);
processProbe(analysisData);
} else {
showError(Messages.getString("SysmexAction.ErrorTitle"), //$NON-NLS-1$
Messages.getString("SysmexAction.WrongDataFormat")); //$NON-NLS-1$
}
if (connection != null) {
_rs232log.logETX();
}
ElexisEventDispatcher.reload(LabItem.class);
boolean background =
CoreHub.localCfg.get(Preferences.BACKGROUND, "n").equalsIgnoreCase("y");
if (!background) {
startShutdownSequence();
}
}
private void stopShutdownSequence(){
if (shutdownThread != null) {
shutdownThread.stopSequence();
}
}
private void startShutdownSequence(){
if (shutdownThread == null) {
shutdownThread = new ShutdownThread();
shutdownThread.setPriority(Thread.MIN_PRIORITY);
shutdownThread.start();
}
shutdownThread.startSequence();
}
private void close(){
if (shutdownThread != null) {
shutdownThread.interrupt();
shutdownThread = null;
}
_ctrl.close();
setChecked(false);
}
/**
* Verbindung zu serieller Schnittstelle wurde getrennt
*/
public void closed(){
_elexislog.log("Closed", Log.INFOS); //$NON-NLS-1$
close();
}
/**
* Verbindung zu serieller Schnittstelle wurde vom Benutzer abgebrochen
*/
public void cancelled(){
_elexislog.log("Cancelled", Log.INFOS); //$NON-NLS-1$
close();
}
/**
* Verbindung zu serieller Schnittstelle hat timeout erreicht.
*/
public void timeout(){
_elexislog.log("Timeout", Log.INFOS); //$NON-NLS-1$
SWTHelper.showError(Messages.getString("SysmexAction.RS232.Timeout.Title"), //$NON-NLS-1$
Messages.getString("SysmexAction.RS232.Timeout.Text")); //$NON-NLS-1$
close();
}
}