Sfoglia il codice sorgente

made the subscribe to event function threadsafe, added real sleep function to coffee.cpp which is resilient to signals

Sebastian 6 anni fa
parent
commit
00597bde53
5 ha cambiato i file con 42 aggiunte e 17 eliminazioni
  1. 1 1
      CoffeeCode/buildno
  2. 35 14
      CoffeeCode/coffee.cpp
  3. 1 0
      CoffeeCode/coffee.h
  4. 4 2
      CoffeeCode/events.cpp
  5. 1 0
      CoffeeCode/hal.cpp

+ 1 - 1
CoffeeCode/buildno

@@ -1 +1 @@
-250
+254

+ 35 - 14
CoffeeCode/coffee.cpp

@@ -72,22 +72,22 @@ void *coffeeThread(void *threadid) {
 
 	//read the database values
 	if (!(totalHeatingTime = sqlGetConf(CFGHeatingTime))) {
-		logger_error("coffee.cpp: Couldn't read the heating time from the database");
+		logger_error("coffee.cpp: Couldn't read the heating time from the database\n");
 		//pthread_exit(EXIT_SUCCESS);
 		exit(EXIT_FAILURE);
 	}
 	if (!(brewCounter = sqlGetConf(CFGbrewcounter))) {
-		logger_error("coffee.cpp: Couldn't read the brew counter from the database");
+		logger_error("coffee.cpp: Couldn't read the brew counter from the database\n");
 		//pthread_exit(EXIT_SUCCESS);
 		exit(EXIT_FAILURE);
 	}
 	if (!(descRawTimestamp = (time_t) sqlGetConf(CFGDescTimestamp))) {
-		logger_error("coffee.cpp: Couldn't read the descaling time from the database");
+		logger_error("coffee.cpp: Couldn't read the descaling time from the database\n");
 		//pthread_exit(EXIT_SUCCESS);
 		exit(EXIT_FAILURE);
 	}
 	if (!(descBrewcount = sqlGetConf(CFGDescBrewCount))) {
-		logger_error("coffee.cpp: Couldn't read the descaling brewcount time from the database");
+		logger_error("coffee.cpp: Couldn't read the descaling brewcount time from the database\n");
 		//pthread_exit(EXIT_SUCCESS);
 		exit(EXIT_FAILURE);
 	}
@@ -101,7 +101,7 @@ void *coffeeThread(void *threadid) {
 	if (halGetRelaisState(RELAIS_POWER) && halGetRelaisState(RELAIS_HEAT)
 			&& !halGetRelaisState(RELAIS_PUMP)) {
 		//wait for heat relais to switch
-		sleep(1);
+		coffeeNap(1,0);
 		if (halIsHeating()) { //Heating is on
 			changeState(STATE_INITALHEATING);
 		} else {
@@ -284,7 +284,7 @@ void *coffeeThread(void *threadid) {
 				//Check waterlevel in gray water tank
 				//turn machine on
 				halMachineOn();
-				sleep(1);
+				coffeeNap(1,0);
 				if (halIsHeating() && !halProxSensorCovered()) { //check if System starts to heat when turned on
 					changeState(STATE_INITALHEATING);
 				} else if (!halIsHeating() && !halProxSensorCovered()) {
@@ -314,7 +314,7 @@ void *coffeeThread(void *threadid) {
 				pause();
 			switch (getSigValue(MODE_STATE)) {
 			case SigPressOpn:
-				usleep(100000); //wait so no load will be switched
+				coffeeNap(1,0); //wait so no load will be switched
 				coffeeIncreaseHeatingTime(halgetHeatingTime());
 				changeState(STATE_OFF);
 				break;
@@ -705,6 +705,29 @@ void coffeeTerminate(event_t *event) {
 	writeBackCache();
 }
 
+/**
+ * coffeeNap does almost the same as sleep() but resumes to sleep after a signal got delivered
+ * sec: seconds to sleep
+ * nanosec: nanoseconds to sleep
+ */
+void coffeeNap (uint64_t sec, uint64_t nanosec){
+	struct timespec sleepTime;
+	clock_gettime(CLOCK_REALTIME, &sleepTime);
+	sleepTime.tv_sec += sec;
+	sleepTime.tv_nsec += nanosec;
+	//overflow
+	if(sleepTime.tv_nsec >= 1000000000) {
+		sleepTime.tv_nsec -= 1000000000;
+		sleepTime.tv_sec++;
+	}
+	int errval = 0;
+	do{
+		errval = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &sleepTime, NULL);
+	}
+	while(errval == EINTR);
+	if(errval) logger_error("coffee.cpp: suspending thread failed with error %d\n", errval);
+}
+
 /**
  * Function to write back the values of the local copies
  * brewCounter and totalHeatingTime
@@ -743,11 +766,9 @@ void coffeeClean(void) {
 	logger(V_BREW, "Cleaning...\n");
 	for (int i = 0; i < 20; i++) {
 		halRelaisOn(RELAIS_PUMP);
-		//TODO the sleep function returns when a signal is delivered
-		//this causes the cleaning to not work properly when the pressure is triggered
-		sleep(3);
+		coffeeNap(3,0);
 		halRelaisOff(RELAIS_PUMP);
-		sleep(15);
+		coffeeNap(15,0);
 	}
 	updateDescaling();
 	descaling = false;
@@ -768,7 +789,7 @@ void coffeeBrew(void) {
 	brewTime = 0;
 	brewTimer.start();
 	while (halGetFlow() < AMOUNT_PREINFUSION) {
-		usleep(50000);
+		coffeeNap(0,50000000);
 		if (getSigValue(MODE_STATE) == SigInt0Psh){
 			stopBrewing();
 			return;
@@ -781,7 +802,7 @@ void coffeeBrew(void) {
 	 */
 	brewTimer.start();
 	while (brewTime < TIME_SOAK) {
-		usleep(100000);
+		coffeeNap(1,100000000);
 		if (getSigValue(MODE_STATE) == SigInt0Psh) {
 			stopBrewing();
 			return;
@@ -796,7 +817,7 @@ void coffeeBrew(void) {
 	halRelaisOn(RELAIS_PUMP);
 	brewTimer.start();
 	while (brewTime < TIME_INFUSION && halGetFlow() < AMOUNT_DBLESPRESSO) {
-		usleep(100000);
+		coffeeNap(1,100000000);
 		if (getSigValue(MODE_STATE) == SigInt0Psh){
 			stopBrewing();
 			break;

+ 1 - 0
CoffeeCode/coffee.h

@@ -68,6 +68,7 @@ time_t * getDescTimestamp (void);
 void brewTimeHandler(void);
 void writeBackCache(void);
 void coffeeTerminate(event_t *event);
+void coffeeNap (uint64_t sec, uint64_t nanosec);
 void coffeeBrew(void);
 void coffeeClean(void);
 void stopBrewing(void);

+ 4 - 2
CoffeeCode/events.cpp

@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <mutex>
 
 #include "events.h"
 #include "logger.h"
@@ -33,6 +34,7 @@ struct events_t {
 };
 
 events_t *firstEvent = NULL; /**< The first element in the event list */
+std::mutex subscribeMutex;
 
 /**
  * Finds the specific event in the list and returns it
@@ -99,8 +101,7 @@ void addSubscriber(events_t *event, void (*handler)(event_t *)) {
  */
 
 void event_subscribe(const char *event, void (*handler)(event_t *)) {
-	//TODO change event name to a typedef enum or similar
-
+	subscribeMutex.lock();
 	events_t * subscribeEvent = event_find(event);
 	if(!subscribeEvent){//create new Event
 		subscribeEvent = (events_t *) malloc(sizeof(events_t));
@@ -117,6 +118,7 @@ void event_subscribe(const char *event, void (*handler)(event_t *)) {
 	}
 	addSubscriber(subscribeEvent, handler);
 	logger(V_HAL, "New subscriber to event \"%s\"\n", event);
+	subscribeMutex.unlock();
 }
 
 /**

+ 1 - 0
CoffeeCode/hal.cpp

@@ -282,6 +282,7 @@ void halIntPressure(void) {
  * If called after a heating process, it returns the total time elapsed during the heating cycle
  */
 double halgetHeatingTime(void){
+	//TODO check return value on negative times
 	if (halIsHeating()) {
 		logger(V_HAL, "Hot Heating Time: %f\n", difftime(time(NULL), heatingCycle[0]));
 		return difftime(time(0), heatingCycle[0]);