hal.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. /*
  2. * hal.cpp
  3. *
  4. * Created on: Aug 3, 2016
  5. * Author: Philipp Hinz, Sebastian Vendt
  6. */
  7. #include <wiringPi.h>
  8. #include <stdlib.h>
  9. #include <stdint.h>
  10. #include <errno.h>
  11. #include <string.h>
  12. #include <signal.h>
  13. #include <ctime>
  14. #include <time.h>
  15. #include <unistd.h>
  16. #include "hal.h"
  17. #include "global.h"
  18. #include "logger.h"
  19. #include "timer.h"
  20. #include "database.h"
  21. const char* SigName[] = {
  22. "NULL",
  23. "SigInt0Psh",
  24. "SigInt0Rls",
  25. "SigInt0RlsLong",
  26. "SigInt1Psh",
  27. "SigInt1Rls",
  28. "SigInt1RlsLong",
  29. "SigPressCls",
  30. "SigPressOpn",
  31. "SigProxOpn",
  32. "SigProxCvrd",
  33. "SigBrewOn",
  34. "SigBrewOff",
  35. "SigPowerUp",
  36. "SigPowerDown",
  37. "SigRotCW",
  38. "SigRotCCW"};
  39. typedef struct timespec timespec;
  40. volatile int flowcnt = 0;
  41. int lastFlowcnt = 0;
  42. int flowResetValue = -1;
  43. bool brewmanual = false;
  44. //local copies of the corresponding database entries
  45. time_t heatingCycleStart = 0;
  46. uint64_t totalHeatingTime = 0; //total heating time in seconds
  47. uint16_t flowResetTime = 0; //see TIME_FLOWRESET for details
  48. int Int0Time, Int1Time;
  49. int idleCounter;
  50. bool idle;
  51. bool flagIgnoreRlsInt0, flagIgnoreRlsInt1;
  52. //storage for the last state of the buttons, the proximity sensor and the pressure sensor
  53. int pinState[4] = {1, 1, 1, 0};
  54. //state of the rotary encoder
  55. //0: rotary1 state at t-1
  56. //1: rotary2 state at t-1
  57. //2: rotary1 state at t
  58. //3: rotary2 state at t
  59. int rotaryState[4] = {1, 0, 0, 1};
  60. timer Int0Timer(&halInt0TimerHandler);
  61. timer Int1Timer(&halInt1TimerHandler);
  62. timer idleTimer(&halIdleTimerHandler);
  63. timer flowResetTimer (&flowResetTimerHandler);
  64. timer flowTimer(&halFlowTimerHandler);
  65. timespec flowTimestep[] = {{0,0},{0,0}};
  66. uint8_t flowIndex = 0;
  67. int16_t tickCounter = 0; //rotary encoder
  68. uint16_t flowtime = 0;
  69. uint16_t lastFlowTime = 0;
  70. bool brewSigFired = false;
  71. //delay of the debounce in milliseconds
  72. #define DELAY_DEBOUNCE 50
  73. #define DELAY_MICRODEB 2
  74. //display turn off after idle time in min
  75. //minimal time is 2min
  76. #define IDLE_TIME 10
  77. /**
  78. * Initializes HAL
  79. */
  80. void halInit(void) {
  81. pinMode(RELAIS_HEAT, OUTPUT);
  82. pinMode(RELAIS_PUMP, OUTPUT);
  83. pinMode(RELAIS_POWER, OUTPUT);
  84. pinMode(PIN_PRESSURE_CTRL, INPUT);
  85. pinMode(PIN_PROXIMITY_SENSOR, INPUT);
  86. pinMode(PIN_INT0, INPUT);
  87. pinMode(PIN_INT1, INPUT);
  88. pinMode(PIN_FLOW, INPUT);
  89. pinMode(PIN_DISP, OUTPUT);
  90. pinMode(PIN_ROTARY1, INPUT);
  91. pinMode(PIN_ROTARY2, INPUT);
  92. idleTimer.setDivider(ms2Divider(60000));
  93. idleCounter = 0;
  94. idle = false;
  95. clock_gettime(CLOCK_REALTIME, &flowTimestep[0]);
  96. clock_gettime(CLOCK_REALTIME, &flowTimestep[1]);
  97. halDisplayOn();
  98. if (!(totalHeatingTime = sqlGetConf(CFGHeatingTime))) {
  99. logger_error("hal.cpp: Couldn't read the total heating time from the database\n");
  100. //pthread_exit(EXIT_SUCCESS);
  101. exit(EXIT_FAILURE);
  102. }
  103. if (!(flowResetTime = sqlGetConf(CFGFlowResetTime))) {
  104. flowResetTime = TIME_FLOWRESET;
  105. logger_error("hal.cpp: Couldn't read the flow reset time from the database\nFalling back to defaults.\n");
  106. }
  107. if (optPower) {
  108. halMachineOn();
  109. } else {
  110. halMachineOff();
  111. }
  112. sleep(1); //wait till the machine eventually turned on when optPower
  113. pinState[3] = halIsHeating();
  114. Int0Timer.setDivider(ms2Divider(200));
  115. Int1Timer.setDivider(ms2Divider(200));
  116. Int0Time = 0;
  117. Int1Time = 0;
  118. flowResetTimer.setDivider(ms2Divider(TIME_FLOWRESET));
  119. flowTimer.setDivider(ms2Divider(200));
  120. flagIgnoreRlsInt0 = false;
  121. flagIgnoreRlsInt1 = false;
  122. event_subscribe("terminate", &halTerminate, "hal.cpp");
  123. if (wiringPiISR(PIN_INT0, INT_EDGE_BOTH, &halInt0) < 0) {
  124. logger_error("Unable to setup ISR0: %s\n", strerror(errno));
  125. return;
  126. }
  127. if (wiringPiISR(PIN_INT1, INT_EDGE_BOTH, &halInt1) < 0) {
  128. logger_error("Unable to setup ISR1: %s\n", strerror(errno));
  129. return;
  130. }
  131. if (wiringPiISR(PIN_FLOW, INT_EDGE_FALLING, &halIntFlow) < 0) {
  132. logger_error("Unable to setup ISRFLOW: %s\n", strerror(errno));
  133. return;
  134. }
  135. if (wiringPiISR(PIN_PRESSURE_CTRL, INT_EDGE_BOTH, &halIntPressure) < 0) {
  136. logger_error("Unable to setup ISRPressure: %s\n", strerror(errno));
  137. return;
  138. }
  139. if (wiringPiISR(PIN_PROXIMITY_SENSOR, INT_EDGE_BOTH, &halIntProximity) < 0) {
  140. logger_error("Unable to setup ISRProximity: %s\n", strerror(errno));
  141. return;
  142. }
  143. if (wiringPiISR(PIN_ROTARY1, INT_EDGE_BOTH, &halIntRotary) < 0) {
  144. logger_error("Unable to setup ISRRotary2: %s\n", strerror(errno));
  145. return;
  146. }
  147. logger(V_BASIC, "hal.cpp: Initialized\n");
  148. }
  149. /**
  150. * Switches relais on
  151. * @param relais Relais ID
  152. */
  153. void halRelaisOn(int relais) {
  154. halRelaisSet(relais, LOW);
  155. }
  156. /**
  157. * Turn the display off
  158. */
  159. void halDisplayOff(){
  160. digitalWrite(PIN_DISP, LOW);
  161. }
  162. /**
  163. * Turn the display on
  164. */
  165. void halDisplayOn(){
  166. digitalWrite(PIN_DISP, HIGH);
  167. }
  168. /**
  169. * Switches relais off
  170. * @param relais Relais ID
  171. */
  172. void halRelaisOff(int relais) {
  173. halRelaisSet(relais, HIGH);
  174. }
  175. /**
  176. * Switches relais to state
  177. * @param relais Relais ID
  178. * @param state LOW(0) or HIGH(1)
  179. */
  180. void halRelaisSet(int relais, int state) {
  181. if (state != HIGH && state != LOW)
  182. return;
  183. switch (relais) {
  184. case RELAIS_POWER:
  185. case RELAIS_HEAT:
  186. case RELAIS_PUMP:
  187. digitalWrite(relais, state);
  188. break;
  189. }
  190. }
  191. /**
  192. * Returns the state of the relais relais
  193. * Returns HIGH when Relais is ON
  194. * @param relais Relais ID
  195. */
  196. int halGetRelaisState(int relais) {
  197. switch (relais) {
  198. case RELAIS_POWER:
  199. case RELAIS_HEAT:
  200. case RELAIS_PUMP:
  201. return !digitalRead(relais);
  202. break;
  203. }
  204. return -1;
  205. }
  206. /**
  207. *
  208. */
  209. void halIntRotary(void) {
  210. //delay(DELAY_MICRODEB);
  211. rotaryState[2] = digitalRead(PIN_ROTARY1);
  212. rotaryState[3] = digitalRead(PIN_ROTARY2);
  213. if (rotaryState[0] != rotaryState[2]) {
  214. //check for the status of the other pin
  215. if (rotaryState[1] != rotaryState[3]) {
  216. if ((rotaryState[2] == HIGH && rotaryState[3] == LOW) || (rotaryState[2] == LOW && rotaryState[3] == HIGH)) {
  217. //clockwise rotation
  218. tickCounter++;
  219. if (!(abs(tickCounter) % ROTARY_STEPSIZE)) {
  220. //logger(V_HAL, "rotary encoder CW \n");
  221. halSendSignal(SigRotCW);
  222. tickCounter = 0;
  223. }
  224. } else if ((rotaryState[2] == HIGH && rotaryState[3] == HIGH) || (rotaryState[2] == LOW && rotaryState[3] == LOW)) {
  225. //counterclockwise rotation
  226. tickCounter--;
  227. if (!(abs(tickCounter) % ROTARY_STEPSIZE)) {
  228. //logger(V_HAL, "rotary encoder CCW \n");
  229. halSendSignal(SigRotCCW);
  230. tickCounter = 0;
  231. }
  232. }
  233. rotaryState[1] = rotaryState[3];
  234. }
  235. rotaryState[0] = rotaryState[2];
  236. }
  237. }
  238. /**
  239. * Interrupt routine for Int0 (Top button)
  240. */
  241. void halInt0(void) {
  242. //wait for a debounce
  243. delay(DELAY_DEBOUNCE);
  244. if (halGetInt0() && !pinState[0]) { //released
  245. logger(V_HAL, "Int0 released\n");
  246. pinState[0] = 1;
  247. if (flagIgnoreRlsInt0) {
  248. flagIgnoreRlsInt0 = false;
  249. } else {
  250. Int0Time = 0;
  251. Int0Timer.stop();
  252. halSendSignal(SigInt0Rls);
  253. }
  254. } else if(!halGetInt0() && pinState[0]) { //pressed
  255. logger(V_HAL, "Int0 pushed\n");
  256. pinState[0] = 0;
  257. halSendSignal(SigInt0Psh);
  258. Int0Time = 0;
  259. Int0Timer.start();
  260. }
  261. }
  262. /**
  263. *
  264. */
  265. void halInt0TimerHandler(void) {
  266. Int0Time += 200;
  267. if (Int0Time >= (TIME_BUTTONLONGPRESS * 1000)) {
  268. halSendSignal(SigInt0RlsLong);
  269. flagIgnoreRlsInt0 = true;
  270. Int0Time = 0;
  271. Int0Timer.stop();
  272. }
  273. }
  274. /**
  275. *
  276. */
  277. void halIdleTimerHandler(void) {
  278. if(++idleCounter == IDLE_TIME){
  279. halEnterIdle();
  280. }
  281. }
  282. /**
  283. * Interrupt routine for Int1 (Bottom button)
  284. */
  285. void halInt1(void) {
  286. delay(DELAY_DEBOUNCE);
  287. if (halGetInt1() && !pinState[1]) {
  288. logger(V_HAL, "Int1 released\n");
  289. pinState[1] = 1;
  290. if (flagIgnoreRlsInt1) {
  291. flagIgnoreRlsInt1 = false;
  292. } else {
  293. Int1Time = 0;
  294. Int1Timer.stop();
  295. halSendSignal(SigInt1Rls);
  296. }
  297. } else if(!halGetInt1() && pinState[1]) {
  298. logger(V_HAL, "Int1 pushed\n");
  299. pinState[1] = 0;
  300. halSendSignal(SigInt1Psh);
  301. Int1Time = 0;
  302. Int1Timer.start();
  303. }
  304. }
  305. /*
  306. *
  307. */
  308. void halInt1TimerHandler(void) {
  309. Int1Time += 200;
  310. if (Int1Time >= (TIME_BUTTONLONGPRESS * 1000)) {
  311. halSendSignal(SigInt1RlsLong);
  312. flagIgnoreRlsInt1 = true;
  313. Int1Time = 0;
  314. Int1Timer.stop();
  315. }
  316. }
  317. /**
  318. * Timer handler to auto-reset the flow counter.
  319. * The timer is started when the flow interrupt is triggered.
  320. * It compares the last value (flowResetValue) with the current flow value
  321. * If they match (e.g no flow within 1000ms) the flow counter is reseted.
  322. * Setting the last value to -1 ensures that when the timer gets called immediately after it is started the comparison will fail.
  323. * This implementation is read-only and so it doesn't need semaphores.
  324. */
  325. void flowResetTimerHandler() {
  326. if(flowResetValue == flowcnt) {
  327. halResetFlow();
  328. return;
  329. }
  330. flowResetValue = flowcnt;
  331. }
  332. /**
  333. *
  334. */
  335. void halFlowTimerHandler() {
  336. flowtime += 200;
  337. }
  338. /**
  339. * Interrupt routine for the flow sensor
  340. * It counts the edges and stores the value in flowcnt
  341. */
  342. void halIntFlow(void) {
  343. //halRelaisOff(RELAIS_POWER);
  344. if(!flowResetTimer.isActive()) flowResetTimer.start();
  345. flowcnt++;
  346. logger(V_HAL, "IntFlow triggered #%d total: %.2fml\n", flowcnt, halGetFlow());
  347. //tracking of flowtime
  348. if(!flowTimer.isActive()) flowTimer.start();
  349. //trigger the brewing signal using the total flow time
  350. if (halGetFlowTime() >= BREW_MANUAL_TRIGGER && !brewSigFired) {
  351. halSendSignal(SigBrewOn);
  352. brewSigFired = true;
  353. }
  354. //subroutine to log the flow to the database
  355. /*timespec deltaT;
  356. clock_gettime(CLOCK_REALTIME, &flowTimestep[flowIndex]);
  357. timespec_diff(&flowTimestep[((flowIndex + 1) % 2)], &flowTimestep[flowIndex], &deltaT);
  358. if (sqlLogFlow(logcycle, halGetFlow()*1000, deltaT.tv_sec * 1000 + deltaT.tv_nsec/1000000)) {
  359. logger_error("hal.cpp: could not log flow to database!");
  360. return;
  361. }
  362. flowIndex = (flowIndex + 1) % 2;*/
  363. }
  364. /**
  365. * Interrupt routine for the pressure control
  366. * It captures the time at closing point and opening point
  367. * Reading heating time via the getHeatingTime function
  368. */
  369. void halIntPressure(void) {
  370. delay(DELAY_DEBOUNCE);
  371. if (halIsHeating() && !pinState[3]) {
  372. logger(V_HAL, "hal.cpp: Pressure Control closed\n");
  373. pinState[3] = 1;
  374. halStartHeatingTime();
  375. halSendSignal(SigPressCls);
  376. } else if(!halIsHeating() && pinState[3]) {
  377. logger(V_HAL, "hal.cpp: Pressure Control opened\n");
  378. pinState[3] = 0;
  379. halStopHeatingTime();
  380. halSendSignal(SigPressOpn);
  381. }
  382. }
  383. /**
  384. *
  385. */
  386. void halStartHeatingTime(void) {
  387. time(&heatingCycleStart);
  388. }
  389. /**
  390. *
  391. */
  392. void halStopHeatingTime(void) {
  393. if (heatingCycleStart != 0) { //only track time if stopwatch was started!
  394. uint64_t timediff = (uint64_t) difftime(time(0), heatingCycleStart);
  395. logger(V_HAL, "hal.cpp: Heating time: %f\n", timediff);
  396. totalHeatingTime += timediff;
  397. heatingCycleStart = 0;
  398. }
  399. }
  400. /**
  401. * Method to handle toggle of the proximity sensor
  402. */
  403. void halIntProximity(void) {
  404. delay(DELAY_DEBOUNCE);
  405. if (digitalRead(PIN_PROXIMITY_SENSOR) && !pinState[2]) {
  406. logger(V_HAL, "hal.cpp: Proximity switch closed\n");
  407. pinState[2] = 1;
  408. } else if(!digitalRead(PIN_PROXIMITY_SENSOR) && pinState[2]){
  409. logger(V_HAL, "hal.cpp: Proximity switch opened\n");
  410. pinState[2] = 0;
  411. }
  412. }
  413. /**
  414. * Returns total flow through sensor in ml
  415. */
  416. float halGetFlow(void) {
  417. return flowcnt * FLOW_ML_PULSE;
  418. }
  419. /**
  420. * Returns the total flow time in ms
  421. */
  422. uint16_t halGetFlowTime(void){
  423. return flowtime;
  424. }
  425. /*
  426. * Returns the last total flow through the sensor in ml after reset
  427. */
  428. float halGetLastFlow(void) {
  429. return lastFlowcnt * FLOW_ML_PULSE;
  430. }
  431. /**
  432. * Returns the total flow time in ms before the last reset.
  433. */
  434. uint16_t halGetLastFlowTime(void){
  435. return lastFlowTime;
  436. }
  437. /**
  438. * Returns the time interval in ms between the last received flow signal and the reset of the flow counter
  439. */
  440. uint16_t halGetFlowResetTime(void) {
  441. return flowResetTime;
  442. }
  443. /**
  444. * Set the value of the Flow reset time. Its the responsibility of the caller to also call halWriteBackCache()!
  445. */
  446. void halSetFlowResetTime(uint16_t val) {
  447. flowResetTime = val;
  448. }
  449. /**
  450. * Resets the Flow counter. Do not call this function manually. It will be automatically triggered
  451. * from the flow reset timer routine!
  452. */
  453. void halResetFlow(void) {
  454. logger(V_HAL, "Flow counter reset, amount so far: %.2f ml\n", halGetFlow());
  455. lastFlowcnt = flowcnt;
  456. flowcnt = 0;
  457. lastFlowTime = flowtime;
  458. flowtime = 0;
  459. flowResetTimer.stop();
  460. flowTimer.stop();
  461. flowResetValue = -1;
  462. if(brewSigFired) {
  463. brewSigFired = false;
  464. halSendSignal(SigBrewOff);
  465. }
  466. }
  467. /**
  468. * Reads the status of the Pressure Control
  469. * @return 1 (true) for closed Pressure Control (heating) and 0 (false) for open
  470. */
  471. bool halIsHeating(void) {
  472. //TODO: eventually rely on the pinState variable instead of reading the pin
  473. //then the state of the pin needs to be set at the very beginning of the initialization
  474. if (digitalRead(PIN_PRESSURE_CTRL) == 0) return true;
  475. else return false;
  476. }
  477. /**
  478. * Get the total elapsed heating time in seconds since the last reset
  479. */
  480. uint64_t halGetTotalHeatingTime() {
  481. return totalHeatingTime;
  482. }
  483. /**
  484. * Set/Reset the total heating time in seconds
  485. */
  486. void halSetTotalHeatingTime(uint64_t newTime) {
  487. totalHeatingTime = newTime;
  488. }
  489. /**
  490. * Returns status of the proximity switch
  491. * @return 1 if the proximity switch is covered and 0 if uncovered
  492. */
  493. bool halProxSensorCovered(void) {
  494. return pinState[2];
  495. }
  496. /**
  497. * Returns the value of the top button Int0 (low active)
  498. * @return LOW or HIGH
  499. */
  500. int halGetInt0(void) {
  501. return digitalRead(PIN_INT0);
  502. }
  503. /**
  504. * Returns the value of the bottom button Int1 (low active)
  505. * @return LOW or HIGH
  506. */
  507. int halGetInt1(void) {
  508. return digitalRead(PIN_INT1);
  509. }
  510. /**
  511. * send Signal to coffee thread
  512. * @param val Integer value assigned to signal
  513. */
  514. void halSendSignal(HalSig val) {
  515. //restart software when lower button is pressed long
  516. if (val == SigInt1RlsLong) {
  517. event_trigger("terminate");
  518. sleep(4);
  519. exit(EXIT_SUCCESS);
  520. return;
  521. }
  522. if (halIdle(val)) return;
  523. sigval value = { 0 };
  524. value.sival_int = (int) val;
  525. try {
  526. if (pthread_sigqueue(thread[THREAD_COFFEE], SIGUSR2, value)) {
  527. logger_error("hal.cpp: Failed to queue signal %d %s\n", val, strerror(errno));
  528. //No Signals reach the state machine anymore...
  529. exit(EXIT_FAILURE);
  530. }
  531. } catch (int e) {
  532. logger_error("Whoops.. %d\n", e);
  533. }
  534. }
  535. /**
  536. * Turn machine on
  537. */
  538. void halMachineOn(void) {
  539. halRelaisOn(RELAIS_HEAT);
  540. halRelaisOff(RELAIS_PUMP);
  541. halRelaisOn(RELAIS_POWER);
  542. idleTimer.stop();
  543. if(halIsHeating()) halStartHeatingTime();
  544. logger(V_HAL, "hal.cpp: Turning machine on\n");
  545. }
  546. /**
  547. * Turn machine off
  548. */
  549. void halMachineOff(void) {
  550. halRelaisOff(RELAIS_HEAT);
  551. halRelaisOff(RELAIS_PUMP);
  552. halRelaisOff(RELAIS_POWER);
  553. idleCounter = 0;
  554. idleTimer.start();
  555. halStopHeatingTime();
  556. halWriteBackCache();
  557. logger(V_HAL, "hal.cpp: Turning machine off\n");
  558. }
  559. /**
  560. *
  561. */
  562. void halEnterIdle(void){
  563. logger(V_HAL, "hal.cpp: Entering Idle Mode\n");
  564. idleTimer.stop();
  565. halDisplayOff();
  566. idle = true;
  567. }
  568. /**
  569. *
  570. */
  571. void halLeaveIdle(void) {
  572. idleCounter = 0;
  573. logger(V_HAL, "hal.cpp: Leaving Idle Mode\n");
  574. halDisplayOn();
  575. idleTimer.start();
  576. idle = false;
  577. }
  578. /**
  579. * processes the signal value with respect to the idle state
  580. * returns true, if the current signal should be dropped
  581. */
  582. bool halIdle(HalSig val){
  583. //idle processing filter for signals
  584. if (idle) {
  585. switch (val) {
  586. case SigInt0Psh:
  587. case SigInt1Psh:
  588. return true;
  589. break;
  590. case SigInt0Rls:
  591. case SigInt0RlsLong:
  592. case SigInt1Rls:
  593. case SigRotCCW:
  594. case SigRotCW:
  595. halLeaveIdle();
  596. return true;
  597. break;
  598. case SigPowerUp:
  599. halLeaveIdle();
  600. return false;
  601. break;
  602. default:
  603. return false;
  604. }
  605. } else {
  606. //reset the idle time on every input
  607. halResetIdleTimer();
  608. return false;
  609. }
  610. }
  611. /**
  612. *
  613. */
  614. void halResetIdleTimer(void) {
  615. idleCounter = 0;
  616. }
  617. /**
  618. * Wrapper function to turn the pump on.
  619. */
  620. void halPumpOn(){
  621. halRelaisOn(RELAIS_PUMP);
  622. }
  623. /**
  624. * Wrapper function to turn the pump off
  625. * and to measure how long the pump is running
  626. */
  627. void halPumpOff(void){
  628. halRelaisOff(RELAIS_PUMP);
  629. }
  630. /**
  631. * Function to calculate the difference between two timespecs
  632. */
  633. void timespec_diff(timespec *start, timespec *stop, timespec *result) {
  634. long int secDiff = stop->tv_sec - start->tv_sec;
  635. long int nsecDiff = stop->tv_nsec - start->tv_nsec;
  636. if (secDiff > 0) {
  637. if (nsecDiff >= 0) {
  638. result->tv_sec = secDiff;
  639. result->tv_nsec = nsecDiff;
  640. } else if (nsecDiff < 0) {
  641. result->tv_sec = --secDiff;
  642. result->tv_nsec = 1000000000 + nsecDiff;
  643. }
  644. } else if (secDiff < 0) {
  645. if (nsecDiff >= 0) {
  646. result->tv_sec = ++secDiff;
  647. result->tv_nsec = -(1000000000 - nsecDiff);
  648. } else if (nsecDiff < 0) {
  649. result->tv_sec = secDiff;
  650. result->tv_nsec = nsecDiff;
  651. }
  652. } else if (secDiff == 0){
  653. result->tv_sec = secDiff;
  654. result->tv_nsec = nsecDiff;
  655. }
  656. return;
  657. }
  658. /*
  659. * Handler for Termination of the hal
  660. */
  661. void halTerminate(event_t *event){
  662. halStopHeatingTime();
  663. halWriteBackCache();
  664. }
  665. /*
  666. * writing back non volatile variables of the hal to the database: totalHeatingTime, flowResetTime
  667. */
  668. void halWriteBackCache(){
  669. if (sqlSetConf(CFGHeatingTime, totalHeatingTime)) {
  670. logger_error("hal.cpp: Couldn't write heating time to database\n");
  671. return;
  672. }
  673. logger(V_BREW, "Writing back heating time: %lld sec\n", totalHeatingTime);
  674. if (sqlSetConf(CFGFlowResetTime, flowResetTime)) {
  675. logger_error("hal.cpp: Couldn't write the flow reset time to database\n");
  676. return;
  677. }
  678. logger(V_BREW, "Writing back flow reset time: %d ms\n", flowResetTime);
  679. }