JSON-RPC messages to transmission-daemon

323 views
Skip to first unread message

Laurie

unread,
Feb 8, 2012, 5:08:37 AM2/8/12
to Jayrock
I am trying to write a plugin in C# for Mediaportal to display stats
about what is running on transmission. It uses JSON-RPC and I am
trying to just create a simple scenario to learn what to do. I want to
simply make a connection, then from that ask the RPC server what its
version is and display that as a message.

They have their rpc-spec listed on the link below:

https://trac.transmissionbt.com/browser/trunk/extras/rpc-spec.txt

I am trying to use WebClient to create the connection to the daemon
and then send the request but I am totally lost (a total newbie to C#
but willing to learn!).

Would anyone be kind enough to provide me some example code on how to
establish a "session" to the rpc server and simply ask it what its
"version" is and then store that to a variable? I can then test this
with my plugin as it stands today (basically I want to use this as a
"test" button in the configuration parameters to verify communication
works).

I have attempted to dissect code from transmission-remote-gui on
Google code, but it is very complex :(

Any help MUCH appreciated!

Atif Aziz

unread,
Feb 9, 2012, 10:29:43 AM2/9/12
to jay...@googlegroups.com
For starters, the spec you've pointed out is an RPC protocol using JSON, but it's not the same JSON-RPC as detailed on http://www.jsonrpc.org. Jayrock comes with a JSON-RPC client that works with the latter. However, it should be straightforward to work with  transmission using WebClient for HTTP and Jayrock for working with JSON.

I don't know transmission and don't have a running version to test anything out but I tried to come up with something based on the spec and reading GetSessionInfo in transmission-remote-gui. I've attached the code and posted it online. Hopefully it'll be enough to get you started on the right foot.

- Atif


--
You received this message because you are subscribed to the Google Groups "Jayrock" group.
To post to this group, send email to jay...@googlegroups.com.
To unsubscribe from this group, send email to jayrock+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/jayrock?hl=en.


Program.cs

Laurie

unread,
Feb 10, 2012, 5:12:35 AM2/10/12
to Jayrock
Thanks very much! I will try this out tonight, I see this is going to
run as a command prompt, I will test it first and then modify it to my
needs as I need it in .dll assembly for my plugin in Mediaportal.

I am guessing I can assign the result of the "invoke" method to a
variable and then display this in the GUI?

Many Many thanks for helping out. When I get it working I will make
sure I credit your assistance :)

On Feb 9, 3:29 pm, Atif Aziz <aziza...@gmail.com> wrote:
> For starters, the spec you've pointed out is an RPC protocol using JSON,
> but it's not the same JSON-RPC as detailed onhttp://www.jsonrpc.org.
> Jayrock comes with a JSON-RPC client that works with the latter. However,
> it should be straightforward to work with  transmission using WebClient for
> HTTP and Jayrock for working with JSON.
>
> I don't know transmission and don't have a running version to test anything
> out but I tried to come up with something based on the spec and
> reading GetSessionInfo
> in transmission-remote-gui<http://code.google.com/p/transmisson-remote-gui/source/browse/trunk/r...>.
> I've attached the code and posted it online<https://gist.github.com/1780657>.
>  Program.cs
> 6KViewDownload

Laurie

unread,
Feb 10, 2012, 5:16:03 AM2/10/12
to Jayrock
Oh, I forgot to add there is also a very detailed standalone
transmission GUI called transmission-remote-dotnet on googlecode that
I had also looked at, but again I could not figure out what was
happening! It was much too complex for what I need right now, as my
plugin will be running requests in the background and simply be
passing them to mediaportal to display as text (to begin with).

Not sure if that helps you verify the code you have already sent :)

Atif Aziz

unread,
Feb 10, 2012, 6:19:01 AM2/10/12
to jay...@googlegroups.com
Ah and I noticed they're using Jayrock too[1].

I guess the code is complex partly due to use of non-blocking operations so that the UI remains responsive. Unfortunately I don't have the time to go through all of it to verify if my initial crack at it is correct or not. The spec seems simpler. :)

I am guessing I can assign the result of the "invoke" method to a
variable and then display this in the GUI?

Yes, that's right. What you find in and you need from  the result of the invoke method depends on what method was invoked.

When you get it working, it would be great if you could drop a line with the changes the code still needed to be functional. It will become food for search engines and future hunters looking to venture in the same area.

- Atif

Laurie

unread,
Feb 12, 2012, 1:09:53 PM2/12/12
to Jayrock
I tried building the code but I get an error on the var responseObject
within the Invoke method :(

The non-generic method
'Jayrock.Json.Conversion.JsonConvert.Import(System.Type,
Jayrock.Json.JsonReader)' cannot be used with type arguments

On Feb 10, 11:19 am, Atif Aziz <aziza...@gmail.com> wrote:
> Ah and I noticed they're using Jayrock too[1].
>
> I guess the code is complex partly due to use of non-blocking operations so
> that the UI remains responsive. Unfortunately I don't have the time to go
> through all of it to verify if my initial crack at it is correct or not.
> The spec seems simpler. :)
>
> I am guessing I can assign the result of the "invoke" method to a
>
> > variable and then display this in the GUI?
>
> Yes, that's right. What you find in and you need from  the result of the
> invoke method depends on what method was invoked.
>
> When you get it working, it would be great if you could drop a line with
> the changes the code still needed to be functional. It will become food for
> search engines and future hunters looking to venture in the same area.
>
> - Atif
>
> [1]http://code.google.com/p/transmission-remote-dotnet/source/browse/#sv...
> >http://groups.google.com/group/jayrock?hl=en.- Hide quoted text -
>
> - Show quoted text -

Atif Aziz

unread,
Feb 12, 2012, 4:29:40 PM2/12/12
to jay...@googlegroups.com
What version of Jayrock are you using?

Laurie

unread,
Feb 12, 2012, 6:25:09 PM2/12/12
to Jayrock
A version that was too old it seems :) Updating solved that issue, but
when I run the exe I now get a crash :(

Unhandled exception: System.argumentNullException: value cannot be
null
Parameter name: address

at Program.cs line:72

at line:18

It seems to be an issue with System.Net.Webclient.UploadString ...
> > > >http://groups.google.com/group/jayrock?hl=en.-Hide quoted text -

Atif Aziz

unread,
Feb 13, 2012, 5:40:13 AM2/13/12
to jay...@googlegroups.com
Yep, looks like I forgot to initialize the Url property with the value supplied in the constructor. I also fixed another similar problem, which was storage of any new Id allocated to the session in the SessionId property (for subsequent invocations). You can find the updated version attached and online.

Let me know how it goes.

- Atif
Program.cs

Laurie

unread,
Feb 13, 2012, 7:06:52 AM2/13/12
to Jayrock
Amazing :) That works, it prints out the whole config of the session!
yay! So now I guess I need to look into how I properly handle this
info :)

Thanks so much for the start! I will report back with my findings :)

On Feb 13, 10:40 am, Atif Aziz <aziza...@gmail.com> wrote:
> Yep, looks like I forgot to initialize the Url property with the value
> supplied in the constructor. I also fixed another similar problem, which
> was storage of any new Id allocated to the session in the SessionId
> property (for subsequent invocations). You can find the updated version
> attached and online <https://gist.github.com/1780657>.
> > > > > >http://groups.google.com/group/jayrock?hl=en.-Hidequoted text -
>
> > > > > - Show quoted text -
>
> > > > --
> > > > You received this message because you are subscribed to the Google
> > Groups
> > > > "Jayrock" group.
> > > > To post to this group, send email to jay...@googlegroups.com.
> > > > To unsubscribe from this group, send email to
> > > > jayrock+u...@googlegroups.com.
> > > > For more options, visit this group at
> > > >http://groups.google.com/group/jayrock?hl=en.-Hide quoted text -
>
> > > - Show quoted text -
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Jayrock" group.
> > To post to this group, send email to jay...@googlegroups.com.
> > To unsubscribe from this group, send email to
> > jayrock+u...@googlegroups.com.
> > For more options, visit this group at
> >http://groups.google.com/group/jayrock?hl=en.
>
>
>
>  Program.cs
> 6KViewDownload

Laurie

unread,
Feb 13, 2012, 11:42:44 AM2/13/12
to Jayrock
So I have had a play with this code and I can now get it to print the
number of active torrents, the speeds etc, perfect.

My next question is how do I pass "arguments" to the server as key/
value pairs? I tried issuing the method "torrent-get" but it throws an
unknown response error, looking at the spec I should be sending it
arguments too:

Method name: "torrent-get".

Request arguments:
(1) An optional "ids" array as described in 3.1.
(2) A required "fields" array of keys. (see list below)

Response arguments:
(1) A "torrents" array of objects, each of which contains the key/
value pairs matching the request's "fields" argument.
(2) If the request's "ids" field was "recently-active", a "removed"
array of torrent-id numbers of recently-removed torrents.

So my question is how do I send the arguments? Do I need to use
JsonArray?
> > > > > > >http://groups.google.com/group/jayrock?hl=en.-Hidequotedtext -
>
> > > > > > - Show quoted text -
>
> > > > > --
> > > > > You received this message because you are subscribed to the Google
> > > Groups
> > > > > "Jayrock" group.
> > > > > To post to this group, send email to jay...@googlegroups.com.
> > > > > To unsubscribe from this group, send email to
> > > > > jayrock+u...@googlegroups.com.
> > > > > For more options, visit this group at
> > > > >http://groups.google.com/group/jayrock?hl=en.-Hidequoted text -
>
> > > > - Show quoted text -
>
> > > --
> > > You received this message because you are subscribed to the Google Groups
> > > "Jayrock" group.
> > > To post to this group, send email to jay...@googlegroups.com.
> > > To unsubscribe from this group, send email to
> > > jayrock+u...@googlegroups.com.
> > > For more options, visit this group at
> > >http://groups.google.com/group/jayrock?hl=en.
>
> >  Program.cs
> > 6KViewDownload

Atif Aziz

unread,
Feb 13, 2012, 12:16:35 PM2/13/12
to jay...@googlegroups.com
You don't need to specifically use a JsonArray. The simplest way would be to setup your arguments as an anonymous object in C# and Jayrock will convert it to JSON:

client.Invoke("torrent-get", new {
  ids = new[] { 1, 2, 3 },
  keys = new[] { "key1", "key2", "key3" } } );

The array, of course, can be built dynamically. You can just build standard arrays, lists or collections and Jayrock will turn them into a JSON array.

- Atif

Laurie

unread,
Feb 13, 2012, 4:16:56 PM2/13/12
to Jayrock
Thanks again for the continued support :)

I have been trying to get this implemented into my plugin and for it
to display the download directory when pressing "test" so I can
confirm if it is connecting to the server correctly.

It seems that some of the classes do not want to work when building as
a class library instead of a console application. It seems that the
method does not get passed correctly and it returns an "unknown
method" response.

My code is here: http://code.google.com/p/mp-transmission/source/browse/
If you could find the time to assist I would be most grateful!

I have also messed with the Program.cs and tried to get the torrent-
get data, which does work, but I am now a bit lost on how I can assign
that data to something sensible that I can then use to display the
file names and percentages ... I have put the code here: http://pastebin.com/5sthjk3R

Laurie.
> ...
>
> read more »- Hide quoted text -

Atif Aziz

unread,
Feb 13, 2012, 6:03:01 PM2/13/12
to jay...@googlegroups.com
Try this:
 
var torrent = (IDictionary) client.Invoke("torrent-get", new { fields = new[] { "name", "percentDone" } }, null);
foreach (IDictionary torrent in (IList) torrent["torrents"])
    Console.WriteLine("{0}: {1}", torrent["name"], torrent["percentDone"]);
 
- Atif

Laurie

unread,
Feb 13, 2012, 6:11:49 PM2/13/12
to Jayrock
Thanks :-)

Do you know why all of this doesn't work in a class library format?
> ...
>
> read more »

Atif Aziz

unread,
Feb 13, 2012, 6:48:48 PM2/13/12
to jay...@googlegroups.com
I'm afraid that I cannot imagine why. It shouldn't make any different as far as Jayrock goes.
 
- Atif
 
 

Laurie

unread,
Feb 14, 2012, 11:09:10 AM2/14/12
to Jayrock
Hi Again!

Thanks very much for the help, I have now succeeded in assigning each
of the "names" into my own arrays of type "string" so that I can
access them elsewhere. I will continue playing, thank you very much
for the help, I am sure I will be back with other questions!

Laurie.
> read more »

Laurie

unread,
Feb 14, 2012, 11:37:33 AM2/14/12
to Jayrock
Just to ensure others can see what was done, here is my code now:
http://pastebin.com/kNnaXLyz

It is VERY amateur as I am just learning, but it does work. I am
probably being inefficient in many places, so any tips appreciated to
make this nicer :)
> ...
>
> read more »

Laurie

unread,
Mar 27, 2012, 6:33:10 AM3/27/12
to Jayrock
Hi Atif,

I wonder if you can help me again ... I have got pretty far with my
plugin and most is working well, now I am trying to get the stop/start/
remove methods written but I am running into difficulty in defining
which exact file to perform the action on. According to the RPC spec:

3.1. Torrent Action Requests

Method name | libtransmission function
---------------------
+-------------------------------------------------
"torrent-start" | tr_torrentStart
"torrent-start-now" | tr_torrentStartNow
"torrent-stop" | tr_torrentStop
"torrent-verify" | tr_torrentVerify
"torrent-reannounce" | tr_torrentManualUpdate ("ask tracker for more
peers")

Request arguments: "ids", which specifies which torrents to use. All
torrents are used if the "ids" argument is omitted. "ids" should be
one of the following:

(1) an integer referring to a torrent id
(2) a list of torrent id numbers, sha1 hash strings, or both
(3) a string, "recently-active", for recently-active torrents

Response arguments: none

I have a list of my "ids" in an array of "int" and I am using a method
to invoke the client:

public static void startTorrent(int startID)
{
var url = new Uri("http://" + LocalSettings.Hostname + ":"
+ LocalSettings.Port + "/transmission/rpc");
var client = new TransmissionClient(url);
client.Invoke("torrent-start", new { fields = new[]
{ startID } }, null);
}

I am calling the method using the selected torrent in the list like
this:

int selected = variables.torrentID[variables.selTorrent];
startTorrent(selected);

Now the issue is that ALL the torrrents start when doing this, not the
one selected, according to the spec above this means that no "ids"
were sent. What am I doing wrong here?

Thanks.
> ...
>
> read more »

Laurie

unread,
Mar 28, 2012, 4:52:11 AM3/28/12
to Jayrock
OK, please ignore my question posted above, it was a simple matter of
changing the name of the array from "fields" to "ids" :)

I do now have a question about building a Json object that I think I
now need to pass to the RPC server for a certain command. When a
torrent is selected to be removed, you can choose either to keep the
data, or pass a boolean value in addition to the array "ids" set to
true and it will remove downloaded data too.

I am trying to work out how to structure this and would love some
help ...

client.Invoke("torrent-remove", new { ids = new[] { removeID} },
null);

This is what I am using to remove a torrent without deleting data and
it works fine, but I cannot work out how to add the boolean value of
"true" to a parameter called "delete-local-data" and pass them both to
the "Invoke" method as the "arguments" object.

The issue being you cannot have a variable with "-" within it, so I
must create an object with that name, then set its value to
"true" ...

Please help!
> ...
>
> read more »

Atif Aziz

unread,
Mar 30, 2012, 11:48:39 AM3/30/12
to jay...@googlegroups.com
Try this:

client.Invoke("torrent-remove", 
  new JsonObject { 
    { "ids", new[] { removeID } }, 
    { "delete-local-data", true } 
  }, 
  null);

- Atif


> ...
>
> read more »

Laurie

unread,
Apr 2, 2012, 4:35:29 AM4/2/12
to jay...@googlegroups.com
Excellent! That worked perfectly! THANKS!
To unsubscribe from this group, send email to jayrock+unsubscribe@googlegroups.com.

Laurie

unread,
Apr 25, 2012, 10:39:40 AM4/25/12
to jay...@googlegroups.com
Hi once again :)

I have had a user of my plugin report that they get an error message when using my plugin. I am unable to replicate it, and the only difference is that they are using XP SP3 where I have only ever tested on Win7 builds.

The error is:

"Method not found: '!!0 Jayrock.Json.Conversion.JsonConvert.Import(System.String)'."

Could this be due to operating system? Is a specific .NET version required to be installed?

Thanks.
Reply all
Reply to author
Forward
0 new messages