diff --git a/pom.xml b/pom.xml index 98d68bf..9112935 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,12 @@ + org.apache.commons + commons-lang3 + 3.8.1 + + + org.springframework.boot spring-boot-starter diff --git a/src/main/java/com/example/mina/boxhandler/Lte3000VirtualBoxHandler.java b/src/main/java/com/example/mina/boxhandler/Lte3000VirtualBoxHandler.java new file mode 100644 index 0000000..0345470 --- /dev/null +++ b/src/main/java/com/example/mina/boxhandler/Lte3000VirtualBoxHandler.java @@ -0,0 +1,209 @@ +package com.example.mina.boxhandler; + +import com.example.mina.base.AbstractVirtualBoxHandler; +import com.example.mina.base.CommandHelper; +import com.example.mina.util.LogUtils; +import com.example.mina.entity.Lte3000DataBuffer; +import com.example.mina.helper.Lte3000CommandHelper; +import lombok.extern.slf4j.Slf4j; +import org.apache.mina.core.buffer.IoBuffer; +import org.apache.mina.core.session.IoSession; + +/** + * @author 杜云山 + * @date 21/03/05 + */ +@Slf4j +public class Lte3000VirtualBoxHandler extends AbstractVirtualBoxHandler { + + private static final byte[] Response_46;// = "Fv7.46 Pv2.15 LTE2250/032X032".getBytes(); + private static final byte[] Response_53 = new byte[]{0x06, 0x30, 0x30, 0x53, 0x03, 0x56}; + private static final byte[] Response_58 = new byte[]{0x06, 0x30, 0x30, 0x58, 0x47, 0x4D, 0x4F, 0x03, 0x18}; + + static { + byte[] bs = "Fv7.46 Pv2.15 XRM2250/032X064".getBytes(); + Response_46 = new byte[bs.length + 6]; + System.arraycopy(bs, 0, Response_46, 4, bs.length); + Response_46[0] = 0x06; + Response_46[1] = 0x30; + Response_46[2] = 0x30; + Response_46[3] = 0x46; + Response_46[bs.length + 4] = 0x03; + Lte3000CommandHelper.setCHK(Response_46); + } + + private Lte3000DataBuffer dataBuffer; + + public Lte3000VirtualBoxHandler() { + this.initMatrix(); + } + + @Override + protected void initMatrix() { + + int row = 32; + int col = 32; + int maxAttenuate = 30; + + dataBuffer = new Lte3000DataBuffer(row, col,maxAttenuate); + } + + private int getBcdPort(byte a, byte b, byte c) { + return (CommandHelper.BCD_REV[a] - 30) * 100 + (CommandHelper.BCD_REV[b] - 30) * 10 + (CommandHelper.BCD_REV[c] - 30); + } + private int getBcdAttn(byte a, byte b) { + return (CommandHelper.BCD_REV[a] - 30) * 10 + (CommandHelper.BCD_REV[b] - 30); + } + + @Override + public void messageReceived(IoSession session, Object message) { + + IoBuffer ioBuffer = (IoBuffer) message; + byte[] bytes = ioBuffer.array(); + + byte[] result = handleMessage(bytes, bytes.length); + + session.write(IoBuffer.wrap(result)); + } + + @Override + protected byte[] handleMessage(byte[] cmd, int len) { + + + + byte[] buffer; + LogUtils.printLTEcmd(cmd, len); + + + //F: Firmware Version / Unit ID P.82 + //0x46 + if (cmd[3] == 'F') { + buffer = Response_46; + LogUtils.println("--Response F(Firmware)--", buffer); + return buffer; + } + + //O:Query Output Channel P.106 + //0x4F + if (cmd[3] == 'O') { + int col = this.getBcdPort(cmd[4], cmd[5], cmd[6]); + + int row = 0; + for (int i = 1; i <= dataBuffer.getMaxRow(); i++) { + if (dataBuffer.getAttenuation(i, col) > 0) { + row = i; + break; + } + } + + buffer = new byte[]{0x06, cmd[1], cmd[2], 0x4F, CommandHelper.BCD[(byte)((row / 100) + 30)], + CommandHelper.BCD[(byte)(((row % 100) / 10) + 30)], CommandHelper.BCD[(byte)((row % 10) + 30)] + , 0x03, 0}; + + Lte3000CommandHelper.setCHK(buffer); + + + LogUtils.println("--Response O(Output)--", buffer); + return buffer; + } + + //S: Set Crosspoint P.115 + //0x53 + if (cmd[3] == 'S') { + buffer = Response_53; + + int row = this.getBcdPort(cmd[7], cmd[8], cmd[9]); + int col = this.getBcdPort(cmd[4], cmd[5], cmd[6]); + + LogUtils.println(" connect row/col ", row + "/" + col); + + for (int i = 1; i <= dataBuffer.getMaxRow(); i++) { + if (i == row) { + dataBuffer.setAttenuation(i, col, 1); + }else{ + dataBuffer.setAttenuation(i, col, 0); + } + + } + + LogUtils.println("--Response S--", buffer); + return buffer; + } + + + //XGMO: Set Gain Control to Manual Mode - Output p.137 + //0x58 0x47 0x4D 0x4F + if (cmd[3] == 'X' && cmd[4] == 'G' && cmd[5] == 'M' && cmd[6] == 'O' ) { +// receive - 0x2 0x30 0x30 0x58 0x47 0x4D 0x4F 0x30 0x30 0x31 0x40 0x2D 0x36 0x33 0x2E 0x30 0x3 0x5B +// 00XGMO001@-63.0[ +// set col/attn 1/63 + + int col = this.getBcdPort(cmd[7], cmd[8], cmd[9]); + int attn = this.getBcdAttn(cmd[12], cmd[13]); + if (cmd[11] == 0x2D) { +// attn *= -1; + } + LogUtils.println(" set col/attn ", col + "/" + attn); + + dataBuffer.setOffset(col, attn); + buffer = Response_58; + + LogUtils.println("--Response XGMO(set)--", buffer); + return buffer; + } + + + //XGRO: Gain Control Read Status - Output P.139 + if (cmd[3] == 'X' && cmd[4] == 'G' && cmd[5] == 'R' && cmd[6] == 'O' ) { +// 06 XX XX 58 46 20 4F 4D/41 40 2B/2D XX XX 2E +// ACK ADR ADR X G R O M/A @ +/- 10s 1s . +// XX 03 XX +// tenths ETX CHK + + int col = this.getBcdPort(cmd[7], cmd[8], cmd[9]); + int attn = dataBuffer.getOffset(col); + + buffer = new byte[]{0x06, 0x30, 0x30, 0x58, 0x47, 0x52, 0x4F, 0x4D, 0x40, 0x2B, + CommandHelper.BCD[(byte)((attn / 10) + 30)], CommandHelper.BCD[(byte)((attn % 10) + 30)] + , 0x2E, 0x30, 0x03, 0}; + + Lte3000CommandHelper.setCHK(buffer); + + LogUtils.println("--Response XGRO(get)--", buffer); + return buffer; + } + + + buffer = new byte[len + 2]; + buffer[0] = (byte)0xFE; + buffer[1] = (byte)0xFE; + System.arraycopy(cmd, 0, buffer, 2, len); + + return buffer; + } + + @Override + public void sessionCreated(IoSession session) { + + log.info("--- abstractVirtual server session created"); + } + + @Override + public void sessionOpened(IoSession session) { + + log.info("--- abstractVirtual server session Opened"); + } + + @Override + public void sessionClosed(IoSession session) { + + log.info("--- abstractVirtual server session Closed"); + } + + @Override + public void messageSent(IoSession session, Object message) { + + log.info("--- abstractVirtual 发送数据成功!{}", message); + } + +} diff --git a/src/main/java/com/example/mina/boxserver/Lte3000VirtualBoxServer.java b/src/main/java/com/example/mina/boxserver/Lte3000VirtualBoxServer.java new file mode 100644 index 0000000..f24a9f6 --- /dev/null +++ b/src/main/java/com/example/mina/boxserver/Lte3000VirtualBoxServer.java @@ -0,0 +1,19 @@ +package com.example.mina.boxserver; + +import com.example.mina.boxhandler.AeroflexVirtualBoxHandler; +import com.example.mina.boxhandler.Lte3000VirtualBoxHandler; +import com.example.mina.property.AeroflexVirtualBoxProperties; +import com.example.mina.property.Lte3000VirtualBoxProperties; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; + + +@Slf4j +@Configuration(proxyBeanMethods = false) +public class Lte3000VirtualBoxServer extends AbstractVirtualBoxServer { + + public Lte3000VirtualBoxServer(Lte3000VirtualBoxProperties lte3000VirtualBoxProperties) { + super(lte3000VirtualBoxProperties, new Lte3000VirtualBoxHandler()); + } + +} diff --git a/src/main/java/com/example/mina/entity/Lte3000DataBuffer.java b/src/main/java/com/example/mina/entity/Lte3000DataBuffer.java new file mode 100644 index 0000000..dab93a6 --- /dev/null +++ b/src/main/java/com/example/mina/entity/Lte3000DataBuffer.java @@ -0,0 +1,31 @@ +package com.example.mina.entity; + +import com.example.mina.base.AbstractHardwareDataBuffer; + + +public class Lte3000DataBuffer extends AbstractHardwareDataBuffer { + + public Lte3000DataBuffer(int row, int col, int maxAtten){ + super(row, col, col, maxAtten); + + matrixData = new Entry[row][col]; + offsetData = new Entry[col]; // LTE is on col + + int offset = maxAtten; + for(int i = 0; i < col; i++){ + offsetData[i] = new Entry(i, 0, "rr", offset, false); +// offset += 5; + } + + for(int i = 0; i < row; i++){ + for(int k = 0; k < col; k++){ + if (i == k) { + matrixData[i][k] = new Entry(i, k, "kk", 1, false); + }else{ + matrixData[i][k] = new Entry(i, k, "kk", 0, false); + } + } + } + } + +} diff --git a/src/main/java/com/example/mina/helper/Lte3000CommandHelper.java b/src/main/java/com/example/mina/helper/Lte3000CommandHelper.java new file mode 100644 index 0000000..7182f95 --- /dev/null +++ b/src/main/java/com/example/mina/helper/Lte3000CommandHelper.java @@ -0,0 +1,180 @@ +package com.example.mina.helper; + +import org.apache.commons.lang3.ArrayUtils; + +import java.nio.charset.StandardCharsets; + +public class Lte3000CommandHelper { + +//20- 21-! 22-" 23-# 24-$ 25-% 26-& 27-' 28-( 29-) 2a-* 2b-+ 2c-, 2d-- 2e-. 2f-/ +//30-0 31-1 32-2 33-3 34-4 35-5 36-6 37-7 38-8 39-9 +// 3a-: 3b-; 3c-< 3d-= 3e-> 3f-? 40-@ +// 41-A 42-B 43-C 44-D 45-E 46-F 47-G 48-H 49-I 4a-J 4b-K 4c-L 4d-M 4e-N 4f-O 50-P 51-Q 52-R 53-S 54-T 55-U 56-V 57-W 58-X 59-Y 5a-Z +// 5b-[ 5c-\ 5d-] 5e-^ 5f-_ 60-` +// 61-a 62-b 63-c 64-d 65-e 66-f 67-g 68-h 69-i 6a-j 6b-k 6c-l 6d-m 6e-n 6f-o 70-p 71-q 72-r 73-s 74-t 75-u 76-v 77-w 78-x 79-y 7a-z +// 7b-{ 7c-| 7d-} 7e-~ + + ////def for Quinteck: +//#define STX 0x02 +//#define ETX 0x03 +//#define ACK 0x06 +//#define NAK 0x15 +//#define RBM_ADDR_H 0x50 +//#define RBM_ADDR_L 0x00 +//#define NEXUS_ADDR_H 0x40 +//#define NEXUS_ADDR_L 0x00 + + public static final byte STX = 0X02; + public static final byte ETX = 0X03; + public static final byte ACK = 0X06; + public static final byte NAK = 0X15; + + public static void main(String[] args) { + byte[] bs = Lte3000CommandHelper.genCommandGetCross(1); + + + + System.exit(0); + + } + + public static void setCHK(byte[] bs) { + bs[bs.length - 1] = 0; + + for (int i = 0; i < bs.length - 1; i++) { + bs[bs.length - 1] ^= bs[i]; + } + } + + public static int getBcdPort(byte a, byte b, byte c) { + //return (CommandHelper.BCD_REV[a] - 30) * 100 + (CommandHelper.BCD_REV[b] - 30) * 10 + (CommandHelper.BCD_REV[c] - 30); + return Integer.parseInt(new StringBuilder().append(a - 0x30).append(b - 0x30).append(c - 0x30).toString()); + } + + /** + * input: "-12.2" + * @param a sign + * @param b tenth + * @param c single + * @param d dot + * @param e tenths + * @return int -12 if -12.2 + */ + public static int getBcdAttn(byte a, byte b, byte c, byte d, byte e) { + String port = new StringBuilder() + //.append((char)a) // sign -/+ + .append(b - 0x30).append(c - 0x30) // integer + //.append((char)d) // . + //.append(e - 0x30) + .toString(); // tenths. + return Integer.parseInt(port); + } + + public static byte[] genCommandSetAttn(int col, int val){ + byte[] command = new byte[18]; + byte[] vCol = intToReversedBytes(col); + byte[] vVal = intToReversedBytes(val); + command[0] = STX; + command[1] = 0x30; + command[2] = 0x30; + command[3] = 'X'; + command[4] = 'G'; + command[5] = 'M'; + command[6] = 'O'; + command[7] = vCol.length > 2 ? vCol[2] : 0x30; + command[8] = vCol.length > 1 ? vCol[1] : 0x30; + command[9] = vCol.length > 0 ? vCol[0] : 0x30; + command[10] = '@'; + command[11] = '-'; + command[12] = vVal.length > 1 ? vVal[1] : 0x30; + command[13] = vVal.length > 0 ? vVal[0] : 0x30; + command[14] = '.'; + command[15] = '0'; + command[16] = ETX; + command[17] = 0; + + setCHK(command); + + return command; + } + + public static byte[] genCommandGetAttn(int col){ + byte[] command = new byte[12]; + byte[] vCol = intToReversedBytes(col); + command[0] = STX; + command[1] = 0x30; + command[2] = 0x30; + command[3] = 'X'; + command[4] = 'G'; + command[5] = 'R'; + command[6] = 'O'; + command[7] = vCol.length > 2 ? vCol[2] : 0x30; + command[8] = vCol.length > 1 ? vCol[1] : 0x30; + command[9] = vCol.length > 0 ? vCol[0] : 0x30; + command[10] = ETX; + command[11] = 0; + + setCHK(command); + + return command; + } + + + public static byte[] genCommandSetCross(int row, int col){ + byte[] command = new byte[12]; + byte[] vRow = intToReversedBytes(row); + byte[] vCol = intToReversedBytes(col); + command[0] = STX; + command[1] = 0x30; + command[2] = 0x30; + command[3] = 'S'; + command[4] = vCol.length > 2 ? vCol[2] : 0x30; + command[5] = vCol.length > 1 ? vCol[1] : 0x30; + command[6] = vCol.length > 0 ? vCol[0] : 0x30; + command[7] = vRow.length > 2 ? vRow[2] : 0x30; + command[8] = vRow.length > 1 ? vRow[1] : 0x30; + command[9] = vRow.length > 0 ? vRow[0] : 0x30; + command[10] = ETX; + command[11] = 0; + + setCHK(command); + + return command; + } + + /** + * 1234 => "1234" => ['4','3','2','1'] + * 1 => [31] + * 12 => [32,31] + * 123 => [33,32,31] + * @param value value to convert + * @return result + */ + public static byte[] intToReversedBytes(int value) { + byte[] result = String.valueOf(value).getBytes(StandardCharsets.US_ASCII); + ArrayUtils.reverse(result); + return result; + } + + public static byte[] genCommandGetCross(int col){ + byte[] command = new byte[9]; + byte[] value = String.valueOf(col).getBytes(StandardCharsets.US_ASCII); + ArrayUtils.reverse(value); + command[0] = STX; + command[1] = 0x30; + command[2] = 0x30; + command[3] = 'O'; + command[4] = value.length >= 3 ? value[2] : 0x30; + command[5] = value.length >= 2 ? value[1] : 0x30; + command[6] = value.length >= 1 ? value[0] : 0x30; + command[7] = ETX; + command[8] = 0; + + setCHK(command); + + return command; + } + + + +} \ No newline at end of file diff --git a/src/main/java/com/example/mina/property/Lte3000VirtualBoxProperties.java b/src/main/java/com/example/mina/property/Lte3000VirtualBoxProperties.java new file mode 100644 index 0000000..dde4586 --- /dev/null +++ b/src/main/java/com/example/mina/property/Lte3000VirtualBoxProperties.java @@ -0,0 +1,22 @@ +package com.example.mina.property; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author 杜云山 + * @date 2021/03/05 + */ +@Getter +@Setter +@ToString +@ConfigurationProperties(prefix = "lte3000-virtual") +@Configuration +@EnableConfigurationProperties(Lte3000VirtualBoxProperties.class) +public class Lte3000VirtualBoxProperties extends AbstractVirtualBoxProperties { + +} \ No newline at end of file diff --git a/src/main/java/com/example/mina/util/LogUtils.java b/src/main/java/com/example/mina/util/LogUtils.java new file mode 100644 index 0000000..c0f9bda --- /dev/null +++ b/src/main/java/com/example/mina/util/LogUtils.java @@ -0,0 +1,63 @@ +package com.example.mina.util; + +public class LogUtils { + + public static String toHexString(byte b){ + String s = Integer.toHexString(b); + if(s.length() > 2){ + s = s.substring(s.length() - 2); + } + s = "0x" +s.toUpperCase(); + + return s; + } + + public static String toHexString(byte[] b) { + if(b == null ) return ""; + + StringBuilder s = new StringBuilder(); + + for(int i = 0; i < b.length; i++){ + s.append(toHexString(b[i])).append(" "); + } + + return s.toString(); + } + + public static String toHexString(byte[] b, int len) { + if(b == null) return ""; + int min = Math.min(len, b.length); + StringBuilder s = new StringBuilder(); + for(int i = 0; i < min; i++){ + s.append(toHexString(b[i])).append(" "); + } + + return s.toString(); + } + + + public static void println(String s) { + System.out.println(s); + } + public static void println(String s, String s2) { + System.out.println(s + s2); + } + public static void println(String title, byte[] bs) { + + System.out.println(title + toHexString(bs)); + } + public static void println(String title, byte[] bs, int len) { + + System.out.println(title + toHexString(bs, len)); + } + + public static void printLTEcmd(byte[] bs, int len) { + + for (int i = 0; i < len; i++) { + System.out.print((char)bs[i]); + } + System.out.println(); + } + + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f5400a5..c648799 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -6,3 +6,7 @@ rbm3000-vitualbox-virtual: name: rbm3000-vitualbox-virtual enable: true port: 9101 +lte3000-virtual: + name: lte3000-virtual + enable: true + port: 9102 -- libgit2 0.21.2