Use LoRa Downlinks with Machinechat JEDI Pro to Control the Dragino LT22222-L I/O Controller


This post is a follow-on project to Using the Dragino LT-22222 LoRa I/O Controller with Machinechat’s JEDI Pro IoT Platform and assumes you have already added the LT-22222-L to your private LoRaWAN network and Machinechat JEDI IoT software. LoRaWAN downlinks are explored in this post and “enqueue downlinks” are used in the Chirpstack LoRaWAN network server to control the relay and digital outputs of the LT22222L I/O controller.



  • JEDI Pro or JEDI Pro SSE
    Adaptable software for IoT data collection, visualization, monitoring and data storage that can be integrated into IoT solutions. Capabilities include: collect data from sensors, devices and machines; build intuitive real-time and historical data and system view dashboards; create rules to monitor and respond to data conditions automatically; receive alert notifications by email and SMS. JEDI Pro SSE is the Seeed Studio Edition version of JEDI Pro that adds a Data Collector for Seeed’s line of SenseCAP LoRaWAN sensors
  • ChirpStack
    The ChirpStack open-source LoRaWAN Network Server stack provides open-source components for LoRaWAN networks. The modular architecture makes it possible to integrate within existing infrastructures.
  • Tera Term
    Tera Term is open source free software terminal emulator supporting UTF-8 protocol.


This post is a follow-on project that builds on the related TechForum post Using the Dragino LT-22222 LoRa I/O Controller with Machinechat’s JEDI Pro IoT Platform which details adding a Dragino LT22222-L LoRa I/O Controller to a private LoRaWAN network and configuring Chirpstack to send the I/O parameters to JEDI Pro. This project looks at the LoRa downlink payload capability within Chirpstack and the ability to set up an executable Python script within JEDI Pro that can be triggered to to enqueue a downlink payload to the LT22222-L. Software and hardware used are the same as described in the previous referenced Dragino LT22222-L post.


For this project, a 12V power supply is used to power the LT-22222 and an FTDI USB to serial TTL cable is connected to the PRO jack serial interface. TeraTerm is used to monitor the serial output of the LT22222-L. Below schematic diagram illustrates how the setup is implemented (see Scheme-it DraginoLT22222 Project).

Electrical connections are shown below:

LT-22222-L FTDI serial cable Power Supply
VIN - +12VDC
PRO-txd (red) 4 - tx (orange) -
PRO-rxd (white) 5 - rx (yellow) -
PRO-gnd (black) 1 - gnd (black) -

Testing enqueue downlink payload in Chirpstack GUI

The Chirpstack Application Server provides the ability to directly enqueue a downlink payload to a LoRa device using the GUI. This is accomplished by going to the Application Device page (example: Applications/FarmTest/Devices/LT22222io )

Towards the bottom of the page the f-port and download packet can be entered. The f-port value can be determined by selecting the “DEVICE DATA” tab and expanding one of the data packets.

The downlink packet needs to converted to Base-64 before entering the download value. For this example we will be sending a payload that turns the LT22222-L’s Relay1 and Relay2 on. Based on section * Relay – Control Relay Output RO1/RO2 of the LT22222-L User Manual the hex value of the downlink is “0x03 0x01 0x01” which converts to “AwEB” in Base-64. Once the f-port value and downlink packet have been entered, select “Enqueue Downlink”.

The LT22222-L relays should turn on and the serial output should look similar to the below.

Setup Python code to enqueue downlink payload using the Chirpstack API

Chirpstack provides an API and example Python code to enqueue a downlink payload to a LoRa device as described in reference The API can be installed using pip as shown below.

sudo python3 -m pip install chirpstack-api

Below example Python code is capable of sending various sequence downlink payloads to the LT22222-L I/O controller to set the digital outputs high/low and turn the relays on/off.

# Change the path above to where python3 is on system - use "which python3" to find out
# NOTE: this code is heavily modified by SBR but based on Machinechat example for below
# - A custom action plugin for JEDI Pro to enqueue downlinks
# for the Plenum Kuando Busylight (LoRaWAN) via ChirpStack using their API:  
# This can also be run from the command line to test
# v0.1 DRM 04/10/2022  (original Machinechat code)
# Depends on Python package: chirpstack_api
# Install:  sudo python3 -m pip install chirpstack_api
# The original code by DRM has been heavily modified to work with Dragino LT-22222-L LoRa I/O controller
# similar to the original code to enqueue downlinks to set parameters and output settings
# per Dragino user manual at below link
# Example: "./ 0x03 0x01 0x01"
# LT-22222 will turn relays 1 and 2 on
# Example: "./ 0x03 0x00 0x00"
# LT-22222 will turn relays 1 and 2 off"

import os
import sys

import grpc
from chirpstack_api.as_pb.external import api

# Kuando has the colors in a strange order: red blue green versus normal RGB
# SR modified for 3 parameters and Dragino LT22222 io controller

# change to 4 for lt22222
args = len(sys.argv)
# create list of 10 integers
arg = list(range(10))

# check count of command line arguments to check if valid
if (args == 4 or args == 5 or args == 6 or args == 8):
        print("args is 4, 5, 6 or 8")
        print("number of args not valid")
        print("program handles 4,5, 6 or 8 command line variables as shown below")
        print("usage: %s arg1 arg2 arg3" % sys.argv[0])
        print("example: %s 0x03 0x01 0x00" % sys.argv[0])

# check if format of command line arguments are valid and store as integer
for x in range(args - 1):
        if (sys.argv[x + 1].startswith("0x")):                
            print(sys.argv[x +1])
            arg[x+1] = int(sys.argv[x+1],16)
                print("invald arg")

# debug
for x in range(args - 1):

#print (arg1)
#print (arg2)
#print (arg3)
#print (ont)
#print (offt)

# Configuration.
# This must point to the ChirpStack API interface.
#server = ""
server = ""
# The Kuando BusyLight DevEUI for which you want to enqueue the downlink.
#dev_eui = bytes([0x20, 0x20, 0x20, 0x41, 0x28, 0x13, 0x05, 0x02])
# for LT22222  eui a8 40 41 46 d1 84 84 96
dev_eui = bytes([0xa8, 0x40, 0x41, 0x46, 0xd1, 0x84, 0x84, 0x96])
# The API token (generated using the ChirpStack web-interface).
# make sure to copy the key when it is displayed - it is hidden after leaving page
# and it is impossible to retrieve the key again.  Have to create new one if that happens
api_token = "put your API token here"

if __name__ == "__main__":
  # Connect without using TLS.
  channel = grpc.insecure_channel(server)

  # Device-queue API client.
  client = api.DeviceQueueServiceStub(channel)

  # Define the API key meta-data.
  auth_token = [("authorization", "Bearer %s" % api_token)]

  # Construct request.
  req = api.EnqueueDeviceQueueItemRequest()
  # Confirmed downlink
  req.device_queue_item.confirmed = True
  if (args == 4): = bytes([arg[1], arg[2], arg[3]])
  elif (args == 5): = bytes([arg[1], arg[2], arg[3], arg[4]])
  elif (args == 6): = bytes([arg[1], arg[2], arg[3], arg[4], arg[5]])
  elif (args == 8): = bytes([arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], arg[7]])
  req.device_queue_item.dev_eui = dev_eui.hex()
  # 15 for Kuando Busylight
  # 2 for LT22222 io controller
  req.device_queue_item.f_port = 2

  resp = client.Enqueue(req, metadata=auth_token)
  # Print the downlink frame-counter value.

You will need to modify the code for the IP, device eui, f port and Chirpstack API key of your setup.

A Chirpstack API key can be created by selecting “Org. API keys” on the main page of the Chirpstack web interface.

Example code can be downloaded from: machinechat/ at master · eewiki/machinechat · GitHub.

NOTE: Possible protobuf error when running Python code
When I first started testing the Python code to control the LT-22222L relays I ran into the below error (I initially had protobuf version 4.21.5 installed on my Ubuntu computer). 0x03 0x01 0x00
exit status 1: Traceback (most recent call last): 
File "./", line 34, in <module> from chirpstack_api.as_pb.external import api 
File "/usr/local/lib/python3.8/dist-packages/chirpstack_api/as_pb/", line 1, in <module> from .as_pb_pb2_grpc import * 
File "/usr/local/lib/python3.8/dist-packages/chirpstack_api/as_pb/", line 5, in <module> from chirpstack_api.as_pb import as_pb_pb2 as chirpstack__api_dot_as__pb_dot_as__pb__pb2 File "/usr/local/lib/python3.8/dist-packages/chirpstack_api/as_pb/", line 17, in <module> from chirpstack_api.common import common_pb2 as chirpstack__api_dot_common_dot_common__pb2 File "/usr/local/lib/python3.8/dist-packages/chirpstack_api/common/", line 1, in <module> from .common_pb2 import * 
File "/usr/local/lib/python3.8/dist-packages/chirpstack_api/common/", line 33, in <module> _descriptor.EnumValueDescriptor( 
File "/usr/local/lib/python3.8/dist-packages/google/protobuf/", line 755, in __new__ _message.Message._CheckCalledFromGeneratedFile() 
TypeError: Descriptors cannot not be created directly. 
If this call came from a file, your generated code is out of date and must be regenerated with protoc >= 3.19.0. If you cannot immediately regenerate your protos, some other possible workarounds are: 
1. Downgrade the protobuf package to 3.20.x or lower. 
2. Set PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python (but this will use pure-Python parsing and will be much slower). 
More information:

To correct the problem I downgraded the protobuf version to 3.20.0 on the Ubuntu Linux computer running Chirpsatck using the below Terminal command.

pip install protobuf==3.20.0

If you still experience the error you may have another install of a newer version of protobuf on your computer. I resolved the issue by running the below Terminal command which uninstalled the newer version and re-installed 3.20.0.

sudo pip install --system protobuf==3.20.0

Set up Rule in JEDI Pro to Trigger LoRa Enqueue Downlink Payload

Machinechat’s JEDI IoT software has the ability to set up rules to trigger actions based on specified conditions. An example rule will be set up to enqueue a LoRa downlink payload using a Rule to trigger the above example Python code as a custom plug-in. The example rule will set up a condition using sensor data from an already included sensor (in this case, humidity data from “LoRaE5Two”) to trigger the Plug-In Executable “” to turn Relay1 on of the LT22222-L when the condition of “humidity >= 80” is met. When implemented, the rule should look similar to below.

When adding the Rule you will need to name the Action, set Action Type to “Custom Plug-In”, select the Plug-In Executable to “” and add the Plug-In Command Line Arguments “0x03 0x01 0x00”.

Once the Rule has been set up, select “VALIDATE PLUG-IN” to test. Output should look similar to below and Relay1 should be turned on.


The Dragino LT-22222-L LoRa I/O controller provides a flexible means to read digital and analog inputs as well as set digital ouptut values and control relay state using Chirpstack/LoRaWAN. Combined with Machinechat’s JEDI Pro IoT application software, a quick and effective solution to monitor/visualize data can be implemented as well as taking action when specific data conditions are met.