作者 钟来

完成摄像头本地解码器开发

正在显示 92 个修改的文件 包含 1475 行增加2902 行删除
... ... @@ -5,6 +5,39 @@ import com.zhonglai.luhui.device.analysis.dto.Message;
/**
* 回复给前端的消息
*/
public interface ApiClientRePlyDto {
void setReplyMessage(Message message);
public class ApiClientRePlyDto {
private int code;
private String message;
private Object data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public void setReplyMessage(Message message)
{
message.setData(this.code);
message.setMessage(this.message);
message.setData(this.data);
}
}
... ...
package com.zhonglai.luhui.api.controller.test;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.google.gson.JsonArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.FeishuUtil;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.api.controller.test.dto.ClueData;
import com.zhonglai.luhui.api.controller.test.dto.TenantAccessToken;
import com.zhonglai.luhui.config.requestbodymiss.RequestReaderHttpServletRequestWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.StreamUtils;
... ... @@ -20,9 +16,7 @@ import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@Api(tags = "测试")
... ... @@ -83,62 +77,6 @@ public class TestController {
"}";
}
private static Map<String, TenantAccessToken> tenant_access_token_map = new HashMap<>();
private static String gettenant_access_token(String yy_app_id,String yy_app_secret) {
if(tenant_access_token_map.containsKey(yy_app_id))
{
TenantAccessToken tenant_access_token = tenant_access_token_map.get(yy_app_id);
// 判断token是否未超时
if (tenant_access_token.getTenant_access_token() != null && System.currentTimeMillis() < tenant_access_token.getTokenExpireTime()) {
return tenant_access_token.getTenant_access_token();
}
}
String url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal";
JsonObject params = new JsonObject();
params.addProperty("app_id", yy_app_id); // 替换为实际的 app_id
params.addProperty("app_secret", yy_app_secret); // 替换为实际的 app_secret
String str = HttpRequest.post(url).header("Content-Type", "application/json; charset=utf-8").body(params.toString()).execute().body();
JsonObject responseMap = GsonConstructor.get().fromJson(str, JsonObject.class);
if (responseMap != null && responseMap.get("code").getAsInt()==0) {
TenantAccessToken tenant_access_token = new TenantAccessToken();
tenant_access_token.setTenant_access_token(responseMap.get("tenant_access_token").getAsString());
// 设置token过期时间,假设token有效期为7200秒
tenant_access_token.setTokenExpireTime(System.currentTimeMillis() + responseMap.get("expire").getAsInt() * 1000);
tenant_access_token_map.put(yy_app_id, tenant_access_token);
return tenant_access_token.getTenant_access_token();
} else {
throw new RuntimeException("Failed to get tenant_access_token: " + str);
}
}
/**
* HTTP URL
* https://open.feishu.cn/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records
* HTTP Method
* POST
* 接口频率限制
* 50 次/秒
*
* 请求头 :Authorization、Content-Type
*/
private static void subFeishuTables(String tenant_access_token,String app_token,String table_id, JsonObject field )
{
String url = "https://open.feishu.cn/open-apis/bitable/v1/apps/"+app_token+"/tables/"+table_id+"/records";
JsonObject params = new JsonObject();
params.add("fields",field);
System.out.println(params.toString());
String str = HttpRequest.post(url).header("Authorization", "Bearer "+tenant_access_token ).header("Content-Type", "application/json").body(params.toString()).execute().body();
System.out.println(str);
}
public static void main(String[] args) {
String jsr= "{\"store_id\":0,\"create_time\":\"1746668144\",\"gender\":\"未知\",\"action_type\":3,\"telephone\":\"18061271693\",\"promotion_id\":0,\"clue_source\":5,\"store_pack_id\":0,\"refer_dy_id\":\"2046931013\",\"app_name\":\"暂未获取到\",\"ad_id\":\"0\",\"module_id\":\"1805421364269097\",\"flow_type\":1,\"name\":\"未命名\",\"site_id\":\"0\",\"remark_dict\":{},\"adv_id\":\"0\",\"clue_type\":2,\"location\":\"山东+泰安\",\"id\":\"7501883876034215974\",\"module_name\":\"官方电话\",\"clue_convert_status\":\"外部流量\",\"refer_dy_name\":\"鱼儿乐>智慧渔业系统\"}";
ClueData clueData = GsonConstructor.get().fromJson(jsr, ClueData.class);
... ... @@ -154,23 +92,24 @@ public class TestController {
private static void subFeishuLiushuiyu(ClueData clueData)
{
JsonObject field = new JsonObject();
field.addProperty("线索时间",Integer.parseInt(clueData.getCreate_time())*1000l);
field.addProperty("账号",clueData.getRefer_dy_name());
field.addProperty("联系方式",clueData.getTelephone());
field.addProperty("渠道","抖音平台");
JSONObject field = new JSONObject();
field.put("线索时间",Integer.parseInt(clueData.getCreate_time())*1000l);
field.put("账号",clueData.getRefer_dy_name());
field.put("联系方式",clueData.getTelephone());
field.put("渠道","测试数据看到请删除");
// field.addProperty("地区",clueData.getLocation());
subFeishuTables(gettenant_access_token("cli_a88a14d3b279d01c","Z3hpYKHeR1yR2aiv6Rp0mcnwKvehkzmT"),"VLGDbZTtPaJIrgsAzzJcyb8Vnve","tblgzxv9TNwKjUFv",field);
FeishuUtil.subFeishuTables(FeishuUtil.gettenant_access_token("cli_a88a14d3b279d01c","Z3hpYKHeR1yR2aiv6Rp0mcnwKvehkzmT"),"VLGDbZTtPaJIrgsAzzJcyb8Vnve","tblgzxv9TNwKjUFv",field);
}
private static void subFeishuLuhui(ClueData clueData)
{
JsonObject field = new JsonObject();
field.addProperty("日期",Integer.parseInt(clueData.getCreate_time())*1000l);
field.addProperty("发送人","");
field.addProperty("接收人",clueData.getRefer_dy_name());
field.addProperty("内容",clueData.getTelephone());
field.addProperty("线索来源","抖音");
field.addProperty("地址",clueData.getLocation());
subFeishuTables(gettenant_access_token("cli_a77e560b9475100c","7E80HFwgkmHjngFWDNsz6Pe1aqtKLC3m"),"YY58bkeMjahX5Uskh4WcnYOCnZc","tbldo1VjlU9jY51Y",field);
JSONObject field = new JSONObject();
field.put("日期",Integer.parseInt(clueData.getCreate_time())*1000l);
field.put("发送人","");
field.put("接收人",clueData.getRefer_dy_name());
field.put("内容",clueData.getTelephone());
field.put("线索来源","抖音");
field.put("地址",clueData.getLocation());
FeishuUtil.subFeishuTables(FeishuUtil.gettenant_access_token("cli_a77e560b9475100c","7E80HFwgkmHjngFWDNsz6Pe1aqtKLC3m"),"YY58bkeMjahX5Uskh4WcnYOCnZc","tbldo1VjlU9jY51Y",field);
}
}
... ...
... ... @@ -35,36 +35,13 @@
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>3.0.9</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/jna.jar</systemPath>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.sun.jna.examples</groupId>
<artifactId>examples</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/examples.jar</systemPath>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jb2011</groupId>
<artifactId>beautyeye_lnf</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/beautyeye_lnf.jar</systemPath>
<optional>true</optional>
</dependency>
<!-- mqtt -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.5</version>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
</dependency>
</dependencies>
<build>
... ... @@ -90,7 +67,7 @@
生成的manifest中classpath的前缀,因为要把第三方jar放到lib目录下,所以classpath的前缀是lib/
-->
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.zhonglai.luhui.camera.hk.sdk.App</mainClass>
<mainClass>com.zhonglai.luhui.camera.App</mainClass>
</manifest>
<!-- 打包时添加本地包引入 -->
<manifestEntries>
... ...
package com.zhonglai.luhui.camera;
import com.zhonglai.luhui.camera.config.SysConfig;
import com.zhonglai.luhui.camera.httpservice.SimpleHttpServer;
import com.zhonglai.luhui.camera.mqtt.MqttService;
import com.zhonglai.luhui.camera.mqtt.Task;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class App
{
private static Logger logger = LoggerFactory.getLogger(App.class);
public static void main( String[] args ) throws IOException, MqttException {
SysConfig.init();
MqttService mqttService = MqttService.getInstance();
Task task = new Task();
task.updata();
// 添加关闭钩子
// 使用Lambda表达式添加关闭钩子
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
logger.info("正在关闭应用程序...");
try {
mqttService.stop();
} catch (MqttException e) {
logger.error("MQTT服务停止异常", e);
}
task.stopScheduler();
logger.info("应用程序关闭成功");
}));
}
}
... ...
package com.zhonglai.luhui.camera.config;
import com.zhonglai.luhui.camera.dto.MqttConfig;
import com.zhonglai.luhui.camera.rtspwebrtc.DockerSecretFetcher;
import java.io.FileReader;
import java.util.HashSet;
import java.util.Properties;
public class SysConfig {
public static MqttConfig mqttConfig;
public static String yuerleApiUrl;
public static String webrtc_host;
public static String webrtc_app;
private static String webrtc_secret;
public static String cameraSerial;
public static Integer sysTaskInterval;
public static void init()
{
//加载properties配置文件
Properties properties = loadProperties();
mqttConfig = new MqttConfig();
mqttConfig.mqttBroker = properties.getProperty("mqtt.broker");
mqttConfig.mqttUserName = properties.getProperty("mqtt.username");
mqttConfig.mqttPassword = properties.getProperty("mqtt.password");
mqttConfig.mqttClientId = properties.getProperty("mqtt.clientId");
mqttConfig.subTopic = new HashSet<>();
String topicsStr = properties.getProperty("mqtt.subTopic");
if(null != topicsStr && !"".equals(topicsStr))
{
if (topicsStr != null && !topicsStr.trim().isEmpty()) {
String[] topics = topicsStr.split(",");
for (String topic : topics) {
mqttConfig.subTopic.add(topic.trim());
}
}
}
yuerleApiUrl = properties.getProperty("yuerle.api.url");
webrtc_host = properties.getProperty("webrtc.host");
webrtc_app = properties.getProperty("webrtc.app");
cameraSerial = properties.getProperty("camera.serial");
sysTaskInterval = Integer.parseInt(properties.getProperty("sys.task.interval"));
}
/**
* 获取webrtc的密钥
* @return
*/
public static String getWebrtcSecret() {
if(null == webrtc_secret)
{
refreshWebrtcSecret();
}
return webrtc_secret;
}
/**
* 刷新webrtc的密钥
*/
public static void refreshWebrtcSecret()
{
webrtc_secret = DockerSecretFetcher.getZLMSecret();
}
public static Properties loadProperties()
{
Properties properties = new Properties();
try {
if(null != System.getProperty("configPath") && !"".equals(System.getProperty("configPath")))
{
properties.load(new FileReader(System.getProperty("configPath")));
}else{
properties.load(SysConfig.class.getClassLoader().getResourceAsStream("sys.properties"));
}
} catch (Exception e) {
e.printStackTrace();
}
return properties;
}
}
... ...
package com.zhonglai.luhui.camera.hk.sdk.dto;
package com.zhonglai.luhui.camera.dto;
public class Camera {
public String name;
... ...
package com.zhonglai.luhui.camera.hk.sdk.dto;
package com.zhonglai.luhui.camera.dto;
import java.util.ArrayList;
import java.util.HashMap;
... ...
package com.zhonglai.luhui.camera.dto;
import java.util.Set;
public class MqttConfig {
public static String mqttBroker;
public static String mqttUserName;
public static String mqttPassword;
public static String mqttClientId;
public static Set<String> subTopic;
}
... ...
package com.zhonglai.luhui.camera.dto;
public class Topic {
public static final String TOPIC_PUT = "PUT";
public static final String TOPIC_READ = "READ";
private String topicType;
private String time;
public Topic()
{
}
public Topic(String stopicStr)
{
String[] strs = stopicStr.split("/");
topicType = strs[0];
time = strs[1];
}
public String getTopicType() {
return topicType;
}
public void setTopicType(String topicType) {
this.topicType = topicType;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
}
... ...
package com.zhonglai.luhui.camera.hk.sdk;
import com.zhonglai.luhui.camera.hk.sdk.func.HCSadpSdkFunc;
import com.zhonglai.luhui.camera.hk.sdk.func.callBack.DeviceFindCallBack;
import com.zhonglai.luhui.camera.hk.sdk.sdk.SdkPath;
import com.zhonglai.luhui.camera.hk.sdk.service.SimpleHttpServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
public class App
{
private static Logger logger = LoggerFactory.getLogger(App.class);
public static void main( String[] args ) throws IOException {
// HCNetSdkFunc netSdk = new HCNetSdkFunc("192.168.0.101","admin","Luhui586", 8000);
HCSadpSdkFunc.getInstance().startSearchDevices(new DeviceFindCallBack());
SimpleHttpServer.startHttpServer(18008);
}
}
package com.zhonglai.luhui.camera.hk.sdk.func;
import com.zhonglai.luhui.camera.hk.sdk.sdk.HCSadpSdk;
import com.zhonglai.luhui.camera.hk.sdk.sdk.SdkPath;
import com.zhonglai.luhui.camera.hk.sdk.sdk.HCSadpSdk.SADP_DEV_NET_PARAM;
import com.zhonglai.luhui.camera.hk.sdk.util.ByteUtil;
import com.zhonglai.luhui.camera.hk.sdk.util.SdkErrorUtil;
import cn.hutool.core.lang.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @ClassName: HkSadpSdkFunc
* @Description: 设备网络搜索SDK函数封装
* @author: ShenYue
* @date: 2019年4月23日 下午4:38:27
*/
public class HCSadpSdkFunc implements SdkFunc{
private static Logger logger = LoggerFactory.getLogger(HCSadpSdkFunc.class);
public static HCSadpSdk sadpSdk = HCSadpSdk.INSTANCE;
private static boolean isInit = false;
private boolean isSearching = false;
private static class HCSadpSdkFuncInstance {
private static final HCSadpSdkFunc INSTANCE = new HCSadpSdkFunc();
}
public static HCSadpSdkFunc getInstance() {
return HCSadpSdkFuncInstance.INSTANCE;
}
private HCSadpSdkFunc() {
super();
init();
}
@Override
public void init() {
if(!isInit){
// 获取SDK版本
int version = sadpSdk.SADP_GetSadpVersion();
System.out.printf("SADP SDK 版本: %d.%d.%d.%d%n",
(version >> 24) & 0xFF,
(version >> 16) & 0xFF,
(version >> 8) & 0xFF,
version & 0xFF);
sadpSdk.SADP_SetLogToFile(3,SdkPath.ROOT_PATH+"/log",1);
isInit=true;
logger.info("HCSadpSdk init success.");
}
}
/**
* 开始搜索网络设备
*/
public boolean startSearchDevices(HCSadpSdk.PDEVICE_FIND_CALLBACK callBack){
Assert.isFalse(isSearching,"device must stop searching first.");
logger.info("HkSadpSdk search devices.");
boolean isSuccess=sadpSdk.SADP_Start_V30(callBack,1,null);
if(isSuccess){
logger.info("searching devices start.");
isSearching=true;
return true;
}else{
logger.error(SdkErrorUtil.getHCSadpErrorMsg());
return false;
}
}
/**
* 手动刷新网络设备
*/
public boolean refreshDevices(){
Assert.isTrue(isSearching,"must start devices searching first.");
logger.info("refresh devices.");
boolean isSuccess=sadpSdk.SADP_SendInquiry();
if(isSuccess){
logger.info("refresh devices success.");
return true;
}else{
logger.error(SdkErrorUtil.getHCSadpErrorMsg());
return false;
}
}
/**
* 停止搜索网络设备
* @return
*/
public boolean stopSearchDevices(){
Assert.isTrue(isSearching,"devices searching not start.");
logger.info("stop search devices.");
boolean isSuccess=sadpSdk.SADP_Stop();
if(isSuccess){
logger.info("stop search devices success.");
isSearching=false;
return true;
}else{
logger.error(SdkErrorUtil.getHCSadpErrorMsg());
return false;
}
}
/**
* 激活设备
* @param serialNO 设备序列号
* @param password 初始密码
* @return
*/
public boolean activeDevice(String serialNO,String password){
logger.info("try to active devices,serialNO = "+serialNO+", password = "+password);
boolean isSuccess=sadpSdk.SADP_ActivateDevice(serialNO,password);
if(isSuccess){
logger.info("active devices success.");
return true;
}else{
logger.error(SdkErrorUtil.getHCSadpErrorMsg());
return false;
}
}
/**
* 修改设备网络参数
* @param sMAC MAC地址
* @param password 设备密码
* @param ip IP地址
* @param gateWay 网关
* @param netMask 子网掩码
* @return
*/
public static boolean setDeviceNetParam(String sMAC,String password,String ip,String gateWay,String netMask){
logger.info("Modify device netParam -> sMAC = "+sMAC+",password= "+password+",ip= "+ip+",gateWay= "+gateWay+",netMask= "+netMask);
SADP_DEV_NET_PARAM.ByValue netParam =new SADP_DEV_NET_PARAM.ByValue();
netParam.szIPv4Address=ByteUtil.setStrToByteArr(ip, 16);
netParam.szIPv4Gateway=ByteUtil.setStrToByteArr(gateWay, 16);
netParam.szIPv4SubnetMask=ByteUtil.setStrToByteArr(netMask, 16);
netParam.szIPv6Gateway=ByteUtil.setStrToByteArr("::", 128);
netParam.szIPv6Address=ByteUtil.setStrToByteArr("::", 128);
netParam.byDhcpEnable=0;
netParam.wPort=8000;
netParam.wHttpPort=80;
netParam.byIPv6MaskLen=0;
netParam.write();
boolean isSuccess=sadpSdk.SADP_ModifyDeviceNetParam(sMAC,password, netParam.getPointer());
if(isSuccess){
logger.info("Modify devices params success.");
return true;
}else{
logger.error(SdkErrorUtil.getHCSadpErrorMsg());
return false;
}
}
@Override
public boolean isSuccess() {
return false;
}
}
package com.zhonglai.luhui.camera.hk.sdk.func;
public interface SdkFunc {
void init();
boolean isSuccess();
}
package com.zhonglai.luhui.camera.hk.sdk.func.callBack;
import com.sun.jna.Pointer;
import com.zhonglai.luhui.camera.hk.sdk.dto.Camera;
import com.zhonglai.luhui.camera.hk.sdk.dto.CameraMap;
import com.zhonglai.luhui.camera.hk.sdk.sdk.HCSadpSdk;
import com.zhonglai.luhui.camera.hk.sdk.util.ConvertUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
public class DeviceFindCallBack implements HCSadpSdk.PDEVICE_FIND_CALLBACK {
private static Logger logger = LoggerFactory.getLogger(DeviceFindCallBack.class);
@Override
public void invoke(HCSadpSdk.SADP_DEVICE_INFO lpDeviceInfo, Pointer pUserData) {
Map<String,Object> map = ConvertUtil.struct2Map(lpDeviceInfo);
logger.info("搜索到设备{}",map);
Camera camera = new Camera();
String name= (String) map.get("szSerialNO");
camera.setName(name);
camera.setRtsp("rtsp://admin:Luhui586@"+map.get("szIPv4Address")+":554/h264/ch1/main/av_stream");
String serialNO = name.substring(9<name.length()?name.length()-9:name.length());
CameraMap.add(serialNO,camera);
}
}
package com.zhonglai.luhui.camera.hk.sdk.sdk;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.win32.StdCallLibrary;
import com.zhonglai.luhui.camera.hk.sdk.App;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
public interface HCSadpSdk extends Library {
HCSadpSdk INSTANCE = (HCSadpSdk) Native.loadLibrary(SdkPath.DLL_PATH, HCSadpSdk.class);
public static class SADP_DEVICE_INFO extends Structure {
public byte[] szSeries = new byte[12];
public byte[] szSerialNO = new byte[48];
public byte[] szMAC = new byte[20];
public byte[] szIPv4Address = new byte[16];
public byte[] szIPv4SubnetMask = new byte[16];
public int dwDeviceType;
public int dwPort;
public int dwNumberOfEncoders;
public int dwNumberOfHardDisk;
public byte[] szDeviceSoftwareVersion = new byte[48];
public byte[] szDSPVersion = new byte[48];
public byte[] szBootTime = new byte[48];
public int iResult;
public byte[] szDevDesc = new byte[24];
public byte[] szOEMinfo = new byte[24];
public byte[] szIPv4Gateway = new byte[16];
public byte[] szIPv6Address = new byte[46];
public byte[] szIPv6Gateway = new byte[46];
public byte byIPv6MaskLen;
public byte bySupport;
public byte byDhcpEnabled;
public byte byDeviceAbility;
public byte wHttpPort;
public short wDigitalChannelNum;
public byte[] szCmsIPv4 = new byte[16];
public short wCmsPort;
public byte byOEMCode;
public byte byActivated;
public byte[] szBaseDesc = new byte[24];
public byte[] byRes = new byte[16];
}
public static class SADP_DEV_NET_PARAM extends Structure {
public byte[] szIPv4Address = new byte[16];
public byte[] szIPv4SubnetMask = new byte[16];
public byte[] szIPv4Gateway = new byte[16];
public byte[] szIPv6Address = new byte[128];
public byte[] szIPv6Gateway = new byte[128];
public short wPort;
public byte byIPv6MaskLen;
public byte byDhcpEnable;
public short wHttpPort;
public byte[] byRes = new byte[126];
public static class ByReference extends SADP_DEV_NET_PARAM implements Structure.ByReference{
}
public static class ByValue extends SADP_DEV_NET_PARAM implements Structure.ByValue{
}
}
boolean SADP_SetLogToFile(int nLogLevel, String strLogDir, int bAutoDel);
boolean SADP_Start_V30(PDEVICE_FIND_CALLBACK pDeviceFindCallBack, int bInstallNPF ,Pointer pUserData);
boolean SADP_SendInquiry();
boolean SADP_Stop();
boolean SADP_ActivateDevice(String sDevSerialNO,String sCommand);
boolean SADP_ModifyDeviceNetParam(String sMAC,String sPassword,Pointer lpNetParam);
public static interface PDEVICE_FIND_CALLBACK extends StdCallLibrary.StdCallCallback {
public void invoke(SADP_DEVICE_INFO lpDeviceInfo,Pointer pUserData);
}
int SADP_GetSadpVersion();
int SADP_GetLastError();
}
package com.zhonglai.luhui.camera.hk.sdk.sdk;
import com.zhonglai.luhui.camera.hk.sdk.App;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.UnsupportedEncodingException;
public class SdkPath {
private static Logger logger = LoggerFactory.getLogger(SdkPath.class);
public static String ROOT_PATH;
public static String DLL_PATH;
static{
ROOT_PATH = System.getProperty("dllPath");
if(null == ROOT_PATH)
{
ROOT_PATH = new File(ClassLoader.getSystemResource("").getPath()).getParentFile().getParent();
}
DLL_PATH = SdkPath.ROOT_PATH+ "/dll/SadpSdk/" +(System.getProperty("os.name").contains("Windows") ? "Sadp.dll" : "libsadp.so");
logger.info("动态库的地址:"+new File(DLL_PATH).getAbsolutePath());
}
}
package com.zhonglai.luhui.camera.hk.sdk.service;
import com.alibaba.fastjson.JSONObject;
import com.sun.net.httpserver.*;
import com.zhonglai.luhui.camera.hk.sdk.dto.Camera;
import com.zhonglai.luhui.camera.hk.sdk.dto.CameraMap;
import com.zhonglai.luhui.camera.rtspwebrtc.WebRtcService;
import java.io.*;
import java.util.*;
/**
* 摄像头数据处理器
*/
public class CamerasHandler implements HttpHandler{
@Override
public void handle(HttpExchange exchange) throws IOException {
// 读取摄像头配置文件
List<Camera> camerasData = CameraMap.toArrayList();
Map<String, String> params = getQueryMap(exchange);
if(params.containsKey("command"))
{
switch (params.get("command"))
{
case "startStream":
startStream(exchange,params);
return;
case "stopStream":
stopStream(exchange,params);
return;
}
}
// 返回摄像头数据
String jsonResponse = JSONObject.toJSONString(camerasData);
returnString(200,exchange,jsonResponse);
}
private void returnString(Integer state,HttpExchange exchange,String jsonResponse) throws IOException
{
exchange.getResponseHeaders().add("Content-Type", "application/json");
exchange.sendResponseHeaders(state, jsonResponse.getBytes().length);
try (OutputStream os = exchange.getResponseBody()) {
os.write(jsonResponse.getBytes());
}
}
private void startStream(HttpExchange exchange,Map<String, String> params) throws IOException {
if(params.containsKey("serialNO") && CameraMap.has(params.get("serialNO")))
{
String rtsp = CameraMap.get(params.get("serialNO")).getRtsp();
String jsonstr = WebRtcService.startStream(params.get("serialNO"),rtsp,"yuerle");
JSONObject jsonObject = JSONObject.parseObject(jsonstr);
if(jsonObject.containsKey("code") && jsonObject.getInteger("code")==0)
{
JSONObject data = jsonObject.getJSONObject("data");
data.put("app","yuerle");
data.put("stream",params.get("serialNO"));
returnString(200,exchange,jsonObject.toJSONString());
return;
}else{
returnString(500,exchange,jsonstr);
return;
}
}
JSONObject json = new JSONObject();
json.put("msg","请输入正确的设备序列号");
returnString(500,exchange,json.toJSONString());
}
private void stopStream(HttpExchange exchange,Map<String, String> params) throws IOException {
if(params.containsKey("serialNO") && CameraMap.has(params.get("serialNO")))
{
String jsonstr = WebRtcService.stopStream(params.get("serialNO"),"yuerle");
if(jsonstr.contains("success"))
{
returnString(200,exchange,jsonstr);
return;
}else{
returnString(500,exchange,jsonstr);
return;
}
}
JSONObject json = new JSONObject();
json.put("msg","请输入正确的设备序列号");
returnString(500,exchange,json.toJSONString());
}
private Map<String,String> getQueryMap(HttpExchange exchange){
String query = exchange.getRequestURI().getQuery();
Map<String, String> params = new HashMap<>();
if (query != null) {
for (String param : query.split("&")) {
String[] pair = param.split("=");
if (pair.length > 1) {
params.put(pair[0], pair[1]);
} else {
params.put(pair[0], null);
}
}
}
return params;
}
}
package com.zhonglai.luhui.camera.hk.sdk.ui;
import java.awt.Color;
import java.util.Date;
import javax.swing.JOptionPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import com.zhonglai.luhui.camera.hk.sdk.util.SdkErrorUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrFormatter;
public class MessageBox {
public static boolean checkHCSadpError(){
String msg=SdkErrorUtil.getHCSadpErrorMsg();
if(msg !=null){
MessageBox.error(msg);
return false;
}
return true;
}
public static void error(String msg,Object...params){
;
JOptionPane.showMessageDialog(null,StrFormatter.format(msg, params),"消息提示",JOptionPane.ERROR_MESSAGE);
throw new RuntimeException(msg);
}
public static void tip(String msg){
JOptionPane.showMessageDialog(null,msg,"消息提示",JOptionPane.INFORMATION_MESSAGE);
}
public static void log(JTextPane console,String msg){
try {
console.getDocument()
.insertString(console.getDocument().getLength(),
getConsoleHeader()+msg+"\r\n",
console.getStyle("def"));
} catch (BadLocationException e) {
e.printStackTrace();
}
}
public static void logWarn(JTextPane console,String msg){
try {
console.getDocument()
.insertString(console.getDocument().getLength(),
getConsoleHeader()+msg+"\r\n",
console.getStyle("warn"));
} catch (BadLocationException e) {
e.printStackTrace();
}
}
public static void logError(JTextPane console,String msg){
try {
console.getDocument()
.insertString(console.getDocument().getLength(),
getConsoleHeader()+msg+"\r\n",
console.getStyle("error"));
} catch (BadLocationException e) {
e.printStackTrace();
}
}
public static void check(boolean condition,String msg,Object...params){
if(!condition){
error(msg,params);
}
}
private static String getConsoleHeader(){
return "Console("+DateUtil.format(new Date(),DatePattern.NORM_TIME_PATTERN)+"):";
}
public static void initJTextPaneStyle(JTextPane pane){
//def
Style noStyle = pane.getStyledDocument().addStyle(null, null);
StyleConstants.setFontFamily(noStyle, "verdana");
StyleConstants.setFontSize(noStyle, 12);
Style def=pane.addStyle("def", noStyle);
//warn
Style warn = pane.addStyle("warn",def);
StyleConstants.setForeground(warn, Color.blue);
//error
Style error = pane.addStyle("error",def);
StyleConstants.setForeground(error, Color.red);
}
}
package com.zhonglai.luhui.camera.hk.sdk.ui;
import java.io.File;
import java.util.List;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import com.zhonglai.luhui.camera.hk.sdk.ui.handler.AbstractHandler;
import com.zhonglai.luhui.camera.hk.sdk.ui.handler.ActiveDeviceHandler;
import com.zhonglai.luhui.camera.hk.sdk.ui.handler.DeviceNetParamHandler;
import com.zhonglai.luhui.camera.hk.sdk.ui.vo.DeviceVo;
import com.zhonglai.luhui.camera.hk.sdk.ui.vo.NetParamVo;
import com.zhonglai.luhui.camera.hk.sdk.util.ConvertUtil;
import cn.hutool.poi.excel.ExcelUtil;
/**
*
* @ClassName: WinHCSadpActiveDevice
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: ShenYue
* @date: 2019年4月30日 上午11:12:01
*/
public class WinHCSadpActiveDevice extends javax.swing.JFrame {
private static final long serialVersionUID = 2658391598049771347L;
private List<DeviceVo> unactiveDevices;
private List<NetParamVo> netParams;
private static final String [] TABLE_HEADER_NAME= new String [] {"设备序列号", "IP", "网关", "子网掩码","MAC", "版本", "激活状态"};
public WinHCSadpActiveDevice() {
initComponents();
}
private void initComponents() {
this.setResizable(false);
this.setLocation(400, 200);
panel = new javax.swing.JPanel();
avctiveButton = new javax.swing.JButton();
importConfigButton = new javax.swing.JButton();
scrollPane = new javax.swing.JScrollPane();
deviceTable = new javax.swing.JTable();
jLabel1 = new javax.swing.JLabel();
jScrollPane2 = new javax.swing.JScrollPane();
console = new javax.swing.JTextPane();
jLabel2 = new javax.swing.JLabel();
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
avctiveButton.setEnabled(false);
avctiveButton.setText("开始激活");
avctiveButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
avctiveButtonEvt(evt);
}
});
importConfigButton.setText("导入配置");
importConfigButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
importConfigButtonEvt(evt);
}
});
deviceTable.setModel(new javax.swing.table.DefaultTableModel(
ConvertUtil.toObjArray(unactiveDevices),
TABLE_HEADER_NAME
));
scrollPane.setViewportView(deviceTable);
jLabel1.setText("设备列表");
jScrollPane2.setViewportView(console);
jLabel2.setText("实时日志");
AbstractHandler.init(console);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(panel);
panel.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(30, 30, 30)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel2)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(jScrollPane2)
.addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 840, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(avctiveButton)
.addGap(36, 36, 36)
.addComponent(importConfigButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel1))))
.addContainerGap(19, Short.MAX_VALUE))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(24, 24, 24)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(avctiveButton)
.addComponent(importConfigButton))
.addGap(18, 18, 18))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addGap(6, 6, 6)))
.addComponent(scrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 305, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(13, 13, 13)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 238, Short.MAX_VALUE)
.addContainerGap())
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
private void avctiveButtonEvt(java.awt.event.ActionEvent evt) {
new Thread(new Runnable() {
@Override
public void run() {
for(int device_index=0;device_index<unactiveDevices.size();device_index++){
ActiveDeviceHandler activeHandler = new ActiveDeviceHandler(unactiveDevices.get(device_index),netParams.get(device_index));
DeviceNetParamHandler netParamHandler = new DeviceNetParamHandler(unactiveDevices.get(device_index),netParams.get(device_index));
activeHandler.setNext(netParamHandler);
activeHandler.handleRequest(true);
}
}
}).start();
}
private void importConfigButtonEvt(java.awt.event.ActionEvent evt) {
// 导入Excel配置
fileChooser = new JFileChooser();
//初始化当前路径
FileSystemView fsv = FileSystemView.getFileSystemView();
File homeFile =fsv.getHomeDirectory();
fileChooser.setCurrentDirectory(homeFile);
//初始化文件过滤器
FileNameExtensionFilter filter = new FileNameExtensionFilter("EXCEL文件","xls","xlsx");
fileChooser.setFileFilter(filter);
//初始化选择模式
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
//是否允许多选
fileChooser.setMultiSelectionEnabled(false);
//打开文件选择器
int i = fileChooser.showDialog(this, "选择");
if(i == JFileChooser.APPROVE_OPTION){
netParams.clear();
File file = fileChooser.getSelectedFile();
List<NetParamVo> importNetParams=ExcelUtil.getReader(file,0).readAll(NetParamVo.class);
if(!importNetParams.isEmpty()){
avctiveButton.setEnabled(true);
MessageBox.check(importNetParams.size()==unactiveDevices.size(),"配置数量不一致,导入配置{}项,未激活设备{}项",importNetParams.size(),unactiveDevices.size());
MessageBox.tip("导入"+netParams.size()+" 个配置项");
}
}
}
// Variables declaration - do not modify
private javax.swing.JButton avctiveButton;
private javax.swing.JButton importConfigButton;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JPanel panel;
private javax.swing.JScrollPane scrollPane;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTable deviceTable;
private javax.swing.JTextPane console;
private javax.swing.JFileChooser fileChooser;
// End of variables declaration
}
package com.zhonglai.luhui.camera.hk.sdk.ui;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.jb2011.lnf.beautyeye.ch3_button.BEButtonUI;
import com.sun.jna.Pointer;
import com.zhonglai.luhui.camera.hk.sdk.func.HCSadpSdkFunc;
import com.zhonglai.luhui.camera.hk.sdk.sdk.HCSadpSdk.PDEVICE_FIND_CALLBACK;
import com.zhonglai.luhui.camera.hk.sdk.sdk.HCSadpSdk.SADP_DEVICE_INFO;
import com.zhonglai.luhui.camera.hk.sdk.ui.render.WindowRender;
import com.zhonglai.luhui.camera.hk.sdk.ui.vo.DeviceVo;
import com.zhonglai.luhui.camera.hk.sdk.util.ConvertUtil;
import cn.hutool.core.lang.Assert;
/**
*
* @ClassName: WinHCSadpLauncher
* @Description: 海康SADP sdk 启动类
* @author: ShenYue
* @date: 2018年6月29日 下午7:52:04
*/
public class WinHCSadpLauncher extends javax.swing.JFrame {
private static final long serialVersionUID = -600334410958525284L;
private boolean isSearching=false;
private List<DeviceVo> devices=new ArrayList<>();
private static final String [] TABLE_HEADER_NAME= new String [] {"设备序列号", "IP", "网关", "子网掩码","MAC", "版本", "激活状态"};
public WinHCSadpLauncher() {
initComponents();
}
private void initComponents() {
this.setResizable(false);
this.setLocation(400, 200);
panel = new javax.swing.JPanel();
scrollPane = new javax.swing.JScrollPane();
deviceTable = new javax.swing.JTable();
startSearchButton = new javax.swing.JButton();
refreshButton = new javax.swing.JButton();
stopSearchButton = new javax.swing.JButton();
batchConfigButton = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
deviceTable.setModel(new javax.swing.table.DefaultTableModel(
ConvertUtil.toObjArray(devices),
TABLE_HEADER_NAME
));
scrollPane.setViewportView(deviceTable);
startSearchButton.setText("搜索设备");
startSearchButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
startSearchButtonEvt(evt);
}
});
refreshButton.setEnabled(false);
refreshButton.setText("刷新");
refreshButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
refreshButtonEvt(evt);
}
});
stopSearchButton.setEnabled(false);
stopSearchButton.setText("停止搜索");
stopSearchButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
stopSearchButtonEvt(evt);
}
});
batchConfigButton.setText("批量激活");
WindowRender.changeButtonStyle(batchConfigButton,BEButtonUI.NormalColor.lightBlue);
batchConfigButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
batchConfigButtonEvt(evt);
}
});
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(panel);
panel.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(batchConfigButton)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(startSearchButton)
.addGap(30, 30, 30)
.addComponent(refreshButton)
.addGap(28, 28, 28)
.addComponent(stopSearchButton))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel2Layout.createSequentialGroup()
.addGap(32, 32, 32)
.addComponent(scrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 893, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addContainerGap(30, Short.MAX_VALUE))
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addComponent(batchConfigButton)
.addGap(18, 18, 18)
.addComponent(scrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 506, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(refreshButton)
.addComponent(stopSearchButton)
.addComponent(startSearchButton))
.addContainerGap(17, Short.MAX_VALUE))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
private void batchConfigButtonEvt(java.awt.event.ActionEvent evt) {
List<DeviceVo> unactiveDevices=devices.stream().filter(d -> !"已激活".equals(d.getActiveStatus())).collect(Collectors.toList());
if(!unactiveDevices.isEmpty()){
MessageBox.tip("没有需要激活的设备!");
}else{
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new WinHCSadpActiveDevice().setVisible(true);
}
});
}
}
private void startSearchButtonEvt(java.awt.event.ActionEvent evt) {
// 设备搜索
boolean success=HCSadpSdkFunc.getInstance().startSearchDevices(new PDEVICE_FIND_CALLBACK() {
@Override
public void invoke(SADP_DEVICE_INFO lpDeviceInfo, Pointer pUserData) {
Map<String, Object> deviceInfo=ConvertUtil.struct2Map(lpDeviceInfo);
DeviceVo device=new DeviceVo(
(String)deviceInfo.get("szSerialNO"),
(String)deviceInfo.get("szIPv4Address"),
(String)deviceInfo.get("szIPv4Gateway"),
(String)deviceInfo.get("szIPv4SubnetMask"),
(String)deviceInfo.get("szMAC"),
(String)deviceInfo.get("szDeviceSoftwareVersion"),
(byte)deviceInfo.get("byActivated"));
if(!devices.contains(device)){
devices.add(device);
refreshTable();
}
}
});
if(!success){
MessageBox.checkHCSadpError();
}else{
startSearch();
}
}
private void refreshButtonEvt(java.awt.event.ActionEvent evt) {
boolean success=HCSadpSdkFunc.getInstance().refreshDevices();
if(!success){
MessageBox.checkHCSadpError();
}
}
private void stopSearchButtonEvt(java.awt.event.ActionEvent evt) {
boolean success=HCSadpSdkFunc.getInstance().stopSearchDevices();
if(!success){
MessageBox.checkHCSadpError();
}else{
devices.clear();
refreshTable();
stopSearch();
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
WindowRender.render();
new WinHCSadpLauncher().setVisible(true);
}
});
}
private void refreshTable(){
synchronized (this) {
deviceTable.removeAll();
deviceTable.setModel(new javax.swing.table.DefaultTableModel(
ConvertUtil.toObjArray(devices),
TABLE_HEADER_NAME
));
}
}
private void startSearch(){
Assert.isFalse(isSearching,"设备搜索中.");
isSearching=true;
refreshButton.setEnabled(true);
stopSearchButton.setEnabled(true);
}
private void stopSearch(){
Assert.isTrue(isSearching,"设备搜索未开启.");
isSearching=false;
refreshButton.setEnabled(false);
stopSearchButton.setEnabled(false);
}
// Variables declaration - do not modify
private javax.swing.JButton startSearchButton;
private javax.swing.JButton refreshButton;
private javax.swing.JButton stopSearchButton;
private javax.swing.JButton batchConfigButton;
private javax.swing.JPanel panel;
private javax.swing.JScrollPane scrollPane;
private javax.swing.JTable deviceTable;
// End of variables declaration
}
package com.zhonglai.luhui.camera.hk.sdk.ui.handler;
import javax.swing.JTextPane;
import com.zhonglai.luhui.camera.hk.sdk.ui.MessageBox;
import com.zhonglai.luhui.camera.hk.sdk.util.SdkErrorUtil;
public abstract class AbstractHandler {
protected AbstractHandler next;
protected static JTextPane console;
public static void init(JTextPane console){
AbstractHandler.console=console;
}
public void setNext(AbstractHandler next) {
this.next = next;
}
public JTextPane getConsole() {
return console;
}
public void handleRequest(boolean success){
if(success){
success=doRequest();
if(success){
MessageBox.log(console,"设备操作成功.");
}
if(next != null){
next.handleRequest(success);
}
}else{
MessageBox.logError(console,SdkErrorUtil.getHCSadpErrorMsg());
}
}
abstract protected boolean doRequest();
}
package com.zhonglai.luhui.camera.hk.sdk.ui.handler;
import com.zhonglai.luhui.camera.hk.sdk.func.HCSadpSdkFunc;
import com.zhonglai.luhui.camera.hk.sdk.ui.MessageBox;
import com.zhonglai.luhui.camera.hk.sdk.ui.vo.DeviceVo;
import com.zhonglai.luhui.camera.hk.sdk.ui.vo.NetParamVo;
public class ActiveDeviceHandler extends AbstractHandler{
private DeviceVo device;
private NetParamVo netParam;
public ActiveDeviceHandler(DeviceVo device, NetParamVo netParam) {
super();
this.device = device;
this.netParam = netParam;
}
@Override
protected boolean doRequest() {
MessageBox.log(console,"开始激活设备 "+device.getSerialNumber());
return HCSadpSdkFunc.getInstance().activeDevice(device.getSerialNumber(),netParam.getPassword());
}
}
package com.zhonglai.luhui.camera.hk.sdk.ui.handler;
import com.zhonglai.luhui.camera.hk.sdk.func.HCSadpSdkFunc;
import com.zhonglai.luhui.camera.hk.sdk.ui.MessageBox;
import com.zhonglai.luhui.camera.hk.sdk.ui.vo.DeviceVo;
import com.zhonglai.luhui.camera.hk.sdk.ui.vo.NetParamVo;
/**
*
* @ClassName: DeviceNetParamHandler
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: ShenYue
* @date: 2019年5月5日 上午11:11:00
*/
public class DeviceNetParamHandler extends AbstractHandler{
private DeviceVo device;
private NetParamVo netParam;
public DeviceNetParamHandler(DeviceVo device, NetParamVo netParam) {
super();
this.device = device;
this.netParam = netParam;
}
@Override
protected boolean doRequest() {
MessageBox.log(console,"设备 "+device.getSerialNumber()+"开始设置配置IP地址、子网掩码、网关。");
return HCSadpSdkFunc.setDeviceNetParam(
device.getMacAddr(),
netParam.getPassword(),
netParam.getIp(),
netParam.getGateWay(),
netParam.getNetMask());
}
}
package com.zhonglai.luhui.camera.hk.sdk.ui.render;
import javax.swing.JButton;
import javax.swing.UIManager;
import org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper;
import org.jb2011.lnf.beautyeye.ch3_button.BEButtonUI;
public class WindowRender {
public static void render(){
//边框样式
BeautyEyeLNFHelper.frameBorderStyle = BeautyEyeLNFHelper.FrameBorderStyle.translucencyAppleLike;
//移除默认设置按钮
UIManager.put("RootPane.setupButtonVisible", false);
//关闭透明效果
BeautyEyeLNFHelper.translucencyAtFrameInactive = false;
try {
BeautyEyeLNFHelper.launchBeautyEyeLNF();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void changeButtonStyle(JButton button,BEButtonUI.NormalColor color){
button.setUI(new BEButtonUI().setNormalColor(color));
}
}
package com.zhonglai.luhui.camera.hk.sdk.ui.vo;
public class CameraVo {
//设备参数
private String ip;
private String username;
private String password;
private int port;
//通道参数
private String chanName;
//平台参数
private String szSipAuthenticateID;
private String wServerSipPort;
private String wLocalSipPort;
private String byStreamType;
private String byEnable;
private String dwRegisterInterval;
private String szDeviceDomain;
private String dwRegisterValid;
private String byTransProtocol;
private String byProtocolVersion;
private String szServerID;
private String szSipAuthenticatePasswd;
private String dwAutoAllocChannelID;
private String szServerDomain;
private String byHeartbeatInterval;
private String byDeviceStatus;
private String szSipServerAddress;
private String szSipUserName;
private String byMaxHeartbeatTimeOut;
private String status;
private String msg;
public CameraVo() {
super();
this.status="未处理";
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getChanName() {
return chanName;
}
public void setChanName(String chanName) {
this.chanName = chanName;
}
public String getSzSipAuthenticateID() {
return szSipAuthenticateID;
}
public void setSzSipAuthenticateID(String szSipAuthenticateID) {
this.szSipAuthenticateID = szSipAuthenticateID;
}
public String getwServerSipPort() {
return wServerSipPort;
}
public void setwServerSipPort(String wServerSipPort) {
this.wServerSipPort = wServerSipPort;
}
public String getwLocalSipPort() {
return wLocalSipPort;
}
public void setwLocalSipPort(String wLocalSipPort) {
this.wLocalSipPort = wLocalSipPort;
}
public String getByStreamType() {
return byStreamType;
}
public void setByStreamType(String byStreamType) {
this.byStreamType = byStreamType;
}
public String getByEnable() {
return byEnable;
}
public void setByEnable(String byEnable) {
this.byEnable = byEnable;
}
public String getDwRegisterInterval() {
return dwRegisterInterval;
}
public void setDwRegisterInterval(String dwRegisterInterval) {
this.dwRegisterInterval = dwRegisterInterval;
}
public String getSzDeviceDomain() {
return szDeviceDomain;
}
public void setSzDeviceDomain(String szDeviceDomain) {
this.szDeviceDomain = szDeviceDomain;
}
public String getDwRegisterValid() {
return dwRegisterValid;
}
public void setDwRegisterValid(String dwRegisterValid) {
this.dwRegisterValid = dwRegisterValid;
}
public String getByTransProtocol() {
return byTransProtocol;
}
public void setByTransProtocol(String byTransProtocol) {
this.byTransProtocol = byTransProtocol;
}
public String getByProtocolVersion() {
return byProtocolVersion;
}
public void setByProtocolVersion(String byProtocolVersion) {
this.byProtocolVersion = byProtocolVersion;
}
public String getSzServerID() {
return szServerID;
}
public void setSzServerID(String szServerID) {
this.szServerID = szServerID;
}
public String getSzSipAuthenticatePasswd() {
return szSipAuthenticatePasswd;
}
public void setSzSipAuthenticatePasswd(String szSipAuthenticatePasswd) {
this.szSipAuthenticatePasswd = szSipAuthenticatePasswd;
}
public String getDwAutoAllocChannelID() {
return dwAutoAllocChannelID;
}
public void setDwAutoAllocChannelID(String dwAutoAllocChannelID) {
this.dwAutoAllocChannelID = dwAutoAllocChannelID;
}
public String getSzServerDomain() {
return szServerDomain;
}
public void setSzServerDomain(String szServerDomain) {
this.szServerDomain = szServerDomain;
}
public String getByHeartbeatInterval() {
return byHeartbeatInterval;
}
public void setByHeartbeatInterval(String byHeartbeatInterval) {
this.byHeartbeatInterval = byHeartbeatInterval;
}
public String getByDeviceStatus() {
return byDeviceStatus;
}
public void setByDeviceStatus(String byDeviceStatus) {
this.byDeviceStatus = byDeviceStatus;
}
public String getSzSipServerAddress() {
return szSipServerAddress;
}
public void setSzSipServerAddress(String szSipServerAddress) {
this.szSipServerAddress = szSipServerAddress;
}
public String getSzSipUserName() {
return szSipUserName;
}
public void setSzSipUserName(String szSipUserName) {
this.szSipUserName = szSipUserName;
}
public String getByMaxHeartbeatTimeOut() {
return byMaxHeartbeatTimeOut;
}
public void setByMaxHeartbeatTimeOut(String byMaxHeartbeatTimeOut) {
this.byMaxHeartbeatTimeOut = byMaxHeartbeatTimeOut;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package com.zhonglai.luhui.camera.hk.sdk.ui.vo;
public class DeviceVo {
/*序列号*/
private String serialNumber;
/*IP*/
private String ip;
/*网关*/
private String gateWay;
/*子网掩码*/
private String netMask;
/*Mac地址*/
private String macAddr;
/*软件版本*/
private String dversion;
/*激活状态*/
private String activeStatus;
public DeviceVo(String serialNumber, String ip, String gateWay,String netMask, String macAddr, String dversion, byte activeStatus) {
super();
this.serialNumber = serialNumber;
this.ip = ip;
this.gateWay = gateWay;
this.netMask= netMask;
this.macAddr = macAddr;
this.dversion = dversion;
this.activeStatus = activeStatus==0 ? "已激活":"未激活" ;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getGateWay() {
return gateWay;
}
public void setGateWay(String gateWay) {
this.gateWay = gateWay;
}
public String getNetMask() {
return netMask;
}
public void setNetMask(String netMask) {
this.netMask = netMask;
}
public String getMacAddr() {
return macAddr;
}
public void setMacAddr(String macAddr) {
this.macAddr = macAddr;
}
public String getDversion() {
return dversion;
}
public void setDversion(String dversion) {
this.dversion = dversion;
}
public String getActiveStatus() {
return activeStatus;
}
public void setActiveStatus(String activeStatus) {
this.activeStatus = activeStatus;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((serialNumber == null) ? 0 : serialNumber.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DeviceVo other = (DeviceVo) obj;
if (!serialNumber.equals(other.serialNumber))
return false;
return true;
}
}
package com.zhonglai.luhui.camera.hk.sdk.ui.vo;
public class GBT28181Vo {
private String byRes3;
private String szSipAuthenticateID;
private String byRes4;
private String wServerSipPort;
private String wLocalSipPort;
private String byStreamType;
private String byEnable;
private String dwRegisterInterval;
private String szDeviceDomain;
private String dwRegisterValid;
private String dwSize;
private String byTransProtocol;
private String byProtocolVersion;
private String szServerID;
private String szSipAuthenticatePasswd;
private String dwAutoAllocChannelID;
private String szServerDomain;
private String byHeartbeatInterval;
private String byDeviceStatus;
private String szSipServerAddress;
private String szSipUserName;
private String byMaxHeartbeatTimeOut;
public String getByRes3() {
return byRes3;
}
public void setByRes3(String byRes3) {
this.byRes3 = byRes3;
}
public String getSzSipAuthenticateID() {
return szSipAuthenticateID;
}
public void setSzSipAuthenticateID(String szSipAuthenticateID) {
this.szSipAuthenticateID = szSipAuthenticateID;
}
public String getByRes4() {
return byRes4;
}
public void setByRes4(String byRes4) {
this.byRes4 = byRes4;
}
public String getwServerSipPort() {
return wServerSipPort;
}
public void setwServerSipPort(String wServerSipPort) {
this.wServerSipPort = wServerSipPort;
}
public String getwLocalSipPort() {
return wLocalSipPort;
}
public void setwLocalSipPort(String wLocalSipPort) {
this.wLocalSipPort = wLocalSipPort;
}
public String getByStreamType() {
return byStreamType;
}
public void setByStreamType(String byStreamType) {
this.byStreamType = byStreamType;
}
public String getByEnable() {
return byEnable;
}
public void setByEnable(String byEnable) {
this.byEnable = byEnable;
}
public String getDwRegisterInterval() {
return dwRegisterInterval;
}
public void setDwRegisterInterval(String dwRegisterInterval) {
this.dwRegisterInterval = dwRegisterInterval;
}
public String getSzDeviceDomain() {
return szDeviceDomain;
}
public void setSzDeviceDomain(String szDeviceDomain) {
this.szDeviceDomain = szDeviceDomain;
}
public String getDwRegisterValid() {
return dwRegisterValid;
}
public void setDwRegisterValid(String dwRegisterValid) {
this.dwRegisterValid = dwRegisterValid;
}
public String getDwSize() {
return dwSize;
}
public void setDwSize(String dwSize) {
this.dwSize = dwSize;
}
public String getByTransProtocol() {
return byTransProtocol;
}
public void setByTransProtocol(String byTransProtocol) {
this.byTransProtocol = byTransProtocol;
}
public String getByProtocolVersion() {
return byProtocolVersion;
}
public void setByProtocolVersion(String byProtocolVersion) {
this.byProtocolVersion = byProtocolVersion;
}
public String getSzServerID() {
return szServerID;
}
public void setSzServerID(String szServerID) {
this.szServerID = szServerID;
}
public String getSzSipAuthenticatePasswd() {
return szSipAuthenticatePasswd;
}
public void setSzSipAuthenticatePasswd(String szSipAuthenticatePasswd) {
this.szSipAuthenticatePasswd = szSipAuthenticatePasswd;
}
public String getDwAutoAllocChannelID() {
return dwAutoAllocChannelID;
}
public void setDwAutoAllocChannelID(String dwAutoAllocChannelID) {
this.dwAutoAllocChannelID = dwAutoAllocChannelID;
}
public String getSzServerDomain() {
return szServerDomain;
}
public void setSzServerDomain(String szServerDomain) {
this.szServerDomain = szServerDomain;
}
public String getByHeartbeatInterval() {
return byHeartbeatInterval;
}
public void setByHeartbeatInterval(String byHeartbeatInterval) {
this.byHeartbeatInterval = byHeartbeatInterval;
}
public String getByDeviceStatus() {
return byDeviceStatus;
}
public void setByDeviceStatus(String byDeviceStatus) {
this.byDeviceStatus = byDeviceStatus;
}
public String getSzSipServerAddress() {
return szSipServerAddress;
}
public void setSzSipServerAddress(String szSipServerAddress) {
this.szSipServerAddress = szSipServerAddress;
}
public String getSzSipUserName() {
return szSipUserName;
}
public void setSzSipUserName(String szSipUserName) {
this.szSipUserName = szSipUserName;
}
public String getByMaxHeartbeatTimeOut() {
return byMaxHeartbeatTimeOut;
}
public void setByMaxHeartbeatTimeOut(String byMaxHeartbeatTimeOut) {
this.byMaxHeartbeatTimeOut = byMaxHeartbeatTimeOut;
}
}
package com.zhonglai.luhui.camera.hk.sdk.ui.vo;
public class NetParamVo {
/*IP*/
private String ip;
/*网关*/
private String gateWay;
/*子网掩码*/
private String netMask;
/*初始密码*/
private String password;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getGateWay() {
return gateWay;
}
public void setGateWay(String gateWay) {
this.gateWay = gateWay;
}
public String getNetMask() {
return netMask;
}
public void setNetMask(String netMask) {
this.netMask = netMask;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.zhonglai.luhui.camera.hk.sdk.ui.vo;
public class VedioCompreDtVo {
private byte byPicQuality;
private byte byStreamType;
private byte byResolution;
private byte byBitrateType;
private int dwVideoFrameRate;
private int dwVideoBitrate;
private int wIntervalFrameI;
private byte byIntervalBPFrame;
public byte getByPicQuality() {
return byPicQuality;
}
public void setByPicQuality(byte byPicQuality) {
this.byPicQuality = byPicQuality;
}
public byte getByStreamType() {
return byStreamType;
}
public void setByStreamType(byte byStreamType) {
this.byStreamType = byStreamType;
}
public byte getByResolution() {
return byResolution;
}
public void setByResolution(byte byResolution) {
this.byResolution = byResolution;
}
public byte getByBitrateType() {
return byBitrateType;
}
public void setByBitrateType(byte byBitrateType) {
this.byBitrateType = byBitrateType;
}
public int getDwVideoFrameRate() {
return dwVideoFrameRate;
}
public void setDwVideoFrameRate(int dwVideoFrameRate) {
this.dwVideoFrameRate = dwVideoFrameRate;
}
public int getDwVideoBitrate() {
return dwVideoBitrate;
}
public void setDwVideoBitrate(int dwVideoBitrate) {
this.dwVideoBitrate = dwVideoBitrate;
}
public int getwIntervalFrameI() {
return wIntervalFrameI;
}
public void setwIntervalFrameI(int wIntervalFrameI) {
this.wIntervalFrameI = wIntervalFrameI;
}
public byte getByIntervalBPFrame() {
return byIntervalBPFrame;
}
public void setByIntervalBPFrame(byte byIntervalBPFrame) {
this.byIntervalBPFrame = byIntervalBPFrame;
}
}
package com.zhonglai.luhui.camera.hk.sdk.ui.vo;
public class VedioCompreVo {
private VedioCompreDtVo struNormHighRecordPara;
private VedioCompreDtVo struEventRecordPara;
private VedioCompreDtVo struNetPara;
public VedioCompreDtVo getStruNormHighRecordPara() {
return struNormHighRecordPara;
}
public void setStruNormHighRecordPara(VedioCompreDtVo struNormHighRecordPara) {
this.struNormHighRecordPara = struNormHighRecordPara;
}
public VedioCompreDtVo getStruEventRecordPara() {
return struEventRecordPara;
}
public void setStruEventRecordPara(VedioCompreDtVo struEventRecordPara) {
this.struEventRecordPara = struEventRecordPara;
}
public VedioCompreDtVo getStruNetPara() {
return struNetPara;
}
public void setStruNetPara(VedioCompreDtVo struNetPara) {
this.struNetPara = struNetPara;
}
}
package com.zhonglai.luhui.camera.hk.sdk.util;
import cn.hutool.core.lang.Assert;
public class ByteUtil {
public static byte[] setStrToByteArr(String str,int arrLen){
byte [] arr = new byte[arrLen];
byte [] strBytes=str.getBytes();
Assert.isTrue(arrLen>strBytes.length,"arrLen is too small.");
for(int i=0;i<strBytes.length;i++){
arr[i]=strBytes[i];
}
return arr;
}
public static int getValidLength(byte[] bytes){
int i = 0;
if (null == bytes || 0 == bytes.length)
return i ;
for (; i < bytes.length; i++) {
if (bytes[i] == '\0')
break;
}
return i;
}
}
package com.zhonglai.luhui.camera.hk.sdk.util;
import java.util.*;
/**
* @author gongjunlang
*/
public class ComnUtil {
/**
* 判断一个对象是否为空
* <p>
* 以下情况为true
* <p>
* 对象为null
* <p>
* 字符串对象为""或者length为0
* <p>
* 集合对象size为0
* <p>
* 数组对象length为0
*
* @param obj
* @return
*/
public static boolean isEmpty(Object obj) {
if (obj == null) {
return true;
} else if (obj instanceof String) {
return ((String) obj).trim().equals("");
} else if (obj instanceof StringBuilder) {
return ((StringBuilder) obj).length() == 0;
} else if (Collection.class.isAssignableFrom(obj.getClass())) {
return ((Collection<?>) obj).size() == 0;
} else if (obj instanceof Map) {
return ((Map<?, ?>) obj).size() == 0;
} else if (obj.getClass().isArray()) {
if (obj instanceof byte[]) {
return ((byte[]) obj).length == 0;
}
if (obj instanceof short[]) {
return ((short[]) obj).length == 0;
}
if (obj instanceof int[]) {
return ((int[]) obj).length == 0;
}
if (obj instanceof long[]) {
return ((long[]) obj).length == 0;
}
if (obj instanceof char[]) {
return ((char[]) obj).length == 0;
}
if (obj instanceof float[]) {
return ((float[]) obj).length == 0;
}
if (obj instanceof double[]) {
return ((double[]) obj).length == 0;
}
if (obj instanceof boolean[]) {
return ((boolean[]) obj).length == 0;
}
return ((Object[]) obj).length == 0;
} else if (obj instanceof StringBuffer) {
return ((StringBuffer) obj).length() == 0;
}
return false;
}
/**
* 判断一个对象是否为空
* <p>
* 以下情况为true
* <p>
* 对象为null
* <p>
* 字符串对象为""或者length为0
* <p>
* 集合对象size为0
* <p>
* 数组对象length为0
* <p>
* 数字对象值为0
*
* @param obj
* @return
*/
public static boolean isEmptyOrZero(Object obj) {
if (Number.class.isAssignableFrom(obj.getClass())) {
if (((Number) obj).intValue() == 0 || ((Number) obj).doubleValue() == 0 || ((Number) obj).longValue() == 0
|| ((Number) obj).floatValue() == 0 || ((Number) obj).shortValue() == 0
|| ((Number) obj).byteValue() == 0) {
return true;
}
}
return isEmpty(obj);
}
/**
* 适用于非复合主键数据
*
* @param key
* @return
*/
public static String getStringWithSingleQuotes(String key, String split) {
String[] ids = key.split(split);
String result = "";
for (String id : ids) {
result += ",'" + id + "'";
}
if (result.length() > 0) {
return result.substring(1);
}
return null;
}
public static List<String> string2List(String key, String split) {
if (isEmpty(key)) {
return new ArrayList<String>();
}
return Arrays.asList(key.split(split));
}
/**
* @param src
* @param concat
* @return
*/
public static <T> T[] concatArray(T[] src, T[] concat) {
List<T> srcList = new ArrayList<T>(Arrays.asList(src));
List<T> concatList = new ArrayList<T>(Arrays.asList(concat));
srcList.addAll(concatList);
return srcList.toArray(src);
}
// public static Object[] concatArray(Object[] src, Object[] concat) {
// List<Object> srcList = new ArrayList<Object>(Arrays.asList(src));
// List<Object> concatList = new ArrayList<Object>(Arrays.asList(concat));
// srcList.addAll(concatList);
// return srcList.toArray(src);
// }
}
package com.zhonglai.luhui.camera.hk.sdk.util;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import com.sun.jna.Structure;
import cn.hutool.json.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @ClassName: ConvertUtil
* @Description: 数据转换工具类
* @author: ShenYue
* @date: 2019年4月22日 下午3:22:59
*/
public class ConvertUtil {
private static Logger logger = LoggerFactory.getLogger(ConvertUtil.class);
/**
* 结构体转map
* @param t 待转换的结构体
* @param ignoreFields 忽略的字段列表
* @return 转换后的map,传入的结构体为NULL时,返回值也为NULL
*/
public static <T> Map<String,Object> struct2Map(T t,String...ignoreFields){
if(t == null){
return null;
}
Class<?> clazz = t.getClass();
List<String> ignoreList=Arrays.asList(ignoreFields);
Map<String,Object> map = new HashMap<>(32);
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields){
Class<?> type=field.getType();
String fieldName=field.getName();
field.setAccessible(true);
try{
if(!ignoreList.contains(fieldName)){
if(isBaseType(type)){
map.put(fieldName,field.get(t));
}else if(type == byte[].class){
byte[] bytes=(byte[]) field.get(t);
int validByteLen=ByteUtil.getValidLength(bytes);
map.put(fieldName,new String(bytes,0,validByteLen));
}else if(type.newInstance() instanceof Structure){
map.put(fieldName,struct2Map(field.get(t)));
}else{
logger.warn("unsupport type "+type);
}
}
} catch ( InstantiationException e) {
logger.error("can not instance obj.");
e.printStackTrace();
} catch (IllegalAccessException e) {
logger.error("no access to convert field.");
e.printStackTrace();
}
}
return map;
}
/**
* 结构体转换为json
* @param t 待转换的结构体
* @param ignoreFields 忽略的字段列表
* @return
*/
public static <T> String struct2Json(T t,String...ignoreFields){
return JSONUtil.toJsonPrettyStr(struct2Map(t,ignoreFields));
}
/**
* 将map中的参数值赋值到结构体中
* @param t 待赋值的结构体
* @param params 封装相关参数的map
* @return 赋值完成的结构体,传入的结构体为NULL时,返回值也为NULL
*/
public static <T> T map2Struct(T t,Map<String,Object> params){
if(t == null){
return null;
}
Class<?> clazz = t.getClass();
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields){
Class<?> type=field.getType();
String fieldName=field.getName();
field.setAccessible(true);
try{
if(params.containsKey(fieldName) && !ComnUtil.isEmpty(params.get(fieldName))){
if(type == byte[].class){
int byteLen = ((byte[])field.get(t)).length;
field.set(t,ComnUtil.isEmpty(params.get(fieldName).toString())? field.get(t) : ByteUtil.setStrToByteArr(params.get(fieldName).toString(),byteLen));
}else if(type == byte.class){
field.set(t,Byte.valueOf(String.valueOf(params.get(fieldName))).intValue());
}else if(type == int.class){
field.set(t,Integer.valueOf(String.valueOf(params.get(fieldName))).intValue());
}else if(type == short.class){
field.set(t,Short.valueOf(String.valueOf(params.get(fieldName))).intValue());
}else if(type == double.class){
field.set(t,Double.valueOf(String.valueOf(params.get(fieldName))).intValue());
}else if(type == float.class){
field.set(t,Float.valueOf(String.valueOf(params.get(fieldName))).intValue());
}else if(type == char.class){
String source=String.valueOf(params.get(fieldName));
if(source.length()!=1){
logger.error("can not convert "+type+" to char.");
throw new RuntimeException("can not convert "+type+" to char.");
}
field.set(t,String.valueOf(params.get(fieldName)).charAt(0));
}else {
logger.warn("unsupport type "+type+","+fieldName+" is skiped.");
}
}
}catch (IllegalAccessException e) {
logger.error("no access to convert field.");
e.printStackTrace();
}
}
return t;
}
/**
* list转obj二维数组
* @param list 待转换的list
* @return
*/
public static <T> Object[][] toObjArray(List<T> list){
try{
if(list== null || list.size()==0){
return null;
}
Field[] fields = list.get(0).getClass().getDeclaredFields();
Object[][] objs=new Object[list.size()][fields.length];
for(int row=0;row<list.size();row++){
T t=list.get(row);
fields =t.getClass().getDeclaredFields();
for(int col=0;col<fields.length;col++){
fields[col].setAccessible(true);
objs[row][col]=fields[col].get(t);
}
}
return objs;
}catch(Exception e){
logger.error("no access to convert field.");
e.printStackTrace();
}
return null;
}
/**
* map转对象
* @param paramMap 待转换map
* @param cls 转换对象的class
* @return
*/
public static <T> T map2Object(Map<?, ?> paramMap, Class<T> cls) {
return JSONObject.parseObject(JSONObject.toJSONString(paramMap), cls);
}
/**
* json转map
* @param jsonObj json字符串
* @return
*/
public static Map<String, Object> jsonToMap(String jsonObj) {
return (Map<String, Object>) JSONObject.parseObject(jsonObj);
}
/**
* 判断是否为基本类型
* @param type 传入类型
* @return
*/
public static boolean isBaseType(Class<?> type) {
if (type.equals(int.class) ||
type.equals(byte.class) ||
type.equals(long.class) ||
type.equals(double.class) ||
type.equals(float.class) ||
type.equals(char.class) ||
type.equals(short.class) ||
type.equals(boolean.class)) {
return true;
}
return false;
}
}
package com.zhonglai.luhui.camera.hk.sdk.util;
import java.util.HashMap;
import java.util.Map;
import cn.hutool.setting.dialect.Props;
public class DicUtil {
private static Props dicEn2CnProps;
private static Props dicCn2EnProps;
private static Props getDicCn2EnProps(){
if(dicCn2EnProps==null){
dicCn2EnProps=new Props("dic/dic_cn_en.properties");
}
return dicCn2EnProps;
}
private static Props getDicEn2CnProps(){
if(dicEn2CnProps==null){
dicEn2CnProps=new Props("dic/dic_en_cn.properties");
}
return dicEn2CnProps;
}
public static Map<String,Object> translateMap2CnKey(Map<String,Object> map,boolean skipNoneNote){
return translateMapKey(map,getDicEn2CnProps(),skipNoneNote);
}
public static Map<String,Object> translateMap2EnKey(Map<String,Object> map,boolean skipNoneNote){
return translateMapKey(map,getDicCn2EnProps(),skipNoneNote);
}
private static Map<String,Object> translateMapKey(Map<String,Object> map,Props dicProps,boolean skipNoneNote){
Map<String,Object> currMap = new HashMap<>();
for (Map.Entry<String,Object> entry : map.entrySet()) {
if(dicProps.containsKey(entry.getKey())){
currMap.put(dicProps.getProperty(entry.getKey()),entry.getValue());
}else{
if(!skipNoneNote){
currMap.put(entry.getKey(),entry.getValue());
}
}
}
return currMap;
}
}
package com.zhonglai.luhui.camera.hk.sdk.util;
import com.zhonglai.luhui.camera.hk.sdk.func.HCSadpSdkFunc;
import cn.hutool.setting.dialect.Props;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SdkErrorUtil {
private static Logger logger = LoggerFactory.getLogger(SdkErrorUtil.class);
private static Props HkNetErrorProps;
private static Props HkSadpErrorProps;
private final static String HK_NET_ERROR_PREFIX="HK_NET_ERROR_";
private final static String HK_SADP_ERROR_PREFIX="HK_SADP_ERROR_";
private static Props getHkNetErrorProps(){
if(HkNetErrorProps==null){
HkNetErrorProps=new Props("hk_net_error.properties");
}
return HkNetErrorProps;
}
private static Props getHkSadpErrorProps(){
if(HkSadpErrorProps==null){
HkSadpErrorProps=new Props("hk_sadp_error.properties");
}
return HkSadpErrorProps;
}
public static String getHCSadpErrorMsg(){
int code=HCSadpSdkFunc.sadpSdk.SADP_GetLastError();
if(code!=0){
String error=getHkSadpErrorProps().getStr(HK_SADP_ERROR_PREFIX+code);
logger.error(code+"--"+error);
return error;
}
return null;
}
}
package com.zhonglai.luhui.camera.hk.sdk.util;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Test {
private static final String BROADCAST_IP = "255.255.255.255";
private static final int BROADCAST_PORT = 37020; // 假设海康搜索使用该端口(根据实际配置)
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();
socket.setBroadcast(true);
String discoveryMessage = "HIKDISCOVERY"; // 模拟发送搜索请求
byte[] buffer = discoveryMessage.getBytes();
DatagramPacket packet = new DatagramPacket(
buffer, buffer.length,
InetAddress.getByName(BROADCAST_IP),
BROADCAST_PORT
);
socket.send(packet);
System.out.println("等待设备响应...");
byte[] recvBuf = new byte[15000];
DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
socket.receive(receivePacket);
String response = new String(receivePacket.getData(), 0, receivePacket.getLength());
System.out.println("发现设备: " + response);
socket.close();
}
}
package com.zhonglai.luhui.camera.hk.sdk.service;
package com.zhonglai.luhui.camera.httpservice;
import com.sun.net.httpserver.*;
... ... @@ -14,7 +14,7 @@ public class SimpleHttpServer {
server.createContext("/static/", new StaticFileHandler("static"));
// 映射 /cameras 到动态摄像头数据
server.createContext("/cameras", new CamerasHandler());
// server.createContext("/cameras", new CamerasHandler());
server.setExecutor(null); // 默认线程池
server.start();
... ...
package com.zhonglai.luhui.camera.mqtt;
import com.alibaba.fastjson.JSONObject;
import com.zhonglai.luhui.camera.dto.Topic;
import com.zhonglai.luhui.camera.mqtt.cmmd.AnalysisCommd;
import com.zhonglai.luhui.camera.mqtt.cmmd.AnalysisPut;
import com.zhonglai.luhui.camera.mqtt.cmmd.AnalysisRead;
public class CommdOperateService {
private Topic topic;
private JSONObject data;
private CommdOperateService(Topic topic,JSONObject data)
{
this.topic = topic;
this.data = data;
}
public static CommdOperateService getInstance(String topic,JSONObject data)
{
return new CommdOperateService(new Topic(topic),data);
}
public AnalysisCommd operate()
{
switch (topic.getTopicType())
{
case Topic.TOPIC_PUT:
return new AnalysisPut(topic.getTime(),data);
case Topic.TOPIC_READ:
return new AnalysisRead(topic.getTime(),data);
default:
return null;
}
}
}
... ...
package com.zhonglai.luhui.camera.mqtt;
import com.alibaba.fastjson.JSONObject;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Set;
/**
* mqtt回调
*/
public class MqttCallback implements MqttCallbackExtended {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private MqttService mqttclient;
public MqttCallback(MqttService mqttclient)
{
this.mqttclient = mqttclient;
}
@Override
public void connectComplete(boolean b, String s) {
log.info("连接成功");
Set<String> topics = mqttclient.subscribe();
log.info("-----------订阅成功:{}--------------------",topics);
}
@Override
public void connectionLost(Throwable cause) {
log.error("连接丢失重新链接",cause);
while (!mqttclient.connect())
{
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
log.info("mqtt发来消息>>>>>>>:{} 《===============》 字符串:【{}】",topic,message.toString());
String str = new String(message.getPayload());
JSONObject jsonObject = JSONObject.parseObject(str);
if (jsonObject.containsKey("1_1") && !jsonObject.getJSONObject("1_1").isEmpty())
{
JSONObject payloaddata = jsonObject.getJSONObject("1_1");
CommdOperateService.getInstance(topic,payloaddata).operate().returnData(mqttclient);
}
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
log.info("消息发送完成");
}
}
... ...
package com.zhonglai.luhui.camera.mqtt;
import com.zhonglai.luhui.camera.config.SysConfig;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.util.Set;
public class MqttService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private MqttClient mqttclient;
private MqttConnectOptions options;
// 使用 volatile 确保多线程内存可见性和禁止指令重排
private static volatile MqttService instance;
private MqttService() {
// 初始化代码
try {
sart();
} catch (MqttException e) {
throw new RuntimeException(e);
}
}
public static MqttService getInstance() {
if (instance == null) {
synchronized (MqttService.class) {
if (instance == null) {
instance = new MqttService();
}
}
}
return instance;
}
private void init() throws MqttException {
if(null == mqttclient)
{
mqttclient = new MqttClient(SysConfig.mqttConfig.mqttBroker, SysConfig.mqttConfig.mqttClientId, new MemoryPersistence());
}
options = new MqttConnectOptions();
options.setCleanSession(true);
options.setConnectionTimeout(15);
options.setKeepAliveInterval(60); // 添加心跳设置,单位为秒
//设置断开后重新连接
options.setAutomaticReconnect(true);
mqttclient.setCallback(new MqttCallback(this));
}
public boolean connect() {
try {
options.setUserName(SysConfig.mqttConfig.mqttUserName);
options.setPassword(SysConfig.mqttConfig.mqttPassword.toCharArray());
mqttclient.connect(options);
return true;
} catch (MqttException e) {
log.error("-----------mqtt连接服务器失败--------------------",e);
}
return false;
}
public void sart() throws MqttException{
log.info("-----------开始启动mqtt监听服务--------------------");
init();
connect();
log.info("-----------mqtt连接服务器成功--------------------");
}
@PreDestroy
public void stop() throws MqttException {
if(null != mqttclient)
{
log.info("退出mqtt服务");
mqttclient.unsubscribe(SysConfig.mqttConfig.subTopic.toArray(new String[SysConfig.mqttConfig.subTopic.size()]));
mqttclient.disconnect();
mqttclient.close();
}
instance = null;
}
public void publish(String topic, String messageStr) throws MqttException {
MqttMessage message = new MqttMessage();
message.setPayload(messageStr.getBytes());
mqttclient.publish(topic,message);
}
public Set<String> subscribe()
{
try {
mqttclient.subscribe(SysConfig.mqttConfig.subTopic.toArray(new String[SysConfig.mqttConfig.subTopic.size()]));
} catch (MqttException e) {
e.printStackTrace();
}
return SysConfig.mqttConfig.subTopic;
}
}
... ...
package com.zhonglai.luhui.camera.mqtt;
import com.alibaba.fastjson.JSONObject;
import com.zhonglai.luhui.camera.config.SysConfig;
import com.zhonglai.luhui.camera.rtspwebrtc.DockerSecretFetcher;
import com.zhonglai.luhui.camera.rtspwebrtc.WebRtcService;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Task {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public void updata() {
// 每隔 30 秒执行一次
scheduler.scheduleAtFixedRate(() -> {
System.out.println("定时任务正在执行...");
try {
String localip = WebRtcService.getLocalIpAddress();
String playurl = WebRtcService.getPlayUrl(localip, SysConfig.webrtc_app, SysConfig.cameraSerial);
boolean oline = WebRtcService.isMediaOnline(SysConfig.cameraSerial, SysConfig.webrtc_app, SysConfig.getWebrtcSecret());
JSONObject jsonObject = new JSONObject();
JSONObject data = new JSONObject();
data.put("playurl", playurl);
data.put("online", oline);
jsonObject.put("1_1",data);
MqttService.getInstance().publish("ADD_POST", jsonObject.toJSONString());
} catch (Exception e) {
logger.error("定时任务执行异常", e);
}
}, 0, SysConfig.sysTaskInterval, TimeUnit.SECONDS);
}
public void stopScheduler() {
if (null != scheduler)
{
logger.info("停止定时任务");
scheduler.shutdown();
}
}
}
... ...
package com.zhonglai.luhui.camera.mqtt.cmmd;
import com.alibaba.fastjson.JSONObject;
import com.zhonglai.luhui.camera.mqtt.MqttService;
public interface AnalysisCommd {
void returnData(MqttService mqttService);
}
... ...
package com.zhonglai.luhui.camera.mqtt.cmmd;
import com.zhonglai.luhui.camera.mqtt.MqttService;
public class AnalysisDefault implements AnalysisCommd{
@Override
public void returnData(MqttService mqttService) {
System.out.println("未知的topic");
}
}
... ...
package com.zhonglai.luhui.camera.mqtt.cmmd;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhonglai.luhui.camera.config.SysConfig;
import com.zhonglai.luhui.camera.mqtt.MqttService;
import com.zhonglai.luhui.camera.rtspwebrtc.WebRtcService;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AnalysisPut implements AnalysisCommd{
private final Logger log = LoggerFactory.getLogger(this.getClass());
private String reStr;
private String time;
public AnalysisPut(String time,JSONObject data)
{
this.time = time;
if(null != data && data.size() != 0)
{
for (String key : data.keySet())
{
switch (key)
{
case "startStream":
reStr = startStream(data);
return;
case "stopStream":
reStr = stopStream(data);
return;
default:
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",0);
jsonObject.put("msg","未知的指令:"+key);
reStr = jsonObject.toJSONString();
return;
}
}
}
}
private String startStream(JSONObject data)
{
String deviceSerial = data.getString("startStream");
if (null != deviceSerial && !"".equals(deviceSerial))
{
String auto_close = "true";
if(data.containsKey("autoClose") && !data.getBoolean("autoClose"))
{
auto_close = "false";
}
JSONObject rtspUrl = WebRtcService.startStreamBySerial(deviceSerial,auto_close);
return rtspUrl.toJSONString();
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",0);
jsonObject.put("msg","摄像头序列号不能为空");
return jsonObject.toJSONString();
}
private String stopStream(JSONObject data)
{
String deviceSerial = data.getString("stopStream");
if (null != deviceSerial && !"".equals(deviceSerial))
{
String str = WebRtcService.stopStream(deviceSerial,SysConfig.webrtc_app,SysConfig.getWebrtcSecret());
JSONObject jsonObject = JSON.parseObject(str);
if(jsonObject.containsKey("code") && jsonObject.getInteger("code")==0)
{
jsonObject.put("code",1);
return jsonObject.toJSONString();
}
jsonObject.put("code",0);
System.out.println(str);
return jsonObject.toJSONString();
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",0);
jsonObject.put("msg","摄像头序列号不能为空");
return jsonObject.toJSONString();
}
@Override
public void returnData(MqttService mqttService) {
String topic = "PUT_REQ/"+time;
try {
log.info("发送指令返回数据:【{}】【{}】",topic,reStr);
mqttService.publish(topic, reStr);
} catch (MqttException e) {
System.err.println(e);
}
}
}
... ...
package com.zhonglai.luhui.camera.mqtt.cmmd;
import com.alibaba.fastjson.JSONObject;
import com.zhonglai.luhui.camera.config.SysConfig;
import com.zhonglai.luhui.camera.mqtt.MqttService;
import com.zhonglai.luhui.camera.rtspwebrtc.WebRtcService;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AnalysisRead implements AnalysisCommd{
private final Logger log = LoggerFactory.getLogger(this.getClass());
private String reStr;
private String time;
public AnalysisRead(String time,JSONObject data)
{
this.time = time;
if(null != data && data.size() != 0)
{
for (String key : data.keySet())
{
switch (key)
{
case "getPlayUrl":
reStr = getPlayUrl(data);
break;
case "getSecret":
reStr = getSecret(data);
break;
default:
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",0);
jsonObject.put("msg","未知的指令:"+key);
reStr = jsonObject.toJSONString();
break;
}
}
}
}
private String getSecret(JSONObject data)
{
String type = data.getString("getSecret");
switch (type)
{
case "memory":
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",1);
jsonObject.put("secret",SysConfig.getWebrtcSecret());
return jsonObject.toJSONString();
default:
return null;
}
}
private String getPlayUrl(JSONObject data)
{
String deviceSerial = data.getString("getPlayUrl");
String localip = WebRtcService.getLocalIpAddress();
String playurl = WebRtcService.getPlayUrl(localip, SysConfig.webrtc_app, deviceSerial);
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",1);
jsonObject.put("playurl",playurl);
return jsonObject.toJSONString();
}
@Override
public void returnData(MqttService mqttService) {
String topic = "READ_REQ/"+time;
try {
log.info("发送指令返回数据:【{}】【{}】",topic,reStr);
mqttService.publish(topic, reStr);
} catch (MqttException e) {
System.err.println(e);
}
}
}
... ...
package com.zhonglai.luhui.camera.rtspwebrtc;
import com.zhonglai.luhui.camera.App;
import com.zhonglai.luhui.camera.config.SysConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Properties;
public class DockerSecretFetcher {
private static Logger logger = LoggerFactory.getLogger(App.class);
public static String getZLMSecret() {
String[] command = {
"docker", "exec", "zlmediakit",
"grep", "^secret=", "/opt/media/conf/config.ini"
};
logger.info("正在通过指令{}获取操作令牌...",command);
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectErrorStream(true); // 合并错误流和标准输出流
try {
Process process = processBuilder.start();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
logger.info("执行指令返回的数据:{}",line);
if (line.startsWith("secret=")) {
return line.substring("secret=".length()).trim();
}
}
}
int exitCode = process.waitFor();
if (exitCode != 0) {
logger.info("命令执行失败,退出码:"+exitCode);
}
} catch (Exception e) {
logger.info("拿操作令牌异常,去配置里面拿:",e);
Properties properties = SysConfig.loadProperties();
return properties.getProperty("webrtc.secret");
}
return null; // 未找到 secret 或执行失败
}
}
... ...
package com.zhonglai.luhui.camera.rtspwebrtc;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhonglai.luhui.camera.App;
import com.zhonglai.luhui.camera.config.SysConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
public class WebRtcService {
private static final String ZLM_API = "http://192.168.0.103:180/index/api";
public static String startStream(String stream,String rtspUrl,String app)
private static Logger logger = LoggerFactory.getLogger(App.class);
private static String localIp;
public static JSONObject startStream(String stream,String rtspUrl,String app,String secret,String auto_close)
{
String url = ZLM_API + "/addStreamProxy?vhost=__defaultVhost__&app=" + app +
"&stream=" + stream + "&url=" + rtspUrl + "&enable_rtsp=1&enable_auto_close=1&enable_mp4=0&secret=Gbc0ThIWCTdlAHlyNVY4sJinYkXjAMBg";
StringBuffer stringBuffer = getZlmApi();
stringBuffer.append("/addStreamProxy?");
stringBuffer.append("secret=");
stringBuffer.append(secret);
stringBuffer.append("&vhost=__defaultVhost__");
stringBuffer.append("&app=");
stringBuffer.append(app);
stringBuffer.append("&stream=");
stringBuffer.append(stream);
stringBuffer.append("&url=");
stringBuffer.append(rtspUrl);
stringBuffer.append("&enable_auto_close=1");
stringBuffer.append("&retry_count=-1&rtp_type=0&timeout_sec=10&enable_hls=false&enable_hls_fmp4=false&enable_mp4=false&enable_rtsp=true&enable_rtmp=false&enable_ts=false&enable_fmp4=true&hls_demand=false&rtsp_demand=false&rtmp_demand=false&ts_demand=false&fmp4_demand=false&enable_audio=true&add_mute_audio=true&mp4_max_second=10&mp4_as_player=false&auto_close="+auto_close);
logger.info("添加流的接口请求:"+stringBuffer.toString());
String str = HttpUtil.get(stringBuffer.toString());
JSONObject jsonObject = JSON.parseObject(str);
if(jsonObject.containsKey("code") && jsonObject.getInteger("code")==0)
{
jsonObject.put("code",1);
String localip = WebRtcService.getLocalIpAddress();
String playurl = WebRtcService.getPlayUrl(localip, SysConfig.webrtc_app, stream);
jsonObject.getJSONObject("data").put("playurl",playurl);
return jsonObject;
}
jsonObject.put("code",0);
System.out.println(str);
return jsonObject;
}
public static String stopStream( String stream,String app,String secret) {
String url = getZlmApi() + "/close_stream?schema=rtsp&vhost=__defaultVhost__&app=" + app + "&stream=" + stream+"&force=1&secret="+secret;
String str = HttpUtil.get(url);
System.out.println(str);
return str;
}
public static String stopStream( String stream,String app) {
String url = ZLM_API + "/close_stream?schema=rtsp&vhost=__defaultVhost__&app=" + app + "&stream=" + stream+"&force=1&secret=Gbc0ThIWCTdlAHlyNVY4sJinYkXjAMBg";
private static StringBuffer getZlmApi()
{
return new StringBuffer().append("http://").append(SysConfig.webrtc_host).append("/index/api");
}
public static JSONObject startStreamBySerial(String deviceSerial,String auto_close)
{
String str = HttpUtil.get(SysConfig.yuerleApiUrl+"?deviceSerial="+deviceSerial);
JSONObject jsonObject = JSON.parseObject(str);
if(jsonObject.containsKey("code") && jsonObject.getInteger("code")==1 && null != jsonObject.get("data"))
{
String enable_rtsp = jsonObject.getString("data");
logger.info("令牌{}获取到设备{}的rtsp地址{}",SysConfig.getWebrtcSecret(),deviceSerial,enable_rtsp);
return WebRtcService.startStream(deviceSerial,enable_rtsp,SysConfig.webrtc_app,SysConfig.getWebrtcSecret(),auto_close);
}
return jsonObject;
}
public static String getPlayUrl(String ip,String app,String stream)
{
return "https://"+ip+"/index/api/webrtc?app="+app+"&stream="+stream+"&type=play";
}
public static boolean isMediaOnline(String stream,String app,String secret) {
String url = getZlmApi() + "/isMediaOnline?secret="+secret+"&schema=rtsp&vhost=__defaultVhost__&app="+app+"&stream="+stream;
String str = HttpUtil.get(url);
System.out.println(str);
return str;
return JSON.parseObject(str).containsKey("online") && JSON.parseObject(str).getBoolean("online");
}
/**
* 获取本机IP
* @return
*/
public static String getLocalIpAddress() {
if(null != localIp)
{
return localIp;
}
try {
// 构造一个连接外部地址的 socket(这里用 Google 的公共 DNS IP)
try (DatagramSocket socket = new DatagramSocket()) {
socket.connect(InetAddress.getByName("8.8.8.8"), 10002);
InetAddress localAddress = socket.getLocalAddress();
return SysConfig.webrtc_host=localIp=localAddress.getHostAddress();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
// startStream("cam1","rtsp://admin:Luhui586@192.168.0.101:554/h264/ch1/main/av_stream","live");
stopStream("live","cam1");
SysConfig.init();
System.out.println(WebRtcService.startStream("BA8609485","rtsp://admin:GCQGTC@192.168.0.101:554/h264/ch1/main/av_stream","yuerle","keXTvTDSHAxFDpBA0MDAHhxWeVXLQmUq","true"));
}
}
... ...
{
"password": "Admin12345",
"port": 8000,
"ip": "192.168.30.188",
"username": "admin",
"status": "未处理"
}
\ No newline at end of file
{"sChanName": "test1"}
\ No newline at end of file
{
"szSipAuthenticateID": "34020000001320000001",
"wServerSipPort": "5060",
"wLocalSipPort": "5060",
"byStreamType": "0",
"byEnable": "1",
"dwRegisterInterval": "60",
"szDeviceDomain": "abc",
"dwRegisterValid": "3600",
"byTransProtocol": "0",
"byProtocolVersion": "2",
"szServerID": "34020000002000000001",
"szSipAuthenticatePasswd": "12345678",
"dwAutoAllocChannelID": "0",
"szServerDomain": "3402000000",
"byHeartbeatInterval": "60",
"byDeviceStatus": "1",
"szSipServerAddress": "10.1.1.1",
"szSipUserName": "34020000001320000001",
"byMaxHeartbeatTimeOut": "3"
}
{
"struEventRecordPara": {
"byPicQuality": 0,
"byVideoEncType": 0,
"byBitrateType": 0,
"byStreamType": 1,
"byres": "",
"wIntervalFrameI": 0,
"byIntervalBPFrame": 0,
"dwVideoFrameRate": 0,
"byENumber": 0,
"dwVideoBitrate": 0,
"byAudioEncType": 0,
"byResolution": 0
},
"struRes": {
"byPicQuality": 0,
"byVideoEncType": 0,
"byBitrateType": 0,
"byStreamType": 1,
"byres": "",
"wIntervalFrameI": 0,
"byIntervalBPFrame": 0,
"dwVideoFrameRate": 0,
"byENumber": 0,
"dwVideoBitrate": 0,
"byAudioEncType": 0,
"byResolution": 0
},
"struNetPara": {
"byPicQuality": 2,
"byVideoEncType": 1,
"byBitrateType": 1,
"byStreamType": 0,
"byres": "",
"wIntervalFrameI": 50,
"byIntervalBPFrame": 2,
"dwVideoFrameRate": 0,
"byENumber": 0,
"dwVideoBitrate": 19,
"byAudioEncType": 0,
"byResolution": 3
},
"struNormHighRecordPara": {
"byPicQuality": 2,
"byVideoEncType": 1,
"byBitrateType": 1,
"byStreamType": 0,
"byres": "",
"wIntervalFrameI": 50,
"byIntervalBPFrame": 2,
"dwVideoFrameRate": 0,
"byENumber": 0,
"dwVideoBitrate": 25,
"byAudioEncType": 0,
"byResolution": 27
},
"dwSize": 116
}
\ No newline at end of file
#base
IP=ip
\u7528\u6237\u540D=username
\u5BC6\u7801=password
\u7AEF\u53E3=port
\u64CD\u4F5C\u72B6\u6001=status
\u9519\u8BEF\u4FE1\u606F=msg
#aisle
\u901A\u9053\u540D\u79F0=chanName
28181\u534F\u8BAE\u4F7F\u80FD=byEnable
\u670D\u52A1\u5668\u57DF =szServerDomain
\u6700\u5927\u5FC3\u8DF3\u8D85\u65F6\u6B21\u6570=byMaxHeartbeatTimeOut
SIP\u7528\u6237\u540D=szSipUserName
SIP\u7528\u6237\u8BA4\u8BC1\u5BC6\u7801=szSipAuthenticatePasswd
\u6CE8\u518C\u6709\u6548\u671F=dwRegisterValid
\u5FC3\u8DF3\u95F4\u9694=byHeartbeatInterval
\u670D\u52A1\u5668ID=szServerID
\u53D6\u6D41\u7C7B\u578B\uFF1A0-\u4E3B\u7801\u6D41\uFF0C1-\u5B50\u7801\u6D41\uFF0C2-\u4E09\u7801\u6D41=byStreamType
\u670D\u52A1\u5668SIP\u7AEF\u53E3=wServerSipPort
\u8BBE\u5907\u662F\u5426\u5728\u7EBF\u72B6\u6001\uFF1A0-\u4FDD\u7559\uFF0C1-\u5728\u7EBF\uFF0C2-\u79BB\u7EBF =byDeviceStatus
\u534F\u8BAE\u7248\u672C\uFF1A0-GB/T28181-2011\uFF0C1-GB/T28181-2015\uFF0C2-GB/T28181-2016=byProtocolVersion
\u662F\u5426\u81EA\u52A8\u5206\u914D\u901A\u9053ID\uFF0C\u6309\u4F4D\u8868\u793A\uFF0C\u53D6\u503C\uFF1A0-\u624B\u52A8\u914D\u7F6E\uFF0C1-\u81EA\u52A8\u5206\u914D=dwAutoAllocChannelID
SIP\u670D\u52A1\u5668\u5730\u5740=szSipServerAddress
SIP\u7528\u6237\u8BA4\u8BC1ID(\u6CE8\u518C\u7528\u6237\u540D)=szSipAuthenticateID
\u6CE8\u518C\u95F4\u9694\uFF08\u6CE8\u518C\u5931\u8D25\u540E\u518D\u6B21\u6CE8\u518C\u7684\u65F6\u95F4\u95F4\u9694\uFF09=dwRegisterInterval
\u8BBE\u5907SIP\u7AEF\u53E3=wLocalSipPort
\u4F20\u8F93\u534F\u8BAE(0-UDP\uFF0C1-TCP)=byTransProtocol
\ No newline at end of file
#base
ip=IP
username=\u7528\u6237\u540D
password=\u5BC6\u7801
port=\u7AEF\u53E3
msg=\u9519\u8BEF\u4FE1\u606F
status=\u64CD\u4F5C\u72B6\u6001
#aisle
chanName=\u901A\u9053\u540D\u79F0
#GBT28181
byEnable=28181\u534F\u8BAE\u4F7F\u80FD
byTransProtocol=\u4F20\u8F93\u534F\u8BAE(0-UDP\uFF0C1-TCP)
wLocalSipPort=\u8BBE\u5907SIP\u7AEF\u53E3
szServerID=\u670D\u52A1\u5668ID
szServerDomain=\u670D\u52A1\u5668\u57DF
szSipServerAddress=SIP\u670D\u52A1\u5668\u5730\u5740
wServerSipPort=\u670D\u52A1\u5668SIP\u7AEF\u53E3
byProtocolVersion=\u534F\u8BAE\u7248\u672C\uFF1A0-GB/T28181-2011\uFF0C1-GB/T28181-2015\uFF0C2-GB/T28181-2016
szSipUserName=SIP\u7528\u6237\u540D
szSipAuthenticateID=SIP\u7528\u6237\u8BA4\u8BC1ID(\u6CE8\u518C\u7528\u6237\u540D)
szSipAuthenticatePasswd=SIP\u7528\u6237\u8BA4\u8BC1\u5BC6\u7801
dwRegisterValid=\u6CE8\u518C\u6709\u6548\u671F
byHeartbeatInterval=\u5FC3\u8DF3\u95F4\u9694
byMaxHeartbeatTimeOut=\u6700\u5927\u5FC3\u8DF3\u8D85\u65F6\u6B21\u6570
byStreamType=\u53D6\u6D41\u7C7B\u578B\uFF1A0-\u4E3B\u7801\u6D41\uFF0C1-\u5B50\u7801\u6D41\uFF0C2-\u4E09\u7801\u6D41
byDeviceStatus=\u8BBE\u5907\u662F\u5426\u5728\u7EBF\u72B6\u6001\uFF1A0-\u4FDD\u7559\uFF0C1-\u5728\u7EBF\uFF0C2-\u79BB\u7EBF
dwRegisterInterval=\u6CE8\u518C\u95F4\u9694\uFF08\u6CE8\u518C\u5931\u8D25\u540E\u518D\u6B21\u6CE8\u518C\u7684\u65F6\u95F4\u95F4\u9694\uFF09
dwAutoAllocChannelID=\u662F\u5426\u81EA\u52A8\u5206\u914D\u901A\u9053ID\uFF0C\u6309\u4F4D\u8868\u793A\uFF0C\u53D6\u503C\uFF1A0-\u624B\u52A8\u914D\u7F6E\uFF0C1-\u81EA\u52A8\u5206\u914D
\ No newline at end of file
docker run -d -p 1935:1935 -p 80:80 -p 443:443 -p 8554:554 -p 10000:10000 -p 10000:10000/udp -p 8000:8000/udp --name zlmediakit --restart=always 3471609dacbf
docker exec zlmediakit grep '^secret=' /opt/media/conf/config.ini
\ No newline at end of file
... ...
HK_NET_ERROR_0=\u6CA1\u6709\u9519\u8BEF\u3002
HK_NET_ERROR_1=\u7528\u6237\u540D\u5BC6\u7801\u9519\u8BEF\u3002\u6CE8\u518C\u65F6\u8F93\u5165\u7684\u7528\u6237\u540D\u6216\u8005\u5BC6\u7801\u9519\u8BEF\u3002
HK_NET_ERROR_2=\u6743\u9650\u4E0D\u8DB3\u3002\u4E00\u822C\u548C\u901A\u9053\u76F8\u5173\uFF0C\u4F8B\u5982\u6709\u9884\u89C8\u901A\u90531\u6743\u9650\uFF0C\u65E0\u9884\u89C8\u901A\u90532\u6743\u9650\uFF0C\u5373\u6709\u9884\u89C8\u6743\u9650\u4F46\u4E0D\u5B8C\u5168\uFF0C\u9884\u89C8\u901A\u90532\u8FD4\u56DE\u6B64\u9519\u8BEF\u3002
HK_NET_ERROR_3=SDK\u672A\u521D\u59CB\u5316\u3002
HK_NET_ERROR_4=\u901A\u9053\u53F7\u9519\u8BEF\u3002\u8BBE\u5907\u6CA1\u6709\u5BF9\u5E94\u7684\u901A\u9053\u53F7\u3002
HK_NET_ERROR_5=\u8BBE\u5907\u603B\u7684\u8FDE\u63A5\u6570\u8D85\u8FC7\u6700\u5927\u3002
HK_NET_ERROR_6=\u7248\u672C\u4E0D\u5339\u914D\u3002SDK\u548C\u8BBE\u5907\u7684\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_7=\u8FDE\u63A5\u8BBE\u5907\u5931\u8D25\u3002\u8BBE\u5907\u4E0D\u5728\u7EBF\u6216\u7F51\u7EDC\u539F\u56E0\u5F15\u8D77\u7684\u8FDE\u63A5\u8D85\u65F6\u7B49\u3002
HK_NET_ERROR_8=\u5411\u8BBE\u5907\u53D1\u9001\u5931\u8D25\u3002
HK_NET_ERROR_9=\u4ECE\u8BBE\u5907\u63A5\u6536\u6570\u636E\u5931\u8D25\u3002
HK_NET_ERROR_10=\u4ECE\u8BBE\u5907\u63A5\u6536\u6570\u636E\u8D85\u65F6\u3002
HK_NET_ERROR_11=\u4F20\u9001\u7684\u6570\u636E\u6709\u8BEF\u3002\u53D1\u9001\u7ED9\u8BBE\u5907\u6216\u8005\u4ECE\u8BBE\u5907\u63A5\u6536\u5230\u7684\u6570\u636E\u9519\u8BEF\uFF0C\u5982\u8FDC\u7A0B\u53C2\u6570\u914D\u7F6E\u65F6\u8F93\u5165\u8BBE\u5907\u4E0D\u652F\u6301\u7684\u503C\u3002
HK_NET_ERROR_12=\u8C03\u7528\u6B21\u5E8F\u9519\u8BEF\u3002
HK_NET_ERROR_13=\u65E0\u6B64\u6743\u9650\u3002\u7528\u6237\u5BF9\u67D0\u4E2A\u529F\u80FD\u6A21\u5757\u7684\u6743\u9650\uFF0C\u4F8B\u5982\u65E0\u9884\u89C8\u6743\u9650\u7528\u6237\u9884\u89C8\u8FD4\u56DE\u6B64\u9519\u8BEF\u3002
HK_NET_ERROR_14=\u8BBE\u5907\u547D\u4EE4\u6267\u884C\u8D85\u65F6\u3002
HK_NET_ERROR_15=\u4E32\u53E3\u53F7\u9519\u8BEF\u3002\u6307\u5B9A\u7684\u8BBE\u5907\u4E32\u53E3\u53F7\u4E0D\u5B58\u5728\u3002
HK_NET_ERROR_16=\u62A5\u8B66\u7AEF\u53E3\u9519\u8BEF\u3002\u6307\u5B9A\u7684\u8BBE\u5907\u62A5\u8B66\u8F93\u5165\u6216\u8005\u8F93\u51FA\u7AEF\u53E3\u4E0D\u5B58\u5728\u3002
HK_NET_ERROR_17=\u53C2\u6570\u9519\u8BEF\u3002SDK\u63A5\u53E3\u4E2D\u7ED9\u5165\u7684\u8F93\u5165\u6216\u8F93\u51FA\u53C2\u6570\u4E3A\u7A7A\uFF0C\u6216\u8005\u53C2\u6570\u683C\u5F0F\u6216\u503C\u4E0D\u7B26\u5408\u8981\u6C42\u3002
HK_NET_ERROR_18=\u8BBE\u5907\u901A\u9053\u5904\u4E8E\u9519\u8BEF\u72B6\u6001
HK_NET_ERROR_19=\u8BBE\u5907\u65E0\u786C\u76D8\u3002\u5F53\u8BBE\u5907\u65E0\u786C\u76D8\u65F6\uFF0C\u5BF9\u8BBE\u5907\u7684\u5F55\u50CF\u6587\u4EF6\u3001\u786C\u76D8\u914D\u7F6E\u7B49\u64CD\u4F5C\u5931\u8D25\u3002
HK_NET_ERROR_20=\u786C\u76D8\u53F7\u9519\u8BEF\u3002\u5F53\u5BF9\u8BBE\u5907\u8FDB\u884C\u786C\u76D8\u7BA1\u7406\u64CD\u4F5C\u65F6\uFF0C\u6307\u5B9A\u7684\u786C\u76D8\u53F7\u4E0D\u5B58\u5728\u65F6\u8FD4\u56DE\u8BE5\u9519\u8BEF\u3002
HK_NET_ERROR_21=\u8BBE\u5907\u786C\u76D8\u6EE1\u3002
HK_NET_ERROR_22=\u8BBE\u5907\u786C\u76D8\u51FA\u9519
HK_NET_ERROR_23=\u8BBE\u5907\u4E0D\u652F\u6301\u3002
HK_NET_ERROR_24=\u8BBE\u5907\u5FD9\u3002
HK_NET_ERROR_25=\u8BBE\u5907\u4FEE\u6539\u4E0D\u6210\u529F\u3002
HK_NET_ERROR_26=\u5BC6\u7801\u8F93\u5165\u683C\u5F0F\u4E0D\u6B63\u786E
HK_NET_ERROR_27=\u786C\u76D8\u6B63\u5728\u683C\u5F0F\u5316\uFF0C\u4E0D\u80FD\u542F\u52A8\u64CD\u4F5C\u3002
HK_NET_ERROR_28=\u8BBE\u5907\u8D44\u6E90\u4E0D\u8DB3\u3002
HK_NET_ERROR_29=\u8BBE\u5907\u64CD\u4F5C\u5931\u8D25\u3002
HK_NET_ERROR_30=\u8BED\u97F3\u5BF9\u8BB2\u3001\u8BED\u97F3\u5E7F\u64AD\u64CD\u4F5C\u4E2D\u91C7\u96C6\u672C\u5730\u97F3\u9891\u6216\u6253\u5F00\u97F3\u9891\u8F93\u51FA\u5931\u8D25\u3002
HK_NET_ERROR_31=\u8BBE\u5907\u8BED\u97F3\u5BF9\u8BB2\u88AB\u5360\u7528\u3002
HK_NET_ERROR_32=\u65F6\u95F4\u8F93\u5165\u4E0D\u6B63\u786E\u3002
HK_NET_ERROR_33=\u56DE\u653E\u65F6\u8BBE\u5907\u6CA1\u6709\u6307\u5B9A\u7684\u6587\u4EF6\u3002
HK_NET_ERROR_34=\u521B\u5EFA\u6587\u4EF6\u51FA\u9519\u3002\u672C\u5730\u5F55\u50CF\u3001\u4FDD\u5B58\u56FE\u7247\u3001\u83B7\u53D6\u914D\u7F6E\u6587\u4EF6\u548C\u8FDC\u7A0B\u4E0B\u8F7D\u5F55\u50CF\u65F6\u521B\u5EFA\u6587\u4EF6\u5931\u8D25\u3002
HK_NET_ERROR_35=\u6253\u5F00\u6587\u4EF6\u51FA\u9519\u3002\u53EF\u80FD\u56E0\u4E3A\u6587\u4EF6\u4E0D\u5B58\u5728\u6216\u8005\u8DEF\u5F84\u9519\u8BEF\u3002
HK_NET_ERROR_36=\u4E0A\u6B21\u7684\u64CD\u4F5C\u8FD8\u6CA1\u6709\u5B8C\u6210\u3002
HK_NET_ERROR_37=\u83B7\u53D6\u5F53\u524D\u64AD\u653E\u7684\u65F6\u95F4\u51FA\u9519\u3002
HK_NET_ERROR_38=\u64AD\u653E\u51FA\u9519\u3002
HK_NET_ERROR_39=\u6587\u4EF6\u683C\u5F0F\u4E0D\u6B63\u786E\u3002
HK_NET_ERROR_40=\u8DEF\u5F84\u9519\u8BEF
HK_NET_ERROR_41=SDK\u8D44\u6E90\u5206\u914D\u9519\u8BEF\u3002
HK_NET_ERROR_42=\u58F0\u5361\u6A21\u5F0F\u9519\u8BEF\u3002\u5F53\u524D\u6253\u5F00\u58F0\u97F3\u64AD\u653E\u6A21\u5F0F\u4E0E\u5B9E\u9645\u8BBE\u7F6E\u7684\u6A21\u5F0F\u4E0D\u7B26\u51FA\u9519\u3002
HK_NET_ERROR_43=\u7F13\u51B2\u533A\u592A\u5C0F\u3002\u63A5\u6536\u8BBE\u5907\u6570\u636E\u7684\u7F13\u51B2\u533A\u6216\u5B58\u653E\u56FE\u7247\u7F13\u51B2\u533A\u4E0D\u8DB3\u3002
HK_NET_ERROR_44=\u521B\u5EFASOCKET\u51FA\u9519\u3002
HK_NET_ERROR_45=\u8BBE\u7F6ESOCKET\u51FA\u9519\u3002
HK_NET_ERROR_46=\u4E2A\u6570\u8FBE\u5230\u6700\u5927\u3002\u5206\u914D\u7684\u6CE8\u518C\u8FDE\u63A5\u6570\u3001\u9884\u89C8\u8FDE\u63A5\u6570\u8D85\u8FC7SDK\u652F\u6301\u7684\u6700\u5927\u6570\u3002
HK_NET_ERROR_47=\u7528\u6237\u4E0D\u5B58\u5728\u3002\u6CE8\u518C\u7684\u7528\u6237ID\u5DF2\u6CE8\u9500\u6216\u4E0D\u53EF\u7528\u3002
HK_NET_ERROR_48=\u5199FLASH\u51FA\u9519\u3002\u8BBE\u5907\u5347\u7EA7\u65F6\u5199FLASH\u5931\u8D25\u3002
HK_NET_ERROR_49=\u8BBE\u5907\u5347\u7EA7\u5931\u8D25\u3002\u7F51\u7EDC\u6216\u5347\u7EA7\u6587\u4EF6\u8BED\u8A00\u4E0D\u5339\u914D\u7B49\u539F\u56E0\u5347\u7EA7\u5931\u8D25\u3002
HK_NET_ERROR_50=\u89E3\u7801\u5361\u5DF2\u7ECF\u521D\u59CB\u5316\u8FC7\u3002
HK_NET_ERROR_51=\u8C03\u7528\u64AD\u653E\u5E93\u4E2D\u67D0\u4E2A\u51FD\u6570\u5931\u8D25\u3002
HK_NET_ERROR_52=\u767B\u5F55\u8BBE\u5907\u7684\u7528\u6237\u6570\u8FBE\u5230\u6700\u5927\u3002
HK_NET_ERROR_53=\u83B7\u5F97\u672C\u5730PC\u7684IP\u5730\u5740\u6216\u7269\u7406\u5730\u5740\u5931\u8D25\u3002
HK_NET_ERROR_54=\u8BBE\u5907\u8BE5\u901A\u9053\u6CA1\u6709\u542F\u52A8\u7F16\u7801\u3002
HK_NET_ERROR_55=IP\u5730\u5740\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_56=MAC\u5730\u5740\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_57=\u5347\u7EA7\u6587\u4EF6\u8BED\u8A00\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_58=\u64AD\u653E\u5668\u8DEF\u6570\u8FBE\u5230\u6700\u5927\u3002
HK_NET_ERROR_59=\u5907\u4EFD\u8BBE\u5907\u4E2D\u6CA1\u6709\u8DB3\u591F\u7A7A\u95F4\u8FDB\u884C\u5907\u4EFD\u3002
HK_NET_ERROR_60=\u6CA1\u6709\u627E\u5230\u6307\u5B9A\u7684\u5907\u4EFD\u8BBE\u5907\u3002
HK_NET_ERROR_61=\u56FE\u50CF\u7D20\u4F4D\u6570\u4E0D\u7B26\uFF0C\u965024\u8272\u3002
HK_NET_ERROR_62=\u56FE\u7247\u9AD8*\u5BBD\u8D85\u9650\uFF0C\u9650128*256\u3002
HK_NET_ERROR_63=\u56FE\u7247\u5927\u5C0F\u8D85\u9650\uFF0C\u9650100K\u3002
HK_NET_ERROR_64=\u8F7D\u5165\u5F53\u524D\u76EE\u5F55\u4E0B\u64AD\u653E\u5E93(PlayCtrl.dll\u3001SuperRender.dll\u3001AudioRender.dll)\u51FA\u9519\u3002
HK_NET_ERROR_65=\u627E\u4E0D\u5230Player Sdk\u4E2D\u67D0\u4E2A\u51FD\u6570\u5165\u53E3\u3002
HK_NET_ERROR_66=\u8F7D\u5165\u5F53\u524D\u76EE\u5F55\u4E0BDSsdk\u51FA\u9519\u3002
HK_NET_ERROR_67=\u627E\u4E0D\u5230DsSdk\u4E2D\u67D0\u4E2A\u51FD\u6570\u5165\u53E3\u3002
HK_NET_ERROR_68=\u8C03\u7528\u786C\u89E3\u7801\u5E93DsSdk\u4E2D\u67D0\u4E2A\u51FD\u6570\u5931\u8D25\u3002
HK_NET_ERROR_69=\u58F0\u5361\u88AB\u72EC\u5360\u3002
HK_NET_ERROR_70=\u52A0\u5165\u591A\u64AD\u7EC4\u5931\u8D25\u3002
HK_NET_ERROR_71=\u5EFA\u7ACB\u65E5\u5FD7\u6587\u4EF6\u76EE\u5F55\u5931\u8D25\u3002
HK_NET_ERROR_72=\u7ED1\u5B9A\u5957\u63A5\u5B57\u5931\u8D25\u3002
HK_NET_ERROR_73=socket\u8FDE\u63A5\u4E2D\u65AD\uFF0C\u6B64\u9519\u8BEF\u901A\u5E38\u662F\u7531\u4E8E\u8FDE\u63A5\u4E2D\u65AD\u6216\u76EE\u7684\u5730\u4E0D\u53EF\u8FBE\u3002
HK_NET_ERROR_74=\u6CE8\u9500\u65F6\u7528\u6237ID\u6B63\u5728\u8FDB\u884C\u67D0\u64CD\u4F5C\u3002
HK_NET_ERROR_75=\u76D1\u542C\u5931\u8D25\u3002
HK_NET_ERROR_76=\u7A0B\u5E8F\u5F02\u5E38\u3002
HK_NET_ERROR_77=\u5199\u6587\u4EF6\u5931\u8D25\u3002\u672C\u5730\u5F55\u50CF\u3001\u8FDC\u7A0B\u4E0B\u8F7D\u5F55\u50CF\u3001\u4E0B\u8F7D\u56FE\u7247\u7B49\u64CD\u4F5C\u65F6\u5199\u6587\u4EF6\u5931\u8D25\u3002
HK_NET_ERROR_78=\u7981\u6B62\u683C\u5F0F\u5316\u53EA\u8BFB\u786C\u76D8\u3002
HK_NET_ERROR_79=\u8FDC\u7A0B\u7528\u6237\u914D\u7F6E\u7ED3\u6784\u4E2D\u5B58\u5728\u76F8\u540C\u7684\u7528\u6237\u540D\u3002
HK_NET_ERROR_80=\u5BFC\u5165\u53C2\u6570\u65F6\u8BBE\u5907\u578B\u53F7\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_81=\u5BFC\u5165\u53C2\u6570\u65F6\u8BED\u8A00\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_82=\u5BFC\u5165\u53C2\u6570\u65F6\u8F6F\u4EF6\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_83=\u9884\u89C8\u65F6\u5916\u63A5IP\u901A\u9053\u4E0D\u5728\u7EBF\u3002
HK_NET_ERROR_84=\u52A0\u8F7D\u6807\u51C6\u534F\u8BAE\u901A\u8BAF\u5E93(StreamTransClient.dll)\u5931\u8D25\u3002
HK_NET_ERROR_85=\u52A0\u8F7D\u8F6C\u5C01\u88C5\u5E93(SystemTransform.dll)\u5931\u8D25\u3002
HK_NET_ERROR_86=\u8D85\u51FA\u6700\u5927\u7684IP\u63A5\u5165\u901A\u9053\u6570\u3002
HK_NET_ERROR_87=\u6DFB\u52A0\u5F55\u50CF\u6807\u7B7E\u6216\u8005\u5176\u4ED6\u64CD\u4F5C\u8D85\u51FA\u6700\u591A\u652F\u6301\u7684\u4E2A\u6570\u3002
HK_NET_ERROR_88=\u56FE\u50CF\u589E\u5F3A\u4EEA\uFF0C\u53C2\u6570\u6A21\u5F0F\u9519\u8BEF\uFF08\u7528\u4E8E\u786C\u4EF6\u8BBE\u7F6E\u65F6\uFF0C\u5BA2\u6237\u7AEF\u8FDB\u884C\u8F6F\u4EF6\u8BBE\u7F6E\u65F6\u9519\u8BEF\u503C\uFF09\u3002
HK_NET_ERROR_89=\u7801\u5206\u5668\u4E0D\u5728\u7EBF\u3002
HK_NET_ERROR_90=\u8BBE\u5907\u6B63\u5728\u5907\u4EFD\u3002
HK_NET_ERROR_91=\u901A\u9053\u4E0D\u652F\u6301\u8BE5\u64CD\u4F5C\u3002
HK_NET_ERROR_92=\u9AD8\u5EA6\u7EBF\u4F4D\u7F6E\u592A\u96C6\u4E2D\u6216\u957F\u5EA6\u7EBF\u4E0D\u591F\u503E\u659C\u3002
HK_NET_ERROR_93=\u53D6\u6D88\u6807\u5B9A\u51B2\u7A81\uFF0C\u5982\u679C\u8BBE\u7F6E\u4E86\u89C4\u5219\u53CA\u5168\u5C40\u7684\u5B9E\u9645\u5927\u5C0F\u5C3A\u5BF8\u8FC7\u6EE4\u3002
HK_NET_ERROR_94=\u6807\u5B9A\u70B9\u8D85\u51FA\u8303\u56F4\u3002
HK_NET_ERROR_95=\u5C3A\u5BF8\u8FC7\u6EE4\u5668\u4E0D\u7B26\u5408\u8981\u6C42\u3002
HK_NET_ERROR_96=\u8BBE\u5907\u6CA1\u6709\u6CE8\u518C\u5230ddns\u4E0A\u3002
HK_NET_ERROR_97=DDNS \u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF\u3002
HK_NET_ERROR_98=\u6B64\u529F\u80FD\u4E0D\u652F\u6301\u8BE5\u64CD\u4F5C\u7CFB\u7EDF\u3002
HK_NET_ERROR_99=\u89E3\u7801\u901A\u9053\u7ED1\u5B9A\u663E\u793A\u8F93\u51FA\u6B21\u6570\u53D7\u9650\u3002
HK_NET_ERROR_100=\u52A0\u8F7D\u5F53\u524D\u76EE\u5F55\u4E0B\u7684\u8BED\u97F3\u5BF9\u8BB2\u5E93\u5931\u8D25\u3002
HK_NET_ERROR_101=\u6CA1\u6709\u6B63\u786E\u7684\u5347\u7EA7\u5305\u3002
HK_NET_ERROR_102=\u7528\u6237\u8FD8\u6CA1\u767B\u5F55\u6210\u529F\u3002
HK_NET_ERROR_103=\u6B63\u5728\u4F7F\u7528\u65E5\u5FD7\u5F00\u5173\u6587\u4EF6\u3002
HK_NET_ERROR_104=\u7AEF\u53E3\u6C60\u4E2D\u7528\u4E8E\u7ED1\u5B9A\u7684\u7AEF\u53E3\u5DF2\u8017\u5C3D\u3002
HK_NET_ERROR_105=\u7801\u6D41\u5C01\u88C5\u683C\u5F0F\u9519\u8BEF\u3002
HK_NET_ERROR_106=IP\u63A5\u5165\u914D\u7F6E\u65F6IPID\u6709\u8BEF\u3002
HK_NET_ERROR_107=\u9884\u89C8\u7EC4\u4EF6\u52A0\u8F7D\u5931\u8D25\u3002
HK_NET_ERROR_108=\u8BED\u97F3\u7EC4\u4EF6\u52A0\u8F7D\u5931\u8D25\u3002
HK_NET_ERROR_109=\u62A5\u8B66\u7EC4\u4EF6\u52A0\u8F7D\u5931\u8D25\u3002
HK_NET_ERROR_110=\u56DE\u653E\u7EC4\u4EF6\u52A0\u8F7D\u5931\u8D25\u3002
HK_NET_ERROR_111=\u663E\u793A\u7EC4\u4EF6\u52A0\u8F7D\u5931\u8D25\u3002
HK_NET_ERROR_112=\u884C\u4E1A\u5E94\u7528\u7EC4\u4EF6\u52A0\u8F7D\u5931\u8D25\u3002
HK_NET_ERROR_113=\u901A\u7528\u914D\u7F6E\u7BA1\u7406\u7EC4\u4EF6\u52A0\u8F7D\u5931\u8D25\u3002
HK_NET_ERROR_114=\u8BBE\u5907\u914D\u7F6E\u6838\u5FC3\u7EC4\u4EF6\u52A0\u8F7D\u5931\u8D25\u3002
HK_NET_ERROR_121=\u5355\u72EC\u52A0\u8F7D\u7EC4\u4EF6\u65F6\uFF0C\u7EC4\u4EF6\u4E0Ecore\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_122=\u9884\u89C8\u7EC4\u4EF6\u4E0Ecore\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_123=\u8BED\u97F3\u7EC4\u4EF6\u4E0Ecore\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_124=\u62A5\u8B66\u7EC4\u4EF6\u4E0Ecore\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_125=\u56DE\u653E\u7EC4\u4EF6\u4E0Ecore\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_126=\u663E\u793A\u7EC4\u4EF6\u4E0Ecore\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_127=\u884C\u4E1A\u5E94\u7528\u7EC4\u4EF6\u4E0Ecore\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_128=\u901A\u7528\u914D\u7F6E\u7BA1\u7406\u7EC4\u4EF6\u4E0Ecore\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_136=\u9884\u89C8\u7EC4\u4EF6\u4E0EHCNetSDK\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_137=\u8BED\u97F3\u7EC4\u4EF6\u4E0EHCNetSDK\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_138=\u62A5\u8B66\u7EC4\u4EF6\u4E0EHCNetSDK\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_139=\u56DE\u653E\u7EC4\u4EF6\u4E0EHCNetSDK\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_140=\u663E\u793A\u7EC4\u4EF6\u4E0EHCNetSDK\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_141=\u884C\u4E1A\u5E94\u7528\u7EC4\u4EF6\u4E0EHCNetSDK\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_142=\u901A\u7528\u914D\u7F6E\u7BA1\u7406\u7EC4\u4EF6\u4E0EHCNetSDK\u7248\u672C\u4E0D\u5339\u914D\u3002
HK_NET_ERROR_150=\u522B\u540D\u91CD\u590D\uFF08HiDDNS\u7684\u914D\u7F6E\uFF09\u3002
HK_NET_ERROR_152=\u7528\u6237\u540D\u4E0D\u5B58\u5728\uFF08V5.1.7~V5.3.1\u7248\u672C\u7684IPC\u3001IPD\u7684\u9519\u8BEF\u7801\uFF09\u3002
HK_NET_ERROR_153=\u7528\u6237\u540D\u88AB\u9501\u5B9A\u3002
HK_NET_ERROR_154=\u65E0\u6548\u7528\u6237ID\u3002
HK_NET_ERROR_155=\u767B\u5F55\u7248\u672C\u4F4E\u3002
HK_NET_ERROR_156=\u52A0\u8F7Dlibeay32.dll\u5E93\u5931\u8D25\u3002
HK_NET_ERROR_157=\u52A0\u8F7Dssleay32.dll\u5E93\u5931\u8D25\u3002
HK_NET_ERROR_158=\u52A0\u8F7Dlibiconv.dll\u5E93\u5931\u8D25\u3002
HK_NET_ERROR_165=\u8FDE\u63A5\u6D4B\u8BD5\u670D\u52A1\u5668\u5931\u8D25\u3002
HK_NET_ERROR_166=NAS\u670D\u52A1\u5668\u6302\u8F7D\u76EE\u5F55\u5931\u8D25\uFF0C\u76EE\u5F55\u65E0\u6548\u6216\u8005\u7528\u6237\u540D\u5BC6\u7801\u9519\u8BEF\u3002
HK_NET_ERROR_167=NAS\u670D\u52A1\u5668\u6302\u8F7D\u76EE\u5F55\u5931\u8D25\uFF0C\u6CA1\u6709\u6743\u9650\u3002
HK_NET_ERROR_168=\u670D\u52A1\u5668\u4F7F\u7528\u57DF\u540D\uFF0C\u4F46\u662F\u6CA1\u6709\u914D\u7F6EDNS\uFF0C\u53EF\u80FD\u9020\u6210\u57DF\u540D\u65E0\u6548\u3002
HK_NET_ERROR_169=\u6CA1\u6709\u914D\u7F6E\u7F51\u5173\uFF0C\u53EF\u80FD\u9020\u6210\u53D1\u9001\u90AE\u4EF6\u5931\u8D25\u3002
HK_NET_ERROR_170=\u7528\u6237\u540D\u5BC6\u7801\u4E0D\u6B63\u786E\uFF0C\u6D4B\u8BD5\u670D\u52A1\u5668\u7684\u7528\u6237\u540D\u6216\u5BC6\u7801\u9519\u8BEF\u3002
HK_NET_ERROR_171=\u8BBE\u5907\u548Csmtp\u670D\u52A1\u5668\u4EA4\u4E92\u5F02\u5E38\u3002
HK_NET_ERROR_172=FTP\u670D\u52A1\u5668\u521B\u5EFA\u76EE\u5F55\u5931\u8D25\u3002
HK_NET_ERROR_173=FTP\u670D\u52A1\u5668\u6CA1\u6709\u5199\u5165\u6743\u9650\u3002
HK_NET_ERROR_174=IP\u51B2\u7A81\u3002
HK_NET_ERROR_175=\u5B58\u50A8\u6C60\u7A7A\u95F4\u5DF2\u6EE1\u3002
HK_NET_ERROR_176=\u4E91\u670D\u52A1\u5668\u5B58\u50A8\u6C60\u65E0\u6548\uFF0C\u6CA1\u6709\u914D\u7F6E\u5B58\u50A8\u6C60\u6216\u8005\u5B58\u50A8\u6C60ID\u9519\u8BEF\u3002
HK_NET_ERROR_177=\u751F\u6548\u9700\u8981\u91CD\u542F\u3002
HK_NET_ERROR_178=\u65AD\u7F51\u7EED\u4F20\u5E03\u9632\u8FDE\u63A5\u5DF2\u7ECF\u5B58\u5728\uFF08\u79C1\u6709SDK\u534F\u8BAE\u5E03\u9632\u8FDE\u63A5\u5DF2\u7ECF\u5EFA\u7ACB\u7684\u60C5\u51B5\u4E0B\uFF0C\u91CD\u590D\u5E03\u9632\u4E14\u9009\u62E9\u65AD\u7F51\u7EED\u4F20\u529F\u80FD\u65F6\u8FD4\u56DE\u8BE5\u9519\u8BEF\uFF09\u3002
HK_NET_ERROR_179=\u65AD\u7F51\u7EED\u4F20\u4E0A\u4F20\u8FDE\u63A5\u5DF2\u7ECF\u5B58\u5728\uFF08EHOME\u534F\u8BAE\u548C\u79C1\u6709SDK\u534F\u8BAE\u4E0D\u80FD\u540C\u65F6\u652F\u6301\u65AD\u7F51\u7EED\u4F20\uFF0C\u5176\u4E2D\u4E00\u79CD\u534F\u8BAE\u5DF2\u7ECF\u5EFA\u8BAE\u8FDE\u63A5\uFF0C\u53E6\u5916\u4E00\u4E2A\u8FDE\u63A5\u5EFA\u7ACB\u65F6\u8FD4\u56DE\u8BE5\u9519\u8BEF\uFF09\u3002
HK_NET_ERROR_180=\u5BFC\u5165\u6587\u4EF6\u683C\u5F0F\u4E0D\u6B63\u786E\u3002
HK_NET_ERROR_181=\u5BFC\u5165\u6587\u4EF6\u5185\u5BB9\u4E0D\u6B63\u786E\u3002
HK_NET_ERROR_182=HRUDP\u8FDE\u63A5\u6570\u8D85\u8FC7\u8BBE\u5907\u9650\u5236\u3002
HK_SADP_ERROR_0=\u6CA1\u6709\u9519\u8BEF
HK_SADP_ERROR_2001=\u8D44\u6E90\u5206\u914D\u9519\u8BEF
HK_SADP_ERROR_2002=SADP \u672A\u542F\u52A8
HK_SADP_ERROR_2003=\u65E0\u7F51\u5361
HK_SADP_ERROR_2004=\u83B7\u53D6\u7F51\u5361\u4FE1\u606F\u5931\u8D25
HK_SADP_ERROR_2005=\u53C2\u6570\u9519\u8BEF
HK_SADP_ERROR_2006=\u6253\u5F00\u7F51\u5361\u5931\u8D25
HK_SADP_ERROR_2007=\u53D1\u9001\u6570\u636E\u5931\u8D25
HK_SADP_ERROR_2008=\u7CFB\u7EDF\u63A5\u53E3\u8C03\u7528\u5931\u8D25
HK_SADP_ERROR_2009=\u8BBE\u5907\u62D2\u7EDD\u5904\u7406
HK_SADP_ERROR_2010=\u5B89\u88C5 NPF \u670D\u52A1\u5931\u8D25
HK_SADP_ERROR_2011=\u8BBE\u5907\u54CD\u5E94\u8D85\u65F6
HK_SADP_ERROR_2012=\u521B\u5EFA socket \u5931\u8D25
HK_SADP_ERROR_2013=\u7ED1\u5B9A socket \u5931\u8D25
HK_SADP_ERROR_2014=\u52A0\u5165\u591A\u64AD\u7EC4\u5931\u8D25
HK_SADP_ERROR_2015=\u53D1\u9001\u51FA\u9519
HK_SADP_ERROR_2016=\u63A5\u6536\u51FA\u9519
HK_SADP_ERROR_2017=\u591A\u64AD XML \u89E3\u6790\u51FA\u9519
HK_SADP_ERROR_2018=\u8BBE\u5907\u9501\u5B9A
HK_SADP_ERROR_2019=\u8BBE\u5907\u672A\u6FC0\u6D3B
HK_SADP_ERROR_2020=\u98CE\u9669\u9AD8\u7684\u5BC6\u7801
HK_SADP_ERROR_2021=\u8BBE\u5907\u5DF2\u6FC0\u6D3B
HK_SADP_ERROR_8888=\u672A\u77E5\u9519\u8BEF
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>多路摄像头实时播放</title>
<script src="https://cdn.jsdelivr.net/npm/zlmrtc4player"></script>
<style>
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 10px;
}
video {
width: 100%;
height: auto;
background: black;
}
</style>
</head>
<body>
<h2>摄像头分屏实时播放</h2>
<div class="grid" id="videoGrid"></div>
<script>
const videoGrid = document.getElementById("videoGrid");
function playStream(videoEl, app, stream, retryCount = 0) {
const maxRetries = 5;
const retryDelay = 3000;
const player = new ZLMRTCClient.Endpoint({
video: videoEl,
protocol: location.protocol === "https:" ? "wss" : "ws",
host: location.hostname,
port: 80,
app,
stream
});
player.play().catch(() => {
if (retryCount < maxRetries) {
console.warn(`播放失败,重试第 ${retryCount + 1} 次:${stream}`);
setTimeout(() => playStream(videoEl, app, stream, retryCount + 1), retryDelay);
} else {
console.error(`播放失败:${stream},已达最大重试次数`);
}
});
}
cameras = [
{
name: '摄像头1',
app: 'live',
stream: 'cam1'
}
];
cameras => {
cameras.forEach(cam => {
const container = document.createElement('div');
const label = document.createElement('p');
label.textContent = cam.name;
const video = document.createElement('video');
video.autoplay = true;
video.muted = true;
video.playsInline = true;
video.controls = true;
container.appendChild(label);
container.appendChild(video);
videoGrid.appendChild(container);
});
}
</script>
</body>
</html>
<html>
<meta charset="utf-8">
<head>
<title>ZLM RTC demo</title>
<script src="./ZLMRTCClient.js"></script>
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script>
// VConsole will be exported to `window.VConsole` by default.
var vConsole = new window.VConsole();
</script>
<style>
video {
width: 40vw;
max-height: 50vh;
height: 22.5vw; /* 默认和宽:高为 16:9 */
object-fit: contain;
background-color: grey;
}
</style>
</head>
<body>
<div style="text-align: center;">
<div>
<video id='video' controls autoplay>
Your browser is too old which doesn't support HTML5 video.
</video>
<video id='selfVideo' controls autoplay>
Your browser is too old which doesn't support HTML5 video.
</video>
</div>
<div style="float: left; width:30%;">
<span>已存在的流列表,点击自动播放:</span>
<ol id="olstreamlist">
<li>初始演示</li>
<li>每秒自动刷新</li>
</ol>
</div>
<div style="float: right; width: 70%">
<p>
<label for="streamUrl">url:</label>
<input type="text" style="co; width:70%" id='streamUrl' value="https://192.168.0.100/index/api/webrtc?app=yuerle&stream=BA8609485&type=play">
</p>
<p>
<label for="simulcast">simulcast:</label>
<input type="checkbox" id='simulcast'>
</p>
<p>
<label for="useCamera">useCamera:</label>
<input type="checkbox" id='useCamera' checked="checked">
</p>
<p>
<label for="audioEnable">audioEnable:</label>
<input type="checkbox" id='audioEnable' checked="checked">
</p>
<p>
<label for="videoEnable">videoEnable:</label>
<input type="checkbox" id='videoEnable' checked="checked">
</p>
<p>
<label for="method">method(play or push or echo):</label>
<input type="radio" name="method" value="echo" >echo
<input type="radio" name="method" value="push" >push
<input type="radio" name="method" value="play" checked = true>play
</p>
<p>
<label for="resolution">resolution:</label>
<select id="resolution">
</select>
</p>
<p>
<label for="datachannel">datachannel:</label>
<input id='datachannel' name="datachannel" type="checkbox" value="0">
</p>
<button onclick="start()">开始(start)</button>
<button onclick="stop()">停止(stop)</button>
<p>
<label for="msgsend">msgsend:</label>
<input type="text" id='msgsend' value="hello word !">
</p>
<p>
<label for="msgrecv">msgrecv:</label>
<input type="text" id='msgrecv' disabled>
</p>
<button onclick="send()">发送(send by datachannel)</button>
<button onclick="close()">关闭(close datachannel)</button>
<p>
<label for="videoDevice">videodevice:</label>
<select id="videoDevice">
</select>
</p>
<p>
<label for="audioDevice">audiodevice:</label>
<select id="audioDevice">
</select>
</p>
<p>
<label for="switchDevice">switchDevice:</label>
<input type="checkbox" id='switchDevice' checked="checked">
</p>
<button onclick="switchVideo()">切换视频(switch video)</button>
<button onclick="switchAudio()">切换音频(switch audio)</button>
</div>
</div>
<script>
var player = null;
var recvOnly = true;
var resArr = [];
var ishttps = 'https:' === document.location.protocol;
var isLocal = "file:" === document.location.protocol;
const searchParams = new URL(document.location.href).searchParams;
let type = searchParams.get('type');
if (!['echo','push','play'].includes(type)) {
type = 'play';
}
recvOnly = type === 'play';
const apiPath = `/index/api/webrtc?app=${searchParams.get('app') ?? 'live'}&stream=${searchParams.get('stream') ?? 'test'}&type=${type}`;
if(!ishttps && !isLocal){
alert('本demo需要在https的网站访问, 如果你要推流的话(this demo must access in site of https if you want to push stream)');
}
const apiHost = isLocal ? "http://127.0.0.1" : `${document.location.protocol}//${window.location.host}`;
var url = apiHost + apiPath;
document.getElementById('streamUrl').value = url;
document.getElementsByName("method").forEach((el,idx) => {
el.checked = el.value === type;
el.onclick = function(e) {
const url = new URL(document.getElementById('streamUrl').value);
url.searchParams.set("type",el.value);
document.getElementById('streamUrl').value = url.toString();
recvOnly = 'play' === el.value;
};
});
ZLMRTCClient.GetAllScanResolution().forEach((r,i) => {
opt = document.createElement('option');
opt.text = `${r.label}(${r.width}x${r.height})`;
opt.value = r;
if (1080*720 <= r.width * r.height && r.width * r.height <= 1280*720) {
opt.selected = true;
}
document.getElementById("resolution").add(opt,null);
});
ZLMRTCClient.GetAllMediaDevice().then(devices=>{
devices.forEach(device=>{
opt = document.createElement('option');
opt.text = device.label + ":"+device.deviceId
opt.value = JSON.stringify(device)
if(device.kind == 'videoinput'){
document.getElementById("videoDevice").add(opt,null)
}else if(device.kind == 'audioinput'){
document.getElementById("audioDevice").add(opt,null)
}else if(device.kind == 'audiooutput'){
// useless
//console.error('not support device')
}
})
}).catch(e=>{
console.error(e);
})
function start_play(){
let elr = document.getElementById("resolution");
let res = elr.options[elr.selectedIndex].text.match(/\d+/g);
let h = parseInt(res.pop());
let w = parseInt(res.pop());
const url = new URL(document.getElementById('streamUrl').value);
const newUrl = new URL(window.location.href);
let count = 0;
if (url.searchParams.has('app')) {
newUrl.searchParams.set('app', url.searchParams.get('app'));
count++;
}
if (url.searchParams.has('stream')) {
newUrl.searchParams.set('stream', url.searchParams.get('stream'));
count++;
}
if (url.searchParams.has('type')) {
newUrl.searchParams.set('type', url.searchParams.get('type'));
count++;
}
if (count > 0) {
window.history.pushState(null, null, newUrl);
}
let elv = document.getElementById("videoDevice");
let ela = document.getElementById("audioDevice");
let vdevid = ''
let adevid = ''
if (!recvOnly) {
if (elv.selectedIndex !== -1) {
vdevid = JSON.parse(elv.options[elv.selectedIndex].value).deviceId
}
if (ela.selectedIndex !== -1) {
adevid = JSON.parse(ela.options[ela.selectedIndex].value).deviceId
}
}
player = new ZLMRTCClient.Endpoint(
{
element: document.getElementById('video'),// video 标签
debug: true,// 是否打印日志
zlmsdpUrl:document.getElementById('streamUrl').value,//流地址
simulcast:document.getElementById('simulcast').checked,
useCamera:document.getElementById('useCamera').checked,
audioEnable:document.getElementById('audioEnable').checked,
videoEnable:document.getElementById('videoEnable').checked,
recvOnly:recvOnly,
resolution:{w,h},
usedatachannel:document.getElementById('datachannel').checked,
videoId:vdevid, // 不填选择默认的
audioId:adevid, // 不填选择默认的
}
);
player.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR,function(e)
{
// ICE 协商出错
console.log('ICE 协商出错');
});
player.on(ZLMRTCClient.Events.WEBRTC_ON_REMOTE_STREAMS,function(s)
{
//获取到了远端流,可以播放,如果element 为null 或者不传,可以在这里播放(如下注释代码)
/*
document.getElementById('video').srcObject=s;
*/
console.log('播放成功',s);
});
player.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED,function(e)
{
// offer anwser 交换失败
console.log('offer anwser 交换失败',e);
stop();
});
player.on(ZLMRTCClient.Events.WEBRTC_ON_LOCAL_STREAM,function(s)
{
// 获取到了本地流
document.getElementById('selfVideo').srcObject=s;
document.getElementById('selfVideo').muted = true;
//console.log('offer anwser 交换失败',e)
});
player.on(ZLMRTCClient.Events.CAPTURE_STREAM_FAILED,function(s)
{
// 获取本地流失败
console.log('获取本地流失败');
});
player.on(ZLMRTCClient.Events.WEBRTC_ON_CONNECTION_STATE_CHANGE,function(state)
{
// RTC 状态变化 ,详情参考 https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/connectionState
console.log('当前状态==>',state);
});
player.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_OPEN,function(event)
{
console.log('rtc datachannel 打开 :',event);
});
player.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_MSG,function(event)
{
console.log('rtc datachannel 消息 :',event.data);
document.getElementById('msgrecv').value = event.data;
});
player.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_ERR,function(event)
{
console.log('rtc datachannel 错误 :',event);
});
player.on(ZLMRTCClient.Events.WEBRTC_ON_DATA_CHANNEL_CLOSE,function(event)
{
console.log('rtc datachannel 关闭 :',event);
});
}
function start()
{
stop();
let elr = document.getElementById("resolution");
let res = elr.options[elr.selectedIndex].text.match(/\d+/g);
let h = parseInt(res.pop());
let w = parseInt(res.pop());
if(document.getElementById('useCamera').checked && !recvOnly)
{
ZLMRTCClient.isSupportResolution(w,h).then(e=>{
start_play();
}).catch(e=>{
alert("not support resolution");
});
}else{
start_play();
}
}
function stop()
{
if(player)
{
player.close();
player = null;
var remote = document.getElementById('video');
if(remote)
{
remote.srcObject = null;
remote.load();
}
var local = document.getElementById('selfVideo');
local.srcObject = null;
local.load();
}
}
function send(){
if(player){
//send msg refernece https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/send
player.sendMsg(document.getElementById('msgsend').value);
}
}
function close(){
if(player){
player.closeDataChannel();
}
}
function on_click_to_play(app, stream) {
console.log(`on_click_to_play: ${app}/${stream}`);
var url = `${document.location.protocol}//${window.location.host}/index/api/webrtc?app=${app}&stream=${stream}&type=play`;
document.getElementById('streamUrl').value = url;
start();
}
function clearStreamList() {
let content = document.getElementById("olstreamlist");
while (content.hasChildNodes()) {
content.removeChild(content.firstChild);
}
}
function fillStreamList(json) {
clearStreamList();
if (json.code != 0 || !json.data) {
return;
}
let ss = {};
for (let o of json.data) {
if (ss[o.app]) {
ss[o.app].add(o.stream);
} else {
let set = new Set();
set.add(o.stream);
ss[o.app] = set;
}
}
for (let o in ss) {
let app = o;
for (let s of ss[o]) {
if (s) {
//console.log(app, s);
let content = document.getElementById("olstreamlist");
let child = `<li app="${app}" stream="${s}" onmouseover="this.style.color='blue';" onclick="on_click_to_play('${app}', '${s}')">${app}/${s}</li>`;
content.insertAdjacentHTML("beforeend", child);
}
}
}
}
async function getData(url) {
const response = await fetch(url, {
method: 'GET'
});
const data = await response.json();
//console.log(data);
return data;
}
function get_media_list() {
let url = document.location.protocol+"//"+window.location.host+"/index/api/getMediaList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc";
let json = getData(url);
json.then((json)=> fillStreamList(json));
}
setInterval(() => {
// get_media_list();
}, 5000);
function switchVideo(){
if(player){
// first arg bool false mean switch to screen video , second ignore
// true mean switch to video , second is camera deviceid
let elv = document.getElementById("videoDevice");
let vdevid = JSON.parse(elv.options[elv.selectedIndex].value).deviceId
player.switchVideo(document.getElementById('switchDevice').checked,vdevid).then(()=>{
// switch video successful
}).catch(e=>{
// switch video failed
console.error(e);
})
}
}
function switchAudio(){
if(player){
// first arg bool false mean switch to screen audio , second ignore
// true mean switch to mic , second is mic deviceid
let ela = document.getElementById("audioDevice");
let adevid = JSON.parse(ela.options[ela.selectedIndex].value).deviceId
player.switcAudio(document.getElementById('switchDevice').checked,adevid).then(()=>{
// switch audio successful
}).catch(e=>{
// switch audio failed
console.error(e);
})
}
}
</script>
</body>
<script>
</script>
</html>
... ...
感谢[big panda](<2381267071@qq.com>) 开发并贡献此webrtc js测试客户端,
其开源项目地址为:https://gitee.com/xiongguangjie/zlmrtcclient.js
\ No newline at end of file
... ...
mqtt.broker=tcp://iot.yu2le.com:1883
mqtt.username=lh_hk_encoder
mqtt.password=Luhui586
mqtt.clientId=9ca6fa549193430e9904553d0c0e3a62
mqtt.subTopic=PUT/+,READ/+
yuerle.api.url=https://ly.api.yu2le.com/bigScreen/getYsLocalIp
webrtc.host=192.168.0.100
webrtc.app=yuerle
webrtc.secret=keXTvTDSHAxFDpBA0MDAHhxWeVXLQmUq
camera.serial=BA8609485
sys.task.interval=60
\ No newline at end of file
... ...
... ... @@ -2,6 +2,7 @@ package com.zhonglai.luhui.device.protocol.wp6.analysis.topic;
import com.google.gson.JsonObject;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.device.analysis.comm.dto.ApiClientRePlyDto;
import com.zhonglai.luhui.device.analysis.dto.MessageCode;
import com.zhonglai.luhui.device.protocol.factory.dto.AnalysisResult;
... ... @@ -14,12 +15,12 @@ public class PutReq {
public AnalysisResult analysisPayload(String payload)
{
JsonObject jsonObject = GsonConstructor.get().fromJson(payload, JsonObject.class);
return new AnalysisResult(false, true, jsonObject, message -> {
if(jsonObject.has("code") && "1".equals(jsonObject.get("code").getAsString()))
{
message.setCode(MessageCode.DEFAULT_SUCCESS_CODE);
message.setMessage("操作成功");
}
});
ApiClientRePlyDto noticeMessage = new ApiClientRePlyDto();
if(jsonObject.has("code") && "1".equals(jsonObject.get("code").getAsString()))
{
noticeMessage.setCode(MessageCode.DEFAULT_SUCCESS_CODE.code);
noticeMessage.setMessage("操作成功");
}
return new AnalysisResult(false, true, jsonObject, noticeMessage);
}
}
... ...
... ... @@ -2,6 +2,7 @@ package com.zhonglai.luhui.device.protocol.wp6.analysis.topic;
import com.google.gson.JsonObject;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.device.analysis.comm.dto.ApiClientRePlyDto;
import com.zhonglai.luhui.device.analysis.dto.MessageCode;
import com.zhonglai.luhui.device.protocol.factory.dto.AnalysisResult;
... ... @@ -21,16 +22,16 @@ public class ReadReq {
{
rJsonObject = jsonObject.getAsJsonObject("data");
}
return new AnalysisResult(false, true, rJsonObject, message -> {
if(jsonObject.has("code") && "1".equals(jsonObject.get("code").getAsString()))
ApiClientRePlyDto noticeMessage = new ApiClientRePlyDto();
if(jsonObject.has("code") && "1".equals(jsonObject.get("code").getAsString()))
{
if(jsonObject.has("data") && null != jsonObject.get("data") && jsonObject.get("data").isJsonObject())
{
if(jsonObject.has("data") && null != jsonObject.get("data") && jsonObject.get("data").isJsonObject())
{
message.setData(GsonConstructor.get().fromJson(jsonObject.getAsJsonObject("data").toString(), HashMap.class));
}
message.setCode(MessageCode.DEFAULT_SUCCESS_CODE);
message.setMessage("操作成功");
noticeMessage.setData(GsonConstructor.get().fromJson(jsonObject.getAsJsonObject("data").toString(), HashMap.class));
}
});
noticeMessage.setCode(MessageCode.DEFAULT_SUCCESS_CODE.code);
noticeMessage.setMessage("操作成功");
}
return new AnalysisResult(false, true, rJsonObject, noticeMessage);
}
}
... ...
... ... @@ -7,21 +7,27 @@ import com.zhonglai.luhui.device.analysis.dto.Message;
import com.zhonglai.luhui.device.analysis.dto.MessageCode;
import com.zhonglai.luhui.device.protocol.factory.dto.AnalysisResult;
import java.util.HashMap;
public class PutReq {
public AnalysisResult analysisPayload(byte[] payload)
{
return analysisPayload(new String(payload));
}
public AnalysisResult analysisPayload(String payload)
public AnalysisResult analysisPayload(String payload)
{
JsonObject jsonObject = GsonConstructor.get().fromJson(payload, JsonObject.class);
return new AnalysisResult(false, true, jsonObject, message -> {
if(jsonObject.has("code") && "1".equals(jsonObject.get("code").getAsString()))
ApiClientRePlyDto message = new ApiClientRePlyDto();
if(jsonObject.has("code") && "1".equals(jsonObject.get("code").getAsString()))
{
if (jsonObject.has("data"))
{
message.setCode(MessageCode.DEFAULT_SUCCESS_CODE);
message.setMessage("操作成功");
message.setData(GsonConstructor.get().fromJson(jsonObject.getAsJsonObject("data"), HashMap.class));
}
});
message.setCode(MessageCode.DEFAULT_SUCCESS_CODE.code);
message.setMessage("操作成功");
}
return new AnalysisResult(false, true, jsonObject, message);
}
}
... ...
... ... @@ -54,16 +54,13 @@ public class PLC004ProtocolParserFactoryImpl implements ProtocolParserFactory {
}
}
JsonObject jsonObject = GsonConstructor.get().fromJson(new String(payload),JsonObject.class);
return new AnalysisResult(false, true, data, new ApiClientRePlyDto() {
@Override
public void setReplyMessage(Message message) {
if(jsonObject.has("result") && "1".equals(jsonObject.get("result").getAsString()))
{
message.setCode(MessageCode.DEFAULT_SUCCESS_CODE);
message.setMessage("操作成功");
}
}
});
ApiClientRePlyDto apiClientRePlyDto = new ApiClientRePlyDto();
if(jsonObject.has("result") && "1".equals(jsonObject.get("result").getAsString()))
{
apiClientRePlyDto.setCode(MessageCode.DEFAULT_SUCCESS_CODE.code);
apiClientRePlyDto.setMessage("操作成功");
}
return new AnalysisResult(false, true, data, apiClientRePlyDto);
default:
return new AnalysisResult(false,false,null);
}
... ...
... ... @@ -30,12 +30,9 @@ public class CkaDtSndR {
Map<String,Object> wmap = new HashMap<>();
wmap.put("1",map);
return new AnalysisResult(false, true, jsonObject, new ApiClientRePlyDto() {
@Override
public void setReplyMessage(Message message) {
message.setCode(MessageCode.DEFAULT_SUCCESS_CODE);
message.setData(wmap);
}
});
ApiClientRePlyDto apiClientRePlyDto = new ApiClientRePlyDto();
apiClientRePlyDto.setCode(MessageCode.DEFAULT_SUCCESS_CODE.code);
apiClientRePlyDto.setData(wmap);
return new AnalysisResult(false, true, jsonObject, apiClientRePlyDto);
}
}
... ...
... ... @@ -92,13 +92,10 @@ public class CkaDtSndS {
senserData.addProperty("111",qiexiangbaohu);
if(DeviceCommandListenService.hasClienConnection(clientid))
{
return new AnalysisResult(true,true,jsonObject,new ApiClientRePlyDto() {
@Override
public void setReplyMessage(Message message) {
message.setCode(MessageCode.DEFAULT_SUCCESS_CODE);
message.setData(JSONObject.parseObject(jsonObject.toString(),HashMap.class));
}
});
ApiClientRePlyDto apiClientRePlyDto = new ApiClientRePlyDto();
apiClientRePlyDto.setCode(MessageCode.DEFAULT_SUCCESS_CODE.code);
apiClientRePlyDto.setData(JSONObject.parseObject(jsonObject.toString(),HashMap.class));
return new AnalysisResult(true,true,jsonObject, apiClientRePlyDto);
}
return new AnalysisResult(true,false,jsonObject);
}
... ...
... ... @@ -29,8 +29,6 @@ public class PersistenceDBService {
private static Map<Integer, IotProtocolClass> iotProtocolClassMap = new HashMap<>();
@Autowired
private DefaultDbService defaultDbService;
@Autowired
private PersistenceDBService persistenceDBService;
/**
* 更新数据库
... ... @@ -63,7 +61,7 @@ public class PersistenceDBService {
ParserDeviceHostDto parserDeviceHostDto = protocolPurificationModel.getParserDeviceHostDto();
if (parserDeviceHostDto.getIotProduct().getIs_sync_db()==1 && null !=parserDeviceHostDto.getIotProduct().getSync_db() && 0!=parserDeviceHostDto.getIotProduct().getSync_db())
{
ProtocolSyncFactory protocolSyncFactory = PluginsClassLoader.getJarClass(ProtocolSyncFactory.class,persistenceDBService.getClassnameFromIotProtocolClassId(parserDeviceHostDto.getIotProduct().getSync_db()));
ProtocolSyncFactory protocolSyncFactory = PluginsClassLoader.getJarClass(ProtocolSyncFactory.class,getClassnameFromIotProtocolClassId(parserDeviceHostDto.getIotProduct().getSync_db()));
// ProtocolSyncFactory protocolSyncFactory = getProtocolSyncService(persistenceDBService.getClassnameFromIotProtocolClassId(parserDeviceHostDto.getIotProduct().getSync_db()));
if(null != protocolSyncFactory)
{
... ...
package com.zhonglai.luhui.lsy.plc.service.service.topic;
import com.alibaba.fastjson.JSONObject;
import com.zhonglai.luhui.device.analysis.comm.dto.ApiClientRePlyDto;
import com.zhonglai.luhui.device.analysis.comm.dto.ServerDto;
import com.zhonglai.luhui.device.analysis.comm.dto.business.BusinessDto;
import com.zhonglai.luhui.device.analysis.comm.factory.BusinessAgreement;
... ... @@ -21,18 +22,18 @@ public class PutReqTopic implements BusinessAgreement<PutReqDto> {
@Override
public ServerDto analysis(Topic topic, PutReqDto data) throws Exception {
clienNoticeService.replySendMessage(topic, message -> {
message.setData(data.getTime());
message.setCode(MessageCode.DEFAULT_FAIL_CODE);
message.setMessage(data.getMsg());
switch (data.getResult())
{
case "1":
message.setCode(MessageCode.DEFAULT_SUCCESS_CODE);
message.setMessage("成功");
break;
}
});
ApiClientRePlyDto apiClientRePlyDto = new ApiClientRePlyDto();
apiClientRePlyDto.setData(data.getTime());
apiClientRePlyDto.setCode(MessageCode.DEFAULT_FAIL_CODE.code);
apiClientRePlyDto.setMessage(data.getMsg());
switch (data.getResult())
{
case "1":
apiClientRePlyDto.setCode(MessageCode.DEFAULT_SUCCESS_CODE.code);
apiClientRePlyDto.setMessage("成功");
break;
}
clienNoticeService.replySendMessage(topic, apiClientRePlyDto);
return null;
}
... ...
... ... @@ -19,8 +19,8 @@ spring:
mqtt:
#链接地址
broker: tcp://175.24.61.68:1883
# broker: tcp://8.129.82.37:1883
# broker: tcp://175.24.61.68:1883
broker: tcp://8.129.82.37:1883
#唯一标识
clientId: ${random.uuid}
topicconfig: "/{{roleid}}/{{username}}/{{clientid}}/{{payloadtype}}/{{topicType}}/{{messageid}}"
... ... @@ -29,7 +29,7 @@ mqtt:
client:
#客户端操作时间
operationTime: 10
productids: 9
productids: 13
#rocketmq配置信息
rocketmq:
... ...
package com.zhonglai.luhui.mqtt.service.topic;
import com.alibaba.fastjson.JSONObject;
import com.zhonglai.luhui.device.analysis.comm.dto.ApiClientRePlyDto;
import com.zhonglai.luhui.device.analysis.comm.dto.ServerDto;
import com.zhonglai.luhui.device.analysis.comm.dto.business.BusinessDto;
import com.zhonglai.luhui.device.analysis.comm.factory.BusinessAgreement;
... ... @@ -22,18 +23,18 @@ public class PutReqTopic implements BusinessAgreement<PutReqDto> {
@Override
public ServerDto analysis(Topic topic, PutReqDto data) throws Exception {
data.setMessageid(topic.getMessageid());
clienNoticeService.replySendMessage(topic, message -> {
message.setData(data.getData());
message.setCode(MessageCode.DEFAULT_SUCCESS_CODE);
message.setMessage("成功");
switch (data.getCode())
{
case 0:
message.setCode(MessageCode.DEFAULT_FAIL_CODE);
message.setMessage("失败");
break;
}
});
ApiClientRePlyDto apiClientRePlyDto = new ApiClientRePlyDto();
apiClientRePlyDto.setData(data.getData());
apiClientRePlyDto.setCode(MessageCode.DEFAULT_SUCCESS_CODE.code);
apiClientRePlyDto.setMessage("成功");
switch (data.getCode())
{
case 0:
apiClientRePlyDto.setCode(MessageCode.DEFAULT_FAIL_CODE.code);
apiClientRePlyDto.setMessage("失败");
break;
}
clienNoticeService.replySendMessage(topic, apiClientRePlyDto);
return null;
}
... ...
... ... @@ -6,6 +6,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.device.analysis.comm.dto.ApiClientRePlyDto;
import com.zhonglai.luhui.device.analysis.comm.dto.thingsmodels.ThingsModelItemBase;
import com.zhonglai.luhui.device.analysis.comm.service.BusinessDataUpdateService;
import com.zhonglai.luhui.device.analysis.dto.topic.AddPostDto;
... ... @@ -97,25 +98,27 @@ public class ReadReqTopic implements BusinessAgreement<ReadReqDto> {
}
data.setData(vjsonObject);
}
clienNoticeService.replySendMessage(topic, message -> {
if(null != data.getData())
{
message.setData(JSONObject.parseObject(data.getData().toJSONString(), HashMap.class));
}
message.setCode(MessageCode.DEFAULT_SUCCESS_CODE);
message.setMessage("成功");
});
ApiClientRePlyDto apiClientRePlyDto = new ApiClientRePlyDto();
if(null != data.getData())
{
apiClientRePlyDto.setData(JSONObject.parseObject(data.getData().toJSONString(), HashMap.class));
}
apiClientRePlyDto.setCode(MessageCode.DEFAULT_SUCCESS_CODE.code);
apiClientRePlyDto.setMessage("成功");
clienNoticeService.replySendMessage(topic, apiClientRePlyDto);
return serverDto;
}else if(0==data.getCode())
{
clienNoticeService.replySendMessage(topic, message -> {
if(null != data.getData())
{
message.setData(JSONObject.parseObject(data.getData().toJSONString(), HashMap.class));
}
message.setCode(MessageCode.DEFAULT_FAIL_CODE);
message.setMessage("失败");
});
ApiClientRePlyDto apiClientRePlyDto = new ApiClientRePlyDto();
if(null != data.getData())
{
apiClientRePlyDto.setData(JSONObject.parseObject(data.getData().toJSONString(), HashMap.class));
}
apiClientRePlyDto.setCode(MessageCode.DEFAULT_FAIL_CODE.code);
apiClientRePlyDto.setMessage("失败");
clienNoticeService.replySendMessage(topic,apiClientRePlyDto);
return null;
}
return null;
... ...
... ... @@ -21,11 +21,11 @@ spring:
redis:
database: 1
# Redis服务器地址 写你的ip
host: 47.112.163.61
host: 119.23.218.181
# Redis服务器连接端口
port: 9527
port: 6379
# Redis服务器连接密码(默认为空)
password: Luhui586
password:
# 连接池最大连接数(使用负值表示没有限制 类似于mysql的连接池
jedis:
pool:
... ... @@ -41,7 +41,7 @@ spring:
mqtt:
#链接地址
broker: tcp://175.24.61.68:1883
broker: tcp://iot.yu2le.com:1883
#唯一标识
clientId: ${random.uuid}
#公司id
... ... @@ -49,7 +49,7 @@ mqtt:
mqtt_usernames: 6_WP
#订阅的topic
topics: ADD_POST,ALL_POST,DB_TOPIC_DISTRIBUTE,GET/+,online,PUT_REQ/+,READ_REQ/+
sub_clientid: '+'
sub_clientid: '866520067506865'
topicconfig: "/{{roleid}}/{{username}}/{{clientid}}/{{payloadtype}}/{{topicType}}/{{messageid}}"
top_return_map: '{"PUT":"PUT_REQ","READ":"READ_REQ"}'
username: sysuser
... ... @@ -68,5 +68,5 @@ sys:
rocketmq:
#nameservice服务器地址(多个以英文逗号隔开)
name-server: 8.129.224.117:9876
send-topic: lh-mqtt-service-deviceCommand-test1
send-tag: 1
\ No newline at end of file
send-topic: lh-mqtt-service-deviceCommand-test
send-tag: 1
... ...
... ... @@ -37,6 +37,7 @@
<module>lh-superweb-jar</module>
<module>lh-ssh-service-lesten</module>
<module>lh-deviceInfo-sync</module>
<module>lh-camera</module>
</modules>
<properties>
... ...
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>摄像头直播</title>
<script src="js/hls.js"></script>
<style>
body { font-family: sans-serif; }
.cam-container { margin-bottom: 40px; }
</style>
</head>
<body>
<h1>摄像头直播页面</h1>
<h2>选择摄像头</h2>
<select id="cameraSelect"></select>
<div id="video-container"></div>
<h2>系统资源占用</h2>
<pre id="sys-info">Loading...</pre>
<script>
// 动态加载摄像头列表
async function loadCameras() {
try {
const res = await fetch('/cameras');
const cameras = await res.json();
const select = document.getElementById('cameraSelect');
select.innerHTML = ''; // 清空现有选项
cameras.forEach(camera => {
const option = document.createElement('option');
option.value = camera.name;
option.textContent = camera.name;
select.appendChild(option);
});
// 更新视频流显示
select.addEventListener('change', updateVideoStream);
updateVideoStream(); // 默认加载第一个摄像头
} catch (err) {
console.error('Failed to load cameras:', err);
}
}
// 更新视频流
function updateVideoStream() {
const cameraName = document.getElementById('cameraSelect').value;
const source = `http://192.168.0.103/DS-2XC3046-LR/SX20250425AACHFZ4535655/index.m3u8`;
// 创建视频元素
const video = document.createElement('video');
video.controls = true;
video.autoplay = true;
video.width = 640;
video.height = 360;
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(source);
hls.attachMedia(video);
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = source;
}
// 更新视频容器
const container = document.getElementById('video-container');
container.innerHTML = ''; // 清空现有视频
container.appendChild(video);
}
// 初始化摄像头选择框
loadCameras();
</script>
</body>
</html>
... ...
此 diff 太大无法显示。
!function(){"use strict";(e=>{const t="single-file-lazy-load",n="single-file-load-image",i="single-file-request-get-adopted-stylesheets",r={family:"font-family",style:"font-style",weight:"font-weight",stretch:"font-stretch",unicodeRange:"unicode-range",variant:"font-variant",featureSettings:"font-feature-settings"},o=e.fetch.bind(e),l=e.CustomEvent,s=e.document,d=e.screen,a=e.Element,c=e.UIEvent,g=e.Event,f=e.FileReader,_=e.Blob,m=e.JSON,u=e.MutationObserver,h=e.URL,p=new Map,y=new Map;let E;function v(){s.addEventListener("single-file-load-deferred-images-start",(()=>w())),s.addEventListener("single-file-load-deferred-images-keep-zoom-level-start",(()=>w(!0))),s.addEventListener("single-file-load-deferred-images-end",(()=>F())),s.addEventListener("single-file-load-deferred-images-keep-zoom-level-end",(()=>F(!0))),s.addEventListener("single-file-load-deferred-images-reset",b),s.addEventListener("single-file-load-deferred-images-keep-zoom-level-reset",(()=>{const e=s.documentElement.style.getPropertyValue("-sf-transform"),t=s.documentElement.style.getPropertyPriority("-sf-transform"),n=s.documentElement.style.getPropertyValue("-sf-transform-origin"),i=s.documentElement.style.getPropertyPriority("-sf-transform-origin"),r=s.documentElement.style.getPropertyValue("-sf-min-height"),o=s.documentElement.style.getPropertyPriority("-sf-min-height");s.documentElement.style.setProperty("transform",e,t),s.documentElement.style.setProperty("transform-origin",n,i),s.documentElement.style.setProperty("min-height",r,o),s.documentElement.style.removeProperty("-sf-transform"),s.documentElement.style.removeProperty("-sf-transform-origin"),s.documentElement.style.removeProperty("-sf-min-height"),b()})),s.addEventListener("single-file-dispatch-scroll-event-start",(()=>{E=!0})),s.addEventListener("single-file-dispatch-scroll-event-end",(()=>{E=!1})),s.addEventListener("single-file-block-cookies-start",(()=>{try{s.__defineGetter__("cookie",(()=>{throw new Error("document.cookie temporary blocked by SingleFile")}))}catch(e){}})),s.addEventListener("single-file-block-cookies-end",(()=>{delete s.cookie})),s.addEventListener("single-file-block-storage-start",(()=>{e._singleFile_localStorage||(e._singleFile_localStorage=e.localStorage,e.__defineGetter__("localStorage",(()=>{throw new Error("localStorage temporary blocked by SingleFile")}))),e._singleFile_indexedDB||(e._singleFile_indexedDB=e.indexedDB,e.__defineGetter__("indexedDB",(()=>{throw new Error("indexedDB temporary blocked by SingleFile")})))})),s.addEventListener("single-file-block-storage-end",(()=>{e._singleFile_localStorage&&(delete e.localStorage,e.localStorage=e._singleFile_localStorage,delete e._singleFile_localStorage),e._singleFile_indexedDB||(delete e.indexedDB,e.indexedDB=e._singleFile_indexedDB,delete e._singleFile_indexedDB)})),s.addEventListener("single-file-request-fetch-supported",(()=>s.dispatchEvent(new l("single-file-response-fetch-supported")))),s.addEventListener("single-file-request-fetch",(async e=>{const{url:t,options:n}=m.parse(e.detail);let i;try{const e=await o(t,n);i={url:t,response:await e.arrayBuffer(),headers:[...e.headers],status:e.status}}catch(e){i={url:t,error:e&&(e.message||e.toString())}}s.dispatchEvent(new l("single-file-response-fetch",{detail:i}))})),s.addEventListener(i,S),s.addEventListener("single-file-bootstrap",(t=>{try{e.bootstrap&&t.detail.data&&e.bootstrap(t.detail.data)}catch(e){}}))}function w(i){const r=s.scrollingElement||s.documentElement,o=r.clientHeight,c=r.clientWidth,f=Math.max(r.scrollHeight-o,o),_=Math.max(r.scrollWidth-c,c);if(s.querySelectorAll("[loading=lazy]").forEach((e=>{e.loading="eager",e.setAttribute(t,"")})),r.__defineGetter__("clientHeight",(()=>f)),r.__defineGetter__("clientWidth",(()=>_)),d.__defineGetter__("height",(()=>f)),d.__defineGetter__("width",(()=>_)),e._singleFile_innerHeight=e.innerHeight,e._singleFile_innerWidth=e.innerWidth,e.__defineGetter__("innerHeight",(()=>f)),e.__defineGetter__("innerWidth",(()=>_)),i||e._singleFile_getBoundingClientRect||(e._singleFile_getBoundingClientRect=a.prototype.getBoundingClientRect,a.prototype.getBoundingClientRect=function(){const t=e._singleFile_getBoundingClientRect.call(this);return this==r&&(t.__defineGetter__("height",(()=>f)),t.__defineGetter__("bottom",(()=>f+t.top)),t.__defineGetter__("width",(()=>_)),t.__defineGetter__("right",(()=>_+t.left))),t}),!e._singleFileImage){const t=e.Image;e._singleFileImage=e.Image,e.__defineGetter__("Image",(function(){return function(){const e=new t(...arguments),i=new t(...arguments);return i.__defineSetter__("src",(t=>{e.src=t,s.dispatchEvent(new l(n,{detail:e.src}))})),i.__defineGetter__("src",(()=>e.src)),i.__defineSetter__("srcset",(t=>{s.dispatchEvent(new l(n)),e.srcset=t})),i.__defineGetter__("srcset",(()=>e.srcset)),i.__defineGetter__("height",(()=>e.height)),i.__defineGetter__("width",(()=>e.width)),i.__defineGetter__("naturalHeight",(()=>e.naturalHeight)),i.__defineGetter__("naturalWidth",(()=>e.naturalWidth)),e.decode&&i.__defineGetter__("decode",(()=>()=>e.decode())),e.onload=e.onloadend=e.onerror=t=>{s.dispatchEvent(new l("single-file-image-loaded",{detail:e.src})),i.dispatchEvent(new g(t.type,t))},i}}))}let m,u;i?(m=o/f,u=c/_):(m=(o+e.scrollY)/f,u=(c+e.scrollX)/_);const h=Math.min(m,u);if(h<1){const e=s.documentElement.style.getPropertyValue("transform"),t=s.documentElement.style.getPropertyPriority("transform"),n=s.documentElement.style.getPropertyValue("transform-origin"),r=s.documentElement.style.getPropertyPriority("transform-origin"),o=s.documentElement.style.getPropertyValue("min-height"),l=s.documentElement.style.getPropertyPriority("min-height");s.documentElement.style.setProperty("transform-origin",(m<1?"50%":"0")+" "+(u<1?"50%":"0")+" 0","important"),s.documentElement.style.setProperty("transform","scale3d("+h+", "+h+", 1)","important"),s.documentElement.style.setProperty("min-height",100/h+"vh","important"),B(),i?(s.documentElement.style.setProperty("-sf-transform",e,t),s.documentElement.style.setProperty("-sf-transform-origin",n,r),s.documentElement.style.setProperty("-sf-min-height",o,l)):(s.documentElement.style.setProperty("transform",e,t),s.documentElement.style.setProperty("transform-origin",n,r),s.documentElement.style.setProperty("min-height",o,l))}if(!i){B();const e=r.getBoundingClientRect();window==window.top&&[...p].forEach((([t,n])=>{const i=n.options&&n.options.root&&n.options.root.getBoundingClientRect,r=i&&n.options.root.getBoundingClientRect(),o=y.get(t);if(o){const l=o.map((t=>{const n=t.getBoundingClientRect();return{target:t,intersectionRatio:1,boundingClientRect:n,intersectionRect:n,isIntersecting:!0,rootBounds:i?r:e,time:0}})).filter((e=>e.boundingClientRect.width&&e.boundingClientRect.height));l.length&&n.callback.call(t,l,t)}}))}}function F(n){s.querySelectorAll("["+t+"]").forEach((e=>{e.loading="lazy",e.removeAttribute(t)})),n||e._singleFile_getBoundingClientRect&&(a.prototype.getBoundingClientRect=e._singleFile_getBoundingClientRect,delete e._singleFile_getBoundingClientRect),e._singleFileImage&&(delete e.Image,e.Image=e._singleFileImage,delete e._singleFileImage),n||B()}function b(){const t=s.scrollingElement||s.documentElement;null!=e._singleFile_innerHeight&&(delete e.innerHeight,e.innerHeight=e._singleFile_innerHeight,delete e._singleFile_innerHeight),null!=e._singleFile_innerWidth&&(delete e.innerWidth,e.innerWidth=e._singleFile_innerWidth,delete e._singleFile_innerWidth),delete t.clientHeight,delete t.clientWidth,delete d.height,delete d.width}if(v(),new u(v).observe(s,{childList:!0}),e.CSS&&e.CSS.paintWorklet&&e.CSS.paintWorklet.addModule){const t=e.CSS.paintWorklet.addModule;e.CSS.paintWorklet.addModule=function(n,i){const r=t.apply(e.CSS.paintWorklet,arguments);return n=new h(n,s.baseURI).href,s.dispatchEvent(new l("single-file-new-worklet",{detail:{moduleURL:n,options:i}})),r}}if(e.FontFace){const t=e.FontFace;e.FontFace=function(){return P(...arguments).then((e=>s.dispatchEvent(new l("single-file-new-font-face",{detail:e})))),new t(...arguments)},e.FontFace.prototype=t.prototype,e.FontFace.toString=function(){return"function FontFace() { [native code] }"};const n=s.fonts.delete;s.fonts.delete=function(e){return P(e.family).then((e=>s.dispatchEvent(new l("single-file-delete-font",{detail:e})))),n.call(s.fonts,e)},s.fonts.delete.toString=function(){return"function delete() { [native code] }"};const i=s.fonts.clear;s.fonts.clear=function(){return s.dispatchEvent(new l("single-file-clear-fonts")),i.call(s.fonts)},s.fonts.clear.toString=function(){return"function clear() { [native code] }"}}if(e.IntersectionObserver){const t=e.IntersectionObserver;e.IntersectionObserver=function(){const e=new t(...arguments),n=t.prototype.observe||e.observe,i=t.prototype.unobserve||e.unobserve,r=arguments[0],o=arguments[1];return n&&(e.observe=function(t){let i=y.get(e);return i||(i=[],y.set(e,i)),i.push(t),n.call(e,t)}),i&&(e.unobserve=function(t){let n=y.get(e);return n&&(n=n.filter((e=>e!=t)),n.length?y.set(e,n):(y.delete(e),p.delete(e))),i.call(e,t)}),p.set(e,{callback:r,options:o}),e},e.IntersectionObserver.prototype=t.prototype,e.IntersectionObserver.toString=function(){return"function IntersectionObserver() { [native code] }"}}function S(e){const t=e.target.shadowRoot;if(e.stopPropagation(),t){t.addEventListener(i,S,{capture:!0}),t.addEventListener("single-file-unregister-request-get-adopted-stylesheets",(()=>t.removeEventListener(i,S)),{once:!0});const e=Array.from(t.adoptedStyleSheets).map((e=>Array.from(e.cssRules).map((e=>e.cssText)).join("\n")));e.length&&t.dispatchEvent(new l("single-file-response-get-adopted-stylesheets",{detail:{adoptedStyleSheets:e}}))}}async function P(e,t,n){const i={};return i["font-family"]=e,i.src=t,n&&Object.keys(n).forEach((e=>{r[e]&&(i[r[e]]=n[e])})),new Promise((e=>{if(i.src instanceof ArrayBuffer){const t=new f;t.readAsDataURL(new _([i.src])),t.addEventListener("load",(()=>{i.src="url("+t.result+")",e(i)}))}else e(i)}))}function B(){try{e.dispatchEvent(new c("resize")),E&&e.dispatchEvent(new c("scroll"))}catch(e){}}})("object"==typeof globalThis?globalThis:window)}();
\ No newline at end of file
... ...