Tidbyt Application Development Fundamentals
I recently purchased a Tidbyt second-generation smart display. I was immediately intrigued by the idea of creating custom applications that could present fun messages or images to those who either have to walk by my office or those I interact with in a Zoom call. The first idea that came to mind was to create a clock that rotated through different Spectro Cloud graphics. Why Spectro Cloud? That’s where I work, so having the logo displayed on my Tidbyt would be a fun way to suprise my coworkers during Zoom calls.
Below is a preview of the final product. The clock rotates through different Spectro Cloud graphics every 60 seconds and supports a 24-hour format.
I want to share the lessons I learned along the way. This post will help you create custom Tidbyt applications and share them with the world. There are so many possibilities with Tidbyt, and the official application store already has a wide variety of applications to choose from. Think of this article as a supplemental guide to the official documentation.
Where to Start?
The first step is to install Pixelet, the Tidbyt development tool. The Installing Pixlet guide provides detailed instructions on how to install Pixelet.
Once you have Pixelet installed, create a new project by issuing the following command:
|
|
You will be prompted for an application name, description, and summary. After you provide the information, Pixelet will create a new directory with the project files.
|
|
Pixelet will generate two new files, sup_world.star
and manifest.yaml
. The sup_world.star
file is where you will write your application code, and the manifest.yaml
file is where you will define the application metadata.
Below is the content of the sup_world.star
and manifest.yaml
files.
|
|
|
|
The next step is to start the application by running the following command:
|
|
Pixelet will start a local development server on http://localhost:8080
. You can preview the application in a web browser by navigating to http://localhost:8080
.
Press Ctrl + C
to stop the development server. If you are on a Mac, you can press Cmd + C
. You will start and stop the development server multiple times throughout the development process.
Core Concepts
Now that you have an application available and understand how to start the development server let’s explore the core concepts of Tidbyt applications.
Programming Language
Tidbyt applications are written in Starlark, which was designed to manage and maintain configuration for the Bazel build system. The syntax may look familiar if you have experience with Python.
Tidbyt used the Go implementation of Starlark.
The best resource I found for understanding Starlark’s capabilities is the Starlark Language Specification document. This document provides a comprehensive overview of the language and its capabilities, such as built-in functions, data types, and control structures. Do keep this document handy as you build your Tidbyt applications. I found myself referencing it multiple times throughout the development process.
Libraries
Tidbyt provides a set of libraries, also called modules, that you can use to build your applications. You can find the list of available modules on the Tidbyt Modules page. I would encourage you to review the modules page and to keep it handy as you build your applications. For example, the load("render.star", "render")
render module is the most important module you will use to build your applications. The rendering module provides a set of functions to create and render elements on the Tidbyt display.
Rendering Elements
You will use the render
module to create and display elements on the Tidbyt display. All Tidbyt applications must return a Root
element that contains the child elements you want to render. The Root
element is the root of the element tree and is the parent of all other elements. Only one Root
element is allowed per application.
When building my application, I struggled with understanding how to create and render elements. I couldn’t find the reference page for the render
module. I later learned that the Tidbyt Wiget page acts as the reference page for the render
module. The page provides information on using common elements such as Text
, Box
, Row
, and Column
, and many other elements that will help you paint your application on the Tidbyt display.
My best advice to you is to replace the return render.Root
function and experiment with different elements and the code snippets provided on the Widget page to observe how the different elements render on the Tidbyt display. The more you experiment, the more you will understand how to make your vision a reality.
|
|
For example, the code below creates a Column
element that contains three Box
elements. The Box
element is a simple element that renders a colored box on the Tidbyt display.
|
|
If you do this for all the widgets, you will better understand how to create and render elements on the Tidbyt display.
apps
directory.Images
You can include images with your application. When images are pre-loaded into the application, they must be base64
encoded. You can convert an image to base64 format using an online tool such as Base64 Image Encoder. Once you have the base64 image, you can use the render.Image
element to render the image on the Tidbyt display. The render.Image
element has a src
property that accepts the base64 image data.
You need to import the encoding/base64.star
module to decode the base64 image data. The encoding/base64.star
module provides a set of functions to encode and decode base64 data. You can use the base64.decode
function to decode the base64 image data.
Can I import a file instead of hardcoding the base64 image data?
Unfortunately, you cannot import an image file directly into the Tidbyt application. You must convert the image to base64 format and hardcode the base64 image data in the application code. The alternative is to download the image from a URL and pass it to the render.Image
element’s src
attribute.
Check out the Loveland Ski Area Webcams application for an example of how to download an image from a URL and pass it to the render.Image
element.
The code example below is from the Crypto Tracke guide. The majority of the code is omitted for brevity. The code snippet shows how to decode the base64 image data and pass it to the render.Image
element. Keep in mind that the image must be either a PNG, GIF, or JPEG image.
|
|
Size
You need to be mindful of the size of the image you render on the Tidbyt display. The Tidbyt display can display 64x32 pixels. If you render an image larger than 64x32 pixels, the image will be cropped. It may take a few tries to get the image size right. I used the free image editing tools from Pinetools to re-size images down to the correct size for my application.
Pixelate
A common mistake when building a Tidbyt application is assuming you have to pixelate the image before rendering it on the display. The Tidbyt display is already pixelated, so you do not need to pixelate the image before rendering it on the display. If you pixelate the image before rendering it on the display, the results may differ from what you expect. Instead, focus your attention on the size of the image and ensure its quality.
Animations
Tidbyt applications support animations. You can animate elements using the render.Animation
element. The animate
element provides a set of methods that you can use to manipulate the element’s behavior. The list of available methods is on the Tidbyt Animation page.
Fonts
Tidbyt supports eight different fonts that you can use in your applications. When using the render.Text
function, you can set the font
property to one of the eight available fonts. Specify the font by its name. For example, to use the 5x8
font, set the font
property to 5x8
.
|
|
Review the Fonts in Pixlet page for more information on the available fonts.
Architecture
Tidbyt has a small section in its documentation where Tidby Architecture is explained. This section is sparse, but it conveys important information such as the display size, caching behavior, secrets management, failure handling, and performance profiling. However, as you comb through the documentation, you will find that the information is scattered throughout the site. Below are some key points to keep in mind as you build your applications.
-
The default application cycle speed is 15 seconds. This means that Tidbyt will display a different application for most end users every 15 seconds. The user can change this value, but it is important to remember that the default value is 15 seconds. In other words, consider the 15-second cycle when designing your applications. If you have an animation that lasts longer than 15 seconds, the animation will be cut off when the application cycle changes, unless the user has changed the cycle speed, or you use the
show_full_animation
property to override the user’s configuration. Check out the App cycle speed page to learn more about the application cycle speed. -
If you use the random module, keep in mind the random seed is updated every 15 seconds. This means that if you use the random module to generate random numbers, the numbers will change every 15 seconds.
-
If you use caching, remember that the cache is global and unique per application, not per installation. All Tidbyt applications share the same cache. This means that if you cache a value in your application, then all other instances of your application will use the same cached value. This is important to keep in mind when building applications that rely on caching.
-
Tidbyt pushes a WebP image file to the display. This image file is sent to the display from their servers. During local development, this is simulated through Pixelet. The image file is generated by your local server, which you can preview in a web browser. If you are creating applications where behavior changes, say a clock application that rotates images every 1 minute. You will not observe the change while the local server is active. The reason that Tidbyt and Pixlet send the image file once and only once to the display. In the real world, the application image file is sent from Tidbyt servers to the device right before the application cycle is about to complete for the current application. So, if you expect a new image to be displayed every 1 minute, you must start and stop the Pixelet server to observe the change. In other words, to get a new image to display in development, you must trigger the change with a server restart. There is extensive discussion about this behavior in the following GitHub issue with potential workarounds.
-
The screen size is 64x32 pixels.
Schema Configuration
Each Tidbyt application can accept configuration values from the user. The configuration values are set in the Tidbyt application settings and passed to the main
function as a config
object.
The config
object will contain any schema fields defined in the schema object.
Using the example code from earlier, a function named get_schema
returns a schema object that defines the configuration fields that the user can set in the application settings. The schema object contains a list of fields that the user can set. Each field has an id,
name,
desc,
and icon
property. The id
property is the unique identifier for the field. The name
property is the field’s name displayed in the application settings. The desc
property is the description of the field that is displayed in the application settings. The icon
property is the icon that is displayed next to the field in the application settings.
|
|
Each schema field can support different types of input. For example, the schema.Text
field supports text input, the schema.Toggle
field supports a toggle switch, and the schema.Option
field supports a dropdown menu. The schema object also supports default values for each field. The default value is the value that is set when the user installs the application. The user can change the value in the application settings.
You can also create more advanced workflows through some of the built-in schema fields. For example, you can trigger an OAuth flow to authenticate the user, get the current geolocation, or use dynamic fields to autogenerate values such as an ID.
For a real-world example, check out the Spectro Cloud clock application schema. Users can choose between the following options:
- Use a 12-hour format or 24-hour format.
- Enable or disable the clock.
Below is the schema configuration for the Spectro Cloud clock application.
|
|
Inside the main
function, you can inspect the config
object to get the configuration values the user sets.The config
object contains the configuration values set by the user and other important metadata, such as the timezone.
The config
object has a set of methods that you can use to get the configuration values. For example, you can use the config.get
function to get a configuration value by specifying its id
. The config.get
function returns the configuration value as a string.
If you know the field type, you can use specific functions such as config.bool
to get a boolean value, or config.str
to get a string value.
|
|
Publish Application
If you aspire to share your application with the world, you can publish it in the Tidbyt application store. To publish an application, you must fork the Tidbyt Community repository. Once you have the repository forked and cloned to your local machine, you can create a new git branch and add your application to the apps
directory.
Tidbyt has detailed instructions on how to publish an application in the Publishing Apps guide. Check out past Pull Requests (PR) from the community repository to get an idea of how to structure your PR and what information to include in the PR description. Feel free to check out the PR for the Spectro Cloud clock application.
Additional Help
If you need additional help, you can reach out to the Tidbyt community on the Tidbyt Discord channel. You can also use the Tidbyt Forum to ask questions and get help from the community.
Closing Thoughts
Building applications for Tidbyt can be a fun and rewarding experience. The possibilities are endless, and the community is constantly developing new and innovative applications. Use the knowledge provided in this article to start building your own applications. Remember to experiment with different elements, review the available modules, and check out the Tidbyt community repository for inspiration.
Spectro Cloud Clock App