网站首页 > 资源文章 正文
哈喽,你好啊,我是雷工!
在实际项目中数据采集SCADA系统的数据时比较多的是通过OPC接口,但OPC常常是需要另外按点位收费的,
随着与信息化平台交互的频繁,常常需要用到通过API访问实时数据。
在KingSCADA中为了能够让用户通过接口方式访问SCADA运行数据并执行相关操作,KingSCADA运行态开放了运行系统实时库处理接口,第三方用户可以通过kxTVAPI模块与KingSCADA运行系统建立通讯,获取相关数据。
这里记录学习《KingSCADA C# 实时库API详细设计手册》以及C#的Demo时的相关笔记。
01 效果演示
示例演示C#通过API接口读取KingSCADA实时数据库的内存变量数值。
02 VS实现步骤
2.1、创建项目
用VS创建一个新项目,命名为KingSCADA_API;
2.2、添加空件
①GroupBox控件
在窗体中添加两个GroupBox控件分别用来显示服务器信息和变量管理两个区域。
②Label控件
添加几个标签设置对应的输入框标签说明;
③TextBox控件
添加几个TextBox控件用于输入服务器IP,端口,用户名,密码,设置变量值,订阅范围,变量ID等输入框。
④Button控件
添加几个Button控件用来做连接,断开,获取所有变量,获取变量值等按钮。
⑤TreeView控件
添加一个TreeView控件,用来显示读取到的变量信息及数据值信息。
2.3、添加引用
在解决方案-引用添加引用,引入所需的dll文件。
2.4、编写代码
①准备
private Connection m_Con = null; //客户端连接服务器类
private ArrayList TagList;
string m_strServerPort; //服务器端口
string m_strUserName; //用户名:KVAdministrator
string m_strPassword; //用户密码:F93E1D6FA158C4D2153BC7F4B36CCD86
private static Dictionary<int, string> m_mapTagIDItemIndex = new Dictionary<int, string>();
private static Dictionary<int, ListViewItem> m_mapListIndex = new Dictionary<int, ListViewItem>();
KXTVClientInfo ClientInfo = new KXTVClientInfo();
②构造函数
public Form1()
{
InitializeComponent();
if (m_Con == null)
{
try
{
m_Con = new Connection();
}
catch (Exception ex)
{
m_Con = null;
MessageBox.Show("Can not create KSCADAServer object with exception " + ex.ToString());
return;
}
}
TagList = new ArrayList();
}
③Loda
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
listView1.Visible = true;
tvTagInfo.Visible = false;
cbbAlarmType.SelectedIndex = 0;
}
④连接服务器
/// <summary>
/// 连接服务器
/// </summary>
private void btConnect_Click(object sender, EventArgs e)
{
if (m_Con == null)
{
try
{
m_Con = new Connection();
}
catch (System.Exception ex)
{
m_Con = null;
MessageBox.Show("Can not create KSCADAServer object with exception " + ex.ToString());
return;
}
}
m_Con.Initialize(); //连接前要使用Initialize函数初始化连接句柄
//初始化连接参数
ConnectionOption option = new ConnectionOption();
option.ServerName = tbServer.Text; //服务器名
option.ServerPort = (System.String)tbPort.Text; //服务器端口
option.ConnectionFlags = 0x00000002; //协议、安全等选项固定2
option.NetUserFlag = 0x00; //网络用户标记固定0
option.UserName = tbUser.Text;//用户名
option.Password = tbPassword.Text; //密码
option.NetworkTimeout = 0x00; //网络超时0
option.Reserved1 = 0x00000001;//保留字节固定为1
//连接服务器
try
{
m_Con.Connect(option, ClientInfo); //调用连接服务器函数
}
catch (Exception ex)
{
MessageBox.Show("Can not connect to server(" + tbServer.Text + "with excepiton " + ex.ToString());
return;
}
try
{
m_Con.OnBlobTagFieldChange += new Connection.BlobTagFieldChangeHandler(OnBlobTagFieldChange); //注册回调函数
}
catch (Exception ex)
{
MessageBox.Show("Failed to register OnTagFieldChange with excepiton " + ex.ToString());
return;
}
MessageBox.Show("连接成功!");
}
⑤断开连接服务器
/// <summary>
/// 断开连接服务器
/// </summary>
private void btDiscon_Click(object sender, EventArgs e)
{
if (m_Con == null)
{
return;
}
if (m_Con.IsConnected)
{
m_Con.Disconnect();
m_Con = null;
}
MessageBox.Show("断开连接成功!");
}
⑥获取变量信息
/// <summary>
/// 获得变量信息(变量名和变量ID)
/// </summary>
private void btnGetTagList_Click(object sender, EventArgs e)
{
listView1.Visible = true;
tvTagInfo.Visible = false;
if (m_Con == null)
{
return;
}
int ItemNum = m_mapListIndex.Count;
if (ItemNum != 0)
{
foreach (KeyValuePair<int, ListViewItem> kv in m_mapListIndex)
{
this.listView1.Items.Remove(kv.Value);
}
m_mapListIndex.Clear();
}
int m_mapTagIDItemIndexNum = m_mapTagIDItemIndex.Count;
if (m_mapTagIDItemIndexNum != 0)
{
m_mapTagIDItemIndex.Clear();
}
List<string> TagNameArray = new List<string>();
List<int> TagIDArray = new List<int>();
List<int> ErrorCodeArray = new List<int>();
int ErrorCode = m_Con.TagGetAllTagName(out TagNameArray); //获得工程中的所有变量名
if (ErrorCode != 0)
{
MessageBox.Show("Get Tag List Failed");
return;
}
ErrorCode = m_Con.TagGetTagIDbyName(TagNameArray, out TagIDArray, out ErrorCodeArray); //由变量名获得变量ID
if (ErrorCode != 0)
{
MessageBox.Show("Get Tag ID Failed");
return;
}
//把变量名和变量ID添加到listView1中
this.listView1.Items.Clear();
int SizeOfArray = TagIDArray.Count;
this.listView1.BeginUpdate();
for (int i = 0; i < SizeOfArray; i++)
{
ListViewItem liv = new ListViewItem();
liv.Text = TagNameArray[i];
string temp;
string temp1 = " ";
temp = TagIDArray[i].ToString("D");
liv.SubItems.Add(temp);
liv.SubItems.Add(temp1);
liv.Focused = true;
this.listView1.Items.Add(liv);
m_mapTagIDItemIndex.Add(TagIDArray[i], TagNameArray[i]);
m_mapListIndex.Add(TagIDArray[i], this.listView1.Items[i]);
}
this.listView1.EndUpdate();
//MessageBox.Show("Get Tag List success");//modify by zhichao.yao
}
⑦获取变量值
/// <summary>
/// 获得选中变量的变量值
/// </summary>
private void btnGetTagValue_Click(object sender, EventArgs e)
{
if (m_Con == null)
{
return;
}
ListViewItem pos = this.listView1.TopItem;
if (pos == null)
{
MessageBox.Show("No items were selected!");
}
else
{
int TagNum = this.listView1.CheckedItems.Count;
int[] TagIDs = new int[TagNum];
List<int> TagIDArray = new List<int>();
for (int i = 0; i < this.listView1.CheckedItems.Count; i++)
{
int.TryParse(this.listView1.CheckedItems[i].SubItems[1].Text, out TagIDs[i]);
}
TagIDArray.AddRange(TagIDs); //获得选中变量的变量ID
List<BrkTagData> ValueArray = new List<BrkTagData>();
List<int> ErrorCodeArray = new List<int>();
int ErrorCode = m_Con.TagGetTagValues(TagIDArray, out ValueArray, out ErrorCodeArray); //由变量(ID)TagIDArray获得变量值ValueArray
if (ErrorCode != 0)
{
MessageBox.Show("Get Tag Data Failed");
return;
}
//从ValueArray列表中解析出变量值
// add by zhichao.yao 12/8/2017
for (int i = 0; i < TagNum; i++)
{
string strTagValue;
byte TagDataType = ValueArray[i].FieldValue.Type; //变量值类型,由变量值类型解析出变量值
switch (TagDataType)
{
case VALUE_TYPE_BOOL.value: //bool型
if (ValueArray[i].FieldValue.bitVal != null)
{
if (ValueArray[i].FieldValue.bitVal == Convert.ToBoolean(1))
{
strTagValue = "TRUE";
}
else
{
strTagValue = "FALSE";
}
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_I1.value: //一字节整数
if (ValueArray[i].FieldValue.i1Val != null)
{
strTagValue = ValueArray[i].FieldValue.i1Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_UI1.value: //一字节无符号整数
if (ValueArray[i].FieldValue.ui1Val != null)
{
strTagValue = ValueArray[i].FieldValue.ui1Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_I2.value: //两字节整数
if (ValueArray[i].FieldValue.i2Val != null)
{
strTagValue = ValueArray[i].FieldValue.i2Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_UI2.value: //两字节无符号整数
if (ValueArray[i].FieldValue.ui2Val != null)
{
strTagValue = ValueArray[i].FieldValue.ui2Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_I4.value: //四字节整数
if (ValueArray[i].FieldValue.i4Val != null)
{
strTagValue = ValueArray[i].FieldValue.i4Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_UI4.value: //四字节无符号整数
if (ValueArray[i].FieldValue.ui4Val != null)
{
strTagValue = ValueArray[i].FieldValue.ui4Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_I8.value: //八字节整数
if (ValueArray[i].FieldValue.i8Val != null)
{
strTagValue = ValueArray[i].FieldValue.i8Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_UI8.value: //八字节无符号整数
if (ValueArray[i].FieldValue.ui8Val != null)
{
strTagValue = ValueArray[i].FieldValue.ui8Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_R4.value: //单精度浮点数
if (ValueArray[i].FieldValue.r4Val != null)
{
strTagValue = ValueArray[i].FieldValue.r4Val.ToString("F");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_R8.value: //双精度浮点数
if (ValueArray[i].FieldValue.r8Val != null)
{
strTagValue = ValueArray[i].FieldValue.r8Val.ToString();
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_STR.value: //ASCII字符串
if (ValueArray[i].FieldValue.strVal != null)
{
strTagValue = ValueArray[i].FieldValue.strVal.ToString();
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_WSTR.value: //Unicode字符串
if (ValueArray[i].FieldValue.wstrVal != null)
{
strTagValue = ValueArray[i].FieldValue.wstrVal.ToString();
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_FILETIME.value: //文件时间
if (ValueArray[i].FieldValue.ftVal != null)
{
strTagValue = ValueArray[i].FieldValue.ftVal.ToString();
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_TIMESTAMP.value: //时间戳
if (ValueArray[i].FieldValue.tsVal != null)
{
strTagValue = ValueArray[i].FieldValue.tsVal.ToString();
}
else
{
strTagValue = "";
}
break;
default:
Debug.Assert(false);
return;
}
// add end by zhichao.yao 12/8/2017
if (m_mapTagIDItemIndex.ContainsKey(TagIDs[i]))
{
this.listView1.CheckedItems[i].SubItems[2].Text = strTagValue;
}
}
}
MessageBox.Show("获取变量值成功!");
}
⑧回调函数
/// <summary>
/// 变量域数据变化回调函数具体实现
/// </summary>
public int OnBlobTagFieldChange(Sorba.BlobStream FieldValueBlob, Sorba.Context context)
{
listView1.Visible = true;
tvTagInfo.Visible = false;
List<BrkTagPubData> FieldValueArray = new List<BrkTagPubData>();
int Count = 0;
m_Con.KXTVBlobtoKXTVTAGDATAArray(FieldValueBlob, FieldValueArray, ref Count); //把BlobSteam流数据转化为变量发布数据列表
if (Count <= 0)
{
return KXTVAPIErrorCode.ERR_INVALID_DATA;
}
else
{
for (int Index = 0; Index < Count; Index++)
{
//FieldValueArray[Index].FieldID == KXTVTagFieldID.KXTVFIELD_Value 的BrkTagPubData数据对应的是变量值域发布数据;
// add by zhichao.yao 12/8/2017
if (FieldValueArray[Index].FieldID == KXTVFIELD_Value.value)
{
int TagID = FieldValueArray[Index].TagID;
string strTagValue;
byte TagDataType = FieldValueArray[Index].FieldValue.Type;
switch (TagDataType)
{
case VALUE_TYPE_BOOL.value:
if (FieldValueArray[Index].FieldValue.bitVal != null)
{
if (FieldValueArray[Index].FieldValue.bitVal == Convert.ToBoolean(1))
{
strTagValue = "TRUE";
}
else
{
strTagValue = "FALSE";
}
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_I1.value:
if (FieldValueArray[Index].FieldValue.i1Val != null)
{
strTagValue = FieldValueArray[Index].FieldValue.i1Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_UI1.value:
if (FieldValueArray[Index].FieldValue.ui1Val != null)
{
strTagValue = FieldValueArray[Index].FieldValue.ui1Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_I2.value:
if (FieldValueArray[Index].FieldValue.i2Val != null)
{
strTagValue = FieldValueArray[Index].FieldValue.i2Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_UI2.value:
if (FieldValueArray[Index].FieldValue.ui2Val != null)
{
strTagValue = FieldValueArray[Index].FieldValue.ui2Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_I4.value:
if (FieldValueArray[Index].FieldValue.i4Val != null)
{
strTagValue = FieldValueArray[Index].FieldValue.i4Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_UI4.value:
if (FieldValueArray[Index].FieldValue.ui4Val != null)
{
strTagValue = FieldValueArray[Index].FieldValue.ui4Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_I8.value:
if (FieldValueArray[Index].FieldValue.i8Val != null)
{
strTagValue = FieldValueArray[Index].FieldValue.i8Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_UI8.value:
if (FieldValueArray[Index].FieldValue.ui8Val != null)
{
strTagValue = FieldValueArray[Index].FieldValue.ui8Val.ToString("D");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_R4.value:
if (FieldValueArray[Index].FieldValue.r4Val != null)
{
strTagValue = FieldValueArray[Index].FieldValue.r4Val.ToString("F");
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_R8.value:
if (FieldValueArray[Index].FieldValue.r8Val != null)
{
strTagValue = FieldValueArray[Index].FieldValue.r8Val.ToString();
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_STR.value:
if (FieldValueArray[Index].FieldValue.strVal != null)
{
strTagValue = FieldValueArray[Index].FieldValue.strVal.ToString();
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_WSTR.value:
if (FieldValueArray[Index].FieldValue.wstrVal != null)
{
strTagValue = FieldValueArray[Index].FieldValue.wstrVal.ToString();
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_FILETIME.value:
if (FieldValueArray[Index].FieldValue.ftVal != null)
{
strTagValue = FieldValueArray[Index].FieldValue.ftVal.ToString();
}
else
{
strTagValue = "";
}
break;
case VALUE_TYPE_TIMESTAMP.value:
if (FieldValueArray[Index].FieldValue.tsVal != null)
{
strTagValue = FieldValueArray[Index].FieldValue.tsVal.ToString();
}
else
{
strTagValue = "";
}
break;
default:
Debug.Assert(false);
return KXTVAPIErrorCode.ERR_INVALID_DATA;
}
// add end by zhichao.yao 12/8/2017
if (m_mapTagIDItemIndex.ContainsKey(TagID))
{
m_mapListIndex[TagID].SubItems[2].Text = strTagValue;
}
}
}
return KXTVAPIErrorCode.ERR_OK;
}
}
03 KingSCADA实现
3.1、创建变量
在建点-数据词典处创建几个内存变量用于测试;
3.2、设置属性
创建测试点位时在属性页要注意勾选【允许其他应用访问】,不然会导致异常。
3.3、创建界面
创建一个界面,连接测试点位,运行状态修改点位值,观察VS测试程序读取数值是否与之一致。
04 运行测试
将KingSCADA测试程序与VS测试程序分别运行起来,操作按钮,看是否能够正常连接KingSCADA并正确显示数据。
05 后记
以上为C#通过API接口连接KingSCADA实时数据库读取数据的实现过程,关于文档中其他函数的相关功能,后续有时间继续学习验证。
猜你喜欢
- 2024-12-10 一个监控PLC的Android应用的开发过程-2
- 2024-12-10 android学习,listview
- 2024-12-10 ListView和RecyclerView的区别
- 2024-12-10 轻松学会:滑动组件ListView和GridView的使用
- 2024-12-10 常见面试题之ListView的复用及如何优化
- 2024-12-10 那些技术—Listview的性能提高篇
- 2024-12-10 Excel VBA,通过ListView查阅工作表数据、外部数据源数据(1/5)
- 2024-12-10 Android中ListView的使用方法
- 2024-12-10 PC SDK二次开发:基于C#语言编写的ABB机器人控制器扫描程序
- 2024-12-10 Excel vba 如何导入导出工作表,数据管理方法介绍
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- 电脑显示器花屏 (79)
- 403 forbidden (65)
- linux怎么查看系统版本 (54)
- 补码运算 (63)
- 缓存服务器 (61)
- 定时重启 (59)
- plsql developer (73)
- 对话框打开时命令无法执行 (61)
- excel数据透视表 (72)
- oracle认证 (56)
- 网页不能复制 (84)
- photoshop外挂滤镜 (58)
- 网页无法复制粘贴 (55)
- vmware workstation 7 1 3 (78)
- jdk 64位下载 (65)
- phpstudy 2013 (66)
- 卡通形象生成 (55)
- psd模板免费下载 (67)
- shift (58)
- localhost打不开 (58)
- 检测代理服务器设置 (55)
- frequency (66)
- indesign教程 (55)
- 运行命令大全 (61)
- ping exe (64)
本文暂时没有评论,来添加一个吧(●'◡'●)