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