前端开发入门到精通的在线学习网站

网站首页 > 资源文章 正文

C#通过API接口读取KingSCADA实时库数据

qiguaw 2024-12-10 19:25:59 资源文章 115 ℃ 0 评论

哈喽,你好啊,我是雷工!

在实际项目中数据采集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实时数据库读取数据的实现过程,关于文档中其他函数的相关功能,后续有时间继续学习验证。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表