您的位置:首页 > 数据库

OPC批量添加数据并且批量更新到数据库的实现

2018-01-04 16:14 951 查看
记录一下今天刚写完并且运行成功的代码和思路,关于工业协议OPC的数据读写,还有与数据库的交互相关问题,重点是批量,如何批量进行导出导入和更新。

OPC不用讲了,工业协议,做物联网的都知道。。。。= =其实就是个DLL包,没啥东西好说的,用人家的东西就行了。从设备上把数据读出来。

其实上个星期写过一个关于门禁系统的数据交互,大概功能是从某大厦把所有门禁的数据读出来,然后更新到数据库,保留数据,供查询使用,但是上次的思路是:

从OPCExplorer或者OPC Client中连接到OPC服务,然后显示所有的点之后,把所有点位用导出导成一个ini文件


如上图的导出,然后见到是ini文件是这样的:



在完成导出之后,根据ini文件里面的字段,自己手动建立一个mysql数据表,经过相关的整理(行转列),然后形成一张包含了OPC所有item点位信息的数据库表,然后在添加OPCitem的时候,用reader.read()(这个read()的是select from table的时候mysql的read方法,不是OPC的方法,后面提到的read()才是OPC的)来从数据库里添加,然后在用OPC的read去读,这种方法就是不直接从OPC服务端里面拿点位,是先把点位导出之后整理成数据库文件,从数据库文件里把点位添加上去,然后再读点位数据,这样如果点位不匹配的话,read()的时候OPC就会报错,因为人家服务端没有你这个点位,搜不到,也就加不上去,只有你数据库表里的所有点位跟OPC里的实际点位完全重叠,才能用这个方法,如果厂商添加了OPCitem,那就报错。

今天写的新OPC工具,目的就是为了解决OPC点位的问题,因为之前的方法不仅麻烦(从ini中手动把点位放到数据表中有大量重复工作),而且一旦点位变就会报错,还需要重新改数据库。这个OPC工具的思路就是:

全部工作在代码中完成,不需要手动去添加item数据,直接写一个代码把所有item从OPC中读出来,然后放到表中,然后读value再更新到表中,这样每次开启程序,就是先添加一遍所有点位,然后就按照设定的速率一直update数据库,这样就解决了老方法的多个问题。下面开始代码(C#):

OPCServer opcServer = new OPCServer();
OPCBrowser opcBrowser;
opcServer.Connect("ICONICS.SimulatorOPCDA.2");
Console.WriteLine("连接OPC成功!");
opcBrowser = opcServer.CreateBrowser();
opcBrowser.ShowBranches();
opcBrowser.ShowLeafs(true);
OPCGroups opcGroups = opcServer.OPCGroups;
OPCGroup opcGroup = opcGroups.Add("HassanGroup");
OPCItems opcItems = opcGroup.OPCItems;
OPCItem opcItem,opcId;
Object value, qty, time;一开始先进行OPC的初始化,这里不赘述,这里用connect的是每台终端都有的一个供实验用的OPC服务,我本机上的是
ICONICS.SimulatorOPCDA.2
,里面的数据是会变动的,跟别人没关系,只存在你自己的主机上。值得一说的是这用了Browser里面的Branches和Leafs,顾名思义这两个东西,就是枝干和叶子结点,就是遍历所有item的方法。
foreach (object turn in opcBrowser)
{
opcItem = opcItems.AddItem(Convert.ToString(turn), 0);
opcItem.Read((short)OPCDataSource.OPCDevice, out value, out qty, out time);
Console.WriteLine(opcItem.ItemID + "=" + opcItem.Value);
//Console.WriteLine("连接数据库成功!");
string sql = string.Format("INSERT INTO /*建的空表名*/ (OpcService, ItemID, ItemValue)"+
"VALUES "+
"('ICONICS.SimulatorOPCDA.2', '{0}', '{1}');", opcItem.ItemID, opcItem.Value);
MySqlCommand cmd = new MySqlCommand(sql, mycon);
//cmd.ExecuteNonQuery();
/*
MySqlCommand cmd1 = new MySqlCommand(sql1, mycon);
MySqlDataReader reader = cmd1.ExecuteReader();
MySqlDataAdapter sda = new MySqlDataAdapter(sql1,mycon);
DataTable dt = new DataTable();
sda.Fill(dt);
Console.WriteLine(dt);
*/
Console.WriteLine("插入表数据成功!");
}

这部分就是怎么从OPC里找出所有的item,然后insert进一个你建好的空表,我建的这个空表有三个字段,分别是OpcService、ItemID和ItemValue,其中OpcService这个不用动,如果你是对单个opc操作的话,基本用不上这个功能,直接设置成固定的名称就行了,ItemID就是点位的名称,主键,ItemValue是读出来的所有item的值。
while (true)
{
mycon.Open();
string sql = "select * from /*建的空表名*/";
MySqlCommand cmd = new MySqlCommand(sql, mycon);
MySqlDataReader reader = cmd.ExecuteReader();
Console.WriteLine("查询 表数据完毕!");
while (reader.Read())
{
opcId = opcGroup.OPCItems.AddItem(Convert.ToString(reader["ItemID"]), 0);
opcId.Read((short)OPCDataSource.OPCDevice, out value, out qty, out time);
string sql1 = String.Format("update opc_items set ItemValue='{0}'"+
"where OpcService='{1}'and ItemID='{2}'",
value, reader["OpcService"], reader["ItemID"]);
MySqlConnection conUpd = new MySqlConnection(connStr);
conUpd.Open();
MySqlCommand cmdUpd = new MySqlCommand(sql1, conUpd);
cmdUpd.ExecuteNonQuery();
conUpd.Close();
}
mycon.Close();
Thread.Sleep(5000);
}这里是往表里添加完所有的点位之后,再持续从opc上读取所有点位的值,然后每5秒update一次数据表,所以写在死循环里,因为这个东西打开之后就要一直读取--更新,读取--更新,所有放着就行,自动每五秒循环一次。这部分的思路其实就是前面所提到的上周写的代码的思路,先查询一个已经存放了所有item点位的数据表,然后从表里把item添加,再放到OPC里去读值,然后回来更新原来的表,搞定!至于为什么while()里面还要再开开一次数据库,这个在前几天的博客里有一篇,目前我还没想好怎么优化这个点,以后再想办法吧。
完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
usi
4000
ng OPCAutomation;
using MySql.Data;
using MySql.Data.MySqlClient;
using System.Configuration;
using System.Data;

namespace OpcTool
{
class Program
{
static void Main(string[] args)
{
OPCServer opcServer = new OPCServer();
OPCBrowser opcBrowser;
opcServer.Connect("ICONICS.SimulatorOPCDA.2");
Console.WriteLine("连接OPC成功!");
opcBrowser = opcServer.CreateBrowser();
opcBrowser.ShowBranches();
opcBrowser.ShowLeafs(true);
OPCGroups opcGroups = opcServer.OPCGroups;
OPCGroup opcGroup = opcGroups.Add("**********");
OPCItems opcItems = opcGroup.OPCItems;
OPCItem opcItem,opcId;
Object value, qty, time;
string connStr = ConfigurationManager.AppSettings["ConnectionString"];
MySqlConnection mycon = new MySqlConnection(connStr);
mycon.Open();
foreach (object turn in opcBrowser)
{
opcItem = opcItems.AddItem(Convert.ToString(turn), 0);
opcItem.Read((short)OPCDataSource.OPCDevice, out value, out qty, out time);
Console.WriteLine(opcItem.ItemID + "=" + opcItem.Value);
//Console.WriteLine("连接数据库成功!");
string sql = string.Format("INSERT INTO opc_items (OpcService, ItemID, ItemValue)"+
"VALUES "+
"('ICONICS.SimulatorOPCDA.2', '{0}', '{1}');", opcItem.ItemID, opcItem.Value);
MySqlCommand cmd = new MySqlCommand(sql, mycon);
//cmd.ExecuteNonQuery();
/*
MySqlCommand cmd1 = new MySqlCommand(sql1, mycon);
MySqlDataReader reader = cmd1.ExecuteReader();
MySqlDataAdapter sda = new MySqlDataAdapter(sql1,mycon);
DataTable dt = new DataTable();
sda.Fill(dt);
Console.WriteLine(dt);
*/
Console.WriteLine("插入表数据成功!");
}
mycon.Close();
while (true)
{
mycon.Open();
string sql = "select * from opc_items";
MySqlCommand cmd = new MySqlCommand(sql, mycon);
MySqlDataReader reader = cmd.ExecuteReader();
Console.WriteLine("查询opc_item表数据完毕!");
while (reader.Read())
{
opcId = opcGroup.OPCItems.AddItem(Convert.ToString(reader["ItemID"]), 0);
opcId.Read((short)OPCDataSource.OPCDevice, out value, out qty, out time);
string sql1 = String.Format("update opc_items set ItemValue='{0}'"+
"where OpcService='{1}'and ItemID='{2}'",
value, reader["OpcService"], reader["ItemID"]);
MySqlConnection conUpd = new MySqlConnection(connStr);
conUpd.Open();
MySqlCommand cmdUpd = new MySqlCommand(sql1, conUpd);
cmdUpd.ExecuteNonQuery();
conUpd.Close();
}
mycon.Close();
Thread.Sleep(5000);
}

Console.ReadKey();

}
}
}
关于物联网的实际解决问题代码和思路以后还有更新,刚入行不久,每天总结点自己学到东西,希望大家能用到,上面的代码和思路都是自己的理解,如果有不对的地方欢迎指正,共同进步!   = _+ 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐