W&T collega
Adattatori per TCP/IP, Ethernet, RS-232, RS-485, USB, 20 mA, Fibra ottica di vetro e plastica, http, SNMP, OPC, Modbus TCP, I/O digitale, I/O analogico, ISA, PCI

Tutorial al Web-IO digitale:

Attivare Web-IO digitale con
Visual Basic.Net attraverso
socket binari


Come successore di MS Visual Basic 5 e 6 ormai VB.Net è disponibile in diverse versioni fino a VB 2019. Anche l’attuale versione Visual Basic offre tutto ciò che è necessario per la programmazione di applicazioni TCP/IP, addirittura il supporto di strutture binarie. In tal modo Visual Basic fino ad oggi è uno strumento ausiliario apprezzato, per la creazione di applicazioni che comunicano con il Web-IO digitale tanto più che la versione Express di Visual Basic è scaricabile gratuitamente da Microsoft. Ulteriori driver o DLL non saranno necessari.

Controllo con Visual Basic

Con il seguente esempio di programma, l’utente può attivare il Web-IO digitale con i suoi input e output con un’applicazione Windows attraverso la modalità socket binario.


Preparativi


Collocazione dei diversi elementi di comando e oggetti di visualizzazione nel modulo VB.net

Elementi di comando Visual Basic

Oltre agli oggetti qui mostrati il programma necessita di un ulteriore timer per il polling (timer_polling).

Nella denominazione dei singoli oggetti è utile utilizzare nomi che ne riprendono il significato. In questo esempio la prima parte del nome descrive il tipo dell’oggetto e la seconda parte la funzione.

Informazioni di base

Mentre la costruzione delle interfacce utente grafiche in Visual Basic Express è ugualmente facile da realizzare come con le versioni precedenti, gli altri compiti hanno bisogno innanzitutto di una fase di rodaggio.

VB nella versione attuale non mette più a disposizione l’elemento di controllo Winsock conosciuto da VB5 e VB6.

Per l’accesso alla rete mediante la proposizione Import deve invece essere istanziato nell’intestazione del testo sorgente il namespace per le classi socket utilizzate. Inoltre deve essere creato il socket, su cui deve svolgersi la comunicazione, e deve essere definito un buffer per i dati di ingresso.

Inoltre l’incapsulamento dei singoli oggetti in VB.Net è stato talmente accentuato che gli oggetti, che sono applicati all’interno di un thread, non consentono l’accesso a partire da un altro thread. Così ad es. una casella di spunta, che era stata creata nel thread A, non può essere impostata dal thread B.

Per rendere tuttavia accessibili le proprietà degli oggetti per altri thread, nel proprio thread devono essere applicate procedure sub per la modifica degli oggetti. Relativamente a queste procedure sub vengono quindi formati delegati mediante i quali gli altri thread possono accedere.

Ad es. per abilitare l’utilizzo degli elementi di comando del modulo dopo la creazione riuscita del collegamento oppure per bloccarli al termine del collegamento, ma anche per adattare agli stati IO effettivi le caselle di spunta degli input/output dopo la ricezione dei dati.

							
Imports System.Net.Sockets
Imports System.Net

Public Class Form1
  Public Structure IO_State
    Dim outputstate0 As Boolean
    Dim outputstate1 As Boolean
    Dim inputstate0 As Boolean
    Dim inputstate1 As Boolean
    Dim countervalue0 As Long
    Dim countervalue1 As Long
  End Structure

  Private Delegate Sub DelegateSub()
  Private connectenable As New DelegateSub(AddressOf connect_enable)
  Private disconnectenable As New DelegateSub(AddressOf disconnect_enable)
  Private formupdate As New DelegateSub(AddressOf form_update)
  Dim TCP_client As Socket
  Dim connection_ar As IAsyncResult
  Dim receivebuffer(511) As Byte
  Dim IOState As IO_State

  Private Sub connect_enable()
    bt_connect.Enabled = False
    gb_io.Enabled = True
    bt_disconnect.Enabled = True
    Timer_polling.Enabled = True
    ToolStripStatusLabel1.Text = "Connected to " + tb_ip.Text + " : " + tb_port.Text
  End Sub

  Private Sub disconnect_enable()
    bt_connect.Enabled = True
    gb_io.Enabled = False
    bt_disconnect.Enabled = False
    timer_polling.Enabled = False
    ToolStripStatusLabel1.Text = "No Connection"
  End Sub

  Private Sub form_update()
    If IOState.inputstate0 = True Then
      cb_input0.Checked = True
    Else
      cb_input0.Checked = False
    End If
    If IOState.inputstate1 = True Then
      cb_input1.Checked = True
    Else
      cb_input1.Checked = False
    End If
    If IOState.outputstate0 = True Then
      cb_output0.Checked = True
    Else
      cb_output0.Checked = False
    End If
    If IOState.outputstate1 = True Then
      cb_Output1.Checked = True
    Else
      cb_Output1.Checked = False
    End If
    tb_counter0.Text = IOState.countervalue0
    tb_counter1.Text = IOState.countervalue1
  End Sub
							
						

Le strutture binarie

Per l’accesso binario è necessario definire le necessarie strutture binarie, con cui si deve comunicare con il Web-IO. Una descrizione dettagliata di queste strutture è disponibile nella breve panoramica binary o nel manuale di programmazione sul Web-IO.

La struttura EADriver
Con le sue quattro variabili a 16 bit è EADriver la struttura di base che è anche un elemento di tutte le altre strutture.

							
Public Structure structEADriver
  Dim Start_1 As UInt16
  Dim Start_2 As UInt16
  Dim StructType As UInt16
  Dim StructLength As UInt16
End Structure

<StructLayout(LayoutKind.Explicit)> Public Structure structOptions
  <FieldOffset(0)> Dim EADriver As structEADriver
  <FieldOffset(8)> Dim Version As UInt32
  <FieldOffset(12)> Dim Options As UInt32
End Structure

Public Structure structSetBit
  Dim EADriver As structEADriver
  Dim Mask As UInt16
  Dim Value As UInt16
End Structure

Public Structure structReadCounter
  Dim EADriver As structEADriver
  Dim CounterIndex As UInt16
End Structure

Public Structure structWriteRegister
  Dim EADriver As structEADriver
  Dim Amount As UInt16
  Dim Value As UInt16
End Structure

Public Structure structRegisterState
  Dim EADriver As structEADriver
  Dim DriverID As UInt16
  Dim InputValue As UInt16
  Dim OutputValue As UInt16
End Structure

<StructLayout(LayoutKind.Explicit)> Public Structure structCounter
  <FieldOffset(0)> Dim EADriver As structEADriver
  <FieldOffset(8)> Dim CounterIndex As UInt16
  <FieldOffset(10)> Dim CounterValue As UInt32
End Structure

<StructLayout(LayoutKind.Explicit)> Public Structure structAllCounter
  <FieldOffset(0)> Dim EADriver As structEADriver
  <FieldOffset(8)> Dim CounterNoOf As UInt16
  <FieldOffset(10)> Dim CounterValue0 As UInt32
  <FieldOffset(14)> Dim CounterValue1 As UInt32
End Structure
							
						

Nelle strutture è importante che le singole variabili vengano archiviate ininterrotte nella memoria. Questo Visual Basic non lo realizza automaticamente, in particolare se in una struttura vengono riunite variabili di dimensioni diverse. Per garantire tuttavia un’occupazione ininterrotta della memoria, si <StructLayout(LayoutKind.Explicit)> definisce che ogni singola variabile <FieldOffset(14)> Viene assegnata mediante un offset fisso alla prima posizione della memoria della struttura.

Controllo del collegamento

Inizializzazione del collegamento

Immettendo l’indirizzo IP del Web-IO nel campo di testo ed_ip e facendo clic sul pulsante bt_connect viene avviata la creazione del collegamento.

							
  Private Sub bt_connect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_connect.Click
    Dim WebIOep As New IPEndPoint(IPAddress.Parse(tb_ip.Text), Val(tb_port.Text))
    If tb_ip.Text <> "" And tb_port.Text <> "" Then
      TCP_client = New Socket(AddressFamily.InterNetwork, SocketType.Stream, _ ProtocolType.Tcp)
      bt_connect.Enabled = False
      Try
        TCP_client.BeginConnect(WebIOep, New AsyncCallback(AddressOf callback_connect), TCP_client)
      Catch ex As Exception
      End Try
    End If
  End Sub
							
						

Creazione del collegamento

Per lo svolgimento della gestione TCP/IP viene innanzitutto definito un IPEndPoint dall’indirizzo IP e dalla porta TCP e con ciò viene inizializzato il socket TCP_client. Durante la richiesta di collegamento viene creato un rimando a una procedura di callback.

Collegamento realizzato

Non appena il Web-IO accetta il collegamento, viene eseguita la procedura di callback. Mediante Invoke il delegato viene richiamato per la procedura che abilita gli elementi di comando e che visualizza lo stato di connessione nella riga di stato. Inoltre viene creato un rimando a una routine di callback per la ricezione dei dati.

Inviando la struttura Options Al Web-IO questo viene istruito, fissando un output a trasmettere lo stato di attivazione modificato attraverso la struttura RegisterState.

							
Private Sub callback_connect(ByVal ar As IAsyncResult)
  Invoke(connectenable)
  connection_ar = ar
  Try
    TCP_client.EndConnect(ar)
    TCP_client.BeginReceive(receivebuffer, 0, 512, SocketFlags.None, New AsyncCallback(AddressOf callback_readdata), TCP_client)
    Dim BufPtr As IntPtr
    Dim Options As structOptions
    Options.EADriver.Start_1 = 0
    Options.EADriver.Start_2 = 0
    Options.EADriver.StructType = &H1F0
    Options.EADriver.StructLength = 16
    Options.Version = 1
    Options.Options = 1
    BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(Options))
    Marshal.StructureToPtr(Options, BufPtr, True)
    sendstructure(BufPtr, Options.EADriver.StructLength)
  Catch ex As Exception
    closeconnections()
  End Try
End Sub
							
						

Disinserzione del collegamento

Il collegamento sussiste finché viene interrotto dall’utente mediante clic sul tasto Disconnect o finché il Web-IO interrompe il collegamento.

							  Private Sub bt_disconnect_Click(ByVal sender	As System.Object, ByVal e As System.EventArgs) Handles bt_disconnect.Click
    Invoke(disconnectenable)
    closeconnections()
  End Sub
							
						

In questo caso viene richiamata una corrispondente procedura.

							  Private Sub closeconnections()
    Try
      TCP_client.EndReceive(connection_ar)
    Catch ex As Exception
    End Try
    Try
      TCP_client.Shutdown(SocketShutdown.Both)
    Catch ex As Exception
    End Try
    Try
      TCP_client.Close()
    Catch ex As Exception
    End Try
    Invoke(disconnectenable)
  End Sub
							
						

Errore di collegamento

Tutte le azioni che riguardano la comunicazione TCP/IP vengono eseguite nell’ambito dell’istruzione Try. Se si verificano degli errori, viene utilizzata anche in questo caso la procedura CloseConnection.

Utilizzo e comunicazione della parte client

Invio di comandi

Non appena viene realizzato un collegamento con il Web-IO, l’utente può inviare strutture binarie al Web-IO controllando i corrispondenti elementi del programma.

							
Private Sub sendstructure(ByVal BufPtr As IntPtr, Bufsize As Integer)
  Dim senddata As Byte()
  ReDim senddata(Bufsize - 1)
  Marshal.Copy(BufPtr, senddata, 0, Bufsize)
  Try
    TCP_client.Send(senddata)
  Catch ex As Exception
    closeconnections()
  End Try
  Marshal.FreeHGlobal(BufPtr)
End Sub
							
						

Visual Basic non prevede alcun metodo per l’invio diretto di strutture binarie. I dati binari possono essere inviati solo come byte array. Per questo all’apertura della funzione sendstructure viene trasmesso un pointer (indicatore). Il suddetto pointer rimanda al punto della memoria da cui è ritrovabile il contenuto della struttura da inviare. Qui è chiaro perché le variabili strutturali devono essere salvate nella memoria in byte ininterrotti. Come secondo parametro viene trasmessa la lunghezza della struttura.

Mediante Marshal.Copy(BufPtr, senddata, 0, Bufsize) i dati strutturali vengono poi copiati in una serie di byte (byte array). Questa serie di byte viene poi inviata al Web-IO.

Impostazione degli output

L’impostazione degli output è resa possibile all’utente da due caselle di spunta cb_outputx. Il programma utilizza a tal scopo l’evento MouseUP di questo oggetto. Se si registra un MouseUP, quindi liberando il checkbox output, il programma esegue la rispettiva procedura e trasmette, a seconda che il checkbox sia stato impostato o meno, la struttura Set-bit opportunamente compilata al Web-IO.

							
Private Sub cb_output0_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles cb_output0.MouseUp
  Dim BufPtr As IntPtr
  Dim SetBit As structSetBit
  SetBit.EADriver.Start_1 = 0
  SetBit.EADriver.Start_2 = 0
  SetBit.EADriver.StructType = 9
  SetBit.EADriver.StructLength = 12
  SetBit.Mask = 1
  If cb_output0.Checked Then
    SetBit.Value = 1
  Else
    SetBit.Value = 0
  End If
  BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(SetBit))
  Marshal.StructureToPtr(SetBit, BufPtr, True)
  sendstructure(BufPtr, SetBit.EADriver.StructLength)
End Sub

Private Sub cb_Output1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles cb_Output1.MouseUp
  Dim BufPtr As IntPtr
  Dim SetBit As structSetBit
  SetBit.EADriver.Start_1 = 0
  SetBit.EADriver.Start_2 = 0
  SetBit.EADriver.StructType = 9
  SetBit.EADriver.StructLength = 12
  SetBit.Mask = 2
  If cb_Output1.Checked Then
    SetBit.Value = 2
  Else
    SetBit.Value = 0
  End If
  BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(SetBit))
  Marshal.StructureToPtr(SetBit, BufPtr, True)
  sendstructure(BufPtr, SetBit.EADriver.StructLength)
End Sub
							
						

Interrogazione dello stato degli output/input

L’utente può richiedere lo stato degli output e degli input facendo clic sul relativo pulsante.

							
  Private Sub bt_outputs_read_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_outputs_read.Click
    Dim BufPtr As IntPtr
    Dim RegisterRequest As structEADriver
    RegisterRequest.Start_1 = 0
    RegisterRequest.Start_2 = 0
    RegisterRequest.StructType = &H21
    RegisterRequest.StructLength = 8
    BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(RegisterRequest))
    Marshal.StructureToPtr(RegisterRequest, BufPtr, True)
    sendstructure(BufPtr, RegisterRequest.StructLength)
  End Sub
							
						

Inviando la struttura RegisterRequest Vengono richiesti gli stati di attivazione di input e output. Il Web-IO risponde a questa richiesta con la struttura RegisterState.

Se fossero interrogati solo gli input, ciò viene avviato attraverso clic sul tasto bt_inputs. A tal scopo viene inviata la struttura ReadRegister a cui il Web-IO risponde con la struttura WriteRegister.

							
  Private Sub bt_inputs_read_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_inputs_read.Click
    Dim BufPtr As IntPtr
    Dim ReadRegister As structEADriver
    ReadRegister.Start_1 = 0
    ReadRegister.Start_2 = 0
    ReadRegister.StructType = 1
    ReadRegister.StructLength = 8
    BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(ReadRegister))
    Marshal.StructureToPtr(ReadRegister, BufPtr, True)
    sendstructure(BufPtr, ReadRegister.StructLength)
  End Sub
							
						

Interrogazione/cancellazione dei counter

È possibile interrogare o cancellare anche gli stati dei counter degli input. A tal scopo viene inviata la struttura ReadCounter o ReadClearCounter, laddove con CounterIndex viene trasmesso il numero del counter. Il Web-IO risponde con la struttura Counter.

							
  Private Sub bt_counter_read0_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_counter_read0.Click
    Dim BufPtr As IntPtr
    Dim ReadCounter As structReadCounter
    ReadCounter.EADriver.Start_1 = 0
    ReadCounter.EADriver.Start_2 = 0
    ReadCounter.EADriver.StructType = &HB0
    ReadCounter.EADriver.StructLength = 10
    ReadCounter.CounterIndex = 0
    BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(ReadCounter))
    Marshal.StructureToPtr(ReadCounter, BufPtr, True)
    sendstructure(BufPtr, ReadCounter.EADriver.StructLength)
  End Sub

  Private Sub bt_counter_read1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_counter_read0.Click
    Dim BufPtr As IntPtr
    Dim ReadCounter As structReadCounter
    ReadCounter.EADriver.Start_1 = 0
    ReadCounter.EADriver.Start_2 = 0
    ReadCounter.EADriver.StructType = &HB0
    ReadCounter.EADriver.StructLength = 10
    ReadCounter.CounterIndex = 1
    BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(ReadCounter))
    Marshal.StructureToPtr(ReadCounter, BufPtr, True)
    sendstructure(BufPtr, ReadCounter.EADriver.StructLength)
  End Sub

  Private Sub bt_counter_clear0_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_counter_clear0.Click
    Dim BufPtr As IntPtr
    Dim ReadClearCounter As structReadCounter
    ReadClearCounter.EADriver.Start_1 = 0
    ReadClearCounter.EADriver.Start_2 = 0
    ReadClearCounter.EADriver.StructType = &HC0
    ReadClearCounter.EADriver.StructLength = 10
    ReadClearCounter.CounterIndex = 0
    BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(ReadClearCounter))
    Marshal.StructureToPtr(ReadClearCounter, BufPtr, True)
    sendstructure(BufPtr, ReadClearCounter.EADriver.StructLength)
  End Sub

  Private Sub bt_counter_clear1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_counter_clear0.Click
    Dim BufPtr As IntPtr
    Dim ReadClearCounter As structReadCounter
    ReadClearCounter.EADriver.Start_1 = 0
    ReadClearCounter.EADriver.Start_2 = 0
    ReadClearCounter.EADriver.StructType = &HC0
    ReadClearCounter.EADriver.StructLength = 10
    ReadClearCounter.CounterIndex = 1
    BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(ReadClearCounter))
    Marshal.StructureToPtr(ReadClearCounter, BufPtr, True)
    sendstructure(BufPtr, ReadClearCounter.EADriver.StructLength)
  End Sub
							
						

Sulla struttura ReadAllCounter o ReadAllCounter è possibile leggere o cancellare contemporaneamente anche tutti i counter. Il Web-IO risponde con la struttura AllCounter.

							
  Private Sub bt_counter_readall_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_counter_readall.Click
    Dim BufPtr As IntPtr
    Dim ReadAllCounter As structEADriver
    ReadAllCounter.Start_1 = 0
    ReadallCounter.Start_2 = 0
    ReadAllCounter.StructType = &HB1
    ReadAllCounter.StructLength = 10
    BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(ReadAllCounter))
    Marshal.StructureToPtr(ReadAllCounter, BufPtr, True)
    sendstructure(BufPtr, ReadAllCounter.StructLength)
  End Sub

  Private Sub bt_counter_clearall_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_counter_clearall.Click
    Dim BufPtr As IntPtr
    Dim ReadClaerAllCounter As structEADriver
    ReadClaerAllCounter.Start_1 = 0
    ReadClaerAllCounter.Start_2 = 0
    ReadClaerAllCounter.StructType = &HC1
    ReadClaerAllCounter.StructLength = 10
    BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(ReadClaerAllCounter))
    Marshal.StructureToPtr(ReadClaerAllCounter, BufPtr, True)
    sendstructure(BufPtr, ReadClaerAllCounter.StructLength)
  End Sub
							
						

Ricezione dei dati dal Web-IO

Analisi e visualizzazione dei dati ricevuti

Il Web-IO invia a seconda della richiesta o dell’evento da scatenare la struttura giusta. Alla ricezione dei dati viene aperta la corrispondente procedura di callback. Per la valutazione i primi 8 byte del byte-array ricevuto riempiono attraverso un’operazione del puntatore innanzitutto una struttura EADriver. L’applicazione riconosce di che tipo di struttura si tratta attraverso la variabile EADriver.StructType.

  • EADriver.StructType = 8
    Struttura WriteRegister per lo stato degli input

  • EADriver.StructType = 31 (hex.)
    Struttura RegisterState per lo stato degli input e output

  • EADriver.StructType = B4 (hex.)
    Struttura Counter per il valore di singoli counter

  • EADriver.StructType = B5 (hex.)
    Struttura AllCounter per il valore di tutti i counter

Per la valutazione il byte array ricevuto riempie ora la struttura adatta attraverso un’operazione del puntatore.

I valori così trasmessi vengono poi valutati e visualizzati. Per gli input e output viene trasmesso attraverso WriteRegister.Value, RegisterStae.InputValue e RegisterStae.outputValue lo schema di bit di tutti gli input e output.

							
Private Sub callback_readdata(ByVal ar As IAsyncResult)
  If TCP_client.Connected Then
    Dim bytesread As Integer
    Try
      bytesread = TCP_client.EndReceive(ar)
    Catch ex As Exception
    End Try
    If bytesread = 0 Then
      closeconnections()
    Else
      Try
        TCP_client.BeginReceive(receivebuffer, 0, 512, SocketFlags.None, New AsyncCallback(AddressOf callback_readdata), TCP_client)
      Catch ex As Exception
        closeconnections()
      End Try
      Dim MyGC As GCHandle = GCHandle.Alloc(receivebuffer, GCHandleType.Pinned)
      Dim EADriver As structEADriver = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, EADriver.GetType)

      Select Case EADriver.StructType
      Case 8
        Dim WriteRegister As structWriteRegister = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, WriteRegister.GetType)
        If (WriteRegister.Value And 1) = 1 Then
          IOState.inputstate0 = True
        Else
          IOState.inputstate0 = False
        End If
        If (WriteRegister.Value And 2) = 2 Then
          IOState.inputstate1 = True
        Else
          IOState.inputstate1 = False
        End If
      Case &H31
        Dim RegisterState As structRegisterState = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, RegisterState.GetType)
        If (RegisterState.InputValue And 1) = 1 Then
          IOState.inputstate0 = True
        Else
          IOState.inputstate0 = False
        End If
        If (RegisterState.InputValue And 2) = 2 Then
          IOState.inputstate1 = True
        Else
          IOState.inputstate1 = False
        End If
        If (RegisterState.OutputValue And 1) = 1 Then
          IOState.outputstate0 = True
        Else
          IOState.outputstate0 = False
        End If
        If (RegisterState.OutputValue And 2) = 2 Then
          IOState.outputstate1 = True
        Else
          IOState.outputstate1 = False
        End If
      Case &HB4
        Dim Counter As structCounter = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, Counter.GetType)
        If Counter.CounterIndex = 0 Then IOState.countervalue0 = Counter.CounterValue.ToString
        If Counter.CounterIndex = 1 Then IOState.countervalue1 = Counter.CounterValue.ToString
      Case &HB5
        Dim AllCounter As structAllCounter = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, AllCounter.GetType)
        IOState.countervalue0 = AllCounter.CounterValue0.ToString
        IOState.countervalue1 = AllCounter.CounterValue1.ToString
      End Select
      Invoke(formupdate)
      MyGC.Free()
    End If
  End If
End Sub
							
						

Polling

Interrogazione ciclica di determinati valori

Per permettere anche un aggiornamento automatico della visualizzazione, viene utilizzato un timer.

In base alle caselle di spunta per il polling degli output, degli input e dei counter le corrispondenti informazioni vengono interrogate dal Web-IO nell’intervallo impostato.

							
  Private Sub timer_polling_Elapsed(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs) Handles timer_polling.Elapsed
    If ((cb_input_polling.Checked Or cb_output_polling.Checked) And TCP_client.Connected) Then
      Dim BufPtr As IntPtr
      Dim RegisterRequest As structEADriver
      RegisterRequest.Start_1 = 0
      RegisterRequest.Start_2 = 0
      RegisterRequest.StructType = 1
      RegisterRequest.StructLength = &H21
      BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(RegisterRequest))
      Marshal.StructureToPtr(RegisterRequest, BufPtr, True)
      sendstructure(BufPtr, RegisterRequest.StructLength)
    End If
    If (cb_counter_polling.Checked And TCP_client.Connected) Then
      Dim BufPtr As IntPtr
      Dim ReadAllCounter As structEADriver
      ReadAllCounter.Start_1 = 0
      ReadAllCounter.Start_2 = 0
      ReadAllCounter.StructType = &HB1
      ReadAllCounter.StructLength = 10
      BufPtr = Marshal.AllocHGlobal(Runtime.InteropServices.Marshal.SizeOf(ReadAllCounter))
      Marshal.StructureToPtr(ReadAllCounter, BufPtr, True)
      sendstructure(BufPtr, ReadAllCounter.StructLength)
    End If
  End Sub
							
						

L’intervallo desiderato può essere immesso nel corrispondente campo di testo. In caso di una modifica l’intervallo del timer viene adattato automaticamente.

							
  Private Sub tb_interval_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tb_interval.TextChanged
    timer_polling.Interval = Val(tb_interval.Text)
  End Sub
							
						

Il programma esempio supporta tutte le comuni funzioni del Web-IO nella modalità socket binario ottimizzata per il Web-IO 2x input digitale, 2x output digitale. Per gli altri modelli di Web-IO devono eventualmente essere eseguiti adattamenti al programma. Una descrizione dettagliata delle strutture binarie è disponibile nella breve panoramica binary o nel manuale di programmazione sul Web-IO.

Download esempio di programma


Prodotti