Page 1 of 1
AddRecordSchedule Perl example?
Posted: Mon Oct 16, 2017 5:37 pm
by darknicht
Can anyone supply a Perl LibXML example for using Dvr/AddRecordSchedule in v29? I am knocking together a small program to search the guide for movies that meet my search criteria and schedule them for recording when/if they show up. I've got everything working except POSTing the schedule back to AddRecordSchedule, and my Google-Fu is failing me on that one.
Looking at some python examples, I know I need to use GetRecordSchedule to create a generic rule for the show I wish to schedule and then modify it and POST it back to AddRecordSchedule. I have pulled the generic rule into a DOM and modified it to what I need, but I just can't figure out how to now POST that DOM back to AddRecordSchedule.
Code: Select all
# Get the default rule for the program
$url = "http://$backend:6544/Dvr/GetRecordSchedule?ChanId=$programChanId&StartTime=$programStartTime";
$domGetRecordSchedule = XML::LibXML->load_xml(location=>$url);
# Modify to create new FindOne rule
($recRuleType) = $domGetRecordSchedule->findnodes('/RecRule/Type');
$recRuleType->removeChildNodes;
$recRuleType->appendText($recType);
($recRuleRecGroup) = $domGetRecordSchedule->findnodes('/RecRule/RecGroup');
$recRuleRecGroup->removeChildNodes;
$recRuleRecGroup->appendText($recGroup);
($recRuleAutoExpire) = $domGetRecordSchedule->findnodes('/RecRule/');
$recRuleAutoExpire->removeChildNodes;
$recRuleAutoExpire->appendText($autoExpire);
From the above, you can see that I have the desired recording rule residing in the DOM named $domGetRecordSchedule and now need to POST that back to my backend. This is my first time using Perl LibXML for posting data, and can't seem to find any examples of how to do so. Any help would be appreciated.
Full disclosure: I'm a hardware hack, not a programmer. I can usually make whatever small programs I need work, but they are not always (ever?) pretty or efficient.
Re: AddRecordSchedule Perl example?
Posted: Tue Oct 17, 2017 10:40 am
by daraden
Not a perl person, but did a quick google of "perl http post xml". looks like you need to use LWP::UserAgent and HTTP::Request to create an http post request.
Re: AddRecordSchedule Perl example?
Posted: Tue Oct 17, 2017 2:01 pm
by pvr4me
I can't help with the Perl bindings...but are you sure you need them? Can you not create a custom recording schedule in Myth and let it set up the rules? Basics are covered in the User Manual:
https://www.mythtv.org/wiki/User_Manual ... tom_Record
Several examples are in the wiki:
https://www.mythtv.org/wiki/Custom_Recording
Craig
Re: AddRecordSchedule Perl example?
Posted: Tue Oct 17, 2017 7:33 pm
by darknicht
daraden wrote: ↑Tue Oct 17, 2017 10:40 am
Not a perl person, but did a quick google of "perl http post xml". looks like you need to use LWP::UserAgent and HTTP::Request to create an http post request.
Yeah, I saw how to post via UserAgent, but I was hoping that there was a method to do so using LibXML since it can get from a URL. I'll likely have to resort to using UserAgent, but it would have been nice to be able to just post back the already built and formatted DOM rather than having to break out all the various nodes from it and pass them to the UserAgent call. Hopefully AddRecordSchedule only requires a handful of arguments passed to it and the majority are optional.
Re: AddRecordSchedule Perl example?
Posted: Tue Oct 17, 2017 7:49 pm
by darknicht
pvr4me wrote: ↑Tue Oct 17, 2017 2:01 pm
I can't help with the Perl bindings...but are you sure you need them? Can you not create a custom recording schedule in Myth and let it set up the rules?
<snip>
Craig
I
could create a custom rule every time I think of a show or movie that I might want to see if it ever makes it to one of the TV channels I subscribe to, but that would require me being in front of the mythtv system when I think of it. My method just requires me to jot the title in a note whenever I see/hear about it and then that note can get sucked into the mythtv system whenever the check is scheduled to run.
My general process flow is...
1) See/hear an ad for a new movie or show, and jot a note on my phone/tablet/laptop with the title
2) Notes get synchronized to my master list automatically whenever I am near my home network
3) Master list gets checked nightly by my scheduling script
4) Anything from my master list that has been seen in the MythTV programming guide gets scheduled to record
I have been using this process with 'tvwish' for several years now and it's been great for grabbing those movies that I see premiering in the theatre, but I'm going to wait to see it whenever it hits TV (in 3-24 months). The only reason I'm moving away from using tvwish is that it started throwing errors when I upgraded to myth v29 and I'd rather move to something using the recommended ServicesAPI and not the direct MySQL access that tvwish uses.
Re: AddRecordSchedule Perl example?
Posted: Wed Oct 18, 2017 5:15 am
by daraden
darknicht wrote: ↑Tue Oct 17, 2017 7:33 pm
Yeah, I saw how to post via UserAgent, but I was hoping that there was a method to do so using LibXML since it can get from a URL. I'll likely have to resort to using UserAgent, but it would have been nice to be able to just post back the already built and formatted DOM rather than having to break out all the various nodes from it and pass them to the UserAgent call. Hopefully AddRecordSchedule only requires a handful of arguments passed to it and the majority are optional.
wouldn't it be possible to use one of the toString/serialize methods to pass the DOM instead using individual nodes?
Re: AddRecordSchedule Perl example?
Posted: Wed Oct 18, 2017 1:46 pm
by bill6502
Hi,
Try looking here:
https://www.mythtv.org/wiki/Perl_API_ex ... e_database
I to don't use Perl and the Writing to the database section is misleading because it's
really using the API as you want. The expire.pl example shows how a POST is done,
but I've never (with the Python equivalent) sent data in XML.
Re: AddRecordSchedule Perl example?
Posted: Wed Oct 18, 2017 11:50 pm
by darknicht
daraden wrote: ↑Wed Oct 18, 2017 5:15 am
wouldn't it be possible to use one of the toString/serialize methods to pass the DOM instead using individual nodes?
That's what I was looking for an example of doing. I was hoping somebody had a slick example already cooked up that I could run with. I'm not really familiar with manipulating the DOM, so this is very much a learning experience for me.
Re: AddRecordSchedule Perl example?
Posted: Wed Oct 18, 2017 11:54 pm
by darknicht
That's pretty close to what I imagine I'll need to do. My last piece of the puzzle is to figure out if there's an easy way to parse through the DOM and pass all the key=>value pairs found. Otherwise, I'll just pull out the required data into my own structure and pass it that way. I should have a chance to play with it again this weekend.
Re: AddRecordSchedule Perl example?
Posted: Fri Oct 20, 2017 3:00 pm
by bill6502
Here's a snippet from my Python version that may help you. As you can
see, not all parameters from the template are going to be sent back in the
Dvr/AddRecordSchedule endpoint. Also, you can see that Station in the
updated template comes from CallSign in the guide (EPG.)
Good luck.
Code: Select all
...
def update_template(template, guide_data, args):
'''
Put the guide information into the template for the new rule.
'''
try:
template['StartTime'] = guide_data['StartTime']
template['EndTime'] = guide_data['EndTime']
template['Title'] = guide_data['Title']
template['Type'] = 'Record {}'.format(args['type']) # Record All or Record One etc.
template['Station'] = guide_data['Channel']['CallSign']
template['ChanId'] = guide_data['Channel']['ChanId']
template['SearchType'] = 'None'
template['Category'] = guide_data['Category'] # The last four can be omitted...
template['SeriesId'] = guide_data['SeriesId']
template['FindTime'] = util.create_find_time(guide_data['StartTime'])
template['Description'] = 'Rule created by add_recording_rule.py'
except KeyError:
return False
return True
def create_rule(backend, postdata, args, opts): # postdata here is my updated template from above
'''
Send the changed data to the backend.
'''
endpoint = 'Dvr/AddRecordSchedule'
params_not_sent = ('AverageDelay', 'CallSign', 'Id', 'LastDeleted',
'LastRecorded', 'NextRecording', 'ParentId')
for param in params_not_sent:
del postdata[param]
...
Re: AddRecordSchedule Perl example?
Posted: Fri Oct 20, 2017 3:24 pm
by darknicht
bill6502 wrote: ↑Fri Oct 20, 2017 3:00 pm
Here's a snippet from my Python version that may help you.
<snip>
Thanks. That looks like it'll push me in the proper direction. At the very least it gives me an indication of which parameters are mandatory for the API call. I was figuring I'd have to do a code-dive or trial and error to figure out what information _must_ be passed. The entry for AddRecordSchedule on the wiki makes it sound like it requires everything gathered from GetRecordSchedule to be passed back to it. I'm glad that is not so, as it makes creating the rule much easier if I only need to pass the items that are different from the default rule.
I'll bang away at the code this weekend and see if I can make headway. Worst case scenario is I just re-write in python since there are pre-existing examples already written. (Thanks to you!)
Everyone's help has been appreciated.
<Edited for typo's>
Re: AddRecordSchedule Perl example?
Posted: Fri Oct 20, 2017 5:20 pm
by bill6502
To be clear, return everything from the template, with the above exceptions.
At least modify the 'top 7', as shown. If you're going the Python route, this link
should get you much closer. Be sure to read the comments at the top for the
requirement.
https://pastebin.com/ADNuuS0P
EDIT, used pastebin as attachement didn't work
Re: AddRecordSchedule Perl example?
Posted: Fri Oct 20, 2017 10:01 pm
by darknicht
Thanks for the link. It looks like it has all the logic I'm missing. I should be able to use that to get something working for myself.
Re: AddRecordSchedule Perl example?
Posted: Fri Oct 27, 2017 10:22 pm
by darknicht
Closing the loop on this question in case anyone else is looking for an example. Below is what I ended up using to create the new recording rule...
Code: Select all
use strict;
use warnings;
use XML::LibXML;
use LWP::UserAgent;
my $browser = LWP::UserAgent->new;
my $response = "";
my $backend = "myth_backend_hostname";
my $url = "";
my $programStartTime = "";
my $programChanId = "";
my $recPriority = 0;
my $recType = "Record One";
my $recGroup = "MyMovies";
my $recAutoExpire = "false";
# ...Omitting a whole bunch of logic code for finding the program StartTime and Channel ID for the program I wish to schedule...
# Get the default rule for the program
$url = "http://$backend:6544/Dvr/GetRecordSchedule?ChanId=$programChanId&StartTime=$programStartTime";
$domGetRecordSchedule = XML::LibXML->load_xml(location=>$url);
# Modify to create new FindOne rule (also converting DOM to HASH as I can pass that directly to useragent post)
foreach my $node ($domGetRecordSchedule->documentElement->childNodes) {
$newRecRule{$node->nodeName} = $node->to_literal;
}
$newRecRule{'AutoExpire'} = $recAutoExpire;
$newRecRule{'RecGroup'} = $recGroup;
$newRecRule{'RecPriority'} = $recPriority;
$newRecRule{'Type'} = $recType;
$newRecRule{'Station'} = $newRecRule{'CallSign'};
delete $newRecRule{'AverageDelay'};
delete $newRecRule{'CallSign'};
delete $newRecRule{'Id'};
delete $newRecRule{'LastDeleted'};
delete $newRecRule{'LastRecorded'};
delete $newRecRule{'NextRecording'};
delete $newRecRule{'ParentId'};
# POST the new rule
$url = "http://$backend:6544/Dvr/AddRecordSchedule";
$response = $browser->post( $url, \%newRecRule );
if ($response->is_success) {
print "......Movie: '$programTitle ($programAirdate)' - '$programId' recording rule created\n";
} else {
print "ERROR: Failed to create recording rule\n";
print $response->content;
print "\nStartTime = ",$newRecRule{'StartTime'}, ", ChanId = ",$newRecRule{'ChanId'};
print "\n";
}
Thanks again to everyone for the help figuring this out!