Basic Display Stream Example
Use WebSockets to send data for display on an LED Matrix.
- SDK directory:
apps/basic/display_stream
- Zentri App Store:
ZENTRI-BADISPSTREAM
API Features Demonstrated
- App Settings API
- HTTP Webserver Stream API
- Network Interface API
- Command API Settings
- Utilities/JSON Parser
- LED Matrix 8x8 Library
Platforms
This app works on:
- AMW004 - Zentri Mackerel evaluation board. See Connecting a Zentri AMW004 to a Zentri ASG001 Backpack
- AMW106 - Zentri Moray evaluation board
Requirements and Prerequisites
Requires a ZentriOS evaluation board and an Adafruit 8x8 LED Matrix, such as provided with the Zentri ASG001 Monitor Backpack.
This app assumes your ZentriOS device is set up with the credentials to join your local network.
Resources
The file settings.ini is packaged with the zap and downloaded to the device.
The script websocket_client.py must be run on a computer connected to the same network as the device.
The script is in the ZentriOS_SDK project folder:
ZentriOS_SDK/apps/basic/display_stream/websocket_client.py
Description
This app demonstrates how to send and receive data via WebSockets to a ZentriOS device. The python script websocket_client.py, connects to the ZentriOS web server and sends a single frame of data. The frame is written to the LED Matrix frame buffer. It appears as a diagonal line on the LED Matrix display.
The python script reads back the data from the frame and displays it as output.
Usage Instructions
The websocket_client.py
python script requires the Python 2.7 websocket-client
module. This is not part of the standard installation and may have to be installed. To install, you can use the command line:
pip install websocket-client
Open a ZentriOS serial terminal to the device. See Getting Started, Opening a ZentriOS Terminal.
This app assumes your ZentriOS device is set up with the credentials to join your local network. If you have not already set up network credentials, on the ZentriOS terminal, run the commands:
network_up -s
save
See the Wi-Fi Command API documentation for network_up and save.
After building, downloading and running the app to the ZentriOS device, the app displays on the ZentriOS terminal:
> Registering stream callbacks
Toggling network to start servers
Display stream app running...
Available routes:
ws://display_stream.local/zapstreams/frame
ws://display_stream.local/zapstreams/flush
Run the script websocket_client.py on a computer connected to the same network as the ZentriOS device. The script can be found in the ZentriOS_SDK project apps folder:
ZentriOS_SDK/apps/basic/display_stream/websocket_client.py
The app displays a message similar to the following on the ZentriOS terminal:
[2015-11-24 | 03:46:35: Opened: 0]
disconnecting: 0
[2015-11-24 | 03:46:38: Closed: 0]
> disconnected: 0
The LED Matrix display shows a diagonal line determined by the data sent from the python script.
The python script outputs the frame value it reads back from the ZentriOS device:
Received '{u'data': u'[128,64,32,16,8,4,2,1]', u'stream': u'frame'}'
WebSocket Streams and Data Exchange
The app provides two WebSocket streams that are served by the ZentriOS webserver.
ws://display_stream.local/streams/frame
is used to send data for display (and read data on display)ws://display_stream.local/streams/flush
is used to flush the display
Data exchange between the client and server is based on a simple protocol in JSON format. The protocol is implemented by callbacks determined by the name of the WebSocket stream on which the message is sent.
Data Exchange Protocol
{
'stream' : <stream name>,
'method' : <method name>,
'data' : <data array>
}
where:
<stream name>
is the stream accessed by the client'frame'
used to write data to the LED Matrix or read the data currently being displayed by the LED Matrix'flush'
used to clear data currently being displayed by the LED Matrix
<method name>
is the method requested by the client'put'
may be used with either stream to update the display.'get'
may only be used with the'frame'
stream to read the data currently on display.
<data array>
carries data for display on the LED Matrix and is required when the'put'
method is used. The<data array>
should be set to null''
when the'flush'
method is used. The'data'
field can be omitted entirely when the'get'
method is used. Data is formatted as a JSON array e.g.[128, 64, 32, 16, 8, 4, 2, 1, 100]
.
The settings.ini
configures the ZentriOS Web Server with a CORS setting allowing resource access from external clients. CORS is required since the Python websocket client is not served by the ZentriOS (origin) device. The ZentriOS network discovery (mDNS) service is also configured to enable the Python websocket client to find the device on the network using a network name (rather than an IP address).
See the following links for additional information about the ZentriOS services used in this app.
Implementation
zn_app_init
- zn_load_app_settings loads the variable configuration in the settings.ini file.
- led_matrix8x8_init and led_matrix8x8_animate initialise the LED Matrix array and start the animation, which as yet has no frames to display.
- The calls to zn_hs_stream_register_callback set up HTTP Server stream callbacks for the frame read/write (
frame_stream_callback
) and flush (flush_stream_callback
) operations. The streams are named "frame" and "flush" and have corresponding URIs as reported in theAvailable routes:
log message. - zn_network_restart brings the network down and back up to start the HTTP and WebSocket servers.
frame_stream_callback
put
:HS_STREAM_READ
- In the data exchange protocol message sent from the Python script, the
put
method corresponds to theHS_STREAM_READ
method callback argument. - In response to the
put
, the callback reads the data with zn_hs_stream_read. - json_parse_context_init initializes JSON parsing.
- json_parse_chunked parses the json data.
- json_context_get_token retrieves a token.
- When the token is identified as part of a frame, the app allocates a frame and copies the frame data from the parsed json.
- led_matrix8x8_push_frame pushes the frame to the device LED matrix. At this point the diagonal line is displayed.
- In the data exchange protocol message sent from the Python script, the
get
:HS_STREAM_WRITE
- In the data exchange protocol message sent from the Python script, the
get
method corresponds to theHS_STREAM_WRITE
method callback argument. - In response to
get
, the callback reads the data from the current frame with led_matrix8x8_get_current_frame. It copies it to a buffer and writes the buffer to the WebSocket stream. At this point the python script receives the data and outputs it.
- In the data exchange protocol message sent from the Python script, the
flush_stream_callback
put
:HS_STREAM_READ
- In the data exchange protocol message sent from the Python script, the
put
method corresponds to theHS_STREAM_READ
method callback argument. - In response to
put
, the callback calls led_matrix8x8_flush_frames to flush frames.
- In the data exchange protocol message sent from the Python script, the
Source
See:
See also: