OEM Template
这是一个针对OEM 单机设备的 FTOptix 项目模板,预置多个功能组件。后台集成WebServer,为使用系统提供Web扩展功能,包括:Charts,3D Model,3D架构图,表单管理,手写签名
1.功能特性
- RA Library: 集成 RA的 Device Library内的面板,包括:Machine Builder,Power Device,IO Device,Network Device,等...
- UI Component: 包括单机HMI常用的UI组件/控件 : 文件管理,数据库管理,用户管理,配方管理,集合控件,树形控件,Svg图表,多页标签
- Report Pro: 这是一个工具集,实现复杂的图表 Report,并以PDF方式输出。图表库可使用 ECharts Library
- WebServer: 使用TCP/IP协议栈实现的Web服务,包括:Http,Websocket
- Charts(图表服务) : 支持 ECharts、Apex 图表库,使用 ajax方式更新数据
- 3D Model(三维模型展示服务):提供3D web应用的后台管理功能,并提供标准通讯协议栈,用以控制3D场景切换,相机控制,实时数据更新,用户操作反馈
- FormIO(表单服务):集成Form.IO的前端部分,Optix提供后台管理,包括表达的创建,存储,录入,数据保存等。
- Signature(手写签名):在画布上手写内容,并保存为图像,可用作用户验证或数据审批的补充手段。
- 3D architecture diagrams(三维架构图) : 前端渲染iCraft的3D文件,并数据的实时交互。
2.项目架构

- UI
- Screens
- StyleSheets:项目内的样式文件
- Widgets: 自定义的控件
- Components: 自定义的组件及相关依赖的控件
- Windows:项目主窗口
- Layouts:UI布局框架
- Pages:项目中所有的实体界面
- Dialogs:对话框窗口
- Template:基础页面的模板
- RA Library:RA Device Library
- Device Settings Widget:Optix Panel / EEC 硬件性能参数的查看UI
- NetLogic 包括基础组件的初始化工作,以及一个数值模拟生成的功能
- WebServer 项目所有 WebServer实例节点,每个服务分开,可单独设置及控制
3.组件介绍
WebServer 与 Optix 的结构
通过 TCP Protocol协议栈,实现WebServer,以线程方式生存在Optix进程中。WebServer实现以下协议: - HTTP: - WebSocket
功能包括:Static File 访问,function 路由, GET/POST 方法
基本路由 template :
{http/https}://{host}:{port}/{controller}/{action}?{query}
- host : web server 开放的 ip
- port : web server 开放的 port
- controller : 自定义的控制器类,继承于 HttpController
- action : 自定义的 api function 名称
Server 实现的示例
public class ChartController : HttpController
{
private readonly ChartEnvironment env;
private readonly string indexHtml;
//构造函数
public ChartController(ChartEnvironment env)
{
this.env = env;
var filepath = Path.Combine(env.WebRootPath, "apex_chart.html");
if (File.Exists(filepath))
{
var content = File.ReadAllText(filepath);
indexHtml = content;
}
else
{
indexHtml = string.Empty;
}
}
//GET {controller}/home
//return html file
[HttpMethod(HttpMethodType.GET)]
public DotNetWebServer.IResult Home()
{
if (!string.IsNullOrWhiteSpace(indexHtml))
{
return new DotNetWebServer.TextResult(indexHtml, "text/html");
}
else
{
return new DotNetWebServer.TextResult("content not found", "text/html");
}
}
//POST {controller}/getoption
//return chart option
[HttpMethod(HttpMethodType.POST)]
public DotNetWebServer.IResult GetOption()
{
var dto = JsonConvert.DeserializeObject<ChartRequestDto>(Request.Body);
if (dto != null)
{
var chartname = dto.Chart;
if (chartname.StartsWith("refid_"))
{
var guid = chartname.Substring("refid_".Length);
var guidString = guid.Replace('_', '-');
NodeId nodeId = NodeId.Of(9, Guid.Parse(guidString));
var node = InformationModel.Get(nodeId);
if (node == null)
{
Log.Warning("chart server", $"not found");
}
var logic = node.GetByType<NetLogicObject>();
logic.ExecuteMethod("GetChartOption", new object[] { }, out var outputArgs);
return new DotNetWebServer.TextResult(outputArgs[0] as string, "text/html");
}
else
{
var filepath = Path.Combine(env.TemplateRootPath, chartname + ".json");
if (File.Exists(filepath))
{
var tpl = File.ReadAllText(filepath);
return new DotNetWebServer.TextResult(tpl, "text/html");
}
else
{
filepath = Path.Combine(env.TemplateRootPath, "demo.json");
var tpl = File.ReadAllText(filepath);
return new DotNetWebServer.TextResult(tpl, "text/html");
}
}
}
else
{
var filepath = Path.Combine(env.TemplateRootPath, "demo.json");
var tpl = File.ReadAllText(filepath);
return new DotNetWebServer.TextResult(tpl, "text/html");
}
}
//POST {controller}/getdata
//return chart data
[HttpMethod(HttpMethodType.POST)]
public DotNetWebServer.IResult GetData()
{
var rsp = new ChartResponseDto();
var dto = JsonConvert.DeserializeObject<ChartRequestDto>(Request.Body);
if (dto != null)
{
var chartname = dto.Chart;
if (chartname.StartsWith("refid_"))
{
var guid = chartname.Substring("refid_".Length);
var guidString = guid.Replace('_', '-');
NodeId nodeId = NodeId.Of(9, Guid.Parse(guidString));
var node = InformationModel.Get(nodeId);
if (node == null)
{
Log.Warning("chart server", $"not found");
}
var logic = node.GetByType<NetLogicObject>();
logic.ExecuteMethod("GetChartData", new object[] { dto.Query }, out var outputArgs);
return new DotNetWebServer.TextResult(outputArgs[0] as string, "application/json");
}
}
return new DotNetWebServer.JsonResult(rsp);
}
}
系统结构:

配置项:
| 参数 | 数据类型 | 作用 |
|---|---|---|
| Port | int | web服务的端口 max:65535 |
| WebRoot | string | web 主目录 |
Chart Server / Chart Browser
图表服务:提供前端浏览器提交的图表数据服务,包括html,css,js等资源响应,GET/POST HttpMothod,可保留所有前端库的功能.
时序图:
Chart Browser
配置参数:
| 名称 | 数据类型 | 说明 |
|---|---|---|
| lib | string | 使用的图表库 apex / echarts |
| background | string | 背景色 ,默认 :ffffff |
| autofresh | bool | 是否自动刷新 |
| period | int | 自动刷新周期,单位秒 |
| option | string | 图表的option |
实例化:
UI : ChartBrowser (Type)
需要在ChartBrowser下层,新建NetLogic。基类修改为:ChartHandleLogic。 重载函数 GetChartData
示例:
public class PageProduct_chart1_RuntimeNetLogic : ChartHandleLogic
{
public override void Start()
{
// Insert code to be executed when the user-defined logic is started
base.Init();
}
public override void Stop()
{
// Insert code to be executed when the user-defined logic is stopped
}
[ExportMethod]
public override void GetChartData(string query, out string data)
{
//base.GetChartData(query, out data);
var rnd = new Random(DateTime.Now.Second);
var data1 = new List<float>();
for (int i = 0; i < 5; i++)
{
data1.Add(rnd.NextSingle()*4 + 6.0f);
}
var rsp = new ChartResponseDto();
rsp.updateSeries = new object[] { new {data = data1}};
data = JsonConvert.SerializeObject(rsp);
}
}
Collection控件
以数据模型的方式,自动呈现N个UI组件,免去手动创建UI。在UI容器中,根据Model节点内的子节点,及节点的类型的对应关系,自动化创建对应的UI组件,并进行关联。
配置参数:
| 名称 | 数据类型 | 说明 |
|---|---|---|
| Model | Alias | 需要呈现的Model节点 |
| UITypeConverter | Alias | UI Type 与数据Type的对应关系的节点 |
UITypeConverter:
Type:Object
每个元素是 Alias,Name是 数据类型的名称,Alias指向对应的 UI Type。 如果需要在UI实例化时进行别名赋值,需要把对应 UI的Alias Name 设置
样例:

Tree 控件
为了呈现一些结构化数据,比如 设备拓扑,配方/参数,菜单导航,需要树形控件。 此控件可根据 Model节点的结构,使用 Optix原生控件生成树形内容,并支持折叠/展开,选中

UI组件:

- TreeView : 主控件
- TreeNode_Accordion : 可折叠的TreeItem组件
- TreeLeafNode_1 : TreeItem 组件
Model 结构:

- Tree根节点
- V1 [Leaf]
- V2 [Leat]
- Node1 [Node]
- V1 [Leaf]
- V2 [Leat]
- Node1_1 [Node]
- Node1_2 [Node]
- Node2 [Node]
User And Group 管理
新建,删除,编辑用户,用户移入/移出 用户组

配置参数:
| 名称 | 数据类型 | 说明 |
|---|---|---|
| Users | Node Pointer | Users Folder |
| Groups | Node Pointer | Groups Folder |
| ExUser | string | 不显示的用户 |
| ExGroups | string | 不显示用户组 |
| Indent | 10 |
Sqlite Database 管理
备份数据库,删除数据库,清空数据库

配置参数:
| 名称 | 数据类型 | 说明 |
|---|---|---|
| BackupDirectory | string | 备份数据库目录 |
| Store | Node Pointer | sqlite store |
Report Pro
使用 FTOptix原生 Report组件功能,生成 带 图表的 报表。图表可使用原生控件 ,ECharts, 1D/2D条码。 外部图表内容需使用脚本 生成 svg,再用 图片控件 Image引用并显示。

功能逻辑图
FTViewer
这是一个基于 E3D进行3D可视化设计的模块,在设备仿真验证后,对场景模型进行再利用。 支持的动画类型及功能: - 平移 X Y Z - 旋转 X Y Z - 颜色变换 ColorMapper - 3D物体的点击,并把物体信息反馈给Optix

设置方法共三步:
1.在optix中,建立 Model 用来对动画变量的组织

2.运行 E3D plugin FTViewer,进行模型动画的绑定,并导出文件 [xxx.json]

3.E3D 场景导出为 FBX, [xxx.fbx]

运行效率:

- CPU : 50%
- Temp. : 65%
实机效果: