With the new Protocol 2.0, it is possible to write programs that are resilient to outages, brief electricity cuts and similar things.
The general approach for such a program is shown below in pseudo code:
func enumerate_callback(...) {
configure_brick();
configure_bricklet();
}
func connected_callback(...) {
ipcon.enumerate();
}
func main() {
ipcon.enumerate();
while (true) {
if (brick_is_configured) {
do_something_with_brick();
}
if (bricklet_is_configured) {
do_something_with_bricklet();
}
}
}
Generally, you have to make sure that the configuration is done while the Bricks and Bricklets are enumerated. This ensures that the configuration (e.g. callback periods) is always there, even if a Brick or Bricklet was restarted and lost its configuration.
To do this, you can put the configuration code in the enumeration callback. You should also make sure, that a new enumeration is triggered if the TCP/IP connection was lost and then reconnected. If the connection was lost, a Brick or Bricklet might have been restarted in the meantime, so it needs to be reconfigured.
In the following you can find C# and Python source code for a program that displays the temperature on a LCD 20x4 Bricklet. This program should keep working if you reconnect/restart the Master Brick or if a Wi-Fi connection is lost. It is even possible to exchange the Temperature or LCD 20x4 Bricklet, since the program uses the UID from the enumeration.
1using Tinkerforge;
2
3// This class will use any LCD Bricklet and Temperature Bricklet that
4// are connected to the PC and display the temperature on the LCD.
5//
6// The program should stay stable if Bricks are connected/disconnected,
7// if the Brick Daemon is restarted or if a Wi-Fi/RS485 connection is lost.
8// It will also keep working if you exchange the Master or one of the
9// Bricklets by a new one of the same type.
10//
11// If a Brick or Bricklet loses its state (e.g. callback configuration)
12// while the connection was lost, it will automatically be reconfigured
13// accordingly.
14class ExampleRugged
15{
16 private static string HOST = "localhost";
17 private static int PORT = 4223;
18
19 private static IPConnection ipcon = null;
20 private static BrickletLCD20x4 lcd = null;
21 private static BrickletTemperature temp = null;
22
23 static void Main()
24 {
25 // Create IP Connection
26 ipcon = new IPConnection();
27
28 // Register IP Connection callbacks
29 ipcon.EnumerateCallback += EnumerateCB;
30 ipcon.Connected += ConnectedCB;
31
32 // Connect to brickd, will trigger cb_connected
33 ipcon.Connect(HOST, PORT);
34 ipcon.Enumerate();
35
36 System.Console.WriteLine("Press enter to exit");
37 System.Console.ReadLine();
38 ipcon.Disconnect();
39 }
40
41 // Callback updates temperature displayed on lcd
42 static void TemperatureCB(BrickletTemperature sender, short temperature)
43 {
44 if(lcd != null)
45 {
46 lcd.ClearDisplay();
47 string s = "Temperature: " + temperature/100.0 + (char)0xdf + "C";
48 lcd.WriteLine(0, 0, s);
49 }
50 }
51
52 // Callback switches lcd backlight on/off based on lcd button 0
53 static void ButtonPressedCB(BrickletLCD20x4 sender, byte button)
54 {
55 if(lcd != null)
56 {
57 if(button == 0)
58 {
59 if(lcd.IsBacklightOn())
60 {
61 lcd.BacklightOff();
62 }
63 else
64 {
65 lcd.BacklightOn();
66 }
67 }
68 }
69 }
70
71 // Callback handles device connections and configures possibly lost
72 // configuration of lcd and temperature callbacks, backlight etc.
73 static void EnumerateCB(IPConnection sender, string UID, string connectedUID,
74 char position, short[] hardwareVersion,
75 short[] firmwareVersion, int deviceIdentifier,
76 short enumerationType)
77 {
78 if(enumerationType == IPConnection.ENUMERATION_TYPE_CONNECTED ||
79 enumerationType == IPConnection.ENUMERATION_TYPE_AVAILABLE)
80 {
81 // Enumeration is for LCD Bricklet
82 if(deviceIdentifier == BrickletLCD20x4.DEVICE_IDENTIFIER)
83 {
84 // Create lcd device object
85 lcd = new BrickletLCD20x4(UID, ipcon);
86 lcd.ButtonPressed += ButtonPressedCB;
87
88 lcd.ClearDisplay();
89 lcd.BacklightOn();
90 }
91 // Enumeration is for Temperature Bricklet
92 if(deviceIdentifier == BrickletTemperature.DEVICE_IDENTIFIER)
93 {
94 // Create temperature device object
95 temp = new BrickletTemperature(UID, ipcon);
96 temp.Temperature += TemperatureCB;
97
98 temp.SetTemperatureCallbackPeriod(50);
99 }
100 }
101 }
102
103 // Callback handles reconnection of IP Connection
104 static void ConnectedCB(IPConnection sender, short connectReason)
105 {
106 // Enumerate devices again. If we reconnected, the Bricks/Bricklets
107 // may have been offline and the configuration may be lost.
108 // In this case we don't care for the reason of the connection
109 ipcon.Enumerate();
110 }
111}
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4from tinkerforge.ip_connection import IPConnection
5from tinkerforge.bricklet_lcd_20x4 import LCD20x4
6from tinkerforge.bricklet_temperature import Temperature
7
8# This class will use any LCD Bricklet and Temperature Bricklet that
9# are connected to the PC and display the temperature on the LCD.
10#
11# The program should stay stable if Bricks are connected/disconnected,
12# if the Brick Daemon is restarted or if a Wi-Fi/RS485 connection is lost.
13# It will also keep working if you exchange the Master or one of the
14# Bricklets by a new one of the same type.
15#
16# If a Brick or Bricklet loses its state (e.g. callback configuration)
17# while the connection was lost, it will automatically be reconfigured
18# accordingly.
19class ExampleRugged:
20 HOST = "localhost"
21 PORT = 4223
22
23 def __init__(self):
24 self.lcd = None
25 self.temp = None
26
27 # Create IP Connection
28 self.ipcon = IPConnection()
29
30 # Register IP Connection callbacks
31 self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE,
32 self.cb_enumerate)
33 self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED,
34 self.cb_connected)
35
36 # Connect to brickd, will trigger cb_connected
37 self.ipcon.connect(ExampleRugged.HOST, ExampleRugged.PORT)
38
39 self.ipcon.enumerate()
40
41 # Callback switches lcd backlight on/off based on lcd button 0
42 def cb_button_pressed(self, button):
43 if self.lcd:
44 if button == 0:
45 if self.lcd.is_backlight_on():
46 self.lcd.backlight_off()
47 else:
48 self.lcd.backlight_on()
49
50 # Callback updates temperature displayed on lcd
51 def cb_temperature(self, temperature):
52 if self.lcd:
53 self.lcd.clear_display()
54 s = 'Temperature: {0:.2f}{1:c}C'.format(temperature/100.0, 0xdf)
55 self.lcd.write_line(0, 0, s)
56
57 # Callback handles device connections and configures possibly lost
58 # configuration of lcd and temperature callbacks, backlight etc.
59 def cb_enumerate(self, uid, connected_uid, position, hardware_version,
60 firmware_version, device_identifier, enumeration_type):
61 if enumeration_type == IPConnection.ENUMERATION_TYPE_CONNECTED or \
62 enumeration_type == IPConnection.ENUMERATION_TYPE_AVAILABLE:
63
64 # Enumeration is for LCD Bricklet
65 if device_identifier == LCD20x4.DEVICE_IDENTIFIER:
66 # Create lcd device object
67 self.lcd = LCD20x4(uid, self.ipcon)
68 self.lcd.register_callback(self.lcd.CALLBACK_BUTTON_PRESSED,
69 self.cb_button_pressed)
70 self.lcd.clear_display()
71 self.lcd.backlight_on()
72 # Enumeration is for Temperature Bricklet
73 if device_identifier == Temperature.DEVICE_IDENTIFIER:
74 # Create temperature device object
75 self.temp = Temperature(uid, self.ipcon)
76 self.temp.register_callback(self.temp.CALLBACK_TEMPERATURE,
77 self.cb_temperature)
78
79 self.temp.set_temperature_callback_period(50)
80
81 # Callback handles reconnection of IP Connection
82 def cb_connected(self, connected_reason):
83 # Enumerate devices again. If we reconnected, the Bricks/Bricklets
84 # may have been offline and the configuration may be lost.
85 # In this case we don't care for the reason of the connection
86 self.ipcon.enumerate()
87
88
89if __name__ == "__main__":
90 ExampleRugged()
91 raw_input('Press key to exit\n') # Use input() in Python 3