Difference between revisions of "User:Bulek"

From LinuxMCE
Jump to: navigation, search
Line 1: Line 1:
 +
==== 'Add Ruby snippets to commands'====
 +
 +
I've created new IR/Codeset group called "Marantz SR Multiroom RS232", although I'm not sure how to handle it. Have also edited coresponding Ruby snippets for each command. Basically those are just simple strings that get send on rs232 to take proper action on device according to received command from LinuxMCE... There are also a lot of other functions that help :
 +
- determining for which child zone command is targeted
 +
- to "normalize" volume levels between Marantz's internal dB units and range of 0-100
 +
 +
 +
Simpler commands from Ruby part of template :
 
<pre><nowiki>
 
<pre><nowiki>
Power
 
#193 Off
 
#SendMultiZoneCommand(cmd, ["@PWR:1", "@MSP:1", "@MAM:2"]) SendMultiZonePowerOffCommand(cmd, ["@AMT:2", "@MSP:1", "@MAM:2"])
 
  
#192 On
+
  Power
#SendMultiZoneCommand(cmd, ["@PWR:2", "@MSP:2", "@MAM:1"]) SendMultiZonePowerOnCommand(cmd, ["@AMT:1", "@MSP:2", "@MAM:1"])
+
#193 Off
 +
#SendMultiZoneCommand(cmd, ["@PWR:1", "@MSP:1", "@MAM:2"]) SendMultiZonePowerOffCommand(cmd, ["@AMT:2", "@MSP:1", "@MAM:2"])
 +
 +
#192 On
 +
#SendMultiZoneCommand(cmd, ["@PWR:2", "@MSP:2", "@MAM:1"]) SendMultiZonePowerOnCommand(cmd, ["@AMT:1", "@MSP:2", "@MAM:1"])
 +
 +
#194 Toggle Power
 +
 +
 +
Inputs
 +
#169 AM
 +
SendMultiZoneCommand(cmd, ["@SRC:H", "@MSC:H", "@MSC:H"])
 +
 +
#164 Aux
 +
SendMultiZoneCommand(cmd, ["@SRC:9", "@MSC:9", "@MSC:9"])
 +
 +
#172 Aux 2
 +
SendMultiZoneCommand(cmd, ["@SRC:A", "@MSC:A", "@MSC:A"])
 +
 +
#162 CD
 +
SendMultiZoneCommand(cmd, ["@SRC:C", "@MSC:C", "@MSC:C"])
 +
 +
#420 CDR
 +
SendMultiZoneCommand(cmd, ["@SRC:D", "@MSC:D", "@MSC:D"])
 +
 +
#178 DSS
 +
SendMultiZoneCommand(cmd, ["@SRC:4", "@MSC:4", "@MSC:4"])
 +
 +
#165 DVD
 +
SendMultiZoneCommand(cmd, ["@SRC:2", "@MSC:2", "@MSC:2"])
 +
 +
#170 FM
 +
SendMultiZoneCommand(cmd, ["@SRC:G", "@MSC:G", "@MSC:G"])
 +
 +
#160 Tape / Tape 1
 +
SendMultiZoneCommand(cmd, ["@SRC:E", "@MSC:E", "@MSC:E"])
 +
 +
#166 Tuner
 +
SendMultiZoneCommand(cmd, ["@SRC:F", "@MSC:F", "@MSC:F"])
 +
 +
#161 TV
 +
SendMultiZoneCommand(cmd, ["@SRC:1", "@MSC:1", "@MSC:1"])
 +
 +
#282 VCR-1
 +
SendMultiZoneCommand(cmd, ["@SRC:3", "@MSC:3", "@MSC:3"])
 +
 +
DSP Modes (Audio)
 +
#891 All Ch Stereo
 +
#<$"@SUR:0H\r"$> SendIrCommand("@SUR:0H")
 +
 +
 +
#97 Mute
 +
SendMultiZoneCommand(cmd, ["@AMT:0", "@MSM:0", "@MAM:0"])
 +
 +
 +
#90 Vol Down
 +
SendMultiZoneCommand(cmd, ["@VOL:2", "@MSV:2", "@MVL:2"])
 +
 +
#89 Vol Up
 +
SendMultiZoneCommand(cmd, ["@VOL:1", "@MSV:1", "@MVL:1"])
 +
 +
Speed Ctrl
 +
#125 Scan Back/Rewind
 +
</nowiki></pre>
 +
 
 +
 
 +
More important parts with more Ruby code :
 +
 
 +
<pre><nowiki>
 +
###########################################################3 Internal Methods
 +
# To do list :
 +
# - parsing of input messages (inputs,mute,volume,power)
 +
# - handling of tuner (with live/TV child device)
 +
# - to properly send events and set device current volume data
 +
 
 +
def DecodeReceivedInfo_candidate(response)
 +
# Examples: Mute/On/Off: @AMT:1,@MSP:2,@MAM:2,  Volume: @VOL:-25,@MSV:-56,@MVL:-56  Inputs:@MSC:2E,@SRC:22,@SRC:2E
 +
  log("DecodeReceivedInfo1: " + response + "\n");
 +
  avrcommand = response[1..3]
 +
  avrvalue = response[5]
 +
  log("DecodeReceivedInfo2: " + response + " -> Command:"+ avrcommand.to_s + " Value: " + avrvalue.to_s + "\n");
 +
 
 +
  case avrcommand
 +
# Input Source changed
 +
    when 'SRC'
 +
    log("Main Zone Input Changed to "+ avrvalue.to_s+ "\n");
 +
    input_param=0
 +
   
 +
    case avrvalue
 +
    when '1'
 +
    log('Main Zone Input Changed to #161: TV')
 +
    input_param=161
 +
    temp_state="Input: TV"
 +
    when '2'
 +
    log('Main Zone Input Changed to #165: DVD')
 +
    input_param=165
 +
    temp_state="Input: TV"
 +
    when '3'
 +
    log('Main Zone Input Changed to #282: VCR-1')
 +
    input_param=282
 +
    temp_state="Input: TV"
 +
    when '4'
 +
    log('Main Zone Input Changed to #178: DSS')
 +
    input_param=178
 +
    temp_state="Input: TV"
 +
    when '9'
 +
    log('Main Zone Input Changed to #164: AUX')
 +
    input_param=164
 +
    temp_state="Input: TV"
 +
    when 'A'
 +
    log('Main Zone Input Changed to #171: AUX2')
 +
    input_param=171
 +
    temp_state="Input: TV"
 +
    when 'C'
 +
    log('Main Zone Input Changed to #162: CD')
 +
    input_param=162
 +
    temp_state="Input: TV"
 +
    when 'D'
 +
    log('Main Zone Input Changed to #420: CDR')
 +
    input_param=420
 +
    temp_state="Input: TV"
 +
    when 'E'
 +
    log('Main Zone Input Changed to #160: TAPE')
 +
    input_param=160
 +
    temp_state="Input: TV"
 +
    when 'F'
 +
    log('Main Zone Input Changed to #166: TUNER')
 +
    input_param=166
 +
    temp_state="Input: TV"
 +
    when 'G'
 +
    log('Main Zone Input Changed to #170: FM')
 +
    input_param=160
 +
    temp_state="Input: TV"
 +
    when 'H'
 +
    log('Main Zone Input Changed to #169: AM')
 +
    input_param=169
 +
    temp_state="Input: TV"
 +
    end
 +
#    device_id = device_.mapPortChannel_Device_.[0.to_s]
 +
log("======= Determiming device ID for Zone 0 : " + device_id.to_s + "\n")
 +
device_.mapPortChannel_Device_.each do |key, value|
 +
log(key.to_s + " => " + value.to_s+ "\n")
 +
end
 +
    cmd = Command.new(device_id, -1001, 1, 2, 49);
 +
    cmd.params_[41] = input_param.to_s();
 +
    SendCommand(cmd);
 +
    SetDeviceDataInDB( device_id, 200, temp_state ) # 200 = DEVICEDATA_State_CONST
 +
 
 +
    when 'VOL'
 +
    volume = response[5..-1].to_i();
 +
    volume_norm = NormalizeVolume_MainZone(volume)
 +
    log("Main Zone Volume Changed: " + volume.to_s + " Normalized Value: " + volume_norm.to_s + "\n");
 +
#    device_id = device_.mapPortChannel_Device_.[0.to_s]
 +
log("======= Determiming device ID for Zone 0 : " + device_id.to_s + "\n")
 +
device_.mapPortChannel_Device_.each do |key, value|
 +
log(key.to_s + " => " + value.to_s+ "\n")
 +
end
 +
    SetDeviceDataInDB( device_id, 158, volume_norm ) # 158 = DEVICEDATA_Volume_Level_CONST
 +
    cmd = Command.new(device_id, -1001, 1, 2, 71);
 +
    cmd.params_[30] = volume_norm
 +
    SendCommand(cmd);
 +
    when 'PWR'
 +
    case avrvalue
 +
    when '1'
 +
    log("Device Power Changed: OFF");
 +
    cmd.params_[10] = "0";
 +
    $DevicePower = 0
 +
    when '2'
 +
    log("Device Power Changed: ON");
 +
    cmd.params_[10] = "1";
 +
    $DevicePower = 1
 +
    end
 +
    cmd = Command.new(device_.devid_, -1001, 1, 2, 48);
 +
    SendCommand(cmd);
 +
    else
 +
    log("Yet not implemented: Handler for command: " + avrcommand.to_s)
 +
    end
 +
   
 +
end   
 +
 
 +
 
 +
def DecodeReceivedInfo(response)
 +
# Examples: Mute/On/Off: @AMT:1,@MSP:2,@MAM:2,  Volume: @VOL:-25,@MSV:-56,@MVL:-56  Inputs:@MSC:2E,@SRC:22,@SRC:2E
 +
  log("DecodeReceivedInfo1: " + response + "\n");
 +
  avrcommand = response[1..3]
 +
  avrvalue = response[5]
 +
  log("DecodeReceivedInfo2: " + response + " -> Command:"+ avrcommand.to_s + " Value: " + avrvalue.to_s + "\n");
 +
 
 +
  case avrcommand
 +
    when 'VOL'
 +
    volume = response[5..-1].to_i();
 +
    volume_norm = NormalizeVolume_MainZone(volume)
 +
    log("Main Zone Volume Changed: " + volume.to_s + " Normalized Value: " + volume_norm.to_s + "\n");
 +
#    device_id = device_.mapPortChannel_Device_.[0.to_s]
 +
log("======= Determiming device ID for Zone 0 : " + device_id.to_s + "\n")
 +
device_.mapPortChannel_Device_.each do |key, value|
 +
log(key.to_s + " => " + value.to_s+ "\n")
 +
if (key.to_s == "0")
 +
device_id = value
 +
end
 +
end
 +
    SetDeviceDataInDB( device_id, 158, volume_norm ) # 158 = DEVICEDATA_Volume_Level_CONST
 +
    cmd = Command.new(device_id, -1001, 1, 2, 71);
 +
    cmd.params_[30] = volume_norm
 +
    SendCommand(cmd);
 +
    when 'PWR'
 +
    case avrvalue
 +
    when '1'
 +
    log("Device Power Changed: OFF")
 +
    cmd.params_[10] = "0";
 +
    $DevicePower = 0
 +
    when '2'
 +
    log("Device Power Changed: ON");
 +
    cmd.params_[10] = "1";
 +
    $DevicePower = 1
 +
    end
 +
    cmd = Command.new(device_.devid_, -1001, 1, 2, 48);
 +
    SendCommand(cmd);
 +
    else
 +
    log("Yet not implemented: Handler for command: " + avrcommand.to_s)
 +
    end
 +
   
 +
end   
 +
 
 +
 
 +
def ReceiveReportCommand()
 +
@buff = conn_.RecvDelimited("\r", 1000)
 +
log("Cmd response from Marantz: " + @buff + "\n")
 +
log("Calling DecodeReceivedInfo: " + @buff + "\n")
 +
temp_resp=@buff;
 +
DecodeReceivedInfo(temp_resp)
 +
log("End of DecodeReceivedInfo: " + temp_resp + "\n")
 +
end
 +
 
 +
def SendIrCommand(command)
 +
        log("SendIrCommand: " + command + "\n")
 +
conn_.Send(command+ "\r")
 +
        log("Sending Command: " + command + "\n")
 +
ReceiveReportCommand()
 +
end
 +
 
 +
def log(line)
 +
#          $log = File.open("/var/log/pluto/" + device_.devid_.to_s + "_Generic_Serial_Device.log", "a")
 +
  $log = File.open("/var/log/pluto/Marantz_SR5600.log", "a")
 +
  logTime = Time.now
 +
  timeStr = logTime.strftime("%d-%m-%Y  %H:%M:%S  ")
 +
 
 +
  $log.puts timeStr + "(***):" + line.to_s
 +
          $log.close
 +
end
 +
 
 +
def SendMultiZoneCommand(cmd, commandsArray, commandParam="")
 +
        log("Got Command with ID: " + cmd.id_.to_s + " from: " + cmd.devidfrom_.to_s + " to: " + cmd.devidto_.to_s + "\n")
 +
zone = GetZone(cmd.devidto_)
 +
if( zone >= 0 and zone < commandsArray.size )
 +
        zone_desc=device_.childdevices_[cmd.devidto_].devdata_[186]
 +
log("Determine zone for command : " + zone_desc + "[" + zone.to_s + "]\n")
 +
SendIrCommand(commandsArray[zone] + commandParam.to_s)
 +
else
 +
log("SendMultiZoneCommand: invalid zone " + zone.to_s + ". Send commands only to valid child devices!!!")
 +
end
 +
end
 +
 
 +
 
 +
def SendMultiZonePowerOnCommand(cmd, commandsArray, commandParam="")
 +
#It will Unmute Zone first and then see also global power should be turned on...
 +
        log("Got Power On Command with ID: " + cmd.id_.to_s + " from: " + cmd.devidfrom_.to_s + " to: " + cmd.devidto_.to_s + "\n")
 +
zone = GetZone(cmd.devidto_)
 +
if( zone >= 0 and zone < commandsArray.size )
 +
        zone_desc=device_.childdevices_[cmd.devidto_].devdata_[186]
 +
log("Determine zone for command : " + zone_desc + "[" + zone.to_s + "]\n")
 +
SendIrCommand(commandsArray[zone] + commandParam.to_s)
 +
$ZoneStatus[zone.to_s] = 'ON'
 +
log("*** Setting zone : " + zone_desc + "[" + zone.to_s + "] to ON\n")
 +
ShowZones()
 +
if ($DevicePower == 0)
 +
SendIrCommand("@PWR:2")
 +
end
 +
$DevicePower = 1
 +
elsif (zone == -1)
 +
if ($DevicePower == 0)
 +
SendIrCommand("@PWR:2")
 +
end
 +
$DevicePower = 1
 +
log("####### Powering device On\n")
 +
else
 +
log("SendMultiZonePowerOnCommand: invalid zone " + zone.to_s + ". Send commands only to valid child devices!!!")
 +
end
 +
end
 +
 
 +
def SendMultiZonePowerOffCommand(cmd, commandsArray, commandParam="")
 +
#It will Mute Zone first and then see if also global power can be turned off...
 +
        log("Got Power Off Command with ID: " + cmd.id_.to_s + " from: " + cmd.devidfrom_.to_s + " to: " + cmd.devidto_.to_s + "\n")
 +
zone = GetZone(cmd.devidto_)
 +
if( zone >= 0 and zone < commandsArray.size )
 +
        zone_desc=device_.childdevices_[cmd.devidto_].devdata_[186]
 +
log("Determine zone for command : " + zone_desc + "[" + zone.to_s + "]\n")
 +
SendIrCommand(commandsArray[zone] + commandParam.to_s)
 +
$ZoneStatus[zone.to_s] = 'OFF'
 +
log("*** Setting zone : " + zone_desc + "[" + zone.to_s + "] to OFF\n")
 +
ShowZones()
 +
if (($ZoneStatus["0"] == 'OFF') and ($ZoneStatus["1"] == 'OFF') and ($ZoneStatus["2"] == 'OFF'))
 +
SendIrCommand("@PWR:1")
 +
$DevicePower = 0
 +
log("####### All zones are muted - device is powered Off\n")
 +
end
 +
else
 +
log("SendMultiZonePowerOffCommand: invalid zone " + zone.to_s + ". Send commands only to valid child devices!!!")
 +
end
 +
end
 +
 
 +
 
 +
def GetZone(deviceDestination)
 +
if( device_.mapDevice_PortChannel_.has_key?(deviceDestination) and
 +
device_.mapDevice_PortChannel_[deviceDestination] != nil and
 +
!device_.mapDevice_PortChannel_[deviceDestination].empty? )
 +
return device_.mapDevice_PortChannel_[deviceDestination].to_i
 +
end
 +
 +
return -1
 +
end
 +
 
 +
def ShowZonesDebug()
 +
log("####### Dev 2 PortChanel\n")
 +
device_.mapDevice_PortChannel_.each do |key, value|
 +
log(key.to_s + " => " + value.to_s + "\n")
 +
end
 +
 +
log("======= PortChanel 2 Dev\n")
 +
device_.mapPortChannel_Device_.each do |key, value|
 +
log(key.to_s + " => " + value.to_s+ "\n")
 +
end
 +
end
 +
 
 +
 
 +
 
 +
def ShowZonesInitialVolumes()
 +
log("####### Show Initial Volume Levels for zones\n")
 +
device_.mapDevice_PortChannel_.each do |key, value|
 +
        volume = device_.childdevices_[key].devdata_[208]
 +
log("Zone " + value.to_s + " => " + volume.to_s + "\n")
 +
SetVolumeInZone(volume,value)
 +
end
 +
 +
end
 +
 
 +
 
 +
def ShowZones()
 +
temp = "####### Zones Status : "
 +
device_.mapDevice_PortChannel_.each do |key, value|
 +
temp = temp + " | Zone " + value.to_s + " => " + $ZoneStatus[value]
 +
end
 +
temp = temp + "\n"
 +
log(temp)
 +
end
 +
 
 +
 
 +
def SetZones(state)
 +
log("####### Setting all zones to " + state + "\n")
 +
device_.mapDevice_PortChannel_.each do |key, value|
 +
$ZoneStatus[value] = state
 +
log("Zone " + value.to_s + " => " + state + "\n")
 +
end
 +
end
 +
 
 +
def InitZones()
 +
log("####### Initializing all zones to OFF\n")
 +
device_.mapDevice_PortChannel_.each do |key, value|
 +
$ZoneStatus[value] = 'OFF'
 +
log("Zone " + value.to_s + " => " + $ZoneStatus[value] + "\n")
 +
end
 +
log("####### Print $ZoneStatus Hash:\n")
 +
$ZoneStatus.each do |key, value|
 +
log("Zone " + key.to_s + " => " + value.to_s + "\n")
 +
end
 +
end
 +
 
 +
def SetVolumeInZone(level,zone)
 +
# Sets Normalized Volume Level (0..100) in certain zone
 +
log("SetVolumeInZone: volume: " + level.to_s + " => Zone: " + zone + "\n")
 +
 
 +
if ( zone == "0")
 +
log("SetVolumeInZone0: volume: " + level.to_s + " => Zone: " + zone + "\n")
 +
      new_level = DeNormalizeVolume_MainZone(level.to_i)
 +
log("SetVolumeInZone00: volume: " + level.to_s + " => Zone: " + zone + "\n")
 +
      temp_str="@VOL:0"+new_level.to_s;
 +
      log("SetVolumeInZone: About to send command :" + temp_str + "\n")
 +
      SendIrCommand(temp_str)
 +
elsif ( zone == "1")
 +
log("SetVolumeInZone1: volume: " + level.to_s + " => Zone: " + zone + "\n")
 +
      new_level = DeNormalizeVolume_OtherZone(level.to_i)
 +
log("SetVolumeInZone11: volume: " + level.to_s + " => Zone: " + zone + "\n")
 +
      temp_str="@MSV:0"+new_level.to_s;
 +
      log("SetVolumeInZone: About to send command :" + temp_str + "\n")
 +
      SendIrCommand(temp_str)
 +
elsif ( zone == "2")
 +
log("SetVolumeInZone2: volume: " + level.to_s + " => Zone: " + zone + "\n")
 +
      new_level = DeNormalizeVolume_OtherZone(level.to_i)
 +
# log("SetVolumeInZone22: volume: " + level + " => Zone: " + zone + "\n")
 +
      temp_str="@MVL:0"+new_level.to_s;
 +
      log("SetVolumeInZone: About to send command :" + temp_str + "\n")
 +
      SendIrCommand(temp_str)
 +
else
 +
      log("SetVolumeInZone: invalid zone " + zone.to_s + ". Send commands only to valid child devices!!!")
 +
end
 +
log("SetVolumeInZone End: volume: " + level.to_s + " => Zone: " + zone + "\n")
 +
 
 +
end
 +
 
 +
 
 +
def NormalizeVolume_MainZone(level)
 +
# Normalizes Marantz Volume Level (-99..+10) to 0-100 boundaries for Main Zone
 +
temp = (level+100)/110.0*100.0
 +
temp=temp.round
 +
        log("Normalizing Main Zone Volume Level from : " + level.to_s + " to " + temp.to_s + "\n")
 +
return temp
 +
end
 +
 
 +
def NormalizeVolume_OtherZone(level)
 +
# Normalizes Marantz Volume Level to 0-100 boundaries for Second Zone (-90..0)
 +
temp = ((level+90.0)/90.0)*100.0
 +
temp=temp.round
 +
        log("Normalizing Other Zone Volume Level from : " + level.to_s + " to " + temp.to_s + "\n")
 +
return temp
 +
end
 +
 
 +
def DeNormalizeVolume_MainZone(level)
 +
# DeNormalizes volume level in 0-100 boundaries to Marantz Volume Level (-99..+10) for Main Zone
 +
temp = (level/100.0)*110.0-99
 +
temp=temp.round
 +
        log("DeNormalizing Main Zone Volume Level from : " + level.to_s + " to " + temp.to_s + "\n")
 +
return temp
 +
end
 +
 
 +
def DeNormalizeVolume_OtherZone(level)
 +
# DeNormalizes volume level in 0-100 boundaries to Marantz Volume Level (-90..0) for Other Zone
 +
temp = ((level/100.0)*90.0)-90.0
 +
temp=temp.round
 +
        log("DeNormalizing Other Zone Volume Level from : " + level.to_s + " to " + temp.to_s + "\n")
 +
return temp
 +
end
 +
 
 +
 
 +
 
 +
 
 +
 
 +
 
 +
 
 +
 
 +
 
 +
 
  
#194 Toggle Power
 
 
  
Inputs
+
###########################################################Process Incoming Data
#164 Aux
+
@buff = conn_.RecvDelimited("\r", 1000)
SendMultiZoneCommand(cmd, ["@SRC:9", "@MSC:9", "@MSC:9"])
+
log("Info from Marantz: " + @buff + "\n")
 +
temp_line=@buff
 +
log("1Calling DecodeReceivedInfo: " + temp_line + "\n")
 +
DecodeReceivedInfo(temp_line)
 +
log("1End of DecodeReceivedInfo: " + temp_line+ "\n")
  
#172 Aux 2
 
SendMultiZoneCommand(cmd, ["@SRC:A", "@MSC:A", "@MSC:A"])
 
  
#162 CD
 
SendMultiZoneCommand(cmd, ["@SRC:C", "@MSC:C", "@MSC:C"])
 
  
#420 CDR
+
###########################################################Set Tuner Frequency
SendMultiZoneCommand(cmd, ["@SRC:D", "@MSC:D", "@MSC:D"])
+
identifier = cmd.params_[216]
 +
# Main Frequency "TFQ:0xxxxx" from 08700 till + 10800
 +
# Multiroom Frequency “MTF:0xxxxx“  from 08700 till + 10800
  
#178 DSS
+
# switch to tuner mode first
SendMultiZoneCommand(cmd, ["@SRC:4", "@MSC:4", "@MSC:4"])
+
SendMultiZoneCommand(cmd, ["@SRC:G", "@MSC:G", "@MSC:G"])
  
#165 DVD
+
# tune to desired frequency
SendMultiZoneCommand(cmd, ["@SRC:2", "@MSC:2", "@MSC:2"])
+
SendMultiZoneCommand(cmd, ["@TFQ:0"+identifier, "@MTF:0"+identifier, "@MTF:0"+identifier])
 +
log("Sending Marantz : Setting tuner frequency to "+identifier+"\n")
  
#170 FM
 
SendMultiZoneCommand(cmd, ["@SRC:G", "@MSC:G", "@MSC:G"])
 
  
#160 Tape / Tape 1
+
###########################################################313 Set Volume command
SendMultiZoneCommand(cmd, ["@SRC:E", "@MSC:E", "@MSC:E"])
+
level = cmd.params_[76]
 +
# Main volume “VOL:0xxx”  from - 99 till + 18
 +
# Multiroom Speakers "MSV:0xxx"  from - 99 till + 0
 +
# Multiroom Speakers “MVL:0xxx”  from - 99 till + 0
 +
zone = GetZone(cmd.devidto_)
 +
log("313:Set Volume Command: Got Cmd with ID: " + cmd.id_.to_s + " from: " + cmd.devidfrom_.to_s + " to: " + cmd.devidto_.to_s + " | Zone : " + zone.to_s + "\n")
 +
if ( zone == 0)
 +
      new_level = DeNormalizeVolume_MainZone(level.to_i)
 +
      temp_str = "@VOL:0"+new_level.to_s
 +
      log("SetVolumeCommand: About to send command :" + temp_str + "\n")
 +
      SendIrCommand(temp_str)
 +
elsif ( zone == 1)
 +
      new_level = DeNormalizeVolume_OtherZone(level.to_i)
 +
      temp_str = "@MSV:0"+new_level.to_s
 +
      SendIrCommand(temp_str)
 +
elsif ( zone == 2)
 +
      new_level = DeNormalizeVolume_OtherZone(level.to_i)
 +
      temp_str = "@MVL:0"+new_level.to_s
 +
      log("SetVolumeCommand: About to send command :" + temp_str + "\n")
 +
      SendIrCommand(temp_str)
  
#166 Tuner
+
else
SendMultiZoneCommand(cmd, ["@SRC:F", "@MSC:F", "@MSC:F"])
+
      log("SetVolumeCommand: invalid zone " + zone.to_s + ":" + zone.to_i + ". Send commands only to valid child devices!!!\n")
 +
end
  
#161 TV
 
SendMultiZoneCommand(cmd, ["@SRC:1", "@MSC:1", "@MSC:1"])
 
  
#282 VCR-1
 
SendMultiZoneCommand(cmd, ["@SRC:3", "@MSC:3", "@MSC:3"])
 
  
DSP Modes (Audio)
 
#891 All Ch Stereo
 
#<$"@SUR:0H\r"$> SendIrCommand("@SUR:0H")
 
  
Internal
 
#373 Private Method Listing
 
          def ReceiveReportCommand()
 
          buff = conn_.RecvDelimited("\r", 1000)
 
          log("Cmd response from Marantz: " + buff + "\n")
 
          end
 
         
 
          def SendIrCommand(command)
 
                  log("SendIrCommand: " + command + "\n")
 
          conn_.Send(command+ "\r")
 
                  log("Sending Command: " + command + "\n")
 
          ReceiveReportCommand()
 
          end
 
         
 
          def log_older(word)
 
          logTime = Time.now
 
          timeStr = logTime.strftime("%d-%m-%Y  %H:%M:%S  ")
 
         
 
          print( timeStr + " " + word)
 
          if( $logFile.nil? == false ) then
 
          $logFile.print( timeStr + " " + word )
 
          $logFile.flush()
 
          end
 
          end
 
         
 
          def log(line)
 
          #          $log = File.open("/var/log/pluto/" + device_.devid_.to_s + "_Generic_Serial_Device.log", "a")
 
            $log = File.open("/var/log/pluto/Marantz_SR5600.log", "a")
 
            logTime = Time.now
 
            timeStr = logTime.strftime("%d-%m-%Y  %H:%M:%S  ")
 
         
 
            $log.puts timeStr + "(***):" + line.to_s
 
                    $log.close
 
          end
 
         
 
          def SendMultiZoneCommand(cmd, commandsArray, commandParam="")
 
                  log("Got Command with ID: " + cmd.id_.to_s + " from: " + cmd.devidfrom_.to_s + " to: " + cmd.devidto_.to_s + "\n")
 
          zone = GetZone(cmd.devidto_)
 
          if( zone >= 0 and zone < commandsArray.size )
 
                  zone_desc=device_.childdevices_[cmd.devidto_].devdata_[186]
 
          log("Determine zone for command : " + zone_desc + "[" + zone.to_s + "]\n")
 
          SendIrCommand(commandsArray[zone] + commandParam.to_s)
 
          else
 
          log("SendMultiZoneCommand: invalid zone " + zone.to_s + ". Send commands only to valid child devices!!!")
 
          end
 
          end
 
         
 
         
 
          def SendMultiZonePowerOnCommand(cmd, commandsArray, commandParam="")
 
          #It will Unmute Zone first and then see also global power should be turned on...
 
                  log("Got Power On Command with ID: " + cmd.id_.to_s + " from: " + cmd.devidfrom_.to_s + " to: " + cmd.devidto_.to_s + "\n")
 
          zone = GetZone(cmd.devidto_)
 
          if( zone >= 0 and zone < commandsArray.size )
 
                  zone_desc=device_.childdevices_[cmd.devidto_].devdata_[186]
 
          log("Determine zone for command : " + zone_desc + "[" + zone.to_s + "]\n")
 
          SendIrCommand(commandsArray[zone] + commandParam.to_s)
 
          $ZoneStatus[zone.to_s] = 'ON'
 
          log("*** Setting zone : " + zone_desc + "[" + zone.to_s + "] to ON\n")
 
          ShowZones()
 
          if ($DevicePower == 0)
 
          SendIrCommand("@PWR:2")
 
          end
 
          $DevicePower = 1
 
          elsif (zone == -1)
 
          if ($DevicePower == 0)
 
          SendIrCommand("@PWR:2")
 
          end
 
          $DevicePower = 1
 
          log("####### Powering device On\n")
 
          else
 
          log("SendMultiZonePowerOnCommand: invalid zone " + zone.to_s + ". Send commands only to valid child devices!!!")
 
          end
 
          end
 
         
 
          def SendMultiZonePowerOffCommand(cmd, commandsArray, commandParam="")
 
          #It will Mute Zone first and then see if also global power can be turned off...
 
                  log("Got Power Off Command with ID: " + cmd.id_.to_s + " from: " + cmd.devidfrom_.to_s + " to: " + cmd.devidto_.to_s + "\n")
 
          zone = GetZone(cmd.devidto_)
 
          if( zone >= 0 and zone < commandsArray.size )
 
                  zone_desc=device_.childdevices_[cmd.devidto_].devdata_[186]
 
          log("Determine zone for command : " + zone_desc + "[" + zone.to_s + "]\n")
 
          SendIrCommand(commandsArray[zone] + commandParam.to_s)
 
          $ZoneStatus[zone.to_s] = 'OFF'
 
          log("*** Setting zone : " + zone_desc + "[" + zone.to_s + "] to OFF\n")
 
          ShowZones()
 
          if (($ZoneStatus["0"] == 'OFF') and ($ZoneStatus["1"] == 'OFF') and ($ZoneStatus["2"] == 'OFF'))
 
          SendIrCommand("@PWR:1")
 
          $DevicePower = 0
 
          log("####### All zones are muted - device is powered Off\n")
 
          end
 
          else
 
          log("SendMultiZonePowerOffCommand: invalid zone " + zone.to_s + ". Send commands only to valid child devices!!!")
 
          end
 
          end
 
         
 
         
 
          def GetZone(deviceDestination)
 
          if( device_.mapDevice_PortChannel_.has_key?(deviceDestination) and
 
          device_.mapDevice_PortChannel_[deviceDestination] != nil and
 
          !device_.mapDevice_PortChannel_[deviceDestination].empty? )
 
          return device_.mapDevice_PortChannel_[deviceDestination].to_i
 
          end
 
         
 
          return -1
 
          end
 
         
 
          def ShowZonesDebug()
 
          log("####### Dev 2 PortChanel\n")
 
          device_.mapDevice_PortChannel_.each do |key, value|
 
          log(key.to_s + " => " + value.to_s + "\n")
 
          end
 
         
 
          log("======= PortChanel 2 Dev\n")
 
          device_.mapPortChannel_Device_.each do |key, value|
 
          log(key.to_s + " => " + value.to_s+ "\n")
 
          end
 
          end
 
         
 
          def ShowZonesInitialVolumes()
 
          log("####### Show Initial Volume Levels for zones\n")
 
          device_.mapDevice_PortChannel_.each do |key, value|
 
                  volume = device_.childdevices_[key].devdata_[208]
 
          log("Zone " + value.to_s + " => " + volume.to_s + "\n")
 
          SetVolumeInZone(volume,value)
 
          end
 
         
 
          end
 
         
 
         
 
          def ShowZones()
 
          temp = "####### Zones Status : "
 
          device_.mapDevice_PortChannel_.each do |key, value|
 
          temp = temp + " | Zone " + value.to_s + " => " + $ZoneStatus[value]
 
          end
 
          temp = temp + "\n"
 
          log(temp)
 
          end
 
         
 
         
 
          def SetZones(state)
 
          log("####### Setting all zones to " + state + "\n")
 
          device_.mapDevice_PortChannel_.each do |key, value|
 
          $ZoneStatus[value] = state
 
          log("Zone " + value.to_s + " => " + state + "\n")
 
          end
 
          end
 
         
 
          def InitZones()
 
          log("####### Initializing all zones to OFF\n")
 
          device_.mapDevice_PortChannel_.each do |key, value|
 
          $ZoneStatus[value] = 'OFF'
 
          log("Zone " + value.to_s + " => " + $ZoneStatus[value] + "\n")
 
          end
 
          log("####### Print $ZoneStatus Hash:\n")
 
          $ZoneStatus.each do |key, value|
 
          log("Zone " + key.to_s + " => " + value.to_s + "\n")
 
          end
 
          end
 
         
 
          def SetVolumeInZone(level,zone)
 
          # Sets Normalized Volume Level (0..100) in certain zone
 
          log("SetVolumeInZone: volume: " + level.to_s + " => Zone: " + zone + "\n")
 
         
 
          if ( zone == "0")
 
          log("SetVolumeInZone0: volume: " + level.to_s + " => Zone: " + zone + "\n")
 
                new_level = DeNormalizeVolume_MainZone(level.to_i)
 
          log("SetVolumeInZone00: volume: " + level.to_s + " => Zone: " + zone + "\n")
 
                temp_str="@VOL:0"+new_level.to_s;
 
                log("SetVolumeInZone: About to send command :" + temp_str + "\n")
 
                SendIrCommand(temp_str)
 
          elsif ( zone == "1")
 
          log("SetVolumeInZone1: volume: " + level.to_s + " => Zone: " + zone + "\n")
 
                new_level = DeNormalizeVolume_OtherZone(level.to_i)
 
          log("SetVolumeInZone11: volume: " + level.to_s + " => Zone: " + zone + "\n")
 
                temp_str="@MSV:0"+new_level.to_s;
 
                log("SetVolumeInZone: About to send command :" + temp_str + "\n")
 
                SendIrCommand(temp_str)
 
          elsif ( zone == "2")
 
          log("SetVolumeInZone2: volume: " + level.to_s + " => Zone: " + zone + "\n")
 
                new_level = DeNormalizeVolume_OtherZone(level.to_i)
 
          # log("SetVolumeInZone22: volume: " + level + " => Zone: " + zone + "\n")
 
                temp_str="@MVL:0"+new_level.to_s;
 
                log("SetVolumeInZone: About to send command :" + temp_str + "\n")
 
                SendIrCommand(temp_str)
 
          else
 
                log("SetVolumeInZone: invalid zone " + zone.to_s + ". Send commands only to valid child devices!!!")
 
          end
 
          log("SetVolumeInZone End: volume: " + level.to_s + " => Zone: " + zone + "\n")
 
         
 
          end
 
         
 
         
 
          def NormalizeVolume_MainZone(level)
 
          # Normalizes Marantz Volume Level (-99..+10) to 0-100 boundaries for Main Zone
 
          temp = (level+100)/110.0*100.0
 
                  log("Normalizing Main Zone Volume Level from : " + level.to_s + " to " + temp.to_s + "\n")
 
          return temp.round
 
          end
 
         
 
          def NormalizeVolume_OtherZone(level)
 
          # Normalizes Marantz Volume Level to 0-100 boundaries for Second Zone (-90..0)
 
          temp = ((level+90.0)/90.0)*100.0
 
                  log("Normalizing Other Zone Volume Level from : " + level.to_s + " to " + temp.to_s + "\n")
 
          return temp.round
 
          end
 
         
 
          def DeNormalizeVolume_MainZone(level)
 
          # DeNormalizes volume level in 0-100 boundaries to Marantz Volume Level (-99..+10) for Main Zone
 
          temp = (level/100.0)*110.0-99
 
                  log("DeNormalizing Main Zone Volume Level from : " + level.to_s + " to " + temp.to_s + "\n")
 
          return temp.round
 
          end
 
         
 
          def DeNormalizeVolume_OtherZone(level)
 
          # DeNormalizes volume level in 0-100 boundaries to Marantz Volume Level (-90..0) for Other Zone
 
          temp = ((level/100.0)*90.0)-90.0
 
                  log("DeNormalizing Other Zone Volume Level from : " + level.to_s + " to " + temp.to_s + "\n")
 
          return temp.round
 
          end
 
#351 Process IDLE
 
ShowZones()
 
  
#350 Process Incoming Data
 
buff = conn_.RecvDelimited("\r", 1000) print "Info from Marantz: " + buff + "\n" log("Info from Marantz: " + buff + "\n")
 
  
#355 Process Initialize
 
$DevicePower = 1 SendIrCommand("@PWR:2") log("Initializing Marantz GSD Device\n") SendIrCommand("@AST:F") # max level of feedback SendIrCommand("@MPW:2") # multi room always on SendIrCommand("@MSP:1") # turn multi room speakers off by default SendIrCommand("@MAM:2") # mute multi room line out by default SendIrCommand("@VOL:0-20") # default main volume -20 SendIrCommand("@MSV:0-60") # default multi speaker volume SendIrCommand("@MVL:0-60") # default multi room line out volume $ZoneStatus = Hash.new() InitZones() ShowZonesInitialVolumes() #$DevicePower = 0 #SendIrCommand("@PWR:1") log("Initialization of Marantz GSD Device finished - Device is powered off!!!!\n")
 
  
#384 Process Receive Command For Child
+
###########################################################Process Initialize
+
$DevicePower = 1
 +
SendIrCommand("@PWR:2")
 +
log("Initializing Marantz GSD Device\n")
  
#356 Process Release
 
log("Shutting down Marantz GSD Device\n") SendIrCommand("@MAM:2") SendIrCommand("@MSP:1") log("Sending Marantz : Power Off: PWR:1\n") SendIrCommand("@PWR:1")
 
  
Misc
 
#587 Preset/Prog/Freq
 
identifier = cmd.params_[216] # Main Frequency "TFQ:0xxxxx" from 08700 till + 10800 # Multiroom Frequency “MTF:0xxxxx“ from 08700 till + 10800 # switch to tuner mode first SendMultiZoneCommand(cmd, ["@SRC:G", "@MSC:G", "@MSC:G"]) # tune to desired frequency SendMultiZoneCommand(cmd, ["@TFQ:0"+identifier, "@MTF:0"+identifier, "@MTF:0"+identifier]) log("Sending Marantz : Setting tuner frequency to "+identifier+"\n")
 
  
Simple Control
+
SendIrCommand("@AST:F") # max level of feedback
#64 Skip Back - Channel/Track Lower
+
+
  
#63 Skip Fwd - Channel/Track Greater
+
SendIrCommand("@MPW:2") # multi room always on
+
  
Sound & Volume
+
SendIrCommand("@MSP:1") # turn multi room speakers off by default
#97 Mute
+
SendMultiZoneCommand(cmd, ["@AMT:0", "@MSM:0", "@MAM:0"])
+
  
#313 Set Volume
+
SendIrCommand("@MAM:2") # mute multi room line out by default
level = cmd.params_[76] # Main volume “VOL:0xxx” from - 99 till + 18 # Multiroom Speakers "MSV:0xxx" from - 99 till + 0 # Multiroom Speakers “MVL:0xxx” from - 99 till + 0 zone = GetZone(cmd.devidto_) log("313:Set Volume Command: Got Cmd with ID: " + cmd.id_.to_s + " from: " + cmd.devidfrom_.to_s + " to: " + cmd.devidto_.to_s + " | Zone : " + zone.to_s + "\n") if ( zone == 0) new_level = DeNormalizeVolume_MainZone(level.to_i) temp_str = "@VOL:0"+new_level.to_s log("SetVolumeCommand: About to send command :" + temp_str + "\n") SendIrCommand(temp_str) elsif ( zone == 1) new_level = DeNormalizeVolume_OtherZone(level.to_i) temp_str = "@MSV:0"+new_level.to_s SendIrCommand(temp_str) elsif ( zone == 2) new_level = DeNormalizeVolume_OtherZone(level.to_i) temp_str = "@MVL:0"+new_level.to_s log("SetVolumeCommand: About to send command :" + temp_str + "\n") SendIrCommand(temp_str) else log("SetVolumeCommand: invalid zone " + zone.to_s + ":" + zone.to_i + ". Send commands only to valid child devices!!!\n") end
+
  
#90 Vol Down
+
SendIrCommand("@VOL:0-20") # default main volume -20
SendMultiZoneCommand(cmd, ["@VOL:2", "@MSV:2", "@MVL:2"])
+
SendIrCommand("@MSV:0-60") # default multi speaker volume
 +
SendIrCommand("@MVL:0-60") # default multi room line out volume
  
#89 Vol Up
+
$ZoneStatus = Hash.new()
SendMultiZoneCommand(cmd, ["@VOL:1", "@MSV:1", "@MVL:1"])
+
  
Speed Ctrl
+
InitZones()
#125 Scan Back/Rewind
+
ShowZonesInitialVolumes()
+
  
#93 Scan Fwd/Fast Fwd
 
 
  
DSP Modes
+
#$DevicePower = 0
 +
#SendIrCommand("@PWR:1")
 +
log("Initialization of Marantz GSD Device finished - Device is powered off!!!!\n")
 
</nowiki></pre>
 
</nowiki></pre>

Revision as of 15:13, 26 June 2008

'Add Ruby snippets to commands'

I've created new IR/Codeset group called "Marantz SR Multiroom RS232", although I'm not sure how to handle it. Have also edited coresponding Ruby snippets for each command. Basically those are just simple strings that get send on rs232 to take proper action on device according to received command from LinuxMCE... There are also a lot of other functions that help :

- determining for which child zone command is targeted
- to "normalize" volume levels between Marantz's internal dB units and range of 0-100


Simpler commands from Ruby part of template :


  Power
 #193 Off
 	#SendMultiZoneCommand(cmd, ["@PWR:1", "@MSP:1", "@MAM:2"]) SendMultiZonePowerOffCommand(cmd, ["@AMT:2", "@MSP:1", "@MAM:2"]) 	
 
 #192 On
 	#SendMultiZoneCommand(cmd, ["@PWR:2", "@MSP:2", "@MAM:1"]) SendMultiZonePowerOnCommand(cmd, ["@AMT:1", "@MSP:2", "@MAM:1"]) 	
 
 #194 Toggle Power
 		
 
 Inputs
 #169 AM
 	SendMultiZoneCommand(cmd, ["@SRC:H", "@MSC:H", "@MSC:H"]) 	
 
 #164 Aux
 	SendMultiZoneCommand(cmd, ["@SRC:9", "@MSC:9", "@MSC:9"]) 	
 
 #172 Aux 2
 	SendMultiZoneCommand(cmd, ["@SRC:A", "@MSC:A", "@MSC:A"]) 	
 
 #162 CD
 	SendMultiZoneCommand(cmd, ["@SRC:C", "@MSC:C", "@MSC:C"]) 	
 
 #420 CDR
 	SendMultiZoneCommand(cmd, ["@SRC:D", "@MSC:D", "@MSC:D"]) 	
 
 #178 DSS
 	SendMultiZoneCommand(cmd, ["@SRC:4", "@MSC:4", "@MSC:4"]) 	
 
 #165 DVD
 	SendMultiZoneCommand(cmd, ["@SRC:2", "@MSC:2", "@MSC:2"]) 	
 
 #170 FM
 	SendMultiZoneCommand(cmd, ["@SRC:G", "@MSC:G", "@MSC:G"]) 	
 
 #160 Tape / Tape 1
 	SendMultiZoneCommand(cmd, ["@SRC:E", "@MSC:E", "@MSC:E"]) 	
 
 #166 Tuner
 	SendMultiZoneCommand(cmd, ["@SRC:F", "@MSC:F", "@MSC:F"]) 	
 
 #161 TV
 	SendMultiZoneCommand(cmd, ["@SRC:1", "@MSC:1", "@MSC:1"]) 	
 
 #282 VCR-1
 	SendMultiZoneCommand(cmd, ["@SRC:3", "@MSC:3", "@MSC:3"]) 	
 
 DSP Modes (Audio)
 #891 All Ch Stereo
 	#<$"@SUR:0H\r"$> SendIrCommand("@SUR:0H") 	
 
 
 #97 Mute
 	SendMultiZoneCommand(cmd, ["@AMT:0", "@MSM:0", "@MAM:0"]) 	
 
 
 #90 Vol Down
 	SendMultiZoneCommand(cmd, ["@VOL:2", "@MSV:2", "@MVL:2"]) 	
 
 #89 Vol Up
 	SendMultiZoneCommand(cmd, ["@VOL:1", "@MSV:1", "@MVL:1"]) 	
 
 Speed Ctrl
 #125 Scan Back/Rewind


More important parts with more Ruby code :

###########################################################3 Internal Methods
# To do list :
# - parsing of input messages (inputs,mute,volume,power)
# - handling of tuner (with live/TV child device)
# - to properly send events and set device current volume data 

def DecodeReceivedInfo_candidate(response)
# Examples: Mute/On/Off: @AMT:1,@MSP:2,@MAM:2,   Volume: @VOL:-25,@MSV:-56,@MVL:-56  Inputs:@MSC:2E,@SRC:22,@SRC:2E
   log("DecodeReceivedInfo1: " + response + "\n");
   avrcommand = response[1..3]
   avrvalue = response[5]
   log("DecodeReceivedInfo2: " + response + " -> Command:"+ avrcommand.to_s + " Value: " + avrvalue.to_s + "\n");

   case avrcommand
# Input Source changed
     	when 'SRC'
     		log("Main Zone Input Changed to "+ avrvalue.to_s+ "\n");
     		input_param=0
     
     		case avrvalue
     			when '1'
     				log('Main Zone Input Changed to #161: TV')
     				input_param=161
     				temp_state="Input: TV"
     			when '2'
     				log('Main Zone Input Changed to #165: DVD')
     				input_param=165
     				temp_state="Input: TV"
     			when '3'
     				log('Main Zone Input Changed to #282: VCR-1')
     				input_param=282
     				temp_state="Input: TV"
     			when '4'
     				log('Main Zone Input Changed to #178: DSS')
     				input_param=178
     				temp_state="Input: TV"
     			when '9'
     				log('Main Zone Input Changed to #164: AUX')
     				input_param=164
     				temp_state="Input: TV"
     			when 'A'
     				log('Main Zone Input Changed to #171: AUX2')
     				input_param=171
     				temp_state="Input: TV"
     			when 'C'
     				log('Main Zone Input Changed to #162: CD')
     				input_param=162
     				temp_state="Input: TV"
     			when 'D'
     				log('Main Zone Input Changed to #420: CDR')
     				input_param=420
     				temp_state="Input: TV"
     			when 'E'
     				log('Main Zone Input Changed to #160: TAPE')
     				input_param=160
     				temp_state="Input: TV"
     			when 'F'
     				log('Main Zone Input Changed to #166: TUNER')
     				input_param=166
     				temp_state="Input: TV"
     			when 'G'
     				log('Main Zone Input Changed to #170: FM')
     				input_param=160
     				temp_state="Input: TV"
     			when 'H'
     				log('Main Zone Input Changed to #169: AM')
     				input_param=169
     				temp_state="Input: TV"
     		end
#     		device_id = device_.mapPortChannel_Device_.[0.to_s]
		log("======= Determiming device ID for Zone 0 : " + device_id.to_s + "\n")
		device_.mapPortChannel_Device_.each do |key, value|
			log(key.to_s + " => " + value.to_s+ "\n")
		end
     		cmd = Command.new(device_id, -1001, 1, 2, 49);
     		cmd.params_[41] = input_param.to_s();
     		SendCommand(cmd);
     		SetDeviceDataInDB( device_id, 200, temp_state ) # 200 = DEVICEDATA_State_CONST

     	when 'VOL'
     		volume = response[5..-1].to_i();
     		volume_norm = NormalizeVolume_MainZone(volume)
     		log("Main Zone Volume Changed: " + volume.to_s + " Normalized Value: " + volume_norm.to_s + "\n");
#     		device_id = device_.mapPortChannel_Device_.[0.to_s]
		log("======= Determiming device ID for Zone 0 : " + device_id.to_s + "\n")
		device_.mapPortChannel_Device_.each do |key, value|
			log(key.to_s + " => " + value.to_s+ "\n")
		end
     		SetDeviceDataInDB( device_id, 158, volume_norm ) # 158 = DEVICEDATA_Volume_Level_CONST
     		cmd = Command.new(device_id, -1001, 1, 2, 71);
     		cmd.params_[30] = volume_norm
     		SendCommand(cmd);
     	when 'PWR'
     		case avrvalue
     			when '1'
     				log("Device Power Changed: OFF");
     				cmd.params_[10] = "0";
     				$DevicePower = 0
     			when '2'
     				log("Device Power Changed: ON");
     				cmd.params_[10] = "1";
     				$DevicePower = 1
     		end
     		cmd = Command.new(device_.devid_, -1001, 1, 2, 48);
     		SendCommand(cmd);
     	else
     		log("Yet not implemented: Handler for command: " + avrcommand.to_s)
     end
    
end     


def DecodeReceivedInfo(response)
# Examples: Mute/On/Off: @AMT:1,@MSP:2,@MAM:2,   Volume: @VOL:-25,@MSV:-56,@MVL:-56  Inputs:@MSC:2E,@SRC:22,@SRC:2E
   log("DecodeReceivedInfo1: " + response + "\n");
   avrcommand = response[1..3]
   avrvalue = response[5]
   log("DecodeReceivedInfo2: " + response + " -> Command:"+ avrcommand.to_s + " Value: " + avrvalue.to_s + "\n");

   case avrcommand
     	when 'VOL'
     		volume = response[5..-1].to_i();
     		volume_norm = NormalizeVolume_MainZone(volume)
     		log("Main Zone Volume Changed: " + volume.to_s + " Normalized Value: " + volume_norm.to_s + "\n");
#     		device_id = device_.mapPortChannel_Device_.[0.to_s]
		log("======= Determiming device ID for Zone 0 : " + device_id.to_s + "\n")
		device_.mapPortChannel_Device_.each do |key, value|
			log(key.to_s + " => " + value.to_s+ "\n")
			if (key.to_s == "0")
				device_id = value
			end
		end
     		SetDeviceDataInDB( device_id, 158, volume_norm ) # 158 = DEVICEDATA_Volume_Level_CONST
     		cmd = Command.new(device_id, -1001, 1, 2, 71);
     		cmd.params_[30] = volume_norm
     		SendCommand(cmd);
     	when 'PWR'
     		case avrvalue
     			when '1'
     				log("Device Power Changed: OFF")
     				cmd.params_[10] = "0";
     				$DevicePower = 0
     			when '2'
     				log("Device Power Changed: ON");
     				cmd.params_[10] = "1";
     				$DevicePower = 1
     		end
     		cmd = Command.new(device_.devid_, -1001, 1, 2, 48);
     		SendCommand(cmd);
     	else
     		log("Yet not implemented: Handler for command: " + avrcommand.to_s)
     end
    
end     


def ReceiveReportCommand()
	@buff = conn_.RecvDelimited("\r", 1000) 
	log("Cmd response from Marantz: " + @buff + "\n")
	log("Calling DecodeReceivedInfo: " + @buff + "\n")
	temp_resp=@buff;
	DecodeReceivedInfo(temp_resp)
	log("End of DecodeReceivedInfo: " + temp_resp + "\n")
end

def SendIrCommand(command)
        log("SendIrCommand: " + command + "\n")
	conn_.Send(command+ "\r")
        log("Sending Command: " + command + "\n")
	ReceiveReportCommand()
end

def log(line)
#          $log = File.open("/var/log/pluto/" + device_.devid_.to_s + "_Generic_Serial_Device.log", "a")
	  $log = File.open("/var/log/pluto/Marantz_SR5600.log", "a")
	  logTime = Time.now
	  timeStr = logTime.strftime("%d-%m-%Y  %H:%M:%S  ")

	  $log.puts timeStr + "(***):" + line.to_s
          $log.close
end 	

def SendMultiZoneCommand(cmd, commandsArray, commandParam="")
        log("Got Command with ID: " + cmd.id_.to_s + " from: " + cmd.devidfrom_.to_s + " to: " + cmd.devidto_.to_s + "\n")
	zone = GetZone(cmd.devidto_)
	if( zone >= 0 and zone < commandsArray.size )
	        zone_desc=device_.childdevices_[cmd.devidto_].devdata_[186]
		log("Determine zone for command : " + zone_desc + "[" + zone.to_s + "]\n")
		SendIrCommand(commandsArray[zone] + commandParam.to_s)
	else
		log("SendMultiZoneCommand: invalid zone " + zone.to_s + ". Send commands only to valid child devices!!!")
	end
end


def SendMultiZonePowerOnCommand(cmd, commandsArray, commandParam="")
#It will Unmute Zone first and then see also global power should be turned on...
        log("Got Power On Command with ID: " + cmd.id_.to_s + " from: " + cmd.devidfrom_.to_s + " to: " + cmd.devidto_.to_s + "\n")
	zone = GetZone(cmd.devidto_)
	if( zone >= 0 and zone < commandsArray.size )
	        zone_desc=device_.childdevices_[cmd.devidto_].devdata_[186]
		log("Determine zone for command : " + zone_desc + "[" + zone.to_s + "]\n")
		SendIrCommand(commandsArray[zone] + commandParam.to_s)
		$ZoneStatus[zone.to_s] = 'ON'
		log("*** Setting zone : " + zone_desc + "[" + zone.to_s + "] to ON\n")
		ShowZones()
		if ($DevicePower == 0)
			SendIrCommand("@PWR:2")
		end
		$DevicePower = 1
	elsif (zone == -1)
		if ($DevicePower == 0)
			SendIrCommand("@PWR:2")
		end
		$DevicePower = 1
		log("####### Powering device On\n")
	else
		log("SendMultiZonePowerOnCommand: invalid zone " + zone.to_s + ". Send commands only to valid child devices!!!")
	end
end

def SendMultiZonePowerOffCommand(cmd, commandsArray, commandParam="")
#It will Mute Zone first and then see if also global power can be turned off...
        log("Got Power Off Command with ID: " + cmd.id_.to_s + " from: " + cmd.devidfrom_.to_s + " to: " + cmd.devidto_.to_s + "\n")
	zone = GetZone(cmd.devidto_)
	if( zone >= 0 and zone < commandsArray.size )
	        zone_desc=device_.childdevices_[cmd.devidto_].devdata_[186]
		log("Determine zone for command : " + zone_desc + "[" + zone.to_s + "]\n")
		SendIrCommand(commandsArray[zone] + commandParam.to_s)
		$ZoneStatus[zone.to_s] = 'OFF'
		log("*** Setting zone : " + zone_desc + "[" + zone.to_s + "] to OFF\n")
		ShowZones()
		if (($ZoneStatus["0"] == 'OFF') and ($ZoneStatus["1"] == 'OFF') and ($ZoneStatus["2"] == 'OFF'))
			SendIrCommand("@PWR:1")
			$DevicePower = 0
			log("####### All zones are muted - device is powered Off\n")
		end
	else
		log("SendMultiZonePowerOffCommand: invalid zone " + zone.to_s + ". Send commands only to valid child devices!!!")
	end
end


def GetZone(deviceDestination)
	if( device_.mapDevice_PortChannel_.has_key?(deviceDestination) and
		device_.mapDevice_PortChannel_[deviceDestination] != nil and
		!device_.mapDevice_PortChannel_[deviceDestination].empty? )
		return device_.mapDevice_PortChannel_[deviceDestination].to_i
	end
	
	return -1
end

def ShowZonesDebug()
	log("####### Dev 2 PortChanel\n")
	device_.mapDevice_PortChannel_.each do |key, value|
		log(key.to_s + " => " + value.to_s + "\n")
	end
	
	log("======= PortChanel 2 Dev\n")
	device_.mapPortChannel_Device_.each do |key, value|
		log(key.to_s + " => " + value.to_s+ "\n")
	end
end



def ShowZonesInitialVolumes()
	log("####### Show Initial Volume Levels for zones\n")
	device_.mapDevice_PortChannel_.each do |key, value|
	        volume = device_.childdevices_[key].devdata_[208]
		log("Zone " + value.to_s + " => " + volume.to_s + "\n")
		SetVolumeInZone(volume,value)
	end
	
end


def ShowZones()
	temp = "####### Zones Status : "
	device_.mapDevice_PortChannel_.each do |key, value|
		temp = temp + " | Zone " + value.to_s + " => " + $ZoneStatus[value] 
	end
	temp = temp + "\n"
	log(temp)
end


def SetZones(state)
	log("####### Setting all zones to " + state + "\n")
	device_.mapDevice_PortChannel_.each do |key, value|
		$ZoneStatus[value] = state
		log("Zone " + value.to_s + " => " + state + "\n")
 	end
end

def InitZones()
	log("####### Initializing all zones to OFF\n")
	device_.mapDevice_PortChannel_.each do |key, value|
		$ZoneStatus[value] = 'OFF'
		log("Zone " + value.to_s + " => " + $ZoneStatus[value] + "\n")
 	end
	log("####### Print $ZoneStatus Hash:\n")
 	$ZoneStatus.each do |key, value|
		log("Zone " + key.to_s + " => " + value.to_s + "\n")
	end
end

def SetVolumeInZone(level,zone)
# Sets Normalized Volume Level (0..100) in certain zone 
	log("SetVolumeInZone: volume: " + level.to_s + " => Zone: " + zone + "\n")

	if ( zone == "0")
		log("SetVolumeInZone0: volume: " + level.to_s + " => Zone: " + zone + "\n")
      		new_level = DeNormalizeVolume_MainZone(level.to_i)
		log("SetVolumeInZone00: volume: " + level.to_s + " => Zone: " + zone + "\n")
      		temp_str="@VOL:0"+new_level.to_s;
      		log("SetVolumeInZone: About to send command :" + temp_str + "\n")
      		SendIrCommand(temp_str)
	elsif ( zone == "1")
		log("SetVolumeInZone1: volume: " + level.to_s + " => Zone: " + zone + "\n")
      		new_level = DeNormalizeVolume_OtherZone(level.to_i)
		log("SetVolumeInZone11: volume: " + level.to_s + " => Zone: " + zone + "\n")
      		temp_str="@MSV:0"+new_level.to_s;
      		log("SetVolumeInZone: About to send command :" + temp_str + "\n")
      		SendIrCommand(temp_str)
	elsif ( zone == "2")
		log("SetVolumeInZone2: volume: " + level.to_s + " => Zone: " + zone + "\n")
      		new_level = DeNormalizeVolume_OtherZone(level.to_i)
#		log("SetVolumeInZone22: volume: " + level + " => Zone: " + zone + "\n")
      		temp_str="@MVL:0"+new_level.to_s;
      		log("SetVolumeInZone: About to send command :" + temp_str + "\n")
      		SendIrCommand(temp_str)
	else
      		log("SetVolumeInZone: invalid zone " + zone.to_s + ". Send commands only to valid child devices!!!")
	end
	log("SetVolumeInZone End: volume: " + level.to_s + " => Zone: " + zone + "\n")

end


def NormalizeVolume_MainZone(level)
# Normalizes Marantz Volume Level (-99..+10) to 0-100 boundaries for Main Zone 
	temp = (level+100)/110.0*100.0
	temp=temp.round
        log("Normalizing Main Zone Volume Level from : " + level.to_s + " to " + temp.to_s + "\n")
	return temp
end

def NormalizeVolume_OtherZone(level)
# Normalizes Marantz Volume Level to 0-100 boundaries for Second Zone (-90..0)
	temp = ((level+90.0)/90.0)*100.0 
	temp=temp.round
        log("Normalizing Other Zone Volume Level from : " + level.to_s + " to " + temp.to_s + "\n")
	return temp
end

def DeNormalizeVolume_MainZone(level)
# DeNormalizes volume level in 0-100 boundaries to Marantz Volume Level (-99..+10) for Main Zone 
	temp = (level/100.0)*110.0-99
	temp=temp.round
        log("DeNormalizing Main Zone Volume Level from : " + level.to_s + " to " + temp.to_s + "\n")
	return temp
end

def DeNormalizeVolume_OtherZone(level)
# DeNormalizes volume level in 0-100 boundaries to Marantz Volume Level (-90..0) for Other Zone 
	temp = ((level/100.0)*90.0)-90.0
	temp=temp.round
        log("DeNormalizing Other Zone Volume Level from : " + level.to_s + " to " + temp.to_s + "\n")
	return temp
end












###########################################################Process Incoming Data
@buff = conn_.RecvDelimited("\r", 1000)
log("Info from Marantz: " + @buff + "\n")
temp_line=@buff
log("1Calling DecodeReceivedInfo: " + temp_line + "\n")
DecodeReceivedInfo(temp_line)
log("1End of DecodeReceivedInfo: " + temp_line+ "\n")



###########################################################Set Tuner Frequency
identifier = cmd.params_[216]
# Main Frequency		"TFQ:0xxxxx"  from 08700 till + 10800
# Multiroom Frequency		“MTF:0xxxxx“  from 08700 till + 10800

# switch to tuner mode first
SendMultiZoneCommand(cmd, ["@SRC:G", "@MSC:G", "@MSC:G"])

# tune to desired frequency
SendMultiZoneCommand(cmd, ["@TFQ:0"+identifier, "@MTF:0"+identifier, "@MTF:0"+identifier])
log("Sending Marantz : Setting tuner frequency to "+identifier+"\n")


###########################################################313 Set Volume command
level = cmd.params_[76]
# Main volume 			“VOL:0xxx”  from - 99 till + 18
# Multiroom Speakers		"MSV:0xxx"  from - 99 till + 0
# Multiroom Speakers		“MVL:0xxx”  from - 99 till + 0
zone = GetZone(cmd.devidto_)
log("313:Set Volume Command: Got Cmd with ID: " + cmd.id_.to_s + " from: " + cmd.devidfrom_.to_s + " to: " + cmd.devidto_.to_s + " | Zone : " + zone.to_s + "\n")
if ( zone == 0)
      new_level = DeNormalizeVolume_MainZone(level.to_i)
      temp_str = "@VOL:0"+new_level.to_s
      log("SetVolumeCommand: About to send command :" + temp_str + "\n")
      SendIrCommand(temp_str)
elsif ( zone == 1)
      new_level = DeNormalizeVolume_OtherZone(level.to_i)
      temp_str = "@MSV:0"+new_level.to_s
      SendIrCommand(temp_str)
elsif ( zone == 2)
      new_level = DeNormalizeVolume_OtherZone(level.to_i)
      temp_str = "@MVL:0"+new_level.to_s
      log("SetVolumeCommand: About to send command :" + temp_str + "\n")
      SendIrCommand(temp_str)

else
      log("SetVolumeCommand: invalid zone " + zone.to_s + ":" + zone.to_i + ". Send commands only to valid child devices!!!\n")
end







###########################################################Process Initialize
$DevicePower = 1
SendIrCommand("@PWR:2")
log("Initializing Marantz GSD Device\n")



SendIrCommand("@AST:F") # max level of feedback

SendIrCommand("@MPW:2") # multi room always on

SendIrCommand("@MSP:1") # turn multi room speakers off by default

SendIrCommand("@MAM:2") # mute multi room line out by default

SendIrCommand("@VOL:0-20") # default main volume -20
SendIrCommand("@MSV:0-60") # default multi speaker volume
SendIrCommand("@MVL:0-60") # default multi room line out volume

$ZoneStatus = Hash.new()

InitZones()
ShowZonesInitialVolumes()


#$DevicePower = 0
#SendIrCommand("@PWR:1")
log("Initialization of Marantz GSD Device finished - Device is powered off!!!!\n")