diff --git a/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs b/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..f7acaacc --- /dev/null +++ b/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ClassLibrary1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("ClassLibrary1")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a66028f7-b342-4dc0-9504-9e07c462ec15")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs new file mode 100644 index 00000000..f00acb30 --- /dev/null +++ b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs @@ -0,0 +1,783 @@ +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: reference the correct DLL + //TODO: compile towards correct platform (x86/64?) "Any" working? + //TODO: kommentera... både wrapper och exempel... + //TODO: kommentera i början av filen... + //error handling? Or just throw it upwards? + //close och init (om den skulle göras alls) görs här i wrappern, de exporteras inte vidare... eller ska de? Inte heller connected/disconnected tellstick + //TODO, use getNumberOfDevices as an example, outside the wrapper, service not running = -6, handle this here or later? Negative values = error + //throwing System.DllNotFoundException if dll's not ready... Handle here or in program? Might aswell keep that error message + + + //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; + + //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; + + //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); + Dictionary eventList = new Dictionary(); + GCHandle eventContextHandle; + 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); + Dictionary deviceChangeEventList = new Dictionary(); + GCHandle deviceChangeEventContextHandle; + 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); + Dictionary rawListenerList = new Dictionary(); + GCHandle rawListenerContextHandle; + 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. + if (eventContextHandle.IsAllocated) + { + eventContextHandle.Free(); + } + if (deviceChangeEventContextHandle.IsAllocated) + { + deviceChangeEventContextHandle.Free(); + } + if (rawListenerContextHandle.IsAllocated) + { + rawListenerContextHandle.Free(); + } + } + + /// + /// 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 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 eventFunction, 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 deviceEventFunction, void* context); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public unsafe delegate int EventFunctionDelegate(int deviceId, int method, char* data, int callbackId, void* context); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public unsafe delegate int DeviceChangeEventFunctionDelegate(int deviceId, int changeEvent, int changeType, int callbackId, void* context); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public unsafe delegate int 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); + } + + /// + /// 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); + } + + /// + /// 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_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 eventFunc, Object obj) + { + int returnValue = 0; + + if (eventList.Count == 0) + { + //first added, register with dll too + //only the context object of the first event will be registered + UnmanagedImport.EventFunctionDelegate eventFunctionDelegate = new UnmanagedImport.EventFunctionDelegate(eventFunction); + if (obj != null) + { + eventContextHandle = GCHandle.Alloc(obj); + registeredEventFunctionId = UnmanagedImport.tdRegisterDeviceEvent(eventFunctionDelegate, (void*)GCHandle.ToIntPtr(eventContextHandle)); //context here or above? + } + else + { + registeredEventFunctionId = UnmanagedImport.tdRegisterDeviceEvent(eventFunctionDelegate, (void*)null); //context here or above? + } + callbackFunctionReferenceList.Add(registeredEventFunctionId, eventFunctionDelegate); + } + + ++lastEventID; + returnValue = lastEventID; + eventList.Add(returnValue, eventFunc); + + 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 deviceEventFunc, 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(deviceEventFunction); + + if (obj != null) + { + deviceChangeEventContextHandle = GCHandle.Alloc(obj); + registeredDeviceChangeEventFunctionId = UnmanagedImport.tdRegisterDeviceChangeEvent(deviceChangeEventFunctionDelegate, (void*)GCHandle.ToIntPtr(deviceChangeEventContextHandle)); + } + else + { + registeredDeviceChangeEventFunctionId = UnmanagedImport.tdRegisterDeviceChangeEvent(deviceChangeEventFunctionDelegate, (void*)null); + } + callbackFunctionReferenceList.Add(registeredDeviceChangeEventFunctionId, deviceChangeEventFunctionDelegate); + + } + ++lastEventID; + returnValue = lastEventID; + deviceChangeEventList.Add(returnValue, deviceEventFunc); + + 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); + + if (obj != null) + { + rawListenerContextHandle = GCHandle.Alloc(obj); + + registeredRawListenerFunctionId = UnmanagedImport.tdRegisterRawDeviceEvent(listeningFunctionDelegate, (void*)GCHandle.ToIntPtr(rawListenerContextHandle)); //TODO context here or above? + } + else + { + registeredRawListenerFunctionId = UnmanagedImport.tdRegisterRawDeviceEvent(listeningFunctionDelegate, (void*)null); + } + callbackFunctionReferenceList.Add(registeredRawListenerFunctionId, listeningFunctionDelegate); + } + ++lastEventID; + returnValue = lastEventID; + rawListenerList.Add(returnValue, listeningFunc); + 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; + } + + /// + /// 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 unsafe 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 unsafe 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) + { + eventList.Remove(eventId); + if (eventList.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); + if (deviceChangeEventContextHandle.IsAllocated) + { + deviceChangeEventContextHandle.Free(); + } + } + + rawListenerList.Remove(eventId); + if (rawListenerList.Count == 0) + { + //no more events in list + UnmanagedImport.tdUnregisterCallback(registeredRawListenerFunctionId); + callbackFunctionReferenceList.Remove(registeredRawListenerFunctionId); + if (rawListenerContextHandle.IsAllocated) + { + rawListenerContextHandle.Free(); + } + } + } + + #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 (release) + { + UnmanagedImport.tdReleaseString(input); + } + 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 int eventFunction(int deviceId, int method, char* data, int callbackId, void* context) + { + foreach (EventCallbackFunction eventFunc in eventList.Values) + { + if (context != null) + { + GCHandle eventContextHandle = GCHandle.FromIntPtr((IntPtr)context); + eventFunc(deviceId, method, getString(data, false), callbackId, (Object)eventContextHandle.Target); + } + else + { + eventFunc(deviceId, method, getString(data, false), callbackId, null); + } + } + + return 0; + } + + /// + /// 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 int deviceEventFunction(int deviceId, int changeEvent, int changeType, int callbackId, void* context) + { + foreach (DeviceChangeEventCallbackFunction deviceEventFunc in deviceChangeEventList.Values) + { + if (context != null) + { + GCHandle deviceChangeEventContextHandle = GCHandle.FromIntPtr((IntPtr)context); + deviceEventFunc(deviceId, changeEvent, changeType, callbackId, (Object)deviceChangeEventContextHandle.Target); + } + else + { + deviceEventFunc(deviceId, changeEvent, changeType, callbackId, null); + } + } + + return 0; + } + + /// + /// 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 int rawListeningFunction(char* data, int controllerId, int callbackId, void* context) + { + foreach (RawListeningCallbackFunction rawListeningFunc in rawListenerList.Values) + { + if (context != null) + { + GCHandle rawListenerContextHandle = GCHandle.FromIntPtr((IntPtr)context); + rawListeningFunc(getString(data, false), controllerId, callbackId, (Object)rawListenerContextHandle.Target); //strings cannot be released here, since they are still in use by calling core (sent to other clients aswell), let the core take care of it with shared pointer + } + else + { + rawListeningFunc(getString(data, false), controllerId, callbackId, null); + } + } + + return 0; + } + + #endregion + } +} diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.csproj b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.csproj new file mode 100644 index 00000000..255d47bb --- /dev/null +++ b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.csproj @@ -0,0 +1,56 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43} + Library + Properties + ClassLibrary1 + TelldusNETWrapper + v2.0 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.sln b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.sln new file mode 100644 index 00000000..28bb73d2 --- /dev/null +++ b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelldusNETWrapper", "TelldusNETWrapper.csproj", "{675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.suo b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.suo new file mode 100644 index 00000000..61636ea2 Binary files /dev/null and b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.suo differ diff --git a/bindings/dotnet/TelldusNETWrapper/app.config b/bindings/dotnet/TelldusNETWrapper/app.config new file mode 100644 index 00000000..b7db2817 --- /dev/null +++ b/bindings/dotnet/TelldusNETWrapper/app.config @@ -0,0 +1,3 @@ + + +