Send more data back from smart scan to enable if a zip was created
This commit is contained in:
parent
1aed597f9c
commit
18e3978134
4 changed files with 78 additions and 15 deletions
|
|
@ -17,6 +17,7 @@ from typing import (
|
|||
Any,
|
||||
Callable,
|
||||
Concatenate,
|
||||
Literal,
|
||||
Mapping,
|
||||
Optional,
|
||||
ParamSpec,
|
||||
|
|
@ -52,6 +53,15 @@ AnyModel = Annotated[
|
|||
]
|
||||
|
||||
|
||||
class LiveScanDetails(BaseModel):
|
||||
"""Details of ongoing scan used for the UI."""
|
||||
|
||||
name: str
|
||||
stitch_timestamp: Optional[float] = None
|
||||
image_count: int = 0
|
||||
scan_phase: Literal["Setup", "Scanning", "Stitching", "Complete"] = "Setup"
|
||||
|
||||
|
||||
class ActiveScanData(scan_directories.BaseScanData):
|
||||
"""A model for the scan data during an ongoing scan.
|
||||
|
||||
|
|
@ -277,12 +287,21 @@ class SmartScanThing(OFMThing):
|
|||
|
||||
_preview_stitcher: Optional[stitching.PreviewStitcher] = None
|
||||
|
||||
_latest_scan_name: Optional[str] = None
|
||||
_latest_scan_live_details: Optional[LiveScanDetails] = None
|
||||
|
||||
@lt.property
|
||||
def latest_scan_name(self) -> Optional[str]:
|
||||
"""The name of the last scan to be started."""
|
||||
return self._latest_scan_name
|
||||
def latest_scan_live_details(self) -> Optional[LiveScanDetails]:
|
||||
"""The details of any ongoing scan, or the previous scan if no san ongoing."""
|
||||
if self._latest_scan_live_details is None:
|
||||
return None
|
||||
# Update image count and stitch timestamp if scan is ongoing.
|
||||
if self._scan_data is not None:
|
||||
self._latest_scan_live_details.image_count = self._scan_data.image_count
|
||||
|
||||
# Use walrus operator to not need to read filesystem timestamp twice
|
||||
if (stitch_time := self.latest_preview_stitch_time) is not None:
|
||||
self._latest_scan_live_details.stitch_timestamp = stitch_time
|
||||
return self._latest_scan_live_details
|
||||
|
||||
@lt.action
|
||||
def sample_scan(self, scan_name: str = "") -> None:
|
||||
|
|
@ -306,7 +325,9 @@ class SmartScanThing(OFMThing):
|
|||
|
||||
workflow.check_before_start(scan_name)
|
||||
self._ongoing_scan = self._scan_dir_manager.new_scan_dir(scan_name)
|
||||
self._latest_scan_name = self.ongoing_scan.name
|
||||
self._latest_scan_live_details = LiveScanDetails(
|
||||
name=self.ongoing_scan.name
|
||||
)
|
||||
self._run_scan(workflow)
|
||||
# Save any final messages.
|
||||
self._ongoing_scan.save_scan_log(self)
|
||||
|
|
@ -328,6 +349,12 @@ class SmartScanThing(OFMThing):
|
|||
# Reraise so the action reports as cancelled if stitching is cancelled.
|
||||
raise e
|
||||
finally:
|
||||
# Save some final details but not set to the base model until after
|
||||
# resetting valued and unlocking just in case somehow pydantic errors.
|
||||
if self._scan_data is not None:
|
||||
final_image_count = self._scan_data.image_count
|
||||
if self._preview_stitcher is not None:
|
||||
last_timestamp = self.latest_preview_stitch_time
|
||||
# However the scan finishes, unset all variables and release lock
|
||||
self._ongoing_scan = None
|
||||
self._scan_data = None
|
||||
|
|
@ -335,6 +362,11 @@ class SmartScanThing(OFMThing):
|
|||
# Ensure any PreviewStitcher created cannot be reused.
|
||||
self._preview_stitcher = None
|
||||
|
||||
# Set the final details so they persist until the next scan
|
||||
self._latest_scan_live_details.image_count = final_image_count
|
||||
self._latest_scan_live_details.stitch_timestamp = last_timestamp
|
||||
self._latest_scan_live_details.scan_phase = "Complete"
|
||||
|
||||
# Remove any scan folders containing zero images.
|
||||
self.purge_empty_scans()
|
||||
|
||||
|
|
@ -449,6 +481,7 @@ class SmartScanThing(OFMThing):
|
|||
correlation_resize=stitching_settings.correlation_resize,
|
||||
)
|
||||
|
||||
self._latest_scan_live_details.scan_phase = "Scanning"
|
||||
# This is the main loop of the scan!
|
||||
self._main_scan_loop(workflow)
|
||||
self._save_final_scan_data(scan_result="success")
|
||||
|
|
@ -553,6 +586,7 @@ class SmartScanThing(OFMThing):
|
|||
@_scan_running
|
||||
def _perform_final_stitch(self) -> None:
|
||||
"""Update the scan zip and perform final stitch of the data."""
|
||||
self._latest_scan_live_details.scan_phase = "Stitching"
|
||||
if self.scan_data.image_count <= 1:
|
||||
self.logger.info("Not performing a stitch as not enough images captured")
|
||||
return
|
||||
|
|
@ -676,14 +710,16 @@ class SmartScanThing(OFMThing):
|
|||
@property
|
||||
def latest_preview_stitch_path(self) -> Optional[str]:
|
||||
"""The path of the latest preview stitched image, or None if not available."""
|
||||
if self.latest_scan_name is None:
|
||||
if self._latest_scan_live_details is None:
|
||||
return None
|
||||
|
||||
return self._scan_dir_manager.get_file_path_from_img_dir(
|
||||
scan_name=self.latest_scan_name, filename="preview.jpg", check_exists=True
|
||||
scan_name=self._latest_scan_live_details.name,
|
||||
filename="preview.jpg",
|
||||
check_exists=True,
|
||||
)
|
||||
|
||||
@lt.property
|
||||
@property
|
||||
def latest_preview_stitch_time(self) -> Optional[float]:
|
||||
"""The modification time of the latest preview image, to allow live updating.
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ def test_initial_properties(entered_smart_scan_thing):
|
|||
"""
|
||||
smart_scan_thing = entered_smart_scan_thing
|
||||
assert smart_scan_thing._scan_dir_manager.base_dir == SCAN_DIR
|
||||
assert smart_scan_thing.latest_scan_name is None
|
||||
assert smart_scan_thing.latest_scan_live_details is None
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ export default {
|
|||
},
|
||||
},
|
||||
|
||||
emits: ["closeTask", "completed", "actionStartedExternally"],
|
||||
emits: ["closeTask", "completed", "finished", "actionStartedExternally"],
|
||||
|
||||
data() {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
<div class="uk-width-1-1 uk-flex uk-flex-center">
|
||||
<div class="uk-width-2-3">
|
||||
<action-button
|
||||
v-if="scanComplete"
|
||||
v-if="scanComplete && imageCount >= 1"
|
||||
thing="smart_scan"
|
||||
action="download_zip"
|
||||
submit-label="Download ZIP"
|
||||
|
|
@ -51,7 +51,10 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 v-if="scanning" class="uk-margin-left">Scan ID: {{ lastScanName }}</h3>
|
||||
<div class="uk-margin-left info-headings">
|
||||
<h3 v-if="scanning" class="uk-margin-left">Scan ID: {{ lastScanName }}</h3>
|
||||
<h3 v-if="scanning" class="uk-margin-left">Images captured: {{ imageCount }}</h3>
|
||||
</div>
|
||||
</template>
|
||||
</actionTab>
|
||||
</template>
|
||||
|
|
@ -79,6 +82,8 @@ export default {
|
|||
taskId: null,
|
||||
taskUrl: null,
|
||||
lastStitchedImage: null,
|
||||
imageCount: null,
|
||||
scanPhase: null,
|
||||
scanComplete: false,
|
||||
scan_name: "",
|
||||
// This adds the parent name as value for prop streamId
|
||||
|
|
@ -123,6 +128,8 @@ export default {
|
|||
startScanning(id, url) {
|
||||
this.lastStitchedImage = null;
|
||||
this.lastScanName = null;
|
||||
this.imageCount = 0;
|
||||
this.scanPhase = null;
|
||||
this.taskId = id;
|
||||
this.taskUrl = url;
|
||||
this.scanComplete = false;
|
||||
|
|
@ -135,17 +142,27 @@ export default {
|
|||
this.taskId = null;
|
||||
this.taskUrl = null;
|
||||
this.lastStitchedImage = null;
|
||||
this.imageCount = null;
|
||||
this.scanPhase = null;
|
||||
this.scanComplete = false;
|
||||
},
|
||||
async pollScan() {
|
||||
if (!this.scanComplete) {
|
||||
// while the scan is running
|
||||
let mtime = await this.readThingProperty("smart_scan", "latest_preview_stitch_time", true);
|
||||
let scanDetails = await this.readThingProperty(
|
||||
"smart_scan",
|
||||
"latest_scan_live_details",
|
||||
true,
|
||||
);
|
||||
this.lastScanName = scanDetails.name;
|
||||
let mtime = scanDetails.stitch_timestamp;
|
||||
this.imageCount = scanDetails.image_count;
|
||||
this.scanPhase = scanDetails.scan_phase;
|
||||
|
||||
if (mtime !== null) {
|
||||
this.lastStitchedImage = `${this.baseUri}/smart_scan/latest_preview_stitch.jpg?t=${mtime}`;
|
||||
}
|
||||
|
||||
this.lastScanName = await this.readThingProperty("smart_scan", "latest_scan_name", true);
|
||||
setTimeout(this.pollScan, 1000); // keep rescheduling until it's stopped
|
||||
}
|
||||
},
|
||||
|
|
@ -163,4 +180,14 @@ export default {
|
|||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped>
|
||||
.info-headings h3 {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
/* If one heading follows another don't have a large top margin. */
|
||||
.info-headings h3 + h3 {
|
||||
margin-top: 5px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue