#include "BiolumeDriver.h"
#include "Syslog.h"

#define HvAdjusting "HV adj"
//maximum record length is as follows:
//record number 6 bytes
//cal string    9 bytes
//pump rpm      6 bytes
//flow rpm      6 bytes
//humidity      4 bytes
//temp          4 bytes
//raw(8*60 vals)480 bytes
//trailers      3 bytes
//total         398 bytes
#define MaxRecordBytes 1024 
#define ReadTimeout 10000
#define InvalidPmt -9999999.

#define PumpOnCmd "g"
#define StartCmd "P"
#define StopCmd "O"
#define YesCmd "Y"

// Serial parameters
#define Baud 19200
#define DataBits 8
#define StopBits 1
#define Parity "NONE"

BiolumeLog::BiolumeLog(DataLog::FileFormat fileFormat) 
  : DataLogWriter(BiolumeLogName, fileFormat, AutoTimeStamp)
{
char name[20];

  //default long name, UNKNOWN units
  addField(_RecordNum = new IntegerData("rrr"));

  //default long name, UNKNOWN units
  addField(_CalString = new FloatData("cal_striing"));

  //default long name, RPM units
  addField(_PumpRPM = new IntegerData("pump"));
  _PumpRPM->setUnits("RPM");

  //default long name, RPM units
  addField(_FlowRPM = new IntegerData("flow"));
  _FlowRPM->setUnits("RPM");

  //default long name, UNCALIBRATED units  
  addField(_Humidity = new IntegerData("humidity"));
  _Humidity->setUnits("UNCALIBRATED");

  //default long name, UNCALIBRATED units  
  addField(_Temperature = new IntegerData("temperature"));
  _Temperature->setUnits("UNCALIBRATED");

  //raw fields
  for (int i=0; i < 60; i++) {
    sprintf(name,"raw_%d\0",i);
    addField(_Raw[i] = new IntegerData(name));
    _Raw[i]->setUnits("UNCALIBRATED");
  }
}


BiolumeLog::~BiolumeLog()
{

  delete _RecordNum;
  delete _CalString;
  delete _PumpRPM;
  delete _FlowRPM;
  delete _Humidity;
  delete _Temperature;
  for (int i = 0; i < 60; i++)
    delete _Raw[i];
}


void BiolumeLog::setFields()
{
  // Doesn't need to do anything, as BiolumeDriver::processRecord() fills
  // field values directly.
}



BiolumeDriver::BiolumeDriver(SerialDevice *device, Boolean verbose)
  : StreamSerialDriver("biolumeDriver", device, MaxRecordBytes, "\xa", 
		       ReadTimeout)
 {
  _verbose = verbose;
  _log = new BiolumeLog(DataLog::BinaryFormat);
}



BiolumeDriver::~BiolumeDriver()
{
  // Stop data, pump, etc
  if (_device->write(StopCmd, strlen(StopCmd)) == -1) {
      Syslog::write("BiolumeDriver::~BiolumeDriver() - "
		    "device->write() failed");
  }

  delete _log;
}


DeviceIF::Status BiolumeDriver::initialize()
{
  // Initialize serial port
  _device->setLineFormat(Baud, DataBits, StopBits, Parity);

  char cmd[10];

  try {
    // Turn on pump
    strcpy(cmd, PumpOnCmd);
    if (_device->write(cmd, strlen(cmd)) == -1) {
      Syslog::write("BiolumeDriver::initialize() - device->write() failed");
      return DeviceIF::Error;
    }

    // Reset record number and start data streaming
    strcpy(cmd, StartCmd);
    if (_device->write(cmd, strlen(cmd)) == -1) {
      Syslog::write("BiolumeDriver::initialize() - device->write() failed");
      return DeviceIF::Error;
    }
  }

  catch (Exception e) {
    Syslog::write("BiolumeDriver::initialize() - caught exception: %s",
		  e.msg);

    return DeviceIF::Error;
  }

  return DeviceIF::Ok;
}



DeviceIF::Status BiolumeDriver::processRecord(unsigned char *record, 
					      int nRecordBytes)
{
  Boolean debug = _verbose;
  char *val;
  int ntokens = 0;
  
  dprintf("BiolumeDriver::processRecord - record=%s", record);

  if ((val = strtok((char *)record,","))){
    _log->_RecordNum->setValue(atoi(val));
    ntokens++;
  }

  if ((val = strtok(NULL,","))){
    _log->_CalString->setValue(atof(val));
    ntokens++;
  }

  if ((val = strtok(NULL,","))){
    _log->_PumpRPM->setValue(atoi(val));
    ntokens++;
  }

  if ((val = strtok(NULL,","))){
    _log->_FlowRPM->setValue(atoi(val));
    ntokens++;
  }

  if ((val = strtok(NULL,","))){
    _log->_Humidity->setValue(atoi(val));
    ntokens++;
  }

  if ((val = strtok(NULL,","))){
    _log->_Temperature->setValue(atoi(val));
    ntokens++;
  }

  for (int i=0; i<60; i++) {
    if ((val = strtok(NULL,","))) {
      _log->_Raw[i]->setValue(atoi(val));
      ntokens++;
    }
  }

  if (ntokens != 66) {
    Syslog::write("BiolumeDriver::processRecord() - parse error");
    return DeviceIF::Error;
  } else {
    _log->write();
  }

  return DeviceIF::Ok;
}

