001package jmri.jmrix.roco.z21.messageformatters; 002 003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 004import jmri.jmrix.Message; 005import jmri.jmrix.roco.z21.Z21MessageFormatter; 006import jmri.jmrix.roco.z21.Z21MessageUtils; 007import jmri.jmrix.roco.z21.Z21Reply; 008 009/** 010 * Formats Z21 CAN Detector Replies. 011 * 012 * @author Paul Bender Copyright (C) 2025 013 */ 014public class Z21CANDetectorReplyFormatter implements Z21MessageFormatter { 015 016 @Override 017 public boolean handlesMessage(Message m) { 018 return m instanceof Z21Reply && ((Z21Reply) m).getOpCode() == 0x00C4; 019 } 020 021 @Override 022 @SuppressFBWarnings(value = "SF_SWITCH_FALLTHROUGH") 023 public String formatMessage(Message m) { 024 if(!handlesMessage(m)){ 025 throw new IllegalArgumentException("Message is not a Z21 CAN Detector Reply"); 026 } 027 int networkID = ( m.getElement(4)&0xFF) + ((m.getElement(5)&0xFF) << 8); 028 int address = ( m.getElement(6)&0xFF) + ((m.getElement(7)&0xFF) << 8); 029 int port = ( m.getElement(8) & 0xFF); 030 int type = ( m.getElement(9) & 0xFF); 031 int value1 = (m.getElement(10)&0xFF) + ((m.getElement(11)&0xFF) << 8); 032 int value2 = (m.getElement(12)&0xFF) + ((m.getElement(13)&0xFF) << 8); 033 String typeString = ""; 034 String value1String; 035 String value2String = ""; 036 switch(type){ 037 case 0x01: 038 typeString = "Input Status"; 039 switch(value1){ 040 case 0x0000: 041 value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_FREE_WITHOUT"); 042 break; 043 case 0x0100: 044 value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_FREE_WITH"); 045 break; 046 case 0x1000: 047 value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_BUSY_WITHOUT"); 048 break; 049 case 0x1100: 050 value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_BUSY_WITH"); 051 break; 052 case 0x1201: 053 value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_OVERLOAD_1"); 054 break; 055 case 0x1202: 056 value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_OVERLOAD_2"); 057 break; 058 case 0x1203: 059 value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_OVERLOAD_3"); 060 break; 061 default: 062 value1String = "<unknown>"; 063 } 064 break; 065 case 0x11: 066 case 0x12: 067 case 0x13: 068 case 0x14: 069 case 0x15: 070 case 0x16: 071 case 0x17: 072 case 0x18: 073 case 0x19: 074 case 0x1A: 075 case 0x1B: 076 case 0x1C: 077 case 0x1D: 078 case 0x1E: 079 case 0x1F: 080 typeString = "Occupancy Info"; 081 value1String = getCanDetectorLocoAddressString(value1); 082 value2String = getCanDetectorLocoAddressString(value2); 083 break; 084 default: 085 value1String = "" + value1; 086 value2String = "" + value2; 087 } 088 089 return Bundle.getMessage("Z21CANDetectorReply",Integer.toHexString(networkID),address,port,typeString,value1String,value2String); 090 } 091 092 // address value is the 16 bits of the two bytes containing the 093 // address. The most significan two bits represent the direction. 094 private String getCanDetectorLocoAddressString(int addressValue) { 095 String addressString; 096 if(addressValue==0) { 097 addressString="end of list"; 098 } else { 099 addressString = "" + (Z21MessageUtils.getCanDetectorLocoAddress(addressValue)).toString(); 100 int direction = (0xC000&addressValue); 101 switch (direction) { 102 case 0x8000: 103 addressString += " direction forward"; 104 break; 105 case 0xC000: 106 addressString += " direction reverse"; 107 break; 108 default: 109 addressString += " direction unknown"; 110 } 111 } 112 return addressString; 113 } 114 115}