Page 1 of 1

What is required to create an IR Device compatible Interface

Posted: Tue Jan 06, 2009 1:15 pm
by ScottBot
The following information is for anybody interested in developing a Hardware Interface that can send and receive IR codes. The details of the actual sending and receiving are specific to the particular hardware that you are interfacing to and are not covered at all here. The information here is really just general information regarding the required interface that the plugin needs to support to allow it to work with the existing HouseBot IRDevice plugin and examples of sending and receiving to/from the server. It does NOT cover IR learning from the interface.

The only interface that needs to be supported by the plugin is the SendIR interface.

Code: Select all

InterfaceInfo g_InterfaceSendIR = { 	
   0,
   "SendIR( IRPosition, [Property Value] )",
   "SendIR",
   "This interface will send the IR command that corresponds to IR Position specified.",			
   hfRequireIRConfiguration,
};
Specifying the hfRequireIRConfiguration flag will enable the association tab for IR codes to be displayed for Devices that use the interface.

Make sure to export the function.

Code: Select all

extern "C" HOUSEBOT_HARDWARE_API BOOL SendIR( HARDWARE_INSTANCE_HANDLE hInstanceHandle, InterfaceArgumentPack* pPack )
{
   // Send the code here.  Something like this can be used and is used as an example below.
   return( m_mapInstances[ hInstanceHandle ]->SendIR( pPack ) );
}

A function similar to the one below must can created and called from the main SendIR() export above. It is called with the InterfaceArgumentPack that contains the IR position and optional property value.

Code: Select all

HARDWARE_RC YourClassHere::SendIR( InterfaceArgumentPack* pPack )
{
   //
   // Make sure we can handle the version of the struct.
   if (pPack->m_nArgumentPackVersion != SUPPORTED_ARGUMENT_PACK_VERSION)
   {
      TraceMessage( ttError, "Unsupported Argument Pack Version [%s].  Must be version [%d]", pPack->m_nArgumentPackVersion, SUPPORTED_ARGUMENT_PACK_VERSION );
      return( hrcFailureAbort );
   }

   //
   // Make sure there are enough arguments.
   if (pPack->m_nNumberOfArguments < 1)
   {
      TraceMessage( ttError, "Invalid number of arguments supplied to SendIR() interface.  Expected 1.  Received %d", pPack->m_nNumberOfArguments );
      return( hrcFailureAbort );
   }

   if (!m_bEnabled)
   {
      return( hrcFailureAbort );
   }

   //
   // Break out the arguments from the argument pack.
   unsigned short  usIRPosition = (unsigned short)IntFromInterfaceArgument( &(pPack->m_aArguments)[ 0 ] );

   HARDWARE_RC rc = hrcSuccess;

   //
   // Get the specified IRCode from the server.  Call the base class to get the info.
   IRCode irCode;
   if (!GetIRCodeFromPosition( usIRPosition, &irCode ))
   {
      TraceMessage( ttError, "Unable to retrieve IRCode from server for IR Position %d", usIRPosition );
      rc = hrcFailureAbort;
   }
   else
   {
      // You now have the IRCode object with the information specific to the IR code.
      // Send it to the physical interface and set rc = something appropriate.
   }

   return( rc );
}
Receiving IR
If your interface can receive IR codes, here are a few tips on how to process and notify.

First you will need to get the IR Codes from the server so you have something to match incoming data against. I have not included every method in the code below, but it should give you the general idea.

Code: Select all

// We're using a member variable array 'm_aIRCodes' to hold the IR codes from the server.
// Clear the old array
ClearIRCodeArray();

//
// Check to see how large a buffer we need
DWORD dwBuffSize = 0;
if (GetIRCodes( NULL, &dwBuffSize ) &&
    (dwBuffSize))
{
   //
   // Allocate the array memory
   IRCode* pCodes = (IRCode*)malloc( dwBuffSize );

   //
   // Get fresh data from the server
   if (GetIRCodes( pCodes, &dwBuffSize ))
   {
      for (int nLoop = 0; pCodes[ nLoop ].m_szDescription; nLoop++)
      {
         // CIRCode is just a simple class to encapsulate the IR code info received from the server.
         // It has a constructor to convert from the basic IRCode object.
         CIRCode* pCode = new CIRCode;
         if (pCode->Init( pCodes+nLoop ))
         {
            //
            // See if it is one of our IR Codes.  Generally, there may be something specific
            // that was stored in the 'interface specific data' portion of the IR data when the
            // code was learned that can identify it as one of our codes.
            if (pCode->IsOneOfOurCodes())
            {
               m_aIRCodes.Add( pCode );
            }
            else
            {
               delete pCode;
            }
         }
         else
         {
            TraceMessage( ttError, "Unable to initialize IR Code [%s].", (IRCode*)(*pCodes+nLoop).m_szDescription );
         }
      }
   }

   //
   // Delete the memory
   free( pCodes );
}
Sending Notifications
To send a notification to the IRDevice when IR is detected, you must send the 'IR Response Received' notification message as shown below.

Code: Select all

   CDataPack   DataPack;
   DataPack.AddData( "IR Number", [string with IR Number goes here] );
   NotifySubscribedDevices( "IR Response Received", "", &DataPack );

Re: What is required to create an IR Device compatible Interface

Posted: Fri Jan 23, 2009 10:38 am
by peter
I've tried to make a IR interface talking with WinLIRC. That works so far. WinLIRC cannot deal with pronto codes. That's way I cannot use the complete workflow with Housebot's remote controls.
Thanks for posting the infos :D

By the way,I still have a question. Where does the IR code number shown in the Remote Code Library come from? Is this just a number generated by Housebot itself? I didn't find a matching number in the pronto xml files.
peter

Re: What is required to create an IR Device compatible Interface

Posted: Fri Jan 23, 2009 12:50 pm
by ScottBot
If your interface can learn the IR codes, you can set the 'Interface Specific Data' member of the IR Code to whatever ASCII data you want to store the code in your non-pronto format. Of course, this would mean that these IR codes would not be able to be used by other IR hardware interfaces, but that's many times the case anyway. You can then get this data from the IR code when requesting it later. It is stored in the library with the pronto code and other properties. You could probably just store the data as pronto data, but that might be a little confusing.

The IR code number is a unique id that is generated by the server when the code is first created.

Re: What is required to create an IR Device compatible Interface

Posted: Mon Jan 26, 2009 6:18 am
by peter
Hi Scott,
Is it true that the association of property values to IR codes is only applicable for sendig IR's? I first expected that if a code is received and finds an associated property value the regarding property is set to that value then. That seems to be not correct. At least it does not work. I see the "IR Code Number Received" changing, but everything else does not change. The Device Help suggests something similar.
What is behind of not doing so?

Best peter

Re: What is required to create an IR Device compatible Interface

Posted: Wed Jan 28, 2009 8:19 pm
by ScottBot
You are correct. The Property Value associations for IR are for SENDING only. Receiving will only set the IR Code number property.
peter wrote:...What is behind of not doing so?Best peter
A couple of things. One is the simple fact the the hardware interface notifications would not suffice for doing this, so an addition to the Hardware Interface API would need to be created that doesn't exist. The other thing is that you can actually chain/associate several IR codes to a single Property Value. This makes sense for sending, but I'm not sure what to make if it for reception.

However, I do agree to the fact that this is a feature that would be nice.