#ifndef METERBUSMASTER_H_
#define METERBUSMASTER_H_

#include <WString.h>
#include <Print.h>
#include "cmd.h"
#include "mBusDialog.h"


const unsigned long RESPONSE_TIMEOUT = 2000;  // millisecond

const uint8_t RX_EN_PIN = 2;
const uint8_t RX_ENABLE = LOW;
const uint8_t RX_DISABLE = HIGH;

const uint8_t CURRENT_IN = A1;
const double U_UNIT = 4.9; // mV
const double R_SHUNT = 10.0;


class SendOctets : public Cmd, public ResponseCallback {
public:
  SendOctets(RequestSender *meterBusMaster) : m_meterBusMaster(meterBusMaster) {}
  virtual String getCmdName() { return "SO"; }
  virtual String getHelp() { return "Send octets"; }
  virtual String exec(String params);
  virtual void sendResponse(uint8_t *responseBuffer, uint16_t responseBufferLength);
  virtual void sendError(uint8_t code);
private:
  RequestSender *m_meterBusMaster;
};

class MeasureCurrent : public Cmd {
public:
  MeasureCurrent(RequestSender *meterBusMaster) : m_meterBusMaster(meterBusMaster) {}
  virtual String getCmdName() { return "MC"; }
  virtual String getHelp() { return "Measure current"; }
  virtual String exec(String params);
private:
  RequestSender *m_meterBusMaster;
};

class CalibrationSupport : public Cmd {
public:
  CalibrationSupport(RequestSender *meterBusMaster) : m_meterBusMaster(meterBusMaster), enable(false) {}
  virtual String getCmdName() { return "CS"; }
  virtual String getHelp() { return "Calibration Support"; }
  virtual String exec(String params);
private:
  RequestSender *m_meterBusMaster;
  bool enable;
};



const uint8_t SEND_BUFFER_SIZE = 30;
const uint8_t RECEIVE_BUFFER_SIZE = 180;

class MeterBusMaster : public RequestSender {
public:
  MeterBusMaster();
  void begin(CmdServer *cmdServer);
  void exec();
  uint8_t *getSendBuffer();
  void sendBufferReady(uint16_t bufLen, ResponseCallback *responseCallback);
  friend class CalibrationSupport;
private:
  SendOctets m_sendOctets;
  MeasureCurrent m_measureCurrent;
  CalibrationSupport m_calibrationSupport;
  bool m_cmdReadyToSend;
  bool m_cmdReadyFromRecv;
  bool m_expectResponse;
  uint16_t m_sendBufLen;
  uint16_t m_recvBufLen;
  uint8_t m_retransmitCount;
  ResponseCallback *m_responseCallback;
  uint8_t m_sendBuffer[SEND_BUFFER_SIZE];
  uint8_t m_recvBuffer[RECEIVE_BUFFER_SIZE];
  bool m_sampling;
  bool m_calibration;
  void prepareResponse(bool err, uint8_t in);
  void sample();
  void hold();

};



#endif /* METERBUSMASTER_H_ */