C# 如何从Proficy Historian查询原始数据?
如何从Proficy Historian/iHistorian检索原始时间序列数据C# 如何从Proficy Historian查询原始数据?,c#,oledb,proficy,historian,C#,Oledb,Proficy,Historian,如何从Proficy Historian/iHistorian检索原始时间序列数据 理想情况下,我会要求提供两个日期之间某个特定标签的数据。我的一位同事将这些数据放在一起: 在web.config中: <add name="HistorianConnectionString" providerName="ihOLEDB.iHistorian.1" connectionString=" Provider=ihOLEDB.iHistorian;
理想情况下,我会要求提供两个日期之间某个特定标签的数据。我的一位同事将这些数据放在一起: 在web.config中:
<add name="HistorianConnectionString"
providerName="ihOLEDB.iHistorian.1"
connectionString="
Provider=ihOLEDB.iHistorian;
User Id=;
Password=;
Data Source=localhost;"
/>
更新: 这很有效,但是我们遇到了一个标签不经常更新的问题。如果标签没有在请求的startDate和endDate的开始或结束附近更新,则趋势看起来很糟糕。更糟糕的是,在请求的窗口期间仍然没有显式的点——我们无法得到任何数据 我通过提出三个问题来解决这个问题:
public DataTable GetProficyData(string tagName, DateTime startDate, DateTime endDate)
{
DataSet ds = new DataSet();
string queryString;
System.Data.OleDb.OleDbDataAdapter adp;
using (System.Data.OleDb.OleDbConnection cn = new System.Data.OleDb.OleDbConnection())
{
cn.ConnectionString = proficyConn.ConnectionString;
cn.Open();
// always get a start value
queryString = string.Format(
"set samplingmode = lab\nselect value as theValue,Timestamp from ihrawdata where tagname = '{0}' AND timestamp between '{1}' and '{2}' order by timestamp",
tagName.Replace("'", "\""), startDate.AddMinutes(-1), startDate);
adp = new System.Data.OleDb.OleDbDataAdapter(queryString, cn);
adp.Fill(ds);
// get the range
queryString = string.Format(
"set samplingmode = rawbytime\nselect value as theValue,Timestamp from ihrawdata where tagname = '{0}' AND timestamp between '{1}' and '{2}' order by timestamp",
tagName.Replace("'", "\""), startDate, endDate);
adp = new System.Data.OleDb.OleDbDataAdapter(queryString, cn);
adp.Fill(ds);
// always get an end value
queryString = string.Format(
"set samplingmode = lab\nselect value as theValue,Timestamp from ihrawdata where tagname = '{0}' AND timestamp between '{1}' and '{2}' order by timestamp",
tagName.Replace("'", "\""), endDate.AddMinutes(-1), endDate);
adp = new System.Data.OleDb.OleDbDataAdapter(queryString, cn);
adp.Fill(ds);
return ds.Tables[0];
}
}
是的,我知道,这些查询应该参数化。Michael——在IP21中,有一个“插值”表,以及“实际”数据点表。Proficy也有吗?有几种不同的采样模式可供您尝试
- 生的
- 插入
- 实验室
- 趋势
- 算计
- 用户API(ihuapi.dll)
- SDK(ihsdk.dll)
- OLEDB(iholedb.dll)
- 客户端访问API(Proficy.Historian.ClientAccess.API)
C:\Program Files\GE Fanuc\Proficy Historian\Docs\iHistorian.chm
,我已经安装了3.5版。请特别注意以下部分
- 使用OLEDB提供程序
- 高级主题|检索
set
SamplingMode = 'Trend',
StartTime = '2010-07-01 00:00:00',
EndTime = '2010-07-02 00:00:00',
IntervalMilliseconds = 1h
select
timestamp,
value,
quality
from
ihRawData
where
tagname = 'YOUR_TAG'
显示使用用户API和SDK的等效方法非常复杂(用户API更复杂),因为它们需要在代码中添加大量管道来进行设置。客户端访问API较新,在后台使用WCF
顺便说一下,OLEDB方法有一些局限性
- 不管文档怎么说,我始终无法让本机查询参数正常工作。例如,如果您想将它与SQL Server Reporting Services一起使用,这是一个很好的例子
- 您不能将样本写入存档或以任何方式更改Historian配置,包括添加/更改标记、写入消息等
- 在某些情况下可能会有点慢
- 它没有规定将多个标记名交叉标记到列中,然后向前传递样本,以便为每个时间戳和标记组合存在一个值。趋势采样模式让您完成了一半,但仍然不会交叉表,也不会实际加载原始样本。然后,用户API和SDK也不能这样做
[DllImport("IHUAPI.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ihuReadRawDataByTime@24")]
public static extern int ihuReadRawDataByTime(int serverhandle, string tagname, ref IHU_TIMESTAMP startTime, ref IHU_TIMESTAMP endTime, ref int noOfSamples, ref IHU_DATA_SAMPLE* dataValues);
...
private int _handle;
public HistorianTypes.ErrorCode ReadRawByTime(string tagName, DateTime startTime, DateTime endTime,
out double[] timeStamps, out double[] values, out IhuComment [] comments)
{
var startTimeStruct = new IhuApi.IHU_TIMESTAMP(); //Custom datetime to epoch extension method
var endTimeStruct = new IhuApi.IHU_TIMESTAMP();
int lRet = 0;
int noOfSamples = 0;
startTimeStruct = DateTimeToTimeStruct(dstZone.ToUniversalTime(startTime));
endTimeStruct = DateTimeToTimeStruct(dstZone.ToUniversalTime(endTime));
IhuApi.IHU_DATA_SAMPLE* dataSample = (IhuApi.IHU_DATA_SAMPLE*)new IntPtr(0);
try {
lRet = IhuApi.ihuReadRawDataByTime
(
_handle, // the handle returned from the connect
tagName, // the single tagname to retrieve
ref startTimeStruct, // start time for query
ref endTimeStruct, // end time for query
ref noOfSamples, // will be set by API
ref dataSample // will be allocated and populated in the user API
);
....
一些注意事项是,iFIX将检查DLL是否在启动时加载,因此您需要执行动态加载/卸载DLL之类的操作,以便其他应用程序不会崩溃。我们通过动态删除/添加注册表项来实现这一点
另一个是,如果您轮询10000个样本,并且其中1个样本已损坏,则会删除所有10000个样本。您需要实现一个坏数据处理程序,该处理程序将从坏数据的任一侧开始,并逐步递增,以获取坏样本任一侧的所有数据
有几个C头文件包含DLL的所有错误代码和函数头。@reallyJim我相信它们是的,不过,在我的情况下,我需要原始数据。几年前,我在PI系统中遇到了同样的问题,所以我确实感受到了你的痛苦!我知道有点晚,但迟做总比不做好。另外,回答关于SO的老问题也是我的风格。我现在没有时间来测试,但这正是我开始时想要的。谢谢你能顺便添加一个关于电子书通常位于何处的注释吗?关于如何以这种方式使用诸如PreviousValue之类的内置historian函数,你有什么想法吗?oledb能做到这一点吗?类似于选择“timestamp,PreviousValue(Time,tagname)from…”的内容@roviuser:我不这么认为,但是发布另一个问题,并清楚地描述您想要什么,我可能会提供帮助。看看我的答案BrianOLE非常慢。使用API具有更好的性能,您还可以编写扩展方法,使您能够完成比OLE开箱即用所支持的更多的工作。对于不获取样本,您可以使用“ReadSamplesByCount”代替时间,这样您至少可以获取1个样本。如果样本数量不多,则该样本可能在您希望显示的时间段之后数年。
[DllImport("IHUAPI.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ihuReadRawDataByTime@24")]
public static extern int ihuReadRawDataByTime(int serverhandle, string tagname, ref IHU_TIMESTAMP startTime, ref IHU_TIMESTAMP endTime, ref int noOfSamples, ref IHU_DATA_SAMPLE* dataValues);
...
private int _handle;
public HistorianTypes.ErrorCode ReadRawByTime(string tagName, DateTime startTime, DateTime endTime,
out double[] timeStamps, out double[] values, out IhuComment [] comments)
{
var startTimeStruct = new IhuApi.IHU_TIMESTAMP(); //Custom datetime to epoch extension method
var endTimeStruct = new IhuApi.IHU_TIMESTAMP();
int lRet = 0;
int noOfSamples = 0;
startTimeStruct = DateTimeToTimeStruct(dstZone.ToUniversalTime(startTime));
endTimeStruct = DateTimeToTimeStruct(dstZone.ToUniversalTime(endTime));
IhuApi.IHU_DATA_SAMPLE* dataSample = (IhuApi.IHU_DATA_SAMPLE*)new IntPtr(0);
try {
lRet = IhuApi.ihuReadRawDataByTime
(
_handle, // the handle returned from the connect
tagName, // the single tagname to retrieve
ref startTimeStruct, // start time for query
ref endTimeStruct, // end time for query
ref noOfSamples, // will be set by API
ref dataSample // will be allocated and populated in the user API
);
....