123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787 |
- /*
- * hal.cpp
- *
- * Created on: Aug 3, 2016
- * Author: Philipp Hinz, Sebastian Vendt
- */
- #include <wiringPi.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <errno.h>
- #include <string.h>
- #include <signal.h>
- #include <ctime>
- #include <time.h>
- #include <unistd.h>
- #include "hal.h"
- #include "global.h"
- #include "logger.h"
- #include "timer.h"
- #include "database.h"
- const char* SigName[] = {
- "NULL",
- "SigInt0Psh",
- "SigInt0Rls",
- "SigInt0RlsLong",
- "SigInt1Psh",
- "SigInt1Rls",
- "SigInt1RlsLong",
- "SigPressCls",
- "SigPressOpn",
- "SigProxOpn",
- "SigProxCvrd",
- "SigBrewOn",
- "SigBrewOff",
- "SigPowerUp",
- "SigPowerDown",
- "SigRotCW",
- "SigRotCCW"};
- typedef struct timespec timespec;
- volatile int flowcnt = 0;
- int lastFlowcnt = 0;
- int flowResetValue = -1;
- bool brewmanual = false;
- //local copies of the corresponding database entries
- time_t heatingCycleStart = 0;
- uint64_t totalHeatingTime = 0; //total heating time in seconds
- uint16_t flowResetTime = 0; //see TIME_FLOWRESET for details
- int Int0Time, Int1Time;
- int idleCounter;
- bool idle;
- bool flagIgnoreRlsInt0, flagIgnoreRlsInt1;
- //storage for the last state of the buttons, the proximity sensor and the pressure sensor
- int pinState[4] = {1, 1, 0, 0};
- //state of the rotary encoder
- //0: rotary1 state at t-1
- //1: rotary2 state at t-1
- //2: rotary1 state at t
- //3: rotary2 state at t
- int rotaryState[4] = {1, 0, 0, 1};
- timer Int0Timer(&halInt0TimerHandler);
- timer Int1Timer(&halInt1TimerHandler);
- timer idleTimer(&halIdleTimerHandler);
- timer flowResetTimer (&flowResetTimerHandler);
- timer flowTimer(&halFlowTimerHandler);
- timespec flowTimestep[] = {{0,0},{0,0}};
- uint8_t flowIndex = 0;
- int16_t tickCounter = 0; //rotary encoder
- uint16_t flowtime = 0;
- uint16_t lastFlowTime = 0;
- bool brewSigFired = false;
- //delay of the debounce in milliseconds
- #define DELAY_DEBOUNCE 50
- #define DELAY_MICRODEB 2
- //display turn off after idle time in min
- //minimal time is 2min
- #define IDLE_TIME 10
- /**
- * Initializes HAL
- */
- void halInit(void) {
- pinMode(RELAIS_HEAT, OUTPUT);
- pinMode(RELAIS_PUMP, OUTPUT);
- pinMode(RELAIS_POWER, OUTPUT);
- pinMode(PIN_PRESSURE_CTRL, INPUT);
- pinMode(PIN_PROXIMITY_SENSOR, INPUT);
- pinMode(PIN_INT0, INPUT);
- pinMode(PIN_INT1, INPUT);
- pinMode(PIN_FLOW, INPUT);
- pinMode(PIN_DISP, OUTPUT);
- pinMode(PIN_ROTARY1, INPUT);
- pinMode(PIN_ROTARY2, INPUT);
- idleTimer.setDivider(ms2Divider(60000));
- idleCounter = 0;
- idle = false;
- clock_gettime(CLOCK_REALTIME, &flowTimestep[0]);
- clock_gettime(CLOCK_REALTIME, &flowTimestep[1]);
- halDisplayOn();
- if (!(totalHeatingTime = sqlGetConf(CFGHeatingTime))) {
- logger_error("hal.cpp: Couldn't read the total heating time from the database\n");
- //pthread_exit(EXIT_SUCCESS);
- exit(EXIT_FAILURE);
- }
- if (!(flowResetTime = sqlGetConf(CFGFlowResetTime))) {
- flowResetTime = TIME_FLOWRESET;
- logger_error("hal.cpp: Couldn't read the flow reset time from the database\nFalling back to defaults.\n");
- }
- if (optPower) {
- halMachineOn();
- } else {
- halMachineOff();
- }
- sleep(1); //wait till the machine eventually turned on when optPower
- //Determine the inital state of the pins for the pressure control and the graywater tank sensor
- //TODO do a proper averaging here
- pinState[3] = halGetPressureSensorPin();
- if (halIsHeating()) logger(V_HAL, "hal.cpp: pressure sensor state set initially to: HEATING\n");
- else logger(V_HAL, "hal.cpp: pressure sensor state set initially to: OPEN\n");
- pinState[2] = halGetProxSensorPin();
- if (halProxSensorCovered()) logger(V_HAL, "hal.cpp: proximity sensor state set initially to: COVERED\n");
- else logger(V_HAL, "hal.cpp: proximity sensor state set initially to: OPEN\n");
- Int0Timer.setDivider(ms2Divider(200));
- Int1Timer.setDivider(ms2Divider(200));
- Int0Time = 0;
- Int1Time = 0;
- flowResetTimer.setDivider(ms2Divider(TIME_FLOWRESET));
- flowTimer.setDivider(ms2Divider(200));
- flagIgnoreRlsInt0 = false;
- flagIgnoreRlsInt1 = false;
- event_subscribe("terminate", &halTerminate, "hal.cpp");
- if (wiringPiISR(PIN_INT0, INT_EDGE_BOTH, &halInt0) < 0) {
- logger_error("Unable to setup ISR0: %s\n", strerror(errno));
- return;
- }
- if (wiringPiISR(PIN_INT1, INT_EDGE_BOTH, &halInt1) < 0) {
- logger_error("Unable to setup ISR1: %s\n", strerror(errno));
- return;
- }
- if (wiringPiISR(PIN_FLOW, INT_EDGE_FALLING, &halIntFlow) < 0) {
- logger_error("Unable to setup ISRFLOW: %s\n", strerror(errno));
- return;
- }
- if (wiringPiISR(PIN_PRESSURE_CTRL, INT_EDGE_BOTH, &halIntPressure) < 0) {
- logger_error("Unable to setup ISRPressure: %s\n", strerror(errno));
- return;
- }
- if (wiringPiISR(PIN_PROXIMITY_SENSOR, INT_EDGE_BOTH, &halIntProximity) < 0) {
- logger_error("Unable to setup ISRProximity: %s\n", strerror(errno));
- return;
- }
- if (wiringPiISR(PIN_ROTARY1, INT_EDGE_BOTH, &halIntRotary) < 0) {
- logger_error("Unable to setup ISRRotary2: %s\n", strerror(errno));
- return;
- }
- logger(V_BASIC, "hal.cpp: Initialized\n");
- }
- /**
- * Switches relais on
- * @param relais Relais ID
- */
- void halRelaisOn(int relais) {
- halRelaisSet(relais, LOW);
- }
- /**
- * Turn the display off
- */
- void halDisplayOff(){
- digitalWrite(PIN_DISP, LOW);
- }
- /**
- * Turn the display on
- */
- void halDisplayOn(){
- digitalWrite(PIN_DISP, HIGH);
- }
- /**
- * Switches relais off
- * @param relais Relais ID
- */
- void halRelaisOff(int relais) {
- halRelaisSet(relais, HIGH);
- }
- /**
- * Switches relais to state
- * @param relais Relais ID
- * @param state LOW(0) or HIGH(1)
- */
- void halRelaisSet(int relais, int state) {
- if (state != HIGH && state != LOW)
- return;
- switch (relais) {
- case RELAIS_POWER:
- case RELAIS_HEAT:
- case RELAIS_PUMP:
- digitalWrite(relais, state);
- break;
- }
- }
- /**
- * Returns the state of the relais relais
- * Returns HIGH when Relais is ON
- * @param relais Relais ID
- */
- int halGetRelaisState(int relais) {
- switch (relais) {
- case RELAIS_POWER:
- case RELAIS_HEAT:
- case RELAIS_PUMP:
- return !digitalRead(relais);
- break;
- }
- return -1;
- }
- /**
- *
- */
- void halIntRotary(void) {
- //delay(DELAY_MICRODEB);
- rotaryState[2] = digitalRead(PIN_ROTARY1);
- rotaryState[3] = digitalRead(PIN_ROTARY2);
- if (rotaryState[0] != rotaryState[2]) {
- //check for the status of the other pin
- if (rotaryState[1] != rotaryState[3]) {
- if ((rotaryState[2] == HIGH && rotaryState[3] == LOW) || (rotaryState[2] == LOW && rotaryState[3] == HIGH)) {
- //clockwise rotation
- tickCounter++;
- if (!(abs(tickCounter) % ROTARY_STEPSIZE)) {
- //logger(V_HAL, "rotary encoder CW \n");
- halSendSignal(SigRotCW);
- tickCounter = 0;
- }
- } else if ((rotaryState[2] == HIGH && rotaryState[3] == HIGH) || (rotaryState[2] == LOW && rotaryState[3] == LOW)) {
- //counterclockwise rotation
- tickCounter--;
- if (!(abs(tickCounter) % ROTARY_STEPSIZE)) {
- //logger(V_HAL, "rotary encoder CCW \n");
- halSendSignal(SigRotCCW);
- tickCounter = 0;
- }
- }
- rotaryState[1] = rotaryState[3];
- }
- rotaryState[0] = rotaryState[2];
- }
- }
- /**
- * Interrupt routine for Int0 (Top button)
- */
- void halInt0(void) {
- //wait for a debounce
- delay(DELAY_DEBOUNCE);
- if (halGetInt0() && !pinState[0]) { //released
- logger(V_HAL, "Int0 released\n");
- pinState[0] = 1;
- if (flagIgnoreRlsInt0) {
- flagIgnoreRlsInt0 = false;
- } else {
- Int0Time = 0;
- Int0Timer.stop();
- halSendSignal(SigInt0Rls);
- }
- } else if(!halGetInt0() && pinState[0]) { //pressed
- logger(V_HAL, "Int0 pushed\n");
- pinState[0] = 0;
- halSendSignal(SigInt0Psh);
- Int0Time = 0;
- Int0Timer.start();
- }
- }
- /**
- *
- */
- void halInt0TimerHandler(void) {
- Int0Time += 200;
- if (Int0Time >= (TIME_BUTTONLONGPRESS * 1000)) {
- halSendSignal(SigInt0RlsLong);
- flagIgnoreRlsInt0 = true;
- Int0Time = 0;
- Int0Timer.stop();
- }
- }
- /**
- *
- */
- void halIdleTimerHandler(void) {
- if(++idleCounter == IDLE_TIME){
- halEnterIdle();
- }
- }
- /**
- * Interrupt routine for Int1 (Bottom button)
- */
- void halInt1(void) {
- delay(DELAY_DEBOUNCE);
- if (halGetInt1() && !pinState[1]) {
- logger(V_HAL, "Int1 released\n");
- pinState[1] = 1;
- if (flagIgnoreRlsInt1) {
- flagIgnoreRlsInt1 = false;
- } else {
- Int1Time = 0;
- Int1Timer.stop();
- halSendSignal(SigInt1Rls);
- }
- } else if(!halGetInt1() && pinState[1]) {
- logger(V_HAL, "Int1 pushed\n");
- pinState[1] = 0;
- halSendSignal(SigInt1Psh);
- Int1Time = 0;
- Int1Timer.start();
- }
- }
- /*
- *
- */
- void halInt1TimerHandler(void) {
- Int1Time += 200;
- if (Int1Time >= (TIME_BUTTONLONGPRESS * 1000)) {
- halSendSignal(SigInt1RlsLong);
- flagIgnoreRlsInt1 = true;
- Int1Time = 0;
- Int1Timer.stop();
- }
- }
- /**
- * Timer handler to auto-reset the flow counter.
- * The timer is started when the flow interrupt is triggered.
- * It compares the last value (flowResetValue) with the current flow value
- * If they match (e.g no flow within 1000ms) the flow counter is reseted.
- * Setting the last value to -1 ensures that when the timer gets called immediately after it is started the comparison will fail.
- * This implementation is read-only and so it doesn't need semaphores.
- */
- void flowResetTimerHandler() {
- if(flowResetValue == flowcnt) {
- halResetFlow();
- return;
- }
- flowResetValue = flowcnt;
- }
- /**
- *
- */
- void halFlowTimerHandler() {
- flowtime += 200;
- }
- /**
- * Interrupt routine for the flow sensor
- * It counts the edges and stores the value in flowcnt
- */
- void halIntFlow(void) {
- //halRelaisOff(RELAIS_POWER);
- if(!flowResetTimer.isActive()) flowResetTimer.start();
- flowcnt++;
- logger(V_HAL, "IntFlow triggered #%d total: %.2fml\n", flowcnt, halGetFlow());
- //tracking of flowtime
- if(!flowTimer.isActive()) flowTimer.start();
- //trigger the brewing signal using the total flow time
- if (halGetFlowTime() >= BREW_MANUAL_TRIGGER && !brewSigFired) {
- halSendSignal(SigBrewOn);
- brewSigFired = true;
- }
- //subroutine to log the flow to the database
- /*timespec deltaT;
- clock_gettime(CLOCK_REALTIME, &flowTimestep[flowIndex]);
- timespec_diff(&flowTimestep[((flowIndex + 1) % 2)], &flowTimestep[flowIndex], &deltaT);
- if (sqlLogFlow(logcycle, halGetFlow()*1000, deltaT.tv_sec * 1000 + deltaT.tv_nsec/1000000)) {
- logger_error("hal.cpp: could not log flow to database!");
- return;
- }
- flowIndex = (flowIndex + 1) % 2;*/
- }
- /**
- * Interrupt routine for the pressure control
- * It captures the time at closing point and opening point
- * Reading heating time via the getHeatingTime function
- */
- void halIntPressure(void) {
- delay(DELAY_DEBOUNCE);
- if (!halGetPressureSensorPin() && pinState[3]) {
- logger(V_HAL, "hal.cpp: Pressure Control closed\n");
- pinState[3] = 0;
- halStartHeatingTime();
- halSendSignal(SigPressCls);
- } else if(halGetPressureSensorPin() && !pinState[3]) {
- logger(V_HAL, "hal.cpp: Pressure Control opened\n");
- pinState[3] = 1;
- halStopHeatingTime();
- halSendSignal(SigPressOpn);
- }
- }
- /**
- *
- */
- void halStartHeatingTime(void) {
- time(&heatingCycleStart);
- }
- /**
- *
- */
- void halStopHeatingTime(void) {
- if (heatingCycleStart != 0) { //only track time if stopwatch was started!
- uint64_t timediff = (uint64_t) difftime(time(0), heatingCycleStart);
- logger(V_HAL, "hal.cpp: Heating time: %f\n", timediff);
- totalHeatingTime += timediff;
- heatingCycleStart = 0;
- }
- }
- /**
- * Method to handle toggle of the proximity sensor
- */
- void halIntProximity(void) {
- delay(DELAY_DEBOUNCE);
- if (halGetProxSensorPin() && !pinState[2]) {
- logger(V_HAL, "hal.cpp: Proximity switch closed\n");
- pinState[2] = 1;
- } else if(!halGetProxSensorPin() && pinState[2]){
- logger(V_HAL, "hal.cpp: Proximity switch opened\n");
- pinState[2] = 0;
- }
- }
- /**
- * Returns total flow through sensor in ml
- */
- float halGetFlow(void) {
- return flowcnt * FLOW_ML_PULSE;
- }
- /**
- * Returns the total flow time in ms
- */
- uint16_t halGetFlowTime(void){
- return flowtime;
- }
- /*
- * Returns the last total flow through the sensor in ml after reset
- */
- float halGetLastFlow(void) {
- return lastFlowcnt * FLOW_ML_PULSE;
- }
- /**
- * Returns the total flow time in ms before the last reset.
- */
- uint16_t halGetLastFlowTime(void){
- return lastFlowTime;
- }
- /**
- * Returns the time interval in ms between the last received flow signal and the reset of the flow counter
- */
- uint16_t halGetFlowResetTime(void) {
- return flowResetTime;
- }
- /**
- * Set the value of the Flow reset time. Its the responsibility of the caller to also call halWriteBackCache()!
- */
- void halSetFlowResetTime(uint16_t val) {
- flowResetTime = val;
- }
- /**
- * Resets the Flow counter. Do not call this function manually. It will be automatically triggered
- * from the flow reset timer routine!
- */
- void halResetFlow(void) {
- logger(V_HAL, "Flow counter reset, amount so far: %.2f ml\n", halGetFlow());
- lastFlowcnt = flowcnt;
- flowcnt = 0;
- lastFlowTime = flowtime;
- flowtime = 0;
- flowResetTimer.stop();
- flowTimer.stop();
- flowResetValue = -1;
- if(brewSigFired) {
- brewSigFired = false;
- halSendSignal(SigBrewOff);
- }
- }
- /**
- * Reads the status of the Pressure Control
- * @return 1 (true) for closed Pressure Control (heating) and 0 (false) for open
- */
- bool halIsHeating(void) {
- return !pinState[3];
- }
- /**
- * Get the total elapsed heating time in seconds since the last reset
- */
- uint64_t halGetTotalHeatingTime() {
- return totalHeatingTime;
- }
- /**
- * Set/Reset the total heating time in seconds
- */
- void halSetTotalHeatingTime(uint64_t newTime) {
- totalHeatingTime = newTime;
- }
- /**
- * Returns filtered status of the proximity switch
- * @return 1 if the proximity switch is covered and 0 if uncovered
- */
- bool halProxSensorCovered(void) {
- return pinState[2];
- }
- /**
- *
- */
- int halGetPressureSensorPin(void) {
- return digitalRead(PIN_PRESSURE_CTRL);
- }
- /**
- * Returns the pin status of the proximity sensor
- */
- int halGetProxSensorPin(void) {
- return digitalRead(PIN_PROXIMITY_SENSOR);
- }
- /**
- * Returns the value of the top button Int0 (low active)
- * @return LOW or HIGH
- */
- int halGetInt0(void) {
- return digitalRead(PIN_INT0);
- }
- /**
- * Returns the value of the bottom button Int1 (low active)
- * @return LOW or HIGH
- */
- int halGetInt1(void) {
- return digitalRead(PIN_INT1);
- }
- /**
- * send Signal to coffee thread
- * @param val Integer value assigned to signal
- */
- void halSendSignal(HalSig val) {
- //restart software when lower button is pressed long
- if (val == SigInt1RlsLong) {
- event_trigger("terminate");
- sleep(4);
- exit(EXIT_SUCCESS);
- return;
- }
- if (halIdle(val)) return;
- sigval value = { 0 };
- value.sival_int = (int) val;
- try {
- if (pthread_sigqueue(thread[THREAD_COFFEE], SIGUSR2, value)) {
- logger_error("hal.cpp: Failed to queue signal %d %s\n", val, strerror(errno));
- //No Signals reach the state machine anymore...
- exit(EXIT_FAILURE);
- }
- } catch (int e) {
- logger_error("Whoops.. %d\n", e);
- }
- }
- /**
- * Turn machine on
- */
- void halMachineOn(void) {
- halRelaisOn(RELAIS_HEAT);
- halRelaisOff(RELAIS_PUMP);
- halRelaisOn(RELAIS_POWER);
- idleTimer.stop();
- if(halIsHeating()) halStartHeatingTime();
- logger(V_HAL, "hal.cpp: Turning machine on\n");
- }
- /**
- * Turn machine off
- */
- void halMachineOff(void) {
- halRelaisOff(RELAIS_HEAT);
- halRelaisOff(RELAIS_PUMP);
- halRelaisOff(RELAIS_POWER);
- idleCounter = 0;
- idleTimer.start();
- halStopHeatingTime();
- halWriteBackCache();
- logger(V_HAL, "hal.cpp: Turning machine off\n");
- }
- /**
- *
- */
- void halEnterIdle(void){
- logger(V_HAL, "hal.cpp: Entering Idle Mode\n");
- idleTimer.stop();
- halDisplayOff();
- idle = true;
- }
- /**
- *
- */
- void halLeaveIdle(void) {
- idleCounter = 0;
- logger(V_HAL, "hal.cpp: Leaving Idle Mode\n");
- halDisplayOn();
- idleTimer.start();
- idle = false;
- }
- /**
- * processes the signal value with respect to the idle state
- * returns true, if the current signal should be dropped
- */
- bool halIdle(HalSig val){
- //idle processing filter for signals
- if (idle) {
- switch (val) {
- case SigInt0Psh:
- case SigInt1Psh:
- return true;
- break;
- case SigInt0Rls:
- case SigInt0RlsLong:
- case SigInt1Rls:
- case SigRotCCW:
- case SigRotCW:
- halLeaveIdle();
- return true;
- break;
- case SigPowerUp:
- halLeaveIdle();
- return false;
- break;
- default:
- return false;
- }
- } else {
- //reset the idle time on every input
- halResetIdleTimer();
- return false;
- }
- }
- /**
- *
- */
- void halResetIdleTimer(void) {
- idleCounter = 0;
- }
- /**
- * Wrapper function to turn the pump on.
- */
- void halPumpOn(){
- halRelaisOn(RELAIS_PUMP);
- }
- /**
- * Wrapper function to turn the pump off
- * and to measure how long the pump is running
- */
- void halPumpOff(void){
- halRelaisOff(RELAIS_PUMP);
- }
- /**
- * Function to calculate the difference between two timespecs
- */
- void timespec_diff(timespec *start, timespec *stop, timespec *result) {
- long int secDiff = stop->tv_sec - start->tv_sec;
- long int nsecDiff = stop->tv_nsec - start->tv_nsec;
- if (secDiff > 0) {
- if (nsecDiff >= 0) {
- result->tv_sec = secDiff;
- result->tv_nsec = nsecDiff;
- } else if (nsecDiff < 0) {
- result->tv_sec = --secDiff;
- result->tv_nsec = 1000000000 + nsecDiff;
- }
- } else if (secDiff < 0) {
- if (nsecDiff >= 0) {
- result->tv_sec = ++secDiff;
- result->tv_nsec = -(1000000000 - nsecDiff);
- } else if (nsecDiff < 0) {
- result->tv_sec = secDiff;
- result->tv_nsec = nsecDiff;
- }
- } else if (secDiff == 0){
- result->tv_sec = secDiff;
- result->tv_nsec = nsecDiff;
- }
- return;
- }
- /*
- * Handler for Termination of the hal
- */
- void halTerminate(event_t *event){
- halStopHeatingTime();
- halWriteBackCache();
- }
- /*
- * writing back non volatile variables of the hal to the database: totalHeatingTime, flowResetTime
- */
- void halWriteBackCache(){
- if (sqlSetConf(CFGHeatingTime, totalHeatingTime)) {
- logger_error("hal.cpp: Couldn't write heating time to database\n");
- return;
- }
- logger(V_BREW, "Writing back heating time: %lld sec\n", totalHeatingTime);
- if (sqlSetConf(CFGFlowResetTime, flowResetTime)) {
- logger_error("hal.cpp: Couldn't write the flow reset time to database\n");
- return;
- }
- logger(V_BREW, "Writing back flow reset time: %d ms\n", flowResetTime);
- }
|