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;
2using System.Collections;
3using System.Collections.Generic;
4using System.Text;
5using System.Threading.Tasks;
6using Waher.Events;
13using Waher.Things.Ip;
14
15namespace Waher.Things.Modbus
16{
21 {
22 private readonly CommunicationLayer sniffers = new CommunicationLayer(false);
23
28 : base()
29 {
30 this.Port = 502;
31 this.Tls = false;
32 }
33
39 public override Task<string> GetTypeNameAsync(Language Language)
40 {
41 return Language.GetStringAsync(typeof(ModbusGatewayNode), 1, "Modbus Gateway");
42 }
43
49 public override Task<bool> AcceptsChildAsync(INode Child)
50 {
51 return Task.FromResult(Child is ModbusUnitNode);
52 }
53
54 #region ICommunicationLayer
55
60 public bool DecoupledEvents => this.sniffers.DecoupledEvents;
61
65 public ISniffer[] Sniffers => this.sniffers.Sniffers;
66
70 public bool HasSniffers => this.sniffers.HasSniffers;
71
76 public void Add(ISniffer Sniffer) => this.sniffers.Add(Sniffer);
77
82 public void AddRange(IEnumerable<ISniffer> Sniffers) => this.sniffers.AddRange(Sniffers);
83
89 public bool Remove(ISniffer Sniffer) => this.sniffers.Remove(Sniffer);
90
95 public IEnumerator<ISniffer> GetEnumerator() => this.sniffers.GetEnumerator();
96
101 IEnumerator IEnumerable.GetEnumerator() => this.sniffers.GetEnumerator();
102
107 public Task ReceiveBinary(byte[] Data) => this.sniffers.ReceiveBinary(Data);
108
113 public Task TransmitBinary(byte[] Data) => this.sniffers.TransmitBinary(Data);
114
119 public Task ReceiveText(string Text) => this.sniffers.ReceiveText(Text);
120
125 public Task TransmitText(string Text) => this.sniffers.TransmitText(Text);
126
131 public Task Information(string Comment) => this.sniffers.Information(Comment);
132
137 public Task Warning(string Warning) => this.sniffers.Warning(Warning);
138
143 public Task Error(string Error) => this.sniffers.Error(Error);
144
149 public Task Exception(Exception Exception) => this.sniffers.Exception(Exception);
150
155 public Task Exception(string Exception) => this.sniffers.Exception(Exception);
156
162 public Task ReceiveBinary(DateTime Timestamp, byte[] Data) => this.sniffers.ReceiveBinary(Timestamp, Data);
163
169 public Task TransmitBinary(DateTime Timestamp, byte[] Data) => this.sniffers.TransmitBinary(Timestamp, Data);
170
176 public Task ReceiveText(DateTime Timestamp, string Text) => this.sniffers.ReceiveText(Timestamp, Text);
177
183 public Task TransmitText(DateTime Timestamp, string Text) => this.sniffers.TransmitText(Timestamp, Text);
184
190 public Task Information(DateTime Timestamp, string Comment) => this.sniffers.Information(Timestamp, Comment);
191
197 public Task Warning(DateTime Timestamp, string Warning) => this.sniffers.Warning(Timestamp, Warning);
198
204 public Task Error(DateTime Timestamp, string Error) => this.sniffers.Error(Timestamp, Error);
205
211 public Task Exception(DateTime Timestamp, string Exception) => this.sniffers.Exception(Timestamp, Exception);
212
218 public Task Exception(DateTime Timestamp, Exception Exception) => this.sniffers.Exception(Timestamp, Exception);
219
220 #endregion
221
222 #region TCP/IP connections
223
224 private readonly static Cache<string, ModbusTcpClient> clients = GetCache();
225 private readonly static MultiReadSingleWriteObject clientsSynchObject = new MultiReadSingleWriteObject(typeof(ModbusGatewayNode));
226
227 private static Cache<string, ModbusTcpClient> GetCache()
228 {
229 Cache<string, ModbusTcpClient> Result = new Cache<string, ModbusTcpClient>(int.MaxValue, TimeSpan.MaxValue, TimeSpan.FromMinutes(5));
230
231 Result.Removed += Result_Removed;
232
233 return Result;
234 }
235
236 private static Task Result_Removed(object Sender, CacheItemEventArgs<string, ModbusTcpClient> e)
237 {
238 try
239 {
240 e.Value.Dispose();
241 }
242 catch (Exception ex)
243 {
244 Log.Exception(ex);
245 }
246
247 return Task.CompletedTask;
248 }
249
254 public async Task<ModbusTcpClient> GetTcpIpConnection()
255 {
256 StringBuilder sb = new StringBuilder();
257
258 sb.Append(this.Host);
259 sb.Append(this.Port.ToString());
260 sb.Append(this.Tls.ToString());
261
262 string Key = sb.ToString();
263
264 if (clients.TryGetValue(Key, out ModbusTcpClient Client))
265 {
266 if (Client.Connected)
267 {
268 this.CheckSniffers(Client);
269 return Client;
270 }
271 else
272 clients.Remove(Key);
273 }
274
275 await clientsSynchObject.BeginWrite();
276 try
277 {
278 if (clients.TryGetValue(Key, out Client))
279 return Client;
280
281 Client = await ModbusTcpClient.Connect(this.Host, this.Port, this.Tls, this.sniffers.Sniffers);
282
283 clients[Key] = Client;
284 }
285 finally
286 {
287 await clientsSynchObject.EndWrite();
288 }
289
290 return Client;
291 }
292
293 private void CheckSniffers(ModbusTcpClient Client)
294 {
295 if (!Client.HasSniffers && !this.sniffers.HasSniffers)
296 return;
297
298 foreach (ISniffer Sniffer in Client.Sniffers)
299 {
300 bool Found = false;
301
302 foreach (ISniffer Sniffer2 in this.sniffers.Sniffers)
303 {
304 if (Sniffer == Sniffer2)
305 {
306 Found = true;
307 break;
308 }
309 }
310
311 if (!Found)
312 Client.Remove(Sniffer);
313 }
314
315 foreach (ISniffer Sniffer in this.sniffers.Sniffers)
316 {
317 bool Found = false;
318
319 foreach (ISniffer Sniffer2 in Client.Sniffers)
320 {
321 if (Sniffer == Sniffer2)
322 {
323 Found = true;
324 break;
325 }
326 }
327
328 if (!Found)
329 Client.Add(Sniffer);
330 }
331 }
332
333 #endregion
334 }
335}
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:13
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:1647
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:15
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:63
Node representing a port on an IP Host machine.
Definition: IpHostPort.cs:21
bool Tls
If connection is encrypted using TLS or not.
Definition: IpHostPort.cs:67
int Port
Port number.
Definition: IpHostPort.cs:55
Node representing a TCP/IP connection to a Modbus Gateway
bool HasSniffers
If sniffers are registered
Task Information(DateTime Timestamp, string Comment)
Called to inform the viewer of something.
Task TransmitText(DateTime Timestamp, string Text)
Called when text has been transmitted.
Task ReceiveText(DateTime Timestamp, string Text)
Called when text has been received.
Task Exception(Exception Exception)
Called to inform the viewer of an exception state.
Task ReceiveBinary(byte[] Data)
Called when binary data has been received.
Task Exception(string Exception)
Called to inform the viewer of an exception state.
Task Error(DateTime Timestamp, string Error)
Called to inform the viewer of an error state.
Task ReceiveText(string Text)
Called when text has been received.
Task TransmitText(string Text)
Called when text has been transmitted.
async Task< ModbusTcpClient > GetTcpIpConnection()
Gets the TCP/IP connection associated with this gateway.
IEnumerator< ISniffer > GetEnumerator()
Gets an enumerator of registered sniffers.
void AddRange(IEnumerable< ISniffer > Sniffers)
Adds a range of sniffers
ISniffer[] Sniffers
Registered sniffers
Task Exception(DateTime Timestamp, string Exception)
Called to inform the viewer of an exception state.
Task Information(string Comment)
Called to inform the viewer of something.
Task ReceiveBinary(DateTime Timestamp, byte[] Data)
Called when binary data has been received.
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 ...
Task Warning(string Warning)
Called to inform the viewer of a warning state.
bool Remove(ISniffer Sniffer)
Removes a sniffer
Task TransmitBinary(DateTime Timestamp, byte[] Data)
Called when binary data has been transmitted.
void Add(ISniffer Sniffer)
Adds a sniffer
bool DecoupledEvents
If events raised from the communication layer are decoupled, i.e. executed in parallel with the sourc...
ModbusGatewayNode()
Node representing a TCP/IP connection to a Modbus Gateway
Task Warning(DateTime Timestamp, string Warning)
Called to inform the viewer of a warning state.
Task Error(string Error)
Called to inform the viewer of an error state.
override Task< string > GetTypeNameAsync(Language Language)
Gets the type name of the node.
Task TransmitBinary(byte[] Data)
Called when binary data has been transmitted.
Task Exception(DateTime Timestamp, Exception 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:11
Interface for nodes that are published through the concentrator interface.
Definition: INode.cs:49