/      日本語

Communicating with Child Devices Using Python (Basic)

How to communicate with child devices using Python
By using a dedicated library, you can communicate with TWELITE child devices via TWELITE STICK from Python.

Basic Operation Check

Connect the TWELITE STICK

Connect the TWELITE STICK to your PC’s USB port.

The factory-default TWELITE is configured in Parent mode of the Parent and Repeater App. It can send and receive data to and from child devices in the TWELITE series, and the logo should light up magenta.

Factory default state

Factory default state

Installing the MWings Library

Prepare a Python 3.12 or later environment.

Install the MWings module, which interprets the output of the Parent and Repeater App.


pip install mwings

The MWings module allows communication with TWELITE child devices via a TWELITE parent device connected to the host.

  • Interprets data received from the parent and converts it into a dictionary, JSON, or pandas DataFrame format*
  • Sends commands generated from dictionaries to the parent device

*The Lite version does not support pandas

Confirming Data Reception

Verify that TWELITE STICK can interpret the received data.

Please run the sample script rx_print_json.py available on GitHub.

This script will print the contents of all types of packets received by the TWELITE STICK in JSON format to the terminal, allowing you to confirm the data.

# -*- coding:utf-8 -*-
# Written for Python 3.12
# Formatted with Black

# MWings example: Receive data, print JSON, typed

from zoneinfo import ZoneInfo

import mwings as mw


# Main function
def main() -> None:
    # Create a twelite object
    twelite = mw.Twelite(mw.utils.ask_user_for_port())

    # Use JST for received data
    twelite.set_timezone(ZoneInfo("Asia/Tokyo"))

    # Register event handlers
    @twelite.on(mw.common.PacketType.APP_ARIA)
    def on_app_aria(packet: mw.parsers.app_aria.ParsedPacket) -> None:
        print(packet.to_json(verbose=False, spread=True))

    @twelite.on(mw.common.PacketType.APP_CUE)
    def on_app_cue(packet: mw.parsers.app_cue.ParsedPacket) -> None:
        print(packet.to_json(verbose=False, spread=True))

    @twelite.on(mw.common.PacketType.APP_CUE_PAL_EVENT)
    def on_app_cue_pal_event(packet: mw.parsers.app_cue_pal_event.ParsedPacket) -> None:
        print(packet.to_json(verbose=False, spread=True))

    @twelite.on(mw.common.PacketType.APP_IO)
    def on_app_io(packet: mw.parsers.app_io.ParsedPacket) -> None:
        print(packet.to_json(verbose=False, spread=True))

    @twelite.on(mw.common.PacketType.APP_TWELITE)
    def on_app_twelite(packet: mw.parsers.app_twelite.ParsedPacket) -> None:
        print(packet.to_json(verbose=False, spread=True))

    @twelite.on(mw.common.PacketType.APP_PAL_AMB)
    def on_app_pal_amb(packet: mw.parsers.app_pal_amb.ParsedPacket) -> None:
        print(packet.to_json(verbose=False, spread=True))

    @twelite.on(mw.common.PacketType.APP_PAL_MOT)
    def on_app_pal_mot(packet: mw.parsers.app_pal_mot.ParsedPacket) -> None:
        print(packet.to_json(verbose=False, spread=True))

    @twelite.on(mw.common.PacketType.APP_PAL_OPENCLOSE)
    def on_app_pal_openclose(packet: mw.parsers.app_pal_openclose.ParsedPacket) -> None:
        print(packet.to_json(verbose=False, spread=True))

    @twelite.on(mw.common.PacketType.APP_UART_ASCII)
    def on_app_uart_ascii(packet: mw.parsers.app_uart_ascii.ParsedPacket) -> None:
        print(packet.to_json(verbose=False, spread=True))

    @twelite.on(mw.common.PacketType.APP_UART_ASCII_EXTENDED)
    def on_app_uart_ascii_extended(
        packet: mw.parsers.app_uart_ascii_extended.ParsedPacket,
    ) -> None:
        print(packet.to_json(verbose=False, spread=True))

    @twelite.on(mw.common.PacketType.ACT)
    def on_act(packet: mw.parsers.act.ParsedPacket) -> None:
        print(packet.to_json(verbose=False, spread=True))

    # Start receiving
    try:
        # Set as daemon thread
        twelite.daemon = True
        # Start the thread, Join to the main thread
        twelite.start()
        print("Started receiving")
        while True:
            twelite.join(0.5)
    except KeyboardInterrupt:
        # Stop the thread
        print("Flushing...")
        twelite.stop()
        print("Completed")


if __name__ == "__main__":
    # Call the main function
    main()

For example, if you have prepared a factory-default TWELITE DIP running the Extremely Simple! Standard App as a child device, just like in the previous section Using TWELITE STAGE APP, you should see an output like the following. To stop the script, press Ctrl+C.

{
  "time_parsed": "2025-07-11T11:45:02.067804+09:00",
  "packet_type": "APP_TWELITE",
  "sequence_number": 4713,
  "source_serial_id": "8201007F",
  "source_logical_id": 120,
  "lqi": 166,
  "supply_voltage": 3254,
  "destination_logical_id": 0,
  "relay_count": 0,
  "periodic": true,
  "di_changed_1": false,
  "di_changed_2": false,
  "di_changed_3": false,
  "di_changed_4": false,
  "di_state_1": false,
  "di_state_2": false,
  "di_state_3": false,
  "di_state_4": false,
  "ai_voltage_1": 2000,
  "ai_voltage_2": 2000,
  "ai_voltage_3": 2000,
  "ai_voltage_4": 2000
}

python rx_export_csv_durable.py -h
usage: rx_export_csv_durable.py [-h] [-v] [-s]

Log packets from App_Wings to csv, line by line

options:
  -h, --help     show this help message and exit
  -v, --verbose  include system information
  -s, --sort     sort columns in the output

Sending and Receiving Arbitrary Data

Here, let’s create a script that specifically communicates with a TWELITE DIP child device prepared just like in Using TWELITE STAGE APP.

Example wiring of TWELITE DIP child device

Example wiring of TWELITE DIP child device

The goal is to display the state of a switch connected to the DI1 pin of the TWELITE DIP and control an LED connected to the DO1 pin.

Receiving Only Standard App Data

Modify rx_print_json.py to create a simplified script that only receives data from the Extremely Simple! Standard App.

# -*- coding:utf-8 -*-

from zoneinfo import ZoneInfo

import mwings as mw


# Main function
def main() -> None:
    # Create a twelite object
    twelite = mw.Twelite(mw.utils.ask_user_for_port())

    # Use JST for received data
    twelite.set_timezone(ZoneInfo("Asia/Tokyo"))

    # Register event handlers
    @twelite.on(mw.common.PacketType.APP_TWELITE)
    def on_app_twelite(packet: mw.parsers.app_twelite.ParsedPacket) -> None:
        print(packet.to_json(verbose=False, spread=True))

    # Start receiving
    try:
        # Set as daemon thread
        twelite.daemon = True
        # Start the thread, Join to the main thread
        twelite.start()
        print("Started receiving")
        while True:
            twelite.join(0.5)
    except KeyboardInterrupt:
        # Stop the thread
        print("Flushing...")
        twelite.stop()
        print("Completed")


if __name__ == "__main__":
    # Call the main function
    main()

Extracting Specific Values

In the previous script, we used the to_json() method to output all data as a JSON string.

Here, we’ll extract only the state of the DI1 pin from parsers.app_twelite.ParsedPacket using the di_state field and display a virtual LED in the terminal.

Rewrite the on_app_twelite() handler as follows:

def on_app_twelite(packet: mw.parsers.app_twelite.ParsedPacket) -> None:
        print(f"\rDO1 LED: {"🔴" if packet.di_state[0] else "⚪"}", end='', flush=True)

If pressing the switch connected to the DI pin of TWELITE DIP causes the red light to appear, it indicates success.

Example display

Example display

Sending Commands to the Parent Device

In addition to displaying data received by the TWELITE STICK, you can also send data from the TWELITE STICK.

In the script’s main loop, we call threading.Thread.join() every 0.5 seconds so that the receiving thread can also terminate when the main thread ends.

        # Start the thread, Join to the main thread
        twelite.start()
        print("Started receiving")
        while True:
            twelite.join(0.5)

Using this mechanism, let’s control the DO1 pin of the TWELITE DIP from the main loop and try blinking the LED every 0.5 seconds.

Modify the previous script as follows. The full script below includes all changes made so far.

# -*- coding:utf-8 -*-

from zoneinfo import ZoneInfo
from typing import Any

import mwings as mw


# Main function
def main() -> None:
    # Create a twelite object
    twelite = mw.Twelite(mw.utils.ask_user_for_port())

    # Use JST for received data
    twelite.set_timezone(ZoneInfo("Asia/Tokyo"))

    # Register event handlers
    @twelite.on(mw.common.PacketType.APP_TWELITE)
    def on_app_twelite(packet: mw.parsers.app_twelite.ParsedPacket) -> None:
        print(f"\rDO1 LED: {"🔴" if packet.di_state[0] else "⚪"}", end='', flush=True)

    # Initialize command
    initial: dict[str, Any] = {
        "destination_logical_id": 0x78,  # All child devices
        "di_to_change": [True, False, False, False],  # Enable DI1
        "di_state": [False, False, False, False],  # Initial state of DIx
    }
    command = mw.serializers.app_twelite.Command(**initial)

    # Toggle the DI1 state
    def toggle_di1() -> None:
        command.di_state[0] = not command.di_state[0]
        twelite.send(command)

    # Start receiving
    try:
        # Set as daemon thread
        twelite.daemon = True
        # Start the thread, Join to the main thread
        twelite.start()
        print("Started receiving")
        while True:
            toggle_di1() # Send
            twelite.join(0.5) # Receive
    except KeyboardInterrupt:
        # Stop the thread
        print("Flushing...")
        twelite.stop()
        print("Completed")


if __name__ == "__main__":
    # Call the main function
    main()

When you run this script, it displays a virtual LED just like before.

Example display

Example display

At the same time, the LED connected to the DO1 pin of TWELITE DIP should continuously blink. When you stop the script, the blinking stops.


Communicating with Child Devices Using Python (Web Server IoT)

Send data from child devices to a web server using Python

Communicating with Child Devices Using Python (Graphical UI)

Build an application with a graphical UI to communicate with child devices using Python