Skip to content

Commit

Permalink
use telnet for sending commands if enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
splattner committed Oct 31, 2023
1 parent c40295d commit e07d8be
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 48 deletions.
2 changes: 1 addition & 1 deletion pkg/clients/denonavr/denonavrclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func NewDenonAVRClient(i *integration.Integration) *DenonAVRClient {
}

metadata := integration.DriverMetadata{
DriverId: "denonavr-dev",
DriverId: "denonavr",
Developer: integration.Developer{
Name: "Sebastian Plattner",
},
Expand Down
21 changes: 20 additions & 1 deletion pkg/denonavr/attributes.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package denonavr

import "reflect"
import (
"fmt"
"reflect"
)

// Set an attribute and call entity Change function if changed
func (d *DenonAVR) SetAttribute(name string, value interface{}) {

d.attributeMutex.Lock()
defer d.attributeMutex.Unlock()

changed := d.attributes[name] == nil || !reflect.DeepEqual(d.attributes[name], value)

d.attributes[name] = value
Expand All @@ -14,3 +20,16 @@ func (d *DenonAVR) SetAttribute(name string, value interface{}) {
}

}

func (d *DenonAVR) GetAttribute(name string) (interface{}, error) {

d.attributeMutex.Lock()
defer d.attributeMutex.Unlock()

if d.attributes[name] == nil {
return nil, fmt.Errorf("Attribute not Found")
}

return d.attributes[name], nil

}
2 changes: 2 additions & 0 deletions pkg/denonavr/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ func (d *DenonAVR) sendCommandToDevice(cmd DenonCommand, payload string) (int, e
if err != nil {
return 404, err
}

return 200, nil
}

return d.sendHTTPCommand(cmd, payload)
Expand Down
13 changes: 9 additions & 4 deletions pkg/denonavr/denonavr.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ type DenonAVR struct {
zoneStatus map[DenonZone]DenonZoneStatus
netAudioStatus DenonNetAudioStatus

attributes map[string]interface{}
// Attributes
attributes map[string]interface{}
attributeMutex sync.Mutex

updateTrigger chan string

Expand Down Expand Up @@ -157,8 +159,6 @@ func (d *DenonAVR) getMainZoneDataFromDevice() {
func (d *DenonAVR) StartListenLoop() {

log.Info("Start Denon Listen Loop")
//@TOOD: replace "example.net:5555" with address you want to connect to.
//telnet.DialToAndCall(d.Host+":23", d)

updateInterval := 5 * time.Second
ticker := time.NewTicker(updateInterval)
Expand All @@ -169,7 +169,12 @@ func (d *DenonAVR) StartListenLoop() {

// Start listening to telnet
if d.telnetEnabled {
go d.listenTelnet()
go func() {
// just try to reconnect if connection lost
for {
d.listenTelnet()
}
}()
}

// do an intial update to make sure we have up to date values
Expand Down
12 changes: 11 additions & 1 deletion pkg/denonavr/power.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package denonavr

import (
log "github.com/sirupsen/logrus"
)

func (d *DenonAVR) TurnOn() error {
if _, err := d.sendCommandToDevice(DenonCommandPower, "ON"); err != nil {
return err
Expand Down Expand Up @@ -30,7 +34,13 @@ func (d *DenonAVR) TogglePower() error {

func (d *DenonAVR) IsOn() bool {

switch d.mainZoneData.ZonePower {
mainzonepower, err := d.GetAttribute("MainZonePower")
if err != nil {
log.WithError(err).Error("MainZonePower attribute not found")
return false
}

switch mainzonepower.(string) {
case "ON":
return true
default:
Expand Down
86 changes: 46 additions & 40 deletions pkg/denonavr/telnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,54 +20,60 @@ type TelnetEvent struct {
func (d *DenonAVR) handleTelnetEvents() {

for {
select {
case event := <-d.telnetEvents:
log.WithFields(log.Fields{
"cmd": event.Command,
"payload": event.Payload,
}).Debug("received telnet event")

parsedCommand := strings.Split(event.Command, "")
command := parsedCommand[0] + parsedCommand[1]
param := strings.Join(parsedCommand[2:], "")

log.WithFields(log.Fields{
"command": DenonCommand(command),
"param": param,
}).Debug("parsed telnet event")

switch DenonCommand(command) {
case DenonCommandMainZoneVolume:
if param != "MAX" {
log.Debug("Main Zone Volume from telnet")
volume, err := strconv.ParseFloat(param, 32)
log.WithField("volume", volume).Debug("Got volume")
if err != nil {
log.WithError(err).Error("failed to parse volume")
}

if len(param) == 3 {
volume = volume / 10
log.WithField("volume", volume).Debug("Got volume after conversion")
}

log.WithField("volume", fmt.Sprintf("%0.1f", volume-80)).Debug("Got volume")

d.SetAttribute("MainZoneVolume", fmt.Sprintf("%0.1f", volume-80))
event := <-d.telnetEvents
parsedCommand := strings.Split(event.Command, "")
command := parsedCommand[0] + parsedCommand[1]
param := strings.Join(parsedCommand[2:], "")

if event.Command == "OPSTS" {
// ignore this
continue
}

log.WithFields(log.Fields{
"cmd": event.Command,
"payload": event.Payload,
"command": DenonCommand(command),
"param": param,
}).Debug("Telnet Event received")

switch DenonCommand(command) {
case DenonCommandPower:
d.SetAttribute("POWER", param)
case DennonCommandZoneMain:
d.SetAttribute("MainZonePower", param)
case DenonCommandMainZoneVolume:
if param != "MAX" {

volume, err := strconv.ParseFloat(param, 32)
if err != nil {
log.WithError(err).Error("failed to parse volume")
}

case DenonCommandMainZoneMute:
log.Debug("Main Zone Mute from telnet")
d.SetAttribute("MainZoneMute", strings.ToLower(param))
// The Volume command need the following
// 10.5 -> MV105
// 11 -> MV11
if len(param) == 3 {
volume = volume / 10
log.WithField("volume", volume).Debug("Got volume after conversion")
}

d.SetAttribute("MainZoneVolume", fmt.Sprintf("%0.1f", volume-80))
}

case DenonCommandMainZoneMute:
d.SetAttribute("MainZoneMute", strings.ToLower(param))
}
}
}

func (d *DenonAVR) listenTelnet() {

defer func() {
log.Debug("Closing Telnet connection")
d.telnet.Close()
}()

go d.handleTelnetEvents()

var err error
Expand All @@ -87,7 +93,7 @@ func (d *DenonAVR) listenTelnet() {
log.WithError(err).Error("failed to set tcp keep alive period")
}

log.Debug("telnet connected")
log.WithField("host", d.Host+":23").Debug("Telnet connected")

for {
data, err := d.telnet.ReadString('\r')
Expand All @@ -105,6 +111,7 @@ func (d *DenonAVR) listenTelnet() {
event.Payload = parsedData[1]
}

// Fire Event for handling
d.telnetEvents <- &event
}
}
Expand All @@ -113,13 +120,12 @@ func (d *DenonAVR) listenTelnet() {
func (d *DenonAVR) sendTelnetCommand(cmd DenonCommand, payload string) error {

d.telnetMutex.Lock()

defer d.telnetMutex.Unlock()

log.WithFields(log.Fields{
"cmd": string(cmd),
"payload": payload,
}).Debug("send telnet command")
}).Debug("Send Telnet command")

_, err := d.telnet.Write([]byte(string(cmd) + payload + "\r"))

Expand Down
10 changes: 9 additions & 1 deletion pkg/denonavr/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"math"
"strings"

log "github.com/sirupsen/logrus"
)

func (d *DenonAVR) SetVolume(volume float64) error {
Expand Down Expand Up @@ -48,7 +50,13 @@ func (d *DenonAVR) MainZoneMuteToggle() error {

func (d *DenonAVR) MainZoneMuted() bool {

switch d.zoneStatus[MainZone].Mute {
mainZoneMute, err := d.GetAttribute("MainZoneMute")
if err != nil {
log.WithError(err).Debug("MainZoneMute attribute not found")
return false
}

switch mainZoneMute.(string) {
case "on":
return true
default:
Expand Down

0 comments on commit e07d8be

Please sign in to comment.