/// <summary> /// Initialization of the serial port based on the port configuration /// </summary> private static ISerialDevice InitSerialPort(PortConfig portConfig) { if (portConfig.Device.Substring(0, 3) == "COM" || portConfig.Device.Substring(0, 8) == "/dev/tty" || portConfig.Device.Substring(0, 11) == "/dev/rfcomm") { try { Log.Information($"Opening port '{portConfig.Device}' ({portConfig.BaudRate}, {portConfig.DataBits}, StopBitsEnum: {portConfig.StopBitsEnum}, ParityEnum: {portConfig.ParityEnum}) for '{portConfig.Direction}'"); var serialPort = OpenSerial(portConfig.Device, portConfig.BaudRate, portConfig.ParityEnum, portConfig.DataBits, portConfig.StopBitsEnum, portConfig.Direction); if (serialPort == null) { Log.Debug("For some reason, serial port creation failed."); } return(serialPort); } catch (Exception ex) { Log.Error($"{ex.Message}"); Log.Debug($"Inner Exception InitSerialPort: {ex.InnerException?.ToString()}"); } } return(null); }
/// <summary> /// Read the byte[] response from a serial port /// </summary> private static byte[] ReadResponse(ISerialDevice serialPort, PortConfig portConfig) { // Log.Verbose("Read next line..."); int bytesRead = 0; int delimiterIndex = 0; var temp = new List <byte>(); var buf = new byte[1]; //read until end delimiter is reached eg. \r\n in 12345\r\n67890 while (serialPort != null && _run && bytesRead < 1024) { var i = serialPort.Read(buf, 0, 1); if (i < 1) { continue; } var str = System.Text.Encoding.Default.GetString(buf); temp.Add(buf[0]); if (str[0] != portConfig.Delimiter[delimiterIndex]) { delimiterIndex = 0; } else { delimiterIndex++; if (delimiterIndex == portConfig.Delimiter.Length) { temp.RemoveRange(temp.Count - portConfig.Delimiter.Length, portConfig.Delimiter.Length); break; } } bytesRead++; } if (bytesRead == _maxBytesToRead) { Log.Warning($"Delimiter '{ShowControlCharacters(portConfig.Delimiter)}' not found in last {_maxBytesToRead} bytes read."); temp.Clear(); } if (!_run) { Log.Debug("Shutdown reading"); temp.Clear(); } if (serialPort == null) { Log.Debug("No port available anymore"); temp.Clear(); } return(temp.ToArray()); }
/// <summary> /// Execution method for a 'Read' or 'Write' task per port. /// </summary> private static async Task SerialTaskBody(string port, PortConfig portConfig, ModuleClient client, SerialMessageBroadcaster serialMessageBroadcaster) { try { Log.Debug($"Creating port"); // create serial port var serialPort = InitSerialPort(portConfig); if (serialPort == null) { Log.Debug($"Task for {port} aborted."); return; } Log.Debug($"Port '{port}' created"); if (portConfig.Direction == "Read") { Log.Debug($"Start read loop"); // Looping infinitely until desired properties are updated. while (serialPort != null && _run) { var response = ReadResponse(serialPort, portConfig); if (portConfig.IgnoreEmptyLines && response.Length == 0) { Log.Debug($"Ignore empty line"); continue; } var data = Encoding.UTF8.GetString(response); if (portConfig.DelimiterInOutput) { if (portConfig.DelimiterAtStart) { data = portConfig.Delimiter + data; } else { data = data + portConfig.Delimiter; } } Log.Debug($"Data read from '{portConfig.Device}': '{data}'"); var serialMessage = new SerialMessage { Data = data, Port = port, TimestampUtc = DateTime.UtcNow, }; var jsonMessage = JsonConvert.SerializeObject(serialMessage); Log.Debug($"Message out: '{jsonMessage}'"); var byteMessage = Encoding.UTF8.GetBytes(jsonMessage); using (var pipeMessage = new Message(byteMessage)) { pipeMessage.ContentType = "application/json"; pipeMessage.ContentEncoding = "utf-8"; pipeMessage.Properties.Add("content-type", "application/edge-serial-json"); await client.SendEventAsync(port, pipeMessage); } Log.Debug($"Message sent to output: {port}"); // wait a certain interval await Task.Delay(portConfig.SleepInterval); } Log.Debug($"Disposing port '{port}'"); // Ingest stopped. Tear down port DisposeSerialPort(serialPort); Log.Debug($"Disposed port '{port}'"); } else if (portConfig.Direction == "Write") { Log.Debug("Let's write to serial"); serialMessageBroadcaster.BroadcastEvent += (sender, se) => { Log.Debug($"Executing BroadcastEvent for port '{se.Port}'"); if (se.Port == port) { Log.Debug($"BroadcastEvent has been picked up"); byte[] valueBytes = se.Message; byte[] delimiterBytes = Encoding.UTF8.GetBytes(portConfig.Delimiter); byte[] totalBytes = valueBytes.Concat(delimiterBytes).ToArray(); Log.Debug($"BroadcastEvent message converted"); if (serialPort != null && totalBytes.Length > 0) { serialPort.Write(totalBytes, 0, totalBytes.Length); Log.Information($"Written to '{se.Port}': '{ShowControlCharacters(Encoding.UTF8.GetString(totalBytes))}'"); } else { Log.Information($"Value not written to '{se.Port}', no port available or empty message"); } Log.Debug($"BroadcastEvent message handled"); } }; while (serialPort != null && _run) { await Task.Delay(portConfig.SleepInterval); } ; } Log.Debug($"Task for {port} ended."); } catch (Exception ex) { // if one task fails, we just shut it down Log.Error($"{ex.Message}"); Log.Debug($"Inner Exception SerialTaskBody: {ex.InnerException?.ToString()}"); } }
public void Validate() { List <string> invalidConfigs = new List <string>(); foreach (var config_pair in PortConfigs) { PortConfig portConfig = config_pair.Value; var key = config_pair.Key; if (portConfig == null) { Console.WriteLine($"{key} configuration is null, remove from dictionary..."); invalidConfigs.Add(key); continue; } if (string.IsNullOrEmpty(portConfig.Device)) { Console.WriteLine($"missing device for {key}"); invalidConfigs.Add(key); } if (string.IsNullOrEmpty(portConfig.Direction)) { portConfig.Direction = DefaultDirection; Console.WriteLine($"Invalid direction for {key}. Set to default {DefaultDirection}"); } if (portConfig.SleepInterval < 1) { portConfig.SleepInterval = DefaultSleepInterval; Console.WriteLine($"Invalid sleep interval for {key}. Set to default {DefaultSleepInterval}"); } if (portConfig.BaudRate < 1) { portConfig.BaudRate = DefaultBaudRate; Console.WriteLine($"Invalid baudRate for {key}. Set to default {DefaultBaudRate}"); } if (!string.IsNullOrEmpty(portConfig.Parity)) { switch (portConfig.Parity) { case "None": portConfig.ParityEnum = Parity.None; break; case "Even": portConfig.ParityEnum = Parity.Even; break; case "Odd": portConfig.ParityEnum = Parity.Odd; break; case "Mark": portConfig.ParityEnum = Parity.Mark; break; case "Space": portConfig.ParityEnum = Parity.Space; break; default: portConfig.Parity = DefaultParity; Console.WriteLine($"Invalid parity '{portConfig.Parity}' for '{key}'. Set to default {DefaultParity}"); break; } ; } else { portConfig.Parity = DefaultParity; Console.WriteLine($"Missing parity for {key}. Set to default {DefaultParity}"); } if (portConfig.DataBits < 1) { portConfig.DataBits = DefaultDataBits; Console.WriteLine($"Invalid databits for {key}. Set to default {DefaultDataBits}"); } if (!string.IsNullOrEmpty(portConfig.StopBits)) { switch (portConfig.StopBits) { case "None": portConfig.StopBitsEnum = StopBits.None; break; case "One": portConfig.StopBitsEnum = StopBits.One; break; case "OnePointFive": portConfig.StopBitsEnum = StopBits.OnePointFive; break; case "Two": portConfig.StopBitsEnum = StopBits.Two; break; default: portConfig.StopBits = DefaultStopBits; Console.WriteLine($"Invalid stopbits '{portConfig.StopBits}' for '{key}'. Set to default {DefaultParity}"); break; } ; } else { portConfig.StopBits = DefaultStopBits; Console.WriteLine($"Missing stopBits for {key}. Set to default {DefaultStopBits}"); } if (string.IsNullOrEmpty(portConfig.Delimiter)) { portConfig.Delimiter = DefaultDelimiter; Console.WriteLine($"Missing delimiter for {key}. Set to defailt {DefaultDelimiter}"); } } foreach (var invalidPort in invalidConfigs) { PortConfigs.Remove(invalidPort); } }