A little while back, one of my colleagues at TAF came to me with an interesting challenge. He had been assigned the task of making a production application raise a visual and audible alarm in response to invalid actions on the part of the user. It doesn’t seem like that hard a problem until one realizes that our applications are actually running in XWindows sessions on an AIX server. This means that the running application thinks that its environment is the AIX server, and it knows nothing about the machine actually displaying the user interface.
In the past, this sort of requirement was handled by using a Programmable Logic Controller (PLC), and running conduits and wires from the PLC to the location where the output was wanted. This gets the job done, but it’s expensive to install and move, and requires a lot of lead time if a change in location is needed. On top of that, one also has to involved the services of a PLC programmer, and it may even require the acquisition of an additional PLC if a free port is unavailable on one of the existing alarm-capable PLCs. We needed to come up with a cheaper, more flexible solution.
At first, it was a bit of a head scratcher, but, as it turns out, an application running under XWindows can get one vital piece of information about its environment: the IP address of the machine actually providing the display. In VA Smalltalk, the command “‘DISPLAY’ abtScanEnv” will give you a response of the form ‘xxx.xxx.xxx.xxx:0.0’ where anything up to the colon (:) is a host name or IP address, and anything after is the XWindows display number. In our case, we’re only concerned with the host name or IP address. If the XWindows display is actually running on the same machine, the host name will be blank, and you’ll get back something like “:0.0”.
Knowing how to get to the physical computer, we can now think about what to do there. While I have complete control over how the client machines are loaded, it’s generally preferable to keep the installed software to a minimum. Everything I needed to do could be done from a UNIX shell prompt, so using some shell scripts seemed the best answer. Modern Linux implementations make it easy to set up TCP daemons using xinetd, so I set up a listener on a TCP port that invoked a simple script.
My Smalltalk program opens the port on the client machine using Totally Objects SocketSet, writes a value to the port, and closes it again. On the client machine, the script reads a line of input from STDIN, and uses that input to invoke an appropriate alarm script. You could do the same thing with VA Smalltalk’s socket support, but if you value your time at all you’ll quickly come to appreciate the benefit of Totally Objects’ product.
This has been working quite well, but a new curve was thrown at me recently. Instead of just firing off an audible alarm, the users wanted the computer to send a voice instruction. Since the number of instructions was fairly small, it wouldn’t have been impractical to record sound files and play the correct one based on an alarm number, but it wouldn’t scale well and keeping clients up-to-date would start to become a challenge.
Instead, a little research turned up the fact that our preferred Linux distribution, Red Hat, includes a speech synthesis system, Festival, with text-to-speech capabilities. Even better, Festival can be run as a daemon that listens on a TCP port. A little bit of shell programming later, and Festival was wrapped as a Linux service. Another bit of Smalltalk code using Totally Objects SocketSet was used to pass text to that service, and we now have generic text-to-speech capability in our application.
Certainly Smalltalk could have been used to implement most of the daemon side of these alarms as well, but some scripting would still have been required. Using the approach we did allows us to keep the installation package light and minimize the skill set required to maintain it in the future. Moreover, testing, troubleshooting and modifications can be done easily from a command prompt the client machine which has a lot of value when you’re trying to fix a problem in a factory a long way from your development environment!