BB1: full E40 S16F11 body — MF, PRRECIPEMETHOD, RCPVARS, PRPROCESSPARAMS

Replaces the simplified <L,3 PRJOBID PPID MTRLOUTSPEC> demo body with
the full SEMI E40-0705 §10.2 shape:

  <L,5 PRJOBID MF PRRECIPEMETHOD
       <L,2 PPID <L,n <L,2 RCPPARNM RCPPARVAL>>>
       <L,n MTRLOUTSPEC>
       <L,n <L,2 PARAMNAME PARAMVAL>>>

ProcessJob now carries the extra fields (MaterialFlag, ProcessRecipeMethod,
RcpVar[], ProcessParam[]) so a tool's recipe engine can later consume
the recipe-variable overrides and per-job process parameters.  Server
S16F11 dispatch populates them via the new ProcessJobStore::set_e40_extras
helper after a successful create.

MaterialFlag + ProcessRecipeMethod enums live in their own tiny header
(`e40_constants.hpp`) so process_jobs.hpp (the store) can use them
without dragging in messages_helpers.hpp (which would create a circular
include via data_model.hpp).

The simplified 3-arg HostHandler::send_create_process_job convenience
remains; it constructs a sensible-default PRJobCreateRequest internally.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 23:44:05 +02:00
parent 4197cdfb25
commit cfa2d1e531
8 changed files with 170 additions and 22 deletions
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <cstdint>
// E40-0705 §10.2 constants used by both the runtime stores (e.g.
// ProcessJob carries MaterialFlag) and the generated message catalog
// (S16F11 PRJobCreate body shape). Kept in its own tiny header so the
// store side can use them without pulling in messages_helpers.hpp,
// which in turn pulls in data_model.hpp -> the stores themselves.
namespace secsgem::gem {
// E40 S16F11 MF (Material Flag). Classifies what the material outspec
// represents. Values from SEMI E40 §10.2.
enum class MaterialFlag : uint8_t {
Substrate = 0, // outspec holds substrate / wafer IDs
Carrier = 1, // outspec holds carrier IDs
Other = 2, // tool-defined
};
// E40 S16F11 PRRECIPEMETHOD. Tells equipment what to do with the
// recipe id in RCPSPEC.
enum class ProcessRecipeMethod : uint8_t {
RecipeOnly = 0, // PPID identifies an existing recipe; use as is
RecipeWithVariableTuning = 1, // PPID + apply RCPVARLIST overrides
};
} // namespace secsgem::gem
+1
View File
@@ -8,6 +8,7 @@
#include <vector>
#include "secsgem/gem/data_model.hpp"
#include "secsgem/gem/e40_constants.hpp"
#include "secsgem/secs2/item.hpp"
#include "secsgem/secs2/message.hpp"
+45 -3
View File
@@ -8,18 +8,39 @@
#include <utility>
#include <vector>
#include "secsgem/gem/e40_constants.hpp"
#include "secsgem/gem/process_job_state.hpp"
#include "secsgem/secs2/item.hpp"
namespace secsgem::gem {
// One Process Job record. The FSM is heap-allocated through unique_ptr so
// the per-PJ state-change handler can capture a stable pointer to
// `this`-style state without invalidation on map rehash.
//
// The MF / recipe-method / rcp-vars / process-params fields are the
// optional E40-0705 §10.2 trailers on S16F11. Simple callers leave
// them defaulted; tools that actually need recipe-variable tuning or
// per-job process parameters populate them.
struct RcpVar {
std::string name;
secs2::Item value;
};
struct ProcessParam {
std::string name;
secs2::Item value;
};
struct ProcessJob {
std::string prjobid;
std::string ppid; // recipe identifier
std::vector<std::string> mtrloutspec; // material identifiers
bool alert_enabled = true; // S16F9 alerts on/off
MaterialFlag mf = MaterialFlag::Substrate;
ProcessRecipeMethod prrecipemethod = ProcessRecipeMethod::RecipeOnly;
std::vector<RcpVar> rcpvars;
std::vector<ProcessParam> prprocessparams;
std::unique_ptr<ProcessJobStateMachine> fsm;
};
@@ -71,9 +92,13 @@ class ProcessJobStore {
if (on_change_) on_change_(id, from, to, trig);
});
order_.push_back(prjobid);
jobs_.emplace(prjobid, ProcessJob{prjobid, std::move(ppid),
std::move(materials), true,
std::move(fsm)});
ProcessJob pj;
pj.prjobid = prjobid;
pj.ppid = std::move(ppid);
pj.mtrloutspec = std::move(materials);
pj.alert_enabled = true;
pj.fsm = std::move(fsm);
jobs_.emplace(prjobid, std::move(pj));
// Synthetic NoState -> Queued so subscribers observe creation. The
// server filters this so it doesn't emit a bogus S16F9 for a PJ
// that's still being acked.
@@ -84,6 +109,23 @@ class ProcessJobStore {
return CreateResult::Created;
}
// After `create`, populate the optional E40-0705 fields on the new PJ.
// Returns true if the PJ exists. These fields don't influence the FSM;
// they're carried so the tool's recipe engine can read them later.
bool set_e40_extras(const std::string& prjobid,
MaterialFlag mf,
ProcessRecipeMethod prrecipemethod,
std::vector<RcpVar> rcpvars,
std::vector<ProcessParam> params) {
auto it = jobs_.find(prjobid);
if (it == jobs_.end()) return false;
it->second.mf = mf;
it->second.prrecipemethod = prrecipemethod;
it->second.rcpvars = std::move(rcpvars);
it->second.prprocessparams = std::move(params);
return true;
}
bool has(const std::string& prjobid) const {
return jobs_.count(prjobid) > 0;
}