using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace TelldusWrapper { public sealed class TelldusNETWrapper //don't allow inheritance { int lastEventID = 0; Dictionary callbackFunctionReferenceList = new Dictionary(); //this prevents errors in "unknown module" due to callback functions being garbage collected since there are no reference to them //TODO List lista = new List(); //Device methods public const int TELLSTICK_TURNON = 1; public const int TELLSTICK_TURNOFF = 2; public const int TELLSTICK_BELL = 4; public const int TELLSTICK_TOGGLE = 8; public const int TELLSTICK_DIM = 16; public const int TELLSTICK_LEARN = 32; public const int TELLSTICK_EXECUTE = 64; public const int TELLSTICK_UP = 128; public const int TELLSTICK_DOWN = 256; public const int TELLSTICK_STOP = 512; //Error codes public const int TELLSTICK_SUCCESS = 0; public const int TELLSTICK_ERROR_NOT_FOUND = -1; public const int TELLSTICK_ERROR_PERMISSION_DENIED = -2; public const int TELLSTICK_ERROR_DEVICE_NOT_FOUND = -3; public const int TELLSTICK_ERROR_METHOD_NOT_SUPPORTED = -4; public const int TELLSTICK_ERROR_COMMUNICATION = -5; public const int TELLSTICK_ERROR_CONNECTING_SERVICE = -6; public const int TELLSTICK_ERROR_UNKNOWN_RESPONSE = -7; public const int TELLSTICK_ERROR_UNKNOWN = -99; //Device typedef public const int TELLSTICK_TYPE_DEVICE = 1; public const int TELLSTICK_TYPE_GROUP = 2; public const int TELLSTICK_TYPE_SCENE = 3; //Device changes public const int TELLSTICK_DEVICE_ADDED = 1; public const int TELLSTICK_DEVICE_CHANGED = 2; public const int TELLSTICK_DEVICE_REMOVED = 3; public const int TELLSTICK_DEVICE_STATE_CHANGED = 4; //Change types public const int TELLSTICK_CHANGE_NAME = 1; public const int TELLSTICK_CHANGE_PROTOCOL = 2; public const int TELLSTICK_CHANGE_MODEL = 3; //variables for event callback (e.g. turnon, turnoff) public delegate int EventCallbackFunction(int deviceId, int method, string data, int callbackId, Object obj); private struct DeviceEventFunctionContext { public EventCallbackFunction eventCallbackFunc; public Object context; public int callbackId; } Dictionary deviceEventList = new Dictionary(); int registeredEventFunctionId = -1; //variables for device event callback (e.g. change of name/protocol) public delegate int DeviceChangeEventCallbackFunction(int deviceId, int changeEvent, int changeType, int callbackId, Object obj); private struct DeviceChangeEventFunctionContext { public DeviceChangeEventCallbackFunction changeEventCallbackFunc; public Object context; public int callbackId; } Dictionary deviceChangeEventList = new Dictionary(); int registeredDeviceChangeEventFunctionId = -1; //variables for raw controller listening callback (e.g. Tellstick Duo receives data) public delegate int RawListeningCallbackFunction(string data, int controllerId, int callbackId, Object obj); private struct RawEventFunctionContext { public RawListeningCallbackFunction rawCallbackFunc; public Object context; public int callbackId; } Dictionary rawListenerList = new Dictionary(); int registeredRawListenerFunctionId = -1; public TelldusNETWrapper() { } ~TelldusNETWrapper() { //clean up if (registeredEventFunctionId != -1) { UnmanagedImport.tdUnregisterCallback(registeredEventFunctionId); } if (registeredDeviceChangeEventFunctionId != -1) { UnmanagedImport.tdUnregisterCallback(registeredDeviceChangeEventFunctionId); } if (registeredRawListenerFunctionId != -1) { UnmanagedImport.tdUnregisterCallback(registeredRawListenerFunctionId); } UnmanagedImport.tdClose(); //Close the library and clean up the cache it uses. } /// /// Imported functions from TelldusCore.dll /// private sealed class UnmanagedImport { private UnmanagedImport() { } //cannot instantiate this class #region Unmanaged Code [DllImport("TelldusCore.dll")] public static extern int tdGetNumberOfDevices(); [DllImport("TelldusCore.dll")] public static extern int tdGetDeviceId(int value); [DllImport("TelldusCore.dll")] public static unsafe extern char* tdGetName(int deviceId); [DllImport("TelldusCore.dll")] public static unsafe extern char* tdGetProtocol(int deviceId); [DllImport("TelldusCore.dll")] public static unsafe extern char* tdGetModel(int deviceId); [DllImport("TelldusCore.dll")] public static unsafe extern char* tdGetDeviceParameter(int deviceId, char* name, char* defaultValue); [DllImport("TelldusCore.dll")] public static unsafe extern bool tdSetName(int deviceId, char* name); [DllImport("TelldusCore.dll")] public static unsafe extern bool tdSetProtocol(int deviceId, char* protocol); [DllImport("TelldusCore.dll")] public static unsafe extern bool tdSetModel(int deviceId, char* model); [DllImport("TelldusCore.dll")] public static unsafe extern bool tdSetDeviceParameter(int deviceId, char* name, char* value); [DllImport("TelldusCore.dll")] public static unsafe extern int tdAddDevice(); [DllImport("TelldusCore.dll")] public static unsafe extern bool tdRemoveDevice(int deviceId); [DllImport("TelldusCore.dll")] public static unsafe extern int tdMethods(int deviceId, int methodsSupported); [DllImport("TelldusCore.dll")] public static extern int tdTurnOn(int deviceId); [DllImport("TelldusCore.dll")] public static extern int tdTurnOff(int deviceId); [DllImport("TelldusCore.dll")] public static extern int tdBell(int deviceId); [DllImport("TelldusCore.dll")] public static extern int tdDim(int deviceId, char level); [DllImport("TelldusCore.dll")] public static extern int tdExecute(int deviceId); [DllImport("TelldusCore.dll")] public static extern int tdUp(int deviceId); [DllImport("TelldusCore.dll")] public static extern int tdDown(int deviceId); [DllImport("TelldusCore.dll")] public static extern int tdStop(int deviceId); [DllImport("TelldusCore.dll")] public static unsafe extern char* tdGetErrorString(int errorNo); [DllImport("TelldusCore.dll")] public static extern void tdClose(); [DllImport("TelldusCore.dll")] public static extern void tdInit(); [DllImport("TelldusCore.dll")] public static unsafe extern int tdRegisterDeviceEvent(Delegate deviceEventFunction, void* context); [DllImport("TelldusCore.dll")] public static extern int tdLastSentCommand(int deviceId, int methods); [DllImport("TelldusCore.dll")] public static extern int tdGetDeviceType(int deviceId); [DllImport("TelldusCore.dll")] public static unsafe extern int tdSendRawCommand(char* command, int reserved); [DllImport("TelldusCore.dll")] public static unsafe extern int tdRegisterRawDeviceEvent(Delegate rawListeningFunction, void* context); [DllImport("TelldusCore.dll")] public static extern int tdLearn(int deviceId); [DllImport("TelldusCore.dll")] public static unsafe extern char* tdLastSentValue(int deviceId); [DllImport("TelldusCore.dll")] public static unsafe extern void tdReleaseString(char* value); [DllImport("TelldusCore.dll")] public static unsafe extern int tdUnregisterCallback(int eventId); [DllImport("TelldusCore.dll")] public static unsafe extern int tdRegisterDeviceChangeEvent(Delegate deviceChangeEventFunction, void* context); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public unsafe delegate void EventFunctionDelegate(int deviceId, int method, char* data, int callbackId, void* context); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public unsafe delegate void DeviceChangeEventFunctionDelegate(int deviceId, int changeEvent, int changeType, int callbackId, void* context); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public unsafe delegate void RawListeningDelegate(char* data, int controllerId, int callbackId, void* context); #endregion } #region Public Methods /// /// Add a new device to the global database of devices. This function must be called first before /// any call to tdSetName(), tdSetProtocol() and similar functions. /// /// The device id for the newly created device. If the creation fails it returnes a /// negative value. public static int tdAddDevice() { return UnmanagedImport.tdAddDevice(); } /// /// Sends bell command to devices supporting this. /// Make sure the device supports this by calling tdMethods() before any calls to this function. /// /// Id of device to sound the bell on /// Success or error code public static int tdBell(int deviceId) { return UnmanagedImport.tdBell(deviceId); } /// /// Close the library and clean up the cache it uses. /// This should be called when the library is not supposed to be used anymore. /// Do not use when this has been instantiated, will be closed in destructor then, only on static methods. /// public static void tdClose() { UnmanagedImport.tdClose(); } /// /// Dims a device. /// Make sure the device supports this by calling tdMethods() before any calls to this function. /// /// The device id to dim /// The level the device should dim to. This value should be 0-255 /// Success or error code public static int tdDim(int deviceId, char level) { return UnmanagedImport.tdDim(deviceId, level); } /// /// Send "down" command to device. /// Make sure the device supports this by calling tdMethods() before any calls to this function. /// /// The device id to send the command to /// Success or error code public static int tdDown(int deviceId) { return UnmanagedImport.tdDown(deviceId); } /// /// Execute a scene action. /// Make sure the device supports this by calling tdMethods() before any calls to this function. /// /// Id of device to perform the execute action on /// Success or error code public static int tdExecute(int deviceId) { return UnmanagedImport.tdExecute(deviceId); } /// /// This function returns the unique id of a device with a specific index. /// To get all the id numbers you should loop over all the devices, use tdGetNumberOfDevices() to get the number of devices /// /// Device index /// Id of device at that position public static int tdGetDeviceId(int order) { return UnmanagedImport.tdGetDeviceId(order); } /// /// Get a protocol specific device parameter /// /// The id of the device to query /// The name of the parameter to query /// A defaultValue to return if the current parameter hasn't previously been set /// Any protocol specific parameter specified by "name" public static unsafe string tdGetDeviceParameter(int deviceId, string name, string defaultValue) { return getString(UnmanagedImport.tdGetDeviceParameter(deviceId, stringToChar(name), stringToChar(defaultValue))); } /// /// Returns which type the device is /// /// Id of the device /// TELLSTICK_TYPE_DEVICE or TELLSTICK_TYPE_GROUP public static int tdGetDeviceType(int deviceId) { return UnmanagedImport.tdGetDeviceType(deviceId); } /// /// Get a human readable string from an error code returned from a function in telldus-core /// /// The error code to translate /// A string ready to show to the user. /// TELLSTICK_SUCCESS /// TELLSTICK_ERROR_NOT_FOUND /// TELLSTICK_ERROR_PERMISSION_DENIED /// TELLSTICK_ERROR_DEVICE_NOT_FOUND /// TELLSTICK_ERROR_METHOD_NOT_SUPPORTED /// TELLSTICK_ERROR_COMMUNICATION /// TELLSTICK_ERROR_CONNECTING_SERVICE /// TELLSTICK_ERROR_UNKNOWN_RESPONSE /// TELLSTICK_ERROR_UNKNOWN /// public static unsafe string tdGetErrorString(int errorNo) { return getString(UnmanagedImport.tdGetErrorString(errorNo)); } /// /// Query a device for it’s name /// /// Id of device to query /// The name of the device or an empty string if the device is not found public static unsafe string tdGetName(int deviceId) { return getString(UnmanagedImport.tdGetName(deviceId)); } /// /// Query a device for which methods it supports. By supplying the methods you support /// the library could remap the methods a device support for better fit the application. /// /// Id of device to query /// Methods that the client application supports /// Supported (both by client application and by device) method-flags OR'ed into an integer /// TELLSTICK_TURNON /// TELLSTICK_TURNOFF /// TELLSTICK_BELL /// TELLSTICK_TOGGLE /// TELLSTICK_DIM /// TELLSTICK_EXECUTE /// TELLSTICK_UP /// TELLSTICK_DOWN /// TELLSTICK_EXECUTE /// TELLSTICK_LEARN /// public static int tdMethods(int deviceId, int methodsSupported) { return UnmanagedImport.tdMethods(deviceId, methodsSupported); } /// /// Query a device for it’s model /// /// Id of device to query /// The model for a device. Not all protocols use this. public static unsafe string tdGetModel(int deviceId) { return getString(UnmanagedImport.tdGetModel(deviceId)); } /// /// This function returns the number of devices configured /// /// The total number of devices configured public static int tdGetNumberOfDevices() { return UnmanagedImport.tdGetNumberOfDevices(); } /// /// Query a device for it’s protocol /// /// Id of device to query /// The protocol for a device. public static unsafe string tdGetProtocol(int deviceId) { return getString(UnmanagedImport.tdGetProtocol(deviceId)); } /// /// Returns the last sent command to a specific device /// /// Id of device to query /// The methods supported by the client. See tdMethods() for more information. /// The last sent command as integer, for example TELLSTICK_TURNON or TELLSTICK_TURNOFF public static int tdLastSentCommand(int deviceId, int methods) { return UnmanagedImport.tdLastSentCommand(deviceId, methods); } /// /// If the last sent command it TELLSTICK_DIM this returns the dimmed value /// /// Id of device to query /// The the value as a human readable string, for example "128" for 50% public static unsafe string tdLastSentValue(int deviceId) { return getString(UnmanagedImport.tdLastSentValue(deviceId)); } /// /// Sends a special learn command to some devices that need a special learn-command to be used from TellStick /// Make sure the device supports this by calling tdMethods() before any calls to this function. /// /// Id of device to learn /// Success or error code public static int tdLearn(int deviceId) { return UnmanagedImport.tdLearn(deviceId); } /// /// Register a callback event function to be called when a device event (e.g. turn on, turn off) occurs /// /// Callback function to be called /// Context object that will be echoed back when function is called. Only the object when the first function is registered will be used. Set to null if not used. /// Callback event id public unsafe int tdRegisterDeviceEvent(EventCallbackFunction deviceEventFunc, Object obj) { int returnValue = 0; if (deviceEventList.Count == 0) { //first added, register with dll too UnmanagedImport.EventFunctionDelegate deviceEventFunctionDelegate = new UnmanagedImport.EventFunctionDelegate(deviceEventFunction); registeredEventFunctionId = UnmanagedImport.tdRegisterDeviceEvent(deviceEventFunctionDelegate, (void*)null); //context here or above? GC.Collect(); callbackFunctionReferenceList.Add(registeredEventFunctionId, deviceEventFunctionDelegate); } ++lastEventID; returnValue = lastEventID; DeviceEventFunctionContext deviceEventFuncContext = new DeviceEventFunctionContext(); deviceEventFuncContext.eventCallbackFunc = deviceEventFunc; deviceEventFuncContext.context = obj; deviceEventFuncContext.callbackId = returnValue; deviceEventList.Add(returnValue, deviceEventFuncContext); return returnValue; } /// /// Register a callback device change event function to be called when a device change event (e.g. change of name, device added) occurs /// /// Callback function to be called /// Context object that will be echoed back when function is called. Only the object when the first function is registered will be used. Set to null if not used. /// Callback event id public unsafe int tdRegisterDeviceChangeEvent(DeviceChangeEventCallbackFunction deviceChangeEventFunc, Object obj) { int returnValue = 0; if (deviceChangeEventList.Count == 0) { //first added, register with dll too //only the context object of the first event will be registered UnmanagedImport.DeviceChangeEventFunctionDelegate deviceChangeEventFunctionDelegate = new UnmanagedImport.DeviceChangeEventFunctionDelegate(deviceChangeEventFunction); registeredDeviceChangeEventFunctionId = UnmanagedImport.tdRegisterDeviceChangeEvent(deviceChangeEventFunctionDelegate, (void*)null); GC.Collect(); callbackFunctionReferenceList.Add(registeredDeviceChangeEventFunctionId, deviceChangeEventFunctionDelegate); } ++lastEventID; returnValue = lastEventID; DeviceChangeEventFunctionContext deviceChangeEventFuncContext = new DeviceChangeEventFunctionContext(); deviceChangeEventFuncContext.changeEventCallbackFunc = deviceChangeEventFunc; deviceChangeEventFuncContext.context = obj; deviceChangeEventFuncContext.callbackId = returnValue; deviceChangeEventList.Add(returnValue, deviceChangeEventFuncContext); return returnValue; } /// /// Register a callback listening function to be called when a listening event (e.g. data is received with Tellstick Duo) occurs /// /// Callback function to be called /// Context object that will be echoed back when function is called. Only the object when the first function is registered will be used. Set to null if not used. /// Callback event id public unsafe int tdRegisterRawDeviceEvent(RawListeningCallbackFunction listeningFunc, Object obj) { int returnValue = 0; if (rawListenerList.Count == 0) { //first added, register with dll too //only the context object of the first event will be registered UnmanagedImport.RawListeningDelegate listeningFunctionDelegate = new UnmanagedImport.RawListeningDelegate(rawListeningFunction); registeredRawListenerFunctionId = UnmanagedImport.tdRegisterRawDeviceEvent(listeningFunctionDelegate, (void*)null); GC.Collect(); callbackFunctionReferenceList.Add(registeredRawListenerFunctionId, listeningFunctionDelegate); } ++lastEventID; returnValue = lastEventID; RawEventFunctionContext rawEventFuncContext = new RawEventFunctionContext(); rawEventFuncContext.rawCallbackFunc = listeningFunc; rawEventFuncContext.context = obj; rawEventFuncContext.callbackId = returnValue; rawListenerList.Add(returnValue, rawEventFuncContext); return returnValue; } /// /// Removes a device. /// /// Id of device to remove /// True on success, false otherwise public static bool tdRemoveDevice(int deviceId) { return UnmanagedImport.tdRemoveDevice(deviceId); } /// /// Send a raw command to TellStick. Please read the TellStick protocol definition on how the command should be constructed. /// /// The command for TellStick in its native format /// /// Success or error code public static unsafe int tdSendRawCommand(string command, int reserved) { char* commandChar = stringToChar(command); int returnValue = UnmanagedImport.tdSendRawCommand(commandChar, reserved); Marshal.FreeHGlobal((IntPtr)commandChar); return returnValue; } /// /// Sets a new protocol specific parameter. Please see the documentation of the protocols before setting any parameter. /// /// Id of device to change /// The name of the parameter to change /// The new value for the parameter /// Success or error code public static unsafe bool tdSetDeviceParameter(int deviceId, string name, string value) { char* nameChar = stringToChar(name); char* valueChar = stringToChar(value); bool returnValue = UnmanagedImport.tdSetDeviceParameter(deviceId, nameChar, valueChar); Marshal.FreeHGlobal((IntPtr)nameChar); Marshal.FreeHGlobal((IntPtr)valueChar); return returnValue; } /// /// Sets a new model for a device. Which model to set depends on the current protocol. /// /// Id of device to change /// The new model /// Success or error code public static unsafe bool tdSetModel(int deviceId, string model) { char* modelChar = stringToChar(model); bool returnValue = UnmanagedImport.tdSetModel(deviceId, modelChar); Marshal.FreeHGlobal((IntPtr)modelChar); return returnValue; } /// /// Sets a new name for a device. /// /// Id of device to change /// The new name /// Success or error code public static unsafe bool tdSetName(int deviceId, string name) { char* nameChar = stringToChar(name); bool returnValue = UnmanagedImport.tdSetName(deviceId, nameChar); Marshal.FreeHGlobal((IntPtr)nameChar); return returnValue; } /// /// This changes the current protocol used by a device. After changing the protocol, setting new parameters is required. /// /// Id of device to change /// The new protocol to use /// Success or error code public static unsafe bool tdSetProtocol(int deviceId, string protocol) { char* protocolChar = stringToChar(protocol); bool returnValue = UnmanagedImport.tdSetProtocol(deviceId, protocolChar); Marshal.FreeHGlobal((IntPtr)protocolChar); return returnValue; } /// /// Send "stop" command to device. /// Make sure the device supports this by calling tdMethods() before any calls to this function. /// /// The device id to stop /// Success or error code public static int tdStop(int deviceId) { return UnmanagedImport.tdStop(deviceId); } /// /// Turns a device on. /// Make sure the device supports this by calling tdMethods() before any calls to this function. /// /// Id of device to turn on /// Success or error code public static int tdTurnOn(int deviceId) { return UnmanagedImport.tdTurnOn(deviceId); } /// /// Turns a device off. /// Make sure the device supports this by calling tdMethods() before any calls to this function. /// /// Id of device to turn off /// Success or error code public static int tdTurnOff(int deviceId) { return UnmanagedImport.tdTurnOff(deviceId); } /// /// Unregister a callback function. All functions will be unregistered automatically when this objekt is deleted. /// /// Id of callback even to unregister public void unregisterCallback(int eventId) { deviceEventList.Remove(eventId); if (deviceEventList.Count == 0) { //no more events in list UnmanagedImport.tdUnregisterCallback(registeredEventFunctionId); callbackFunctionReferenceList.Remove(registeredEventFunctionId); /* if (eventContextHandle.IsAllocated) { eventContextHandle.Free(); } */ } deviceChangeEventList.Remove(eventId); if (deviceChangeEventList.Count == 0) { //no more events in list UnmanagedImport.tdUnregisterCallback(registeredDeviceChangeEventFunctionId); callbackFunctionReferenceList.Remove(registeredDeviceChangeEventFunctionId); } rawListenerList.Remove(eventId); if (rawListenerList.Count == 0) { //no more events in list UnmanagedImport.tdUnregisterCallback(registeredRawListenerFunctionId); callbackFunctionReferenceList.Remove(registeredRawListenerFunctionId); } } /// /// Send "up" command to device. /// Make sure the device supports this by calling tdMethods() before any calls to this function. /// /// The device id to send the command to /// Success or error code public static int tdUp(int deviceId) { return UnmanagedImport.tdUp(deviceId); } #endregion #region Private Methods /// /// Convert char* to correctly encoded string, clean up received char* /// /// Char* to convert /// Converted string private static unsafe string getString(char* input) { return getString(input, true); } /// /// Convert char* to correctly encoded string, clean up of received char* is optional /// /// Char* to convert /// Clean up char* or not (don't do that if it is still should be used somewhere) /// Converted string private static unsafe string getString(char* input, bool release) { string returnString = System.Text.Encoding.UTF8.GetString(System.Text.Encoding.Unicode.GetBytes(new string(input))); if (returnString.Contains("\0")) { returnString = returnString.Substring(0, returnString.IndexOf('\0')); } if (release) { UnmanagedImport.tdReleaseString(input); } GC.Collect(); return returnString; } /// /// Convert string to correctly encoded char* /// /// String to convert /// Converted char* private static unsafe char* stringToChar(string input) { input = String.Concat(input, char.MinValue); //add null terminator byte[] inputByte = System.Text.Encoding.UTF8.GetBytes(input); int size = Marshal.SystemDefaultCharSize * inputByte.Length; IntPtr inputPointer = Marshal.AllocHGlobal(size); Marshal.Copy(inputByte, 0, inputPointer, inputByte.Length); return (char*)inputPointer; } /// /// Event function wrapper that will call all registered event functions with C#-arguments when /// this event function is called from telldus core, with C++-style arguments. This function will /// be registered with telldus core when the first event callback function is added. /// /// Id of affected device /// Method that was executed on device /// Optional data that was sent to the method (e.g. dim value) /// Callback event id /// Context (optional) /// 0 private unsafe void deviceEventFunction(int deviceId, int method, char* data, int callbackId, void* context) { foreach (DeviceEventFunctionContext deviceEventFuncContext in deviceEventList.Values) { deviceEventFuncContext.eventCallbackFunc(deviceId, method, getString(data, false), deviceEventFuncContext.callbackId, deviceEventFuncContext.context); GC.Collect(); } } /// /// Event function wrapper that will call all registered device change event functions with C#-arguments when /// this device change event function is called from telldus core, with C++-style arguments. This function will /// be registered with telldus core when the first device change event callback function is added. /// /// Id of affected device /// Method that was executed, TELLSTICK_DEVICE_ADDED, TELLSTICK_DEVICE_CHANGED, TELLSTICK_DEVICE_REMOVED, TELLSTICK_DEVICE_STATE_CHANGED /// Type of change TELLSTICK_CHANGE_NAME, TELLSTICK_CHANGE_PROTOCOL, TELLSTICK_CHANGE_MODEL /// Callback event id /// Context (optional) /// 0 private unsafe void deviceChangeEventFunction(int deviceId, int changeEvent, int changeType, int callbackId, void* context) { foreach (DeviceChangeEventFunctionContext deviceChangeEventFuncContext in deviceChangeEventList.Values) { deviceChangeEventFuncContext.changeEventCallbackFunc(deviceId, changeEvent, changeType, deviceChangeEventFuncContext.callbackId, deviceChangeEventFuncContext.context); GC.Collect(); } } /// /// Event function wrapper that will call all registered listening functions with C#-arguments when /// this listening function is called from telldus core, with C++-style arguments. This function will /// be registered with telldus core when the first listening callback function is added. /// /// Received data /// Id of receiving controller /// Callback event id /// Context (optional) /// 0 private unsafe void rawListeningFunction(char* data, int controllerId, int callbackId, void* context) { foreach (RawEventFunctionContext rawListeningFuncContext in rawListenerList.Values) { rawListeningFuncContext.rawCallbackFunc(getString(data, false), controllerId, rawListeningFuncContext.callbackId, rawListeningFuncContext.context); GC.Collect(); } } #endregion } }