onkyoctl

package module
v0.0.0-...-bc83b55 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 17, 2021 License: MIT Imports: 17 Imported by: 0

README

OnkyoCTL

onkyoctl is a library and command line tool to control Onkyo devices over the network.

You can switch the receiver on and off (from and to standby mode), change the volume, input source and switch between speaker sets A/B.

Note: This code has been developed and tested with a single receiver model (TX-8250).

Library Usage

The Device type is used to control a receiver. To set it up, a Config object is required, which at least needs the IP address or hostname for the receiver:

c := onkyoctl.NewDefaultConfig()
c.Host = "192.168.1.2"
d := onkyoctl.NewDevice(c)
d.Start()
defer d.Stop()
Single Commands

If you only want to send a single command, use the AutoConnect config setting to connect automatically.

c := onkyoctl.NewDefaultConfig()
c.Host = "192.168.1.2"
c.AutoConnect = true            // connect as soon as required
d := onkyoctl.NewDevice(c)

d.SendCommand("volume", 25)     // will automatically connect
d.Stop()

We still need to Stop() the device if we want to disconnect after the command is sent.

Receive Status Changes

The commands do not return an immediate response. Instead, we need to observe the receiver for status changes to determine whether a command was successful.

Register the OnMessage callback to receive notifications for all messages sent by the receiver:

d.OnMessage(func(name, value string) {
    // name is e.g. "volume"
    // value is e.g. "45"
})
Continuous Connection

The receiver supports a long-living connection over which we can send several commands and receive messages for status updates. Unfortunately, the device supports exactly one client connection. If another client connects, the receiver will terminate our connection and serve the new client instead.

The onkyoctl library deals with this by allowing an automatic reconnect after a short hold-off time. This is also useful to (re-)connect to the receiver as soon as it becomes available on the network (for example after it was switched off).

c := onkyoctl.NewDefaultConfig()
// ...
c.AllowReconnect = true
c.ReconnectSeconds = 10

d := onkyoctl.NewDevice(c)
d.Start()
defer d.Stop()
// ...

If AllowReconnect is true, the device will reconnect when the connection is lost. Commands that were issued while the device is disconnected are queued and will be sent as soon as we are reconnected.

The OnConnected and OnDisconnected callbacks can be used to react to changes in the connection status:

///...
d.OnConnected(func() {
    // do something when the device (re-)connects
})
d.OnDisconnected(func(){
    // do something when we lose connection
})

Warning: The reconnect behavior means that as soon as we reconnect, we will cause the receiver to disconnect any other client that is currently connected. To avoid completely blocking other clients, use ReconnectSeconds to give other clients sufficient time to complete their tasks. If you have other clients that need a constant connection to the receiver, this will not work.

Command Line Usage

The command line tool supports three sub commands.

The default command is do and you do not need to spell it out. It takes a space-separated list of pairs and sends these to the device. It does not wait for a reply.

$ onkyoctl power on volume up speaker-a on

Use the status command to query properties of the device. When called without arguments, a default set of properties is queried.

$ onkyoctl status power volume
power: on
volume: 23.5

or without arguments:

$ onkyoctl status
power: on
volume: 23.5
mute: off
speaker-a: on
speaker-b: off
input: game

The watch command connects to the device and prints out any status messages it receives. Use ctrl + c to quit.

$ onkyoctl watch
volume: 23.5
volume: 26
volume: 29.5
volume: 32

Configuration

For command line usage, the configuration file is expected at: ~/.config/onkyoctl.ini.

It looks like this:

# IP address of the onkyo device
# you will probably want to set this
Host = 192.168.1.2

# Port number (default: 60128)
Port = 60123

# Reconnect after connection loss?
AllowReconnect = false
ReconnectSeconds = 5

# Reconnect when a message needs to be sent?
AutoConnect = false

When used as a library, the Config struct is used to configure a Device. Use ReadConfig(path) to populate it from an .ini file or set individual options directly.

Similar Projects

Documentation

Index

Constants

View Source
const Version = "0.4.3"

Version is the version string.

Variables

View Source
var (
	ErrNotConnected = errors.New("not connected")
	ErrTimeout      = errors.New("timeout")
)

Functions

func ParseHeader

func ParseHeader(data []byte) (int, int, error)

ParseHeader parses the header of an eISCP message and returns the header size and payload size

Types

type Callback

type Callback func(name, value string)

Callback is the type for message callback functions.

type Command

type Command struct {
	Name      string
	Group     ISCPGroup
	ParamType ParamType
	Lookup    map[string]string
	Lower     int
	Upper     int
	Scale     int
}

Command is the "friendly" wrapper around an ISCP command group.

func (*Command) CreateCommand

func (c *Command) CreateCommand(param interface{}) (ISCPCommand, error)

CreateCommand creates an ISCP command with the given parameter. An error is returned if the parameter is invalid.

func (*Command) CreateQuery

func (c *Command) CreateQuery() ISCPCommand

CreateQuery generates the "xxxQSTN" command for this Command.

func (*Command) ParseParam

func (c *Command) ParseParam(raw string) (string, error)

ParseParam converts the ISCP param value to the friendly version.

type CommandSet

type CommandSet interface {
	// ReadCommand finds the command definition for an ISCP command
	// and converts the parameter.
	ReadCommand(command ISCPCommand) (string, string, error)

	// CreateCommand creates an ISCP command for the given friendly name
	// and parameter.
	// An error is returned if the name or parameter is invalid.
	CreateCommand(name string, param interface{}) (ISCPCommand, error)

	// CreateQuery creates a QSTN command for the given friendly name.
	CreateQuery(name string) (ISCPCommand, error)
}

A CommandSet represents a set of known/supported commands and can be used to convert the "friendly" version to ISCP and vice-versa.

func BasicCommands

func BasicCommands() CommandSet

BasicCommands creates a command set with some commonly used commands.

func NewBasicCommandSet

func NewBasicCommandSet(commands []Command) CommandSet

NewBasicCommandSet creates a new CommandSet from the given list of command definitions.

func ReadCommands

func ReadCommands(path string) (CommandSet, error)

ReadCommands loads a CommandSet from a YAML file specified by the given path.

type Config

type Config struct {
	Host             string
	Port             int
	AutoConnect      bool
	AllowReconnect   bool
	ReconnectSeconds int
	CommandFile      string
	Commands         CommandSet
	Log              Logger
}

Config holds configuration settings.

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a Config struct with default values.

func ReadConfig

func ReadConfig(source interface{}) (*Config, error)

ReadConfig reads configuration from ini format from the given source. Source can be a path, an opened file or a []byte array.

type ConnectionState

type ConnectionState int

ConnectionState is the type used to describe the connection status for the client.

const (
	Disconnected ConnectionState = iota
	Connecting
	Connected
	Disconnecting
)

func (ConnectionState) String

func (cs ConnectionState) String() string

type Device

type Device struct {
	Host string
	Port int
	// contains filtered or unexported fields
}

Device is an Onkyo device.

func NewDevice

func NewDevice(cfg *Config) *Device

NewDevice sets up a new Onkyo device.

func (*Device) OnConnected

func (d *Device) OnConnected(callback func())

OnConnected is called when the deivce is (re-)connected.

func (*Device) OnDisconnected

func (d *Device) OnDisconnected(callback func())

OnDisconnected is called when the device is disconnected.

func (*Device) OnMessage

func (d *Device) OnMessage(callback Callback)

OnMessage sets the handler for received messages to the given function. This will replace any existing handler.

func (*Device) Query

func (d *Device) Query(name string) error

Query sends a QSTN command for the given friendly name.

This method calls `SendISCP()` behind the scenes.

func (*Device) SendCommand

func (d *Device) SendCommand(name string, param interface{}) error

SendCommand sends an "friendly" command (e.g. "power off") to the device.

This method calls `SendISCP()` behind the scenes.

func (*Device) SendISCP

func (d *Device) SendISCP(cmd ISCPCommand, timeout time.Duration) error

SendISCP sends a raw ISCP command to the device.

You must `Start()` before you can send messages. The device may lose its connection after start. With AutoConnect set to true, attempts to connect and returns an error only if that fails. Without autoconnect, an error is returned if the device is not connected.

The message is send asynchronously. Use a non-zero timeout to wait until the message is sent. Note that the message may still be sent even if `ErrTimeout` is returned.

func (*Device) Start

func (d *Device) Start()

Start connects to the device and starts receiving messages.

func (*Device) Stop

func (d *Device) Stop()

Stop disconnects from the device and stop message processing.

type EISCPMessage

type EISCPMessage struct {
	// contains filtered or unexported fields
}

EISCPMessage is the type for eISCP messages.

func NewEISCPMessage

func NewEISCPMessage(command ISCPCommand) *EISCPMessage

NewEISCPMessage creates a new eISCP message for the given command.

func ParseEISCP

func ParseEISCP(data []byte) (*EISCPMessage, error)

ParseEISCP reads an eISCP message from a byte array.

func (*EISCPMessage) Command

func (e *EISCPMessage) Command() ISCPCommand

Command returns the ISCP command for this message.

func (*EISCPMessage) Raw

func (e *EISCPMessage) Raw() []byte

Raw returns the byte data (header and payload) for this message.

func (*EISCPMessage) String

func (e *EISCPMessage) String() string

type ISCPCommand

type ISCPCommand string

An ISCPCommand is a low-level command like PWR01 (power on) or MVLUP (master volume up).

type ISCPGroup

type ISCPGroup string

ISCPGroup is the 3-digit ISCP command group, e.g. "PWR" or "MVL".

func SplitISCP

func SplitISCP(command ISCPCommand) (ISCPGroup, string)

SplitISCP splits an ISCP command into group and parameter.

type ISCPMessage

type ISCPMessage struct {
	// contains filtered or unexported fields
}

ISCPMessage is the base message for ISCP. The messages consists of: ! - start character 1 - receiver type ... - <command> \r\n - terminator

func NewISCPMessage

func NewISCPMessage(command ISCPCommand) *ISCPMessage

NewISCPMessage creates a new ISCP message with the given command.

func ParseISCP

func ParseISCP(data []byte) (*ISCPMessage, error)

ParseISCP parses an ISCP message from a byte array.

func (*ISCPMessage) Command

func (i *ISCPMessage) Command() ISCPCommand

Command returns the ISCP command for a message.

func (*ISCPMessage) Format

func (i *ISCPMessage) Format() string

Format returns the string representation for an ISCPMessage. Includes terminating newline (CRLF).

func (*ISCPMessage) String

func (i *ISCPMessage) String() string

func (*ISCPMessage) ToEISCP

func (i *ISCPMessage) ToEISCP() *EISCPMessage

ToEISCP converts this message to eISCP format.

type LogLevel

type LogLevel int

LogLevel is the type for log levels.

const (
	// Debug log level
	Debug LogLevel = iota
	// Info log level
	Info
	// Warning log level
	Warning
	// Error log level
	Error
	// NoLog means no messages are logged, regardless of severity
	NoLog
)

type Logger

type Logger interface {
	Debug(msg string, v ...interface{})
	Info(msg string, v ...interface{})
	Warning(msg string, v ...interface{})
	Error(msg string, v ...interface{})
}

Logger is the interface used for logging.

func NewLogger

func NewLogger(level LogLevel) Logger

NewLogger returns a Logger with the given log level.

type MessageHandler

type MessageHandler func(ISCPCommand)

MessageHandler is a callback function to handle incoming messages.

type ParamType

type ParamType string

ParamType is the kind of parameter expcted by a Command.

const (
	// OnOff commands accept only on/off as parameter.
	OnOff ParamType = "onOff"
	// OnOffToggle commands work like on/off but accept an additional "toggle".
	OnOffToggle ParamType = "onOffToggle"
	// Enum based commands expect parameters from a list of values.
	Enum ParamType = "enum"
	// EnumToggle works like Enum but accepts an additional toggle/cycle parameter.
	EnumToggle ParamType = "enumToggle"
	// IntRange accepts an integer value with min and max values.
	IntRange ParamType = "intRange"
	// IntRangeEnum accepts integers and additional values from a list.
	IntRangeEnum ParamType = "intRangeEnum"
)

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL