001package jmri.jmrix.ipocs;
002
003import org.slf4j.Logger;
004import org.slf4j.LoggerFactory;
005
006import jmri.Turnout;
007import jmri.implementation.AbstractTurnout;
008import jmri.jmrix.ipocs.protocol.Message;
009import jmri.jmrix.ipocs.protocol.enums.RqPointsCommand;
010import jmri.jmrix.ipocs.protocol.packets.Packet;
011import jmri.jmrix.ipocs.protocol.packets.PointsStatusPacket;
012import jmri.jmrix.ipocs.protocol.packets.ThrowPointsPacket;
013
014/**
015 *
016 * @author Fredrik Elestedt Copyright (C) 2020
017 * @since 4.21.2
018 */
019public class IpocsTurnout extends AbstractTurnout implements IpocsClientListener {
020
021  private final static Logger log = LoggerFactory.getLogger(IpocsTurnout.class);
022  private final IpocsPortController portController;
023
024  IpocsTurnout(IpocsPortController portController, String systemName, String userName) {
025    super(systemName, userName);
026    this.portController = portController;
027    this.portController.addListener(this);
028    super._validFeedbackNames = new String[]{"MONITORING"};
029    super._validFeedbackModes = new int[]{MONITORING};
030    super._validFeedbackTypes = MONITORING;
031    super._activeFeedbackType = MONITORING;
032    Message msg = portController.getLastStatus(userName);
033    if (msg != null) {
034      onMessage(null, msg);
035    }
036  }
037
038  @Override
039  protected void forwardCommandChangeToLayout(int s) {
040    Message order = new Message();
041    order.setObjectName(getUserName());
042    ThrowPointsPacket packet = new ThrowPointsPacket();
043    switch (s) {
044      case THROWN:
045        packet.setCommand(RqPointsCommand.Left);
046        break;
047      case CLOSED:
048        packet.setCommand(RqPointsCommand.Right);
049        break;
050      case UNKNOWN:
051        // ignore, but not an error as normal during AbstractTurnout testCreate()
052        return;
053      default:
054        log.error("Unknown turnout order state: {}", s);
055        return;
056    }
057    order.getPackets().add(packet);
058    portController.send(order);
059  }
060
061  @Override
062  protected void turnoutPushbuttonLockout(boolean locked) {
063    // Not supported
064  }
065
066  // ipocs turnouts don't support inversion, no need to override super.canInvert() reply
067
068  @Override
069  public void clientConnected(IpocsClientHandler client) {
070    // Nothing to do when a client connects.
071  }
072
073  @Override
074  public void clientDisconnected(IpocsClientHandler client) {
075    newKnownState(Turnout.UNKNOWN);
076  }
077
078  @Override
079  public void onMessage(IpocsClientHandler client, Message msg) {
080    if (!msg.getObjectName().equals(super.getUserName())) {
081      return;
082    }
083    // We have a status, let's interpret it.
084    for (Packet packet : msg.getPackets()) {
085        if (packet.getId() == PointsStatusPacket.IDENT) {
086            switch (((PointsStatusPacket) packet).getState()) {
087                case Left:
088                    newKnownState(Turnout.THROWN);
089                    break;
090                case Right:
091                    newKnownState(Turnout.CLOSED);
092                    break;
093                case Moving:
094                    newKnownState(Turnout.INCONSISTENT);
095                    break;
096                case OutOfControl:
097                    newKnownState(Turnout.UNKNOWN);
098                    break;
099                default:
100                    log.error("Unknown turnout state {}", ((PointsStatusPacket) packet).getState().toString());
101                    break;
102            }
103        }
104    }
105  }
106}