001package jmri.jmrix.rps; 002 003import java.util.ArrayList; 004import javax.vecmath.Point3d; 005import jmri.Sensor; 006import jmri.implementation.AbstractSensor; 007import org.slf4j.Logger; 008import org.slf4j.LoggerFactory; 009 010/** 011 * Extend jmri.AbstractSensor for RPS systems. 012 * <p> 013 * System names are "RSpppp", where ppp is a representation of the region, for 014 * example "RS(0,0,0);(1,0,0);(1,1,0);(0,1,0)". 015 * 016 * @author Bob Jacobsen Copyright (C) 2007 017 */ 018public class RpsSensor extends AbstractSensor 019 implements MeasurementListener { 020 021 public RpsSensor(String systemName, String prefix) { 022 super(systemName); 023 // create Region from all but prefix 024 region = new Region(systemName.substring(prefix.length() + 1)); // multichar prefix from memo 025 Model.instance().addRegion(region); 026 } 027 028 public RpsSensor(String systemName, String userName, String prefix) { 029 super(systemName, userName); 030 // create Region from all but prefix 031 region = new Region(systemName.substring(prefix.length() + 1)); // multichar prefix from memo 032 Model.instance().addRegion(region); 033 } 034 035 @Override 036 public void notify(Measurement r) { 037 Point3d p = new Point3d(r.getX(), r.getY(), r.getZ()); 038 Integer id = Integer.valueOf(r.getReading().getId()); 039 040 // ignore if code not OK 041 if (!r.isOkPoint()) { 042 return; 043 } 044 045 // ignore if not in Z fiducial volume 046 if (r.getZ() > 20 || r.getZ() < -20) { 047 return; 048 } 049 050 log.debug("starting {}", getSystemName()); 051 if (region.isInside(p)) { 052 notifyInRegion(id); 053 } else { 054 notifyOutOfRegion(id); 055 } 056 if (contents.size() > 0) { 057 setOwnState(Sensor.ACTIVE); 058 } else { 059 setOwnState(Sensor.INACTIVE); 060 } 061 } 062 063 // if somebody outside sets state to INACTIVE, clear list 064 @Override 065 public void setOwnState(int state) { 066 if (state == Sensor.INACTIVE) { 067 if (contents.size() > 0) { 068 contents = new ArrayList<Integer>(); 069 } 070 } 071 super.setOwnState(state); 072 } 073 074 Region getRegion() { 075 return region; 076 } 077 078 java.util.List<Integer> getContents() { 079 return contents; 080 } 081 082 void notifyInRegion(Integer id) { 083 // make sure region contains this Reading.getId(); 084 if (!contents.contains(id)) { 085 contents.add(id); 086 notifyArriving(id); 087 } 088 } 089 090 void notifyOutOfRegion(Integer id) { 091 // make sure region does not contain this Reading.getId(); 092 if (contents.contains(id)) { 093 contents.remove(id); 094 notifyLeaving(id); 095 } 096 } 097 098 transient Region region; 099 ArrayList<Integer> contents = new ArrayList<Integer>(); 100 101 /** 102 * Notify parameter listeners that a device has left the region covered by 103 * this sensor 104 * @param id Number of region being left 105 */ 106 void notifyLeaving(Integer id) { 107 firePropertyChange("Leaving", null, id); 108 } 109 110 /** 111 * Notify parameter listeners that a device has entered the region covered 112 * by this sensor 113 * @param id Number of region being entered 114 */ 115 void notifyArriving(Integer id) { 116 firePropertyChange("Arriving", null, id); 117 } 118 119 @Override 120 public void dispose() { 121 Model.instance().removeRegion(region); 122 super.dispose(); 123 } 124 125 @Override 126 public void requestUpdateFromLayout() { 127 } 128 129 private final static Logger log = LoggerFactory.getLogger(RpsSensor.class); 130 131}