Advertisement
Guest User

Untitled

a guest
Feb 26th, 2018
313
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 121.78 KB | None | 0 0
  1. using System;
  2. using Ventuz.Kernel;
  3. using System.Net.Sockets;
  4. using System.Net;
  5. using System.IO.Ports;
  6. using System.Reflection;
  7. using System.Collections.Generic;
  8. using System.Text;
  9. using EasyModbus;
  10. using System.Runtime.Serialization;
  11.  
  12. using System.Threading;
  13.  
  14. public class Script : ScriptBase, System.IDisposable
  15. {
  16.  
  17. ModbusClient modbus;
  18.  
  19.  
  20. private bool changed;
  21.  
  22. public Script()
  23. {
  24.  
  25.  
  26. setTimeout(() => {
  27. OnConnect(0);
  28. }, 500);
  29.  
  30. }
  31.  
  32.  
  33.  
  34. public override void Validate()
  35. {
  36.  
  37.  
  38. }
  39.  
  40.  
  41. List<double> latestDistancesPerFrame = new List<double>();
  42.  
  43. public override bool Generate()
  44. {
  45. if (changed)
  46. {
  47. changed = false;
  48. return true;
  49. }
  50.  
  51.  
  52. setTimeout(() => {
  53.  
  54.  
  55. // read modbus position
  56. if(modbus != null && modbus.Connected){
  57.  
  58. try {
  59. var posVal = modbus.ReadHoldingRegisters(0, 1)[0];
  60. if(currentPosition > 150 && Math.Abs(posVal - currentPosition) > 50){
  61. // we dont beleive in this new posValue
  62.  
  63. // if we have info about prev movement
  64. if(latestDistancesPerFrame.Count > 0){
  65. // predict where current pos will be
  66. // calculate average distance per frame
  67. double sum = 0;
  68. foreach(var val in latestDistancesPerFrame){
  69. sum += val;
  70. }
  71.  
  72. var avgSpeed = sum / latestDistancesPerFrame.Count;
  73.  
  74. // apply distance change per frame
  75. currentPosition += (int)avgSpeed;
  76. }
  77.  
  78.  
  79. }else{
  80. // add distance per frame to latest distances
  81. latestDistancesPerFrame.Add(posVal - currentPosition);
  82.  
  83. if(latestDistancesPerFrame.Count > 10){
  84. latestDistancesPerFrame.RemoveAt(0);
  85. }
  86.  
  87. currentPosition = posVal;
  88. }
  89.  
  90.  
  91. ErrorCode = modbus.ReadHoldingRegisters(10, 1)[0];
  92.  
  93. //currentPosition = Math.Max(currentPosition, ErrorCode);
  94.  
  95.  
  96. changed = true;
  97. }catch{
  98.  
  99. }
  100. }
  101.  
  102.  
  103. // return true;
  104.  
  105.  
  106.  
  107. }, 500);
  108.  
  109.  
  110.  
  111. return true;
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118. }
  119.  
  120. public bool OnSetPosition(int arg)
  121. {
  122. if(!modbus.Connected){
  123. VLog.Info("Failed to set position cause modbus is not connected");
  124. }
  125.  
  126.  
  127. modbus.WriteSingleRegister(1, positionValue);
  128. modbus.WriteSingleCoil(6, true);
  129. modbus.WriteSingleCoil(6, false);
  130.  
  131. return false;
  132. }
  133.  
  134. public bool OnStop(int arg)
  135. {
  136. if(!modbus.Connected){
  137. VLog.Info("Failed cause modbus is not connected");
  138. }
  139.  
  140.  
  141. modbus.WriteSingleCoil(7, true);
  142. modbus.WriteSingleCoil(7, false);
  143.  
  144. return false;
  145. }
  146.  
  147. // This Method is called if the function/method SetSpeed is invoked by the user or a bound event.
  148. // Return true, if this component has to be revalidated!
  149. public bool OnSetSpeed(int arg)
  150. {
  151. if(!modbus.Connected){
  152. VLog.Info("Failed cause modbus is not connected");
  153. }
  154.  
  155. modbus.WriteSingleRegister(2, (int) Mathf.Clamp(speedValue, 10, 300));
  156.  
  157. return false;
  158. }
  159.  
  160.  
  161. public bool OnJogLeft(int arg)
  162. {
  163. if(!modbus.Connected){
  164. VLog.Info("Failed cause modbus is not connected");
  165. }
  166.  
  167. modbus.WriteSingleCoil(3, true);
  168. return false;
  169. }
  170.  
  171. public bool OnJogRight(int arg)
  172. {
  173. if(!modbus.Connected){
  174. VLog.Info("Failed cause modbus is not connected");
  175. }
  176. modbus.WriteSingleCoil(4, true);
  177. return false;
  178. }
  179.  
  180. public bool OnHomingCommand(int arg)
  181. {
  182. if(!modbus.Connected){
  183. VLog.Info("Failed cause modbus is not connected");
  184. }
  185.  
  186. modbus.WriteSingleCoil(5, true);
  187. modbus.WriteSingleCoil(5, false);
  188.  
  189. return false;
  190. }
  191.  
  192. public virtual void Dispose()
  193. {
  194. OnDisconnect(0);
  195. }
  196.  
  197. // This Method is called if the function/method Connect is invoked by the user or a bound event.
  198. // Return true, if this component has to be revalidated!
  199. public bool OnConnect(int arg)
  200. {
  201.  
  202. connectionStatus = "Connecting";
  203.  
  204. setTimeout(() => {
  205.  
  206. try{
  207. modbus = new ModbusClient(IP, port);
  208. modbus.Connect();
  209. connectionStatus = "Connected";
  210. }catch(Exception ex){
  211. connectionStatus = "Exception";
  212. VLog.Info("EXCEPTION: " + ex.Message + " " + ex.StackTrace);
  213. }
  214. }, 0);
  215.  
  216.  
  217. return false;
  218. }
  219.  
  220. // This Method is called if the function/method Disconnect is invoked by the user or a bound event.
  221. // Return true, if this component has to be revalidated!
  222. public bool OnDisconnect(int arg)
  223. {
  224. if(modbus != null){
  225. modbus.Disconnect();
  226. }
  227.  
  228. connectionStatus = "Disconnected";
  229. return false;
  230. }
  231.  
  232.  
  233.  
  234.  
  235.  
  236. // CONVERSIONS
  237.  
  238.  
  239.  
  240. // UTILS
  241.  
  242. public void setTimeout(Action TheAction, int Timeout)
  243. {
  244. Thread t = new Thread(
  245. () =>
  246. {
  247. Thread.Sleep(Timeout);
  248. TheAction.Invoke();
  249. }
  250. );
  251. t.Start();
  252. }
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281. }
  282.  
  283.  
  284. static class Mathf {
  285. public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
  286. {
  287. if (val.CompareTo(min) < 0) return min;
  288. else if(val.CompareTo(max) > 0) return max;
  289. else return val;
  290. }
  291. }
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300. // ModBusClient.cs
  301.  
  302.  
  303. /// <summary>
  304. /// Implements a ModbusClient.
  305. /// </summary>
  306. public partial class ModbusClient
  307. {
  308. public enum RegisterOrder { LowHigh = 0, HighLow = 1 };
  309. private bool debug = false;
  310. private TcpClient tcpClient;
  311. private string ipAddress = "127.0.0.1";
  312. private int port = 502;
  313. private uint transactionIdentifierInternal = 0;
  314. private byte [] transactionIdentifier = new byte[2];
  315. private byte [] protocolIdentifier = new byte[2];
  316. private byte[] crc = new byte[2];
  317. private byte [] length = new byte[2];
  318. private byte unitIdentifier = 0x01;
  319. private byte functionCode;
  320. private byte [] startingAddress = new byte[2];
  321. private byte [] quantity = new byte[2];
  322. private bool udpFlag = false;
  323. private int portOut;
  324. private int baudRate = 9600;
  325. private int connectTimeout = 1000;
  326. public byte[] receiveData;
  327. public byte[] sendData;
  328. private SerialPort serialport;
  329. private Parity parity = Parity.Even;
  330. private StopBits stopBits = StopBits.One;
  331. private bool connected = false;
  332. private bool[] mqttCoilsOldValues;
  333. private bool[] mqttDiscreteInputsOldValues;
  334. private int[] mqttInputRegistersOldValues;
  335. private int[] mqttHoldingRegistersOldValues;
  336. //private EasyModbus2Mqtt easyModbus2Mqtt;
  337. private bool mqttRetainMessages;
  338. public int NumberOfRetries { get; set; }// = 3;
  339. private int countRetries = 0;
  340. string mqttRootTopic = "easymodbusclient";
  341. public string MqttUserName { get; set; }
  342. public string MqttPassword { get; set; }
  343. public bool MqttPushOnChange { get; set;} // = true;
  344.  
  345. public int MqttBrokerPort { get; set; }// = 1883;
  346.  
  347. public delegate void ReceiveDataChanged(object sender);
  348. public event ReceiveDataChanged receiveDataChanged;
  349.  
  350. public delegate void SendDataChanged(object sender);
  351. public event SendDataChanged sendDataChanged;
  352.  
  353. public delegate void ConnectedChanged(object sender);
  354. public event ConnectedChanged connectedChanged;
  355.  
  356. NetworkStream stream;
  357.  
  358. /// <summary>
  359. /// Constructor which determines the Master ip-address and the Master Port.
  360. /// </summary>
  361. /// <param name="ipAddress">IP-Address of the Master device</param>
  362. /// <param name="port">Listening port of the Master device (should be 502)</param>
  363. public ModbusClient(string ipAddress, int port)
  364. {
  365.  
  366. NumberOfRetries = 3;
  367. MqttPushOnChange = true;
  368. MqttBrokerPort = 1883;
  369.  
  370. if (debug) StoreLogData.Instance.Store("EasyModbus library initialized for Modbus-TCP, IPAddress: " + ipAddress + ", Port: " + port, System.DateTime.Now);
  371. #if (!COMMERCIAL)
  372. Console.WriteLine("EasyModbus Client Library Version: " + Assembly.GetExecutingAssembly().GetName().Version.ToString());
  373. Console.WriteLine("Copyright (c) Stefan Rossmann Engineering Solutions");
  374. Console.WriteLine();
  375. #endif
  376. this.ipAddress = ipAddress;
  377. this.port = port;
  378. }
  379.  
  380. /// <summary>
  381. /// Constructor which determines the Serial-Port
  382. /// </summary>
  383. /// <param name="serialPort">Serial-Port Name e.G. "COM1"</param>
  384. public ModbusClient(string serialPort)
  385. {
  386. if (debug) StoreLogData.Instance.Store("EasyModbus library initialized for Modbus-RTU, COM-Port: " + serialPort, System.DateTime.Now);
  387. #if (!COMMERCIAL)
  388. Console.WriteLine("EasyModbus Client Library Version: " + Assembly.GetExecutingAssembly().GetName().Version.ToString());
  389. Console.WriteLine("Copyright (c) Stefan Rossmann Engineering Solutions");
  390. Console.WriteLine();
  391. #endif
  392. this.serialport = new SerialPort();
  393. serialport.PortName = serialPort;
  394. serialport.BaudRate = baudRate;
  395. serialport.Parity = parity;
  396. serialport.StopBits = stopBits;
  397. serialport.WriteTimeout = 10000;
  398. serialport.ReadTimeout = connectTimeout;
  399.  
  400. serialport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
  401. }
  402.  
  403. /// <summary>
  404. /// Parameterless constructor
  405. /// </summary>
  406. public ModbusClient()
  407. {
  408. if (debug) StoreLogData.Instance.Store("EasyModbus library initialized for Modbus-TCP", System.DateTime.Now);
  409. #if (!COMMERCIAL)
  410. Console.WriteLine("EasyModbus Client Library Version: " + Assembly.GetExecutingAssembly().GetName().Version.ToString());
  411. Console.WriteLine("Copyright (c) Stefan Rossmann Engineering Solutions");
  412. Console.WriteLine();
  413. #endif
  414. }
  415.  
  416. /// <summary>
  417. /// Establish connection to Master device in case of Modbus TCP. Opens COM-Port in case of Modbus RTU
  418. /// </summary>
  419. public void Connect()
  420. {
  421. if (serialport != null)
  422. {
  423. if (!serialport.IsOpen)
  424. {
  425. if (debug) StoreLogData.Instance.Store("Open Serial port " + serialport.PortName, System.DateTime.Now);
  426. serialport.BaudRate = baudRate;
  427. serialport.Parity = parity;
  428. serialport.StopBits = stopBits;
  429. serialport.WriteTimeout = 10000;
  430. serialport.ReadTimeout = connectTimeout;
  431. serialport.Open();
  432. connected = true;
  433.  
  434.  
  435. }
  436. if (connectedChanged != null)
  437. try
  438. {
  439. connectedChanged(this);
  440. }
  441. catch
  442. {
  443.  
  444. }
  445. return;
  446. }
  447. if (!udpFlag)
  448. {
  449. if (debug) StoreLogData.Instance.Store("Open TCP-Socket, IP-Address: " + ipAddress + ", Port: " + port, System.DateTime.Now);
  450. tcpClient = new TcpClient();
  451. var result = tcpClient.BeginConnect(ipAddress, port, null, null);
  452. var success = result.AsyncWaitHandle.WaitOne(connectTimeout);
  453. if (!success)
  454. {
  455. throw new EasyModbus.Exceptions.ConnectionException("connection timed out");
  456. }
  457. tcpClient.EndConnect(result);
  458.  
  459. //tcpClient = new TcpClient(ipAddress, port);
  460. stream = tcpClient.GetStream();
  461. stream.ReadTimeout = connectTimeout;
  462. connected = true;
  463. }
  464. else
  465. {
  466. tcpClient = new TcpClient();
  467. connected = true;
  468. }
  469. if (connectedChanged != null)
  470. try
  471. {
  472. connectedChanged(this);
  473. }
  474. catch
  475. {
  476.  
  477. }
  478. }
  479.  
  480. /// <summary>
  481. /// Establish connection to Master device in case of Modbus TCP.
  482. /// </summary>
  483. public void Connect(string ipAddress, int port)
  484. {
  485. if (!udpFlag)
  486. {
  487. if (debug) StoreLogData.Instance.Store("Open TCP-Socket, IP-Address: " + ipAddress + ", Port: " + port, System.DateTime.Now);
  488. tcpClient = new TcpClient();
  489. var result = tcpClient.BeginConnect(ipAddress, port, null, null);
  490. var success = result.AsyncWaitHandle.WaitOne(connectTimeout);
  491. if (!success)
  492. {
  493. throw new EasyModbus.Exceptions.ConnectionException("connection timed out");
  494. }
  495. tcpClient.EndConnect(result);
  496.  
  497. //tcpClient = new TcpClient(ipAddress, port);
  498. stream = tcpClient.GetStream();
  499. stream.ReadTimeout = connectTimeout;
  500. connected = true;
  501. }
  502. else
  503. {
  504. tcpClient = new TcpClient();
  505. connected = true;
  506. }
  507.  
  508. if (connectedChanged != null)
  509. connectedChanged(this);
  510. }
  511.  
  512. /// <summary>
  513. /// Converts two ModbusRegisters to Float - Example: EasyModbus.ModbusClient.ConvertRegistersToFloat(modbusClient.ReadHoldingRegisters(19,2))
  514. /// </summary>
  515. /// <param name="registers">Two Register values received from Modbus</param>
  516. /// <returns>Connected float value</returns>
  517. public static float ConvertRegistersToFloat(int[] registers)
  518. {
  519. if (registers.Length != 2)
  520. throw new ArgumentException("Input Array length invalid - Array langth must be '2'");
  521. int highRegister = registers[1];
  522. int lowRegister = registers[0];
  523. byte[] highRegisterBytes = BitConverter.GetBytes(highRegister);
  524. byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister);
  525. byte[] floatBytes = {
  526. lowRegisterBytes[0],
  527. lowRegisterBytes[1],
  528. highRegisterBytes[0],
  529. highRegisterBytes[1]
  530. };
  531. return BitConverter.ToSingle(floatBytes, 0);
  532. }
  533.  
  534. /// <summary>
  535. /// Converts two ModbusRegisters to Float, Registers can by swapped
  536. /// </summary>
  537. /// <param name="registers">Two Register values received from Modbus</param>
  538. /// <param name="registerOrder">Desired Word Order (Low Register first or High Register first</param>
  539. /// <returns>Connected float value</returns>
  540. public static float ConvertRegistersToFloat(int[] registers, RegisterOrder registerOrder)
  541. {
  542. int [] swappedRegisters = {registers[0],registers[1]};
  543. if (registerOrder == RegisterOrder.HighLow)
  544. swappedRegisters = new int[] {registers[1],registers[0]};
  545. return ConvertRegistersToFloat(swappedRegisters);
  546. }
  547.  
  548. /// <summary>
  549. /// Converts two ModbusRegisters to 32 Bit Integer value
  550. /// </summary>
  551. /// <param name="registers">Two Register values received from Modbus</param>
  552. /// <returns>Connected 32 Bit Integer value</returns>
  553. public static Int32 ConvertRegistersToInt(int[] registers)
  554. {
  555. if (registers.Length != 2)
  556. throw new ArgumentException("Input Array length invalid - Array langth must be '2'");
  557. int highRegister = registers[1];
  558. int lowRegister = registers[0];
  559. byte[] highRegisterBytes = BitConverter.GetBytes(highRegister);
  560. byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister);
  561. byte[] doubleBytes = {
  562. lowRegisterBytes[0],
  563. lowRegisterBytes[1],
  564. highRegisterBytes[0],
  565. highRegisterBytes[1]
  566. };
  567. return BitConverter.ToInt32(doubleBytes, 0);
  568. }
  569.  
  570. /// <summary>
  571. /// Converts two ModbusRegisters to 32 Bit Integer Value - Registers can be swapped
  572. /// </summary>
  573. /// <param name="registers">Two Register values received from Modbus</param>
  574. /// <param name="registerOrder">Desired Word Order (Low Register first or High Register first</param>
  575. /// <returns>Connecteds 32 Bit Integer value</returns>
  576. public static Int32 ConvertRegistersToInt(int[] registers, RegisterOrder registerOrder)
  577. {
  578. int[] swappedRegisters = { registers[0], registers[1] };
  579. if (registerOrder == RegisterOrder.HighLow)
  580. swappedRegisters = new int[] { registers[1], registers[0] };
  581. return ConvertRegistersToInt(swappedRegisters);
  582. }
  583.  
  584. /// <summary>
  585. /// Convert four 16 Bit Registers to 64 Bit Integer value Register Order "LowHigh": Reg0: Low Word.....Reg3: High Word, "HighLow": Reg0: High Word.....Reg3: Low Word
  586. /// </summary>
  587. /// <param name="registers">four Register values received from Modbus</param>
  588. /// <returns>64 bit value</returns>
  589. public static Int64 ConvertRegistersToLong(int[] registers)
  590. {
  591. if (registers.Length != 4)
  592. throw new ArgumentException("Input Array length invalid - Array langth must be '4'");
  593. int highRegister = registers[3];
  594. int highLowRegister = registers[2];
  595. int lowHighRegister = registers[1];
  596. int lowRegister = registers[0];
  597. byte[] highRegisterBytes = BitConverter.GetBytes(highRegister);
  598. byte[] highLowRegisterBytes = BitConverter.GetBytes(highLowRegister);
  599. byte[] lowHighRegisterBytes = BitConverter.GetBytes(lowHighRegister);
  600. byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister);
  601. byte[] longBytes = {
  602. lowRegisterBytes[0],
  603. lowRegisterBytes[1],
  604. lowHighRegisterBytes[0],
  605. lowHighRegisterBytes[1],
  606. highLowRegisterBytes[0],
  607. highLowRegisterBytes[1],
  608. highRegisterBytes[0],
  609. highRegisterBytes[1]
  610. };
  611. return BitConverter.ToInt64(longBytes, 0);
  612. }
  613.  
  614. /// <summary>
  615. /// Convert four 16 Bit Registers to 64 Bit Integer value - Registers can be swapped
  616. /// </summary>
  617. /// <param name="registers">four Register values received from Modbus</param>
  618. /// <param name="registerOrder">Desired Word Order (Low Register first or High Register first</param>
  619. /// <returns>Connected 64 Bit Integer value</returns>
  620. public static Int64 ConvertRegistersToLong(int[] registers, RegisterOrder registerOrder)
  621. {
  622. if (registers.Length != 4)
  623. throw new ArgumentException("Input Array length invalid - Array langth must be '4'");
  624. int[] swappedRegisters = { registers[0], registers[1], registers[2], registers[3] };
  625. if (registerOrder == RegisterOrder.HighLow)
  626. swappedRegisters = new int[] { registers[3], registers[2], registers[1], registers[0] };
  627. return ConvertRegistersToLong(swappedRegisters);
  628. }
  629.  
  630. /// <summary>
  631. /// Convert four 16 Bit Registers to 64 Bit double prec. value Register Order "LowHigh": Reg0: Low Word.....Reg3: High Word, "HighLow": Reg0: High Word.....Reg3: Low Word
  632. /// </summary>
  633. /// <param name="registers">four Register values received from Modbus</param>
  634. /// <returns>64 bit value</returns>
  635. public static double ConvertRegistersToDouble(int[] registers)
  636. {
  637. if (registers.Length != 4)
  638. throw new ArgumentException("Input Array length invalid - Array langth must be '4'");
  639. int highRegister = registers[3];
  640. int highLowRegister = registers[2];
  641. int lowHighRegister = registers[1];
  642. int lowRegister = registers[0];
  643. byte[] highRegisterBytes = BitConverter.GetBytes(highRegister);
  644. byte[] highLowRegisterBytes = BitConverter.GetBytes(highLowRegister);
  645. byte[] lowHighRegisterBytes = BitConverter.GetBytes(lowHighRegister);
  646. byte[] lowRegisterBytes = BitConverter.GetBytes(lowRegister);
  647. byte[] longBytes = {
  648. lowRegisterBytes[0],
  649. lowRegisterBytes[1],
  650. lowHighRegisterBytes[0],
  651. lowHighRegisterBytes[1],
  652. highLowRegisterBytes[0],
  653. highLowRegisterBytes[1],
  654. highRegisterBytes[0],
  655. highRegisterBytes[1]
  656. };
  657. return BitConverter.ToDouble(longBytes, 0);
  658. }
  659.  
  660. /// <summary>
  661. /// Convert four 16 Bit Registers to 64 Bit double prec. value - Registers can be swapped
  662. /// </summary>
  663. /// <param name="registers">four Register values received from Modbus</param>
  664. /// <param name="registerOrder">Desired Word Order (Low Register first or High Register first</param>
  665. /// <returns>Connected double prec. float value</returns>
  666. public static double ConvertRegistersToDouble(int[] registers, RegisterOrder registerOrder)
  667. {
  668. if (registers.Length != 4)
  669. throw new ArgumentException("Input Array length invalid - Array langth must be '4'");
  670. int[] swappedRegisters = { registers[0], registers[1], registers[2], registers[3] };
  671. if (registerOrder == RegisterOrder.HighLow)
  672. swappedRegisters = new int[] { registers[3], registers[2], registers[1], registers[0] };
  673. return ConvertRegistersToDouble(swappedRegisters);
  674. }
  675.  
  676. /// <summary>
  677. /// Converts float to two ModbusRegisters - Example: modbusClient.WriteMultipleRegisters(24, EasyModbus.ModbusClient.ConvertFloatToTwoRegisters((float)1.22));
  678. /// </summary>
  679. /// <param name="floatValue">Float value which has to be converted into two registers</param>
  680. /// <returns>Register values</returns>
  681. public static int[] ConvertFloatToRegisters(float floatValue)
  682. {
  683. byte[] floatBytes = BitConverter.GetBytes(floatValue);
  684. byte[] highRegisterBytes =
  685. {
  686. floatBytes[2],
  687. floatBytes[3],
  688. 0,
  689. 0
  690. };
  691. byte[] lowRegisterBytes =
  692. {
  693.  
  694. floatBytes[0],
  695. floatBytes[1],
  696. 0,
  697. 0
  698. };
  699. int[] returnValue =
  700. {
  701. BitConverter.ToInt32(lowRegisterBytes, 0),
  702. BitConverter.ToInt32(highRegisterBytes, 0)
  703. };
  704. return returnValue;
  705. }
  706.  
  707. /// <summary>
  708. /// Converts float to two ModbusRegisters Registers - Registers can be swapped
  709. /// </summary>
  710. /// <param name="floatValue">Float value which has to be converted into two registers</param>
  711. /// <param name="registerOrder">Desired Word Order (Low Register first or High Register first</param>
  712. /// <returns>Register values</returns>
  713. public static int[] ConvertFloatToRegisters(float floatValue, RegisterOrder registerOrder)
  714. {
  715. int[] registerValues = ConvertFloatToRegisters(floatValue);
  716. int[] returnValue = registerValues;
  717. if (registerOrder == RegisterOrder.HighLow)
  718. returnValue = new Int32[] { registerValues[1], registerValues[0] };
  719. return returnValue;
  720. }
  721.  
  722. /// <summary>
  723. /// Converts 32 Bit Value to two ModbusRegisters
  724. /// </summary>
  725. /// <param name="intValue">Int value which has to be converted into two registers</param>
  726. /// <returns>Register values</returns>
  727. public static int[] ConvertIntToRegisters(Int32 intValue)
  728. {
  729. byte[] doubleBytes = BitConverter.GetBytes(intValue);
  730. byte[] highRegisterBytes =
  731. {
  732. doubleBytes[2],
  733. doubleBytes[3],
  734. 0,
  735. 0
  736. };
  737. byte[] lowRegisterBytes =
  738. {
  739.  
  740. doubleBytes[0],
  741. doubleBytes[1],
  742. 0,
  743. 0
  744. };
  745. int[] returnValue =
  746. {
  747. BitConverter.ToInt32(lowRegisterBytes, 0),
  748. BitConverter.ToInt32(highRegisterBytes, 0)
  749. };
  750. return returnValue;
  751. }
  752.  
  753. /// <summary>
  754. /// Converts 32 Bit Value to two ModbusRegisters Registers - Registers can be swapped
  755. /// </summary>
  756. /// <param name="intValue">Double value which has to be converted into two registers</param>
  757. /// <param name="registerOrder">Desired Word Order (Low Register first or High Register first</param>
  758. /// <returns>Register values</returns>
  759. public static int[] ConvertIntToRegisters(Int32 intValue, RegisterOrder registerOrder)
  760. {
  761. int[] registerValues = ConvertIntToRegisters(intValue);
  762. int[] returnValue = registerValues;
  763. if (registerOrder == RegisterOrder.HighLow)
  764. returnValue = new Int32[] { registerValues[1], registerValues[0] };
  765. return returnValue;
  766. }
  767.  
  768. /// <summary>
  769. /// Converts 64 Bit Value to four ModbusRegisters
  770. /// </summary>
  771. /// <param name="longValue">long value which has to be converted into four registers</param>
  772. /// <returns>Register values</returns>
  773. public static int[] ConvertLongToRegisters(Int64 longValue)
  774. {
  775. byte[] longBytes = BitConverter.GetBytes(longValue);
  776. byte[] highRegisterBytes =
  777. {
  778. longBytes[6],
  779. longBytes[7],
  780. 0,
  781. 0
  782. };
  783. byte[] highLowRegisterBytes =
  784. {
  785. longBytes[4],
  786. longBytes[5],
  787. 0,
  788. 0
  789. };
  790. byte[] lowHighRegisterBytes =
  791. {
  792. longBytes[2],
  793. longBytes[3],
  794. 0,
  795. 0
  796. };
  797. byte[] lowRegisterBytes =
  798. {
  799.  
  800. longBytes[0],
  801. longBytes[1],
  802. 0,
  803. 0
  804. };
  805. int[] returnValue =
  806. {
  807. BitConverter.ToInt32(lowRegisterBytes, 0),
  808. BitConverter.ToInt32(lowHighRegisterBytes, 0),
  809. BitConverter.ToInt32(highLowRegisterBytes, 0),
  810. BitConverter.ToInt32(highRegisterBytes, 0)
  811. };
  812. return returnValue;
  813. }
  814.  
  815. /// <summary>
  816. /// Converts 64 Bit Value to four ModbusRegisters - Registers can be swapped
  817. /// </summary>
  818. /// <param name="longValue">long value which has to be converted into four registers</param>
  819. /// <param name="registerOrder">Desired Word Order (Low Register first or High Register first</param>
  820. /// <returns>Register values</returns>
  821. public static int[] ConvertLongToRegisters(Int64 longValue, RegisterOrder registerOrder)
  822. {
  823. int[] registerValues = ConvertLongToRegisters(longValue);
  824. int[] returnValue = registerValues;
  825. if (registerOrder == RegisterOrder.HighLow)
  826. returnValue = new int[] { registerValues[3], registerValues[2], registerValues[1], registerValues[0] };
  827. return returnValue;
  828. }
  829.  
  830. /// <summary>
  831. /// Converts 64 Bit double prec Value to four ModbusRegisters
  832. /// </summary>
  833. /// <param name="doubleValue">double value which has to be converted into four registers</param>
  834. /// <returns>Register values</returns>
  835. public static int[] ConvertDoubleToRegisters(double doubleValue)
  836. {
  837. byte[] doubleBytes = BitConverter.GetBytes(doubleValue);
  838. byte[] highRegisterBytes =
  839. {
  840. doubleBytes[6],
  841. doubleBytes[7],
  842. 0,
  843. 0
  844. };
  845. byte[] highLowRegisterBytes =
  846. {
  847. doubleBytes[4],
  848. doubleBytes[5],
  849. 0,
  850. 0
  851. };
  852. byte[] lowHighRegisterBytes =
  853. {
  854. doubleBytes[2],
  855. doubleBytes[3],
  856. 0,
  857. 0
  858. };
  859. byte[] lowRegisterBytes =
  860. {
  861.  
  862. doubleBytes[0],
  863. doubleBytes[1],
  864. 0,
  865. 0
  866. };
  867. int[] returnValue =
  868. {
  869. BitConverter.ToInt32(lowRegisterBytes, 0),
  870. BitConverter.ToInt32(lowHighRegisterBytes, 0),
  871. BitConverter.ToInt32(highLowRegisterBytes, 0),
  872. BitConverter.ToInt32(highRegisterBytes, 0)
  873. };
  874. return returnValue;
  875. }
  876.  
  877. /// <summary>
  878. /// Converts 64 Bit double prec. Value to four ModbusRegisters - Registers can be swapped
  879. /// </summary>
  880. /// <param name="doubleValue">double value which has to be converted into four registers</param>
  881. /// <param name="registerOrder">Desired Word Order (Low Register first or High Register first</param>
  882. /// <returns>Register values</returns>
  883. public static int[] ConvertDoubleToRegisters(double doubleValue, RegisterOrder registerOrder)
  884. {
  885. int[] registerValues = ConvertDoubleToRegisters(doubleValue);
  886. int[] returnValue = registerValues;
  887. if (registerOrder == RegisterOrder.HighLow)
  888. returnValue = new int[] { registerValues[3], registerValues[2], registerValues[1], registerValues[0] };
  889. return returnValue;
  890. }
  891.  
  892. /// <summary>
  893. /// Converts 16 - Bit Register values to String
  894. /// </summary>
  895. /// <param name="registers">Register array received via Modbus</param>
  896. /// <param name="offset">First Register containing the String to convert</param>
  897. /// <param name="stringLength">number of characters in String (must be even)</param>
  898. /// <returns>Converted String</returns>
  899. public static string ConvertRegistersToString(int[] registers, int offset, int stringLength)
  900. {
  901. byte[] result = new byte[stringLength];
  902. byte[] registerResult = new byte[2];
  903.  
  904. for (int i = 0; i < stringLength / 2; i++)
  905. {
  906. registerResult = BitConverter.GetBytes(registers[offset + i]);
  907. result[i * 2] = registerResult[0];
  908. result[i * 2 + 1] = registerResult[1];
  909. }
  910. return System.Text.Encoding.Default.GetString(result);
  911. }
  912.  
  913. /// <summary>
  914. /// Converts a String to 16 - Bit Registers
  915. /// </summary>
  916. /// <param name="registers">Register array received via Modbus</param>
  917. /// <returns>Converted String</returns>
  918. public static int[] ConvertStringToRegisters(string stringToConvert)
  919. {
  920. byte[] array = System.Text.Encoding.ASCII.GetBytes(stringToConvert);
  921. int[] returnarray = new int[stringToConvert.Length / 2 + stringToConvert.Length % 2];
  922. for (int i = 0; i < returnarray.Length; i++)
  923. {
  924. returnarray[i] = array[i * 2];
  925. if (i * 2 + 1 < array.Length)
  926. {
  927. returnarray[i] = returnarray[i] | ((int) array[i * 2 + 1] << 8);
  928. }
  929. }
  930. return returnarray;
  931. }
  932.  
  933.  
  934. /// <summary>
  935. /// Calculates the CRC16 for Modbus-RTU
  936. /// </summary>
  937. /// <param name="data">Byte buffer to send</param>
  938. /// <param name="numberOfBytes">Number of bytes to calculate CRC</param>
  939. /// <param name="startByte">First byte in buffer to start calculating CRC</param>
  940. public static UInt16 calculateCRC(byte[] data, UInt16 numberOfBytes, int startByte)
  941. {
  942. byte[] auchCRCHi = {
  943. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
  944. 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  945. 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
  946. 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  947. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
  948. 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  949. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
  950. 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  951. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
  952. 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  953. 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
  954. 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  955. 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
  956. 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  957. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
  958. 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  959. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
  960. 0x40
  961. };
  962.  
  963. byte[] auchCRCLo = {
  964. 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
  965. 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
  966. 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
  967. 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
  968. 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
  969. 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
  970. 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
  971. 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
  972. 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
  973. 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
  974. 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
  975. 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
  976. 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
  977. 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
  978. 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
  979. 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
  980. 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
  981. 0x40
  982. };
  983. UInt16 usDataLen = numberOfBytes;
  984. byte uchCRCHi = 0xFF;
  985. byte uchCRCLo = 0xFF;
  986. int i = 0;
  987. int uIndex ;
  988. while (usDataLen > 0)
  989. {
  990. usDataLen--;
  991. if ((i + startByte) < data.Length)
  992. {
  993. uIndex = uchCRCLo ^ data[i + startByte];
  994. uchCRCLo = (byte) (uchCRCHi ^ auchCRCHi[uIndex]);
  995. uchCRCHi = auchCRCLo[uIndex];
  996. }
  997. i++;
  998. }
  999. return (UInt16) ((UInt16) uchCRCHi << 8 | uchCRCLo);
  1000. }
  1001.  
  1002. private bool dataReceived = false;
  1003. private bool receiveActive = false;
  1004. private byte[] readBuffer = new byte[256];
  1005. private int bytesToRead = 0;
  1006. private int actualPositionToRead = 0;
  1007. DateTime dateTimeLastRead;
  1008. /*
  1009. private void DataReceivedHandler(object sender,
  1010. SerialDataReceivedEventArgs e)
  1011. {
  1012. long ticksWait = TimeSpan.TicksPerMillisecond * 2000;
  1013. SerialPort sp = (SerialPort)sender;
  1014.  
  1015. if (bytesToRead == 0 || sp.BytesToRead == 0)
  1016. {
  1017. actualPositionToRead = 0;
  1018. sp.DiscardInBuffer();
  1019. dataReceived = false;
  1020. receiveActive = false;
  1021. return;
  1022. }
  1023.  
  1024. if (actualPositionToRead == 0 && !dataReceived)
  1025. readBuffer = new byte[256];
  1026.  
  1027. //if ((DateTime.Now.Ticks - dateTimeLastRead.Ticks) > ticksWait)
  1028. //{
  1029. // readBuffer = new byte[256];
  1030. // actualPositionToRead = 0;
  1031. //}
  1032. int numberOfBytesInBuffer = sp.BytesToRead;
  1033. sp.Read(readBuffer, actualPositionToRead, ((numberOfBytesInBuffer + actualPositionToRead) > readBuffer.Length) ? 0 : numberOfBytesInBuffer);
  1034. actualPositionToRead = actualPositionToRead + numberOfBytesInBuffer;
  1035. //sp.DiscardInBuffer();
  1036. //if (DetectValidModbusFrame(readBuffer, (actualPositionToRead < readBuffer.Length) ? actualPositionToRead : readBuffer.Length) | bytesToRead <= actualPositionToRead)
  1037. if (actualPositionToRead >= bytesToRead)
  1038. {
  1039.  
  1040. dataReceived = true;
  1041. bytesToRead = 0;
  1042. actualPositionToRead = 0;
  1043. if (debug) StoreLogData.Instance.Store("Received Serial-Data: " + BitConverter.ToString(readBuffer), System.DateTime.Now);
  1044.  
  1045. }
  1046.  
  1047.  
  1048. //dateTimeLastRead = DateTime.Now;
  1049. }
  1050. */
  1051.  
  1052.  
  1053. private void DataReceivedHandler(object sender,
  1054. SerialDataReceivedEventArgs e)
  1055. {
  1056. serialport.DataReceived -= DataReceivedHandler;
  1057.  
  1058. //while (receiveActive | dataReceived)
  1059. // System.Threading.Thread.Sleep(10);
  1060. receiveActive = true;
  1061.  
  1062. const long ticksWait = TimeSpan.TicksPerMillisecond * 2000;//((40*10000000) / this.baudRate);
  1063.  
  1064.  
  1065. SerialPort sp = (SerialPort) sender;
  1066. if (bytesToRead == 0)
  1067. {
  1068. sp.DiscardInBuffer();
  1069. receiveActive = false;
  1070. serialport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
  1071. return;
  1072. }
  1073. readBuffer = new byte[256];
  1074. int numbytes = 0;
  1075. int actualPositionToRead = 0;
  1076. DateTime dateTimeLastRead = DateTime.Now;
  1077. do{
  1078. try {
  1079. dateTimeLastRead = DateTime.Now;
  1080. while ((sp.BytesToRead) == 0)
  1081. {
  1082. System.Threading.Thread.Sleep(10);
  1083. if ((DateTime.Now.Ticks - dateTimeLastRead.Ticks) > ticksWait)
  1084. break;
  1085. }
  1086. numbytes = sp.BytesToRead;
  1087.  
  1088.  
  1089. byte[] rxbytearray = new byte[numbytes];
  1090. sp.Read(rxbytearray, 0, numbytes);
  1091. Array.Copy(rxbytearray, 0, readBuffer, actualPositionToRead, (actualPositionToRead + rxbytearray.Length) <= bytesToRead ? rxbytearray.Length : bytesToRead - actualPositionToRead);
  1092.  
  1093. actualPositionToRead = actualPositionToRead + rxbytearray.Length;
  1094.  
  1095. }
  1096. catch (Exception){
  1097.  
  1098. }
  1099.  
  1100. if (bytesToRead <= actualPositionToRead)
  1101. break;
  1102.  
  1103. if (DetectValidModbusFrame(readBuffer, (actualPositionToRead < readBuffer.Length) ? actualPositionToRead : readBuffer.Length) | bytesToRead <= actualPositionToRead)
  1104. break;
  1105. }
  1106. while ((DateTime.Now.Ticks - dateTimeLastRead.Ticks) < ticksWait) ;
  1107.  
  1108. //10.000 Ticks in 1 ms
  1109.  
  1110. receiveData = new byte[actualPositionToRead];
  1111. Array.Copy(readBuffer, 0, receiveData, 0, (actualPositionToRead < readBuffer.Length) ? actualPositionToRead : readBuffer.Length);
  1112. if (debug) StoreLogData.Instance.Store("Received Serial-Data: " + BitConverter.ToString(readBuffer), System.DateTime.Now);
  1113. bytesToRead = 0;
  1114.  
  1115.  
  1116.  
  1117.  
  1118. dataReceived = true;
  1119. receiveActive = false;
  1120. serialport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
  1121. if (receiveDataChanged != null)
  1122. {
  1123.  
  1124. receiveDataChanged(this);
  1125.  
  1126. }
  1127.  
  1128. //sp.DiscardInBuffer();
  1129. }
  1130.  
  1131. public static bool DetectValidModbusFrame(byte[] readBuffer, int length)
  1132. {
  1133. // minimum length 6 bytes
  1134. if (length < 6)
  1135. return false;
  1136. //SlaveID correct
  1137. if ((readBuffer[0] < 1) | (readBuffer[0] > 247))
  1138. return false;
  1139. //CRC correct?
  1140. byte[] crc = new byte[2];
  1141. crc = BitConverter.GetBytes(calculateCRC(readBuffer, (ushort) (length - 2), 0));
  1142. if (crc[0] != readBuffer[length - 2] | crc[1] != readBuffer[length - 1])
  1143. return false;
  1144. return true;
  1145. }
  1146.  
  1147. /// <summary>
  1148. /// Read Discrete Inputs from Server device (FC2) and publishes the values to a MQTT-Broker.
  1149. /// The Topic will be easymodbusclient/discreteinputs/'address' e.g. easymodbusclient/discreteinputs/0 for address "0".
  1150. /// Note that the Address that will be publishes is "0"-Based. The Root topic can be changed using the Parameter
  1151. /// By default we are using the Standard-Port 1883. This Port can be changed using the Property "MqttBrokerPort"
  1152. /// A Username and Passowrd can be provided using the Properties "MqttUserName" and "MqttPassword"
  1153. /// 'MqttRootTopic' Default is 'easymodbusclient'
  1154. /// </summary>
  1155. /// <param name="startingAddress">First discrete input to read</param>
  1156. /// <param name="quantity">Number of discrete Inputs to read</param>
  1157. /// <param name="mqttBrokerAddress">Broker address the values will be published to</param>
  1158. /// <returns>Boolean Array which contains the discrete Inputs</returns>
  1159. public bool[] ReadDiscreteInputs(int startingAddress, int quantity, string mqttBrokerAddress)
  1160. {
  1161. bool[] returnValue = this.ReadDiscreteInputs(startingAddress, quantity);
  1162. List<String> topic = new List<String>();
  1163. List<String> payload = new List<String>();
  1164. if (MqttPushOnChange && mqttDiscreteInputsOldValues == null)
  1165. mqttDiscreteInputsOldValues = new bool[65535];
  1166. for (int i = 0; i < returnValue.Length; i++)
  1167. {
  1168. if (mqttDiscreteInputsOldValues == null ? true : (mqttDiscreteInputsOldValues[i] != returnValue[i]))
  1169. {
  1170. topic.Add(mqttRootTopic + "/discreteinputs/" + (i + startingAddress).ToString());
  1171. payload.Add(returnValue[i].ToString());
  1172. mqttDiscreteInputsOldValues[i] = returnValue[i];
  1173. }
  1174.  
  1175. }
  1176. /*if (easyModbus2Mqtt == null)
  1177. easyModbus2Mqtt = new EasyModbus2Mqtt();
  1178. easyModbus2Mqtt.MqttBrokerPort = this.MqttBrokerPort;
  1179. easyModbus2Mqtt.MqttUserName = this.MqttUserName;
  1180. easyModbus2Mqtt.MqttPassword = this.MqttPassword;
  1181. easyModbus2Mqtt.RetainMessages = this.mqttRetainMessages;
  1182. easyModbus2Mqtt.publish(topic.ToArray(), payload.ToArray(), mqttBrokerAddress);
  1183. */
  1184. return returnValue;
  1185. }
  1186.  
  1187.  
  1188. /// <summary>
  1189. /// Read Discrete Inputs from Server device (FC2).
  1190. /// </summary>
  1191. /// <param name="startingAddress">First discrete input to read</param>
  1192. /// <param name="quantity">Number of discrete Inputs to read</param>
  1193. /// <returns>Boolean Array which contains the discrete Inputs</returns>
  1194. public bool[] ReadDiscreteInputs(int startingAddress, int quantity)
  1195. {
  1196. if (debug) StoreLogData.Instance.Store("FC2 (Read Discrete Inputs from Master device), StartingAddress: " + startingAddress + ", Quantity: " + quantity, System.DateTime.Now);
  1197. transactionIdentifierInternal++;
  1198. if (serialport != null)
  1199. if (!serialport.IsOpen)
  1200. {
  1201. if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now);
  1202. throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
  1203. }
  1204. if (tcpClient == null & !udpFlag & serialport == null)
  1205. {
  1206. if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now);
  1207. throw new EasyModbus.Exceptions.ConnectionException("connection error");
  1208. }
  1209. if (startingAddress > 65535 | quantity > 2000)
  1210. {
  1211. if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now);
  1212. throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 2000");
  1213. }
  1214. bool[] response;
  1215. this.transactionIdentifier = BitConverter.GetBytes((uint) transactionIdentifierInternal);
  1216. this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000);
  1217. this.length = BitConverter.GetBytes((int) 0x0006);
  1218. this.functionCode = 0x02;
  1219. this.startingAddress = BitConverter.GetBytes(startingAddress);
  1220. this.quantity = BitConverter.GetBytes(quantity);
  1221. Byte[] data = new byte[]
  1222. {
  1223. this.transactionIdentifier[1],
  1224. this.transactionIdentifier[0],
  1225. this.protocolIdentifier[1],
  1226. this.protocolIdentifier[0],
  1227. this.length[1],
  1228. this.length[0],
  1229. this.unitIdentifier,
  1230. this.functionCode,
  1231. this.startingAddress[1],
  1232. this.startingAddress[0],
  1233. this.quantity[1],
  1234. this.quantity[0],
  1235. this.crc[0],
  1236. this.crc[1]
  1237. };
  1238. crc = BitConverter.GetBytes(calculateCRC(data, 6, 6));
  1239. data[12] = crc[0];
  1240. data[13] = crc[1];
  1241.  
  1242. if (serialport != null)
  1243. {
  1244. dataReceived = false;
  1245. if (quantity % 8 == 0)
  1246. bytesToRead = 5 + quantity / 8;
  1247. else
  1248. bytesToRead = 6 + quantity / 8;
  1249. // serialport.ReceivedBytesThreshold = bytesToRead;
  1250. serialport.Write(data, 6, 8);
  1251. if (debug)
  1252. {
  1253. byte [] debugData = new byte[8];
  1254. Array.Copy(data, 6, debugData, 0, 8);
  1255. if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  1256. }
  1257. if (sendDataChanged != null)
  1258. {
  1259. sendData = new byte[8];
  1260. Array.Copy(data, 6, sendData, 0, 8);
  1261. sendDataChanged(this);
  1262.  
  1263. }
  1264. data = new byte[2100];
  1265. readBuffer = new byte[256];
  1266. DateTime dateTimeSend = DateTime.Now;
  1267. byte receivedUnitIdentifier = 0xFF;
  1268.  
  1269.  
  1270. while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  1271. {
  1272. while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  1273. System.Threading.Thread.Sleep(1);
  1274. data = new byte[2100];
  1275. Array.Copy(readBuffer, 0, data, 6, readBuffer.Length);
  1276. receivedUnitIdentifier = data[6];
  1277. }
  1278. if (receivedUnitIdentifier != this.unitIdentifier)
  1279. data = new byte[2100];
  1280. else
  1281. countRetries = 0;
  1282. }
  1283. else if (tcpClient.Client.Connected | udpFlag)
  1284. {
  1285. if (udpFlag)
  1286. {
  1287. UdpClient udpClient = new UdpClient();
  1288. IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port);
  1289. udpClient.Send(data, data.Length - 2, endPoint);
  1290. portOut = ((IPEndPoint) udpClient.Client.LocalEndPoint).Port;
  1291. udpClient.Client.ReceiveTimeout = 5000;
  1292. endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut);
  1293. data = udpClient.Receive(ref endPoint);
  1294. }
  1295. else
  1296. {
  1297. stream.Write(data, 0, data.Length - 2);
  1298. if (debug)
  1299. {
  1300. byte [] debugData = new byte[data.Length - 2];
  1301. Array.Copy(data, 0, debugData, 0, data.Length - 2);
  1302. if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  1303. }
  1304. if (sendDataChanged != null)
  1305. {
  1306. sendData = new byte[data.Length - 2];
  1307. Array.Copy(data, 0, sendData, 0, data.Length - 2);
  1308. sendDataChanged(this);
  1309. }
  1310. data = new Byte[2100];
  1311. int NumberOfBytes = stream.Read(data, 0, data.Length);
  1312. if (receiveDataChanged != null)
  1313. {
  1314. receiveData = new byte[NumberOfBytes];
  1315. Array.Copy(data, 0, receiveData, 0, NumberOfBytes);
  1316. if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now);
  1317. receiveDataChanged(this);
  1318. }
  1319. }
  1320. }
  1321. if (data[7] == 0x82 & data[8] == 0x01)
  1322. {
  1323. if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now);
  1324. throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master");
  1325. }
  1326. if (data[7] == 0x82 & data[8] == 0x02)
  1327. {
  1328. if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now);
  1329. throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid");
  1330. }
  1331. if (data[7] == 0x82 & data[8] == 0x03)
  1332. {
  1333. if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now);
  1334. throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid");
  1335. }
  1336. if (data[7] == 0x82 & data[8] == 0x04)
  1337. {
  1338. if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now);
  1339. throw new EasyModbus.Exceptions.ModbusException("error reading");
  1340. }
  1341. if (serialport != null)
  1342. {
  1343. crc = BitConverter.GetBytes(calculateCRC(data, (ushort) (data[8] + 3), 6));
  1344. if ((crc[0] != data[data[8] + 9] | crc[1] != data[data[8] + 10]) & dataReceived)
  1345. {
  1346. if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now);
  1347. if (NumberOfRetries <= countRetries)
  1348. {
  1349. countRetries = 0;
  1350. throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed");
  1351. }
  1352. else
  1353. {
  1354. countRetries++;
  1355. return ReadDiscreteInputs(startingAddress, quantity);
  1356. }
  1357. }
  1358. else if (!dataReceived)
  1359. {
  1360. if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now);
  1361. if (NumberOfRetries <= countRetries)
  1362. {
  1363. countRetries = 0;
  1364. throw new TimeoutException("No Response from Modbus Slave");
  1365. }
  1366. else
  1367. {
  1368. countRetries++;
  1369. return ReadDiscreteInputs(startingAddress, quantity);
  1370. }
  1371. }
  1372. }
  1373. response = new bool[quantity];
  1374. for (int i = 0; i < quantity; i++)
  1375. {
  1376. int intData = data[9 + i / 8];
  1377. int mask = Convert.ToInt32(Math.Pow(2, (i % 8)));
  1378. response[i] = Convert.ToBoolean((intData & mask) / mask);
  1379. }
  1380. return (response);
  1381. }
  1382.  
  1383. /// <summary>
  1384. /// Read coils from Server device (FC1) and publishes the values to a MQTT-Broker.
  1385. /// The Topic will be easymodbusclient/coils/'address' e.g. easymodbusclient/coils/0 for address "0".
  1386. /// Note that the Address that will be publishes is "0"-Based. The Root topic can be changed using the Parameter
  1387. /// 'MqttRootTopic' Default is 'easymodbusclient'
  1388. /// By default we are using the Standard-Port 1883. This Port can be changed using the Property "MqttBrokerPort"
  1389. /// A Username and Passowrd can be provided using the Properties "MqttUserName" and "MqttPassword"
  1390. /// </summary>
  1391. /// <param name="startingAddress">First coil to read</param>
  1392. /// <param name="quantity">Number of coils to read</param>
  1393. /// <param name="mqttBrokerAddress">Broker address 8the values will be published to</param>
  1394. /// <returns>Boolean Array which contains the coild</returns>
  1395. public bool[] ReadCoils(int startingAddress, int quantity, string mqttBrokerAddress)
  1396. {
  1397.  
  1398. bool[] returnValue = this.ReadCoils(startingAddress, quantity);
  1399. List<String> topic = new List<String>();
  1400. List<String> payload = new List<String>();
  1401. if (MqttPushOnChange && mqttCoilsOldValues == null)
  1402. mqttCoilsOldValues = new bool[65535];
  1403. for (int i = 0; i < returnValue.Length; i++)
  1404. {
  1405. if (mqttCoilsOldValues == null ? true : (mqttCoilsOldValues[i] != returnValue[i]))
  1406. {
  1407. topic.Add(mqttRootTopic + "/coils/" + (i + startingAddress).ToString());
  1408. payload.Add(returnValue[i].ToString());
  1409. mqttCoilsOldValues[i] = returnValue[i];
  1410. }
  1411. }
  1412. /*if (easyModbus2Mqtt == null)
  1413. easyModbus2Mqtt = new EasyModbus2Mqtt();
  1414. easyModbus2Mqtt.MqttBrokerPort = this.MqttBrokerPort;
  1415. easyModbus2Mqtt.MqttUserName = this.MqttUserName;
  1416. easyModbus2Mqtt.MqttPassword = this.MqttPassword;
  1417. easyModbus2Mqtt.RetainMessages = this.mqttRetainMessages;
  1418. easyModbus2Mqtt.publish(topic.ToArray(), payload.ToArray(), mqttBrokerAddress);
  1419. */
  1420.  
  1421. return returnValue;
  1422. }
  1423.  
  1424. /// <summary>
  1425. /// Read Coils from Server device (FC1).
  1426. /// </summary>
  1427. /// <param name="startingAddress">First coil to read</param>
  1428. /// <param name="quantity">Numer of coils to read</param>
  1429. /// <returns>Boolean Array which contains the coils</returns>
  1430. public bool[] ReadCoils(int startingAddress, int quantity)
  1431. {
  1432. if (debug) StoreLogData.Instance.Store("FC1 (Read Coils from Master device), StartingAddress: " + startingAddress + ", Quantity: " + quantity, System.DateTime.Now);
  1433. transactionIdentifierInternal++;
  1434. if (serialport != null)
  1435. if (!serialport.IsOpen)
  1436. {
  1437. if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now);
  1438. throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
  1439. }
  1440. if (tcpClient == null & !udpFlag & serialport == null)
  1441. {
  1442. if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now);
  1443. throw new EasyModbus.Exceptions.ConnectionException("connection error");
  1444. }
  1445. if (startingAddress > 65535 | quantity > 2000)
  1446. {
  1447. if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now);
  1448. throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 2000");
  1449. }
  1450. bool[] response;
  1451. this.transactionIdentifier = BitConverter.GetBytes((uint) transactionIdentifierInternal);
  1452. this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000);
  1453. this.length = BitConverter.GetBytes((int) 0x0006);
  1454. this.functionCode = 0x01;
  1455. this.startingAddress = BitConverter.GetBytes(startingAddress);
  1456. this.quantity = BitConverter.GetBytes(quantity);
  1457. Byte[] data = new byte[]{
  1458. this.transactionIdentifier[1],
  1459. this.transactionIdentifier[0],
  1460. this.protocolIdentifier[1],
  1461. this.protocolIdentifier[0],
  1462. this.length[1],
  1463. this.length[0],
  1464. this.unitIdentifier,
  1465. this.functionCode,
  1466. this.startingAddress[1],
  1467. this.startingAddress[0],
  1468. this.quantity[1],
  1469. this.quantity[0],
  1470. this.crc[0],
  1471. this.crc[1]
  1472. };
  1473.  
  1474. crc = BitConverter.GetBytes(calculateCRC(data, 6, 6));
  1475. data[12] = crc[0];
  1476. data[13] = crc[1];
  1477. if (serialport != null)
  1478. {
  1479. dataReceived = false;
  1480. if (quantity % 8 == 0)
  1481. bytesToRead = 5 + quantity / 8;
  1482. else
  1483. bytesToRead = 6 + quantity / 8;
  1484. // serialport.ReceivedBytesThreshold = bytesToRead;
  1485. serialport.Write(data, 6, 8);
  1486. if (debug)
  1487. {
  1488. byte [] debugData = new byte[8];
  1489. Array.Copy(data, 6, debugData, 0, 8);
  1490. if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  1491. }
  1492. if (sendDataChanged != null)
  1493. {
  1494. sendData = new byte[8];
  1495. Array.Copy(data, 6, sendData, 0, 8);
  1496. sendDataChanged(this);
  1497.  
  1498. }
  1499. data = new byte[2100];
  1500. readBuffer = new byte[256];
  1501. DateTime dateTimeSend = DateTime.Now;
  1502. byte receivedUnitIdentifier = 0xFF;
  1503. while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  1504. {
  1505. while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  1506. System.Threading.Thread.Sleep(1);
  1507. data = new byte[2100];
  1508.  
  1509. Array.Copy(readBuffer, 0, data, 6, readBuffer.Length);
  1510. receivedUnitIdentifier = data[6];
  1511. }
  1512. if (receivedUnitIdentifier != this.unitIdentifier)
  1513. data = new byte[2100];
  1514. else
  1515. countRetries = 0;
  1516. }
  1517. else if (tcpClient.Client.Connected | udpFlag)
  1518. {
  1519. if (udpFlag)
  1520. {
  1521. UdpClient udpClient = new UdpClient();
  1522. IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port);
  1523. udpClient.Send(data, data.Length - 2, endPoint);
  1524. portOut = ((IPEndPoint) udpClient.Client.LocalEndPoint).Port;
  1525. udpClient.Client.ReceiveTimeout = 5000;
  1526. endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut);
  1527. data = udpClient.Receive(ref endPoint);
  1528. }
  1529. else
  1530. {
  1531. stream.Write(data, 0, data.Length - 2);
  1532. if (debug)
  1533. {
  1534. byte [] debugData = new byte[data.Length - 2];
  1535. Array.Copy(data, 0, debugData, 0, data.Length - 2);
  1536. if (debug) StoreLogData.Instance.Store("Send MocbusTCP-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  1537. }
  1538. if (sendDataChanged != null)
  1539. {
  1540. sendData = new byte[data.Length - 2];
  1541. Array.Copy(data, 0, sendData, 0, data.Length - 2);
  1542. sendDataChanged(this);
  1543.  
  1544. }
  1545. data = new Byte[2100];
  1546. int NumberOfBytes = stream.Read(data, 0, data.Length);
  1547. if (receiveDataChanged != null)
  1548. {
  1549. receiveData = new byte[NumberOfBytes];
  1550. Array.Copy(data, 0, receiveData, 0, NumberOfBytes);
  1551. if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now);
  1552. receiveDataChanged(this);
  1553. }
  1554. }
  1555. }
  1556. if (data[7] == 0x81 & data[8] == 0x01)
  1557. {
  1558. if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now);
  1559. throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master");
  1560. }
  1561. if (data[7] == 0x81 & data[8] == 0x02)
  1562. {
  1563. if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now);
  1564. throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid");
  1565. }
  1566. if (data[7] == 0x81 & data[8] == 0x03)
  1567. {
  1568. if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now);
  1569. throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid");
  1570. }
  1571. if (data[7] == 0x81 & data[8] == 0x04)
  1572. {
  1573. if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now);
  1574. throw new EasyModbus.Exceptions.ModbusException("error reading");
  1575. }
  1576. if (serialport != null)
  1577. {
  1578. crc = BitConverter.GetBytes(calculateCRC(data, (ushort) (data[8] + 3), 6));
  1579. if ((crc[0] != data[data[8] + 9] | crc[1] != data[data[8] + 10]) & dataReceived)
  1580. {
  1581. if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now);
  1582. if (NumberOfRetries <= countRetries)
  1583. {
  1584. countRetries = 0;
  1585. throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed");
  1586. }
  1587. else
  1588. {
  1589. countRetries++;
  1590. return ReadCoils(startingAddress, quantity);
  1591. }
  1592. }
  1593. else if (!dataReceived)
  1594. {
  1595. if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now);
  1596. if (NumberOfRetries <= countRetries)
  1597. {
  1598. countRetries = 0;
  1599. throw new TimeoutException("No Response from Modbus Slave");
  1600. }
  1601. else
  1602. {
  1603. countRetries++;
  1604. return ReadCoils(startingAddress, quantity);
  1605. }
  1606. }
  1607. }
  1608. response = new bool[quantity];
  1609. for (int i = 0; i < quantity; i++)
  1610. {
  1611. int intData = data[9 + i / 8];
  1612. int mask = Convert.ToInt32(Math.Pow(2, (i % 8)));
  1613. response[i] = Convert.ToBoolean((intData & mask) / mask);
  1614. }
  1615. return (response);
  1616. }
  1617.  
  1618. /// <summary>
  1619. /// Read Holding Registers from Server device (FC3) and publishes the values to a MQTT-Broker.
  1620. /// The Topic will be easymodbusclient/holdingregisters/'address' e.g. easymodbusclient/holdingregisters/0 for address "0".
  1621. /// Note that the Address that will be publishes is "0"-Based. The Root topic can be changed using the Parameter
  1622. /// 'MqttRootTopic' Default is 'easymodbusclient'
  1623. /// By default we are using the Standard-Port 1883. This Port can be changed using the Property "MqttBrokerPort"
  1624. /// A Username and Passowrd can be provided using the Properties "MqttUserName" and "MqttPassword"
  1625. /// </summary>
  1626. /// <param name="startingAddress">First Holding Register to read</param>
  1627. /// <param name="quantity">Number of Holding Registers to read</param>
  1628. /// <param name="mqttBrokerAddress">Broker address the values will be published to</param>
  1629. /// <returns>Boolean Array which contains the Holding Registers</returns>
  1630. public int[] ReadHoldingRegisters(int startingAddress, int quantity, string mqttBrokerAddress)
  1631. {
  1632. int[] returnValue = this.ReadHoldingRegisters(startingAddress, quantity);
  1633. List<String> topic = new List<String>();
  1634. List<String> payload = new List<String>();
  1635. if (MqttPushOnChange && mqttHoldingRegistersOldValues == null)
  1636. mqttHoldingRegistersOldValues = new int[65535];
  1637. for (int i = 0; i < returnValue.Length; i++)
  1638. {
  1639. if (mqttHoldingRegistersOldValues == null ? true : (mqttHoldingRegistersOldValues[i] != returnValue[i]))
  1640. {
  1641. topic.Add(mqttRootTopic + "/holdingregisters/" + (i + startingAddress).ToString());
  1642. payload.Add(returnValue[i].ToString());
  1643. mqttHoldingRegistersOldValues[i] = returnValue[i];
  1644. }
  1645. }
  1646. /* if (easyModbus2Mqtt == null)
  1647. easyModbus2Mqtt = new EasyModbus2Mqtt();
  1648. easyModbus2Mqtt.MqttBrokerPort = this.MqttBrokerPort;
  1649. easyModbus2Mqtt.MqttUserName = this.MqttUserName;
  1650. easyModbus2Mqtt.MqttPassword = this.MqttPassword;
  1651. easyModbus2Mqtt.RetainMessages = this.mqttRetainMessages;
  1652. easyModbus2Mqtt.publish(topic.ToArray(), payload.ToArray(), mqttBrokerAddress);*/
  1653. return returnValue;
  1654. }
  1655.  
  1656. /// <summary>
  1657. /// Read Holding Registers from Master device (FC3).
  1658. /// </summary>
  1659. /// <param name="startingAddress">First holding register to be read</param>
  1660. /// <param name="quantity">Number of holding registers to be read</param>
  1661. /// <returns>Int Array which contains the holding registers</returns>
  1662. public int[] ReadHoldingRegisters(int startingAddress, int quantity)
  1663. {
  1664. if (debug) StoreLogData.Instance.Store("FC3 (Read Holding Registers from Master device), StartingAddress: " + startingAddress + ", Quantity: " + quantity, System.DateTime.Now);
  1665. transactionIdentifierInternal++;
  1666. if (serialport != null)
  1667. if (!serialport.IsOpen)
  1668. {
  1669. if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now);
  1670. throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
  1671. }
  1672. if (tcpClient == null & !udpFlag & serialport == null)
  1673. {
  1674. if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now);
  1675. throw new EasyModbus.Exceptions.ConnectionException("connection error");
  1676. }
  1677. if (startingAddress > 65535 | quantity > 125)
  1678. {
  1679. if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now);
  1680. throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 125");
  1681. }
  1682. int[] response;
  1683. this.transactionIdentifier = BitConverter.GetBytes((uint) transactionIdentifierInternal);
  1684. this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000);
  1685. this.length = BitConverter.GetBytes((int) 0x0006);
  1686. this.functionCode = 0x03;
  1687. this.startingAddress = BitConverter.GetBytes(startingAddress);
  1688. this.quantity = BitConverter.GetBytes(quantity);
  1689. Byte[] data = new byte[]{ this.transactionIdentifier[1],
  1690. this.transactionIdentifier[0],
  1691. this.protocolIdentifier[1],
  1692. this.protocolIdentifier[0],
  1693. this.length[1],
  1694. this.length[0],
  1695. this.unitIdentifier,
  1696. this.functionCode,
  1697. this.startingAddress[1],
  1698. this.startingAddress[0],
  1699. this.quantity[1],
  1700. this.quantity[0],
  1701. this.crc[0],
  1702. this.crc[1]
  1703. };
  1704. crc = BitConverter.GetBytes(calculateCRC(data, 6, 6));
  1705. data[12] = crc[0];
  1706. data[13] = crc[1];
  1707. if (serialport != null)
  1708. {
  1709. dataReceived = false;
  1710. bytesToRead = 5 + 2 * quantity;
  1711. // serialport.ReceivedBytesThreshold = bytesToRead;
  1712. serialport.Write(data, 6, 8);
  1713. if (debug)
  1714. {
  1715. byte [] debugData = new byte[8];
  1716. Array.Copy(data, 6, debugData, 0, 8);
  1717. if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  1718. }
  1719. if (sendDataChanged != null)
  1720. {
  1721. sendData = new byte[8];
  1722. Array.Copy(data, 6, sendData, 0, 8);
  1723. sendDataChanged(this);
  1724.  
  1725. }
  1726. data = new byte[2100];
  1727. readBuffer = new byte[256];
  1728.  
  1729. DateTime dateTimeSend = DateTime.Now;
  1730. byte receivedUnitIdentifier = 0xFF;
  1731. while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  1732. {
  1733. while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  1734. System.Threading.Thread.Sleep(1);
  1735. data = new byte[2100];
  1736. Array.Copy(readBuffer, 0, data, 6, readBuffer.Length);
  1737.  
  1738. receivedUnitIdentifier = data[6];
  1739. }
  1740. if (receivedUnitIdentifier != this.unitIdentifier)
  1741. data = new byte[2100];
  1742. else
  1743. countRetries = 0;
  1744. }
  1745. else if (tcpClient.Client.Connected | udpFlag)
  1746. {
  1747. if (udpFlag)
  1748. {
  1749. UdpClient udpClient = new UdpClient();
  1750. IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port);
  1751. udpClient.Send(data, data.Length - 2, endPoint);
  1752. portOut = ((IPEndPoint) udpClient.Client.LocalEndPoint).Port;
  1753. udpClient.Client.ReceiveTimeout = 5000;
  1754. endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut);
  1755. data = udpClient.Receive(ref endPoint);
  1756. }
  1757. else
  1758. {
  1759. stream.Write(data, 0, data.Length - 2);
  1760. if (debug)
  1761. {
  1762. byte [] debugData = new byte[data.Length - 2];
  1763. Array.Copy(data, 0, debugData, 0, data.Length - 2);
  1764. if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  1765. }
  1766. if (sendDataChanged != null)
  1767. {
  1768. sendData = new byte[data.Length - 2];
  1769. Array.Copy(data, 0, sendData, 0, data.Length - 2);
  1770. sendDataChanged(this);
  1771.  
  1772. }
  1773. data = new Byte[256];
  1774. int NumberOfBytes = stream.Read(data, 0, data.Length);
  1775. if (receiveDataChanged != null)
  1776. {
  1777. receiveData = new byte[NumberOfBytes];
  1778. Array.Copy(data, 0, receiveData, 0, NumberOfBytes);
  1779. if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now);
  1780. receiveDataChanged(this);
  1781. }
  1782. }
  1783. }
  1784. if (data[7] == 0x83 & data[8] == 0x01)
  1785. {
  1786. if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now);
  1787. throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master");
  1788. }
  1789. if (data[7] == 0x83 & data[8] == 0x02)
  1790. {
  1791. if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now);
  1792. throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid");
  1793. }
  1794. if (data[7] == 0x83 & data[8] == 0x03)
  1795. {
  1796. if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now);
  1797. throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid");
  1798. }
  1799. if (data[7] == 0x83 & data[8] == 0x04)
  1800. {
  1801. if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now);
  1802. throw new EasyModbus.Exceptions.ModbusException("error reading");
  1803. }
  1804. if (serialport != null)
  1805. {
  1806. crc = BitConverter.GetBytes(calculateCRC(data, (ushort) (data[8] + 3), 6));
  1807. if ((crc[0] != data[data[8] + 9] | crc[1] != data[data[8] + 10]) & dataReceived)
  1808. {
  1809. if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now);
  1810. if (NumberOfRetries <= countRetries)
  1811. {
  1812. countRetries = 0;
  1813. throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed");
  1814. }
  1815. else
  1816. {
  1817. countRetries++;
  1818. return ReadHoldingRegisters(startingAddress, quantity);
  1819. }
  1820. }
  1821. else if (!dataReceived)
  1822. {
  1823. if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now);
  1824. if (NumberOfRetries <= countRetries)
  1825. {
  1826. countRetries = 0;
  1827. throw new TimeoutException("No Response from Modbus Slave");
  1828. }
  1829. else
  1830. {
  1831. countRetries++;
  1832. return ReadHoldingRegisters(startingAddress, quantity);
  1833. }
  1834.  
  1835.  
  1836. }
  1837. }
  1838. response = new int[quantity];
  1839. for (int i = 0; i < quantity; i++)
  1840. {
  1841. byte lowByte;
  1842. byte highByte;
  1843. highByte = data[9 + i * 2];
  1844. lowByte = data[9 + i * 2 + 1];
  1845.  
  1846. data[9 + i * 2] = lowByte;
  1847. data[9 + i * 2 + 1] = highByte;
  1848.  
  1849. response[i] = BitConverter.ToInt16(data, (9 + i * 2));
  1850. }
  1851. return (response);
  1852. }
  1853.  
  1854. /// <summary>
  1855. /// Read Input Registers from Server device (FC4) and publishes the values to a MQTT-Broker.
  1856. /// The Topic will be easymodbusclient/inputregisters/'address' e.g. easymodbusclient/inputregisters/0 for address "0".
  1857. /// Note that the Address that will be publishes is "0"-Based. The Root topic can be changed using the Parameter
  1858. /// 'MqttRootTopic' Default is 'easymodbusclient'
  1859. /// By default we are using the Standard-Port 1883. This Port can be changed using the Property "MqttBrokerPort"
  1860. /// A Username and Passowrd can be provided using the Properties "MqttUserName" and "MqttPassword"
  1861. /// </summary>
  1862. /// <param name="startingAddress">First Input Register to read</param>
  1863. /// <param name="quantity">Number of Input Registers to read</param>
  1864. /// <param name="mqttBrokerAddress">Broker address 8the values will be published to</param>
  1865. /// <returns>Boolean Array which contains the Input Registers</returns>
  1866. public int[] ReadInputRegisters(int startingAddress, int quantity, string mqttBrokerAddress)
  1867. {
  1868. int[] returnValue = this.ReadInputRegisters(startingAddress, quantity);
  1869. List<String> topic = new List<String>();
  1870. List<String> payload = new List<String>();
  1871. if (MqttPushOnChange && mqttInputRegistersOldValues == null)
  1872. mqttInputRegistersOldValues = new int[65535];
  1873. for (int i = 0; i < returnValue.Length; i++)
  1874. {
  1875. if (mqttInputRegistersOldValues == null ? true : (mqttInputRegistersOldValues[i] != returnValue[i]))
  1876. {
  1877. topic.Add(mqttRootTopic + "/inputregisters/" + (i + startingAddress).ToString());
  1878. payload.Add(returnValue[i].ToString());
  1879. mqttInputRegistersOldValues[i] = returnValue[i];
  1880. }
  1881. }
  1882. /* if (easyModbus2Mqtt == null)
  1883. easyModbus2Mqtt = new EasyModbus2Mqtt();
  1884. easyModbus2Mqtt.MqttBrokerPort = this.MqttBrokerPort;
  1885. easyModbus2Mqtt.MqttUserName = this.MqttUserName;
  1886. easyModbus2Mqtt.MqttPassword = this.MqttPassword;
  1887. easyModbus2Mqtt.RetainMessages = this.mqttRetainMessages;
  1888. easyModbus2Mqtt.publish(topic.ToArray(), payload.ToArray(), mqttBrokerAddress);*/
  1889. return returnValue;
  1890. }
  1891.  
  1892. /// <summary>
  1893. /// Read Input Registers from Master device (FC4).
  1894. /// </summary>
  1895. /// <param name="startingAddress">First input register to be read</param>
  1896. /// <param name="quantity">Number of input registers to be read</param>
  1897. /// <returns>Int Array which contains the input registers</returns>
  1898. public int[] ReadInputRegisters(int startingAddress, int quantity)
  1899. {
  1900.  
  1901. if (debug) StoreLogData.Instance.Store("FC4 (Read Input Registers from Master device), StartingAddress: " + startingAddress + ", Quantity: " + quantity, System.DateTime.Now);
  1902. transactionIdentifierInternal++;
  1903. if (serialport != null)
  1904. if (!serialport.IsOpen)
  1905. {
  1906. if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now);
  1907. throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
  1908. }
  1909. if (tcpClient == null & !udpFlag & serialport == null)
  1910. {
  1911. if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now);
  1912. throw new EasyModbus.Exceptions.ConnectionException("connection error");
  1913. }
  1914. if (startingAddress > 65535 | quantity > 125)
  1915. {
  1916. if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now);
  1917. throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 125");
  1918. }
  1919. int[] response;
  1920. this.transactionIdentifier = BitConverter.GetBytes((uint) transactionIdentifierInternal);
  1921. this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000);
  1922. this.length = BitConverter.GetBytes((int) 0x0006);
  1923. this.functionCode = 0x04;
  1924. this.startingAddress = BitConverter.GetBytes(startingAddress);
  1925. this.quantity = BitConverter.GetBytes(quantity);
  1926. Byte[] data = new byte[]{ this.transactionIdentifier[1],
  1927. this.transactionIdentifier[0],
  1928. this.protocolIdentifier[1],
  1929. this.protocolIdentifier[0],
  1930. this.length[1],
  1931. this.length[0],
  1932. this.unitIdentifier,
  1933. this.functionCode,
  1934. this.startingAddress[1],
  1935. this.startingAddress[0],
  1936. this.quantity[1],
  1937. this.quantity[0],
  1938. this.crc[0],
  1939. this.crc[1]
  1940. };
  1941. crc = BitConverter.GetBytes(calculateCRC(data, 6, 6));
  1942. data[12] = crc[0];
  1943. data[13] = crc[1];
  1944. if (serialport != null)
  1945. {
  1946. dataReceived = false;
  1947. bytesToRead = 5 + 2 * quantity;
  1948.  
  1949.  
  1950. // serialport.ReceivedBytesThreshold = bytesToRead;
  1951. serialport.Write(data, 6, 8);
  1952. if (debug)
  1953. {
  1954. byte [] debugData = new byte[8];
  1955. Array.Copy(data, 6, debugData, 0, 8);
  1956. if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  1957. }
  1958. if (sendDataChanged != null)
  1959. {
  1960. sendData = new byte[8];
  1961. Array.Copy(data, 6, sendData, 0, 8);
  1962. sendDataChanged(this);
  1963.  
  1964. }
  1965. data = new byte[2100];
  1966. readBuffer = new byte[256];
  1967. DateTime dateTimeSend = DateTime.Now;
  1968. byte receivedUnitIdentifier = 0xFF;
  1969.  
  1970. while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  1971. {
  1972. while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  1973. System.Threading.Thread.Sleep(1);
  1974. data = new byte[2100];
  1975. Array.Copy(readBuffer, 0, data, 6, readBuffer.Length);
  1976. receivedUnitIdentifier = data[6];
  1977. }
  1978.  
  1979. if (receivedUnitIdentifier != this.unitIdentifier)
  1980. data = new byte[2100];
  1981. else
  1982. countRetries = 0;
  1983. }
  1984. else if (tcpClient.Client.Connected | udpFlag)
  1985. {
  1986. if (udpFlag)
  1987. {
  1988. UdpClient udpClient = new UdpClient();
  1989. IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port);
  1990. udpClient.Send(data, data.Length - 2, endPoint);
  1991. portOut = ((IPEndPoint) udpClient.Client.LocalEndPoint).Port;
  1992. udpClient.Client.ReceiveTimeout = 5000;
  1993. endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut);
  1994. data = udpClient.Receive(ref endPoint);
  1995. }
  1996. else
  1997. {
  1998. stream.Write(data, 0, data.Length - 2);
  1999. if (debug)
  2000. {
  2001. byte [] debugData = new byte[data.Length - 2];
  2002. Array.Copy(data, 0, debugData, 0, data.Length - 2);
  2003. if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  2004. }
  2005. if (sendDataChanged != null)
  2006. {
  2007. sendData = new byte[data.Length - 2];
  2008. Array.Copy(data, 0, sendData, 0, data.Length - 2);
  2009. sendDataChanged(this);
  2010. }
  2011. data = new Byte[2100];
  2012. int NumberOfBytes = stream.Read(data, 0, data.Length);
  2013. if (receiveDataChanged != null)
  2014. {
  2015. receiveData = new byte[NumberOfBytes];
  2016. Array.Copy(data, 0, receiveData, 0, NumberOfBytes);
  2017. if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now);
  2018. receiveDataChanged(this);
  2019. }
  2020. }
  2021. }
  2022. if (data[7] == 0x84 & data[8] == 0x01)
  2023. {
  2024. if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now);
  2025. throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master");
  2026. }
  2027. if (data[7] == 0x84 & data[8] == 0x02)
  2028. {
  2029. if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now);
  2030. throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid");
  2031. }
  2032. if (data[7] == 0x84 & data[8] == 0x03)
  2033. {
  2034. if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now);
  2035. throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid");
  2036. }
  2037. if (data[7] == 0x84 & data[8] == 0x04)
  2038. {
  2039. if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now);
  2040. throw new EasyModbus.Exceptions.ModbusException("error reading");
  2041. }
  2042. if (serialport != null)
  2043. {
  2044. crc = BitConverter.GetBytes(calculateCRC(data, (ushort) (data[8] + 3), 6));
  2045. if ((crc[0] != data[data[8] + 9] | crc[1] != data[data[8] + 10]) & dataReceived)
  2046. {
  2047. if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now);
  2048. if (NumberOfRetries <= countRetries)
  2049. {
  2050. countRetries = 0;
  2051. throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed");
  2052. }
  2053. else
  2054. {
  2055. countRetries++;
  2056. return ReadInputRegisters(startingAddress, quantity);
  2057. }
  2058. }
  2059. else if (!dataReceived)
  2060. {
  2061. if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now);
  2062. if (NumberOfRetries <= countRetries)
  2063. {
  2064. countRetries = 0;
  2065. throw new TimeoutException("No Response from Modbus Slave");
  2066.  
  2067. }
  2068. else
  2069. {
  2070. countRetries++;
  2071. return ReadInputRegisters(startingAddress, quantity);
  2072. }
  2073.  
  2074. }
  2075. }
  2076. response = new int[quantity];
  2077. for (int i = 0; i < quantity; i++)
  2078. {
  2079. byte lowByte;
  2080. byte highByte;
  2081. highByte = data[9 + i * 2];
  2082. lowByte = data[9 + i * 2 + 1];
  2083.  
  2084. data[9 + i * 2] = lowByte;
  2085. data[9 + i * 2 + 1] = highByte;
  2086.  
  2087. response[i] = BitConverter.ToInt16(data, (9 + i * 2));
  2088. }
  2089. return (response);
  2090. }
  2091.  
  2092.  
  2093. /// <summary>
  2094. /// Write single Coil to Master device (FC5).
  2095. /// </summary>
  2096. /// <param name="startingAddress">Coil to be written</param>
  2097. /// <param name="value">Coil Value to be written</param>
  2098. public void WriteSingleCoil(int startingAddress, bool value)
  2099. {
  2100.  
  2101. if (debug) StoreLogData.Instance.Store("FC5 (Write single coil to Master device), StartingAddress: " + startingAddress + ", Value: " + value, System.DateTime.Now);
  2102. transactionIdentifierInternal++;
  2103. if (serialport != null)
  2104. if (!serialport.IsOpen)
  2105. {
  2106. if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now);
  2107. throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
  2108. }
  2109. if (tcpClient == null & !udpFlag & serialport == null)
  2110. {
  2111. if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now);
  2112. throw new EasyModbus.Exceptions.ConnectionException("connection error");
  2113. }
  2114. byte[] coilValue = new byte[2];
  2115. this.transactionIdentifier = BitConverter.GetBytes((uint) transactionIdentifierInternal);
  2116. this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000);
  2117. this.length = BitConverter.GetBytes((int) 0x0006);
  2118. this.functionCode = 0x05;
  2119. this.startingAddress = BitConverter.GetBytes(startingAddress);
  2120. if (value == true)
  2121. {
  2122. coilValue = BitConverter.GetBytes((int) 0xFF00);
  2123. }
  2124. else
  2125. {
  2126. coilValue = BitConverter.GetBytes((int) 0x0000);
  2127. }
  2128. Byte[] data = new byte[]{ this.transactionIdentifier[1],
  2129. this.transactionIdentifier[0],
  2130. this.protocolIdentifier[1],
  2131. this.protocolIdentifier[0],
  2132. this.length[1],
  2133. this.length[0],
  2134. this.unitIdentifier,
  2135. this.functionCode,
  2136. this.startingAddress[1],
  2137. this.startingAddress[0],
  2138. coilValue[1],
  2139. coilValue[0],
  2140. this.crc[0],
  2141. this.crc[1]
  2142. };
  2143. crc = BitConverter.GetBytes(calculateCRC(data, 6, 6));
  2144. data[12] = crc[0];
  2145. data[13] = crc[1];
  2146. if (serialport != null)
  2147. {
  2148. dataReceived = false;
  2149. bytesToRead = 8;
  2150. // serialport.ReceivedBytesThreshold = bytesToRead;
  2151. serialport.Write(data, 6, 8);
  2152. if (debug)
  2153. {
  2154. byte [] debugData = new byte[8];
  2155. Array.Copy(data, 6, debugData, 0, 8);
  2156. if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  2157. }
  2158. if (sendDataChanged != null)
  2159. {
  2160. sendData = new byte[8];
  2161. Array.Copy(data, 6, sendData, 0, 8);
  2162. sendDataChanged(this);
  2163.  
  2164. }
  2165. data = new byte[2100];
  2166. readBuffer = new byte[256];
  2167. DateTime dateTimeSend = DateTime.Now;
  2168. byte receivedUnitIdentifier = 0xFF;
  2169. while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  2170. {
  2171. while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  2172. System.Threading.Thread.Sleep(1);
  2173. data = new byte[2100];
  2174. Array.Copy(readBuffer, 0, data, 6, readBuffer.Length);
  2175. receivedUnitIdentifier = data[6];
  2176. countRetries = 0;
  2177. }
  2178.  
  2179. }
  2180. else if (tcpClient.Client.Connected | udpFlag)
  2181. {
  2182. if (udpFlag)
  2183. {
  2184. UdpClient udpClient = new UdpClient();
  2185. IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port);
  2186. udpClient.Send(data, data.Length - 2, endPoint);
  2187. portOut = ((IPEndPoint) udpClient.Client.LocalEndPoint).Port;
  2188. udpClient.Client.ReceiveTimeout = 5000;
  2189. endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut);
  2190. data = udpClient.Receive(ref endPoint);
  2191. }
  2192. else
  2193. {
  2194. stream.Write(data, 0, data.Length - 2);
  2195. if (debug)
  2196. {
  2197. byte [] debugData = new byte[data.Length - 2];
  2198. Array.Copy(data, 0, debugData, 0, data.Length - 2);
  2199. if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  2200. }
  2201. if (sendDataChanged != null)
  2202. {
  2203. sendData = new byte[data.Length - 2];
  2204. Array.Copy(data, 0, sendData, 0, data.Length - 2);
  2205. sendDataChanged(this);
  2206.  
  2207. }
  2208. data = new Byte[2100];
  2209. int NumberOfBytes = stream.Read(data, 0, data.Length);
  2210. if (receiveDataChanged != null)
  2211. {
  2212. receiveData = new byte[NumberOfBytes];
  2213. Array.Copy(data, 0, receiveData, 0, NumberOfBytes);
  2214. if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now);
  2215. receiveDataChanged(this);
  2216. }
  2217. }
  2218. }
  2219. if (data[7] == 0x85 & data[8] == 0x01)
  2220. {
  2221. if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now);
  2222. throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master");
  2223. }
  2224. if (data[7] == 0x85 & data[8] == 0x02)
  2225. {
  2226. if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now);
  2227. throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid");
  2228. }
  2229. if (data[7] == 0x85 & data[8] == 0x03)
  2230. {
  2231. if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now);
  2232. throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid");
  2233. }
  2234. if (data[7] == 0x85 & data[8] == 0x04)
  2235. {
  2236. if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now);
  2237. throw new EasyModbus.Exceptions.ModbusException("error reading");
  2238. }
  2239. if (serialport != null)
  2240. {
  2241. crc = BitConverter.GetBytes(calculateCRC(data, 6, 6));
  2242. if ((crc[0] != data[12] | crc[1] != data[13]) & dataReceived)
  2243. {
  2244. if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now);
  2245. if (NumberOfRetries <= countRetries)
  2246. {
  2247. countRetries = 0;
  2248. throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed");
  2249. }
  2250. else
  2251. {
  2252. countRetries++;
  2253. WriteSingleCoil(startingAddress, value);
  2254. }
  2255. }
  2256. else if (!dataReceived)
  2257. {
  2258. if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now);
  2259. if (NumberOfRetries <= countRetries)
  2260. {
  2261. countRetries = 0;
  2262. throw new TimeoutException("No Response from Modbus Slave");
  2263.  
  2264. }
  2265. else
  2266. {
  2267. countRetries++;
  2268. WriteSingleCoil(startingAddress, value);
  2269. }
  2270. }
  2271. }
  2272. }
  2273.  
  2274.  
  2275. /// <summary>
  2276. /// Write single Register to Master device (FC6).
  2277. /// </summary>
  2278. /// <param name="startingAddress">Register to be written</param>
  2279. /// <param name="value">Register Value to be written</param>
  2280. public void WriteSingleRegister(int startingAddress, int value)
  2281. {
  2282. if (debug) StoreLogData.Instance.Store("FC6 (Write single register to Master device), StartingAddress: " + startingAddress + ", Value: " + value, System.DateTime.Now);
  2283. transactionIdentifierInternal++;
  2284. if (serialport != null)
  2285. if (!serialport.IsOpen)
  2286. {
  2287. if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now);
  2288. throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
  2289. }
  2290. if (tcpClient == null & !udpFlag & serialport == null)
  2291. {
  2292. if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now);
  2293. throw new EasyModbus.Exceptions.ConnectionException("connection error");
  2294. }
  2295. byte[] registerValue = new byte[2];
  2296. this.transactionIdentifier = BitConverter.GetBytes((uint) transactionIdentifierInternal);
  2297. this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000);
  2298. this.length = BitConverter.GetBytes((int) 0x0006);
  2299. this.functionCode = 0x06;
  2300. this.startingAddress = BitConverter.GetBytes(startingAddress);
  2301. registerValue = BitConverter.GetBytes((int) value);
  2302.  
  2303. Byte[] data = new byte[]{ this.transactionIdentifier[1],
  2304. this.transactionIdentifier[0],
  2305. this.protocolIdentifier[1],
  2306. this.protocolIdentifier[0],
  2307. this.length[1],
  2308. this.length[0],
  2309. this.unitIdentifier,
  2310. this.functionCode,
  2311. this.startingAddress[1],
  2312. this.startingAddress[0],
  2313. registerValue[1],
  2314. registerValue[0],
  2315. this.crc[0],
  2316. this.crc[1]
  2317. };
  2318. crc = BitConverter.GetBytes(calculateCRC(data, 6, 6));
  2319. data[12] = crc[0];
  2320. data[13] = crc[1];
  2321. if (serialport != null)
  2322. {
  2323. dataReceived = false;
  2324. bytesToRead = 8;
  2325. // serialport.ReceivedBytesThreshold = bytesToRead;
  2326. serialport.Write(data, 6, 8);
  2327. if (debug)
  2328. {
  2329. byte [] debugData = new byte[8];
  2330. Array.Copy(data, 6, debugData, 0, 8);
  2331. if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  2332. }
  2333. if (sendDataChanged != null)
  2334. {
  2335. sendData = new byte[8];
  2336. Array.Copy(data, 6, sendData, 0, 8);
  2337. sendDataChanged(this);
  2338.  
  2339. }
  2340. data = new byte[2100];
  2341. readBuffer = new byte[256];
  2342. DateTime dateTimeSend = DateTime.Now;
  2343. byte receivedUnitIdentifier = 0xFF;
  2344. while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  2345. {
  2346. while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  2347. System.Threading.Thread.Sleep(1);
  2348. data = new byte[2100];
  2349. Array.Copy(readBuffer, 0, data, 6, readBuffer.Length);
  2350. receivedUnitIdentifier = data[6];
  2351. }
  2352. if (receivedUnitIdentifier != this.unitIdentifier)
  2353. data = new byte[2100];
  2354. else
  2355. countRetries = 0;
  2356. }
  2357. else if (tcpClient.Client.Connected | udpFlag)
  2358. {
  2359. if (udpFlag)
  2360. {
  2361. UdpClient udpClient = new UdpClient();
  2362. IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port);
  2363. udpClient.Send(data, data.Length - 2, endPoint);
  2364. portOut = ((IPEndPoint) udpClient.Client.LocalEndPoint).Port;
  2365. udpClient.Client.ReceiveTimeout = 5000;
  2366. endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut);
  2367. data = udpClient.Receive(ref endPoint);
  2368. }
  2369. else
  2370. {
  2371. stream.Write(data, 0, data.Length - 2);
  2372. if (debug)
  2373. {
  2374. byte [] debugData = new byte[data.Length - 2];
  2375. Array.Copy(data, 0, debugData, 0, data.Length - 2);
  2376. if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  2377. }
  2378. if (sendDataChanged != null)
  2379. {
  2380. sendData = new byte[data.Length - 2];
  2381. Array.Copy(data, 0, sendData, 0, data.Length - 2);
  2382. sendDataChanged(this);
  2383.  
  2384. }
  2385. data = new Byte[2100];
  2386. int NumberOfBytes = stream.Read(data, 0, data.Length);
  2387. if (receiveDataChanged != null)
  2388. {
  2389. receiveData = new byte[NumberOfBytes];
  2390. Array.Copy(data, 0, receiveData, 0, NumberOfBytes);
  2391. if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now);
  2392. receiveDataChanged(this);
  2393. }
  2394. }
  2395. }
  2396. if (data[7] == 0x86 & data[8] == 0x01)
  2397. {
  2398. if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now);
  2399. throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master");
  2400. }
  2401. if (data[7] == 0x86 & data[8] == 0x02)
  2402. {
  2403. if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now);
  2404. throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid");
  2405. }
  2406. if (data[7] == 0x86 & data[8] == 0x03)
  2407. {
  2408. if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now);
  2409. throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid");
  2410. }
  2411. if (data[7] == 0x86 & data[8] == 0x04)
  2412. {
  2413. if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now);
  2414. throw new EasyModbus.Exceptions.ModbusException("error reading");
  2415. }
  2416. if (serialport != null)
  2417. {
  2418. crc = BitConverter.GetBytes(calculateCRC(data, 6, 6));
  2419. if ((crc[0] != data[12] | crc[1] != data[13]) & dataReceived)
  2420. {
  2421. if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now);
  2422. if (NumberOfRetries <= countRetries)
  2423. {
  2424. countRetries = 0;
  2425. throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed");
  2426. }
  2427. else
  2428. {
  2429. countRetries++;
  2430. WriteSingleRegister(startingAddress, value);
  2431. }
  2432. }
  2433. else if (!dataReceived)
  2434. {
  2435. if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now);
  2436. if (NumberOfRetries <= countRetries)
  2437. {
  2438. countRetries = 0;
  2439. throw new TimeoutException("No Response from Modbus Slave");
  2440.  
  2441. }
  2442. else
  2443. {
  2444. countRetries++;
  2445. WriteSingleRegister(startingAddress, value);
  2446. }
  2447. }
  2448. }
  2449. }
  2450.  
  2451. /// <summary>
  2452. /// Write multiple coils to Master device (FC15).
  2453. /// </summary>
  2454. /// <param name="startingAddress">First coil to be written</param>
  2455. /// <param name="values">Coil Values to be written</param>
  2456. public void WriteMultipleCoils(int startingAddress, bool[] values)
  2457. {
  2458. string debugString = "";
  2459. for (int i = 0; i < values.Length;i++)
  2460. debugString = debugString + values[i] + " ";
  2461. if (debug) StoreLogData.Instance.Store("FC15 (Write multiple coils to Master device), StartingAddress: " + startingAddress + ", Values: " + debugString, System.DateTime.Now);
  2462. transactionIdentifierInternal++;
  2463. byte byteCount = (byte) ((values.Length % 8 != 0 ? values.Length / 8 + 1 : (values.Length / 8)));
  2464. byte[] quantityOfOutputs = BitConverter.GetBytes((int) values.Length);
  2465. byte singleCoilValue = 0;
  2466. if (serialport != null)
  2467. if (!serialport.IsOpen)
  2468. {
  2469. if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now);
  2470. throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
  2471. }
  2472. if (tcpClient == null & !udpFlag & serialport == null)
  2473. {
  2474. if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now);
  2475. throw new EasyModbus.Exceptions.ConnectionException("connection error");
  2476. }
  2477. this.transactionIdentifier = BitConverter.GetBytes((uint) transactionIdentifierInternal);
  2478. this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000);
  2479. this.length = BitConverter.GetBytes((int) (7 + (byteCount)));
  2480. this.functionCode = 0x0F;
  2481. this.startingAddress = BitConverter.GetBytes(startingAddress);
  2482.  
  2483.  
  2484.  
  2485. Byte[] data = new byte[14 + 2 + (values.Length % 8 != 0 ? values.Length / 8 : (values.Length / 8) - 1)];
  2486. data[0] = this.transactionIdentifier[1];
  2487. data[1] = this.transactionIdentifier[0];
  2488. data[2] = this.protocolIdentifier[1];
  2489. data[3] = this.protocolIdentifier[0];
  2490. data[4] = this.length[1];
  2491. data[5] = this.length[0];
  2492. data[6] = this.unitIdentifier;
  2493. data[7] = this.functionCode;
  2494. data[8] = this.startingAddress[1];
  2495. data[9] = this.startingAddress[0];
  2496. data[10] = quantityOfOutputs[1];
  2497. data[11] = quantityOfOutputs[0];
  2498. data[12] = byteCount;
  2499. for (int i = 0; i < values.Length; i++)
  2500. {
  2501. if ((i % 8) == 0)
  2502. singleCoilValue = 0;
  2503. byte CoilValue;
  2504. if (values[i] == true)
  2505. CoilValue = 1;
  2506. else
  2507. CoilValue = 0;
  2508.  
  2509.  
  2510. singleCoilValue = (byte) ((int) CoilValue << (i % 8) | (int) singleCoilValue);
  2511.  
  2512. data[13 + (i / 8)] = singleCoilValue;
  2513. }
  2514. crc = BitConverter.GetBytes(calculateCRC(data, (ushort) (data.Length - 8), 6));
  2515. data[data.Length - 2] = crc[0];
  2516. data[data.Length - 1] = crc[1];
  2517. if (serialport != null)
  2518. {
  2519. dataReceived = false;
  2520. bytesToRead = 8;
  2521. // serialport.ReceivedBytesThreshold = bytesToRead;
  2522. serialport.Write(data, 6, data.Length - 6);
  2523. if (debug)
  2524. {
  2525. byte [] debugData = new byte[data.Length - 6];
  2526. Array.Copy(data, 6, debugData, 0, data.Length - 6);
  2527. if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  2528. }
  2529. if (sendDataChanged != null)
  2530. {
  2531. sendData = new byte[data.Length - 6];
  2532. Array.Copy(data, 6, sendData, 0, data.Length - 6);
  2533. sendDataChanged(this);
  2534.  
  2535. }
  2536. data = new byte[2100];
  2537. readBuffer = new byte[256];
  2538. DateTime dateTimeSend = DateTime.Now;
  2539. byte receivedUnitIdentifier = 0xFF;
  2540. while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  2541. {
  2542. while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  2543. System.Threading.Thread.Sleep(1);
  2544. data = new byte[2100];
  2545. Array.Copy(readBuffer, 0, data, 6, readBuffer.Length);
  2546. receivedUnitIdentifier = data[6];
  2547. }
  2548. if (receivedUnitIdentifier != this.unitIdentifier)
  2549. data = new byte[2100];
  2550. else
  2551. countRetries = 0;
  2552. }
  2553. else if (tcpClient.Client.Connected | udpFlag)
  2554. {
  2555. if (udpFlag)
  2556. {
  2557. UdpClient udpClient = new UdpClient();
  2558. IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port);
  2559. udpClient.Send(data, data.Length - 2, endPoint);
  2560. portOut = ((IPEndPoint) udpClient.Client.LocalEndPoint).Port;
  2561. udpClient.Client.ReceiveTimeout = 5000;
  2562. endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut);
  2563. data = udpClient.Receive(ref endPoint);
  2564. }
  2565. else
  2566. {
  2567. stream.Write(data, 0, data.Length - 2);
  2568. if (debug)
  2569. {
  2570. byte [] debugData = new byte[data.Length - 2];
  2571. Array.Copy(data, 0, debugData, 0, data.Length - 2);
  2572. if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  2573. }
  2574. if (sendDataChanged != null)
  2575. {
  2576. sendData = new byte[data.Length - 2];
  2577. Array.Copy(data, 0, sendData, 0, data.Length - 2);
  2578. sendDataChanged(this);
  2579.  
  2580. }
  2581. data = new Byte[2100];
  2582. int NumberOfBytes = stream.Read(data, 0, data.Length);
  2583. if (receiveDataChanged != null)
  2584. {
  2585. receiveData = new byte[NumberOfBytes];
  2586. Array.Copy(data, 0, receiveData, 0, NumberOfBytes);
  2587. if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now);
  2588. receiveDataChanged(this);
  2589. }
  2590. }
  2591. }
  2592. if (data[7] == 0x8F & data[8] == 0x01)
  2593. {
  2594. if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now);
  2595. throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master");
  2596. }
  2597. if (data[7] == 0x8F & data[8] == 0x02)
  2598. {
  2599. if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now);
  2600. throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid");
  2601. }
  2602. if (data[7] == 0x8F & data[8] == 0x03)
  2603. {
  2604. if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now);
  2605. throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid");
  2606. }
  2607. if (data[7] == 0x8F & data[8] == 0x04)
  2608. {
  2609. if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now);
  2610. throw new EasyModbus.Exceptions.ModbusException("error reading");
  2611. }
  2612. if (serialport != null)
  2613. {
  2614. crc = BitConverter.GetBytes(calculateCRC(data, 6, 6));
  2615. if ((crc[0] != data[12] | crc[1] != data[13]) & dataReceived)
  2616. {
  2617. if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now);
  2618. if (NumberOfRetries <= countRetries)
  2619. {
  2620. countRetries = 0;
  2621. throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed");
  2622. }
  2623. else
  2624. {
  2625. countRetries++;
  2626. WriteMultipleCoils(startingAddress, values);
  2627. }
  2628. }
  2629. else if (!dataReceived)
  2630. {
  2631. if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now);
  2632. if (NumberOfRetries <= countRetries)
  2633. {
  2634. countRetries = 0;
  2635. throw new TimeoutException("No Response from Modbus Slave");
  2636.  
  2637. }
  2638. else
  2639. {
  2640. countRetries++;
  2641. WriteMultipleCoils(startingAddress, values);
  2642. }
  2643. }
  2644. }
  2645. }
  2646.  
  2647. /// <summary>
  2648. /// Write multiple registers to Master device (FC16).
  2649. /// </summary>
  2650. /// <param name="startingAddress">First register to be written</param>
  2651. /// <param name="values">register Values to be written</param>
  2652. public void WriteMultipleRegisters(int startingAddress, int[] values)
  2653. {
  2654. string debugString = "";
  2655. for (int i = 0; i < values.Length;i++)
  2656. debugString = debugString + values[i] + " ";
  2657. if (debug) StoreLogData.Instance.Store("FC16 (Write multiple Registers to Server device), StartingAddress: " + startingAddress + ", Values: " + debugString, System.DateTime.Now);
  2658. transactionIdentifierInternal++;
  2659. byte byteCount = (byte) (values.Length * 2);
  2660. byte[] quantityOfOutputs = BitConverter.GetBytes((int) values.Length);
  2661. if (serialport != null)
  2662. if (!serialport.IsOpen)
  2663. {
  2664. if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now);
  2665. throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
  2666. }
  2667. if (tcpClient == null & !udpFlag & serialport == null)
  2668. {
  2669. if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now);
  2670. throw new EasyModbus.Exceptions.ConnectionException("connection error");
  2671. }
  2672. this.transactionIdentifier = BitConverter.GetBytes((uint) transactionIdentifierInternal);
  2673. this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000);
  2674. this.length = BitConverter.GetBytes((int) (7 + values.Length * 2));
  2675. this.functionCode = 0x10;
  2676. this.startingAddress = BitConverter.GetBytes(startingAddress);
  2677.  
  2678. Byte[] data = new byte[13 + 2 + values.Length * 2];
  2679. data[0] = this.transactionIdentifier[1];
  2680. data[1] = this.transactionIdentifier[0];
  2681. data[2] = this.protocolIdentifier[1];
  2682. data[3] = this.protocolIdentifier[0];
  2683. data[4] = this.length[1];
  2684. data[5] = this.length[0];
  2685. data[6] = this.unitIdentifier;
  2686. data[7] = this.functionCode;
  2687. data[8] = this.startingAddress[1];
  2688. data[9] = this.startingAddress[0];
  2689. data[10] = quantityOfOutputs[1];
  2690. data[11] = quantityOfOutputs[0];
  2691. data[12] = byteCount;
  2692. for (int i = 0; i < values.Length; i++)
  2693. {
  2694. byte[] singleRegisterValue = BitConverter.GetBytes((int) values[i]);
  2695. data[13 + i * 2] = singleRegisterValue[1];
  2696. data[14 + i * 2] = singleRegisterValue[0];
  2697. }
  2698. crc = BitConverter.GetBytes(calculateCRC(data, (ushort) (data.Length - 8), 6));
  2699. data[data.Length - 2] = crc[0];
  2700. data[data.Length - 1] = crc[1];
  2701. if (serialport != null)
  2702. {
  2703. dataReceived = false;
  2704. bytesToRead = 8;
  2705. // serialport.ReceivedBytesThreshold = bytesToRead;
  2706. serialport.Write(data, 6, data.Length - 6);
  2707.  
  2708. if (debug)
  2709. {
  2710. byte [] debugData = new byte[data.Length - 6];
  2711. Array.Copy(data, 6, debugData, 0, data.Length - 6);
  2712. if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  2713. }
  2714. if (sendDataChanged != null)
  2715. {
  2716. sendData = new byte[data.Length - 6];
  2717. Array.Copy(data, 6, sendData, 0, data.Length - 6);
  2718. sendDataChanged(this);
  2719.  
  2720. }
  2721. data = new byte[2100];
  2722. readBuffer = new byte[256];
  2723. DateTime dateTimeSend = DateTime.Now;
  2724. byte receivedUnitIdentifier = 0xFF;
  2725. while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  2726. {
  2727. while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  2728. System.Threading.Thread.Sleep(1);
  2729. data = new byte[2100];
  2730. Array.Copy(readBuffer, 0, data, 6, readBuffer.Length);
  2731. receivedUnitIdentifier = data[6];
  2732. }
  2733. if (receivedUnitIdentifier != this.unitIdentifier)
  2734. data = new byte[2100];
  2735. else
  2736. countRetries = 0;
  2737. }
  2738. else if (tcpClient.Client.Connected | udpFlag)
  2739. {
  2740. if (udpFlag)
  2741. {
  2742. UdpClient udpClient = new UdpClient();
  2743. IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port);
  2744. udpClient.Send(data, data.Length - 2, endPoint);
  2745. portOut = ((IPEndPoint) udpClient.Client.LocalEndPoint).Port;
  2746. udpClient.Client.ReceiveTimeout = 5000;
  2747. endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut);
  2748. data = udpClient.Receive(ref endPoint);
  2749. }
  2750. else
  2751. {
  2752. stream.Write(data, 0, data.Length - 2);
  2753. if (debug)
  2754. {
  2755. byte [] debugData = new byte[data.Length - 2];
  2756. Array.Copy(data, 0, debugData, 0, data.Length - 2);
  2757. if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  2758. }
  2759. if (sendDataChanged != null)
  2760. {
  2761. sendData = new byte[data.Length - 2];
  2762. Array.Copy(data, 0, sendData, 0, data.Length - 2);
  2763. sendDataChanged(this);
  2764. }
  2765. data = new Byte[2100];
  2766. int NumberOfBytes = stream.Read(data, 0, data.Length);
  2767. if (receiveDataChanged != null)
  2768. {
  2769. receiveData = new byte[NumberOfBytes];
  2770. Array.Copy(data, 0, receiveData, 0, NumberOfBytes);
  2771. if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now);
  2772. receiveDataChanged(this);
  2773. }
  2774. }
  2775. }
  2776. if (data[7] == 0x90 & data[8] == 0x01)
  2777. {
  2778. if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now);
  2779. throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master");
  2780. }
  2781. if (data[7] == 0x90 & data[8] == 0x02)
  2782. {
  2783. if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now);
  2784. throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid");
  2785. }
  2786. if (data[7] == 0x90 & data[8] == 0x03)
  2787. {
  2788. if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now);
  2789. throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid");
  2790. }
  2791. if (data[7] == 0x90 & data[8] == 0x04)
  2792. {
  2793. if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now);
  2794. throw new EasyModbus.Exceptions.ModbusException("error reading");
  2795. }
  2796. if (serialport != null)
  2797. {
  2798. crc = BitConverter.GetBytes(calculateCRC(data, 6, 6));
  2799. if ((crc[0] != data[12] | crc[1] != data[13]) & dataReceived)
  2800. {
  2801. if (debug) StoreLogData.Instance.Store("CRCCheckFailedException Throwed", System.DateTime.Now);
  2802. if (NumberOfRetries <= countRetries)
  2803. {
  2804. countRetries = 0;
  2805. throw new EasyModbus.Exceptions.CRCCheckFailedException("Response CRC check failed");
  2806. }
  2807. else
  2808. {
  2809. countRetries++;
  2810. WriteMultipleRegisters(startingAddress, values);
  2811. }
  2812. }
  2813. else if (!dataReceived)
  2814. {
  2815. if (debug) StoreLogData.Instance.Store("TimeoutException Throwed", System.DateTime.Now);
  2816. if (NumberOfRetries <= countRetries)
  2817. {
  2818. countRetries = 0;
  2819. throw new TimeoutException("No Response from Modbus Slave");
  2820.  
  2821. }
  2822. else
  2823. {
  2824. countRetries++;
  2825. WriteMultipleRegisters(startingAddress, values);
  2826. }
  2827. }
  2828. }
  2829. }
  2830.  
  2831. /// <summary>
  2832. /// Read/Write Multiple Registers (FC23).
  2833. /// </summary>
  2834. /// <param name="startingAddressRead">First input register to read</param>
  2835. /// <param name="quantityRead">Number of input registers to read</param>
  2836. /// <param name="startingAddressWrite">First input register to write</param>
  2837. /// <param name="values">Values to write</param>
  2838. /// <returns>Int Array which contains the Holding registers</returns>
  2839. public int[] ReadWriteMultipleRegisters(int startingAddressRead, int quantityRead, int startingAddressWrite, int[] values)
  2840. {
  2841.  
  2842. string debugString = "";
  2843. for (int i = 0; i < values.Length;i++)
  2844. debugString = debugString + values[i] + " ";
  2845. if (debug) StoreLogData.Instance.Store("FC23 (Read and Write multiple Registers to Server device), StartingAddress Read: " + startingAddressRead + ", Quantity Read: " + quantityRead + ", startingAddressWrite: " + startingAddressWrite + ", Values: " + debugString, System.DateTime.Now);
  2846. transactionIdentifierInternal++;
  2847. byte [] startingAddressReadLocal = new byte[2];
  2848. byte [] quantityReadLocal = new byte[2];
  2849. byte[] startingAddressWriteLocal = new byte[2];
  2850. byte[] quantityWriteLocal = new byte[2];
  2851. byte writeByteCountLocal = 0;
  2852. if (serialport != null)
  2853. if (!serialport.IsOpen)
  2854. {
  2855. if (debug) StoreLogData.Instance.Store("SerialPortNotOpenedException Throwed", System.DateTime.Now);
  2856. throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
  2857. }
  2858. if (tcpClient == null & !udpFlag & serialport == null)
  2859. {
  2860. if (debug) StoreLogData.Instance.Store("ConnectionException Throwed", System.DateTime.Now);
  2861. throw new EasyModbus.Exceptions.ConnectionException("connection error");
  2862. }
  2863. if (startingAddressRead > 65535 | quantityRead > 125 | startingAddressWrite > 65535 | values.Length > 121)
  2864. {
  2865. if (debug) StoreLogData.Instance.Store("ArgumentException Throwed", System.DateTime.Now);
  2866. throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 2000");
  2867. }
  2868. int[] response;
  2869. this.transactionIdentifier = BitConverter.GetBytes((uint) transactionIdentifierInternal);
  2870. this.protocolIdentifier = BitConverter.GetBytes((int) 0x0000);
  2871. this.length = BitConverter.GetBytes((int) 0x0006);
  2872. this.functionCode = 0x17;
  2873. startingAddressReadLocal = BitConverter.GetBytes(startingAddressRead);
  2874. quantityReadLocal = BitConverter.GetBytes(quantityRead);
  2875. startingAddressWriteLocal = BitConverter.GetBytes(startingAddressWrite);
  2876. quantityWriteLocal = BitConverter.GetBytes(values.Length);
  2877. writeByteCountLocal = Convert.ToByte(values.Length * 2);
  2878. Byte[] data = new byte[17 + 2 + values.Length * 2];
  2879. data[0] = this.transactionIdentifier[1];
  2880. data[1] = this.transactionIdentifier[0];
  2881. data[2] = this.protocolIdentifier[1];
  2882. data[3] = this.protocolIdentifier[0];
  2883. data[4] = this.length[1];
  2884. data[5] = this.length[0];
  2885. data[6] = this.unitIdentifier;
  2886. data[7] = this.functionCode;
  2887. data[8] = startingAddressReadLocal[1];
  2888. data[9] = startingAddressReadLocal[0];
  2889. data[10] = quantityReadLocal[1];
  2890. data[11] = quantityReadLocal[0];
  2891. data[12] = startingAddressWriteLocal[1];
  2892. data[13] = startingAddressWriteLocal[0];
  2893. data[14] = quantityWriteLocal[1];
  2894. data[15] = quantityWriteLocal[0];
  2895. data[16] = writeByteCountLocal;
  2896.  
  2897. for (int i = 0; i < values.Length; i++)
  2898. {
  2899. byte[] singleRegisterValue = BitConverter.GetBytes((int) values[i]);
  2900. data[17 + i * 2] = singleRegisterValue[1];
  2901. data[18 + i * 2] = singleRegisterValue[0];
  2902. }
  2903. crc = BitConverter.GetBytes(calculateCRC(data, (ushort) (data.Length - 8), 6));
  2904. data[data.Length - 2] = crc[0];
  2905. data[data.Length - 1] = crc[1];
  2906. if (serialport != null)
  2907. {
  2908. dataReceived = false;
  2909. bytesToRead = 5 + 2 * quantityRead;
  2910. // serialport.ReceivedBytesThreshold = bytesToRead;
  2911. serialport.Write(data, 6, data.Length - 6);
  2912. if (debug)
  2913. {
  2914. byte [] debugData = new byte[data.Length - 6];
  2915. Array.Copy(data, 6, debugData, 0, data.Length - 6);
  2916. if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  2917. }
  2918. if (sendDataChanged != null)
  2919. {
  2920. sendData = new byte[data.Length - 6];
  2921. Array.Copy(data, 6, sendData, 0, data.Length - 6);
  2922. sendDataChanged(this);
  2923. }
  2924. data = new byte[2100];
  2925. readBuffer = new byte[256];
  2926. DateTime dateTimeSend = DateTime.Now;
  2927. byte receivedUnitIdentifier = 0xFF;
  2928. while (receivedUnitIdentifier != this.unitIdentifier & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  2929. {
  2930. while (dataReceived == false & !((DateTime.Now.Ticks - dateTimeSend.Ticks) > TimeSpan.TicksPerMillisecond * this.connectTimeout))
  2931. System.Threading.Thread.Sleep(1);
  2932. data = new byte[2100];
  2933. Array.Copy(readBuffer, 0, data, 6, readBuffer.Length);
  2934. receivedUnitIdentifier = data[6];
  2935. }
  2936. if (receivedUnitIdentifier != this.unitIdentifier)
  2937. data = new byte[2100];
  2938. else
  2939. countRetries = 0;
  2940. }
  2941. else if (tcpClient.Client.Connected | udpFlag)
  2942. {
  2943. if (udpFlag)
  2944. {
  2945. UdpClient udpClient = new UdpClient();
  2946. IPEndPoint endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), port);
  2947. udpClient.Send(data, data.Length - 2, endPoint);
  2948. portOut = ((IPEndPoint) udpClient.Client.LocalEndPoint).Port;
  2949. udpClient.Client.ReceiveTimeout = 5000;
  2950. endPoint = new IPEndPoint(System.Net.IPAddress.Parse(ipAddress), portOut);
  2951. data = udpClient.Receive(ref endPoint);
  2952. }
  2953. else
  2954. {
  2955. stream.Write(data, 0, data.Length - 2);
  2956. if (debug)
  2957. {
  2958. byte [] debugData = new byte[data.Length - 2];
  2959. Array.Copy(data, 0, debugData, 0, data.Length - 2);
  2960. if (debug) StoreLogData.Instance.Store("Send ModbusTCP-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
  2961. }
  2962. if (sendDataChanged != null)
  2963. {
  2964. sendData = new byte[data.Length - 2];
  2965. Array.Copy(data, 0, sendData, 0, data.Length - 2);
  2966. sendDataChanged(this);
  2967.  
  2968. }
  2969. data = new Byte[2100];
  2970. int NumberOfBytes = stream.Read(data, 0, data.Length);
  2971. if (receiveDataChanged != null)
  2972. {
  2973. receiveData = new byte[NumberOfBytes];
  2974. Array.Copy(data, 0, receiveData, 0, NumberOfBytes);
  2975. if (debug) StoreLogData.Instance.Store("Receive ModbusTCP-Data: " + BitConverter.ToString(receiveData), System.DateTime.Now);
  2976. receiveDataChanged(this);
  2977. }
  2978. }
  2979. }
  2980. if (data[7] == 0x97 & data[8] == 0x01)
  2981. {
  2982. if (debug) StoreLogData.Instance.Store("FunctionCodeNotSupportedException Throwed", System.DateTime.Now);
  2983. throw new EasyModbus.Exceptions.FunctionCodeNotSupportedException("Function code not supported by master");
  2984. }
  2985. if (data[7] == 0x97 & data[8] == 0x02)
  2986. {
  2987. if (debug) StoreLogData.Instance.Store("StartingAddressInvalidException Throwed", System.DateTime.Now);
  2988. throw new EasyModbus.Exceptions.StartingAddressInvalidException("Starting address invalid or starting address + quantity invalid");
  2989. }
  2990. if (data[7] == 0x97 & data[8] == 0x03)
  2991. {
  2992. if (debug) StoreLogData.Instance.Store("QuantityInvalidException Throwed", System.DateTime.Now);
  2993. throw new EasyModbus.Exceptions.QuantityInvalidException("quantity invalid");
  2994. }
  2995. if (data[7] == 0x97 & data[8] == 0x04)
  2996. {
  2997. if (debug) StoreLogData.Instance.Store("ModbusException Throwed", System.DateTime.Now);
  2998. throw new EasyModbus.Exceptions.ModbusException("error reading");
  2999. }
  3000. response = new int[quantityRead];
  3001. for (int i = 0; i < quantityRead; i++)
  3002. {
  3003. byte lowByte;
  3004. byte highByte;
  3005. highByte = data[9 + i * 2];
  3006. lowByte = data[9 + i * 2 + 1];
  3007.  
  3008. data[9 + i * 2] = lowByte;
  3009. data[9 + i * 2 + 1] = highByte;
  3010.  
  3011. response[i] = BitConverter.ToInt16(data, (9 + i * 2));
  3012. }
  3013. return (response);
  3014. }
  3015.  
  3016. /// <summary>
  3017. /// Close connection to Master Device.
  3018. /// </summary>
  3019. public void Disconnect()
  3020. {
  3021. if (debug) StoreLogData.Instance.Store("Disconnect", System.DateTime.Now);
  3022. if (serialport != null)
  3023. {
  3024. if (serialport.IsOpen & !this.receiveActive)
  3025. serialport.Close();
  3026. if (connectedChanged != null)
  3027. connectedChanged(this);
  3028. return;
  3029. }
  3030. if (stream != null)
  3031. stream.Close();
  3032. if (tcpClient != null)
  3033. tcpClient.Close();
  3034. connected = false;
  3035. if (connectedChanged != null)
  3036. connectedChanged(this);
  3037.  
  3038. }
  3039.  
  3040. /// <summary>
  3041. /// Destructor - Close connection to Master Device.
  3042. /// </summary>
  3043. ~ ModbusClient()
  3044. {
  3045. if (debug) StoreLogData.Instance.Store("Destructor called - automatically disconnect", System.DateTime.Now);
  3046. if (serialport != null)
  3047. {
  3048. if (serialport.IsOpen)
  3049. serialport.Close();
  3050. return;
  3051. }
  3052. if (tcpClient != null & !udpFlag)
  3053. {
  3054. if (stream != null)
  3055. stream.Close();
  3056. tcpClient.Close();
  3057. }
  3058. }
  3059.  
  3060. /// <summary>
  3061. /// Returns "TRUE" if Client is connected to Server and "FALSE" if not. In case of Modbus RTU returns if COM-Port is opened
  3062. /// </summary>
  3063. public bool Connected
  3064. {
  3065. get
  3066. {
  3067. if (serialport != null)
  3068. {
  3069. return (serialport.IsOpen);
  3070. }
  3071.  
  3072. if (udpFlag & tcpClient != null)
  3073. return true;
  3074. if (tcpClient == null)
  3075. return false;
  3076. else
  3077. {
  3078. return connected;
  3079.  
  3080. }
  3081.  
  3082. }
  3083. }
  3084.  
  3085. public bool Available(int timeout)
  3086. {
  3087. // Ping's the local machine.
  3088. System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping();
  3089. IPAddress address = System.Net.IPAddress.Parse(ipAddress);
  3090.  
  3091. // Create a buffer of 32 bytes of data to be transmitted.
  3092. string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
  3093. byte[] buffer = System.Text.Encoding.ASCII.GetBytes(data);
  3094.  
  3095. // Wait 10 seconds for a reply.
  3096. System.Net.NetworkInformation.PingReply reply = pingSender.Send(address, timeout, buffer);
  3097.  
  3098. if (reply.Status == System.Net.NetworkInformation.IPStatus.Success)
  3099. return true;
  3100. else
  3101. return false;
  3102. }
  3103.  
  3104. /// <summary>
  3105. /// Gets or Sets the IP-Address of the Server.
  3106. /// </summary>
  3107. public string IPAddress
  3108. {
  3109. get
  3110. {
  3111. return ipAddress;
  3112. }
  3113. set
  3114. {
  3115. ipAddress = value;
  3116. }
  3117. }
  3118.  
  3119. /// <summary>
  3120. /// Gets or Sets the Port were the Modbus-TCP Server is reachable (Standard is 502).
  3121. /// </summary>
  3122. public int Port
  3123. {
  3124. get
  3125. {
  3126. return port;
  3127. }
  3128. set
  3129. {
  3130. port = value;
  3131. }
  3132. }
  3133.  
  3134. /// <summary>
  3135. /// Gets or Sets the UDP-Flag to activate Modbus UDP.
  3136. /// </summary>
  3137. public bool UDPFlag
  3138. {
  3139. get
  3140. {
  3141. return udpFlag;
  3142. }
  3143. set
  3144. {
  3145. udpFlag = value;
  3146. }
  3147. }
  3148.  
  3149. /// <summary>
  3150. /// Gets or Sets the Unit identifier in case of serial connection (Default = 0)
  3151. /// </summary>
  3152. public byte UnitIdentifier
  3153. {
  3154. get
  3155. {
  3156. return unitIdentifier;
  3157. }
  3158. set
  3159. {
  3160. unitIdentifier = value;
  3161. }
  3162. }
  3163.  
  3164.  
  3165. /// <summary>
  3166. /// Gets or Sets the Baudrate for serial connection (Default = 9600)
  3167. /// </summary>
  3168. public int Baudrate
  3169. {
  3170. get
  3171. {
  3172. return baudRate;
  3173. }
  3174. set
  3175. {
  3176. baudRate = value;
  3177. }
  3178. }
  3179.  
  3180. /// <summary>
  3181. /// Gets or Sets the of Parity in case of serial connection
  3182. /// </summary>
  3183. public Parity Parity
  3184. {
  3185. get
  3186. {
  3187. if (serialport != null)
  3188. return parity;
  3189. else
  3190. return Parity.Even;
  3191. }
  3192. set
  3193. {
  3194. if (serialport != null)
  3195. parity = value;
  3196. }
  3197. }
  3198.  
  3199.  
  3200. /// <summary>
  3201. /// Gets or Sets the number of stopbits in case of serial connection
  3202. /// </summary>
  3203. public StopBits StopBits
  3204. {
  3205. get
  3206. {
  3207. if (serialport != null)
  3208. return stopBits;
  3209. else
  3210. return StopBits.One;
  3211. }
  3212. set
  3213. {
  3214. if (serialport != null)
  3215. stopBits = value;
  3216. }
  3217. }
  3218.  
  3219. /// <summary>
  3220. /// Gets or Sets the connection Timeout in case of ModbusTCP connection
  3221. /// </summary>
  3222. public int ConnectionTimeout
  3223. {
  3224. get
  3225. {
  3226. return connectTimeout;
  3227. }
  3228. set
  3229. {
  3230. connectTimeout = value;
  3231. }
  3232. }
  3233.  
  3234. /// <summary>
  3235. /// Gets or Sets the serial Port
  3236. /// </summary>
  3237. public string SerialPort
  3238. {
  3239. get
  3240. {
  3241.  
  3242. return serialport.PortName;
  3243. }
  3244. set
  3245. {
  3246. if (value == null)
  3247. {
  3248. serialport = null;
  3249. return;
  3250. }
  3251. if (serialport != null)
  3252. serialport.Close();
  3253. this.serialport = new SerialPort();
  3254. this.serialport.PortName = value;
  3255. serialport.BaudRate = baudRate;
  3256. serialport.Parity = parity;
  3257. serialport.StopBits = stopBits;
  3258. serialport.WriteTimeout = 10000;
  3259. serialport.ReadTimeout = connectTimeout;
  3260. serialport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
  3261. }
  3262. }
  3263.  
  3264. /// <summary>
  3265. /// Gets or Sets the Filename for the LogFile
  3266. /// </summary>
  3267. public string LogFileFilename
  3268. {
  3269. get
  3270. {
  3271. return StoreLogData.Instance.Filename;
  3272. }
  3273. set
  3274. {
  3275. StoreLogData.Instance.Filename = value;
  3276. if (StoreLogData.Instance.Filename != null)
  3277. debug = true;
  3278. else
  3279. debug = false;
  3280. }
  3281. }
  3282.  
  3283. /// <summary>
  3284. /// Gets or Sets the Mqtt Root Topic
  3285. /// </summary>
  3286. public string MqttRootTopic
  3287. {
  3288. get
  3289. {
  3290. return this.mqttRootTopic;
  3291. }
  3292. set
  3293. {
  3294. this.mqttRootTopic = value;
  3295. }
  3296. }
  3297.  
  3298. /// <summary>
  3299. /// Disables or Enables to Retain the Messages in the Broker - default is false (Enabled)
  3300. /// </summary>
  3301. public bool MqttRetainMessages
  3302. {
  3303. get
  3304. {
  3305. return this.mqttRetainMessages;
  3306. }
  3307. set
  3308. {
  3309. this.mqttRetainMessages = value;
  3310. }
  3311. }
  3312.  
  3313. }
  3314.  
  3315.  
  3316.  
  3317.  
  3318.  
  3319.  
  3320.  
  3321.  
  3322.  
  3323.  
  3324.  
  3325.  
  3326.  
  3327.  
  3328.  
  3329. //// StoreLogData.cs
  3330.  
  3331. namespace EasyModbus
  3332. {
  3333. /// <summary>
  3334. /// Store Log-Data in a File
  3335. /// </summary>
  3336. public sealed class StoreLogData
  3337. {
  3338. private String filename = null;
  3339. private static volatile StoreLogData instance;
  3340. private static object syncObject = new Object();
  3341.  
  3342. /// <summary>
  3343. /// Private constructor; Ensures the access of the class only via "instance"
  3344. /// </summary>
  3345. private StoreLogData()
  3346. {
  3347. }
  3348.  
  3349. /// <summary>
  3350. /// Returns the instance of the class (singleton)
  3351. /// </summary>
  3352. /// <returns>instance (Singleton)</returns>
  3353. public static StoreLogData Instance
  3354. {
  3355. get
  3356. {
  3357. if (instance == null)
  3358. {
  3359. lock (syncObject)
  3360. {
  3361. if (instance == null)
  3362. instance = new StoreLogData();
  3363. }
  3364. }
  3365.  
  3366. return instance;
  3367. }
  3368. }
  3369.  
  3370. /// <summary>
  3371. /// Store message in Log-File
  3372. /// </summary>
  3373. /// <param name="message">Message to append to the Log-File</param>
  3374. public void Store(String message)
  3375. {
  3376. if (this.filename == null)
  3377. return;
  3378.  
  3379. using (System.IO.StreamWriter file =
  3380. new System.IO.StreamWriter(Filename, true))
  3381. {
  3382. file.WriteLine(message);
  3383. }
  3384. }
  3385.  
  3386. /// <summary>
  3387. /// Store message in Log-File including Timestamp
  3388. /// </summary>
  3389. /// <param name="message">Message to append to the Log-File</param>
  3390. /// <param name="timestamp">Timestamp to add to the same Row</param>
  3391. public void Store(String message, DateTime timestamp)
  3392. {
  3393. try
  3394. {
  3395. using (System.IO.StreamWriter file =
  3396. new System.IO.StreamWriter(Filename, true))
  3397. {
  3398. file.WriteLine(timestamp.ToString("dd.MM.yyyy H:mm:ss.ff ") + message);
  3399. }
  3400. }
  3401. catch (Exception e)
  3402. {
  3403.  
  3404. }
  3405. }
  3406.  
  3407. /// <summary>
  3408. /// Gets or Sets the Filename to Store Strings in a File
  3409. /// </summary>
  3410. public string Filename
  3411. {
  3412. get
  3413. {
  3414. return filename;
  3415. }
  3416. set
  3417. {
  3418. filename = value;
  3419. }
  3420. }
  3421. }
  3422. }
  3423.  
  3424.  
  3425. // Exceptions.cs
  3426.  
  3427.  
  3428.  
  3429. namespace EasyModbus.Exceptions
  3430. {
  3431. /// <summary>
  3432. /// Exception to be thrown if serial port is not opened
  3433. /// </summary>
  3434. public class SerialPortNotOpenedException : ModbusException
  3435. {
  3436. public SerialPortNotOpenedException()
  3437. : base()
  3438. {
  3439. }
  3440.  
  3441. public SerialPortNotOpenedException(string message)
  3442. : base(message)
  3443. {
  3444. }
  3445.  
  3446. public SerialPortNotOpenedException(string message, Exception innerException)
  3447. : base(message, innerException)
  3448. {
  3449. }
  3450.  
  3451. protected SerialPortNotOpenedException(SerializationInfo info, StreamingContext context)
  3452. : base(info, context)
  3453. {
  3454. }
  3455. }
  3456.  
  3457. /// <summary>
  3458. /// Exception to be thrown if Connection to Modbus device failed
  3459. /// </summary>
  3460. public class ConnectionException : ModbusException
  3461. {
  3462. public ConnectionException()
  3463. : base()
  3464. {
  3465. }
  3466.  
  3467. public ConnectionException(string message)
  3468. : base(message)
  3469. {
  3470. }
  3471.  
  3472. public ConnectionException(string message, Exception innerException)
  3473. : base(message, innerException)
  3474. {
  3475. }
  3476.  
  3477. protected ConnectionException(SerializationInfo info, StreamingContext context)
  3478. : base(info, context)
  3479. {
  3480. }
  3481. }
  3482.  
  3483. /// <summary>
  3484. /// Exception to be thrown if Modbus Server returns error code "Function code not supported"
  3485. /// </summary>
  3486. public class FunctionCodeNotSupportedException : ModbusException
  3487. {
  3488. public FunctionCodeNotSupportedException()
  3489. : base()
  3490. {
  3491. }
  3492.  
  3493. public FunctionCodeNotSupportedException(string message)
  3494. : base(message)
  3495. {
  3496. }
  3497.  
  3498. public FunctionCodeNotSupportedException(string message, Exception innerException)
  3499. : base(message, innerException)
  3500. {
  3501. }
  3502.  
  3503. protected FunctionCodeNotSupportedException(SerializationInfo info, StreamingContext context)
  3504. : base(info, context)
  3505. {
  3506. }
  3507. }
  3508.  
  3509. /// <summary>
  3510. /// Exception to be thrown if Modbus Server returns error code "quantity invalid"
  3511. /// </summary>
  3512. public class QuantityInvalidException : ModbusException
  3513. {
  3514. public QuantityInvalidException()
  3515. : base()
  3516. {
  3517. }
  3518.  
  3519. public QuantityInvalidException(string message)
  3520. : base(message)
  3521. {
  3522. }
  3523.  
  3524. public QuantityInvalidException(string message, Exception innerException)
  3525. : base(message, innerException)
  3526. {
  3527. }
  3528.  
  3529. protected QuantityInvalidException(SerializationInfo info, StreamingContext context)
  3530. : base(info, context)
  3531. {
  3532. }
  3533. }
  3534.  
  3535. /// <summary>
  3536. /// Exception to be thrown if Modbus Server returns error code "starting adddress and quantity invalid"
  3537. /// </summary>
  3538. public class StartingAddressInvalidException : ModbusException
  3539. {
  3540. public StartingAddressInvalidException()
  3541. : base()
  3542. {
  3543. }
  3544.  
  3545. public StartingAddressInvalidException(string message)
  3546. : base(message)
  3547. {
  3548. }
  3549.  
  3550. public StartingAddressInvalidException(string message, Exception innerException)
  3551. : base(message, innerException)
  3552. {
  3553. }
  3554.  
  3555. protected StartingAddressInvalidException(SerializationInfo info, StreamingContext context)
  3556. : base(info, context)
  3557. {
  3558. }
  3559. }
  3560.  
  3561. /// <summary>
  3562. /// Exception to be thrown if Modbus Server returns error code "Function Code not executed (0x04)"
  3563. /// </summary>
  3564. public class ModbusException : Exception
  3565. {
  3566. public ModbusException()
  3567. : base()
  3568. {
  3569. }
  3570.  
  3571. public ModbusException(string message)
  3572. : base(message)
  3573. {
  3574. }
  3575.  
  3576. public ModbusException(string message, Exception innerException)
  3577. : base(message, innerException)
  3578. {
  3579. }
  3580.  
  3581. protected ModbusException(SerializationInfo info, StreamingContext context)
  3582. : base(info, context)
  3583. {
  3584. }
  3585. }
  3586.  
  3587. /// <summary>
  3588. /// Exception to be thrown if CRC Check failed
  3589. /// </summary>
  3590. public class CRCCheckFailedException : ModbusException
  3591. {
  3592. public CRCCheckFailedException()
  3593. : base()
  3594. {
  3595. }
  3596.  
  3597. public CRCCheckFailedException(string message)
  3598. : base(message)
  3599. {
  3600. }
  3601.  
  3602. public CRCCheckFailedException(string message, Exception innerException)
  3603. : base(message, innerException)
  3604. {
  3605. }
  3606.  
  3607. protected CRCCheckFailedException(SerializationInfo info, StreamingContext context)
  3608. : base(info, context)
  3609. {
  3610. }
  3611. }
  3612.  
  3613. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement