#include "marlin2.h" #include "esphome/core/log.h" #include namespace esphome { static const char *TAG = "marlin2"; #ifdef USE_SENSOR void Marlin2::add_sensor(const std::string& sName, sensor::Sensor *sens) { sensors.push_back({sName, sens}); } sensor::Sensor* Marlin2::find_sensor(std::string key) { for (const auto& pair : sensors) { if (key == std::string(pair.first)) { // Convert char* to std::string for comparison return pair.second; } } return nullptr; // Return nullptr if no match is found } #endif #ifdef USE_TEXT_SENSOR void Marlin2::add_text_sensor(const std::string& sName, text_sensor::TextSensor *sens) { text_sensors.push_back({sName, sens}); } text_sensor::TextSensor* Marlin2::find_text_sensor(std::string key) { for (const auto& pair : text_sensors) { if (key == std::string(pair.first)) { // Convert char* to std::string for comparison return pair.second; } } return nullptr; // Return nullptr if no match is found } #endif void Marlin2::setup() { MarlinOutput.reserve(256); MarlinOutput = ""; MarlinResponseOutput.reserve(256); MarlinResponseOutput = ""; MarlinTime.reserve(32); PrinterState.reserve(32); //ESP_LOGD(TAG, "M155 S10"); write_str("\r\n\r\nM155 S10\r\n"); write_str("\r\n\r\nM117 ESP Home Connected!\r\n"); flush(); set_printer_state("IDLE"); } void Marlin2::write(std::string gcode) { ESP_LOGD(TAG, "->GCODE: %s", gcode.c_str()); write_str((std::string("\r\n\r\n") + gcode + std::string("\r\n")).c_str()); flush(); } void Marlin2::update() { while (available()) { char c = read(); if( c == '\n' || c == '\r' ) { //ESP_LOGD(TAG, "#%s#",MarlinOutput.c_str()); process_line(); } else { MarlinOutput += c; } } if(millis() - millisProgress > 15000 && print_progress != 100) { millisProgress = millis(); //ESP_LOGD(TAG, "M27"); //ESP_LOGD(TAG, "M31"); write_str("M27\r\nM31\r\n"); } } void Marlin2::process_line() { if(MarlinOutput.size() < 3) { MarlinOutput=""; return; } if(MarlinOutput.compare("ok") == 0 || MarlinOutput.compare(" ok") == 0) { listingFile = false; MarlinOutput=""; return; } ESP_LOGD(TAG, "DEBUG>#%s#",MarlinOutput.c_str()); if(!listingFile && MarlinOutput.compare("Begin file list") == 0) { ESP_LOGD(TAG, "Listing of files started!"); listingFile = true; //reset string for next line MarlinOutput=""; return; } if(listingFile && MarlinOutput.compare("End file list") == 0) { ESP_LOGD(TAG, "Listing of files stopped!"); listingFile = false; //reset string for next line #ifdef USE_TEXT_SENSOR std::string sd_files; for (const auto& [key, value] : file_table_) { if (!sd_files.empty()) sd_files += "|"; sd_files += key; } if (find_text_sensor("sd_card_files") != nullptr){ ESP_LOGD(TAG, "SD Files: %s", sd_files.c_str()); find_text_sensor("sd_card_files")->publish_state(sd_files.c_str()); } #endif MarlinOutput=""; return; } if(listingFile && MarlinOutput.find(".GCO ") > 1) { int first_space = MarlinOutput.find(' '); int second_space = MarlinOutput.find(' ', first_space + 1); if(first_space > 0) { std::string short_name = MarlinOutput.substr(0, first_space); if (short_name.find("/") != std::string::npos){ // Omit subdirectories ESP_LOGD(TAG, "peskočeno kvůli vnořen %s",short_name.c_str()); MarlinOutput=""; return; } std::string long_name = short_name; if (second_space > first_space){ long_name = MarlinOutput.substr(second_space + 1); } file_table_[long_name] = short_name; } //reset string for next line MarlinOutput=""; return; } //Parse periodic Temperature read out message if( MarlinOutput.find(" T:") == 0 || MarlinOutput.find("T:") == 0 || MarlinOutput.find("ok T:") == 0 || MarlinOutput.find(" ok T:") == 0 ) { float ext_temperature, ext_set_temperature, bed_temperature, bed_set_temperature; if (process_temp_msg(&ext_temperature, &ext_set_temperature, &bed_temperature, &bed_set_temperature) != 0) { #ifdef USE_SENSOR if (find_sensor("bed_temperature") != nullptr) find_sensor("bed_temperature")->publish_state(bed_temperature); if (find_sensor("bed_set_temperature") != nullptr) find_sensor("bed_set_temperature")->publish_state(bed_set_temperature); if (find_sensor("ext_temperature") != nullptr) find_sensor("ext_temperature")->publish_state(ext_temperature); if (find_sensor("ext_set_temperature") != nullptr) find_sensor("ext_set_temperature")->publish_state(ext_set_temperature); #endif #ifdef USE_TEXT_SENSOR if(bed_set_temperature==0.0 && ext_set_temperature==0.0) { if(ext_temperature < 32.0 && bed_temperature < 32.0){ //TODO define constants for these set_printer_state("IDLE"); } else if(ext_temperature < 150.0 && bed_temperature < 55.0){ set_printer_state("COOLING"); } } if(print_progress == 0.0 && (bed_set_temperature!=0.0 || ext_set_temperature!=0.0)) { //print_time_offset = print_time save print time ofset to deduct from total value send to hass set_printer_state("PREHEATING"); } #endif //ESP_LOGD(TAG, "Bed Temperature=%.1f°C Ext Temperature=%.1f°C ", bed_temperature, ext_temperature); } //reset string for next line MarlinOutput=""; return; } //Parse Progress of the print if(MarlinOutput.find("SD printing byte") == 0 ) { print_progress = process_progress_msg(); #ifdef USE_SENSOR if (find_sensor("print_progress") != nullptr) find_sensor("print_progress")->publish_state(print_progress); //ESP_LOGD(TAG, "progress=%.1f", print_progress); #endif set_printer_state("PRINTING"); //reset string for next line MarlinOutput=""; return; } //Parse Printitme if(MarlinOutput.find("echo:Print time: ") == 0) { double current=0; double remaining=0; if (process_print_time_msg(¤t, &remaining, print_progress) != 0) { #ifdef USE_SENSOR if (find_sensor("print_time") != nullptr) find_sensor("print_time")->publish_state(current); if (find_sensor("print_time_remaining") != nullptr) find_sensor("print_time_remaining")->publish_state(remaining); #endif //ESP_LOGD(TAG, "time=%f remaining=%f", current, remaining); } //reset string for next line MarlinOutput=""; return; } //File opened: salma_~2.gco Size: 12279971 if(MarlinOutput.find("File opened: ") == 0) { size_t first_space = MarlinOutput.find("File opened: "); size_t second_space = MarlinOutput.find(" Size: "); if (first_space != std::string::npos && second_space != std::string::npos) { size_t start = first_space + std::strlen("File opened: "); size_t len = second_space - start; ESP_LOGD(TAG, "position"); std::string filename = from_dos_name(MarlinOutput.substr(start, len)); ESP_LOGD("Soubor: %s\n", filename.c_str()); #ifdef USE_TEXT_SENSOR if (find_text_sensor("sd_card_file_selected") != nullptr){ find_text_sensor("sd_card_file_selected")->publish_state(filename.c_str()); } #endif } //reset string for next line MarlinOutput=""; return; } //Print From SD Card Started if(MarlinOutput.compare("File selected") == 0) { set_printer_state("PRINTING"); //reset string for next line MarlinOutput=""; return; } //Print Finished if(MarlinOutput.compare("Done printing") == 0) { print_progress = 100; #ifdef USE_SENSOR if (find_sensor("print_progress") != nullptr) find_sensor("print_progress")->publish_state(print_progress); if (find_sensor("print_time_remaining") != nullptr) find_sensor("print_time_remaining")->publish_state(0); #endif #ifdef USE_TEXT_SENSOR set_printer_state("FINISHED"); #endif //reset string for next line MarlinOutput=""; return; } // //Print Paused // if(MarlinOutput.compare("Printer halted") == 0) { // set_printer_state("PAUSED"); // //reset string for next line // MarlinOutput=""; // return; // } // //Print Stoped if(MarlinOutput.compare("Print Aborted") == 0) { set_printer_state("STOPPED"); //reset string for next line MarlinOutput=""; return; } ESP_LOGD(TAG, ">#%s#",MarlinOutput.c_str()); MarlinOutput=""; return; } int Marlin2::process_temp_msg(float* ext_temperature, float* ext_set_temperature, float* bed_temperature, float* bed_set_temperature) { float dc; while(MarlinOutput.find(" ") != std::string::npos) MarlinOutput.erase(MarlinOutput.find(' '), 1); while(MarlinOutput.find("ok") != std::string::npos) MarlinOutput.erase(MarlinOutput.find("ok"), 2); if(sscanf(MarlinOutput.c_str() ,"T:%f/%fB:%f/%f", ext_temperature, ext_set_temperature, bed_temperature, bed_set_temperature) == 4 ) return 1; if(sscanf(MarlinOutput.c_str() ,"T:%f/%f(%f)B:%f/%f(%f)", ext_temperature, ext_set_temperature, &dc, bed_temperature, bed_set_temperature, &dc) == 6 ) return 2; if(sscanf(MarlinOutput.c_str() ,"T:%f/%fT0:%f/%fT1:%f/%fB:%f/%f", ext_temperature, ext_set_temperature, &dc, &dc, &dc, &dc, bed_temperature, bed_set_temperature) == 8 ) return 3; if(sscanf(MarlinOutput.c_str() ,"T0:%f/%fT1:%f/%fB:%f/%f", ext_temperature, ext_set_temperature, &dc, &dc, bed_temperature, bed_set_temperature) == 6 ) return 4; return 0; } float Marlin2::process_progress_msg(){ float current = std::stoi(MarlinOutput.substr(17)); float total = std::stoi(MarlinOutput.substr(MarlinOutput.find('/')+1)); if (total==0) { return 0.0; } return round(((float) current * 100.0) / (float) total); } int Marlin2::process_print_time_msg(double* current, double* remaining, float progress){ MarlinTime = MarlinOutput.substr(16); float d = 0, h = 0, m = 0, s = 0; //ESP_LOGD(TAG,MarlinTime.c_str()); if (sscanf(MarlinTime.c_str() ,"%fd %fh %fm %fs", &d, &h, &m, &s)!=4) { d=0; if (sscanf(MarlinTime.c_str() ,"%fh %fm %fs", &h, &m, &s)!=3) { d=0; h=0; if (sscanf(MarlinTime.c_str() ,"%fm %fs", &m, &s)!=2) { d=0; h=0; m=0; if (sscanf(MarlinTime.c_str() ,"%fs", &s)!=1) { return 0; } } } } *current = round(((d)*24*60*60) + ((h)*60*60) + ((m)*60) + (s)); if(progress != 0.0 && progress != 100.0) { *remaining = (((100 * *current) / round(progress)) - *current); } return 1; } void Marlin2::set_printer_state(std::string status){ #ifdef USE_TEXT_SENSOR // if (!PrinterState.compare(status)) // return; if (find_text_sensor("printer_state") != nullptr){ find_text_sensor("printer_state")->publish_state(status); } // ESP_LOGD(TAG, "Printer Status %s", status.c_str()); // PrinterState = status; #endif } std::string Marlin2::to_dos_name(std::string filename) { auto it = file_table_.find(filename); if (it != file_table_.end()) { return file_table_[filename]; } return filename; } std::string Marlin2::from_dos_name(std::string dos_filename ) { for (const auto& [key, value] : file_table_) { if (value == dos_filename) { return key; } } return dos_filename; } std::string to_lower(std::string s) { return s; // String arduinoStr(s.c_str()); // převod na Arduino String // arduinoStr.toLowerCase(); // změní obsah přímo // return std::string(arduinoStr.c_str()); // zpět na std::string } } // namespace esphome