1472 lines
65 KiB
VB.net
1472 lines
65 KiB
VB.net
Imports System.IO
|
|
Imports System.Net.Sockets
|
|
Imports System.Reflection
|
|
Imports System.Security.Cryptography
|
|
Imports System.Text
|
|
Imports System.Text.Json
|
|
Imports System.Threading
|
|
|
|
Public Class Form1
|
|
Private Const ConfigFileName As String = "moxa-okuma-settings.json"
|
|
|
|
Private ReadOnly cboAzienda As New ComboBox()
|
|
Private ReadOnly cboMacchina As New ComboBox()
|
|
Private ReadOnly txtIpMoxa As New TextBox()
|
|
Private ReadOnly nudPorta As New NumericUpDown()
|
|
Private ReadOnly nudTimeoutConnessione As New NumericUpDown()
|
|
Private ReadOnly nudTimeoutInattivita As New NumericUpDown()
|
|
Private ReadOnly nudPausaRiga As New NumericUpDown()
|
|
Private ReadOnly nudPausaCarattere As New NumericUpDown()
|
|
Private ReadOnly nudDimensioneBlocco As New NumericUpDown()
|
|
Private ReadOnly nudPausaBlocco As New NumericUpDown()
|
|
Private ReadOnly nudAttesaPrimaInvio As New NumericUpDown()
|
|
Private ReadOnly nudAttesaDopoInvio As New NumericUpDown()
|
|
Private ReadOnly chkInvioRigaPerRiga As New CheckBox()
|
|
Private ReadOnly chkInvioCaratterePerCarattere As New CheckBox()
|
|
Private ReadOnly chkInvioBlocchi As New CheckBox()
|
|
Private ReadOnly cboTerminatoreInvio As New ComboBox()
|
|
Private ReadOnly txtFileInvio As New TextBox()
|
|
Private ReadOnly txtFileRicezione As New TextBox()
|
|
Private ReadOnly btnSfogliaInvio As New Button()
|
|
Private ReadOnly btnSfogliaRicezione As New Button()
|
|
Private ReadOnly btnTestConnessione As New Button()
|
|
Private ReadOnly btnInvia As New Button()
|
|
Private ReadOnly btnRicevi As New Button()
|
|
Private ReadOnly btnAnnulla As New Button()
|
|
Private ReadOnly mnuSblocca As New ToolStripMenuItem("Sblocca controlli")
|
|
Private ReadOnly mnuCambiaPassword As New ToolStripMenuItem("Cambia password")
|
|
Private ReadOnly mnuPulisciLog As New ToolStripMenuItem("Pulisci log")
|
|
Private ReadOnly mnuInformazioni As New ToolStripMenuItem("Informazioni su")
|
|
Private ReadOnly btnAggiornaStatoMoxa As New Button()
|
|
Private ReadOnly chkMonitorStatoMoxa As New CheckBox()
|
|
Private ReadOnly nudIntervalloStatoMoxa As New NumericUpDown()
|
|
Private ReadOnly lstStatoMoxa As New ListView()
|
|
Private ReadOnly imgStatoMoxa As New ImageList()
|
|
Private ReadOnly txtFileModifica As New TextBox()
|
|
Private ReadOnly txtNomeFileModifica As New TextBox()
|
|
Private ReadOnly btnSfogliaModifica As New Button()
|
|
Private ReadOnly btnRendiMaiuscolo As New Button()
|
|
Private ReadOnly btnAggiungiElementiOkuma As New Button()
|
|
Private ReadOnly btnSalvaModifica As New Button()
|
|
Private ReadOnly rtbEditorModifica As New RichTextBox()
|
|
Private ReadOnly statusTimer As New System.Windows.Forms.Timer()
|
|
Private ReadOnly txtLog As New TextBox()
|
|
Private ReadOnly progress As New ProgressBar()
|
|
Private ReadOnly lockedControls As New List(Of Control)()
|
|
|
|
Private appConfig As AppConfig
|
|
Private cts As CancellationTokenSource
|
|
Private controlsUnlocked As Boolean
|
|
Private loadingSelection As Boolean
|
|
Private checkingMoxaStatus As Boolean
|
|
Private currentEditDirectory As String = ""
|
|
|
|
Public Sub New()
|
|
InitializeComponent()
|
|
appConfig = LoadOrCreateConfig()
|
|
CleanupOldTemporaryReceives()
|
|
BuildInterface()
|
|
LoadCompanies()
|
|
SetControlsUnlocked(False)
|
|
End Sub
|
|
|
|
Private Sub BuildInterface()
|
|
Text = "LMEMoxaTransfer"
|
|
Icon = New Icon(Path.Combine(Application.StartupPath, "Assets", "app-icon.ico"))
|
|
MinimumSize = New Size(1030, 690)
|
|
Size = New Size(1120, 760)
|
|
StartPosition = FormStartPosition.CenterScreen
|
|
|
|
Dim shell As New TableLayoutPanel With {
|
|
.Dock = DockStyle.Fill,
|
|
.ColumnCount = 1,
|
|
.RowCount = 2,
|
|
.Margin = Padding.Empty,
|
|
.Padding = Padding.Empty
|
|
}
|
|
shell.RowStyles.Add(New RowStyle(SizeType.AutoSize))
|
|
shell.RowStyles.Add(New RowStyle(SizeType.Percent, 100))
|
|
Controls.Add(shell)
|
|
|
|
Dim mainMenu = BuildMainMenu()
|
|
MainMenuStrip = mainMenu
|
|
mainMenu.Dock = DockStyle.Fill
|
|
shell.Controls.Add(mainMenu, 0, 0)
|
|
|
|
Dim tabs As New TabControl With {.Dock = DockStyle.Fill, .Margin = Padding.Empty}
|
|
Dim tabTrasferimento As New TabPage("Trasferimento programmi")
|
|
Dim tabModificaFile As New TabPage("Modifica file")
|
|
Dim tabStatoMoxa As New TabPage("Stato Moxa")
|
|
tabs.TabPages.Add(tabTrasferimento)
|
|
tabs.TabPages.Add(tabModificaFile)
|
|
tabs.TabPages.Add(tabStatoMoxa)
|
|
shell.Controls.Add(tabs, 0, 1)
|
|
|
|
Dim root As New TableLayoutPanel With {
|
|
.Dock = DockStyle.Fill,
|
|
.ColumnCount = 1,
|
|
.RowCount = 4,
|
|
.Padding = New Padding(14)
|
|
}
|
|
root.RowStyles.Add(New RowStyle(SizeType.AutoSize))
|
|
root.RowStyles.Add(New RowStyle(SizeType.AutoSize))
|
|
root.RowStyles.Add(New RowStyle(SizeType.Percent, 100))
|
|
root.RowStyles.Add(New RowStyle(SizeType.AutoSize))
|
|
tabTrasferimento.Controls.Add(root)
|
|
|
|
Dim grpConnessione As New GroupBox With {
|
|
.Text = "Connessione Moxa",
|
|
.Dock = DockStyle.Top,
|
|
.AutoSize = True,
|
|
.Padding = New Padding(12)
|
|
}
|
|
root.Controls.Add(grpConnessione, 0, 0)
|
|
|
|
Dim conn As New TableLayoutPanel With {.Dock = DockStyle.Fill, .ColumnCount = 10, .AutoSize = True}
|
|
conn.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
|
|
conn.ColumnStyles.Add(New ColumnStyle(SizeType.Absolute, 150))
|
|
conn.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
|
|
conn.ColumnStyles.Add(New ColumnStyle(SizeType.Absolute, 230))
|
|
conn.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
|
|
conn.ColumnStyles.Add(New ColumnStyle(SizeType.Absolute, 135))
|
|
conn.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
|
|
conn.ColumnStyles.Add(New ColumnStyle(SizeType.Absolute, 90))
|
|
conn.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
|
|
conn.ColumnStyles.Add(New ColumnStyle(SizeType.Absolute, 90))
|
|
grpConnessione.Controls.Add(conn)
|
|
|
|
cboAzienda.DropDownStyle = ComboBoxStyle.DropDownList
|
|
cboAzienda.Dock = DockStyle.Fill
|
|
cboMacchina.DropDownStyle = ComboBoxStyle.DropDownList
|
|
cboMacchina.Dock = DockStyle.Fill
|
|
txtIpMoxa.Dock = DockStyle.Fill
|
|
txtIpMoxa.ReadOnly = True
|
|
nudPorta.Minimum = 1
|
|
nudPorta.Maximum = 65535
|
|
nudTimeoutConnessione.Minimum = 1
|
|
nudTimeoutConnessione.Maximum = 120
|
|
nudTimeoutInattivita.Minimum = 1
|
|
nudTimeoutInattivita.Maximum = 120
|
|
|
|
conn.Controls.Add(New Label With {.Text = "Azienda", .AutoSize = True, .Anchor = AnchorStyles.Left}, 0, 0)
|
|
conn.Controls.Add(cboAzienda, 1, 0)
|
|
conn.Controls.Add(New Label With {.Text = "Macchina", .AutoSize = True, .Anchor = AnchorStyles.Left, .Margin = New Padding(14, 0, 3, 0)}, 2, 0)
|
|
conn.Controls.Add(cboMacchina, 3, 0)
|
|
conn.Controls.Add(New Label With {.Text = "IP Moxa", .AutoSize = True, .Anchor = AnchorStyles.Left, .Margin = New Padding(14, 0, 3, 0)}, 4, 0)
|
|
conn.Controls.Add(txtIpMoxa, 5, 0)
|
|
conn.Controls.Add(New Label With {.Text = "Porta", .AutoSize = True, .Anchor = AnchorStyles.Left, .Margin = New Padding(14, 0, 3, 0)}, 6, 0)
|
|
conn.Controls.Add(nudPorta, 7, 0)
|
|
conn.Controls.Add(New Label With {.Text = "Timeout s", .AutoSize = True, .Anchor = AnchorStyles.Left, .Margin = New Padding(14, 0, 3, 0)}, 8, 0)
|
|
conn.Controls.Add(nudTimeoutConnessione, 9, 0)
|
|
|
|
Dim grpTrasferimento As New GroupBox With {
|
|
.Text = "Invio e ricezione programmi",
|
|
.Dock = DockStyle.Top,
|
|
.AutoSize = True,
|
|
.Padding = New Padding(12),
|
|
.Margin = New Padding(0, 12, 0, 12)
|
|
}
|
|
root.Controls.Add(grpTrasferimento, 0, 1)
|
|
|
|
Dim transfer As New TableLayoutPanel With {.Dock = DockStyle.Fill, .ColumnCount = 4, .RowCount = 10, .AutoSize = True}
|
|
transfer.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
|
|
transfer.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 100))
|
|
transfer.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
|
|
transfer.ColumnStyles.Add(New ColumnStyle(SizeType.Absolute, 120))
|
|
grpTrasferimento.Controls.Add(transfer)
|
|
|
|
ConfigureButton(btnSfogliaInvio, "Sfoglia")
|
|
ConfigureButton(btnSfogliaRicezione, "Sfoglia")
|
|
ConfigureButton(btnTestConnessione, "Test connessione")
|
|
ConfigureButton(btnInvia, "Invia a Okuma")
|
|
ConfigureButton(btnRicevi, "Ricevi da Okuma")
|
|
ConfigureButton(btnAnnulla, "Annulla")
|
|
btnAnnulla.Enabled = False
|
|
|
|
txtFileInvio.Dock = DockStyle.Fill
|
|
txtFileRicezione.Dock = DockStyle.Fill
|
|
cboTerminatoreInvio.DropDownStyle = ComboBoxStyle.DropDownList
|
|
cboTerminatoreInvio.Items.AddRange(New Object() {"Nessuno", "CR", "LF", "CRLF", "%", "% + CRLF"})
|
|
chkInvioRigaPerRiga.Text = "Invio riga per riga"
|
|
chkInvioRigaPerRiga.AutoSize = True
|
|
chkInvioCaratterePerCarattere.Text = "Invio carattere per carattere"
|
|
chkInvioCaratterePerCarattere.AutoSize = True
|
|
chkInvioBlocchi.Text = "Invio a blocchi (% + CRLF)"
|
|
chkInvioBlocchi.AutoSize = True
|
|
ConfigureNumericDefaults()
|
|
|
|
transfer.Controls.Add(New Label With {.Text = "File da inviare", .AutoSize = True, .Anchor = AnchorStyles.Left}, 0, 0)
|
|
transfer.Controls.Add(txtFileInvio, 1, 0)
|
|
transfer.Controls.Add(btnSfogliaInvio, 2, 0)
|
|
transfer.Controls.Add(btnInvia, 3, 0)
|
|
transfer.Controls.Add(New Label With {.Text = "Cartella ricezione", .AutoSize = True, .Anchor = AnchorStyles.Left}, 0, 1)
|
|
transfer.Controls.Add(txtFileRicezione, 1, 1)
|
|
transfer.Controls.Add(btnSfogliaRicezione, 2, 1)
|
|
transfer.Controls.Add(btnRicevi, 3, 1)
|
|
transfer.Controls.Add(New Label With {.Text = "Terminatore invio", .AutoSize = True, .Anchor = AnchorStyles.Left}, 0, 2)
|
|
transfer.Controls.Add(cboTerminatoreInvio, 1, 2)
|
|
transfer.Controls.Add(btnAnnulla, 3, 2)
|
|
transfer.Controls.Add(New Label With {.Text = "Pausa riga ms", .AutoSize = True, .Anchor = AnchorStyles.Left}, 0, 3)
|
|
transfer.Controls.Add(nudPausaRiga, 1, 3)
|
|
transfer.Controls.Add(chkInvioRigaPerRiga, 2, 3)
|
|
transfer.Controls.Add(New Label With {.Text = "Pausa carattere ms", .AutoSize = True, .Anchor = AnchorStyles.Left}, 0, 4)
|
|
transfer.Controls.Add(nudPausaCarattere, 1, 4)
|
|
transfer.Controls.Add(chkInvioCaratterePerCarattere, 2, 4)
|
|
transfer.Controls.Add(New Label With {.Text = "Modo Okuma READ", .AutoSize = True, .Anchor = AnchorStyles.Left}, 0, 5)
|
|
transfer.Controls.Add(chkInvioBlocchi, 1, 5)
|
|
transfer.Controls.Add(New Label With {.Text = "Dim. blocco byte", .AutoSize = True, .Anchor = AnchorStyles.Left}, 2, 5)
|
|
transfer.Controls.Add(nudDimensioneBlocco, 3, 5)
|
|
transfer.Controls.Add(New Label With {.Text = "Pausa blocco ms", .AutoSize = True, .Anchor = AnchorStyles.Left}, 0, 6)
|
|
transfer.Controls.Add(nudPausaBlocco, 1, 6)
|
|
transfer.Controls.Add(New Label With {.Text = "Fine ricez. s", .AutoSize = True, .Anchor = AnchorStyles.Left}, 2, 6)
|
|
transfer.Controls.Add(nudTimeoutInattivita, 3, 6)
|
|
transfer.Controls.Add(New Label With {.Text = "Attesa prima invio s", .AutoSize = True, .Anchor = AnchorStyles.Left}, 0, 7)
|
|
transfer.Controls.Add(nudAttesaPrimaInvio, 1, 7)
|
|
transfer.Controls.Add(btnTestConnessione, 3, 7)
|
|
transfer.Controls.Add(New Label With {.Text = "Attesa dopo invio s", .AutoSize = True, .Anchor = AnchorStyles.Left}, 0, 8)
|
|
transfer.Controls.Add(nudAttesaDopoInvio, 1, 8)
|
|
|
|
Dim hint As New Label With {
|
|
.Text = "Prima di ricevere o inviare, selezionare azienda e macchina. I parametri Moxa vengono compilati dal file JSON nello start path.",
|
|
.AutoSize = True,
|
|
.Dock = DockStyle.Fill,
|
|
.ForeColor = Color.FromArgb(70, 70, 70),
|
|
.Margin = New Padding(0, 10, 0, 0)
|
|
}
|
|
transfer.SetColumnSpan(hint, 4)
|
|
transfer.Controls.Add(hint, 0, 9)
|
|
|
|
txtLog.Dock = DockStyle.Fill
|
|
txtLog.Multiline = True
|
|
txtLog.ScrollBars = ScrollBars.Vertical
|
|
txtLog.ReadOnly = True
|
|
txtLog.Font = New Font("Consolas", 10.0F)
|
|
root.Controls.Add(txtLog, 0, 2)
|
|
|
|
progress.Dock = DockStyle.Fill
|
|
progress.Style = ProgressBarStyle.Blocks
|
|
root.Controls.Add(progress, 0, 3)
|
|
|
|
lockedControls.AddRange({nudPorta, nudTimeoutConnessione, nudTimeoutInattivita, cboTerminatoreInvio, nudPausaRiga, nudPausaCarattere, nudDimensioneBlocco, nudPausaBlocco, nudAttesaPrimaInvio, nudAttesaDopoInvio, chkInvioRigaPerRiga, chkInvioCaratterePerCarattere, chkInvioBlocchi})
|
|
|
|
AddHandler cboAzienda.SelectedIndexChanged, AddressOf CompanyChanged
|
|
AddHandler cboMacchina.SelectedIndexChanged, AddressOf MachineChanged
|
|
AddHandler mnuSblocca.Click, AddressOf UnlockClicked
|
|
AddHandler mnuCambiaPassword.Click, AddressOf ChangePasswordClicked
|
|
AddHandler mnuPulisciLog.Click, AddressOf ClearLogClicked
|
|
AddHandler mnuInformazioni.Click, AddressOf AboutClicked
|
|
AddHandler btnSfogliaInvio.Click, AddressOf SelectInputFile
|
|
AddHandler btnSfogliaRicezione.Click, AddressOf SelectOutputFile
|
|
AddHandler btnTestConnessione.Click, AddressOf TestConnectionClicked
|
|
AddHandler btnInvia.Click, AddressOf SendClicked
|
|
AddHandler btnRicevi.Click, AddressOf ReceiveClicked
|
|
AddHandler btnAnnulla.Click, Sub() cts?.Cancel()
|
|
|
|
txtFileRicezione.Text = GetInitialReceiveDirectory()
|
|
BuildEditFileTab(tabModificaFile)
|
|
BuildStatusTab(tabStatoMoxa)
|
|
Log($"Pronto. Configurazione: {ConfigPath()}")
|
|
End Sub
|
|
|
|
Private Function BuildMainMenu() As MenuStrip
|
|
Dim menu As New MenuStrip()
|
|
Dim strumenti As New ToolStripMenuItem("Strumenti")
|
|
strumenti.DropDownItems.Add(mnuSblocca)
|
|
strumenti.DropDownItems.Add(mnuCambiaPassword)
|
|
strumenti.DropDownItems.Add(New ToolStripSeparator())
|
|
strumenti.DropDownItems.Add(mnuPulisciLog)
|
|
|
|
Dim aiuto As New ToolStripMenuItem("?")
|
|
aiuto.DropDownItems.Add(mnuInformazioni)
|
|
|
|
menu.Items.Add(strumenti)
|
|
menu.Items.Add(aiuto)
|
|
Return menu
|
|
End Function
|
|
|
|
Private Function GetInitialReceiveDirectory() As String
|
|
If Not String.IsNullOrWhiteSpace(appConfig.LastReceiveDirectory) AndAlso Directory.Exists(appConfig.LastReceiveDirectory) Then
|
|
Return appConfig.LastReceiveDirectory
|
|
End If
|
|
|
|
Return Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
|
|
End Function
|
|
|
|
Private Sub BuildEditFileTab(tab As TabPage)
|
|
Dim root As New TableLayoutPanel With {
|
|
.Dock = DockStyle.Fill,
|
|
.ColumnCount = 1,
|
|
.RowCount = 3,
|
|
.Padding = New Padding(14)
|
|
}
|
|
root.RowStyles.Add(New RowStyle(SizeType.AutoSize))
|
|
root.RowStyles.Add(New RowStyle(SizeType.Percent, 100))
|
|
root.RowStyles.Add(New RowStyle(SizeType.AutoSize))
|
|
tab.Controls.Add(root)
|
|
|
|
Dim selectors As New TableLayoutPanel With {.Dock = DockStyle.Top, .ColumnCount = 4, .RowCount = 2, .AutoSize = True}
|
|
selectors.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
|
|
selectors.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 100))
|
|
selectors.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
|
|
selectors.ColumnStyles.Add(New ColumnStyle(SizeType.Absolute, 150))
|
|
root.Controls.Add(selectors, 0, 0)
|
|
|
|
ConfigureButton(btnSfogliaModifica, "Sfoglia")
|
|
ConfigureButton(btnRendiMaiuscolo, "Rendi Maiuscolo")
|
|
ConfigureButton(btnAggiungiElementiOkuma, "Aggiungi elementi Necessari")
|
|
ConfigureButton(btnSalvaModifica, "Salva")
|
|
txtFileModifica.Dock = DockStyle.Fill
|
|
txtFileModifica.ReadOnly = True
|
|
txtNomeFileModifica.Dock = DockStyle.Fill
|
|
|
|
selectors.Controls.Add(New Label With {.Text = "File", .AutoSize = True, .Anchor = AnchorStyles.Left}, 0, 0)
|
|
selectors.Controls.Add(txtFileModifica, 1, 0)
|
|
selectors.Controls.Add(btnSfogliaModifica, 2, 0)
|
|
selectors.Controls.Add(New Label With {.Text = "Nome salvataggio", .AutoSize = True, .Anchor = AnchorStyles.Left, .Margin = New Padding(0, 8, 3, 0)}, 0, 1)
|
|
selectors.Controls.Add(txtNomeFileModifica, 1, 1)
|
|
|
|
rtbEditorModifica.Dock = DockStyle.Fill
|
|
rtbEditorModifica.Font = New Font("Consolas", 10.0F)
|
|
rtbEditorModifica.WordWrap = False
|
|
rtbEditorModifica.AcceptsTab = True
|
|
rtbEditorModifica.ScrollBars = RichTextBoxScrollBars.Both
|
|
rtbEditorModifica.DetectUrls = False
|
|
rtbEditorModifica.HideSelection = False
|
|
rtbEditorModifica.Margin = New Padding(0, 12, 0, 12)
|
|
root.Controls.Add(rtbEditorModifica, 0, 1)
|
|
|
|
Dim actions As New FlowLayoutPanel With {.Dock = DockStyle.Fill, .AutoSize = True, .FlowDirection = FlowDirection.LeftToRight}
|
|
actions.Controls.Add(btnRendiMaiuscolo)
|
|
actions.Controls.Add(btnAggiungiElementiOkuma)
|
|
actions.Controls.Add(btnSalvaModifica)
|
|
root.Controls.Add(actions, 0, 2)
|
|
|
|
AddHandler btnSfogliaModifica.Click, AddressOf SelectEditFile
|
|
AddHandler btnRendiMaiuscolo.Click, AddressOf UppercaseEditFile
|
|
AddHandler btnAggiungiElementiOkuma.Click, AddressOf AddOkumaElements
|
|
AddHandler btnSalvaModifica.Click, AddressOf SaveEditedFile
|
|
End Sub
|
|
|
|
Private Sub SelectEditFile(sender As Object, e As EventArgs)
|
|
Using dialog As New OpenFileDialog With {
|
|
.Title = "Seleziona file da modificare",
|
|
.Filter = "Tutti i file (*.*)|*.*",
|
|
.CheckFileExists = True
|
|
}
|
|
If Directory.Exists(currentEditDirectory) Then
|
|
dialog.InitialDirectory = currentEditDirectory
|
|
Else
|
|
dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
|
|
End If
|
|
|
|
If dialog.ShowDialog(Me) <> DialogResult.OK Then
|
|
Return
|
|
End If
|
|
|
|
Dim bytes = File.ReadAllBytes(dialog.FileName)
|
|
Dim content = Encoding.Latin1.GetString(bytes)
|
|
txtFileModifica.Text = dialog.FileName
|
|
txtNomeFileModifica.Text = Path.GetFileName(dialog.FileName)
|
|
currentEditDirectory = Path.GetDirectoryName(dialog.FileName)
|
|
rtbEditorModifica.Text = ToVisibleControlText(content)
|
|
Log($"File caricato per modifica: {dialog.FileName}")
|
|
End Using
|
|
End Sub
|
|
|
|
Private Sub UppercaseEditFile(sender As Object, e As EventArgs)
|
|
rtbEditorModifica.Text = rtbEditorModifica.Text.ToUpperInvariant()
|
|
End Sub
|
|
|
|
Private Sub AddOkumaElements(sender As Object, e As EventArgs)
|
|
Dim fileName = txtNomeFileModifica.Text.Trim()
|
|
If String.IsNullOrWhiteSpace(fileName) Then
|
|
MessageBox.Show(Me, "Inserire il nome del file da usare nell'intestazione Okuma.", "Modifica file", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
|
Return
|
|
End If
|
|
|
|
Dim content = FromVisibleControlText(rtbEditorModifica.Text)
|
|
Dim header = ChrW(&H12) & " $" & fileName & " %" & vbCrLf
|
|
Dim footer = "%" & vbCrLf & ChrW(&H14)
|
|
|
|
If Not content.StartsWith(ChrW(&H12), StringComparison.Ordinal) Then
|
|
content = header & content
|
|
End If
|
|
|
|
If Not EndsWithOkumaFooter(content) Then
|
|
If content.Length > 0 AndAlso Not content.EndsWith(vbCrLf, StringComparison.Ordinal) Then
|
|
content &= vbCrLf
|
|
End If
|
|
content &= footer
|
|
End If
|
|
|
|
rtbEditorModifica.Text = ToVisibleControlText(content)
|
|
End Sub
|
|
|
|
Private Sub SaveEditedFile(sender As Object, e As EventArgs)
|
|
Dim fileName = txtNomeFileModifica.Text.Trim()
|
|
If String.IsNullOrWhiteSpace(fileName) OrElse fileName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0 Then
|
|
MessageBox.Show(Me, "Inserire un nome file valido.", "Salva file", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
|
Return
|
|
End If
|
|
|
|
Using dialog As New SaveFileDialog With {
|
|
.Title = "Salva file modificato",
|
|
.Filter = "Tutti i file (*.*)|*.*",
|
|
.FileName = fileName,
|
|
.OverwritePrompt = True
|
|
}
|
|
If Directory.Exists(currentEditDirectory) Then
|
|
dialog.InitialDirectory = currentEditDirectory
|
|
ElseIf Not String.IsNullOrWhiteSpace(txtFileModifica.Text) AndAlso Directory.Exists(Path.GetDirectoryName(txtFileModifica.Text)) Then
|
|
dialog.InitialDirectory = Path.GetDirectoryName(txtFileModifica.Text)
|
|
Else
|
|
dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
|
|
End If
|
|
|
|
If dialog.ShowDialog(Me) <> DialogResult.OK Then
|
|
Return
|
|
End If
|
|
|
|
Dim content = FromVisibleControlText(rtbEditorModifica.Text)
|
|
File.WriteAllBytes(dialog.FileName, Encoding.Latin1.GetBytes(content))
|
|
currentEditDirectory = Path.GetDirectoryName(dialog.FileName)
|
|
txtFileModifica.Text = dialog.FileName
|
|
txtNomeFileModifica.Text = Path.GetFileName(dialog.FileName)
|
|
Log($"File modificato salvato: {dialog.FileName}")
|
|
End Using
|
|
End Sub
|
|
|
|
Private Shared Function EndsWithOkumaFooter(content As String) As Boolean
|
|
Dim trimmed = content.TrimEnd(ControlChars.Cr, ControlChars.Lf, ControlChars.NullChar, " "c, ControlChars.Tab)
|
|
Return trimmed.EndsWith(ChrW(&H14), StringComparison.Ordinal)
|
|
End Function
|
|
|
|
Private Shared Function ToVisibleControlText(content As String) As String
|
|
Dim builder As New StringBuilder(content.Length)
|
|
Dim i = 0
|
|
While i < content.Length
|
|
Dim ch = content(i)
|
|
Select Case AscW(ch)
|
|
Case &HA
|
|
builder.Append(Environment.NewLine)
|
|
Case &HD
|
|
If i + 1 < content.Length AndAlso content(i + 1) = ControlChars.Lf Then
|
|
i += 1
|
|
End If
|
|
builder.Append(Environment.NewLine)
|
|
Case &H12
|
|
builder.Append("[DC2]")
|
|
Case &H14
|
|
builder.Append("[DC4]")
|
|
Case Else
|
|
builder.Append(ch)
|
|
End Select
|
|
i += 1
|
|
End While
|
|
Return builder.ToString()
|
|
End Function
|
|
|
|
Private Shared Function FromVisibleControlText(visibleText As String) As String
|
|
Dim builder As New StringBuilder(visibleText.Length)
|
|
Dim i = 0
|
|
While i < visibleText.Length
|
|
If visibleText(i) = "["c Then
|
|
Dim closeIndex = visibleText.IndexOf("]"c, i + 1)
|
|
If closeIndex > i Then
|
|
Dim token = visibleText.Substring(i + 1, closeIndex - i - 1)
|
|
Dim controlChar As Char
|
|
If TryParseControlToken(token, controlChar) Then
|
|
builder.Append(controlChar)
|
|
i = closeIndex + 1
|
|
Continue While
|
|
End If
|
|
End If
|
|
End If
|
|
|
|
builder.Append(visibleText(i))
|
|
i += 1
|
|
End While
|
|
Return builder.ToString()
|
|
End Function
|
|
|
|
Private Shared Function TryParseControlToken(token As String, ByRef controlChar As Char) As Boolean
|
|
Select Case token.Trim().ToUpperInvariant()
|
|
Case "DC2"
|
|
controlChar = ChrW(&H12)
|
|
Return True
|
|
Case "DC4"
|
|
controlChar = ChrW(&H14)
|
|
Return True
|
|
End Select
|
|
|
|
controlChar = ControlChars.NullChar
|
|
Return False
|
|
End Function
|
|
|
|
Private Sub BuildStatusTab(tab As TabPage)
|
|
Dim root As New TableLayoutPanel With {
|
|
.Dock = DockStyle.Fill,
|
|
.ColumnCount = 1,
|
|
.RowCount = 2,
|
|
.Padding = New Padding(14)
|
|
}
|
|
root.RowStyles.Add(New RowStyle(SizeType.AutoSize))
|
|
root.RowStyles.Add(New RowStyle(SizeType.Percent, 100))
|
|
tab.Controls.Add(root)
|
|
|
|
Dim actions As New FlowLayoutPanel With {.Dock = DockStyle.Fill, .AutoSize = True, .FlowDirection = FlowDirection.LeftToRight}
|
|
ConfigureButton(btnAggiornaStatoMoxa, "Aggiorna")
|
|
chkMonitorStatoMoxa.Text = "Controllo automatico"
|
|
chkMonitorStatoMoxa.AutoSize = True
|
|
chkMonitorStatoMoxa.Checked = True
|
|
chkMonitorStatoMoxa.Margin = New Padding(16, 8, 0, 3)
|
|
nudIntervalloStatoMoxa.Minimum = 5
|
|
nudIntervalloStatoMoxa.Maximum = 3600
|
|
nudIntervalloStatoMoxa.Value = Math.Max(nudIntervalloStatoMoxa.Minimum, Math.Min(nudIntervalloStatoMoxa.Maximum, appConfig.MonitorRefreshSeconds))
|
|
nudIntervalloStatoMoxa.Width = 80
|
|
|
|
actions.Controls.Add(btnAggiornaStatoMoxa)
|
|
actions.Controls.Add(chkMonitorStatoMoxa)
|
|
actions.Controls.Add(New Label With {.Text = "Intervallo s", .AutoSize = True, .Margin = New Padding(16, 9, 3, 3)})
|
|
actions.Controls.Add(nudIntervalloStatoMoxa)
|
|
root.Controls.Add(actions, 0, 0)
|
|
|
|
imgStatoMoxa.ImageSize = New Size(16, 16)
|
|
imgStatoMoxa.ColorDepth = ColorDepth.Depth32Bit
|
|
imgStatoMoxa.Images.Add("unknown", CreateStatusIcon(Color.Gray))
|
|
imgStatoMoxa.Images.Add("online", CreateStatusIcon(Color.FromArgb(0, 150, 70)))
|
|
imgStatoMoxa.Images.Add("offline", CreateStatusIcon(Color.FromArgb(210, 40, 40)))
|
|
|
|
lstStatoMoxa.Dock = DockStyle.Fill
|
|
lstStatoMoxa.View = View.Details
|
|
lstStatoMoxa.FullRowSelect = True
|
|
lstStatoMoxa.GridLines = True
|
|
lstStatoMoxa.SmallImageList = imgStatoMoxa
|
|
lstStatoMoxa.Columns.Add("Macchina", 280)
|
|
lstStatoMoxa.Columns.Add("IP Moxa", 140)
|
|
lstStatoMoxa.Columns.Add("Porta", 70)
|
|
lstStatoMoxa.Columns.Add("Stato", 130)
|
|
lstStatoMoxa.Columns.Add("Ultimo controllo", 160)
|
|
lstStatoMoxa.Columns.Add("Note", 220)
|
|
root.Controls.Add(lstStatoMoxa, 0, 1)
|
|
|
|
lockedControls.Add(chkMonitorStatoMoxa)
|
|
lockedControls.Add(nudIntervalloStatoMoxa)
|
|
|
|
statusTimer.Interval = CInt(nudIntervalloStatoMoxa.Value) * 1000
|
|
statusTimer.Enabled = chkMonitorStatoMoxa.Checked
|
|
AddHandler btnAggiornaStatoMoxa.Click, AddressOf RefreshMoxaStatusClicked
|
|
AddHandler statusTimer.Tick, AddressOf StatusTimerTick
|
|
AddHandler nudIntervalloStatoMoxa.ValueChanged, AddressOf StatusIntervalChanged
|
|
AddHandler chkMonitorStatoMoxa.CheckedChanged, AddressOf StatusMonitorChanged
|
|
|
|
PopulateMoxaStatusList()
|
|
End Sub
|
|
|
|
Private Shared Function CreateStatusIcon(color As Color) As Bitmap
|
|
Dim bitmap As New Bitmap(16, 16)
|
|
Using g = Graphics.FromImage(bitmap)
|
|
g.Clear(Color.Transparent)
|
|
Using brush As New SolidBrush(color)
|
|
g.FillEllipse(brush, 2, 2, 12, 12)
|
|
End Using
|
|
Using pen As New Pen(Color.FromArgb(80, 0, 0, 0))
|
|
g.DrawEllipse(pen, 2, 2, 12, 12)
|
|
End Using
|
|
End Using
|
|
Return bitmap
|
|
End Function
|
|
|
|
Private Sub ConfigureNumericDefaults()
|
|
nudPorta.Minimum = 1
|
|
nudPorta.Maximum = 65535
|
|
nudTimeoutConnessione.Minimum = 1
|
|
nudTimeoutConnessione.Maximum = 120
|
|
nudTimeoutInattivita.Minimum = 1
|
|
nudTimeoutInattivita.Maximum = 120
|
|
nudPausaRiga.Minimum = 0
|
|
nudPausaRiga.Maximum = 2000
|
|
nudPausaCarattere.Minimum = 0
|
|
nudPausaCarattere.Maximum = 200
|
|
nudDimensioneBlocco.Minimum = 1
|
|
nudDimensioneBlocco.Maximum = 1024
|
|
nudPausaBlocco.Minimum = 0
|
|
nudPausaBlocco.Maximum = 5000
|
|
nudAttesaPrimaInvio.Minimum = 0
|
|
nudAttesaPrimaInvio.Maximum = 60
|
|
nudAttesaDopoInvio.Minimum = 0
|
|
nudAttesaDopoInvio.Maximum = 30
|
|
End Sub
|
|
|
|
Private Sub LoadCompanies()
|
|
loadingSelection = True
|
|
cboAzienda.Items.Clear()
|
|
For Each company In appConfig.Companies
|
|
cboAzienda.Items.Add(company.Name)
|
|
Next
|
|
loadingSelection = False
|
|
|
|
If cboAzienda.Items.Count > 0 Then
|
|
Dim index = Math.Max(0, appConfig.Companies.FindIndex(Function(c) c.Name = appConfig.DefaultCompany))
|
|
cboAzienda.SelectedIndex = index
|
|
End If
|
|
|
|
PopulateMoxaStatusList()
|
|
End Sub
|
|
|
|
Private Sub PopulateMoxaStatusList()
|
|
If lstStatoMoxa.Columns.Count = 0 Then
|
|
Return
|
|
End If
|
|
|
|
lstStatoMoxa.BeginUpdate()
|
|
lstStatoMoxa.Items.Clear()
|
|
lstStatoMoxa.Groups.Clear()
|
|
|
|
For Each company In appConfig.Companies
|
|
Dim group As New ListViewGroup(company.Name, HorizontalAlignment.Left)
|
|
lstStatoMoxa.Groups.Add(group)
|
|
|
|
For Each machine In company.Machines
|
|
Dim item As New ListViewItem(machine.Name, "unknown") With {
|
|
.Group = group,
|
|
.Tag = New MoxaStatusTarget With {.Company = company.Name, .Machine = machine}
|
|
}
|
|
item.SubItems.Add(machine.IpMoxa)
|
|
item.SubItems.Add(appConfig.DefaultSettings.Port.ToString())
|
|
item.SubItems.Add("Non controllato")
|
|
item.SubItems.Add("")
|
|
item.SubItems.Add(machine.Note)
|
|
lstStatoMoxa.Items.Add(item)
|
|
Next
|
|
Next
|
|
|
|
lstStatoMoxa.EndUpdate()
|
|
End Sub
|
|
|
|
Private Sub CompanyChanged(sender As Object, e As EventArgs)
|
|
If loadingSelection OrElse cboAzienda.SelectedIndex < 0 Then
|
|
Return
|
|
End If
|
|
|
|
Dim company = CurrentCompany()
|
|
If Not String.Equals(appConfig.DefaultCompany, company.Name, StringComparison.Ordinal) Then
|
|
appConfig.DefaultCompany = company.Name
|
|
SaveConfig()
|
|
End If
|
|
|
|
loadingSelection = True
|
|
cboMacchina.Items.Clear()
|
|
For Each machine In company.Machines
|
|
cboMacchina.Items.Add(machine.Name)
|
|
Next
|
|
loadingSelection = False
|
|
|
|
If cboMacchina.Items.Count > 0 Then
|
|
cboMacchina.SelectedIndex = 0
|
|
End If
|
|
End Sub
|
|
|
|
Private Sub MachineChanged(sender As Object, e As EventArgs)
|
|
If loadingSelection Then
|
|
Return
|
|
End If
|
|
|
|
ApplyCurrentMachineSettings()
|
|
End Sub
|
|
|
|
Private Sub ApplyCurrentMachineSettings()
|
|
Dim machine = CurrentMachine()
|
|
If machine Is Nothing Then
|
|
Return
|
|
End If
|
|
|
|
Dim defaults = appConfig.DefaultSettings
|
|
txtIpMoxa.Text = machine.IpMoxa
|
|
nudPorta.Value = defaults.Port
|
|
nudTimeoutConnessione.Value = defaults.ConnectionTimeoutSeconds
|
|
nudTimeoutInattivita.Value = defaults.ReceiveIdleTimeoutSeconds
|
|
cboTerminatoreInvio.SelectedItem = defaults.SendTerminator
|
|
nudPausaRiga.Value = defaults.LineDelayMs
|
|
nudPausaCarattere.Value = defaults.CharDelayMs
|
|
chkInvioRigaPerRiga.Checked = defaults.LinePaced
|
|
chkInvioCaratterePerCarattere.Checked = defaults.CharPaced
|
|
chkInvioBlocchi.Checked = defaults.BlockPaced
|
|
nudDimensioneBlocco.Value = defaults.BlockSizeBytes
|
|
nudPausaBlocco.Value = defaults.BlockDelayMs
|
|
nudAttesaPrimaInvio.Value = defaults.WaitBeforeSendSeconds
|
|
nudAttesaDopoInvio.Value = defaults.WaitAfterSendSeconds
|
|
Log($"Macchina selezionata: {CurrentCompany().Name} / {machine.Name} - IP Moxa {machine.IpMoxa}.")
|
|
End Sub
|
|
|
|
Private Function CurrentCompany() As CompanyConfig
|
|
If cboAzienda.SelectedIndex < 0 OrElse cboAzienda.SelectedIndex >= appConfig.Companies.Count Then
|
|
Return Nothing
|
|
End If
|
|
Return appConfig.Companies(cboAzienda.SelectedIndex)
|
|
End Function
|
|
|
|
Private Function CurrentMachine() As MachineConfig
|
|
Dim company = CurrentCompany()
|
|
If company Is Nothing OrElse cboMacchina.SelectedIndex < 0 OrElse cboMacchina.SelectedIndex >= company.Machines.Count Then
|
|
Return Nothing
|
|
End If
|
|
Return company.Machines(cboMacchina.SelectedIndex)
|
|
End Function
|
|
|
|
Private Sub UnlockClicked(sender As Object, e As EventArgs)
|
|
If controlsUnlocked Then
|
|
SetControlsUnlocked(False)
|
|
Return
|
|
End If
|
|
|
|
If String.IsNullOrWhiteSpace(appConfig.AdminPasswordHash) OrElse String.IsNullOrWhiteSpace(appConfig.AdminPasswordSalt) Then
|
|
Dim newPassword = PromptPassword("Password non configurata", "Inserire una nuova password amministratore:")
|
|
If String.IsNullOrEmpty(newPassword) Then
|
|
Return
|
|
End If
|
|
SetPassword(newPassword)
|
|
SaveConfig()
|
|
SetControlsUnlocked(True)
|
|
Return
|
|
End If
|
|
|
|
Dim password = PromptPassword("Sblocca controlli", "Inserire la password:")
|
|
If password Is Nothing Then
|
|
Return
|
|
End If
|
|
|
|
If VerifyPassword(password) Then
|
|
SetControlsUnlocked(True)
|
|
Else
|
|
MessageBox.Show(Me, "Password non corretta.", "Accesso negato", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
|
End If
|
|
End Sub
|
|
|
|
Private Sub ChangePasswordClicked(sender As Object, e As EventArgs)
|
|
If Not String.IsNullOrWhiteSpace(appConfig.AdminPasswordHash) AndAlso Not String.IsNullOrWhiteSpace(appConfig.AdminPasswordSalt) Then
|
|
Dim oldPassword = PromptPassword("Cambia password", "Inserire la vecchia password:")
|
|
If oldPassword Is Nothing Then
|
|
Return
|
|
End If
|
|
If Not VerifyPassword(oldPassword) Then
|
|
MessageBox.Show(Me, "Vecchia password non corretta.", "Password", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
|
Return
|
|
End If
|
|
End If
|
|
|
|
Dim newPassword = PromptPassword("Cambia password", "Inserire la nuova password:")
|
|
If String.IsNullOrEmpty(newPassword) Then
|
|
Return
|
|
End If
|
|
|
|
SetPassword(newPassword)
|
|
SaveConfig()
|
|
MessageBox.Show(Me, "Password aggiornata.", "Password", MessageBoxButtons.OK, MessageBoxIcon.Information)
|
|
End Sub
|
|
|
|
Private Sub ClearLogClicked(sender As Object, e As EventArgs)
|
|
txtLog.Clear()
|
|
End Sub
|
|
|
|
Private Sub AboutClicked(sender As Object, e As EventArgs)
|
|
Dim version = Assembly.GetExecutingAssembly().GetName().Version
|
|
MessageBox.Show(Me,
|
|
$"LMEMoxaTransfer{Environment.NewLine}{Environment.NewLine}Azienda: Compomac SPA{Environment.NewLine}Autore: Livio Merola{Environment.NewLine}Versione: {version}",
|
|
"Informazioni su",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Information)
|
|
End Sub
|
|
|
|
Private Async Sub RefreshMoxaStatusClicked(sender As Object, e As EventArgs)
|
|
Await RefreshMoxaStatusAsync()
|
|
End Sub
|
|
|
|
Private Async Sub StatusTimerTick(sender As Object, e As EventArgs)
|
|
If chkMonitorStatoMoxa.Checked Then
|
|
Await RefreshMoxaStatusAsync()
|
|
End If
|
|
End Sub
|
|
|
|
Private Sub StatusIntervalChanged(sender As Object, e As EventArgs)
|
|
statusTimer.Interval = CInt(nudIntervalloStatoMoxa.Value) * 1000
|
|
appConfig.MonitorRefreshSeconds = CInt(nudIntervalloStatoMoxa.Value)
|
|
SaveConfig()
|
|
End Sub
|
|
|
|
Private Sub StatusMonitorChanged(sender As Object, e As EventArgs)
|
|
statusTimer.Enabled = chkMonitorStatoMoxa.Checked
|
|
End Sub
|
|
|
|
Private Async Function RefreshMoxaStatusAsync() As Task
|
|
If checkingMoxaStatus Then
|
|
Return
|
|
End If
|
|
|
|
checkingMoxaStatus = True
|
|
btnAggiornaStatoMoxa.Enabled = False
|
|
Try
|
|
For Each item As ListViewItem In lstStatoMoxa.Items
|
|
Dim target = TryCast(item.Tag, MoxaStatusTarget)
|
|
If target Is Nothing Then
|
|
Continue For
|
|
End If
|
|
|
|
item.ImageKey = "unknown"
|
|
item.SubItems(3).Text = "Controllo..."
|
|
item.SubItems(4).Text = DateTime.Now.ToString("HH:mm:ss")
|
|
Dim online = Await IsMoxaReachableAsync(target.Machine.IpMoxa, appConfig.DefaultSettings.Port, TimeSpan.FromMilliseconds(1200))
|
|
item.ImageKey = If(online, "online", "offline")
|
|
item.SubItems(3).Text = If(online, "Raggiungibile", "Non raggiungibile")
|
|
item.SubItems(4).Text = DateTime.Now.ToString("HH:mm:ss")
|
|
Next
|
|
Finally
|
|
btnAggiornaStatoMoxa.Enabled = True
|
|
checkingMoxaStatus = False
|
|
End Try
|
|
End Function
|
|
|
|
Private Shared Async Function IsMoxaReachableAsync(ip As String, port As Integer, timeout As TimeSpan) As Task(Of Boolean)
|
|
If String.IsNullOrWhiteSpace(ip) Then
|
|
Return False
|
|
End If
|
|
|
|
Using client As New TcpClient()
|
|
Try
|
|
Dim connectTask = client.ConnectAsync(ip.Trim(), port)
|
|
Dim completed = Await Task.WhenAny(connectTask, Task.Delay(timeout))
|
|
If completed IsNot connectTask Then
|
|
Return False
|
|
End If
|
|
Await connectTask
|
|
Return True
|
|
Catch
|
|
Return False
|
|
End Try
|
|
End Using
|
|
End Function
|
|
|
|
Private Sub SetControlsUnlocked(unlocked As Boolean)
|
|
controlsUnlocked = unlocked
|
|
For Each control In lockedControls
|
|
control.Enabled = unlocked
|
|
Next
|
|
mnuSblocca.Text = If(unlocked, "Blocca controlli", "Sblocca controlli")
|
|
End Sub
|
|
|
|
Private Async Sub TestConnectionClicked(sender As Object, e As EventArgs)
|
|
Await RunTransferAsync(Async Function(token)
|
|
Using client = Await ConnectAsync(token)
|
|
Log("Test OK: connessione TCP aperta, nessun dato inviato a Okuma.")
|
|
End Using
|
|
End Function)
|
|
End Sub
|
|
|
|
Private Shared Sub ConfigureButton(button As Button, text As String)
|
|
button.Text = text
|
|
button.AutoSize = True
|
|
button.MinimumSize = New Size(110, 32)
|
|
button.Margin = New Padding(8, 3, 0, 3)
|
|
End Sub
|
|
|
|
Private Sub SelectInputFile(sender As Object, e As EventArgs)
|
|
Using dlg As New OpenFileDialog()
|
|
dlg.Title = "Seleziona programma da inviare a Okuma"
|
|
dlg.Filter = "Programmi CNC|*.min;*.eia;*.iso;*.txt;*.nc|Tutti i file|*.*"
|
|
If dlg.ShowDialog(Me) = DialogResult.OK Then
|
|
txtFileInvio.Text = dlg.FileName
|
|
End If
|
|
End Using
|
|
End Sub
|
|
|
|
Private Sub SelectOutputFile(sender As Object, e As EventArgs)
|
|
Using dlg As New FolderBrowserDialog()
|
|
dlg.Description = "Scegli la cartella dove salvare il programma ricevuto"
|
|
dlg.UseDescriptionForTitle = True
|
|
If Directory.Exists(txtFileRicezione.Text) Then
|
|
dlg.SelectedPath = txtFileRicezione.Text
|
|
End If
|
|
If dlg.ShowDialog(Me) = DialogResult.OK Then
|
|
txtFileRicezione.Text = dlg.SelectedPath
|
|
appConfig.LastReceiveDirectory = dlg.SelectedPath
|
|
SaveConfig()
|
|
End If
|
|
End Using
|
|
End Sub
|
|
|
|
Private Async Sub SendClicked(sender As Object, e As EventArgs)
|
|
If CurrentMachine() Is Nothing Then
|
|
MessageBox.Show(Me, "Selezionare azienda e macchina.", "Macchina mancante", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
|
Return
|
|
End If
|
|
If Not File.Exists(txtFileInvio.Text) Then
|
|
MessageBox.Show(Me, "Selezionare un file esistente da inviare.", "File mancante", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
|
Return
|
|
End If
|
|
|
|
Await RunTransferAsync(Async Function(token)
|
|
Dim fileBytes = Await File.ReadAllBytesAsync(txtFileInvio.Text, token)
|
|
fileBytes = RemoveUtf8BomIfPresent(fileBytes)
|
|
LogFirstBytes(fileBytes)
|
|
LogNonStandardCncBytes(fileBytes)
|
|
Dim blockPaced = chkInvioBlocchi.Checked
|
|
Dim terminator = If(blockPaced, Encoding.ASCII.GetBytes("%" & vbCrLf), GetTerminatorBytes())
|
|
|
|
Using client = Await ConnectAsync(token)
|
|
Using stream = client.GetStream()
|
|
Dim waitBeforeSend = CInt(nudAttesaPrimaInvio.Value)
|
|
If waitBeforeSend > 0 Then
|
|
Log($"Attesa prima del primo byte: {waitBeforeSend} s.")
|
|
Await Task.Delay(TimeSpan.FromSeconds(waitBeforeSend), token)
|
|
End If
|
|
|
|
If blockPaced Then
|
|
Dim blockSize = CInt(nudDimensioneBlocco.Value)
|
|
Dim blockDelayMs = CInt(nudPausaBlocco.Value)
|
|
Log($"Invio Okuma READ: blocchi da {blockSize} byte con pausa {blockDelayMs} ms.")
|
|
Await SendBlockPacedAsync(stream, fileBytes, blockSize, blockDelayMs, token)
|
|
ElseIf chkInvioRigaPerRiga.Checked Then
|
|
Await SendLinePacedAsync(stream, fileBytes, CInt(nudPausaRiga.Value), CInt(nudPausaCarattere.Value), chkInvioCaratterePerCarattere.Checked, token)
|
|
Else
|
|
Await stream.WriteAsync(fileBytes, token)
|
|
End If
|
|
|
|
If terminator.Length > 0 Then
|
|
Await stream.WriteAsync(terminator, token)
|
|
End If
|
|
Await stream.FlushAsync(token)
|
|
|
|
Dim waitAfterSend = CInt(nudAttesaDopoInvio.Value)
|
|
If blockPaced Then
|
|
waitAfterSend = Math.Max(waitAfterSend, 1)
|
|
End If
|
|
If waitAfterSend > 0 Then
|
|
Await Task.Delay(TimeSpan.FromSeconds(waitAfterSend), token)
|
|
End If
|
|
End Using
|
|
End Using
|
|
Log($"Inviati {fileBytes.Length:N0} byte a Okuma.")
|
|
End Function)
|
|
End Sub
|
|
|
|
Private Async Sub ReceiveClicked(sender As Object, e As EventArgs)
|
|
If CurrentMachine() Is Nothing Then
|
|
MessageBox.Show(Me, "Selezionare azienda e macchina.", "Macchina mancante", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
|
Return
|
|
End If
|
|
If String.IsNullOrWhiteSpace(txtFileRicezione.Text) Then
|
|
MessageBox.Show(Me, "Scegliere una cartella di destinazione per la ricezione.", "Cartella mancante", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
|
Return
|
|
End If
|
|
|
|
Await RunTransferAsync(Async Function(token)
|
|
Dim destinationDirectory = Path.GetFullPath(txtFileRicezione.Text)
|
|
Directory.CreateDirectory(destinationDirectory)
|
|
Dim temporaryPath = CreateTemporaryReceivePath()
|
|
Using client = Await ConnectAsync(token)
|
|
Using stream = client.GetStream()
|
|
Dim received = Await ReceiveUntilIdleAsync(stream, temporaryPath, token)
|
|
Log($"Ricevuti {received:N0} byte da Okuma.")
|
|
End Using
|
|
End Using
|
|
Dim finalPath = PromptAndSaveReceivedFile(temporaryPath, destinationDirectory)
|
|
Log($"File ricevuto salvato in: {finalPath}")
|
|
End Function)
|
|
End Sub
|
|
|
|
Private Async Function RunTransferAsync(action As Func(Of CancellationToken, Task)) As Task
|
|
SetBusy(True)
|
|
cts = New CancellationTokenSource()
|
|
|
|
Try
|
|
Await action(cts.Token)
|
|
Log("Operazione completata.")
|
|
Catch ex As OperationCanceledException
|
|
Log("Operazione annullata.")
|
|
Catch ex As Exception
|
|
Log("Errore: " & ex.Message)
|
|
MessageBox.Show(Me, ex.Message, "Errore trasferimento", MessageBoxButtons.OK, MessageBoxIcon.Error)
|
|
Finally
|
|
cts.Dispose()
|
|
cts = Nothing
|
|
SetBusy(False)
|
|
End Try
|
|
End Function
|
|
|
|
Private Shared Async Function SendLinePacedAsync(stream As NetworkStream, data As Byte(), lineDelayMs As Integer, charDelayMs As Integer, charPaced As Boolean, token As CancellationToken) As Task
|
|
Dim start = 0
|
|
For i = 0 To data.Length - 1
|
|
If data(i) = 10 Then
|
|
Await WriteChunkAsync(stream, data, start, i - start + 1, charDelayMs, charPaced, token)
|
|
Await stream.FlushAsync(token)
|
|
start = i + 1
|
|
If lineDelayMs > 0 Then
|
|
Await Task.Delay(lineDelayMs, token)
|
|
End If
|
|
End If
|
|
Next
|
|
If start < data.Length Then
|
|
Await WriteChunkAsync(stream, data, start, data.Length - start, charDelayMs, charPaced, token)
|
|
End If
|
|
End Function
|
|
|
|
Private Shared Async Function WriteChunkAsync(stream As NetworkStream, data As Byte(), offset As Integer, count As Integer, charDelayMs As Integer, charPaced As Boolean, token As CancellationToken) As Task
|
|
If Not charPaced Then
|
|
Await stream.WriteAsync(data.AsMemory(offset, count), token)
|
|
Return
|
|
End If
|
|
|
|
For i = offset To offset + count - 1
|
|
Await stream.WriteAsync(data.AsMemory(i, 1), token)
|
|
If charDelayMs > 0 Then
|
|
Await Task.Delay(charDelayMs, token)
|
|
End If
|
|
Next
|
|
End Function
|
|
|
|
Private Shared Async Function SendBlockPacedAsync(stream As NetworkStream, data As Byte(), blockSize As Integer, blockDelayMs As Integer, token As CancellationToken) As Task
|
|
Dim offset = 0
|
|
While offset < data.Length
|
|
Dim count = Math.Min(blockSize, data.Length - offset)
|
|
Await stream.WriteAsync(data.AsMemory(offset, count), token)
|
|
Await stream.FlushAsync(token)
|
|
offset += count
|
|
If offset < data.Length AndAlso blockDelayMs > 0 Then
|
|
Await Task.Delay(blockDelayMs, token)
|
|
End If
|
|
End While
|
|
End Function
|
|
|
|
Private Async Function ConnectAsync(token As CancellationToken) As Task(Of TcpClient)
|
|
Dim machine = CurrentMachine()
|
|
If machine Is Nothing Then
|
|
Throw New InvalidOperationException("Macchina non selezionata.")
|
|
End If
|
|
|
|
Dim ip = machine.IpMoxa.Trim()
|
|
Dim port = CInt(nudPorta.Value)
|
|
Dim timeout = TimeSpan.FromSeconds(CInt(nudTimeoutConnessione.Value))
|
|
Dim client As New TcpClient With {.NoDelay = True}
|
|
|
|
Log($"Connessione a {ip}:{port}...")
|
|
Dim connectTask = client.ConnectAsync(ip, port, token).AsTask()
|
|
Dim completed = Await Task.WhenAny(connectTask, Task.Delay(timeout, token))
|
|
If completed IsNot connectTask Then
|
|
client.Dispose()
|
|
Throw New TimeoutException($"Connessione non riuscita entro {timeout.TotalSeconds:N0} secondi.")
|
|
End If
|
|
|
|
Await connectTask
|
|
Log("Connessione aperta.")
|
|
Return client
|
|
End Function
|
|
|
|
Private Async Function ReceiveUntilIdleAsync(stream As NetworkStream, destinationPath As String, token As CancellationToken) As Task(Of Long)
|
|
Dim buffer(8191) As Byte
|
|
Dim total As Long = 0
|
|
Dim idleTimeout = TimeSpan.FromSeconds(CInt(nudTimeoutInattivita.Value))
|
|
|
|
Log("In attesa dati. Avviare l'invio programma dal controllo Okuma.")
|
|
Using output As New FileStream(destinationPath, FileMode.Create, FileAccess.Write, FileShare.Read, 8192, useAsync:=True)
|
|
Do
|
|
Dim readTask = stream.ReadAsync(buffer.AsMemory(0, buffer.Length), token).AsTask()
|
|
Dim completed = Await Task.WhenAny(readTask, Task.Delay(idleTimeout, token))
|
|
|
|
If completed IsNot readTask Then
|
|
If total = 0 Then
|
|
Throw New TimeoutException("Nessun dato ricevuto prima del timeout di inattivita.")
|
|
End If
|
|
Exit Do
|
|
End If
|
|
|
|
Dim count = Await readTask
|
|
If count = 0 Then
|
|
Exit Do
|
|
End If
|
|
|
|
Await output.WriteAsync(buffer.AsMemory(0, count), token)
|
|
total += count
|
|
progress.Value = CInt(Math.Min(progress.Maximum, total Mod progress.Maximum))
|
|
Log($"Ricevuti {total:N0} byte...")
|
|
Loop
|
|
End Using
|
|
|
|
Return total
|
|
End Function
|
|
|
|
Private Shared Function CreateTemporaryReceivePath() As String
|
|
Dim tempDirectory = Path.Combine(Application.StartupPath, "RicezioniTemp")
|
|
Directory.CreateDirectory(tempDirectory)
|
|
Return Path.Combine(tempDirectory, $"ricezione_okuma_{DateTime.Now:yyyyMMdd_HHmmss}_{Guid.NewGuid():N}.tmp")
|
|
End Function
|
|
|
|
Private Shared Sub CleanupOldTemporaryReceives()
|
|
Dim tempDirectory = Path.Combine(Application.StartupPath, "RicezioniTemp")
|
|
If Not Directory.Exists(tempDirectory) Then
|
|
Return
|
|
End If
|
|
|
|
For Each filePath In Directory.EnumerateFiles(tempDirectory, "*.tmp")
|
|
Try
|
|
If File.GetLastWriteTime(filePath) < DateTime.Now.AddDays(-7) Then
|
|
File.Delete(filePath)
|
|
End If
|
|
Catch
|
|
End Try
|
|
Next
|
|
End Sub
|
|
|
|
Private Function PromptAndSaveReceivedFile(temporaryPath As String, destinationDirectory As String) As String
|
|
If Not File.Exists(temporaryPath) Then
|
|
Return temporaryPath
|
|
End If
|
|
|
|
Dim suggestedName = ExtractProgramFileName(File.ReadAllBytes(temporaryPath))
|
|
If String.IsNullOrWhiteSpace(suggestedName) Then
|
|
suggestedName = "programma_okuma.min"
|
|
Log("Nessun nome programma preceduto da $ trovato nel file ricevuto: propongo un nome predefinito.")
|
|
End If
|
|
|
|
Dim chosenName As String = Nothing
|
|
Do
|
|
chosenName = PromptReceivedFileName(suggestedName)
|
|
If chosenName Is Nothing Then
|
|
Log($"Nome finale annullato: il file temporaneo resta in {temporaryPath}")
|
|
Return temporaryPath
|
|
End If
|
|
|
|
chosenName = Path.GetFileName(chosenName.Trim())
|
|
If Not String.IsNullOrWhiteSpace(chosenName) AndAlso chosenName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 Then
|
|
Exit Do
|
|
End If
|
|
|
|
MessageBox.Show(Me, "Nome file non valido.", "Nome file", MessageBoxButtons.OK, MessageBoxIcon.Warning)
|
|
Loop
|
|
|
|
Dim finalPath = Path.Combine(destinationDirectory, chosenName)
|
|
|
|
If File.Exists(finalPath) Then
|
|
Dim overwrite = MessageBox.Show(Me, $"Il file {chosenName} esiste gia'. Sovrascriverlo?", "File esistente", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
|
|
If overwrite <> DialogResult.Yes Then
|
|
Return PromptAndSaveReceivedFile(temporaryPath, destinationDirectory)
|
|
End If
|
|
End If
|
|
|
|
File.Move(temporaryPath, finalPath, True)
|
|
Return finalPath
|
|
End Function
|
|
|
|
Private Shared Function ExtractProgramFileName(data As Byte()) As String
|
|
Dim invalidChars = Path.GetInvalidFileNameChars()
|
|
|
|
For i = 0 To data.Length - 1
|
|
If data(i) <> AscW("$"c) Then
|
|
Continue For
|
|
End If
|
|
|
|
Dim builder As New StringBuilder()
|
|
For j = i + 1 To data.Length - 1
|
|
Dim value = data(j)
|
|
If value = 0 OrElse value = &HD OrElse value = &HA OrElse value = &H9 OrElse value = AscW("$"c) Then
|
|
Exit For
|
|
End If
|
|
If value < &H20 OrElse value > &H7E Then
|
|
Exit For
|
|
End If
|
|
|
|
Dim ch = ChrW(value)
|
|
If Array.IndexOf(invalidChars, ch) >= 0 Then
|
|
Exit For
|
|
End If
|
|
|
|
builder.Append(ch)
|
|
Next
|
|
|
|
Dim candidate = builder.ToString().Trim()
|
|
If candidate.Length > 0 AndAlso candidate.Contains("."c) Then
|
|
Return candidate
|
|
End If
|
|
Next
|
|
|
|
Return ""
|
|
End Function
|
|
|
|
Private Function PromptReceivedFileName(suggestedName As String) As String
|
|
Using form As New Form With {.Text = "Nome file ricevuto", .StartPosition = FormStartPosition.CenterParent, .FormBorderStyle = FormBorderStyle.FixedDialog, .MinimizeBox = False, .MaximizeBox = False, .ClientSize = New Size(440, 140)}
|
|
Dim label As New Label With {.Text = "Conferma o modifica il nome file da salvare:", .Left = 12, .Top = 12, .Width = 410, .AutoSize = False}
|
|
Dim textBox As New TextBox With {.Left = 12, .Top = 42, .Width = 410, .Text = suggestedName}
|
|
Dim ok As New Button With {.Text = "Salva", .Left = 256, .Top = 88, .Width = 78, .DialogResult = DialogResult.OK}
|
|
Dim cancel As New Button With {.Text = "Annulla", .Left = 344, .Top = 88, .Width = 78, .DialogResult = DialogResult.Cancel}
|
|
form.Controls.AddRange({label, textBox, ok, cancel})
|
|
form.AcceptButton = ok
|
|
form.CancelButton = cancel
|
|
textBox.SelectAll()
|
|
|
|
If form.ShowDialog(Me) = DialogResult.OK Then
|
|
Return textBox.Text
|
|
End If
|
|
End Using
|
|
|
|
Return Nothing
|
|
End Function
|
|
|
|
Private Function GetTerminatorBytes() As Byte()
|
|
Select Case CStr(cboTerminatoreInvio.SelectedItem)
|
|
Case "CR"
|
|
Return Encoding.ASCII.GetBytes(vbCr)
|
|
Case "LF"
|
|
Return Encoding.ASCII.GetBytes(vbLf)
|
|
Case "CRLF"
|
|
Return Encoding.ASCII.GetBytes(vbCrLf)
|
|
Case "%"
|
|
Return Encoding.ASCII.GetBytes("%")
|
|
Case "% + CRLF"
|
|
Return Encoding.ASCII.GetBytes("%" & vbCrLf)
|
|
Case Else
|
|
Return Array.Empty(Of Byte)()
|
|
End Select
|
|
End Function
|
|
|
|
Private Shared Function RemoveUtf8BomIfPresent(data As Byte()) As Byte()
|
|
If data.Length < 3 OrElse data(0) <> &HEF OrElse data(1) <> &HBB OrElse data(2) <> &HBF Then
|
|
Return data
|
|
End If
|
|
|
|
Dim cleanLength = data.Length - 3
|
|
If cleanLength = 0 Then
|
|
Return Array.Empty(Of Byte)()
|
|
End If
|
|
|
|
Dim clean(cleanLength - 1) As Byte
|
|
Buffer.BlockCopy(data, 3, clean, 0, clean.Length)
|
|
Return clean
|
|
End Function
|
|
|
|
Private Sub LogFirstBytes(data As Byte())
|
|
If data.Length = 0 Then
|
|
Log("File vuoto: nessun byte da inviare prima del terminatore.")
|
|
Return
|
|
End If
|
|
|
|
Dim previewLength = Math.Min(16, data.Length)
|
|
Dim preview As New StringBuilder()
|
|
For i = 0 To previewLength - 1
|
|
If i > 0 Then
|
|
preview.Append(" ")
|
|
End If
|
|
preview.Append(data(i).ToString("X2"))
|
|
Next
|
|
|
|
Log($"Primi byte inviati: {preview}")
|
|
If data(0) > &H7F Then
|
|
Log($"Attenzione: il primo byte e' > 7 bit ({data(0):X2}). Per Okuma 7E1 puo' essere un carattere non valido.")
|
|
End If
|
|
End Sub
|
|
|
|
Private Sub LogNonStandardCncBytes(data As Byte())
|
|
Dim firstInvalidPosition As Integer = -1
|
|
Dim firstInvalidValue As Byte = 0
|
|
Dim invalidCount As Integer
|
|
|
|
For i = 0 To data.Length - 1
|
|
Dim value = data(i)
|
|
Dim isAllowedControl = value = &H9 OrElse value = &HA OrElse value = &HD
|
|
Dim isPrintableAscii = value >= &H20 AndAlso value <= &H7E
|
|
If Not isAllowedControl AndAlso Not isPrintableAscii Then
|
|
invalidCount += 1
|
|
If firstInvalidPosition < 0 Then
|
|
firstInvalidPosition = i
|
|
firstInvalidValue = value
|
|
End If
|
|
End If
|
|
Next
|
|
|
|
If invalidCount > 0 Then
|
|
Log($"Avviso: trovati {invalidCount} byte di controllo/non ASCII. Primo valore 0x{firstInvalidValue:X2} alla posizione {firstInvalidPosition}. Invio comunque.")
|
|
End If
|
|
End Sub
|
|
|
|
Private Sub SetBusy(isBusy As Boolean)
|
|
btnInvia.Enabled = Not isBusy
|
|
btnRicevi.Enabled = Not isBusy
|
|
btnTestConnessione.Enabled = Not isBusy
|
|
btnSfogliaInvio.Enabled = Not isBusy
|
|
btnSfogliaRicezione.Enabled = Not isBusy
|
|
mnuSblocca.Enabled = Not isBusy
|
|
mnuCambiaPassword.Enabled = Not isBusy
|
|
mnuPulisciLog.Enabled = Not isBusy
|
|
btnAnnulla.Enabled = isBusy
|
|
If Not isBusy Then
|
|
For Each control In lockedControls
|
|
control.Enabled = controlsUnlocked
|
|
Next
|
|
Else
|
|
For Each control In lockedControls
|
|
control.Enabled = False
|
|
Next
|
|
End If
|
|
progress.Style = If(isBusy, ProgressBarStyle.Marquee, ProgressBarStyle.Blocks)
|
|
If Not isBusy Then
|
|
progress.Value = 0
|
|
End If
|
|
End Sub
|
|
|
|
Private Sub Log(message As String)
|
|
If InvokeRequired Then
|
|
BeginInvoke(Sub() Log(message))
|
|
Return
|
|
End If
|
|
txtLog.AppendText($"{DateTime.Now:HH:mm:ss} {message}{Environment.NewLine}")
|
|
End Sub
|
|
|
|
Private Shared Function ConfigPath() As String
|
|
Return Path.Combine(Application.StartupPath, ConfigFileName)
|
|
End Function
|
|
|
|
Private Function LoadOrCreateConfig() As AppConfig
|
|
Dim path = ConfigPath()
|
|
If File.Exists(path) Then
|
|
Dim loaded = JsonSerializer.Deserialize(Of AppConfig)(File.ReadAllText(path), JsonOptions())
|
|
If loaded IsNot Nothing Then
|
|
Return loaded
|
|
End If
|
|
End If
|
|
|
|
Dim created = CreateDefaultConfig()
|
|
appConfig = created
|
|
SetPassword("moxa")
|
|
SaveConfig()
|
|
Return appConfig
|
|
End Function
|
|
|
|
Private Sub SaveConfig()
|
|
File.WriteAllText(ConfigPath(), JsonSerializer.Serialize(appConfig, JsonOptions()))
|
|
End Sub
|
|
|
|
Private Shared Function JsonOptions() As JsonSerializerOptions
|
|
Return New JsonSerializerOptions With {.WriteIndented = True, .PropertyNameCaseInsensitive = True}
|
|
End Function
|
|
|
|
Private Function VerifyPassword(password As String) As Boolean
|
|
Dim salt = Convert.FromBase64String(appConfig.AdminPasswordSalt)
|
|
Dim expected = Convert.FromBase64String(appConfig.AdminPasswordHash)
|
|
Using pbkdf2 As New Rfc2898DeriveBytes(password, salt, 100000, HashAlgorithmName.SHA256)
|
|
Dim actual = pbkdf2.GetBytes(expected.Length)
|
|
Return CryptographicOperations.FixedTimeEquals(actual, expected)
|
|
End Using
|
|
End Function
|
|
|
|
Private Sub SetPassword(password As String)
|
|
Dim salt(15) As Byte
|
|
RandomNumberGenerator.Fill(salt)
|
|
Using pbkdf2 As New Rfc2898DeriveBytes(password, salt, 100000, HashAlgorithmName.SHA256)
|
|
appConfig.AdminPasswordSalt = Convert.ToBase64String(salt)
|
|
appConfig.AdminPasswordHash = Convert.ToBase64String(pbkdf2.GetBytes(32))
|
|
End Using
|
|
End Sub
|
|
|
|
Private Function PromptPassword(title As String, prompt As String) As String
|
|
Using form As New Form With {.Text = title, .StartPosition = FormStartPosition.CenterParent, .FormBorderStyle = FormBorderStyle.FixedDialog, .MinimizeBox = False, .MaximizeBox = False, .ClientSize = New Size(360, 130)}
|
|
Dim label As New Label With {.Text = prompt, .Left = 12, .Top = 12, .Width = 330, .AutoSize = False}
|
|
Dim textBox As New TextBox With {.Left = 12, .Top = 42, .Width = 330, .UseSystemPasswordChar = True}
|
|
Dim ok As New Button With {.Text = "OK", .Left = 176, .Top = 84, .Width = 78, .DialogResult = DialogResult.OK}
|
|
Dim cancel As New Button With {.Text = "Annulla", .Left = 264, .Top = 84, .Width = 78, .DialogResult = DialogResult.Cancel}
|
|
form.Controls.AddRange({label, textBox, ok, cancel})
|
|
form.AcceptButton = ok
|
|
form.CancelButton = cancel
|
|
If form.ShowDialog(Me) = DialogResult.OK Then
|
|
Return textBox.Text
|
|
End If
|
|
End Using
|
|
Return Nothing
|
|
End Function
|
|
|
|
Private Shared Function CreateDefaultConfig() As AppConfig
|
|
Return New AppConfig With {
|
|
.DefaultCompany = "SECUREX",
|
|
.MonitorRefreshSeconds = 30,
|
|
.DefaultSettings = New TransferSettings With {
|
|
.Port = 10001,
|
|
.ConnectionTimeoutSeconds = 10,
|
|
.ReceiveIdleTimeoutSeconds = 15,
|
|
.SendTerminator = "%",
|
|
.LineDelayMs = 100,
|
|
.CharDelayMs = 10,
|
|
.LinePaced = True,
|
|
.CharPaced = False,
|
|
.BlockPaced = False,
|
|
.BlockSizeBytes = 32,
|
|
.BlockDelayMs = 100,
|
|
.WaitBeforeSendSeconds = 2,
|
|
.WaitAfterSendSeconds = 2
|
|
},
|
|
.Companies = New List(Of CompanyConfig) From {
|
|
New CompanyConfig With {.Name = "SECUREX", .Machines = New List(Of MachineConfig) From {
|
|
New MachineConfig With {.Name = "M4 - N2LB 300", .IpMoxa = "192.168.0.101", .IpMachineWise = "192.168.0.214", .Note = "OSP-U100L"},
|
|
New MachineConfig With {.Name = "M5 - N3LB 300", .IpMoxa = "192.168.0.146", .IpMachineWise = "192.168.0.47", .Note = "OSP-E100L"},
|
|
New MachineConfig With {.Name = "M8 - CENTRO OKUMA", .IpMoxa = "192.168.0.113", .IpMachineWise = "192.168.0.68", .Note = "OSP-P200M"},
|
|
New MachineConfig With {.Name = "M11 - TORNIO OKUMA LB25I-N", .IpMoxa = "192.168.0.88", .IpMachineWise = "192.168.0.223"},
|
|
New MachineConfig With {.Name = "M12 - TORNIO OKUMA LB 400", .IpMoxa = "192.168.0.99", .IpMachineWise = "192.168.0.66"}
|
|
}},
|
|
New CompanyConfig With {.Name = "EMILIA", .Machines = New List(Of MachineConfig) From {
|
|
New MachineConfig With {.Name = "M1", .IpMoxa = "192.168.30.8", .IpMachineWise = "192.168.30.221"},
|
|
New MachineConfig With {.Name = "M2", .IpMoxa = "192.168.30.9", .IpMachineWise = "192.168.30.222"},
|
|
New MachineConfig With {.Name = "M3", .IpMoxa = "192.168.30.10", .IpMachineWise = "192.168.30.223"},
|
|
New MachineConfig With {.Name = "M4 - CENTRO LAVORO OKUMA", .IpMoxa = "192.168.30.11", .IpMachineWise = "192.168.30.224"},
|
|
New MachineConfig With {.Name = "M5", .IpMoxa = "192.168.30.12", .IpMachineWise = "192.168.30.225"},
|
|
New MachineConfig With {.Name = "M6", .IpMoxa = "192.168.30.13", .IpMachineWise = "192.168.30.226"}
|
|
}},
|
|
New CompanyConfig With {.Name = "SMART", .Machines = New List(Of MachineConfig) From {
|
|
New MachineConfig With {.Name = "M1", .IpMoxa = "192.168.35.10", .IpMachineWise = "192.168.35.212"},
|
|
New MachineConfig With {.Name = "M2", .IpMoxa = "192.168.35.11", .IpMachineWise = "192.168.35.211"},
|
|
New MachineConfig With {.Name = "M3", .IpMoxa = "192.168.35.12", .IpMachineWise = "192.168.35.213"},
|
|
New MachineConfig With {.Name = "M4 - CENTRO LAVORO OKUMA", .IpMoxa = "192.168.35.13", .IpMachineWise = "192.168.35.214"}
|
|
}}
|
|
}
|
|
}
|
|
End Function
|
|
End Class
|
|
|
|
Public Class AppConfig
|
|
Public Property AdminPasswordHash As String = ""
|
|
Public Property AdminPasswordSalt As String = ""
|
|
Public Property DefaultCompany As String = ""
|
|
Public Property MonitorRefreshSeconds As Integer = 30
|
|
Public Property LastReceiveDirectory As String = ""
|
|
Public Property DefaultSettings As New TransferSettings()
|
|
Public Property Companies As New List(Of CompanyConfig)()
|
|
End Class
|
|
|
|
Public Class CompanyConfig
|
|
Public Property Name As String = ""
|
|
Public Property Machines As New List(Of MachineConfig)()
|
|
End Class
|
|
|
|
Public Class MachineConfig
|
|
Public Property Name As String = ""
|
|
Public Property IpMoxa As String = ""
|
|
Public Property IpMachineWise As String = ""
|
|
Public Property Note As String = ""
|
|
End Class
|
|
|
|
Friend Class MoxaStatusTarget
|
|
Public Property Company As String = ""
|
|
Public Property Machine As MachineConfig
|
|
End Class
|
|
|
|
Public Class TransferSettings
|
|
Public Property Port As Integer = 10001
|
|
Public Property ConnectionTimeoutSeconds As Integer = 10
|
|
Public Property ReceiveIdleTimeoutSeconds As Integer = 15
|
|
Public Property SendTerminator As String = "%"
|
|
Public Property LineDelayMs As Integer = 100
|
|
Public Property CharDelayMs As Integer = 10
|
|
Public Property LinePaced As Boolean = True
|
|
Public Property CharPaced As Boolean = False
|
|
Public Property BlockPaced As Boolean = False
|
|
Public Property BlockSizeBytes As Integer = 32
|
|
Public Property BlockDelayMs As Integer = 100
|
|
Public Property WaitBeforeSendSeconds As Integer = 2
|
|
Public Property WaitAfterSendSeconds As Integer = 2
|
|
End Class
|