JS8 Commands for API (TCP/IP)

Messages from JS8Call
CLOSE – JS8Call has been closed
INBOX.MESSAGES – A list of inbox messages
INBOX.MESSAGE – A single inbox message
MODE.SPEED – The current TX speed
PING – Keepalive from JS8Call
RIG.FREQ – The rig frequency has been changed
RIG.PTT – PTT has been toggled
RX.ACTIVITY – We received something
RX.BAND_ACTIVITY – The band activity window
RX.CALL_ACTIVITY – The call activity window
RX.CALL_SELECTED – The currently selected callsign
RX.DIRECTED – A complete message
RX.SPOT – A station we have heard
RX.TEXT – Contents of the QSO window
STATION.CALLSIGN – Callsign of the station
STATION.GRID – Grid locator of the station
STATION.INFO – QTH/info of the station
STATION.STATUS – Status of the station
TX.FRAME – Something we are sending
TX.TEXT – Text in the outgoing message window

Messages to JS8Call
INBOX.GET_MESSAGES – Get a list of inbox messages
INBOX.STORE_MESSAGE – Store a message in the inbox
MODE.GET_SPEED – Get the TX speed
MODE.SET_SPEED – Set the TX speed
RIG.GET_FREQ – Get the current dial freq and offset
RIG.SET_FREQ – Set the current dial freq and offset
RX.GET_BAND_ACTIVITY – Get the contents of the band activity window
RX.GET_CALL_ACTIVITY – Get the contents of the call activity window
RX.GET_CALL_SELECTED – Get the currently selected callsign
RX.GET_TEXT – Get the contents of the QSO qindow
STATION.GET_CALLSIGN – Get the station callsign
STATION.GET_GRID – Get the station grid
STATION.SET_GRID – Set the station grid
STATION.GET_INFO – Get the station QTH/info
STATION.SET_INFO – Set the station QTH/info
STATION.GET_STATUS – Get the station status
STATION.SET_STATUS – Set the station status
TX.SEND_MESSAGE – Send a message via JS8Call
TX.SET_TEXT – Sets the text in the outgoing message box, but does not send it.
WINDOW.RAISE – Focus the JS8Call window

The python example below is modified form the JS8 source code available here: http://js8call.com/

from __future__ import print_function

from socket import socket, AF_INET, SOCK_STREAM

import json
import time

#make sure you open port 2442 prior to opening JS8 application

#ubuntu command: sudo ufw allow 2442

server = ('127.0.0.1', 2442)

def from_message(content):
    try:
        return json.loads(content)
    except ValueError:
        return {}


def to_message(typ, value='', params=None):
    if params is None:
        params = {}
    return json.dumps({'type': typ, 'value': value, 'params': params})


class Client(object):
    first = True
    def process(self, message):
        typ = message.get('type', '')
        value = message.get('value', '')
        params = message.get('params', {})
        if not typ:
            return

        if typ in ('RX.ACTIVITY',):
            # skip
            return

        print('->', typ)

        if value:
            print('-> value', value)

        if params:
            print('-> params: ', params)


    def send(self, *args, **kwargs):
        params = kwargs.get('params', {})
        if '_ID' not in params:
            params['_ID'] = '{}'.format(int(time.time()*1000))
            kwargs['params'] = params
        message = to_message(*args, **kwargs)
        print('outgoing message:', message)
        self.sock.send((message + '\n').encode()) # remember to send the newline at the end :)
    
    def send2(self):
        message = "{'type': 'STATION.GET_STATUS', 'value': '', 'params': {'_ID': '1645105873058'}}"
        print('outgoing message:', message)
        self.sock.send((message + '\n').encode()) # remember to send the newline at the end :)
    
    def connect(self):
        print('connecting to', ':'.join(map(str, server)))
        self.sock = socket(AF_INET, SOCK_STREAM)
        self.sock.connect(server)
        self.connected = True
        try:
            # send a simple example query after connected

            self.send("TX.SET_TEXT", "WHAT IS GOING ON?")
			
            #list of commands here: 
            #https://planetarystatusreport.com/?p=646
            
            while self.connected:
                content = self.sock.recv(65500)
                if not content:
                    break
                print('incoming message')

                try:
                    message = json.loads(content)
                except ValueError:
                    message = {}

                if not message:
                    continue

                self.process(message)

        finally:
            self.sock.close()

    def close(self):
        self.connected = False

def main():
    s = Client()
    s.connect()

if __name__ == '__main__':
    main()