68eea0144cbace8b3be1301b04d0868cbc0ba8d5
[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  * NOTES:
11  * - Remember, the coke machine echoes your text back to you!
12  */
13 #include "common.h"
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdarg.h>
17 #include <pthread.h>
18 #include <unistd.h>
19 #include <modbus/modbus.h>
20
21 #define MIN_DISPENSE_PERIOD     5
22
23 // === CONSTANTS ===
24 const int       ciCoke_MinPeriod = 5;
25 const int       ciCoke_DropBitBase = 0;
26 const int       ciCoke_StatusBitBase = 0;
27
28 // === IMPORTS ===
29
30 // === PROTOTYPES ===
31  int    Coke_InitHandler();
32  int    Coke_CanDispense(int User, int Item);
33  int    Coke_DoDispense(int User, int Item);
34
35 // === GLOBALS ===
36 tHandler        gCoke_Handler = {
37         "coke",
38         Coke_InitHandler,
39         Coke_CanDispense,
40         Coke_DoDispense
41 };
42 const char      *gsCoke_ModbusAddress = "130.95.13.73";
43 modbus_t        *gCoke_Modbus;
44 time_t  gtCoke_LastDispenseTime;
45  int    gbCoke_DummyMode = 1;
46
47 // == CODE ===
48 int Coke_InitHandler()
49 {
50         // Configuable dummy/blank mode (all dispenses succeed)
51         // TODO: Find a better way of handling missing/invalid options
52         if( Config_GetValueCount("coke_dummy_mode") > 0 )
53         {
54                 gbCoke_DummyMode = Config_GetValue_Bool("coke_dummy_mode", 0);
55                 if(gbCoke_DummyMode == -1)      gbCoke_DummyMode = 0;
56         }
57
58         // Open modbus
59         if( !gbCoke_DummyMode )
60         {
61                 printf("Connecting to coke machine on '%s'\n", gsCoke_ModbusAddress);
62                 
63                 modbus_new_tcp(gsCoke_ModbusAddress, 502);
64                 if( !gCoke_Modbus )
65                 {
66                         perror("coke - modbus_new_tcp");
67                 }
68                 
69                 if( gCoke_Modbus && modbus_connect(gCoke_Modbus) )
70                 {
71                         perror("coke - modbus_connect");
72                         modbus_free(gCoke_Modbus);
73                         gCoke_Modbus = NULL;
74                 }
75         }
76
77         return 0;
78 }
79
80 int Coke_CanDispense(int UNUSED(User), int Item)
81 {
82         uint8_t status;
83         // Sanity please
84         if( Item < 0 || Item > 6 )      return -1;
85
86         // Check for 'dummy' mode
87         if( gbCoke_DummyMode )
88                 return 0;
89         
90         // Can't dispense if the machine is not connected
91         if( !gCoke_Modbus )
92                 return -2;
93
94         if( modbus_read_bits(gCoke_Modbus, ciCoke_StatusBitBase + Item, 1, &status) )
95         {
96                 // TODO: Check for a connection issue
97                 perror("Coke_CanDispense - modbus_read_bits");
98         }
99
100         return status == 0;
101 }
102
103 /**
104  * \brief Actually do a dispense from the coke machine
105  */
106 int Coke_DoDispense(int UNUSED(User), int Item)
107 {
108         // Sanity please
109         if( Item < 0 || Item > 6 )      return -1;
110
111         // Check for 'dummy' mode
112         if( gbCoke_DummyMode )
113                 return 0;
114         
115         // Can't dispense if the machine is not connected
116         if( !gCoke_Modbus )
117                 return -2;
118
119         // Make sure there are not two dispenses within n seconds
120         if( time(NULL) - gtCoke_LastDispenseTime < ciCoke_MinPeriod )
121         {
122                  int    delay = ciCoke_MinPeriod - (time(NULL) - gtCoke_LastDispenseTime);
123                 printf("Wait %i seconds?\n", delay);
124                 sleep( delay );
125                 printf("wait done\n");
126         }
127         
128         // Dispense
129         if( modbus_write_bit(gCoke_Modbus, ciCoke_DropBitBase + Item, 1) )
130         {
131                 // TODO: Handle connection issues
132                 perror("Coke_DoDispense - modbus_write_bit");
133         }
134         
135         return 0;
136 }
137

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