# DataBase产品说明

### 概述

使用场景

- 工业自动化：在生产线监控、设备状态监测、故障诊断等场景中， PLC 可以与数据库有效配合
- 预测性维护：通过对历史数据的分析，可以实现设备的预测性维护，降低停机时间

下载:🧷Database V1.0

主要功能及产品组件

DataBase实现通过PLC编程将PLC变量和数据库进行交互(目前支持与mysql数据库交互，其他种类数据库后续支持);支持的交互功能包括：创建表、读取表中数据、追加数据、更新表中数据、保留表中最后某几行；其余常用的从数据库功能后续逐步增加支持，如：删除表中特定行数据、插入数据、查询表名、查询表结构、删表等；

整体架构

### 操作使用教程

下载：🧷DataBase操作手册.zip

本文中所提及所有软件安装程序、示例工程等内容，均可在中科时代官方网站/资源下载 中获得。

资源下载专区

DataBase教程资料包

您可以通过以下链接，观看操作演示教学视频。您可以看到产品工程师最为详细的讲解以及操作，这将帮助您更快的掌握以及学习使用本产品。

### 安装卸载

DataBase产品有三个组件，所以要使用DataBase需要从安装这三个组件开始，下面将详细介绍：

1.工智机端安装database RTE组件

- 上传deb包到工智机Linux环境的/home/sinsegye目录下，上传方法参考附录；
- 上传完成后在工智机上执行命令安装（参考下方截图，如果模块文件名发生变化则命令行中的文件名做相应更改）

> sudo dpkg -i sf4401db_0.0.1-rc.4_amd64.deb

- 修改RTE的配置文件，ComponentManger模块下加入sf4401db，同时需要去掉SE4100；

> sudo vim /usr/local/etc/SinsegyeRTE/SinsegyeRTE.cfg

> [ComponentManager]
> Component.0=retainDeamon
> Component.1=CmpCanBusUtils
> Component.2=CmpSinsegyeLibs
> Component.3=SinsegyeCmp
> Component.4=sf4401db

- 重启RTE服务，使新加入的sf4401db被调用

> sudo systemctl restart sinsegyerte.service

2.工智机端部署数据库后台服务组件

首先需要部署.Net SDK 6.0.0，请在可访问互联网状态下执行如下命令

> wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
> #若工智机系统不是22.04，请将第一条命令中的22.04换成对应的版本
> sudo dpkg -i packages-microsoft-prod.deb
> sudo rm -rf packages-microsoft-prod.deb
> sudo apt-get update
> sudo apt-get install -y dotnet-sdk-6.0
> sudo apt-get install -y aspnetcore-runtime-6.0
> sudo apt-get install -y dotnet-runtime-6.0
> sudo cp -r /usr/lib/dotnet/host/ /usr/share/dotnet/ #非22.04版本可能不需要
> sudo cp -r /usr/lib/dotnet/shared/ /usr/share/dotnet/ #非22.04版本可能不需要
> dotnet --info #查看net服务信息，无报错代表安装成功

上传数据库后台服务包到工智机/home/sinsegye目录下（上传方法参考附录），然后解压

> sudo unzip dbservice.zip

上传dbservice.service文件到/lib/systemd/system/下（上传方法参考附录），然后执行如下命令

> sudo systemctl daemon-reload
> sudo systemctl status dbservice.service
> sudo systemctl start dbservice.service
> sudo systemctl enable dbservice.service

3.IDE侧部署DataBase的library

MetaFacture中点击最上面的菜单栏 ”工具“ -- ”库存储“ ；

弹出的对话窗中点击”安装“ -- 选中SF4401_DB.library -- 点击“打开”；

工程中双击“库管理器” -- “添加库” -- 双击“SF4401_DB” ，加载库完成；

### 更新安装

1.升级工智机database RTE组件

- 上传升级版deb包到工智机Linux环境的/home/sinsegye目录下，上传方法参考附录；
- 上传完成后在工智机上执行命令安装（参考下方截图，如果模块文件名发生变化则命令行中的文件名做相应更改）

> sudo dpkg -i sf4401db_0.0.1-rc.4_amd64.deb

重启RTE服务，使新升级的的sf4401db被调用

> sudo systemctl restart sinsegyerte.service

2.升级工智机数据库后台服务

上传数据库后台服务升级包到工智机/home/sinsegye目录下（上传方法参考附录），然后解压

> sudo unzip dbservice.zip

上传新的dbservice.service文件到/lib/systemd/system/下（上传方法参考附录），然后执行如下命令

> sudo systemctl daemon-reload
> sudo systemctl status dbservice.service
> sudo systemctl start dbservice.service
> sudo systemctl enable dbservice.service

3.升级IDE侧DataBase的library

MetaFacture中点击最上面的菜单栏 ”工具“ -- ”库存储“ ；

弹出的对话窗中点击”安装“ -- 选中新版的SF4401_DB.library -- 点击“打开”；

工程中双击“库管理器” -- “添加库” -- 双击新安装的“SF4401_DB” ，加载库完成；

### 卸载过程

1.卸载工智机database RTE模块

工智机上执行命令卸载

> sudo dpkg -r sf4401db

修改RTE的配置文件，ComponentManger模块下去掉sf4401_db

> sudo vim /usr/local/etc/SinsegyeRTE/SinsegyeRTE.cfg

2.卸载工智机端数据库后台服务

工智机上执行如下命令

> sudo systemctl stop dbservice.service
> sudo systemctl disable dbservice.service
> sudo rm -rf /lib/systemd/system/dbservice.service
> sudo systemctl daemon-reload
> sudo rm -rf /home/sinsegye/dbservice/

3.卸载IDE侧的DataBase library

MetaFacture界面点击“工具” -- “库存储”

对话框中选中安装的sf4401的库，点击“卸载”

### 快速启动

（一）本例软、硬件配置

- 硬件：SX58工智机 / win10 PC
- 软件：MetaFacutre V1.0.6.2

（二）本例实验操作步骤

实验要求：按照“安装卸载”部分中的“安装过程”配置完成DataBase环境，并且mysql数据库中存在test1数据库

1.建立与数据库连接的实验步骤如下：

POU中声明区域调用SF4401_DB库的功能块FB_PLCDBAddConnection

> fbCreateCon : SF4401.FB_PLCDBAddConnection;
> sdbs : STRING := 'test1'; //定义数据库的名称test1
> addcon_execute：bool;

POU中程序区域调用fbCreateCon,配置数据库的IP和端口、名称、数据库用户名密码

> fbCreateCon(sNetID:= '192.168.111.152:3306', //mysql数据库的ip和端口
> eDBType:= 0, //0代表数据库类型mysql
> sDBServer:= sdbs, //数据库的名称
> sDBUserId:= 'remoteuser',
> sDBPassword:= 'password',
> bExecute:= addcon_execute,
> tTimeout:= T#5S, bBusy=> ,
> bError=> ,
> sDBID=> DBID,
> sMessage=> );

触发bExecute上升沿即可建立与数据库的连接

2.获取数据库ID的实验步骤如下：

实验要求：需要先做实验1建立与mysql数据库的连接

POU中声明区域调用SF4401_DB库的功能块FB_PLCDBGetConnection

> fbGetCon : SF4401.FB_PLCDBGetConnection;
> sdbs : STRING := 'test1'; //定义数据库的名称test1
> get_execute : Bool;
> DBID: STRING:= ''; //用于存放获取的数据库的ID

POU中程序区域调用fbGetCon

> fbGetCon(sNetID:= '192.168.111.152:3306',
> name:= sdbs,
> eDBType:= 0,
> bExecute:= get_execute,
> tTimeout:= T#5S,
> bBusy=> ,
> bError=> ,
> sDBID=> DBID,
> sMessage=>);

触发bExecute上升沿即可获取数据的ID

3.创建表的试验步骤如下：

试验要求：需要先做实验2获取到数据库的ID
POU中声明区域调用SF4401_DB库的功能块FB_PLCDBDeleteConnection，调用ST_ColumnInfo定义表的列信息

> fbCreateTable : SF4401.FB_PLCDBCreateTable;
> ColumnInfo : ARRAY[0..255] OF SF4401.ST_ColumnInfo;
> table_name : STRING := 'test1.dbtest_table1'; //要创建的表名称

POU中程序区域定义表的每一列的名称和属性，调用fbCreateTable

> ColumnInfo[0].sName := 'Long_test';ColumnInfo[0].eType := SF4401.E_ColumnType.Long; ColumnInfo[0].nLength := 8;
> ColumnInfo[1].sName := 'Int_test';ColumnInfo[1].eType := SF4401.E_ColumnType.Integer; ColumnInfo[1].nLength := 4;
> ColumnInfo[2].sName := 'Bool_test';ColumnInfo[2].eType := SF4401.E_ColumnType.Bool_; ColumnInfo[2].nLength := 1;
> ColumnInfo[3].sName := 'Long_test2';ColumnInfo[3].eType := SF4401.E_ColumnType.Long; ColumnInfo[3].nLength := 8;
> ColumnInfo[4].sName := 'String_Test';ColumnInfo[4].eType := SF4401.E_ColumnType.STRING_; ColumnInfo[4].nLength := 81;
> ColumnInfo[5].sName := 'Double_test';ColumnInfo[5].eType := SF4401.E_ColumnType.Double; ColumnInfo[5].nLength := 8;
> ColumnInfo[6].sName := 'Double_test2';ColumnInfo[6].eType := SF4401.E_ColumnType.Double; ColumnInfo[6].nLength := 8;
> ColumnInfo[7].sName := 'Time_test';ColumnInfo[7].eType := SF4401.E_ColumnType.DateTime; ColumnInfo[7].nLength := 8;
> //将定义好的表创建
> fbCreateTable(sDBID:= DBID, //实验2获取的数据的ID
> sTableName:= table_name, //表的名称
> aTableCfg:= ColumnInfo,
> cbTableCfg:= 8,
> bExecute:= table_execute,
> tTimeout:= T#5S,
> bBusy=> ,
> bError=> ,
> sMessage=>);

触发bExecute上升沿即可在数据库test1创建成功表dbtest_table1

4.表中写入数据

试验要求：需要先做实验3，创建表dbtest_table1

POU中声明区域调用SF4401_DB库的功能块SF4401.FB_PLCDBWrite;定义要写入的表的列信息；

> fbWrite : SF4401.FB_PLCDBWrite;
> writeColumnNames: ARRAY [0..255] OF STRING(50);
> writeStructArr : ARRAY [0..255] OF ST_TestDataBase;

ST_TestDataBase为定义好的结构体，定义了表的每一列的列名及类型信息；

> TYPE ST_TestDataBase :
> STRUCT
> Long_test : LINT;
> Int_test : DINT;
> Bool_test : BOOL;
> Long_test2 : LINT;
> String_Test : STRING;
> Double_test : LREAL;
> Double_test2 : LREAL;
> Time_test : DATE_AND_TIME;
> END_STRUCT
> END_TYPE

POU中程序区域设置表的列名信息，然后给每一列赋值，然后调用fbWrite触发写入动作；

> writeColumnNames[0] := 'Long_test';
> writeColumnNames[1] := 'Int_test';
> writeColumnNames[2] := 'Bool_test';
> writeColumnNames[3] := 'Long_test2';
> writeColumnNames[4] := 'String_Test';
> writeColumnNames[5] := 'Double_test';
> writeColumnNames[6] := 'Double_test2';
> writeColumnNames[7] := 'Time_test';

> writeStructArr[0].Long_test := 110;
> writeStructArr[0].Int_test := 111;
> writeStructArr[0].Bool_test := FALSE;
> writeStructArr[0].Long_test2 := 115;
> writeStructArr[0].String_Test := 'asdsadsada';
> writeStructArr[0].Double_test := 101.0;
> writeStructArr[0].Double_test2 := 100.0;
> writeStructArr[0].Time_Test := DT#2024-10-22-13:10:00;

> writeStructArr[1].Long_test := 216;
> writeStructArr[1].Int_test := 215;
> writeStructArr[1].Bool_test := TRUE;
> writeStructArr[1].Long_test2 := 200;
> writeStructArr[1].String_Test := 'gggsdfsfdsf';
> writeStructArr[1].Double_test := 200.0;
> writeStructArr[1].Double_test2 := 200.0;
> writeStructArr[1].Time_Test := DT#2024-10-22-13:13:00;

> writeStructArr[2].Long_test := 214;
> writeStructArr[2].Int_test := 215;
> writeStructArr[2].Bool_test := TRUE;
> writeStructArr[2].Long_test2 := 200;
> writeStructArr[2].String_Test := 'gggsdfsfdsf';
> writeStructArr[2].Double_test := 200.0;
> writeStructArr[2].Double_test2 := 200.0;
> writeStructArr[2].Time_Test := DT#2024-10-21-12:12:12;

> fbWrite(sDBID:= DBID,
> sTableName:= table_name,
> sColumnNames:= writeColumnNames,
> sOrderByColumn:=writeColumnNames[0],
> pRecord:= ADR(writeStructArr),
> cbRecord:= SIZEOF(ST_TestDataBase),
> dataCount:= 3,
> eDBWriteMode:= SF4401.E_WriteMode.DB_Append, //Append模式使用
> //eDBWriteMode:= SF4401.E_WriteMode.DB_RingBuff_count // RingBuff_count模式使用
> nRingBuffParameter:= 10,
> bExecute:= write_append_execute,
> tTimeout:= T#5S,
> bBusy=> ,
> bError=> ,
> sMessage=>);

触发bExecute上升沿即可在表dbtest_table1写入数据

5.读取表中数据

试验要求：需要先做实验3和4，创建表dbtest_table1并写入数据
POU中声明区域调用SF4401_DB库的功能块FB_PLCDBReadStruct，定义要读的表的列信息ColumnNames，定义保存数据的变量myCustomStructArr；

> fbReadStruct : SF4401.FB_PLCDBReadStruct;
> ColumnNames: ARRAY [0..255] OF STRING(50);
> myCustomStructArr : ARRAY [0..3] OF ST_TestDataBase;

POU中程序区域要读的表的列名信息，然后调用fbReadStruct

> ColumnNames[0] := 'Long_test';
> ColumnNames[1] := 'Int_test';
> ColumnNames[2] := 'Bool_test';
> ColumnNames[3] := 'Long_test2';
> ColumnNames[4] := 'String_Test';
> ColumnNames[5] := 'Double_test';
> ColumnNames[6] := 'Double_test2';
> ColumnNames[7] := 'Time_Test';

> fbReadStruct(
> sDBID:= DBID,
> sTableName:= table_name,
> sColumnNames:= ColumnNames,
> sOrderByColumn:= 'id',
> eOrderType:= SF4401.E_OrderType.ASC,
> nStartIndex:= 1,
> nRecordCount:= 2,
> pData:= ADR(myCustomStructArr),
> cbData:= SIZEOF(ST_TestDataBase),
> bExecute:= read_execute,
> tTimeout:= T#5S,
> bBusy=> ,
> bError=> ,
> sMessage=>);

触发bExecute上升沿即可读取表dbtest_table1中的数据，保存在myCustomStructArr中

6.断开与mysql数据库的连接

实验要求：需要有做实验1与数据库建立连接，并获取数据库ID信息

POU中声明区域调用SF4401_DB库的功能块FB_PLCDBDeleteConnection

> fbDelCon : SF4401.FB_PLCDBDeleteConnection;
> DBID : STRING :='';
> delecon_execute : Bool;

POU中程序区域调用fbDelCon，输入数据库的ip和端口以及ID

> fbDelCon(
> sNetID:= '192.168.111.152:3306',
> sDBID:= DBID,
> bExecute:= delcon_execute,
> tTimeout:= T#5S,
> bBusy=> ,
> bError=> ,
> sMessage=>);