Notice: This forum has been recovered from an old backup, so some content, links, and dates may be outdated. The forum is currently read-only while we restore sign-in and registration functionality. Details

If you find this forum valuable and would like to help keep it online, donations to help cover hosting and domain costs are greatly appreciated, but never expected. You can support the forum through Buy Me a Coffee or Ko-fi. Thank you for helping preserve the EventGhost community.

Denon & Marantz Network Control Plugin

Questions and comments specific to a particular plugin should go here.
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Denon & Marantz Network Control Plugin

Post by kgschlosser »

I am trying to make this a really simple means to move information back and forth.. so if say the person closes the API you would be able to shut down the thread. and when the person reconnects there wouldn't have to be another query to everything for statuses. it's right there.. only the marantz plugin would have to do the status query on startup. This will take care of any needlessly sending and receiving things. but this will also make a sweet means for you to send data as well.. because all you would have to do is to set the same attribute that you use to grab the data from...

so this is how I have Started setting it up..


assumed
data = eg.plugin.Marantz.Storage (or whatever i decide to name it)


so

Code: Select all

volume = data.MainZone.Volume.value
description = data.MainZone.Volume.description
commands = data.MainZone.Volume.commands
if a command is received from the AVR the plugin will use the same mechanism to set the data that you would but it will include the whole received message..
the plugin knows to convert anything it has to and to trigger an event if the data has changed. no reason to trigger an event if the data is the same. that will cause macros and what have you to fire off for no reason.

Code: Select all

data.MainZone.Volume.value = receivedData (received Data being MV425)
and if you want to send a command from your plugin leave off any none "specific" command characters
so if you want to turn the volume up you would set the attribute to 'UP'
and down is 'DOWN' and a specific value would be the number.

upper case lower case. ints strings floats... doesn't matter.. it does any conversions it needs to. save for one thing... specific to the volume... if you want to send over the actual Db to set to it has to be a string with the Db on the end. put the decimal in don't put the decimal in. doesn't matter on any of the formats. for Db it has to have the - in the string. this is due to the fact there is a +10.0 db and a -10.0 db. space or no space. between the value and Db. doesn't matter. anything that has a value that is - and + that could be the same.. the - HAS to be included

Code: Select all

data.MainZone.Volume.value = '535' , 535, '53.5', 53.5 and in Db '-265Db', '-26.5Db', '-265 Db', '-26.5 Db'  (leave off the MV) 
and I do know this API that i am working with is only good for AVR's made since 2011. and there really can't be that many to choose from.. but the big issue is not the model numbers... it's the firmware.. because they can add functionality from the firmware. I am going to send off an e-mail to them for a list of the firmware.. and what each firmware supports for commands.. as well as an actual complete copy of every single command since the documentation on their API is all messed up.

and if and when i get a list of supported command to the firmware i will be able to reply with None if the avr does not support that command.. for the whole command

Code: Select all

if data.MainZone.Volumeis not None:
    do code here

This should be by far the easiest way to send data back and forth..

because if there is no one connected... there is no need for a timer to update information. when someone connects.. set the timer.. so every 100 ms or so get the data. I do not believe I will need to implement thread locking. but if i do it's no biggie because the last object class in the chain would be the one in the run. so Volume is a "command" object. and MainZone is a parent.

You will have more layers.

Code: Select all

data.MainZone.ChannelVolume.SurroundBackLeft
data.MainZone.ChannelVolume.SurroundBackLeft = 'UP'
data.MainZone.ChannelVolume.SurroundBackLeft = 'DOWN'
data.MainZone.ChannelVolume.SurroundBackLeft = 5
it will follow the same grouping structure that I set for the macros when they get added.

I think it's a very simple API. the only thing that has any complexities are the volumes. the only commands that i recollect that don't make any sense are the left and right in the surround mode. those do not conform to everything else.. but i think for the surround modes i will "fix" the none standard API for them. Everything else is Up and Down. except that one..
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Denon & Marantz Network Control Plugin

Post by kgschlosser »

what is making this to be very hard is the lack of command codes for the volume and inputs for the 2 zones. but also the lack of a zone designation for anything main zone related.

then it would be easy to associate Z2SI to zone 2 source input. or Z2MV to zone 2 master volume. but they didn't do that they smooshed the AVR responses for SI and MV for the zones all under the Z2 command heading.. which doesn't follow the MainZone API. it's almost like it was 2 different people with 2 different API structures worked on this and didn't communicate with one another and in the end they just smooshed the 2 together

I do not know who has who's' head up who's backside over there but.. they need some direction on how to make an API that would be very easy for someone making an external piece of software
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Denon & Marantz Network Control Plugin

Post by kgschlosser »

so this is what i sent Marantz.

Code: Select all

Me and another person is in the processing of making a Plugin which will allow control of Marantz/Denon AVR's and Processors.

What I am running into an issue is.. I really do not know which API sheet to download. I need a complete set of commands for all products that fall into this category. But also I need a list of which firmware supports what commands. 

The plugin fixes the issue of only one IP (Telnet) device being able to connect at a time, and we are also going to provide a web portal that allows for all commands to be accessed instead of the current web portal which only allows a small portion of them. 

One of the things I have noticed is that an app for android or IOS Uses some other means of communication. but this triggers all kinds of undocumented responses to be sent from the AVR/Processor over the telnet connection. Is there any information available on those?

I am not sure as of yet exactly how the Power for the zones work. I am hoping that if I wanted to turn on Zone 2 and the AVR was in a powered off state. By sending Z2ON it would power On the AVR but "turn off" Zone 3 and the Main Zone. So I ask the question do I specifically need to tell it to turn the AVR on and then the 2 zones off. or does it do this by design.

And I am not sure who handles this. but there is data corruption for some of the API downloads. and incorrect file extensions. The API sheet would be far easier to read if it contained a sheet of all the commands available. then specific sheets for the various firmware revisions. (if firmware revisions share the same commands, those can be grouped together). 

And as a suggestion..

I am not sure who came up with the API but it seems like 2 different groups or people did. because there is no standard structure.
as an example.. Z2 and Z3 command/response prefix if for Volume/power/Input. and the MainZone has it's own prefix but only for tuning the main zone on and off which is ZM. 

where as the MainZone is
MV for Master Volume
SI for Source Input
PW for Power

It also would be nice if MainZone had a prefix of it's own. and only commands that would affect the Main Zone would be in it..
ZM = Main Zone
Z2 = Zone 2
Z3 = Zone 3

In this world of everything talking to each other. Making a really simple API means that more people will write ways for things to talk to it. Which will increase the popularity of the Item. and increase sales..
If you like the work I have been doing then feel free to Image
User avatar
yokel22
Experienced User
Posts: 265
Joined: Thu Feb 05, 2015 5:56 pm
Location: U.S. - Kansas city

Re: Denon & Marantz Network Control Plugin

Post by yokel22 »

Yes, the Zone 2/3 commands make no sense in context of the MainZone.

These are the xml returns i get from the AVR, i thought they might be useful since you can't even really see what's going on with the AVR. Specifically the nodes for ModelId, BrandId, & SalesArea.

Main Zone:

Code: Select all

<item>
<FriendlyName>
<value>Master Bedroom</value>
</FriendlyName>
<Power>
<value>ON</value>
</Power>
<ZonePower>
<value>ON</value>
</ZonePower>
<RenameZone>
<value>MAIN ZONE</value>
</RenameZone>
<TopMenuLink>
<value>ON</value>
</TopMenuLink>
<VideoSelectDisp>
<value>ON</value>
</VideoSelectDisp>
<VideoSelect>
<value/>
</VideoSelect>
<VideoSelectOnOff>
<value>OFF</value>
</VideoSelectOnOff>
<VideoSelectLists>
<value index="ON" table="On" param=""/>
<value index="OFF" table="Off" param=""/>
</VideoSelectLists>
<ECOModeDisp>
<value>ON</value>
</ECOModeDisp>
<ECOMode>
<value>OFF</value>
</ECOMode>
<ECOModeLists>
<value index="ON" table="On" param=""/>
<value index="OFF" table="Off" param=""/>
<value index="AUTO" table="Auto" param=""/>
</ECOModeLists>
<AddSourceDisplay>
<value>FALSE</value>
</AddSourceDisplay>
<ModelId>
<value>1</value>
</ModelId>
<BrandId>
<value>DENON_MODEL</value>
</BrandId>
<SalesArea>
<value>1</value>
</SalesArea>
<InputFuncSelect>
<value>Online Music</value>
</InputFuncSelect>
<NetFuncSelect>
<value>NET</value>
</NetFuncSelect>
<selectSurround>
<value>Stereo</value>
</selectSurround>
<VolumeDisplay>
<value>Absolute</value>
</VolumeDisplay>
<MasterVolume>
<value>-11.0</value>
</MasterVolume>
<Mute>
<value>off</value>
</Mute>
<RemoteMaintenance>
<value/>
</RemoteMaintenance>
<SubwooferDisplay>
<value>FALSE</value>
</SubwooferDisplay>
<Zone2VolDisp>
<value>TRUE</value>
</Zone2VolDisp>
</item>
Zone 2:

Code: Select all

<item>
<FriendlyName>
<value>Master Bedroom</value>
</FriendlyName>
<Power>
<value>ON</value>
</Power>
<ZonePower>
<value>ON</value>
</ZonePower>
<RenameZone>
<value>ZONE2</value>
</RenameZone>
<TopMenuLink>
<value>ON</value>
</TopMenuLink>
<VideoSelectDisp>
<value>ON</value>
</VideoSelectDisp>
<VideoSelect>
<value/>
</VideoSelect>
<VideoSelectOnOff>
<value>OFF</value>
</VideoSelectOnOff>
<VideoSelectLists>
<value index="ON" table="On" param=""/>
<value index="OFF" table="Off" param=""/>
</VideoSelectLists>
<ECOModeDisp>
<value>ON</value>
</ECOModeDisp>
<ECOMode>
<value>OFF</value>
</ECOMode>
<ECOModeLists>
<value index="ON" table="On" param=""/>
<value index="OFF" table="Off" param=""/>
<value index="AUTO" table="Auto" param=""/>
</ECOModeLists>
<AddSourceDisplay>
<value>FALSE</value>
</AddSourceDisplay>
<ModelId>
<value>1</value>
</ModelId>
<BrandId>
<value>DENON_MODEL</value>
</BrandId>
<SalesArea>
<value>1</value>
</SalesArea>
<InputFuncSelect>
<value>Online Music</value>
</InputFuncSelect>
<NetFuncSelect>
<value>NET</value>
</NetFuncSelect>
<selectSurround>
<value>Stereo</value>
</selectSurround>
<VolumeDisplay>
<value>Absolute</value>
</VolumeDisplay>
<MasterVolume>
<value>-18</value>
</MasterVolume>
<Mute>
<value>off</value>
</Mute>
<RemoteMaintenance>
<value/>
</RemoteMaintenance>
<SubwooferDisplay>
<value>FALSE</value>
</SubwooferDisplay>
<Zone2VolDisp>
<value>TRUE</value>
</Zone2VolDisp>
</item>
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Denon & Marantz Network Control Plugin

Post by kgschlosser »

Those xml responses are from HTTP requests yes??


if they are the issue with doing a connection via HTTP to the AVR is the lack of commands supported by the AVR when using that method.

it's like 1/6th of the available commands (if that)

I think making something so the 2 plugins can work together would offer the user a full feature set from any device. they would just have to port forward whatever port they specify in your app to the computer running EG and can access it from any browser. and you could then do whatever it is you like as far as the page layout. let the user pick some colors of the various display grafix. people like to have the ability to customize. gives them a sense that they had a part in making it. but also will allow them to put together something that would suit their color scheme in the home if accessing it from tablets throughout the home. I know this can also be done via cookie data so they would be able to do it on a per device basis.. but that would be something to do if you wanted to in the future.

the data that comes back from the AVR over the Telnet connection are like CVFL ** this is for the Main Zone Channel Volume Front Left and the ** would be the amount that it is set to. and when sending a command it would be the same if a user inputed value (replacing the ** with the value) and CVFL UP if they wanted to move it one position up


so basically most things fall into the Up Down ** for commands. there are some that are specialized. more so in the settings area of things. that is why i said i was going to "translate" the API for the Surround Mode Left and Right. and turn it into Up and Down
If you like the work I have been doing then feel free to Image
User avatar
yokel22
Experienced User
Posts: 265
Joined: Thu Feb 05, 2015 5:56 pm
Location: U.S. - Kansas city

Re: Denon & Marantz Network Control Plugin

Post by yokel22 »

They are from http requests. If you look at this plugin, the core actions are run over WS(the same telnet cmds). The http requests are just to initialize all variables with one request, instead of 4-5 WS requests. This is how the default Web-UI that runs off the AVR's port 80 is done too. When i look in the console window for the default Web-UI I'll see the request for that xml once a second. But the rest of the cmds are handled over port 23's WS connection.

I'm not really sure that it's even necessary to write a separate plugin to do this. Unless your wanting to accomplish it without the Webserver Plugin and packaging a smaller version. You'd just have to include the html files when the plugin installs and if possible tell it to add the webserver plugin with a pre-configed html file locations.

Everything will be completely configurable via html and css. That's why i suggested a web-ui instead of Wx. Maybe i'm wrong in my thinking, but html and css are languages most EG users will already be a little familiar with. If you want what i can do via the plugin though is to have Wx config's to allow for changes to the html and css. Then the user just has to enter things like "Font Color, Background color, Icons, Spacing" into the plugins config.
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Denon & Marantz Network Control Plugin

Post by kgschlosser »

it looks as tho

Code: Select all

UGDN\r 
can be sent over telnet connection to get the firmware revision.. but that is really going to dictate what commands it supports and what commands don't. but also makes grouping easier.. because if there are 40 different models (because of different regions of the world) that use the same firmware.. based on that firmware we know what commands it will be able to use.

as an example... a firmware revision for a US model will not have commands for Analog Tuner but will have HDRadio commands... but a firmware revision for anywhere else will not have commands for HDRadio but will have commands for Analog and also if they expand functionality through firmware and turn on commands for models that didn't previously have those commands. it makes it easy for me to add availability to those commands. and for you.. you wouldn't have to do a thing. that is if you make the plugin in a manner that is dynamic based on that None checking for an attribute. so I would do a page layout in a manner that is modular. I will make a commands attribute that can be accessed to get a list of available commands for that item. and it wouldn't be that hard to also add another called commandDescriptions.. that would also be a list. and that list would be indexed the same as commands. and you would provide to the user the description list and based on the selection now have the index number to pull the command to be sent off..

i could make an item class to be callable where you would only have to pass the index number instead. actually this might be the way to go because i can set up conversions from Db into a 1-100 scale make a command for each and dynamically make a display description and i can pass the length of the list to you. and you could make something like a volume knob with steps based on the length of the list. and use the step number to reference the index to send to my plugin which will pull the command to be sent off and when the AVR responds back have it update a display attribute nice user friendly display of the current status of that item to put into some kind of a "lcd display" have a button to click for the display to cycle through the various available statuses. but for the item they just changed have it flash up for like 3 seconds and then go back to whatever it was displaying before.


IDK. i don't know how extensive your skills are with doing something like that.. I can pretty much take care of anything you need for supplied for information form the AVR and for controlling the AVR. I would just need to know how you want to send data back and forth.. and what would be easiest. I am a dumdum in the area of anything web code based.. or what would be needed to make it easiest.. or how updates to the page get done..

if you want to educate an old man on how this is done it might help so i can set things up in an easy way.
If you like the work I have been doing then feel free to Image
User avatar
yokel22
Experienced User
Posts: 265
Joined: Thu Feb 05, 2015 5:56 pm
Location: U.S. - Kansas city

Re: Denon & Marantz Network Control Plugin

Post by yokel22 »

All i'd really need are lists of possible inputs, zones, etc. Basically if you give me a list or dictionary i can have those appended to a select menu or a custom menu with icons and other styling. Or have images for each item in the list. Same for any other type of control that will have varying cmds based on model. Any Action can be called directly from the web-ui via javascript, no interaction is required on the Denon/Marantz plugin end.

To see a basic version of how the webserver plugin handles information exchange, see the first post here: viewtopic.php?f=13&t=9487

The Webserver broadcast data functions are the ones that would mainly be used.
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Denon & Marantz Network Control Plugin

Post by kgschlosser »

I was thinking without the use of the webserver plugin.. and if they wanted to add a button to access the AVR it would be via a link... I do not know how hard any of this is... i just look at all the code with the webserver plugin and the fact that most of things wouldn't be needed but would require setup in the plugin for variables and things of that nature which would not change at all and the user would have to enter.. maybe?? I really do not know how that thing works...

what is the formatting of the commands sent to the avr?? is it the exact same commands that appear in the API? or something different.. I ask this because In the other thread for the Marantz plugin. we are getting all kinds of undocumented responses from the AVR but only when something is connected by some other means (android or IOS app)

we know this... the VAR will only allow for one connection to the telnet

so if the android or IOS app use the web api to control it.. but EG is connected via telnet.. how is it still being controlled???.. it can't be by use of the telnet...

does the web portal on the AVR still function when something is connected to the telnet???
because if it does then the telnet is not the means it is using to communicate commands. and this would bring about the understanding of why it has a very limited command set when using the we portal. otherwise it would have the full command set that the telnet does.. and from what i have read is that the http API does not have anywhere near the same number

because the use of the telnet has about 750 "commands" this does not include commands that have user input.. for things like volume which is 103 in it's self. so you have to figure each channel volume command set has 26 commands each. and there are 31 command sets for channel volume just for the Main Zone. so there are 806 unique commands just for the Channel Volume for the Main Zone alone

I have a running list of commands that is HUGE absolutely massive. I have a running dictionary of commands descriptions events. and whatever else and I am not even close to being done and it's at 3000 lines so far. and this does not include any of the user input ones.. only a ** as a place holder for requesting user input. and those commands/events get generated at time of use.

But because of things like the AVR model and what the max volume is.. I am thinking I may opt for having them created at plugin startup instead of dynamically each and every time.. because if something else is going to need the data. it needs to be set in place instead of dynamically being provided.. especially if it is needed for displaying things like volume increments
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Denon & Marantz Network Control Plugin

Post by kgschlosser »

broadcast data functions?. explain what those exactly are.. is that a websockets thing?
If you like the work I have been doing then feel free to Image
User avatar
yokel22
Experienced User
Posts: 265
Joined: Thu Feb 05, 2015 5:56 pm
Location: U.S. - Kansas city

Re: Denon & Marantz Network Control Plugin

Post by yokel22 »

It's Json data formatted. For sending data sets instead of single variables.

What your wanting to do would basically just involve having a side plugin that has a simpler webserver built in. Then build in whatever communication is needed between the Marantz/Denon plugin. Then everything could be set to autoload whatever commands are need on the web-ui plugin. Then the user could configure the UI to there liking from the eg config.

The WebUi and Android app have no problem communicating when a telnet connection is active. The http api still functions normally too. So they must be using REST commands for everything. But there are alot of options in the web-ui that i haven't seen documented anywhere for the REST api. I can send you a copy of the javascript that runs on the default web-UI if you want a closer look. I know there's an index of all available AVR's in there too that reference the modelId number.

EDIT: This is from the default web-ui javascript . It's parsing the xml for the modelId then appending the available inputs for each model. These are the basic lists that would be needed.

Code: Select all

function parseFuncXml(data) {
	var selectSource = data.getValue("InputFuncSelect");
	var rename = data.find("RenameSource value");
	var source = data.find("InputFuncList value");

	//Source Area
	if(parseInt( data.getValue( "ModelId" ) ) == 1){ // EnModelAVRX10
		$("div#S3").css("display", "block");
		appendSource($("div#S3 div.btn31"), $("<div>CBL/SAT</div>"), "SAT/CBL");
		appendSource($("div#S3 div.btn32"), $("<div>DVD/Blu-ray</div>"), "DVD");
		appendSource($("div#S3 div.btn33"), $("<div>Blu-ray</div>"), "BD");
		appendSource($("div#S3 div.btn34"), $("<div>Game</div>"), "GAME");
		appendSource($("div#S3 div.btn35"), $("<div>AUX</div>"), "AUX1");
		appendSource($("div#S3 div.btn36"), $("<div>Media Player</div>"), "MPLAY");
		appendSource($("div#S3 div.btn37"), $("<div>iPod/USB</div>"), "USB/IPOD");
		appendSource($("div#S3 div.btn38"), $("<div>TV Audio</div>"), "TV");
		appendSource($("div#S3 div.btn39"), $("<div>Tuner</div>"), "TUNER");
		appendSource($("div#S3 div.btn310"), $("<div>Online Music</div>"), "NETHOME");
		appendSource($("div#S3 div.btn311"), $("<div>Bluetooth</div>"), "BT");
		appendSource($("div#S3 div.btn312"), $("<div>Internet Radio</div>"), "IRP");
		$("div#S3 div.btn313").css("display", "none");
		$("div#S3 div.btn314").css("display", "none");
		$("div#S3 div.btn315").css("display", "none");

	}else if ((parseInt( data.getValue( "ModelId" ) ) == 2) || // EnModelAVRX20
	          (parseInt( data.getValue( "ModelId" ) ) == 3) || // EnModelAVRX30
	          (parseInt( data.getValue( "ModelId" ) ) == 7) || // EnModelNR16
	          (parseInt( data.getValue( "ModelId" ) ) == 8)){ // EnModelSR50
		$("div#S3").css("display", "block");
		appendSource($("div#S3 div.btn31"), $("<div>CBL/SAT</div>"), "SAT/CBL");
		appendSource($("div#S3 div.btn32"), $("<div>DVD</div>"), "DVD");
		appendSource($("div#S3 div.btn33"), $("<div>Blu-ray</div>"), "BD");
		appendSource($("div#S3 div.btn34"), $("<div>Game</div>"), "GAME");
		appendSource($("div#S3 div.btn35"), $("<div>AUX1</div>"), "AUX1");
		appendSource($("div#S3 div.btn36"), $("<div>Media Player</div>"), "MPLAY");
		appendSource($("div#S3 div.btn37"), $("<div>TV Audio</div>"), "TV");
		appendSource($("div#S3 div.btn38"), $("<div>AUX2</div>"), "AUX2");
		appendSource($("div#S3 div.btn39"), $("<div>Tuner</div>"), "TUNER");
		appendSource($("div#S3 div.btn310"), $("<div>iPod/USB</div>"), "USB/IPOD");
		appendSource($("div#S3 div.btn311"), $("<div>CD</div>"), "CD");
		appendSource($("div#S3 div.btn312"), $("<div>Bluetooth</div>"), "BT");
		appendSource($("div#S3 div.btn313"), $("<div>Online Music</div>"), "NETHOME");
		appendSource($("div#S3 div.btn314"), $("<div>Media Server</div>"), "SERVER");
		appendSource($("div#S3 div.btn315"), $("<div>Internet Radio</div>"), "IRP");

	}else if(parseInt( data.getValue( "ModelId" ) ) == 9){ // EnModelSR60
		$("div#S3").css("display", "block");
		appendSource($("div#S3 div.btn31"), $("<div>CBL/SAT</div>"), "SAT/CBL");
		appendSource($("div#S3 div.btn32"), $("<div>DVD</div>"), "DVD");
		appendSource($("div#S3 div.btn33"), $("<div>Blu-ray</div>"), "BD");
		appendSource($("div#S3 div.btn34"), $("<div>Game</div>"), "GAME");
		appendSource($("div#S3 div.btn35"), $("<div>AUX1</div>"), "AUX1");
		appendSource($("div#S3 div.btn36"), $("<div>Media Player</div>"), "MPLAY");
		appendSource($("div#S3 div.btn37"), $("<div>TV Audio</div>"), "TV");
		appendSource($("div#S3 div.btn38"), $("<div>AUX2</div>"), "AUX2");
		appendSource($("div#S3 div.btn39"), $("<div>Tuner</div>"), "TUNER");
		appendSource($("div#S3 div.btn310"), $("<div>iPod/USB</div>"), "USB/IPOD");
		appendSource($("div#S3 div.btn311"), $("<div>CD</div>"), "CD");
		appendSource($("div#S3 div.btn312"), $("<div>Bluetooth</div>"), "BT");
		appendSource($("div#S3 div.btn313"), $("<div>Online Music</div>"), "NETHOME");
		appendSource($("div#S3 div.btn314"), $("<div>Phono</div>"), "PHONO");
		appendSource($("div#S3 div.btn315"), $("<div>Internet Radio</div>"), "IRP");

	}else if((parseInt( data.getValue( "ModelId" ) ) == 4) || // EnModelAVRX40
			 (parseInt( data.getValue( "ModelId" ) ) == 5) || // EnModelAVRX50
	         (parseInt( data.getValue( "ModelId" ) ) == 6) || // EnModelAVRX70
	         (parseInt( data.getValue( "ModelId" ) ) == 10) || // EnModelSR70
	         (parseInt( data.getValue( "ModelId" ) ) == 11) || // EnModelAV77
	         (parseInt( data.getValue( "ModelId" ) ) == 12)){ // EnModelAV88
		$("div#S4").css("display", "block");
		appendSource($("div#S4 div.btn41"), $("<div>CBL/SAT</div>"), "SAT/CBL");
		appendSource($("div#S4 div.btn42"), $("<div>DVD</div>"), "DVD");
		appendSource($("div#S4 div.btn43"), $("<div>Media Player</div>"), "MPLAY");
		appendSource($("div#S4 div.btn44"), $("<div>TV Audio</div>"), "TV");
		appendSource($("div#S4 div.btn45"), $("<div>Blu-ray</div>"), "BD");
		appendSource($("div#S4 div.btn46"), $("<div>AUX1</div>"), "AUX1");
		if(parseInt( data.getValue( "ModelId" ) ) == 4){ // EnModelAVRX40
			appendSource($("div#S4 div.btn47"), $("<div>Tuner</div>"), "TUNER");
		}else{
			if(parseInt( data.getValue( "SalesArea" ) ) == 0){ // NA
				appendSource($("div#S4 div.btn47"), $("<div>HD Radio</div>"), "HDRADIO");
			}else{
				appendSource($("div#S4 div.btn47"), $("<div>Tuner</div>"), "TUNER");
			}
		}
		appendSource($("div#S4 div.btn48"), $("<div>Bluetooth</div>"), "BT");
		appendSource($("div#S4 div.btn49"), $("<div>Game</div>"), "GAME");
		appendSource($("div#S4 div.btn410"), $("<div>AUX2</div>"), "AUX2");
		appendSource($("div#S4 div.btn411"), $("<div>Phono</div>"), "PHONO");
		appendSource($("div#S4 div.btn412"), $("<div>iPod/USB</div>"), "USB/IPOD");
		appendSource($("div#S4 div.btn413"), $("<div>CD</div>"), "CD");
		appendSource($("div#S4 div.btn414"), $("<div>Online Music</div>"), "NETHOME");
		appendSource($("div#S4 div.btn415"), $("<div>Media Server</div>"), "SERVER");
		appendSource($("div#S4 div.btn416"), $("<div>Internet Radio</div>"), "IRP");

		if((parseInt( data.getValue( "ModelId" ) ) == 6) || // EnModelAVRX70
	       (parseInt( data.getValue( "ModelId" ) ) == 12)){ // EnModelAV88
	         
			//Additional Source
			if (data.getValue("AddSourceDisplay") == "TRUE") {
				$("div#AddSource").css("display", "block");

				// Additioanl Source
				var ListAddSource = $( "div#AddSource div.AddSourceLabel select" ).empty();

				var opt = $( "<option/>" );
				opt.html( "" ).attr( "value", "" );
				ListAddSource.append( opt );
				
				var opt = $( "<option/>" );
				opt.html( "AUX3" ).attr( "value", "AUX3" );
				ListAddSource.append( opt );
				
				var opt = $( "<option/>" );
				opt.html( "AUX4" ).attr( "value", "AUX4" );
				ListAddSource.append( opt );
				
				var opt = $( "<option/>" );
				opt.html( "AUX5" ).attr( "value", "AUX5" );
				ListAddSource.append( opt );
				
				var opt = $( "<option/>" );
				opt.html( "AUX6" ).attr( "value", "AUX6" );
				ListAddSource.append( opt );
				
				var opt = $( "<option/>" );
				opt.html( "AUX7" ).attr( "value", "AUX7" );
				ListAddSource.append( opt );
			}
		}
	}

		//  Source Name
	$("#source .RParamSource").html(selectSource);

	//  PlayerView
	if(selectSource=="Online Music" || selectSource=="iPod/USB" || selectSource=="Bluetooth" ){
		$("#source .btnPlayerView").html("<a href='../NetAudio/index.html'>PlayerView ></a>");
	}else if(selectSource=="HD Radio"){
		$("#source .btnPlayerView").html("<a href='../Tuner/HDRADIO/index.html'>PlayerView ></a>");
	}else if(selectSource=="Tuner"){
		$("#source .btnPlayerView").html("<a href='../Tuner/TUNER/index.html'>PlayerView ></a>");
	}else{
		$("#source .btnPlayerView").html("&nbsp;");
	}


	if (data.getValue("BrandId") == "DENON_MODEL") {
		$("div#left").css("background-color", "#0e1033");

	   	//LOGO
		$("div#menuItemLogo").html("<img src= ../img/denon_Logo.gif>");

		//Quick Select
		$("#QuickSelectLabel .RParamQuickSelect").html("Quick Select");
		$("div#QuickSelect").css("visibility", "visible");
			}else{
	   $("div#left").css("background-color", "#b3b3b3");

		//LOGO
		$("div#menuItemLogo").html("<img src= ../img/marantz_Logo.png>");

		//Smart Select
		$("#QuickSelectLabel .RParamQuickSelect").html("Smart Select");
		$("div#QuickSelect").css("visibility", "visible");
	}


}


function parseSurroundXml(data) {
	var selectSurround = data.getValue("selectSurround");
	//  Source Name
	$("#SurroundLabel .RParamSoundMode").html(selectSurround);
}

/**
 * "/goform/formMainZone_MainZoneXml.xml" ´┐¢´┐¢´┐¢p´┐¢[´┐¢X´┐¢´┐¢´┐¢´┐¢html´┐¢´┐¢´┐¢\´┐¢z´┐¢´┐¢´┐¢´┐¢BVolume´┐¢´┐¢´┐¢´┐¢
 *
 * @since	2009/1/7
 * @param {XMLDocument} data ./index.html.xml.asp ´┐¢╠ôÃé¦ì´┐¢´┐¢¦î´┐¢´┐¢´┐¢
 */
function parseVolumeXml(data) {
	var bar;
	var bMute = data.getValue("Mute") != "off";

	//  Source Name
	if (bMute) {
		$("#VolumeLabel .RParamVolume").html("MUTING On");
	} else {
		$("#VolumeLabel .RParamVolume").html(data.getVolume());
	}

}
Corresponding model list:

Code: Select all

 ModelId
	EnModelUnknown,		//(0)
	EnModelAVRX10,		//(1)
	EnModelAVRX20,		//(2)
	EnModelAVRX30,		//(3)
	EnModelAVRX40,		//(4)
	EnModelAVRX50,		//(5)
	EnModelAVRX70,		//(6)
	EnModelNR16,		//(7)
	EnModelSR50,		//(8)
	EnModelSR60,		//(9)
	EnModelSR70,		//(10)
	EnModelAV77,		//(11)
	EnModelAV88,		//(12)
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Denon & Marantz Network Control Plugin

Post by kgschlosser »

ok so we now know that none of the apps or the webUI use the telnet or any of those commands.

I am trying to understand what you are trying to accomplish if you are interfacing with their webUI and not the telnet port. is it just to redesign the UI? because doing that will add no extra functionality. as I had stated before the web UI only supports about 1/6th of the actual command set. so if you were going to do a redesign I would suggest using the telnet to do this and add all the extra functionality..


maybe i have something all fumbled up here.. so lets start over...


you are in the process of making a web UI for the AVR. how is/was your version going to send commands and receive status updates???
If you like the work I have been doing then feel free to Image
User avatar
yokel22
Experienced User
Posts: 265
Joined: Thu Feb 05, 2015 5:56 pm
Location: U.S. - Kansas city

Re: Denon & Marantz Network Control Plugin

Post by yokel22 »

There are no actions in this plugin that use the web api. They are all over a websocket connection. It uses the same cmd set the telnet version uses. The only difference is this plugin was designed to open the connection, send cmd, then close connection. Nuts would have to confirm this but i believe it was to alleviate the problem of multiple device connections.

I added a single request to the web api for two reasons. First, i can send one request to the api and parse out twenty of the most pertinent variables. Where if I used the telnet/socket connection it would take atleast 6 individual requests. Second, the initial idea i had to solve the multiple connection problem was to setup a polling thread. I was using this function to create the initial dictionary, then i would put this into a polling thread and compare the two dicts for value changes. Then trigger an event if there is a value change. Like i said this is how the web ui handles it and why i thought of implementing it this way.

Code: Select all

def initValues (self):
        zmDict = {}
        url = 'http://' + str(self.host) + ':80/goform/formMainZone_MainZoneXml.xml'

        try:
            r = urllib2.urlopen(url, timeout = 1).read()
        except urllib2.HTTPError, e:
            eg.PrintNotice("Connection error, wrong IP or AVR not accessible")
            return False
        except urllib2.URLError, e:
            eg.PrintNotice("Connection error, wrong IP or AVR not accessible")
            return False

        j = minidom.parseString(r)

        po = j.getElementsByTagName('ZonePower')[0]
        Power = po.getElementsByTagName('value')[0].firstChild.nodeValue
        friend = j.getElementsByTagName('FriendlyName')[0]
        Name = friend.getElementsByTagName('value')[0].firstChild.nodeValue
        put = j.getElementsByTagName('InputFuncSelect')[0]
        Input = put.getElementsByTagName('value')[0].firstChild.nodeValue
        mut = j.getElementsByTagName('Mute')[0]
        Mute = mut.getElementsByTagName('value')[0].firstChild.nodeValue
        vol = j.getElementsByTagName('MasterVolume')[0]
        volu = vol.getElementsByTagName('value')[0].firstChild.nodeValue
        Volume = str((float(volu)+80))

        zmDict = {"Power":Power, "Input":Input, "Volume":Volume, "Mute":Mute}
        self.TriggerEvent(Name, zmDict)

        z2Dict = {}
        url2 = 'http://' + str(self.host) + ':80/goform/formMainZone_MainZoneXml.xml?=&ZoneName=ZONE2'

        try:
            q = urllib2.urlopen(url2, timeout = 1).read()
        except urllib2.HTTPError, e:
            return False
        except urllib2.URLError, e:
            return False

        q = urllib2.urlopen(url2).read()
        y = minidom.parseString(q)

        po2 = y.getElementsByTagName('ZonePower')[0]
        Power2 = po2.getElementsByTagName('value')[0].firstChild.nodeValue
        friend2 = y.getElementsByTagName('FriendlyName')[0]
        Name2 = friend2.getElementsByTagName('value')[0].firstChild.nodeValue + "Z2"
        put2 = y.getElementsByTagName('InputFuncSelect')[0]
        Input2 = put2.getElementsByTagName('value')[0].firstChild.nodeValue
        mut2 = y.getElementsByTagName('Mute')[0]
        Mute2 = mut2.getElementsByTagName('value')[0].firstChild.nodeValue
        vol2 = y.getElementsByTagName('MasterVolume')[0]
        volu2 = vol2.getElementsByTagName('value')[0].firstChild.nodeValue
        Volume2 = str((float(volu2)+80))

        z2Dict = {"Power":Power2, "Input":Input2, "Volume":Volume2, "Mute":Mute2}
        self.TriggerEvent(Name2, z2Dict) 
As for the web ui. To build and update variables I'm using the event dictionary "zmDict = {"Power":Power, "Input":Input, "Volume":Volume, "Mute":Mute}
self.TriggerEvent(Name, zmDict)". When this event is triggered on plugin start I use the variables to build the intial page and controls. Two update the page you just need to rely on the plugin events. When Power changes, you use that event to tell the webserver plugin to broadcast that value & the javascript will tell the page what to do with that information.

To send commands from the web ui. You can do this two ways. Have it trigger an event in EG then use that event to trigger the plugin's action. Or you can call the plugin's action directly via python statement. The second way won't show anything in the log window.

I'm happy to explain further, but if you spend 5 minutes looking at the demo, I'm confident it can explain it much better. viewtopic.php?f=13&t=9487
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Denon & Marantz Network Control Plugin

Post by kgschlosser »

yokel22 wrote:The second way won't show anything in the log window.
ah see that is where my plugin throws down the trump card. because my version has no need to disconnect.

because of the use of multi threaded sockets and opening a telnet port so other devices can connect to EG instead of the AVR. and EG forwards all information from the AVR to each connection. and also forwards any commands received to the AVR. so EG ends up being the man in the middle. but allows for an unlimited number of connections to it. and will pass the data to and fro. so the "middle man" EG can always stay connected which allows for things like this. Ifyou walk over and turn the volume knob on the AVR. It shows up as an event in EG Instantly. this could also power your UI so you would have instant updates on it. instead of your plugin having to poll and dodge other connections which can lead to lag. and if some other device does not drop the connection to the AVR your plugin would be rendered inoperable.


:-D
If you like the work I have been doing then feel free to Image
User avatar
yokel22
Experienced User
Posts: 265
Joined: Thu Feb 05, 2015 5:56 pm
Location: U.S. - Kansas city

Re: Denon & Marantz Network Control Plugin

Post by yokel22 »

Yep, that's why I stopped working on it when I saw you had a better solution.
Post Reply