diff --git a/Projects/HelloWorld/BaseXML/CnlStatus.xml b/Projects/HelloWorld/BaseXML/CnlStatus.xml index eb254c085..cca9c31c5 100644 --- a/Projects/HelloWorld/BaseXML/CnlStatus.xml +++ b/Projects/HelloWorld/BaseXML/CnlStatus.xml @@ -52,7 +52,7 @@ 11 - Extremely low + Low low Blue Blue DodgerBlue @@ -92,7 +92,7 @@ 15 - Extremely high + High high Red Red LightCoral diff --git a/Projects/HelloWorld/BaseXML/DevType.xml b/Projects/HelloWorld/BaseXML/DevType.xml index ca1878903..eb4b71bcb 100644 --- a/Projects/HelloWorld/BaseXML/DevType.xml +++ b/Projects/HelloWorld/BaseXML/DevType.xml @@ -45,7 +45,7 @@ 208 CE6850 - DrvCE6850 + DrvCe6850 Electricity meter CE6850 (6822, 6823, 6827, 6828, 6850М) manufactured by Energomera @@ -128,9 +128,9 @@ 222 - Wiren Board ST - DrvWirenBoardST - Wiren Board controller with the custom Sensor-Tools firmware + Anemon + DrvAnemon + Receives data from Anemon controllers manufactured by Disystec 223 @@ -153,7 +153,7 @@ 226 CE30X - DrvCE301 + DrvCe301 Electricity meters CE30X, which use IEC 61107-2011, manufactured by Energomera @@ -216,6 +216,12 @@ DrvMqttPublisher Transmits channel data to MQTT broker and receives commands + + 237 + CSV Reader + DrvCsvReader + Reads data from a CSV file + 1001 Custom driver diff --git a/Projects/HelloWorld/BaseXML/ViewType.xml b/Projects/HelloWorld/BaseXML/ViewType.xml index 714428e4b..cb5f7fa64 100644 --- a/Projects/HelloWorld/BaseXML/ViewType.xml +++ b/Projects/HelloWorld/BaseXML/ViewType.xml @@ -2,48 +2,44 @@ 1 - Table view + Table TableView tbl + Requires Main Plugin 2 - Scheme view + Scheme SchemeView sch - + Requires Scheme Plugin 3 - Web page view + Web page WebPageView + Requires Web Page Plugin 4 - Chart Pro view + Chart Pro ChartProView Requires Chart Pro Plugin 5 - Dashboard view + Dashboard DashboardView dash Requires Dashboard Plugin 6 - Map view + Map MapView map Requires Map Plugin - - 7 - Elastic report - ElasticRep - Requires Elastic Report Plugin - 101 Custom view diff --git a/Projects/WirenBoardDemo/BaseXML/CnlStatus.xml b/Projects/WirenBoardDemo/BaseXML/CnlStatus.xml index eb254c085..cca9c31c5 100644 --- a/Projects/WirenBoardDemo/BaseXML/CnlStatus.xml +++ b/Projects/WirenBoardDemo/BaseXML/CnlStatus.xml @@ -52,7 +52,7 @@ 11 - Extremely low + Low low Blue Blue DodgerBlue @@ -92,7 +92,7 @@ 15 - Extremely high + High high Red Red LightCoral diff --git a/Projects/WirenBoardDemo/BaseXML/DevType.xml b/Projects/WirenBoardDemo/BaseXML/DevType.xml index 242c22bf6..eb4b71bcb 100644 --- a/Projects/WirenBoardDemo/BaseXML/DevType.xml +++ b/Projects/WirenBoardDemo/BaseXML/DevType.xml @@ -45,7 +45,7 @@ 208 CE6850 - DrvCE6850 + DrvCe6850 Electricity meter CE6850 (6822, 6823, 6827, 6828, 6850М) manufactured by Energomera @@ -86,8 +86,8 @@ 215 - OPC - DrvOpc + OPC Classic + DrvOpcClassic Interacts with controllers according to the OPC DA and OPC AE specifications @@ -128,9 +128,9 @@ 222 - Wiren Board ST - DrvWirenBoardST - Wiren Board controller with the custom Sensor-Tools firmware + Anemon + DrvAnemon + Receives data from Anemon controllers manufactured by Disystec 223 @@ -153,7 +153,7 @@ 226 CE30X - DrvCE301 + DrvCe301 Electricity meters CE30X, which use IEC 61107-2011, manufactured by Energomera @@ -184,7 +184,7 @@ 231 MQTT DrvMqtt - Interacts with controllers via MQTT protocol + Interacts with controllers via MQTT protocol. Deprecated 232 @@ -216,6 +216,12 @@ DrvMqttPublisher Transmits channel data to MQTT broker and receives commands + + 237 + CSV Reader + DrvCsvReader + Reads data from a CSV file + 1001 Custom driver diff --git a/Projects/WirenBoardDemo/BaseXML/ViewType.xml b/Projects/WirenBoardDemo/BaseXML/ViewType.xml index 714428e4b..cb5f7fa64 100644 --- a/Projects/WirenBoardDemo/BaseXML/ViewType.xml +++ b/Projects/WirenBoardDemo/BaseXML/ViewType.xml @@ -2,48 +2,44 @@ 1 - Table view + Table TableView tbl + Requires Main Plugin 2 - Scheme view + Scheme SchemeView sch - + Requires Scheme Plugin 3 - Web page view + Web page WebPageView + Requires Web Page Plugin 4 - Chart Pro view + Chart Pro ChartProView Requires Chart Pro Plugin 5 - Dashboard view + Dashboard DashboardView dash Requires Dashboard Plugin 6 - Map view + Map MapView map Requires Map Plugin - - 7 - Elastic report - ElasticRep - Requires Elastic Report Plugin - 101 Custom view diff --git a/ScadaAdmin/OpenExtensions/ExtDepPostgreSql/ExtDepPostgreSql.csproj b/ScadaAdmin/OpenExtensions/ExtDepPostgreSql/ExtDepPostgreSql.csproj index 373e36c85..fe27ae21c 100644 --- a/ScadaAdmin/OpenExtensions/ExtDepPostgreSql/ExtDepPostgreSql.csproj +++ b/ScadaAdmin/OpenExtensions/ExtDepPostgreSql/ExtDepPostgreSql.csproj @@ -18,7 +18,7 @@ - + diff --git a/ScadaAdmin/OpenExtensions/ExtProjectTools/Controls/CtrlMainMenu.cs b/ScadaAdmin/OpenExtensions/ExtProjectTools/Controls/CtrlMainMenu.cs index c00b4606c..efb75963b 100644 --- a/ScadaAdmin/OpenExtensions/ExtProjectTools/Controls/CtrlMainMenu.cs +++ b/ScadaAdmin/OpenExtensions/ExtProjectTools/Controls/CtrlMainMenu.cs @@ -47,8 +47,9 @@ private void SetMenuItemsEnabled() miChannelMapByDevice.Enabled = projectIsOpen; miChannelMapByObject.Enabled = projectIsOpen; miDeviceMap.Enabled = projectIsOpen; + miObjectMap.Enabled = projectIsOpen; miCheckIntegrity.Enabled = projectIsOpen; - miEncryptPassword.Enabled = projectIsOpen; + miEncryptPassword.Enabled = true; miImportTable.Enabled = projectIsOpen; miExportTable.Enabled = projectIsOpen; } diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmCnl.Designer.cs b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmCnl.Designer.cs index e5f0f75f8..f10c46747 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmCnl.Designer.cs +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmCnl.Designer.cs @@ -536,7 +536,7 @@ private void InitializeComponent() lblHiHi.Name = "lblHiHi"; lblHiHi.Size = new System.Drawing.Size(86, 15); lblHiHi.TabIndex = 10; - lblHiHi.Text = "Extremely high"; + lblHiHi.Text = "High high"; // // txtHigh // @@ -587,7 +587,7 @@ private void InitializeComponent() lblLoLo.Name = "lblLoLo"; lblLoLo.Size = new System.Drawing.Size(81, 15); lblLoLo.TabIndex = 4; - lblLoLo.Text = "Extremely low"; + lblLoLo.Text = "Low low"; // // chkShared // diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmCnl.cs b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmCnl.cs index aa5233677..23a1cedce 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmCnl.cs +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmCnl.cs @@ -278,7 +278,7 @@ private void btnCreateLim_Click(object sender, EventArgs e) { // create new limit int.TryParse(txtCnlNum.Text, out int cnlNum); - FrmLimCreate frmLimCreate = new(configDatabase) { CnlNum = cnlNum }; + FrmLimCreate frmLimCreate = new(configDatabase, cnlNum); if (frmLimCreate.ShowDialog() == DialogResult.OK) { diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmLimCreate.Designer.cs b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmLimCreate.Designer.cs index 5f75d254a..9ade1b8d3 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmLimCreate.Designer.cs +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmLimCreate.Designer.cs @@ -28,225 +28,216 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.txtName = new System.Windows.Forms.TextBox(); - this.lblName = new System.Windows.Forms.Label(); - this.numLimID = new System.Windows.Forms.NumericUpDown(); - this.lblLimID = new System.Windows.Forms.Label(); - this.chkIsBoundToCnl = new System.Windows.Forms.CheckBox(); - this.chkIsShared = new System.Windows.Forms.CheckBox(); - this.txtHiHi = new System.Windows.Forms.TextBox(); - this.lblHiHi = new System.Windows.Forms.Label(); - this.txtHigh = new System.Windows.Forms.TextBox(); - this.lblHigh = new System.Windows.Forms.Label(); - this.txtLow = new System.Windows.Forms.TextBox(); - this.lblLow = new System.Windows.Forms.Label(); - this.txtLoLo = new System.Windows.Forms.TextBox(); - this.lblLoLo = new System.Windows.Forms.Label(); - this.txtDeadband = new System.Windows.Forms.TextBox(); - this.lblDeadband = new System.Windows.Forms.Label(); - this.btnOK = new System.Windows.Forms.Button(); - this.btnCancel = new System.Windows.Forms.Button(); - ((System.ComponentModel.ISupportInitialize)(this.numLimID)).BeginInit(); - this.SuspendLayout(); + txtName = new System.Windows.Forms.TextBox(); + lblName = new System.Windows.Forms.Label(); + numLimID = new System.Windows.Forms.NumericUpDown(); + lblLimID = new System.Windows.Forms.Label(); + chkIsBoundToCnl = new System.Windows.Forms.CheckBox(); + chkIsShared = new System.Windows.Forms.CheckBox(); + txtHiHi = new System.Windows.Forms.TextBox(); + lblHiHi = new System.Windows.Forms.Label(); + txtHigh = new System.Windows.Forms.TextBox(); + lblHigh = new System.Windows.Forms.Label(); + txtLow = new System.Windows.Forms.TextBox(); + lblLow = new System.Windows.Forms.Label(); + txtLoLo = new System.Windows.Forms.TextBox(); + lblLoLo = new System.Windows.Forms.Label(); + txtDeadband = new System.Windows.Forms.TextBox(); + lblDeadband = new System.Windows.Forms.Label(); + btnOK = new System.Windows.Forms.Button(); + btnCancel = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)numLimID).BeginInit(); + SuspendLayout(); // // txtName // - this.txtName.Location = new System.Drawing.Point(121, 27); - this.txtName.Name = "txtName"; - this.txtName.Size = new System.Drawing.Size(312, 23); - this.txtName.TabIndex = 3; + txtName.Location = new System.Drawing.Point(121, 27); + txtName.Name = "txtName"; + txtName.Size = new System.Drawing.Size(312, 23); + txtName.TabIndex = 3; // // lblName // - this.lblName.AutoSize = true; - this.lblName.Location = new System.Drawing.Point(118, 9); - this.lblName.Name = "lblName"; - this.lblName.Size = new System.Drawing.Size(39, 15); - this.lblName.TabIndex = 2; - this.lblName.Text = "Name"; + lblName.AutoSize = true; + lblName.Location = new System.Drawing.Point(118, 9); + lblName.Name = "lblName"; + lblName.Size = new System.Drawing.Size(39, 15); + lblName.TabIndex = 2; + lblName.Text = "Name"; // // numLimID // - this.numLimID.Location = new System.Drawing.Point(15, 27); - this.numLimID.Minimum = new decimal(new int[] { - 1, - 0, - 0, - 0}); - this.numLimID.Name = "numLimID"; - this.numLimID.Size = new System.Drawing.Size(100, 23); - this.numLimID.TabIndex = 1; - this.numLimID.Value = new decimal(new int[] { - 1, - 0, - 0, - 0}); + numLimID.Location = new System.Drawing.Point(15, 27); + numLimID.Minimum = new decimal(new int[] { 1, 0, 0, 0 }); + numLimID.Name = "numLimID"; + numLimID.Size = new System.Drawing.Size(100, 23); + numLimID.TabIndex = 1; + numLimID.Value = new decimal(new int[] { 1, 0, 0, 0 }); // // lblLimID // - this.lblLimID.AutoSize = true; - this.lblLimID.Location = new System.Drawing.Point(12, 9); - this.lblLimID.Name = "lblLimID"; - this.lblLimID.Size = new System.Drawing.Size(18, 15); - this.lblLimID.TabIndex = 0; - this.lblLimID.Text = "ID"; + lblLimID.AutoSize = true; + lblLimID.Location = new System.Drawing.Point(12, 9); + lblLimID.Name = "lblLimID"; + lblLimID.Size = new System.Drawing.Size(18, 15); + lblLimID.TabIndex = 0; + lblLimID.Text = "ID"; // // chkIsBoundToCnl // - this.chkIsBoundToCnl.AutoSize = true; - this.chkIsBoundToCnl.Location = new System.Drawing.Point(15, 56); - this.chkIsBoundToCnl.Name = "chkIsBoundToCnl"; - this.chkIsBoundToCnl.Size = new System.Drawing.Size(125, 19); - this.chkIsBoundToCnl.TabIndex = 4; - this.chkIsBoundToCnl.Text = "Bound to channels"; - this.chkIsBoundToCnl.UseVisualStyleBackColor = true; + chkIsBoundToCnl.AutoSize = true; + chkIsBoundToCnl.Location = new System.Drawing.Point(15, 56); + chkIsBoundToCnl.Name = "chkIsBoundToCnl"; + chkIsBoundToCnl.Size = new System.Drawing.Size(125, 19); + chkIsBoundToCnl.TabIndex = 4; + chkIsBoundToCnl.Text = "Bound to channels"; + chkIsBoundToCnl.UseVisualStyleBackColor = true; // // chkIsShared // - this.chkIsShared.AutoSize = true; - this.chkIsShared.Location = new System.Drawing.Point(15, 81); - this.chkIsShared.Name = "chkIsShared"; - this.chkIsShared.Size = new System.Drawing.Size(62, 19); - this.chkIsShared.TabIndex = 5; - this.chkIsShared.Text = "Shared"; - this.chkIsShared.UseVisualStyleBackColor = true; + chkIsShared.AutoSize = true; + chkIsShared.Location = new System.Drawing.Point(15, 81); + chkIsShared.Name = "chkIsShared"; + chkIsShared.Size = new System.Drawing.Size(62, 19); + chkIsShared.TabIndex = 5; + chkIsShared.Text = "Shared"; + chkIsShared.UseVisualStyleBackColor = true; // // txtHiHi // - this.txtHiHi.Location = new System.Drawing.Point(333, 121); - this.txtHiHi.Name = "txtHiHi"; - this.txtHiHi.Size = new System.Drawing.Size(100, 23); - this.txtHiHi.TabIndex = 13; + txtHiHi.Location = new System.Drawing.Point(333, 121); + txtHiHi.Name = "txtHiHi"; + txtHiHi.Size = new System.Drawing.Size(100, 23); + txtHiHi.TabIndex = 13; // // lblHiHi // - this.lblHiHi.AutoSize = true; - this.lblHiHi.Location = new System.Drawing.Point(330, 103); - this.lblHiHi.Name = "lblHiHi"; - this.lblHiHi.Size = new System.Drawing.Size(86, 15); - this.lblHiHi.TabIndex = 12; - this.lblHiHi.Text = "Extremely high"; + lblHiHi.AutoSize = true; + lblHiHi.Location = new System.Drawing.Point(330, 103); + lblHiHi.Name = "lblHiHi"; + lblHiHi.Size = new System.Drawing.Size(60, 15); + lblHiHi.TabIndex = 12; + lblHiHi.Text = "High high"; // // txtHigh // - this.txtHigh.Location = new System.Drawing.Point(227, 121); - this.txtHigh.Name = "txtHigh"; - this.txtHigh.Size = new System.Drawing.Size(100, 23); - this.txtHigh.TabIndex = 11; + txtHigh.Location = new System.Drawing.Point(227, 121); + txtHigh.Name = "txtHigh"; + txtHigh.Size = new System.Drawing.Size(100, 23); + txtHigh.TabIndex = 11; // // lblHigh // - this.lblHigh.AutoSize = true; - this.lblHigh.Location = new System.Drawing.Point(224, 103); - this.lblHigh.Name = "lblHigh"; - this.lblHigh.Size = new System.Drawing.Size(33, 15); - this.lblHigh.TabIndex = 10; - this.lblHigh.Text = "High"; + lblHigh.AutoSize = true; + lblHigh.Location = new System.Drawing.Point(224, 103); + lblHigh.Name = "lblHigh"; + lblHigh.Size = new System.Drawing.Size(33, 15); + lblHigh.TabIndex = 10; + lblHigh.Text = "High"; // // txtLow // - this.txtLow.Location = new System.Drawing.Point(121, 121); - this.txtLow.Name = "txtLow"; - this.txtLow.Size = new System.Drawing.Size(100, 23); - this.txtLow.TabIndex = 9; + txtLow.Location = new System.Drawing.Point(121, 121); + txtLow.Name = "txtLow"; + txtLow.Size = new System.Drawing.Size(100, 23); + txtLow.TabIndex = 9; // // lblLow // - this.lblLow.AutoSize = true; - this.lblLow.Location = new System.Drawing.Point(118, 103); - this.lblLow.Name = "lblLow"; - this.lblLow.Size = new System.Drawing.Size(29, 15); - this.lblLow.TabIndex = 8; - this.lblLow.Text = "Low"; + lblLow.AutoSize = true; + lblLow.Location = new System.Drawing.Point(118, 103); + lblLow.Name = "lblLow"; + lblLow.Size = new System.Drawing.Size(29, 15); + lblLow.TabIndex = 8; + lblLow.Text = "Low"; // // txtLoLo // - this.txtLoLo.Location = new System.Drawing.Point(15, 121); - this.txtLoLo.Name = "txtLoLo"; - this.txtLoLo.Size = new System.Drawing.Size(100, 23); - this.txtLoLo.TabIndex = 7; + txtLoLo.Location = new System.Drawing.Point(15, 121); + txtLoLo.Name = "txtLoLo"; + txtLoLo.Size = new System.Drawing.Size(100, 23); + txtLoLo.TabIndex = 7; // // lblLoLo // - this.lblLoLo.AutoSize = true; - this.lblLoLo.Location = new System.Drawing.Point(12, 103); - this.lblLoLo.Name = "lblLoLo"; - this.lblLoLo.Size = new System.Drawing.Size(81, 15); - this.lblLoLo.TabIndex = 6; - this.lblLoLo.Text = "Extremely low"; + lblLoLo.AutoSize = true; + lblLoLo.Location = new System.Drawing.Point(12, 103); + lblLoLo.Name = "lblLoLo"; + lblLoLo.Size = new System.Drawing.Size(51, 15); + lblLoLo.TabIndex = 6; + lblLoLo.Text = "Low low"; // // txtDeadband // - this.txtDeadband.Location = new System.Drawing.Point(15, 165); - this.txtDeadband.Name = "txtDeadband"; - this.txtDeadband.Size = new System.Drawing.Size(100, 23); - this.txtDeadband.TabIndex = 15; + txtDeadband.Location = new System.Drawing.Point(15, 165); + txtDeadband.Name = "txtDeadband"; + txtDeadband.Size = new System.Drawing.Size(100, 23); + txtDeadband.TabIndex = 15; // // lblDeadband // - this.lblDeadband.AutoSize = true; - this.lblDeadband.Location = new System.Drawing.Point(12, 147); - this.lblDeadband.Name = "lblDeadband"; - this.lblDeadband.Size = new System.Drawing.Size(61, 15); - this.lblDeadband.TabIndex = 14; - this.lblDeadband.Text = "Deadband"; + lblDeadband.AutoSize = true; + lblDeadband.Location = new System.Drawing.Point(12, 147); + lblDeadband.Name = "lblDeadband"; + lblDeadband.Size = new System.Drawing.Size(61, 15); + lblDeadband.TabIndex = 14; + lblDeadband.Text = "Deadband"; // // btnOK // - this.btnOK.Location = new System.Drawing.Point(277, 204); - this.btnOK.Name = "btnOK"; - this.btnOK.Size = new System.Drawing.Size(75, 23); - this.btnOK.TabIndex = 22; - this.btnOK.Text = "OK"; - this.btnOK.UseVisualStyleBackColor = true; - this.btnOK.Click += new System.EventHandler(this.btnOK_Click); + btnOK.Location = new System.Drawing.Point(277, 204); + btnOK.Name = "btnOK"; + btnOK.Size = new System.Drawing.Size(75, 23); + btnOK.TabIndex = 22; + btnOK.Text = "OK"; + btnOK.UseVisualStyleBackColor = true; + btnOK.Click += btnOK_Click; // // btnCancel // - this.btnCancel.Location = new System.Drawing.Point(358, 204); - this.btnCancel.Name = "btnCancel"; - this.btnCancel.Size = new System.Drawing.Size(75, 23); - this.btnCancel.TabIndex = 23; - this.btnCancel.Text = "Cancel"; - this.btnCancel.UseVisualStyleBackColor = true; + btnCancel.Location = new System.Drawing.Point(358, 204); + btnCancel.Name = "btnCancel"; + btnCancel.Size = new System.Drawing.Size(75, 23); + btnCancel.TabIndex = 23; + btnCancel.Text = "Cancel"; + btnCancel.UseVisualStyleBackColor = true; // // FrmLimCreate // - this.AcceptButton = this.btnOK; - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.CancelButton = this.btnCancel; - this.ClientSize = new System.Drawing.Size(445, 239); - this.Controls.Add(this.btnCancel); - this.Controls.Add(this.btnOK); - this.Controls.Add(this.txtDeadband); - this.Controls.Add(this.lblDeadband); - this.Controls.Add(this.txtHiHi); - this.Controls.Add(this.lblHiHi); - this.Controls.Add(this.txtHigh); - this.Controls.Add(this.lblHigh); - this.Controls.Add(this.txtLow); - this.Controls.Add(this.lblLow); - this.Controls.Add(this.txtLoLo); - this.Controls.Add(this.lblLoLo); - this.Controls.Add(this.chkIsShared); - this.Controls.Add(this.chkIsBoundToCnl); - this.Controls.Add(this.txtName); - this.Controls.Add(this.lblName); - this.Controls.Add(this.numLimID); - this.Controls.Add(this.lblLimID); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "FrmLimCreate"; - this.ShowInTaskbar = false; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Create Limit"; - this.Load += new System.EventHandler(this.FrmLimCreate_Load); - ((System.ComponentModel.ISupportInitialize)(this.numLimID)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - + AcceptButton = btnOK; + AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + CancelButton = btnCancel; + ClientSize = new System.Drawing.Size(445, 239); + Controls.Add(btnCancel); + Controls.Add(btnOK); + Controls.Add(txtDeadband); + Controls.Add(lblDeadband); + Controls.Add(txtHiHi); + Controls.Add(lblHiHi); + Controls.Add(txtHigh); + Controls.Add(lblHigh); + Controls.Add(txtLow); + Controls.Add(lblLow); + Controls.Add(txtLoLo); + Controls.Add(lblLoLo); + Controls.Add(chkIsShared); + Controls.Add(chkIsBoundToCnl); + Controls.Add(txtName); + Controls.Add(lblName); + Controls.Add(numLimID); + Controls.Add(lblLimID); + FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + MaximizeBox = false; + MinimizeBox = false; + Name = "FrmLimCreate"; + ShowInTaskbar = false; + StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + Text = "Create Limit"; + Load += FrmLimCreate_Load; + ((System.ComponentModel.ISupportInitialize)numLimID).EndInit(); + ResumeLayout(false); + PerformLayout(); } #endregion diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmLimCreate.cs b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmLimCreate.cs index 1ce13b63d..ae24ec9d7 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmLimCreate.cs +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmLimCreate.cs @@ -20,7 +20,7 @@ * * Author : Mikhail Shiryaev * Created : 2022 - * Modified : 2022 + * Modified : 2023 */ using Scada.Admin.App.Code; @@ -54,23 +54,20 @@ private FrmLimCreate() /// /// Initializes a new instance of the class. /// - public FrmLimCreate(ConfigDatabase configDatabase) + public FrmLimCreate(ConfigDatabase configDatabase, int cnlNum) : this() { this.configDatabase = configDatabase ?? throw new ArgumentNullException(nameof(configDatabase)); - CnlNum = 0; + CnlNum = cnlNum; LimEntity = null; - - numLimID.Value = configDatabase.LimTable.GetNextPk(); - numLimID.Maximum = ConfigDatabase.MaxID; } /// - /// Gets or sets the channel number for which a limit is created. + /// Gets the channel number for which a limit is created. /// - public int CnlNum { get; set; } + public int CnlNum { get; } /// /// Gets the limit. @@ -152,8 +149,11 @@ private void FrmLimCreate_Load(object sender, EventArgs e) { FormTranslator.Translate(this, GetType().FullName); - if (CnlNum > 0) - txtName.Text = string.Format(AppPhrases.DefaultLimName, CnlNum); + numLimID.Maximum = ConfigDatabase.MaxID; + numLimID.Value = configDatabase.LimTable.PkExists(CnlNum) + ? configDatabase.LimTable.GetNextPk() // get available limit ID + : CnlNum; // limit ID equals channel number + txtName.Text = string.Format(AppPhrases.DefaultLimName, CnlNum); } private void btnOK_Click(object sender, EventArgs e) diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmLimCreate.resx b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmLimCreate.resx index f298a7be8..af32865ec 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmLimCreate.resx +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Forms/Tables/FrmLimCreate.resx @@ -1,4 +1,64 @@ - + + + diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/ScadaAdmin.csproj b/ScadaAdmin/ScadaAdmin/ScadaAdmin/ScadaAdmin.csproj index 7b68a2400..5998cd253 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/ScadaAdmin.csproj +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/ScadaAdmin.csproj @@ -12,7 +12,7 @@ Copyright © 2023 lamp.ico 6.1.1 - 6.1.1.0 + 6.1.1.1 diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.en-GB/BaseXML/CnlStatus.xml b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.en-GB/BaseXML/CnlStatus.xml index eb254c085..cca9c31c5 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.en-GB/BaseXML/CnlStatus.xml +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.en-GB/BaseXML/CnlStatus.xml @@ -52,7 +52,7 @@ 11 - Extremely low + Low low Blue Blue DodgerBlue @@ -92,7 +92,7 @@ 15 - Extremely high + High high Red Red LightCoral diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.en-GB/BaseXML/DevType.xml b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.en-GB/BaseXML/DevType.xml index 8f397418f..eb4b71bcb 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.en-GB/BaseXML/DevType.xml +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.en-GB/BaseXML/DevType.xml @@ -216,6 +216,12 @@ DrvMqttPublisher Transmits channel data to MQTT broker and receives commands + + 237 + CSV Reader + DrvCsvReader + Reads data from a CSV file + 1001 Custom driver diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.en-GB/BaseXML/ViewType.xml b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.en-GB/BaseXML/ViewType.xml index 83344e4e3..cb5f7fa64 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.en-GB/BaseXML/ViewType.xml +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.en-GB/BaseXML/ViewType.xml @@ -2,40 +2,40 @@ 1 - Table view + Table TableView tbl Requires Main Plugin 2 - Scheme view + Scheme SchemeView sch Requires Scheme Plugin 3 - Web page view + Web page WebPageView Requires Web Page Plugin 4 - Chart Pro view + Chart Pro ChartProView Requires Chart Pro Plugin 5 - Dashboard view + Dashboard DashboardView dash Requires Dashboard Plugin 6 - Map view + Map MapView map Requires Map Plugin diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.ru-RU/BaseXML/CnlStatus.xml b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.ru-RU/BaseXML/CnlStatus.xml index afb5e9c22..0b2d4d14a 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.ru-RU/BaseXML/CnlStatus.xml +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.ru-RU/BaseXML/CnlStatus.xml @@ -102,7 +102,7 @@ 21 - Good + Хороший Green Green LightGreen diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.ru-RU/BaseXML/DevType.xml b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.ru-RU/BaseXML/DevType.xml index 7f22f19d4..dc1cb3df8 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.ru-RU/BaseXML/DevType.xml +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.ru-RU/BaseXML/DevType.xml @@ -216,6 +216,12 @@ DrvMqttPublisher Транслирует данные каналов на MQTT-брокер и принимает команды + + 237 + CSV-считыватель + DrvCsvReader + Считывает данные из CSV-файла + 1001 Пользовательский драйвер diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.ru-RU/BaseXML/Quantity.xml b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.ru-RU/BaseXML/Quantity.xml index 709b71988..d29e09b0d 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.ru-RU/BaseXML/Quantity.xml +++ b/ScadaAdmin/ScadaAdmin/ScadaAdmin/Templates/EmptyProject.ru-RU/BaseXML/Quantity.xml @@ -51,7 +51,7 @@ Состояние State lamp.png - States + Состояния 12 diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdminCommon/Config/NumberingOptions.cs b/ScadaAdmin/ScadaAdmin/ScadaAdminCommon/Config/NumberingOptions.cs index 5200b8a01..d5cdbb738 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdminCommon/Config/NumberingOptions.cs +++ b/ScadaAdmin/ScadaAdmin/ScadaAdminCommon/Config/NumberingOptions.cs @@ -74,24 +74,17 @@ public int AdjustID(int nextID) /// public int AdjustID(int nextID, bool keepGap) { - if (!keepGap && (Multiplicity <= 1 || ((nextID - Shift) % Multiplicity) == 0)) - return nextID; - int adjustedID = keepGap && Gap > 0 ? nextID + Gap : nextID; if (Multiplicity > 1) { - int remainder = adjustedID % Multiplicity; + int remainder = (adjustedID - Shift) % Multiplicity; if (remainder > 0) adjustedID = adjustedID - remainder + Multiplicity; - - return adjustedID + Shift; - } - else - { - return adjustedID; } + + return adjustedID; } /// diff --git a/ScadaAdmin/ScadaAdmin/ScadaAdminCommon/Lang/ScadaAdmin.en-GB.xml b/ScadaAdmin/ScadaAdmin/ScadaAdminCommon/Lang/ScadaAdmin.en-GB.xml index 1ff35000c..c97a00ad9 100644 --- a/ScadaAdmin/ScadaAdmin/ScadaAdminCommon/Lang/ScadaAdmin.en-GB.xml +++ b/ScadaAdmin/ScadaAdmin/ScadaAdminCommon/Lang/ScadaAdmin.en-GB.xml @@ -104,10 +104,10 @@ Name Is Bound to Channels Is Shared - Extremely Low + Low Low Low High - Extremely High + High High Deadband @@ -362,10 +362,10 @@ Limit Create Show only shared limits - Extremely low + Low low Low High - Extremely high + High high Deadband Archives Events @@ -415,10 +415,10 @@ Name Bound to channels Shared - Extremely low + Low low Low High - Extremely high + High high Deadband OK Cancel diff --git a/ScadaAgent/ScadaAgent/AgentClient/AgentClient.csproj b/ScadaAgent/ScadaAgent/AgentClient/AgentClient.csproj index 2b1e6505c..27f6f82b2 100644 --- a/ScadaAgent/ScadaAgent/AgentClient/AgentClient.csproj +++ b/ScadaAgent/ScadaAgent/AgentClient/AgentClient.csproj @@ -4,12 +4,11 @@ netstandard2.0 Scada.Agent.Client True + 6.1.0 Mikhail Shiryaev Rapid Software LLC Rapid SCADA Copyright © 2023 - 6.1.0 - 6.1.0.0 diff --git a/ScadaAgent/ScadaAgent/ScadaAgentApp/ScadaAgentApp.csproj b/ScadaAgent/ScadaAgent/ScadaAgentApp/ScadaAgentApp.csproj index f7aeac01c..5186db211 100644 --- a/ScadaAgent/ScadaAgent/ScadaAgentApp/ScadaAgentApp.csproj +++ b/ScadaAgent/ScadaAgent/ScadaAgentApp/ScadaAgentApp.csproj @@ -9,7 +9,7 @@ Rapid SCADA Copyright © 2023 6.1.0 - 6.1.0.0 + 6.1.0.1 diff --git a/ScadaAgent/ScadaAgent/ScadaAgentEngine/PathBuilder.cs b/ScadaAgent/ScadaAgent/ScadaAgentEngine/PathBuilder.cs index ed5f7090c..43ef0e21d 100644 --- a/ScadaAgent/ScadaAgent/ScadaAgentEngine/PathBuilder.cs +++ b/ScadaAgent/ScadaAgent/ScadaAgentEngine/PathBuilder.cs @@ -20,7 +20,7 @@ * * Author : Mikhail Shiryaev * Created : 2021 - * Modified : 2021 + * Modified : 2023 */ using Scada.Protocol; @@ -38,7 +38,7 @@ internal class PathBuilder { private readonly string instanceDir; // the instance directory private readonly string instanceLogDir; // the instance log directory - private readonly string agentShortDir; // the short name of the Agent directory + private readonly string agentDir; // the full name of the Agent directory /// @@ -48,9 +48,7 @@ public PathBuilder(string instanceDir, string instanceLogDir, string agentDir) { this.instanceDir = instanceDir ?? throw new ArgumentNullException(nameof(instanceDir)); this.instanceLogDir = instanceLogDir ?? throw new ArgumentNullException(nameof(instanceLogDir)); - - DirectoryInfo agentDirInfo = new DirectoryInfo(agentDir); - agentShortDir = agentDirInfo.Name; + this.agentDir = agentDir ?? throw new ArgumentNullException(nameof(agentDir)); } @@ -86,7 +84,7 @@ private bool FolderToString(TopFolder topFolder, out string path) return true; case TopFolder.Agent: - path = agentShortDir; + path = "ScadaAgent"; return true; default: @@ -159,16 +157,23 @@ public string GetAbsolutePath(RelativePath relativePath) { List paths = new List(); - if (relativePath.AppFolder == AppFolder.Log && !string.IsNullOrEmpty(instanceLogDir)) - paths.Add(instanceLogDir); + if (relativePath.TopFolder == TopFolder.Agent) + { + paths.Add(agentDir); // this Agent application + } else - paths.Add(instanceDir); + { + if (relativePath.AppFolder == AppFolder.Log && !string.IsNullOrEmpty(instanceLogDir)) + paths.Add(instanceLogDir); + else + paths.Add(instanceDir); - if (FolderToString(relativePath.TopFolder, out string path)) - paths.Add(path); + if (FolderToString(relativePath.TopFolder, out string topPath)) + paths.Add(topPath); + } - if (FolderToString(relativePath.AppFolder, relativePath.TopFolder == TopFolder.Web, out path)) - paths.Add(path); + if (FolderToString(relativePath.AppFolder, relativePath.TopFolder == TopFolder.Web, out string appPath)) + paths.Add(appPath); if (!string.IsNullOrEmpty(relativePath.Path)) paths.Add(relativePath.Path); diff --git a/ScadaAgent/ScadaAgent/ScadaAgentEngine/ScadaAgentEngine.csproj b/ScadaAgent/ScadaAgent/ScadaAgentEngine/ScadaAgentEngine.csproj index cc4b9be06..17590c0a0 100644 --- a/ScadaAgent/ScadaAgent/ScadaAgentEngine/ScadaAgentEngine.csproj +++ b/ScadaAgent/ScadaAgent/ScadaAgentEngine/ScadaAgentEngine.csproj @@ -9,7 +9,7 @@ Mikhail Shiryaev Copyright © 2023 6.1.0 - 6.1.0.0 + 6.1.0.1 diff --git a/ScadaAgent/ScadaAgent/ScadaAgentWkr/ScadaAgentWkr.csproj b/ScadaAgent/ScadaAgent/ScadaAgentWkr/ScadaAgentWkr.csproj index d152f4c44..dea2ea60a 100644 --- a/ScadaAgent/ScadaAgent/ScadaAgentWkr/ScadaAgentWkr.csproj +++ b/ScadaAgent/ScadaAgent/ScadaAgentWkr/ScadaAgentWkr.csproj @@ -11,7 +11,7 @@ Rapid SCADA Copyright © 2023 6.1.0 - 6.1.0.0 + 6.1.0.1 diff --git a/ScadaComm/OpenDrivers/DrvMqttClient.Common/Config/SubscriptionConfig.cs b/ScadaComm/OpenDrivers/DrvMqttClient.Common/Config/SubscriptionConfig.cs index fde7015a0..a22721c69 100644 --- a/ScadaComm/OpenDrivers/DrvMqttClient.Common/Config/SubscriptionConfig.cs +++ b/ScadaComm/OpenDrivers/DrvMqttClient.Common/Config/SubscriptionConfig.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Scada.ComponentModel; +using System.Collections.ObjectModel; using System.Xml; using NCM = System.ComponentModel; @@ -23,7 +24,7 @@ public SubscriptionConfig() ReadOnly = false; JsEnabled = false; JsFileName = ""; - SubItems = new List(); + SubItems = new ObservableCollection(); Parent = null; } @@ -56,7 +57,7 @@ public SubscriptionConfig() /// Gets the subitems that represent multiple device tags for the topic. /// [DisplayName, Category, Description, NCM.TypeConverter(typeof(CollectionConverter))] - public List SubItems { get; private set; } + public ObservableCollection SubItems { get; } /// diff --git a/ScadaComm/OpenDrivers/DrvMqttClient.Common/DrvMqttClient.Common.csproj b/ScadaComm/OpenDrivers/DrvMqttClient.Common/DrvMqttClient.Common.csproj index dc8270b43..cf53b1943 100644 --- a/ScadaComm/OpenDrivers/DrvMqttClient.Common/DrvMqttClient.Common.csproj +++ b/ScadaComm/OpenDrivers/DrvMqttClient.Common/DrvMqttClient.Common.csproj @@ -10,7 +10,7 @@ Rapid SCADA Copyright © 2023 6.0.0 - 6.0.0.3 + 6.0.0.4 diff --git a/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DevMqttClientLogic.cs b/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DevMqttClientLogic.cs index 701169002..a06eddb7c 100644 --- a/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DevMqttClientLogic.cs +++ b/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DevMqttClientLogic.cs @@ -162,8 +162,12 @@ private void ExecuteJavaScript(ReceivedMessage message, SubscriptionTag subscrip { // initialize engine jsEngine ??= new Engine() - .SetValue("log", new Action(s => Log.WriteLine(s))) - .SetValue("setValue", new Action((i, x) => { subscriptionTag.JsValues[i] = x; })); + .SetValue("log", new Action(s => Log.WriteLine(s))); + + // set script methods and variables that depend on current call + jsEngine.SetValue("setValue", new Action((i, x) => { subscriptionTag.JsValues[i] = x; })); + jsEngine.SetValue("topic", message.Topic); + jsEngine.SetValue("payload", message.Payload); // load source code subscriptionTag.JsSource ??= @@ -178,10 +182,6 @@ private void ExecuteJavaScript(ReceivedMessage message, SubscriptionTag subscrip subscriptionTag.JsValues[i] = double.NaN; } - // set script variables - jsEngine.SetValue("topic", message.Topic); - jsEngine.SetValue("payload", message.Payload); - try { // execute script @@ -307,14 +307,15 @@ public override void InitDeviceTags() { if (subscriptionConfig.JsEnabled && subscriptionConfig.SubItems.Count > 0) { - for (int i = 0, cnt = subscriptionConfig.SubItems.Count; i < cnt; i++) + int idx = 0; + + foreach (string subItem in subscriptionConfig.SubItems) { - string suffix = "." + subscriptionConfig.SubItems[i]; DeviceTag deviceTag = tagGroup.AddTag( - subscriptionConfig.TagCode + suffix, - subscriptionConfig.DisplayName + suffix); + subscriptionConfig.TagCode + "." + subItem, + subscriptionConfig.DisplayName + "." + subItem); - if (i == 0) + if (idx++ == 0) Subscribe(subscriptionConfig, deviceTag); } } diff --git a/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DrvMqttClient.Logic.csproj b/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DrvMqttClient.Logic.csproj index b9f329274..047b22327 100644 --- a/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DrvMqttClient.Logic.csproj +++ b/ScadaComm/OpenDrivers/DrvMqttClient.Logic/DrvMqttClient.Logic.csproj @@ -11,7 +11,7 @@ Rapid SCADA Copyright © 2023 6.0.0 - 6.0.0.3 + 6.0.0.4 diff --git a/ScadaComm/OpenDrivers/DrvMqttClient.View/DevMqttClientView.cs b/ScadaComm/OpenDrivers/DrvMqttClient.View/DevMqttClientView.cs index 43e86d074..b15425728 100644 --- a/ScadaComm/OpenDrivers/DrvMqttClient.View/DevMqttClientView.cs +++ b/ScadaComm/OpenDrivers/DrvMqttClient.View/DevMqttClientView.cs @@ -65,14 +65,13 @@ public override ICollection GetCnlPrototypes() { if (subscriptionConfig.JsEnabled && subscriptionConfig.SubItems.Count > 0) { - for (int i = 0, cnt = subscriptionConfig.SubItems.Count; i < cnt; i++) + foreach (string subItem in subscriptionConfig.SubItems) { - string suffix = "." + subscriptionConfig.SubItems[i]; cnlPrototypes.Add(new CnlPrototype { - Name = subscriptionConfig.DisplayName + suffix, + Name = subscriptionConfig.DisplayName + "." + subItem, CnlTypeID = CnlTypeID.Input, - TagCode = subscriptionConfig.TagCode + suffix, + TagCode = subscriptionConfig.TagCode + "." + subItem, EventMask = eventMask }); } diff --git a/ScadaComm/OpenDrivers/DrvMqttClient.View/DrvMqttClient.View.csproj b/ScadaComm/OpenDrivers/DrvMqttClient.View/DrvMqttClient.View.csproj index 5f9753978..08c50fe0b 100644 --- a/ScadaComm/OpenDrivers/DrvMqttClient.View/DrvMqttClient.View.csproj +++ b/ScadaComm/OpenDrivers/DrvMqttClient.View/DrvMqttClient.View.csproj @@ -12,7 +12,7 @@ Rapid SCADA Copyright © 2023 6.0.0 - 6.0.0.3 + 6.0.0.4 diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.Logic/DevCsvReaderLogic.cs b/ScadaComm/OpenDrivers2/DrvCsvReader.Logic/DevCsvReaderLogic.cs new file mode 100644 index 000000000..f43deb36b --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.Logic/DevCsvReaderLogic.cs @@ -0,0 +1,476 @@ +// Copyright (c) Rapid Software LLC. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Scada.Comm.Config; +using Scada.Comm.Devices; +using Scada.Comm.Drivers.DrvSms; +using Scada.Comm.Lang; +using Scada.Data.Const; +using Scada.Lang; +using System.Data; +using System.Globalization; + +namespace Scada.Comm.Drivers.DrvCsvReader.Logic +{ + /// + /// Implements the device logic. + /// Реализует логику устройства. + /// + internal class DevCsvReaderLogic : DeviceLogic + { + /// + /// Represents a data row. + /// + private class DataRow + { + public DataRow(int tagCount) + { + Timestamp = DateTime.MinValue; + Values = new double[tagCount]; + } + public DateTime Timestamp { get; set; } + public double[] Values { get; } + } + + /// + /// The maximum line length in bytes. + /// + private const int MaxLineLength = 1024; + /// + /// The string that identifies a header row. + /// + private const string HeaderText = "Timestamp"; + /// + /// The initial year in Demo mode. + /// + private const int InitialYearDemo = 2001; + /// + /// Specifies the time interval when data is considered outdated. + /// + private static readonly TimeSpan DataLifetime = TimeSpan.FromMinutes(1); + + private readonly CsvReaderOptions options; // the CSV reader options + private readonly NumberFormatInfo nfi; // the value format + private FileStream fileStream; // the stream of the data file + private TextReader textReader; // reads the data file + private string[] tagNames; // the tag names from file + private bool justOpened; // indicates that the data file is just opened + private long lastFileSize; // the file size measured after iteration + private DateTime lastTimestamp; // the last timestamp parsed + private DateTime prevVirtualTime; // the previous time in Demo mode + private DataRow prevDataRow; // the previously read data row + + + /// + /// Gets a value indicating whether the data file is open. + /// + private bool FileIsOpen => textReader != null; + + + /// + /// Initializes a new instance of the class. + /// + public DevCsvReaderLogic(ICommContext commContext, ILineContext lineContext, DeviceConfig deviceConfig) + : base(commContext, lineContext, deviceConfig) + { + options = new CsvReaderOptions(deviceConfig.PollingOptions.CustomOptions); + nfi = new NumberFormatInfo { NumberDecimalSeparator = options.DecimalSeparator }; + fileStream = null; + textReader = null; + tagNames = Array.Empty(); + justOpened = false; + lastFileSize = 0; + lastTimestamp = DateTime.MinValue; + prevVirtualTime = DateTime.MinValue; + prevDataRow = null; + + ConnectionRequired = false; + } + + + /// + /// Defines a full path and opens a data file. + /// + private bool OpenDataFile() + { + string fileName = string.IsNullOrEmpty(options.FileName) + ? $"{DriverUtils.DriverCode}_{DeviceNum:D3}.csv" + : options.FileName; + + string filePath = Path.IsPathRooted(fileName) + ? fileName + : Path.Combine(AppDirs.StorageDir, fileName); + + if (File.Exists(filePath)) + { + try + { + fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + textReader = new StreamReader(fileStream); + justOpened = true; + + Log.WriteLine(Locale.IsRussian ? + "Открыт файл данных {0}" : + "Data file {0} opened", filePath); + return true; + } + catch (Exception ex) + { + Log.WriteLine(Locale.IsRussian ? + "Ошибка: Не удалось открыть файл данных: {0}" : + "Error: Unable to open data file: {0}", ex.Message); + return false; + } + } + else + { + Log.WriteLine(Locale.IsRussian ? + "Ошибка: Не найден файл данных {0}" : + "Error: Data file {0} not found", filePath); + return false; + } + } + + /// + /// Closes the data file if it is open. + /// + private void CloseDataFile() + { + fileStream?.Dispose(); + textReader?.Dispose(); + justOpened = false; + lastFileSize = 0; + lastTimestamp = DateTime.MinValue; + } + + /// + /// Reads tag names from the file. + /// + private void ReadTagNames() + { + Log.WriteLine(); + Log.WriteAction(Locale.IsRussian ? + "Чтение наименований тегов для устройства {0}" : + "Read tag names for the device {0}", Title); + + if (OpenDataFile()) + { + try + { + string header = textReader.ReadLine(); + string[] lineParts = header.Split(options.FieldDelimiter); + + if (lineParts[0] == HeaderText && lineParts.Length > 1) + tagNames = lineParts.AsSpan(1).ToArray(); + } + catch (Exception ex) + { + Log.WriteLine(CommPhrases.ErrorPrefix + ex.Message); + } + } + } + + /// + /// Reads data from the file. + /// + private void ReadData() + { + if (!FileIsOpen) + OpenDataFile(); + + try + { + if (FileIsOpen) + { + if (options.ReadMode == ReadMode.RealTime) + ReadDataRealTime(); + else + ReadDataDemo(); + + DeviceData.SetDateTime(TagCode.Timestamp, lastTimestamp, + lastTimestamp > DateTime.MinValue ? CnlStatusID.Defined : CnlStatusID.Undefined); + DeviceData.Set(TagCode.Position, fileStream.Position); + lastFileSize = fileStream.Length; + } + else + { + InvalidateData(); + } + } + catch (Exception ex) + { + DeviceData.Invalidate(0, options.TagCount); + LastRequestOK = false; + Log.WriteLine(Locale.IsRussian ? + "Ошибка при чтении из файла: {0}" : + "Error reading from file: {0}", ex.Message); + } + } + + /// + /// Reads data in RealTime mode. + /// + private void ReadDataRealTime() + { + bool newDataFound = false; + string line; + + if (fileStream.Length < lastFileSize) + { + Log.WriteLine(Locale.IsRussian ? + "Файл был перезаписан" : + "File was overwritten"); + justOpened = true; + } + + if (justOpened) + { + line = ReadLastLine(); + justOpened = false; + } + else + { + line = textReader.ReadLine(); + } + + while (line != null) + { + DateTime utcNow = DateTime.UtcNow; + + if (ParseDataRow(line, out DataRow dataRow) && DataRowIsCurrent(dataRow, utcNow)) + { + newDataFound = true; + lastTimestamp = dataRow.Timestamp; + CopyValues(dataRow); + } + + line = textReader.ReadLine(); + } + + LogNewData(newDataFound); + } + + /// + /// Reads data in Demo mode. + /// + private void ReadDataDemo() + { + DateTime virtualTime = GetVirtualTime(); + bool newDataFound = false; + DataRow dataRow; + + // start over + if (prevVirtualTime > virtualTime) + { + prevDataRow = null; + fileStream.Seek(0, SeekOrigin.Begin); + } + + // read data + string line = ""; + dataRow = prevDataRow; + + while (line != null && (dataRow == null || dataRow.Timestamp < virtualTime)) + { + line = textReader.ReadLine(); + dataRow = ParseDataRow(line); + } + + // get tag values + if (DataRowIsCurrent(dataRow, virtualTime)) + { + newDataFound = prevDataRow != dataRow; + lastTimestamp = dataRow.Timestamp; + CopyValues(dataRow); + } + + LogNewData(newDataFound); + prevVirtualTime = virtualTime; + prevDataRow = dataRow; + } + + /// + /// Reads the last line in the data file. + /// + private string ReadLastLine() + { + if (fileStream.Length <= MaxLineLength) + fileStream.Seek(0, SeekOrigin.Begin); + else + fileStream.Seek(-MaxLineLength, SeekOrigin.End); + + // skip first line + if (textReader.ReadLine() == null) + return null; + + // search for last line + string currentLine; + string lastLine = null; + + do + { + currentLine = textReader.ReadLine(); + + if (currentLine != null) + lastLine = currentLine; + } while (currentLine != null); + + return lastLine; + } + + /// + /// Converts the line parts to a data row. + /// + private bool ParseDataRow(string line, out DataRow dataRow) + { + if (!string.IsNullOrEmpty(line)) + { + string[] lineParts = line.Split(options.FieldDelimiter); + + if (DateTime.TryParse(lineParts[0], out DateTime timestamp)) + { + timestamp = DateTime.SpecifyKind(timestamp, DateTimeKind.Utc); + dataRow = new DataRow(options.TagCount) { Timestamp = timestamp }; + RetrieveValues(lineParts, dataRow); + return true; + } + } + + dataRow = null; + return false; + } + + /// + /// Converts the line parts to a data row. + /// + private DataRow ParseDataRow(string line) + { + ParseDataRow(line, out DataRow dataRow); + return dataRow; + } + + /// + /// Retrieves data values from the line parts. + /// + private void RetrieveValues(string[] lineParts, DataRow dataRow) + { + for (int valIdx = 0; valIdx < dataRow.Values.Length; valIdx++) + { + int partIdx = valIdx + 1; + dataRow.Values[valIdx] = partIdx <= lineParts.Length && + double.TryParse(lineParts[partIdx], NumberStyles.Float, nfi, out double value) + ? value + : double.NaN; + } + } + + /// + /// Copies the values of the data row to the device data. + /// + private void CopyValues(DataRow dataRow) + { + for (int i = 0; i < dataRow.Values.Length; i++) + { + DeviceData.Set(i, dataRow.Values[i]); + } + } + + /// + /// Checks whether the timestamp of the data row is close to the current time. + /// + private static bool DataRowIsCurrent(DataRow dataRow, DateTime currentTime) + { + return dataRow != null && + currentTime - DataLifetime <= dataRow.Timestamp && dataRow.Timestamp <= currentTime + DataLifetime; + } + + /// + /// Logs a message indicating whether new data was found or not. + /// + private void LogNewData(bool newDataFound) + { + if (newDataFound) + { + Log.WriteLine(Locale.IsRussian ? + "Считаны новые данные" : + "New data has been read"); + } + else + { + Log.WriteLine(Locale.IsRussian ? + "Новых данных нет" : + "No new data available"); + } + } + + /// + /// Получить виртуальное время на основе текущего времени и установленного периода. + /// + private DateTime GetVirtualTime() + { + DateTime utcNow = DateTime.UtcNow; + DateTime startDate = new(InitialYearDemo, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + return options.DemoPeriod switch + { + DemoPeriod.OneHour => startDate.Add(utcNow.TimeOfDay).AddHours(-utcNow.Hour), + DemoPeriod.OneDay => startDate.Add(utcNow.TimeOfDay), + DemoPeriod.OneMonth => startDate.Add(utcNow.TimeOfDay).AddDays(utcNow.Day - 1), + _ => throw new ScadaException("Uknonwn demo period.") + }; ; + } + + + /// + /// Performs actions when starting a communication line. + /// + public override void OnCommLineStart() + { + ReadTagNames(); + } + + /// + /// Performs actions when terminating a communication line. + /// + public override void OnCommLineTerminate() + { + CloseDataFile(); + } + + /// + /// Initializes the device tags. + /// + public override void InitDeviceTags() + { + // Main Data group + TagGroup tagGroup = new("Main Data"); + + for (int tagNum = 1; tagNum <= options.TagCount; tagNum++) + { + string tagCode = TagCode.GetMainTagCode(tagNum); + tagGroup.AddTag( + tagCode, + tagNum <= tagNames.Length ? tagNames[tagNum - 1] : tagCode); + } + + DeviceTags.AddGroup(tagGroup); + + // Reading Status group + tagGroup = new("Reading Status"); + tagGroup.AddTag(TagCode.Timestamp, TagCode.Timestamp).SetFormat(TagFormat.DateTime); + tagGroup.AddTag(TagCode.Position, TagCode.Position).SetFormat(TagFormat.IntNumber); + DeviceTags.AddGroup(tagGroup); + } + + /// + /// Performs a communication session. + /// + public override void Session() + { + base.Session(); + ReadData(); + FinishRequest(); + FinishSession(); + } + } +} diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.Logic/DrvCsvReader.Logic.csproj b/ScadaComm/OpenDrivers2/DrvCsvReader.Logic/DrvCsvReader.Logic.csproj new file mode 100644 index 000000000..a82dbec72 --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.Logic/DrvCsvReader.Logic.csproj @@ -0,0 +1,30 @@ + + + + net6.0 + enable + disable + Scada.Comm.Drivers.DrvCsvReader.Logic + Mikhail Shiryaev + Rapid Software LLC + Rapid SCADA + Copyright © 2023 + 6.0.0 + 6.0.0.0 + + + + + + + ..\..\ScadaComm\ScadaCommCommon\bin\Release\netstandard2.0\ScadaCommCommon.dll + + + ..\..\..\ScadaCommon\ScadaCommon\bin\Release\netstandard2.0\ScadaCommon.dll + + + ..\..\..\ScadaCommon\ScadaCommon.Log\bin\Release\netstandard2.0\ScadaCommon.Log.dll + + + + diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.Logic/DrvCsvReaderLogic.cs b/ScadaComm/OpenDrivers2/DrvCsvReader.Logic/DrvCsvReaderLogic.cs new file mode 100644 index 000000000..1bf5be973 --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.Logic/DrvCsvReaderLogic.cs @@ -0,0 +1,36 @@ +// Copyright (c) Rapid Software LLC. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Scada.Comm.Config; +using Scada.Comm.Devices; + +namespace Scada.Comm.Drivers.DrvCsvReader.Logic +{ + /// + /// Implements the driver logic. + /// Реализует логику драйвера. + /// + public class DrvCsvReaderLogic : DriverLogic + { + /// + /// Initializes a new instance of the class. + /// + public DrvCsvReaderLogic(ICommContext commContext) + : base(commContext) + { + } + + /// + /// Gets the driver code. + /// + public override string Code => DriverUtils.DriverCode; + + /// + /// Creates a new device. + /// + public override DeviceLogic CreateDevice(ILineContext lineContext, DeviceConfig deviceConfig) + { + return new DevCsvReaderLogic(CommContext, lineContext, deviceConfig); + } + } +} diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.Logic/Storage/DrvCsvReader_001.csv b/ScadaComm/OpenDrivers2/DrvCsvReader.Logic/Storage/DrvCsvReader_001.csv new file mode 100644 index 000000000..3fa0984b3 --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.Logic/Storage/DrvCsvReader_001.csv @@ -0,0 +1,4 @@ +Timestamp,TagA,TagB,TagC +2023-11-04 00:00:00,1.1,1,0 +2023-11-04 00:01:00,1.2,0,1 +2023-11-04 00:02:00,1.3,1,0 diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/CsvReaderOptions.cs b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/CsvReaderOptions.cs new file mode 100644 index 000000000..0f4444743 --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/CsvReaderOptions.cs @@ -0,0 +1,78 @@ +// Copyright (c) Rapid Software LLC. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Scada.Config; +using System.ComponentModel; + +namespace Scada.Comm.Drivers.DrvCsvReader +{ + /// + /// Represents CSV reader options. + /// Представляет параметры считывателя CSV. + /// + internal class CsvReaderOptions + { + /// + /// Initializes a new instance of the class. + /// + public CsvReaderOptions() + { + TagCount = 1; + FileName = ""; + DecimalSeparator = "."; + FieldDelimiter = ","; + ReadMode = ReadMode.RealTime; + DemoPeriod = DemoPeriod.OneHour; + } + + /// + /// Initializes a new instance of the class. + /// + public CsvReaderOptions(OptionList options) + : this() + { + TagCount = options.GetValueAsInt("TagCount", TagCount); + FileName = options.GetValueAsString("FileName", FileName); + DecimalSeparator = options.GetValueAsString("DecimalSeparator", DecimalSeparator); + FieldDelimiter = options.GetValueAsString("FieldDelimiter", FieldDelimiter); + ReadMode = options.GetValueAsEnum("ReadMode", ReadMode); + DemoPeriod = options.GetValueAsEnum("DemoPeriod", DemoPeriod); + } + + + [Description("The number of device tags.")] + public int TagCount { get; set; } + + [Description("The name of the CSV file containing data to read.")] + public string FileName { get; set; } + + [Description("The string used as the decimal separator in numeric values.")] + public string DecimalSeparator { get; set; } + + [Description("The delimiter used to separate fields.")] + public string FieldDelimiter { get; set; } + + [Description("The reading mode. " + + "In RealTime mode, the driver reads data according to the current time. " + + "In Demo mode, the driver reads data cyclically.")] + public ReadMode ReadMode { get; set; } + + [Description("The data period defining the reading loop in demo mode.")] + public DemoPeriod DemoPeriod { get; set; } + + + /// + /// Adds the options to the list. + /// + public void AddToOptionList(OptionList options) + { + options.Clear(); + options["TagCount"] = TagCount.ToString(); + options["FileName"] = FileName; + options["DecimalSeparator"] = DecimalSeparator; + options["FieldDelimiter"] = FieldDelimiter; + options["ReadMode"] = ReadMode.ToString(); + options["DemoPeriod"] = DemoPeriod.ToString(); + } + } +} diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/DemoPeriod.cs b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/DemoPeriod.cs new file mode 100644 index 000000000..6a3d238b7 --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/DemoPeriod.cs @@ -0,0 +1,16 @@ +// Copyright (c) Rapid Software LLC. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Scada.Comm.Drivers.DrvCsvReader +{ + /// + /// Specifies the periods in demo mode. + /// Задаёт периоды в демо-режиме. + /// + internal enum DemoPeriod + { + OneHour, + OneDay, + OneMonth + } +} diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/DriverUtils.cs b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/DriverUtils.cs new file mode 100644 index 000000000..1457380b8 --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/DriverUtils.cs @@ -0,0 +1,17 @@ +// Copyright (c) Rapid Software LLC. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Scada.Comm.Drivers.DrvCsvReader +{ + /// + /// The class provides helper methods for the driver. + /// Класс, предоставляющий вспомогательные методы для драйвера. + /// + internal static class DriverUtils + { + /// + /// The driver code. + /// + public const string DriverCode = "DrvCsvReader"; + } +} diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/DrvCsvReader.Shared.projitems b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/DrvCsvReader.Shared.projitems new file mode 100644 index 000000000..8b1f81119 --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/DrvCsvReader.Shared.projitems @@ -0,0 +1,18 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + 1afbc156-92ee-4118-84d6-ae163d0e654e + + + Scada.Comm.Drivers.DrvCsvReader + + + + + + + + + \ No newline at end of file diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/DrvCsvReader.Shared.shproj b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/DrvCsvReader.Shared.shproj new file mode 100644 index 000000000..b7234b969 --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/DrvCsvReader.Shared.shproj @@ -0,0 +1,13 @@ + + + + 1afbc156-92ee-4118-84d6-ae163d0e654e + 14.0 + + + + + + + + diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/ReadMode.cs b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/ReadMode.cs new file mode 100644 index 000000000..41f44e652 --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/ReadMode.cs @@ -0,0 +1,22 @@ +// Copyright (c) Rapid Software LLC. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Scada.Comm.Drivers.DrvCsvReader +{ + /// + /// Specifies the reading modes. + /// Задаёт режимы чтения. + /// + internal enum ReadMode + { + /// + /// The driver reads data according to the current time + /// + RealTime, + + /// + /// The driver reads data cyclically. + /// + Demo + } +} diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/TagCode.cs b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/TagCode.cs new file mode 100644 index 000000000..0727e9a4b --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.Shared/TagCode.cs @@ -0,0 +1,20 @@ +// Copyright (c) Rapid Software LLC. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Scada.Comm.Drivers.DrvSms +{ + /// + /// Specifies the device tag codes. + /// Задаёт коды тегов устройства. + /// + internal static class TagCode + { + public const string Timestamp = nameof(Timestamp); + public const string Position = nameof(Position); + + public static string GetMainTagCode(int tagNum) + { + return "Tag" + tagNum; + } + } +} diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.View/DevCsvReaderView.cs b/ScadaComm/OpenDrivers2/DrvCsvReader.View/DevCsvReaderView.cs new file mode 100644 index 000000000..184a1e10f --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.View/DevCsvReaderView.cs @@ -0,0 +1,77 @@ +// Copyright (c) Rapid Software LLC. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Scada.Comm.Config; +using Scada.Comm.Devices; +using Scada.Comm.Drivers.DrvSms; +using Scada.Forms.Forms; + +namespace Scada.Comm.Drivers.DrvCsvReader.View +{ + /// + /// Implements the device user interface. + /// Реализует пользовательский интерфейс устройства. + /// + internal class DevCsvReaderView : DeviceView + { + /// + /// Initializes a new instance of the class. + /// + public DevCsvReaderView(DriverView parentView, LineConfig lineConfig, DeviceConfig deviceConfig) + : base(parentView, lineConfig, deviceConfig) + { + CanShowProperties = true; + } + + + /// + /// Shows a modal dialog box for editing device properties. + /// + public override bool ShowProperties() + { + CsvReaderOptions options = new(DeviceConfig.PollingOptions.CustomOptions); + FrmOptions frmOptions = new() { Options = options }; + + if (frmOptions.ShowDialog() == DialogResult.OK) + { + options.AddToOptionList(DeviceConfig.PollingOptions.CustomOptions); + return true; + } + else + { + return false; + } + } + + /// + /// Gets the default polling options for the device. + /// + public override PollingOptions GetPollingOptions() + { + PollingOptions pollingOptions = PollingOptions.CreateDefault(); + new CsvReaderOptions().AddToOptionList(pollingOptions.CustomOptions); + return pollingOptions; + } + + /// + /// Gets the channel prototypes for the device. + /// + public override ICollection GetCnlPrototypes() + { + List cnlPrototypes = new(); + CsvReaderOptions options = new(DeviceConfig.PollingOptions.CustomOptions); + + for (int tagNum = 1; tagNum <= options.TagCount; tagNum++) + { + string tagCode = TagCode.GetMainTagCode(tagNum); + cnlPrototypes.Add(new CnlPrototype + { + Name = tagCode, + TagCode = tagCode + }); + } + + return cnlPrototypes; + } + } +} diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.View/DrvCsvReader.View.csproj b/ScadaComm/OpenDrivers2/DrvCsvReader.View/DrvCsvReader.View.csproj new file mode 100644 index 000000000..77fbf5020 --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.View/DrvCsvReader.View.csproj @@ -0,0 +1,35 @@ + + + + net6.0-windows + disable + true + true + enable + Scada.Comm.Drivers.DrvCsvReader.View + Mikhail Shiryaev + Rapid Software LLC + Rapid SCADA + Copyright © 2023 + 6.0.0 + 6.0.0.0 + + + + + + + ..\..\ScadaComm\ScadaCommCommon\bin\Release\netstandard2.0\ScadaCommCommon.dll + + + ..\..\..\ScadaCommon\ScadaCommon\bin\Release\netstandard2.0\ScadaCommon.dll + + + ..\..\..\ScadaCommon\ScadaCommon.Forms\bin\Release\net6.0-windows\ScadaCommon.Forms.dll + + + ..\..\..\ScadaCommon\ScadaCommon.Log\bin\Release\netstandard2.0\ScadaCommon.Log.dll + + + + diff --git a/ScadaComm/OpenDrivers2/DrvCsvReader.View/DrvCsvReaderView.cs b/ScadaComm/OpenDrivers2/DrvCsvReader.View/DrvCsvReaderView.cs new file mode 100644 index 000000000..41a771c43 --- /dev/null +++ b/ScadaComm/OpenDrivers2/DrvCsvReader.View/DrvCsvReaderView.cs @@ -0,0 +1,65 @@ +// Copyright (c) Rapid Software LLC. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Scada.Comm.Config; +using Scada.Comm.Devices; +using Scada.Lang; + +namespace Scada.Comm.Drivers.DrvCsvReader.View +{ + /// + /// Implements the driver user interface. + /// Реализует пользовательский интерфейс драйвера. + /// + public class DrvCsvReaderView : DriverView + { + /// + /// Initializes a new instance of the class. + /// + public DrvCsvReaderView() + : base() + { + CanCreateDevice = true; + } + + + /// + /// Gets the driver name. + /// + public override string Name + { + get + { + return Locale.IsRussian ? + "CSV-считыватель" : + "CSV Reader"; + } + } + + /// + /// Gets the driver description. + /// + public override string Descr + { + get + { + return (Locale.IsRussian ? + "Считывает данные из CSV-файла.\n\n" + + "Пример файла данных:\n": + "Reads data from a CSV file.\n\n" + + "Data file example:\n") + + "Timestamp,TagA,TagB,TagC\n" + + "2001-01-01 00:00:00,1.23,1,0"; + } + } + + + /// + /// Creates a new device user interface. + /// + public override DeviceView CreateDeviceView(LineConfig lineConfig, DeviceConfig deviceConfig) + { + return new DevCsvReaderView(this, lineConfig, deviceConfig); + } + } +} diff --git a/ScadaComm/OpenDrivers2/OpenDrivers2.sln b/ScadaComm/OpenDrivers2/OpenDrivers2.sln index b132391c1..55649bfb4 100644 --- a/ScadaComm/OpenDrivers2/OpenDrivers2.sln +++ b/ScadaComm/OpenDrivers2/OpenDrivers2.sln @@ -46,7 +46,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DrvSms.View", "DrvSms.View\ EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "DrvSms.Shared", "DrvSms.Shared\DrvSms.Shared.shproj", "{3C5B9DB4-E1E0-4F37-8F3D-68B86699838E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DrvSms.Tests", "DrvSms.Tests\DrvSms.Tests.csproj", "{CD09400A-97CF-4024-9520-CCEB87CAA877}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DrvSms.Tests", "DrvSms.Tests\DrvSms.Tests.csproj", "{CD09400A-97CF-4024-9520-CCEB87CAA877}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DrvCsvReader", "DrvCsvReader", "{C364D1FF-62DD-4F20-93E9-EE0121ED3B9C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DrvCsvReader.Logic", "DrvCsvReader.Logic\DrvCsvReader.Logic.csproj", "{5976FDBE-B0FA-4FFF-B381-62165EB92B84}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DrvCsvReader.View", "DrvCsvReader.View\DrvCsvReader.View.csproj", "{3935CB8C-946E-429B-A772-D8E4BD9673B9}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "DrvCsvReader.Shared", "DrvCsvReader.Shared\DrvCsvReader.Shared.shproj", "{1AFBC156-92EE-4118-84D6-AE163D0E654E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -98,6 +106,14 @@ Global {CD09400A-97CF-4024-9520-CCEB87CAA877}.Debug|Any CPU.Build.0 = Debug|Any CPU {CD09400A-97CF-4024-9520-CCEB87CAA877}.Release|Any CPU.ActiveCfg = Release|Any CPU {CD09400A-97CF-4024-9520-CCEB87CAA877}.Release|Any CPU.Build.0 = Release|Any CPU + {5976FDBE-B0FA-4FFF-B381-62165EB92B84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5976FDBE-B0FA-4FFF-B381-62165EB92B84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5976FDBE-B0FA-4FFF-B381-62165EB92B84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5976FDBE-B0FA-4FFF-B381-62165EB92B84}.Release|Any CPU.Build.0 = Release|Any CPU + {3935CB8C-946E-429B-A772-D8E4BD9673B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3935CB8C-946E-429B-A772-D8E4BD9673B9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3935CB8C-946E-429B-A772-D8E4BD9673B9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3935CB8C-946E-429B-A772-D8E4BD9673B9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -118,16 +134,22 @@ Global {C3C10372-279B-412D-BDDA-FFD6BB205674} = {7602BCE7-6013-427D-8850-C2B988C474CB} {3C5B9DB4-E1E0-4F37-8F3D-68B86699838E} = {7602BCE7-6013-427D-8850-C2B988C474CB} {CD09400A-97CF-4024-9520-CCEB87CAA877} = {7602BCE7-6013-427D-8850-C2B988C474CB} + {5976FDBE-B0FA-4FFF-B381-62165EB92B84} = {C364D1FF-62DD-4F20-93E9-EE0121ED3B9C} + {3935CB8C-946E-429B-A772-D8E4BD9673B9} = {C364D1FF-62DD-4F20-93E9-EE0121ED3B9C} + {1AFBC156-92EE-4118-84D6-AE163D0E654E} = {C364D1FF-62DD-4F20-93E9-EE0121ED3B9C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {621E3959-3A13-41B5-A559-AA02854D93A0} EndGlobalSection GlobalSection(SharedMSBuildProjectFiles) = preSolution DrvHttpNotif.Shared\DrvHttpNotif.Shared.projitems*{111a85fb-e7b0-417c-8857-7d0b88a5f050}*SharedItemsImports = 5 + DrvCsvReader.Shared\DrvCsvReader.Shared.projitems*{1afbc156-92ee-4118-84d6-ae163d0e654e}*SharedItemsImports = 13 DrvSnmp.Shared\DrvSnmp.Shared.projitems*{29f3f057-0b4f-4938-b775-6bcef0645c90}*SharedItemsImports = 5 DrvSms.Shared\DrvSms.Shared.projitems*{2d052a7c-3b0c-468f-b52c-1b8aeaa174d2}*SharedItemsImports = 5 + DrvCsvReader.Shared\DrvCsvReader.Shared.projitems*{3935cb8c-946e-429b-a772-d8e4bd9673b9}*SharedItemsImports = 5 DrvSms.Shared\DrvSms.Shared.projitems*{3c5b9db4-e1e0-4f37-8f3d-68b86699838e}*SharedItemsImports = 13 DrvEmail.Shared\DrvEmail.Shared.projitems*{546559c2-4cf8-41af-bbae-0be46f1289f6}*SharedItemsImports = 5 + DrvCsvReader.Shared\DrvCsvReader.Shared.projitems*{5976fdbe-b0fa-4fff-b381-62165eb92b84}*SharedItemsImports = 5 DrvSnmp.Shared\DrvSnmp.Shared.projitems*{5c9089a5-4feb-4fee-b96a-3fede615c898}*SharedItemsImports = 5 DrvEmail.Shared\DrvEmail.Shared.projitems*{6593c194-5edf-459f-9cba-321a870b9677}*SharedItemsImports = 5 DrvEmail.Shared\DrvEmail.Shared.projitems*{a28f2459-d7f3-4f5b-a53e-216cabe2310f}*SharedItemsImports = 13 diff --git a/ScadaCommon/PostgreSqlStorage/PostgreSqlStorage.csproj b/ScadaCommon/PostgreSqlStorage/PostgreSqlStorage.csproj index 54d558422..a75af91c1 100644 --- a/ScadaCommon/PostgreSqlStorage/PostgreSqlStorage.csproj +++ b/ScadaCommon/PostgreSqlStorage/PostgreSqlStorage.csproj @@ -11,7 +11,7 @@ - + diff --git a/ScadaCommon/ScadaCommon.Forms/Forms/FrmModuleConfig.Designer.cs b/ScadaCommon/ScadaCommon.Forms/Forms/FrmModuleConfig.Designer.cs index 09047d43e..7b9355f9d 100644 --- a/ScadaCommon/ScadaCommon.Forms/Forms/FrmModuleConfig.Designer.cs +++ b/ScadaCommon/ScadaCommon.Forms/Forms/FrmModuleConfig.Designer.cs @@ -28,240 +28,234 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.toolStrip = new System.Windows.Forms.ToolStrip(); - this.btnAdd = new System.Windows.Forms.ToolStripButton(); - this.btnAddWithChoice = new System.Windows.Forms.ToolStripDropDownButton(); - this.btnMoveUp = new System.Windows.Forms.ToolStripButton(); - this.btnMoveDown = new System.Windows.Forms.ToolStripButton(); - this.btnDelete = new System.Windows.Forms.ToolStripButton(); - this.pnlBottom = new System.Windows.Forms.Panel(); - this.btnSave = new System.Windows.Forms.Button(); - this.btnClose = new System.Windows.Forms.Button(); - this.btnCancel = new System.Windows.Forms.Button(); - this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); - this.treeView = new System.Windows.Forms.TreeView(); - this.cmsTree = new System.Windows.Forms.ContextMenuStrip(this.components); - this.miCollapseAll = new System.Windows.Forms.ToolStripMenuItem(); - this.ilTree = new System.Windows.Forms.ImageList(this.components); - this.propertyGrid = new System.Windows.Forms.PropertyGrid(); - this.toolStrip.SuspendLayout(); - this.pnlBottom.SuspendLayout(); - this.tableLayoutPanel.SuspendLayout(); - this.cmsTree.SuspendLayout(); - this.SuspendLayout(); + components = new System.ComponentModel.Container(); + toolStrip = new ToolStrip(); + btnAdd = new ToolStripButton(); + btnAddWithChoice = new ToolStripDropDownButton(); + btnMoveUp = new ToolStripButton(); + btnMoveDown = new ToolStripButton(); + btnDelete = new ToolStripButton(); + pnlBottom = new Panel(); + btnSave = new Button(); + btnClose = new Button(); + btnCancel = new Button(); + tableLayoutPanel = new TableLayoutPanel(); + treeView = new TreeView(); + cmsTree = new ContextMenuStrip(components); + miCollapseAll = new ToolStripMenuItem(); + ilTree = new ImageList(components); + propertyGrid = new PropertyGrid(); + toolStrip.SuspendLayout(); + pnlBottom.SuspendLayout(); + tableLayoutPanel.SuspendLayout(); + cmsTree.SuspendLayout(); + SuspendLayout(); // // toolStrip // - this.toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.btnAdd, - this.btnAddWithChoice, - this.btnMoveUp, - this.btnMoveDown, - this.btnDelete}); - this.toolStrip.Location = new System.Drawing.Point(0, 0); - this.toolStrip.Name = "toolStrip"; - this.toolStrip.Size = new System.Drawing.Size(734, 25); - this.toolStrip.TabIndex = 0; - this.toolStrip.Text = "toolStrip1"; + toolStrip.Items.AddRange(new ToolStripItem[] { btnAdd, btnAddWithChoice, btnMoveUp, btnMoveDown, btnDelete }); + toolStrip.Location = new Point(0, 0); + toolStrip.Name = "toolStrip"; + toolStrip.Size = new Size(734, 25); + toolStrip.TabIndex = 0; + toolStrip.Text = "toolStrip1"; // // btnAdd // - this.btnAdd.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.btnAdd.Image = global::Scada.Forms.Properties.Resources.add; - this.btnAdd.ImageTransparentColor = System.Drawing.Color.Magenta; - this.btnAdd.Name = "btnAdd"; - this.btnAdd.Size = new System.Drawing.Size(23, 22); - this.btnAdd.ToolTipText = "Add"; - this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click); + btnAdd.DisplayStyle = ToolStripItemDisplayStyle.Image; + btnAdd.Image = Properties.Resources.add; + btnAdd.ImageTransparentColor = Color.Magenta; + btnAdd.Name = "btnAdd"; + btnAdd.Size = new Size(23, 22); + btnAdd.ToolTipText = "Add"; + btnAdd.Click += btnAdd_Click; // // btnAddWithChoice // - this.btnAddWithChoice.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.btnAddWithChoice.Image = global::Scada.Forms.Properties.Resources.add; - this.btnAddWithChoice.ImageTransparentColor = System.Drawing.Color.Magenta; - this.btnAddWithChoice.Name = "btnAddWithChoice"; - this.btnAddWithChoice.Size = new System.Drawing.Size(29, 22); + btnAddWithChoice.DisplayStyle = ToolStripItemDisplayStyle.Image; + btnAddWithChoice.Image = Properties.Resources.add; + btnAddWithChoice.ImageTransparentColor = Color.Magenta; + btnAddWithChoice.Name = "btnAddWithChoice"; + btnAddWithChoice.Size = new Size(29, 22); // // btnMoveUp // - this.btnMoveUp.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.btnMoveUp.Image = global::Scada.Forms.Properties.Resources.move_up; - this.btnMoveUp.ImageTransparentColor = System.Drawing.Color.Magenta; - this.btnMoveUp.Name = "btnMoveUp"; - this.btnMoveUp.Size = new System.Drawing.Size(23, 22); - this.btnMoveUp.ToolTipText = "Move Up"; - this.btnMoveUp.Click += new System.EventHandler(this.btnMoveUp_Click); + btnMoveUp.DisplayStyle = ToolStripItemDisplayStyle.Image; + btnMoveUp.Image = Properties.Resources.move_up; + btnMoveUp.ImageTransparentColor = Color.Magenta; + btnMoveUp.Name = "btnMoveUp"; + btnMoveUp.Size = new Size(23, 22); + btnMoveUp.ToolTipText = "Move Up"; + btnMoveUp.Click += btnMoveUp_Click; // // btnMoveDown // - this.btnMoveDown.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.btnMoveDown.Image = global::Scada.Forms.Properties.Resources.move_down; - this.btnMoveDown.ImageTransparentColor = System.Drawing.Color.Magenta; - this.btnMoveDown.Name = "btnMoveDown"; - this.btnMoveDown.Size = new System.Drawing.Size(23, 22); - this.btnMoveDown.ToolTipText = "Move Down"; - this.btnMoveDown.Click += new System.EventHandler(this.btnMoveDown_Click); + btnMoveDown.DisplayStyle = ToolStripItemDisplayStyle.Image; + btnMoveDown.Image = Properties.Resources.move_down; + btnMoveDown.ImageTransparentColor = Color.Magenta; + btnMoveDown.Name = "btnMoveDown"; + btnMoveDown.Size = new Size(23, 22); + btnMoveDown.ToolTipText = "Move Down"; + btnMoveDown.Click += btnMoveDown_Click; // // btnDelete // - this.btnDelete.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.btnDelete.Image = global::Scada.Forms.Properties.Resources.delete; - this.btnDelete.ImageTransparentColor = System.Drawing.Color.Magenta; - this.btnDelete.Name = "btnDelete"; - this.btnDelete.Size = new System.Drawing.Size(23, 22); - this.btnDelete.ToolTipText = "Delete"; - this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click); + btnDelete.DisplayStyle = ToolStripItemDisplayStyle.Image; + btnDelete.Image = Properties.Resources.delete; + btnDelete.ImageTransparentColor = Color.Magenta; + btnDelete.Name = "btnDelete"; + btnDelete.Size = new Size(23, 22); + btnDelete.ToolTipText = "Delete"; + btnDelete.Click += btnDelete_Click; // // pnlBottom // - this.pnlBottom.Controls.Add(this.btnSave); - this.pnlBottom.Controls.Add(this.btnClose); - this.pnlBottom.Controls.Add(this.btnCancel); - this.pnlBottom.Dock = System.Windows.Forms.DockStyle.Bottom; - this.pnlBottom.Location = new System.Drawing.Point(0, 496); - this.pnlBottom.Name = "pnlBottom"; - this.pnlBottom.Size = new System.Drawing.Size(734, 45); - this.pnlBottom.TabIndex = 2; + pnlBottom.Controls.Add(btnSave); + pnlBottom.Controls.Add(btnClose); + pnlBottom.Controls.Add(btnCancel); + pnlBottom.Dock = DockStyle.Bottom; + pnlBottom.Location = new Point(0, 496); + pnlBottom.Name = "pnlBottom"; + pnlBottom.Size = new Size(734, 45); + pnlBottom.TabIndex = 2; // // btnSave // - this.btnSave.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.btnSave.Location = new System.Drawing.Point(485, 10); - this.btnSave.Name = "btnSave"; - this.btnSave.Size = new System.Drawing.Size(75, 23); - this.btnSave.TabIndex = 0; - this.btnSave.Text = "Save"; - this.btnSave.UseVisualStyleBackColor = true; - this.btnSave.Click += new System.EventHandler(this.btnSave_Click); + btnSave.Anchor = AnchorStyles.Top | AnchorStyles.Right; + btnSave.Location = new Point(485, 10); + btnSave.Name = "btnSave"; + btnSave.Size = new Size(75, 23); + btnSave.TabIndex = 0; + btnSave.Text = "Save"; + btnSave.UseVisualStyleBackColor = true; + btnSave.Click += btnSave_Click; // // btnClose // - this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.btnClose.Location = new System.Drawing.Point(647, 10); - this.btnClose.Name = "btnClose"; - this.btnClose.Size = new System.Drawing.Size(75, 23); - this.btnClose.TabIndex = 2; - this.btnClose.Text = "Close"; - this.btnClose.UseVisualStyleBackColor = true; + btnClose.Anchor = AnchorStyles.Top | AnchorStyles.Right; + btnClose.Location = new Point(647, 10); + btnClose.Name = "btnClose"; + btnClose.Size = new Size(75, 23); + btnClose.TabIndex = 2; + btnClose.Text = "Close"; + btnClose.UseVisualStyleBackColor = true; // // btnCancel // - this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.btnCancel.Location = new System.Drawing.Point(566, 10); - this.btnCancel.Name = "btnCancel"; - this.btnCancel.Size = new System.Drawing.Size(75, 23); - this.btnCancel.TabIndex = 1; - this.btnCancel.Text = "Cancel"; - this.btnCancel.UseVisualStyleBackColor = true; - this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + btnCancel.Anchor = AnchorStyles.Top | AnchorStyles.Right; + btnCancel.Location = new Point(566, 10); + btnCancel.Name = "btnCancel"; + btnCancel.Size = new Size(75, 23); + btnCancel.TabIndex = 1; + btnCancel.Text = "Cancel"; + btnCancel.UseVisualStyleBackColor = true; + btnCancel.Click += btnCancel_Click; // // tableLayoutPanel // - this.tableLayoutPanel.ColumnCount = 2; - this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 40F)); - this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 60F)); - this.tableLayoutPanel.Controls.Add(this.treeView, 0, 0); - this.tableLayoutPanel.Controls.Add(this.propertyGrid, 1, 0); - this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel.Location = new System.Drawing.Point(0, 25); - this.tableLayoutPanel.Name = "tableLayoutPanel"; - this.tableLayoutPanel.RowCount = 1; - this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel.Size = new System.Drawing.Size(734, 471); - this.tableLayoutPanel.TabIndex = 1; + tableLayoutPanel.ColumnCount = 2; + tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F)); + tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 60F)); + tableLayoutPanel.Controls.Add(treeView, 0, 0); + tableLayoutPanel.Controls.Add(propertyGrid, 1, 0); + tableLayoutPanel.Dock = DockStyle.Fill; + tableLayoutPanel.Location = new Point(0, 25); + tableLayoutPanel.Name = "tableLayoutPanel"; + tableLayoutPanel.RowCount = 1; + tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); + tableLayoutPanel.Size = new Size(734, 471); + tableLayoutPanel.TabIndex = 1; // // treeView // - this.treeView.ContextMenuStrip = this.cmsTree; - this.treeView.Dock = System.Windows.Forms.DockStyle.Fill; - this.treeView.HideSelection = false; - this.treeView.ImageIndex = 0; - this.treeView.ImageList = this.ilTree; - this.treeView.Location = new System.Drawing.Point(3, 3); - this.treeView.Name = "treeView"; - this.treeView.SelectedImageIndex = 0; - this.treeView.Size = new System.Drawing.Size(287, 465); - this.treeView.TabIndex = 0; - this.treeView.AfterCollapse += new System.Windows.Forms.TreeViewEventHandler(this.treeView_AfterCollapseExpand); - this.treeView.AfterExpand += new System.Windows.Forms.TreeViewEventHandler(this.treeView_AfterCollapseExpand); - this.treeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView_AfterSelect); + treeView.ContextMenuStrip = cmsTree; + treeView.Dock = DockStyle.Fill; + treeView.HideSelection = false; + treeView.ImageIndex = 0; + treeView.ImageList = ilTree; + treeView.Location = new Point(3, 3); + treeView.Name = "treeView"; + treeView.SelectedImageIndex = 0; + treeView.Size = new Size(287, 465); + treeView.TabIndex = 0; + treeView.AfterCollapse += treeView_AfterCollapseExpand; + treeView.AfterExpand += treeView_AfterCollapseExpand; + treeView.AfterSelect += treeView_AfterSelect; // // cmsTree // - this.cmsTree.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.miCollapseAll}); - this.cmsTree.Name = "cmsTree"; - this.cmsTree.Size = new System.Drawing.Size(137, 26); + cmsTree.Items.AddRange(new ToolStripItem[] { miCollapseAll }); + cmsTree.Name = "cmsTree"; + cmsTree.Size = new Size(137, 26); // // miCollapseAll // - this.miCollapseAll.Image = global::Scada.Forms.Properties.Resources.collapse_all; - this.miCollapseAll.Name = "miCollapseAll"; - this.miCollapseAll.Size = new System.Drawing.Size(136, 22); - this.miCollapseAll.Text = "Collapse All"; - this.miCollapseAll.Click += new System.EventHandler(this.miCollapseAll_Click); + miCollapseAll.Image = Properties.Resources.collapse_all; + miCollapseAll.Name = "miCollapseAll"; + miCollapseAll.Size = new Size(136, 22); + miCollapseAll.Text = "Collapse All"; + miCollapseAll.Click += miCollapseAll_Click; // // ilTree // - this.ilTree.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit; - this.ilTree.ImageSize = new System.Drawing.Size(16, 16); - this.ilTree.TransparentColor = System.Drawing.Color.Transparent; + ilTree.ColorDepth = ColorDepth.Depth32Bit; + ilTree.ImageSize = new Size(16, 16); + ilTree.TransparentColor = Color.Transparent; // // propertyGrid // - this.propertyGrid.Dock = System.Windows.Forms.DockStyle.Fill; - this.propertyGrid.Location = new System.Drawing.Point(296, 3); - this.propertyGrid.Name = "propertyGrid"; - this.propertyGrid.Size = new System.Drawing.Size(435, 465); - this.propertyGrid.TabIndex = 1; - this.propertyGrid.PropertyValueChanged += new System.Windows.Forms.PropertyValueChangedEventHandler(this.propertyGrid_PropertyValueChanged); + propertyGrid.Dock = DockStyle.Fill; + propertyGrid.Location = new Point(296, 3); + propertyGrid.Name = "propertyGrid"; + propertyGrid.Size = new Size(435, 465); + propertyGrid.TabIndex = 1; + propertyGrid.PropertyValueChanged += propertyGrid_PropertyValueChanged; + propertyGrid.SelectedGridItemChanged += propertyGrid_SelectedGridItemChanged; // // FrmModuleConfig // - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.CancelButton = this.btnClose; - this.ClientSize = new System.Drawing.Size(734, 541); - this.Controls.Add(this.tableLayoutPanel); - this.Controls.Add(this.pnlBottom); - this.Controls.Add(this.toolStrip); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "FrmModuleConfig"; - this.ShowIcon = false; - this.ShowInTaskbar = false; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Module Configuration"; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmModuleConfig_FormClosing); - this.Load += new System.EventHandler(this.FrmModuleConfig_Load); - this.toolStrip.ResumeLayout(false); - this.toolStrip.PerformLayout(); - this.pnlBottom.ResumeLayout(false); - this.tableLayoutPanel.ResumeLayout(false); - this.cmsTree.ResumeLayout(false); - this.ResumeLayout(false); - this.PerformLayout(); - + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + CancelButton = btnClose; + ClientSize = new Size(734, 541); + Controls.Add(tableLayoutPanel); + Controls.Add(pnlBottom); + Controls.Add(toolStrip); + MaximizeBox = false; + MinimizeBox = false; + Name = "FrmModuleConfig"; + ShowIcon = false; + ShowInTaskbar = false; + StartPosition = FormStartPosition.CenterParent; + Text = "Module Configuration"; + FormClosing += FrmModuleConfig_FormClosing; + Load += FrmModuleConfig_Load; + toolStrip.ResumeLayout(false); + toolStrip.PerformLayout(); + pnlBottom.ResumeLayout(false); + tableLayoutPanel.ResumeLayout(false); + cmsTree.ResumeLayout(false); + ResumeLayout(false); + PerformLayout(); } #endregion - private System.Windows.Forms.ToolStrip toolStrip; - private System.Windows.Forms.Panel pnlBottom; - private System.Windows.Forms.Button btnSave; - private System.Windows.Forms.Button btnClose; - private System.Windows.Forms.Button btnCancel; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; - private System.Windows.Forms.TreeView treeView; - private System.Windows.Forms.PropertyGrid propertyGrid; - private System.Windows.Forms.ToolStripButton btnAdd; - private System.Windows.Forms.ToolStripButton btnMoveUp; - private System.Windows.Forms.ToolStripDropDownButton btnAddWithChoice; - private System.Windows.Forms.ToolStripButton btnMoveDown; - private System.Windows.Forms.ToolStripButton btnDelete; - private System.Windows.Forms.ImageList ilTree; - private System.Windows.Forms.ContextMenuStrip cmsTree; - private System.Windows.Forms.ToolStripMenuItem miCollapseAll; + private ToolStrip toolStrip; + private Panel pnlBottom; + private Button btnSave; + private Button btnClose; + private Button btnCancel; + private TableLayoutPanel tableLayoutPanel; + private TreeView treeView; + private PropertyGrid propertyGrid; + private ToolStripButton btnAdd; + private ToolStripButton btnMoveUp; + private ToolStripDropDownButton btnAddWithChoice; + private ToolStripButton btnMoveDown; + private ToolStripButton btnDelete; + private ImageList ilTree; + private ContextMenuStrip cmsTree; + private ToolStripMenuItem miCollapseAll; } } \ No newline at end of file diff --git a/ScadaCommon/ScadaCommon.Forms/Forms/FrmModuleConfig.cs b/ScadaCommon/ScadaCommon.Forms/Forms/FrmModuleConfig.cs index a80dc53a7..e449022a8 100644 --- a/ScadaCommon/ScadaCommon.Forms/Forms/FrmModuleConfig.cs +++ b/ScadaCommon/ScadaCommon.Forms/Forms/FrmModuleConfig.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Scada.Lang; +using System.ComponentModel; namespace Scada.Forms.Forms { @@ -31,6 +32,8 @@ public FrmModuleConfig(ConfigProvider configProvider) { this.configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider)); modified = false; + btnSave.Enabled = false; + btnCancel.Enabled = false; } @@ -45,9 +48,12 @@ private bool Modified } set { - modified = value; - btnSave.Enabled = modified; - btnCancel.Enabled = modified; + if (modified != value) + { + modified = value; + btnSave.Enabled = modified; + btnCancel.Enabled = modified; + } } } @@ -157,7 +163,7 @@ private void SetButtonsEnabled() private void FrmModuleConfig_Load(object sender, EventArgs e) { - FormTranslator.Translate(this, GetType().FullName, + FormTranslator.Translate(this, GetType().FullName, new FormTranslatorOptions { ContextMenus = new ContextMenuStrip[] { cmsTree } }); if (!string.IsNullOrEmpty(configProvider.FormTitle)) @@ -273,6 +279,26 @@ private void propertyGrid_PropertyValueChanged(object s, PropertyValueChangedEve Modified = true; } + private void propertyGrid_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e) + { + if (e.OldSelection?.Value is INotifyPropertyChanged notifyPropertyChanged1) + { + notifyPropertyChanged1.PropertyChanged -= selectedGridItem_PropertyChanged; + } + + if (e.NewSelection?.Value is INotifyPropertyChanged notifyPropertyChanged2) + { + notifyPropertyChanged2.PropertyChanged -= selectedGridItem_PropertyChanged; + notifyPropertyChanged2.PropertyChanged += selectedGridItem_PropertyChanged; + } + } + + private void selectedGridItem_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + // usually called many times + Modified = true; + } + private void btnSave_Click(object sender, EventArgs e) { if (configProvider.SaveConfig(out string errMsg)) diff --git a/ScadaCommon/ScadaCommon.Forms/Forms/FrmModuleConfig.resx b/ScadaCommon/ScadaCommon.Forms/Forms/FrmModuleConfig.resx index dc6852aa9..9572f22eb 100644 --- a/ScadaCommon/ScadaCommon.Forms/Forms/FrmModuleConfig.resx +++ b/ScadaCommon/ScadaCommon.Forms/Forms/FrmModuleConfig.resx @@ -1,4 +1,64 @@ - + + + diff --git a/ScadaCommon/ScadaCommon.MultiDb/ScadaCommon.MultiDb.csproj b/ScadaCommon/ScadaCommon.MultiDb/ScadaCommon.MultiDb.csproj index 54b43379a..81a85c30a 100644 --- a/ScadaCommon/ScadaCommon.MultiDb/ScadaCommon.MultiDb.csproj +++ b/ScadaCommon/ScadaCommon.MultiDb/ScadaCommon.MultiDb.csproj @@ -16,7 +16,7 @@ - + diff --git a/ScadaCommon/ScadaCommon/Config/ConfigBase.cs b/ScadaCommon/ScadaCommon/Config/ConfigBase.cs index ad6f98652..782675069 100644 --- a/ScadaCommon/ScadaCommon/Config/ConfigBase.cs +++ b/ScadaCommon/ScadaCommon/Config/ConfigBase.cs @@ -20,13 +20,14 @@ * * Author : Mikhail Shiryaev * Created : 2021 - * Modified : 2022 + * Modified : 2023 */ using Scada.Lang; using Scada.Storages; using System; using System.IO; +using System.Text; namespace Scada.Config { @@ -134,7 +135,37 @@ public bool Load(string fileName, out string errMsg) return false; } } - + + /// + /// Saves the configuration to the specified storage. + /// + public bool Save(IStorage storage, string fileName, out string errMsg) + { + if (storage == null) + throw new ArgumentNullException(nameof(storage)); + + try + { + using (MemoryStream stream = new MemoryStream()) + { + using (StreamWriter writer = new StreamWriter(stream)) + { + Save(writer); + string contents = Encoding.UTF8.GetString(stream.ToArray()); + storage.WriteText(DataCategory.Config, fileName, contents); + } + } + + errMsg = ""; + return true; + } + catch (Exception ex) + { + errMsg = BuildSaveErrorMessage(ex); + return false; + } + } + /// /// Saves the configuration to the specified file. /// diff --git a/ScadaCommon/ScadaCommon/Data/Const/CnlStatusID.cs b/ScadaCommon/ScadaCommon/Data/Const/CnlStatusID.cs index 4ff3d37c9..049f71886 100644 --- a/ScadaCommon/ScadaCommon/Data/Const/CnlStatusID.cs +++ b/ScadaCommon/ScadaCommon/Data/Const/CnlStatusID.cs @@ -20,7 +20,7 @@ * * Author : Mikhail Shiryaev * Created : 2020 - * Modified : 2020 + * Modified : 2023 */ #pragma warning disable 1591 // Missing XML comment for publicly visible type or member @@ -38,11 +38,11 @@ public static class CnlStatusID public const int Archival = 2; public const int FormulaError = 3; public const int Unreliable = 4; - public const int ExtremelyLow = 11; + public const int LoLo = 11; public const int Low = 12; public const int Normal = 13; public const int High = 14; - public const int ExtremelyHigh = 15; + public const int HiHi = 15; public const int Good = 21; public const int Warning = 22; public const int Error = 23; diff --git a/ScadaCommon/ScadaCommon/Data/Models/ViewBase.cs b/ScadaCommon/ScadaCommon/Data/Models/ViewBase.cs index 697d2dfdd..b52932562 100644 --- a/ScadaCommon/ScadaCommon/Data/Models/ViewBase.cs +++ b/ScadaCommon/ScadaCommon/Data/Models/ViewBase.cs @@ -53,7 +53,7 @@ public ViewBase(View viewEntity) StoredOnServer = true; Args = ParseArgs(); Title = GetTitle(); - Resources = null; + Resources = new List(); CnlNumList = new List(); CnlNumSet = new HashSet(); } diff --git a/ScadaCommon/ScadaCommon/Dbms/ConnectionStringBuilder.cs b/ScadaCommon/ScadaCommon/Dbms/ConnectionStringBuilder.cs index e4463c2a6..139116947 100644 --- a/ScadaCommon/ScadaCommon/Dbms/ConnectionStringBuilder.cs +++ b/ScadaCommon/ScadaCommon/Dbms/ConnectionStringBuilder.cs @@ -102,16 +102,22 @@ public static string Build(DbConnectionOptions options, KnownDBMS forceDBMS, boo } /// - /// Builds a connection string according to the database connection options, overwriting the DBMS. + /// Builds a connection string according to the database connection options. /// If a non-empty connection string is specified in the options, it is returned. /// public static string BuildConnectionString(this DbConnectionOptions options) { - if (options == null) - return ""; + return BuildConnectionString(options, false); + } - return string.IsNullOrEmpty(options.ConnectionString) - ? Build(options, false) + /// + /// Builds a connection string according to the database connection options. + /// If a non-empty connection string is specified in the options, it is returned. + /// + public static string BuildConnectionString(this DbConnectionOptions options, bool hidePassword) + { + return string.IsNullOrEmpty(options?.ConnectionString) + ? Build(options, hidePassword) : options.ConnectionString; } @@ -121,10 +127,7 @@ public static string BuildConnectionString(this DbConnectionOptions options) /// public static string BuildConnectionString(this DbConnectionOptions options, KnownDBMS forceDBMS) { - if (options == null) - return ""; - - return string.IsNullOrEmpty(options.ConnectionString) + return string.IsNullOrEmpty(options?.ConnectionString) ? Build(options, forceDBMS, false) : options.ConnectionString; } diff --git a/ScadaDoc/ScadaDoc/Code/DocUtils.cs b/ScadaDoc/ScadaDoc/Code/DocUtils.cs index 5302d540e..66fa0c9a4 100644 --- a/ScadaDoc/ScadaDoc/Code/DocUtils.cs +++ b/ScadaDoc/ScadaDoc/Code/DocUtils.cs @@ -28,8 +28,9 @@ public static string ConvertToString(this KnownLang lang) return lang switch { KnownLang.En => "English", - KnownLang.Ru => "Russian", KnownLang.Es => "Spanish", + KnownLang.Fr => "French", + KnownLang.Ru => "Russian", KnownLang.Zh => "简体中文", _ => lang.ToString() }; diff --git a/ScadaDoc/ScadaDoc/Code/KnownLang.cs b/ScadaDoc/ScadaDoc/Code/KnownLang.cs index 4201cce88..43737b201 100644 --- a/ScadaDoc/ScadaDoc/Code/KnownLang.cs +++ b/ScadaDoc/ScadaDoc/Code/KnownLang.cs @@ -11,8 +11,9 @@ public enum KnownLang { None, En, - Ru, Es, + Fr, + Ru, Zh } } diff --git a/ScadaDoc/ScadaDoc/Code/PageMeta.cs b/ScadaDoc/ScadaDoc/Code/PageMeta.cs index 1d861a3b1..82eb59609 100644 --- a/ScadaDoc/ScadaDoc/Code/PageMeta.cs +++ b/ScadaDoc/ScadaDoc/Code/PageMeta.cs @@ -33,8 +33,9 @@ public static PageMeta Parse(string pagePath) pageMeta.Lang = langStr switch { "en" => KnownLang.En, - "ru" => KnownLang.Ru, "es" => KnownLang.Es, + "fr" => KnownLang.Fr, + "ru" => KnownLang.Ru, "zh" => KnownLang.Zh, _ => KnownLang.None }; diff --git a/ScadaDoc/ScadaDoc/Code/VersionMenu.cs b/ScadaDoc/ScadaDoc/Code/VersionMenu.cs index 6b916218d..268206117 100644 --- a/ScadaDoc/ScadaDoc/Code/VersionMenu.cs +++ b/ScadaDoc/ScadaDoc/Code/VersionMenu.cs @@ -49,34 +49,47 @@ public VersionMenu(KnownLang lang) }; /// - /// Russian versions of the documentation. + /// Spanish versions of the documentation. /// - public static readonly VersionMenu Ru = new(KnownLang.Ru) + public static readonly VersionMenu Es = new(KnownLang.Es) { - new VersionItem - { - Version = KnownVersion.V61, - Text = KnownVersion.V61.ConvertToString(), - Url = "/ru/latest/" - }, new VersionItem { Version = KnownVersion.V58, Text = KnownVersion.V58.ConvertToString(), - Url = "/ru/5.8/" + Url = "/es/5.8/" } }; /// - /// Spanish versions of the documentation. + /// French versions of the documentation. /// - public static readonly VersionMenu Es = new(KnownLang.Es) + public static readonly VersionMenu Fr = new(KnownLang.Fr) { + new VersionItem + { + Version = KnownVersion.V61, + Text = KnownVersion.V61.ConvertToString(), + Url = "/fr/latest/" + } + }; + + /// + /// Russian versions of the documentation. + /// + public static readonly VersionMenu Ru = new(KnownLang.Ru) + { + new VersionItem + { + Version = KnownVersion.V61, + Text = KnownVersion.V61.ConvertToString(), + Url = "/ru/latest/" + }, new VersionItem { Version = KnownVersion.V58, Text = KnownVersion.V58.ConvertToString(), - Url = "/es/5.8/" + Url = "/ru/5.8/" } }; @@ -102,11 +115,13 @@ public VersionMenu(KnownLang lang) /// The menus for all languages. /// public static readonly List All = new() - { - En, - Ru, - Es, - Zh + { + // In alphabet order + En, // English + Fr, // French + Ru, // Russian + Es, // English + Zh // 简体中文 }; @@ -118,8 +133,9 @@ public static VersionMenu GetMenu(KnownLang lang) return lang switch { KnownLang.En => En, - KnownLang.Ru => Ru, KnownLang.Es => Es, + KnownLang.Fr => Fr, + KnownLang.Ru => Ru, KnownLang.Zh => Zh, _ => Empty }; diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/Modules/PlgChartPro.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/Modules/PlgChartPro.cshtml index f72165051..3489053e5 100644 --- a/ScadaDoc/ScadaDoc/Pages/En/Version61/Modules/PlgChartPro.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/Modules/PlgChartPro.cshtml @@ -10,7 +10,12 @@ @@ -98,6 +103,13 @@

The following figure helps to understand the layout of the chart in order to change the plugin configuration.

- Компоновка графика + Chart parts +
+ +

View Mode

+

Chart Pro Plugin supports the view mode, in which a chart node is added to the view tree of Webstation. To display the chart as a view, add the following row to the Views table:

+
+ Views table
+

The Path field contains the path in the view tree. The View Type field should be set to Chart Pro. The view arguments correspond to the query string parameters described above.

diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/Modules/PlgDashboard.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/Modules/PlgDashboard.cshtml new file mode 100644 index 000000000..6e1397b83 --- /dev/null +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/Modules/PlgDashboard.cshtml @@ -0,0 +1,111 @@ +@page "/en/latest/modules/plg-dashboard" +@{ + Layout = "_ArticleLayout"; + ViewBag.Title = "Dashboard Plugin"; +} + +@section Styles { + +} + +@section Scripts { + +} + + + +
+

Dashboard Plugin

+ +

Overview

+

Dashboard Plugin displays useful widgets on dashboards: charts, current data and arbitrary frames, for example, CCTV camera stream. Settings of each dashboard allow to specify column count and widget aspect ratio. Download the plugin using the link. The appearance of Dashboard Plugin is shown in the following figure.

+
+ Dashboard Plugin +
+ +

Installation

+

Dashboard Plugin is installed according to the instructions. No unusual actions are required during installation.

+ +

Configuring

+

Adding Dashboards

+

Configuration of each dashboard is stored in a separate XML file. The dashboard example, Dashboard1.xml, is included in the plugin installation package. Dashboard files should be located in the views directory.

+

In order to display dashboard nodes in the explorer tree of Webstation, perform the following settings in the project:

+
    +
  1. Create and edit a dashboard file in the views directory.
  2. +
  3. Specify the dashboard path in the Views table of the configuration database.
  4. +
+
+ Dashboard file +
+
+ Views table +
+

It is required to explicitly specify the view type because the Webstation application cannot automatically determine the type based on the xml file extension.

+ +

Dashboard File Structure

+

A dashboard consists of widgets. The layout of widgets on the dashboard is controlled by the Bootstrap grid system. Widgets are arranged in rows, each of which can contain up to 12 widgets. For a widget, you can set the width from 1 to 12, so that the total width of the widgets in the row is equal to 12. If the widget width is not specified, it is calculated automatically. The breakpoint specifies the web page width, which determines how the widgets are positioned. If the page is wider than the breakpoint, the widgets are displayed in a row; otherwise, the widgets are displayed one below the other.

+

Consider the contents of a dashboard configuration file:

+ +
<?xml version="1.0" encoding="utf-8" ?>
+<DashboardView>
+  <DashboardOptions>
+    <!-- Widget AspectRatio = Width / Height -->
+    <AspectRatio>1.33</AspectRatio>
+    <!-- Breakpoint: ExtraSmall | Small | Medium | Large | ExtraLarge | ExtraExtraLarge -->
+    <Breakpoint>Small</Breakpoint>
+  </DashboardOptions>
+  <Widgets>
+    <!-- The total width of the columns in a line is 12 -->
+    <Row>
+      <Widget type="Chart" columnWidth="5" cnlNums="101,102" />
+      <Widget type="Chart" columnWidth="4" cnlNums="101,103" mode="fixed" period="-2" title="Sample Chart" profile="PlgChartPro.xml" />
+      <Widget type="CurData" columnWidth="3" cnlNums="101-105" title="Sample Data" />
+    </Row>
+    <Row columnCount="2">
+      <Widget type="View" viewID="2" />
+      <Widget type="CustomUrl" url="https://www.youtube.com/embed/xAieE-QtOeM" />
+    </Row>
+  </Widgets>
+</DashboardView>
+ +

+ The DashboardOptions section contains common dashboard parameters:
+ AspectRatio - ratio of widget width to its height,
+ Breakpoint determines the web page width to switch widget layout. +

+

The Widgets section contains a list of widgets that are displayed on a dashboard. The dashboard can contain an arbitrary number of widgets, but no more than 12 in one row. Please note that too many widgets on one dashboard can slow down the performance of the web application.

+

+ The attribute of the Row element:
+ columnCount - number of columns to display widgets of a given row. If the columnCount attribute is specified for the row, then the columnWidth attribute is not required for widgets in that row. +

+

+ The main attributes of the Widget element:
+ type - widget type,
+ columnWidth - widget width from 1 to 12,
+ cnlNums - channel numbers. +

+ +

+ Widgets of the following types are supported:
+ Chart - a chart of the specified channels,
+ CurData - a table contains current data of the specified channels,
+ View - a view having the specified ID,
+ CustomUrl - custom web page. +

+ +

Widgets of the Chart type support attributes that match the query string parameters described in the Chart Pro Plugin documentation. When events are filtered by view, the filter uses the channel numbers specified in the cnlNums attributes of the widgets.

+
diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/Modules/PlgElasticReport.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/Modules/PlgElasticReport.cshtml new file mode 100644 index 000000000..3564895bf --- /dev/null +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/Modules/PlgElasticReport.cshtml @@ -0,0 +1,133 @@ +@page "/en/latest/modules/plg-elastic-report" +@{ + Layout = "_ArticleLayout"; + ViewBag.Title = "Elastic Report Plugin"; +} + +@section Styles { + +} + +@section Scripts { + +} + + + +
+

Elastic Report Plugin

+

Overview

+

Elastic Report Plugin allows to generate reports according to a custom configuration. Using this plugin, you can build almost any desired report. A user simply selects the period and clicks the generate report button. Report configurations are created by an administrator. Download the plugin using the link.

+ +

Installation

+

Elastic Report Plugin is installed according to the instructions. During installation, complete the following additional step: copy the PlgElasticReport.xml file from the plugin distribution into your project. The file should be displayed in the project explorer under the Webstation > Configuration Files node.

+ +

Configuring

+

A report consists of a set of sections, which are listed in the output document, one by one. Each section has its own type, parameters, and data binding. In addition, the report has the general parameters that affect all sections. The same report can be generated in a variety of formats. Currently supported PDF, Excel and HTML formats. The appearance of the same report, generated in different formats may slightly differ.

+ +

Report Form

+

Each report form requires the creation of a separate configuration file in XML format. The configuration file specifies the report formatting and determines the binding of report data to channels. This file should be saved in the views directory or a subdirectory within the project.

+
+ Report file +
+

Configuration files may be edited using any text editor. For example, the free editor Notepad++ is convenient for working with XML files.

+

An example report file ElasticReport1.xml is contained in the plugin installation package. This example includes a detailed description of the options and demonstrates the generation of report sections of all possible types.

+

The main elements of the report configuration file:

+
    +
  • The InputOptions element contains options for the input report form, with which a user enters the report parameters and starts generating the document.
  • +
  • The OutputOptions element contains formatting options for the generated document.
  • +
  • + The Document element defines the content of the report. +
      +
    • The DocumentOptions element specifies basic options that apply to the entire document.
    • +
    • The Section element describes a report section containing data. A report includes one or more sections of various types.
    • +
    +
  • +
+

The supported section types:

+
    +
  • The TimeData section displays channel data for the selected time period. Channels are displayed horizontally, timestamps are displayed vertically.
  • +
  • The TimeTime section displays data of one channel in a compact form. Timestamps are displayed in the horizontal and vertical section headers.
  • +
  • The DataData section displays data in a table form. Each cell can be linked to its own channel.
  • +
+

The plugin provides the generation of reports based on historical data. Reports on current data and events are not supported. When choosing a historical archive for a report, it is recommended to give preference to an archive with a data writing period that matches or is close to the step of the report sections. This will avoid fetching unnecessary data.

+ +

Report List

+

The PlgElasticReport.xml configuration file contains a list of reports divided into groups, which are displayed on the Main Menu > Reports page. Example of file contents:

+
<?xml version="1.0" encoding="utf-8" ?>
+<PlgElasticReport>
+  <ReportGroup name="Elastic Reports" isPublic="false" objNum="0">
+    <ReportItem reportID="1" isPublic="false" objNum="0" config="Reports\ElasticReport1.xml" prefix="MyRep" cnlNums="">My report</ReportItem>
+  </ReportGroup>
+</PlgElasticReport>
+ +

+ The ReportGroup element attributes:
+ name - the display name of the report group;
+ isPublic - a value indicating whether the group is public, that is, available to all users;
+ objNum - the number of the object to which reports of the group belong. Restricts the group visibility according to a user's access rights to the object. +

+

+ The ReportItem element attributes:
+ reportID - the report identifier, unique within the configuration file;
+ isPublic - a value indicating whether the report is public, that is, available to all users;
+ objNum - the number of the object to the report belong. Restricts the report visibility according to a user's access rights to the object;
+ config - the path of the report form configuration file relative to the views directory,
+ prefix - the file name prefix used when downloading the report,
+ cnlNums - the predefined channel numbers for which the report is generated. +

+ +

Styling

+

You can customize your own report styles, including fonts, colors, cell sizes, etc. For each report format, styles are configured separately.

+ +

PDF Styles

+

The PdfStyleDefault.xml and PdfStyleCustom.xml files specify the formatting of reports in PDF format. These files are located in the web application directory ScadaWeb\wwwroot\plugins\ElasticReport\templates. The PdfStyleDefault.xml file contains the default styles and should remain unchanged. Custom styles are added to the PdfStyleCustom.xml file. When creating custom styles, you can inherit new styles from existing ones or override existing styles.

+ +

Excel Styles

+

Similarly, the ExcelStyleDefault.xml and ExcelStyleCustom.xml files, located in the same directory, specify the formatting of reports in Excel format. The ExcelStyleDefault.xml file contains default styles and should remain unchanged. Custom styles are added to the ExcelStyleCustom.xml file. Please note that PDF and Excel style file formats are different.

+ +

HTML Styles

+

The html-style-default.scss and html-style-custom.css files define the display of reports in HTML format. The files are located in the ScadaWeb\wwwroot\plugins\ElasticReport\css directory. Custom styles are added to the html-style-custom.css file using Cascading Style Sheets (CSS) rules.

+ +

Fonts

+

Fonts in PDF Format

+

When generating reports in PDF format, the Arial font is used by default. If the required font is not available in the operating system, it is replaced with the built-in Segoe WP font. To change the report font, edit the styles file.

+

The font search is performed using the following algorithm:

+
    +
  1. The search directory is selected. On Windows, the search is performed in the C:\Windows\Fonts directory, on Linux in the /usr/share/fonts/truetype directory
  2. +
  3. + Based on the font name (FontFamily), the required font file names are determined. +
      +
    1. Regular font: FontFamily.ttf, FontFamily-Regular.ttf
    2. +
    3. Bold font: FontFamilyb.ttf, FontFamilybd.ttf, FontFamily-Bold.ttf
    4. +
    5. Italic font: FontFamilyi.ttf, FontFamily-Italic.ttf, FontFamily-Oblique.ttf
    6. +
    7. Bold italic font: FontFamilybi.ttf, FontFamily-BoldItalic.ttf, FontFamily-BoldOblique.ttf
    8. +
    +
  4. +
  5. Fallback font file names (candidates) are determined. For bold or italic fonts, regular font files are used as candidates. There are no fallback options for a regular font.
  6. +
  7. If a desired or fallback font is found in the search directory, the font file is loaded and provided for report generation. The search is not case sensitive.
  8. +
+

The default fonts usually do not contain characters for languages such as Chinese and Korean. To generate reports in such languages, it is recommended to install the Arial Unicode MS font. On Windows, the font installation is required for all users so that the font file is placed in the C:\Windows\Fonts directory.

+
+ Install font +
+ +

Fonts in Excel Format

+

In generated reports in Excel format, only the font name is specified; the font itself is not included in the report file. The default font is Arial. When a file is opened in Microsoft Excel or Libre Office Calc, the application loads the font from the system. If the font is missing, automatic replacement is used. You can change the font using the styles file.

+
diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/AdministratorHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/AdministratorHistory.cshtml index afaa9233a..be21562ac 100644 --- a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/AdministratorHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/AdministratorHistory.cshtml @@ -23,6 +23,11 @@

Administrator History

Administrator Application

+
ScadaAdmin 6.1.1.1 (December 10, 2023)
+
    +
  • Fixed creation of channel limits
  • +
+
ScadaAdmin 6.1.1.0 (September 25, 2023)
  • Added the Code column to the Channels table
  • diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/AgentHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/AgentHistory.cshtml index a044ba334..0567a8f30 100644 --- a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/AgentHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/AgentHistory.cshtml @@ -5,6 +5,11 @@ }

    Agent History

    +
    ScadaAgent 6.1.0.1 (December 10, 2023)
    +
      +
    • Fixed temporary directory when configuration is uploaded to another instance
    • +
    +
    ScadaAgent 6.1.0.0 (March 21, 2023)
    + @**** DrvCsvReader ****@ +

    CSV Reader

    +
    DrvCsvReader 6.0.0.0 (December 10, 2023)
    +
      +
    • Initial development of the driver
    • +
    + @**** DrvDbImport ****@

    DB Import

    DrvDbImport 6.0.0.1 (September 25, 2023)
    @@ -236,6 +244,11 @@ @**** DrvMqttClient ****@

    MQTT Client

    +
    DrvMqttClient 6.0.0.4 (December 10, 2023)
    +
      +
    • Fixed JavaScript execution
    • +
    +
    DrvMqttClient 6.0.0.3 (July 04, 2023)
    • Optimized driver configuration source code
    • @@ -280,6 +293,11 @@ @**** DrvOpcClassic ****@

      OPC Classic

      +
      DrvOpcClassic 6.0.1.1 (December 10, 2023)
      +
        +
      • Improved reconnection when connection is lost
      • +
      +
      DrvOpcClassic 6.0.1.0 (September 25, 2023)
      • Added support for synchronous reading
      • diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ScadaHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ScadaHistory.cshtml index 0026e418a..4ab36604a 100644 --- a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ScadaHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ScadaHistory.cshtml @@ -6,6 +6,35 @@

        History of Rapid SCADA

        +
        Rapid SCADA 6.1.6 (December 10, 2023)
        +
          +
        • + Server 6.1.1.1 +
            +
          • ModActiveDirectory 6.0.2.0
          • +
          • ModArcPostgreSql 6.1.2.0
          • +
          • ModDbExport 6.0.0.2
          • +
          +
        • +
        • + Communicator 6.1.1.1 +
            +
          • DrvCsvReader 6.0.0.0
          • +
          • DrvMqttClient 6.0.0.4
          • +
          • DrvOpcClassic 6.0.1.1
          • +
          +
        • +
        • + Webstation 6.1.2.2 +
            +
          • PlgMain 6.0.3.1
          • +
          +
        • +
        • Agent 6.1.0.1
        • +
        • Administrator 6.1.1.1
        • +
        • Scheme Editor 5.3.1.1
        • +
        +
        Rapid SCADA 6.1.5 (September 25, 2023)
        • Server 6.1.1.1
        • diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ServerHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ServerHistory.cshtml index 6021e37da..666bab733 100644 --- a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ServerHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/ServerHistory.cshtml @@ -78,6 +78,11 @@ @**** ModActiveDirectory ****@

          Active Directory Module

          +
          ModActiveDirectory 6.0.2.0 (December 10, 2023)
          +
            +
          • User information is stored in PostgreSQL database
          • +
          +
          ModActiveDirectory 6.0.1.0 (March 21, 2023)
          • Added an option to enable or disable search in Active Directory
          • @@ -119,6 +124,11 @@ @**** ModArcPostgreSql ****@

            PostgreSQL Archive

            +
            ModArcPostgreSql 6.1.2.0 (December 10, 2023)
            +
              +
            • Added a partition size of one day
            • +
            +
            ModArcPostgreSql 6.1.1.1 (August 03, 2023)
            • Fixed batch size
            • @@ -141,6 +151,12 @@ @**** ModAutoControl ****@

              Automatic Control Module

              +
              ModAutoControl 6.0.0.3 (December 10, 2023)
              +
                +
              • Fixed copying a command value in data change trigger
              • +
              • Fixed trigger copying on the configuration form
              • +
              +
              ModAutoControl 6.0.0.2 (September 25, 2023)
              • Fixes on module configuration form
              • @@ -160,6 +176,12 @@ @**** ModDbExport ****@

                DB Export

                +
                ModDbExport 6.0.0.2 (December 10, 2023)
                +
                  +
                • Fixed query filter editing
                • +
                • Added available query parameters
                • +
                +
                ModDbExport 6.0.0.1 (July 04, 2023)
                • Optimized module configuration source code
                • @@ -183,6 +205,11 @@ @**** ModRapidGate ****@

                  Rapid Gate

                  +
                  ModRapidGate 6.0.1.3 (December 10, 2023)
                  +
                    +
                  • Fixed a bug when sending acknowledgments
                  • +
                  +
                  ModRapidGate 6.0.1.2 (July 04, 2023)
                  • Optimized module configuration source code
                  • diff --git a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/WebstationHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/WebstationHistory.cshtml index 4e75c5269..f93f9f2ef 100644 --- a/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/WebstationHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/En/Version61/VersionHistory/WebstationHistory.cshtml @@ -28,6 +28,13 @@

                    Webstation History

                    Webstation Application

                    +
                    ScadaWeb 6.1.2.2 (December 10, 2023)
                    +
                      +
                    • Fixed authorization handling
                    • +
                    • New features of modal forms
                    • +
                    • Changes in CSS and JavaScript
                    • +
                    +
                    ScadaWeb 6.1.2.1 (September 25, 2023)
                    • Fixed translation on the channel selection page
                    • @@ -101,6 +108,11 @@

                    Chart Pro

                    +
                    PlgChartPro 6.0.2.2 (December 10, 2023)
                    +
                      +
                    • Fixed links to dialog pages and API
                    • +
                    +
                    PlgChartPro 6.0.2.1 (September 25, 2023)
                    • Translation fixed
                    • @@ -188,6 +200,12 @@

                    Main Plugin

                    +
                    PlgMain 6.0.3.1 (December 10, 2023)
                    +
                      +
                    • Fixed link to dialog pages
                    • +
                    • Event window is disabled if the number of displayed events is 0
                    • +
                    +
                    PlgMain 6.0.3.0 (August 03, 2023)
                    • Changes in JavaScript API
                    • diff --git a/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Index.cshtml b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Index.cshtml new file mode 100644 index 000000000..1de92cc70 --- /dev/null +++ b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Index.cshtml @@ -0,0 +1,4 @@ +@page "/fr/latest/" +@{ + Response.Redirect("software-overview/introduction"); +} diff --git a/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/InstallLinux.cshtml b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/InstallLinux.cshtml new file mode 100644 index 000000000..83bb24ed7 --- /dev/null +++ b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/InstallLinux.cshtml @@ -0,0 +1,135 @@ +@page "/fr/latest/installation/install-linux" +@{ + Layout = "_ArticleLayout"; + ViewBag.Title = "Installation sur Linux"; +} + +@section Styles { + +} + +@section Scripts { + +} + + + +
                      +

                      Installation sur Linux

                      +

                      Cet article fournit les commandes pour les systèmes d’exploitation Ubuntu et Debian. Si vous installez Rapid SCADA sur d’autres OS que Linux, utilisez les commandes appropriées.

                      + +

                      Installation

                      +
                        +
                      1. +

                        Installez ASP.NET Core Runtime 6.0.x en suivant les instructions.

                        +

                        Si l’installation de .NET depuis le dossier est impossible, suivez l’installation manuelle décrite si dessous :

                        +
                          +
                        1. Téléchargez les fichiers binaires .NET correspondant au système d’exploitation depuis ce lien.
                        2. +
                        3. Extrayez et copiez les fichiers téléchargés dans /usr/share/dotnet/
                        4. +
                        5. + Créez le fichier dotnet exécutable : +
                          sudo chmod +x /usr/share/dotnet/dotnet
                          +
                        6. +
                        7. + Créez un lien vers le fichier dotnet : +
                          sudo ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet
                          +
                        8. +
                        +
                      2. +
                      3. + Installez Rapid SCADA depuis le package (option 1) +
                        sudo dpkg -i rapidscada_VERSION_all.deb
                        +
                      4. +
                      5. + Installez manuellement Rapid SCADA (option 2) +
                          +
                        1. Copiez les fichiers extraits depuis le dossier scada vers /opt/scada
                        2. +
                        3. + Créez le script exécutable : +
                          sudo chmod +x /opt/scada/make_executable.sh
                          +sudo /opt/scada/make_executable.sh
                          +
                        4. +
                        5. Copiez les fichiers extraits depuis le dossier daemons vers /etc/systemd/system
                        6. +
                        7. + Activez les démons: +
                          sudo systemctl enable scadaagent6.service
                          +sudo systemctl enable scadaserver6.service
                          +sudo systemctl enable scadacomm6.service
                          +sudo systemctl enable scadaweb6.service
                          +
                        8. +
                        +
                      6. +
                      7. + Créez le lecteur de RAM pour l’écriture des logs : +
                          +
                        1. + Créez le dossier pour les logs : +
                          sudo mkdir /var/log/scada
                          +
                        2. +
                        3. + Faire une copie de sauvegarde du fichier /etc/fstab, et ajoutez les lignes suivantes au fichier +
                          tmpfs           /var/log/scada  tmpfs   defaults,noatime,size=100m    0    0
                          +
                        4. +
                        +
                      8. +
                      9. + Installez et paramétrez Nginx : +
                          +
                        1. + Installez Nginx en utilisant les instructions : + lien 1, + lien 2, + lien 3. + Commandes d’installation : +
                          sudo apt update
                          +sudo apt install nginx
                          +
                        2. +
                        3. + Créez le certificat auto-signé : +
                          sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
                          +
                        4. +
                        5. Copiez les fichiers extraits nginx/default vers /etc/nginx/sites-available après avoir sauvegardé les fichiers existants.
                        6. +
                        +
                      10. +
                      11. + Redémarrez l’ordinateur : +
                        sudo reboot
                        +
                      12. +
                      13. + Après le redémarrage, ouvrez http://localhost ou http://SERVER_IP dans un navigateur web.
                        + Nom d'utilisateur : admin
                        + Mot de passe : scada +
                      14. +
                      + +

                      Désinstallation

                      +
                        +
                      1. Restaurez le fichier d'origine /etc/fstab
                      2. +
                      3. + Si Rapid SCADA a été installé depuis le package : +
                        sudo dpkg -r rapidscada
                        +
                      4. +
                      5. + Si Rapid SCADA a été installé manuellement : +
                          +
                        1. + Désactivez les démons : +
                          sudo systemctl disable scadaagent6.service
                          +sudo systemctl disable scadaserver6.service
                          +sudo systemctl disable scadacomm6.service
                          +sudo systemctl disable scadaweb6.service
                          +
                        2. +
                        3. Supprimez les fichiers démon précédemment ajoutés de /etc/systemd/system
                        4. +
                        5. Supprimez-le dossier /opt/scada avec tout son contenu.
                        6. +
                        +
                      6. +
                      7. Supprimez Nginx et .NET si c’est nécessaire.
                      8. +
                      +
                      diff --git a/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/InstallModules.cshtml b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/InstallModules.cshtml new file mode 100644 index 000000000..329cf5829 --- /dev/null +++ b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/InstallModules.cshtml @@ -0,0 +1,149 @@ +@page "/fr/latest/installation/install-modules" +@{ + Layout = "_ArticleLayout"; + ViewBag.Title = "Installation des modules"; +} + + + +
                      +

                      Installation des modules

                      +

                      Rapid SCADA supporte des modules additionnels qui permettent d’étendre les fonctionnalités de l’application. Vous pouvez trouver les modules disponibles dans la section Téléchargement du site web officiel et dans le Module Store. La version du module installé doit être compatible avec la version installée de Rapid SCADA. Les informations de compatibilité est fournit sur la page sur les modules dans le Module Store. Les modules publiés dans la section Téléchargement sont compatibles avec la version courante de Rapid SCADA.

                      + +

                      Installation des modules serveur

                      +

                      La séquence d’installation d’un nouveau module ou pour le mettre à jour pour l’application Server est la suivante :

                      +
                        +
                      1. Fermez l’application Administrator si elle est ouverte.
                      2. +
                      3. Dézippez le package d’installation du module.
                      4. +
                      5. Copiez tous les fichiers du dossier SCADA du package du module installation vers le dossier d'installation Rapid SCADA en conservant la hiérarchie des répertoires.
                      6. +
                      7. Sous Windows, recherchez les fichiers de bibliothèque *.dll copiés, ouvrez leurs propriétés une par une et déverrouillez les fichiers.
                      8. +
                      9. Lancez Administrator, ouvrez le projet trouvez et ouvrez la page Server > Modules dans l’explorateur du projet.
                      10. +
                      11. Sélectionnez le module installé dans la liste des modules qui ne sont pas utilisés et cliquez sur le bouton Activate.
                      12. +
                      13. Si la distribution du module contient des fichiers de configuration situés dans le répertoire SCADA\ScadaServer\Config, copiez-les dans votre projet.
                      14. +
                      15. Effectuez la configuration du module spécifié dans la documentation du module.
                      16. +
                      17. Enregistrez le projet et téléchargez la configuration sur le serveur.
                      18. +
                      19. + Si le module nécessite une inscription : +
                          +
                        1. Au démarrage, le module écrit le code informatique dans un fichier.
                        2. +
                        3. Dans l’application Administrator, sélectionnez le module et cliquez sur le bouton Register.
                        4. +
                        5. Obtenez une clé d’enregistrement, saisissez-la dans le champ approprié et réenregistrez.
                        6. +
                        7. Téléchargez à nouveau la configuration sur le serveur.
                        8. +
                        +
                      20. +
                      + +

                      Structure des fichiers du module

                      + + + + + + + + + + + + + + + + + +
                      ScadaAdmin\Lang\*.xmlFichiers de langue de l’UI pour l’application Administrator
                      ScadaAdmin\Lib\*.View.dllBibliothèque d’UI pour l’application Administrator
                      ScadaServer\Config\*.xmlConfiguration du module à copier dans le projet
                      ScadaServer\Mod\*.Logic.dllBibliothèque logique de modules pour l’application Server
                      + +

                      Installer les pilotes du communicateur

                      +

                      Voici la séquence d’installation d’un nouveau pilote ou de mise à jour d’un pilote existant de l’application Communicator :

                      +
                        +
                      1. Fermez l’application Aministrator si elle est en cours d’exécution.
                      2. +
                      3. Décompressez-le package d’installation du pilote.
                      4. +
                      5. Copiez tous les fichiers du dossier SCADA du package d’installation du pilote vers le répertoire d’installation Rapid SCADA en conservant la hiérarchie des répertoires.
                      6. +
                      7. Sous Windows, recherchez les fichiers de bibliothèque *.dll copiés, ouvrez leurs propriétés une par un et déverrouillez les fichiers.
                      8. +
                      9. Démarrez l’Administrator, ouvrez le projet, recherchez et ouvrez la page Communicator > Drivers dans l’explorateur de projet.
                      10. +
                      11. Assurez-vous que le pilote installé figure dans la liste des pilotes disponibles. Et si le pilote est sélectionné, sa description s’affiche.
                      12. +
                      13. Effectuez la configuration de la ligne de communication et du périphérique spécifiés dans la documentation du pilote.
                      14. +
                      15. Enregistrez le projet et téléchargez la configuration sur le serveur.
                      16. +
                      17. + Si le pilote nécessite une inscription : +
                          +
                        1. Une fois démarré, le pilote écrit le code informatique dans un fichier..
                        2. +
                        3. Dans l’application Administrator, sélectionnez le pilote et cliquez sur le bouton Register.
                        4. +
                        5. Obtenez une clef d’enregistrement, saisissez-la dans le champ approprié et enregistrez.
                        6. +
                        7. Téléchargez à nouveau la configuration sur le serveur.
                        8. +
                        +
                      18. +
                      + +

                      Structure des fichiers du pilote

                      + + + + + + + + + + + + + +
                      ScadaAdmin\Lang\*.xmlFichiers de langue de l’UI pour l’application Administrator
                      ScadaAdmin\Lib\*.View.dllUBibliothèque d’UI pour l’application Administrator.
                      ScadaComm\Drv\*.Logic.dllBibliothèque logique de pilote pour l’application Communicator.
                      + +

                      Installation des plugins de la WebStation

                      +

                      Les modules supplémentaires pour l’application Webstation sont appelés plugins. La séquence d’installation d’un nouveau plugin ou de mise à jour d’un plugin existant est la suivante :

                      +
                        +
                      1. Fermez l’application Administrator si elle est en cours d’exécution.
                      2. +
                      3. Décompressez le package d’installation du plugin.
                      4. +
                      5. Copiez tous les fichiers du dossier SCADA du package d’installation du plugin vers le répertoire d'installation Rapid SCADA en conservant la hiérarchie des répertoires.
                      6. +
                      7. Sous Windows, recherchez les fichiers de bibliothèque *.dll copiés, ouvrer leurs propriétés un par un et déverrouillez les fichiers.
                      8. +
                      9. Démarrez l’Administrator, ouvrez le projet, recherchez et ouvrez la page Webstation > Plugins dans l’explorateur de projet.
                      10. +
                      11. Sélectionnez le plugin installé dans la liste des plugins inutilisés et cliquez sur le bouton Activate.
                      12. +
                      13. Si la distribution du plugin contient des fichiers de configuration situés dans le répertoire SCADA\ScadaWeb\Config directory, copiez-les dans votre projet.
                      14. +
                      15. Si la distribution du plugin contient des vues situées dans le répertoire SCADA\Views, il est recommandé de les copier dans votre projet à titre d’exemple.
                      16. +
                      17. Effectuez la configuration du plugin spécifié dans la documentation du plugin.
                      18. +
                      19. Enregistrez le projet et téléchargez la configuration sur le serveur.
                      20. +
                      21. + Si le plugin nécessite une inscription : +
                          +
                        1. Une fois démarré, le plugin écrit le code informatique dans un fichier.
                        2. +
                        3. Dans l’application Administrator, sectionnez le plugin et cliquez sur le bouton Register.
                        4. +
                        5. Obtenez une clé d’enregistrement, saisissez-la dans le champ approprié et enregistrez.
                        6. +
                        7. Téléchargez à nouveau la configuration sur le serveur.
                        8. +
                        +
                      22. +
                      + +

                      Structure des fichiers du plugin

                      + + + + + + + + + + + + + + + + + + + + + +
                      ScadaAdmin\Lib\*.View.dllBibliothèque d’interface utilisateur pour l’application Administrator.
                      ScadaWeb\config\*.xmlConfiguration du plugin à copier dans le projet.
                      ScadaWeb\lang\*.xmlFichiers de langue du plugin pour l’application Webstation
                      ScadaWeb\wwwroot\*.*Fichiers de plugin statiques pour l’application Webstation.
                      ScadaWeb\*.dllBibliothèques de plugins pour l’application Webstation.
                      +
                      diff --git a/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/InstallWindows.cshtml b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/InstallWindows.cshtml new file mode 100644 index 000000000..60ec0b92e --- /dev/null +++ b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/InstallWindows.cshtml @@ -0,0 +1,98 @@ +@page "/fr/latest/installation/install-windows" +@{ + Layout = "_ArticleLayout"; + ViewBag.Title = "Installation sur Windows"; +} + + + +
                      +

                      Installation sur Windows

                      +

                      Préparation à l’installation

                      +

                      Rapid SCADA requiert Internet Information Services (IIS) et .NET Runtime pour être installé. Selon la version de Windows, la procédure d’installation de certains composants pourrait varier.

                      + +

                      Ouvrez Panneau de configuration > Programmes > Activer ou désactiver des fonctionnalités Windows et sélectionnez Internet Information Services. La sélection des fonctionnalités enfant à IIS peuvent être couchées par défaut.

                      +
                      + IIS components +
                      + +

                      Téléchargez depuis ce lien et installez ASP.NET Core Runtime 6.0.x (Hosting Bundle) et .NET Desktop Runtime.

                      +
                      + Download .NET +
                      + +

                      Après que l’installation des composants soit terminée, ouvrez Panneau de configuration > Système et sécurité > Outils d’administration > Gestionnaire des services Internet (IIS), naviguez dans Modules, assurer vous qu’AspNetCoreModuleV2 est installé. Si le module est manquant, réinstallez Hosting Bundle.

                      +
                      + IIS modules +
                      + +

                      Installation

                      +

                      Télécharger et décompressez le package de distribution Rapid SCADA. Lancez le fichier ScadaSetup.exe pour ouvrir l’installeur comme vu sur les captures ci-dessous. L’installation doit être réalisée avec le compte administrateur. Cliquez sur le bouton Install pour ouvrir les options d’installation.

                      +

                      Note: Si l’installateur ne démarre pas, ouvrez les fichiers de *.dll, *.exe et débloquez les fichiers.

                      +
                      + Rapid SCADA installer +
                      +
                      + Rapid SCADA installer. Choose applications +
                      +
                      + Rapid SCADA installer. Choose directory +
                      +
                      + Rapid SCADA installer. Web application options +
                      + +

                      Le port http 80 est utilisé par le site web par défaut. Par conséquent, le programme d’installation suggère un port différent, tel que 10008. Pour utiliser le port 80 pour Rapid SCADA, le site Web par défaut doit être arrêté.

                      +

                      Après que l’installation soit terminée correctement, ouvrez un navigateur web et parcourez http://localhost:10008
                      + Nom d'utilisateur : admin
                      + Mot de passe : scada

                      +

                      La première fois que l’application web se lance, cela peut prendre du temps dû au chargement des données, vous aurez besoin d’attendre environ 10 secondes et ensuite de rafraîchir la page de connexion. Par défaut, Rapid SCADA fonctionne avec le projet Hello Word. Si une erreur est rencontrée pendant la procédure d’installation, analysez-les en utilisant les logs d’installation. Utilisez le forum de support pour trouver une solution.

                      + +

                      TLes services Rapid SCADA écrivent activement des fichiers de log. Pour prolonger la durée de vie du disque dur et augmenter les performances du système, il est recommandé de configurer la journalisation sur le lecteur RAM. Voici la marche à suivre :

                      +
                        +
                      1. Installer le logiciel de création de lecteurs RAM, AMD Radeon RAMDisk ou Dataram RAMDisk.
                      2. +
                      3. Spécifier le dossier où les logs de ScadaInstanceConfig.xml seront enregistrés, par exemple, R:\SCADA\
                      4. +
                      5. Redémarrez les services Rapid SACDA et relancez votre ordinateur.
                      6. +
                      + +

                      Si l’application web n’est pas utilisée, il s’arrête. Sur un serveur de production, il est préférable que l’application web fonctionne continuellement. Pour s’en assurer, démarrez Gestionnaire de Services Internet (IIS), sélectionnez l’application ScadaAppPool,ouvrez les Réglages avancés de l’application, et définissez les options suivantes :

                      +
                        +
                      • Général – Mode de départ :AlwaysRunning
                      • +
                      • Model de procédure – Délais Idle : 0
                      • +
                      • Recyclage – Intervalle de temps régulier : 0
                      • +
                      + +

                      UpMise à jourdate

                      +

                      L’installateur permet de mettre à jour la version précédemment installée de Rapid SCADA version 6.

                      + +
                      +

                      Important

                      +
                        +
                      • Il est impossible d’utiliser l’installateur pour mettre à jour des versions de Rapid SCADA version 5 vers Rapid SCADA version 6.
                      • +
                      • La fonctionnalité de mise à jour ne vérifie pas la compatibilité du projet en cours d’exécution avec la nouvelle version du logiciel.
                      • +
                      • La mise à jour doit être avant tout testée sur un serveur de test et seulement après cette vérification être lancée sur le serveur de production./li> +
                      +
                      + +

                      La mise à jour fonctionne à la suite de ces instructions :

                      +
                        +
                      1. Vérifiez si le dossier d’installation spécifié existe.
                      2. +
                      3. Arrêtez les services de mise à jour.
                      4. +
                      5. Créez une copie de l’application mise à jour.
                      6. +
                      7. Mettez à jour l’application sélectionnée. Quand l’application a été mise à jour, les fichiers existant sur écrasés par les nouveaux. Les dossiers de configuration et de stockage de l’application ne sont pas affectés. Les modules du logiciel qui ont été installés de manière additionnelle restent inchangés.
                      8. +
                      9. Démarrez les services.
                      10. +
                      + +

                      Désinstallation

                      +

                      Désinstaller Rapid SCADA est aussi possible via l’installeur. Par conséquent, il est recommandé de ne pas supprimer la distribution Rapid SCADA de votre ordinateur après l’installation.

                      +

                      Les projets Rapid SCADA créés par les utilisateurs sont localisés dans le dossier Documents folder. Par conséquent, après la suppression de Rapid SCADA, les projets restent. Il n’est vraiment pas recommandé de sauvegarder les projets à l’intérieur du dossier d’installation, car ils pourraient être accidentellement supprimés par l’installateur.

                      +
                      diff --git a/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/InstallWindowsManual.cshtml b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/InstallWindowsManual.cshtml new file mode 100644 index 000000000..ff40c0553 --- /dev/null +++ b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/InstallWindowsManual.cshtml @@ -0,0 +1,77 @@ +@page "/fr/latest/installation/install-windows-manual" +@{ + Layout = "_ArticleLayout"; + ViewBag.Title = "Installation sur Windows manuellement"; +} + + + +
                      +

                      Installation sur Windows manuellement

                      +

                      Installer Rapid SCADA manuellement fournit le contrôle total de l’installation du logiciel, sa mise à jour et sa suppression

                      + +

                      Installation

                      +
                        +
                      1. Installez Internet Information Service (IIS) via la sélection des composants Windows correspondant.
                      2. +
                      3. +

                        Installez ASP.NET Core Runtime 6.0.x (Hosting Bundle) et .NET Desktop Runtime depuis ce lien.

                        +

                        Note: Si l’application web n’est pas requise sur Windows, passez le premier item et n’installez que .NET Desktop Runtime.

                        +
                      4. +
                      5. Copiez les fichiers de l’application dans le répertoire d’installation de Rapid SCADA C:\Program Files\SCADA
                      6. +
                      7. + Enregistrez les services en exécutant les fichiers suivants en tant qu’administrateur :
                        + ScadaAgent\svc_install.bat
                        + ScadaComm\svc_install.bat
                        + ScadaServer\svc_install.bat +
                      8. +
                      9. + Enregistrez l’application web : +
                          +
                        1. Ouvrez le manager IIS.
                        2. +
                        3. Ouvrez la liste de modules et vérifiez que le module AspNetCoreModuleV2 est présent.
                        4. +
                        5. Créez un pool d’application nommé ScadaAppPool, définissez la version .NET CLR sur No Managed Code.
                        6. +
                        7. Ouvrez les paramètres avancés du pool d’application créé, et définissez le paramètre Identité de LocalSystem.
                        8. +
                        9. Ajoutez un nouveau site web nommé ScadaWeb, spécifiez le pool d’application créé, rendez disponible le port TCP et le chemin
                          C:\Program Files\SCADA\ScadaWeb
                        10. +
                        +

                        Note: Le port http 80 est utilisé par le site web par defaut. Utilisez un autre port comme 10008 ou arrêtez le site web par défaut.

                        +
                      10. +
                      11. + Créez un lecteur RAM pour écrire des journaux : +
                          +
                        1. Installez un logiciel de création de lecteur RAM, par exemple, AMD Radeon RAMDisk ou Dataram RAMDisk.
                        2. +
                        3. Spécifiez le dossier de log dans ScadaInstanceConfig.xml, par exemple, R:\SCADA\
                        4. +
                        +
                      12. +
                      13. Créez un raccourci vers l’application Administrateur (ScadaAdmin.exe) sur le bureau.
                      14. +
                      15. Redémarrez l’ordinateur pour lancer les services automatiquement.
                      16. +
                      17. + Après le redémarrage, ouvrez http://localhost:PORT ou http://SERVER_IP:PORT dans un navigateur web.
                        + Nom d'utilisateur : admin
                        + Mot de passe : scada +
                      18. +
                      + +

                      Désinstallation

                      +
                        +
                      1. + Arrêtez et désenregistrez les services en exécutant les fichiers suivants en tant qu’administrateur :
                        + ScadaAgent\svc_stop.bat
                        + ScadaAgent\svc_uninstall.bat
                        + ScadaComm\svc_stop.bat
                        + ScadaComm\svc_uninstall.bat
                        + ScadaServer\svc_stop.bat
                        + ScadaServer\svc_uninstall.bat +
                      2. +
                      3. Désactivez le lecteur RAM.
                      4. +
                      5. Ouvrez le manager IIS et supprimez l’application web et le pool d’application précédemment créés.
                      6. +
                      7. Supprimez le dossier d’installation Rapid SCADA avec tous son contenu.
                      8. +
                      9. Supprimez le lien vers l’application Administrator sur votre bureau.
                      10. +
                      +
                      diff --git a/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/Safety.cshtml b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/Safety.cshtml new file mode 100644 index 000000000..591d475de --- /dev/null +++ b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/Safety.cshtml @@ -0,0 +1,26 @@ +@page "/fr/latest/installation/safety" +@{ + Layout = "_ArticleLayout"; + ViewBag.Title = "Recommandations de sécurité"; +} + +

                      Recommandations de sécurité

                      + +

                      Protection des fichiers

                      +

                      Si Rapid SCADA est utilisé dans un environnement d’entreprise, assurez-vous que les autres utilisateurs n’ont pas accès au répertoire d'installation de Rapid SCADA. Windows, ouvrez les propriétés du répertoire contenant les applications Rapid SCADA, choisissez l’onglet Security, vérifiez et configurez les droits d’accès.

                      + +

                      HTTPS

                      +

                      Configurez un serveur Web pour activer le protocole HTTPS pour l’application Webstation. Grâce à HTTPS, tout le trafic entre un navigateur et le serveur Web, y compris les mots de passe, est crypté.

                      + +

                      VPN

                      +

                      Utilisez un VPN pour fournir un accès aux utilisateurs externes. Si possible, évitez l’accès ouvert à Webstation depuis l’extérieur.

                      + +

                      Mots de passe

                      +

                      Changez le mot de passe par défaut. Pour créer un mot de passe fort, utilisez un générateur de mot de passe, par exemple celui-ci. Si une entreprise utilise Active Directory, le paramétrage de l’authentification utilisateur Rapid SCADA basé sur Active Directory améliore la sécurité du système.

                      +

                      Mots de passe devant être configurés :

                      +
                        +
                      • Mots de passe utilisateur dans l’onglet Users du projet.
                      • +
                      • Mot de passe pour la connexion à l’application Server dans les paramètres de Communicator et Webstation
                      • +
                      • Mot de passe agent, localisé dans le fichier ScadaAgentConfig.xml.
                      • +
                      • Mot de passe pour la connexion à l’application Agent dans le profil de déploiement.
                      • +
                      diff --git a/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/SystemRequirements.cshtml b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/SystemRequirements.cshtml new file mode 100644 index 000000000..92ea35c57 --- /dev/null +++ b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/Installation/SystemRequirements.cshtml @@ -0,0 +1,31 @@ +@page "/fr/latest/installation/system-requirements" +@{ + Layout = "_ArticleLayout"; + ViewBag.Title = "Configurations requises"; +} + +

                      Configurations requises

                      +

                      Exigences logicielles du serveur

                      +

                      Windows:

                      +
                        +
                      • Système d’exploitation : Microsoft Windows Server 2016/2019/2022, Microsoft Windows 10/11.
                      • +
                      • .NET Runtime 6.0.
                      • +
                      • Microsoft IIS est requis pour déployer l’application web.
                      • +
                      + +

                      Linux:

                      +
                        +
                      • Système d’exploitation : Ubuntu (recommandé), Alpine, CentOS, Debian, Fedora, OpenSUSE, Red Hat, et plus.
                      • +
                      • .NET Runtime 6.0.
                      • +
                      • Nginx est requis pour déployer l’application web.
                      • +
                      + +

                      Exigences hardware du serveur

                      +

                      La configuration hardware d’un serveur dépend de l’échelle du système automatisé. La configuration minimum est déterminée par les exigences du système d’exploitation.

                      +

                      Par défaut, Rapid SCADA utilise ses propres systèmes de management de bases de données intégrées, l’installation d’un SGBD tiers n’est donc pas nécessaire. Le logiciel peut fonctionner sur des machines physiques ou virtuelles.

                      + +

                      Exigences relatives au poste de travail

                      +
                        +
                      • Mise à jour du navigateur Chrome, Firefox, Safari ou Edge.
                      • +
                      • Microsoft Office ou LibreOffice sont requis pour afficher les rapports.
                      • +
                      diff --git a/ScadaDoc/ScadaDoc/Pages/Fr/Version61/SoftwareOverview/Introduction.cshtml b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/SoftwareOverview/Introduction.cshtml new file mode 100644 index 000000000..f03cddd9a --- /dev/null +++ b/ScadaDoc/ScadaDoc/Pages/Fr/Version61/SoftwareOverview/Introduction.cshtml @@ -0,0 +1,142 @@ +@page "/fr/latest/software-overview/introduction" +@{ + Layout = "_ArticleLayout"; + ViewBag.Title = "Introduction"; +} + + + +
                      +

                      Introduction

                      +

                      Qu’est-ce que Rapid SCADA

                      +

                      Rapid SCADA est une plateforme d’automatisation industrielle open source. Le logiciel prêt à l’emploi fournit des outils de création rapide de système de surveillance et de contrôle.

                      +

                      L’open source est la clef de la transparence et de la sécurité des logiciels. Le code open source est disponible sur GitHub. Rapid SCADA est délivré sous Apache License 2.0 qui permet la création de nouveaux produits logiciels dérivés.

                      +

                      Rapid SCADA est le choix parfait pour la création d’importants systèmes d’automatisation industrielle distribués. Rapid SCADA fonctionne sur serveur, sur calculateurs embarqués et sur le cloud. Les nœuds Rapid SCADA échangent des informations entre eux, et interagissent avec des bases de données externes en temps réel.

                      +

                      Les principales classes de systèmes développées utilisées par Rapid SCADA sont les suivantes :

                      +
                        +
                      • Systèmes d’automatisation industrielle et systèmes IIoT.
                      • +
                      • Systèmes de contrôle de procédures.
                      • +
                      • Systèmes de comptabilité énergétiques.
                      • +
                      + +

                      Principales caractéristiques

                      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                      Général
                      Familles de systèmes d’exploitation prises en chargeWindows, Linux
                      Nombre illimité de canaux, tags et appareils
                      Configuration et maintenance à distance des projets
                      Travail simultané sur des projets avec GIT
                      Support technique gratuit et payant
                      Sécurité
                      HTTPS, SSL
                      Protection contre les attaques par force brute
                      Captcha à la connexion
                      Surveillance des connexions
                      Cryptage du mot de passe
                      Journalisation de l’activité des utilisateurs
                      Redondace
                      Serveur principal et serveur de sauvegarde avec synchronisation automatique des données
                      Serveurs centraux et distants avec synchronisation automatique des données
                      Mise en miroir
                      Archivage
                      Stockage des donnéesFichiers, PostgreSQL, InfluxDB
                      Nombre maximum d’archives indépendantes31
                      Période d’écriture
                      Écriture sur le changement
                      Connectivité
                      Intégration avec des bases de donnéesOracle, MS SQL, MySQL, PostgreSQL
                      Protocoles industriels OPC UA, OPC Classic, Modbus, MQTT, SNMP, etc.
                      Programmation
                      REST API
                      Exemples de modules avec code source
                      Documentation pour les développeurs
                      +
                      diff --git a/ScadaDoc/ScadaDoc/Pages/Index.cshtml b/ScadaDoc/ScadaDoc/Pages/Index.cshtml index 97b3b4d87..a7899bf95 100644 --- a/ScadaDoc/ScadaDoc/Pages/Index.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/Index.cshtml @@ -1,5 +1,4 @@ @page -@model Scada.Doc.Pages.IndexModel @{ Layout = "_BasicLayout"; ViewBag.Title = "Documentation"; diff --git a/ScadaDoc/ScadaDoc/Pages/Index.cshtml.cs b/ScadaDoc/ScadaDoc/Pages/Index.cshtml.cs deleted file mode 100644 index 821bd8dd0..000000000 --- a/ScadaDoc/ScadaDoc/Pages/Index.cshtml.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace Scada.Doc.Pages -{ - public class IndexModel : PageModel - { - public void OnGet() - { - } - } -} diff --git a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Installation/InstallLinux.cshtml b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Installation/InstallLinux.cshtml index d8f0853ba..0cbf7324c 100644 --- a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Installation/InstallLinux.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Installation/InstallLinux.cshtml @@ -67,7 +67,7 @@ sudo systemctl enable scadaweb6.service Создать RAM-диск для записи журналов:
                      1. Создать директорию журналов, выполнив команду -
                        sudo mkdir /var/log/scadasudo mkdir /var/log/scada
                        +
                        sudo mkdir /var/log/scada
                      2. Добавить в файл /etc/fstab указанную нижу строку, предварительно сохранив резервную копию существующего файла.
                        tmpfs           /var/log/scada  tmpfs   defaults,noatime,size=100m    0    0
                        diff --git a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Modules/PlgChartPro.cshtml b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Modules/PlgChartPro.cshtml index 2f71f48af..0bfe01adc 100644 --- a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Modules/PlgChartPro.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Modules/PlgChartPro.cshtml @@ -10,7 +10,12 @@ @@ -100,4 +105,11 @@
                        Компоновка графика
                        + +

                        Режим представлений

                        +

                        Плагин Графики Про поддерживает работу в режиме представлений, при котором узел графика добавляется в дерево представлений Вебстанции. Чтобы показать график как представление, необходимо добавить в таблицу представлений строку следующего вида:

                        +
                        + Таблица Представления +
                        +

                        Поле Путь содержит путь в дереве представлений. Тип представления - График Про. Аргументы представления соответствуют параметрам строки запроса, описанным выше.

                    diff --git a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Modules/PlgDashboard.cshtml b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Modules/PlgDashboard.cshtml index 2bcf00eb0..0caaf8e05 100644 --- a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Modules/PlgDashboard.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Modules/PlgDashboard.cshtml @@ -21,7 +21,7 @@
                  • Конфигурирование
                  • @@ -33,17 +33,79 @@

                    Обзор

                    Плагин Дэшборды отображает полезные виджеты на дэшбордах: графики, текущие данные и произвольные фреймы, например, изображение с камеры видео-наблюдения. Настройки каждого дэшборда позволяют задать количество столбцов и соотношение сторон виджетов. Скачать плагин можно по ссылке. Внешний вид плагина Дэшборды показан на следующем рисунке.

                    +
                    + Плагин Дэшборды +

                    Установка

                    - +

                    Установка плагина Дэшборды выполняется по инструкции. В ходе установки каких-либо нестандартных действий не требуется.

                    Конфигурирование

                    +

                    Подключение дэшбордов

                    +

                    Конфигурация каждого дэшборда сохраняется в отдельном файле формата XML. Пример файла дэшборда Dashboard1.xml содержится в установочном пакете плагина. Файлы дэшбордов должны располагаться в директории представлений.

                    +

                    Чтобы дэшборды появились в дереве представлений Вебстанции, в проекте необходимо выполнить следующие настройки:

                    +
                      +
                    1. Создать и отредактировать файл дэшборда в директории представлений.
                    2. +
                    3. Прописать путь к дэшборду в таблице Представления базы конфигурации.
                    4. +
                    +
                    + Файл дэшборда +
                    +
                    + Таблица Представления +
                    +

                    Необходимо явно указать тип представления, потому что приложение Вебстанция не может автоматически определить тип по расширению файлов xml.

                    +

                    Структура файла дэшборда

                    +

                    Дэшборд состоит из виджетов. Расположением виджетов на дэшборде управляет табличная система Bootstrap. Виджеты располагаются по строкам, каждая из которых может содержать до 12 виджетов. Для виджета можно задать ширину от 1 до 12, таким образом, чтобы суммарная ширина виджетов в строке была равна 12. Если ширина виджета не указана, она рассчитывается автоматически. Точка разрыва определяет ширину веб-страницы, больше которой виджеты отображаются на одной строке, в противоположном случае виджеты отображаются один под другим.

                    +

                    Рассмотрим содержимое файла дэшборда:

                    -

                    Подключение дэшбордов

                    - +
                    <?xml version="1.0" encoding="utf-8" ?>
                    +<DashboardView>
                    +  <DashboardOptions>
                    +    <!-- Widget AspectRatio = Width / Height -->
                    +    <AspectRatio>1.33</AspectRatio>
                    +    <!-- Breakpoint: ExtraSmall | Small | Medium | Large | ExtraLarge | ExtraExtraLarge -->
                    +    <Breakpoint>Small</Breakpoint>
                    +  </DashboardOptions>
                    +  <Widgets>
                    +    <!-- The total width of the columns in a line is 12 -->
                    +    <Row>
                    +      <Widget type="Chart" columnWidth="5" cnlNums="101,102" />
                    +      <Widget type="Chart" columnWidth="4" cnlNums="101,103" mode="fixed" period="-2" title="Sample Chart" profile="PlgChartPro.xml" />
                    +      <Widget type="CurData" columnWidth="3" cnlNums="101-105" title="Sample Data" />
                    +    </Row>
                    +    <Row columnCount="2">
                    +      <Widget type="View" viewID="2" />
                    +      <Widget type="CustomUrl" url="https://www.youtube.com/embed/xAieE-QtOeM" />
                    +    </Row>
                    +  </Widgets>
                    +</DashboardView>
                    -

                    Структура файла дэшборда

                    +

                    + Секция DashboardOptions содержит общие параметры дэшборда:
                    + AspectRatio - отношение ширины виджетов к высоте,
                    + Breakpoint - точка разрыва. +

                    +

                    Секция Widgets содержит список виджетов, которые отображаются на дэшборде. Количество виджетов на дэшборде произвольное, но не более 12 на одной строке. Следует учитывать, что слишком большое количество виджетов на одном дэшборде может снизить быстродействие веб-приложения.

                    +

                    + Атрибут элемента Row:
                    + columnCount - количество столбцов, на которые разбиваются виджеты данной строки. Если для строки указан атрибут columnCount, то для виджетов этой строки атрибут columnWidth не требуется. +

                    +

                    + Основные атрибуты элемента Widget:
                    + type - тип виджета,
                    + columnWidth - ширина виджета от 1 до 12,
                    + cnlNums - номера каналов. +

                    +

                    + Поддерживаются виджеты следующих типов:
                    + Chart - график заданных каналов,
                    + CurData - таблица текущих значений заданных каналов,
                    + View - представление с указанным идентификатором,
                    + CustomUrl - произвольная веб-страница. +

                    +

                    Виджеты типа Chart поддерживают атрибуты, которые совпадают с параметрами строки запроса, описанными в документации на плагин Графики Про. При фильтрации событий по представлению используются номера каналов, заданные в атрибутах cnlNums виджетов.

diff --git a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Modules/PlgElasticReport.cshtml b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Modules/PlgElasticReport.cshtml new file mode 100644 index 000000000..66d578483 --- /dev/null +++ b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/Modules/PlgElasticReport.cshtml @@ -0,0 +1,133 @@ +@page "/ru/latest/modules/plg-elastic-report" +@{ + Layout = "_ArticleLayout"; + ViewBag.Title = "Плагин Гибкий отчёт"; +} + +@section Styles { + +} + +@section Scripts { + +} + + + +
+

Плагин Гибкий отчёт

+

Обзор

+

Плагин Гибкий отчёт позволяет генерировать отчёты в соответствии с пользовательской конфигурацией. С помощью данного плагина Вы можете построить практически любой необходимый отчёт. Пользователю достаточно выбрать период и нажать на кнопку генерации отчёта. Конфигурации отчётов предварительно создаются администратором. Скачать плагин можно по ссылке.

+ +

Установка

+

Плагин Гибкий отчёт устанавливается по инструкции. В ходе установки выполните дополнительное действие: скопируйте файл PlgElasticReport.xml из дистрибутива плагина в свой проект. Файл должен отображаться в проводнике проекта внутри узла Вебстанция > Конфигурационные файлы.

+ +

Конфигурирование

+

Отчёт состоит из секций, которые выводятся в выходной документ одна за другой. Каждая секция имеет свой тип, параметры и привязку к данным. Кроме того, отчёт имеет общие параметры, влияющие на все секции. Один и тот же отчёт может быть сгенерирован в различных форматах. В настоящий момент поддерживаются форматы PDF, Excel и HTML. При этом внешний вид одного и того же отчёта, сгенерированного в разных форматах, может незначительно отличаться.

+ +

Форма отчёта

+

Для каждой отчётной формы создаётся отдельный файл конфигурации в формате XML. Файл конфигурации задаёт форматирование отчёта и определяет привязку данных отчёта к каналам. Этот файл должен быть сохранён в директории представлений или в её поддиректории внутри проекта.

+
+ Файл отчёта +
+

Редактирование файлов конфигурации может осуществляться в любом текстовом редакторе. Например, бесплатный редактор Notepad++ удобен для работы с XML-файлами.

+

Пример файла отчёта ElasticReport1.xml содержится в установочном пакете плагина. Данный пример включает подробное описание параметров настройки и демонстрирует формирование секций отчёта всех возможных типов.

+

Основные элементы файла конфигурации отчёта:

+
    +
  • Элемент InputOptions содержит настройки входной формы отчёта, с помощью которой пользователь вводит параметры отчёта и запускает формирование документа.
  • +
  • Элемент OutputOptions содержит настройки форматирования генерируемого документа.
  • +
  • + Элемент Document определяет содержимое отчёта. +
      +
    • Элемент DocumentOptions задаёт основные параметры, относящиеся ко всему документу.
    • +
    • Элемент Section описывает секцию отчёта, содержащую данные. Отчёт включает одну или несколько секций различных типов.
    • +
    +
  • +
+

Поддерживаемые типы секций:

+
    +
  • Секция TimeData отображает данные каналов за выбранный период времени. По горизонтали расположены каналы, по вертикали - временные точки.
  • +
  • Секция TimeTime отображает данные одного канала в компактной форме. По горизонтали и вертикали расположены временные точки.
  • +
  • Секция DataData отображает данные в форме таблицы, каждая ячейка которой может быть привязана к своему каналу.
  • +
+

Плагин позволяет формировать отчёты по историческим данным. Отчёты по текущим данным и событиям не поддерживаются. При выборе исторического архива, на основе которого строится отчёт, рекомендуется отдавать предпочтение архиву с периодом записи данных, совпадающим или близким к шагу секций отчёта. Это позволит избежать выборки лишних данных.

+ +

Список отчётов

+

Конфигурационный файл PlgElasticReport.xml содержит список отчётов по группам, которые отображаются на странице Главное меню > Отчёты. Пример содержимого файла:

+
<?xml version="1.0" encoding="utf-8" ?>
+<PlgElasticReport>
+  <ReportGroup name="Elastic Reports" isPublic="false" objNum="0">
+    <ReportItem reportID="1" isPublic="false" objNum="0" config="Reports\ElasticReport1.xml" prefix="MyRep" cnlNums="">My report</ReportItem>
+  </ReportGroup>
+</PlgElasticReport>
+ +

+ Атрибуты элемента ReportGroup:
+ name - отображаемое наименование группы отчётов;
+ isPublic - является ли группа публичной, то есть доступной всем пользователям;
+ objNum - номер объекта, к которому относятся отчёты группы. Ограничивает видимость группы в соответствии с правами пользователя на объект. +

+

+ Атрибуты элемента ReportItem:
+ reportID - идентификатор отчёта, уникальный в пределах конфигурационного файла;
+ isPublic - является ли отчёт публичным, то есть доступным всем пользователям;
+ objNum - номер объекта, к которому относится отчёт. Ограничивает доступность отчёта в соответствии с правами пользователя на объект;
+ config - путь к файлу конфигурации отчётной формы относительно директории представлений,
+ prefix - префикс имени файла, используемый при скачивании отчёта,
+ cnlNums - фиксированные номера каналов, по которым строится отчёт. +

+ +

Стили

+

Имеется возможность настроить собственные стили отчётов: шрифты, цвета, размеры ячеек и т.д. Для каждого формата отчётов стили настраиваются отдельно.

+ +

PDF-стили

+

Файлы PdfStyleDefault.xml и PdfStyleCustom.xml задают форматирование отчётов в формате PDF. Эти файлы расположены в директории веб-приложения ScadaWeb\wwwroot\plugins\ElasticReport\templates. Файл PdfStyleDefault.xml содержит стили по умолчанию и должен оставаться неизменным. Пользовательские стили добавляются в файл PdfStyleCustom.xml. Создавая пользовательские стили, можно наследовать новые стили от существующих или переопределять существующие стили.

+ +

Excel-стили

+

Аналогично файлы ExcelStyleDefault.xml и ExcelStyleCustom.xml, расположенные в той же директории, задают форматирование отчётов в формате Excel. Файл ExcelStyleDefault.xml содержит стили по умолчанию и должен оставаться неизменным. Пользовательские стили добавляются в файл ExcelStyleCustom.xml. Будьте внимательны, форматы файлов стилей PDF и Excel отличаются.

+ +

HTML-стили

+

Файлы html-style-default.scss и html-style-custom.css определяют отображение отчётов в формате HTML. Файлы расположены в директории ScadaWeb\wwwroot\plugins\ElasticReport\css. Пользовательские стили добавляются в файл html-style-custom.css по правилам каскадных таблиц стилей (CSS).

+ +

Шрифты

+

Шрифты в формате PDF

+

При формировании отчётов в формате PDF по умолчанию используется шрифт Arial. Если требуемый шрифт отсутствует в операционной системе, он заменяется на встроенный шрифт Segoe WP. Чтобы изменить шрифт отчётов, необходимо отредактировать файл стилей.

+

Поиск шрифта для загрузки происходит по следующему алгоритму:

+
    +
  1. Определяется директория поиска. На Windows поиск выполняется в директории C:\Windows\Fonts, на Linux - в директории /usr/share/fonts/truetype
  2. +
  3. + На основе имени шрифта (FontFamily) определяются требуемые имена файлов шрифтов. +
      +
    1. Обычный шрифт: FontFamily.ttf, FontFamily-Regular.ttf
    2. +
    3. Жирный шрифт: FontFamilyb.ttf, FontFamilybd.ttf, FontFamily-Bold.ttf
    4. +
    5. Наклонный шрифт: FontFamilyi.ttf, FontFamily-Italic.ttf, FontFamily-Oblique.ttf
    6. +
    7. Жирный и наклонный: FontFamilybi.ttf, FontFamily-BoldItalic.ttf, FontFamily-BoldOblique.ttf
    8. +
    +
  4. +
  5. Определяются запасные имена файлов шрифтов (кандидаты). Для жирного или наклонного шрифта в качестве кандидатов используются файлы обычного шрифта. Для обычного шрифта запасные варианты отсутствуют.
  6. +
  7. Если в директории поиска находится желаемый или запасной шрифт, то файл шрифта загружается и предоставляется для генерации отчёта. Поиск не чувствителен к регистру символов.
  8. +
+

Установленные по умолчанию шрифты обычно не содержат символов таких языков как китайский и корейский. Для формирования отчётов на таких языках рекомендуется установить шрифт Arial Unicode MS. На Windows установка шрифта должна производиться для всех пользователей, чтобы файл шрифта был помещён в директорию C:\Windows\Fonts

+
+ Установка шрифта +
+ +

Шрифты в формате Excel

+

В генерируемых отчётах в формате Excel указывается только наименование шрифта, сам шрифт не включается в файл отчёта. По умолчанию используется шрифт Arial. При открытии файла с помощью Microsoft Excel или Libre Office Calc шрифт загружается приложением из системы. Если шрифт отсутствует, используется автоматическая замена. Изменить шрифт можно с помощью файла стилей.

+
diff --git a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/AdministratorHistory.cshtml b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/AdministratorHistory.cshtml index 8c5139c36..702cd33b4 100644 --- a/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/AdministratorHistory.cshtml +++ b/ScadaDoc/ScadaDoc/Pages/Ru/Version61/VersionHistory/AdministratorHistory.cshtml @@ -23,6 +23,11 @@

История Администратора

Приложение Администратор

+
ScadaAdmin 6.1.1.1 (10.12.2023)
+
    +
  • Исправлено создание границ канала
  • +
+
ScadaAdmin 6.1.1.0 (25.09.2023)