001package jmri.jmrix.rfid; 002 003import jmri.IdTag; 004import org.slf4j.Logger; 005import org.slf4j.LoggerFactory; 006 007/** 008 * Timeout specific implementation of an RfidSensor. 009 * <p> 010 * Certain RFID readers only send a message when an RFID tag is within the 011 * proximity of the reader - no message is sent when it leaves. 012 * <p> 013 * As a result, this implementation simulates this message using a timeout 014 * mechanism - if no further tags are sensed within a pre-defined time period, 015 * the Sensor state reverts to {@link IdTag#UNSEEN}. 016 * <hr> 017 * This file is part of JMRI. 018 * <p> 019 * JMRI is free software; you can redistribute it and/or modify it under the 020 * terms of version 2 of the GNU General Public License as published by the Free 021 * Software Foundation. See the "COPYING" file for a copy of this license. 022 * <p> 023 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY 024 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 025 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 026 * 027 * @author Matthew Harris Copyright (C) 2014 028 * @since 3.9.2 029 */ 030public class TimeoutRfidSensor extends RfidSensor { 031 032 /** 033 * Timeout in ms 034 */ 035 private static final int TIMEOUT = 1000; 036 037 /** 038 * Time when something was last sensed by this object 039 */ 040 private long whenLastSensed = 0; 041 042 /** 043 * Reference to the timeout thread for this object 044 */ 045 private transient TimeoutThread timeoutThread = null; 046 047 private final boolean logDebug = log.isDebugEnabled(); 048 049 public TimeoutRfidSensor(String systemName) { 050 super(systemName); 051 } 052 053 public TimeoutRfidSensor(String systemName, String userName) { 054 super(systemName, userName); 055 } 056 057 @Override 058 public void notify(IdTag t) { 059 super.notify(t); 060 whenLastSensed = System.currentTimeMillis(); 061 if (timeoutThread == null) { 062 (timeoutThread = new TimeoutThread()).start(); 063 } 064 } 065 066 private void cleanUpTimeout() { 067 if (logDebug) { 068 log.debug("Cleanup timeout thread for {}", mSystemName); 069 } 070 timeoutThread = null; 071 } 072 073 private class TimeoutThread extends Thread { 074 075 TimeoutThread() { 076 super(); 077 this.setName("Timeout-" + mSystemName); 078 } 079 080 @Override 081// @SuppressWarnings("SleepWhileInLoop") 082 public void run() { 083 while ((whenLastSensed + TIMEOUT) > System.currentTimeMillis()) { 084 try { 085 Thread.sleep(50); 086 } catch (InterruptedException ex) { 087 } 088 } 089 TimeoutRfidSensor.super.notify(null); 090 if (logDebug) { 091 log.debug("Timeout-{}", mSystemName); 092 } 093 cleanUpTimeout(); 094 } 095 096 } 097 098 private static final Logger log = LoggerFactory.getLogger(TimeoutRfidSensor.class); 099 100}