diff options
author | David Crocker <dcrocker@eschertech.com> | 2020-01-11 14:40:42 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2020-01-11 14:40:42 +0300 |
commit | 4eadb321aa742abfc31686ea7bc577fb1c25d5dd (patch) | |
tree | b16d4db3ea8b1a7a10f20104a456562b8da35859 /src | |
parent | 5ff678917d3eee259687d5ef235c107126330898 (diff) |
Added Job members to object model
Also changed all calls to gmtime to use gmtime_r instead, for thread
safety
Diffstat (limited to 'src')
-rw-r--r-- | src/GCodes/GCodeBuffer/StringParser.cpp | 10 | ||||
-rw-r--r-- | src/GCodes/GCodeFileInfo.cpp | 36 | ||||
-rw-r--r-- | src/GCodes/GCodeFileInfo.h | 5 | ||||
-rw-r--r-- | src/GCodes/GCodes.cpp | 14 | ||||
-rw-r--r-- | src/GCodes/GCodes3.cpp | 5 | ||||
-rw-r--r-- | src/Libraries/Fatfs/fattime_rtc.cpp | 29 | ||||
-rw-r--r-- | src/Logger.cpp | 5 | ||||
-rw-r--r-- | src/Movement/BedProbing/Grid.cpp | 7 | ||||
-rw-r--r-- | src/Movement/Move.cpp | 2 | ||||
-rw-r--r-- | src/Networking/FtpResponder.cpp | 7 | ||||
-rw-r--r-- | src/ObjectModel/ObjectModel.cpp | 17 | ||||
-rw-r--r-- | src/ObjectModel/ObjectModel.h | 16 | ||||
-rw-r--r-- | src/Platform.cpp | 5 | ||||
-rw-r--r-- | src/Platform.h | 4 | ||||
-rw-r--r-- | src/PrintMonitor.cpp | 53 | ||||
-rw-r--r-- | src/PrintMonitor.h | 122 | ||||
-rw-r--r-- | src/RepRap.cpp | 19 | ||||
-rw-r--r-- | src/Storage/FileInfoParser.cpp | 16 | ||||
-rw-r--r-- | src/Storage/MassStorage.cpp | 7 | ||||
-rw-r--r-- | src/Tools/Filament.cpp | 7 | ||||
-rw-r--r-- | src/Version.h | 2 |
21 files changed, 252 insertions, 136 deletions
diff --git a/src/GCodes/GCodeBuffer/StringParser.cpp b/src/GCodes/GCodeBuffer/StringParser.cpp index db99746f..88616244 100644 --- a/src/GCodes/GCodeBuffer/StringParser.cpp +++ b/src/GCodes/GCodeBuffer/StringParser.cpp @@ -1617,6 +1617,16 @@ void StringParser::AppendAsString(ExpressionValue val, const StringRef& str) str.cat(IP4String(val.uVal).c_str()); break; + case TYPE_OF(DateTime): + { + const time_t time = val.Get40BitValue(); + tm timeInfo; + gmtime_r(&time, &timeInfo); + str.catf("%04u-%02u-%02u %02u:%02u:%02u", + timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec); + } + break; + default: throw ConstructParseException("string value expected"); } diff --git a/src/GCodes/GCodeFileInfo.cpp b/src/GCodes/GCodeFileInfo.cpp new file mode 100644 index 00000000..4c6e0ca1 --- /dev/null +++ b/src/GCodes/GCodeFileInfo.cpp @@ -0,0 +1,36 @@ +/* + * GCodeFileInfo.cpp + * + * Created on: 11 Jan 2020 + * Author: David + */ + +#include "GCodeFileInfo.h" + +void GCodeFileInfo::Init() noexcept +{ + isValid = false; + incomplete = true; + firstLayerHeight = 0.0; + objectHeight = 0.0; + layerHeight = 0.0; + printTime = simulatedTime = 0; + numFilaments = 0; + generatedBy.Clear(); + fileSize = 0; + for (size_t extr = 0; extr < MaxExtruders; extr++) + { + filamentNeeded[extr] = 0.0; + } +} + +unsigned int GCodeFileInfo::GetNumLayers() const noexcept +{ + if (layerHeight <= 0.0) { return 0; } + const float nl = (firstLayerHeight > 0.0) + ? (objectHeight - firstLayerHeight)/layerHeight + 1 + : objectHeight/layerHeight; + return rintf(max<float>(nl, 0.0)); +} + +// End diff --git a/src/GCodes/GCodeFileInfo.h b/src/GCodes/GCodeFileInfo.h index 944fbb3d..7c6e09ac 100644 --- a/src/GCodes/GCodeFileInfo.h +++ b/src/GCodes/GCodeFileInfo.h @@ -13,8 +13,9 @@ // Struct to hold Gcode file information struct GCodeFileInfo { - GCodeFileInfo() { Init(); } - void Init(); + GCodeFileInfo() noexcept { Init(); } + void Init() noexcept; + unsigned int GetNumLayers() const noexcept; FilePosition fileSize; time_t lastModifiedTime; diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index 0bd8fd89..6ba38903 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -1270,12 +1270,11 @@ void GCodes::SaveResumeInfo(bool wasPowerFailure) // Write the header comment buf.printf("; File \"%s\" resume print after %s", printingFilename, (wasPowerFailure) ? "power failure" : "print paused"); - if (platform.IsDateTimeSet()) + tm timeInfo; + if (platform.GetDateTime(timeInfo)) { - time_t timeNow = platform.GetDateTime(); - const struct tm * const timeInfo = gmtime(&timeNow); buf.catf(" at %04u-%02u-%02u %02u:%02u", - timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, timeInfo->tm_hour, timeInfo->tm_min); + timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, timeInfo.tm_hour, timeInfo.tm_min); } buf.cat("\nG21\n"); // set units to mm because we will be writing positions in mm bool ok = f->Write(buf.c_str()) @@ -4117,12 +4116,11 @@ bool GCodes::WriteConfigOverrideHeader(FileStore *f) const { String<MaxFilenameLength> buf; buf.copy("; config-override.g file generated in response to M500"); - if (platform.IsDateTimeSet()) + tm timeInfo; + if (platform.GetDateTime(timeInfo)) { - time_t timeNow = platform.GetDateTime(); - const struct tm * const timeInfo = gmtime(&timeNow); buf.catf(" at %04u-%02u-%02u %02u:%02u", - timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, timeInfo->tm_hour, timeInfo->tm_min); + timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, timeInfo.tm_hour, timeInfo.tm_min); } buf.cat('\n'); bool ok = f->Write(buf.c_str()); diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp index 3ffeef1e..651dfc95 100644 --- a/src/GCodes/GCodes3.cpp +++ b/src/GCodes/GCodes3.cpp @@ -935,9 +935,8 @@ GCodeResult GCodes::FindCenterOfCavity(GCodeBuffer& gb, const StringRef& reply, // Deal with a M905 GCodeResult GCodes::SetDateTime(GCodeBuffer& gb, const StringRef& reply) { - const time_t now = platform.GetDateTime(); - struct tm timeInfo; - gmtime_r(&now, &timeInfo); + tm timeInfo; + (void)platform.GetDateTime(timeInfo); bool seen = false; if (gb.Seen('P')) diff --git a/src/Libraries/Fatfs/fattime_rtc.cpp b/src/Libraries/Fatfs/fattime_rtc.cpp index b632385b..e41e40e4 100644 --- a/src/Libraries/Fatfs/fattime_rtc.cpp +++ b/src/Libraries/Fatfs/fattime_rtc.cpp @@ -65,24 +65,21 @@ */ extern "C" uint32_t get_fattime() noexcept { - const Platform& platform = reprap.GetPlatform(); - if (!platform.IsDateTimeSet()) + // Retrieve current date and time from RTC + tm timeInfo; + if (reprap.GetPlatform().GetDateTime(timeInfo)) { - // Date and time have not been set, return default timestamp instead - return 0x210001; + const uint32_t ul_time = ((timeInfo.tm_year + 1900 - 1980) << 25) + | ((timeInfo.tm_mon + 1) << 21) + | (timeInfo.tm_mday << 16) + | (timeInfo.tm_hour << 11) + | (timeInfo.tm_min << 5) + | (timeInfo.tm_sec >> 1); + return ul_time; } - // Retrieve current date and time from RTC - time_t timeNow = platform.GetDateTime(); - struct tm timeInfo; - gmtime_r(&timeNow, &timeInfo); - - uint32_t ul_time = ((timeInfo.tm_year + 1900 - 1980) << 25) - | ((timeInfo.tm_mon + 1) << 21) - | (timeInfo.tm_mday << 16) - | (timeInfo.tm_hour << 11) - | (timeInfo.tm_min << 5) - | (timeInfo.tm_sec >> 1); - return ul_time; + // Date and time have not been set, return default timestamp instead + return 0x210001; } +// End diff --git a/src/Logger.cpp b/src/Logger.cpp index cdb435e7..bbe893fa 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -148,9 +148,10 @@ bool Logger::WriteDateTime(time_t time) noexcept } else { - const struct tm * const timeInfo = gmtime(&time); + tm timeInfo; + gmtime_r(&time, &timeInfo); buf.printf("%04u-%02u-%02u %02u:%02u:%02u ", - timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec); + timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec); } return logFile.Write(buf.c_str()); } diff --git a/src/Movement/BedProbing/Grid.cpp b/src/Movement/BedProbing/Grid.cpp index 28b15518..214abfd6 100644 --- a/src/Movement/BedProbing/Grid.cpp +++ b/src/Movement/BedProbing/Grid.cpp @@ -288,12 +288,11 @@ bool HeightMap::SaveToFile(FileStore *f, float zOffset) const // Write the header comment buf.copy(HeightMapComment); - if (reprap.GetPlatform().IsDateTimeSet()) + tm timeInfo; + if (reprap.GetPlatform().GetDateTime(timeInfo)) { - time_t timeNow = reprap.GetPlatform().GetDateTime(); - const struct tm * const timeInfo = gmtime(&timeNow); buf.catf(" generated at %04u-%02u-%02u %02u:%02u", - timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, timeInfo->tm_hour, timeInfo->tm_min); + timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, timeInfo.tm_hour, timeInfo.tm_min); } float mean, deviation, minError, maxError; (void)GetStatistics(mean, deviation, minError, maxError); diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp index 9c573781..bfa32619 100644 --- a/src/Movement/Move.cpp +++ b/src/Movement/Move.cpp @@ -56,7 +56,7 @@ static const ObjectModelArrayDescriptor axesArrayDescriptor = { - nullptr, + nullptr, // no lock needed [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return reprap.GetGCodes().GetVisibleAxes(); }, [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue { return ExpressionValue(self, 3); } }; diff --git a/src/Networking/FtpResponder.cpp b/src/Networking/FtpResponder.cpp index 293f81c9..470616c7 100644 --- a/src/Networking/FtpResponder.cpp +++ b/src/Networking/FtpResponder.cpp @@ -684,10 +684,11 @@ void FtpResponder::ProcessLine() noexcept // Example for a typical UNIX-like file list: // "drwxr-xr-x 2 ftp ftp 0 Apr 11 2013 bin\r\n" const char dirChar = (fileInfo.isDirectory) ? 'd' : '-'; - const struct tm * const timeInfo = gmtime(&fileInfo.lastModified); + tm timeInfo; + gmtime_r(&fileInfo.lastModified, &timeInfo); dataBuf->catf("%crw-rw-rw- 1 ftp ftp %13lu %s %02d %04d %s\r\n", - dirChar, fileInfo.size, MassStorage::GetMonthName(timeInfo->tm_mon + 1), - timeInfo->tm_mday, timeInfo->tm_year + 1900, fileInfo.fileName.c_str()); + dirChar, fileInfo.size, MassStorage::GetMonthName(timeInfo.tm_mon + 1), + timeInfo.tm_mday, timeInfo.tm_year + 1900, fileInfo.fileName.c_str()); } while (MassStorage::FindNext(fileInfo)); } } diff --git a/src/ObjectModel/ObjectModel.cpp b/src/ObjectModel/ObjectModel.cpp index 2c915a7c..860b8f24 100644 --- a/src/ObjectModel/ObjectModel.cpp +++ b/src/ObjectModel/ObjectModel.cpp @@ -210,6 +210,23 @@ bool ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& } break; + case TYPE_OF(DateTime): + { + const time_t time = val.Get40BitValue(); + if (time == 0) + { + buf->cat("null"); + } + else + { + tm timeInfo; + gmtime_r(&time, &timeInfo); + buf->catf("\"%04u-%02u-%02uT%02u:%02u:%02u\"", + timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec); + } + } + break; + case NoType: buf->cat("null"); break; diff --git a/src/ObjectModel/ObjectModel.h b/src/ObjectModel/ObjectModel.h index 75d3a723..6d860a40 100644 --- a/src/ObjectModel/ObjectModel.h +++ b/src/ObjectModel/ObjectModel.h @@ -25,6 +25,14 @@ class Enum32; class ObjectModel; // forward declaration class ObjectModelArrayDescriptor; // forward declaration +// Encapsulated time_t, used to facilitate overloading the ExpressionValue constructor +struct DateTime +{ + DateTime(time_t t) : tim(t) { } + + time_t tim; +}; + // Function template used to get constexpr type codes // Each type must return a unique type code in the range 1 to 127 (0 is NoType) template<class T> constexpr TypeCode TypeOf() noexcept; @@ -40,6 +48,7 @@ template<> constexpr TypeCode TypeOf<const ObjectModel*>() noexcept { return 8; template<> constexpr TypeCode TypeOf<const char*>() noexcept { return 9; } template<> constexpr TypeCode TypeOf<IPAddress>() noexcept { return 10; } template<> constexpr TypeCode TypeOf<const ObjectModelArrayDescriptor*>() noexcept { return 11; } +template<> constexpr TypeCode TypeOf<DateTime>() noexcept { return 12; } #define TYPE_OF(_t) (TypeOf<_t>()) @@ -58,7 +67,8 @@ class StringParser; struct ExpressionValue { TypeCode type; // what type is stored in the union - uint8_t param; // additional parameter, e.g. number of usual displayed decimal places for a float, or table # for an ObjectModel + uint8_t param; // additional parameter, e.g. number of usual displayed decimal places for a float, + // or table # for an ObjectModel, or 8 extra bits for a date/time union { bool bVal; @@ -83,6 +93,7 @@ struct ExpressionValue explicit constexpr ExpressionValue(const ObjectModelArrayDescriptor *omad) noexcept : type(TYPE_OF(const ObjectModelArrayDescriptor*)), param(0), omadVal(omad) { } explicit constexpr ExpressionValue(IPAddress ip) noexcept : type(TYPE_OF(IPAddress)), param(0), uVal(ip.GetV4LittleEndian()) { } explicit constexpr ExpressionValue(nullptr_t dummy) noexcept : type(NoType), param(0), uVal(0) { } + explicit ExpressionValue(DateTime t) noexcept : type(TYPE_OF(DateTime)), param(t.tim >> 32), uVal((uint32_t)t.tim) { } void Set(bool b) noexcept { type = TYPE_OF(bool); bVal = b; } void Set(char c) noexcept { type = TYPE_OF(char); cVal = c; } @@ -90,6 +101,9 @@ struct ExpressionValue void Set(int i) noexcept { type = TYPE_OF(int32_t); iVal = i; } void Set(float f) noexcept { type = TYPE_OF(float); fVal = f; param = 1; } void Set(const char *s) noexcept { type = TYPE_OF(const char*); sVal = s; } + + // Extract a 40-bit value that we have stored. Used to retrieve date/times. + uint64_t Get40BitValue() const noexcept { return ((uint64_t)param << 32) | uVal; } }; enum class ObjectModelReportFlags : uint16_t diff --git a/src/Platform.cpp b/src/Platform.cpp index 0466ad95..5804d205 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -1602,9 +1602,10 @@ void Platform::Diagnostics(MessageType mtype) noexcept if (srdBuf[slot].when != 0) { const time_t when = (time_t)srdBuf[slot].when; - const struct tm * const timeInfo = gmtime(&when); + tm timeInfo; + gmtime_r(&when, &timeInfo); scratchString.printf("at %04u-%02u-%02u %02u:%02u", - timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, timeInfo->tm_hour, timeInfo->tm_min); + timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, timeInfo.tm_hour, timeInfo.tm_min); } else { diff --git a/src/Platform.h b/src/Platform.h index 0fb6fa6e..a2c06d57 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -310,7 +310,9 @@ public: // Real-time clock bool IsDateTimeSet() const noexcept { return realTime != 0; } // Has the RTC been set yet? - time_t GetDateTime() const noexcept { return realTime; } // Retrieves the current RTC datetime and returns true if it's valid + time_t GetDateTime() const noexcept { return realTime; } // Retrieves the current RTC datetime + bool GetDateTime(tm& rslt) const noexcept { return gmtime_r(&realTime, &rslt) != nullptr && realTime != 0; } + // Retrieves the broken-down current RTC datetime and returns true if it's valid bool SetDateTime(time_t time) noexcept; // Sets the current RTC date and time or returns false on error // Communications and data storage diff --git a/src/PrintMonitor.cpp b/src/PrintMonitor.cpp index a94b1423..8d7deead 100644 --- a/src/PrintMonitor.cpp +++ b/src/PrintMonitor.cpp @@ -25,13 +25,62 @@ Licence: GPL #include "Platform.h" #include "RepRap.h" +#if SUPPORT_OBJECT_MODEL + +// Object model table and functions +// Note: if using GCC version 7.3.1 20180622 and lambda functions are used in this table, you must compile this file with option -std=gnu++17. +// Otherwise the table will be allocated in RAM instead of flash, which wastes too much RAM. + +// Macro to build a standard lambda function that includes the necessary type conversions +#define OBJECT_MODEL_FUNC(...) OBJECT_MODEL_FUNC_BODY(PrintMonitor, __VA_ARGS__) + +const ObjectModelArrayDescriptor PrintMonitor::filamentArrayDescriptor = +{ + nullptr, // no lock needed + [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t + { return ((const PrintMonitor*)self)->printingFileInfo.numFilaments; }, + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue + { return ExpressionValue(((const PrintMonitor*)self)->printingFileInfo.filamentNeeded[context.GetIndex(0)]); } +}; + +constexpr ObjectModelTableEntry PrintMonitor::objectModelTable[] = +{ + // Within each group, these entries must be in alphabetical order + // 0. PrintMonitor members + { "File", OBJECT_MODEL_FUNC(self, 1), ObjectModelEntryFlags::none }, + { "LastFileName", OBJECT_MODEL_FUNC(self->filenameBeingPrinted.c_str()), ObjectModelEntryFlags::none }, + { "Layer", OBJECT_MODEL_FUNC((int32_t)self->currentLayer), ObjectModelEntryFlags::none }, + { "TimesLeft", OBJECT_MODEL_FUNC(self, 2), ObjectModelEntryFlags::none }, + + // 1. ParsedFileInfo members + { "Filament", OBJECT_MODEL_FUNC_NOSELF(&filamentArrayDescriptor), ObjectModelEntryFlags::none }, + { "FirstLayerHeight", OBJECT_MODEL_FUNC(self->printingFileInfo.firstLayerHeight), ObjectModelEntryFlags::none }, + { "GeneratedBy", OBJECT_MODEL_FUNC(self->printingFileInfo.generatedBy.c_str()), ObjectModelEntryFlags::none }, + { "Height", OBJECT_MODEL_FUNC(self->printingFileInfo.objectHeight), ObjectModelEntryFlags::none }, + { "LastModified", OBJECT_MODEL_FUNC(DateTime(self->printingFileInfo.lastModifiedTime)), ObjectModelEntryFlags::none }, + { "LayerHeight", OBJECT_MODEL_FUNC(self->printingFileInfo.layerHeight), ObjectModelEntryFlags::none }, + { "NumLayers", OBJECT_MODEL_FUNC((int32_t)self->printingFileInfo.GetNumLayers()), ObjectModelEntryFlags::none }, + { "PrintTime", OBJECT_MODEL_FUNC((int32_t)self->printingFileInfo.printTime), ObjectModelEntryFlags::none }, + { "SimulatedTime", OBJECT_MODEL_FUNC((int32_t)self->printingFileInfo.simulatedTime), ObjectModelEntryFlags::none }, + { "Size", OBJECT_MODEL_FUNC((int32_t)self->printingFileInfo.fileSize), ObjectModelEntryFlags::none }, // note, using int32_t limits us to 2Gb + + // 2. TimesLeft members + { "Filament", OBJECT_MODEL_FUNC(self->EstimateTimeLeft(filamentBased)), ObjectModelEntryFlags::none }, + { "File", OBJECT_MODEL_FUNC(self->EstimateTimeLeft(fileBased)), ObjectModelEntryFlags::none }, + { "Layer", OBJECT_MODEL_FUNC(self->EstimateTimeLeft(layerBased)), ObjectModelEntryFlags::none }, +}; + +constexpr uint8_t PrintMonitor::objectModelTableDescriptor[] = { 3, 4, 10, 3 }; + +DEFINE_GET_OBJECT_MODEL_TABLE(PrintMonitor) + +#endif + PrintMonitor::PrintMonitor(Platform& p, GCodes& gc) noexcept : platform(p), gCodes(gc), isPrinting(false), heatingUp(false), printStartTime(0), pauseStartTime(0), totalPauseTime(0), currentLayer(0), warmUpDuration(0.0), firstLayerDuration(0.0), firstLayerFilament(0.0), firstLayerProgress(0.0), lastLayerChangeTime(0.0), lastLayerFilament(0.0), lastLayerZ(0.0), numLayerSamples(0), layerEstimatedTimeLeft(0.0), printingFileParsed(false) { - filenameBeingPrinted[0] = 0; - printingFileInfo.Init(); } void PrintMonitor::Init() noexcept diff --git a/src/PrintMonitor.h b/src/PrintMonitor.h index dbb0ab90..ad690682 100644 --- a/src/PrintMonitor.h +++ b/src/PrintMonitor.h @@ -20,8 +20,9 @@ Licence: GPL #ifndef PRINTMONITOR_H #define PRINTMONITOR_H -#include "RepRapFirmware.h" -#include "Storage/FileInfoParser.h" // for struct GCodeFileInfo +#include <RepRapFirmware.h> +#include <GCodes/GCodeFileInfo.h> +#include <ObjectModel/ObjectModel.h> const float LAYER_HEIGHT_TOLERANCE = 0.015; // Tolerance for comparing two Z heights (in mm) @@ -39,63 +40,68 @@ enum PrintEstimationMethod layerBased }; -class PrintMonitor +class PrintMonitor INHERIT_OBJECT_MODEL { - public: - PrintMonitor(Platform& p, GCodes& gc) noexcept; - void Spin() noexcept; - void Init() noexcept; - - bool IsPrinting() const noexcept; // Is a file being printed? - void StartingPrint(const char *filename) noexcept; // Called to indicate a file will be printed (see M23) - void StartedPrint() noexcept; // Called whenever a new live print starts (see M24) - void StoppedPrint() noexcept; // Called whenever a file print has stopped - float FractionOfFilePrinted() const noexcept; // Return the fraction printed (0..1) - - // Return an estimate in seconds based on a specific estimation method - float EstimateTimeLeft(PrintEstimationMethod method) const noexcept; - - // Provide some information about the file being printed - unsigned int GetCurrentLayer() const noexcept; - float GetCurrentLayerTime() const noexcept; - float GetPrintDuration() const noexcept; - float GetWarmUpDuration() const noexcept; - float GetFirstLayerDuration() const noexcept; - float GetFirstLayerHeight() const noexcept; - - const char *GetPrintingFilename() const noexcept { return (isPrinting) ? filenameBeingPrinted.c_str() : nullptr; } - bool GetPrintingFileInfo(GCodeFileInfo& info) noexcept; - void SetPrintingFileInfo(const char *filename, GCodeFileInfo& info) noexcept; - - private: - Platform& platform; - GCodes& gCodes; - uint32_t lastUpdateTime; - - // Information/Events concerning the file being printed - void FirstLayerComplete() noexcept; - void LayerComplete() noexcept; - - bool isPrinting; - bool heatingUp; - uint64_t printStartTime; - uint64_t heatingStartedTime; - uint64_t pauseStartTime, totalPauseTime; - - unsigned int currentLayer; - float warmUpDuration, firstLayerDuration; - float firstLayerFilament, firstLayerProgress; - float lastLayerChangeTime, lastLayerFilament, lastLayerZ; - - unsigned int numLayerSamples; - float layerDurations[MAX_LAYER_SAMPLES]; - float filamentUsagePerLayer[MAX_LAYER_SAMPLES]; - float fileProgressPerLayer[MAX_LAYER_SAMPLES]; - float layerEstimatedTimeLeft; - - bool printingFileParsed; - GCodeFileInfo printingFileInfo; - String<MaxFilenameLength> filenameBeingPrinted; +public: + PrintMonitor(Platform& p, GCodes& gc) noexcept; + void Spin() noexcept; + void Init() noexcept; + + bool IsPrinting() const noexcept; // Is a file being printed? + void StartingPrint(const char *filename) noexcept; // Called to indicate a file will be printed (see M23) + void StartedPrint() noexcept; // Called whenever a new live print starts (see M24) + void StoppedPrint() noexcept; // Called whenever a file print has stopped + float FractionOfFilePrinted() const noexcept; // Return the fraction printed (0..1) + + // Return an estimate in seconds based on a specific estimation method + float EstimateTimeLeft(PrintEstimationMethod method) const noexcept; + + // Provide some information about the file being printed + unsigned int GetCurrentLayer() const noexcept; + float GetCurrentLayerTime() const noexcept; + float GetPrintDuration() const noexcept; + float GetWarmUpDuration() const noexcept; + float GetFirstLayerDuration() const noexcept; + float GetFirstLayerHeight() const noexcept; + + const char *GetPrintingFilename() const noexcept { return (isPrinting) ? filenameBeingPrinted.c_str() : nullptr; } + bool GetPrintingFileInfo(GCodeFileInfo& info) noexcept; + void SetPrintingFileInfo(const char *filename, GCodeFileInfo& info) noexcept; + +protected: + DECLARE_OBJECT_MODEL + + static const ObjectModelArrayDescriptor filamentArrayDescriptor; + +private: + Platform& platform; + GCodes& gCodes; + uint32_t lastUpdateTime; + + // Information/Events concerning the file being printed + void FirstLayerComplete() noexcept; + void LayerComplete() noexcept; + + bool isPrinting; + bool heatingUp; + uint64_t printStartTime; + uint64_t heatingStartedTime; + uint64_t pauseStartTime, totalPauseTime; + + unsigned int currentLayer; + float warmUpDuration, firstLayerDuration; + float firstLayerFilament, firstLayerProgress; + float lastLayerChangeTime, lastLayerFilament, lastLayerZ; + + unsigned int numLayerSamples; + float layerDurations[MAX_LAYER_SAMPLES]; + float filamentUsagePerLayer[MAX_LAYER_SAMPLES]; + float fileProgressPerLayer[MAX_LAYER_SAMPLES]; + float layerEstimatedTimeLeft; + + bool printingFileParsed; + GCodeFileInfo printingFileInfo; + String<MaxFilenameLength> filenameBeingPrinted; }; inline bool PrintMonitor::IsPrinting() const noexcept { return isPrinting; } diff --git a/src/RepRap.cpp b/src/RepRap.cpp index a2031d88..7465d48c 100644 --- a/src/RepRap.cpp +++ b/src/RepRap.cpp @@ -131,6 +131,7 @@ constexpr ObjectModelTableEntry RepRap::objectModelTable[] = // 0. MachineModel root { "Electronics", OBJECT_MODEL_FUNC(self->platform), ObjectModelEntryFlags::none }, { "Heat", OBJECT_MODEL_FUNC(self->heat), ObjectModelEntryFlags::none }, + { "Job", OBJECT_MODEL_FUNC(self->printMonitor), ObjectModelEntryFlags::none }, { "Move", OBJECT_MODEL_FUNC(self->move), ObjectModelEntryFlags::none }, { "Network", OBJECT_MODEL_FUNC(self->network), ObjectModelEntryFlags::none }, { "State", OBJECT_MODEL_FUNC(self, 1), ObjectModelEntryFlags::none }, @@ -144,7 +145,7 @@ constexpr ObjectModelTableEntry RepRap::objectModelTable[] = // { "randomProbe", OBJECT_MODEL_FUNC(&(self->GetMove().GetProbePoints())), TYPE_OF(ObjectModel), 0, ObjectModelEntryFlags::none }, }; -constexpr uint8_t RepRap::objectModelTableDescriptor[] = { 2, 5, 3 }; +constexpr uint8_t RepRap::objectModelTableDescriptor[] = { 2, 6, 3 }; DEFINE_GET_OBJECT_MODEL_TABLE(RepRap) @@ -2093,8 +2094,9 @@ OutputBuffer *RepRap::GetFilelistResponse(const char *dir, unsigned int startAt) bytesLeft -= response->EncodeString(fileInfo.fileName, false); bytesLeft -= response->catf(",\"size\":%" PRIu32, fileInfo.size); - const struct tm * const timeInfo = gmtime(&fileInfo.lastModified); - if (timeInfo->tm_year <= /*19*/80) + tm timeInfo; + gmtime_r(&fileInfo.lastModified, &timeInfo); + if (timeInfo.tm_year <= /*19*/80) { // Don't send the last modified date if it is invalid bytesLeft -= response->cat('}'); @@ -2102,8 +2104,7 @@ OutputBuffer *RepRap::GetFilelistResponse(const char *dir, unsigned int startAt) else { bytesLeft -= response->catf(",\"date\":\"%04u-%02u-%02uT%02u:%02u:%02u\"}", - timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, - timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec); + timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec); } } ++filesFound; @@ -2163,12 +2164,12 @@ bool RepRap::GetFileInfoResponse(const char *filename, OutputBuffer *&response, if (info.isValid) { response->printf("{\"err\":0,\"size\":%lu,",info.fileSize); - const struct tm * const timeInfo = gmtime(&info.lastModifiedTime); - if (timeInfo->tm_year > /*19*/80) + tm timeInfo; + gmtime_r(&info.lastModifiedTime, &timeInfo); + if (timeInfo.tm_year > /*19*/80) { response->catf("\"lastModified\":\"%04u-%02u-%02uT%02u:%02u:%02u\",", - timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, - timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec); + timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec); } response->catf("\"height\":%.2f,\"firstLayerHeight\":%.2f,\"layerHeight\":%.2f,", diff --git a/src/Storage/FileInfoParser.cpp b/src/Storage/FileInfoParser.cpp index d232f360..d6b8d933 100644 --- a/src/Storage/FileInfoParser.cpp +++ b/src/Storage/FileInfoParser.cpp @@ -12,22 +12,6 @@ #include "PrintMonitor.h" #include "GCodes/GCodes.h" -void GCodeFileInfo::Init() -{ - isValid = false; - incomplete = true; - firstLayerHeight = 0.0; - objectHeight = 0.0; - layerHeight = 0.0; - printTime = simulatedTime = 0; - numFilaments = 0; - generatedBy.Clear(); - for (size_t extr = 0; extr < MaxExtruders; extr++) - { - filamentNeeded[extr] = 0.0; - } -} - #if HAS_MASS_STORAGE FileInfoParser::FileInfoParser() noexcept diff --git a/src/Storage/MassStorage.cpp b/src/Storage/MassStorage.cpp index 81882d14..2041e09f 100644 --- a/src/Storage/MassStorage.cpp +++ b/src/Storage/MassStorage.cpp @@ -467,10 +467,11 @@ time_t MassStorage::GetLastModifiedTime(const char *filePath) noexcept bool MassStorage::SetLastModifiedTime(const char *filePath, time_t time) noexcept { - const struct tm * const timeInfo = gmtime(&time); + tm timeInfo; + gmtime_r(&time, &timeInfo); FILINFO fno; - fno.fdate = (WORD)(((timeInfo->tm_year - 80) * 512U) | (timeInfo->tm_mon + 1) * 32U | timeInfo->tm_mday); - fno.ftime = (WORD)(timeInfo->tm_hour * 2048U | timeInfo->tm_min * 32U | timeInfo->tm_sec / 2U); + fno.fdate = (WORD)(((timeInfo.tm_year - 80) * 512U) | (timeInfo.tm_mon + 1) * 32U | timeInfo.tm_mday); + fno.ftime = (WORD)(timeInfo.tm_hour * 2048U | timeInfo.tm_min * 32U | timeInfo.tm_sec / 2U); const bool ok = (f_utime(filePath, &fno) == FR_OK); if (!ok) { diff --git a/src/Tools/Filament.cpp b/src/Tools/Filament.cpp index 2ce3e7b9..d9a15d11 100644 --- a/src/Tools/Filament.cpp +++ b/src/Tools/Filament.cpp @@ -109,12 +109,11 @@ void Filament::LoadAssignment() noexcept // Write header buf.copy(FilamentAssignmentFileComment); - if (reprap.GetPlatform().IsDateTimeSet()) + tm timeInfo; + if (reprap.GetPlatform().GetDateTime(timeInfo)) { - time_t timeNow = reprap.GetPlatform().GetDateTime(); - const struct tm * const timeInfo = gmtime(&timeNow); buf.catf(" generated at %04u-%02u-%02u %02u:%02u", - timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, timeInfo->tm_hour, timeInfo->tm_min); + timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, timeInfo.tm_hour, timeInfo.tm_min); } buf.cat('\n'); file->Write(buf.c_str()); diff --git a/src/Version.h b/src/Version.h index f1966a37..769875f8 100644 --- a/src/Version.h +++ b/src/Version.h @@ -20,7 +20,7 @@ #endif #ifndef DATE -# define DATE "2020-01-10b2" +# define DATE "2020-01-11b1" #endif #define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman, printm3d" |