/* * SleepArchiver - cross-platform data manager for Sleeptracker-series watches. * Copyright (C) 2009-2011 Pavel Fatin <http://pavelfatin.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.pavelfatin.sleeparchiver.model; import com.pavelfatin.sleeparchiver.lang.Utilities; import gnu.io.CommPortIdentifier; import gnu.io.PortInUseException; import gnu.io.SerialPort; import gnu.io.UnsupportedCommOperationException; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; public class Device { private static final int HANDSHAKE = 86; private static final int TIMEOUT = 2000; private static final int BUFFER = 250; private static final int DELAY = 500; private String _app; private int _year; public Device(String app, int year) { _app = app; _year = year; } public Night readData() { List<CommPortIdentifier> ids = findFreeSerialPorts(); for (CommPortIdentifier id : ids) { try { return readNight(id, _app, _year); } catch (ProtocolException e) { // do nothing } catch (IOException e) { // do nothing } catch (UnsupportedCommOperationException e) { // do nothing } catch (PortInUseException e) { // do nothing } } return null; } private static Night readNight(CommPortIdentifier id, String app, int year) throws IOException, UnsupportedCommOperationException, PortInUseException { SerialPort port = (SerialPort) id.open(app, TIMEOUT); try { port.setSerialPortParams(2400, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); port.setInputBufferSize(BUFFER); port.setRTS(false); port.setDTR(true); sendHandshake(port); sleep(DELAY); return readNight(port, year); } finally { port.close(); } } private static void sleep(int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { throw new RuntimeException(e); } } private static void sendHandshake(SerialPort port) throws IOException { OutputStream out = port.getOutputStream(); try { out.write(HANDSHAKE); out.flush(); } finally { Utilities.close(out); } } private static Night readNight(SerialPort port, int year) throws IOException { InputStream in = new BufferedInputStream(port.getInputStream()); try { return readNight(new DeviceReader(in, year)); } finally { Utilities.close(in); } } static Night readNight(InputStream stream, int year) throws IOException { return readNight(new DeviceReader(stream, year)); } private static Night readNight(DeviceReader reader) throws IOException { reader.readHandshake(); Date date = reader.readDate(); reader.skip(); int window = reader.readByte(); Time toBed = reader.readTime(); Time alarm = reader.readTime(); int count = reader.readByte(); List<Time> moments = new ArrayList<Time>(); for (int i = 0; i < count; i++) { moments.add(reader.readTime()); reader.skip(); } int minutesLow = reader.readByte(); int minutesHigh = reader.readByte(); int dataChecksum = reader.getChecksum(); int checksum = reader.readByte(); if (dataChecksum != checksum) { throw new ProtocolException(String.format( "Incorrect checksum: %d, expected: %d", dataChecksum, checksum)); } reader.readEnding(); return new Night(date, alarm, window, toBed, moments); } private static List<CommPortIdentifier> findFreeSerialPorts() { List<CommPortIdentifier> result = new ArrayList<CommPortIdentifier>(); Enumeration e = CommPortIdentifier.getPortIdentifiers(); while (e.hasMoreElements()) { CommPortIdentifier id = (CommPortIdentifier) e.nextElement(); if (id.getPortType() == CommPortIdentifier.PORT_SERIAL) { if (!id.isCurrentlyOwned()) { result.add(id); } } } return result; } }