For this project we are assuming, that you have a Delphi development environment set up and that you have a rudimentary understanding of the Delphi language.
If you are totally new to Delphi itself you should start here. If you are new to the Tinkerforge API, you should start here.
We are setting the following goals for this project:
Since this project will likely run 24/7, we will also make sure that the application is as robust towards external influences as possible. The application should still work when
In the following we will show step-by-step how this can be achieved.
To start off, we need to define where our program should connect to:
const
HOST = 'localhost';
PORT = 4223;
If the WIFI Extension is used or if the Brick Daemon is running on a different PC, you have to exchange "localhost" with the IP address or hostname of the WIFI Extension or PC.
When the program is started, we need to register the OnEnumerate
callback and the OnConnected
callback and trigger a first
enumerate:
procedure TWeatherStation.Execute;
begin
ipcon := TIPConnection.Create;
ipcon.Connect(HOST, PORT);
ipcon.OnEnumerate := {$ifdef FPC}@{$endif}EnumerateCB;
ipcon.OnConnected := {$ifdef FPC}@{$endif}ConnectedCB;
ipcon.Enumerate;
end;
The enumerate callback is triggered if a Brick gets connected over USB or if
the Enumerate
function is called. This allows to discover the Bricks and
Bricklets in a stack without knowing their types or UIDs beforehand.
The connected callback is triggered if the connection to the WIFI Extension or to the Brick Daemon got established. In this callback we need to trigger the enumerate again, if the reason is an auto reconnect:
procedure TWeatherStation.ConnectedCB(sender: TIPConnection; const connectedReason: byte);
begin
if (connectedReason = IPCON_CONNECT_REASON_AUTO_RECONNECT) then begin
ipcon.Enumerate;
end;
end;
An auto reconnect means, that the connection to the WIFI Extension or to the Brick Daemon was lost and could subsequently be established again. In this case the Bricklets may have lost their configurations and we have to reconfigure them. Since the configuration is done during the enumeration process (see below), we have to trigger another enumeration.
Step 1 put together:
const
HOST = 'localhost';
PORT = 4223;
type
TWeatherStation = class
private
ipcon: TIPConnection;
public
procedure ConnectedCB(sender: TIPConnection; const connectedReason: byte);
procedure Execute;
end;
procedure TWeatherStation.ConnectedCB(sender: TIPConnection; const connectedReason: byte);
begin
if (connectedReason = IPCON_CONNECT_REASON_AUTO_RECONNECT) then begin
ipcon.Enumerate;
end;
end;
procedure TWeatherStation.Execute;
begin
ipcon := TIPConnection.Create;
ipcon.Connect(HOST, PORT);
ipcon.OnEnumerate := {$ifdef FPC}@{$endif}EnumerateCB;
ipcon.OnConnected := {$ifdef FPC}@{$endif}ConnectedCB;
ipcon.Enumerate;
end;
During the enumeration we want to configure all of the weather measuring Bricklets. Doing this during the enumeration ensures that Bricklets get reconfigured if the stack was disconnected or there was a power loss.
The configurations should be performed on first startup
(IPCON_ENUMERATION_TYPE_CONNECTED
) as well as whenever the enumeration is
triggered externally by us (IPCON_ENUMERATION_TYPE_AVAILABLE
):
procedure TWeatherStation.EnumerateCB(sender: TIPConnection; const uid: string;
const connectedUid: string; const position: char;
const hardwareVersion: TVersionNumber;
const firmwareVersion: TVersionNumber;
const deviceIdentifier: word; const enumerationType: byte);
begin
if ((enumerationType = IPCON_ENUMERATION_TYPE_CONNECTED) or
(enumerationType = IPCON_ENUMERATION_TYPE_AVAILABLE)) then begin
The LCD 20x4 configuration is simple, we want the current text cleared and we want the backlight on:
if (deviceIdentifier = BRICKLET_LCD_20X4_DEVICE_IDENTIFIER) then begin
brickletLCD := TBrickletLCD20x4.Create(UID, ipcon);
brickletLCD.ClearDisplay();
brickletLCD.BacklightOn();
end;
We configure the Ambient Light, Humidity and Barometer Bricklet to return their respective measurements continuously with a period of 1000ms (1s):
else if (deviceIdentifier = BRICKLET_AMBIENT_LIGHT_DEVICE_IDENTIFIER) then begin
brickletAmbientLight := TBrickletAmbientLight.Create(uid, ipcon);
brickletAmbientLight.SetIlluminanceCallbackPeriod(1000);
brickletAmbientLight.OnIlluminance := {$ifdef FPC}@{$endif}IlluminanceCB;
end
else if (deviceIdentifier = BRICKLET_HUMIDITY_DEVICE_IDENTIFIER) then begin
brickletHumidity := TBrickletHumidity.Create(uid, ipcon);
brickletHumidity.SetHumidityCallbackPeriod(1000);
brickletHumidity.OnHumidity := {$ifdef FPC}@{$endif}HumidityCB;
end
else if (deviceIdentifier = BRICKLET_BAROMETER_DEVICE_IDENTIFIER) then begin
brickletBarometer := TBrickletBarometer.Create(uid, ipcon);
brickletBarometer.SetAirPressureCallbackPeriod(1000);
brickletBarometer.OnAirPressure := {$ifdef FPC}@{$endif}AirPressureCB;
end;
This means that the Bricklets will call the IlluminanceCB
, HumidityCB
and AirPressureCB
callback functions whenever the value has changed, but
with a maximum period of 1000ms.
Step 2 put together:
procedure TWeatherStation.EnumerateCB(sender: TIPConnection; const uid: string;
const connectedUid: string; const position: char;
const hardwareVersion: TVersionNumber;
const firmwareVersion: TVersionNumber;
const deviceIdentifier: word; const enumerationType: byte);
begin
if ((enumerationType = IPCON_ENUMERATION_TYPE_CONNECTED) or
(enumerationType = IPCON_ENUMERATION_TYPE_AVAILABLE)) then begin
if (deviceIdentifier = BRICKLET_LCD_20X4_DEVICE_IDENTIFIER) then begin
brickletLCD := TBrickletLCD20x4.Create(UID, ipcon);
brickletLCD.ClearDisplay();
brickletLCD.BacklightOn();
end
else if (deviceIdentifier = BRICKLET_AMBIENT_LIGHT_DEVICE_IDENTIFIER) then begin
brickletAmbientLight := TBrickletAmbientLight.Create(uid, ipcon);
brickletAmbientLight.SetIlluminanceCallbackPeriod(1000);
brickletAmbientLight.OnIlluminance := {$ifdef FPC}@{$endif}IlluminanceCB;
end
else if (deviceIdentifier = BRICKLET_HUMIDITY_DEVICE_IDENTIFIER) then begin
brickletHumidity := TBrickletHumidity.Create(uid, ipcon);
brickletHumidity.SetHumidityCallbackPeriod(1000);
brickletHumidity.OnHumidity := {$ifdef FPC}@{$endif}HumidityCB;
end
else if (deviceIdentifier = BRICKLET_BAROMETER_DEVICE_IDENTIFIER) then begin
brickletBarometer := TBrickletBarometer.Create(uid, ipcon);
brickletBarometer.SetAirPressureCallbackPeriod(1000);
brickletBarometer.OnAirPressure := {$ifdef FPC}@{$endif}AirPressureCB;
end;
end;
end;
We want a neat arrangement of the measurements on the display, such as:
Illuminanc 137.39 lx
Humidity 34.10 %
Air Press 987.70 mb
Temperature 22.64 °C
The decimal marks and the units should be below each other. To achieve this we use two characters for the unit, two decimal places and crop the name to use the maximum characters that are left. That's why "Illuminanc" is missing its final "e".
text := Format('%6.2f', [value])
The code above converts a floating point value to a string according to the given format specification. The result will be at least 6 characters long with 2 decimal places, filled up with spaces from the left if it would be shorter than 6 characters otherwise.
procedure TWeatherStation.IlluminanceCB(sender: TBrickletAmbientLight; const illuminance: word);
var text: string;
begin
text := Format('Illuminanc %6.2f lx', [illuminance/10.0]);
brickletLCD.WriteLine(0, 0, text);
end;
procedure TWeatherStation.HumidityCB(sender: TBrickletHumidity; const humidity: word);
var text: string;
begin
text := Format('Humidity %6.2f %%', [humidity/10.0]);
brickletLCD.WriteLine(1, 0, text);
end;
procedure TWeatherStation.AirPressureCB(sender: TBrickletBarometer; const airPressure: longint);
var text: string;
begin
text := Format('Air Press %7.2f mb', [airPressure/1000.0]);
brickletLCD.WriteLine(2, 0, text);
end;
We are still missing the temperature. The Barometer Bricklet can
measure temperature, but it doesn't have a callback for it. As a
simple workaround we can retrieve the temperature in the AirPressureCB
callback function:
procedure TWeatherStation.AirPressureCB(sender: TBrickletBarometer; const airPressure: longint);
var text: string; temperature: smallint;
begin
text := Format('Air Press %7.2f mb', [airPressure/1000.0]);
brickletLCD.WriteLine(2, 0, text);
temperature := brickletBarometer.GetChipTemperature;
text := Format('Temperature %5.2f %sC', [temperature/100.0, '' + char($DF)]);
brickletLCD.WriteLine(3, 0, text);
end;
Step 3 put together:
procedure TWeatherStation.IlluminanceCB(sender: TBrickletAmbientLight; const illuminance: word);
var text: string;
begin
text := Format('Illuminanc %6.2f lx', [illuminance/10.0]);
brickletLCD.WriteLine(0, 0, text);
end;
procedure TWeatherStation.HumidityCB(sender: TBrickletHumidity; const humidity: word);
var text: string;
begin
text := Format('Humidity %6.2f %%', [humidity/10.0]);
brickletLCD.WriteLine(1, 0, text);
end;
procedure TWeatherStation.AirPressureCB(sender: TBrickletBarometer; const airPressure: longint);
var text: string; temperature: smallint;
begin
text := Format('Air Press %7.2f mb', [airPressure/1000.0]);
brickletLCD.WriteLine(2, 0, text);
temperature := brickletBarometer.GetChipTemperature;
{ 0xDF == ° on LCD 20x4 charset }
text := Format('Temperature %5.2f %sC', [temperature/100.0, '' + char($DF)]);
brickletLCD.WriteLine(3, 0, text);
end;
That's it. If we would copy these three steps together in one file and execute it, we would have a working Weather Station!
There are some obvious ways to make the output better.
The name could be cropped according to the exact space that is available
(depending on the number of digits of the measured value). Also, reading the
temperature in the AirPressureCB
callback function is suboptimal. If the
air pressure doesn't change, we won't update the temperature. It would be better to read the temperature in a different thread in an endless
loop with a one second sleep after each read. But we want to keep this code as
simple as possible.
However, we do not meet all of our goals yet. The program is not yet robust enough. What happens if it can't connect on startup? What happens if the enumerate after an auto reconnect doesn't work?
What we need is error handling!
On startup, we need to try to connect until the connection works:
while (true) do begin
try
ipcon.Connect(HOST, PORT);
break;
except
on e: Exception do begin
WriteLn('Connection Error: ' + e.Message);
Sleep(1000);
end;
end;
end;
and we need to try enumerating until the message goes through:
while (true) do begin
try
ipcon.Enumerate;
break;
except
on e: Exception do begin
WriteLn('Enumeration Error: ' + e.Message);
Sleep(1000);
end;
end;
end;
With these changes it is now possible to first start the program and connect the Weather Station afterwards.
We also need to make sure, that we only write to the LCD if it is already initialized:
procedure TWeatherStation.IlluminanceCB(sender: TBrickletAmbientLight; const illuminance: word);
var text: string;
begin
if (brickletLCD <> nil) then begin
text := Format('Illuminanc %6.2f lx', [illuminance/10.0]);
brickletLCD.WriteLine(0, 0, text);
WriteLn('Write to line 0: ' + text);
end;
end;
and that we have to deal with errors during the initialization:
if (deviceIdentifier = BRICKLET_AMBIENT_LIGHT_DEVICE_IDENTIFIER) then begin
try
brickletAmbientLight := TBrickletAmbientLight.Create(uid, ipcon);
brickletAmbientLight.SetIlluminanceCallbackPeriod(1000);
brickletAmbientLight.OnIlluminance := {$ifdef FPC}@{$endif}IlluminanceCB;
WriteLn('Ambient Light initialized');
except
on e: Exception do begin
WriteLn('Ambient Light init failed: ' + e.Message);
brickletAmbientLight := nil;
end;
end;
end;
Additionally we added some logging. With the logging we can later find out what exactly caused a problem, if the Weather Station failed for some time period.
For example, if we connect to the Weather Station via Wi-Fi and we have regular auto reconnects, it likely means that the Wi-Fi connection is not very stable.
That's it! We are already done with our Weather Station and all of the goals should be met.
Now all of the above put together (download):
program WeatherStation;
{$ifdef MSWINDOWS}{$apptype CONSOLE}{$endif}
{$ifdef FPC}{$mode OBJFPC}{$H+}{$endif}
uses
Device,
SysUtils,
IPConnection,
BrickletLCD20x4,
BrickletHumidity,
BrickletBarometer,
BrickletHumidityV2,
BrickletBarometerV2,
BrickletAmbientLight,
BrickletAmbientLightV2,
BrickletAmbientLightV3;
const
HOST = 'localhost';
PORT = 4223;
type
TWeatherStation = class
private
ipcon: TIPConnection;
brickletLCD: TBrickletLCD20x4;
brickletHumidity: TBrickletHumidity;
brickletBarometer: TBrickletBarometer;
brickletHumidityV2: TBrickletHumidityV2;
brickletBarometerV2: TBrickletBarometerV2;
brickletAmbientLight: TBrickletAmbientLight;
brickletAmbientLightV2: TBrickletAmbientLightV2;
brickletAmbientLightV3: TBrickletAmbientLightV3;
public
procedure Execute;
constructor Create;
destructor Destroy; override;
procedure EnumerateCB(sender: TIPConnection;
const uid: string;
const connectedUid: string;
const position: char;
const hardwareVersion: TVersionNumber;
const firmwareVersion: TVersionNumber;
const deviceIdentifier: word;
const enumerationType: byte);
procedure HumidityCB(sender: TBrickletHumidity; const humidity: word);
procedure HumidityV2CB(sender: TBrickletHumidityV2; const humidity: word);
procedure ConnectedCB(sender: TIPConnection; const connectedReason: byte);
procedure AirPressureCB(sender: TBrickletBarometer; const airPressure: longint);
procedure IlluminanceCB(sender: TBrickletAmbientLight; const illuminance: word);
procedure AirPressureV2CB(sender: TBrickletBarometerV2; const airPressure: longint);
procedure IlluminanceV2CB(sender: TBrickletAmbientLightV2; const illuminance: longword);
procedure IlluminanceV3CB(sender: TBrickletAmbientLightV3; const illuminance: longword);
end;
var
ws: TWeatherStation;
constructor TWeatherStation.Create;
begin
ipcon := nil;
brickletLCD := nil;
brickletHumidity := nil;
brickletBarometer := nil;
brickletHumidityV2 := nil;
brickletBarometerV2 := nil;
brickletAmbientLight := nil;
brickletAmbientLightV2 := nil;
brickletAmbientLightV3 := nil;
end;
destructor TWeatherStation.Destroy;
begin
if (ipcon <> nil) then ipcon.Destroy;
if (brickletLCD <> nil) then brickletLCD.Destroy;
if (brickletHumidity <> nil) then brickletHumidity.Destroy;
if (brickletBarometer <> nil) then brickletBarometer.Destroy;
if (brickletHumidityV2 <> nil) then brickletHumidityV2.Destroy;
if (brickletBarometerV2 <> nil) then brickletBarometerV2.Destroy;
if (brickletAmbientLight <> nil) then brickletAmbientLight.Destroy;
if (brickletAmbientLightV2 <> nil) then brickletAmbientLightV2.Destroy;
if (brickletAmbientLightV3 <> nil) then brickletAmbientLightV3.Destroy;
inherited Destroy;
end;
procedure TWeatherStation.ConnectedCB(sender: TIPConnection; const connectedReason: byte);
begin
if (connectedReason = IPCON_CONNECT_REASON_AUTO_RECONNECT) then
begin
WriteLn('Auto Reconnect');
while (true) do begin
try
ipcon.Enumerate;
break;
except
on e: Exception do
begin
WriteLn('Enumeration Error: ' + e.Message);
Sleep(1000);
end;
end;
end;
end;
end;
procedure TWeatherStation.EnumerateCB(sender: TIPConnection; const uid: string;
const connectedUid: string; const position: char;
const hardwareVersion: TVersionNumber;
const firmwareVersion: TVersionNumber;
const deviceIdentifier: word; const enumerationType: byte);
begin
if ((enumerationType = IPCON_ENUMERATION_TYPE_CONNECTED) or
(enumerationType = IPCON_ENUMERATION_TYPE_AVAILABLE)) then
begin
if (deviceIdentifier = BRICKLET_LCD_20X4_DEVICE_IDENTIFIER) then
begin
try
brickletLCD := TBrickletLCD20x4.Create(UID, ipcon);
brickletLCD.ClearDisplay;
brickletLCD.BacklightOn;
WriteLn('LCD 20x4 initialized');
except
on e: Exception do
begin
WriteLn('LCD 20x4 init failed: ' + e.Message);
brickletLCD := nil;
end;
end;
end
else if (deviceIdentifier = BRICKLET_AMBIENT_LIGHT_DEVICE_IDENTIFIER) then
begin
try
brickletAmbientLight := TBrickletAmbientLight.Create(uid, ipcon);
brickletAmbientLight.SetIlluminanceCallbackPeriod(1000);
brickletAmbientLight.OnIlluminance := {$ifdef FPC}@{$endif}IlluminanceCB;
WriteLn('Ambient Light initialized');
except
on e: Exception do
begin
WriteLn('Ambient Light init failed: ' + e.Message);
brickletAmbientLight := nil;
end;
end;
end
else if (deviceIdentifier = BRICKLET_AMBIENT_LIGHT_V2_DEVICE_IDENTIFIER) then
begin
try
brickletAmbientLightV2 := TBrickletAmbientLightV2.Create(uid, ipcon);
brickletAmbientLightV2.SetConfiguration(BRICKLET_AMBIENT_LIGHT_V2_ILLUMINANCE_RANGE_64000LUX,
BRICKLET_AMBIENT_LIGHT_V2_INTEGRATION_TIME_200MS);
brickletAmbientLightV2.SetIlluminanceCallbackPeriod(1000);
brickletAmbientLightV2.OnIlluminance := {$ifdef FPC}@{$endif}IlluminanceV2CB;
WriteLn('Ambient Light 2.0 initialized');
except
on e: Exception do
begin
WriteLn('Ambient Light 2.0 init failed: ' + e.Message);
brickletAmbientLightV2 := nil;
end;
end;
end
else if (deviceIdentifier = BRICKLET_AMBIENT_LIGHT_V3_DEVICE_IDENTIFIER) then
begin
try
brickletAmbientLightV3 := TBrickletAmbientLightV3.Create(uid, ipcon);
brickletAmbientLightV3.SetConfiguration(BRICKLET_AMBIENT_LIGHT_V2_ILLUMINANCE_RANGE_64000LUX,
BRICKLET_AMBIENT_LIGHT_V2_INTEGRATION_TIME_200MS);
brickletAmbientLightV3.SetIlluminanceCallbackConfiguration(1000, False, 'x', 0, 0);
brickletAmbientLightV3.OnIlluminance := {$ifdef FPC}@{$endif}IlluminanceV3CB;
WriteLn('Ambient Light 3.0 initialized');
except
on e: Exception do
begin
WriteLn('Ambient Light 3.0 init failed: ' + e.Message);
brickletAmbientLightV3 := nil;
end;
end;
end
else if (deviceIdentifier = BRICKLET_HUMIDITY_DEVICE_IDENTIFIER) then
begin
try
brickletHumidity := TBrickletHumidity.Create(uid, ipcon);
brickletHumidity.SetHumidityCallbackPeriod(1000);
brickletHumidity.OnHumidity := {$ifdef FPC}@{$endif}HumidityCB;
WriteLn('Humidity initialized');
except
on e: Exception do
begin
WriteLn('Humidity init failed: ' + e.Message);
brickletHumidity := nil;
end;
end;
end
else if (deviceIdentifier = BRICKLET_HUMIDITY_V2_DEVICE_IDENTIFIER) then
begin
try
brickletHumidityV2 := TBrickletHumidityV2.Create(uid, ipcon);
brickletHumidityV2.SetHumidityCallbackConfiguration(1000, true, 'x', 0, 0);
brickletHumidityV2.OnHumidity := {$ifdef FPC}@{$endif}HumidityV2CB;
WriteLn('Humidity 2.0 initialized');
except
on e: Exception do
begin
WriteLn('Humidity 2.0 init failed: ' + e.Message);
brickletHumidityV2 := nil;
end;
end;
end
else if (deviceIdentifier = BRICKLET_BAROMETER_DEVICE_IDENTIFIER) then
begin
try
brickletBarometer := TBrickletBarometer.Create(uid, ipcon);
brickletBarometer.SetAirPressureCallbackPeriod(1000);
brickletBarometer.OnAirPressure := {$ifdef FPC}@{$endif}AirPressureCB;
WriteLn('Barometer initialized');
except
on e: Exception do
begin
WriteLn('Barometer init failed: ' + e.Message);
brickletBarometer := nil;
end;
end;
end
else if (deviceIdentifier = BRICKLET_BAROMETER_V2_DEVICE_IDENTIFIER) then
begin
try
brickletBarometerV2 := TBrickletBarometerV2.Create(uid, ipcon);
brickletBarometerV2.SetAirPressureCallbackConfiguration(1000, False, 'x', 0, 0);
brickletBarometerV2.OnAirPressure := {$ifdef FPC}@{$endif}AirPressureV2CB;
WriteLn('Barometer 2.0 initialized');
except
on e: Exception do
begin
WriteLn('Barometer 2.0 init failed: ' + e.Message);
brickletBarometerV2 := nil;
end;
end;
end;
end;
end;
procedure TWeatherStation.IlluminanceCB(sender: TBrickletAmbientLight; const illuminance: word);
var text: string;
begin
if (brickletLCD <> nil) then
begin
text := Format('Illuminanc %6.2f lx', [illuminance/10.0]);
brickletLCD.WriteLine(0, 0, text);
WriteLn('Write to line 0: ' + text);
end;
end;
procedure TWeatherStation.IlluminanceV2CB(sender: TBrickletAmbientLightV2;
const illuminance: longword);
var text: string;
begin
if (brickletLCD <> nil) then
begin
text := Format('Illumina %8.2f lx', [illuminance/100.0]);
brickletLCD.WriteLine(0, 0, text);
WriteLn('Write to line 0: ' + text);
end;
end;
procedure TWeatherStation.IlluminanceV3CB(sender: TBrickletAmbientLightV3;
const illuminance: longword);
var text: string;
begin
if (brickletLCD <> nil) then
begin
text := Format('Illumina %8.2f lx', [illuminance / 100.0]);
brickletLCD.WriteLine(0, 0, text);
WriteLn('Write to line 0: ' + text);
end;
end;
procedure TWeatherStation.HumidityCB(sender: TBrickletHumidity;
const humidity: word);
var text: string;
begin
if (brickletLCD <> nil) then
begin
text := Format('Humidity %6.2f %%', [humidity/10.0]);
brickletLCD.WriteLine(1, 0, text);
WriteLn('Write to line 1: ' + text);
end;
end;
procedure TWeatherStation.HumidityV2CB(sender: TBrickletHumidityV2;
const humidity: word);
var text: string;
begin
if (brickletLCD <> nil) then
begin
text := Format('Humidity %6.2f %%', [humidity/100.0]);
brickletLCD.WriteLine(1, 0, text);
WriteLn('Write to line 1: ' + text);
end;
end;
procedure TWeatherStation.AirPressureCB(sender: TBrickletBarometer;
const airPressure: longint);
var text: string; temperature: smallint;
begin
if (brickletLCD <> nil) then
begin
text := Format('Air Press %7.2f mb', [airPressure/1000.0]);
brickletLCD.WriteLine(2, 0, text);
WriteLn('Write to line 2: ' + text);
try
temperature := brickletBarometer.GetChipTemperature;
except
on e: Exception do
begin
WriteLn('Could not get temperature: ' + e.Message);
exit;
end;
end;
{ $DF == ° on LCD 20x4 charset. }
text := Format('Temperature %5.2f %sC', [temperature/100.0, '' + char($DF)]);
brickletLCD.WriteLine(3, 0, text);
text := StringReplace(text, char($DF), '°', [rfReplaceAll]);
WriteLn('Write to line 3: ' + text);
end;
end;
procedure TWeatherStation.AirPressureV2CB(sender: TBrickletBarometerV2;
const airPressure: longint);
var text: string;
temperature: smallint;
begin
if (brickletLCD <> nil) then
begin
text := Format('Air Press %7.2f mb', [airPressure/1000.0]);
brickletLCD.WriteLine(2, 0, text);
WriteLn('Write to line 2: ' + text);
try
temperature := brickletBarometerV2.GetTemperature;
except
on e: Exception do
begin
WriteLn('Could not get temperature: ' + e.Message);
exit;
end;
end;
{ $DF == ° on LCD 20x4 charset. }
text := Format('Temperature %5.2f %sC', [temperature/100.0, '' + char($DF)]);
brickletLCD.WriteLine(3, 0, text);
text := StringReplace(text, char($DF), '°', [rfReplaceAll]);
WriteLn('Write to line 3: ' + text);
end;
end;
procedure TWeatherStation.Execute;
begin
ipcon := TIPConnection.Create;
while (true) do
begin
try
ipcon.Connect(HOST, PORT);
break;
except
on e: Exception do
begin
WriteLn('Connection Error: ' + e.Message);
Sleep(1000);
end;
end;
end;
ipcon.OnEnumerate := {$ifdef FPC}@{$endif}EnumerateCB;
ipcon.OnConnected := {$ifdef FPC}@{$endif}ConnectedCB;
while (true) do
begin
try
ipcon.Enumerate;
break;
except
on e: Exception do
begin
WriteLn('Enumeration Error: ' + e.Message);
Sleep(1000);
end;
end;
end;
WriteLn('Press key to exit');
ReadLn;
end;
begin
ws := TWeatherStation.Create;
ws.Execute;
ws.Destroy;
end.