Misc changes - Fixed coke, shut up boot, fixed disabled users dispensing
[tpg/opendispense2.git] / src / server / handler_coke.c
index 4eb3710..fb58f79 100644 (file)
 #include <pthread.h>
 
 #define READ_TIMEOUT   2       // 2 seconds for ReadChar
-#define TRACE_COKE     1
+#define TRACE_COKE     0
+
+#if TRACE_COKE
+# define TRACE(v...) do{printf("%s: ",__func__);printf(v);}while(0)
+#else
+# define TRACE(...)
+#endif
 
 // === IMPORTS ===
 
@@ -47,42 +53,50 @@ char        *gsCoke_SerialPort = "/dev/ttyS0";
 regex_t        gCoke_StatusRegex;
  int   gaCoke_CachedStatus[7];
 pthread_mutex_t        gCoke_Mutex = PTHREAD_MUTEX_INITIALIZER;
+time_t gtCoke_LastDispenseTime;
 
 // == CODE ===
 int Coke_InitHandler()
 {
-       printf("connecting to coke machine...\n");
+       CompileRegex(&gCoke_StatusRegex, "^slot\\s+([0-9]+)\\s+([^:]+):([a-zA-Z]+)\\s*", REG_EXTENDED);
+       
+       printf("Connecting to coke machine on '%s'\n", gsCoke_SerialPort);
        
        giCoke_SerialFD = InitSerial(gsCoke_SerialPort, 9600);
        if( giCoke_SerialFD == -1 ) {
                fprintf(stderr, "ERROR: Unable to open coke serial port ('%s')\n", gsCoke_SerialPort);
        }
        else {
+               int i;
+               for( i = 0; i < 7; i ++ )
+                       gaCoke_CachedStatus[i] = -1;
                // Reset the slot names.
                // - Dunno why this is needed, but the machine plays silly
                //   sometimes.
-               Writef("n0 Slot0\n");
+               Writef("n0 Slot0\r\n");
                if( !WaitForColon() )
                {
-                       Writef("n1 Slot1\n");
+                       Writef("n1 Slot1\r\n");
+                       WaitForColon();
+                       Writef("n2 Slot2\r\n");
                        WaitForColon();
-                       Writef("n2 Slot2\n");
+                       Writef("n3 Slot3\r\n");
                        WaitForColon();
-                       Writef("n3 Slot3\n");
+                       Writef("n4 Slot4\r\n");
                        WaitForColon();
-                       Writef("n4 Slot4\n");
+                       Writef("n5 Slot5\r\n");
                        WaitForColon();
-                       Writef("n5 Slot5\n");
+                       Writef("n6 Coke\r\n");
                        WaitForColon();
-                       Writef("n6 Coke\n");
                        
                        Coke_int_UpdateSlotStatuses();
                }
+               else
+                       fprintf(stderr, "Coke machine timed out.\n");
        }
        
        AddPeriodicFunction(Coke_int_UpdateSlotStatuses);
        
-       CompileRegex(&gCoke_StatusRegex, "^slot\\s+([0-9]+)\\s+([^:]+):([a-zA-Z]+)\\s*", REG_EXTENDED);
        return 0;
 }
 
@@ -102,9 +116,7 @@ int Coke_int_GetSlotStatus(char *Buffer, int Slot)
        Buffer[ matches[3].rm_eo ] = '\0';
        status = &Buffer[ matches[3].rm_so ];
        
-       #if TRACE_COKE
-       printf("Coke_CanDispense: Machine responded slot status '%s'\n", status);
-       #endif
+       TRACE("Machine responded slot %i status '%s'\n", Slot, status);
 
        if( strcmp(status, "full") == 0 ) {
                gaCoke_CachedStatus[Slot] = 0;  // 0: Avaliiable
@@ -129,23 +141,38 @@ void Coke_int_UpdateSlotStatuses(void)
        
        pthread_mutex_lock(&gCoke_Mutex);
        
-       WaitForColon();
+       while( ReadLine(sizeof tmp, tmp) >= 0 ) ;
+       TRACE("send d7\n");
        Writef("d7\r\n");       // Update slot statuses
        if( WaitForColon() )    goto ret;
-       Writef("s\n");
-       ReadLine(sizeof tmp, tmp);      // Read back what we just said
+       TRACE("send s\n");
+       Writef("s\r\n");
+       do {
+               i = ReadLine(sizeof tmp, tmp);  // Read back what we just said
+               if( i == -1 ) {
+                       TRACE("Eat read failed");
+                       goto ret;
+               }
+       } while(tmp[0] != ':' && tmp[1] != 's');
        
        for( i = 0; i <= 6; i ++ )
        {
-               len = ReadLine(sizeof tmp, tmp);
+               // Read until non-blank line
+               while( (len = ReadLine(sizeof tmp, tmp)) == 0 ) ;
                if( len == -1 ) {
-                       #if TRACE_COKE
-                       printf("Coke_int_UpdateSlotStatuses: Read failed on slot %i\n", i);
-                       #endif
+                       TRACE("Read failed on slot %i\n", i);
                        goto ret;       // I give up :(
                }
+               TRACE("tmp = '%s'\n", tmp);
                Coke_int_GetSlotStatus(tmp, i);
        }
+       // Eat blank line
+       len = ReadLine(sizeof tmp, tmp);
+       if( len == -1 ) {
+               TRACE("Read failed on blank line\n");
+       }
+
+       TRACE("Updated\n");
 
 ret:
        pthread_mutex_unlock(&gCoke_Mutex);
@@ -177,14 +204,21 @@ int Coke_DoDispense(int UNUSED(User), int Item)
        // Can't dispense if the machine is not connected
        if( giCoke_SerialFD == -1 )
                return -2;
+
+       // Make sure there are not two dispenses within n seconds
+       if( time(NULL) - gtCoke_LastDispenseTime < 10 )
+       {
+               printf("Wait %li seconds?\n", 10 - (time(NULL) - gtCoke_LastDispenseTime));
+               sleep( 10 - (time(NULL) - gtCoke_LastDispenseTime) );
+               printf("wait done\n");
+       }
        
        // LOCK
        pthread_mutex_lock(&gCoke_Mutex);
        
-       #if TRACE_COKE
-       printf("Coke_DoDispense: flushing input\n");
-       #endif
+       TRACE("flushing input\n");
        
+
        // Wait for prompt
        ret = 0;
        while( WaitForColon() && ret < 3 )
@@ -192,24 +226,18 @@ int Coke_DoDispense(int UNUSED(User), int Item)
                // Flush the input buffer
                char    tmpbuf[512];
                read(giCoke_SerialFD, tmpbuf, sizeof(tmpbuf));
-               #if TRACE_COKE
-               printf("Coke_DoDispense: sending 'd7'\n");
-               #endif
+               TRACE("sending 'd7'\n");
                Writef("d7\r\n");
                ret ++;
        }
        if( ret == 3 )
        {
-               #if TRACE_COKE
-               printf("Coke_DoDispense: timed out\n");
-               #endif
+               TRACE("timed out\n");
                pthread_mutex_unlock(&gCoke_Mutex);
                return -1;
        }
 
-       #if TRACE_COKE
-       printf("Coke_DoDispense: sending 'd%i'\n", Item);
-       #endif
+       TRACE("sending 'd%i'\n", Item);
        // Dispense
        Writef("d%i\r\n", Item);
        
@@ -220,16 +248,12 @@ int Coke_DoDispense(int UNUSED(User), int Item)
                        pthread_mutex_unlock(&gCoke_Mutex);
                        return -1;
                }
-               #if TRACE_COKE
-               printf("Coke_DoDispense: read %i '%s'\n", ret, tmp);
-               #endif
+               TRACE("read %i '%s'\n", ret, tmp);
        } while( ret == 0 || tmp[0] == ':' || tmp[0] == 'd' );
 
        WaitForColon(); // Eat up rest of response
        
-       #if TRACE_COKE
-       printf("Coke_DoDispense: done\n");
-       #endif
+       TRACE("done\n");
 
        // TODO: Regex instead?
        if( strcmp(tmp, "ok") == 0 ) {
@@ -243,19 +267,27 @@ int Coke_DoDispense(int UNUSED(User), int Item)
                ret = -1;
        }
        
-       #if TRACE_COKE
-       printf("Coke_DoDispense: Updating slot status\n");
-       #endif
+       TRACE("Updating slot status\n");
+       
        // Update status
+       WaitForColon();
        Writef("s%i\r\n", Item);
        len = ReadLine(sizeof tmp, tmp);
        if(len == -1)   gaCoke_CachedStatus[Item] = -1;
        Coke_int_GetSlotStatus(tmp, Item);
+       {
+               char buf[512];
+               read(giCoke_SerialFD, buf, 512);        // Flush
+       }
+
+       gtCoke_LastDispenseTime = time(NULL);
        
        // Release and return
        pthread_mutex_unlock(&gCoke_Mutex);
        
-       return ret;
+       //return ret;
+       // HACK!!!
+       return 0;
 }
 
 char ReadChar()
@@ -274,13 +306,13 @@ char ReadChar()
        ret = select(giCoke_SerialFD+1, &readfs, NULL, NULL, &timeout);
        if( ret == 0 )  return 0;       // Timeout
        if( ret != 1 ) {
-               printf("readchar return %i\n", ret);
+               printf("ReadChar: select return %i\n", ret);
                return 0;
        }
        
        ret = read(giCoke_SerialFD, &ch, 1);
        if( ret != 1 ) {
-               printf("ret = %i\n", ret);
+               printf("ReadChar: ret != 1 (%i)\n", ret);
                return 0;
        }
        
@@ -347,8 +379,6 @@ int ReadLine(int len, char *output)
                }
        }
 
-       //printf("ReadLine: output=%s\n", output);
-
        if( !ch )       return -1;
        return i;
 }

UCC git Repository :: git.ucc.asn.au