// Use the specified storage object to find a print file and return an // appropriate PrintData instance, placing the print data in the specified // dataParentDirectory. The print data is renamed to or placed in a directory // named according to specified newName. PrintData* PrintData::CreateFromNewData(const PrintFileStorage& storage, const std::string& dataParentDirectory, const std::string& newName) { // avoid naming collisions by clearing the specified data parent directory PurgeDirectory(dataParentDirectory); // create a destination path for the print data // for a tar.gz, the archive is extracted into a directory at this path // for a zip, the archive is renamed to this path std::string printDataDestination = dataParentDirectory + "/" + newName; if (storage.HasTarGz()) { // make a directory to extract to mkdir(printDataDestination.c_str(), 0755); // extract the archive bool extractSuccessful = TarGzFile::Extract(storage.GetFilePath(), printDataDestination); // remove the print file regardless of extraction success remove(storage.GetFilePath().c_str()); if (!extractSuccessful) { // cleanup if extract failed PurgeDirectory(printDataDestination); rmdir(printDataDestination.c_str()); return NULL; } return new PrintDataDirectory(printDataDestination); } else if (storage.HasZip()) { // move the zip file to the specified parent directory rename(storage.GetFilePath().c_str(), printDataDestination.c_str()); PrintDataZip::Initialize(); try { return new PrintDataZip(printDataDestination); } catch (const zppError& e) { // not a valid zip file // remove unusable file remove(printDataDestination.c_str()); return NULL; } } else // did not find a recognized file return NULL; }
/* * vislib::sys::Path::DeleteDirectory */ void vislib::sys::Path::DeleteDirectory(const StringA& path, bool recursive) { if (!File::Exists(path)) return; // we don't delete non-existing stuff StringA fullPath = Resolve(path); if (!fullPath.EndsWith(SEPARATOR_A)) fullPath += SEPARATOR_A; if (recursive) { // remove files and directory PurgeDirectory(fullPath, true); } #ifdef _WIN32 if (RemoveDirectoryA(fullPath) == 0) { #else /* _WIN32 */ if (rmdir(fullPath) != 0) { #endif /* _WIN32 */ throw vislib::sys::SystemException(__FILE__, __LINE__); } } /* * vislib::sys::Path::DeleteDirectory */ void vislib::sys::Path::DeleteDirectory(const StringW& path, bool recursive) { #ifdef _WIN32 if (!File::Exists(path)) return; // we don't delete non-existing stuff StringW fullPath = Resolve(path); if (!fullPath.EndsWith(SEPARATOR_W)) fullPath += SEPARATOR_W; if (recursive) { // remove files and directory PurgeDirectory(fullPath, true); } if (RemoveDirectoryW(fullPath) == 0) { throw vislib::sys::SystemException(__FILE__, __LINE__); } #else /* _WIN32 */ // linux is stupid DeleteDirectory(W2A(path), recursive); #endif /* _WIN32 */ } /* * vislib::sys::Path::FindExecutablePath */ vislib::StringA vislib::sys::Path::FindExecutablePath( const vislib::StringA& filename) { #ifdef _WIN32 bool found = false; DWORD bufSize = MAX_PATH; char *buffer = new char[bufSize]; // first try: "SearchPath" DWORD rv = ::SearchPathA(NULL, filename.PeekBuffer(), NULL, bufSize, buffer, NULL); if (rv > 0) { found = true; if (rv + 1 > bufSize) { bufSize = rv + 1; delete[] buffer; buffer = new char[bufSize]; rv = ::SearchPathA(NULL, filename.PeekBuffer(), NULL, bufSize, buffer, NULL); if (rv == 0) { // failed found = false; } } } if (!found) { // second try: "AssocQueryString" // NOTE: // AssocQueryString does not work as specified! It is not possible to ask // for the size of the string buffer holding the value returned. Therefore // this implementation increases the buffersize until the returned strings // no longer grow. DWORD bufLen = MAX_PATH; HRESULT hr; bufSize = MAX_PATH; do { hr = ::AssocQueryStringA(ASSOCF_INIT_BYEXENAME, ASSOCSTR_EXECUTABLE, filename.PeekBuffer(), NULL, buffer, &bufSize); if ((hr != E_POINTER) && (hr != S_OK)) { // error break; } if (bufSize == bufLen) { bufLen += MAX_PATH; bufSize = bufLen; delete[] buffer; buffer = new char[bufSize]; } else { found = true; } } while (bufSize == bufLen); } if (found) { vislib::StringA retval(buffer); delete[] buffer; return retval; } else { return ""; } #else /* _WIN32 */ // Note: // Do not use "Console::Run" or "Process" methods because they might use // this method to determine the full path of their binaries. So we avoid // calling cycles by just using "popen" directly vislib::StringA cmd("which "); vislib::StringA ret; cmd += filename; cmd += " 2> /dev/null"; const int bufferSize = 1024; char buffer[bufferSize]; FILE *which = ::popen(cmd.PeekBuffer(), "r"); if (which == NULL) { return ""; } while (!::feof(which)) { ret += fgets(buffer, bufferSize, which); } ::pclose(which); vislib::StringA::Size end = ret.Find('\n'); if (end != vislib::StringA::INVALID_POS) { ret.Truncate(end); } if (ret.EndsWith(filename)) { return ret; } else { return ""; } #endif /* _WIN32 */ }
// Remove the print data and the directory containing it bool PrintDataDirectory::Remove() { return PurgeDirectory(_directoryPath) && (rmdir(_directoryPath.c_str()) == 0); }
// Constructor. Settings::Settings(const std::string& path) : _settingsPath(path), _errorHandler(NULL) { // The default values of all settings are defined here. // Printer settings are common to all prints. // Z_MICRONS_PER_REV == 2000 (2 mm lead screw pitch at 1:1 gear ratio) // R_MILLIDEGREES_PER_REV == 180000 (2:1 gear ratio for rotation) std::ostringstream printerSettings; printerSettings << "\"" << DOWNLOAD_DIR << "\":\"" << ROOT_DIR << "/download\"," << "\"" << STAGING_DIR << "\":\"" << ROOT_DIR << "/staging\"," << "\"" << PRINT_DATA_DIR << "\":\"" << ROOT_DIR << "/print_data\"," << "\"" << HARDWARE_REV << "\": 1," << "\"" << LAYER_OVERHEAD << "\": 0.660," << "\"" << MAX_TEMPERATURE << "\": 80.0," << "\"" << INSPECTION_HEIGHT << "\": 60000," << "\"" << MAX_Z_TRAVEL << "\": 160000," << "\"" << DETECT_JAMS << "\": 1," << "\"" << MAX_UNJAM_TRIES << "\": 5," << "\"" << MOTOR_TIMEOUT_FACTOR << "\": 1.1," << "\"" << MIN_MOTOR_TIMEOUT_SEC << "\": 15.0," << "\"" << PROJECTOR_LED_CURRENT << "\": -1," << "\"" << MICRO_STEPS_MODE << "\": 6," << "\"" << Z_STEP_ANGLE << "\": 1800," << "\"" << Z_MICRONS_PER_REV << "\": 2000," << "\"" << R_STEP_ANGLE << "\": 1800," << "\"" << R_MILLIDEGREES_PER_REV << "\": 180000," << "\"" << Z_HOMING_JERK << "\": 500000," << "\"" << Z_HOMING_SPEED << "\": 4500," << "\"" << R_HOMING_JERK << "\": 100000," << "\"" << R_HOMING_SPEED << "\": 5," << "\"" << R_HOMING_ANGLE << "\": -60000," << "\"" << Z_START_PRINT_JERK << "\": 100000," << "\"" << Z_START_PRINT_SPEED << "\": 4500," << "\"" << Z_START_PRINT_POSITION << "\": -165000," << "\"" << R_START_PRINT_JERK << "\": 100000," << "\"" << R_START_PRINT_SPEED << "\": 5," << "\"" << R_START_PRINT_ANGLE << "\": 60000," << "\"" << FRONT_PANEL_AWAKE_TIME << "\": 30," << "\"" << IMAGE_SCALE_FACTOR << "\": 1.0," << "\"" << USB_DRIVE_DATA_DIR << "\": \"/EmberUSB\"," << "\"" << FW_VERSION << "\": \"\""; // Print settings are specific to a print, rather than the printer as a whole std::ostringstream printSpecificSettings; printSpecificSettings << "\"" << JOB_NAME_SETTING << "\": \"\"," << "\"" << USER_NAME_SETTING << "\": \"\"," << "\"" << JOB_ID_SETTING << "\": \"\"," << "\"" << PRINT_FILE_SETTING << "\": \"\"," << "\"" << LAYER_THICKNESS << "\": 25," << "\"" << FIRST_EXPOSURE << "\": 5.0," << "\"" << BURN_IN_LAYERS << "\": 1," << "\"" << BURN_IN_EXPOSURE << "\": 4.0," << "\"" << MODEL_EXPOSURE << "\": 2.5," << "\"" << HOME_ON_APPROACH << "\": 0," << "\"" << FL_SEPARATION_R_JERK << "\": 100000," << "\"" << FL_SEPARATION_R_SPEED << "\": 6," << "\"" << FL_APPROACH_R_JERK << "\": 100000," << "\"" << FL_APPROACH_R_SPEED << "\": 6," << "\"" << FL_Z_LIFT << "\": 2000," << "\"" << FL_SEPARATION_Z_JERK << "\": 100000," << "\"" << FL_SEPARATION_Z_SPEED << "\": 4500," << "\"" << FL_APPROACH_Z_JERK << "\": 100000," << "\"" << FL_APPROACH_Z_SPEED << "\": 4500," << "\"" << FL_ROTATION << "\": 60000," << "\"" << FL_EXPOSURE_WAIT << "\": 0," << "\"" << FL_SEPARATION_WAIT << "\": 0," << "\"" << FL_APPROACH_WAIT << "\": 0," << "\"" << FL_PRESS << "\": 0," << "\"" << FL_PRESS_SPEED << "\": 4500," << "\"" << FL_PRESS_WAIT << "\": 0," << "\"" << FL_UNPRESS_SPEED << "\": 4500," << "\"" << BI_SEPARATION_R_JERK << "\": 100000," << "\"" << BI_SEPARATION_R_SPEED << "\": 11," << "\"" << BI_APPROACH_R_JERK << "\": 100000," << "\"" << BI_APPROACH_R_SPEED << "\": 11," << "\"" << BI_Z_LIFT << "\": 2000," << "\"" << BI_SEPARATION_Z_JERK << "\": 100000," << "\"" << BI_SEPARATION_Z_SPEED << "\": 4500," << "\"" << BI_APPROACH_Z_JERK << "\": 100000," << "\"" << BI_APPROACH_Z_SPEED << "\": 4500," << "\"" << BI_ROTATION << "\": 60000," << "\"" << BI_EXPOSURE_WAIT << "\": 0," << "\"" << BI_SEPARATION_WAIT << "\": 0," << "\"" << BI_APPROACH_WAIT << "\": 0," << "\"" << BI_PRESS << "\": 0," << "\"" << BI_PRESS_SPEED << "\": 4500," << "\"" << BI_PRESS_WAIT << "\": 0," << "\"" << BI_UNPRESS_SPEED << "\": 4500," << "\"" << ML_SEPARATION_R_JERK << "\": 100000," << "\"" << ML_SEPARATION_R_SPEED << "\": 12," << "\"" << ML_APPROACH_R_JERK << "\": 100000," << "\"" << ML_APPROACH_R_SPEED << "\": 12," << "\"" << ML_Z_LIFT << "\": 2000," << "\"" << ML_SEPARATION_Z_JERK << "\": 100000," << "\"" << ML_SEPARATION_Z_SPEED << "\": 4500," << "\"" << ML_APPROACH_Z_JERK << "\": 100000," << "\"" << ML_APPROACH_Z_SPEED << "\": 4500," << "\"" << ML_ROTATION << "\": 60000," << "\"" << ML_EXPOSURE_WAIT << "\": 0," << "\"" << ML_SEPARATION_WAIT << "\": 0," << "\"" << ML_APPROACH_WAIT << "\": 0," << "\"" << ML_PRESS << "\": 0," << "\"" << ML_PRESS_SPEED << "\": 4500," << "\"" << ML_PRESS_WAIT << "\": 0," << "\"" << ML_UNPRESS_SPEED << "\": 4500"; std::ostringstream JSONPrefix; JSONPrefix << "{\"" << SETTINGS_ROOT_KEY << "\":{"; // define the default value for each of the settings std::ostringstream defaultJSON; defaultJSON << JSONPrefix.str() << printerSettings.str() << "," << printSpecificSettings.str() << "}}"; _defaultJSON = defaultJSON.str(); // create a JSON string containing the default print specific settings std::ostringstream defaultPrintSpecificJSON; defaultPrintSpecificJSON << JSONPrefix.str() << printSpecificSettings.str() << "}}"; _defaultPrintSpecificJSON = defaultPrintSpecificJSON.str(); // create the set of valid setting names Document doc; doc.Parse(_defaultJSON.c_str()); const Value& root = doc[SETTINGS_ROOT_KEY]; for (Value::ConstMemberIterator itr = root.MemberBegin(); itr != root.MemberEnd(); ++itr) { _names.insert(itr->name.GetString()); } // Make sure the parent directory of the settings file exists EnsureSettingsDirectoryExists(); if (!Load(path, true)) { RestoreAll(); // clear any print data, since it probably doesn't use default settings, // but don't call any code that uses Settings! PurgeDirectory(root[PRINT_DATA_DIR].GetString()); } }