设备心跳
This commit is contained in:
parent
b76658ad20
commit
29fd114361
@ -44,6 +44,10 @@
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-xml</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
|
@ -48,9 +48,9 @@ public class JsonUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T parse(String json, TypeReference<T> clazz) {
|
||||
public static <T> T parse(String xml, TypeReference<T> clazz) {
|
||||
try {
|
||||
return mapper.readValue(json, clazz);
|
||||
return mapper.readValue(xml, clazz);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
|
@ -0,0 +1,111 @@
|
||||
package cn.skcks.docking.gb28181.common.xml;
|
||||
|
||||
import com.fasterxml.jackson.core.json.JsonReadFeature;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
@SuppressWarnings({"unused"})
|
||||
public class XmlUtils {
|
||||
private static final ObjectMapper mapper = new XmlMapper();
|
||||
static {
|
||||
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
|
||||
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
|
||||
// 如果json中有新增的字段并且是实体类类中不存在的,不报错
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false);
|
||||
// 允许出现特殊字符和转义符
|
||||
mapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
|
||||
// 允许出现单引号
|
||||
mapper.configure(JsonReadFeature.ALLOW_SINGLE_QUOTES.mappedFeature(), true);
|
||||
// 大驼峰 (首字母大写)
|
||||
mapper.setPropertyNamingStrategy(new PropertyNamingStrategies.UpperCamelCaseStrategy());
|
||||
}
|
||||
|
||||
public static String toXml(Object obj) {
|
||||
try {
|
||||
return mapper.writeValueAsString(obj);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] toByteXml(Object obj) {
|
||||
try {
|
||||
return mapper.writeValueAsString(obj).getBytes();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] toByteXml(Object obj, Charset charset) {
|
||||
try {
|
||||
return mapper.writeValueAsString(obj).getBytes(charset);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] toByteXml(Object obj, String charset) {
|
||||
try {
|
||||
return mapper.writeValueAsString(obj).getBytes(Charset.forName(charset));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T parse(byte[] xml, Class<T> clazz) {
|
||||
return parse(new String(xml), clazz);
|
||||
}
|
||||
|
||||
public static <T> T parse(byte[] xml, Class<T> clazz, Charset charset) {
|
||||
return parse(new String(xml, charset), clazz);
|
||||
}
|
||||
|
||||
public static <T> T parse(byte[] xml, Class<T> clazz, String charset) {
|
||||
return parse(new String(xml, Charset.forName(charset)), clazz);
|
||||
}
|
||||
|
||||
public static <T> T parse(String xml, Class<T> clazz) {
|
||||
try {
|
||||
return mapper.readValue(xml, clazz);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T parse(byte[] xml, TypeReference<T> clazz) {
|
||||
return parse(new String(xml), clazz);
|
||||
}
|
||||
|
||||
public static <T> T parse(byte[] xml, TypeReference<T> clazz, Charset charset) {
|
||||
return parse(new String(xml, charset), clazz);
|
||||
}
|
||||
|
||||
public static <T> T parse(byte[] xml, TypeReference<T> clazz, String charset) {
|
||||
return parse(new String(xml, Charset.forName(charset)), clazz);
|
||||
}
|
||||
|
||||
public static <T> T parse(String xml, TypeReference<T> clazz) {
|
||||
try {
|
||||
return mapper.readValue(xml, clazz);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T convert(Object object, Class<T> clazz) {
|
||||
return XmlUtils.parse(XmlUtils.toXml(object), clazz);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package cn.skcks.docking.gb28181.core.sip.gb28181.constant;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class CmdType {
|
||||
public static final String KEEPALIVE = "Keepalive";
|
||||
public static final String DEVICE_CONFIG = "DeviceConfig";
|
||||
public static final String DEVICE_CONTROL = "DeviceControl";
|
||||
public static final String DEVICE_STATUS = "DeviceStatus";
|
||||
public static final String CATALOG = "Catalog";
|
||||
public static final String ALARM = "Alarm";
|
||||
public static final String MOBILE_POSITION = "MobilePosition";
|
||||
public static final String BROADCAST = "Broadcast";
|
||||
public static final String RECORD_INFO = "RecordInfo";
|
||||
public static final String MEDIA_STATUS = "MediaStatus";
|
||||
public static final String CONFIG_DOWNLOAD = "ConfigDownload";
|
||||
public static final String PRESET_QUERY = "PresetQuery";
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package cn.skcks.docking.gb28181.core.sip.gb28181.constant;
|
||||
|
||||
public class DefaultConstant {
|
||||
public class GB28181Constant {
|
||||
public static final String CHARSET = "GB2312";
|
||||
public static final String GEO_COORD_SYS = "WGS84";
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package cn.skcks.docking.gb28181.core.sip.message.processor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -15,8 +14,10 @@ public interface MessageProcessor {
|
||||
|
||||
class Method {
|
||||
public static final String REGISTER = "REGISTER";
|
||||
public static final String MESSAGE = "MESSAGE";
|
||||
}
|
||||
|
||||
void init();
|
||||
void process(RequestEvent requestEvent);
|
||||
|
||||
default MessageFactory getMessageFactory() {
|
||||
|
@ -0,0 +1,77 @@
|
||||
package cn.skcks.docking.gb28181.core.sip.message.processor.message.request;
|
||||
|
||||
import cn.skcks.docking.gb28181.common.xml.XmlUtils;
|
||||
import cn.skcks.docking.gb28181.core.sip.gb28181.constant.CmdType;
|
||||
import cn.skcks.docking.gb28181.core.sip.message.processor.message.request.dto.MessageDto;
|
||||
import cn.skcks.docking.gb28181.core.sip.gb28181.constant.GB28181Constant;
|
||||
import cn.skcks.docking.gb28181.core.sip.listener.SipListener;
|
||||
import cn.skcks.docking.gb28181.core.sip.message.processor.MessageProcessor;
|
||||
import cn.skcks.docking.gb28181.core.sip.message.sender.SipMessageSender;
|
||||
import cn.skcks.docking.gb28181.core.sip.utils.SipUtil;
|
||||
import cn.skcks.docking.gb28181.orm.mybatis.dynamic.model.DockingDevice;
|
||||
import cn.skcks.docking.gb28181.service.docking.device.DockingDeviceService;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sip.RequestEvent;
|
||||
import javax.sip.header.CallIdHeader;
|
||||
import javax.sip.message.Response;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class MessageRequestProcessor implements MessageProcessor {
|
||||
private final SipListener sipListener;
|
||||
private final DockingDeviceService deviceService;
|
||||
private final SipMessageSender sender;
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
public void init() {
|
||||
sipListener.addProcessor(Method.MESSAGE, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(RequestEvent requestEvent) {
|
||||
SIPRequest request = (SIPRequest)requestEvent.getRequest();
|
||||
String deviceId = SipUtil.getUserIdFromFromHeader(request);
|
||||
CallIdHeader callIdHeader = request.getCallIdHeader();
|
||||
|
||||
MessageDto messageDto = XmlUtils.parse(request.getRawContent(), MessageDto.class, GB28181Constant.CHARSET);
|
||||
log.debug("接收到的消息 => {}", messageDto);
|
||||
|
||||
DockingDevice device = deviceService.getDevice(deviceId);
|
||||
String senderIp = request.getLocalAddress().getHostAddress();
|
||||
|
||||
if(device == null){
|
||||
log.info("未找到相关设备信息 => {}", deviceId);
|
||||
Response response = response(request,Response.NOT_FOUND,"设备未注册");
|
||||
sender.send(senderIp,response);
|
||||
return;
|
||||
}
|
||||
|
||||
if(messageDto.getCmdType().equalsIgnoreCase(CmdType.KEEPALIVE)){
|
||||
Response response = response(request,Response.OK,"OK");
|
||||
// 更新设备在线状态
|
||||
deviceService.online(device, response);
|
||||
sender.send(senderIp,response);
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public Response response(SIPRequest request, int status, String message){
|
||||
if (request.getToHeader().getTag() == null) {
|
||||
request.getToHeader().setTag(SipUtil.generateTag());
|
||||
}
|
||||
SIPResponse response = (SIPResponse)getMessageFactory().createResponse(status, request);
|
||||
if (message != null) {
|
||||
response.setReasonPhrase(message);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package cn.skcks.docking.gb28181.core.sip.message.processor.message.request.dto;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
|
||||
import lombok.Data;
|
||||
|
||||
@JacksonXmlRootElement(localName = "xml")
|
||||
@Data
|
||||
public class MessageDto {
|
||||
private String cmdType;
|
||||
|
||||
@JacksonXmlProperty(localName = "SN")
|
||||
private String sn;
|
||||
|
||||
@JacksonXmlProperty(localName = "DeviceID")
|
||||
private String deviceId;
|
||||
|
||||
private String status;
|
||||
}
|
@ -4,7 +4,7 @@ import cn.hutool.core.date.DateUtil;
|
||||
import cn.skcks.docking.gb28181.config.sip.SipConfig;
|
||||
import cn.skcks.docking.gb28181.core.sip.dto.RemoteInfo;
|
||||
import cn.skcks.docking.gb28181.core.sip.dto.SipTransactionInfo;
|
||||
import cn.skcks.docking.gb28181.core.sip.gb28181.constant.DefaultConstant;
|
||||
import cn.skcks.docking.gb28181.core.sip.gb28181.constant.GB28181Constant;
|
||||
import cn.skcks.docking.gb28181.core.sip.gb28181.sip.GbSipDate;
|
||||
import cn.skcks.docking.gb28181.core.sip.listener.SipListener;
|
||||
import cn.skcks.docking.gb28181.core.sip.message.auth.DigestServerAuthenticationHelper;
|
||||
@ -46,7 +46,8 @@ public class RegisterRequestProcessor implements MessageProcessor {
|
||||
private final DockingDeviceService dockingDeviceService;
|
||||
|
||||
@PostConstruct
|
||||
private void init(){
|
||||
@Override
|
||||
public void init(){
|
||||
sipListener.addProcessor(Method.REGISTER,this);
|
||||
}
|
||||
|
||||
@ -61,7 +62,7 @@ public class RegisterRequestProcessor implements MessageProcessor {
|
||||
SipUri uri = (SipUri)address.getURI();
|
||||
String deviceId = uri.getUser();
|
||||
log.debug("请求注册 设备id => {}", deviceId);
|
||||
DockingDevice device = dockingDeviceService.getDeviceInfo(deviceId);
|
||||
DockingDevice device = dockingDeviceService.getDevice(deviceId);
|
||||
String senderIp = request.getLocalAddress().getHostAddress();
|
||||
RemoteInfo remoteInfo = SipUtil.getRemoteInfoFromRequest(request, false);
|
||||
log.debug("远程连接信息 => {}", remoteInfo);
|
||||
@ -135,8 +136,8 @@ public class RegisterRequestProcessor implements MessageProcessor {
|
||||
if (device == null) {
|
||||
device = new DockingDevice();
|
||||
device.setStreamMode(ListeningPoint.UDP);
|
||||
device.setCharset(DefaultConstant.CHARSET);
|
||||
device.setGeoCoordSys(DefaultConstant.GEO_COORD_SYS);
|
||||
device.setCharset(GB28181Constant.CHARSET);
|
||||
device.setGeoCoordSys(GB28181Constant.GEO_COORD_SYS);
|
||||
device.setDeviceId(deviceId);
|
||||
device.setOnLine(false);
|
||||
} else {
|
||||
@ -144,10 +145,10 @@ public class RegisterRequestProcessor implements MessageProcessor {
|
||||
device.setStreamMode(ListeningPoint.UDP);
|
||||
}
|
||||
if (ObjectUtils.isEmpty(device.getCharset())) {
|
||||
device.setCharset(DefaultConstant.CHARSET);
|
||||
device.setCharset(GB28181Constant.CHARSET);
|
||||
}
|
||||
if (ObjectUtils.isEmpty(device.getGeoCoordSys())) {
|
||||
device.setGeoCoordSys(DefaultConstant.GEO_COORD_SYS);
|
||||
device.setGeoCoordSys(GB28181Constant.GEO_COORD_SYS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@ import org.mybatis.dynamic.sql.SqlBuilder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.sip.message.Response;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ -32,7 +31,7 @@ public class DockingDeviceService {
|
||||
* @param deviceId 设备id
|
||||
* @return 设备信息
|
||||
*/
|
||||
public DockingDevice getDeviceInfo(String deviceId) {
|
||||
public DockingDevice getDevice(String deviceId) {
|
||||
DockingDevice device = deviceCacheService.getDevice(deviceId);
|
||||
if (device == null) {
|
||||
device = dockingDeviceMapper
|
||||
@ -65,7 +64,7 @@ public class DockingDeviceService {
|
||||
dockingDeviceMapper.insert(device);
|
||||
});
|
||||
|
||||
getDeviceInfo(deviceId);
|
||||
getDevice(deviceId);
|
||||
onlineCacheService.setOnline(deviceId, DeviceConstant.KEEP_ALIVE_INTERVAL * 3, DeviceConstant.UNIT);
|
||||
setTransaction(deviceId, response);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user