001package jmri.jmrix.powerline.insteon2412s;
002
003import jmri.jmrix.powerline.SerialTrafficController;
004import jmri.jmrix.powerline.X10Sequence;
005import jmri.util.StringUtil;
006
007/**
008 * Contains the data payload of a serial reply packet. Note that it's _only_ the
009 * payload.
010 *
011 * @author Bob Jacobsen Copyright (C) 2002, 2006, 2007, 2008, 2009 Converted to
012 * multiple connection
013 * @author kcameron Copyright (C) 2011
014 */
015public class SpecificReply extends jmri.jmrix.powerline.SerialReply {
016
017    // create a new one
018    public SpecificReply(SerialTrafficController tc) {
019        super(tc);
020        setBinary(true);
021    }
022
023    public SpecificReply(String s, SerialTrafficController tc) {
024        super(tc, s);
025        setBinary(true);
026    }
027
028    @Override
029    public String toMonitorString() {
030        // check for valid length
031        int len = getNumDataElements();
032        StringBuilder text = new StringBuilder();
033        if ((getElement(0) & 0xFF) != Constants.HEAD_STX) {
034            text.append("INVALID HEADER: ").append(String.format("0x%1X", getElement(0) & 0xFF));
035            text.append(" len: ").append(len);
036        } else {
037            switch (getElement(1) & 0xFF) {
038                case Constants.FUNCTION_REQ_STD:
039                    text.append("Send Cmd ");
040                    if (len == 8 || len == 22) {
041                        if ((getElement(5) & Constants.FLAG_BIT_STDEXT) == Constants.FLAG_STD) {
042                            text.append(" Std");
043                        } else if (len == 22) {
044                            text.append(" Ext");
045                        }
046                        switch (getElement(5) & Constants.FLAG_MASK_MSGTYPE) {
047                            case Constants.FLAG_TYPE_P2P:
048                                text.append(" Direct");
049                                break;
050                            case Constants.FLAG_TYPE_ACK:
051                                text.append(" ACK");
052                                break;
053                            case Constants.FLAG_TYPE_NAK:
054                                text.append(" NAK");
055                                break;
056                            case Constants.FLAG_TYPE_GBCAST:
057                                text.append(" Group Broadcast");
058                                break;
059                            case Constants.FLAG_TYPE_GBCLEANUP:
060                                text.append(" Group Broadcast Cleanup");
061                                break;
062                            case Constants.FLAG_TYPE_GBCLEANACK:
063                                text.append(" Group Broadcast Cleanup ACK");
064                                break;
065                            case Constants.FLAG_TYPE_GBCLEANNAK:
066                                text.append(" Group Broadcast Cleanup NAK");
067                                break;
068                            default:
069                                log.warn("Unhandled msg type: {}", getElement(5) & Constants.FLAG_MASK_MSGTYPE);
070                                break;
071                        }
072                        text.append(" message,");
073                        text.append(String.format(" %d hops left",
074                            (getElement(5) & Constants.FLAG_MASK_HOPSLEFT >> Constants.FLAG_SHIFT_HOPSLEFT)));
075                        text.append(String.format(" , %d max hops", (getElement(5) & Constants.FLAG_MASK_MAXHOPS)));
076                        text.append(" addr ").append(String.format("%1$X.%2$X.%3$X",
077                            (getElement(2) & 0xFF), (getElement(3) & 0xFF), (getElement(4) & 0xFF)));
078                        switch (getElement(6) & 0xFF) {
079                            case Constants.CMD_LIGHT_ON_FAST:
080                                text.append(" ON FAST ");
081                                text.append((getElement(7) & 0xFF) / 256.0);
082                                break;
083                            case Constants.CMD_LIGHT_ON_RAMP:
084                                text.append(" ON RAMP ");
085                                text.append((getElement(7) & 0xFF) / 256.0);
086                                break;
087                            case Constants.CMD_LIGHT_OFF_FAST:
088                                text.append(" OFF FAST ");
089                                text.append((getElement(7) & 0xFF) / 256.0);
090                                break;
091                            case Constants.CMD_LIGHT_OFF_RAMP:
092                                text.append(" OFF RAMP ");
093                                text.append((getElement(7) & 0xFF) / 256.0);
094                                break;
095                            case Constants.CMD_LIGHT_CHG:
096                                text.append(" CHG ");
097                                text.append((getElement(7) & 0xFF) / 256.0);
098                                break;
099                            default:
100                                text.append(" Unknown cmd: ").append(StringUtil.twoHexFromInt(getElement(6) & 0xFF));
101                                break;
102                        }
103                        if ((getElement(8) & 0xFF) == Constants.REPLY_NAK) {
104                            text.append(" NAK - command not processed");
105                        }
106                    } else {
107                        text.append(" !! Length wrong: ").append(len);
108                    }
109                    break;
110                case Constants.POLL_REQ_BUTTON:
111                    text.append("Poll Button ");
112                    int button = ((getElement(2) & Constants.BUTTON_BITS_ID) >> 4) + 1;
113                    text.append(button);
114                    int op = getElement(2) & Constants.BUTTON_BITS_OP;
115                    if (op == Constants.BUTTON_HELD) {
116                        text.append(" HELD");
117                    } else if (op == Constants.BUTTON_REL) {
118                        text.append(" RELEASED");
119                    } else if (op == Constants.BUTTON_TAP) {
120                        text.append(" TAP");
121                    }
122                    break;
123                case Constants.POLL_REQ_BUTTON_RESET:
124                    text.append("Reset by Button at Power Cycle");
125                    break;
126                case Constants.FUNCTION_REQ_X10:
127                    text.append("Send Cmd X10 ");
128                    if ((getElement(3) & Constants.FLAG_BIT_X10_CMDUNIT) == Constants.FLAG_X10_RECV_CMD) {
129                        text.append(X10Sequence.formatCommandByte(getElement(2) & 0xFF));
130                    } else {
131                        text.append(X10Sequence.formatAddressByte(getElement(2) & 0xFF));
132                    }
133                    if ((getElement(4) & 0xFF) == Constants.REPLY_NAK) {
134                        text.append(" NAK - command not processed");
135                    }
136                    break;
137                case Constants.POLL_REQ_X10:
138                    text.append("Poll Cmd X10 ");
139                    if ((getElement(3) & Constants.FLAG_BIT_X10_CMDUNIT) == Constants.FLAG_X10_RECV_CMD) {
140                        text.append(X10Sequence.formatCommandByte(getElement(2) & 0xFF));
141                    } else {
142                        text.append(X10Sequence.formatAddressByte(getElement(2) & 0xFF));
143                    }
144                    break;
145                default: {
146                    text.append(" Unknown command: ").append(StringUtil.twoHexFromInt(getElement(1) & 0xFF));
147                    text.append(" len: ").append(len);
148                }
149            }
150        }
151        return text + "\n";
152    }
153
154    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SpecificReply.class);
155
156}