001package jmri.jmrix.can.cbus.simulator; 002 003import javax.annotation.CheckForNull; 004 005import jmri.jmrix.can.CanReply; 006import jmri.jmrix.can.CanSystemConnectionMemo; 007import jmri.jmrix.can.cbus.CbusConstants; 008 009import jmri.jmrix.can.cbus.node.*; 010import jmri.jmrix.can.cbus.swing.simulator.NdPane; 011 012/** 013 * Simulating a MERG CBUS Node. 014 * 015 * @author Steve Young Copyright (C) 2018 2019 016 * @see CbusSimulator 017 * @since 4.15.2 018 */ 019public class CbusDummyNode extends CbusNode { 020 021 private NdPane _pane; 022 023 /** 024 * Create a new CbusDummyNode. 025 * @param sysmemo System Connection to use, can be null. 026 * @param nodenumber the initial Node Number. 027 */ 028 public CbusDummyNode( @CheckForNull CanSystemConnectionMemo sysmemo, int nodenumber ){ 029 super( sysmemo, nodenumber ); 030 super.setNodeInFLiMMode(false); 031 setCanId(sysmemo); 032 _pane = null; 033 } 034 035 /** 036 * Uses in-class CanListener 037 * {@inheritDoc} 038 */ 039 @Override 040 public CbusNodeCanListener getNewCanListener(){ 041 canListener = new CbusDummyNodeCanListener(_memo,this); 042 return canListener; 043 } 044 045 private CbusDummyNodeCanListener canListener; 046 047 // total events on module 048 protected void sendNUMEV(){ 049 CanReply r = new CanReply(4); 050 r.setElement(0, CbusConstants.CBUS_NUMEV); 051 r.setElement(1, getNodeNumber() >> 8); 052 r.setElement(2, getNodeNumber() & 0xff); 053 r.setElement(3, (Math.max(0, (getNodeEventManager().getTotalNodeEvents())) & 0xff ) ); 054 send.sendWithDelay(r,canListener.getSendIn(),canListener.getSendOut(),canListener.getDelay()); 055 } 056 057 protected void sendENRSP(){ 058 int extraDelay = 5; 059 for (int i = 0; i < getNodeEventManager().getTotalNodeEvents(); i++) { 060 061 CbusNodeEvent ndEv = getNodeEventManager().getNodeEventByArrayID(i); 062 if (ndEv==null){ 063 break; 064 } 065 066 if ( ndEv.getIndex()<0 ) { 067 ndEv.setIndex( getNodeEventManager().getNextFreeIndex() ); 068 } 069 070 CanReply r = new CanReply(8); 071 r.setElement(0, CbusConstants.CBUS_ENRSP); 072 r.setElement(1, getNodeNumber() >> 8); 073 r.setElement(2, getNodeNumber() & 0xff); 074 r.setElement(3, ndEv.getNn() >> 8); 075 r.setElement(4, ndEv.getNn() & 0xff); 076 r.setElement(5, ndEv.getEn() >> 8); 077 r.setElement(6, ndEv.getEn() & 0xff); 078 r.setElement(7, ndEv.getIndex() & 0xff); 079 send.sendWithDelay(r,canListener.getSendIn(),canListener.getSendOut(),canListener.getDelay() + ( extraDelay * i ) ); 080 } 081 } 082 083 protected void sendNEVAL( int index, int varIndex ){ 084 085 CbusNodeEvent _ndEv = getNodeEventManager().getNodeEventByIndex(index); 086 087 if ( index < 0 || index > 255 ){ 088 sendCMDERR(7); 089 } 090 091 // for future sim. of CMDERR5 support 092 // if (varIndex>40) { 093 // 094 // sendCMDERR(5); 095 // return; 096 // } 097 098 else if (_ndEv==null){ 099 sendCMDERR(12); 100 } 101 else { 102 CanReply r = new CanReply(6); 103 r.setElement(0, CbusConstants.CBUS_NEVAL); 104 r.setElement(1, getNodeNumber() >> 8); 105 r.setElement(2, getNodeNumber() & 0xff); 106 r.setElement(3, index & 0xff); 107 r.setElement(4, varIndex & 0xff); 108 r.setElement(5, _ndEv.getEvVar(varIndex) & 0xff); 109 send.sendWithDelay(r,canListener.getSendIn(),canListener.getSendOut(),canListener.getDelay()); 110 } 111 } 112 113 protected void sendPARAMS() { 114 CanReply r = new CanReply(8); 115 r.setElement(0, CbusConstants.CBUS_PARAMS); 116 r.setElement(1, getNodeParamManager().getParameter(1) & 0xff ); 117 r.setElement(2, getNodeParamManager().getParameter(2) & 0xff ); 118 r.setElement(3, getNodeParamManager().getParameter(3) & 0xff); 119 r.setElement(4, getNodeParamManager().getParameter(4) & 0xff); 120 r.setElement(5, getNodeParamManager().getParameter(5) & 0xff); 121 r.setElement(6, getNodeParamManager().getParameter(6) & 0xff); 122 r.setElement(7, getNodeParamManager().getParameter(7) & 0xff); 123 send.sendWithDelay(r,canListener.getSendIn(),canListener.getSendOut(),canListener.getDelay()); 124 } 125 126 protected void sendPNN() { 127 CanReply r = new CanReply(6); 128 r.setElement(0, CbusConstants.CBUS_PNN); 129 r.setElement(1, getNodeNumber() >> 8); 130 r.setElement(2, getNodeNumber() & 0xff); 131 r.setElement(3, getNodeParamManager().getParameter(1) & 0xff ); 132 r.setElement(4, getNodeParamManager().getParameter(3) & 0xff ); 133 r.setElement(5, getNodeParamManager().getParameter(8) & 0xff ); 134 send.sendWithDelay(r,canListener.getSendIn(),canListener.getSendOut(),canListener.getDelay()); 135 } 136 137 // Parameter answer 138 protected void sendPARAN( int index ){ 139 try { 140 CanReply r = new CanReply(5); 141 r.setElement(0, CbusConstants.CBUS_PARAN); 142 r.setElement(1, getNodeNumber() >> 8); 143 r.setElement(2, getNodeNumber() & 0xff); 144 r.setElement(3, index & 0xff); 145 r.setElement(4, getNodeParamManager().getParameter(index) & 0xff); 146 send.sendWithDelay(r,canListener.getSendIn(),canListener.getSendOut(),canListener.getDelay()); 147 } 148 catch (ArrayIndexOutOfBoundsException e) { 149 sendCMDERR(9); 150 } 151 } 152 153 // NV Answer 154 protected void sendNVANS( int index ) { 155 try { 156 CanReply r = new CanReply(5); 157 r.setElement(0, CbusConstants.CBUS_NVANS); 158 r.setElement(1, getNodeNumber() >> 8); 159 r.setElement(2, getNodeNumber() & 0xff); 160 r.setElement(3, index & 0xff ); 161 r.setElement(4, getNodeNvManager().getNV(index) & 0xff ); 162 send.sendWithDelay(r,canListener.getSendIn(),canListener.getSendOut(),canListener.getDelay()); 163 } 164 catch (ArrayIndexOutOfBoundsException e) { 165 sendCMDERR(10); 166 } 167 } 168 169 protected void setDummyNV(int index, int newval) { 170 171 // not per CBUS spec. however some modules do this... 172 if ( this.getnvWriteInLearnOnly() && !this.getNodeInLearnMode() ){ 173 sendCMDERR(2); 174 return; 175 } 176 177 if ( newval<0 || newval > 255 ) { 178 sendCMDERR(12); 179 return; 180 } 181 182 if (index==0) { 183 sendCMDERR(10); 184 return; 185 } 186 try { 187 getNodeNvManager().setNV(index,newval); 188 if ( getsendsWRACKonNVSET() ){ 189 sendWRACK(); 190 } 191 } 192 catch(ArrayIndexOutOfBoundsException e){ 193 sendCMDERR(10); 194 } 195 } 196 197 protected void sendCMDERR(int errorId) { 198 CanReply r = new CanReply(4); 199 r.setElement(0, CbusConstants.CBUS_CMDERR); 200 r.setElement(1, getNodeNumber() >> 8); 201 r.setElement(2, getNodeNumber() & 0xff); 202 r.setElement(3, errorId & 0xff); 203 send.sendWithDelay(r,canListener.getSendIn(),canListener.getSendOut(),canListener.getDelay()); 204 } 205 206 protected void sendWRACK(){ 207 CanReply r = new CanReply(3); 208 r.setElement(0, CbusConstants.CBUS_WRACK); 209 r.setElement(1, getNodeNumber() >> 8); 210 r.setElement(2, getNodeNumber() & 0xff); 211 send.sendWithDelay(r,canListener.getSendIn(),canListener.getSendOut(),canListener.getDelay()); 212 } 213 214 // sim of FiLM Button 215 public void flimButton() { 216 // send request for node number 217 if ( getNodeParamManager().getParameter(3) >0 ) { // module type set 218 setNodeInSetupMode(true); 219 CanReply r = new CanReply(3); 220 r.setElement(0, CbusConstants.CBUS_RQNN); 221 r.setElement(1, getNodeNumber() >> 8); 222 r.setElement(2, getNodeNumber() & 0xff); 223 send.sendWithDelay(r,canListener.getSendIn(),canListener.getSendOut(),canListener.getDelay()); 224 } 225 } 226 227 public void setPane(NdPane pane) { 228 _pane = pane; 229 } 230 231 protected void setDNN(int nn){ 232 setNodeNumber(nn); 233 setNodeInFLiMMode(true); 234 setNodeInSetupMode(false); 235 if (_pane != null) { 236 _pane.updateNodeGui(); 237 } 238 CanReply r = new CanReply(3); 239 r.setElement(0, CbusConstants.CBUS_NNACK); 240 r.setElement(1, getNodeNumber() >> 8); 241 r.setElement(2, getNodeNumber() & 0xff); 242 send.sendWithDelay(r,canListener.getSendIn(),canListener.getSendOut(),canListener.getDelay()); 243 } 244 245 // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusDummyNode.class); 246 247}