#include <errno.h>
#define MIN_DISPENSE_PERIOD 5
+#define COKE_RECONNECT_RATELIMIT 2
// === CONSTANTS ===
const int ciCoke_MinPeriod = 5;
int Coke_int_GetSlotFromItem(int Item, int bDispensing);
int Coke_int_IsSlotEmpty(int Slot);
int Coke_int_DropSlot(int Slot);
+static int _ReadBit(int BitNum, uint8_t *Value);
+static int _WriteBit(int BitNum, uint8_t Value);
// === GLOBALS ===
tHandler gCoke_Handler = {
const char *gsCoke_ModbusAddress = "130.95.13.73";
modbus_t *gCoke_Modbus;
time_t gtCoke_LastDispenseTime;
+time_t gtCoke_LastReconnectTime;
int gbCoke_DummyMode = 1;
int giCoke_NextCokeSlot = 0;
sleep( delay );
printf("wait done\n");
}
+ gtCoke_LastDispenseTime = time(NULL);
return Coke_int_DropSlot(slot);
}
// --- INTERNAL FUNCTIONS ---
int Coke_int_ConnectToPLC(void)
{
+ // Ratelimit
+ if( time(NULL) - gtCoke_LastReconnectTime < COKE_RECONNECT_RATELIMIT )
+ return -1;
+
if( !gCoke_Modbus )
{
gCoke_Modbus = modbus_new_tcp(gsCoke_ModbusAddress, 502);
if( !gCoke_Modbus )
{
perror("coke - modbus_new_tcp");
+ gtCoke_LastReconnectTime = time(NULL);
return 1;
}
}
printf("Connecting to coke PLC machine on '%s'\n", gsCoke_ModbusAddress);
+ fprintf(stderr, "Connecting to coke PLC machine on '%s'\n", gsCoke_ModbusAddress);
if( modbus_connect(gCoke_Modbus) )
{
+ gtCoke_LastReconnectTime = time(NULL);
perror("coke - modbus_connect");
modbus_free(gCoke_Modbus);
gCoke_Modbus = NULL;
if( Slot < 0 || Slot > 9 ) return -1;
- if(!gCoke_Modbus)
- return -2;
-
errno = 0;
- if( modbus_read_bits(gCoke_Modbus, ciCoke_StatusBitBase + Slot, 1, &status) <= 0 )
+ if( _ReadBit(ciCoke_StatusBitBase + Slot, &status) )
{
- // TODO: Retry connection, or fail
perror("Coke_int_IsSlotEmpty - modbus_read_bits");
return -2;
}
if(Slot < 0 || Slot > 9) return -1;
- // Can't dispense if the machine is not connected
- if( !gCoke_Modbus )
- return -2;
-
// Check if a dispense is in progress
- if( modbus_read_bits(gCoke_Modbus, ciCoke_DropBitBase + Slot, 1, &res) <= 0 )
+ if( _ReadBit(ciCoke_DropBitBase + Slot, &res) )
{
perror("Coke_int_DropSlot - modbus_read_bits#1");
return -2;
}
// Dispense
- if( modbus_write_bit(gCoke_Modbus, ciCoke_DropBitBase + Slot, 1) < 0 )
+ if( _WriteBit(ciCoke_DropBitBase + Slot, 1) )
{
perror("Coke_int_DropSlot - modbus_write_bit");
return -2;
// Check that it started
usleep(1000); // 1ms
- if( modbus_read_bits(gCoke_Modbus, ciCoke_DropBitBase + Slot, 1, &res) <= 0 )
+ if( _ReadBit(ciCoke_DropBitBase + Slot, &res) )
{
perror("Coke_int_DropSlot - modbus_read_bits#2");
return -2;
return 0;
}
+int _ReadBit(int BitNum, uint8_t *Value)
+{
+ errno = 0;
+ if( !gCoke_Modbus && Coke_int_ConnectToPLC() )
+ return -1;
+ if( modbus_read_bits( gCoke_Modbus, BitNum, 1, Value) >= 0 )
+ return 0;
+ if( Coke_int_ConnectToPLC() )
+ return -1;
+ if( modbus_read_bits( gCoke_Modbus, BitNum, 1, Value) >= 0 )
+ return 0;
+ return -1;
+}
+
+int _WriteBit(int BitNum, uint8_t Value)
+{
+ errno = 0;
+ if( !gCoke_Modbus && Coke_int_ConnectToPLC() )
+ return -1;
+ if( modbus_write_bit( gCoke_Modbus, BitNum, Value != 0 ) >= 0 )
+ return 0;
+ if( Coke_int_ConnectToPLC() )
+ return -1;
+ if( modbus_write_bit( gCoke_Modbus, BitNum, Value != 0 ) >= 0 )
+ return 0;
+ return -1;
+}
+