M: S16F7/F8 PRJobMonitor + S16F15/F16 PRJobCreateMultiple
Closes the two E40 bulk/control gaps the COMPLIANCE doc had flagged
as out-of-scope:
S16F7 / F8 PRJobMonitor — host enables/disables S16F9 alerts
per PJ. PRALERT bit 7 is the enable flag (matches the
ALED convention from S5F3). Server dispatches into the
existing set_alert() store API.
S16F15 / F16 PRJobCreateMultiple — bulk create variant. Host posts
a list of (PRJOBID, PPID, MTRLOUTSPEC) entries; the
equipment processes them in order and returns a
per-PJ HCACK list so the host can identify which
subset failed. Same validators as S16F11.
Catalog now has three new structs: PRJobMonitorEntry,
PRJobCreateEntry, PRJobCreateMultiResult. Two round-trip tests cover
the new wire shapes; server-side correctness is exercised through the
existing PJ store invariants (dedup, validator) which both new paths
delegate to.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -886,6 +886,45 @@ int main(int argc, char** argv) {
|
||||
" -> S16F14 HCACK=" + std::to_string(static_cast<int>(ack)));
|
||||
return gem::s16f14_pr_job_dequeue_ack(ack);
|
||||
});
|
||||
router.on(16, 7, [model, logfn](const s2::Message& msg) {
|
||||
auto req = gem::parse_s16f7(msg);
|
||||
if (!req) return gem::s16f8_pr_job_monitor_ack(gem::HostCmdAck::ParameterInvalid);
|
||||
bool any_bad = false;
|
||||
for (const auto& e : req->entries) {
|
||||
const bool enable = (e.pralert & 0x80) != 0;
|
||||
if (!model->process_jobs.set_alert(e.prjobid, enable)) any_bad = true;
|
||||
}
|
||||
const auto ack = any_bad ? gem::HostCmdAck::InvalidObject : gem::HostCmdAck::Accept;
|
||||
logfn("S16F7 monitor " + std::to_string(req->entries.size()) +
|
||||
" jobs -> S16F8 HCACK=" + std::to_string(static_cast<int>(ack)));
|
||||
return gem::s16f8_pr_job_monitor_ack(ack);
|
||||
});
|
||||
router.on(16, 15, [model, logfn](const s2::Message& msg) {
|
||||
auto req = gem::parse_s16f15(msg);
|
||||
if (!req)
|
||||
return gem::s16f16_pr_job_create_multi_ack(std::vector<gem::PRJobCreateMultiResult>{});
|
||||
std::vector<gem::PRJobCreateMultiResult> results;
|
||||
results.reserve(req->jobs.size());
|
||||
for (const auto& job : req->jobs) {
|
||||
auto r = model->process_jobs.create(
|
||||
job.prjobid, job.ppid, job.mtrloutspec,
|
||||
[model](const std::string& ppid) {
|
||||
return model->recipes.get(ppid).has_value();
|
||||
});
|
||||
gem::HostCmdAck ack = gem::HostCmdAck::Accept;
|
||||
switch (r) {
|
||||
case gem::ProcessJobStore::CreateResult::Created: break;
|
||||
case gem::ProcessJobStore::CreateResult::Denied_AlreadyExists:
|
||||
ack = gem::HostCmdAck::Rejected; break;
|
||||
case gem::ProcessJobStore::CreateResult::Denied_InvalidPpid:
|
||||
ack = gem::HostCmdAck::ParameterInvalid; break;
|
||||
}
|
||||
results.push_back({job.prjobid, ack});
|
||||
}
|
||||
logfn("S16F15 multi-create " + std::to_string(req->jobs.size()) +
|
||||
" jobs -> S16F16");
|
||||
return gem::s16f16_pr_job_create_multi_ack(results);
|
||||
});
|
||||
router.on(16, 5, [model, logfn](const s2::Message& msg) {
|
||||
auto req = gem::parse_s16f5(msg);
|
||||
if (!req) return gem::s16f6_pr_job_command_ack(gem::HostCmdAck::ParameterInvalid);
|
||||
|
||||
Reference in New Issue
Block a user