Skip navigation
All Places > All Things PI - Ask, Discuss, Connect > PI Square中文论坛 > Blog
stang

PI SDK 开发基础篇

Posted by stang Aug 19, 2016

: 为了更好的利用站内资源营造一个更好的中文开发资源空间,本文是转发修正帖,原作者为OSIsoft技术工程师王曦(Xi Wang),原帖地址:PI SDK 基础篇

 

本帖旨在介绍使用PI SDK进行开发之初的基本功能。如服务器连接,搜索PI点,读取快照值,读取归档值等。基本程序提供C++C#两种语言的编写方法。这两种语言都需调用PI SDK函数包中一些基本函数库:PISDKPISDKCommonPITimeServer。

说明:本帖中的程序段仅适用于功能性的介绍,不宜直接复制使用,因为程序段之中没有加入任何错误警告功能或抛出例外

说明:PI SDK 是过时的技术

 

 

1. 连PI接服务器

 

C++ 程序

 

#include "stdafx.h"
#include <iostream>
#include <string>
#include "ATLComTime.h"   //for COleDateTime

#import "C:\Program Files\PIPC\PISDK\PISDKCommon.dll" no_namespace
#import "C:\Program Files\PIPC\PISDK\PITimeServer.dll" no_namespace
#import "C:\Program Files\PIPC\PISDK\PISDK.dll" rename("Connected", "PISDKConnected") no_namespace

IPISDKPtr       spPISDK = NULL; //定义新的PISDK指针类
ServerPtr       spServer = NULL; //定义新的PI服务器指针类

// 定义PI服务器连接函数 --- PIServerConnet()

static ServerPtr PIServerConnect(_bstr_t servername)
{
    ::CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); //初始化COM
    spPISDK.CreateInstance(__uuidof(PISDK)); //在COM中初始化新的PISDK指针类
    spServer = spPISDK->GetServers()->GetItem(servername);  //通过传递进来的服务器名来连接该服务器。   注:需要使用_bstr_t字符串类型参数
    return spServer; //返回PI服务器指针
}

int _tmain(int argc, _TCHAR* argv[])
{
    _bstr_t servername = "XWANG-KQ8HT8KU8"; //定义服务器名。
    spServer = PIServerConnect(servername); //接收返回的的PI服务器指针类型
    return 0;
}

 

C#程序

 

using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using PISDK;
 using PISDKCommon;
 using PITimeServer;

namespace DemPISDK
 {
    class Program
    {
        static void Main(string[] args)
        {
            Server server = ConnectToServer("servername");  //获取返回的PI服务器类型
        }

         private static Server ConnectToServer(string servername)
         {
             PISDK.PISDK pisdk = new PISDK.PISDK();            //定义新的PISDK类
             Server server = null; //定义新的PI服务器类
             server = pisdk.Servers[servername]; //获取服务器名
            server.Open(); //连接PI数据库
             return server;      
         }
    }
}

 

以下所有的功能都将在连接上PI 服务器之后才能实现,因此,将省略PI服务器连接这一部分

 

2. 创建PI点

 

创建单点

 

C++ 程序

 

static PIPointPtr CreatePIPoint (ServerPtr spServer)
 {
    _NamedValuesPtr nvAttribues = NULL; // 定义PI点的属性
    return spServer->PIPoints->Add("test1","classic",PointTypeConstants::pttypFloat32,nvAttribues); // 创建PI点
 }

 

C# 程序

 

private static PIPoint CreatePIPoint ( Server server)
{
    NamedValues nvAttributes nvAttributes = new NamedValues(); // 定义PI点的属性
    return server.PIPoints.Add("test1", "classic", PointTypeConstants.pttypeFloat32, nvAttributes); // 创建PI点
}

创建多点

 

C++程序

 

static void PointsCreation (ServerPtr spServer)
{
    IPIPoints2Ptr spipipoints2 = (IPIPoints2Ptr)spServer->PIPoints; // 创建 IPIPoints2指针,并让其指向传入ServerPtr指针的那片区域

     _variant_t description = "test"; // 创建“描述”属性的variant类型
     _variant_t engunits = "m"; // 创建“工程单位”属性的variant类型
     _variant_t classtype = "classic"; // 创建“点的种类”属性的variant类型
     _variant_t pt = PointTypeConstants::pttypFloat32; // 创建“点的数据类型”属性的variant类型
 
     _NamedValuesPtr nvAttributes; // 创建一个指向点属性的指针
    nvAttributes.CreateInstance(__uuidof(NamedValues)); // 为这个指针创建一片空间,用于存储点的属性
    nvAttributes->Add("descriptor", &description); // 增加“描述”属性
    nvAttributes->Add("engunits", &engunits);
    nvAttributes->Add("ptclassName", &classtype);
    nvAttributes->Add("pointType", &pt);
 
     _variant_t var_nvAttributes; // 创建一个variant类型的指针
    VariantInit(&var_nvAttributes); // 初始化对于上面指针的二级指针为VT_EMPTY
     V_VT (&var_nvAttributes) = VT_DISPATCH; // 将这个二级指针转变为VT_DISPATCH类型
     V_DISPATCH(&var_nvAttributes) = nvAttributes; // 将这个二级指针指向点属相的指针
 
     _NamedValuesPtr nvPoints; // 创建一个定义PI点表的指针
    nvPoints.CreateInstance(__uuidof(NamedValues)); // 为该指针定义一片空间
     nvPoints->Add("test2", &var_nvAttributes); // 加入点名,及其属性
     nvPoints->Add("test3", &var_nvAttributes);
 
     _PIErrorsPtr Errors; // 创建一个PIError的指针
     Errors.CreateInstance(__uuidof(PIErrors)); // 为该指针定义一片空间
     _PIErrors **ErrorsPtr = &Errors; // 为该指针定义一个二级指针
 
     _PointListPtr PointList; // 创建一个PointList的指针
    PointList.CreateInstance(__uuidof(PointList)); // 为该指针定义一片空间
     _PointList **PointListPtr = &PointList; // 为该指针定义一个二级指针 
    spipipoints2->AddTags(nvPoints,ErrorsPtr,PointListPtr,NULL); // 使用之前定义的IPIPoints2类型的指针加入点表
}

这个程序相对较复杂,主要使用了C++中的标准DISPATCH接口类型

 

C#程序

 

private static PointList CreatePIPoints(Server server)
 {
    NamedValues nvTags = new NamedValues();
 
     NamedValues nvAttributes = new NamedValues();
 
    nvAttributes.Add("descriptor", "Test Description");
    nvAttributes.Add("ptclassname", "classic");
    nvAttributes.Add("pointsource", "L");
    nvAttributes.Add("pointtype", PointTypeConstants.pttypFloat32);
 
    nvTags.Add("testAddTag", nvAttributes);
    nvTags.Add("testAddTags001", nvAttributes);
    nvTags.Add("testAddTags002", nvAttributes);
    nvTags.Add("testAddTags003", nvAttributes);
 
     PIErrors errs = new PIErrors();
     PointList ptlist = new PointList();
     IPIPoints2 ipipoints2 = (IPIPoints2)server.PIPoints;
    ipipoints2.AddTags(nvTags, out errs, out ptlist);
 
     return ptlist;
 }

相比起C++程序,C#程序更为通俗

 

这两段程序值得注意的是,在点的创建过程中,点属性中的pointclass和pointtype是必须创建并设定的,如果没有,所有的点是不能被创建的

 

3. 搜点

 

C++程序

 

static PIPointPtr GetPIPointsByName(ServerPtr server, _bstr_t tagname)
 {
    return server->PIPoints->GetItem(tagname); // 返回一个PIPoint类型的指针
}

 

C#程序:

 

private static PIPoint GetPIPointByName(Server server, String tagname)
 {
    return server.PIPoints[tagname]; // 返回一个PIPoint类型的指针
 }

 

按条件搜点表


C++程序

 

static _PointListPtr SearchPIPoints(ServerPtr server, _bstr_t condition)
 {
    return server->GetPoints(condition, NULL);            //返回PointList指针类
 }

 

C#程序

 

private static PointList SearchPIPoints(Server server, String condition)
 {
    return server.GetPoints(condition);                   
 }

4. 编辑点

 

按编辑单点的特定属性

 

C++程序

 

static void TagEdit (ServerPtr spServer)
{
    _bstr_t tagname = "test2"; // 给出点名
     PIPointPtr spPoint; // 创建PIPointPtr类指针接收点的一切信息
     spPoint = spServer->PIPoints->GetItem(tagname); // 将点名传给spPoint指针
 
     _bstr_t tag_description = "descriptor"; // 定义需要调整的属性
     PointAttributePtr pa_attribute = spPoint->PointAttributes->GetItem(tag_description);   // 将属性指针指向之前定义的需要调整的属性
     spPoint->PointAttributes->ReadOnly = VARIANT_FALSE; // 将只读属性关闭
     pa_attribute->Value = "test for tag edit"; // 更改需要调整属性的值
     spPoint->PointAttributes->ReadOnly = VARIANT_TRUE; // 将只读属性打开
}

C# 程序

 

private static void EditPIPoint(PIPoint pt)
 {
     Server server = new Server;

     server.PIPoints[test2];

     PointAttribute attr = pt.PointAttributes["descriptor"];
    pt.PointAttributes.ReadOnly = false;
     attr.Value = "new description";
    pt.PointAttributes.ReadOnly = true;
 }

编辑一组点

 

C++程序

 

static void EditPoints (ServerPtr, spServer)
{
    _bstr_t condition = "tag='test*'"; // 给定编辑点的搜索条件
     _PointListPtr ptlist; // 创建一个点表指针
     ptlist = spServer->GetPoints(condition,NULL); // 将按条件搜索出的点存储到点表里
     _NamedValuesPtr nvTags; // 创建一个接收点表信息的指针
    nvTags.CreateInstance(__uuidof(NamedValues)); // 分配内存区域
     _NamedValuesPtr nvAttributes; // 创建一个接收点属性的指针
     nvAttributes.CreateInstance(__uuidof(NamedValues)); // 分配内存区域
     _variant_t descriptions = "test for points edit"; // 将需要更改的信息创建成 _variant_t类型
 
     nvAttributes->Add("descriptor", &descriptions); // 将修改的信息存储至之前创建的接收点属性的指针指向的区域
     _variant_t var_attributes; // 创建一个新的_variant_t类型参数
    VariantInit(&var_attributes); // 初始化_variant_t类型参数 
     V_VT(&var_attributes) = VT_DISPATCH; // 将_variant_t类型参数转变成VT_DISPATCH接口类型参数
     V_DISPATCH(&var_attributes) = nvAttributes; // 将VT_DISPATCH接口类型参数等同于之前存储属性的那片区域
 
     for (int i = 1; i <= ptlist->Count; i++) // 这个FOR循环是为将符合条件的所有的点的点名和属性加入到指向点表信息指针指向的内存区域
     {
         _variant_t vi = i;
         PIPointPtr spTag = ptlist->Item[&vi];
         nvTags->Add(spTag->Name, &var_attributes);
     }
 
     _PIErrorsPtr Errors; // 需要实例化一个PIErrors
     Errors.CreateInstance(__uuidof(PIErrors));
     _PIErrors **ErrorsPtr = &Errors; // 用一个二级指针指向这个实例
 
     IPIPoints2Ptr ipi_points2 = (IPIPoints2Ptr)spServer->PIPoints;  // 使用 IPIPoints2Ptr类型指针指向点表
     ipi_points2->EditTags(nvTags, &Errors, NULL); // 使用上述指针类里的编辑点的函数,将点表中所有的点的信息做更改
}

 

C#程序

 

private static void EditPIPoints(Server server, PointList ptlist)
 {
     NamedValues nvTags = new NamedValues();
     NamedValues nvAttributes = new NamedValues();
 
    nvAttributes.Add("descriptor", "edited description");

    foreach(PIPoint pt in ptlist)
     {
        nvTags.Add(pt.Name, nvAttributes);
     }
 
     PIErrors errs = new PIErrors();
 
     IPIPoints2 ipipoints2 = (IPIPoints2)server.PIPoints;
     ipipoints2.EditTags(nvTags, out errs);
 
     foreach (PIError err in errs)
     {
        Console.WriteLine(err.Description);
     }
 }

在C#程序中,没有写点表如何获得的,只是直接调用之前按条件搜索点表的程序,原理是一样的

 

以下内容为如何从PI服务器中取出点/点表的一些值。这些程序是基于点的操作,因此,将不再重复如何搜索点/点表。如果使用下述函数,请首先参看本帖第三部分---搜索点/点表

 

5. 取快照值

 

取单快照值

 

C++程序

 

static _PIValuePtr GetSnapshot(PIPointPtr pt)         // 传入点信息
 {
    return (_PIValuePtr)pt->Data->GetSnapshot();
 }

 

C#程序

 

private static PIValue GetSnapshot(PIPoint pt)
 {
    return pt.Data.Snapshot;
 }

取点表快照

 

C++程序

 

static PointValuesPtr GetSnapshot(_PointListPtr sppointlist) // 传入点表信息
 {
    PointValuesPtr ptValues = sppointlist->Data->GetSnapshot(NULL);
    return ptValues;
 }

 

C#程序

 

 

private static PointValues GetSnapshot(PointList ptlist)
 {
    NamedValues nvErrs = new NamedValues();
    PointValues ptvalues = ptlist.Data.get_Snapshot(out nvErrs);
 }

 

6. 取某时刻历史数据

单点某时数据

 

C++程序

 

static _PIValuePtr GetArchive(PIPointPtr pt)
 {
    _bstr_t time = "*-2h"; // 以下内容为将字符串时间转化为_variant_t 类型的时间
    _PITimeFormatPtr sptime;
    sptime.CreateInstance (__uuidof(PITimeFormat));
    sptime->InputString = time;
    _variant_t vtStart;
    VariantInit (&vtStart);
    V_VT (&vtStart) = VT_DISPATCH;
    V_DISPATCH(&vtStart) = sptime; 
    return (_PIValuePtr)pt->Data->ArcValue(vtStart, RetrievalTypeConstants::rtAuto, NULL);      // 将PI点指针类型的指针转换成PI Value类型的指针,并执行函数。
 }

C#程序

 

private static PIValue GetArchive(PIPoint pt)
 { 
    PITimeFormat time = new PITimeFormat();
    time.InputString = "*-2h";
    return pt.Data.ArcValue(time, RetrievalTypeConstants.rtAuto);
 }

这边文档翻译自pisquare相同名字的博客,想要看到更多信息可以参考pisquare上的相关内容。Coresight Squared

这个系列目前包括以下三个内容:

  1. windows Server核心版安装和配置<<您现在在这里
  2. PI Coresight安装
  3. Kerberos配置

 

Server核心版 - 安装和配置

 

Server核心版是安装Windows Server2012 R2时的默认设置:

 

第一次登陆您的Server Core机器 - 在欢迎界面只有一个命令行!

用服务器配置工具 (sconfig) 来重命名机器, 配置 DNS 设置, 加入一个Windows 域, 启用 Windows 更新, 启用Remote Management远程管理等等.

要使用这个工具, 在命令行中执行sconfig。使用sconfig很容易, 不过我建议按照如下方式进行:

 

1. 配置DNS设置

选择 Option 8 > select index of the Ethernet card(选择网卡的id) > 选择 Option 2 (Set DNS Servers)(选择DNS Server) > set preferred (and alternate) DNS server(s) (选择备用DNS Server)

2. 将电脑添加到Windows域当中

选择Option 1 > 选择 D 作为域 > 输入域名 > 确认并完成

3. 重命名电脑 - 这个选项在电脑加入Windows 域之后会自动弹出.

4. 重启 - 在sconfig中使用Option 13.

 

5. 启用Windows更新

选择 Option 5 > 选择 A 作为自动

6. 配置入站防火墙设置

使用Powershell, 启用文件和防火墙共享 进站规则以便将PI Coresight安装文件拷贝到这台机器上。这个规则在安装完Coresight之后可以被禁用

 

Enable-NetFirewallRule -DisplayGroup "File And Printer Sharing"  

 

为了更好的远程管理,启用如下防火墙规则

Enable-NetFirewallRule -DisplayGroup "Remote Event Log Management"  
Enable-NetFirewallRule -DisplayGroup "Remote Service Management"  
Enable-NetFirewallRule -DisplayGroup "Remote Volume Management"  

7. 激活所有PI Coresight需要的角色和功能

 

使用 CSRolesFeatures.ps1 (这个post的附件或者可以在 pastebin找到) 可以迅速完成这项工作。使用robocopy将此文件拷贝到核心版Server的机器上(命令行中有此工具)或者使用Windows Explorer的复制和粘贴功能。

 

比如,从本地D:\Downloads文件夹下将 CSRolesFeatures.ps1 拷贝到CORESQUAREDC:\Temp 使用 robocopy:

 

robocopy "D:\Downloads" "\\CORESQUARED\C$\Temp" CSRolesFeatures.ps1

 

 

在核心版服务器上打开PowerShell对话框 (在命令行中执行 powershell 命令) 并允许在当前session执行脚本,并运行此脚本。

Set-Executionpolicy RemoteSigned -Scope Process  
.\CSRolesFeatures.ps1 -Mode Install -IsCore $true  

 

当此脚本运行完成后,在命令行中用shutdown /r /t 0命令重启机器

 

Server 核心版 – 启用远程管理

 

使用sconfig > 选择 Option 4 > 选择 option 1 来启用远程管理。

 

使用远程管理来添加/删除Windows功能, 维护本地用户和组,查看事件日志等

 

remote IIS Management需要Web Server Management Service。用 PowerShell来 安装此服务并且设置相关的注册表配置:

Install-WindowsFeature Web-Mgmt-Service  
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\WebManagement\Server -Name EnableRemoteManagement -Value 1  

最后用 net start WMSVC启动Web Management service。您也可以将这个服务设为自动:sc config wmsvc start=auto

 

现在Server核心版可以完全被远程的workstation管理了(Server Manager 用于常用的管理, IIS Manager 用于IIS的管理)!

 

要远程连接Server核心版的IIS,在远程任意一台机器上打开IIS Manager,右键选择 Start Page 并选择 Connect to a Server... 选项:

“PI System新功能介绍” 在线研讨会已经圆满结束,我们希望您能觉得参加这次交流会是一次收获丰富的愉快经历,能够帮助你更好的了解最新发布的 PI System,让您在日后的工作中更好的使用 PI System,提高工作效率并推动创新。

 

您可以通过以下链接,下载本次会议的 PPT 资料:

 

 

 

如果您有任何问题,或是想进一步的咨询有关 PI System的产品信息,请在本帖留言或者通过以下电子邮件与我们保持联系 marketingcn@osisoft.com 。我们将为您做进一步的安排。

“如何让 PI AF 为您所用”在线研讨会已经圆满结束,我们希望您能觉得参加这次交流会是一次收获丰富的愉快经历,通过基于AF架构的案例分享,对您的日常工作能有所启发。

 

您可通过以下链接下载本次会议的资料:

 

  • 会议时间: 2016614日,星期二 时间:上午10 - 11
  • 会议录像:点此回看或是下载
  • 王普乐 《如何让PI
         AF
    为您所用》:点此下载PPT
  • 孙玉鹏 《蓝星PI
         AF
    应用案例分享》:点此下载PPT
  • 马天明 《南通星辰PI AF应用案例分享》:点此下载PPT

 

 

如果您有任何问题,或是想进一步的咨询有关 PI AF 的产品信息,请在本帖留言或者通过以下电子邮件与我们保持联系 marketingcn@osisoft.com 。我们将为您做进一步的安排。




PI Coresight 2016 在线研讨会已经圆满结束,我们希望您能觉得参加这次交流会是一次收获丰富的愉快经历,能够帮助你更好的了解 如何PI Coresight 实现 PI System 数据可视化。


您可通过以下链接下载本次会议的资料:

 

如果您有任何问题,或是想进一步的咨询有关 PI Coresight的产品信息,可以在本帖留言,或者通过以下电子邮件与我们保持联系 marketingcn@osisoft.com 。我们将为您做进一步的安排。




PI Coresight 2016 在线研讨会已经圆满结束,我们希望您能觉得参加这次交流会是一次收获丰富的愉快经历,让您对PI Coresight 2016 有了初步的了解。

您可通过以下链接下载本次会议的资料:

 

  • 会议时间:2016 年719日,星期二,上午10-11
  • 会议录像:点此回看或是下载
  • 徐初 PI Coresight
         2016
    介绍》:点此下载PPT
  • 张新桥《PI Coresight 应用初探》:点此下载PPT

 

 

如果您有任何问题,可以在本帖下留言,或是想进一步的咨询有关 PI Coresight2016 的产品信息,也可以通过以下电子邮件与我们保持联系marketingcn@osisoft.com 。我们将为您做进一步的安排。




PI Coresight 2016相比于之前版本有非常大的变化,其中一项重要的改进是允许用户自己添加自定义的图案。pisquare中已经有非常多相关的post,如添加谷歌地图,添加RSS种子添加时间轴等等,并且不断有新的post更新。相关的配置文档可以在此处找到,此外在github上有关于custom symbol比较详细的介绍,下面结合其中一个案例(单个值的图形),简单介绍一下创建custom symbol的基本方法,和一些配置参数。

在PI Coresight的安装文件夹下INSTALLATION_FOLDER\Scripts\app\editor\symbols\ext创建名为sym-simplevalue.js的文件。如果ext文件夹不存在,您需要手动创建此文件夹。

将如下代码添加到刚创建的js文件中,这会初始化用于创建custom symbol的结构。这个代码创建了一个IIFE(immediately invoked functional expression,立即执行函数),此函数将会取到将会被用来注册symbol的PI Coresight对象

(function (CS) {
})(window.Coresight);

创建一个定义对象,并注册。这里symbol catalog是一个我们用来注册和管理所有Coresight symbols。我们这样会创建一个空的对象,并将其传递到注册函数中。因为这是一个立即执行函数,一旦浏览器执行它,它将会运行这个注册的代码

(function (CS) {
    var definition = {};
    CS.symbolCatalog.register(definition);
})(window.Coresight);

接下来我们,开始添加一个新的图案中必须的部分:

typeName是PI Coresight注册时使用的一个内部名字。这个名字在所有Coresight的图案中必须是唯一的。

datasourceBehavior用来指定有多少搜索结果(None用来表示静态值,Single表示单个值,Multiple表示多个值。此处我们使用单个值,如果需要画自定义的trend,那就需要多个值,即multiple)可以被用来创建这个图案。

(function (CS) {
    var definition = {
        typeName: 'simplevalue',
        datasourceBehavior: CS.DatasourceBehaviors.Single
    };
    CS.symbolCatalog.register(definition);
})(window.Coresight);

接下来,我们将添加一些具体使用的信息:这里我们会添加getDefaultConfig属性。这个函数是用来指定一系列symbol形态的参数的。如这里我们指定datashape为Value,那我们会显示一个value的图案

(function (CS) {
   var definition = {
  typeName: 'simplevalue',
  datasourceBehavior: CS.DatasourceBehaviors.Single,
   getDefaultConfig: function() {
   return {
  DataShape: 'Value'
  };
  }
  };
   CS.symbolCatalog.register(definition);
})(window.Coresight);

在继续完善之前的代码之前,我们现在与之前js文件相同的文件夹下创建一个名为sym-simplevalue-template.html的函数,这里命名的规则是:sym-<图案类型名>-template.html。这是一个symbol框架会默认去寻找的名字,如果template路径没有在symbol中被指定的话(可以通过templateUrl来指定)。加入以下内容到HTML文件。这里现在只是一个占位符。

<div style="background: red">
    <div>Simple Value</div>
</div>

这里,为了让这个心得图案被PI Coresight 网页服务器接收到,需要运行IIS reset

接下来,打开Coresight的页面,搜索一个PI点或者AF属性,将该属性拖动到画布中。您会发现当您放下这个item之后,您还无法选择它。这是因为这个图案没有包括一个init函数。

为了修复这个问题,我们需要更新getDefaultConfig函数,让它返回高(Height)和宽(Width)。此外我们需要添加初始化(initialization)函数到definition对象中。init函数是在图案被添加到画布的时候被调用的。

(function (CS) {
    var definition = {
        typeName: 'simplevalue',
        datasourceBehavior: CS.DatasourceBehaviors.Single,
        getDefaultConfig: function() {
            return {
                DataShape: 'Value',
                Height: 150,
                Width: 150
            };
        },
        init: init
    };


    function init() {
    }


    CS.symbolCatalog.register(definition);
})(window.Coresight);

再在Coresight中添加新的图案。图案现在可以被选择、移动,并且可以使用Coresight中的撤销功能了。这样基础架构已经搭好了,为了给图案添加新的功能,我们需要扩展init函数。我们会添加一个新的参数到这个函数中scope。Scope是一个从AngularJS中借用的,是一个让页面和后台JS更方便互动的框架。init函数会有一个函数来处理当图案获得一个新的数据时。最终我们会添加一个返回函数到init函数中,让PI Coresight知道如何和图案交互。

function init(scope) {
    function onUpdate(data) {
    }
    return { dataUpdate: onUpdate };
}

上面这段代码告诉PI Coresight每当数据更新时去调用onUpdate函数。现在我们需要对onUpdate函数做一些扩展

用下面这段函数来添加一些变量到scope中:value,timelabel。这样可以让这些变量在HTML展示画面中使用。为了完整性,我们会检查data和Label这两个变量在被onUpdate函数使用时是否已经被定义了。

function init(scope) {
    function onUpdate(data) {
        if(data) {
            scope.value = data.Value;
            scope.time = data.Time;
            if(data.Label) {
                scope.label = data.Label;
            }
        }
    }
    return { dataUpdate: onUpdate };
}

现在我们可以更新HTML文件来显示这些值了。我们使用AngularJS的样式来标记{{}}。此外我们还在div中添加了一些背景颜色的style。

<div style="background: orange; color: black">
    <div>{{label}}</div>
    <div>{{value}}</div>
    <div>{{time}}</div>
</div>

重新尝试在Coresight中添加这个新的图案。

接下来我们介绍如何修改这个图案的颜色。首先我们需要添加一个内容菜单的选项到图案中,这是通过添加configOptions属性来实现的。configOptions是一个图案可用属性的一个函数,它会返回一个控制配置的数组。在这个案例中,我们返回了名为‘Format Symbol’的对象。在这里使用的‘mode’是用来指定配置类型的。这样当我们右键点击图案,选择配置图案时,我们将会打开右侧PI Coresight 配置画面。

var definition = {
    typeName: 'simplevalue',
    datasourceBehavior: CS.DatasourceBehaviors.Single,
    getDefaultConfig: function() {
        return {
            DataShape: 'Value',
            Height: 150,
            Width: 150
        };
    },
    configOptions: function () {
        return [{
            title: 'Format Symbol',
            mode: 'format'
        }];
    },
    init: init
};

接下来我们需要创建一个configurationHTML的画面。在相同文件夹下创建sym-simplevalue-config.html文件。命名规则是sym-<图案名>-config.html。同理,如果不按照这个规则命名,需要在configTemplateUrl参数中指定。下面这个例子中包含了两种配置:文字颜色和背景颜色。我们这里使用了format-color-picker,这是一个AngularJS的服务让Coresight可以给图案挑选颜色。format-color-picker有两个属性:property和config。property对应config对象中传递进来的属性,config是图案中的config对象。

<div class="c-side-pane t-toolbar">
    <span style="color:#fff; margin-left:15px">Text Color</span>
</div>
<format-color-picker id="textColor" property="TextColor" config="config"></format-color-picker>
<div class="c-side-pane t-toolbar">
    <span style="color:#fff; margin-left:15px">Background Color</span>
</div>
<format-color-picker id="backgroundColor" property="BackgroundColor" config="config"></format-color-picker>

我们也需要对原来的展示页面做一些修改,使得我们配置页面的属性也可以关联进来。这里我们需要用到一个AngularJS的辅助工具,ng-style

<div ng-style="{background: config.BackgroundColor, color: config.TextColor}">
    <div>{{label}}</div>
    <div>{{value}}</div>
    <div>{{time}}</div>
</div>

最后,我们还可以配置我们的图案,使之可以显示或隐藏一部分属性。要做到这点,我们需要更新getDefaultConfig函数,使之包含可以显示或者隐藏标题和时间的boolean形变。如下面的代码所示,默认我们是会显示标题,但不显示时间戳

getDefaultConfig: function() {
    return {
        DataShape: 'Value',
        Height: 150,
        Width: 150,
        BackgroundColor: 'rgb(255,0,0)',
        TextColor: 'rgb(0,255,0)',
        ShowLabel: true,
        ShowTime: false
    };
},

同时,展示的html画面也需要做一些修改,我们通过ng-show的辅助工具(同样也是angularJS的功能)可以控制是否显示相应的属性。当绑定的值为true是,将会显示这个元素,反之则隐藏这个元素。

<div ng-style="{background: config.BackgroundColor, color: config.TextColor}">
    <div ng-show="config.ShowLabel">{{label}}</div>
    <div>{{value}}</div>
    <div ng-show="config.ShowTime">{{time}}</div>
</div>

最后,我们对配置页面也需要做一些修改,使之可以选择是否显示时间或者标题。

<div class="c-side-pane t-toolbar">
    <span style="color:#fff; margin-left:15px">Text Color</span>
</div>
<format-color-picker id="textColor" property="TextColor" config="config"></format-color-picker>
<div class="c-side-pane t-toolbar">
    <span style="color:#fff; margin-left:15px">Background Color</span>
</div>
<format-color-picker id="backgroundColor" property="BackgroundColor" config="config"></format-color-picker>


<div class="c-side-pane t-toolbar">
    <span style="color:#fff; margin-left:15px">Show Options</span>
</div>
<div class="c-config-content">Show Label:
    <input type="checkbox" ng-model="config.ShowLabel">
</div>
<div class="c-config-content">Show Time:
    <input type="checkbox" ng-model="config.ShowTime">
</div>

这样基本的功能就完成了,下面我们修改一下配置信息使之可以显示multistate。要做到这一点,我们必须添加StateVariables到图案的definition对象。

var definition = {
    typeName: 'simplevalue',
    datasourceBehavior: CS.DatasourceBehaviors.Single,
    getDefaultConfig: function() {
        return {
            DataShape: 'Value',
            Height: 150,
            Width: 150,
            BackgroundColor: 'rgb(255,0,0)',
            TextColor: 'rgb(0,255,0)'
        };
    },
    StateVariables: [ 'MultistateColor' ],
    configOptions: function () {
        return [{
            title: 'Format Symbol',
            mode: 'format'
        }];
    },
    init: init
};

此外还需要对展示页面做一些修改,使得页面颜色可以使用multistate中定义的颜色。这里,如果multistate被定义了,那颜色就会用multistate的定义,如果没有定义,就用默认的颜色。

<div ng-style="{background: config.BackgroundColor, color: MultistateColor || config.TextColor}">
    <div ng-show="config.ShowLabel">{{label}}</div>
    <div>{{value}}</div>
    <div ng-show="config.ShowTime">{{time}}</div>
</div>

原文post在此链接How to customize the appearance of PI Coresight 2016  ,作者为KenjiJerome。以下为原文链接的翻译:

 

改变Coresight页面Tab的外观,如下

to

您能将“PI Coresight”的title改为任意内容,如此处所示,内容已被改为Kenji Coresight,有三处地方可以做这些修改

 

1. For the Homepage:

%PIHOME64%\Coresight\Views\Home\Index.cshtml

ViewBag.Title = "PI Coresight";

 

2. For a ProcessBook Page:%PIHOME64%\Coresight\Scripts\app\pbviewer\pbviewer.navigation.js

function setTitle(displayName) {
     var title = 'PI Coresight';

 

3 PI Coresight Display:%PIHOME64%\Coresight\Scripts\app\editor\display\coresight.display-controller.js

 function setTitle(displayName) {  
            var title = 'PI Coresight'; 

 

如果想改变移动端的展示,可以修改如下内容: %PIHOME64%\Coresight\Views\M\Index.cshtml

<title>PI Coresight</title>  
<div data-role="page" data-title="PI  Coresight" id="mostrecent" class="appBackground">  
<div data-role="page" data-title="PI Coresight" id="search" class="appBackground">  
<div data-role="page" data-title="PI Coresight" id="csdisplay" class="appBackground" data-add-back-btn="true">  
<div data-role="page" data-title="PI Coresight" id="pbdisplay" class="appBackground" data-add-back-btn="true">  
<div data-role="page" data-title="PI Coresight" id="element" class="appBackground unselectable" data-add-back-btn="true">  
<div data-role="page" data-title="PI Coresight" id="trend" class="appBackground unselectable" data-add-back-btn="true">  
<div data-role="page" data-title="PI Coresight" id="servicesandtools"> 

 

您也能改变site的网站图标,只要改变%PIHOME64%\Coresight\Images\logo.png文件即可

to

 

如果您想改变Help的内容,您可以在%PIHOME64%\Coresight\Scripts\app\editor\layout\coresight.cs-header-directive.js中修改,例如如果您将以下内容注释了,将会在Help中删除PI Live Library

  1. { id: 'HelpMenuOnLine', title: CS.Messages.HelpMenuOnLine, url: 'https://livelibrary.osisoft.com/LiveLibrary/content/' + lang + '/coresight-v7/GUID-7EF650C5-1235-4F8A-AC61-2EB1D2A3A5BF ' }, 

to

 

如果您不想让用户创建新的display

删除 在 %PIHOME64%\Coresight\Scripts\app\editor\layout\coresight.cs-header-directive.js中的div class="c-new-display"

You can delete all of the followings.

<div class="c-new-display t-display-content-font">  
            <div class="c-icon-display" ng-click="navCtrl.newDisplay()" title="{{::newDisplayTooltip}}">  
                <div class="c-new-display-rollover">  
                    <div>  
                        <svg id="new-display-icon" class="t-icon-fill" version="1.1" x="0px" y="0px"  
                             width="25px" height="25px" viewBox="0 -4 25 25" enable-background="new 0 0 25 25" xml:space="preserve">  
                        <path d="M9.677,0.823c-5.12,0-9.271,4.188-9.271,9.354c0,5.169,4.151,9.356,9.271,9.356  
                                    c5.119,0,9.271-4.188,9.271-9.356C18.948,5.012,14.796,0.823,9.677,0.823" />  
                        <polygon fill="#091d3a" points="15.553,8.831 10.982,8.831 10.982,4.114 8.37,4.114 8.37,8.831 3.8,8.831 3.8,11.527 8.37,11.527  
                                    8.37,16.243 10.982,16.243 10.982,11.527 15.553,11.527" />  
                        </svg>  
                    </div>  
                    <div class="t-font-color-white" style="text-decoration: none">{{::newDisplayLinkText}}</div>  
                </div>  
            </div>  
        </div>

 

这样所有用户都不能再创建新display了

但是您仍然可以手动通过如下url来创建新的display

https://ServerName/coresight/#/Displays/New/

 

如果您想保持所有display都是显示kiosk mode,您可以注释以下语句

%PIHOME64%\Coresight\Scripts\app\editor\display\coresight.displays-controller.js

 

// if (parms.mode === 'kiosk')  
setKioskMode(true);  

If you do this, all users/ all displays can be seen as Kiosk mode.We could not choose which users can see display without kiosk. So if you want to create/edit display, you need to change comments out again. (Found with Jerome Lefebvre)

 

PI Coresight 2016 Value object 会显示工具提示. 如果您不想显示

%PIHOME64%\Coresight\Scripts\app\editor\symbols\coresight.sym-value.js

//valueLabel.path = data.Path;  

 

如果您这样做,您将不会看到工具提示

在默认情况下,多状态(multi-state)将会改变背景颜色By default, Value object's Multi-State changes background color.

如果您想改变字体本身大小,需要修改 sym-value-template.html的"Fill ||”

%PIHOME64%\Coresight\Scripts\app\editor\symbols\sym-value-template.html

     
               
     
                         
     
               
 
 

这样您将可以改变文字颜色而不是背景色

 

为了改变画面的背景色,您可以修改t-display-container类

%PIHOME64%\Coresight\Content\css\theme.base-colors.css

contains the t-display-container.

.t-display-container {  
  background-color: white; } 

 

这样就显示白色的背景色了

PI Coresight 2016 可以使用自定义的图案,具体可以参考如下repository

GitHub - osisoft/PI-Coresight-Custom-Symbols: Learn how to add a custom symbol, created with JavaScript and HTML, to PI …

如果您不自己设置,默认您定义的custom symbol将会显示 图案.

您可以找自己想要的图案(png/jpg格式),或者直接截屏(注意将display背景色改为#48586b

将图案放置到 %PIHOME64%\Coresight\Images 文件夹下

在custom symbol的配置js文件中指定iconURL参数

 

var defintion = {  
typeName: 'liquidgauge',  
iconUrl: 'Images/liquid.png',  

效果如下图所示.

如果您点击这个item,您会发现这个图片是包含背景颜色的。当然您最好可以创建一个没有背景色的图案,但能用系统自带的画图工具来获得image总是比较简单的方法

第三方软件也是个不错的方案,例如

https://inkscape.org/en/

 

我还没有检查所有的item,但是看上去HTML5在修改了很多内容之后,仍然可以正常工作。当然这些并不是我们OSI官方的修改