Typica is a free program for professional coffee roasters. https://typica.us
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

productionroaster.xml 32KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. <window id="basicWindow">
  2. <layout type="vertical">
  3. <splitter type = "vertical" id = "main">
  4. <splitter type = "horizontal" id = "indicators" />
  5. <widget id="widget">
  6. <layout type="horizontal" id="controlpanel">
  7. <button name="Start Batch" type="push" id="startbutton" />
  8. <button name="Stop Batch" type="annotation" id="stopbutton" annotation="End" />
  9. </layout>
  10. </widget>
  11. <splitter type="horizontal" id="logsplit">
  12. <measurementtable id="log" />
  13. <graph id="graph" />
  14. </splitter>
  15. </splitter>
  16. </layout>
  17. <menu name="File">
  18. <item id="open" shortcut="Ctrl+O">Open…</item>
  19. <item id="save" shortcut="Ctrl+S">Save…</item>
  20. <item id="print" shortcut="Ctrl+P">Print…</item>
  21. <item id="export">Export CSV…</item>
  22. <item id="svgexport">Export XHTML+SVG…</item>
  23. <item id="quit" shortcut="Ctrl+Q">Quit</item>
  24. </menu>
  25. <menu name="Batch">
  26. <item id="new" shortcut="Ctrl+N">New Batch…</item>
  27. <item id="compare">Load Additional Profiles...</item>
  28. </menu>
  29. <menu name="Log">
  30. <item id="showC">Display Celsius</item>
  31. <item id="showF">Display Fahrenheit</item>
  32. <item id="setSample">New Sample Parameters</item>
  33. <separator />
  34. <item id="clear" shortcut="Ctrl+L">Clear Log</item>
  35. <separator />
  36. <item id="ms">Millisecond View</item>
  37. <item id="1s">1 Second View</item>
  38. <item id="5s">5 Second View</item>
  39. <item id="10s">10 Second View</item>
  40. <item id="15s">15 Second View</item>
  41. <item id="30s">30 Second View</item>
  42. <item id="1m">1 Minute View</item>
  43. <separator />
  44. <item id="manual" shortcut="Ctrl+E">Manual Entry</item>
  45. </menu>
  46. <menu name="Graph">
  47. <item id="unshift">Reset Translation</item>
  48. </menu>
  49. <program>
  50. <![CDATA[
  51. var window = this;
  52. var targetOffset = 0;
  53. var gtrans = 0;
  54. var targetDetector = new ThresholdDetector;
  55. window.targetcolumnname = "";
  56. var currentDetector = new ThresholdDetector;
  57. var translationChannel = -1;
  58. targetDetector.timeForValue.connect(function(value) {
  59. targetOffset = value;
  60. });
  61. var epoch = new QTime;
  62. epoch = epoch.currentTime;
  63. var translationCurrentColumn = -1;
  64. var configModel = new DeviceTreeModel;
  65. var rootIndex = configModel.index(roasterlist.currentIndex, 0);
  66. var channels = new Array();
  67. var annotationButtons = new Array();
  68. var nidevices = new Array();
  69. var dataqsdkdevices = new Array();
  70. var temperatureDisplays = new Array();
  71. var columnNames = new Array();
  72. var modbusdevices = new Array();
  73. var rateCalculators = new Array();
  74. var rateadapters = new Array();
  75. var rateoffsets = new Array();
  76. var ratezeros = new Array();
  77. var channelType = new Array();
  78. var indicatorPanel = findChildObject(this, 'indicators');
  79. var annotationPanel = findChildObject(this, 'controlpanel');
  80. var log = findChildObject(this, 'log');
  81. var tabControls = new Array();
  82. var start = findChildObject(this, 'startbutton');
  83. var stop = findChildObject(this, 'stopbutton');
  84. stop.enabled = false;
  85. tabControls.push(start);
  86. tabControls.push(stop);
  87. var nsparam = findChildObject(this, 'setSample');
  88. nsparam.enabled = false;
  89. var graph = findChildObject(this, 'graph');
  90. var hasTranslated = false;
  91. var externtrans = undefined;
  92. window.translateLoadedSeries = function(translation) {
  93. var lc = Number(QSettings.value("liveColumn"));
  94. for(var i = 1; i < lc - 1; i++)
  95. {
  96. graph.setSeriesTranslation(i, translation);
  97. }
  98. };
  99. window.translateCurrentSeries = function(translation) {
  100. var lc = Number(QSettings.value("liveColumn"));
  101. for(var i = 0; i < columnNames.length; i++)
  102. {
  103. graph.setSeriesTranslation(lc + i, translation);
  104. }
  105. };
  106. var selectedRoasterName = configModel.data(rootIndex, 0);
  107. var machineReference = configModel.referenceElement(configModel.data(rootIndex, 32));
  108. var selectedRoasterID = machineReference.databaseid;
  109. if(configModel.hasChildren(rootIndex)) {
  110. for(var i = 0; i < configModel.rowCount(rootIndex); i++) {
  111. var driverIndex = configModel.index(i, 0, rootIndex);
  112. var driverReference = configModel.referenceElement(configModel.data(driverIndex, 32));
  113. if(driverReference.driver == "nidaqmxbase" || driverReference.driver == "nidaqmx") {
  114. if(configModel.hasChildren(driverIndex)) {
  115. for(var j = 0; j < configModel.rowCount(driverIndex); j++) {
  116. var deviceIndex = configModel.index(j, 0, driverIndex);
  117. var deviceReference = configModel.referenceElement(configModel.data(deviceIndex, 32));
  118. if(deviceReference.driver == "nidaqmxbase9211series" || deviceReference.driver == "nidaqmx9211series") {
  119. var device = new DAQ(deviceReference.deviceID, driverReference.driver);
  120. nidevices.push(device);
  121. var DAQChannels = 0;
  122. if(configModel.hasChildren(deviceIndex)) {
  123. for(var k = 0; k < configModel.rowCount(deviceIndex); k++) {
  124. var channelIndex = configModel.index(k, 0, deviceIndex);
  125. var channelReference = configModel.referenceElement(configModel.data(channelIndex, 32));
  126. if(channelReference.driver == "ni9211seriestc") {
  127. var channel;
  128. if(channelReference.type == "J") {
  129. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeJ);
  130. }
  131. else if(channelReference.type == "K") {
  132. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeK);
  133. }
  134. else if(channelReference.type == "T") {
  135. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeT);
  136. }
  137. else if(channelReference.type == "B") {
  138. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeB);
  139. }
  140. else if(channelReference.type == "E") {
  141. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeE);
  142. }
  143. else if(channelReference.type == "N") {
  144. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeN);
  145. }
  146. else if(channelReference.type == "R") {
  147. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeR);
  148. }
  149. else if(channelReference.type == "S") {
  150. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeS);
  151. }
  152. channels.push(channel);
  153. channelType.push("T");
  154. columnNames.push(channelReference.columnname);
  155. DAQChannels++;
  156. var indicator = new TemperatureDisplay;
  157. temperatureDisplays.push(indicator);
  158. var decorator = new WidgetDecorator(indicator, configModel.data(channelIndex, 0), 2);
  159. channel.newData.connect(indicator.setValue);
  160. indicatorPanel.addWidget(decorator);
  161. }
  162. }
  163. switch(DAQChannels) {
  164. case 1:
  165. device.setClockRate(4);
  166. break;
  167. case 2:
  168. device.setClockRate(2);
  169. break;
  170. case 3:
  171. device.setClockRate(1.5);
  172. break;
  173. case 4:
  174. device.setClockRate(1);
  175. break;
  176. }
  177. device.start();
  178. }
  179. }
  180. else if(deviceReference.driver == "nidaqmxtc01")
  181. {
  182. var device = new DAQ(deviceReference.deviceID, "nidaqmx");
  183. var channel;
  184. if(deviceReference.type == "J")
  185. {
  186. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeJ);
  187. }
  188. else if(deviceReference.type == "K")
  189. {
  190. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeK);
  191. }
  192. else if(deviceReference.type == "T")
  193. {
  194. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeT);
  195. }
  196. else if(deviceReference.type == "B")
  197. {
  198. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeB);
  199. }
  200. else if(deviceReference.type == "E")
  201. {
  202. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeE);
  203. }
  204. else if(deviceReference.type == "N")
  205. {
  206. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeN);
  207. }
  208. else if(deviceReference.type == "R")
  209. {
  210. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeR);
  211. }
  212. else if(deviceReference.type == "S")
  213. {
  214. channel = device.newChannel(DAQ.Fahrenheit, DAQ.TypeS);
  215. }
  216. channels.push(channel);
  217. channelType.push("T");
  218. columnNames.push(deviceReference.columnname);
  219. var indicator = new TemperatureDisplay;
  220. temperatureDisplays.push(indicator);
  221. var decorator = new WidgetDecorator(indicator, configModel.data(deviceIndex, 0), 2);
  222. channel.newData.connect(indicator.setValue);
  223. indicatorPanel.addWidget(decorator);
  224. device.start();
  225. nidevices.push(device);
  226. }
  227. }
  228. }
  229. }
  230. else if(driverReference.driver == "dataqsdk") {
  231. var device;
  232. if(driverReference.autoSelect == "true") {
  233. device = new DataqSdkDevice(driverReference.deviceNumber);
  234. }
  235. else {
  236. device = new DataqSdkDevice(driverReference.port);
  237. }
  238. var sampleRate = 6;
  239. if(configModel.hasChildren(driverIndex)) {
  240. for(var j = 0; j < configModel.rowCount(driverIndex); j++) {
  241. var channelIndex = configModel.index(j, 0, driverIndex);
  242. var channelReference = configModel.referenceElement(configModel.data(channelIndex, 32));
  243. var indicator = new TemperatureDisplay;
  244. var unit;
  245. if(channelReference.type == "Temperature") {
  246. unit = Units.Fahrenheit;
  247. channelType.push("T");
  248. temperatureDisplays.push(indicator);
  249. }
  250. else {
  251. unit = Units.Unitless;
  252. indicator.setDisplayUnits(Units.Unitless);
  253. channelType.push("C");
  254. indicator.digitCount = 6;
  255. }
  256. var channel = device.newChannel(unit);
  257. var calibrator = new LinearCalibrator;
  258. calibrator.measuredLower = channelReference.calibrationMeasuredLower;
  259. calibrator.measuredUpper = channelReference.calibrationMeasuredUpper;
  260. calibrator.mappedLower = channelReference.calibrationMappedLower;
  261. calibrator.mappedUpper = channelReference.calibrationMappedUpper;
  262. calibrator.sensitivity = channelReference.calibrationSensitivity;
  263. if(channelReference.calibrationClosedInterval == 'true') {
  264. calibrator.closedRange = true;
  265. }
  266. // device.setSmoothingEnabled(j) = channelReference.smoothing;
  267. channel.newData.connect(calibrator.newMeasurement)
  268. channels.push(calibrator);
  269. columnNames.push(channelReference.column);
  270. var decorator = new WidgetDecorator(indicator, configModel.data(channelIndex, 0), 2);
  271. calibrator.newData.connect(indicator.setValue);
  272. indicatorPanel.addWidget(decorator);
  273. }
  274. sampleRate /= configModel.rowCount(driverIndex);
  275. }
  276. device.setClockRate(sampleRate);
  277. device.start();
  278. dataqsdkdevices.push(device);
  279. }
  280. else if(driverReference.driver == "modbusrtu")
  281. {
  282. var device = new ModbusRTUDevice(configModel, driverIndex);
  283. modbusdevices.push(device);
  284. var pvchannel = device.pVChannel();
  285. channels.push(pvchannel);
  286. channelType.push("T");
  287. columnNames.push(driverReference.pvcolname);
  288. var indicator = new TemperatureDisplay;
  289. temperatureDisplays.push(indicator);
  290. var decorator = new WidgetDecorator(indicator, configModel.data(driverIndex, 0) + " PV", 2);
  291. pvchannel.newData.connect(indicator.setValue);
  292. indicatorPanel.addWidget(decorator);
  293. if(driverReference.sVEnabled == "true")
  294. {
  295. var svchannel = device.sVChannel();
  296. channels.push(svchannel);
  297. channelType.push("C");
  298. columnNames.push(driverReference.svcolname);
  299. var indicator = new TemperatureDisplay;
  300. temperatureDisplays.push(indicator);
  301. var decorator = new WidgetDecorator(indicator, configModel.data(driverIndex, 0) + " SV", 2);
  302. svchannel.newData.connect(indicator.setValue);
  303. indicatorPanel.addWidget(decorator);
  304. }
  305. if(driverReference.sVWritable == "true")
  306. {
  307. var outputControl = new AnnotationSpinBox;
  308. device.SVLowerChanged.connect(function(min) {
  309. outputControl.minimum = min;
  310. });
  311. outputControl.minimum = device.SVLower();
  312. device.SVUpperChanged.connect(function(max) {
  313. outputControl.maximum = max;
  314. });
  315. outputControl.maximum = device.SVUpper();
  316. device.SVDecimalChanged.connect(function(prec) {
  317. outputControl.decimals = prec;
  318. });
  319. outputControl.decimals = device.decimals();
  320. outputControl.editingFinished.connect(function() {
  321. device.outputSV(outputControl.value);
  322. });
  323. var layout = new QBoxLayout;
  324. var label = new QLabel("Change SV");
  325. layout.addWidget(label, 0, 2);
  326. layout.addWidget(outputControl, 0, 1);
  327. annotationPanel.addLayout(layout);
  328. tabControls.push(outputControl);
  329. }
  330. }
  331. else if(driverReference.driver == "annotationbutton")
  332. {
  333. var button = new AnnotationButton(driverReference.buttontext);
  334. button.setAnnotation(driverReference.annotationtext);
  335. annotationButtons.push(button);
  336. annotationPanel.addWidget(button);
  337. tabControls.push(button);
  338. }
  339. else if(driverReference.driver == "reconfigurablebutton")
  340. {
  341. var button = new AnnotationButton(driverReference.buttontext);
  342. button.setAnnotation(driverReference.annotationtext);
  343. annotationButtons.push(button);
  344. annotationPanel.addWidget(button);
  345. tabControls.push(button);
  346. nsparam.enabled = true;
  347. nsparam.triggered.connect(function() {
  348. var setParam = createWindow("sampleParameters");
  349. setParam.windowTitle = "Typica - Set Sample Parameters";
  350. setParam.button = button;
  351. });
  352. }
  353. else if(driverReference.driver == "annotationspinbox")
  354. {
  355. var layout = new QBoxLayout;
  356. var label = new QLabel(driverReference.label);
  357. layout.addWidget(label, 0, 2);
  358. var spinbox = new AnnotationSpinBox;
  359. spinbox.setPretext(driverReference.pretext);
  360. spinbox.setPosttext(driverReference.posttext);
  361. spinbox.minimum = driverReference.minimum;
  362. spinbox.maximum = driverReference.maximum;
  363. spinbox.decimals = driverReference.precision;
  364. layout.addWidget(spinbox, 0, 1);
  365. annotationPanel.addLayout(layout);
  366. annotationButtons.push(spinbox);
  367. tabControls.push(spinbox);
  368. }
  369. else if(driverReference.driver == "freeannotation")
  370. {
  371. var layout = new QBoxLayout;
  372. var label = new QLabel(driverReference.labeltext);
  373. var control = new QLineEdit;
  374. layout.addWidget(label, 0, 2);
  375. layout.addWidget(control, 0, 1);
  376. annotationPanel.addLayout(layout);
  377. tabControls.push(control);
  378. control.returnPressed.connect(function() {
  379. for(var i = window.firstTempColumn; i < window.annotationColumn; i++) {
  380. log.newAnnotation(control.text, i, window.annotationColumn);
  381. }
  382. });
  383. }
  384. else if(driverReference.driver == "linearspline")
  385. {
  386. var colname = driverReference.source;
  387. for(var j = 0; j < columnNames.length; j++)
  388. {
  389. if(columnNames[j] == colname)
  390. {
  391. var calibrator = new LinearSplineInterpolator;
  392. var sv = driverReference.sourcevalues;
  393. var dv = driverReference.destinationvalues;
  394. var sourcevalues = sv.slice(2, sv.length-2).split(",");
  395. var destvalues = dv.slice(2, dv.length-2).split(",");
  396. if(sourcevalues.length > 1 && destvalues.length == sourcevalues.length)
  397. {
  398. for(var k = 0; k < sourcevalues.length; k++)
  399. {
  400. calibrator.add_pair(Number(sourcevalues[k]),Number(destvalues[k]));
  401. }
  402. var indicator = new TemperatureDisplay;
  403. temperatureDisplays.push(indicator);
  404. var decorator = new WidgetDecorator(indicator, configModel.data(driverIndex, 0), 2);
  405. channels[j].newData.connect(calibrator.newMeasurement);
  406. calibrator.newData.connect(indicator.setValue);
  407. channels.push(calibrator);
  408. channelType.push(channelType[j]);
  409. columnNames.push(driverReference.destination);
  410. indicatorPanel.addWidget(decorator);
  411. }
  412. break;
  413. }
  414. }
  415. }
  416. else if(driverReference.driver == "translation")
  417. {
  418. var colname = driverReference.column;
  419. window.targetcolumnname = colname;
  420. for(var j = 0; j < columnNames.length; j++)
  421. {
  422. if(columnNames[j] == colname)
  423. {
  424. translationChannel = j;
  425. var indicator = new TemperatureDisplay;
  426. indicator.digitCount = 4;
  427. externtrans = indicator;
  428. indicator.display(0);
  429. var decorator = new WidgetDecorator(indicator, configModel.data(driverIndex, 0), 2);
  430. indicatorPanel.addWidget(decorator);
  431. currentDetector.timeForValue.connect(function(value) {
  432. if(!hasTranslated)
  433. {
  434. var currentOffset = value;
  435. if(targetOffset != 0)
  436. {
  437. var translation = currentOffset - targetOffset;
  438. externtrans.display(translation);
  439. gtrans = translation;
  440. if(translation > 0)
  441. {
  442. window.translateLoadedSeries(translation);
  443. }
  444. else
  445. {
  446. window.translateCurrentSeries(-translation);
  447. }
  448. }
  449. }
  450. hasTranslated = true;
  451. });
  452. var resetTranslation = findChildObject(this, 'unshift');
  453. resetTranslation.triggered.connect(function() {
  454. if(gtrans > 0) {
  455. window.translateLoadedSeries(-gtrans);
  456. }
  457. else {
  458. window.translateCurrentSeries(gtrans);
  459. }
  460. gtrans = 0;
  461. indicator.display(0);
  462. });
  463. }
  464. }
  465. targetDetector.setThreshold(driverReference.FValue);
  466. currentDetector.setThreshold(driverReference.FValue);
  467. }
  468. else if(driverReference.driver == "rate")
  469. {
  470. var primaryColumn = driverReference.column;
  471. for(var j = 0; j < columnNames.length; j++)
  472. {
  473. if(columnNames[j] == primaryColumn)
  474. {
  475. var rate = new RateOfChange(driverReference.cache, driverReference.scale);
  476. channels[j].newData.connect(rate.newMeasurement);
  477. var indicator = new TemperatureDisplay;
  478. indicator.setRelativeMode(true);
  479. indicator.display(0);
  480. indicator.digitCount = 9;
  481. var decorator = new WidgetDecorator(indicator, configModel.data(driverIndex, 0), 2);
  482. indicatorPanel.addWidget(decorator);
  483. rate.newData.connect(indicator.setValue);
  484. temperatureDisplays.push(indicator);
  485. channels.push(rate);
  486. channelType.push("T");
  487. columnNames.push(configModel.data(driverIndex, 0));
  488. }
  489. }
  490. }
  491. }
  492. }
  493. for(var i = 1; i < tabControls.length; i++)
  494. {
  495. setTabOrder(tabControls[i-1], tabControls[i]);
  496. }
  497. log.setHeaderData(0, "Time");
  498. for(var i = 0; i < columnNames.length; i++) {
  499. log.setHeaderData(i + 1, columnNames[i]);
  500. }
  501. log.setHeaderData(columnNames.length + 1, "Note");
  502. for(var i = 0; i < channels.length; i++) {
  503. log.addToCurrentColumnSet(i + 1);
  504. }
  505. var timer = new TimerDisplay;
  506. timer.displayFormat = "mm:ss";
  507. timer.autoReset = true;
  508. var btdecorator = new WidgetDecorator(timer, "Batch Timer", 2);
  509. indicatorPanel.addWidget(btdecorator);
  510. var vsplit = findChildObject(this, 'main');
  511. var isplit = findChildObject(this, 'indicators');
  512. var lsplit = findChildObject(this, 'logsplit');
  513. window.aboutToClose.connect(function() {
  514. for(var i = 0; i < nidevices.length; i++)
  515. {
  516. nidevices[i].stop();
  517. nidevices[i].deleteLater();
  518. }
  519. for(var i = 0; i < modbusdevices.length; i++)
  520. {
  521. modbusdevices[i].deleteLater();
  522. }
  523. for(var i = 0; i < dataqsdkdevices.length; i++)
  524. {
  525. dataqsdkdevices[i].deleteLater();
  526. }
  527. delete nidevices;
  528. delete modbusdevices;
  529. delete dataqsdkdevices;
  530. window.saveSizeAndPosition("window");
  531. vsplit.saveState("script/mainSplitter");
  532. isplit.saveState("script/instrumentSplitter");
  533. lsplit.saveState("script/logSplitter");
  534. log.saveState("script/log", 7);
  535. window.navigationWindow.loggingWindow = undefined;
  536. });
  537. this.restoreSizeAndPosition('window');
  538. vsplit.restoreState("script/mainSplitter");
  539. isplit.restoreState("script/instrumentSplitter");
  540. lsplit.restoreState("script/logSplitter");
  541. log.restoreState("script/log", 7);
  542. var offsets = new Array();
  543. var zeroemitters = new Array();
  544. var adapters = new Array();
  545. for(var i = 0; i < channels.length; i++) {
  546. var offset = new MeasurementTimeOffset(epoch);
  547. offsets.push(offset);
  548. channels[i].newData.connect(offset.newMeasurement);
  549. var adapter = new MeasurementAdapter(i + 1);
  550. adapters.push(adapter);
  551. offset.measurement.connect(adapter.newMeasurement);
  552. var emitter = new ZeroEmitter(i + 1);
  553. zeroemitters.push(emitter);
  554. channels[i].newData.connect(emitter.newMeasurement);
  555. emitter.measurement.connect(log.newMeasurement);
  556. emitter.measurement.connect(graph.newMeasurement);
  557. }
  558. start.clicked.connect(function() {
  559. start.enabled = false;
  560. hasTranslated = false;
  561. var epoch = new QTime();
  562. epoch = epoch.currentTime();
  563. for(var i = 0; i < offsets.length; i++)
  564. {
  565. offsets[i].setZeroTime(epoch);
  566. zeroemitters[i].emitZero();
  567. adapters[i].measurement.connect(log.newMeasurement);
  568. adapters[i].measurement.connect(graph.newMeasurement);
  569. }
  570. for(var i = 0; i < rateadapters.length; i++)
  571. {
  572. rateoffsets[i].setZeroTime(epoch);
  573. ratezeros[i].emitZero();
  574. rateadapters[i].measurement.connect(graph.newMeasurement);
  575. }
  576. timer.startTimer();
  577. if(typeof(currentBatchInfo) == 'undefined') { } else {
  578. query = new QSqlQuery();
  579. query.exec("SELECT now()::timestamp without time zone");
  580. query.next();
  581. var result = query.value(0);
  582. query = query.invalidate();
  583. var timefield = findChildObject(currentBatchInfo, 'time');
  584. timefield.text = result.replace('T', ' ');
  585. }
  586. if(translationChannel >= 0)
  587. {
  588. offsets[translationChannel].measurement.connect(currentDetector.newMeasurement);
  589. }
  590. if(typeof(externtrans) != 'undefined') {
  591. externtrans.display(0);
  592. }
  593. stop.enabled = true;
  594. window.windowModified = true;
  595. graph.setTimeIndicatorEnabled(true);
  596. });
  597. for(var i = 0; i < annotationButtons.length; i++) {
  598. if(channels.length > 0)
  599. {
  600. annotationButtons[i].annotation.connect(log.newAnnotation);
  601. annotationButtons[i].setTemperatureColumn(1);
  602. annotationButtons[i].setAnnotationColumn(channels.length + 1);
  603. annotationButtons[i].annotation.connect(function(note, tcol, ncol) {
  604. for(var i = tcol; i < ncol; i++) {
  605. log.newAnnotation(note, i, ncol);
  606. }
  607. });
  608. }
  609. }
  610. start.setFocus();
  611. stop.annotation.connect(log.newAnnotation);
  612. stop.clicked.connect(timer.stopTimer);
  613. stop.setTemperatureColumn(1);
  614. stop.setAnnotationColumn(channels.length + 1);
  615. QSettings.setValue("liveColumn", 1);
  616. var lc = 1;
  617. stop.clicked.connect(function() {
  618. stop.enabled = false;
  619. for(var i = 0; i < adapters.length; i++)
  620. {
  621. adapters[i].measurement.disconnect(log.newMeasurement);
  622. adapters[i].measurement.disconnect(graph.newMeasurement);
  623. }
  624. for(var i = 0; i < rateadapters.length; i++)
  625. {
  626. rateadapters[i].measurement.disconnect(graph.newMeasurement);
  627. }
  628. if(typeof(currentBatchInfo) == 'undefined') { } else {
  629. lc = Number(QSettings.value("liveColumn"));
  630. var duration = log.lastTime(lc);
  631. var durfield = findChildObject(currentBatchInfo, 'duration');
  632. durfield.text = duration;
  633. log.clearOutputColumns();
  634. for(var i = 0; i < channels.length; i++) {
  635. if(channelType[i] == "T") {
  636. log.addOutputTemperatureColumn(lc + i);
  637. }
  638. else {
  639. log.addOutputControlColumn(lc + i);
  640. }
  641. }
  642. log.addOutputAnnotationColumn(lc + channels.length);
  643. var filename = log.saveTemporary();
  644. currentBatchInfo.tempData = filename;
  645. currentBatchInfo.raise();
  646. currentBatchInfo.activateWindow();
  647. }
  648. if(translationChannel >= 0)
  649. {
  650. offsets[translationChannel].measurement.disconnect(currentDetector.newMeasurement);
  651. }
  652. start.enabled = true;
  653. window.windowModified = false;
  654. graph.setTimeIndicatorEnabled(false);
  655. });
  656. stop.annotation.connect(function(note, tcol, ncol) {
  657. for(var i = tcol; i < ncol; i++) {
  658. log.newAnnotation(note, i, ncol);
  659. }
  660. });
  661. var quitMenu = findChildObject(this, 'quit');
  662. quitMenu.triggered.connect(function() {
  663. window.close();
  664. Application.quit();
  665. });
  666. var v1 = findChildObject(this, 'ms');
  667. v1.triggered.connect(log.LOD_ms);
  668. var v2 = findChildObject(this, '1s');
  669. v2.triggered.connect(log.LOD_1s);
  670. var v3 = findChildObject(this, '5s');
  671. v3.triggered.connect(log.LOD_5s);
  672. var v4 = findChildObject(this, '10s');
  673. v4.triggered.connect(log.LOD_10s);
  674. var v5 = findChildObject(this, '15s');
  675. v5.triggered.connect(log.LOD_15s);
  676. var v6 = findChildObject(this, '30s');
  677. v6.triggered.connect(log.LOD_30s);
  678. var v7 = findChildObject(this, '1m');
  679. v7.triggered.connect(log.LOD_1m);
  680. var showC = findChildObject(this, 'showC');
  681. showC.triggered.connect(function() {
  682. for(var i = 0; i < temperatureDisplays.length; i++)
  683. {
  684. temperatureDisplays[i].setDisplayUnits(Units.Celsius);
  685. }
  686. log.setDisplayUnits(Units.Celsius);
  687. graph.showC();
  688. });
  689. var showF = findChildObject(this, 'showF');
  690. showF.triggered.connect(function() {
  691. for(var i = 0; i < temperatureDisplays.length; i++)
  692. {
  693. temperatureDisplays[i].setDisplayUnits(Units.Fahrenheit);
  694. }
  695. log.setDisplayUnits(Units.Fahrenheit);
  696. graph.showF();
  697. });
  698. var clear = findChildObject(this, 'clear');
  699. clear.triggered.connect(log.clear);
  700. clear.triggered.connect(graph.clear);
  701. clear.triggered.connect(function() {
  702. window.windowTitle = "Typica [*]";
  703. log.setHeaderData(0, "Time");
  704. QSettings.setValue("liveColumn", 1);
  705. window.postLoadColumnSetup(0);
  706. if(typeof(externtrans) != 'undefined') {
  707. externtrans.display(0);
  708. }
  709. });
  710. var openMenu = findChildObject(this, 'open');
  711. var compareMenu = findChildObject(this, 'compare');
  712. compareMenu.triggered.connect(function() {
  713. QSettings.setValue('cseries', lc+1);
  714. var history = createWindow("history");
  715. history.windowTitle = 'Typica - Roasting Log';
  716. });
  717. var printMenu = findChildObject(this, 'print');
  718. printMenu.triggered.connect(function() {
  719. var exportWindow = createWindow("print");
  720. exportWindow.windowTitle = "Typica - Print";
  721. exportWindow.log = log;
  722. });
  723. var svgExportMenu = findChildObject(this, 'svgexport');
  724. svgExportMenu.triggered.connect(function() {
  725. var exportWindow = createWindow("exportWindow");
  726. exportWindow.windowTitle = "Typica - Export XHTML+SVG";
  727. exportWindow.log = log;
  728. });
  729. openMenu.triggered.connect(function() {
  730. var filename = QFileDialog.getOpenFileName(window, 'Open Log…', QSettings.value('script/lastDir', '') + '/');
  731. if(filename != '') {
  732. var file = new QFile(filename);
  733. var input = new XMLInput(file, 1);
  734. targetseries = -1;
  735. input.newTemperatureColumn.connect(log.setHeaderData);
  736. input.newTemperatureColumn.connect(function(col, text) {
  737. if(text == window.targetcolumnname) {
  738. targetseries = col;
  739. }
  740. });
  741. input.newAnnotationColumn.connect(log.setHeaderData);
  742. input.measure.connect(graph.newMeasurement);
  743. input.measure.connect(log.newMeasurement);
  744. input.measure.connect(function(data, series) {
  745. if(series == targetseries) {
  746. targetDetector.newMeasurement(data);
  747. }
  748. });
  749. input.annotation.connect(log.newAnnotation);
  750. input.annotation.connect(function(note, tcol, ncol) {
  751. for(var i = tcol; i < ncol; i++) {
  752. log.newAnnotation(note, i, ncol);
  753. }
  754. });
  755. var lc;
  756. input.lastColumn.connect(function(c) {
  757. lc = c;
  758. QSettings.setValue("liveColumn", c + 1);
  759. window.postLoadColumnSetup(c);
  760. });
  761. input.input();
  762. window.windowTitle = 'Typica - [*]' + baseName(filename);
  763. QSettings.setValue("script/lastDir", dir(filename));
  764. log.newAnnotation("End", 1, lc);
  765. }
  766. });
  767. window.postLoadColumnSetup = function(c) {
  768. for(var i = 0; i < adapters.length; i++)
  769. {
  770. adapters[i].setColumn(c + i + 1);
  771. zeroemitters[i].setColumn(c + i + 1);
  772. log.setHeaderData(c + i + 1, columnNames[i]);
  773. }
  774. log.setHeaderData(c + columnNames.length + 1, "Note");
  775. stop.setTemperatureColumn(c + 1);
  776. stop.setAnnotationColumn(c + columnNames.length + 1);
  777. for(var i = 0; i < annotationButtons.length; i++)
  778. {
  779. annotationButtons[i].setTemperatureColumn(c + 1);
  780. annotationButtons[i].setAnnotationColumn(c + columnNames.length + 1);
  781. }
  782. log.clearCurrentColumnSet();
  783. for(var i = 0; i < channels.length; i++) {
  784. log.addToCurrentColumnSet(c + i + 1);
  785. }
  786. window.firstTempColumn = c + 1;
  787. window.annotationColumn = c + columnNames.length + 1;
  788. }
  789. var saveMenu = findChildObject(this, 'save');
  790. saveMenu.triggered.connect(function() {
  791. var filename = QFileDialog.getSaveFileName(window, "Save Log As…", QSettings.value("script/lastDir", "") + "/");
  792. if(filename != "") {
  793. var lc = Number(QSettings.value("liveColumn"));
  794. var file = new QFile(filename);
  795. log.clearOutputColumns();
  796. for(var i = 0; i < columnNames.length; i++)
  797. {
  798. if(channelType[i] == "T") {
  799. log.addOutputTemperatureColumn(lc + i);
  800. }
  801. else {
  802. log.addOutputControlColumn(lc + i);
  803. }
  804. }
  805. log.addOutputAnnotationColumn(lc + columnNames.length);
  806. log.saveXML(file);
  807. QSettings.setValue("script/lastDir", dir(filename));
  808. }
  809. });
  810. var exportMenu = findChildObject(this, 'export');
  811. exportMenu.triggered.connect(function() {
  812. var filename = QFileDialog.getSaveFileName(window, "Export CSV As…", QSettings.value("script/lastDir", "") + "/");
  813. if(filename != "") {
  814. var lc = Number(QSettings.value("liveColumn"));
  815. var file = new QFile(filename);
  816. log.clearOutputColumns();
  817. for(var i = 0; i < columnNames.length; i++)
  818. {
  819. log.addOutputTemperatureColumn(lc + i);
  820. }
  821. log.addOutputAnnotationColumn(lc + columnNames.length);
  822. log.saveCSV(file);
  823. QSettings.setValue("script/lastDir", dir(filename));
  824. }
  825. });
  826. var manual = findChildObject(this, 'manual');
  827. manual.triggered.connect(function() {
  828. var entry = new LogEditWindow();
  829. entry.show();
  830. });
  831. var newMenu = findChildObject(this, 'new');
  832. newMenu.triggered.connect(function() {
  833. var bwindow = createWindow("batchWindow");
  834. bwindow.windowTitle = "Typica - [*]New Batch";
  835. });
  836. window.postLoadColumnSetup(0);
  837. ]]>
  838. </program>
  839. </window>