001package jmri.jmrix.powerline.insteon2412s; 002 003import jmri.Sensor; 004import jmri.jmrix.powerline.SerialReply; 005import jmri.jmrix.powerline.SerialTrafficController; 006import jmri.jmrix.powerline.X10Sequence; 007import jmri.util.StringUtil; 008import org.slf4j.Logger; 009import org.slf4j.LoggerFactory; 010 011/** 012 * Manage the system-specific Sensor implementation. 013 * <p> 014 * System names are "PSann", where a is the unit id, nn is the unit number 015 * without padding. 016 * <p> 017 * Sensors are numbered from 1. 018 * 019 * @author Bob Jacobsen Copyright (C) 2003, 2006, 2007, 2008, 2009 020 * @author Ken Cameron, (C) 2009, 2010 sensors from poll replies Converted to multiple connection 021 * @author kcameron Copyright (C) 2011 022 */ 023public class SpecificSensorManager extends jmri.jmrix.powerline.SerialSensorManager { 024 025 public SpecificSensorManager(SerialTrafficController tc) { 026 super(tc); 027 this.tc = tc; 028 } 029 030 SerialTrafficController tc = null; 031 032 /** 033 * Process a reply to a poll of Sensors of one node 034 */ 035 @Override 036 public synchronized void reply(SerialReply r) { 037 // process for updates 038 processForPollReq(r); 039 } 040 041 private void processForPollReq(SerialReply l) { 042 if ((l.getElement(0) & 0xFF) == Constants.HEAD_STX) { 043 // process the POLL_REQ_X10 and update/create sensors as needed 044 if (((l.getElement(1) & 0xFF) == Constants.POLL_REQ_X10) && l.getNumDataElements() == 4) { 045 // valid poll of X10 message 046 int dat = l.getElement(2) & 0xFF; 047 int flag = l.getElement(3) & 0xFF; 048 String newHouseCode = X10Sequence.houseValueToText(X10Sequence.decode((dat >> 4) & 0x0F)); 049 int newCmdCode = dat & 0x0F; 050 int newAddrCode = -1; 051 Sensor sensor; 052 if ((flag & Constants.FLAG_BIT_X10_CMDUNIT) == Constants.FLAG_X10_RECV_CMD) { 053 if ((newCmdCode == X10Sequence.FUNCTION_ALL_LIGHTS_OFF || newCmdCode == X10Sequence.FUNCTION_ALL_UNITS_OFF || newCmdCode == X10Sequence.FUNCTION_ALL_LIGHTS_ON)) { 054 // some sort of 'global' command, process for all matching the house code 055 getNamedBeanSet().forEach(sensorInSet -> { 056 String sName = sensorInSet.getSystemName(); 057 if (newHouseCode.compareTo(tc.getAdapterMemo().getSerialAddress().houseCodeFromSystemName(sName)) == 0) { 058 try { 059 if (newCmdCode == X10Sequence.FUNCTION_ALL_LIGHTS_OFF || newCmdCode == X10Sequence.FUNCTION_ALL_UNITS_OFF) { 060 sensorInSet.setKnownState(Sensor.INACTIVE); 061 } else { 062 sensorInSet.setKnownState(Sensor.ACTIVE); 063 } 064 } catch (jmri.JmriException e) { 065 if (newCmdCode == X10Sequence.FUNCTION_ALL_LIGHTS_OFF || newCmdCode == X10Sequence.FUNCTION_ALL_UNITS_OFF) { 066 log.error("Exception setting {} sensor INACTIVE", sName, e); 067 } else { 068 log.error("Exception setting {} sensor ACTIVE", sName, e); 069 } 070 } 071 } 072 }); 073 } else { 074 if (newHouseCode != null && newAddrCode > 0) { 075 String sysName = getSystemPrefix() + "S" + newHouseCode + newAddrCode; 076 sensor = provideSensor(sysName); 077 if (newCmdCode == X10Sequence.FUNCTION_ON || newCmdCode == X10Sequence.FUNCTION_BRIGHT || newCmdCode == X10Sequence.FUNCTION_STATUS_ON) { 078 try { 079 sensor.setKnownState(Sensor.ACTIVE); 080 } catch (jmri.JmriException e) { 081 log.error("Exception setting {} sensor ACTIVE", sysName, e); 082 } 083 } 084 if (newCmdCode == X10Sequence.FUNCTION_OFF || newCmdCode == X10Sequence.FUNCTION_DIM || newCmdCode == X10Sequence.FUNCTION_STATUS_OFF) { 085 try { 086 sensor.setKnownState(Sensor.INACTIVE); 087 } catch (jmri.JmriException e) { 088 log.error("Exception setting {} sensor INACTIVE", sysName, e); 089 } 090 } 091 } 092 } 093 } 094 } else if (((l.getElement(1) & 0xFF) == Constants.POLL_REQ_STD) && l.getNumDataElements() == 11) { 095 // figure how to decode an standard Insteon poll command 096 int highAddr = l.getElement(5) & 0xFF; 097 int middleAddr = l.getElement(6) & 0xFF; 098 int lowAddr = l.getElement(7) & 0xFF; 099 int cmd1 = l.getElement(9) & 0xFF; 100 StringBuilder sysName = new StringBuilder(); 101 sysName.append(getSystemPrefix()); 102 sysName.append("S"); 103 sysName.append(StringUtil.twoHexFromInt(highAddr)); 104 sysName.append("."); 105 sysName.append(StringUtil.twoHexFromInt(middleAddr)); 106 sysName.append("."); 107 sysName.append(StringUtil.twoHexFromInt(lowAddr)); 108 Sensor sensor = null; 109 try { 110 sensor = provideSensor(new String(sysName)); 111 } catch(java.lang.IllegalArgumentException iae){ 112 // if provideSensor fails, it will throw an IllegalArgumentException, so catch that,log it if debugging is enabled, and then re-throw it. 113 log.debug("Attempt access sensor {} failed", sysName); 114 throw iae; 115 } 116 if (cmd1 == Constants.CMD_LIGHT_ON_FAST || cmd1 == Constants.CMD_LIGHT_ON_RAMP) { 117 try { 118 sensor.setKnownState(Sensor.ACTIVE); 119 } catch (jmri.JmriException e) { 120 log.error("Exception setting {} sensor ACTIVE", sysName, e); 121 } 122 } 123 if (cmd1 == Constants.CMD_LIGHT_OFF_FAST || cmd1 == Constants.CMD_LIGHT_OFF_RAMP) { 124 try { 125 sensor.setKnownState(Sensor.INACTIVE); 126 } catch (jmri.JmriException e) { 127 log.error("Exception setting {} sensor INACTIVE", sysName, e); 128 } 129 } 130 } 131 } 132 } 133 134 private final static Logger log = LoggerFactory.getLogger(SpecificSensorManager.class); 135}