Logic Machine Forum
Yamaha R-N301 control and PA System automation - Printable Version

+- Logic Machine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: Yamaha R-N301 control and PA System automation (/showthread.php?tid=27)



Yamaha R-N301 control and PA System automation - gtsamis - 09.07.2015

Hi,
For anyone it might help I wanted to share some scripts to control Yamaha R-N301 HiFi Receiver and automate a Public Announcement system using SNOM PA1.
The main objective is to make the necessary settings (input, volume etc) on R-N301 when PA receives a call and return to previous state when the call ends.
I am basically new to scripting so any suggestions are welcome.

 
I have created the following objects on logic machine
[Image: MGoq9n0.png]

Using Snom PA1 Action URL feature and Logic Machine remote services to update object 2/6/11 when a call is connected or disconnects.
[Image: 5yya0fY.png]


On Connected : http://remote:remote@192.168.16.10/cgi-bin/scada-remote/request.cgi?m=json&r=grp&fn=write&alias=2/6/11&value=true
On Disconnected: http://remote:remote@192.168.16.10/cgi-bin/scada-remote/request.cgi?m=json&r=grp&fn=write&alias=2/6/11&value=false

Scripts
1. Yamaha R-N301 control and feedback function
Code:
--[[
Basic control and feedback function for Yamaha R-N301 amplifier

Input cmd
Get feedback             : GET eg rn301('GET', '<Main_Zone><Basic_Status>GetParam</Basic_Status></Main_Zone>')
Send command            : PUT eg rn301('PUT', '<System><Power_Control><Power>Standby</Power></Power_Control></System>')

Input param
Update feedback objects                    : <Main_Zone><Basic_Status>GetParam</Basic_Status></Main_Zone>
Power on                : <System><Power_Control><Power>On</Power></Power_Control></System>
Standby                    : <System><Power_Control><Power>Standby</Power></Power_Control></System>
Mute On                    : <Main_Zone><Volume><Mute>On</Mute></Volume></Main_Zone>
Mute Off                : <Main_Zone><Volume><Mute>Off</Mute></Volume></Main_Zone>
Volume (0-100)                     : <Main_Zone><Volume><Lvl><Val>50</Val><Exp>0</Exp><Unit></Unit></Lvl></Volume></Main_Zone>
Input                     : <Main_Zone><Input><Input_Sel>LINE1</Input_Sel></Input></Main_Zone>

Returns table with status feedback (Result, Rescode, Power, Volume, Mute, Input)
]]--

function rn301(cmd, param)
require 'socket.http'

-- Create HTTP post body
local request_body = '<?xml version="1.0" encoding="utf-8"?>' ..
                          '<YAMAHA_AV cmd="' .. cmd.. '">' ..
                              (param or '') ..
                           '</YAMAHA_AV>'

local response_body = { }
local status_tbl = { }
-- Send command to amplifier
local result, code  = socket.http.request
{
 url = 'http://192.168.16.22/YamahaRemoteControl/ctrl',
 method = 'POST',
 headers =
 {
   ["Content-Type"] = "application/x-www-form-urlencoded",
   ["Content-Length"] = request_body:len(),
 },
 source = ltn12.source.string(request_body),
 sink = ltn12.sink.table(response_body),
}

-- Check responce from amplifier
if result and code==200 then
        status_tbl['Result']=result
        status_tbl['ResCode']=code
        
       if cmd == 'GET' then    
            if type(response_body) == "table" then
                 response_body=table.concat(response_body)
                  power=string.sub(string.match(response_body,"<Power>%a+</Power>"), 8, -9)
                status_tbl['Power']=power
                -- Manipulate and update power feedback object
                if power=='On' then
                     grp.write('2/6/51', true)
               else  
                     grp.write('2/6/51', false)
               end
         
                 volume=tonumber(string.sub(string.match(response_body,"<Val>%d+</Val>"), 6, -7))
                status_tbl['Volume']=volume
                -- Update volume feedback object
                grp.write('2/6/53', volume)
            
                  mute=string.sub(string.match(response_body,"<Mute>%a+</Mute>"), 7, -8)
                 status_tbl['Mute']=mute
                 -- Manipulate and update mute feedback object
               if mute == 'On' then
                     grp.write('2/6/52', true)
               else
                     grp.write('2/6/52', false)
                end
       
                 input=string.sub(string.match(response_body,"<Input_Sel>.*</Input_Sel>"), 12, -13)
                 status_tbl['Input']=input
                 -- Update input feedback object
                grp.write('2/6/54', input)
           else
                 alert('HTTP Request Error: Response is empty or unknown')
            end
        end
else
    alert('HTTP Request Error: ' .. code)
end
return status_tbl
end

2. Object 2/6/11 event script
Code:
value=event.getvalue()

-- Update feedback objects
rn301('GET', '<Main_Zone><Basic_Status>GetParam</Basic_Status></Main_Zone>')
yamaha=grp.getvalue('2/6/51')

-- 1st case: Call Connected and R-N301 already On
-- Store current power status, input and volume level
-- Set Input to Line1(PA system), Volume to 50 and make sure mute is off    
if value and yamaha then
    storage.set('yamaha_pwr',yamaha)
 prv_volume=grp.getvalue('2/6/53')
 storage.set('yamaha_volume',prv_volume)
 prv_input=grp.getvalue('2/6/54')
 storage.set('yamaha_input',prv_input)
 rn301('PUT', '<Main_Zone><Volume><Mute>Off</Mute></Volume></Main_Zone>')
 rn301('PUT', '<Main_Zone><Volume><Lvl><Val>50</Val><Exp>0</Exp><Unit></Unit></Lvl></Volume></Main_Zone>')
    rn301('PUT', '<Main_Zone><Input><Input_Sel>LINE1</Input_Sel></Input></Main_Zone>')

-- 2nd case: Call Connected and R-N301 already on Standby
-- Store current power status
-- Power On R-N301, set Input to Line1(PA system), Volume to 50 and make sure mute is off
elseif value and not (yamaha) then
 storage.set('yamaha_pwr',yamaha)
 rn301('PUT', '<System><Power_Control><Power>On</Power></Power_Control></System>')
 rn301('PUT', '<Main_Zone><Volume><Mute>Off</Mute></Volume></Main_Zone>')
 rn301('PUT', '<Main_Zone><Volume><Lvl><Val>50</Val><Exp>0</Exp><Unit></Unit></Lvl></Volume></Main_Zone>')
    rn301('PUT', '<Main_Zone><Input><Input_Sel>LINE1</Input_Sel></Input></Main_Zone>')

-- 3rd case: Call Disconnects and R-N301 was On before call
-- Set Input, Volume to previous state  and make sure Mute is off
elseif (not value) and storage.get('yamaha_pwr',0) then
    prv_volume=storage.get('yamaha_volume',30)
    prv_input=storage.get('yamaha_input','CD')
    rn301('PUT', '<Main_Zone><Volume><Mute>Off</Mute></Volume></Main_Zone>')
    rn301('PUT', '<Main_Zone><Volume><Lvl><Val>' .. prv_volume .. '</Val><Exp>0</Exp><Unit></Unit></Lvl></Volume></Main_Zone>')
    rn301('PUT', '<Main_Zone><Input><Input_Sel>' .. prv_input .. '</Input_Sel></Input></Main_Zone>')

-- 4th case: Call Disconnects and R-N301 was Off before call
-- Just make sure Mute is off and then power off
else
    rn301('PUT', '<Main_Zone><Volume><Mute>Off</Mute></Volume></Main_Zone>')
 rn301('PUT', '<System><Power_Control><Power>Standby</Power></Power_Control></System>')
end

-- Update feedback objects
rn301('GET', '<Main_Zone><Basic_Status>GetParam</Basic_Status></Main_Zone>')
 



RE: Yamaha R-N301 control and PA System automation - admin - 09.07.2015

Nice example, one small improvement: you can use captures inside of regexps like this:

Code:
power=string.sub(string.match(response_body,"<Power>%a+</Power>"), 8, -9)

power=string.match(response_body,"<Power>(%a+)</Power>")

Both lines do exactly the same thing, but you don't have to count characters when using captures Smile


RE: Yamaha R-N301 control and PA System automation - gtsamis - 09.07.2015

(09.07.2015, 11:54)admin Wrote: Nice example, one small improvement: you can use captures inside of regexps like this:

Code:
power=string.sub(string.match(response_body,"<Power>%a+</Power>"), 8, -9)

power=string.match(response_body,"<Power>(%a+)</Power>")

Both lines do exactly the same thing, but you don't have to count characters when using captures Smile

Rolleyes  You are right, didn't cross my mind to use string.match because the reply is pretty much static but will be helpfull on futher control.

Thank you

For anyone find it usefull below are the complete responce from Yamaha R-N301 on GET command. PUT command replies only the header section.

Headers:
Code:
200 OK
Server: Network_Player/3.1 (R-N301)
Content-Type: text/xml; charset="utf-8"
Content-Length: 480

Body:
Code:
<YAMAHA_AVrsp="GET"RC="0">
    <Main_Zone>
       <Basic_Status>
            <Power_Control>
                <Power>On</Power>
            </Power_Control>
        <Volume>
            <Lvl>
                <Val>45</Val>
                <Exp>0</Exp>
                <Unit/>
            </Lvl>
            <Mute>Off</Mute>
        </Volume>
        <Input>
            <Input_Sel>SERVER</Input_Sel>
            <Input_Sel_Item_Info>
            <Param>SERVER</Param>
            <RW>RW</RW>
            <Title/>
            <Icon>
                <On>/YamahaRemoteControl/Icons/icon067.png</On>
                <Off/>
            </Icon>
            <Src_Name>SERVER</Src_Name>
            <Src_Number>1</Src_Number>
            </Input_Sel_Item_Info>
        </Input>
       </Basic_Status>
    </Main_Zone>
</YAMAHA_AV>