Directory of Sample Code
|
|
Site and Mailing List Search:
|
This is a collection of EmStar code samples that are very useful for cutting and pasting. Can't remember the usual arguments to an options structure or a callback function, and too lazy to look it up? Me too! So just cut and paste from these samples!
Contents:
Timers and Timing
Link Device Clients: Sending and Receving Packets
Status Devices
Query Device
Live Command Inputs to EmStar Processes
Status Clients
Client-configurable Status Devices
Locking Query Servers
Query Clients
Observing Neighbor and Routing Tables
Providing and Using Sensor Data
Creating a Socket Server
Using and Configuring a Serial Port
Parsing Command Line Options
Emstar Application Initialization
Timers and Timing
How to run timer:
$ obj.i686-linux/skeletons/timer Sun Oct 10 12:03:45.445: cb_func: 4 more timeouts Sun Oct 10 12:03:46.455: cb_func: 3 more timeouts Sun Oct 10 12:03:47.465: cb_func: 2 more timeouts Sun Oct 10 12:03:48.475: cb_func: 1 more timeouts Sun Oct 10 12:03:49.485: cb_func: 0 more timeouts Sun Oct 10 12:03:50.495: cb_func: No more timeouts ^C
-
Setting a timer to fire every N milliseconds: timer.c:72 triggered_status.c:255
-
Setting a one-shot timer to fire in N milliseconds (one-shot nature depends on the return value of timer handler function): query_example.c:186
-
Timer callback examples: timer.c:50 query_example.c:105 triggered_status.c:105
-
Implementing a simple refractory timer: read_packets.c:72
-
Getting uptime information: query_example.c:208
Link Device Clients: Sending and Receving Packets
coming soon.. how to run this
-
Configuring an event to receive packets from a link device: read_packets.c:145
-
Writing to a link device: (Given an event that is receiving packets from the link.) read_packets.c:78
-
Implementing a --uses <link> command-line option: read_packets.c:133
-
Packet event callback: read_packets.c:53
Status Devices
How to run the triggered_status example program.
### Run trig_status $ obj.i686-linux/skeletons/trig_status & Sun Oct 10 12:04:58.307: main: Triggered status example starting ### Cat the device a few times. ### You should notice the status report changes every second $ cat /dev/samples/trig The current state is: Crash! $ cat /dev/samples/trig The current state is: Crash! $ cat /dev/samples/trig The current state is: Bam! ### Use echocat to see the state change periodically: $ obj.i686-linux/bin/echocat -w /dev/samples/trig The current state is: Bam! The current state is: Bash! The current state is: Crash! The current state is: Boom! Sun Oct 10 12:05:46.613: echocat_shutdown: echocat shutting down ### Use echocat to observe the output as binary: $ obj.i686-linux/bin/echocat -w -b -H /dev/samples/trig 1097435158.700440: 4 bytes 0000: 00 00 00 00 .... 1097435160.615427: 4 bytes 0000: 01 00 00 00 .... 1097435162.629647: 4 bytes 0000: 02 00 00 00 .... 1097435164.636950: 4 bytes 0000: 03 00 00 00 .... 1097435166.646140: 4 bytes 0000: 04 00 00 00 .... Sun Oct 10 12:06:07.086: echocat_shutdown: echocat shutting down
-
Configuring a Status device: triggered_status.c:236
-
Implementing a printable handler for a status device (presents human-readable output to the user): triggered_status.c:153
-
Implementing a binary handler for a status device (presents a binary output to another program): triggered_status.c:133
-
Triggering a client to reread on a state change: triggered_status.c:113
Query Device
How to run the query_example program.
### Run query_example, no args. $ obj.i686-linux/skeletons/query_example & Sun Oct 10 12:07:14.147: main: Starting up query_example ### Then cat /dev/samples/query for more information $ cat /dev/samples/query Usage for this example query device. Accepts commands: reply=<reply text> delay=<response delay in ms> try the following: echocat /dev/samples/query test echocat /dev/samples/query delay=2000 echocat /dev/samples/query delay=2000:reply=this is my reply echocat /dev/samples/query " " NOTE: echocat is in obj.<platform>/bin ### Try those suggestions $ obj.i686-linux/bin/echocat /dev/samples/query test Sun Oct 10 12:07:56.444: sample_process: In process callback.. command string is 'test' Sun Oct 10 12:07:56.444: sample_process: unknown key: test Immediate response: 'No reply requested' Uptime is 42 seconds $ obj.i686-linux/bin/echocat /dev/samples/query delay=2000 Sun Oct 10 12:08:33.114: sample_process: In process callback.. command string is 'delay=2000' Sun Oct 10 12:08:33.114: sample_process: In process callback.. delaying for 2000 ms Sun Oct 10 12:08:35.125: complete_transaction: In timer callback.. Delayed response (2000 ms): 'No reply requested' $ obj.i686-linux/bin/echocat /dev/samples/query delay=2000:reply=this is my reply Sun Oct 10 12:09:00.772: sample_process: In process callback.. command string is 'delay=2000:reply=this is my reply' Sun Oct 10 12:09:00.772: sample_process: In process callback.. delaying for 2000 ms Sun Oct 10 12:09:02.775: complete_transaction: In timer callback.. Delayed response (2000 ms): 'this is my reply' $ obj.i686-linux/bin/echocat /dev/samples/query " " Sun Oct 10 12:09:21.902: sample_process: In process callback.. command string is ' ' Sun Oct 10 12:09:21.902: sample_process: unknown key: Immediate response: 'this is my reply' Uptime is 127 seconds
-
Configuring a Query device: query_example.c:305
-
Implementing a usage message for a Query Device: query_example.c:217
-
Implementing a transaction with a delayed completion: query_example.c:185 query_example.c:117
-
Parsing command strings: query_example.c:155
Live Command Inputs to EmStar Processes
coming soon.. command device.. status write callback.. more parsing
Status Clients
coming soon..
Client-configurable Status Devices
coming soon...
Locking Query Servers
coming soon..
Query Clients
coming soon..
Observing Neighbor and Routing Tables
coming soon..
Providing and Using Sensor Data
coming soon..
Creating a Socket Server
The libevent library contains various helper functions for interfacing I/O to the EmStar event system. Among other things it provides a fully non-blocking sockets library that enables both creating TCP servers and clients. There is a sample program libevent/util/serial_server.c that is a very simple example of how to create a socket server. This program opens a serial port, configures it, and exposes the raw byte stream via a tcp server.
How to run serial_server:
$ obj.i686-linux/libevent/serial_server --device /dev/ttyS0 --port 8001 --baud 57600 & Thu Jun 30 09:22:14.568 2005: main: serial_server (connected to '/dev/ttyS0', exposed on port 8001) starting...
Then, you can use telnet to connect to that port:
$ telnet localhost 8001 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. ....now you can read/write to the serial port
This program supports multiple clients; all received data will be copied to each, but there is no locking to prevent writers from interleaving their data.
Looking at the code:
-
During initialization, configure the server port by defining the port (in host byte order) and handler functions for processing the connections: serial_server.c:213
-
Then, call the event constructor, saving an event reference. You'll need that reference to access the clients, and to control or close the port: serial_server.c:222
-
In this case, we have a fairly simple problem so all we do is receive data from any client connection, and dump it to the serial port. Our handler gets a buf_t containing new data and writes it to an already-opened serial port using write_to_fd(), a helper function in libmisc. After writing, it frees the buffer, and returns EVENT_RENEW to await more data. serial_server.c:116
-
When data comes in from the serial port, we need to pass it off to each of the clients (peers). We do this by iterating through the peers, and calling a send function for each. These send calls will never block; they buffer any data you provide. Note that the send call will NOT free that buffer we pass in; we must do that. serial_server.c:91
For further information:
-
There are many more additional callbacks to control the behavior of the server (on accept, close, write queue drained, etc.) event_tcp_server.h:50
-
There are several accessors for getting peer information, including getting and setting a per-peer and per-server private data pointer. event_tcp_server.h:75
-
The event_tcp_server library also supports client connections, including a data structure for managing collections of clients. event_tcp_server.h:113
Using and Configuring a Serial Port
There are several helper functions in libmisc to open and configure a serial port. The serial_server utility program provides a simple example of these functions. See Creating a Socket Server for instructions on running an interacting serial_server.
-
First, use open() to open the serial port: serial_server.c:189
-
Next, configure the baud rate and whether hardware flow control is desired: serial_server.c:195
-
You may want to flush the input buffer; it's also usually a good idea to set the file descriptor non-blocking to avoid getting into cases where the port blocks and your server becomes unresponsive. serial_server.c:198
-
Finally, use g_event_add() to register this file descriptor with the event system: serial_server.c:205 This references an event handler at: serial_server.c:60 The event handler will check the condition (INPUT if readable, or EXCEPT if the device was unregistered under you) and if necessary will read and process more data from the serial port.
Parsing Command Line Option
EmStar provides some useful helper functions for parsing command line options and providing standard usage information. All EmStar programs support a certain set of standard command line options that are parsed by the call to misc_init(). These include options that configure various simulation parameters (optional node and group ID overrides) and a host of other standard options.
You can parse additional options after that call using a suite of functions in libmisc/misc_opt.h. These options parse "out" options, meaning that they remove them from the argument list. This means they can be parsed in any order and by several different non-coordinating components. There are various functions for parsing strings, "switches", integers, etc.
An example of the use of these functions can be found in serial_server. Instructions for running the program are above in Creating a Socket Server.
-
Serial server calls misc_init() to process common EmStar options: serial_server.c:172
-
Serial server uses several option parsing functions to parse its options. misc_args_remain() checks for remaining unparsed args and reports on what they are. serial_server.c:174
-
In case of a request for help or an error in the argument parsing, serial server uses the misc_print_usage() to print out a usage statement. This helper automatically includes usage on the various standard options, and appends your custom summary string (second argument) and argument description (third argument): serial_server.c:147
Emstar Application Initialization
When you write a new EmStar application, there is a standard form you use to construct the main() function. We will show this form using the example of serial_server (see instructions in Creating a Socket Server to run it):
-
Call misc_init(). This performs many important inializations. serial_server.c:172
-
Parse command line arguments. serial_server.c:174
-
Perform application inialization and register any intial events. Alternatively, you may delay these sorts of initialization using a timer. serial_server.c:188
-
Connect back to emrun. This enables emrun to control your applications logging level, request graceful shutdown, monitor responsivenes, etc. serial_server.c:229
-
Enter the "main loop". From here all activation is via event handler callback functions. serial_server.c:237