package com.genersoft.iot.vmp.gb28181.utils; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.Gb28181Sdp; import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo; import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.GitUtil; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.header.Subject; import gov.nist.javax.sip.message.SIPRequest; import org.apache.commons.lang3.RandomStringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.ObjectUtils; import javax.sdp.SdpFactory; import javax.sdp.SdpParseException; import javax.sdp.SessionDescription; import javax.sip.PeerUnavailableException; import javax.sip.SipFactory; import javax.sip.header.FromHeader; import javax.sip.header.Header; import javax.sip.header.UserAgentHeader; import javax.sip.message.Request; import java.text.ParseException; import java.time.LocalDateTime; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * @author panlinlin * @version 1.0.0 * @description JAIN SIP的工具类 * @createTime 2021年09月27日 15:12:00 */ public class SipUtils { private final static Logger logger = LoggerFactory.getLogger(SipUtils.class); public static String getUserIdFromFromHeader(Request request) { FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME); return getUserIdFromFromHeader(fromHeader); } /** * 从subject读取channelId * */ public static String getChannelIdFromRequest(Request request) { Header subject = request.getHeader("subject"); if (subject == null) { // 如果缺失subject return null; } return ((Subject) subject).getSubject().split(":")[0]; } public static String getUserIdFromFromHeader(FromHeader fromHeader) { AddressImpl address = (AddressImpl)fromHeader.getAddress(); SipUri uri = (SipUri) address.getURI(); return uri.getUser(); } public static String getNewViaTag() { return "z9hG4bK" + RandomStringUtils.randomNumeric(10); } public static UserAgentHeader createUserAgentHeader(GitUtil gitUtil) throws PeerUnavailableException, ParseException { List agentParam = new ArrayList<>(); agentParam.add("WVP-Pro "); if (gitUtil != null ) { if (!ObjectUtils.isEmpty(gitUtil.getBuildVersion())) { agentParam.add("v"); agentParam.add(gitUtil.getBuildVersion() + "."); } if (!ObjectUtils.isEmpty(gitUtil.getCommitTime())) { agentParam.add(gitUtil.getCommitTime()); } } return SipFactory.getInstance().createHeaderFactory().createUserAgentHeader(agentParam); } public static String getNewFromTag(){ return UUID.randomUUID().toString().replace("-", ""); // return getNewTag(); } public static String getNewTag(){ return String.valueOf(System.currentTimeMillis()); } /** * 云台指令码计算 * * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 * @param moveSpeed 镜头移动速度 默认 0XFF (0-255) * @param zoomSpeed 镜头缩放速度 默认 0X1 (0-255) */ public static String cmdString(int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) { int cmdCode = 0; if (leftRight == 2) { cmdCode|=0x01; // 右移 } else if(leftRight == 1) { cmdCode|=0x02; // 左移 } if (upDown == 2) { cmdCode|=0x04; // 下移 } else if(upDown == 1) { cmdCode|=0x08; // 上移 } if (inOut == 2) { cmdCode |= 0x10; // 放大 } else if(inOut == 1) { cmdCode |= 0x20; // 缩小 } StringBuilder builder = new StringBuilder("A50F01"); String strTmp; strTmp = String.format("%02X", cmdCode); builder.append(strTmp, 0, 2); strTmp = String.format("%02X", moveSpeed); builder.append(strTmp, 0, 2); builder.append(strTmp, 0, 2); //优化zoom低倍速下的变倍速率 if ((zoomSpeed > 0) && (zoomSpeed <16)) { zoomSpeed = 16; } strTmp = String.format("%X", zoomSpeed); builder.append(strTmp, 0, 1).append("0"); //计算校验码 int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + moveSpeed + moveSpeed + (zoomSpeed /*<< 4*/ & 0XF0)) % 0X100; strTmp = String.format("%02X", checkCode); builder.append(strTmp, 0, 2); return builder.toString(); } public static String getNewCallId() { return (int) Math.floor(Math.random() * 1000000000) + ""; } public static int getTypeCodeFromGbCode(String deviceId) { if (ObjectUtils.isEmpty(deviceId)) { return 0; } return Integer.parseInt(deviceId.substring(10, 13)); } /** * 判断是否是前端外围设备 * @param deviceId * @return */ public static boolean isFrontEnd(String deviceId) { int typeCodeFromGbCode = getTypeCodeFromGbCode(deviceId); return typeCodeFromGbCode > 130 && typeCodeFromGbCode < 199; } /** * 从请求中获取设备ip地址和端口号 * @param request 请求 * @param sipUseSourceIpAsRemoteAddress false 从via中获取地址, true 直接获取远程地址 * @return 地址信息 */ public static RemoteAddressInfo getRemoteAddressFromRequest(SIPRequest request, boolean sipUseSourceIpAsRemoteAddress) { String remoteAddress; int remotePort; if (sipUseSourceIpAsRemoteAddress) { remoteAddress = request.getPeerPacketSourceAddress().getHostAddress(); remotePort = request.getPeerPacketSourcePort(); }else { // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息 // 获取到通信地址等信息 remoteAddress = request.getTopmostViaHeader().getReceived(); remotePort = request.getTopmostViaHeader().getRPort(); // 解析本地地址替代 if (ObjectUtils.isEmpty(remoteAddress) || remotePort == -1) { remoteAddress = request.getPeerPacketSourceAddress().getHostAddress(); remotePort = request.getPeerPacketSourcePort(); } } return new RemoteAddressInfo(remoteAddress, remotePort); } public static DeviceChannel updateGps(DeviceChannel deviceChannel, String geoCoordSys) { if (deviceChannel.getLongitude()*deviceChannel.getLatitude() > 0) { if (geoCoordSys == null) { geoCoordSys = "WGS84"; } if ("WGS84".equals(geoCoordSys)) { deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude()); deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude()); Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude()); deviceChannel.setLongitudeGcj02(position[0]); deviceChannel.setLatitudeGcj02(position[1]); }else if ("GCJ02".equals(geoCoordSys)) { deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude()); deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude()); Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude()); deviceChannel.setLongitudeWgs84(position[0]); deviceChannel.setLatitudeWgs84(position[1]); }else { deviceChannel.setLongitudeGcj02(0.00); deviceChannel.setLatitudeGcj02(0.00); deviceChannel.setLongitudeWgs84(0.00); deviceChannel.setLatitudeWgs84(0.00); } }else { deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude()); deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude()); deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude()); deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude()); } return deviceChannel; } public static Gb28181Sdp parseSDP(String sdpStr) throws SdpParseException { // jainSip不支持y= f=字段, 移除以解析。 int ssrcIndex = sdpStr.indexOf("y="); int mediaDescriptionIndex = sdpStr.indexOf("f="); // 检查是否有y字段 SessionDescription sdp; String ssrc = null; String mediaDescription = null; if (mediaDescriptionIndex == 0 && ssrcIndex == 0) { sdp = SdpFactory.getInstance().createSessionDescription(sdpStr); }else { String lines[] = sdpStr.split("\\r?\\n"); StringBuilder sdpBuffer = new StringBuilder(); for (String line : lines) { if (line.trim().startsWith("y=")) { ssrc = line.substring(2); }else if (line.trim().startsWith("f=")) { mediaDescription = line.substring(2); }else { sdpBuffer.append(line.trim()).append("\r\n"); } } sdp = SdpFactory.getInstance().createSessionDescription(sdpBuffer.toString()); } return Gb28181Sdp.getInstance(sdp, ssrc, mediaDescription); } public static String getSsrcFromSdp(String sdpStr) { // jainSip不支持y= f=字段, 移除以解析。 int ssrcIndex = sdpStr.indexOf("y="); if (ssrcIndex == 0) { return null; } String lines[] = sdpStr.split("\\r?\\n"); for (String line : lines) { if (line.trim().startsWith("y=")) { return line.substring(2); } } return null; } public static String parseTime(String timeStr) { if (ObjectUtils.isEmpty(timeStr)){ return null; } LocalDateTime localDateTime; try { localDateTime = LocalDateTime.parse(timeStr); }catch (DateTimeParseException e) { try { localDateTime = LocalDateTime.parse(timeStr, DateUtil.formatterISO8601); }catch (DateTimeParseException e2) { logger.error("[格式化时间] 无法格式化时间: {}", timeStr); return null; } } return localDateTime.format(DateUtil.formatter); } }