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