import java.io.*;
import java.net.*;

public class TcpServer {
    // 0：DO 继电器输出接口
    // 1：DI 开关量输入接口
    // 2：AI 模拟量输入接口
    // 3：VO 语音输出接口
    // 4：PC电脑开关机接口
    private int Type = 3;
    private BufferedReader reader;
    private BufferedWriter writer;
    private ServerSocket server;
    private Socket client;
    //服务端使用的端口
    private int serverPort = 6000;

    void TcpServerDemo() {

        try {
            System.out.println("本机作为服务端");
            System.out.println("本机端口：" + serverPort);
            server = new ServerSocket(serverPort);

            System.out.println("等待客户机的连接");
            client = server.accept();
            System.out.println("连接成功");
            String clientAddr = client.getRemoteSocketAddress().toString().substring(1);//需要跟下一句合并
            String[] clientAddrs = clientAddr.split(":");
            System.out.println("客户端IP：" + clientAddrs[0] + " 端口：" + clientAddrs[1]);

            reader = new BufferedReader(new InputStreamReader(client.getInputStream(),"GB2312"));
            writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream(),"GB2312"));
            switch (Type)
            {
                case 0:
                    TestDO();
                    break;
                case 1:
                    TestDI();
                    break;
                case 2:
                    TestAI();
                    break;
                case 3:
                    TestVO();
                    break;
                case 4:
                    TestPC();
                    break;
                default:
                    break;
            }
            System.out.println("测试完成！");

            System.out.println("更多控制指令的详细解释请查阅《网络控制器AT指令手册V2.9.PDF》");
            System.out.println("本Demo仅用于开发参考，不能直接用于商业项目实施！");
        }catch(Exception e) {
            e.printStackTrace();
        }
    }

    private void TestDO()
    {
        try
        {
            System.out.println("DO 继电器输出接口测试");
            //控制 DO 继电器输出接口 OUT1 吸合；发送指令：AT+STACH1=1<回车换行>
            String msg = "AT+STACH1=1\r\n";// \r\n(回车换行)
            System.out.println("控制 DO 继电器输出接口 OUT1 吸合，发送指令：AT+STACH1=1\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //时间单位改成 秒；发送指令：AT+DLYUNIT=0<回车换行>
            msg = "AT+DLYUNIT=0\r\n";// \r\n(回车换行)
            System.out.println("时间单位改成 秒；发送指令：AT+DLYUNIT=0\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //控制 DO 继电器输出接口 OUT1 点动开，开启后延时5秒再关闭
            msg =  "AT+STACH1=3,5,100000,1000000\r\n";// \r\n(回车换行)
            System.out.println("控制 DO 继电器输出接口 OUT1 点动开，开启后延时5秒再关闭；发送指令：AT+STACH1=3,5,100000,1000000\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //控制 DO 继电器输出接口 OUT1~OUT4 间隔 1 秒轮流吸合
            msg =  "AT+DODLY=1,1,4,1,1\r\n";// \r\n(回车换行)
            System.out.println("控制 DO 继电器输出接口 OUT1~OUT4 间隔 1 秒轮流吸合；发送指令：AT+DODLY=1,1,4,1,1\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //继电器 OUT1 每天早上 8 点定时吸合
            msg =  "AT+AUTOCONT=2,TASK1,[CYC:1],[T:3,0|1|2|3|4|5|6,08:00:00],[DO:0,1,1,100000,100000,1000000],[N:1,0]\r\n";// \r\n(回车换行)
            System.out.println("继电器 OUT1 每天早上 8 点定时吸合；发送指令：AT+AUTOCONT=2,TASK1,[CYC:1],[T:3,0|1|2|3|4|5|6,08:00:00],[DO:0,1,1,100000,100000,1000000],[N:1,0]\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //N1/DI1 联动控制继电器 OUT1 点动输出 5 秒
            msg =  "AT+LINKAGE1=3,5,100000,1,1000000\r\n";// \r\n(回车换行)
            System.out.println("N1/DI1 联动控制继电器 OUT1 点动输出 5 秒；发送指令：AT+LINKAGE1=3,5,100000,1,1000000\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //上电默认状态设置为吸合
            msg =  "AT+DODEFSTA=1\r\n";// \r\n(回车换行)
            System.out.println("上电默认状态设置为吸合；发送指令：AT+DODEFSTA=1\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //使能状态主动上传
            msg =  "AT+KPUPLOAD=1\r\n";// \r\n(回车换行)
            System.out.println("使能状态主动上传；发送指令：AT+KPUPLOAD=1\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //使能掉电保存
            msg =  "AT+KPKEEP=1\r\n";// \r\n(回车换行)
            System.out.println("使能掉电保存；发送指令：AT+KPUPLOAD=1\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");

        }catch(Exception e) {
            e.printStackTrace();
        }
    }

    private void TestDI()
    {
        try
        {
            //上传类型 uploadType 0：被动上传  1：定时上传  2：触发上传(所有通道)  3：触发上传(单个通道)
            int uploadType = 1;
            int uploadInterval = 300; //上传间隔 单位：10ms

            System.out.println("DI 开关量输入接口测试");
            //读取 DI 开关量输入接口 IN1/DI1 的状态 被动上传(实时读取)
            String msg = "AT+OCCH1=?\r\n";// \r\n(回车换行)
            System.out.println("读取 DI 开关量输入接口 IN1/DI1 的状态：发送指令：AT+OCCH1=?\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //设置DI上传模式
            msg = "AT+OCMOD="+uploadType+","+ (uploadType == 1? uploadInterval : 0)+"\r\n";// \r\n(回车换行)
            System.out.println("设置DI上传模式；发送指令："+msg.replace("\r\n","")+"\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");

        }catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private void TestAI()
    {
        try
        {
            //上传类型 uploadType 0：被动上传  1：定时上传  2：触发上传  3：定时+触发上传
            int uploadType = 1;
            int uploadInterval = 30; //上传间隔 单位：100ms

            System.out.println("AI 模拟量输入接口");
            //设置 AI1 接口的信号类型是电压型
            String msg = "AT+AIMODE1=0\r\n";// \r\n(回车换行)
            System.out.println("设置 AI1 接口的信号类型是电压型，发送指令：AT+AIMODE1=0\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //读取 AI1 接口实时采样值 被动上传(实时读取)
            msg = "AT+AIVALUE1=?\r\n";// \r\n(回车换行)
            System.out.println("读取 AI1 接口实时采样值；发送指令：AT+AIVALUE1=?\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            if (uploadType == 1)
            {
                //设置3秒上传1次AI1接口采样值(定时上传)
                uploadInterval = 30;
                msg = "AT+AIUPLOAD1="+uploadType+","+uploadInterval+"\r\n";
            }
            else if (uploadType == 2)
            {
                //设置AI1接口采样值高于2000并持续3秒触发上传
                uploadInterval = 0;
                msg = "AT+AIUPLOAD1="+uploadType+","+uploadInterval +",20,0,2000,0,0\r\n";
            }
            else if (uploadType == 3)
            {
                //设置3秒上传1次和AI1接口采样值高于2000并持续3秒触发上传
                uploadInterval = 30;
                msg = "AT+AIUPLOAD1="+uploadType+","+uploadInterval +",20,0,2000,0,0\r\n";
            }
            System.out.println("读取 AI1 接口实时采样值；发送指令："+msg.trim()+"\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("设备应答：" + msg);
            System.out.println("指令执行成功!");
        }catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    // 0：晓玲（女声）
    // 1：尹小坚（男声）
    // 2：易小强（男声）
    // 3：田蓓蓓（女声）
    // 4：唐老鸭（效果器）
    // 5：小燕子（女童声）
    private int TtsPronunciationPeople = 0;

    // 语调
    // 0 - 不识别汉语拼音 1 - 识别汉语拼音
    // 注意：
    // 1）拼音格式为：1 至 6 位字母 + 1 位数字
    // 2）声调用 1 位数字表示 ：1 阴平、2 阳平、3 上声、4 去声、5 轻声
    private int ToneOfVoice = 0;

    // 语速 1-10档
    private int TtsSpeed = 5;

    // 语调 1-10档
    private int TtsIntonation = 5;

    // 音量 1-10档
    private int TtsVolume = 5;

    // TTS循环次数
    private int TtsTimes = 1;

    // TTS间隔时间
    private int TtsInterval = 1;
    private void TestVO()
    {
        try {
            System.out.println("VO 语音输出接口测试：");
            //控制 VO1 接口播放文字“泥人科技” 实时播放
            System.out.println("控制 VO1 接口播放文字“泥人科技” 实时播放  发送指令：AT+TTS1=1,0,8\\r\\n泥人科技\\r\\n");
            String msg = "AT+TTS1=1,0,8\r\n泥人科技";
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("指令应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(2000);

            //控制 VO1 接口播放语音文件 1
            System.out.println("控制 VO1 接口播放语音文件 1   发送指令：AT+AUDIO1=1,10\\r\\n");
            msg = "AT+AUDIO1=1,10\r\n";
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("指令应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //VO1 接口每天早上 8 点播放语音文件 1  定时播放
            System.out.println("VO1 接口每天早上 8 点播放语音文件 1  发送指令：AT+AUTOCONT=2,TASK1,[CYC:1],[T:3,0|1|2|3|4|5|6,08:00:00],[VO:0,1,1,10,1,0],[N:1,0]\\r\\n");
            msg = "AT+AUTOCONT=2,TASK1,[CYC:1],[T:3,0|1|2|3|4|5|6,08:00:00],[VO:0,1,1,10,1,0],[N:1,0]\r\n";
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("指令应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //IN1/DI1 联动播放语音文件 1  开关量联动播放
            System.out.println("IN1/DI1 联动播放语音文件 1 发送指令：AT+AUTOCONT=2,TASK1,[CYC:1],[DI:3,1,1],[VO:0,1,1,10,1,0],[N:1,0]\\r\\n");
            msg = "AT+AUTOCONT=2,TASK1,[CYC:1],[DI:3,1,1],[VO:0,1,1,10,1,0],[N:1,0]\r\n";
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("指令应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //使用VO1 接口、晓玲的声音 声调：0 语速：5 语调：5 音量：5播放文本  文本播放拓展(发音人、声调、语速、语调)
            String[] pronunciationPeople = new String[] { "3", "51", "52", "53", "54", "55" };
            //if (string.IsNullOrEmpty(txt)) return;
            String txt = "[m" + pronunciationPeople[TtsPronunciationPeople] + "][s"
                    + TtsSpeed + "][t" + TtsIntonation
                    + "][v" + TtsVolume + "]" + "欢迎[i" + ToneOfVoice+"]shi3用" + "泥人科技1234567890";
            byte[] bytes = txt.getBytes("GB2312");
            //以GB2312的格式转为byte数组
            msg = "AT+TTS1=1,0," + TtsTimes + ","
                    + TtsInterval + "," + bytes.length + "\r\n" + txt;
            //将字符串指令转换为byte数组  编码为GB2312
            System.out.println("使用VO1 接口、晓玲的声音 语速：5 语调：5 音量：5播放“泥人科技1234567890”  发送指令："+msg+"\\r\\n");
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("指令应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void TestPC()
    {
        try {
            //上传类型 uploadType 0：被动上传  1：定时上传  2：触发上传  3：定时+触发上传
            int uploadType = 1;
            int uploadInterval = 30; //上传间隔 单位：100ms
            System.out.println("电脑开关机接口测试:");

            System.out.println("发送电脑开机指令：AT+PCSSSTA=1\\r\\n");
            String msg = "AT+PCSSSTA=1\r\n";
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("电脑开关机应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(1000);

            System.out.println("发送每天早上8点定时开机指令：AT+AUTOCONT=2,TASK1,[T:3,0|1|2|3|4|5|6,08:00:00],[PC:0,1],[N:1,0]\\r\\n");
            msg = "AT+AUTOCONT=2,TASK1,[T:3,0|1|2|3|4|5|6,08:00:00],[PC:0,1],[N:1,0]\r\n";
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("电脑开关机应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //被动上传(实时读取)
            System.out.println("读取电脑开关机状态：AT+PCSSSTA=?\\r\\n");
            msg = "AT+PCSSSTA=?\r\n";
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("电脑开关机应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);

            //定时上传、触发上传、定时 + 触发上传
            if (uploadType == 1)
            {
                //设置 3 秒上传 1 次电脑开关机状态
                msg = "AT+PCSSSTA="+uploadType+","+uploadInterval+"\r\n";
                System.out.println("发送设置 3 秒上传 1 次电脑开关机状态指令："+msg.trim()+"\\r\\n");
            }
            else if (uploadType == 2)
            {
                //设置电脑开关机状态触发上传
                msg = "AT+PCSSSTA="+uploadType+"+\r\n";
                System.out.println("发送设置电脑开关机状态触发上传指令："+msg.trim()+"\\r\\n");
            }
            else if (uploadType == 3)
            {
                //设置3秒和触发电脑开关机 上传1次电脑开关机状态
                msg = "AT+PCSSSTA="+uploadType+","+uploadInterval+"\r\n";
                System.out.println("发送设置3秒和触发电脑开关机 上传1次电脑开关机状态指令："+msg.trim()+"\\r\\n");
            }
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("电脑开关机应答：" + msg);
            System.out.println("指令执行成功!");
			Thread.sleep(100);
			
			System.out.println("上电自动开机功能启用：AT+PCSSAUTO=1\\r\\n");
            msg = "AT+PCSSAUTO=1\r\n";
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("电脑开关机应答：" + msg);
            System.out.println("指令执行成功!");
            Thread.sleep(100);
			
			System.out.println("上上电禁用机箱按键，即按键失效：AT+PCSSEXTKEY=1\\r\\n");
            msg = "AT+PCSSEXTKEY=1\r\n";
            //发送数据
            writer.write(msg);
            writer.flush();
            //读数据
            msg = reader.readLine();
            msg = msg.replace("\r\n", "\\r\\n");
            System.out.println("电脑开关机应答：" + msg);
            System.out.println("指令执行成功!");

        }catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        TcpServer tcp = new TcpServer();
        tcp.TcpServerDemo();
    }
}
