编写定制工序计算
可以编写用于 APS 的定制 C 例程以计算选定工序的工序持续时间。如果选择了工序的“定制计划员规则”字段,系统将调用您的定制计算例程。
关于标准工序计算例程
标准工序计算例程为 ol_opercalc。缺省情况下,它返回值 -1.0,表示用于标准 (即非定制) 计算以确定工序的持续时间的算法。例程 C 代码显示如下。
#include "ol_api.h"
double
ol_opercalc(opercalc)
opercalc_s* opercalc;
{
return(-1.0);
}
输入到标准例程
输入 ol_opercalc 是用于 opercalc_s 结构的指示器。如下所示,该结构包含用来计算工序持续时间的信息。
/*------------------------------------------------------------------------*/
typedef struct attid_struct
/*------------------------------------------------------------------------*/
{
char attid[MAX_OLXFSTR+1];
char attvalue[MAX_OLXFSTR+1];
}
attid_s;
/*------------------------------------------------------------------------*/
typedef struct reslist_struct
/*------------------------------------------------------------------------*/
{
char resource[MAX_OLXFSTR+1];
char category[MAX_OLXFSTR+1];
double catbufpre;
double catbufpost;
long numresattids;
attid_s** resattidlist;
}
reslist_s;
/*------------------------------------------------------------------------*/
typedef struct opercalc_struct
/*------------------------------------------------------------------------*/
{
char operation[MAX_OLXFSTR+1];
char order[MAX_OLXFSTR+1];
char part[MAX_OLXFSTR+1];
double quantity;
char startwindow[14];
char endwindow[14];
long oprflags;
double oprsetup;
double oprcycle;
double oprbufpre;
double oprbufpost;
long oprovltype;
double oprovlvalue;
long matltag;
long numresources;
reslist_s** resourcelist;
long numoprattids;
attid_s** oprattidlist;
long numordattids;
attid_s** ordattidlist;
long numprtattids;
attid_s** prtattidlist;
}
opercalc_s;
从标准例程输出
有两种从 ol_opercalc 输出的类型。
- 该功能返回值。从 ol_opercalc 返回的预期即可以是以小时为单位的工序持续时间合计 (如双班类型) 或值 -1.0 (或任何负值)。负值表示系统将使用标准 (非定制) 工序计算。
- 三参数集。这些参数是结构 opercalc_s 的组成部分:
- oprsetup - 工序准备时间 (时数)
- oprovltype - 工序重叠类型
- oprovlvalue - 工序重叠值
当算法将这些参数传递到 ol_opercalc 时,参数包含从数据库获得的用户特定值。将其返回算法前可以在 ol_opercalc 中进行修改。如果进行了修改,系统将做出如下响应:
- oprsetup - 将更改用于该工序的准备时间。
- oprovltype - 将重新计算用于该工序的重叠偏移。
- oprovlvalue - 将重新计算用于该工序的重叠偏移。
可以通过原始数据库或修改 oprovltype 启用工序重叠。如果启用,并且如果 oprsetup 进行了修改和/或 ol_opercalc 退回值表示其他 oprcycle 值正在生效(考虑工序的“固定计划时数”和“定制计划员规则”字段的设置),系统将重新计算用于该工序的重叠偏移。
编写定制例程
编写例程时,确保返回值为双班类型。返回值必须表示用于使用特定资源的指定零件数,在可供生产的时间间隔内,所需工序持续时间的合计 (以小时为单位)。
以下示范 ol_opercalc 例程决定特定资源的工序时间。
#include "ol_api.h"
double
ol_opercalc(opercalc)
opercalc_s* opercalc;
{
FILE* log_fp;
int i,j;
double dTime;
log_fp = fopen("d:\\opercalc50.txt","a");
fprintf(log_fp,
"\nopercalc: oper=>%s<\n",
opercalc->operation );
fflush(log_fp);
fprintf(log_fp,
"opercalc: numoprattids=%d\n",
opercalc->numoprattids );
fflush(log_fp);
for (i=0;i<opercalc->numoprattids;i++)
{
fprintf(log_fp,
"opercalc: opr attid =>%s<\n"
"opercalc: opr attvalue=>%s<\n",
opercalc->oprattidlist[i]->attid,
opercalc->oprattidlist[i]->attvalue );
fflush(log_fp);
}
fprintf(log_fp,
"opercalc: order=>%s<\n",
opercalc->order );
fflush(log_fp);
fprintf(log_fp,
"opercalc: numordattids=%d\n",
opercalc->numordattids );
fflush(log_fp);
for (i=0;i<opercalc->numordattids;i++)
{
fprintf(log_fp,
"opercalc: ord attid =>%s<\n"
"opercalc: ord attvalue=>%s<\n",
opercalc->ordattidlist[i]->attid,
opercalc->ordattidlist[i]->attvalue );
fflush(log_fp);
}
fprintf(log_fp,
"opercalc: part=>%s<\n",
opercalc->part );
fflush(log_fp);
fprintf(log_fp,
"opercalc: numprtattids=%d\n",
opercalc->numprtattids );
fflush(log_fp);
for (i=0;i<opercalc->numprtattids;i++)
{
fprintf(log_fp,
"opercalc: prt attid =>%s<\n"
"opercalc: prt attvalue=>%s<\n",
opercalc->prtattidlist[i]->attid,
opercalc->prtattidlist[i]->attvalue );
fflush(log_fp);
}
fprintf(log_fp,
"opercalc: quantity=%f\n",
opercalc->quantity );
fflush(log_fp);
fprintf(log_fp,
"opercalc: start=>%s<\n",
opercalc->startwindow );
fflush(log_fp);
fprintf(log_fp,
"opercalc: end=>%s<\n",
opercalc->endwindow );
fflush(log_fp);
fprintf(log_fp,
"opercalc: oprflags=%d\n",
opercalc->oprflags );
fflush(log_fp);
fprintf(log_fp,
"opercalc: oprsetup=%f\n",
opercalc->oprsetup );
fflush(log_fp);
fprintf(log_fp,
"opercalc: oprcycle=%f\n",
opercalc->oprcycle );
fflush(log_fp);
fprintf(log_fp,
"opercalc: oprbufpre=%f\n",
opercalc->oprbufpre );
fflush(log_fp);
fprintf(log_fp,
"opercalc: oprbufpost=%f\n",
opercalc->oprbufpost );
fflush(log_fp);
fprintf(log_fp,
"opercalc: oprovltype=%d\n",
opercalc->oprovltype );
fflush(log_fp);
fprintf(log_fp,
"opercalc: oprovlvalue=%f\n",
opercalc->oprovlvalue );
fflush(log_fp);
fprintf(log_fp,
"opercalc: numresources=%d\n",
opercalc->numresources );
fflush(log_fp);
for (i=0;i<opercalc->numresources;i++)
{
fprintf(log_fp,
"opercalc: resource=>%s<\n",
opercalc->resourcelist[i]->resource );
fflush(log_fp);
fprintf(log_fp,
"opercalc: category=>%s<\n",
opercalc->resourcelist[i]->category );
fflush(log_fp);
fprintf(log_fp,
"opercalc: catbufpre=%f\n",
opercalc->resourcelist[i]->catbufpre );
fflush(log_fp);
fprintf(log_fp,
"opercalc: catbufpost=%f\n",
opercalc->resourcelist[i]->catbufpost );
fflush(log_fp);
fprintf(log_fp,
"opercalc: numresattids=%d\n",
opercalc->resourcelist[i]->numresattids );
fflush(log_fp);
for (j=0;j<opercalc->resourcelist[i]->numresattids;j++)
{
fprintf(log_fp,
"opercalc: res attid =>%s<\n"
"opercalc: res attvalue=>%s<\n",
opercalc->resourcelist[i]->resattidlist[j]->attid,
opercalc->resourcelist[i]->resattidlist[j]->attvalue );
fflush(log_fp);
}
}
dTime = -1.0;
if ( (!strcmp(opercalc->part,"SA-50910")) &&
(!strcmp(opercalc->operation,
"SA-50910 SA-5.20")) &&
(!strcmp(opercalc->resourcelist[0]->resource,"PNT10.1")) )
{
if ( opercalc->oprflags == 2 )
{
fprintf(log_fp, "opercalc: per cycle\n");
fflush(log_fp);
if ( opercalc->quantity > 10.0 )
{
opercalc->oprsetup = 0.15;
fprintf(log_fp, "opercalc: changing oprsetup\n");
opercalc->oprcycle = 0.25;
fprintf(log_fp, "opercalc: changing oprcycle\n");
opercalc->oprovltype = 1;
fprintf(log_fp, "opercalc: changing oprovltype\n");
opercalc->oprovlvalue = opercalc->quantity / 2;
fprintf(log_fp, "opercalc: changing oprovlvalue\n");
opercalc->oprbufpre = opercalc->quantity / 2;
fprintf(log_fp, "opercalc: changing oprbufpre to qty/2=%f\n",
opercalc->oprbufpre);
opercalc->oprbufpost = opercalc->quantity / 4;
fprintf(log_fp, "opercalc: changing oprbufpost to qty/4=%f\n",
opercalc->oprbufpost);
// dTime = opercalc->oprcycle * opercalc->quantity;
fflush(log_fp);
}
}
else
{
fprintf(log_fp, "opercalc: per load\n");
fflush(log_fp);
dTime = 1.0;
/* opercalc->oprsetup = 0.0;
opercalc->oprcycle = 0.1;
opercalc->oprovltype = 1;
opercalc->oprovlvalue = 3.0; */
}
}
fprintf(log_fp, "opercalc: dTime = >%f<\n", dTime );
fflush(log_fp);
fclose(log_fp);
return(dTime);
}
创建 Opercalc.dll
调用定制例程
当 APS 运行时,仅当工序的 JOBSTEP.STEPTMRL 字段设置为 2(选择了“定制计划员规则”,“固定计划时数”包含值)或 3(选择了“定制计划员规则”,“固定计划时数”为空或 0),才使用定制例程。具有 STEPTMRL 值 2 的工序使用固定循环时间,值 3 使用每件循环时间。
如果清除了工序的“定制计划员规则”,系统将不调用定制 ol_opercalc 例程。