package ch.elexis.connect.afinion; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.text.MessageFormat; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; import org.eclipse.jface.action.Action; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.ui.plugin.AbstractUIPlugin; import ch.elexis.connect.afinion.packages.PackageException; import ch.elexis.connect.afinion.packages.Record; 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; import ch.elexis.data.Query; public class AfinionAS100Action extends Action implements ComPortListener { AfinionConnection _ctrl; Labor _myLab; Thread msgDialogThread; Thread infoDialogThread; Patient selectedPatient; Logger _rs232log; Log _elexislog = Log.get("AfinionAS100Action"); Record lastRecord = null; boolean background; int debugRecord = 0; // test only!! for production must be 0! String simulate = null; // "C:\\Temp\\Afinion\\afinion.log"; // declare filename to the log for // test only!! for production must be null! // "c:/temp/afinion/test.log"; oder null // Anweisung zum Logfile: // Wenn das Häckchen "Logging" in der Konfiguration eingeschaltet ist, werden die empfangenen // Resultate vom Afinion Gerät in ein Logfile geschrieben: C:\Users\tony\elexis\afinion.log // Dieses Logfile enthält pro Verbindung eine Section: // -S- "'08.07.2009, 21:51:38'" == Section Start // -E- "'08.07.2009, 21:52:11'" == Section Ende // Dazwischen werden die erhaltenen Daten mit <-- "..." geloggt. // Für die Simulation muss der Bereich zwischen den Anführungszeichen aus <-- "..." in einem // eigenständigen Logfile vorliegen. Die Binären Daten müssen dabei unverändert übernommen // werden. // Tipp: Logfile kopieren, mit Ultradedit in der HEX-Darstellung editieren und überzählige // Zeichen löschen (Ausschneiden). Beim speichern sollte es dann i.O. sein. // Kontrolle: Die Dateigrösse sollte 2568 Bytes sein (immer 10 Resultate à 256 Bytes plus 8 // Bytes footer) public AfinionAS100Action(){ super(Messages.getString("AfinionAS100Action.ButtonName"), AS_CHECK_BOX); //$NON-NLS-1$ setToolTipText(Messages.getString("AfinionAS100Action.ToolTip")); //$NON-NLS-1$ setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin("ch.elexis.connect.afinion", //$NON-NLS-1$ "icons/afinion.png")); //$NON-NLS-1$ } private void initConnection(){ if (_ctrl != null && _ctrl.isOpen()) { _ctrl.close(); } _ctrl = new AfinionConnection(Messages.getString("AfinionAS100Action.ConnectionName"), //$NON-NLS-1$ CoreHub.localCfg.get(Preferences.PORT, Messages.getString("AfinionAS100Action.DefaultPort")), CoreHub.localCfg.get( //$NON-NLS-1$ Preferences.PARAMS, Messages.getString("AfinionAS100Action.DefaultParams")), //$NON-NLS-1$ this); Calendar cal = new GregorianCalendar(); if (debugRecord != 0) { SWTHelper.showInfo("Debugging!!!", "Record " + debugRecord); //$NON-NLS-2$ // beim debuggen wollen wir alle Records sehen! cal.add(Calendar.DATE, -365); } cal.add(Calendar.HOUR, -cal.get(Calendar.HOUR_OF_DAY)); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); _ctrl.setCurrentDate(cal); 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 + "afinion.log"); //$NON-NLS-1$ } catch (FileNotFoundException e) { SWTHelper.showError(Messages.getString("AfinionAS100Action.LogError.Title"), //$NON-NLS-1$ Messages.getString("AfinionAS100Action.LogError.Text")); //$NON-NLS-1$ _rs232log = new Logger(); } } else { _rs232log = new Logger(false); } background = CoreHub.localCfg.get(Preferences.BACKGROUND, "n").equalsIgnoreCase("y"); } @Override public void run(){ if (isChecked()) { if (simulate == null) { initConnection(); _rs232log.logStart(); String msg = _ctrl.connect(); if (msg == null) { String timeoutStr = CoreHub.localCfg.get(Preferences.TIMEOUT, Messages.getString("AfinionAS100Action.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("AfinionAS100Action.WaitMsg"), 1, 4, 0, timeout, background, false); //$NON-NLS-1$ return; } else { _rs232log.log("Error"); //$NON-NLS-1$ SWTHelper.showError( Messages.getString("AfinionAS100Action.RS232.Error.Title"), msg); //$NON-NLS-1$ } } else { SWTHelper.showInfo("Simulating!!!", simulate); // test only ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { FileInputStream inputStream = new FileInputStream(simulate); int test = inputStream.read(); int ETX = 0x03; int DLE = 0x10; while (test != -1 && test != ETX) { while (test != -1 && test != DLE) { baos.write(test); test = inputStream.read(); } test = inputStream.read(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } byte[] data = baos.toByteArray(); gotData(null, data); } } else { if (_ctrl.isOpen()) { _ctrl.sendBreak(); _ctrl.close(); } } setChecked(false); _rs232log.logEnd(); } public void gotBreak(final AbstractConnection connection){ connection.close(); setChecked(false); _rs232log.log("Break"); //$NON-NLS-1$ _rs232log.logEnd(); SWTHelper.showError(Messages.getString("AfinionAS100Action.RS232.Break.Title"), Messages //$NON-NLS-1$ .getString("AfinionAS100Action.RS232.Break.Text")); //$NON-NLS-1$ } /** * Liest Bytes aus einem Bytearray */ private byte[] subBytes(final byte[] bytes, final int pos, final int length){ byte[] retVal = new byte[length]; for (int i = 0; i < length; i++) { retVal[i] = bytes[pos + i]; } return retVal; } /** * Einzelner Messwert wird verarbeitet * * @param probe */ private void processRecord(final Record record){ UiDesk.getDisplay().syncExec(new Runnable() { public void run(){ selectedPatient = ElexisEventDispatcher.getSelectedPatient(); Patient probePat = null; String vorname = null; String name = null; String patientElexisStr = Messages.getString("AfinionAS100Action.UnknownPatientHeaderString"); String patientDeviceStr = record.getId(); Long patId = null; if (patientDeviceStr != null) { // Suchkriterium für Patientenzuordnung Query<Patient> patQuery = new Query<Patient>(Patient.class); if (patientDeviceStr != null && patientDeviceStr.length() > 0) { String[] parts = patientDeviceStr.split(","); //$NON-NLS-1$ if (parts.length > 1) { try { patId = new Long(parts[0]); } catch (NumberFormatException e) { // Do nothing } if (patId != null) { // PatId, Name name = getFirstUpper(parts[1]); } else { // Name, Vorname name = getFirstUpper(parts[0]); vorname = getFirstUpper(parts[1]); patQuery.add(Patient.FLD_FIRSTNAME, "like", vorname + "%"); //$NON-NLS-1$ //$NON-NLS-2$ } } else if (parts.length == 1) { try { patId = new Long(patientDeviceStr); } catch (NumberFormatException e) { // Do nothing } if (patId == null) { // PatId, Name name = getFirstUpper(patientDeviceStr); } } if (patId != null) { patQuery.add(Patient.FLD_PATID, "=", patId.toString()); //$NON-NLS-1$ } if (name != null && name.length() > 0) { patQuery.add(Patient.FLD_NAME, "like", name + "%"); //$NON-NLS-1$ //$NON-NLS-2$ } if (vorname != null && vorname.length() > 0) { patQuery.add(Patient.FLD_FIRSTNAME, "like", vorname + "%"); //$NON-NLS-1$ //$NON-NLS-2$ } List<Patient> patientList = patQuery.execute(); if (patientList.size() == 1) { probePat = patientList.get(0); patientDeviceStr = record.getId(); patientElexisStr = probePat.getName() + " " + probePat.getVorname(); } } } if ((patientDeviceStr == null) || (patientDeviceStr.equals(""))) { patientDeviceStr = Messages.getString("AfinionAS100Action.NoPatientInfo"); } String warning = ""; // Gemäss Mail von Frau Rytz (Axis-Shield) vom 3.8.09: Anstelle der Warnung soll der // Wert als <min // oder >max angezeigt werden // Wurde in SubRecordPart.getResultStr implementiert // if (record.isOutOfRange()) { // warning = Messages.getString("AfinionAS100Action.ValueOutOfRangeWarning"); // } String text = MessageFormat.format( Messages.getString("AfinionAS100Action.ValueInfoMsg"), patientDeviceStr, patientElexisStr, record.getRunNr(), record //$NON-NLS-1$ .getText(), warning); boolean ok = MessageDialog.openConfirm(UiDesk.getTopShell(), Messages.getString("AfinionAS100Action.DeviceName"), text); //$NON-NLS-1$ if (ok) { boolean showSelectionDialog = false; if (probePat != null) { selectedPatient = probePat; } else { showSelectionDialog = true; } if (showSelectionDialog) { UiDesk.getDisplay().syncExec(new Runnable() { public void run(){ // TODO: Filter vorname/name in KontaktSelektor einbauen KontaktSelektor ksl = new KontaktSelektor( Hub.getActiveShell(), Patient.class, Messages.getString("AfinionAS100Action.Patient.Title"), //$NON-NLS-1$ Messages.getString("AfinionAS100Action.Patient.Text"), Patient.DEFAULT_SORT); //$NON-NLS-1$ ksl.create(); ksl.getShell().setText( Messages.getString("AfinionAS100Action.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 { record.write(selectedPatient); } catch (PackageException e) { SWTHelper.showError( Messages.getString("AfinionAS100Action.ProbeError.Title"), e //$NON-NLS-1$ .getMessage()); } } else { SWTHelper.showError(Messages.getString("AfinionAS100Action.Patient.Title"), //$NON-NLS-1$ Messages.getString("AfinionAS100Action.NoPatientSelectedMsg")); //$NON-NLS-1$ } _rs232log.log("Saved"); //$NON-NLS-1$ ElexisEventDispatcher.reload(LabItem.class); } } }); } /** * Messagedaten von Afinion wurden gelesen */ public void gotData(final AbstractConnection connection, final byte[] data){ if (_rs232log != null) { _rs232log.logRX(new String(data)); } // Record lesen int pos = 0; int i = 0; int validRecords = 0; while (i < 10) { byte[] subbytes = subBytes(data, pos, 256); Record tmpRecord = new Record(subbytes); String text = tmpRecord.toString(); System.out.println("DEBUG: " + text); _elexislog.log(text, Log.DEBUGMSG); if (tmpRecord.isValid()) { if (debugRecord != 0) { // lets debug that given record if (tmpRecord.getRecordNum() <= debugRecord) { lastRecord = tmpRecord; } if (tmpRecord.getRecordNum() == debugRecord) { validRecords = 0; } } else { lastRecord = tmpRecord; } text = lastRecord.toString(); System.out.println(text); _elexislog.log(text, Log.INFOS); validRecords++; } pos += 256; i++; } if (validRecords == 10) { // Read next 10 records Calendar cal = lastRecord.getCalendar(); cal.add(Calendar.SECOND, 1); if (_ctrl != null) { _ctrl.setCurrentDate(cal); _ctrl.setState(AfinionConnection.SEND_PAT_REQUEST); } } else { if (_ctrl != null) { _ctrl.setState(AfinionConnection.ENDING); _ctrl.close(); } setChecked(false); if (lastRecord != null) { processRecord(lastRecord); } else { SWTHelper .showInfo( Messages.getString("AfinionAS100Action.DeviceName"), Messages.getString("AfinionAS100Action.NoValuesMsg")); //$NON-NLS-2$ } _rs232log.log("Saved"); //$NON-NLS-1$ ElexisEventDispatcher.reload(LabItem.class); } } public void closed(){ _ctrl.close(); _rs232log.log("Closed"); //$NON-NLS-1$ setChecked(false); _rs232log.logEnd(); } public void cancelled(){ _ctrl.close(); _rs232log.log("Cancelled"); //$NON-NLS-1$ setChecked(false); _rs232log.logEnd(); } public void timeout(){ _ctrl.close(); _rs232log.log("Timeout"); //$NON-NLS-1$ SWTHelper.showError(Messages.getString("AfinionAS100Action.RS232.Timeout.Title"), Messages //$NON-NLS-1$ .getString("AfinionAS100Action.RS232.Timeout.Text")); //$NON-NLS-1$ setChecked(false); _rs232log.logEnd(); } /** * Erstes Zeichen wird Uppercase gemacht */ private String getFirstUpper(String str){ if (str == null) { return null; } str = str.trim(); String retStr = str.toUpperCase(); if (str.length() > 1) { retStr = str.substring(0, 1).toUpperCase() + str.substring(1).trim(); } return retStr; } }