001package jmri.jmris; 002 003import java.beans.PropertyChangeEvent; 004import java.beans.PropertyChangeListener; 005import java.io.IOException; 006import java.util.HashMap; 007import java.util.Map; 008 009import jmri.InstanceManager; 010import jmri.JmriException; 011import jmri.Sensor; 012import jmri.SensorManager; 013import org.slf4j.Logger; 014import org.slf4j.LoggerFactory; 015 016/** 017 * Abstract interface between the a JMRI sensor and a network connection 018 * 019 * @author Paul Bender Copyright (C) 2010 020 */ 021public abstract class AbstractSensorServer { 022 023 private static final String ERROR_SENDING_STATUS = "Error Sending Status"; 024 private final HashMap<String, SensorListener> sensors; 025 private static final Logger log = LoggerFactory.getLogger(AbstractSensorServer.class); 026 027 public AbstractSensorServer(){ 028 sensors = new HashMap<>(); 029 } 030 031 /* 032 * Protocol Specific Abstract Functions 033 */ 034 public abstract void sendStatus(String sensor, int Status) throws IOException; 035 036 public abstract void sendErrorStatus(String sensor) throws IOException; 037 038 public abstract void parseStatus(String statusString) throws JmriException, IOException; 039 040 protected synchronized void addSensorToList(String sensorName) { 041 if (!sensors.containsKey(sensorName)) { 042 Sensor s = InstanceManager.getDefault(SensorManager.class).getSensor(sensorName); 043 if(s!=null) { 044 SensorListener sl = new SensorListener(sensorName); 045 s.addPropertyChangeListener(sl); 046 sensors.put(sensorName, sl ); 047 } 048 } 049 } 050 051 protected synchronized void removeSensorFromList(String sensorName) { 052 if (sensors.containsKey(sensorName)) { 053 Sensor s = InstanceManager.getDefault(SensorManager.class).getSensor(sensorName); 054 if(s!=null) { 055 s.removePropertyChangeListener(sensors.get(sensorName)); 056 sensors.remove(sensorName); 057 } 058 } 059 } 060 061 public Sensor initSensor(String sensorName) { 062 Sensor sensor = InstanceManager.getDefault(SensorManager.class).provideSensor(sensorName); 063 this.addSensorToList(sensorName); 064 return sensor; 065 } 066 067 public void setSensorActive(String sensorName) { 068 Sensor sensor; 069 // load address from sensorAddrTextField 070 try { 071 addSensorToList(sensorName); 072 sensor = InstanceManager.getDefault(SensorManager.class).getSensor(sensorName); 073 if (sensor == null) { 074 log.error("Sensor {} is not available", sensorName); 075 } else { 076 if (sensor.getKnownState() != Sensor.ACTIVE) { 077 // set state to ACTIVE 078 log.debug("changing sensor '{}' to Active ({}->{})", sensorName, sensor.getKnownState(), Sensor.ACTIVE); 079 sensor.setKnownState(Sensor.ACTIVE); 080 } else { 081 // just notify the client. 082 log.debug("not changing sensor '{}', already Active ({})", sensorName, sensor.getKnownState()); 083 sendStatusWithErrorHandling(sensorName,Sensor.ACTIVE); 084 } 085 } 086 } catch (JmriException ex) { 087 log.error("set sensor active", ex); 088 } 089 } 090 091 public void dispose() { 092 for (Map.Entry<String, SensorListener> sensor : this.sensors.entrySet()) { 093 Sensor s = InstanceManager.getDefault(SensorManager.class).getSensor(sensor.getKey()); 094 if(s!=null) { 095 s.removePropertyChangeListener(sensor.getValue()); 096 } 097 } 098 this.sensors.clear(); 099 } 100 101 public void setSensorInactive(String sensorName) { 102 Sensor sensor; 103 try { 104 addSensorToList(sensorName); 105 sensor = InstanceManager.getDefault(SensorManager.class).getSensor(sensorName); 106 107 if (sensor == null) { 108 log.error("Sensor {} is not available",sensorName); 109 } else { 110 if (sensor.getKnownState() != Sensor.INACTIVE) { 111 // set state to INACTIVE 112 log.debug("changing sensor '{}' to InActive ({}->{})", sensorName, sensor.getKnownState(), Sensor.INACTIVE); 113 sensor.setKnownState(Sensor.INACTIVE); 114 } else { 115 // just notify the client. 116 log.debug("not changing sensor '{}', already InActive ({})", sensorName, sensor.getKnownState()); 117 sendStatusWithErrorHandling(sensorName,Sensor.INACTIVE); 118 } 119 } 120 } catch (JmriException ex) { 121 log.error("set sensor inactive", ex); 122 } 123 } 124 125 private void sendStatusWithErrorHandling(String sensorName,int status){ 126 try { 127 sendStatus(sensorName, status); 128 } catch (IOException ie) { 129 log.error(ERROR_SENDING_STATUS); 130 } 131 } 132 133 class SensorListener implements PropertyChangeListener { 134 135 SensorListener(String sensorName) { 136 name = sensorName; 137 sensor = InstanceManager.getDefault(SensorManager.class).getSensor(sensorName); 138 } 139 140 // update state as state of sensor changes 141 @Override 142 public void propertyChange(PropertyChangeEvent e) { 143 // If the Commanded State changes, show transition state as "<inconsistent>" 144 if (e.getPropertyName().equals("KnownState")) { 145 int now = ((Integer) e.getNewValue()).intValue(); 146 try { 147 sendStatus(name, now); 148 } catch (IOException ie) { 149 log.debug(ERROR_SENDING_STATUS); 150 // if we get an error, de-register 151 sensor.removePropertyChangeListener(this); 152 removeSensorFromList(name); 153 } 154 } 155 } 156 String name = null; 157 Sensor sensor = null; 158 } 159}