CM15A Plugin: Updated

HouseBot Plugin Development Discussions.
Post Reply
Nightrader_
Member
Posts: 30
Joined: Sun May 23, 2010 6:45 pm

CM15A Plugin: Updated

Post by Nightrader_ »

Update: I have a beta version ready, you can control device, but I have not gotten the recieve work yet.
download the attached zip and unzip the dll into your housebot plugin interfaces folder, restart Housebot.
I will post details soon (and the source).

"back to your regular scheduled programing"

I have been working on getting a CM15a hardware interface plugin.

My problem is I do not know CPP.

If someone could look this over and tell me why it is not working..

Code: Select all

#include "..\..\stdafx.h"
#include "TemplateInstance.h"
#include "..\..\Common\InterfaceAPI.h"
#include "..\..\Common\DataPack.h"

#include <ole2.h>

#include <objbase.h>
#include <wchar.h>

#include "..\..\ahscript.h"

const GUID CLSID_ActiveHome =           {0x001000AF, 0x2DEF, 0x0208, {0x10, 0xB6, 0xDC, 0x5B, 0xA6, 0x92, 0xC8, 0x58}};
const GUID IID_IActiveHome =            {0x001000AF, 0x3DEF, 0x0910, {0x10, 0xB6, 0xDC, 0x5B, 0xA6, 0x92, 0xC8, 0x58}};
const GUID IID__IActiveHomeEvents =     {0x001000AF, 0x3DEF, 0x0912, {0x10, 0xB6, 0xDC, 0x5B, 0xA6, 0x92, 0xC8, 0x58}};

HRESULT __fastcall AnsiToUnicode(LPCSTR pszA, LPOLESTR *ppszW)
{

    ULONG cCharacters;
    DWORD dwError;

    // If input is null then just return the same.
    if (NULL == pszA)
    {
        ppszW = NULL;
        return NOERROR;
    }

    // Determine number of wide characters to be allocated for the
    // Unicode string.
    cCharacters =  strlen(pszA)+1;

    // Use of the OLE allocator is required if the resultant Unicode
    // string will be passed to another COM component and if that
    // component will free it. Otherwise you can use your own allocator.
    *ppszW = (LPOLESTR) CoTaskMemAlloc(cCharacters*2);
    if (NULL == *ppszW)
        return E_OUTOFMEMORY;

    // Covert to Unicode.
    if (0 == MultiByteToWideChar(CP_ACP, 0, pszA, cCharacters,
                  *ppszW, cCharacters))
    {
        dwError = GetLastError();
        CoTaskMemFree(*ppszW);
        *ppszW = NULL;
        return HRESULT_FROM_WIN32(dwError);
    }

    return NOERROR;
}
/*
 * UnicodeToAnsi converts the Unicode string pszW to an ANSI string
 * and returns the ANSI string through ppszA. Space for the
 * the converted string is allocated by UnicodeToAnsi.
 */ 

HRESULT __fastcall UnicodeToAnsi(LPCOLESTR pszW, LPSTR* ppszA)
{

    ULONG cbAnsi, cCharacters;
    DWORD dwError;

    // If input is null then just return the same.
    if (pszW == NULL)
    {
        *ppszA = NULL;
        return NOERROR;
    }

    cCharacters = wcslen(pszW)+1;
    // Determine number of bytes to be allocated for ANSI string. An
    // ANSI string can have at most 2 bytes per character (for Double
    // Byte Character Strings.)
    cbAnsi = cCharacters*2;

    // Use of the OLE allocator is not required because the resultant
    // ANSI  string will never be passed to another COM component. You
    // can use your own allocator.
    *ppszA = (LPSTR) CoTaskMemAlloc(cbAnsi);
    if (NULL == *ppszA)
        return E_OUTOFMEMORY;

    // Convert to ANSI.
    if (0 == WideCharToMultiByte(CP_ACP, 0, pszW, cCharacters, *ppszA,
                  cbAnsi, NULL, NULL))
    {
        dwError = GetLastError();
        CoTaskMemFree(*ppszA);
        *ppszA = NULL;
        return HRESULT_FROM_WIN32(dwError);
    }
    return NOERROR;

}




// ====================================================================
// Method Name : CTemplateHardwareInstance
// Description : CTemplateHardwareInstance constructor
// Parameters  : hInstance - Hardware Instance Handle passed by HBRegisterProperties()
//                pCallBackInfo - Copy of callback info structure passed by HBModuleInit()
// ====================================================================
CTemplateHardwareInstance::CTemplateHardwareInstance( HARDWARE_INSTANCE_HANDLE hInstance, CallBackInfo* pCallBackInfo ) :
   CHardwareInstance( hInstance, pCallBackInfo ),
   m_bEnabled( FALSE )
{
   hInstanceHandle = hInstance;            
   m_dwStartCount = GetTickCount();
}

// ====================================================================
// Method Name : RegisterProperties
// Description : This method is called by the server to allow the
//                instance to register all of its properties.
// Returns     : TRUE if successful.  FALSE if unsuccessful.
// ====================================================================
BOOL CTemplateHardwareInstance::RegisterProperties()
{
   //
   // Register the properties.
   const char* aValues[] = { "Yes", "No", NULL };
   RegisterHardwareModuleProperty( "Enabled", ptToggle, aValues, "No", TRUE );

   //
   // Get the current state of the property values.
   LPCTSTR szEnabled = GetPropertyValueFromName( "Enabled" );
   if ((szEnabled) && (0 == strcmp( szEnabled, "Yes")))
   {
      m_bEnabled = TRUE;
   }
   else
   {
      m_bEnabled = FALSE;
   }

   //
   // Add a button to test notifications
   RegisterHardwareModuleButton( 2, "Subscription Notification", "Press to send a subscription notification to Devices" );

   return( TRUE );
}


// ====================================================================
// Method Name : UpdatePropertyValue
// Description : This method is called by the server when the user
//                changes a property value.
// Parameters  : szPropertyName - Name of property that has changed.
//               szNewValue - New value of the property.
// Returns     : Returns TRUE if changed successfully.  Returns FALSE if not changed successfully.
// ====================================================================
BOOL CTemplateHardwareInstance::UpdatePropertyValue( const char* szPropertyName, const char* szNewValue )
{
   //
   // See if it is the "Enabled" property.
   if (0 == strcmpi( szPropertyName, "Enabled" ))
   {
      //
      // Set our private member m_bEnabled based on the new value.
      if (0 == strcmpi( szNewValue, "Yes" ))
      {
         m_bEnabled = TRUE;
      }
      else
      {
         m_bEnabled = FALSE;
      }
   }
   return( TRUE );
}

// ====================================================================
// Method Name : PropertyButtonClick
// Description : This method is called by the server when the user
//                presses a property button
// Parameters  : nButtonCallbackID - Button ID passed in RegisterHardwareModuleButton()
//                that identifies the button pressed.
// ====================================================================
BOOL CTemplateHardwareInstance::PropertyButtonClick( int nButtonCallbackID )
{
   if (nButtonCallbackID == 1)
   {
   //
   // Note: If compiled using MFC and a CDialog is envolked, you must make sure the
   // MFC module state is correctly managed before creating the dialog.  The comments
   // below show how to do this.
   //    AFX_MANAGE_STATE(AfxGetStaticModuleState());
   //       CMainIRConfigurationDlg dlg( this );
   //       dlg.DoModal();
   //       return( TRUE );


      //
      // The user pressed a button.  We will trace all of the server IR
      // codes to the error log.

      //
      // Check to see how large a buffer we need for the IRCode array
      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 ))
         {
            //
            // Codes were returned
            for (int nLoop = 0; pCodes[ nLoop ].m_szDescription; nLoop++)
            {
               TraceMessage( ttError, "IR Code %d ID = %d; Description [%s]", nLoop, pCodes[ nLoop ].m_nCodeID, pCodes[ nLoop ].m_szDescription );
            }

            //
            // Delete the server memory
            free( pCodes );
         }
         else
         {
            TraceMessage( ttError, "No IR Codes were found on the server" );
         }
      }
   }
   else if (nButtonCallbackID == 2)
   {
      //
      // Button 2 is the subscription notification test.
      //
       // Setup a DataPack with ANY kind of info we need to send along.
      // CDataPacks is simply a container that manages multiple key/value types.
      CDataPack   DataPack;
      DataPack.AddData( "HouseCode", "C" );
      DataPack.AddData( "UnitCode", "1" );
      DataPack.AddData( "Command", "Off" );
      DataPack.AddData( "RepeatCount", "1" );

      //
      // If the data can be categorized somehow, it's best to specify the category type
      // in the filter.  For example, this is used in X10 interfaces to specify which HouseCode and
      // UnitCode the data is for (H=%d;U=%d).  This allows Devices to register to receive only data
      // that is specific to their needs.
      //
      // This example will only be picked up by Devices that have registered for the
      // "Sample Notification List 1" list with a "Module=1" filter.
      NotifySubscribedDevices( "H=C", "U=1", &DataPack );

      //
      // This example will broadcast the data to all Devices that have subscribed to the
      // "Sample Notification List Broadcast" list.
      NotifySubscribedDevices( "X10 Broadcast", NULL, &DataPack );
   }
   else if (nButtonCallbackID == 3)
	{
		static int nDeviceNum = 0;
		char szDeviceName[ 256 ];
		wsprintf( szDeviceName, "Group Main| Group Sub | Dynamically Created Null Device %d", ++nDeviceNum );
//		wsprintf( szDeviceName, "xAP|Bathroom|BathroomLight" );
		//
		// Button 3 will create a new device on the server.
		if (FALSE == CreateDevice( "Null Device", szDeviceName, "This device was created from the Template Hardware Interface sample", hInstanceHandle ))
		{
			TraceMessage( ttError, "Unable to create the new devices.  It may already exist." );
		}
	}

   return( FALSE );
}
//
//
BOOL CTemplateHardwareInstance::Init(void)
{
    int nReturn = 0;
    HRESULT hr;
    hr = CoInitialize(NULL);
    //IActiveHome* pActiveHome;

    hr = CoCreateInstance( CLSID_ActiveHome, NULL, CLSCTX_INPROC|CLSCTX_LOCAL_SERVER, IID_IActiveHome, (LPVOID *) &pActiveHome );
   return (true);  
}

void CTemplateHardwareInstance::Terminate()
{

    pActiveHome->Release();
    pActiveHome = NULL;
    //CoUninitialize();
}
 
// ====================================================================
// Method Name : Query
// Description : This function allows a Device to query the interface for
//                information.  The query and response are pre-established
//                format and types.
// Parameters  : szQuery - Null terminated string that specifies the query.
//               pResponse - Void pointer to a pre-established data type that
//                will provide the response data from the query.
// Notes       : This function is not meant as an ad-hoc method for
//                interrogating the interface.  It is only used for Devices
//                to communicate with Interfaces that they know well.
// ====================================================================
BOOL CTemplateHardwareInstance::Query( LPCTSTR szQuery, void* pResponse )
{
   //
   // Check to see what the query is
   if (0 == strcmpi( szQuery, "How Long Have You Been Running" ))
   {
      //
      // The void data is actually a char* for this query.
      wsprintf( (char*)pResponse, "Running Time: %d Seconds", (GetTickCount() - m_dwStartCount) / 1000 );

      return( TRUE );
   }

   //
   // We do not support the query specified.
   return( FALSE );
}


HARDWARE_RC CTemplateHardwareInstance::InterfaceCall( InterfaceArgumentPack* pPack )
{
   TraceMessage( ttError, "Call made to HBInterface().  Calling function %s", pPack->m_szInterfaceSignature );
   ::MessageBeep( MB_ICONHAND );
   return( hrcSuccess );
}
/*
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//helper function for single byte char to unicode translatation
HRESULT AnsiToUnicode(LPCSTR pszA, LPOLESTR pszW) {

    ULONG lALen;
    ULONG lWLen; 
    DWORD dwError;
    lALen = strlen(pszA)+11;
    lWLen = strlen((char*)pszW) - 2;
    if (0 == MultiByteToWideChar(CP_ACP, 0, pszA, lALen,
                  pszW, lWLen))     {
        dwError = GetLastError();
        return HRESULT_FROM_WIN32(dwError);
    }
    return NOERROR;
}
*/
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// Template specific exports
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
HARDWARE_RC CTemplateHardwareInstance::SendX10( InterfaceArgumentPack* pPack )
{
    //
    // Make sure we are enabled.
    if (!m_bEnabled)
    {
      TraceMessage( ttWarning, "SendX10() interface is disabled." );
      return( hrcFailureAbort );
    }
    
    //
    // Verify the interface argument pack.
    //
    // Make sure we can handle the version of the struct.
    if (pPack->m_nArgumentPackVersion != 1)
    {
      TraceMessage( ttError, "Unsupported Argument Pack Version [%s].  Must be version [%d]", pPack->m_nArgumentPackVersion, 1 );
      return( hrcFailureAbort );
    }
    
    //
    // Make sure there are enough arguments.
    if (pPack->m_nNumberOfArguments != 4)
    {
      TraceMessage( ttError, "Invalid number of arguments supplied to SendX10() interface.  Expected 4.  Received %d", pPack->m_nNumberOfArguments );
      return( hrcFailureAbort );
    }
    
    HARDWARE_RC hresult = hrcSuccess;
    //
    // Get the Values
    const char* szHouseCode = TextFromInterfaceArgument( &(pPack->m_aArguments)[ 0 ] );
    const char* szUnitCode = TextFromInterfaceArgument( &(pPack->m_aArguments)[ 1 ] );
    const char* szCommand = TextFromInterfaceArgument( &(pPack->m_aArguments)[ 2 ] );
    const char* szRepeatCount = TextFromInterfaceArgument( &(pPack->m_aArguments)[ 3 ] );

    char* chTemp = new char[20];
    wchar_t* wchTemp = L"sendplc"; // command to send
    char* chParm = new char[20];
    wchar_t* wchParm = new wchar_t[50]; // HouseCodeUnitCode Cmd (A1 On)
    if (chParm && wchParm && chTemp && wchTemp) {
        //concatenate all parameters into one parameter string
    
        VARIANT varReseved1;
        VariantInit(&varReseved1);
        VARIANT varReseved2;
        VariantInit(&varReseved2);
    
        VARIANT varAction;
        VariantInit(&varAction);
        varAction.vt = VT_BSTR;
    
        VARIANT varParm;
        VariantInit(&varParm);
        varParm.vt = VT_BSTR;
    
        sprintf(chParm, " %s%s %s\n", szHouseCode, szUnitCode, szCommand);
        AnsiToUnicode(chParm, &wchParm);
        
        varAction.bstrVal = ::SysAllocString(wchTemp);
        varParm.bstrVal = ::SysAllocString(wchParm);
        
        
        // Grab Data to send to Trace
        UnicodeToAnsi(varAction.bstrVal, &chTemp);
        UnicodeToAnsi(varParm.bstrVal, &chParm);
        
        TraceMessage( ttDebug, "SendX10  varAction=%s, varParm=%s", chTemp, chParm); 
    
        VARIANT varReturn;
        
        HRESULT hr;
        hr = pActiveHome->SendAction(varAction, varParm, varReseved1, varReseved2, &varReturn);
        if (FAILED(hr)) {
            TraceMessage( ttError, "error: SendAction hr=0x%x\n", (unsigned int)hr);
        }
    
        SysFreeString(varAction.bstrVal);
        SysFreeString(varParm.bstrVal);
    
    }

    delete [] chTemp;
    delete [] chParm;

    return( hresult );
}

Thanks in advance.
Attachments
CM15A.0.20.zip
Beta version 0.20
(30.44 KiB) Downloaded 482 times
Last edited by Nightrader_ on Thu Jun 10, 2010 9:55 pm, edited 1 time in total.
Nightrader_
Member
Posts: 30
Joined: Sun May 23, 2010 6:45 pm

Re: CM15A Plugin

Post by Nightrader_ »

I am using Dev-C++ and MinGW,

I stole most of the code out of the MinGW sample in the ActiveHomePro SDK.
EDIT: (not counting the code I stole from the HB SDK :o )
It compiles and HB loads and all seems to work, but the Lights do not turn on :( , I get no errors and the Trace output looks good. If I force an invalid value the ActiveHome control returns the correct error.

The ActiveHome SDK's original code compiles in the IDE and works correctly, in fact I can use it while HB is running.

no matter what I seem to do (with my very limited C++ skills), HB is not able to talk to the CM15A with this code.

Thanks,
Gene
Any help would be very appreciated. :D
markd
Advanced Member
Posts: 234
Joined: Fri Jul 21, 2006 4:32 pm

Re: CM15A Plugin

Post by markd »

Well, I haven't tried to do a plugin for Housebot. . . but I typically use a debugger to step through my code when it is doing something (or nothing ;-) unexpectedly. Do you have a debugger?

Another method is it to "stub out" portions of the code. So rather than trying to actually DO anything in your plugin, just have it return a fixed value when called. Then you can figure out if that mechanism is working correctly. All about the divide and conquer.

I see some stuff that refers to IR codes- aer you sure you have the correct code?
Nightrader_
Member
Posts: 30
Joined: Sun May 23, 2010 6:45 pm

Re: CM15A Plugin

Post by Nightrader_ »

Thank you for the reply,
markd wrote:Well, I haven't tried to do a plugin for Housebot. . . but I typically use a debugger to step through my code when it is doing something (or nothing ;-) unexpectedly. Do you have a debugger?Another method is it to "stub out" portions of the code. So rather than trying to actually DO anything in your plugin, just have it return a fixed value when called. Then you can figure out if that mechanism is working correctly. All about the divide and conquer.
I have been coding off and on since early 1980, my problem is over the years I have settled on Delphi and have not really coded in anything else since the 90's. CPP is for the big boys, I'm just an old guy that loves to play with omputers and electronics. :?
markd wrote:I see some stuff that refers to IR codes- aer you sure you have the correct coe?
That is stuff from the Housebot SDK that I copied and I just have not deleted, it is not needed in anyway for the CM15A.
The CTemplateHardwareInstance::SendX10 is where the magic happens (or is supposed to happen).

I have Delphi code that has been running for some time that uses the same ActiceHome COM object, all of that has been working fine. My code is no where near as cool as HouseBot :)

The ActiveHome side is very simple, there is a SendAction function that you use to talk to the X10 devices and a RecvAction Eevent that allows the X10 devices to talk back.. I figured it would be easy to implement, in the code above all seems to work, I am guessing it might be a problem with the variants (see the line pActiveHome->SendAction) because I send the char values to the trace log and they are corrrect.

I would love it most if there was a delphi version of the HouseBot SDK, it would be nothing to bust out all I needed then, (I want to do a TCP interface as well as a custom 1-wire interface).

Once it is working, I intend on posting all the code here for all to play with. (which I will post all of what I have now if anyone is interested)

Any help is appreciated.

UPDATE:
I broke down and grabbed Visual Studio off our MSDN gold partner site and I have installed it on my devel box :( . I have complied both ActiveHome sdk samples and they work, am now working on doing up the HouseBot sdk sample.
Thanks,
Gene
markd
Advanced Member
Posts: 234
Joined: Fri Jul 21, 2006 4:32 pm

Re: CM15A Plugin

Post by markd »

I use the express versions, which are free and easy to use- a nice SDK makes life so much easier.

Once you slim down the code to just what is needed, if you still need C++ help let me know. . . I'm hip deep in a multi-platform recompile for my graphics shaders.

Markd
Nightrader_
Member
Posts: 30
Joined: Sun May 23, 2010 6:45 pm

Re: CM15A Plugin

Post by Nightrader_ »

markd wrote:I use the express versions, which are free and easy to use- a nice SDK makes life so much easier.

Once you slim down the code to just what is needed, if you still need C++ help let me know. . . I'm hip deep in a multi-platform recompile for my graphics shaders.

Markd
Thanks. EDIT: I forgot to add, I got the same results as with MinGW...

If you could wrap this into something that I could pass Strings to, I think I could figure the rest out (I would also like to loose the two "vReserved")

virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE SendAction(
/* [in] */ VARIANT bszAction,
/* [defaultvalue][in] */ VARIANT bstrParam,
/* [defaultvalue][in] */ VARIANT vReserved1,
/* [defaultvalue][in] */ VARIANT vReserved2,
/* [retval][out] */ VARIANT *vReturn) = 0;


Here is how I call it now all with VARIANT
HRESULT hr;
hr = pActiveHome->SendAction(varAction, varParm, varReseved1, varReseved2, &varReturn);


If I could do this then I would not have to deal with the VARIANT:
HRESULT SendAction( char* szAction, char* szParm, char** szReturn);
then I could do this:
HRESULT hr;
hr = pActiveHome->SendAction( szAction, szParm, &szrReturn);


I know how to work with PChars :D
Thanks for all your help.

Here is the entire "ahscript.h" file from the ActiveHome SDK

Code: Select all


/* this ALWAYS GENERATED file contains the definitions for the interfaces */


 /* File created by MIDL compiler version 6.00.0361 */
/* at Wed Nov 17 15:47:51 2004
 */
/* Compiler settings for .\ahscript.idl:
    Oicf, W1, Zp8, env=Win32 (32b run)
    protocol : dce , ms_ext, c_ext, robust
    error checks: allocation ref bounds_check enum stub_data 
    VC __declspec() decoration level: 
         __declspec(uuid()), __declspec(selectany), __declspec(novtable)
         DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING(  )

#pragma warning( disable: 4049 )  /* more than 64k source lines */


/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 475
#endif

#include "rpc.h"
#include "rpcndr.h"

#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif // __RPCNDR_H_VERSION__

#ifndef COM_NO_WINDOWS_H
#include "windows.h"
#include "ole2.h"
#endif /*COM_NO_WINDOWS_H*/

#ifndef __ahscript_h__
#define __ahscript_h__

#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

/* Forward Declarations */ 

#ifndef __IActiveHome_FWD_DEFINED__
#define __IActiveHome_FWD_DEFINED__
typedef interface IActiveHome IActiveHome;
#endif 	/* __IActiveHome_FWD_DEFINED__ */


#ifndef ___IActiveHomeEvents_FWD_DEFINED__
#define ___IActiveHomeEvents_FWD_DEFINED__
typedef interface _IActiveHomeEvents _IActiveHomeEvents;
#endif 	/* ___IActiveHomeEvents_FWD_DEFINED__ */


#ifndef ___DIActiveHomeEvents_FWD_DEFINED__
#define ___DIActiveHomeEvents_FWD_DEFINED__
typedef interface _DIActiveHomeEvents _DIActiveHomeEvents;
#endif 	/* ___DIActiveHomeEvents_FWD_DEFINED__ */


#ifndef __ActiveHome_FWD_DEFINED__
#define __ActiveHome_FWD_DEFINED__

#ifdef __cplusplus
typedef class ActiveHome ActiveHome;
#else
typedef struct ActiveHome ActiveHome;
#endif /* __cplusplus */

#endif 	/* __ActiveHome_FWD_DEFINED__ */


/* header files for imported files */
#include "oaidl.h"
#include "ocidl.h"

#ifdef __cplusplus
extern "C"{
#endif 

void * __RPC_USER MIDL_user_allocate(size_t);
void __RPC_USER MIDL_user_free( void * ); 

#ifndef __IActiveHome_INTERFACE_DEFINED__
#define __IActiveHome_INTERFACE_DEFINED__

/* interface IActiveHome */
/* [unique][helpstring][nonextensible][dual][uuid][object] */ 


EXTERN_C const IID IID_IActiveHome;

#if defined(__cplusplus) && !defined(CINTERFACE)
    
    MIDL_INTERFACE("001000AF-3DEF-0910-10B6-DC5BA692C858")
    IActiveHome : public IDispatch
    {
    public:
        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE SendAction( 
            /* [in] */ VARIANT bszAction,
            /* [defaultvalue][in] */ VARIANT bstrParam,
            /* [defaultvalue][in] */ VARIANT vReserved1,
            /* [defaultvalue][in] */ VARIANT vReserved2,
            /* [retval][out] */ VARIANT *vReturn) = 0;
        
        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_OnRecvAction( 
            /* [in] */ IDispatch *pRecvAction) = 0;
        
    };
    
#else 	/* C style interface */

    typedef struct IActiveHomeVtbl
    {
        BEGIN_INTERFACE
        
        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
            IActiveHome * This,
            /* [in] */ REFIID riid,
            /* [iid_is][out] */ void **ppvObject);
        
        ULONG ( STDMETHODCALLTYPE *AddRef )( 
            IActiveHome * This);
        
        ULONG ( STDMETHODCALLTYPE *Release )( 
            IActiveHome * This);
        
        HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( 
            IActiveHome * This,
            /* [out] */ UINT *pctinfo);
        
        HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( 
            IActiveHome * This,
            /* [in] */ UINT iTInfo,
            /* [in] */ LCID lcid,
            /* [out] */ ITypeInfo **ppTInfo);
        
        HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( 
            IActiveHome * This,
            /* [in] */ REFIID riid,
            /* [size_is][in] */ LPOLESTR *rgszNames,
            /* [in] */ UINT cNames,
            /* [in] */ LCID lcid,
            /* [size_is][out] */ DISPID *rgDispId);
        
        /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( 
            IActiveHome * This,
            /* [in] */ DISPID dispIdMember,
            /* [in] */ REFIID riid,
            /* [in] */ LCID lcid,
            /* [in] */ WORD wFlags,
            /* [out][in] */ DISPPARAMS *pDispParams,
            /* [out] */ VARIANT *pVarResult,
            /* [out] */ EXCEPINFO *pExcepInfo,
            /* [out] */ UINT *puArgErr);
        
        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *SendAction )( 
            IActiveHome * This,
            /* [in] */ VARIANT bszAction,
            /* [defaultvalue][in] */ VARIANT bstrParam,
            /* [defaultvalue][in] */ VARIANT vReserved1,
            /* [defaultvalue][in] */ VARIANT vReserved2,
            /* [retval][out] */ VARIANT *vReturn);
        
        /* [helpstring][propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_OnRecvAction )( 
            IActiveHome * This,
            /* [in] */ IDispatch *pRecvAction);
        
        END_INTERFACE
    } IActiveHomeVtbl;

    interface IActiveHome
    {
        CONST_VTBL struct IActiveHomeVtbl *lpVtbl;
    };

    

#ifdef COBJMACROS


#define IActiveHome_QueryInterface(This,riid,ppvObject)	\
    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)

#define IActiveHome_AddRef(This)	\
    (This)->lpVtbl -> AddRef(This)

#define IActiveHome_Release(This)	\
    (This)->lpVtbl -> Release(This)


#define IActiveHome_GetTypeInfoCount(This,pctinfo)	\
    (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)

#define IActiveHome_GetTypeInfo(This,iTInfo,lcid,ppTInfo)	\
    (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)

#define IActiveHome_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)	\
    (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)

#define IActiveHome_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)	\
    (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)


#define IActiveHome_SendAction(This,bszAction,bstrParam,vReserved1,vReserved2,vReturn)	\
    (This)->lpVtbl -> SendAction(This,bszAction,bstrParam,vReserved1,vReserved2,vReturn)

#define IActiveHome_put_OnRecvAction(This,pRecvAction)	\
    (This)->lpVtbl -> put_OnRecvAction(This,pRecvAction)

#endif /* COBJMACROS */


#endif 	/* C style interface */



/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IActiveHome_SendAction_Proxy( 
    IActiveHome * This,
    /* [in] */ VARIANT bszAction,
    /* [defaultvalue][in] */ VARIANT bstrParam,
    /* [defaultvalue][in] */ VARIANT vReserved1,
    /* [defaultvalue][in] */ VARIANT vReserved2,
    /* [retval][out] */ VARIANT *vReturn);


void __RPC_STUB IActiveHome_SendAction_Stub(
    IRpcStubBuffer *This,
    IRpcChannelBuffer *_pRpcChannelBuffer,
    PRPC_MESSAGE _pRpcMessage,
    DWORD *_pdwStubPhase);


/* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IActiveHome_put_OnRecvAction_Proxy( 
    IActiveHome * This,
    /* [in] */ IDispatch *pRecvAction);


void __RPC_STUB IActiveHome_put_OnRecvAction_Stub(
    IRpcStubBuffer *This,
    IRpcChannelBuffer *_pRpcChannelBuffer,
    PRPC_MESSAGE _pRpcMessage,
    DWORD *_pdwStubPhase);



#endif 	/* __IActiveHome_INTERFACE_DEFINED__ */



#ifndef __ActiveHomeScriptLib_LIBRARY_DEFINED__
#define __ActiveHomeScriptLib_LIBRARY_DEFINED__

/* library ActiveHomeScriptLib */
/* [helpstring][version][uuid] */ 


EXTERN_C const IID LIBID_ActiveHomeScriptLib;

#ifndef ___IActiveHomeEvents_INTERFACE_DEFINED__
#define ___IActiveHomeEvents_INTERFACE_DEFINED__

/* interface _IActiveHomeEvents */
/* [object][helpstring][uuid] */ 


EXTERN_C const IID IID__IActiveHomeEvents;

#if defined(__cplusplus) && !defined(CINTERFACE)
    
    MIDL_INTERFACE("001000AF-3DEF-0912-10B6-DC5BA692C858")
    _IActiveHomeEvents : public IUnknown
    {
    public:
        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE RecvAction( 
            /* [in] */ VARIANT bszAction,
            /* [in] */ VARIANT bszParm1,
            /* [in] */ VARIANT bszParm2,
            /* [in] */ VARIANT bszParm3,
            /* [in] */ VARIANT bszParm4,
            /* [in] */ VARIANT bszParm5,
            /* [in] */ VARIANT bszReserved) = 0;
        
    };
    
#else 	/* C style interface */

    typedef struct _IActiveHomeEventsVtbl
    {
        BEGIN_INTERFACE
        
        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
            _IActiveHomeEvents * This,
            /* [in] */ REFIID riid,
            /* [iid_is][out] */ void **ppvObject);
        
        ULONG ( STDMETHODCALLTYPE *AddRef )( 
            _IActiveHomeEvents * This);
        
        ULONG ( STDMETHODCALLTYPE *Release )( 
            _IActiveHomeEvents * This);
        
        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *RecvAction )( 
            _IActiveHomeEvents * This,
            /* [in] */ VARIANT bszAction,
            /* [in] */ VARIANT bszParm1,
            /* [in] */ VARIANT bszParm2,
            /* [in] */ VARIANT bszParm3,
            /* [in] */ VARIANT bszParm4,
            /* [in] */ VARIANT bszParm5,
            /* [in] */ VARIANT bszReserved);
        
        END_INTERFACE
    } _IActiveHomeEventsVtbl;

    interface _IActiveHomeEvents
    {
        CONST_VTBL struct _IActiveHomeEventsVtbl *lpVtbl;
    };

    

#ifdef COBJMACROS


#define _IActiveHomeEvents_QueryInterface(This,riid,ppvObject)	\
    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)

#define _IActiveHomeEvents_AddRef(This)	\
    (This)->lpVtbl -> AddRef(This)

#define _IActiveHomeEvents_Release(This)	\
    (This)->lpVtbl -> Release(This)


#define _IActiveHomeEvents_RecvAction(This,bszAction,bszParm1,bszParm2,bszParm3,bszParm4,bszParm5,bszReserved)	\
    (This)->lpVtbl -> RecvAction(This,bszAction,bszParm1,bszParm2,bszParm3,bszParm4,bszParm5,bszReserved)

#endif /* COBJMACROS */


#endif 	/* C style interface */



/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE _IActiveHomeEvents_RecvAction_Proxy( 
    _IActiveHomeEvents * This,
    /* [in] */ VARIANT bszAction,
    /* [in] */ VARIANT bszParm1,
    /* [in] */ VARIANT bszParm2,
    /* [in] */ VARIANT bszParm3,
    /* [in] */ VARIANT bszParm4,
    /* [in] */ VARIANT bszParm5,
    /* [in] */ VARIANT bszReserved);


void __RPC_STUB _IActiveHomeEvents_RecvAction_Stub(
    IRpcStubBuffer *This,
    IRpcChannelBuffer *_pRpcChannelBuffer,
    PRPC_MESSAGE _pRpcMessage,
    DWORD *_pdwStubPhase);



#endif 	/* ___IActiveHomeEvents_INTERFACE_DEFINED__ */


#ifndef ___DIActiveHomeEvents_DISPINTERFACE_DEFINED__
#define ___DIActiveHomeEvents_DISPINTERFACE_DEFINED__

/* dispinterface _DIActiveHomeEvents */
/* [helpstring][uuid] */ 


EXTERN_C const IID DIID__DIActiveHomeEvents;

#if defined(__cplusplus) && !defined(CINTERFACE)

    MIDL_INTERFACE("001000AF-3DEF-0911-10B6-DC5BA692C858")
    _DIActiveHomeEvents : public IDispatch
    {
    };
    
#else 	/* C style interface */

    typedef struct _DIActiveHomeEventsVtbl
    {
        BEGIN_INTERFACE
        
        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
            _DIActiveHomeEvents * This,
            /* [in] */ REFIID riid,
            /* [iid_is][out] */ void **ppvObject);
        
        ULONG ( STDMETHODCALLTYPE *AddRef )( 
            _DIActiveHomeEvents * This);
        
        ULONG ( STDMETHODCALLTYPE *Release )( 
            _DIActiveHomeEvents * This);
        
        HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( 
            _DIActiveHomeEvents * This,
            /* [out] */ UINT *pctinfo);
        
        HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( 
            _DIActiveHomeEvents * This,
            /* [in] */ UINT iTInfo,
            /* [in] */ LCID lcid,
            /* [out] */ ITypeInfo **ppTInfo);
        
        HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( 
            _DIActiveHomeEvents * This,
            /* [in] */ REFIID riid,
            /* [size_is][in] */ LPOLESTR *rgszNames,
            /* [in] */ UINT cNames,
            /* [in] */ LCID lcid,
            /* [size_is][out] */ DISPID *rgDispId);
        
        /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( 
            _DIActiveHomeEvents * This,
            /* [in] */ DISPID dispIdMember,
            /* [in] */ REFIID riid,
            /* [in] */ LCID lcid,
            /* [in] */ WORD wFlags,
            /* [out][in] */ DISPPARAMS *pDispParams,
            /* [out] */ VARIANT *pVarResult,
            /* [out] */ EXCEPINFO *pExcepInfo,
            /* [out] */ UINT *puArgErr);
        
        END_INTERFACE
    } _DIActiveHomeEventsVtbl;

    interface _DIActiveHomeEvents
    {
        CONST_VTBL struct _DIActiveHomeEventsVtbl *lpVtbl;
    };

    

#ifdef COBJMACROS


#define _DIActiveHomeEvents_QueryInterface(This,riid,ppvObject)	\
    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)

#define _DIActiveHomeEvents_AddRef(This)	\
    (This)->lpVtbl -> AddRef(This)

#define _DIActiveHomeEvents_Release(This)	\
    (This)->lpVtbl -> Release(This)


#define _DIActiveHomeEvents_GetTypeInfoCount(This,pctinfo)	\
    (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)

#define _DIActiveHomeEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo)	\
    (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)

#define _DIActiveHomeEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)	\
    (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)

#define _DIActiveHomeEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)	\
    (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)

#endif /* COBJMACROS */


#endif 	/* C style interface */


#endif 	/* ___DIActiveHomeEvents_DISPINTERFACE_DEFINED__ */


EXTERN_C const CLSID CLSID_ActiveHome;

#ifdef __cplusplus

class DECLSPEC_UUID("001000AF-2DEF-0208-10B6-DC5BA692C858")
ActiveHome;
#endif
#endif /* __ActiveHomeScriptLib_LIBRARY_DEFINED__ */

/* Additional Prototypes for ALL interfaces */

unsigned long             __RPC_USER  VARIANT_UserSize(     unsigned long *, unsigned long            , VARIANT * ); 
unsigned char * __RPC_USER  VARIANT_UserMarshal(  unsigned long *, unsigned char *, VARIANT * ); 
unsigned char * __RPC_USER  VARIANT_UserUnmarshal(unsigned long *, unsigned char *, VARIANT * ); 
void                      __RPC_USER  VARIANT_UserFree(     unsigned long *, VARIANT * ); 

/* end of Additional Prototypes */

#ifdef __cplusplus
}
#endif

#endif


Nightrader_
Member
Posts: 30
Joined: Sun May 23, 2010 6:45 pm

Re: CM15A Plugin

Post by Nightrader_ »

Just and update..

I worked on this off and on all weekend, with no luck. The code I have will work as a console app, but when copied over to the DLL and recompiled same results, does not matter if I am using MinGW or Visual Studio so it has to be something with the code... I wish I was better with C++. My thinking is it must be something with the VARIANTS...

Anyway, as soon as I get time after work, I will zip up all the code I have and post it here, maybe someone can figure it out. In the mean time I have created Null Devices and wrapped them with Tasks to control my X10 Devices (send only, no receive).

Thanks,
Gene

UPDATE: sorry, got busy and did not get a chance to upload that code, I will try and get it today.
Nightrader_
Member
Posts: 30
Joined: Sun May 23, 2010 6:45 pm

Re: CM15A Plugin

Post by Nightrader_ »

Here is the code, please excuse the poor code as this is my raw code, no comments, just code, this is currently not working, you should be able to locate the SendX10 member function where the trouble is.

If anyone is able to fix this, please PM me, I am curious to know what I am doing wrong in the code.

Thanks to anyone willing to take a stab at fixing this...

Gene
Attachments
CM15A HB Plugin Source 05.02.2010.zip
(102.03 KiB) Downloaded 509 times
Nightrader_
Member
Posts: 30
Joined: Sun May 23, 2010 6:45 pm

Re: CM15A Plugin

Post by Nightrader_ »

Update:

I have pushed aside the C++ code and have started porting the sdk files to Pascal (Delphi), I have a working skeleton for the hardware interface, by the end of the weekend I should have it completed enough to post here.

Gene
Nightrader_
Member
Posts: 30
Joined: Sun May 23, 2010 6:45 pm

Re: CM15A Plugin: Updated

Post by Nightrader_ »

Posted first beta, download from link in first post.

This is from the C++ Code, while working on the Delphi conversion I had a idea to test and it worked.. In the original code I was creating the ActiveHome object in the Init function and Destroy it int the Terminate, sounded normal, I got to thinking, that was what was different from the Console version, so I decided to create an instance of the ActiveHome object inside the SendX10 function and Bang it worked.
So in the current beta I am still Creating and Destroying the original one and it lives as long as the instance of TemplateInstance, but I am using the one i create in the SendX10 event, as soon as I figure out the issue with the original object, I will get the events works and the device notifications.

Please post here any issues that are not mentioned in the readme.txt

Thanks,
Gene
Nightrader_
Member
Posts: 30
Joined: Sun May 23, 2010 6:45 pm

Re: CM15A Plugin: Updated

Post by Nightrader_ »

Here is a quick update:

I have gotten the Receive working in the Delphi version, but can not seem to get the send working, I still have the send working in the C++ version, currently I have the C++ version setup as my main X10 interface and I have the Delphi version set to my rf Switches and my rf Motion detectors, this actually works out nice as I do not want Housebot to echo the state changes for these items on the PLC side, and the notifications sent by the Delphi version get to ALL my X10 devices, so all is almost good.

If anyone is interested in testing these version, please PM me and I will gladly send them, I would post them here, but I still like to get one or the other working correctly first.

Thanks,
Gene
Post Reply