Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ModbusGatewayNode.cs
1using System;
4using System.Linq;
5using System.Text;
6using System.Threading.Tasks;
7using Waher.Events;
14using Waher.Things.Ip;
15
16namespace Waher.Things.Modbus
17{
22 {
23 private readonly CommunicationLayer sniffers = new CommunicationLayer(false);
24
29 : base()
30 {
31 this.Port = 502;
32 this.Tls = false;
33 }
34
40 public override Task<string> GetTypeNameAsync(Language Language)
41 {
42 return Language.GetStringAsync(typeof(ModbusGatewayNode), 1, "Modbus Gateway");
43 }
44
50 public override Task<bool> AcceptsChildAsync(INode Child)
51 {
52 return Task.FromResult(Child is ModbusUnitNode);
53 }
54
55 #region ICommunicationLayer
56
61 public bool DecoupledEvents => this.sniffers.DecoupledEvents;
62
66 public ISniffer[] Sniffers => this.sniffers.Sniffers;
67
71 public bool HasSniffers => this.sniffers.HasSniffers;
72
77 public void Add(ISniffer Sniffer)
78 {
79 if (!this.sniffers.Contains(Sniffer))
80 this.sniffers.Add(Sniffer);
81 }
82
87 public void AddRange(IEnumerable<ISniffer> Sniffers) => this.sniffers.AddRange(Sniffers);
88
94 public bool Remove(ISniffer Sniffer) => this.sniffers.Remove(Sniffer);
95
100 public IEnumerator<ISniffer> GetEnumerator() => this.sniffers.GetEnumerator();
101
106 IEnumerator IEnumerable.GetEnumerator() => this.sniffers.GetEnumerator();
107
112 public void ReceiveBinary(int Count) => this.sniffers.ReceiveBinary(Count);
113
120 public void ReceiveBinary(bool ConstantBuffer, byte[] Data) => this.sniffers.ReceiveBinary(ConstantBuffer, Data);
121
130 public void ReceiveBinary(bool ConstantBuffer, byte[] Data, int Offset, int Count) => this.sniffers.ReceiveBinary(ConstantBuffer, Data, Offset, Count);
131
136 public void TransmitBinary(int Count) => this.sniffers.TransmitBinary(Count);
137
144 public void TransmitBinary(bool ConstantBuffer, byte[] Data) => this.sniffers.TransmitBinary(ConstantBuffer, Data);
145
154 public void TransmitBinary(bool ConstantBuffer, byte[] Data, int Offset, int Count) => this.sniffers.TransmitBinary(ConstantBuffer, Data, Offset, Count);
155
160 public void ReceiveText(string Text) => this.sniffers.ReceiveText(Text);
161
166 public void TransmitText(string Text) => this.sniffers.TransmitText(Text);
167
172 public void Information(string Comment) => this.sniffers.Information(Comment);
173
178 public void Warning(string Warning) => this.sniffers.Warning(Warning);
179
184 public void Error(string Error) => this.sniffers.Error(Error);
185
190 public void Exception(Exception Exception) => this.sniffers.Exception(Exception);
191
196 public void Exception(string Exception) => this.sniffers.Exception(Exception);
197
203 public void ReceiveBinary(DateTime Timestamp, int Count) => this.sniffers.ReceiveBinary(Timestamp, Count);
204
212 public void ReceiveBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data) => this.sniffers.ReceiveBinary(Timestamp, ConstantBuffer, Data);
213
223 public void ReceiveBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data, int Offset, int Count) => this.sniffers.ReceiveBinary(Timestamp, ConstantBuffer, Data, Offset, Count);
224
230 public void TransmitBinary(DateTime Timestamp, int Count) => this.sniffers.TransmitBinary(Timestamp, Count);
231
232
240 public void TransmitBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data) => this.sniffers.TransmitBinary(Timestamp, ConstantBuffer, Data);
241
251 public void TransmitBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data, int Offset, int Count) => this.sniffers.TransmitBinary(Timestamp, ConstantBuffer, Data, Offset, Count);
252
258 public void ReceiveText(DateTime Timestamp, string Text) => this.sniffers.ReceiveText(Timestamp, Text);
259
265 public void TransmitText(DateTime Timestamp, string Text) => this.sniffers.TransmitText(Timestamp, Text);
266
272 public void Information(DateTime Timestamp, string Comment) => this.sniffers.Information(Timestamp, Comment);
273
279 public void Warning(DateTime Timestamp, string Warning) => this.sniffers.Warning(Timestamp, Warning);
280
286 public void Error(DateTime Timestamp, string Error) => this.sniffers.Error(Timestamp, Error);
287
293 public void Exception(DateTime Timestamp, string Exception) => this.sniffers.Exception(Timestamp, Exception);
294
300 public void Exception(DateTime Timestamp, Exception Exception) => this.sniffers.Exception(Timestamp, Exception);
301
302 #endregion
303
304 #region TCP/IP connections
305
306 private readonly static Cache<string, ModbusTcpClient> clients = GetCache();
307 private readonly static MultiReadSingleWriteObject clientsSynchObject = new MultiReadSingleWriteObject(typeof(ModbusGatewayNode));
308
309 private static Cache<string, ModbusTcpClient> GetCache()
310 {
311 Cache<string, ModbusTcpClient> Result = new Cache<string, ModbusTcpClient>(int.MaxValue, TimeSpan.MaxValue, TimeSpan.FromMinutes(5));
312
313 Result.Removed += Result_Removed;
314
315 return Result;
316 }
317
318 private static Task Result_Removed(object Sender, CacheItemEventArgs<string, ModbusTcpClient> e)
319 {
320 try
321 {
322 e.Value.Dispose();
323 }
324 catch (Exception ex)
325 {
326 Log.Exception(ex);
327 }
328
329 return Task.CompletedTask;
330 }
331
336 public async Task<ModbusTcpClient> GetTcpIpConnection()
337 {
338 StringBuilder sb = new StringBuilder();
339
340 sb.Append(this.Host);
341 sb.Append(this.Port.ToString());
342 sb.Append(this.Tls.ToString());
343
344 string Key = sb.ToString();
345
346 if (clients.TryGetValue(Key, out ModbusTcpClient Client))
347 {
348 if (Client.Connected)
349 {
350 this.CheckSniffers(Client);
351 return Client;
352 }
353 else
354 clients.Remove(Key);
355 }
356
357 await clientsSynchObject.BeginWrite();
358 try
359 {
360 if (clients.TryGetValue(Key, out Client))
361 return Client;
362
363 Client = await ModbusTcpClient.Connect(this.Host, this.Port, this.Tls, this.sniffers.Sniffers);
364
365 clients[Key] = Client;
366 }
367 finally
368 {
369 await clientsSynchObject.EndWrite();
370 }
371
372 return Client;
373 }
374
375 private void CheckSniffers(ModbusTcpClient Client)
376 {
377 if (!Client.HasSniffers && !this.sniffers.HasSniffers)
378 return;
379
380 foreach (ISniffer Sniffer in Client.Sniffers)
381 {
382 bool Found = false;
383
384 foreach (ISniffer Sniffer2 in this.sniffers.Sniffers)
385 {
386 if (Sniffer == Sniffer2)
387 {
388 Found = true;
389 break;
390 }
391 }
392
393 if (!Found)
394 Client.Remove(Sniffer);
395 }
396
397 foreach (ISniffer Sniffer in this.sniffers.Sniffers)
398 {
399 bool Found = false;
400
401 foreach (ISniffer Sniffer2 in Client.Sniffers)
402 {
403 if (Sniffer == Sniffer2)
404 {
405 Found = true;
406 break;
407 }
408 }
409
410 if (!Found)
411 Client.Add(Sniffer);
412 }
413 }
414
415 #endregion
416
417 #region Commands
418
422 public override Task<IEnumerable<ICommand>> Commands => this.GetCommands();
423
424 private async Task<IEnumerable<ICommand>> GetCommands()
425 {
426 List<ICommand> Commands = new List<ICommand>();
427 Commands.AddRange(await base.Commands);
428 return Commands.ToArray();
429 }
430
431 #endregion
432 }
433}
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1657
Simple base class for classes implementing communication protocols.
virtual bool Remove(ISniffer Sniffer)
ICommunicationLayer.Remove
ISniffer[] Sniffers
Registered sniffers.
bool HasSniffers
If there are sniffers registered on the object.
virtual void Add(ISniffer Sniffer)
ICommunicationLayer.Add
static async Task< ModbusTcpClient > Connect(string Host, int Port, params ISniffer[] Sniffers)
Connects to an Modbus TCP/IP Gateway
Implements an in-memory cache.
Definition: Cache.cs:17
Event arguments for cache item removal events.
ValueType Value
Value of item that was removed.
Contains information about a language.
Definition: Language.cs:17
Task< string > GetStringAsync(Type Type, int Id, string Default)
Gets the string value of a string ID. If no such string exists, a string is created with the default ...
Definition: Language.cs:209
Represents an object that allows single concurrent writers but multiple concurrent readers....
string Host
Host name or IP address.
Definition: IpHost.cs:73
Node representing a port on an IP Host machine.
Definition: IpHostPort.cs:24
bool Tls
If connection is encrypted using TLS or not.
Definition: IpHostPort.cs:70
int Port
Port number.
Definition: IpHostPort.cs:58
Node representing a TCP/IP connection to a Modbus Gateway
void TransmitBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data, int Offset, int Count)
Called when binary data has been transmitted.
bool HasSniffers
If sniffers are registered
void Warning(string Warning)
Called to inform the viewer of a warning state.
void TransmitText(string Text)
Called when text has been transmitted.
override Task< IEnumerable< ICommand > > Commands
Available command objects. If no commands are available, null is returned.
void TransmitBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data)
Called when binary data has been transmitted.
void Error(DateTime Timestamp, string Error)
Called to inform the viewer of an error state.
void TransmitBinary(DateTime Timestamp, int Count)
Called when binary data has been transmitted.
void ReceiveBinary(int Count)
Called when binary data has been received.
void TransmitBinary(bool ConstantBuffer, byte[] Data, int Offset, int Count)
Called when binary data has been transmitted.
async Task< ModbusTcpClient > GetTcpIpConnection()
Gets the TCP/IP connection associated with this gateway.
void TransmitBinary(bool ConstantBuffer, byte[] Data)
Called when binary data has been transmitted.
void Information(string Comment)
Called to inform the viewer of something.
void ReceiveBinary(DateTime Timestamp, int Count)
Called when binary data has been received.
IEnumerator< ISniffer > GetEnumerator()
Gets an enumerator of registered sniffers.
void AddRange(IEnumerable< ISniffer > Sniffers)
Adds a range of sniffers
void ReceiveBinary(bool ConstantBuffer, byte[] Data, int Offset, int Count)
Called when binary data has been received.
void ReceiveText(string Text)
Called when text has been received.
void ReceiveBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data)
Called when binary data has been received.
ISniffer[] Sniffers
Registered sniffers
void Warning(DateTime Timestamp, string Warning)
Called to inform the viewer of a warning state.
void Exception(DateTime Timestamp, string Exception)
Called to inform the viewer of an exception state.
void Error(string Error)
Called to inform the viewer of an error state.
override Task< bool > AcceptsChildAsync(INode Child)
If the node accepts a presumptive child, i.e. can receive as a child (if that child accepts the node ...
bool Remove(ISniffer Sniffer)
Removes a sniffer
void Exception(Exception Exception)
Called to inform the viewer of an exception state.
void ReceiveText(DateTime Timestamp, string Text)
Called when text has been received.
void TransmitBinary(int Count)
Called when binary data has been transmitted.
void Add(ISniffer Sniffer)
Adds a sniffer
void Exception(DateTime Timestamp, Exception Exception)
Called to inform the viewer of an exception state.
bool DecoupledEvents
If events raised from the communication layer are decoupled, i.e. executed in parallel with the sourc...
void ReceiveBinary(DateTime Timestamp, bool ConstantBuffer, byte[] Data, int Offset, int Count)
Called when binary data has been received.
ModbusGatewayNode()
Node representing a TCP/IP connection to a Modbus Gateway
override Task< string > GetTypeNameAsync(Language Language)
Gets the type name of the node.
void Information(DateTime Timestamp, string Comment)
Called to inform the viewer of something.
void TransmitText(DateTime Timestamp, string Text)
Called when text has been transmitted.
void ReceiveBinary(bool ConstantBuffer, byte[] Data)
Called when binary data has been received.
void Exception(string Exception)
Called to inform the viewer of an exception state.
Represents a Unit Device on a Modbus network.
Interface for observable classes implementing communication protocols.
Interface for sniffers. Sniffers can be added to ICommunicationLayer classes to eavesdrop on communic...
Definition: ISniffer.cs:10
Interface for nodes that are published through the concentrator interface.
Definition: INode.cs:49