Author Topic: Best Approach to Controlling a Network Device  (Read 45020 times)

tschak909

  • LinuxMCE God
  • ****
  • Posts: 5549
  • DOES work for LinuxMCE.
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #15 on: November 01, 2013, 09:36:49 pm »
If you notice, this is a pointer to a RokuDevice class. This code is abstracted into RokuDevice.cpp and .h, have a look there.

I did this, to keep the main C++ code clean, and to compartmentalize all the CURL logic  in place.

-Thom

golgoj4

  • NEEDS to work for LinuxMCE
  • ***
  • Posts: 1193
  • hrumpf!
    • View Profile
    • Mah Website
Re: Best Approach to Controlling a Network Device
« Reply #16 on: November 02, 2013, 12:30:28 am »
I also have a RPI and it's been sitting in my desk drawer waiting to be unleashed.  I played around with RaspBMC a little and liked it but am trying to get more from LMCE so I've put it on hold.  I'd like to see the PI running as an MD but I'm also going to use them as squeezeslaves.  I know zero about coding and wish I could give you guys a hand other than testing.  Anyone have any ideas where and what code I can learn to help you guys out.

Be a little more patient. I finally got all my pi's setup and toolchain to build qorbiter for it. which can play audio for sure!
re what to learn, depends on what you like to do. pretty stuff everyone sees (GUI), or quiet things everyone uses and never realizes it (everything else).

Im always looking for more people who are interested in learning QML, which is similar to javascript in MANY ways, but in general we are all happy if anyone jumps in to contribute in most ways. Except management. don't think you can really do better than possy. jus sayin.

-langston
Linuxmce - Where everyone is never wrong, but we are always behind xbmc in the media / ui department.

CentralMedia

  • Guru
  • ****
  • Posts: 161
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #17 on: November 03, 2013, 07:28:00 pm »
Ok, so the send function under sys/socket.h, is what is transmitting similar to what the curl will do or its what curl is based on?

Honestly I did not know that struct addrinfo *m_pServerInfo, was a definition of a pointer.

Additional, I googled all the includes, to understand what they provide and an understanding of the processes with the code, got links similar to below.
Quote
http://pubs.opengroup.org/onlinepubs/009604499/basedefs/sys/socket.h.html

Is there any other site, which defines the options you can include?


tschak909

  • LinuxMCE God
  • ****
  • Posts: 5549
  • DOES work for LinuxMCE.
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #18 on: November 03, 2013, 08:36:37 pm »
Ah actually, yes, in this case, I just did direct socket comms, not curl.

And yes, it will be similar.

Some more reading material:

http://stackoverflow.com/questions/11973994/json-requests-in-c-using-libcurl
and http://zserge.bitbucket.org/jsmn.html provides a C library for parsing simple JSON.

You can use libcurl to get the json, and then use jsmn to spit out something more useful.

-Thom

CentralMedia

  • Guru
  • ****
  • Posts: 161
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #19 on: November 05, 2013, 04:40:37 pm »
Thanks

Well I believe I have made some steps, got basic function under c++, as I was able to get a one off command to work, move right, have not handled getting the response as suggested, working on.

Have not done an LNMCE specific stuff yet, just trying to understand the process, that is coding in c++ and how all works, attempt shown  below
Quote
/**********************************
Testing the use of libcurl to send JSON
to XBMC

Put together from findings on google

************************************/
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <curl/curl.h>

int main()
{
   CURL *curl;
   CURLcode res;
   struct curl_slist *headers=NULL;
   char jsonObj[80];
   int a=1;
   float b=2.0;
   if (0 != curl_global_init(CURL_GLOBAL_ALL))
    {
      fprintf(stderr, "Global Call Failed: %s\n", "Some error");
      return false;
    }
   else
   {
      curl = curl_easy_init();
      if (curl)
      {
         sprintf(jsonObj, "\"jsonrpc\": \"%.1f\", \"method\": \"%s\", \"id\": \"%d\"", b, "Input.Right", a);
         /*Ok curl initialized, let first set the URL for XBMC */
         curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.80.150:80/jsonrpc");
         /*Set header here as CURLOPT_HTTPHEADER requires this variable type*/
         headers = curl_slist_append(headers, "Content-Type: application/json");
         curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
         /* Now specify the POST data */
         /*fprintf(stderr, jsonObj); to check what the object was doing, realized it converts everything to string, which fails for the    ID
         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj);*/
         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"jsonrpc\": \"2.0\", \"method\": \"Input.Left\", \"id\": 1}");
         curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)-1);
         curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
         res = curl_easy_perform(curl); /*So I segment faulting here */
         
         if(res != CURLE_OK)
         {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
         }
         /* always cleanup */
         
         curl_easy_cleanup(curl);
      }
      fprintf(stderr, "Clean global: %s\n", " ");
      curl_global_cleanup();
      return 0;
   }
}

What was helpful also, was curl at the command prompt, has an option to build the code, though it did not work when compiled, was nice
Quote
curl -i -X POST -H "Content-Type: application/json" -d "{\"jsonrpc\": \"2.0\", \"method\": \"Input.Right\", \"id\": 1}" http://192.168.80.150:80/jsonrpc --libcurl mytest.txt

Yes not nice, but seeing the light, currently testing options, as pass right, left, etc, then realized c++ does not support case statement with strings, so did with an if and else if, using compare.

 Now its time to start properly working on what can be the base, a xbmc_control.h and xbmc_control.cpp.

Any advice is welcomed, as c++ is totally new to me, google is truly a friend, wish I had more time, LOL.



tschak909

  • LinuxMCE God
  • ****
  • Posts: 5549
  • DOES work for LinuxMCE.
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #20 on: November 05, 2013, 07:18:32 pm »
Fantastic. Now you should try to at least, bring the "sending to device" stuff into at least its own function that can easily be called from the different commands, so all you have to do is just call that function...e.g.

take all the curl initialization code, and put it into getConfig...and make a variable, m_Curl, so that it can be easily dealt with in both the GetConfig() and your new send function.

-Thom

CentralMedia

  • Guru
  • ****
  • Posts: 161
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #21 on: November 06, 2013, 02:40:31 am »
Silly question

Ok, I created an xbmc.h and xbmc.cpp.

For the time I made it extremely basic, but my question comes, examples I am seeing online, create the class and the initialize it in main in the same .cpp file, I was wondering, if I have .h (hearder) and .cpp (code) files below, would need a separate .cpp file, lets say for testing, runXBMC.cpp, where I include the xbmc.h and then instantiate the object and call the function or I have this totally off?

xbmc.h
Quote
#include <string>
class xbmc
{
   private:
      string m_url;
   protected:
   public:
      xbmc(string url);
      SendToXBMC();
   
};

xbmc.cpp
Quote
#define _FILE_OFFSET_BITS 64
#include <curl/curl.h>
#include <xbmc.h>
/*Lets try this again, hopefully nicer*/
xbmc::SendToXBMC()
{
   CURL *curl;
   CURLcode res;
   struct curl_slist *headers=NULL;
   if (0 != curl_global_init(CURL_GLOBAL_ALL))
    {
      fprintf(stderr, "Global Call Failed: %s\n", "Some error");
      return false;
    }
   else
   {
      curl=curl_easy_init();
      if (curl)
      {
         /*Ok curl initialized, let first set the URL for XBMC */
         curl_easy_setopt(curl, CURLOPT_URL, m_url);
         /*Set header here as CURLOPT_HTTPHEADER requires this variable type*/
         headers = curl_slist_append(headers, "Content-Type: application/json");
         curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_headers);
         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"jsonrpc\": \"2.0\", \"method\": \"Input.Left\", \"id\": 1}"); /*need to create a json object to pass here*/
         curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)-1);
         curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
         res = curl_easy_perform(curl);
         if(res != CURLE_OK)
         {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
         }
         curl_easy_cleanup(curl);
         
      }
   }
   
   curl_global_cleanup();
}
/*Constructor URL for the XBMC PI to pass here*/
xbmc::xbmc(string url)
{
   m_url=url;
}

Have not compiled this as yet

Should add, this is from the perspective that when creating the device in LNMCE, it would give the ability to instantiate.
« Last Edit: November 06, 2013, 02:44:08 am by CentralMedia »

CentralMedia

  • Guru
  • ****
  • Posts: 161
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #22 on: November 06, 2013, 03:58:19 pm »
Ok found this, which I think clears up some stuff for me

Quote
http://www.learncpp.com/cpp-tutorial/19-header-files/

CentralMedia

  • Guru
  • ****
  • Posts: 161
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #23 on: November 06, 2013, 05:14:19 pm »
I am failing at the following, bit stumped, see attached

Quote
g++ main.cpp -o test
main.cpp: In function ‘int main()’:
main.cpp:9: error: no matching function for call to ‘xbmc::xbmc()’
xbmc.h:10: note: candidates are: xbmc::xbmc(std::string)
xbmc.h:5: note:                 xbmc::xbmc(const xbmc&)
main.cpp:11: error: conflicting declaration ‘xbmc xbmc_url’
main.cpp:8: error: ‘xbmc_url’ has a previous declaration as ‘std::string xbmc_url’


tschak909

  • LinuxMCE God
  • ****
  • Posts: 5549
  • DOES work for LinuxMCE.
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #24 on: November 06, 2013, 05:21:02 pm »
try m_xbmc = xbmc::xbmc(xbmc_url);

this will set up m_xbmc appropriately.

When you move this into DCE, you may want to do

Code: [Select]
xbmc* m_pXBMC;
m_pXBMC = new xbmc::xbmc(xbmc_url);
m_pXBMC->DoSomething();

and in your DCE device's destructor, do:
Code: [Select]
delete m_pXBMC;
m_pXBMC=NULL;

This is demonstrating two ways to instantiate an object, either on the stack (The former), or on the heap (The latter)...the latter is usually preferred, as it uses heap (main memory) versus the stack, which is limited, and tends to get destroyed when functions end. When you do a new, you need to do a corresponding delete, to make sure you give the memory back to the operating system, otherwise, you'll have a memory leak.

-Thom

CentralMedia

  • Guru
  • ****
  • Posts: 161
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #25 on: November 06, 2013, 11:37:41 pm »
Hi tschak909

I tried it and getting the following error

Quote
g++ main.cpp -o test
/tmp/cchrNCNr.o: In function `main':
main.cpp:(.text+0x81): undefined reference to `xbmc::xbmc(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
main.cpp:(.text+0xb1): undefined reference to `xbmc::~xbmc()'
main.cpp:(.text+0xc3): undefined reference to `xbmc::~xbmc()'
collect2: ld returned 1 exit status

I even tried but no luck, same error
Quote
xbmc m_xbmc(xbmc_url);

Would this be the linker not getting the code for the xbmc.h from xbmc.cpp?

tschak909

  • LinuxMCE God
  • ****
  • Posts: 5549
  • DOES work for LinuxMCE.
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #26 on: November 06, 2013, 11:51:57 pm »
The unresolved symbols are because you're bringing in the source code for the xbmc class, but the compiler isn't linking in the xbmc compiled output, so that it knows where the compiled code is... you need to also compile in xbmc.cpp, as well.

at the very least,

Code: [Select]
gcc -o test main.cpp xbmc.cpp

-Thom

CentralMedia

  • Guru
  • ****
  • Posts: 161
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #27 on: November 07, 2013, 01:52:29 am »
Hi tschak909

This worked, I have a question though, is it acceptable to include in main.cpp the xbmc.cpp?

tschak909

  • LinuxMCE God
  • ****
  • Posts: 5549
  • DOES work for LinuxMCE.
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #28 on: November 07, 2013, 02:08:12 am »
It works, but it is better form to have each class have its own cpp and .h (usually, there are exceptions, just look in our DCE library)

This is all somewhat moot, because when you get ready to run DCEGen to make a C++ project, it will make the skeleton classes for the DCE device, that you just fill in the methods.

Now that you've made a xbmc class, you've encapsulated the logic to talk to it, and can more easily call it from the generated classes that DCEGen will make.

Oh, also, DCEGen will make a Makefile for you, so that you can build the device, without having to manually run gcc.

-Thom

CentralMedia

  • Guru
  • ****
  • Posts: 161
    • View Profile
Re: Best Approach to Controlling a Network Device
« Reply #29 on: November 07, 2013, 01:44:48 pm »
Ok thanks

Well did some testing with calling the function, just navigation, see code attached.

Now, its what is maybe the hardest part, not clear in my head yet that why, getting the json output, checking it and doing something with it, fun times, looking at what you suggested, but they indicated a demo.c but it was not there when I did the hg clone, found another example, but have to wrap my head around it.

Suggestions from anyone is also welcomed.