/// /// Copyright (c) 2015 Sensus Metering Systems /// using System; using System.Collections.Generic; using System.Globalization; using System.IO.Ports; using System.Text; using System.Threading; using log4net; using TBF.BenchControl.Generic; using TBF.Boxes; namespace TBF.BenchControl.Modbus.Common { /// /// Root component for Modbus communication via serial port (RS485) /// public class Modbus : ComponentBase, IDevice, GenericDevices.IModbus { private static readonly ILog log = LogManager.GetLogger(typeof(Modbus)); public override string ToString() { return string.Format("Modbus({0})", Cfg.ToString(1)); } private readonly ModbusCfg modbusCommonCfg; /// Private fields SerialPort serialPort; Thread workerThread; bool stopWorkerThread; public Modbus() { } /// /// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232) /// Connection settings: 19200 Bd 8-bits No-parity 1-stop-bit Flow control: none or hardware. /// public Modbus(ModbusCfg cfg, IList components) : base(cfg) { serialPort = null; modbusCommonCfg = cfg; log.Debug(this.ToString()); } ~Modbus() { } public void Initialize() { if (modbusCommonCfg.DebugLevel == Entities.DebugMode.Simulate) { log.FatalFormat("Simulated device {0}", ToString()); return; } string comPortName = "COM" + modbusCommonCfg.ComPortNr.ToString(); serialPort = new SerialPort(comPortName, modbusCommonCfg.BaudRate, modbusCommonCfg.Parity, modbusCommonCfg.DataBits, modbusCommonCfg.StopBits); serialPort.Handshake = modbusCommonCfg.Handshake; serialPort.Open(); stopWorkerThread = false; workerThread = new Thread(Worker); workerThread.Start(); log.FatalFormat("Successfully initialized device {0}", ToString()); } /// /// Send a modbus message. /// This function calculates and overwrites the last 2 bytes /// of the message - CRC as specified in Modbus specification. /// /// Message incl CRC, CRC bytes dont have to be set public void SendMessage(byte[] message) { if (modbusCommonCfg.DebugLevel == Entities.DebugMode.Simulate) return; Telegram.UpdateTelegramCRC(message); log.Debug(Telegram.LogTelegram("Sending message ", message)); serialPort.Write(message, 0, message.Length); } void Worker() { while (!stopWorkerThread) { Thread.Sleep(250); if (stopWorkerThread) break; int nrBytes = serialPort.BytesToRead; if (nrBytes > 0) { char[] buffer = new char[nrBytes]; serialPort.Read(buffer, 0, nrBytes); string s = Telegram.LogTelegram("Received: ", new string(buffer)); /// ODO: Add handler //OnQuidoReceived(this, new QuidoReceivedEventArgs(s)); } } } /// Run this device public void RunDeviceBefore() { } /// Run this device public void RunDeviceAfter() { } /// Stop this device public void StopDevice() { if (serialPort != null) { stopWorkerThread = true; workerThread.Join(2000); serialPort.Close(); } } } }