Starting with Raspberry Pi, the TCP/IP server of this recipe (in the Raspberry Pi folder of this recipe), starts the same as the Delphi application that we've just written. If you have followed all the necessary steps, by clicking on the switches on the Delphi app, you will be able to turn the relative light bulb ON and OFF on the circuit associated with the Raspberry Pi.
Let's understand how the various elements involved work. The server is very similar to the one in the previous recipe, so I will only focus on the points that are different:
- It initializes the GPIO pins, that is, it makes the UnExport and sets the pin direction to OUTPUT. The first point is used to start from a clean situation, and the second is used to specify that the direction of the pin is out because we have to turn the relays on and off:
const
RELAY_PIN_1: integer = 17;
RELAY_PIN_2: integer = 18;
procedure InitializeGPIO(PRaspberry Pi: TRaspberry Pi);
begin
PRaspberry Pi.UnExport([RELAY_PIN_1, RELAY_PIN_2]);
PRaspberry Pi.SetPINDirection(RELAY_PIN_1, TGPIODirection.dirOUTPUT);
PRaspberry Pi.SetPINDirection(RELAY_PIN_2, TGPIODirection.dirOUTPUT);
PRaspberry Pi.SetPIN(RELAY_PIN_1, True);
PRaspberry Pi.SetPIN(RELAY_PIN_2, True);
end;
- It starts listening at port 8008 and when it reads something, it passes it to the HandleClient method.
- In the HandleClient method, it understands which command is passed by the TCP/IP client. Once the value is understood, it is passed to the HandleGPIOCmd method.
- The HandleGPIOCmd method defines the logic to interpret the client command, and this makes changes to the filesystem through the TRaspberry Pi class:
function HandleGPIOCmd(PRaspberry Pi: TRaspberry Pi; PCmd: string): string;
var
LPin: string;
LDir, LPinI: integer;
begin
// command accept 2 chars: PIN and Direction ex. R1, L1, R0.
LPin := PCmd[1];
// light bulb 1
if LPin = 'R' then
LPinI := RELAY_PIN_1
// light bulb 2
else if LPin = 'L' then
LPinI := RELAY_PIN_2
else
exit('');
LDir := StrToInt(PCmd[2]);
PRaspberry Pi.SetPIN(LPinI, LDir > 0);
exit('ok');
end;
The following table is used to describe the commands and actions for this:
Command | Action |
R1 |
Turns light bulb 1 ON |
R0 |
Turns light bulb 1 OFF |
L1 |
Turns light bulb 2 ON |
L0 |
Turns light bulb 2 OFF |
The Delphi application is very simple to understand. When you click on the switch, the command to be sent is constructed (R1-R0-G1-G0), depending on which switch and its status. This value is passed to the SendCmd method that sets up a class for the TCP/IP communication and sends the command:
procedure TMainForm.greenLEDSwitchSwitch(Sender: TObject);
var
LCMD: String;
begin
LCMD := 'G' + ifthen(greenLEDSwitch.IsChecked, '1', '0');
SendCmd(LCMD);
end;
procedure TMainForm.redLEDSwitchSwitch(Sender: TObject);
var
LCMD: String;
begin
LCMD := 'R' + ifthen(redLEDSwitch.IsChecked, '1', '0');
SendCmd(LCMD);
end;
If exceptions are raised during TCP/IP communication, they are written to the Memo1 component.