Commit af27778be6b51d9a7a478432de1b155526dec1fb

Authored by 김태훈
1 parent 93eb4676f3
Exists in master and in 2 other branches fhd, fhd-demo

HACCP 구현

app/gui/oven_control/autocook.cpp
1 1 #include "autocook.h"
2 2 #include "soundplayer.h"
  3 +#include "haccp.h"
3 4  
4 5 AutoCook::AutoCook() : currentStepIndex(0), done_(false), doorOpened(false), checkingCoreTemp(false)
5 6 {
... ... @@ -12,7 +13,6 @@ AutoCook::AutoCook(Cook cook) : AutoCook()
12 13 for (int idx = 0; idx < this->cook.steps.size(); idx++)
13 14 this->cook.steps[idx].time *= 1000;
14 15  
15   -
16 16 startStep();
17 17 }
18 18  
... ... @@ -71,6 +71,19 @@ void AutoCook::startStep()
71 71 break;
72 72 }
73 73  
  74 + HACCP::autoStart(cook.root);
  75 +
  76 + for (int i = 0; i < 5; i++)
  77 + {
  78 + Define::CookConfigType type = cook.configs[i].type;
  79 + if (type == Define::ConfigNotUsed)
  80 + continue;
  81 +
  82 + HACCP::setConfig(type, cook.configs[i].current);
  83 + }
  84 +
  85 + HACCP::setStep(currentStep.type);
  86 +
74 87 advance();
75 88 }
76 89  
... ... @@ -81,6 +94,8 @@ void AutoCook::nextStep()
81 94 CookStep &currentStep = cook.steps[currentStepIndex];
82 95 CookStep &nextStep = cook.steps[currentStepIndex + 1];
83 96  
  97 + HACCP::setStep(nextStep.type);
  98 +
84 99 Define::StepClass currentClass = Define::classify(currentStep.type);
85 100 Define::StepClass nextClass = Define::classify(nextStep.type);
86 101  
... ... @@ -315,6 +330,7 @@ bool AutoCook::advance()
315 330 {
316 331 done_ = true;
317 332  
  333 + HACCP::done();
318 334 SoundPlayer::playStop();
319 335  
320 336 if (currentStep.dehumidification)
... ... @@ -360,6 +376,7 @@ bool AutoCook::advance()
360 376 {
361 377 done_ = true;
362 378  
  379 + HACCP::done();
363 380 SoundPlayer::playStop();
364 381  
365 382 if (currentStep.dehumidification)
... ...
app/gui/oven_control/autocookwindow.cpp
... ... @@ -17,6 +17,7 @@
17 17 #include "autocookselectionpopup.h"
18 18 #include "autocookcheckconfigwindow.h"
19 19 #include "manualviewerdlg.h"
  20 +#include "haccp.h"
20 21  
21 22 AutoCookWindow::AutoCookWindow(QWidget *parent, Cook cook) :
22 23 QMainWindow(parent),
... ... @@ -110,6 +111,7 @@ AutoCookWindow::AutoCookWindow(QWidget *parent, Cook cook) :
110 111 AutoCookWindow::~AutoCookWindow()
111 112 {
112 113 Oven::getInstance()->stop();
  114 + HACCP::done();
113 115  
114 116 delete ui;
115 117 }
... ... @@ -749,6 +751,9 @@ void AutoCookWindow::startProcess(int process)
749 751  
750 752 SoundPlayer::playStart();
751 753  
  754 + HACCP::autoStart(cook.root);
  755 + HACCP::setProcess(Define::MakeCrisper);
  756 +
752 757 break;
753 758 }
754 759 case Define::KeepWarm:
... ... @@ -756,6 +761,9 @@ void AutoCookWindow::startProcess(int process)
756 761 processSelected = false;
757 762 selectedProcess = (Define::Process) process;
758 763  
  764 + HACCP::autoStart(cook.root);
  765 + HACCP::setProcess(Define::KeepWarm);
  766 +
759 767 KeepWarmPopup *p = new KeepWarmPopup(this);
760 768 p->showFullScreen();
761 769 p->raise();
... ... @@ -778,6 +786,7 @@ void AutoCookWindow::checkProcess()
778 786 Oven *oven = Oven::getInstance();
779 787 if (oven->currentTemp() >= oven->temp())
780 788 {
  789 + HACCP::done();
781 790 SoundPlayer::playStop();
782 791 oven->stopCooking();
783 792 checkProcessTimer.stop();
... ...
app/gui/oven_control/define.cpp
... ... @@ -566,3 +566,36 @@ QString Define::name(Define::Mode mode)
566 566 return "";
567 567 }
568 568 }
  569 +
  570 +QString Define::name(Define::CookConfigType type)
  571 +{
  572 + switch (type)
  573 + {
  574 + case Brightness:
  575 + return "brightness";
  576 + case BurnDegree:
  577 + return "cookinglevel";
  578 + case SoftBoilDegree:
  579 + return "boiledlevel";
  580 + case PieceSize:
  581 + return "size";
  582 + case CrispyDegree:
  583 + return "crispy1";
  584 + case MoistDegree:
  585 + return "moisten1";
  586 + case Thickness:
  587 + return "thickness";
  588 + case Humidity:
  589 + return "humidity";
  590 + case Temperature:
  591 + return "temperature";
  592 + case Time:
  593 + return "cookingtime";
  594 + case CoreTemperature:
  595 + return "coretemperature";
  596 + case Thermometer:
  597 + return "coretemperaturesensor";
  598 + default:
  599 + return "unknownconfig";
  600 + }
  601 +}
... ...
app/gui/oven_control/define.h
... ... @@ -9,7 +9,7 @@
9 9  
10 10 // 0 for normal
11 11 // 1 for premium
12   -#define MODEL_GRADE 0
  12 +#define MODEL_GRADE 1
13 13  
14 14 namespace Define
15 15 {
... ... @@ -52,6 +52,7 @@ namespace Define
52 52 QString iconActiveted(CookConfigType type);
53 53 QString minimum(CookConfigType type);
54 54 QString maximum(CookConfigType type);
  55 + QString name(CookConfigType type);
55 56  
56 57 enum StepClass
57 58 {
... ...
app/gui/oven_control/engineermenuwindow.cpp
... ... @@ -11,6 +11,7 @@
11 11 #include "fileprocessor.h"
12 12 #include "fileprocessdlg.h"
13 13 #include "usbcheckpopupdlg.h"
  14 +#include "haccp.h"
14 15  
15 16 #include <QKeyEvent>
16 17  
... ... @@ -28,10 +29,14 @@ EngineerMenuWindow::EngineerMenuWindow(QWidget *parent) :
28 29  
29 30 foreach (QPushButton *button, findChildren<QPushButton *>())
30 31 connect(button, &QPushButton::pressed, SoundPlayer::playClick);
  32 +
  33 + HACCP::engineeringStart();
31 34 }
32 35  
33 36 EngineerMenuWindow::~EngineerMenuWindow()
34 37 {
  38 + HACCP::done();
  39 +
35 40 delete ui;
36 41 }
37 42  
... ...
app/gui/oven_control/haccp.cpp
... ... @@ -0,0 +1,651 @@
  1 +#include "haccp.h"
  2 +
  3 +#include <QDateTime>
  4 +#include <QDir>
  5 +#include <QTextStream>
  6 +#include <QTimer>
  7 +
  8 +#include "unistd.h"
  9 +
  10 +#include "stringer.h"
  11 +#include "oven.h"
  12 +
  13 +namespace
  14 +{
  15 +
  16 +enum Type { Invalid, Manual, Auto, Multi, Wash, Engineering };
  17 +
  18 +struct Stamp
  19 +{
  20 + QDateTime time;
  21 + int temp;
  22 + int targetCoreTemp;
  23 + int curCoreTemp;
  24 + bool door;
  25 + QString caption;
  26 +};
  27 +
  28 +struct Config
  29 +{
  30 + Define::CookConfigType type;
  31 + int level;
  32 +};
  33 +
  34 +struct Data
  35 +{
  36 + QDateTime startedAt;
  37 + Type type;
  38 + QString autoRoot;
  39 + QList<Config> autoConfig;
  40 + int washType;
  41 + QList<Stamp> records;
  42 +} data;
  43 +
  44 +QDateTime initializedTime;
  45 +int processCount;
  46 +QTimer checkTimer;
  47 +QTime lastStampedTime;
  48 +
  49 +Define::Mode lastMode;
  50 +int lastFan;
  51 +bool lastDoor;
  52 +bool lastDamper;
  53 +bool lastSideNozzle;
  54 +bool lastCoreTempEnabled;
  55 +
  56 +int figureProcessCount();
  57 +void initData(Type type);
  58 +void start();
  59 +void stamp(QString caption = "");
  60 +void stampStart();
  61 +void stampMode(Define::Mode mode);
  62 +void stampDamper();
  63 +void stampSideNozzle();
  64 +void stampEnd();
  65 +void stampError(QString error);
  66 +void saveData();
  67 +void check();
  68 +}
  69 +
  70 +namespace HACCP
  71 +{
  72 +
  73 +void init()
  74 +{
  75 + // make the directory if it doesn't exist
  76 + QDir().mkpath("/prime/haccp");
  77 +
  78 + initializedTime = QDateTime::currentDateTime();
  79 + processCount = figureProcessCount() + 1;
  80 +
  81 + checkTimer.setInterval(100);
  82 + QObject::connect(&checkTimer, &QTimer::timeout, check);
  83 +
  84 + Oven *oven = Oven::getInstance();
  85 + QObject::connect(oven, &Oven::changed, check);
  86 +}
  87 +
  88 +void autoStart(const QString &path)
  89 +{
  90 + initData(Auto);
  91 + data.autoRoot = path;
  92 +
  93 + start();
  94 +}
  95 +
  96 +void manualStart()
  97 +{
  98 + qDebug() << __FUNCTION__;
  99 +
  100 + initData(Manual);
  101 + start();
  102 +}
  103 +
  104 +void multiStart()
  105 +{
  106 + initData(Multi);
  107 + start();
  108 +}
  109 +
  110 +void washStart(int type)
  111 +{
  112 + initData(Wash);
  113 + data.washType = type;
  114 +}
  115 +
  116 +void engineeringStart()
  117 +{
  118 + initData(Engineering);
  119 +}
  120 +
  121 +void done()
  122 +{
  123 + qDebug() << __FUNCTION__;
  124 + if (data.type == Invalid)
  125 + return;
  126 +
  127 + stampEnd();
  128 + saveData();
  129 +}
  130 +
  131 +void error(QString code)
  132 +{
  133 + if (data.type == Invalid)
  134 + return;
  135 +
  136 + stampError(code);
  137 + saveData();
  138 +}
  139 +
  140 +void setConfig(Define::CookConfigType type, int level)
  141 +{
  142 + data.autoConfig.append(Config{type, level});
  143 +}
  144 +
  145 +void setStep(Define::StepType type)
  146 +{
  147 + switch (type)
  148 + {
  149 + case Define::Preheat:
  150 + stamp("preheat");
  151 + break;
  152 + case Define::Load:
  153 + stamp("load");
  154 + break;
  155 + case Define::PutThermometer:
  156 + stamp("therometer");
  157 + break;
  158 + case Define::Cut:
  159 + stamp("cut");
  160 + break;
  161 + case Define::Pour:
  162 + stamp("pour");
  163 + break;
  164 + case Define::Bake:
  165 + stamp("bake");
  166 + break;
  167 + case Define::Dry:
  168 + stamp("dry");
  169 + break;
  170 + case Define::Ferment:
  171 + stamp("ferment");
  172 + break;
  173 + case Define::BlowSteam:
  174 + stamp("steaming");
  175 + break;
  176 + case Define::CoolDown:
  177 + stamp("cooldown");
  178 + break;
  179 + case Define::Steam:
  180 + stamp("steam");
  181 + break;
  182 + case Define::Roast:
  183 + stamp("roasting");
  184 + break;
  185 + case Define::Boil:
  186 + stamp("boil");
  187 + break;
  188 + case Define::Thicken:
  189 + stamp("thicken");
  190 + break;
  191 + case Define::WarmUp:
  192 + stamp("warmup");
  193 + break;
  194 + case Define::MakeCrispy:
  195 + stamp("crispy2");
  196 + break;
  197 + case Define::Finish:
  198 + stamp("finish");
  199 + break;
  200 + case Define::Damp:
  201 + stamp("damp");
  202 + break;
  203 + case Define::Defer:
  204 + stamp("defer");
  205 + break;
  206 + case Define::Grill:
  207 + stamp("grill");
  208 + break;
  209 + case Define::End:
  210 + stamp("end");
  211 + break;
  212 + case Define::Burn:
  213 + stamp("burn");
  214 + break;
  215 + case Define::Fry:
  216 + stamp("fry");
  217 + break;
  218 + case Define::HeatUp:
  219 + stamp("heatup");
  220 + break;
  221 + case Define::Ripen:
  222 + stamp("ripen");
  223 + break;
  224 + case Define::RipenKeep:
  225 + stamp("ripenkeep");
  226 + break;
  227 + case Define::BoilSteadily:
  228 + stamp("boilsteadily");
  229 + break;
  230 + case Define::CookGratin:
  231 + stamp("cookgratin");
  232 + break;
  233 + case Define::Brown:
  234 + stamp("brown");
  235 + break;
  236 + case Define::Simmer:
  237 + stamp("simmer");
  238 + break;
  239 + case Define::Moisten:
  240 + stamp("moisten2");
  241 + break;
  242 + }
  243 +}
  244 +
  245 +void setProcess(Define::Process type)
  246 +{
  247 + switch (type)
  248 + {
  249 + case Define::CookAgain:
  250 + stamp("again");
  251 + break;
  252 + case Define::MakeCrisper:
  253 + stamp("crispy3");
  254 + break;
  255 + case Define::KeepWarm:
  256 + stamp("heatreserve");
  257 + break;
  258 + }
  259 +}
  260 +
  261 +}
  262 +
  263 +
  264 +namespace
  265 +{
  266 +
  267 +QString path()
  268 +{
  269 + return "/prime/haccp";
  270 +}
  271 +
  272 +QString path(int year)
  273 +{
  274 + return QString("/prime/haccp/%1").arg(year, 4, 10, QLatin1Char('0'));
  275 +}
  276 +
  277 +QString path(int year, int month)
  278 +{
  279 + return QString("/prime/haccp/%1/%2")
  280 + .arg(year, 4, 10, QLatin1Char('0'))
  281 + .arg(month, 2, 10, QLatin1Char('0'));
  282 +}
  283 +
  284 +QString path(int year, int month, int day)
  285 +{
  286 + return QString("/prime/haccp/%1/%2/%3")
  287 + .arg(year, 4, 10, QLatin1Char('0'))
  288 + .arg(month, 2, 10, QLatin1Char('0'))
  289 + .arg(day, 2, 10, QLatin1Char('0'));
  290 +}
  291 +
  292 +QString path(int year, int month, int day, int proc)
  293 +{
  294 + return QString("/prime/haccp/%1/%2/%3/%4")
  295 + .arg(year, 4, 10, QLatin1Char('0'))
  296 + .arg(month, 2, 10, QLatin1Char('0'))
  297 + .arg(day, 2, 10, QLatin1Char('0'))
  298 + .arg(proc);
  299 +}
  300 +
  301 +int figureLatest(const QString &path, QDir::Filter filter)
  302 +{
  303 + QDir root(path);
  304 + if (!root.exists())
  305 + return -1;
  306 +
  307 + QStringList list = root.entryList(filter);
  308 + if (list.empty())
  309 + return -1;
  310 +
  311 + int latest = -1;
  312 + foreach (QString e, list)
  313 + {
  314 + bool ok;
  315 + int num = e.toInt(&ok);
  316 + if (!ok)
  317 + continue;
  318 +
  319 + if (num > latest)
  320 + latest = num;
  321 + }
  322 +
  323 + return latest;
  324 +}
  325 +
  326 +int figureLatestDir(const QString &path)
  327 +{
  328 + return figureLatest(path, QDir::AllDirs);
  329 +}
  330 +
  331 +int figureLatestFile(const QString &path)
  332 +{
  333 + return figureLatest(path, QDir::Files);
  334 +}
  335 +
  336 +int figureProcessCount()
  337 +{
  338 + int year = figureLatestDir(path());
  339 + if (year < 0)
  340 + return 0;
  341 +
  342 + int month = figureLatestDir(path(year));
  343 + if (month < 0)
  344 + return 0;
  345 +
  346 + int day = figureLatestDir(path(year, month));
  347 + if (day < 0)
  348 + return 0;
  349 +
  350 + int proc = figureLatestFile(path(year, month, day));
  351 + if (proc < 0)
  352 + return 0;
  353 +
  354 + return proc;
  355 +}
  356 +
  357 +void initData(Type type)
  358 +{
  359 + data.type = type;
  360 + data.autoRoot = QString();
  361 + data.autoConfig.clear();
  362 + data.washType = 0;
  363 + data.records.clear();
  364 +
  365 + if (initializedTime.isValid())
  366 + {
  367 + data.startedAt = initializedTime;
  368 + stampStart();
  369 + }
  370 + else
  371 + data.startedAt = QDateTime::currentDateTime();
  372 +
  373 +}
  374 +
  375 +void start()
  376 +{
  377 + qDebug() << __FUNCTION__;
  378 +
  379 + lastMode = Define::InvalidMode;
  380 + lastFan = -1;
  381 + lastDoor = false;
  382 + lastDamper = false;
  383 + lastSideNozzle = false;
  384 + lastCoreTempEnabled = false;
  385 +
  386 + Oven *oven = Oven::getInstance();
  387 + stampMode(oven->mode());
  388 +
  389 + checkTimer.start();
  390 +}
  391 +
  392 +void stamp(QString caption)
  393 +{
  394 + qDebug() << __FUNCTION__;
  395 +
  396 + if (data.type == Invalid)
  397 + return;
  398 +
  399 + Oven *oven = Oven::getInstance();
  400 +
  401 + Stamp s;
  402 + s.time = QDateTime::currentDateTime();
  403 + s.temp = oven->currentTemp();
  404 +
  405 + if (oven->interTempEnabled())
  406 + {
  407 + s.targetCoreTemp = oven->interTemp();
  408 + s.curCoreTemp = oven->currentInterTemp();
  409 + }
  410 + else
  411 + {
  412 + s.targetCoreTemp = 0;
  413 + s.curCoreTemp = 0;
  414 + }
  415 +
  416 + s.door = oven->door();
  417 + s.caption = caption;
  418 +
  419 + data.records.append(s);
  420 +
  421 + lastDoor = oven->door();
  422 + lastStampedTime.start();
  423 +}
  424 +
  425 +void stampStart()
  426 +{
  427 + qDebug() << __FUNCTION__;
  428 +
  429 + stamp("START (POWER ON)");
  430 +}
  431 +
  432 +void stampMode(Define::Mode mode)
  433 +{
  434 + qDebug() << __FUNCTION__;
  435 +
  436 + switch (mode)
  437 + {
  438 + case Define::SteamMode:
  439 + stamp("Mode STEAM");
  440 + break;
  441 + case Define::CombiMode:
  442 + stamp("Mode COMBI");
  443 + break;
  444 + case Define::DryMode:
  445 + stamp("Mode DRY");
  446 + break;
  447 + }
  448 +
  449 + lastMode = mode;
  450 +}
  451 +
  452 +void stampFan(int fan)
  453 +{
  454 + qDebug() << __FUNCTION__;
  455 +
  456 + lastFan = fan;
  457 + stamp(QString("FAN = %1").arg(fan));
  458 +}
  459 +
  460 +void stampDamper()
  461 +{
  462 + qDebug() << __FUNCTION__;
  463 +
  464 + stamp("DAMPER");
  465 +}
  466 +
  467 +void stampSideNozzle()
  468 +{
  469 + qDebug() << __FUNCTION__;
  470 +
  471 + stamp("SIDE NOZZLE");
  472 +}
  473 +
  474 +void stampEnd()
  475 +{
  476 + qDebug() << __FUNCTION__;
  477 +
  478 + stamp("END");
  479 +}
  480 +
  481 +void stampError(QString error)
  482 +{
  483 + stamp(QString("END (%1)").arg(error));
  484 +}
  485 +
  486 +void saveData()
  487 +{
  488 + qDebug() << __FUNCTION__;
  489 +
  490 + if (data.records.isEmpty())
  491 + {
  492 + data.type = Invalid;
  493 + return;
  494 + }
  495 +
  496 + QDate date = data.startedAt.date();
  497 +
  498 + QDir().mkpath(path(date.year(), date.month(), date.day()));
  499 +
  500 + QString p = path(date.year(), date.month(), date.day(), processCount);
  501 +
  502 + QFile file(p);
  503 + if (!file.open(QIODevice::Truncate | QIODevice::WriteOnly))
  504 + {
  505 + qDebug() << "Failed to open";
  506 + return;
  507 + }
  508 +
  509 + QTextStream stream(&file);
  510 + stream.setCodec("UTF-8");
  511 +
  512 + // TODO: fill them
  513 + stream << "No.," << processCount << "\n";
  514 + stream << "Typ," << "\n";
  515 + stream << "Serial No.," << "\n";
  516 + stream << "Version," << "\n";
  517 + stream << "Time," << data.startedAt.toString("yyyy.MM.dd HH:mm:ss") << "\n";
  518 +
  519 + stream << "Progr,";
  520 + switch (data.type)
  521 + {
  522 + case Manual:
  523 + stream << 1;
  524 + break;
  525 + case Auto:
  526 + stream << data.autoRoot;
  527 + break;
  528 + case Multi:
  529 + stream << 4;
  530 + break;
  531 + case Wash:
  532 + stream << 6 << "-" << data.washType;
  533 + break;
  534 + case Engineering:
  535 + stream << 999;
  536 + break;
  537 + }
  538 + stream << "\n";
  539 +
  540 + stream << "\n"
  541 + << "#1,Time\n"
  542 + << "#2,Inner Tank Temp\n"
  543 + << "#3,Food Temp (Target)\n"
  544 + << "#4,Food Temp\n"
  545 + << "#5,Door Open / Closed\n";
  546 +
  547 + stream << "\n";
  548 +
  549 + stream << "#1,#2,#3,#4,#5\n";
  550 + for (int i = 0; i < data.records.size(); i++)
  551 + {
  552 + const Stamp &s = data.records.at(i);
  553 + if (!s.caption.isEmpty() && i+1 < data.records.size())
  554 + {
  555 + Stamp &n = data.records[i+1];
  556 +
  557 + int secs = data.startedAt.secsTo(s.time);
  558 + int nextSecs = data.startedAt.secsTo(n.time);
  559 + if (secs == nextSecs
  560 + && s.temp == n.temp
  561 + && s.targetCoreTemp == n.targetCoreTemp
  562 + && s.curCoreTemp == n.curCoreTemp
  563 + && s.door == n.door)
  564 + {
  565 + if (n.caption.isEmpty())
  566 + n.caption = s.caption;
  567 + else
  568 + n.caption = QString("%1\n%2").arg(s.caption).arg(n.caption);
  569 +
  570 + continue;
  571 + }
  572 + }
  573 +
  574 + if (!s.caption.isEmpty())
  575 + stream << s.caption << "\n";
  576 +
  577 + stream << Stringer::timeSecs(data.startedAt.secsTo(s.time)) << ","
  578 + << s.temp << ","
  579 + << s.targetCoreTemp << ","
  580 + << s.curCoreTemp << ","
  581 + << (s.door ? "O\n" : "C\n");
  582 + }
  583 +
  584 + if (!data.autoConfig.isEmpty())
  585 + {
  586 + foreach (Config c, data.autoConfig)
  587 + stream << Define::name(c.type)
  588 + << " = "
  589 + << c.level << "\n";
  590 + }
  591 +
  592 + stream.flush();
  593 + file.close();
  594 + sync();
  595 +
  596 + initializedTime = QDateTime();
  597 + processCount++;
  598 +
  599 + data.type = Invalid;
  600 +
  601 + checkTimer.stop();
  602 +}
  603 +
  604 +void check()
  605 +{
  606 + switch (data.type)
  607 + {
  608 + case Invalid:
  609 + case Wash:
  610 + case Engineering:
  611 + return;
  612 + default:
  613 + break;
  614 + }
  615 +
  616 + Oven *oven = Oven::getInstance();
  617 +
  618 + if (oven->mode() != lastMode)
  619 + stampMode(oven->mode());
  620 +
  621 + if (oven->fan() != lastFan)
  622 + stampFan(oven->fan());
  623 +
  624 + if (oven->damper() != lastDamper)
  625 + {
  626 + lastDamper = oven->damper();
  627 + if (lastDamper)
  628 + stampDamper();
  629 + }
  630 +
  631 + if (oven->humidification() != lastSideNozzle)
  632 + {
  633 + lastSideNozzle = oven->humidification();
  634 + if (lastSideNozzle)
  635 + stampSideNozzle();
  636 + }
  637 +
  638 + if (oven->interTempEnabled() != lastCoreTempEnabled)
  639 + {
  640 + lastCoreTempEnabled = oven->interTempEnabled();
  641 + stamp();
  642 + }
  643 +
  644 + if (oven->door() != lastDoor)
  645 + stamp();
  646 +
  647 + if (lastStampedTime.elapsed() > 60 * 1000 - 100)
  648 + stamp();
  649 +}
  650 +
  651 +}
... ...
app/gui/oven_control/haccp.h
... ... @@ -0,0 +1,29 @@
  1 +#ifndef HACCP_H
  2 +#define HACCP_H
  3 +
  4 +#include <QString>
  5 +
  6 +#include "define.h"
  7 +
  8 +namespace HACCP
  9 +{
  10 +
  11 +void init();
  12 +
  13 +void autoStart(const QString &path);
  14 +void manualStart();
  15 +void multiStart();
  16 +void washStart(int type);
  17 +void engineeringStart();
  18 +
  19 +void done();
  20 +void error(QString code);
  21 +
  22 +// For auto cook
  23 +void setConfig(Define::CookConfigType type, int level);
  24 +void setStep(Define::StepType type);
  25 +void setProcess(Define::Process type);
  26 +
  27 +}
  28 +
  29 +#endif // HACCP_H
... ...
app/gui/oven_control/keepwarmpopup.cpp
... ... @@ -3,6 +3,8 @@
3 3  
4 4 #include <QKeyEvent>
5 5  
  6 +#include "haccp.h"
  7 +
6 8 KeepWarmPopup::KeepWarmPopup(QWidget *parent) :
7 9 QWidget(parent),
8 10 ui(new Ui::KeepWarmPopup)
... ... @@ -19,6 +21,8 @@ KeepWarmPopup::KeepWarmPopup(QWidget *parent) :
19 21  
20 22 KeepWarmPopup::~KeepWarmPopup()
21 23 {
  24 + HACCP::done();
  25 +
22 26 delete ui;
23 27 }
24 28  
... ...
app/gui/oven_control/main.cpp
... ... @@ -5,6 +5,8 @@
5 5 #include "ovenstatics.h"
6 6 #include "config.h"
7 7 #include "inputoverwatcher.h"
  8 +#include "haccp.h"
  9 +
8 10 #include <QApplication>
9 11  
10 12 int main(int argc, char *argv[])
... ... @@ -32,6 +34,8 @@ int main(int argc, char *argv[])
32 34 pal.setColor(QPalette::Disabled, QPalette::Light, QColor(0, 0, 0, 0));
33 35 QApplication::setPalette(pal);
34 36  
  37 + HACCP::init();
  38 +
35 39 MainWindow w;
36 40 w.showFullScreen();
37 41  
... ...
app/gui/oven_control/manualcookwindow.cpp
... ... @@ -22,6 +22,7 @@
22 22 #include "washwindow.h"
23 23 #include "errorpopupdlg.h"
24 24 #include "manualviewerdlg.h"
  25 +#include "haccp.h"
25 26  
26 27 #include <QTime>
27 28  
... ... @@ -559,6 +560,8 @@ void ManualCookWindow::onOvenUpdated(Oven *oven)
559 560 lastCheckedCooking = oven->cooking();
560 561 cookDone = true;
561 562  
  563 + HACCP::done();
  564 +
562 565 emit done();
563 566 }
564 567 }
... ... @@ -619,6 +622,7 @@ void ManualCookWindow::start()
619 622 s.coreTemp = oven->interTemp();
620 623  
621 624 CookHistory::record(s);
  625 + HACCP::manualStart();
622 626  
623 627 if (monitorLevel > 0 && oven->door())
624 628 {
... ... @@ -637,6 +641,7 @@ void ManualCookWindow::stop()
637 641  
638 642 oven->stop();
639 643 startCookingTimer.stop();
  644 + HACCP::done();
640 645 }
641 646  
642 647 void ManualCookWindow::addFavorite()
... ...
app/gui/oven_control/multicookcontroller.cpp
1 1 #include "multicookcontroller.h"
2 2  
3 3 #include "oven.h"
  4 +#include "haccp.h"
4 5  
5 6 MultiCookController::MultiCookController(QObject *parent) : QObject(parent)
6 7 {
... ... @@ -47,7 +48,11 @@ void MultiCookController::check()
47 48 {
48 49 case Idle:
49 50 if (!container->isEmpty())
  51 + {
50 52 state = Preheating;
  53 +
  54 + HACCP::multiStart();
  55 + }
51 56 break;
52 57 case Preheating:
53 58 checkPreheating();
... ... @@ -81,6 +86,7 @@ void MultiCookController::checkPreheating()
81 86 if (container->isEmpty())
82 87 {
83 88 state = Idle;
  89 + HACCP::done();
84 90 oven->stop();
85 91 return;
86 92 }
... ... @@ -110,6 +116,7 @@ void MultiCookController::checkRunning()
110 116 if (container->isEmpty())
111 117 {
112 118 state = Idle;
  119 + HACCP::done();
113 120 oven->stop();
114 121 return;
115 122 }
... ... @@ -117,6 +124,7 @@ void MultiCookController::checkRunning()
117 124 if (container->isFinished())
118 125 {
119 126 state = Finished;
  127 + HACCP::done();
120 128 oven->stop();
121 129 container->stop();
122 130 return;
... ... @@ -188,6 +196,7 @@ void MultiCookController::checkFinished()
188 196 if (oven->door())
189 197 {
190 198 state = Idle;
  199 + HACCP::done();
191 200  
192 201 for (int i = 0; i < 10; i++)
193 202 {
... ...
app/gui/oven_control/oven_control.pro
... ... @@ -141,7 +141,8 @@ SOURCES += main.cpp\
141 141 multicookselectionwindow.cpp \
142 142 multicookmanualwindow.cpp \
143 143 multicookautowindow.cpp \
144   - multicookbook.cpp
  144 + multicookbook.cpp \
  145 + haccp.cpp
145 146  
146 147  
147 148 HEADERS += mainwindow.h \
... ... @@ -273,7 +274,8 @@ HEADERS += mainwindow.h \
273 274 multicookselectionwindow.h \
274 275 multicookmanualwindow.h \
275 276 multicookautowindow.h \
276   - multicookbook.h
  277 + multicookbook.h \
  278 + haccp.h
277 279  
278 280 FORMS += mainwindow.ui \
279 281 manualcookwindow.ui \
... ...
app/gui/oven_control/stringer.cpp
... ... @@ -237,11 +237,14 @@ QString Stringer::dateTime(const QDateTime &amp;dateTime, DateTimeType type)
237 237  
238 238 QString Stringer::time(int msecs)
239 239 {
240   - int t = qCeil(msecs / 1000.0);
  240 + return timeSecs(qCeil(msecs / 1000.0));
  241 +}
241 242  
242   - int h = t / (60*60);
243   - int m = (t/60) % 60;
244   - int s = t % 60;
  243 +QString Stringer::timeSecs(int secs)
  244 +{
  245 + int h = secs / (60*60);
  246 + int m = (secs/60) % 60;
  247 + int s = secs % 60;
245 248  
246 249 return QString("%1:%2:%3")
247 250 .arg(h, 2, 10, QLatin1Char('0'))
... ...
app/gui/oven_control/stringer.h
... ... @@ -28,6 +28,7 @@ QString unusedTemperature();
28 28 QString unusedTemperature(QString style);
29 29 QString dateTime(const QDateTime &dateTime, DateTimeType type = TwoLine);
30 30 QString time(int msecs);
  31 +QString timeSecs(int secs);
31 32  
32 33 }
33 34  
... ...
app/gui/oven_control/washwindow.cpp
... ... @@ -11,6 +11,7 @@
11 11 #include "ovenstatics.h"
12 12 #include "cooldownpopup.h"
13 13 #include "manualviewerdlg.h"
  14 +#include "haccp.h"
14 15  
15 16 WashWindow::WashWindow(QWidget *parent) :
16 17 QMainWindow(parent),
... ... @@ -389,6 +390,7 @@ void WashWindow::onChanged()
389 390 {
390 391 state = Running;
391 392  
  393 + HACCP::washStart(type);
392 394 updateView();
393 395 }
394 396 else
... ... @@ -403,6 +405,7 @@ void WashWindow::onChanged()
403 405 {
404 406 state = Idle;
405 407  
  408 + HACCP::done();
406 409 SoundPlayer::playStop();
407 410 DirtyLevel::wash(type);
408 411 OvenStatistics::getInstance()->setWashState(false);
... ... @@ -424,6 +427,7 @@ void WashWindow::onChanged()
424 427 case Stopping:
425 428 if (!udp->getData().cleaning_sate)
426 429 {
  430 + HACCP::done();
427 431 SoundPlayer::playStop();
428 432 OvenStatistics::getInstance()->setWashState(false);
429 433  
... ... @@ -437,6 +441,7 @@ void WashWindow::onChanged()
437 441 {
438 442 state = RunningClean;
439 443  
  444 + HACCP::washStart(6);
440 445 updateView();
441 446 }
442 447 else
... ... @@ -450,6 +455,8 @@ void WashWindow::onChanged()
450 455 else
451 456 {
452 457 state = Idle;
  458 +
  459 + HACCP::done();
453 460 SoundPlayer::playStop();
454 461 OvenStatistics::getInstance()->setWashState(false);
455 462  
... ...