001package jmri.jmrix.can.cbus.simulator;
002
003import jmri.jmrix.AbstractMessage;
004import jmri.jmrix.can.CanReply;
005import jmri.jmrix.can.CanSystemConnectionMemo;
006import jmri.jmrix.can.cbus.CbusConstants;
007
008// import org.slf4j.Logger;
009// import org.slf4j.LoggerFactory;
010
011/**
012 * Class to represent a Processing of CAN Frames for a CbusDummyNode.
013 *
014 * @author Steve Young Copyright (C) 2019,2020
015 */
016public class CbusDummyNodeCanListener extends CbusSimCanListener {
017
018    private final CbusDummyNode _dummyNode;
019    
020    /**
021     * Create a new CbusDummyNodeCanListener
022     *
023     * @param connmemo The CAN Connection to listen to.
024     * @param node The Node
025     */
026    public CbusDummyNodeCanListener ( CanSystemConnectionMemo connmemo, CbusDummyNode node ){
027        super(connmemo,node);
028        _dummyNode = node;
029        setDelay (40);
030    }
031    
032    @Override
033    protected void startProcessFrame(AbstractMessage m) {
034        // extended or module type unset
035        if ( _dummyNode.getNodeParamManager().getParameter(3) == 0 ) {
036            return;
037        }
038
039        if ( _dummyNode.getNodeInSetupMode() ) {
040            processDummyCanSetupMode(m);
041        }
042        else if ( _dummyNode.getNodeInFLiMMode() ) {
043            if ( m.getElement(0) == CbusConstants.CBUS_QNN ) { // Query Nodes
044                _dummyNode.sendPNN();
045            }
046            if (_dummyNode.getNodeNumber() == ( m.getElement(1) * 256 ) + m.getElement(2) ) {
047                processDummyCanFLimMode(m);
048            }
049            if ( _dummyNode.getNodeInLearnMode() ){
050                processDummyCanLearnMode(m);
051            }
052        }
053    }
054    
055    private void processDummyCanFLimMode(AbstractMessage m){
056        switch (m.getElement(0)) {
057            case CbusConstants.CBUS_NNULN:
058                // Node exit learn mode
059                _dummyNode.setNodeInLearnMode(false);
060                break;
061            case CbusConstants.CBUS_NNLRN:
062                // Node enter learn mode
063                _dummyNode.setNodeInLearnMode(true);
064                break;
065            case CbusConstants.CBUS_RQNPN:
066                // Request Node Parameters by Index
067                _dummyNode.sendPARAN(m.getElement(3));
068                break;
069            case CbusConstants.CBUS_NVRD:
070                // Request Node Variable by Index
071                _dummyNode.sendNVANS(m.getElement(3));
072                break;
073            case CbusConstants.CBUS_NVSET:
074                // Set Node Variable
075                _dummyNode.setDummyNV(m.getElement(3),m.getElement(4));
076                break;
077            default:
078                processDummyCanFLimModeEventStuff(m);
079        }
080    }
081    
082    private void processDummyCanFLimModeEventStuff(AbstractMessage m){
083        switch (m.getElement(0)) {    
084            case CbusConstants.CBUS_RQEVN:
085                // Request number of events
086                _dummyNode.sendNUMEV();
087                break;
088            case CbusConstants.CBUS_NERD:
089                // Readback all stored events in node
090                _dummyNode.sendENRSP();
091                break;
092            case CbusConstants.CBUS_REVAL:
093                // Request for read of an event variable
094                _dummyNode.sendNEVAL(m.getElement(3),m.getElement(4));
095                break;
096            default:
097                break;
098        }
099    }
100    
101    private void processDummyCanSetupMode(AbstractMessage m){
102        
103        switch (m.getElement(0)) {
104            case CbusConstants.CBUS_RQNP:
105                // Request Node Parameters
106                _dummyNode.sendPARAMS();
107                break;
108            case CbusConstants.CBUS_SNN:
109                // Set Node Number
110                _dummyNode.setDNN( ( m.getElement(1) * 256 ) + m.getElement(2) );
111                break;
112            case CbusConstants.CBUS_RQMN:
113                // Request Module Name
114
115                byte[] byteArr = jmri.util.StringUtil.fullTextToHexArray( _dummyNode.getNodeNameFromName(),7 );
116                CanReply r = new CanReply(8);
117                r.setElement(0, CbusConstants.CBUS_NAME);
118                r.setElement(1, byteArr[0] & 0xff);
119                r.setElement(2, byteArr[1] & 0xff);
120                r.setElement(3, byteArr[2] & 0xff);
121                r.setElement(4, byteArr[3] & 0xff);
122                r.setElement(5, byteArr[4] & 0xff);
123                r.setElement(6, byteArr[5] & 0xff);
124                r.setElement(7, byteArr[6] & 0xff);
125                send.sendWithDelay(r,getSendIn(),getSendOut(),getDelay());
126                break;
127            default:
128                break;
129        }
130        
131    }
132    
133    private void processDummyCanLearnMode(AbstractMessage m){
134        switch (m.getElement(0)) {
135            case CbusConstants.CBUS_EVLRN:
136                // Teach node event
137                evLearn(
138                        ( ( m.getElement(1) * 256 ) + m.getElement(2) ),
139                        ( ( m.getElement(3) * 256 ) + m.getElement(4) ),
140                        m.getElement(5),
141                        m.getElement(6) );
142                break;
143            case CbusConstants.CBUS_EVULN:
144                // Node Unlearn event
145                _dummyNode.getNodeEventManager().removeEvent( ( m.getElement(1) * 256 ) + m.getElement(2) ,
146                        ( ( m.getElement(3) * 256 ) + m.getElement(4) ) );
147                break;
148            case CbusConstants.CBUS_NNCLR:
149                // clear all events
150                if ( ( ( m.getElement(1) * 256 ) + m.getElement(2) ) ==  _dummyNode.getNodeNumber() ) {
151                    // no response expected
152                    _dummyNode.getNodeEventManager().resetNodeEventsToZero();
153                }   break;
154            default:
155                break;
156        }
157    }
158    
159    private void evLearn(int nn, int en, int index, int val){
160        
161        if ( val < 0 || val > 255 ) {
162            _dummyNode.sendCMDERR(11);
163            return;
164        }
165        if ( index < 0 || index > 255 ) {
166            _dummyNode.sendCMDERR(6);
167            return;
168        }
169        _dummyNode.getNodeEventManager().provideNodeEvent(nn,en).setEvVar(index,val);
170        if ( _dummyNode.getNodeEventManager().provideNodeEvent(nn,en).getIndex()< 0 ) {
171            _dummyNode.getNodeEventManager().provideNodeEvent(nn,en).setIndex(
172                _dummyNode.getNodeEventManager().getNextFreeIndex() );
173        }
174        _dummyNode.sendWRACK();
175    }
176
177    // private static final Logger log = LoggerFactory.getLogger(CbusDummyNodeCanListener.class);
178    
179}