Tutorial - Rugged Approach – Tinkerforge

- Getting Started
  - Primer
  - Tutorials
    - First Steps
    - Rugged Approach
      - C#
      - Python
    - Authentication
    - RED Brick
  - FAQ
- Hardware
  - Bricks
  - Bricklets
  - Master Extensions
  - Power Supplies
  - Accessories
  - Timeline
- Software
  - Brick Daemon (brickd)
  - Brick Viewer (brickv)
  - API Bindings
  - Firmwares and Plugins
  - Device Identifier
  - Source Code and Bug Tracking
  - Programming Interface
- Starter Kits
  - Weather Station
  - Hardware Hacking
  - Server Room Monitoring
  - Blinkenlights
  - Internet of Things
  - Camera Slider
- Embedded Boards
  - Raspberry Pi
- Specifications
  - Technical Data
  - TCP/IP Protocol
  - Modbus Protocol
  - Wireshark Dissector

# Tutorial - Rugged Approach

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 looks as follows (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 configuration is done while the Bricks and Bricklets are enumerated. This ensures that the configurations (e.g. callback periods) are 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 is 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 source codes for a program that shows 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.

## C#

Download (ExampleRugged.cs)

      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();
        }
    }

## Python

Download (example_rugged.py)

     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

The content of this page is licensed under Creative Commons Attribution 3.0 Unported License.