初始化

This commit is contained in:
2020-06-28 09:01:37 +08:00
commit 88f72990f5
522 changed files with 49365 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
package bean;
import lombok.Data;
/**
* @Author: Xu
* @Date:
*/
@Data
public class OpcConfigBean {
private String host;
private String user;
private String clsid;
private String password;
private String opcid;
}

View File

@@ -0,0 +1,397 @@
package bean;
import bean.interfacebean.OpcClient;
import org.apache.log4j.Logger;
import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.common.JISystem;
import org.jinterop.dcom.core.*;
import org.openscada.opc.dcom.list.ClassDetails;
import org.openscada.opc.lib.common.ConnectionInformation;
import org.openscada.opc.lib.da.*;
import org.openscada.opc.lib.da.browser.FlatBrowser;
import org.openscada.opc.lib.list.Categories;
import org.openscada.opc.lib.list.Category;
import org.openscada.opc.lib.list.ServerList;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
/**
* Description:
*
* @author: XuChenChen
* @date: 2020/3/25 10:20
*/
public class UtgardOpcClient implements OpcClient {
private static Logger logger = Logger.getLogger(UtgardOpcClient.class);
private Server mServer = null;
private final ConnectionInformation connectionInfo = new ConnectionInformation();
private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
public UtgardOpcClient(OpcConfigBean configBean,String opcServerId)
{
setLoggerOutput(false);
if (mServer==null)
{
System.out.println("创建连接");
if (configBean == null) {
try {
throw new Exception("opcServerId"+opcServerId+"不存在!");
} catch (Exception e) {
myErrorHandler(e);
}
}
connectServer(configBean.getHost(), configBean.getClsid(),configBean.getUser(), configBean.getPassword());
}
}
/**
* 检测是否正常连接
* @return
*/
public Boolean CheckServiceStart() {
return mServer != null;
}
private void myErrorHandler(Exception e)
{
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter, true));
logger.error( stringWriter.toString());
}
/**
* 用于关闭默认log输出
* @param key false关闭true打开
*/
private void setLoggerOutput(boolean key) {
java.util.logging.Logger systemLogger = java.util.logging.Logger.getLogger("org.jinterop");
ConsoleHandler consoleHandler = new ConsoleHandler();
if (!key) {
systemLogger.setLevel(Level.WARNING);
consoleHandler.setLevel(Level.WARNING);
}
}
/**
* 连接opc server
*
* @param host opcServer ip
* @param clsid opcServer 程序注册表CLSID
* @param user opcServer windows账户
* @param password opcServer windows密码
*/
public synchronized boolean connectServer(String host, String clsid, String user, String password) {
boolean mState = false;
try {
connectionInfo.setHost(host);
connectionInfo.setClsid(clsid);
connectionInfo.setUser(user);
connectionInfo.setPassword(password);
myServerConnect(connectionInfo, executor);
CheckConnectState();
mState = true;
} catch (Exception e) {
myErrorHandler(e);
} finally {
if (!mState) {
mServer = null;
logger.error("Connect Opc Server Fail!");
}
}
if (mState) {
logger.info("Connect Opc Server successful!");
}
return mState;
}
protected void myServerConnect(ConnectionInformation connectionInfo, ScheduledExecutorService executor) throws Exception
{
mServer = new Server(connectionInfo, executor);
JISystem.setAutoRegisteration(true); //添加自动注册。
mServer.connect();
mServer.addStateListener(new ServerConnectionStateListener() {
public void connectionStateChanged(boolean state) {
logger.info("Connect state changer,now:" + state);
}
});
}
protected void CheckConnectState(){
Timer timer = new Timer();
TimerTask task = new TimerTask() {
int timeOutCount = 0;
@Override
public void run() {
if (mServer==null)
{
System.out.println("连接终止,取消检测");
cancel();
return;
}
if (mServer.getServerState()==null)
{
timeOutCount++;
System.out.println("超时,次数:" + timeOutCount);
if (timeOutCount ==3)
{
try {
System.out.println("连接断开,尝试重连。。");
myServerConnect(connectionInfo,executor);
timeOutCount =0;
} catch (Exception e) {
myErrorHandler(e);
}
}
}
}
};
timer.schedule(task,0,3000);
}
@Override
public synchronized void disconnectServer() {
if (mServer == null) {
logger.info("Connect is null!");
return;
}
mServer.disconnect();
mServer = null;
logger.info("Disconnect Server");
}
/**
* 显示server上的OPC服务器应用列表
*/
public void showAllOPCServer(String host, String user, String password) {
try {
ServerList serverList = new ServerList(host, user, password, "");
// 支持DA 1.0DA 2.0规范
Collection<ClassDetails> detailsList = serverList.listServersWithDetails(
new Category[]{Categories.OPCDAServer10, Categories.OPCDAServer20}, new Category[]{});
for (final ClassDetails details : detailsList) {
logger.info("Description=" + details.getDescription() + "\nClsId=" + details.getClsId() + "\nProgId=" + details.getProgId());
}
} catch (Exception e) {
myErrorHandler(e);
}
}
/**
* 检查opc server中是否包含指定的地址点列表
*/
public boolean checkItemList(List<String> list) {
// 获取opc server上的所有检测点
FlatBrowser flatBrowser = mServer.getFlatBrowser();
if (flatBrowser == null) {
return false;
}
try {
Collection<String> collection = flatBrowser.browse();
return collection.containsAll(list);
} catch (Exception e) {
myErrorHandler(e);
}
return false;
}
/**
* 检查opc server中是否包含指定的一个地址点
*/
private boolean checkItem(String address) {
// 获取opc server上的所有检测点
FlatBrowser flatBrowser = mServer.getFlatBrowser();
if (flatBrowser == null) {
return false;
}
try {
Collection<String> collection = flatBrowser.browse();
return collection.contains(address);
} catch (Exception e) {
myErrorHandler(e);
}
return false;
}
/**
* 输地址以及新值进行修改。
*
* @param labelName PLC标签名
* @param value 值 支持String,Boolean,Short,Number型
* @return 操作结果
*/
@Override
public boolean setValueByName(String labelName, Object value) {
boolean result = false;
try {
if (!checkItem(labelName)) throw new Exception("Not found:" + labelName);
} catch (Exception e) {
myErrorHandler(e);
return false;
}
try {
Group group = mServer.addGroup();
Item item = group.addItem(labelName);
int type = item.read(true).getValue().getType();
if (type == JIVariant.VT_BSTR && value instanceof String) {
String stringValue = value.toString();
item.write(new JIVariant(stringValue));
logger.info("Address:" + labelName + ",Write:" + value + " successful");
result = true;
} else if (type == JIVariant.VT_BOOL && value instanceof Boolean) {
Boolean booleanValue = (Boolean) value;
item.write(new JIVariant(booleanValue));
logger.info("Address:" + labelName + ",Write:" + value + " successful");
result = true;
} else if (type == JIVariant.VT_I2 && value instanceof Short) {
Short shortValue = (Short) value;
item.write(new JIVariant(shortValue));
logger.info("Address:" + labelName + ",Write:" + value + " successful");
result = true;
}
//TODO 暂时尚未测试 可能需要修复
else if ((type == JIVariant.VT_UI1 || type == JIVariant.VT_UI2 || type == JIVariant.VT_UI4) && value instanceof Number) {
Number numberValue = (Number) value;
JIUnsignedShort jIUnsignedShort = (JIUnsignedShort) JIUnsignedFactory.getUnsigned(numberValue, JIFlags.FLAG_REPRESENTATION_UNSIGNED_SHORT);
item.write(new JIVariant(jIUnsignedShort));
logger.info("Address:" + labelName + ",Write:" + value + " successful");
result = true;
} else if (type == JIVariant.VT_EMPTY) {
logger.warn("Write failed,PLC may not be connected! Value type=VT_EMPTY");
result = false;
} else {
logger.warn("Address:" + labelName + "Value type:" + type + " not support!");
result = false;
}
mServer.removeGroup(group, true);
} catch (Exception e) {
myErrorHandler(e);
}
return result;
}
/**
* 同步取得单个标签值
* 可取数组类型floatbooleanshort。
* 单数据类型 floatbooleanshortstring
*
* @param labelName PLC标签名
* @return 标签数据 string类型
*/
@Override
public ArrayList getValueByName(String labelName) {
try {
if (!checkItem(labelName)) throw new Exception("Not found:" + labelName);
} catch (Exception e) {
myErrorHandler(e);
return null;
}
ArrayList returnValue;
try {
Group group = mServer.addGroup();
Item item = group.addItem(labelName);
JIVariant JiValue=item.read(true).getValue();
returnValue = value(JiValue.getType(), JiValue);
mServer.removeGroup(group, true);
} catch (Exception e) {
myErrorHandler(e);
return null;
}
logger.info("Read Address:" + labelName + ",Type:" + returnValue.getClass().getName() + ",Value:" + returnValue.toString());
return returnValue;
}
/**
* Description: 对标签值进行处理
*/
private ArrayList value(int type, JIVariant item) throws Exception{
JIArray JiArray = item.getObjectAsArray();
ArrayList list=new ArrayList<>();
//Array of REAL4
if (type == 8196) return new ArrayList<>(Arrays.asList((Float[]) JiArray.getArrayInstance()));
//ARRAY of SHORT
else if (type == 8194) return new ArrayList<>(Arrays.asList((Short[]) JiArray.getArrayInstance()));
//ARRAY of Boolean
else if (type == 8203) return new ArrayList<>(Arrays.asList((Boolean[]) JiArray.getArrayInstance()));
//Fixme 字符串数组无法转换
else if (type == 8200) {
String[] VALUE= new String[20];
// String[] value = (String[]) JiArray.getArrayInstance();
VALUE = (String[]) JiArray.getArrayInstance();
return new ArrayList<>(Arrays.asList(VALUE));
}
//Short
else if (type == JIVariant.VT_I2)
{
list.add(item.getObjectAsShort());
return list;
}
//String
else if (type == JIVariant.VT_BSTR) {
list.add(item.getObjectAsString2());
return list;
}
//Number
else if (type == JIVariant.VT_UI1 || type == JIVariant.VT_UI2 || type == JIVariant.VT_UI4)
{
list.add(item.getObjectAsUnsigned().getValue());
return list;
}
//boolean
else if (type == JIVariant.VT_BOOL)
{
list.add(item.getObjectAsBoolean());
return list;
}
else if (type == JIVariant.VT_EMPTY) throw new Exception("Read failed,PLC may not be connected! Value type=VT_EMPTY");
else if (type == JIVariant.VT_NULL) throw new Exception("Read failed,PLC may not be connected! Value type=VT_NULL");
else throw new Exception("Return value type that cannot be processed. Type:" + type);
}
/**
* 对多个标签值进行读取
*/
@Override
public Map<String,ArrayList> getValuesByNameList(ArrayList<String> NameList)
{
Map<String,ArrayList> returnMap = new HashMap<>();
for (String name:NameList)
{
returnMap.put(name,getValueByName(name));
}
return returnMap;
}
public void asyncReadObject(final String itemId, int period) throws Exception {
// 第三个参数用于设置初始化时是否执行访问
AccessBase accessBase;
accessBase = new Async20Access(mServer, 1000, false);
accessBase.addItem(itemId, new DataCallback() {
public void changed(Item item, ItemState itemState) {
// System.out.println("asyncReadObject item=" + itemState);
try {
Object value = itemState.getValue().getObject();
System.out.println(value.toString());
} catch (JIException e) {
myErrorHandler(e);
}
}
});
// 开始读取
accessBase.bind();
Thread.sleep( 1000);
accessBase.unbind();
}
}

View File

@@ -0,0 +1,16 @@
package bean.interfacebean;
import java.util.ArrayList;
import java.util.Map;
/**
* @Author: Xu
* @Date:
*/
public interface OpcClient {
void disconnectServer();
boolean setValueByName(String labelName, Object value);
ArrayList getValueByName(String labelName);
Map<String,ArrayList> getValuesByNameList(ArrayList<String> NameList);
}

View File

@@ -0,0 +1,10 @@
package config;
/**
* @Author: Xu
* @Date:
*/
public class MyConfig {
public static final String MAIN_PROPERTIES_PATH ="OpcClient\\opcConfig.json";
public static final String TEST_PROPERTIES_PATH =".\\opcConfig.json";
}

View File

@@ -0,0 +1,116 @@
package factionry;
import java.util.Map;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import bean.OpcConfigBean;
import bean.UtgardOpcClient;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import bean.interfacebean.OpcClient;
/**
* Description:
* @author: XuChenChen
* @date: 2020/5/20 12:19
* @param:
* @return:
*/
public class OpeClientFactory {
public static Map<String,UtgardOpcClient> utgardOpcClientMap=new HashMap<>();
private static File filePath;
//本地文件配置,路径可配。
public static void setFilePath(File filePath) {
OpeClientFactory.filePath = filePath;
}
/**
* 根据传入的opcserverid判定连接是否为同一个如果为同一个则返回连接本体
* 否则根据opcserverid创建新的连接。存入数组后返回。
* @param opcServerId
* @return
*/
public static OpcClient getUtgardOpcClient(String opcServerId) {
if (utgardOpcClientMap==null||utgardOpcClientMap.isEmpty()||utgardOpcClientMap.get(opcServerId)==null)
{
synchronized (OpeClientFactory.class)
{
if (utgardOpcClientMap.get(opcServerId)==null||!utgardOpcClientMap.get(opcServerId).CheckServiceStart())
{
UtgardOpcClient utgardOpcClient = new UtgardOpcClient(getLocalConfig(opcServerId),opcServerId);
if (utgardOpcClient.CheckServiceStart()) utgardOpcClientMap.put(opcServerId, utgardOpcClient);
}
}
}
return utgardOpcClientMap.get(opcServerId);
}
/*
获取本地的连接配置
*/
private static OpcConfigBean getLocalConfig(String opcServerId)
{
String str = null;
try {
//fixme 设定为相对路径,可以根据需求改为绝对路径。
BufferedInputStream in = new BufferedInputStream(new FileInputStream(filePath.getAbsolutePath()));
byte[] bytes = new byte[2048];
int n;
str = null;
while ((n = in.read(bytes, 0, bytes.length)) != -1) {
//转换成字符串
str = new String(bytes, 0, n, "GBK");
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
ArrayList<OpcConfigBean> opcConfigBeans = JSON.parseObject(str, new TypeReference<ArrayList<OpcConfigBean>>() {});
if (opcConfigBeans != null)
{
for (OpcConfigBean obj:opcConfigBeans) {
if (obj.getOpcid().equals(opcServerId)) return obj;
}
};
return null;
}
public static Map<String,OpcConfigBean> getLocalConfigsMap() {
Map<String,OpcConfigBean> result= new HashMap<> ();
ArrayList<OpcConfigBean> opcConfigBeans = getLocalConfigsList();
if (opcConfigBeans != null) {
for (OpcConfigBean obj : opcConfigBeans) {
result.put(obj.getOpcid(), obj);
}
return result;
}
return null;
}
public static ArrayList<OpcConfigBean> getLocalConfigsList() {
String str = null;
try {
//fixme 设定为相对路径,可以根据需求改为绝对路径。
BufferedInputStream in = new BufferedInputStream(new FileInputStream(filePath.getAbsolutePath()));
byte[] bytes = new byte[2048];
int n;
str = null;
while ((n = in.read(bytes, 0, bytes.length)) != -1) {
//转换成字符串
str = new String(bytes, 0, n, "GBK");
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
ArrayList<OpcConfigBean> opcConfigBeans = JSON.parseObject(str, new TypeReference<ArrayList<OpcConfigBean>>() {});
if (opcConfigBeans != null) {
return opcConfigBeans;
}
return null;
}
}

View File

@@ -0,0 +1,63 @@
import bean.OpcConfigBean;
import config.MyConfig;
import factionry.OpeClientFactory;
import bean.interfacebean.OpcClient;
import org.junit.Test;
import java.io.File;
import java.util.Map;
/**
* @Author: Xu
* @Date:
*/
public class opcTest {
public static void main(String[] args) {
//设置本地配置文件的路径(目前为根据相对路径。
OpeClientFactory.setFilePath(new File(MyConfig.MAIN_PROPERTIES_PATH));
//传入想要查询的变量所在的opcid opcid根据本地的配置文件具体设置可变。
final OpcClient utgardOpcClient = OpeClientFactory.getUtgardOpcClient("5102");
// System.out.println(utgardOpcClient.getValueByName("MWSMART.NewPLC.NewItem"));
System.out.println(utgardOpcClient.getValueByName("TEST.A1"));
System.out.println(utgardOpcClient);
utgardOpcClient.disconnectServer();
}
private static void delay(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test
public void test1()
{
OpeClientFactory.setFilePath(new File(MyConfig.TEST_PROPERTIES_PATH));
//测试不同的opcserver是否可以创建不同的连接
for (int i = 0; i < 2; i++) {
OpcClient utgardOpcClient = OpeClientFactory.getUtgardOpcClient(i+"");
System.out.println(""+i+"个:"+utgardOpcClient);
}
//测试创建完成后是否存在与进程中。 连接失败的进程不会保存到连接map中
// for (int i = 0; i < 2; i++) {
// OpcClient utgardOpcClient = OpeClientFactory.getUtgardOpcClient(i+"");
// System.out.println("复检 第"+i+"个:"+utgardOpcClient);
// }
}
@Test
public void test2()
{
//提供获取map以及list的方法供用户在进行添加时判断opcid是否存在。
OpeClientFactory.setFilePath(new File(MyConfig.TEST_PROPERTIES_PATH));
Map<String, OpcConfigBean> localConfigs = OpeClientFactory.getLocalConfigsMap();
OpcConfigBean opcConfigBean = localConfigs.get("1");
System.out.println(opcConfigBean.toString());
System.out.println("============");
System.out.println(OpeClientFactory.getLocalConfigsList());
}
}

View File

@@ -0,0 +1,23 @@
log4j.rootLogger = debug,stdout,D,E
### \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u03E2\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u0327 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern =[%-5p]%d{yyyy-MM-dd HH:mm:ss} Method:%c:%m%n
### \uFFFD\uFFFD\uFFFDDEBUG \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u03F5\uFFFD\uFFFD\uFFFD\u05BE\uFFFD\uFFFD=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = D://logs/opclog.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %l %m%n
### \uFFFD\uFFFD\uFFFDERROR \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u03F5\uFFFD\uFFFD\uFFFD\u05BE\uFFFD\uFFFD=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =D://logs/opcerror.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %l %m%n