/*
  ModbusTCP dataloger
  Autor: Jiří Soviš

  Vypracováno pod GNU General Public License <http://www.gnu.org/licenses/>.
*/
#define WIZNET_W5100 1

#include <Ethernet.h>

IPAddress ModbusDeviceIP(192, 168, 1, 254); // Adresa programovatelné stanice
IPAddress moduleIPAddress(192, 168, 1, 253); // Adresa datalogeru

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xE1 };

#include <ModbusTCP.h>

ModbusTCP Modbus(1);

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4); // Adresa LCD, počet sloupců, počet řádků

#include <SPI.h>
#include <SD.h>

const int chipSelect = 4;

unsigned count = 0;     // počet správných požadavků
unsigned count2 = 0;    // počet chybových požadavků

int len = 0;            // množství dat v buferu - registers
int len2;               // množství dat v buferu - coils

void setup()
{
  lcd.begin();
  lcd.backlight();
  lcd.print("MODBUS dataloger");

  if (!SD.begin(chipSelect)) {
    lcd.setCursor(0, 1);      // sloupec 1, řádek 2
    lcd.print("SD err");
    while (1);
  }

  Ethernet.begin(mac, moduleIPAddress);
  Modbus.setServerIPAddress(ModbusDeviceIP);
  delay(4000);
}


void loop()
{
  File file = SD.open("datalog.txt", FILE_WRITE);
  uint8_t result;

  lcd.setCursor(17, 0);
  lcd.print("00");                                   // vymazání předchozího chybového kódu pro registry

  lcd.setCursor(17, 1);
  lcd.print("00");                                   // vymazání předchozího chybového kódu pro coily

  lcd.setCursor(0, 1);
  lcd.print("   ");                                  // vymazání chybové hlášky Err z předchozí chyby (3*mezera)


  Modbus.setTransactionID(random(1, 100));           // Transaction ID zprávy
  result = Modbus.readHoldingRegisters(1024, 16);    // Požadavek na 16 registrů (2byte * 16) od adresy 1024


  lcd.setCursor(17, 0);
  lcd.print(result, HEX);                             // vypiš chybový kód (pokud proběhl požadavek správně vypíše se 00)

  if (result != 0)                                    // požadavek neproběhl správně - chyba
  {
    lcd.setCursor(0, 1);
    lcd.print("Err1");

    ++count2;
    delay(200);
  }
  else  {

    len = Modbus.getResponseBufferLength();           // množství dat v bufferu

    ++count;

    // výpis dat do souboru
    if (file) {
      for (byte j = 0; j < len; j++)
      {
        file.print(Modbus.getResponseBuffer(j));
        file.print(",");
      }
    }

    // výpis - Datum a čas z přijatých dat z programovetelné stanice T2032CX
    lcd.setCursor(10, 2);
    lcd.print("20");
    lcd.print(Modbus.getResponseBuffer(5));
    lcd.print("-");
    lcd.print(Modbus.getResponseBuffer(3));
    lcd.print("-");
    lcd.print(Modbus.getResponseBuffer(0));

    lcd.setCursor(10, 3);
    lcd.print(Modbus.getResponseBuffer(2));
    lcd.print(":");
    lcd.print(Modbus.getResponseBuffer(1));
    lcd.print(":");
    lcd.print(Modbus.getResponseBuffer(4));
  }
  Modbus.clearResponseBuffer();



  Modbus.setTransactionID(random(1, 100));           // Transaction ID zprávy
  result = Modbus.readCoils(0, 6);                   // Požadavek na 6 coilů od adresy 0

  lcd.setCursor(17, 1);
  lcd.print(result, HEX);                             // vypiš chybový kód (pokud proběhl požadavek správně vypíše se 00)

  if (result != 0)
  {
    lcd.setCursor(6, 1);
    lcd.print("Err2");

    ++count2;
    delay(200);
  }
  else
  {
    len2 = Modbus.getResponseBufferLength();

    if (file) {
      for (byte j = 0; j < len2; j++)
      {
        file.print(Modbus.getResponseBuffer(j));
        file.print(",");
      }
    }

    ++count;
  }

  Modbus.clearResponseBuffer();


  file.println("\0\n");
  file.close();

  lcd.setCursor(0, 2);
  lcd.print(count);

  lcd.setCursor(0, 3);
  lcd.print(count2);
  delay(5000);
}
