17f73a26011fca5bf795c8185c08627908f70ed7
[tpg/opendispense2.git] / src / server / handler_coke.c
1 /*
2  * OpenDispense 2 
3  * UCC (University [of WA] Computer Club) Electronic Accounting System
4  *
5  * handler_coke.c - Coke controller code
6  *
7  * This file is licenced under the 3-clause BSD Licence. See the file
8  * COPYING for full details.
9  */
10 #include "common.h"
11 #include <stdio.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
16 #include <regex.h>
17
18 // === IMPORTS ===
19
20 // === PROTOTYPES ===
21  int    Coke_InitHandler();
22  int    Coke_CanDispense(int User, int Item);
23  int    Coke_DoDispense(int User, int Item);
24 void    WaitForColon();
25  int    ReadLine(int len, char *output);
26
27 // === GLOBALS ===
28 tHandler        gCoke_Handler = {
29         "coke",
30         Coke_InitHandler,
31         Coke_CanDispense,
32         Coke_DoDispense
33 };
34 char    *gsCoke_SerialPort = "/dev/ttyS0";
35  int    giCoke_SerialFD;
36 regex_t gCoke_StatusRegex;
37
38 // == CODE ===
39 int Coke_InitHandler()
40 {
41         printf("connecting to coke machine...\n");
42         
43         giCoke_SerialFD = InitSerial(gsCoke_SerialPort, 9600);
44         if( giCoke_SerialFD == -1 ) {
45                 fprintf(stderr, "ERROR: Unable to open coke serial port ('%s')\n", gsCoke_SerialPort);
46         }
47         
48         CompileRegex(&gCoke_StatusRegex, "^slot\\s+(\\d)\\s+([^:]+):([a-zA-Z]+)\\s*", REG_EXTENDED);
49         return 0;
50 }
51
52 int Coke_CanDispense(int User, int Item)
53 {
54         char    tmp[32], *status;
55         regmatch_t      matches[4];
56          int    ret;
57
58         // Sanity please
59         if( Item < 0 || Item > 6 )      return -1;      // -EYOURBAD
60         
61         write(giCoke_SerialFD, "\r\n", 2);
62         write(giCoke_SerialFD, "\r\n", 2);
63         write(giCoke_SerialFD, "\r\n", 2);
64         
65         WaitForColon();
66         
67         // Ask the coke machine
68         sprintf(tmp, "s%i\r\n", Item);
69         write(giCoke_SerialFD, tmp, 4);
70         
71         WaitForColon();
72
73         ret = ReadLine(sizeof(tmp)-1, tmp);
74         printf("ret = %i, tmp = '%s'\n", ret, tmp);
75         
76         if( ret <= 0 ) {
77                 fprintf(stderr, "Coke machine is not being chatty (read = %i)\n", ret);
78                 if( ret == -1 ) {
79                         perror("Coke Machine");
80                 }
81                 return -1;
82         }
83         ret = RunRegex(&gCoke_StatusRegex, tmp, sizeof(matches)/sizeof(matches[0]), matches, "Bad Response");
84         if( ret ) {
85                 return -1;
86         }
87
88         tmp[ matches[3].rm_eo ] = '\0';
89         status = &tmp[ matches[3].rm_so ];
90
91         printf("Machine responded slot status '%s'\n", status);
92
93         if( strcmp(status, "full") == 0 )
94                 return 0;
95
96         return 1;
97 }
98
99 /**
100  * \brief Actually do a dispense from the coke machine
101  */
102 int Coke_DoDispense(int User, int Item)
103 {
104         char    tmp[32], *status;
105         regmatch_t      matches[4];
106
107         // Sanity please
108         if( Item < 0 || Item > 6 )      return -1;
109
110         WaitForColon();
111
112         // Dispense
113         sprintf(tmp, "d%i\r\n", Item);
114         write(giCoke_SerialFD, tmp, 4);
115         
116         WaitForColon();
117
118         // Get status
119         ReadLine(sizeof(tmp)-1, tmp);
120         
121         tmp[ matches[3].rm_eo ] = '\0';
122         status = &tmp[ matches[3].rm_so ];
123
124         printf("Machine responded slot status '%s'\n", status);
125
126         return 0;
127 }
128
129 char ReadChar()
130 {
131         fd_set  readfs;
132         char    ch = 0;
133          int    ret;
134         
135         FD_ZERO(&readfs);
136         FD_SET(giCoke_SerialFD, &readfs);
137         
138         ret = select(giCoke_SerialFD+1, &readfs, NULL, NULL, NULL);
139         if( ret != 1 ) {
140                 printf("readchar return %i\n", ret);
141                 return 0;
142         }
143         
144         ret = read(giCoke_SerialFD, &ch, 1);
145         if( ret != 1 ) {
146                 printf("ret = %i\n", ret);
147                 return 0;
148         }
149         
150         return ch;
151 }
152
153 void WaitForColon()
154 {
155         fd_set  readfs;
156         char    ch = 0;
157         
158         FD_SET(giCoke_SerialFD, &readfs);
159         
160         while( (ch = ReadChar()) != ':' && ch != 0);
161 }
162
163 int ReadLine(int len, char *output)
164 {
165         char    ch;
166          int    i = 0;
167         
168         for(;;)
169         {
170                 ch = ReadChar();
171                 
172                 
173                 if( i < len )
174                         output[i++] = ch;
175                 
176                 if( ch == '\0' ) {
177                         return -1;
178                 }
179                 if( ch == '\n' || ch == '\r' ) {
180                         if( i < len )
181                                 output[--i] = '\0';
182                         return i;
183                 }
184         }
185 }
186
187

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