Lire un fichier d'un logiciel tiers
- maxpeigne
- Dieu du process

- Messages : 771
- Enregistré le : 11 oct. 2015, 17:31
- Localisation : Nord pas de calais
Lire un fichier d'un logiciel tiers
Bonjour à tous,
J'ai un logiciel tiers qui me donne un fichier (.csv ou .txt) avec des parametres que j'aimerai récupérer dans un automate (peu importe la marque, Schneider, Siemens...). J'imagine que cela ne peut pas se faire sans une interface...
Alors je sais le faire avec un logiciel de supervision (PCVue), mais est faisable avec une IHM? (encore une fois peut importe la marque).
J'ai essayé avec Vijeo Designer, mais passer par le gestionnaire de donnée n'est pas top.
Idéalement, j'aimerai trouver une IHM où je puisse indiquer un dossier présent sur un PC ou un serveur du réseau afin d'y importer les parametres de mon fichier .csv
Connaissez vous du matériel qui fait cela?
Merci.
J'ai un logiciel tiers qui me donne un fichier (.csv ou .txt) avec des parametres que j'aimerai récupérer dans un automate (peu importe la marque, Schneider, Siemens...). J'imagine que cela ne peut pas se faire sans une interface...
Alors je sais le faire avec un logiciel de supervision (PCVue), mais est faisable avec une IHM? (encore une fois peut importe la marque).
J'ai essayé avec Vijeo Designer, mais passer par le gestionnaire de donnée n'est pas top.
Idéalement, j'aimerai trouver une IHM où je puisse indiquer un dossier présent sur un PC ou un serveur du réseau afin d'y importer les parametres de mon fichier .csv
Connaissez vous du matériel qui fait cela?
Merci.
http://automacile.fr - Site et tutoriels sur l'arduino.
- filou59
- Forcené des structures

- Messages : 190
- Enregistré le : 20 oct. 2015, 23:26
- Localisation : Nord
Re: Lire un fichier d'un logiciel tiers
Depuis un afficheur proface on peu lire un fichier, mais il faut qu'il soit sur la carte SD ou sur la clef usb.
Si tu veux lire un fichier depuis le reseau, c'est probablement possible chez proface avec les nouveaux SP5000 équipé de la box qui tourne sur une base windows.
Si tu veux lire un fichier depuis le reseau, c'est probablement possible chez proface avec les nouveaux SP5000 équipé de la box qui tourne sur une base windows.
Re: Lire un fichier d'un logiciel tiers
Tu peux directement l'injecter et le lire dans l'automate normalement. Ou alors lire un emplacement réseau depuis l'automate
Moi je fais ça sous Beckhoff, tu ouvre le fichier, tu le "décortiques", puis tu affectes les paramètres.
Moi je fais ça sous Beckhoff, tu ouvre le fichier, tu le "décortiques", puis tu affectes les paramètres.
- itasoft
- Mi homme - Mi automate

- Messages : 7805
- Enregistré le : 20 oct. 2015, 10:15
- Localisation : Lyon
- Contact :
Re: Lire un fichier d'un logiciel tiers
Slts,
Je récapitule :
-Tu as un logiciel tiers sur ton PC qui te génère des paramètres dans un fichier .CSV
-Tu veux à partir de ton PC envoyer ce fichier dans l’automate afin de récupérer ces paramètres dans des variables de l’automate.
C’est bien ça que tu veux faire ??????
Je récapitule :
-Tu as un logiciel tiers sur ton PC qui te génère des paramètres dans un fichier .CSV
-Tu veux à partir de ton PC envoyer ce fichier dans l’automate afin de récupérer ces paramètres dans des variables de l’automate.
C’est bien ça que tu veux faire ??????
Automaticien privé (de tout)
itasoft@free.fr
itasoft@free.fr
- maxpeigne
- Dieu du process

- Messages : 771
- Enregistré le : 11 oct. 2015, 17:31
- Localisation : Nord pas de calais
Re: Lire un fichier d'un logiciel tiers
Merci pour vos réponses!

Merci encore pour vos conseils!
Exactement. Comme je ne pense pas que l'automate peut aller lire ce type de fichier directement dans un PC, j'ai pensé passer par une IHM (maintenant si tu as une autre solution je suis preneur).itasoft a écrit : ↑02 févr. 2017, 15:27 Slts,
Je récapitule :
-Tu as un logiciel tiers sur ton PC qui te génère des paramètres dans un fichier .CSV
-Tu veux à partir de ton PC envoyer ce fichier dans l’automate afin de récupérer ces paramètres dans des variables de l’automate.
C’est bien ça que tu veux faire ??????
Tu penses que ca fonctionnerait aussi avec un wago (étant donné qu'ils ont un air de famille et que j'en ais un sous la main)?
Je ne connais pas encore proface mais ca sera le moment de m'y intéresserfilou59 a écrit : ↑02 févr. 2017, 11:07 Depuis un afficheur proface on peu lire un fichier, mais il faut qu'il soit sur la carte SD ou sur la clef usb.
Si tu veux lire un fichier depuis le reseau, c'est probablement possible chez proface avec les nouveaux SP5000 équipé de la box qui tourne sur une base windows.
Merci encore pour vos conseils!
http://automacile.fr - Site et tutoriels sur l'arduino.
- filou59
- Forcené des structures

- Messages : 190
- Enregistré le : 20 oct. 2015, 23:26
- Localisation : Nord
Re: Lire un fichier d'un logiciel tiers
Oui j'avais pas parlé de WAGO vu que tu parlais d'IHM.
Mais c'est faisable sans aucun problème. Ya des bibliotheques toute faite et des exemples sur leur site normalement.
Mais c'est faisable sans aucun problème. Ya des bibliotheques toute faite et des exemples sur leur site normalement.
- Bernardo59
- Mi homme - Mi automate

- Messages : 1054
- Enregistré le : 20 oct. 2015, 05:48
- Localisation : Nimes
- Contact :
Re: Lire un fichier d'un logiciel tiers
Salut Max,
Si c'est du Modbus TCP, personnellement je ferai un programme en VB.NET ou C#.
Ce programme irait récupérer les valeurs de ton fichier CSV (après il faut voir le nombre...) toutes les 500 ms ou 1s ça dépend.
J'irai ensuite écrire les données dans l'automate via le protocole Modbus TCP.
Après il faut voir ce que tu as comme fichier, comme automate mais c'est jouable.
J'ai une librairie en Modbus TCP si ça te dit.
@+
Si c'est du Modbus TCP, personnellement je ferai un programme en VB.NET ou C#.
Ce programme irait récupérer les valeurs de ton fichier CSV (après il faut voir le nombre...) toutes les 500 ms ou 1s ça dépend.
J'irai ensuite écrire les données dans l'automate via le protocole Modbus TCP.
Après il faut voir ce que tu as comme fichier, comme automate mais c'est jouable.
J'ai une librairie en Modbus TCP si ça te dit.
@+
- maxpeigne
- Dieu du process

- Messages : 771
- Enregistré le : 11 oct. 2015, 17:31
- Localisation : Nord pas de calais
Re: Lire un fichier d'un logiciel tiers
Ca me tente bien, par contre je ne comprends pas trop comment je peux "écrire les données dans l'automate via le protocole Modbus TCP". Cela serait fait via un script VB.Net ou C#?
Je ne connais pas encore ces langages, si je dois m’intéresser à l'un d'eux vous me conseillerez lequel?
Merci!
http://automacile.fr - Site et tutoriels sur l'arduino.
- Bernardo59
- Mi homme - Mi automate

- Messages : 1054
- Enregistré le : 20 oct. 2015, 05:48
- Localisation : Nimes
- Contact :
Re: Lire un fichier d'un logiciel tiers
Salut Max,
Quoi qu'il arrive, l'automate sera Client et Serveur en même temps. Du moins chez Schneider ça marche comme ça, Siemens pareil.
Donc tu peux avoir un logiciel qui peut-être Client Modbus TCP pour écrire au Serveur Modbus TCP (l'automate).
Il va donc utiliser la fonction 06 ou 16 du protocole Modbus pour écrire la valeur d'un ou plusieurs mots.
Le but du logiciel et d'ouvrir ton fichier .CSV, de récupérer les données et d'envoyer une trame au Serveur Modbus TCP.
Niveau langage, je ne peux que te conseiller le VB.NET si tu n'as jamais pratiqué, sinon tu peux commencer par le C# directement mais ça sera plus long.
Je te donne le code source de la classe (a intégrer dans Visual Studio) :
Quoi qu'il arrive, l'automate sera Client et Serveur en même temps. Du moins chez Schneider ça marche comme ça, Siemens pareil.
Donc tu peux avoir un logiciel qui peut-être Client Modbus TCP pour écrire au Serveur Modbus TCP (l'automate).
Il va donc utiliser la fonction 06 ou 16 du protocole Modbus pour écrire la valeur d'un ou plusieurs mots.
Le but du logiciel et d'ouvrir ton fichier .CSV, de récupérer les données et d'envoyer une trame au Serveur Modbus TCP.
Niveau langage, je ne peux que te conseiller le VB.NET si tu n'as jamais pratiqué, sinon tu peux commencer par le C# directement mais ça sera plus long.
Je te donne le code source de la classe (a intégrer dans Visual Studio) :
Code : Tout sélectionner
Imports System.Collections
Imports System.Text
Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading
Namespace ModbusTCP
''' <summary>
''' Modbus TCP common driver class. This class implements a modbus TCP master driver.
''' It supports the following commands:
'''
''' Read coils
''' Read discrete inputs
''' Write single coil
''' Write multiple cooils
''' Read holding register
''' Read input register
''' Write single register
''' Write multiple register
'''
''' All commands can be sent in synchronous or asynchronous mode. If a value is accessed
''' in synchronous mode the program will stop and wait for slave to response. If the
''' slave didn't answer within a specified time a timeout exception is called.
''' The class uses multi threading for both synchronous and asynchronous access. For
''' the communication two lines are created. This is necessary because the synchronous
''' thread has to wait for a previous command to finish.
'''
''' </summary>
Public Class Master
' ------------------------------------------------------------------------
' Constants for access
Private Const fctReadCoil As Byte = 1
Private Const fctReadDiscreteInputs As Byte = 2
Private Const fctReadHoldingRegister As Byte = 3
Private Const fctReadInputRegister As Byte = 4
Private Const fctWriteSingleCoil As Byte = 5
Private Const fctWriteSingleRegister As Byte = 6
Private Const fctWriteMultipleCoils As Byte = 15
Private Const fctWriteMultipleRegister As Byte = 16
Private Const fctReadWriteMultipleRegister As Byte = 23
''' <summary>Constant for exception illegal function.</summary>
Public Const excIllegalFunction As Byte = 1
''' <summary>Constant for exception illegal data address.</summary>
Public Const excIllegalDataAdr As Byte = 2
''' <summary>Constant for exception illegal data value.</summary>
Public Const excIllegalDataVal As Byte = 3
''' <summary>Constant for exception slave device failure.</summary>
Public Const excSlaveDeviceFailure As Byte = 4
''' <summary>Constant for exception acknowledge.</summary>
Public Const excAck As Byte = 5
''' <summary>Constant for exception slave is busy/booting up.</summary>
Public Const excSlaveIsBusy As Byte = 6
''' <summary>Constant for exception gate path unavailable.</summary>
Public Const excGatePathUnavailable As Byte = 10
''' <summary>Constant for exception not connected.</summary>
Public Const excExceptionNotConnected As Byte = 253
''' <summary>Constant for exception connection lost.</summary>
Public Const excExceptionConnectionLost As Byte = 254
''' <summary>Constant for exception response timeout.</summary>
Public Const excExceptionTimeout As Byte = 255
''' <summary>Constant for exception wrong offset.</summary>
Private Const excExceptionOffset As Byte = 128
''' <summary>Constant for exception send failt.</summary>
Private Const excSendFailt As Byte = 100
' ------------------------------------------------------------------------
' Private declarations
Private Shared _timeout As UShort = 500
Private Shared _refresh As UShort = 10
Private Shared _connected As Boolean = False
Private tcpAsyCl As Socket
Private tcpAsyClBuffer As Byte() = New Byte(2047) {}
Private tcpSynCl As Socket
Private tcpSynClBuffer As Byte() = New Byte(2047) {}
' ------------------------------------------------------------------------
''' <summary>Response data event. This event is called when new data arrives</summary>
Public Delegate Sub ResponseData(ByVal id As UShort, ByVal unit As Byte, ByVal [function] As Byte, ByVal data As Byte())
''' <summary>Response data event. This event is called when new data arrives</summary>
Public Event OnResponseData As ResponseData
''' <summary>Exception data event. This event is called when the data is incorrect</summary>
Public Delegate Sub ExceptionData(ByVal id As UShort, ByVal unit As Byte, ByVal [function] As Byte, ByVal exception As Byte)
''' <summary>Exception data event. This event is called when the data is incorrect</summary>
Public Event OnException As ExceptionData
' ------------------------------------------------------------------------
''' <summary>Response timeout. If the slave didn't answers within in this time an exception is called.</summary>
''' <value>The default value is 500ms.</value>
Public Property timeout() As UShort
Get
Return _timeout
End Get
Set(ByVal value As UShort)
_timeout = value
End Set
End Property
' ------------------------------------------------------------------------
''' <summary>Refresh timer for slave answer. The class is polling for answer every X ms.</summary>
''' <value>The default value is 10ms.</value>
Public Property refresh() As UShort
Get
Return _refresh
End Get
Set(ByVal value As UShort)
_refresh = value
End Set
End Property
' ------------------------------------------------------------------------
''' <summary>Shows if a connection is active.</summary>
Public ReadOnly Property connected() As Boolean
Get
Return _connected
End Get
End Property
' ------------------------------------------------------------------------
''' <summary>Create master instance without parameters.</summary>
Public Sub New()
End Sub
' ------------------------------------------------------------------------
''' <summary>Create master instance with parameters.</summary>
''' <param name="ip">IP adress of modbus slave.</param>
''' <param name="port">Port number of modbus slave. Usually port 502 is used.</param>
Public Sub New(ByVal ip As String, ByVal port As UShort)
connect(ip, port)
End Sub
' ------------------------------------------------------------------------
''' <summary>Start connection to slave.</summary>
''' <param name="ip">IP adress of modbus slave.</param>
''' <param name="port">Port number of modbus slave. Usually port 502 is used.</param>
Public Sub connect(ByVal ip As String, ByVal port As UShort)
Try
Dim _ip As IPAddress
If IPAddress.TryParse(ip, _ip) = False Then
Dim hst As IPHostEntry = Dns.GetHostEntry(ip)
ip = hst.AddressList(0).ToString()
End If
' ----------------------------------------------------------------
' Connect asynchronous client
tcpAsyCl = New Socket(IPAddress.Parse(ip).AddressFamily, SocketType.Stream, ProtocolType.Tcp)
tcpAsyCl.Connect(New IPEndPoint(IPAddress.Parse(ip), port))
tcpAsyCl.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, _timeout)
tcpAsyCl.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, _timeout)
tcpAsyCl.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1)
' ----------------------------------------------------------------
'' Connect synchronous client
'tcpSynCl = New Socket(IPAddress.Parse(ip).AddressFamily, SocketType.Stream, ProtocolType.Tcp)
'tcpSynCl.Connect(New IPEndPoint(IPAddress.Parse(ip), port))
'tcpSynCl.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, _timeout)
'tcpSynCl.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, _timeout)
'tcpSynCl.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1)
_connected = True
Catch [error] As System.IO.IOException
_connected = False
Throw ([error])
End Try
End Sub
' ------------------------------------------------------------------------
''' <summary>Stop connection to slave.</summary>
Public Sub disconnect()
Dispose()
End Sub
' ------------------------------------------------------------------------
''' <summary>Destroy master instance.</summary>
Protected Overrides Sub Finalize()
Try
Dispose()
Finally
MyBase.Finalize()
End Try
End Sub
' ------------------------------------------------------------------------
''' <summary>Destroy master instance</summary>
Public Sub Dispose()
If tcpAsyCl IsNot Nothing Then
If tcpAsyCl.Connected Then
Try
tcpAsyCl.Shutdown(SocketShutdown.Both)
Catch
End Try
tcpAsyCl.Close()
End If
tcpAsyCl = Nothing
End If
If tcpSynCl IsNot Nothing Then
If tcpSynCl.Connected Then
Try
tcpSynCl.Shutdown(SocketShutdown.Both)
Catch
End Try
tcpSynCl.Close()
End If
tcpSynCl = Nothing
End If
End Sub
Friend Sub CallException(ByVal id As UShort, ByVal unit As Byte, ByVal [function] As Byte, ByVal exception As Byte)
If (tcpAsyCl Is Nothing) OrElse (tcpSynCl Is Nothing) Then
Return
End If
If exception = excExceptionConnectionLost Then
tcpSynCl = Nothing
tcpAsyCl = Nothing
End If
RaiseEvent OnException(id, unit, [function], exception)
End Sub
Friend Shared Function SwapUInt16(ByVal inValue As UInt16) As UInt16
Return CType(((inValue And &HFF00) >> 8) Or ((inValue And &HFF) << 8), UInt16)
End Function
' ------------------------------------------------------------------------
''' <summary>Read coils from slave asynchronous. The result is given in the response function.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address from where the data read begins.</param>
''' <param name="numInputs">Length of data.</param>
Public Sub ReadCoils(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal numInputs As UShort)
WriteAsyncData(CreateReadHeader(id, unit, startAddress, numInputs, fctReadCoil), id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Read coils from slave synchronous.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address from where the data read begins.</param>
''' <param name="numInputs">Length of data.</param>
''' <param name="values">Contains the result of function.</param>
Public Sub ReadCoils(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal numInputs As UShort, ByRef values As Byte())
values = WriteSyncData(CreateReadHeader(id, unit, startAddress, numInputs, fctReadCoil), id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Read discrete inputs from slave asynchronous. The result is given in the response function.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address from where the data read begins.</param>
''' <param name="numInputs">Length of data.</param>
Public Sub ReadDiscreteInputs(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal numInputs As UShort)
WriteAsyncData(CreateReadHeader(id, unit, startAddress, numInputs, fctReadDiscreteInputs), id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Read discrete inputs from slave synchronous.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address from where the data read begins.</param>
''' <param name="numInputs">Length of data.</param>
''' <param name="values">Contains the result of function.</param>
Public Sub ReadDiscreteInputs(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal numInputs As UShort, ByRef values As Byte())
values = WriteSyncData(CreateReadHeader(id, unit, startAddress, numInputs, fctReadDiscreteInputs), id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Read holding registers from slave asynchronous. The result is given in the response function.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address from where the data read begins.</param>
''' <param name="numInputs">Length of data.</param>
Public Sub ReadHoldingRegister(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal numInputs As UShort)
WriteAsyncData(CreateReadHeader(id, unit, startAddress, numInputs, fctReadHoldingRegister), id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Read holding registers from slave synchronous.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address from where the data read begins.</param>
''' <param name="numInputs">Length of data.</param>
''' <param name="values">Contains the result of function.</param>
Public Sub ReadHoldingRegister(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal numInputs As UShort, ByRef values As Byte())
values = WriteSyncData(CreateReadHeader(id, unit, startAddress, numInputs, fctReadHoldingRegister), id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Read input registers from slave asynchronous. The result is given in the response function.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address from where the data read begins.</param>
''' <param name="numInputs">Length of data.</param>
Public Sub ReadInputRegister(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal numInputs As UShort)
WriteAsyncData(CreateReadHeader(id, unit, startAddress, numInputs, fctReadInputRegister), id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Read input registers from slave synchronous.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address from where the data read begins.</param>
''' <param name="numInputs">Length of data.</param>
''' <param name="values">Contains the result of function.</param>
Public Sub ReadInputRegister(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal numInputs As UShort, ByRef values As Byte())
values = WriteSyncData(CreateReadHeader(id, unit, startAddress, numInputs, fctReadInputRegister), id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Write single coil in slave asynchronous. The result is given in the response function.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address from where the data read begins.</param>
''' <param name="OnOff">Specifys if the coil should be switched on or off.</param>
Public Sub WriteSingleCoils(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal OnOff As Boolean)
Dim data As Byte()
data = CreateWriteHeader(id, unit, startAddress, 1, 1, fctWriteSingleCoil)
If OnOff = True Then
data(10) = 255
Else
data(10) = 0
End If
WriteAsyncData(data, id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Write single coil in slave synchronous.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address from where the data read begins.</param>
''' <param name="OnOff">Specifys if the coil should be switched on or off.</param>
''' <param name="result">Contains the result of the synchronous write.</param>
Public Sub WriteSingleCoils(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal OnOff As Boolean, ByRef result As Byte())
Dim data As Byte()
data = CreateWriteHeader(id, unit, startAddress, 1, 1, fctWriteSingleCoil)
If OnOff = True Then
data(10) = 255
Else
data(10) = 0
End If
result = WriteSyncData(data, id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Write multiple coils in slave asynchronous. The result is given in the response function.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address from where the data read begins.</param>
''' <param name="numBits">Specifys number of bits.</param>
''' <param name="values">Contains the bit information in byte format.</param>
Public Sub WriteMultipleCoils(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal numBits As UShort, ByVal values As Byte())
Dim numBytes As Byte = Convert.ToByte(values.Length)
Dim data As Byte()
data = CreateWriteHeader(id, unit, startAddress, numBits, CByte(numBytes + 2), fctWriteMultipleCoils)
Array.Copy(values, 0, data, 13, numBytes)
WriteAsyncData(data, id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Write multiple coils in slave synchronous.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address from where the data read begins.</param>
''' <param name="numBits">Specifys number of bits.</param>
''' <param name="values">Contains the bit information in byte format.</param>
''' <param name="result">Contains the result of the synchronous write.</param>
Public Sub WriteMultipleCoils(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal numBits As UShort, ByVal values As Byte(), ByRef result As Byte())
Dim numBytes As Byte = Convert.ToByte(values.Length)
Dim data As Byte()
data = CreateWriteHeader(id, unit, startAddress, numBits, CByte(numBytes + 2), fctWriteMultipleCoils)
Array.Copy(values, 0, data, 13, numBytes)
result = WriteSyncData(data, id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Write single register in slave asynchronous. The result is given in the response function.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address to where the data is written.</param>
''' <param name="values">Contains the register information.</param>
Public Sub WriteSingleRegister(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal values As Byte())
Dim data As Byte()
data = CreateWriteHeader(id, unit, startAddress, 1, 1, fctWriteSingleRegister)
data(10) = values(0)
data(11) = values(1)
WriteAsyncData(data, id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Write single register in slave synchronous.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address to where the data is written.</param>
''' <param name="values">Contains the register information.</param>
''' <param name="result">Contains the result of the synchronous write.</param>
Public Sub WriteSingleRegister(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal values As Byte(), ByRef result As Byte())
Dim data As Byte()
data = CreateWriteHeader(id, unit, startAddress, 1, 1, fctWriteSingleRegister)
data(10) = values(0)
data(11) = values(1)
result = WriteSyncData(data, id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Write multiple registers in slave asynchronous. The result is given in the response function.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address to where the data is written.</param>
''' <param name="values">Contains the register information.</param>
Public Sub WriteMultipleRegister(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal values As Byte())
Dim numBytes As UShort = Convert.ToUInt16(values.Length)
If numBytes Mod 2 > 0 Then
numBytes += 1
End If
Dim data As Byte()
data = CreateWriteHeader(id, unit, startAddress, Convert.ToUInt16(numBytes \ 2), Convert.ToUInt16(numBytes + 2), fctWriteMultipleRegister)
Array.Copy(values, 0, data, 13, values.Length)
WriteAsyncData(data, id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Write multiple registers in slave synchronous.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startAddress">Address to where the data is written.</param>
''' <param name="values">Contains the register information.</param>
''' <param name="result">Contains the result of the synchronous write.</param>
Public Sub WriteMultipleRegister(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal values As Byte(), ByRef result As Byte())
Dim numBytes As UShort = Convert.ToUInt16(values.Length)
If numBytes Mod 2 > 0 Then
numBytes += 1
End If
Dim data As Byte()
data = CreateWriteHeader(id, unit, startAddress, Convert.ToUInt16(numBytes \ 2), Convert.ToUInt16(numBytes + 2), fctWriteMultipleRegister)
Array.Copy(values, 0, data, 13, values.Length)
result = WriteSyncData(data, id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Read/Write multiple registers in slave asynchronous. The result is given in the response function.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startReadAddress">Address from where the data read begins.</param>
''' <param name="numInputs">Length of data.</param>
''' <param name="startWriteAddress">Address to where the data is written.</param>
''' <param name="values">Contains the register information.</param>
Public Sub ReadWriteMultipleRegister(ByVal id As UShort, ByVal unit As Byte, ByVal startReadAddress As UShort, ByVal numInputs As UShort, ByVal startWriteAddress As UShort, ByVal values As Byte())
Dim numBytes As UShort = Convert.ToUInt16(values.Length)
If numBytes Mod 2 > 0 Then
numBytes += 1
End If
Dim data As Byte()
data = CreateReadWriteHeader(id, unit, startReadAddress, numInputs, startWriteAddress, Convert.ToUInt16(numBytes \ 2))
Array.Copy(values, 0, data, 17, values.Length)
WriteAsyncData(data, id)
End Sub
' ------------------------------------------------------------------------
''' <summary>Read/Write multiple registers in slave synchronous. The result is given in the response function.</summary>
''' <param name="id">Unique id that marks the transaction. In asynchonous mode this id is given to the callback function.</param>
''' <param name="unit">Unit identifier (previously slave address). In asynchonous mode this unit is given to the callback function.</param>
''' <param name="startReadAddress">Address from where the data read begins.</param>
''' <param name="numInputs">Length of data.</param>
''' <param name="startWriteAddress">Address to where the data is written.</param>
''' <param name="values">Contains the register information.</param>
''' <param name="result">Contains the result of the synchronous command.</param>
Public Sub ReadWriteMultipleRegister(ByVal id As UShort, ByVal unit As Byte, ByVal startReadAddress As UShort, ByVal numInputs As UShort, ByVal startWriteAddress As UShort, ByVal values As Byte(), _
ByRef result As Byte())
Dim numBytes As UShort = Convert.ToUInt16(values.Length)
If numBytes Mod 2 > 0 Then
numBytes += 1
End If
Dim data As Byte()
data = CreateReadWriteHeader(id, unit, startReadAddress, numInputs, startWriteAddress, Convert.ToUInt16(numBytes \ 2))
Array.Copy(values, 0, data, 17, values.Length)
result = WriteSyncData(data, id)
End Sub
' ------------------------------------------------------------------------
' Create modbus header for read action
Private Function CreateReadHeader(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal length As UShort, ByVal [function] As Byte) As Byte()
Dim data As Byte() = New Byte(11) {}
Dim _id As Byte() = BitConverter.GetBytes(CShort(id))
data(0) = _id(1)
' Slave id high byte
data(1) = _id(0)
' Slave id low byte
data(5) = 6
' Message size
data(6) = unit
' Slave address
data(7) = [function]
' Function code
Dim _adr As Byte() = BitConverter.GetBytes(CShort(IPAddress.HostToNetworkOrder(CShort(startAddress))))
data(8) = _adr(0)
' Start address
data(9) = _adr(1)
' Start address
Dim _length As Byte() = BitConverter.GetBytes(CShort(IPAddress.HostToNetworkOrder(CShort(length))))
data(10) = _length(0)
' Number of data to read
data(11) = _length(1)
' Number of data to read
Return data
End Function
' ------------------------------------------------------------------------
' Create modbus header for write action
Private Function CreateWriteHeader(ByVal id As UShort, ByVal unit As Byte, ByVal startAddress As UShort, ByVal numData As UShort, ByVal numBytes As UShort, ByVal [function] As Byte) As Byte()
Dim data As Byte() = New Byte(numBytes + 10) {}
Dim _id As Byte() = BitConverter.GetBytes(CShort(id))
data(0) = _id(1)
' Slave id high byte
data(1) = _id(0)
' Slave id low byte
Dim _size As Byte() = BitConverter.GetBytes(CShort(IPAddress.HostToNetworkOrder(CShort(5 + numBytes))))
data(4) = _size(0)
' Complete message size in bytes
data(5) = _size(1)
' Complete message size in bytes
data(6) = unit
' Slave address
data(7) = [function]
' Function code
Dim _adr As Byte() = BitConverter.GetBytes(CShort(IPAddress.HostToNetworkOrder(CShort(startAddress))))
data(8) = _adr(0)
' Start address
data(9) = _adr(1)
' Start address
If [function] >= fctWriteMultipleCoils Then
Dim _cnt As Byte() = BitConverter.GetBytes(CShort(IPAddress.HostToNetworkOrder(CShort(numData))))
data(10) = _cnt(0)
' Number of bytes
data(11) = _cnt(1)
' Number of bytes
data(12) = CByte(numBytes - 2)
End If
Return data
End Function
' ------------------------------------------------------------------------
' Create modbus header for read/write action
Private Function CreateReadWriteHeader(ByVal id As UShort, ByVal unit As Byte, ByVal startReadAddress As UShort, ByVal numRead As UShort, ByVal startWriteAddress As UShort, ByVal numWrite As UShort) As Byte()
Dim data As Byte() = New Byte(numWrite * 2 + 16) {}
Dim _id As Byte() = BitConverter.GetBytes(CShort(id))
data(0) = _id(1)
' Slave id high byte
data(1) = _id(0)
' Slave id low byte
Dim _size As Byte() = BitConverter.GetBytes(CShort(IPAddress.HostToNetworkOrder(CShort(11 + numWrite * 2))))
data(4) = _size(0)
' Complete message size in bytes
data(5) = _size(1)
' Complete message size in bytes
data(6) = unit
' Slave address
data(7) = fctReadWriteMultipleRegister
' Function code
Dim _adr_read As Byte() = BitConverter.GetBytes(CShort(IPAddress.HostToNetworkOrder(CShort(startReadAddress))))
data(8) = _adr_read(0)
' Start read address
data(9) = _adr_read(1)
' Start read address
Dim _cnt_read As Byte() = BitConverter.GetBytes(CShort(IPAddress.HostToNetworkOrder(CShort(numRead))))
data(10) = _cnt_read(0)
' Number of bytes to read
data(11) = _cnt_read(1)
' Number of bytes to read
Dim _adr_write As Byte() = BitConverter.GetBytes(CShort(IPAddress.HostToNetworkOrder(CShort(startWriteAddress))))
data(12) = _adr_write(0)
' Start write address
data(13) = _adr_write(1)
' Start write address
Dim _cnt_write As Byte() = BitConverter.GetBytes(CShort(IPAddress.HostToNetworkOrder(CShort(numWrite))))
data(14) = _cnt_write(0)
' Number of bytes to write
data(15) = _cnt_write(1)
' Number of bytes to write
data(16) = CByte(numWrite * 2)
Return data
End Function
' ------------------------------------------------------------------------
' Write asynchronous data
Private Sub WriteAsyncData(ByVal write_data As Byte(), ByVal id As UShort)
If (tcpAsyCl IsNot Nothing) AndAlso (tcpAsyCl.Connected) Then
Try
tcpAsyCl.BeginSend(write_data, 0, write_data.Length, SocketFlags.None, New AsyncCallback(AddressOf OnSend), Nothing)
tcpAsyCl.BeginReceive(tcpAsyClBuffer, 0, tcpAsyClBuffer.Length, SocketFlags.None, New AsyncCallback(AddressOf OnReceive), tcpAsyCl)
Catch generatedExceptionName As SystemException
CallException(id, write_data(6), write_data(7), excExceptionConnectionLost)
End Try
Else
CallException(id, write_data(6), write_data(7), excExceptionConnectionLost)
End If
End Sub
' ------------------------------------------------------------------------
' Write asynchronous data acknowledge
Private Sub OnSend(ByVal result As System.IAsyncResult)
If result.IsCompleted = False Then
CallException(&HFFFF, &HFF, &HFF, excSendFailt)
End If
End Sub
' ------------------------------------------------------------------------
' Write asynchronous data response
Private Sub OnReceive(ByVal result As System.IAsyncResult)
If result.IsCompleted = False Then
CallException(&HFF, &HFF, &HFF, excExceptionConnectionLost)
End If
Dim id As UShort = SwapUInt16(BitConverter.ToUInt16(tcpAsyClBuffer, 0))
Dim unit As Byte = tcpAsyClBuffer(6)
Dim [function] As Byte = tcpAsyClBuffer(7)
Dim data As Byte()
' ------------------------------------------------------------
' Write response data
If ([function] >= fctWriteSingleCoil) AndAlso ([function] <> fctReadWriteMultipleRegister) Then
data = New Byte(1) {}
Array.Copy(tcpAsyClBuffer, 10, data, 0, 2)
Else
' ------------------------------------------------------------
' Read response data
data = New Byte(tcpAsyClBuffer(8) - 1) {}
Array.Copy(tcpAsyClBuffer, 9, data, 0, tcpAsyClBuffer(8))
End If
' ------------------------------------------------------------
' Response data is slave exception
If [function] > excExceptionOffset Then
[function] -= excExceptionOffset
CallException(id, unit, [function], tcpAsyClBuffer(8))
' ------------------------------------------------------------
' Response data is regular data
Else
'ElseIf OnResponseData IsNot Nothing Then
RaiseEvent OnResponseData(id, unit, [function], data)
End If
End Sub
' ------------------------------------------------------------------------
' Write data and and wait for response
Private Function WriteSyncData(ByVal write_data As Byte(), ByVal id As UShort) As Byte()
If tcpSynCl.Connected Then
Try
tcpSynCl.Send(write_data, 0, write_data.Length, SocketFlags.None)
Dim result As Integer = tcpSynCl.Receive(tcpSynClBuffer, 0, tcpSynClBuffer.Length, SocketFlags.None)
Dim unit As Byte = tcpSynClBuffer(6)
Dim [function] As Byte = tcpSynClBuffer(7)
Dim data As Byte()
If result = 0 Then
CallException(id, unit, write_data(7), excExceptionConnectionLost)
End If
' ------------------------------------------------------------
' Response data is slave exception
If [function] > excExceptionOffset Then
[function] -= excExceptionOffset
CallException(id, unit, [function], tcpSynClBuffer(8))
Return Nothing
' ------------------------------------------------------------
' Write response data
ElseIf ([function] >= fctWriteSingleCoil) AndAlso ([function] <> fctReadWriteMultipleRegister) Then
data = New Byte(1) {}
Array.Copy(tcpSynClBuffer, 10, data, 0, 2)
Else
' ------------------------------------------------------------
' Read response data
data = New Byte(tcpSynClBuffer(8) - 1) {}
Array.Copy(tcpSynClBuffer, 9, data, 0, tcpSynClBuffer(8))
End If
Return data
Catch generatedExceptionName As SystemException
CallException(id, write_data(6), write_data(7), excExceptionConnectionLost)
End Try
Else
CallException(id, write_data(6), write_data(7), excExceptionConnectionLost)
End If
Return Nothing
End Function
End Class
End Namespace