9 #include <QCoreApplication>
40 connect(
m_timer, SIGNAL(timeout()),
51 void FRONIUS::slotQuit() {
67 BaudRateType speed = BAUD9600;
69 case 110: speed = BAUD110;
break;
70 case 300: speed = BAUD300;
break;
71 case 600: speed = BAUD600;
break;
72 case 1200: speed = BAUD1200;
break;
73 case 2400: speed = BAUD2400;
break;
74 case 4800: speed = BAUD4800;
break;
75 case 9600: speed = BAUD9600;
break;
76 case 19200: speed = BAUD19200;
break;
77 case 38400: speed = BAUD38400;
break;
78 case 57600: speed = BAUD57600;
break;
79 case 115200: speed = BAUD115200;
break;
82 spset.BaudRate = speed;
83 spset.DataBits = DATA_8;
84 spset.Parity = PAR_NONE;
85 spset.StopBits = STOP_1;
86 spset.FlowControl = FLOW_OFF;
87 spset.Timeout_Millisec =
m_line.timeout;
89 m_port =
new QextSerialPort(
m_line.device, spset, QextSerialPort::Polling);
90 m_port->open(QIODevice::ReadWrite);
94 err.error = tr(
"Could not open %1: %2").arg(
m_line.device).arg(
m_port->errorString());
103 tr(
"Could not open serial port %1").arg(
m_line.device)
105 QTimer::singleShot(3333,
this, SLOT(
open()));
111 m_retries =
m_line.retries;
140 tr(
"Sleeping %1 secs to begin new reading cycle").arg(secs)
142 m_timer->setInterval(secs*1000);
151 tr(
"Going to read next invertor")
174 tr(
"Reading header from serial port")
176 n =
m_port->read((
char *)&response, FRONIUS_response::HEADER_LENGTH );
179 if (n != FRONIUS_response::HEADER_LENGTH) {
180 throw tr(
"Header invalid: %1 bytes read, should be %2.")
182 .arg(FRONIUS_response::HEADER_LENGTH)
188 throw tr(
"Header invalid.");
196 tr(
"Reading rest of datagram from serial port")
198 n =
m_port->read((
char *)response.buffer.buffer, response.length+1);
202 throw tr(
"Response checksum error");
207 if (address >= 1000) {
208 address = address - 1000;
210 if (response.device_number != address) {
211 throw tr(
"Wrong invertor address in response: should be: %1, read: %2")
213 .arg(response.device_number)
218 if (response.command == FRONIUS_ERROR) {
220 throw tr(
"Error: %1").arg(errmsg);
246 tr(
"Writing command to serial port")
249 if (address >= 1000) {
250 address = address - 1000;
256 m_port->write((
char *)&request,
sizeof(request));
259 QEventLoop eventLoop;
260 QTimer::singleShot(300, &eventLoop, SLOT(
quit()));
277 if (command != response.command) {
280 throw tr(
"Bad response: requested command: %1 response: %2 ").arg(reqcmd).arg(reccmd);
286 case FRONIUS_CMD_GET_VERSION:
287 x = QString(
"%1 %2.%3.%4")
288 .arg(response.buffer.Version.ifcType)
289 .arg(response.buffer.Version.versionMajor)
290 .arg(response.buffer.Version.versionMinor)
291 .arg(response.buffer.Version.versionRelease)
294 case FRONIUS_CMD_GET_DEVICE_TYPE:
295 x = response.buffer.DeviceType.typeIdentification;
297 case FRONIUS_CMD_GET_DATE_TIME:
298 x = response.
value().toDouble() / 60.0;
300 case FRONIUS_CMD_GET_ACTIVE_INVERTOR_NUMBER:
301 case FRONIUS_CMD_GET_POWER_NOW:
302 case FRONIUS_CMD_GET_AC_CURRENT_NOW:
303 case FRONIUS_CMD_GET_AC_VOLTAGE_NOW:
304 case FRONIUS_CMD_GET_AC_FREQUENCY_NOW:
305 case FRONIUS_CMD_GET_DC_CURRENT_NOW:
306 case FRONIUS_CMD_GET_DC_VOLTAGE_NOW:
307 case FRONIUS_CMD_GET_ENERGY_DAY:
308 case FRONIUS_CMD_GET_MAXIMUM_POWER_DAY:
309 case FRONIUS_CMD_GET_MAXIMUM_AC_VOLTAGE_DAY:
310 case FRONIUS_CMD_GET_MINIMUM_AC_VOLTAGE_DAY:
311 case FRONIUS_CMD_GET_MAXIMUM_DC_VOLTAGE_DAY:
312 case FRONIUS_CMD_GET_ENERGY_TOTAL:
313 case FRONIUS_CMD_GET_MAXIMUM_POWER_TOTAL:
314 case FRONIUS_CMD_GET_MAXIMUM_AC_VOLTAGE_TOTAL:
315 case FRONIUS_CMD_GET_MINIMUM_AC_VOLTAGE_TOTAL:
316 case FRONIUS_CMD_GET_MAXIMUM_DC_VOLTAGE_TOTAL:
317 case FRONIUS_CMD_GET_TEMPERATURE_1:
318 case FRONIUS_CMD_GET_TEMPERATURE_2:
319 case FRONIUS_CMD_GET_IRRADIANCE:
320 x = response.
value();
322 case FRONIUS_CMD_GET_OPERATING_HOURS_DAY:
323 case FRONIUS_CMD_GET_OPERATING_HOURS_TOTAL:
324 x = response.
value().toDouble() / 60.0;
326 case FRONIUS_CMD_GET_ENERGY_YEAR:
327 case FRONIUS_CMD_GET_YIELD_YEAR:
328 case FRONIUS_CMD_GET_YIELD_DAY:
330 case FRONIUS_CMD_GET_INVERTOR_STATUS:
339 throw tr(
"Value cannot be recognized: %1")
363 x.invertor = invertor.invertor;
365 for (m_nr=m_retries; m_nr>0; m_nr--) {
367 if (invertor.now_power) x.now_power =
readValue(FRONIUS_CMD_GET_POWER_NOW).toDouble();
368 if (invertor.now_ac_current) x.now_ac_current =
readValue(FRONIUS_CMD_GET_AC_CURRENT_NOW).toDouble();
369 if (invertor.now_ac_voltage) x.now_ac_voltage =
readValue(FRONIUS_CMD_GET_AC_VOLTAGE_NOW).toDouble();
370 if (invertor.now_ac_frequency) x.now_ac_frequency =
readValue(FRONIUS_CMD_GET_AC_FREQUENCY_NOW).toDouble();
371 if (invertor.now_dc_current) x.now_dc_current =
readValue(FRONIUS_CMD_GET_DC_CURRENT_NOW).toDouble();
372 if (invertor.now_dc_voltage) x.now_dc_voltage =
readValue(FRONIUS_CMD_GET_DC_VOLTAGE_NOW).toDouble();
373 if (invertor.day_energy) x.day_energy =
readValue(FRONIUS_CMD_GET_ENERGY_DAY).toDouble();
374 if (invertor.day_power_maximum) x.day_power_maximum =
readValue(FRONIUS_CMD_GET_MAXIMUM_POWER_DAY).toDouble();
375 if (invertor.day_ac_voltage_maximum) x.day_ac_voltage_maximum =
readValue(FRONIUS_CMD_GET_MAXIMUM_AC_VOLTAGE_DAY).toDouble();
376 if (invertor.day_ac_voltage_minimum) x.day_ac_voltage_minimum =
readValue(FRONIUS_CMD_GET_MINIMUM_AC_VOLTAGE_DAY).toDouble();
377 if (invertor.day_dc_voltage_maximum) x.day_dc_voltage_maximum =
readValue(FRONIUS_CMD_GET_MAXIMUM_DC_VOLTAGE_DAY).toDouble();
378 if (invertor.day_operating_hours) x.day_operating_hours =
readValue(FRONIUS_CMD_GET_OPERATING_HOURS_DAY).toDouble();
379 if (invertor.total_energy) x.total_energy =
readValue(FRONIUS_CMD_GET_ENERGY_TOTAL).toDouble();
380 if (invertor.total_power_maximum) x.total_power_maximum =
readValue(FRONIUS_CMD_GET_MAXIMUM_POWER_TOTAL).toDouble();
381 if (invertor.total_ac_voltage_maximum) x.total_ac_voltage_maximum =
readValue(FRONIUS_CMD_GET_MAXIMUM_AC_VOLTAGE_TOTAL).toDouble();
382 if (invertor.total_ac_voltage_minimum) x.total_ac_voltage_minimum =
readValue(FRONIUS_CMD_GET_MINIMUM_AC_VOLTAGE_TOTAL).toDouble();
383 if (invertor.total_dc_voltage_maximum) x.total_dc_voltage_maximum =
readValue(FRONIUS_CMD_GET_MAXIMUM_DC_VOLTAGE_TOTAL).toDouble();
384 if (invertor.total_operating_hours) x.total_operating_hours =
readValue(FRONIUS_CMD_GET_OPERATING_HOURS_TOTAL).toDouble();
385 if (invertor.temperature_1) x.temperature_1 =
readValue(FRONIUS_CMD_GET_TEMPERATURE_1).toDouble();
386 if (invertor.temperature_2) x.temperature_2 =
readValue(FRONIUS_CMD_GET_TEMPERATURE_2).toDouble();
387 if (invertor.irradiance) x.irradiance =
readValue(FRONIUS_CMD_GET_IRRADIANCE).toDouble();
389 x.status =
readValue(FRONIUS_CMD_GET_INVERTOR_STATUS).toString();
390 }
catch (QString e) {
391 x.status =
"UNKNOWN";
399 qDebug() <<
"Repeated invertor reading:" << x.invertor <<
"try: " << m_nr;
405 tr(
"Error: %1").arg(e)
410 qDebug() <<
"Repeated invertor reading:" << x.invertor <<
"try: " << m_nr <<
"gave up";
412 x.error = QString(
"%1 Command: %2").arg(e).arg(cmdmsg);
424 if (x.now_power.toDouble() < 0)
throw tr(
"Now power < 0");
425 if (x.now_power.toDouble() > 15000)
throw tr(
"Now power > 15000");
435 QString commandString;
437 case FRONIUS_CMD_GET_VERSION:
438 commandString = tr(
"getVersion");
440 case FRONIUS_CMD_GET_DEVICE_TYPE:
441 commandString = tr(
"getDeviceType");
443 case FRONIUS_CMD_GET_DATE_TIME:
444 commandString = tr(
"getDateTime");
446 case FRONIUS_CMD_GET_ACTIVE_INVERTOR_NUMBER:
447 commandString = tr(
"getActiveInverterNumber");
449 case FRONIUS_CMD_GET_POWER_NOW:
450 commandString = tr(
"getPowerNow");
452 case FRONIUS_CMD_GET_ENERGY_TOTAL:
453 commandString = tr(
"getEnergyTotal");
455 case FRONIUS_CMD_GET_ENERGY_DAY:
456 commandString = tr(
"getEnergyDay");
458 case FRONIUS_CMD_GET_ENERGY_YEAR:
459 commandString = tr(
"getEnergyYear");
461 case FRONIUS_CMD_GET_AC_CURRENT_NOW:
462 commandString = tr(
"getACCurrentNow");
464 case FRONIUS_CMD_GET_AC_VOLTAGE_NOW:
465 commandString = tr(
"getACVoltageNow");
467 case FRONIUS_CMD_GET_AC_FREQUENCY_NOW:
468 commandString = tr(
"getACFrequencyNow");
470 case FRONIUS_CMD_GET_DC_CURRENT_NOW:
471 commandString = tr(
"getDCCurrentNow");
473 case FRONIUS_CMD_GET_DC_VOLTAGE_NOW:
474 commandString = tr(
"getDCVoltageNow");
476 case FRONIUS_CMD_GET_YIELD_DAY:
477 commandString = tr(
"getYieldDay");
479 case FRONIUS_CMD_GET_MAXIMUM_POWER_DAY:
480 commandString = tr(
"getMaximumPowerDay");
482 case FRONIUS_CMD_GET_MAXIMUM_AC_VOLTAGE_DAY:
483 commandString = tr(
"getMaximumACVoltageDay");
485 case FRONIUS_CMD_GET_MINIMUM_AC_VOLTAGE_DAY:
486 commandString = tr(
"getMinimumACVoltageDay");
488 case FRONIUS_CMD_GET_MAXIMUM_DC_VOLTAGE_DAY:
489 commandString = tr(
"getMaximumDCVoltageDay");
491 case FRONIUS_CMD_GET_OPERATING_HOURS_DAY:
492 commandString = tr(
"getOperatingHoursDay");
494 case FRONIUS_CMD_GET_YIELD_YEAR:
495 commandString = tr(
"getYieldYear");
497 case FRONIUS_CMD_GET_MAXIMUM_POWER_TOTAL:
498 commandString = tr(
"getMaximumPowerTotal");
500 case FRONIUS_CMD_GET_MAXIMUM_AC_VOLTAGE_TOTAL:
501 commandString = tr(
"getMaximumACVoltageTotal");
503 case FRONIUS_CMD_GET_MINIMUM_AC_VOLTAGE_TOTAL:
504 commandString = tr(
"getMinimumACVoltageTotal");
506 case FRONIUS_CMD_GET_MAXIMUM_DC_VOLTAGE_TOTAL:
507 commandString = tr(
"getMaximumDCVoltageTotal");
509 case FRONIUS_CMD_GET_OPERATING_HOURS_TOTAL:
510 commandString = tr(
"getOperatingHoursTotal");
512 case FRONIUS_CMD_GET_TEMPERATURE_1:
513 commandString = tr(
"getTemperature1");
515 case FRONIUS_CMD_GET_TEMPERATURE_2:
516 commandString = tr(
"getTemperature2");
518 case FRONIUS_CMD_GET_IRRADIANCE:
519 commandString = tr(
"getIrradiance");
522 commandString = tr(
"Unknown command");
525 return commandString;
536 switch (errorInformation) {
537 case FRONIUS_PROTOCOL_ERROR_UNKNOWN_COMMAND:
538 errorString = tr(
"unknown command");
540 case FRONIUS_PROTOCOL_ERROR_TIMEOUT:
541 errorString = tr(
"timeout");
543 case FRONIUS_PROTOCOL_ERROR_INCORRECT_DATA_STRUCTURE:
544 errorString = tr(
"incorrect data structure");
546 case FRONIUS_PROTOCOL_ERROR_COMMAND_QUEUE_FULL:
547 errorString = tr(
"command queue full");
549 case FRONIUS_PROTOCOL_ERROR_DEVICE_OR_OPTION_NA:
550 errorString = tr(
"device or option not available");
552 case FRONIUS_PROTOCOL_ERROR_NO_RESPONSE:
553 errorString = tr(
"no response");
555 case FRONIUS_PROTOCOL_ERROR_SENSOR_ERROR:
556 errorString = tr(
"sensor error");
558 case FRONIUS_PROTOCOL_ERROR_SENSOR_NOT_ACTIVE:
559 errorString = tr(
"sensor not active");
561 case FRONIUS_PROTOCOL_ERROR_INCORRECT_COMMAND:
562 errorString = tr(
"incorrect command");
564 case FRONIUS_PROTOCOL_ERROR_DEVICE_ID_COLLISION:
565 errorString = tr(
"device id collision");
568 errorString = tr(
"unknown error information");
581 QString statusString;
582 switch (statusInformation) {
583 case FRONIUS_STATUS_STARTUP:
584 statusString =
"STARTING";
586 case FRONIUS_STATUS_OPERATION:
587 statusString =
"MPPT";
589 case FRONIUS_STATUS_MANUAL_STANDBY:
590 statusString =
"STANDBY";
592 case FRONIUS_STATUS_FAILURE:
593 statusString =
"FAULT";
596 statusString =
"UNKNOWN";
void quit()
Quits the running thread.
void loop()
Loops the invertors's list.
QString decodeError(FRONIUS::Error)
Converts fronius error code to text description.
void readInvertor()
Reads values from current invertor.
QVariant value()
Decodes and returns value stored in response.
Response from fronius invertor.
void open()
Opens serial port.
void data(DBT_DATA)
Signal to send retrieved data to other objects.
void checkData(const DBT_DATA &)
Basic data check.
Error
List of all fronius error codes.
FRONIUS()
Constructor. The very basic initializations.
int m_current_invertor_index
Current index in INVERTOR::m_invertors list.
Class describing database table DATA.
QVariant readValue(FRONIUS::Command)
Reads one value from invertor.
DBT_LINES m_line
Stores information about line.
QList< DBT_INVERTORS > m_invertors
Stores information about all invertors connected to the line.
QTimer * m_timer
Timer for main loop.
bool isChecksumValid()
Check header validity.
Structure of fronius request sent to invertor over serial line.
QextSerialPort * m_port
Serial port device.
void readResponse(FRONIUS_response &)
Reads and checks response read from invertor.
QVariant decodeResponse(FRONIUS_response &, FRONIUS::Command)
Decode response from invertor and returnsi retrieved value.
QString decodeStatus(FRONIUS::Status)
Converts fronius error code to text description.
Virtual class for invertor communication.
Command m_command
Current command processed.
bool isHeaderValid()
Check header validity.
QString decodeCommand(FRONIUS::Command)
Converts fronius command code to text description.
void loopFinished(int number_of_ok, int number_of_err)
Signal is sent when reading cycle was finished and all invertors were read.
void slotInit()
Function called within running thread to initialize all needed child objects.
void setStatus(int address, int retries, const QString &command, const QString &status)
Set status of line.
Class describing database table INVERTORS.
Command
List of all fronius commands.