对接厦门名望LED

-----------------------------对接类(包含测试main方法)----------------------------------
协议开发 主要是对接厦门名望的led/三级诱导屏的语音和显示

import com.tnar.xiamen.model.LedText;
import com.tnar.xiamen.util.UdpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

/**
 * @author gaotianyu
 * @date Created in 2021-03-02 14:51
 */
public class MingWangHongKa {

    private final static Logger log = LoggerFactory.getLogger(UdpClient.class);

    private static final char[] hexArray = "0123456789ABCDEF".toCharArray();

    //test-main方法
    public static void main(String[] args) {
        //line代表想显示到第几行  kuan代表宽度多少 文字超过要设置移动
        List<LedText> texts = Arrays.asList( new LedText(1, "第一行测试左移", 1),
                new LedText(2, "第二行", 1),
                new LedText(3, "第三行", 1));
        try {
            for (LedText ledText : texts) {
                byte[] by=verticalLedTextToByte(ledText,12);
                System.out.println(toHex(by));
                DirectionalDatagramPacket packet = DirectionalDatagramPacket.getInstance("192.168.1.185",8800, Integer.MAX_VALUE);
                UdpClient.sendAndReceive(packet.newPacket(by));
            }
        } catch (Exception e) {
            log.info("异常:"+e);
        }
    }

    /**
     * 调用语音接口
     * @param text 播放的文字
     * @param ip 对应led的ip
     */
    public static void speakLed(String text,String ip) {
        try {
            byte[] by = getVoiceBytes(text);
            DirectionalDatagramPacket packet = DirectionalDatagramPacket.getInstance(ip,8800,Integer.MAX_VALUE);
            UdpClient.sendAndReceive(packet.newPacket(by));
        } catch (Exception e) {
            log.info("异常:"+e);
        }
    }

    /**
     * 调用显示接口
     * @param texts 显示的文字
     * @param ip 对应led/三级诱导屏幕ip
     * @param kuan 屏幕总宽度 宽度=横点阵数总和除以8   常态一小块为 横32 竖16点阵数 宽度就是32/8=4
     */
    public static void showLed(List<LedText> texts, String ip,int kuan){
        try {
            for (LedText ledText : texts) {
                byte[] by=verticalLedTextToByte(ledText,kuan);
                System.out.println(toHex(by));
                DirectionalDatagramPacket packet = DirectionalDatagramPacket.getInstance(ip,8800, Integer.MAX_VALUE);
                UdpClient.sendAndReceive(packet.newPacket(by));
            }
        } catch (Exception e) {
            log.info("异常:"+e);
        }
    }

    /**
     * 红卡(红色控制卡)语音
     * @param text
     * @return
     */
    private static byte[] getVoiceBytes(String text) {
        //输出流最终输出 要转byte[]数组
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //手动写入到一个底层输出流
        DataOutputStream dos = new DataOutputStream(bos);
        byte[] message =buildPlayMessageByteWithOptions(text);
        //播放信息长度
        int messageLength=message.length;
        //语音长度
        int yuyin= 2 + 16 + messageLength;
        //数据长度
        int shuju= 1 + 2 + yuyin + 2;
        //总长度
        int zong= 4 + 4 + 1 + 4 + 4 + shuju + 2;
        byte[] head = {(byte) 0xFE, (byte) 0x5C, (byte) 0x4B, (byte) 0x89};
        try {
            //头------------4
            dos.write(head);
            // 总长度--------4
            dos.write(intTo4ByteLE(zong));
            // 命令-语音播放-----------1
            dos.writeByte(0x68);
            // 232-2 的 2------------4
            dos.write(intTo4ByteLE(2));
            //数据长度--------------4
            dos.write(intTo4ByteLE(shuju));
            //数据协议固定头
            dos.writeByte(0xFD);
            //语音长度
            dos.write(intTo2ByteLE(yuyin));
            //语音文本固定头
            dos.writeByte(0x01);
            dos.writeByte(0x00);
            // 语音设置
            dos.writeByte(0x5b);
            dos.writeByte(0x76);
            dos.writeByte(0x31);  //音量
            dos.writeByte(0x5d);

            dos.writeByte(0x5b);
            dos.writeByte(0x73);
            dos.writeByte(0x35);  //语速
            dos.writeByte(0x5d);

            dos.writeByte(0x5b);
            dos.writeByte(0x74);
            dos.writeByte(0x35);  //语调
            dos.writeByte(0x5d);

            dos.writeByte(0x5b);
            dos.writeByte(0x6d);
            dos.writeByte(0x33);  //声音性别控制(男or女)
            dos.writeByte(0x5d);
            //语音内容
            dos.write(message);
            //预留
            dos.writeByte(0x00);
            dos.writeByte(0x00);
            //结束
            dos.writeByte(0xFF);
            dos.writeByte(0xFF);
        }catch (IOException e) {
            log.info("客户端异常:{}"+e);
        }finally {
            try{
                if (dos != null){
                    dos.close();
                }
                if (bos != null){
                    bos.close();
                }
            }catch (IOException e) {
                log.info("客户端finally异常:{}"+e);
            }
        }
        return bos.toByteArray();
    }

    /**
     * 蓝卡(蓝色控制卡)显示
     * @param text
     * @param line
     * @param color
     * @param fontSize
     * @param kuan
     * @return
     */
    private static byte[] getShowBytes(String text, int line, byte color, byte fontSize,int kuan) {
        //输出流最终输出 要转byte[]数组
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //手动写入到一个底层输出流
        DataOutputStream dos = new DataOutputStream(bos);
        //显示的数据
        byte[] message =buildPlayMessageByteWithOptions(text);
        // 文本内容长度
        // 显示数据+固定10位字节
        int textLength =  message.length + 10;
        // 数据长度
        // 25为窗口长度  4为素材属性长度  23为素材属性 4为文本内容长度 textLength为文本内容
        int contentLength = 25 + 4 + 23 + 4 + textLength;
        // 总长度
        // 17为头部长度   contentLength为数据长度   2为结束符
        int totalLength = 17 + contentLength + 2;
        //包头4字节
        byte[] head = {(byte) 0xFE, (byte) 0x5C, (byte) 0x4B, (byte) 0x89};
        try {
            //-----头部长度开始------
            //头------------4字节
            dos.write(head);
            //总长度--------4字节
            dos.write(intTo4ByteLE(totalLength));
            // 命令-文本播放-----------1字节
            dos.writeByte(0x31);
            // 发送编号--------------4字节
            dos.write(new byte[] {(byte) 0x92, 0x79, (byte) 0x95, 0x72});
            //数据长度------------4字节
            dos.write(intTo4ByteLE(contentLength));
            //-----头部长度结束------

            //-----数据长度开始------
            //-----窗口长度开始------
            //窗口编号-----9字节
            dos.write(new byte[] {0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30});
            dos.writeByte((byte) (0x30 + line));
            // 固定分隔符----1字节
            dos.writeByte((byte) 0x2C);
            //显示方式---1字节
            dos.writeByte(putShowStyle(message,kuan));
            //速度1-8 值越大速度越慢----1字节
            dos.writeByte(0x01);
            //停留  0-255秒 0不停留-----1字节
            dos.writeByte(0x00);
            // 开始时间-----6字节
            dos.write(new byte[] {0x30, 0x31, 0x30, 0x31, 0x30, 0x31});
            // 结束时间-----6字节
            dos.write(new byte[] {0x39, 0x39, 0x31, 0x32, 0x33, 0x31});
            //-----窗口长度结束------
            //文本属性长度
            dos.write(intTo4ByteLE(19));
            //-------文本属性长度开始-------
            // 第 7 个 0x01 所有素材立即更新 0x02 本素材立即更新,其他素材显示不变 0x03 本素材不立即更新,按正常显示进行。
            // 第 9 个 0x01 为 单基色, 0x02 为双基色
            dos.writeByte(0x55);
            dos.writeByte((byte)0xAA);
            dos.writeByte(0x00);
            dos.writeByte(0x00);
            dos.writeByte(0x37);
            dos.writeByte(0x01);                 //红卡的话填 0x32
            dos.writeByte(0x01);//第 7 个        //红卡的话填 0x32
            dos.writeByte(0x31);
            dos.writeByte(0x01);//第 9 个        //红卡的话填 0x32    0x31 为 单基色, 0x32 为双基色
            dos.writeByte(0x31);
            dos.writeByte(0x00);
            dos.writeByte(0x00);
            dos.writeByte(0x08);//单字长度=屏幕宽/8
            dos.writeByte(0x00);
            dos.writeByte(0x08);//单字高度
            dos.writeByte(0x00);
            dos.writeByte(color);//颜色
            dos.writeByte(fontSize);//字号
            dos.writeByte(0x00);
            //----文本属性长度结束-----------
            //文本内容长度
            dos.write(intTo4ByteLE(textLength));
            //-----文本内容长度开始------
            // 文本长度
            dos.write(message);
            // 文本固定结尾------10字节
            dos.write(new byte[] {(byte) 0xFF, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00});
            //-----文本内容长度结束------
            //-----数据长度结束------

            //结束符号-------2字节
            dos.writeByte(0xFF);
            dos.writeByte(0xFF);
        }catch (Exception e) {
            log.info("客户端异常:{}"+e);
        }finally {
            try{
                if (dos != null){
                    dos.close();
                }
                if (bos != null){
                    bos.close();
                }
            }catch (IOException e) {
                log.info("客户端finally异常:{}"+e);
            }
        }
        return bos.toByteArray();
    }

    //判断文字是否移动
    private static byte putShowStyle(byte[] showStyle,int kuan){
        if(showStyle.length<=kuan){
            // 显示效果 没有效果立即显示
            return (byte) 0x09;
        }else{
            // 显示文字超过屏幕宽度时显示左移
            return (byte) 0x01;
        }
    }

    //颜色字体转换
    private static byte[] verticalLedTextToByte(LedText ledText,int kuan) {
        int font=16;       //16位点阵       //0x01宋体 0x02楷体  0x03黑体  0x04隶书
        int size=1;
        byte fontSize=(byte)(font+size);
        byte color=0x01;   //设置默认为红色
        switch (ledText.getColor()) {
            case 1://红色
                color=0x01;
                break;
            case 2://绿色
                color=0x02;
                break;
            case 3://黄色
                color=0x03;
                break;
            default:
                break;
        }
        return getShowBytes(ledText.getText(), ledText.getLine(), color,fontSize,kuan);
    }

    //------下面方法都是进制转化

    public static String toHex(byte[] bytes) {
        return toHex(bytes, bytes.length);
    }

    public static String toHex(byte[] bytes, int len) {
        char[] hexChars = new char[len * 2];
        for (int j = 0; j < len; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

    private static byte[] buildPlayMessageByteWithOptions(String text) {
        return text.getBytes(Charset.forName("GBK"));
    }

    private static byte[] intTo4ByteLE(int yourInt){
        byte[]bytes=new byte[4];
        bytes[0]=(byte) (yourInt&0xff);
        bytes[1]=(byte) ((yourInt>>8)&0xff);
        bytes[2]=(byte) ((yourInt>>16)&0xff);
        bytes[3]=(byte) ((yourInt>>24)&0xff);
        return bytes;
    }

    private static byte[] intTo2ByteLE(int yourInt){
        byte[]bytes=new byte[2];
        bytes[0]=(byte) ((yourInt>>8)&0xff);
        bytes[1]=(byte) (yourInt&0xff);
        return bytes;
    }
}

----------------------------输出实体类---------------------

/**
 * @author gaotianyu
 * @date Created in 2021-03-02 14:50
 */
public class LedText {

    public LedText(int line, String text, int color) {
        this.line = line;
        this.text = text;
        this.color = color;
    }

    public LedText(int line, String text) {
        this.line = line;
        this.text = text;
    }

    public LedText() {
    }

    /**
     *
     */
    private int line;

    /**
     *
     */
    private String text;

    public int getColor() {
        return color;
    }

    public void setColor(int color) {
        this.color = color;
    }

    /**
     *
     */
    private int color;

    public int getLine() {
        return line;
    }

    public void setLine(int line) {
        this.line = line;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }


    @Override
    public String toString() {
        return "LedText{" +
                "line=" + line +
                ", text='" + text + '\'' +
                ", color=" + color +
                '}';
    }
}

--------------------------------------UDP发送类----------------------------------------

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.concurrent.TimeUnit;

/**
 * @author gaotianyu
 * @date Created in 2021-03-02 14:44
 */
//名望UDP
public class UdpClient {

    private final static Logger log = LoggerFactory.getLogger(UdpClient.class);

    private volatile static UdpClient instance;

    private DatagramSocket socket;

    private UdpClient() {
        try {
            //创建一个流套接字并将其连接到主机上
            socket = new DatagramSocket();
        } catch (SocketException e) {
            System.out.println("construct udp socket error: "+ e.getMessage());
        }
    }

    private static DatagramSocket getInstance() {
        if (instance == null) {
            synchronized (UdpClient.class) {
                if (instance == null) {
                    instance = new UdpClient();
                }
            }
        }
        return instance.socket;
    }

    public static void send(DatagramPacket packet, long delay) {
        try {
            getInstance().send(packet);
            if (delay > 0) {
                TimeUnit.MILLISECONDS.sleep(delay);
            }
        } catch (IOException | InterruptedException e) {
            log.info("异常:"+e);
        }
    }

    public static DatagramPacket sendAndReceive(DatagramPacket packet) {
        try {
            DatagramSocket datagramSocket = getInstance();
            //发送数据
            datagramSocket.send(packet);
            datagramSocket.setSoTimeout(1000);
            datagramSocket.receive(packet);
        } catch (SocketTimeoutException e) {
            log.info("异常:"+e);
        } catch (IOException e) {
            log.info("异常:"+e);
        }
        return packet;
    }
}

------------------------------发送初始化------------------------

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @author gaotianyu
 * @date Created in 2021-03-02 14:59
 */
public class DirectionalDatagramPacket {

    private final static Logger log = LoggerFactory.getLogger(DirectionalDatagramPacket.class);

    private InetAddress address;
    private int port;
    private int max_bytes = 0;

    public static DirectionalDatagramPacket getInstance(String ip, int port, int max_byte){

        DirectionalDatagramPacket ret = new DirectionalDatagramPacket();
        ret.init(ip, port, max_byte);
        return ret;
    }

    public DatagramPacket newPacket(byte[] bytes){
        if (address == null) {
            log.info("address为null");
            return null;
        }
        if (this.max_bytes > 0 && bytes.length > this.max_bytes){
            log.info("byte数组超过了最大限制");
            return null;
        }
        return new DatagramPacket(bytes ,bytes.length , address , port);
    }

    private void init(String ip, int port, int max_byte) {
        this.max_bytes = max_byte;
        this.port = port;
        try {
            this.address = InetAddress.getByName(ip);
        } catch (UnknownHostException e) {
            log.info("异常:"+e);
        }
    }

    private DirectionalDatagramPacket() {
        super();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值