Jump to content

User:Bulek: Difference between revisions

From LinuxMCE
No edit summary
No edit summary
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 14: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")