Skip to main content

Python library and utilities for interacting with the JS8Call-improved API via TCP

Project description

js8call-improved

Jeff Francis gjfrancis@protonmail.com, N0GQ


⚠️ ALPHA SOFTWARE — READ BEFORE USING ⚠️

This library should be considered Alpha quality software. It has not been extensively tested against a running JS8Call-improved instance. APIs may change, functions may behave unexpectedly, and some features may not yet work correctly. Use with caution, especially in any automated or unattended scenario involving actual transmissions.

The library is also subject to change as the JS8Call-improved API itself evolves and improves. Function signatures, return values, and the set of supported commands may all shift in future releases without notice until the API stabilizes. Watch the changelog and pin to a specific version in production code.


Note: This library targets the JS8Call-improved fork. It is not compatible with the original (legacy) JS8Call software. For the original JS8Call, see js8call-legacy.

Installation

pip install js8call-improved

Or from source:

git clone https://github.com/jfrancis42/js8net-improved.git
cd js8net-improved
pip install .

In your Python code, import the library as:

from js8call_improved import *

The Library

js8call-improved is a python3 package for interacting with the JS8Call-improved API. It works exclusively in TCP mode and targets the API extensions introduced in JS8Call-improved (API v2.6+), while also supporting all commands available in the original API (v2.5).

The JS8Call-improved API is a significant improvement over the legacy API, adding remote configuration control, filter management, PTT status, queue depth queries, OS/version introspection, and much more. The underlying protocol is the same JSON-over-TCP transport used by the legacy software.

This library is closely modeled on js8call-legacy to make migration as smooth as possible. See the Differences from js8call-legacy section below for a complete list of changes.

Getting Started

To get started, import the library, then tell it to connect to your JS8Call-improved instance:

from js8call_improved import *
start_net("10.1.1.141", 2242)

Note that the default port is 2242, not 2442. This is the default API port in JS8Call-improved (configurable under Settings → Reporting → API).

At this point, three daemon threads are running: one receives messages from JS8Call-improved and updates internal state; one sends queued commands; one sends keepalive heartbeats every five minutes.

API Reference

Connection

start_net(host, port)

Connect to a JS8Call-improved instance. Default: localhost, port 2242.

Frequency Control

get_freq()

Returns {'dial': hz, 'freq': hz, 'offset': hz}.

set_freq(dial, offset)

Set dial frequency and audio offset, both in Hz.

get_ptt()

New in js8call-improved. Get current PTT state. Returns True if transmitting, False if not.

set_tune(enabled)

New in js8call-improved. Enable (True) or disable (False) continuous carrier tune mode for antenna tuning.

tx_halt()

New in js8call-improved. Emergency stop: immediately halt any ongoing transmission.

Station Configuration

get_callsign()
get_grid()
set_grid(grid)
get_info()
set_info(info)

These work identically to their js8call-legacy counterparts.

get_status()
set_status(status_text)

New in js8call-improved. Get or set the station status message.

get_version()

New in js8call-improved. Returns the JS8Call-improved version string.

get_os()

New in js8call-improved. Returns OS information from the running JS8Call-improved instance.

get_spot()
set_spot(enabled)

New in js8call-improved. Get or set the spot-enabled state.

get_config()

New in js8call-improved. Fetch the full station configuration as a dict. Keys include: AUTO_REPLY, JS8HB, HBACK, MULTI_DECODER, HB_INTERVAL, HB_TIMER_ACTIVE, MONITOR, TX_ENABLED, SPEED, CAN_HB, AUTOREPLY_CONFIRMATION, MY_GROUPS, AVOID_ALLCALL.

set_auto_reply(enabled)
set_js8hb(enabled)
set_hback(enabled)
set_multi_decoder(enabled)

New in js8call-improved. Toggle autoreply, JS8 heartbeat networking, heartbeat acknowledgements, and simultaneous multi-decoder on or off.

set_hb_interval(minutes)
set_hb_timer(active)
send_hb()

New in js8call-improved. Control the automated heartbeat: set the interval in minutes, start/stop the timer, or trigger an immediate API-level heartbeat. Note: send_hb() triggers JS8Call-improved's built-in heartbeat mechanism and is distinct from send_heartbeat(), which constructs and queues a heartbeat message directly.

set_groups(groups)

New in js8call-improved. Replace the list of subscribed groups. Pass a list of strings, e.g. ["@GROUPONE", "@GROUPTWO"].

set_avoid_allcall(enabled)

New in js8call-improved. Opt out of (True) or back in to (False) @ALLCALL messages.

Activity Queries

get_call_activity()

Get the list of recently heard callsigns (right panel). Returns a list of Callstation objects.

get_call_selected()

Return the callsign currently selected in the GUI.

get_band_activity()

Get the band activity list (left panel). Returns a list of Bandstation objects.

get_free_offsets()

New in js8call-improved. Get available (unoccupied) frequency segments in the passband. Returns a dict with:

  • FREE: list of {'LOW': hz, 'HIGH': hz, 'WIDTH': hz} segments
  • BANDWIDTH: signal bandwidth in Hz for the current speed
  • SPEED: current speed mode
  • LOW, HIGH: usable passband limits in Hz
get_filter()
set_filter(center, width)
set_filter_enabled(enabled)

New in js8call-improved. Get, set, or toggle the bandpass filter. center and width are in Hz.

Text Buffers

get_rx_text()
get_tx_text()
set_tx_text(text)

These work identically to their js8call-legacy counterparts.

Transmission Queue

get_queue_depth()

New in js8call-improved. Returns the number of messages currently waiting in the transmit queue.

Speed Control

get_speed()
set_speed(speed)
speed_name(speed)

Speed values: 0=Normal, 1=Fast, 2=Turbo, 4=Slow, 8=Ultra.

Change from js8call-legacy: Speed 8 (Ultra/JS8-60) is newly supported. speed_name() now returns 'Ultra' for speed 8 instead of 'Invalid'.

Window

raise_window()

Bring the JS8Call-improved window to the foreground.

Messaging

send_message(message)
send_directed_message(dest_call, message)
send_inbox_message(dest_call, message)

These work identically to their js8call-legacy counterparts.

send_heartbeat(grid=False)

Construct and queue a heartbeat message over the air. See also send_hb().

send_aprs(dest, message)
send_aprs_grid(grid)
send_sms(phone, message)
send_email(address, message)
send_sota(summit, freq, mode, comment=False)
send_pota(park, freq, mode, comment=False)

These work identically to their js8call-legacy counterparts.

query_snr(dest_call)
query_grid(dest_call)
query_status(dest_call)
query_info(dest_call)
query_hearing(dest_call)

These work identically to their js8call-legacy counterparts.

get_messages()
store_message(callsign, text)

These work identically to their js8call-legacy counterparts.

Connection Health

alive()

Returns True if a valid response was received in the last ~5.5 minutes.

Receiving Messages

Incoming messages that don't map to a query response are placed into rx_queue (protected by rx_lock). The message types you'll typically see are:

  • RX.SPOT — spot message
  • RX.ACTIVITY — partial frame (a fragment of a larger message)
  • RX.DIRECTED — complete reassembled directed message
  • RX.TEXT — received text buffer update
  • STATION.CLOSINGnew in js8call-improved: JS8Call-improved is shutting down; the closing global is also set to True

Example receive loop:

while True:
    if not rx_queue.empty():
        with rx_lock:
            message = rx_queue.get()
            if message['type'] == 'RX.DIRECTED':
                print(message['params']['FROM'], '->', message['params']['TO'])
                print(message['value'])
            elif message['type'] == 'STATION.CLOSING':
                print("JS8Call-improved is shutting down.")
    time.sleep(0.1)

Differences from js8call-legacy

Users migrating from js8call-legacy should note the following changes:

Item js8call-legacy js8call-improved
Import from js8call_legacy import * from js8call_improved import *
Default port 2442 2242
Speed 8 (Ultra) Not supported; speed_name(8) returns 'Invalid' Supported; speed_name(8) returns 'Ultra'
send_heartbeat() Sends heartbeat over the air Same behavior; see also new send_hb()
STATION.CLOSING Not handled Sets closing=True global; queued for user processing
get_status() / set_status() Not available New functions
get_version() / get_os() Not available New functions
get_ptt() / set_tune() / tx_halt() Not available New functions
get_spot() / set_spot() Not available New functions
get_config() Not available New function; returns full config dict
set_auto_reply() / set_js8hb() / set_hback() / set_multi_decoder() Not available New functions
set_hb_interval() / set_hb_timer() / send_hb() Not available New functions
set_groups() / set_avoid_allcall() Not available New functions
get_free_offsets() Not available New function
get_filter() / set_filter() / set_filter_enabled() Not available New functions
get_queue_depth() Not available New function

All other functions (get_callsign(), get_grid(), set_grid(), get_info(), set_info(), get_freq(), set_freq(), get_call_activity(), get_band_activity(), get_call_selected(), get_rx_text(), get_tx_text(), set_tx_text(), get_speed(), set_speed(), raise_window(), send_message(), send_directed_message(), send_inbox_message(), send_heartbeat(), send_aprs(), send_aprs_grid(), send_sms(), send_email(), send_sota(), send_pota(), query_snr(), query_grid(), query_status(), query_info(), query_hearing(), get_messages(), store_message(), alive()) are drop-in compatible with js8call-legacy.

Bundled Scripts

Script Description
send_aprs.py Send an APRS message to a callsign
send_email.py Send an email via a JS8 gateway
send_sms.py Send an SMS via a JS8 gateway
send_heartbeat.py Send a heartbeat message
send_message.py Send a directed message
send_pota.py Submit a POTA spot
send_sota.py Submit a SOTA spot
send_grid.py Send your grid square to APRS; optionally track via GPSD
fill_grids.py Query stations with missing grid squares
make_calldb.py Build a local callsign database (USA, Canada, Australia)
stations.py Report current station activity
example.py Example code showing basic library usage

All scripts accept --js8-host and --js8-port (default localhost:2242), or the environment variables JS8HOST and JS8PORT combined with --env. Speed arguments now accept 8 for Ultra mode in addition to the legacy values.

For GPS tracking with send_grid.py, install the optional dependency:

pip install gpsd-py3

Credits

  • The SVG icons are from Creative Commons and Font Awesome Free.
  • Thanks to COAS Book in Las Cruces, NM for being awesome. https://www.coasbooks.com/

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

js8call_improved-0.1.0.tar.gz (21.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

js8call_improved-0.1.0-py3-none-any.whl (30.3 kB view details)

Uploaded Python 3

File details

Details for the file js8call_improved-0.1.0.tar.gz.

File metadata

  • Download URL: js8call_improved-0.1.0.tar.gz
  • Upload date:
  • Size: 21.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for js8call_improved-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ef1d8a71d356e17f6655db1fdb18758a282740ab55273058eb60ccd515ba2aea
MD5 6d61636e57dc26ee6944bbea9b1bac25
BLAKE2b-256 d74976180a607a670cc09e94f2887f74aa1c2c75659b5653b587b4ddb275f5e6

See more details on using hashes here.

File details

Details for the file js8call_improved-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for js8call_improved-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 46aa1a5e82111bf28878dcec3dc3cb7b015c27e58a1ae03b0cdef8a2f060ba19
MD5 70f39f4b6c04e773946b913811857d8b
BLAKE2b-256 195aab744be604a39e78ab0635e17d4ea06d03a46620fefc571db2e5c28a2c4a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page