Changeset View
Standalone View
src/atcore.cpp
Show First 20 Lines • Show All 55 Lines • ▼ Show 20 Line(s) | 47 | struct AtCorePrivate { | |||
---|---|---|---|---|---|
56 | QStringList commandQueue; //!< @param commandQueue: the list of commands to send to the printer | 56 | QStringList commandQueue; //!< @param commandQueue: the list of commands to send to the printer | ||
57 | bool ready = false; //!< @param ready: True if printer is ready for a command | 57 | bool ready = false; //!< @param ready: True if printer is ready for a command | ||
58 | QTimer *tempTimer = nullptr; //!< @param tempTimer: timer connected to the checkTemperature function | 58 | QTimer *tempTimer = nullptr; //!< @param tempTimer: timer connected to the checkTemperature function | ||
59 | float percentage; //!< @param percentage: print job percent | 59 | float percentage; //!< @param percentage: print job percent | ||
60 | QByteArray posString; //!< @param posString: stored string from last M114 return | 60 | QByteArray posString; //!< @param posString: stored string from last M114 return | ||
61 | AtCore::STATES printerState; //!< @param printerState: State of the Printer | 61 | AtCore::STATES printerState; //!< @param printerState: State of the Printer | ||
62 | QStringList serialPorts; //!< @param seralPorts: Detected serial Ports | 62 | QStringList serialPorts; //!< @param seralPorts: Detected serial Ports | ||
63 | QTimer *serialTimer = nullptr; //!< @param serialTimer: Timer connected to locateSerialPorts | 63 | QTimer *serialTimer = nullptr; //!< @param serialTimer: Timer connected to locateSerialPorts | ||
64 | bool sdCardMounted = false; //!< @param sdCardMounted: True if Sd Card is mounted. | ||||
65 | bool sdCardReadingFileList = false; //!< @param sdCardReadingFileList: True while getting file names from sd card | ||||
66 | QString sdCardFileName; //!< @param sdCardFileName: name of file being used from sd card. | ||||
67 | bool sdCardPrinting = false; //!< @param sdCardPrinting: True if currently printing from sd card. | ||||
tcanabrava: Those (with the exception of the sdCardPrinting) could be a bitmask | |||||
Its only two bools so the gain from making them a bitmask would be negligible. I might remove the check for card mounted since it doesn't really matter one way or the other to the printer or the host . for instance if you request an filelist (m20) with no card mounted you just get an empty list.. rizzitello: Its only two bools so the gain from making them a bitmask would be negligible. I might remove… | |||||
patrickelectric: make the 3 bools one after the other because of the memory alignment. | |||||
68 | QStringList sdCardFileList; //!< @param sdCardFileList: List of files on sd card. | ||||
64 | }; | 69 | }; | ||
65 | 70 | | |||
66 | AtCore::AtCore(QObject *parent) : | 71 | AtCore::AtCore(QObject *parent) : | ||
67 | QObject(parent), | 72 | QObject(parent), | ||
68 | d(new AtCorePrivate) | 73 | d(new AtCorePrivate) | ||
69 | { | 74 | { | ||
70 | qRegisterMetaType<AtCore::STATES>("AtCore::STATES"); | 75 | qRegisterMetaType<AtCore::STATES>("AtCore::STATES"); | ||
71 | setState(AtCore::DISCONNECTED); | 76 | setState(AtCore::DISCONNECTED); | ||
▲ Show 20 Lines • Show All 220 Lines • ▼ Show 20 Line(s) | 295 | if (!d->serialTimer) { | |||
292 | connect(d->serialTimer, &QTimer::timeout, this, &AtCore::locateSerialPort); | 297 | connect(d->serialTimer, &QTimer::timeout, this, &AtCore::locateSerialPort); | ||
293 | } | 298 | } | ||
294 | d->serialTimer->start(newTime); | 299 | d->serialTimer->start(newTime); | ||
295 | } | 300 | } | ||
296 | 301 | | |||
297 | void AtCore::newMessage(const QByteArray &message) | 302 | void AtCore::newMessage(const QByteArray &message) | ||
298 | { | 303 | { | ||
299 | d->lastMessage = message; | 304 | d->lastMessage = message; | ||
305 | | ||||
306 | if (message.contains("End file list")) { | ||||
patrickelectric: this should be handle by the fw plugin. | |||||
patrickelectric: Maybe we should create a messageHaveTemperatureData() in AtCore | |||||
rizzitello: yeah lets discuss that. | |||||
307 | d->sdCardReadingFileList = false; | ||||
308 | emit(sdCardFileListChanged(d->sdCardFileList)); | ||||
309 | } else if (d->sdCardReadingFileList) { | ||||
310 | // Below is to not add directories | ||||
311 | if (!message.endsWith('/')) { | ||||
312 | QString fileName = QString::fromLocal8Bit(message); | ||||
313 | fileName.chop(fileName.length() - fileName.lastIndexOf(QChar::fromLatin1(' '))); | ||||
314 | d->sdCardFileList.append(fileName); | ||||
315 | qCDebug(ATCORE_CORE) << "Adding " << fileName << " to file list"; | ||||
316 | } | ||||
317 | } else { | ||||
300 | if (message.startsWith(QString::fromLatin1("X:").toLocal8Bit())) { | 318 | if (message.startsWith(QString::fromLatin1("X:").toLocal8Bit())) { | ||
301 | d->posString = message; | 319 | d->posString = message; | ||
302 | d->posString.resize(d->posString.indexOf('E')); | 320 | d->posString.resize(d->posString.indexOf('E')); | ||
303 | d->posString.replace(':', ""); | 321 | d->posString.replace(':', ""); | ||
304 | } | 322 | } else if (message.contains("SD card")) { | ||
305 | 323 | if (message.contains("inserted")) { | |||
306 | //Check if have temperature info and decode it | 324 | d->sdCardMounted = true; | ||
307 | if (d->lastMessage.contains("T:") || d->lastMessage.contains("B:")) { | 325 | } else if (message.contains("removed")) { | ||
326 | d->sdCardMounted = false; | ||||
327 | } | ||||
328 | emit sdMountChanged(d->sdCardMounted); | ||||
329 | } else if (message.contains("Begin file list")) { | ||||
330 | if (d->sdCardMounted != true) { | ||||
331 | d->sdCardMounted = true; | ||||
332 | emit sdMountChanged(true); | ||||
333 | } | ||||
334 | d->sdCardReadingFileList = true; | ||||
335 | d->sdCardFileList.clear(); | ||||
336 | } else if (d->lastMessage.contains("T:") || d->lastMessage.contains("B:")) { | ||||
308 | temperature().decodeTemp(message); | 337 | temperature().decodeTemp(message); | ||
309 | } | 338 | } | ||
339 | } | ||||
310 | emit(receivedMessage(d->lastMessage)); | 340 | emit(receivedMessage(d->lastMessage)); | ||
311 | } | 341 | } | ||
312 | 342 | | |||
313 | void AtCore::setRelativePosition() | 343 | void AtCore::setRelativePosition() | ||
314 | { | 344 | { | ||
315 | pushCommand(GCode::toCommand(GCode::G91)); | 345 | pushCommand(GCode::toCommand(GCode::G91)); | ||
316 | } | 346 | } | ||
317 | 347 | | |||
318 | void AtCore::setAbsolutePosition() | 348 | void AtCore::setAbsolutePosition() | ||
319 | { | 349 | { | ||
320 | pushCommand(GCode::toCommand(GCode::G90)); | 350 | pushCommand(GCode::toCommand(GCode::G90)); | ||
321 | } | 351 | } | ||
322 | 352 | | |||
323 | float AtCore::percentagePrinted() const | 353 | float AtCore::percentagePrinted() const | ||
324 | { | 354 | { | ||
355 | /* | ||||
356 | if(d->sdCardPrinting) { | ||||
357 | pushCommand(GCode::toCommand(GCode::M27)); | ||||
358 | } else { | ||||
359 | return d->percentage; | ||||
360 | } | ||||
361 | */ | ||||
325 | return d->percentage; | 362 | return d->percentage; | ||
326 | } | 363 | } | ||
327 | 364 | | |||
328 | void AtCore::print(const QString &fileName) | 365 | void AtCore::print(const QString &fileName, bool sdPrint) | ||
329 | { | 366 | { | ||
367 | if (sdPrint) { | ||||
368 | pushCommand(GCode::toCommand(GCode::M23, fileName)); | ||||
369 | d->sdCardFileName = fileName; | ||||
370 | pushCommand(GCode::toCommand(GCode::M24)); | ||||
371 | setState(AtCore::STARTPRINT); | ||||
372 | setState(AtCore::BUSY); | ||||
373 | d->sdCardPrinting = true; | ||||
374 | } else { | ||||
patrickelectric: ```
if () {
something
return
}
```
This will remove one indentation level. | |||||
330 | if (state() == AtCore::CONNECTING) { | 375 | if (state() == AtCore::CONNECTING) { | ||
patrickelectric: This if need to be after connecting if | |||||
331 | qCDebug(ATCORE_CORE) << "Load a firmware plugin to print."; | 376 | qCDebug(ATCORE_CORE) << "Load a firmware plugin to print."; | ||
332 | return; | 377 | return; | ||
333 | } | 378 | } | ||
334 | //START A THREAD AND CONNECT TO IT | 379 | //START A THREAD AND CONNECT TO IT | ||
335 | setState(AtCore::STARTPRINT); | 380 | setState(AtCore::STARTPRINT); | ||
336 | QThread *thread = new QThread(); | 381 | QThread *thread = new QThread(); | ||
337 | PrintThread *printThread = new PrintThread(this, fileName); | 382 | PrintThread *printThread = new PrintThread(this, fileName); | ||
338 | printThread->moveToThread(thread); | 383 | printThread->moveToThread(thread); | ||
339 | 384 | | |||
340 | connect(printThread, &PrintThread::printProgressChanged, this, &AtCore::printProgressChanged, Qt::QueuedConnection); | 385 | connect(printThread, &PrintThread::printProgressChanged, this, &AtCore::printProgressChanged, Qt::QueuedConnection); | ||
341 | connect(thread, &QThread::started, printThread, &PrintThread::start); | 386 | connect(thread, &QThread::started, printThread, &PrintThread::start); | ||
342 | connect(printThread, &PrintThread::finished, thread, &QThread::quit); | 387 | connect(printThread, &PrintThread::finished, thread, &QThread::quit); | ||
343 | connect(thread, &QThread::finished, printThread, &PrintThread::deleteLater); | 388 | connect(thread, &QThread::finished, printThread, &PrintThread::deleteLater); | ||
344 | if (!thread->isRunning()) { | 389 | if (!thread->isRunning()) { | ||
345 | thread->start(); | 390 | thread->start(); | ||
346 | } | 391 | } | ||
347 | } | 392 | } | ||
393 | } | ||||
348 | 394 | | |||
349 | void AtCore::pushCommand(const QString &comm) | 395 | void AtCore::pushCommand(const QString &comm) | ||
350 | { | 396 | { | ||
351 | d->commandQueue.append(comm); | 397 | d->commandQueue.append(comm); | ||
352 | if (d->ready) { | 398 | if (d->ready) { | ||
353 | processQueue(); | 399 | processQueue(); | ||
354 | } | 400 | } | ||
355 | } | 401 | } | ||
356 | 402 | | |||
357 | void AtCore::closeConnection() | 403 | void AtCore::closeConnection() | ||
358 | { | 404 | { | ||
359 | if (serialInitialized()) { | 405 | if (serialInitialized()) { | ||
360 | if (state() == AtCore::BUSY) { | 406 | if (state() == AtCore::BUSY) { | ||
361 | //we have to clean print if printing. | 407 | //we have to clean print if printing. | ||
362 | setState(AtCore::STOP); | 408 | setState(AtCore::STOP); | ||
363 | } | 409 | } | ||
364 | if (firmwarePluginLoaded()) { | 410 | if (firmwarePluginLoaded()) { | ||
365 | disconnect(firmwarePlugin(), &IFirmware::readyForCommand, this, &AtCore::processQueue); | 411 | disconnect(firmwarePlugin(), &IFirmware::readyForCommand, this, &AtCore::processQueue); | ||
366 | if (firmwarePlugin()->name() != QStringLiteral("Grbl")) { | 412 | if (firmwarePlugin()->name() != QStringLiteral("Grbl")) { | ||
367 | disconnect(d->tempTimer, &QTimer::timeout, this, &AtCore::checkTemperature); | 413 | disconnect(d->tempTimer, &QTimer::timeout, this, &AtCore::checkTemperature); | ||
368 | d->tempTimer->stop(); | 414 | d->tempTimer->stop(); | ||
369 | } | 415 | } | ||
370 | } | 416 | } | ||
371 | serial()->close(); | 417 | serial()->close(); | ||
372 | setState(AtCore::DISCONNECTED); | 418 | setState(AtCore::DISCONNECTED); | ||
patrickelectric: We should remove the file only if the user want. | |||||
This Clears the list of file we have stored on the sd card. So that our gui list is also cleared because we are no longer connected to a printer. rizzitello: This Clears the list of file we have stored on the sd card. So that our gui list is also… | |||||
373 | } | 419 | } | ||
374 | } | 420 | } | ||
375 | 421 | | |||
376 | AtCore::STATES AtCore::state(void) | 422 | AtCore::STATES AtCore::state(void) | ||
377 | { | 423 | { | ||
378 | return d->printerState; | 424 | return d->printerState; | ||
379 | } | 425 | } | ||
380 | 426 | | |||
381 | void AtCore::setState(AtCore::STATES state) | 427 | void AtCore::setState(AtCore::STATES state) | ||
382 | { | 428 | { | ||
383 | if (state != d->printerState) { | 429 | if (state != d->printerState) { | ||
384 | qCDebug(ATCORE_CORE) << "Atcore state changed from [" \ | 430 | qCDebug(ATCORE_CORE) << "Atcore state changed from [" \ | ||
385 | << d->printerState << "] to [" << state << "]"; | 431 | << d->printerState << "] to [" << state << "]"; | ||
386 | d->printerState = state; | 432 | d->printerState = state; | ||
387 | emit(stateChanged(d->printerState)); | 433 | emit(stateChanged(d->printerState)); | ||
388 | } | 434 | } | ||
389 | } | 435 | } | ||
390 | 436 | | |||
391 | void AtCore::stop() | 437 | void AtCore::stop() | ||
392 | { | 438 | { | ||
393 | setState(AtCore::STOP); | 439 | setState(AtCore::STOP); | ||
394 | d->commandQueue.clear(); | 440 | if (d->sdCardPrinting) { | ||
441 | pushCommand(GCode::toCommand(GCode::M25)); | ||||
442 | d->sdCardFileName = QStringLiteral(""); | ||||
patrickelectric: ```
QStringLiteral()
```
("") will create a stringLiteral from a copy. | |||||
443 | pushCommand(GCode::toCommand(GCode::M23, d->sdCardFileName)); | ||||
444 | d->sdCardPrinting = false; | ||||
445 | } | ||||
395 | setExtruderTemp(0, 0); | 446 | setExtruderTemp(0, 0); | ||
447 | d->commandQueue.clear(); | ||||
396 | setBedTemp(0); | 448 | setBedTemp(0); | ||
397 | home(AtCore::X); | 449 | home(AtCore::X); | ||
398 | } | 450 | } | ||
399 | 451 | | |||
400 | void AtCore::emergencyStop() | 452 | void AtCore::emergencyStop() | ||
401 | { | 453 | { | ||
402 | if (state() == AtCore::BUSY) { | 454 | if (state() == AtCore::BUSY) { | ||
403 | setState(AtCore::STOP); | 455 | setState(AtCore::STOP); | ||
404 | } | 456 | } | ||
405 | d->commandQueue.clear(); | 457 | d->commandQueue.clear(); | ||
458 | if (d->sdCardPrinting) { | ||||
459 | stop(); | ||||
460 | } | ||||
patrickelectric: Why are you not changing the atcore state ? | |||||
The state is changed in the stop command. The reason that its changed for non sd prints is because the thread will see the change then clean itself up . Sd Prints needs to be stoped a litte differently rizzitello: The state is changed in the stop command. The reason that its changed for non sd prints is… | |||||
406 | serial()->pushCommand(GCode::toCommand(GCode::M112).toLocal8Bit()); | 461 | serial()->pushCommand(GCode::toCommand(GCode::M112).toLocal8Bit()); | ||
407 | } | 462 | } | ||
408 | 463 | | |||
409 | void AtCore::requestFirmware() | 464 | void AtCore::requestFirmware() | ||
410 | { | 465 | { | ||
411 | if (serialInitialized()) { | 466 | if (serialInitialized()) { | ||
412 | qCDebug(ATCORE_CORE) << "Sending " << GCode::toString(GCode::M115); | 467 | qCDebug(ATCORE_CORE) << "Sending " << GCode::toString(GCode::M115); | ||
413 | serial()->pushCommand(GCode::toCommand(GCode::M115).toLocal8Bit()); | 468 | serial()->pushCommand(GCode::toCommand(GCode::M115).toLocal8Bit()); | ||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Line(s) | |||||
463 | 518 | | |||
464 | void AtCore::detectFirmware() | 519 | void AtCore::detectFirmware() | ||
465 | { | 520 | { | ||
466 | connect(serial(), &SerialLayer::receivedCommand, this, &AtCore::findFirmware); | 521 | connect(serial(), &SerialLayer::receivedCommand, this, &AtCore::findFirmware); | ||
467 | } | 522 | } | ||
468 | 523 | | |||
469 | void AtCore::pause(const QString &pauseActions) | 524 | void AtCore::pause(const QString &pauseActions) | ||
470 | { | 525 | { | ||
526 | if (d->sdCardPrinting) { | ||||
527 | pushCommand(GCode::toCommand(GCode::M25)); | ||||
528 | } else { | ||||
471 | pushCommand(GCode::toCommand(GCode::M114)); | 529 | pushCommand(GCode::toCommand(GCode::M114)); | ||
472 | setState(AtCore::PAUSE); | | |||
473 | if (!pauseActions.isEmpty()) { | 530 | if (!pauseActions.isEmpty()) { | ||
474 | QStringList temp = pauseActions.split(QChar::fromLatin1(',')); | 531 | QStringList temp = pauseActions.split(QChar::fromLatin1(',')); | ||
475 | for (int i = 0; i < temp.length(); i++) { | 532 | for (int i = 0; i < temp.length(); i++) { | ||
476 | pushCommand(temp.at(i)); | 533 | pushCommand(temp.at(i)); | ||
477 | } | 534 | } | ||
478 | } | 535 | } | ||
479 | } | 536 | } | ||
537 | setState(AtCore::PAUSE); | ||||
538 | } | ||||
480 | 539 | | |||
481 | void AtCore::resume() | 540 | void AtCore::resume() | ||
482 | { | 541 | { | ||
542 | if (d->sdCardPrinting) { | ||||
543 | pushCommand(GCode::toCommand(GCode::M24)); | ||||
544 | } else { | ||||
483 | pushCommand(GCode::toCommand(GCode::G0, QString::fromLatin1(d->posString))); | 545 | pushCommand(GCode::toCommand(GCode::G0, QString::fromLatin1(d->posString))); | ||
546 | } | ||||
almost all users use not sdcard to print, if put sdcard as a first option in this if, almost all users will miss the if and lost this processing time :) patrickelectric: almost all users use not sdcard to print, if put sdcard as a first option in this if, almost… | |||||
rizzitello: We want to push the resume string we saved on pause anyway . | |||||
patrickelectric: I'm talking about branch prediction :) | |||||
484 | setState(AtCore::BUSY); | 547 | setState(AtCore::BUSY); | ||
485 | } | 548 | } | ||
486 | 549 | | |||
487 | /*~~~~~Control Slots ~~~~~~~~*/ | 550 | /*~~~~~Control Slots ~~~~~~~~*/ | ||
488 | 551 | | |||
489 | void AtCore::home() | 552 | void AtCore::home() | ||
490 | { | 553 | { | ||
491 | pushCommand(GCode::toCommand(GCode::G28)); | 554 | pushCommand(GCode::toCommand(GCode::G28)); | ||
▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Line(s) | |||||
613 | } | 676 | } | ||
614 | QStringList AtCore::portSpeeds() const | 677 | QStringList AtCore::portSpeeds() const | ||
615 | { | 678 | { | ||
616 | return serial()->validBaudRates(); | 679 | return serial()->validBaudRates(); | ||
617 | } | 680 | } | ||
618 | 681 | | |||
619 | void AtCore::setIdleHold(uint delay) | 682 | void AtCore::setIdleHold(uint delay) | ||
620 | { | 683 | { | ||
621 | if (delay != 0) { | 684 | if (delay != 0) { | ||
patrickelectric: if(delay) | |||||
622 | pushCommand(GCode::toCommand(GCode::M84, QString::number(delay))); | 685 | pushCommand(GCode::toCommand(GCode::M84, QString::number(delay))); | ||
623 | } else { | 686 | } else { | ||
624 | pushCommand(GCode::toCommand(GCode::M84)); | 687 | pushCommand(GCode::toCommand(GCode::M84)); | ||
625 | } | 688 | } | ||
626 | } | 689 | } | ||
690 | | ||||
691 | bool AtCore::isSdMounted() | ||||
692 | { | ||||
693 | return d->sdCardMounted; | ||||
694 | } | ||||
695 | | ||||
696 | void AtCore::getSDFileList() | ||||
697 | { | ||||
698 | pushCommand(GCode::toCommand(GCode::M20)); | ||||
I don't know if this make sense, because isSdMounted can be false and mounted true, or otherwise. patrickelectric: I don't know if this make sense, because isSdMounted can be false and mounted true, or… | |||||
This is our one check that the state were setting it to is not the state it currently is . If they are equal we don't need to set them or do the emit. rizzitello: This is our one check that the state were setting it to is not the state it currently is . If… | |||||
699 | } | ||||
700 | | ||||
701 | QStringList AtCore::sdFileList() | ||||
702 | { | ||||
703 | if (d->sdCardFileList.isEmpty()) { | ||||
patrickelectric: Check if sd is mounted. | |||||
You would think that matters, but in testing this just returns no list if that is the case. Unfortunatly this is the only way so far to see if an sd card was inserted at boot time since the printer will not other wise report it. Not ideal but working. rizzitello: You would think that matters, but in testing this just returns no list if that is the case. | |||||
704 | getSDFileList(); | ||||
705 | } | ||||
706 | return d->sdCardFileList; | ||||
patrickelectric: this function should return the filelist ?
| |||||
No that will the file list will be extracted from the retruns. AtCore has no way to pair sent commands with their returned strings. rizzitello: No that will the file list will be extracted from the retruns. AtCore has no way to pair sent… | |||||
707 | } | ||||
708 | | ||||
709 | void AtCore::sdDelete(const QString &fileName) | ||||
710 | { | ||||
711 | pushCommand(GCode::toCommand(GCode::M30, fileName)); | ||||
712 | getSDFileList(); | ||||
713 | } | ||||
714 | | ||||
715 | void AtCore::mountSd(int slot) | ||||
716 | { | ||||
717 | pushCommand(GCode::toCommand(GCode::M21, QString::number(slot))); | ||||
patrickelectric: Get the reference | |||||
718 | } | ||||
719 | | ||||
720 | void AtCore::umountSd(int slot) | ||||
721 | { | ||||
722 | pushCommand(GCode::toCommand(GCode::M22, QString::number(slot))); | ||||
723 | } | ||||
patrickelectric: should we test if fileName exist in the sdcard ? | |||||
I don't think there is a need todo so. If the file is not found it is not deleted. Clients should only allow you to delete files picked from a list of files on the card not by letting the user type any file name. rizzitello: I don't think there is a need todo so. If the file is not found it is not deleted. Clients… | |||||
One thing is the client, other is atcore. The function need to make sense and not allow this kind of behaviour, this is a library and need to do what make sense, if the file does not exist we should qwarning a message about it and return. patrickelectric: One thing is the client, other is atcore. The function need to make sense and not allow this… | |||||
patrickelectric: Check if slot is a valid number | |||||
patrickelectric: ? | |||||
There is no way to check this data that I am aware of. Docs say its almost always 0 rizzitello: There is no way to check this data that I am aware of. Docs say its almost always 0 | |||||
patrickelectric: same |
Those (with the exception of the sdCardPrinting) could be a bitmask