public int Start() { //MessageBox.Show("Starting Modbus station " + name, "Info"); buffers.Clear(); if (channels.Count > 0) { //// Data Space analyse channels.Sort(channels[0].Compare); foreach (ModbusChannelImp ch in channels) { bool found = false; foreach (ModbusBuffer buf in buffers) { if (ch.ModbusDataType == buf.ModbusDataType) { int mult; if (ch.ModbusDataType == ModbusDataType.Input || ch.ModbusDataType == ModbusDataType.Coil) { mult = 8; } else { mult = 1; } if (((ch.ModbusDataAddress - buf.lastAddress) < 4 * mult) && (buf.numInputs < 110 * mult)) // Optimization - "holes" in address space less than 4 bytes // will be included in one read until max frame 2*110+4 is reached { buf.lastAddress = ch.ModbusDataAddress; buf.numInputs = (ushort)(buf.lastAddress - buf.startAddress + 1); buf.channels.Add(ch); found = true; } } } if (!found) { // Set up a new buffer ModbusBuffer buf = new ModbusBuffer(); buf.numInputs = 1; buf.startAddress = buf.lastAddress = ch.ModbusDataAddress; buf.ModbusDataType = ch.ModbusDataType; buf.channels.Add(ch); buffers.Add(buf); } } //// Run Thread channelUpdaterThread = new Thread(new ParameterizedThreadStart(ChannelUpdaterThreadProc)); channelUpdaterThread.Start(this); return(0); } return(1); }
protected void ReadBuffer(ModbusBaseClientStation self, IModbusMaster master, ModbusBuffer buf) { try { ushort[] registers; byte[] adr; bool[] inputs; if (buf.pauseCounter == 0) { ushort startAddress = buf.startAddress; ushort numInputs = buf.numInputs; switch (buf.ModbusDataType) { case ModbusDataTypeEx.InputRegister: case ModbusDataTypeEx.HoldingRegister: if (buf.ModbusDataType == ModbusDataTypeEx.InputRegister) { registers = master.ReadInputRegisters(buf.slaveId, startAddress, numInputs); } else { registers = master.ReadHoldingRegisters(buf.slaveId, startAddress, numInputs); } DateTime dt = DateTime.Now; int iresult = 0; uint uresult = 0; double fresult = 0.0; foreach (ModbusChannelImp ch in buf.channels) { switch (ch.DeviceDataType) { case ModbusDeviceDataType.Int: adr = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress]); switch (ch.ConversionType) { case ModbusConversionType.SwapBytes: byte tmp = adr[0]; adr[0] = adr[1]; adr[1] = tmp; iresult = BitConverter.ToInt16(adr, 0); break; default: iresult = BitConverter.ToInt16(adr, 0); break; } if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Int32) { ch.DoUpdate(iresult, dt, ChannelStatusFlags.Good); } else if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Double) { ch.DoUpdate((double)(ch.K * iresult + ch.D), dt, ChannelStatusFlags.Good); } else if (self.LoggingLevel >= ModbusLog.logWarnings) { Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert, self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString())); } break; case ModbusDeviceDataType.UInt: adr = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress]); switch (ch.ConversionType) { case ModbusConversionType.SwapBytes: byte tmp = adr[0]; adr[0] = adr[1]; adr[1] = tmp; uresult = BitConverter.ToUInt16(adr, 0); break; default: uresult = BitConverter.ToUInt16(adr, 0); break; } if (ch.ModbusFs2InternalType == ModbusFs2InternalType.UInt32) { ch.DoUpdate(uresult, dt, ChannelStatusFlags.Good); } else if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Double) { ch.DoUpdate((double)(ch.K * uresult + ch.D), dt, ChannelStatusFlags.Good); } else if (self.LoggingLevel >= ModbusLog.logWarnings) { Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert, self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString())); } break; case ModbusDeviceDataType.DInt: byte[] adr0 = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress]); byte[] adr1 = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress + 1]); byte[] res = new byte[4]; res = self.SwapBytesIn(adr0, adr1, ch.ConversionType); iresult = BitConverter.ToInt32(res, 0); if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Int32) { ch.DoUpdate(iresult, dt, ChannelStatusFlags.Good); } else if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Double) { ch.DoUpdate((double)(ch.K * iresult + ch.D), dt, ChannelStatusFlags.Good); } else if (self.LoggingLevel >= ModbusLog.logWarnings) { Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert, self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString())); } break; case ModbusDeviceDataType.DUInt: adr0 = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress]); adr1 = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress + 1]); res = self.SwapBytesIn(adr0, adr1, ch.ConversionType); uresult = BitConverter.ToUInt32(res, 0); if (ch.ModbusFs2InternalType == ModbusFs2InternalType.UInt32) { ch.DoUpdate(uresult, dt, ChannelStatusFlags.Good); } else if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Double) { ch.DoUpdate((double)(ch.K * uresult + ch.D), dt, ChannelStatusFlags.Good); } else if (self.LoggingLevel >= ModbusLog.logWarnings) { Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert, self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString())); } break; case ModbusDeviceDataType.Float: adr0 = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress]); adr1 = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress + 1]); res = self.SwapBytesIn(adr0, adr1, ch.ConversionType); fresult = BitConverter.ToSingle(res, 0); if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Double) { ch.DoUpdate((double)(ch.K * fresult + ch.D), dt, ChannelStatusFlags.Good); } else if (self.LoggingLevel >= ModbusLog.logWarnings) { Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert, self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString())); } break; case ModbusDeviceDataType.Bool: bool bit = (registers[ch.ModbusDataAddress - buf.startAddress] & (0x01 << ch.BitIndex)) > 0; if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Boolean) { ch.DoUpdate(bit, dt, ChannelStatusFlags.Good); } else if (self.LoggingLevel >= ModbusLog.logWarnings) { Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert, self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString())); } break; case ModbusDeviceDataType.String: byte[] str = new byte[2 * ch.DeviceDataLen]; Decoder ascii = (new ASCIIEncoding()).GetDecoder(); int bytesUsed = 0; int charsUsed = 0; bool completed = false; int j = 0; // Conversion strategy: FIRST NONPRINTABLE CHARACTER (ORD < 32) BREAKS CONVERSION, string consists of printables converted before for (int i = 0; i < ch.DeviceDataLen; i++) { byte[] word = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress + i]); if (ch.ConversionType == ModbusConversionType.SwapBytes) { if (word[1] < 32) { break; // nonprintable character } str[j++] = word[1]; if (word[0] < 32) { break; // nonprintable character } str[j++] = word[0]; } else { if (word[0] < 32) { break; // nonprintable character } str[j++] = word[0]; if (word[1] < 32) { break; // nonprintable character } str[j++] = word[1]; //Array.Copy(BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress + i]), 0, str, 2 * i, 2); } } string sresult; if (j > 0) { char[] chars = new char[j]; ascii.Convert(str, 0, j, chars, 0, j, true, out bytesUsed, out charsUsed, out completed); sresult = new String(chars); } else { sresult = ""; } if (ch.ModbusFs2InternalType == ModbusFs2InternalType.String) { ch.DoUpdate(sresult, dt, ChannelStatusFlags.Good); } else if (self.LoggingLevel >= ModbusLog.logWarnings) { Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert, self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString())); } break; } } break; case ModbusDataTypeEx.Coil: case ModbusDataTypeEx.Input: if (buf.ModbusDataType == ModbusDataTypeEx.Coil) { inputs = master.ReadCoils(buf.slaveId, startAddress, numInputs); } else { inputs = master.ReadInputs(buf.slaveId, startAddress, numInputs); } dt = DateTime.Now; foreach (ModbusChannelImp ch in buf.channels) { if (ch.ModbusFs2InternalType == ModbusFs2InternalType.UInt32) { uint val = (uint)(inputs[ch.ModbusDataAddress - buf.startAddress] ? 1 : 0); ch.DoUpdate(val, dt, ChannelStatusFlags.Good); } else if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Boolean) { bool val = inputs[ch.ModbusDataAddress - buf.startAddress]; ch.DoUpdate(val, dt, ChannelStatusFlags.Good); } else if (self.LoggingLevel >= ModbusLog.logWarnings) { Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert, self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString())); } } break; } // Case if (self.failures.ContainsKey(buf.slaveId)) { // failure signal defined self.failures[buf.slaveId].Value = false; } } // If else { buf.pauseCounter--; } } // Try catch (Modbus.SlaveException e) { buf.pauseCounter = self.FailedCount; if (self.failures.ContainsKey(buf.slaveId)) { // failure signal defined self.failures[buf.slaveId].Value = true; } foreach (ModbusChannelImp ch in buf.channels) { ch.StatusFlags = ChannelStatusFlags.Bad; } if (self.LoggingLevel >= ModbusLog.logWarnings) { Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrReceive, self.Name, buf.slaveId, buf.ModbusDataType.ToString(), buf.startAddress, buf.numInputs, e.Message)); } } catch (TimeoutException e) { buf.pauseCounter = self.FailedCount; if (self.failures.ContainsKey(buf.slaveId)) { // failure signal defined self.failures[buf.slaveId].Value = true; } foreach (ModbusChannelImp ch in buf.channels) { ch.StatusFlags = ChannelStatusFlags.Bad; } if (self.LoggingLevel >= ModbusLog.logWarnings) { Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrReceive, self.Name, buf.slaveId, buf.ModbusDataType.ToString(), buf.startAddress, buf.numInputs, e.Message)); } } }
public int Start() { //MessageBox.Show("Starting Modbus station " + name, "Info"); if (!StationActive) { return(1); } buffers.Clear(); failures.Clear(); sendQueue.Clear(); if (channels.Count > 0) { //// Data Space analyse channels.Sort(channels[0].Compare); foreach (ModbusChannelImp ch in channels) { if (ch.ModbusReadWrite != ModbusReadWrite.WriteOnly && ch.ModbusDataType != ModbusDataTypeEx.DeviceFailureInfo) { bool found = false; foreach (ModbusBuffer buf in buffers) { if (ch.SlaveId == buf.slaveId && ch.ModbusDataType == buf.ModbusDataType) { int mult; if (ch.ModbusDataType == ModbusDataTypeEx.Input || ch.ModbusDataType == ModbusDataTypeEx.Coil) { mult = 16; } else { mult = 1; } if (((ch.ModbusDataAddress - buf.lastAddress) < 4 * mult) && ((buf.lastAddress - buf.startAddress + ch.DeviceDataLen) < 120 * mult)) // Optimization - "holes" in address space less than 4 words // will be included in one read until max frame 2*120 bytes is reached { buf.lastAddress = (ushort)((ch.ModbusDataAddress + ch.DeviceDataLen - 1) > buf.lastAddress ? ch.ModbusDataAddress + ch.DeviceDataLen - 1 : buf.lastAddress); buf.numInputs = (ushort)((buf.lastAddress - buf.startAddress + ch.DeviceDataLen) > buf.numInputs ? buf.lastAddress - buf.startAddress + ch.DeviceDataLen : buf.numInputs); buf.channels.Add(ch); ch.StatusFlags = ChannelStatusFlags.Bad; found = true; } } } if (!found) { // Set up a new buffer ModbusBuffer buf = new ModbusBuffer(); buf.slaveId = ch.SlaveId; buf.numInputs = ch.DeviceDataLen; buf.startAddress = ch.ModbusDataAddress; buf.lastAddress = (ushort)(ch.ModbusDataAddress + ch.DeviceDataLen - 1); buf.ModbusDataType = ch.ModbusDataType; buf.channels.Add(ch); ch.StatusFlags = ChannelStatusFlags.Bad; buf.pauseCounter = 0; buffers.Add(buf); } } if (ch.ModbusDataType == ModbusDataTypeEx.DeviceFailureInfo) { if (failures.ContainsKey(ch.SlaveId)) { // failure signal already defined, parameterization error if (LoggingLevel >= ModbusLog.logErrors) { Env.Current.Logger.LogError(string.Format(StringConstants.ErrFailureTwice, this.Name, failures[ch.SlaveId].Name, ch.Name)); } } else { failures.Add(ch.SlaveId, ch); ch.Value = true; } } } return(0); } return(1); }