Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2020-01-11 14:40:42 +0300
committerDavid Crocker <dcrocker@eschertech.com>2020-01-11 14:40:42 +0300
commit4eadb321aa742abfc31686ea7bc577fb1c25d5dd (patch)
treeb16d4db3ea8b1a7a10f20104a456562b8da35859 /src
parent5ff678917d3eee259687d5ef235c107126330898 (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.cpp10
-rw-r--r--src/GCodes/GCodeFileInfo.cpp36
-rw-r--r--src/GCodes/GCodeFileInfo.h5
-rw-r--r--src/GCodes/GCodes.cpp14
-rw-r--r--src/GCodes/GCodes3.cpp5
-rw-r--r--src/Libraries/Fatfs/fattime_rtc.cpp29
-rw-r--r--src/Logger.cpp5
-rw-r--r--src/Movement/BedProbing/Grid.cpp7
-rw-r--r--src/Movement/Move.cpp2
-rw-r--r--src/Networking/FtpResponder.cpp7
-rw-r--r--src/ObjectModel/ObjectModel.cpp17
-rw-r--r--src/ObjectModel/ObjectModel.h16
-rw-r--r--src/Platform.cpp5
-rw-r--r--src/Platform.h4
-rw-r--r--src/PrintMonitor.cpp53
-rw-r--r--src/PrintMonitor.h122
-rw-r--r--src/RepRap.cpp19
-rw-r--r--src/Storage/FileInfoParser.cpp16
-rw-r--r--src/Storage/MassStorage.cpp7
-rw-r--r--src/Tools/Filament.cpp7
-rw-r--r--src/Version.h2
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"