Windows10 开启远程桌面并添加用户

1.右键我的电脑—-选择属性
2.选择远程设置
3.选中允许远程协助此计算机
4.点击选择用户,如需新建用户的话,点击打开用户账户
5.点击管理其他账户
6.点击添加新用户
7.点击添加一个账户
8.点击用户,添加新用户
9.设置账号名和密码
10.点击创建,创建成功

【WINDOWS10 卸载】安全补丁右键不能卸载处理方法

温馨提示:卸载安全更新可能会带来资讯安全风险,请您衡量风险。)


在更新界面中所有的安全更新没有卸载选项

选取更新的时候左上角应该有可卸载的文字,在安全更新上鼠标左键和右键都没有反应

办法
搜索栏输入【CMD】找到 【命令提示符】,右击【以管理员身份打开】
在【命令提示符】中输入如下命令后回车:
wusa /uninstall /kb:XXXXXXX(补丁编号)
(譬如:wusa /uninstall /kb:5040427) )

1
2
3
4
5
(譬如:wusa /uninstall /kb:5040427) )


wusa /uninstall /kb:5005112

OPC-DA-ALL-List-OPC-(四)-OPC Client Java调用之Utgard

Utgard是什么

官方网站http://openscada.org/projects/utgard/

utgard是一个开源的项目,基于j-interop做的,用于和OPC SERVER通讯。

j-interop是纯java封装的用于COM/DCOM通讯的开源项目,这样就不必使用JNI

Utgard使用

  • 依赖的jar包
j-interop.jar 与COM和DCOM通讯的开源项目
j-interopdeps.jar
jcifs-1.2.19.jar
org.openscada.opc.dcom-1.1.0-20141118.151415-27.jar Utgard dcom的jar包
org.openscada.opc.lib-1.1.0-20141118.151453-1.jar Utgard opc的jar包
slf4j-api-1.7.6.jar Log4j依赖的jar包
log4j-1.2.16.jar Log4j的jar包

Utgard与opc通讯分为两种方式

  • Utgard OPC的API
  • Utgard DCOM的API

示例代码参见

OPC_Client_Utgard项目

关键API示例

  • 列举某Server下的所有OPC连接
1
2
3
4
5
6
7
8
9
10
11
ServerList serverList = new ServerList("10.1.5.123", "freud",
"password", "");

Collection<ClassDetails> classDetails = serverList
.listServersWithDetails(new Category[] {
Categories.OPCDAServer10, Categories.OPCDAServer20,
Categories.OPCDAServer30 }, new Category[] {});

for (ClassDetails cds : classDetails) {
System.out.println(cds.getProgId() + "=" + cds.getDescription());
}
  • 列举连接下的所有Group和Item
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public static void main(String[] args) throws Exception {
ConnectionInformation ci = new ConnectionInformation();
ci.setHost("10.1.5.123");
ci.setDomain("");
ci.setUser("freud");
ci.setPassword("password");
ci.setClsid("F8582CF2-88FB-11D0-B850-00C0F0104305");

Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor());

server.connect();

dumpTree(server.getTreeBrowser().browse(), 0);
dumpFlat(server.getFlatBrowser());

server.disconnect();
}

private static void dumpFlat(final FlatBrowser browser)
throws IllegalArgumentException, UnknownHostException, JIException {
for (String name : browser.browse()) {
System.out.println(name);
}
}

private static void dumpTree(final Branch branch, final int level) {

for (final Leaf leaf : branch.getLeaves()) {
dumpLeaf(leaf, level);
}
for (final Branch subBranch : branch.getBranches()) {
dumpBranch(subBranch, level);
dumpTree(subBranch, level + 1);
}
}

private static String printTab(int level) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < level; i++) {
sb.append("\t");
}
return sb.toString();
}

private static void dumpLeaf(final Leaf leaf, final int level) {
System.out.println(printTab(level) + "Leaf: " + leaf.getName() + ":"
+ leaf.getItemId());
}

private static void dumpBranch(final Branch branch, final int level) {
System.out.println(printTab(level) + "Branch: " + branch.getName());
}
  • Item的同步查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public static void main(String[] args) throws Exception {

ConnectionInformation ci = new ConnectionInformation();
ci.setHost("10.1.5.123");
ci.setDomain("");
ci.setUser("freud");
ci.setPassword("password");
ci.setClsid("F8582CF2-88FB-11D0-B850-00C0F0104305");

Server server = new Server(ci,
Executors.newSingleThreadScheduledExecutor());

server.connect();

Group group = server.addGroup();
Item item = group.addItem("Random.Real5");

Map<String, Item> items = group.addItems("Random.Real1",
"Random.Real2", "Random.Real3", "Random.Real4");

dumpItem(item);

for (Entry<String, Item> temp : items.entrySet()) {
dumpItem(temp.getValue());
}

server.dispose();
}

private static void dumpItem(Item item) throws JIException {
System.out.println("[" + (++count) + "],ItemName:[" + item.getId()
+ "],value:" + item.read(false).getValue());
}

private static int count;
  • Item的异步查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private static final int PERIOD = 100;

private static final int SLEEP = 2000;

public static void main(String[] args) throws Exception {

ConnectionInformation ci = new ConnectionInformation();
ci.setHost("10.1.5.123");
ci.setDomain("");
ci.setUser("freud");
ci.setPassword("password");
ci.setClsid("F8582CF2-88FB-11D0-B850-00C0F0104305");

Server server = new Server(ci,
Executors.newSingleThreadScheduledExecutor());

server.connect();

AccessBase access = new SyncAccess(server, PERIOD);

access.addItem("Random.Real5", new DataCallback() {
private int i;

public void changed(Item item, ItemState itemstate) {
System.out.println("[" + (++i) + "],ItemName:[" + item.getId()
+ "],value:" + itemstate.getValue());
}
});

access.bind();
Thread.sleep(SLEEP);
access.unbind();
server.dispose();
}
  • Item的发布订阅查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private static final int PERIOD = 100;

private static final int SLEEP = 2000;

public static void main(String[] args) throws Exception {

ConnectionInformation ci = new ConnectionInformation();
ci.setHost("10.1.5.123");
ci.setDomain("");
ci.setUser("freud");
ci.setPassword("password");
ci.setClsid("F8582CF2-88FB-11D0-B850-00C0F0104305");

Server server = new Server(ci,
Executors.newSingleThreadScheduledExecutor());

server.connect();

AccessBase access = new Async20Access(server, PERIOD, false);

access.addItem("Random.Real5", new DataCallback() {

private int count;

public void changed(Item item, ItemState itemstate) {
System.out.println("[" + (++count) + "],ItemName:["
+ item.getId() + "],value:" + itemstate.getValue());
}
});

access.bind();
Thread.sleep(SLEEP);
access.unbind();
server.dispose();
}
  • 自动重连Item异步读取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private static final int PERIOD = 100;

private static final int SLEEP = 2000;

public static void main(String[] args) throws Exception {

ConnectionInformation ci = new ConnectionInformation();
ci.setHost("10.1.5.123");
ci.setDomain("");
ci.setUser("freud");
ci.setPassword("password");
ci.setClsid("F8582CF2-88FB-11D0-B850-00C0F0104305");

Server server = new Server(ci,
Executors.newSingleThreadScheduledExecutor());

AutoReconnectController controller = new AutoReconnectController(server);

controller.connect();

AccessBase access = new SyncAccess(server, PERIOD);

access.addItem("Random.Real5", new DataCallback() {
private int i;

public void changed(Item item, ItemState itemstate) {
System.out.println("[" + (++i) + "],ItemName:[" + item.getId()
+ "],value:" + itemstate.getValue());
}
});

access.bind();
Thread.sleep(SLEEP);
access.unbind();
controller.disconnect();
}
  • Item同步写入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public static void main(String[] args) throws Exception {

ConnectionInformation ci = new ConnectionInformation();
ci.setHost("10.1.5.123");
ci.setDomain("");
ci.setUser("freud");
ci.setPassword("password");
ci.setClsid("F8582CF2-88FB-11D0-B850-00C0F0104305");

Server server = new Server(ci,
Executors.newSingleThreadScheduledExecutor());

server.connect();

Group group = server.addGroup();
Item item = group.addItem("Square Waves.Real4");

final Float[] integerData = new Float[] { 1202f, 1203f, 1204f };
final JIArray array = new JIArray(integerData, false);
final JIVariant value = new JIVariant(array);

item.write(value);
Thread.sleep(2000);

dumpItem(item);

server.dispose();

}

private static void dumpItem(Item item) throws JIException {
System.out.println("[" + (++count) + "],ItemName:[" + item.getId()
+ "],value:" + item.read(true).getValue());
}

private static int count;
  • Item异步写入

OPC-DA-ALL-List-OPC-(三)-OPC主要功能

同步访问

OPC服务器把按照OPC应用程序的要求得到的数据访问结果作为方法的参数返回给OPC应用程序,OPC应用程序在结果被返回为止一直必须处于等待状态。

Synch Read

异步访问

OPC服务器接到OPC应用程序的要求后,几乎立即将方法返回。OPC应用程序随后可以进行其他处理。当OPC服务器完成数据访问时,触发OPC应用程序的异步访问完成事件,将数据访问结果传送给OPC应用程序。OPC应用程序在VB的事件处理程序中接受从OPC服务器传送来的数据。

Asynch Read

订阅方式数据采集

并不需要OPC应用程序向OPC服务器要求,就可以自动接到从OPC服务器送来的变化通知的订阅方式数据采集(Subscription)。服务器按一定的更新周期(UpdateRate)更新OPC服务器的数据缓冲器的数值时,如果发现数值有变化时,就会以数据变化事件(DataChange)通知OPC应用程序。如果OPC服务器支持不敏感带(DeadBand),而且OPC标签的数据类型是模拟量的情况,只有现在值与前次值的差的绝对值超过一定限度时,才更新缓冲器数据并通知OPC应用程序。由此可以无视模拟值的微小变化,从而减轻OPC服务器和OPC应用程序的负荷。

Publish and subscribe

上述的OPC功能可以总结为如下表:

Feature sumary

三种方式的性能总结:

Performance sumary

OPC-DA-ALL-List-OPC-(二)-什么是OPC

OPC

OPC(OLE for Process Control, 用于过程控制的OLE)是一个工业标准,管理这个标准国际组织是OPC基金会.

为什么需要OPC

OPC是为了不同供应厂商的设备和应用程序之间的软件接口标准化,使其间的数据交换更加简单化的目的而提出的。作为结果,从而可以向用户提供不依靠于特定开发语言和开发环境的可以自由组合使用的过程控制软件组件产品。

利用驱动器的系统连接:

Driver connection

利用OPC的控制系统构成:

OPC connection

Opc的分层结构

OPC Structure

OPC对象中的最上层的对象是OPC服务器。一个OPC服务器里可以设置一个以上的OPC组。OPC服务器经常对应于某种特定的控制设备。例如,某种DCS控制系统,或者某种PLC控制装置。

OPC组是可以进行某种目的数据访问的多个的OPC标签的集合,例如某监视画面里所有需要更新的位号变量。正因为有了OPC组,OPC应用程序就可以以同时需要的数据为一批的进行数据访问,也可以以OPC组为单位启动或停止数据访问。此外OPC组还提供组内任何OPC标签的数值变化时向OPC应用程序通知的数据变化事件

OPC-DA-ALL-List-OPC-(一)-安装Matrikon OPC Simulation Server

安装OPC Server模拟器

可以在此处下载
或者去官网下载

双击下载下来的MatrikonOPCSimulation.EXE安装文件

Collecting Information

接受并Next

Complete Setup

选择Complete Setup并Next

Select the install path

安装路径为c:\Program Files\Matrikon\OPC然后Next

Create quick start icon

默认,Next

Confirm password

默认密码是MatrikonOPC然后选择Next

Ready to start

然后选择Next进行安装

最后安装完成会出现如下图示

Install finished

选择第一个和第二个Checked,其他选项Uncheck 第一个的意思是打开MatrikonOPC Configuration Panel 第二个的意思是打开Quick
Start文档(有兴趣可以看一下,英文的)

本次安装包含三部分

  • Analyzer分析器
  • Explorer浏览器
  • Simulation模拟器

OPC-DA-ALL-List-转载

OPC

框架对比

img

*

1.PLC
和OPC
*

使用的PLC:西门子的S7-300,具体型号如下图

img

使用的OPC server软件:

项目使用KEPServer V6
(427M,中文):百度网盘 ,密码: ykj2

KEPServer的123网盘分享:https://www.123pan.com/s/Lwn8Vv-4qnx
提取码:pTA9

模拟仿真用的 MatrikonOPC
Simulation(50M),百度网盘,密码: mcur

2.连接测试

什么是OPC

OPC是工业控制和生产自动化领域中使用的硬件和软件的接口标准,以便有效地在应用和过程控制设备之间读写数据。O代表OLE(
对象链接和嵌入),P (process过程),C (control控制)。
OPC服务器包括3类对象(Object):服务器对象(Server)、项对象(Item)和组对象(Group)。
OPC标准采用
C/S模式
,OPC服务器负责向OPC客户端不断的提供数据。

img

来源:OPC-(二)-什么是OPC

img

OPC server软件使用

MatrikonOPC: 使用Matrikon OPC Server Simulation

Server和Client

要实现的是Client(Java)和Client(PLC)之间的通信
中间借助OPCServer,Server上设定好地址变量,不同的Client读写这些变量值实现通信。
示意图如下

img

配置Server和Client

OPC和DCOM配置:通信不成功都是配置的问题。。。
配置OPCserver
一般一个电脑(win10)同时安装Server(比如KEPServer)和Client(Java编写的),就配置这个电脑就行
如果是在两个电脑上,那就都需要配置。

3.通信实现

img

Utgard

源码:https://github.com/ctron/org.openscada.utgard

Github上的

最全面的测试(Utgard和JeasyOPC测试):OPC_Client

博客参考

Github上的:资料下载

4.实现过程

1.补充学习了一下OPC的概念:

2.使用MatrikonOPC,了解OPCserver是怎么用的

3.关于OPC UA

  • 支持的OPC UA的西门子PLC至少是s7-1500(2021年10月27日 14:58:00 现在不能确定,看到一个回答,s7-300如果有网口就能和OPCUA通信)
  • 我的s7-300是没法用的,所以就不需要搜集OPC UA的资料了
  • 更正(2021年9月16日11:13:32):最近看OPC UA的资料,发现使用UA是可以的。

4.关于用Java实现

  • C#和C++都不用配置DCOM,直接调用函数
  • 既然是非要用Java,那就别想太方便,需要配置DCOM。

5.关于Utgard

utgard是一个开源的项目,基于j-interop
做的,用于和OPC SERVER通讯。

  • j-interop是纯java封装的用于COM/DCOM通讯的开源项目,这样就不必使用JNI

6.关于JeasyOPC

  • JeasyOPC源码下载
  • 借助一个dll库来实现的和OPCServer的通信,但是JCustomOpc.dll,,太老了,而且支持只32位系统

7.最终实现

  • 当然选Utgard
  • 过程就是把需要的jar包找到,

然后复制编程指导
里的读写代码,读就是启动线程一直对相应地址变量读取数值,写就是对相应地址变量写入数值

8.测试

  • 参考OPC_Client里的例子
  • 关于配置文件的代码直接复制用了
  • 例子实际也用不到,试了试,,因为实际只需要对地址变量读写数值就可以了

9.关于订阅方式数据采集

参考:https://www.hifreud.com/2014/12/27/opc-3-main-feature-in-opc/#订阅方式数据采集

并不需要OPC应用程序向OPC服务器要求,就可以自动接到从OPC服务器送来的变化通知的订阅方式数据采集(Subscription)。服务器按一定的更新周期(UpdateRate)更新OPC服务器的数据缓冲器的数值时,如果发现数值有变化时,就会以数据变化事件(DataChange)通知OPC应用程序。

因为没有使用这种订阅方式,所以当时没试过,后来尝试使用Async20Access,会报错。参考上面文章,说是:还必须设置身份标识,,我没试成功。

img

10.问题:

  • 在虚拟机里用localhost一直报错,要写固定IP才行
  • 配置里的IP是安装OPCServer软件的电脑的IP,如果使用无线连接,请查看无线的IP地址
  • 能不能循环对一个组(group)监控?好像不可以,官方Demo里有两种数据读取方式:1.循环监控item;2.item添加到group,只读取一次
  • 如果Java写的client和安装OPCServer软件是两台电脑:那两个电脑都要配置相同DCOM,包括账号密码都要一样

win10家庭版是否可以?可以,有些麻烦,主要是用户管理部分配置,有人已经验证过可以,我就不试了。建议虚拟机装win10专业版,参考

  • 关于组态王,作为OPCSerever,我怎么尝试都没连接上,,有人能连上,我就不试了。
  • 关于异步:我使用的同步读取数据,,异步读取没试过,别问我异步的问题。
  • group是客户端维护还是服务端维护:服务端可以建自己的分组,但是客户端看到的还是一个个单独的item,group是客户端自己的分组。我是这样理解的。

客户端能不能读到服务端的所有item列表:当然可以,请参考

关于KEPServer的注册表ID

img

11.maven依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!--utgard -->
<dependency>
<groupId>org.openscada.external</groupId>
<artifactId>org.openscada.external.jcifs</artifactId>
<version>1.2.25</version>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.openscada.jinterop</groupId>
<artifactId>org.openscada.jinterop.core</artifactId>
<version>2.1.8</version>
</dependency>
<dependency>
<groupId>org.openscada.jinterop</groupId>
<artifactId>org.openscada.jinterop.deps</artifactId>
<version>1.5.0</version>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.openscada.utgard</groupId>
<artifactId>org.openscada.opc.dcom</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.openscada.utgard</groupId>
<artifactId>org.openscada.opc.lib</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.61</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>