1.代码如下

package com.xi.board.common;import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.checksum.crc16.CRC16XModem;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import org.apache.commons.lang3.StringUtils;import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;/*** 通讯接口* <p>* 本协议用于河南天龙电子有限公司生产的可变信息标志(包括全点阵的可变限速标志)* 与监控计算机之间的通信。可变信息标志操作系统 (CMSOS) 的版本应为第四版。可变信* 息标志的通信接口为网络接口 RJ-45 和串型接口 RS-232。*/
public class CommunicationUtils {/*** 数据帧 头*/private static String headHex = "02 ";/*** 数据帧 尾*/private static String tailHex = " 03";/*** 向可变信息标志上载文件的数据帧** @param address  帧地址* @param filePath 上载的文件*/public static List<String> getTxtFrame(String address, String filePath) {address = HexUtil.encodeHexStr(address + "10"); 帧地址 + 帧类型List<String> list = new ArrayList<>();//上载文件时,如文件长度超过 2048 字节,必须把文件分割成等于 2048 字节的若干段(最后一段为0-2047字节),每段依次发送 。File file = FileUtil.file(filePath);
//        System.out.println(FileUtil.readString(file, CharsetUtil.CHARSET_GBK));//打印文件内容String fileName = file.getName();String fileNameHexStr = HexUtil.encodeHexStr(fileName, CharsetUtil.CHARSET_GBK); //文件名 不定长 ASCII 码字符串String bodyHeadHex = fileNameHexStr + "2b"; //分隔符 1 字节,0x2B,表明文件名的结束long fileLength = file.length(); //获取文件指针偏移量long l = fileLength / 2048 + 1;for (int i = 0; i < l; i++) {String fileLengthHex = StringUtils.leftPad(String.valueOf(i * 2048), 8, "0");//文件指针偏移; 4 字节十六进制数,先发高字节,后发低字节String bodyHex = address + bodyHeadHex + fileLengthHex; //帧数据体byte[] bytes = FileUtil.readBytes(file);String encodeHexStr = HexUtil.encodeHexStr(bytes);if (i + 1 == l) {bodyHex += encodeHexStr.substring(i * 2048);} else {bodyHex += encodeHexStr.substring(i * 2048, (i + 1) * 2048);}//组装完整的一帧数据String data = checkAndAssemble(bodyHex);//添加进集合list.add(data);}return list;}/*** 向可变信息标志上载文件的数据帧(废弃-不实用)** @param address  帧地址* @param x        左上角x坐标* @param y        左上角y坐标* @param fontSize 字体大小(例如24x24点阵汉字就传24) 可选值 16 24 32 48* @param red      红色RGB值* @param green    绿色RGB值* @param blue     蓝色RGB值* @param content  文字内容* @return*/public static List<String> getTxtFrame(String address, Integer x, Integer y, Integer fontSize, Integer red, Integer green, Integer blue, String content) {address = HexUtil.encodeHexStr(address + "10"); //帧地址 + 帧类型List<String> list = new ArrayList<>();//上载文件时,如文件长度超过 2048 字节,必须把文件分割成等于 2048 字节的若干段(最后一段为0-2047字节),每段依次发送 。String fileNameHexStr = HexUtil.encodeHexStr("play.lst", CharsetUtil.CHARSET_GBK); //文件名 不定长 ASCII 码字符串String bodyHeadHex = fileNameHexStr + "2b"; //分隔符 1 字节,0x2B,表明文件名的结束try {content = new String(content.getBytes("gbk"), "gbk");} catch (UnsupportedEncodingException e) {System.out.println("转GBK编码失败!");e.printStackTrace();}String fileContent = "[list]\r\n" +"item_no=1\r\n" +"item0=500,1,2,\\C" + StringUtils.leftPad(x.toString(), 3, "0") + StringUtils.leftPad(y.toString(), 3, "0") +"\\fs" + StringUtils.leftPad(fontSize.toString(), 2, "0") + StringUtils.leftPad(fontSize.toString(), 2, "0") +"\\c" + StringUtils.leftPad(red.toString(), 3, "0") + StringUtils.leftPad(green.toString(), 3, "0") + StringUtils.leftPad(blue.toString(), 3, "0") + "000" +content + "\r\n";
//        System.out.println(fileContent);//打印文件内容long fileLength = fileContent.length(); //获取文件指针偏移量long l = fileLength / 2048 + 1;for (int i = 0; i < l; i++) {String fileLengthHex = StringUtils.leftPad(String.valueOf(i * 2048), 8, "0");//文件指针偏移; 4 字节十六进制数,先发高字节,后发低字节String bodyHex = address + bodyHeadHex + fileLengthHex; //帧数据体byte[] bytes = StrUtil.bytes(fileContent, CharsetUtil.CHARSET_GBK);String encodeHexStr = HexUtil.encodeHexStr(bytes);if (i + 1 == l) {bodyHex += encodeHexStr.substring(i * 2048);} else {bodyHex += encodeHexStr.substring(i * 2048, (i + 1) * 2048);}//组装完整的一帧数据String data = checkAndAssemble(bodyHex);//添加进集合list.add(data);}return list;}/*** 帧校验及其帧数据组装加上头和尾** @param bodyHex*/private static String checkAndAssemble(String bodyHex) {//帧校验采用 16 位的 CRC 校验String checkHex = checkHex(bodyHex);//帧数据体bodyHex += checkHex;//帧数据或帧校验中如有某个字节等于帧头、帧尾 或 0x1B ,则在发送此帧时需转换为两个字节,即 0x1B 和 (此字节减去 0x1B)bodyHex = hexEncodeHandle(bodyHex);//格式化十六进制字符串String frameHex = headHex + bodyHex + tailHex;
//        System.out.println("帧数据:" + frameHex.toUpperCase());return frameHex.toUpperCase();}/*** 帧校验采用 16 位的 CRC 校验** @param bodyHex* @return*/private static String checkHex(String bodyHex) {CRC16XModem crc16IBM = new CRC16XModem();crc16IBM.update(HexUtil.decodeHex(bodyHex));String checkHex = crc16IBM.getHexValue();
//        System.out.println("CRC16校验值:" + checkHex);return StringUtils.leftPad(checkHex,4,"0");}/*** 帧数据或帧校验中如有某个字节等于帧头、帧尾 或 0x1B ,则在发送此帧时需转换为两个字节,即 0x1B 和 (此字节减去 0x1B)* 0x02 转换为 0x1B, 0xE7* 0x03 转换为 0x1B, 0xE8* 0x1B 转换为 0x1B, 0x00** @param bodyHex* @return*/private static String hexEncodeHandle(String bodyHex) {//格式化16进制(字节用空格隔开)bodyHex = HexUtil.format(bodyHex).toLowerCase();//数据或帧校验中如有某个字节等于帧头、帧尾 或 0x1B ,则在发送此帧时需转换为两个字节,即 0x1B 和 (此字节减去 0x1B)bodyHex = bodyHex.replaceAll("1b", "1b 00").replaceAll("02", "1b e7").replaceAll("03", "1b e8");return bodyHex;}/*** 帧数据或帧校验中如有某个字节等于帧头、帧尾 或 0x1B ,则在发送此帧时需转换为两个字节,即 0x1B 和 (此字节减去 0x1B)* 00x1B, 0xE7 转换为 x02* 0x1B, 0xE8 转换为 0x03* 0x1B, 0x00 转换为 0x1B** @param bodyHex* @return*/private static String hexDecodeHandle(String bodyHex) {//格式化16进制(字节用空格隔开)bodyHex = HexUtil.format(bodyHex.replaceAll(" ", "")).toLowerCase();//数据或帧校验中如有某个字节等于帧头、帧尾 或 0x1B ,则在发送此帧时需转换为两个字节,即 0x1B 和 (此字节减去 0x1B)bodyHex = bodyHex.replaceAll("1b 00", "1b").replaceAll("1b e7", "02").replaceAll("1b e8", "03");return bodyHex.replace(" ", "");}/*** 十六进制字符串转二进制字符串** @param hexStr 十六进制字符串转二进制字符串* @return*/private static String hexToBinaryString(String hexStr) {StringBuilder stringBuilder = new StringBuilder();String tmp = "";boolean isHeadZero = true;for (int i = 0; i < hexStr.length(); i++) {tmp = "0000" + Integer.toBinaryString(Integer.parseInt(hexStr.substring(i, i + 1), 16));String substring = tmp.substring(tmp.length() - 4);if (isHeadZero && substring.equals("0000")) {  //针对天龙可变信息标志通讯协议进行特殊处理continue;} else {isHeadZero = false;}stringBuilder.append(substring);}return stringBuilder.toString();}/*** 发送 取可变信息标志的当前故障 的帧数据** @return*/public static String getErrorContent(String address) {address = HexUtil.encodeHexStr(address + "01"); //帧地址 + 帧类型String data = checkAndAssemble(address);return data;}/*** 解析 取可变信息标志的当前故障 的应答帧数据* 注:* 0* 1保留* 2控制器故障* 3显示模组故障* 4显示模组电源故障* ……** @param hexStr 应答帧数据* @return*/public static List<String> analysisErrorContent(String hexStr) {hexStr = hexDecodeHandle(hexStr);List<String> data = new ArrayList<>();//获取内容帧数据String bodyHex = hexStr.substring(6, hexStr.length() - 6);//16进制转字符串String decodeHexStr = HexUtil.decodeHexStr(bodyHex, CharsetUtil.CHARSET_GBK);for (int i = 0; i < decodeHexStr.length(); i++) {String errorCode = decodeHexStr.substring(i, i + 1);if (errorCode.equals("1")) { //每一位对应一种故障类型,如此位为1,则有故障;如此位为0,则无故障。data.add(errorCode);//故障类型添加到数组}}return data;}/*** 取可变信息标志的当前显示内容** @param address 帧地址* @return*/public static String getBoardContent(String address) {address = HexUtil.encodeHexStr(address + "97"); //帧地址 + 帧类型String data = checkAndAssemble(address);return data;}/*** 解析 取可变信息标志的当前显示内容 的应答帧数据** @param hexStr 应答帧数据* @param isProd 是否生产环境* @return*/public static HashMap<String, String> analysisBoardContent(String hexStr, Boolean isProd) {hexStr = hexDecodeHandle(hexStr);//获取内容帧数据String bodyHex = hexStr.substring(6, hexStr.length() - 6);//结果HashMap<String, String> map = new HashMap<>();if (isProd) {//hex转字符串String index = HexUtil.decodeHexStr(bodyHex.substring(0, 6), CharsetUtil.CHARSET_GBK); //序号String time = HexUtil.decodeHexStr(bodyHex.substring(6, 16), CharsetUtil.CHARSET_GBK); //停留时间String type = HexUtil.decodeHexStr(bodyHex.substring(16, 20), CharsetUtil.CHARSET_GBK); //出字方式String speed = HexUtil.decodeHexStr(bodyHex.substring(20, 30), CharsetUtil.CHARSET_GBK); //出字速度String content = HexUtil.decodeHexStr(bodyHex.substring(30), CharsetUtil.CHARSET_GBK); //显示字符串map.put("index", index);map.put("time", time);map.put("type", type);map.put("speed", speed);map.put("content", content);}else {map.put("content",  HexUtil.decodeHexStr(bodyHex, CharsetUtil.CHARSET_GBK));}return map;}public static List<String> getTxtFrameByFileContent(String address, String fileContent) {address = HexUtil.encodeHexStr(address + "10"); //帧地址 + 帧类型List<String> list = new ArrayList<>();//上载文件时,如文件长度超过 2048 字节,必须把文件分割成等于 2048 字节的若干段(最后一段为0-2047字节),每段依次发送 。String fileNameHexStr = HexUtil.encodeHexStr("play.lst", CharsetUtil.CHARSET_GBK); //文件名 不定长 ASCII 码字符串String bodyHeadHex = fileNameHexStr + "2b"; //分隔符 1 字节,0x2B,表明文件名的结束fileContent = fileContent.replaceAll("\r\n","\n").replaceAll("\n","\r\n");try {fileContent = new String(fileContent.getBytes("gbk"), "gbk");} catch (UnsupportedEncodingException e) {System.out.println("转GBK编码失败!");e.printStackTrace();}System.out.println(fileContent);//打印文件内容long fileLength = fileContent.length(); //获取文件指针偏移量long l = fileLength / 2048 + 1;for (int i = 0; i < l; i++) {String fileLengthHex = StringUtils.leftPad(String.valueOf(i * 2048), 8, "0");//文件指针偏移; 4 字节十六进制数,先发高字节,后发低字节String bodyHex = address + bodyHeadHex + fileLengthHex; //帧数据体byte[] bytes = StrUtil.bytes(fileContent, CharsetUtil.CHARSET_GBK);String encodeHexStr = HexUtil.encodeHexStr(bytes);if (i + 1 == l) {bodyHex += encodeHexStr.substring(i * 2048);} else {bodyHex += encodeHexStr.substring(i * 2048, (i + 1) * 2048);}//组装完整的一帧数据String data = checkAndAssemble(bodyHex);//添加进集合list.add(data);}return list;}
}

2.play.lst文件内容

[list]
item_no=1
item0=500,1,2,\C000000\fs2424\c000255000000谨慎驾驶注意安全

下载地址为:https://download.csdn.net/download/houjiezhuang/87065257

[天龙/汉威]可变信息标志通信协议-向可变信息标志上载文件(JAVA版)相关推荐

  1. 汉威危化品安全风险监测预警平台 助力企业摆脱新旧领域风险

    随着化工行业的发展与跨越,一大批石油化工.新材料.现代煤化工项目加快步伐,油气对外依存度持续攀升,但化工行业高风险性质仍未改变,甚至面对着生产.储存.运输.废弃处置等传统风险,与新能源.海洋石油.氢能 ...

  2. 汉威智慧水务守护城镇供水“最后一公里”

    水是生命之源,与人们的生活息息相关,身居高层住宅的你,对自来水怎么从水厂流入你家水龙头了解多少呢?流入你家水龙头的水有没有安全隐患呢? 由于城市高层建筑发展迅速,市政供水管网压力不足,输水网络太广,水 ...

  3. 汉威科技气体监测报警系列产品守护油气设施安全

    进入21世纪,在纷繁复杂的国际能源地缘政治背景下,国际油价剧烈波动,我国的能源安全问题也随之凸现.作为国家经济发展和人民生活的重要保障,能源问题关乎国计民生.所以,提升石油.天然气等储备.传输设施的安 ...

  4. 汉威科技转型记:物联网的未来模式应该是“五星级酒店托管”

     关注ITValue,查看企业级市场最新鲜.最具价值的报道! 汉威科技展示厅 郑州,对于异乡客而言,这座中原城市往往只是祖国交通枢纽上贯通南北的重要节点.若是说它与科技有什么关系的话,或许离不开那座& ...

  5. 世界传感器大会:汉威科技新品震撼全场!

    8月21日,2022世界传感器大会如约在郑州开幕,这场堪称全球顶级的行业盛会,汇聚了全球近200家传感器领域的知名企业,他们也带来了自家的最新产品. 这次大会不仅是行业前沿成果分享的平台,更是各家企业 ...

  6. logo语言linux,用 screenfetch 和 linux_logo 显示带有酷炫 Linux 标志的基本硬件信息

    想在屏幕上显示出你的 Linux 发行版的酷炫标志和基本硬件信息吗?不用找了,来试试超赞的 screenfetch 和 linux_logo 工具. Linux Logo 来看看 screenfetc ...

  7. 用screenfetch显示带有酷炫Linux标志的基本硬件信息

    想在屏幕上显示出你的 Linux 发行版的酷炫标志和基本硬件信息吗?不用找了,来试试超赞的 screenfetch 和 linux_logo 工具. Linux Logo 来看看 screenfetc ...

  8. 汉威大厦中智公积金_中智租房支取公积金相关说明

    办理公积金业务的员工,需本人携带所有材料原件及复印件到中智公司办理,不得委托他人代办. 办理地点:朝阳区光华路 7 号汉威大厦西区 27 层公积金组 一.主租房人为中智雇员: 1 .房屋租赁合同原件及 ...

  9. Java基础练习题5--[给定一段字符串,将里面的信息进行提取,(注意:需要考虑信息是可变的)String s=“张三:上机成绩=90,笔试成绩=78“+“李四:上机成绩=68,笔试成绩......]

    题目:给定一段字符串,将里面的信息进行提取,(注意:需要考虑信息是可变的) String s = "张三:上机成绩=90,笔试成绩=78;" + "李四:上机成绩=68, ...

最新文章

  1. c语言:输出一个菱形图
  2. 使用GDAL创建Erdas格式的金字塔
  3. bzoj[1835][ZJOI2010]base 基地选址
  4. 对asn.net三层架构的初步认识
  5. hdu 3046(最小割最大流)
  6. ftp.listfiles()卡住,不报错
  7. python字典按键值排序_Python字典『键 值』排序
  8. 美术外包管理从原始1.0到工业4.0
  9. [简明python教程]学习笔记2014-04-28 23:45:56
  10. 区块链 Zilliqa是什么
  11. 数据库 的日志已满,备份该数据库的事务日志以释放一些日志空间的解决办法 ...
  12. ITSS服务管理体系建立流程(四个阶段)附:广东软件行业协会ITSS评估
  13. 折线统计html,canvas制作简单的HTML图表,折线或者矩形统计(原创)
  14. php微信授权登录sdk,微信授权登录如何使用?总结微信授权登录实例用法
  15. 常见的DNS记录类型有哪些?如何查询DNS解析记录?
  16. maven 多模块项目,打包其中一个项目,Could not find artifact org.javaboy:commons:pom:1.0-SNAPSHOT
  17. 【VC++游戏开发#六】2D篇 —— 粒子系统(一):浪漫唯美的场景之雪花飞舞
  18. CAD中如何把一个DWG文件里的块插入到另一个DWG中
  19. 利用webSocket实现扫码登录PC端
  20. runjs.work中的代码如何分享给别人

热门文章

  1. 超简单二进制转十六进制口诀!!
  2. 【京东商城首页实战9】导航菜单栏和下拉列表
  3. 初识ESP8266(一)————接入点与无线终端模式
  4. 课表APP(未完成版)
  5. Widget API 接口实例演示(二) ——Telephony类和PIM类
  6. 多叉树 转换为二叉树 算法
  7. VUE+WebPack实现精美Html5游戏设计:cardBattle的启动场景设计
  8. eclipse开发Android app的一些问题及解决方法
  9. 号称可替代MATLAB的国产软件来了!
  10. 腾讯唯一时序数据库:CTSDB 解密