A small demo in Python


Introduction

Writing a FreeLCD client is not that hard, and on this page we'll write a simple one from scratch in Python. The only thing it does is display the current time.

(Please make sure you are running flcdd version 0.3 or newer, and that the server was configured with '--enable-curses'. If the server was built without curses support, you will need a real display.)

Configuring the daemon

We use the following configuration file (flcdd.xml):

  <?xml version="1.0" encoding="utf-8"?>
  <flcdd-config>
    <output name="display">
      <driver name="naive">
        <width>10</width><height>1</height>
      </driver>
      <backend name="curses">
        <width>10</width><height>1</height>
      </backend>
    </output>
  </flcdd-config>

If you have a real display device, you can select a matching driver (e.g. 'cfontz') and backend (e.g. 'serial'). But the curses output should work for everyone. If you use curses, the daemon must be started with the --foreground flag, otherwise it cannot use the terminal. For a CrystalFontz serial device on COM1:, the configuration file looks like this:

  <?xml version="1.0" encoding="utf-8"?>
  <flcdd-config>
    <output name="display">
      <driver name="cfontz">
        <width>20</width><height>4</height>
      </driver>
      <backend name="serial">
        <device>/dev/ttyS0</device>
        <baudrate>9600</baudrate>
      </backend>
    </output>
  </flcdd-config>

Writing the client

The Python script is nothing fancy either:

#!/usr/bin/python

import sys
import time
from socket import *

def main(args):
        s = socket (AF_INET, SOCK_STREAM);
        s.connect (("localhost", 8783))
        layout = open ("layout.xml", "r")
        content = layout.readlines()
        for line in content: s.send (line)
        layout.close()

        while 1:
                time.sleep (1)
                s.send (time.strftime ('<data name="chronos">\
                        <value name="time"><hrs>%H</hrs><min>%M</min>\
                        <sec>%S</sec></value></data>'))
        
if __name__ == '__main__':
        sys.exit (main (sys.argv))

The client first opens a TCP/IP socket to localhost, port 8783. If your daemon is running on another machine, you should change 'localhost' to that machine's name. It then sends the contents of a file 'layout.xml' through the socket. Indeed, that's the layout of the screen, and we will take a look at that later on. Finally, the client enters an infinite loop, where it sends new values for the 'time' field every second.

The layout

To keep things simple, the file 'layout.xml' only has one row with one field:

  <screen name="chronos">
    <layout>
      <row><field type="time" name="time"/></row>
    </layout>
  </screen>
  <screen name="chronos">
    <layout>
      <row><field type="time" name="time"/></row>
    </layout>
  </screen>

What it looks like

Here's a screenshot from the same setup, but with a slightly different daemon configuration. The curses screen is now 7 characters wide, and the seconds field is left out to make it fit.

Scripts

Version 0.3 allows the user to extend data representations by adding their own Scheme scripts. I have written two of them for testing purposes: one of them shows the time in 12-hour format, the other one shows the time in beats. They can be found in the scripts/ directory. The user can select one of these formats as the default, but the client can also tell the server that a certain format is preferred by adding an attribute to the value tag.

The file layout.xml is extended. We add a top row with a label, and another time field with a custom format ('beats') inside the second row. Also, we add a 'halign' attribute to both time fields, so they become horizontally centered.

  <screen name="chronos">
    <layout>
      <row>
        <label name="header">Python clock</label>
      </row>
      <row>
        <field halign="center" type="time" name="time"/>
        <field halign="center" type="time" name="time2" format="beats"/>
      </row>
    </layout>
  </screen>

The last step would be to add the field 'time2' to the Python script. Both time fields have the same value, but a field's name must be unique within the layout. (Then again, it does not happen often one wants to display the exact same data more than once on the same screen. So normally this is not a nuisance.)

Here's a photo of what it should look like:

Files


Updated: $Date: 2004/06/24 09:55:05 $ $Author: unicorn $