Project Awesome project awesome

OATIS

Server Based Studio Clock and Tally system, supporting messaging, physical GPI's and OSC triggering.

Package 4 stars GitHub

OATIS V2 - On Air Tally Indicator System

logo

Overview

OATIS is a tally indicator system for use in Radio and TV that is platform agnostic, designed to run on Linux and Mac OSX, support is not gauranteed for Windows, as it has not currently been tested (I don't own a Windows PC...).

Designed to operate in a server-client model, multiple displays can be centrally managed using a lightweight server application and configuration tool.

Screenshot 2026-02-02 at 08 37 50

Features

Physical and Network triggers:

  • Support for physical GPI's and GPO's using the Arduino Uno R3 and Arduino Mega, giving you upto 52 inputs / outputs.
  • Multiple Arduinos can be connected to the server, giving scope for increased I/O if needed.
  • Support for network input and output triggers using the OSC Protocol, both UDP and TCP.
  • Inputs can be linked to display indicator lamps to show the state of the input trigger.

Logic

  • Group Physical and Network inputs into a Logical Input using conditions: AND, NAND, OR, NOR.
  • Use a single Logical Output to trigger multiple physical or network outputs.

Customizable displays:

  • Display Builder allows custom displays to be built and applied to multiple clients.
  • Currently available display widgets:
    • Studio Clock
    • Analogue Clock
    • Digital Clock
    • Indicator Lamp
    • Static Text
    • Static Image
    • Stacked Image (Changable via an OSC trigger)
    • Date-Logo-Location Top-Banner
    • More to be added in the future, suggestions are welcomed!
  • Multiple clocks can be displayed at once with the option to change the timezone depending on location.
  • Sync your client device via NTP for accurate time.
  • Add your Own Logo to client displays.

Messaging:

  • Client displays can be used to show short messages by way of a scrolling ticker at the top of the screen.
  • The background colour of each message can be chosen by the user.
  • Clients are segregated into Logical Messaging groups for sending messages to a group of clients.
  • Message console application for sending messages to clients.
Screenshot 2026-01-16 at 18 20 20

Remote management of Display Devices:

  • Device Display settings can be changed remotley using the configuration tool.
  • Display templates, image files and config are sent to client devices over the network.
  • Devices can be identified using the configuration tool, bringing up a device information screen showing the clients configuration and IP information.

Setup

This version of OATIS is built to run on Python 3.11.8.

Install the Dependencies in the requirements.txt file

pip3 install -r requirements.txt

Install SQlite

sudo apt-get install sqlite3

Microcontroller Setup

If you are using Physical GPI's the Arduino needs to be flashed with the Firmata code to enable communication via serial with OATIS. See below for steps how to do this.
The Firmata protocol is used to communicate between OASTIS and the Arduino. Arduino R3 and Arduino Mega are supported only.

Open Arduino IDE, navigate to Tools > Manage Libraries

logo

In the search box type "firmata express"

Select version 1.2.0 and hit install, you will probably get a prompt asking if you want to install with dependencies, select yes!

logo

Open Arduino IDE and navigate to File > Examples > FirmataExpress > FirmataExpress

logo

Upload the Sketch to your Board, you are now ready to use the microcontroller with OATIS.

Build the Database - It's not as scrary as it sounds...I promise!

OATIS will complain if it does not find a valid database file. The database needs to be built using the config tool.

Screenshot 2026-01-10 at 07 43 19

Launch the Config tool using the main_config_tool.py script.
A prompt will show on the first run as below, select yes. The required tables and default data the application needs to run will be built and added.

Screenshot 2025-09-22 at 21 47 50

Config tool will then continue to launch.

OATIS Configuration Tool Tabs

  • Image Store - Used for uploading images to the database to be diaplayed on client devices.
  • Device Config - Used for adding a client device to the system, assiging a Message Group and Display Instance.
  • GPIO Config - Used for configuring Arduino Microcontrollers, their COM port and pin configuration.
  • Input Triggers - Configuration of Physical and Network Inputs.
  • Input Logics - Provide a method of grouping multiple Physical and Network Input Triggers using the logic functions: AND, NAND, OR, NOR.
  • Output Logics - Provide a method of grouping multiple Physical and Network Output Triggers, providing the capability to trigger multiple outputs from a single input.
  • Output Triggers - Configuration of Physical and Network Outputs.
  • Display Templates - A tool for building client display layouts.
  • Display Instances - Provides a method of configuring a Display Template for use on a client device.
  • Messaging Groups - Provides a method to create Logical Groups of devices messages can be sent to.
  • Server Config - Used for initialising the Database, Backup and Restore of configuration and setting the IP Address of the Server.

Set Server IP Address

Launch the Config tool using the main_config_tool.py script, navigate to the Server Config tab.
Select IP Settings.
Use the dropdown to select the interface you would like to use for server communication. Each entry in the dropdown will be an ip address of an active interface on the machine.
A loopback IP address will also be shown which can be used for system testing if you want to run the client and server on the same machine.

Screenshot 2026-01-10 at 07 48 25

Once selected hit save.

Adding Microcontrollers

Navigate to the GPIO Config tab.
Hit Add Controller.
Enter a name for the controller.
Enter the location of the controller, e.g. equipment room.
Select which type of Arduino you are using.
Use the COM port dropdown to select the USB-Serial port to use to communicate with the Arduino.

Screenshot 2026-01-10 at 07 54 54

Once the type of Arduino has been selected, the Pin Mode Configuration should load.
Here you can specify which Arduino pins to use as Inputs, Outputs or Disable.

Screenshot 2026-01-10 at 07 58 02

Once done, hit save.

PLEASE NOTE: Any changes to the Port, or Pin configuration will require a server restart to push the latest configuration to the Arduino.

Creating Message Groups

Message groups are used to logically group client devices when sending messages to them.
Go to the Messaging Groups tab, enter a name for your message group and hit save.

Screenshot 2026-01-10 at 08 06 03

Adding logos to the database

Logos should have an aspect ratio of 30:9 to avoid scaling issues, e.g. 300 x 90 or 600x180, add an appropriatley sized logo depending on your intended display resolution.
Images must be in PNG format.
To add a logo image head to the Image Store tab.
Click Add then click select an image file.
Select your image file using the file browser.
Once the preview is shown, hit save.

Screenshot 2026-01-10 at 08 13 49

Creating Display Templates

Head to the Display Templates tab.
Name the display template.
Select the number of rows and columns you require. A preview will be shown in layout builder window.

Screenshot 2026-01-10 at 08 19 51

Now you need to create surfaces on the grid for widgets to be assigned to.
This is done by assigning each block a surface id.
From Display Surfaces, select an ID, then select a block on the layout builder window to assign the id.
Use the id's to create display surfaces. The ID's must be assigned as rectangles and must not be duplicated accross non-adjacent sections, OATIS will complain if you do this.

Screenshot 2026-01-10 at 08 26 00

Once done click Build to create the display sections.
Hover over the layout builder window to see the display surfaces.

Screenshot 2026-01-10 at 08 26 25

Next assign a widget to each section.
Click on a widget from the Display Widgets, then click the Display Surface you want to assign it to.
Each section must contain a widget.

Screenshot 2026-01-10 at 08 29 09

Once done hit save.

Creating a Display Instance

Head to the Display Instances tab.
Click Add.
Give the Display Instance a Name.
Select which Display Template you want to use.
The selected Display Template should render in the preview window.
Click on each Widget to Configure.

Screenshot 2026-01-10 at 14 44 52

Adding a Client Display Device

Click on the Device Config tab.
Click Add.
Name the device.
Set it's IP address.
Set it's location, this is used for logical grouping.
Assign a Message Group.
Assign a Display Instance.
Hit save.

Screenshot 2026-01-10 at 14 47 52

When a client has been added three buttons will be enabled below the device settings allowing the user to reload the display template if changes are made, and identify the device.

Adding Input Triggers

Click on the Input Triggers tab.
Click Add.
Enter a name for the trigger.
Select the controller that will sense the trigger, Network for OSC inputs, any others listed will be Physical Arduinos. Then select the address on that controller for the trigger.

For a Physical Controller, this will be the pin number. Screenshot 2026-01-13 at 22 56 14

For a Network Controller, this will be the OSC address. Screenshot 2026-01-13 at 22 58 37

Adding Input Logics

Input Logics allow a many-to-one relationship to be setup, allowing a group of input triggers to trigger a single Logical Input based on a condition chosen by the user.
Click on the Input Logics tab.
Click Add.
Enter a name for the Input Logic.
Listed on the left are all the configured Input Triggers, select which ones you would like to trigger this Input Logic and use the arrow buttons to move them into the Active Input Triggers Column. You can select multiple by holding down Ctrl.
Then select the high-condition for this Input Logic, this determins how the Input Logic behaves when the Active Input Triggers go high or low. The available options are AND, NAND, OR, NOR. Once done hit save.

Screenshot 2026-01-13 at 23 07 07

Adding Output Triggers

Physical GPO's or OSC commands can be set as Output Triggers. Click on the Output Triggers tab.
Click Add.
Enter a name for the Output Trigger.
Select the type of output, GPO for a physical Arduino Output, or Network for an OSC Output.
If GPO is selected, select the controller to use and the address to trigger.
The rest of the input fields will be greyed out.
Screenshot 2026-01-13 at 23 37 04

If Network is selected, the Controller will automatically be set to Network, and address will be greyed out.
Enter the IP address of the OSC Client you want to send a command to.
Enter the port and select the protocol to use.
Enter the OSC command to send to the client when this Output Trigger goes high, adding optional arguments, each seperated by a space.
Enter the OSC command to send to the client when this Output Trigger goes low, adding optional arguments, each seperated by a space.
Click Save once done.

Screenshot 2026-01-13 at 23 40 35Screenshot 2026-01-13 at 23 13 25

Adding Output Logics

Output Logics allow a one-to-many relationship to be setup, allowing a single Logical Input to trigger multiple Output Triggers. Click on the Output Logics tab.
Click Add.
Enter a name for the Output Logic.
Select the Input Logic that will trigger this Output logic.
Listed on the left are all the configured Output Triggers, select which outputs you want this output Logic to Trigger and use the arrows to move them to the Active Output Triggers Column. Once done hit save.

Screenshot 2026-01-13 at 23 14 48

Launching the Server

Launch the server using the main_server.py script.
The status of the server will show stopped.

Screenshot 2026-01-13 at 09 20 38

Before starting the server, make sure any physical GPIO controllers are plugged in and that you have set the server IP address in config tool.
If you don't set the IP address the server will default to the loopback address of 127.0.0.1.
If you change the server IP address when the server is running, you will need to restart the server for this to take affect. Click start to boot the server. The status will change to booting.

Screenshot 2026-01-13 at 09 24 04

If the server starts ok the status will change to running. If the server does not start, it is likley you have a misconfigured GPIO controller. If the port has changed or the server cannot communicate with the controller the server will not boot. The server will tell you why in the GUI.

Screenshot 2026-01-13 at 09 26 20

Launching the Remote Client

Launch the main_client.py script. On first run a GUI window will open prompting you to set the IP address to use for the client and the server.
Once these IP's have been set the client will boot without launching this window on subsequent launches.
To change the IP's in the future hit "i" on a keyboard when OATIS is running, this will close the client and set a flag to bring up the IP configuration menu on next launch.

Screenshot 2026-01-13 at 09 42 14

If the client has a successful connection to the server, the small circular indicator in the bottom of the clockface will remain grey. If the server cannot be reached this will flash red.

To exit the client, press "ESC" on the keyboard.

Launching the Message Console

Launch the main_message_console.py script.
On first run it will default to the loopback address and will probably show Server Offline if the server is using a different IP.

Screenshot 2025-09-20 at 20 29 48

To set the IP of the Message Console, hit ESC to bring up the configuration window.
Use the dropdown to set the device IP and enter the Server IP.
Hit Save, you will automatically return to the Message Console main screen.

Screenshot 2025-09-20 at 20 33 06

If you've set everything correctly, Message Groups assigned to devices will populate in the GUI.
The status bar will show as below: Screenshot 2025-09-20 at 20 34 11

Sending a Message

Use the top free-text field to enter your message.
Choose a background colour.
Select which message groups you want to send the message to and move these to the selected groups column using the arrow.
Once happy click the green arrow to make the message active.
The message groups will move to the active messages column.

Screenshot 2025-09-20 at 21 16 21

Stopping a message

Select from the active messages column the messages you want to stop.
Hit the red arrow button.

API's

OATIS has a series of API's that allow Interaction by external devices and software:

  • OSC Protocol
  • Server listens on UDP / TCP port 1337

Network Input Triggers

Network Input Triggers are user configurable. The user chooses which OSC address will be used to trigger the Input Trigger. Valid arguments are:

  • 1 > Triggers the Input Trigger High
  • 0 > Triggers the Input Trigger Low
Screenshot 2026-01-16 at 16 56 44

Changing Stacked Images

Stacked Images are a series of images stacked ontop of each other on a client display layout.
The visible image (the one at the top of the stack) can be changed through the below API.

Command:

/client/control/stacked_image

Arguments:

"device_id" "image_stack_id" "image_id"

Where:

  • device_id is the id of the client device you want to change the image on.
  • image_stack_id is the id of the Image Stack we will be interacting with.
  • image_id is the id of the image we want to raise to the front.

Messaging

Messages can be sent to clients using the Message Console, but should you want to interface your own application, they can also be sent using an OSC API.

Sending a Message to a Client

Command:

/messaging/send_message

Arguments:

"message_text" "bg_colour_hex" "message_group_id"

Where:

  • message_text is the message you want to send to each client, this will be displayed on the scrolling ticker at the top of the screen.
  • bg_colour_hex is the background colour of the scrolling ticker in hexadecimal format.
  • message_group_id is the id of the message group we want to target the message at.

Stopping an Active Message

Command:

/messaging/stop_message

Arguments:

"message_group_id"

Where:

  • message_group_id is the id of the message group we want to tell to stop displaying any active messages.
Back to Broadcasting