diff --git a/.gitignore b/.gitignore index 567609b1..2c86bf2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ build/ +qtcreator-build/ +Doxyfile +html/ +latex/ +CMakeLists.txt.user diff --git a/tellstick.net/Properties/AssemblyInfo.cs b/3rdparty/tellstick.net/Properties/AssemblyInfo.cs similarity index 100% rename from tellstick.net/Properties/AssemblyInfo.cs rename to 3rdparty/tellstick.net/Properties/AssemblyInfo.cs diff --git a/tellstick.net/TellStick.NET.csproj b/3rdparty/tellstick.net/TellStick.NET.csproj similarity index 100% rename from tellstick.net/TellStick.NET.csproj rename to 3rdparty/tellstick.net/TellStick.NET.csproj diff --git a/tellstick.net/TellStick.cs b/3rdparty/tellstick.net/TellStick.cs similarity index 100% rename from tellstick.net/TellStick.cs rename to 3rdparty/tellstick.net/TellStick.cs diff --git a/tellstickcontroller/License b/3rdparty/tellstickcontroller/License similarity index 100% rename from tellstickcontroller/License rename to 3rdparty/tellstickcontroller/License diff --git a/tellstickcontroller/Readme b/3rdparty/tellstickcontroller/Readme similarity index 100% rename from tellstickcontroller/Readme rename to 3rdparty/tellstickcontroller/Readme diff --git a/tellstickcontroller/examples/power_off_all_lights b/3rdparty/tellstickcontroller/examples/power_off_all_lights similarity index 100% rename from tellstickcontroller/examples/power_off_all_lights rename to 3rdparty/tellstickcontroller/examples/power_off_all_lights diff --git a/tellstickcontroller/examples/power_off_bedroom_mythtv b/3rdparty/tellstickcontroller/examples/power_off_bedroom_mythtv similarity index 100% rename from tellstickcontroller/examples/power_off_bedroom_mythtv rename to 3rdparty/tellstickcontroller/examples/power_off_bedroom_mythtv diff --git a/tellstickcontroller/examples/power_on_all_lights b/3rdparty/tellstickcontroller/examples/power_on_all_lights similarity index 100% rename from tellstickcontroller/examples/power_on_all_lights rename to 3rdparty/tellstickcontroller/examples/power_on_all_lights diff --git a/tellstickcontroller/examples/power_on_bedroom_mythtv b/3rdparty/tellstickcontroller/examples/power_on_bedroom_mythtv similarity index 100% rename from tellstickcontroller/examples/power_on_bedroom_mythtv rename to 3rdparty/tellstickcontroller/examples/power_on_bedroom_mythtv diff --git a/tellstickcontroller/examples/swap_livingroom_tv_mode b/3rdparty/tellstickcontroller/examples/swap_livingroom_tv_mode similarity index 100% rename from tellstickcontroller/examples/swap_livingroom_tv_mode rename to 3rdparty/tellstickcontroller/examples/swap_livingroom_tv_mode diff --git a/tellstickcontroller/examples/tellstickController.conf b/3rdparty/tellstickcontroller/examples/tellstickController.conf similarity index 100% rename from tellstickcontroller/examples/tellstickController.conf rename to 3rdparty/tellstickcontroller/examples/tellstickController.conf diff --git a/tellstickcontroller/tellstick.conf b/3rdparty/tellstickcontroller/tellstick.conf similarity index 100% rename from tellstickcontroller/tellstick.conf rename to 3rdparty/tellstickcontroller/tellstick.conf diff --git a/tellstickcontroller/tellstickController b/3rdparty/tellstickcontroller/tellstickController similarity index 100% rename from tellstickcontroller/tellstickController rename to 3rdparty/tellstickcontroller/tellstickController diff --git a/tellstickcontroller/tellstickController.conf b/3rdparty/tellstickcontroller/tellstickController.conf similarity index 100% rename from tellstickcontroller/tellstickController.conf rename to 3rdparty/tellstickcontroller/tellstickController.conf diff --git a/tellstickcontroller/tellstickControllerRfcmd b/3rdparty/tellstickcontroller/tellstickControllerRfcmd similarity index 100% rename from tellstickcontroller/tellstickControllerRfcmd rename to 3rdparty/tellstickcontroller/tellstickControllerRfcmd diff --git a/tellstickcontroller/tellstickControllerRfcmd.conf b/3rdparty/tellstickcontroller/tellstickControllerRfcmd.conf similarity index 100% rename from tellstickcontroller/tellstickControllerRfcmd.conf rename to 3rdparty/tellstickcontroller/tellstickControllerRfcmd.conf diff --git a/tellstickcontroller/tellstickControllerTdtool b/3rdparty/tellstickcontroller/tellstickControllerTdtool similarity index 100% rename from tellstickcontroller/tellstickControllerTdtool rename to 3rdparty/tellstickcontroller/tellstickControllerTdtool diff --git a/tellstickcontroller/tellstickControllerTdtool.conf b/3rdparty/tellstickcontroller/tellstickControllerTdtool.conf similarity index 100% rename from tellstickcontroller/tellstickControllerTdtool.conf rename to 3rdparty/tellstickcontroller/tellstickControllerTdtool.conf diff --git a/tellstickd/LICENSE b/3rdparty/tellstickd/LICENSE similarity index 100% rename from tellstickd/LICENSE rename to 3rdparty/tellstickd/LICENSE diff --git a/tellstickd/README b/3rdparty/tellstickd/README similarity index 100% rename from tellstickd/README rename to 3rdparty/tellstickd/README diff --git a/tellstickd/init_script/tellstickd b/3rdparty/tellstickd/init_script/tellstickd similarity index 100% rename from tellstickd/init_script/tellstickd rename to 3rdparty/tellstickd/init_script/tellstickd diff --git a/tellstickd/init_script/tellstickd.debian b/3rdparty/tellstickd/init_script/tellstickd.debian similarity index 100% rename from tellstickd/init_script/tellstickd.debian rename to 3rdparty/tellstickd/init_script/tellstickd.debian diff --git a/tellstickd/tellstickd b/3rdparty/tellstickd/tellstickd similarity index 100% rename from tellstickd/tellstickd rename to 3rdparty/tellstickd/tellstickd diff --git a/tellstickd/tellstickd.conf b/3rdparty/tellstickd/tellstickd.conf similarity index 100% rename from tellstickd/tellstickd.conf rename to 3rdparty/tellstickd/tellstickd.conf diff --git a/docs/telldus-core.dox b/docs/telldus-core.dox index a34afe64..9185076e 100644 --- a/docs/telldus-core.dox +++ b/docs/telldus-core.dox @@ -187,10 +187,54 @@ * tdReleaseString(name); * \endcode * + * \subsection sec_bu_sensors Sensors + * + * Retrieving sensor values can be done in two ways. Either by a polling + * interface or by callbacks. The client application can implement one or both + * of these interfaces. For callbacks, read more under \ref sec_events. + * + * Each of the sensors can have one or several value types. Currently only + * temperature and humidity are implemented. + * + * There is no API to add, remove or edit sensors. Each sensor that + * TellStick Duo has got any data from is added to an internal list. It is up to + * the client application to filter and only show the sensors your are + * interested in. + * + * To iterate over the list of sensors, call tdSensor() repeatedly as long as it + * returns \c TELLSTICK_SUCCESS. The parameters \c protocol, \c model, + * \c sensorId, and \c dataTypes are sent by reference and will be filled with + * the values. + * + * Example: + * \code + * char protocol[DATA_LENGTH], model[DATA_LENGTH]; + * int sensorId = 0, dataTypes = 0; + * while(tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes) == TELLSTICK_SUCCESS) { + * //Print the sensor + * printf("%s,\t%s,\t%i\n", protocol, model, sensorId); + * } + * \endcode + * + * The type of sensor values the sensor supports are stored as flags in the + * parameter \c sensorId. Call tdSensorValue() for each type. + * + * Example: + * \code + * char value[DATA_LENGTH]; + * char timeBuf[80]; + * time_t timestamp = 0; + * if (dataTypes & TELLSTICK_TEMPERATURE) { + * tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, value, DATA_LENGTH, (int *)×tamp); + * strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + * printf("Temperature:\t%sº\t(%s)\n", value, timeBuf); + * } + * \endcode + * * \section sec_events Events * - * To get events from either a TellStick Duo or if another software changes the - * status of a device you have to register for a callback. + * To get events from either a TellStick Duo, another software changes the + * status of a device, or new sensors values you have to register for a callback. * * \subsection sec_events_registering Registering for callbacks * @@ -198,6 +242,7 @@ * \li tdRegisterDeviceEvent() * \li tdRegisterDeviceChangeEvent() * \li tdRegisterRawDeviceEvent() + * \li tdRegisterSensorEvent() * * These all work in the same way. The first parameter is a function-pointer to * the callback function. The second parameter is an optional void pointer. This @@ -212,13 +257,14 @@ * * Many devices (for example motion detectors) resends their messages many times * to ensure that they are received correctly. If a deviceeventcallback or - * rawdeviceeventcallback in turn is calling a controlling function, for example tdTurnOn, - * it may be neccessary to implement some solution to wait for the device to finish its - * resending, before executing the controlling function. See how this can be done in the python example. + * rawdeviceeventcallback in turn is calling a controlling function, for example + * tdTurnOn, it may be neccessary to implement some solution to wait for the + * device to finish its resending, before executing the controlling function. + * See how this can be done in the python example. * * \subsection sec_events_callbacks Callbacks * - * telldus-core currently implements three different callback function for + * telldus-core currently implements four different callback function for * different purposes. * * \subsubsection sec_events_callbacks_deviceevent DeviceEvent @@ -234,9 +280,10 @@ * - const char *data - For some methods this contains data. For TELLSTICK_DIM * this hold the current value. * - int callbackId - id of callback - * - void *context - see "Registering for callbacks" for description + * - void *context - see \ref sec_events_registering for description * * \subsubsection sec_events_callbacks_devicechangeevent DeviceChangeEvent + * * This event is fired when the data around a device is changed. It can only be * triggered by another software. Use this callback to keep your list of devices * in sync. @@ -256,19 +303,33 @@ * - TELLSTICK_CHANGE_PROTOCOL - Use tdGetProtocol() to read the new value. * - TELLSTICK_CHANGE_MODEL - Use tdGetModel() to read the new value. * - int callbackId - id of callback - * - void *context - see "Registering for callbacks" for description + * - void *context - see \ref sec_events_registering for description * * \subsubsection sec_events_callbacks_rawdeviceevent RawDeviceEvent * - * Use this callback with caution. It outputs everything from the Duo without - * any preprocessing. This can be used to get events from devices not already - * configured. + * Use this callback with caution. It outputs everything from a TellStick Duo + * without any preprocessing. This can be used to get events from devices not + * already configured. * * Parameters: * - const char *data - raw device data * - int controllerId - id of receiving controller, can identify the TellStick if several exists in the system * - int callbackId - id of callback - * - void *context - see "Registering for callbacks" for description + * - void *context - see \ref sec_events_registering for description + * + * \subsubsection sec_events_callbacks_sensorevent SensorEvent + * + * This event is fired when a new sensor value is retrieved. + * + * Parameters: + * - const char *protocol - The sensors protocol + * - const char *model - The model of the sensor + * - int id - The unique id for the sensor. + * - int dataType - Flags for which types of data the sensor supports + * - const char *value - A human readable string of the data + * - int timestamp - The timestamp when the latest value was received + * - int callbackId - id of callback + * - void *context - See \ref sec_events_registering for description * * \subsection sec_events_example Example * diff --git a/examples/php/live/authentication/common.php b/examples/php/live/authentication/common.php new file mode 100644 index 00000000..05873f77 --- /dev/null +++ b/examples/php/live/authentication/common.php @@ -0,0 +1,19 @@ +getAccessToken(constant('ACCESS_TOKEN')); + + $_SESSION['accessToken'] = $consumer->getToken(); + $_SESSION['accessTokenSecret'] = $consumer->getTokenSecret(); + + header('Location:index.php'); +} catch (Exception $e) { + ?> +

Authorization failed!

+

Go back

+ getRequestToken(constant('REQUEST_TOKEN'), constant('BASE_URL').'/getAccessToken.php'); + +$_SESSION['token'] = $consumer->getToken(); +$_SESSION['tokenSecret'] = $consumer->getTokenSecret(); + +$url = $consumer->getAuthorizeUrl(constant('AUTHORIZE_TOKEN')); +header('Location:'.$url); diff --git a/examples/php/live/authentication/index.php b/examples/php/live/authentication/index.php new file mode 100644 index 00000000..a0a78db9 --- /dev/null +++ b/examples/php/live/authentication/index.php @@ -0,0 +1,47 @@ +We have no access token, connect us +

We have access!

+

+ In your system, store these values to do requests for this user:
+ Token:
+ Secret: +

+

Clear the token and restart

+

List users devices

+ constant('TELLSTICK_TURNON') | constant('TELLSTICK_TURNOFF'), + ); + $response = $consumer->sendRequest(constant('REQUEST_URI').'/devices/list', $params, 'GET'); + echo '
';
+	echo( htmlentities($response->getBody()));
+}
+
+?>

List users clients

sendRequest(constant('REQUEST_URI').'/clients/list', $params, 'GET'); + echo '
';
+	echo( htmlentities($response->getBody()));
+}
+
+
diff --git a/rfcmd/CMakeLists.txt b/rfcmd/CMakeLists.txt
new file mode 100644
index 00000000..af4b4484
--- /dev/null
+++ b/rfcmd/CMakeLists.txt
@@ -0,0 +1,88 @@
+cmake_minimum_required(VERSION 2.4)
+
+INCLUDE_DIRECTORIES(
+  /usr/src/linux/include
+)
+
+#### Project: rfcmd ####
+
+PROJECT(rfcmd)
+
+SET(rfcmd_DESCRIPTION
+	"Sends RF remote commands through a Telldus TellStick"
+)
+
+SET(rfcmd_SRCS
+  rfcmd.c
+)
+
+IF(${RFCMD_DEBUG})
+	ADD_DEFINITIONS( -DRFCMD_DEBUG )
+ENDIF(${RFCMD_DEBUG})
+
+IF (BUILD_RFCMD_WITH_LIBFTDI)
+	ADD_DEFINITIONS( -DLIBFTDI )
+
+	SET(rfcmd_SRCS
+		${rfcmd_SRCS}
+		ftdi.c
+	)
+ENDIF (BUILD_RFCMD_WITH_LIBFTDI)
+ADD_EXECUTABLE(rfcmd
+  ${rfcmd_SRCS}
+)
+
+IF (BUILD_RFCMD_WITH_SEMAPHORES)
+	FIND_LIBRARY(SEM_LIBRARY rt)
+	TARGET_LINK_LIBRARIES(rfcmd
+		${SEM_LIBRARY}
+	)
+ELSE (BUILD_RFCMD_WITH_SEMAPHORES)
+	ADD_DEFINITIONS( -DNO_SEMAPHORES )
+ENDIF (BUILD_RFCMD_WITH_SEMAPHORES)
+
+
+
+IF (BUILD_RFCMD_WITH_LIBFTDI)
+	FIND_LIBRARY(FTDI_LIBRARY ftdi)
+
+	TARGET_LINK_LIBRARIES(rfcmd
+	${FTDI_LIBRARY}
+	)
+ENDIF (BUILD_RFCMD_WITH_LIBFTDI)
+
+INSTALL(TARGETS rfcmd RUNTIME DESTINATION bin)
+
+IF (UNIX)
+	IF (GENERATE_MAN)
+		ADD_CUSTOM_COMMAND(
+			TARGET rfcmd
+			POST_BUILD
+			COMMAND help2man -n ${rfcmd_DESCRIPTION} ./rfcmd > rfcmd.1
+			WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+			COMMENT "Generating man file rfcmd.1"
+		)
+		INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/rfcmd.1 DESTINATION share/man/man1)
+	ENDIF (GENERATE_MAN)
+ENDIF (UNIX)
+
+#### Project: find_telldus ####
+
+IF (BUILD_RFCMD_WITH_LIBFTDI)
+	PROJECT(find_telldus)
+
+	SET(find_telldus_SRCS
+		find_telldus.c
+	)
+
+	ADD_EXECUTABLE(find_telldus
+		${find_telldus_SRCS}
+	)
+
+	TARGET_LINK_LIBRARIES(find_telldus
+	${FTDI_LIBRARY}
+	)
+
+	INSTALL(TARGETS find_telldus RUNTIME DESTINATION bin)
+
+ENDIF (BUILD_RFCMD_WITH_LIBFTDI)
diff --git a/rfcmd/COPYING b/rfcmd/COPYING
new file mode 100644
index 00000000..60549be5
--- /dev/null
+++ b/rfcmd/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    
+    Copyright (C) 19yy  
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  , 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/rfcmd/Makefile b/rfcmd/Makefile
new file mode 100644
index 00000000..4836075a
--- /dev/null
+++ b/rfcmd/Makefile
@@ -0,0 +1,22 @@
+
+SRCS=	rfcmd.c ftdi.c
+CFLAGS=-O2	-Wall -I/usr/local/include
+LFLAGS=	-L/usr/local/lib -R/usr/local/lib
+#linux:LFLAGS=-Wl,-rpath,/usr/local/lib
+LIBS=	-lftdi -lusb
+PROG= 	rfcmd
+FT=	find_telldus
+OBJS= 	$(SRCS:.c=.o)
+CC= 	gcc
+
+all: $(PROG) $(FT)
+
+$(PROG): $(OBJS)
+	$(CC) $(CFLAGS) $(OBJS) -o $(PROG) $(LFLAGS) $(LIBS)
+
+rfcmd.o: rfcmd.c
+
+ftdi.o:	ftdi.c
+
+$(FT): $(FT).c
+	$(CC) $(CFLAGS) -o $@ $(FT).c $(LFLAGS) $(LIBS)
diff --git a/rfcmd/build.sh b/rfcmd/build.sh
new file mode 100644
index 00000000..fb5100b9
--- /dev/null
+++ b/rfcmd/build.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+set -e
+make clean || { echo "Warning: make clean failed"; }
+make || { echo "make failed"; exit 1; }
+make install || { echo "make install failed"; exit 1; }
+echo rfcmd built and installed!
diff --git a/rfcmd/find_telldus.c b/rfcmd/find_telldus.c
new file mode 100644
index 00000000..5c44915e
--- /dev/null
+++ b/rfcmd/find_telldus.c
@@ -0,0 +1,42 @@
+/* find_all.c
+
+   Example for ftdi_usb_find_all()
+
+   This program is distributed under the GPL, version 2
+*/
+
+#include 
+#include 
+
+int main(int argc, char **argv)
+{
+  int ret, i;
+  struct ftdi_context ftdic;
+  struct ftdi_device_list *devlist, *curdev;
+  char manufacturer[128], description[128];
+  
+  ftdi_init(&ftdic);
+
+  if((ret = ftdi_usb_find_all(&ftdic, &devlist, 0x1781, 0x0c30)) < 0) {
+    fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
+    return EXIT_FAILURE;
+  }
+  
+  printf("Number of FTDI devices (telldus) found: %d\n", ret);
+  
+  i = 0;
+  for (curdev = devlist; curdev != NULL; i++) {
+    printf("Checking device: %d\n", i);
+    if((ret = ftdi_usb_get_strings(&ftdic, curdev->dev, manufacturer, 128, description, 128, NULL, 0)) < 0) {
+      fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
+      return EXIT_FAILURE;
+    }
+    printf("Manufacturer: %s, Description: %s\n\n", manufacturer, description);
+    curdev = curdev->next;
+  }
+  
+  ftdi_list_free(&devlist);
+  ftdi_deinit(&ftdic);
+  
+  return EXIT_SUCCESS;
+}
diff --git a/rfcmd/ftdi.c b/rfcmd/ftdi.c
new file mode 100644
index 00000000..c229f2cb
--- /dev/null
+++ b/rfcmd/ftdi.c
@@ -0,0 +1,110 @@
+/*
+ * TellStick libftdi libusb version
+ * tested with 0.15 : http://www.intra2net.com/en/developer/libftdi
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#define BAUD 4800
+
+void ftdiCleanup(struct ftdi_context *ctx) {
+	ftdi_usb_close( ctx );
+	ftdi_deinit( ctx );
+}
+
+/*
+ * use libftdi and libusb to send command
+ * no kernel driver needed
+ */
+int usbWriteFtdi(char *cmdstr)
+{
+	struct ftdi_context ctx;
+	int device=0x0c30, vendor=0x1781;
+	int retrycnt;
+	int retval = 0;
+
+	if (ftdi_init( &ctx )) {
+		char *err = ftdi_get_error_string(&ctx);
+		fprintf(stderr,  "usb - init error: %s\n", err);
+		return 1;
+	}
+
+	retval = ftdi_usb_open(&ctx, vendor, device);
+	if (retval) {
+		char *err = ftdi_get_error_string(&ctx);
+		// FreeBSD says -3 when another rfcmd is running...
+		// Same on other systems?
+		if(retval == -3) {
+			fprintf(stderr,  "usb - open error: %s. Is it busy?\n", err);
+		} else {
+			fprintf(stderr,  "usb - open error: %s\n", err);
+		}
+
+		ftdi_deinit( &ctx );
+		return 2;
+	}
+
+	if (ftdi_usb_reset( &ctx )) {
+		char *err = ftdi_get_error_string(&ctx);
+		fprintf(stderr,  "usb - reset error: %s\n", err);
+		retval = 3;
+		ftdiCleanup(&ctx);
+		return retval;
+	}
+
+	if (ftdi_disable_bitbang( &ctx ) || ftdi_set_baudrate(&ctx, BAUD)) {
+		char *err = ftdi_get_error_string(&ctx);
+		fprintf(stderr,  "usb - init failed: %s\n", err);
+		ftdiCleanup(&ctx);
+		return 4;
+	}
+
+	retval = ftdi_write_data( &ctx, cmdstr, strlen(cmdstr) );
+	if (retval < 0) {
+		char *err = ftdi_get_error_string(&ctx);
+		fprintf(stderr,  "usb - write failed: %s\n", err);
+		ftdiCleanup(&ctx);
+		return 5;
+	}	else if(retval != strlen(cmdstr)) {
+		fprintf(stderr,  "usb - warning: %d bytes written instead of %d\n", 
+				retval, (int)strlen(cmdstr));
+	}
+
+	/**
+	 * Wait for Tellstick to be done with cmd, read back until we've received
+	 * a \n indicating end of response.
+	 * Wait max 5000 * 1000uS.
+	 * XXX: Can the tellstick report errors?
+	 */
+	retval = 0;
+	retrycnt = 5000;
+	while (retrycnt--) {
+		unsigned char inb;
+		int bytes;
+
+		bytes = ftdi_read_data(&ctx, &inb, 1);
+		if (bytes == 0) {
+			usleep(1000);
+		} else if (bytes > 0) {
+			// Done when newline is received
+			if(inb == '\n') {
+				ftdiCleanup(&ctx);
+				return retval;
+			}
+		} else {
+			char *err = ftdi_get_error_string(&ctx);
+			fprintf(stderr,  "usb - read error: %s\n", err);
+			ftdiCleanup(&ctx);
+			return 6;
+		}
+	}
+
+	// if we get here we failed to readback
+	fprintf(stderr,  "usb - warning: never got newline response, giving up on wait\n");
+	return retval;
+}
+
+
diff --git a/rfcmd/rfcmd.c b/rfcmd/rfcmd.c
new file mode 100644
index 00000000..76901da5
--- /dev/null
+++ b/rfcmd/rfcmd.c
@@ -0,0 +1,663 @@
+/****************************************************************************
+ ** rfcmd.c ***********************************************************
+ ****************************************************************************
+ *
+ * rfcmd - utility to control NEXA and other RF remote receivers through a TellStick
+ * USB interface
+ *
+ * Copyright (C) 2007 Tord Andersson 
+ *
+ * License: GPL v. 2
+ *
+ * Authors:
+ *   Tord Andersson 
+ *   Micke Prag 
+ *   Gudmund Berggren
+ *
+ *   Tapani Rintala / userspace libusb / libftdi - version 02-2009
+ */
+
+/*******************************************************************************
+ * Modifications from rfcmd.c ver 0.2 done by Gudmund
+ *  Added support for IKEA
+ * Note:
+ * 1. System code
+ * 2. Level 0 == Off (For dimmers and non dimmers)
+ *    Level 1== 10%. (for dimmers)
+ *     ....
+ *    Level 9 == 90 % (for dimmers)
+ *    Level 10 == 100 %  (or ON for non dimmers)
+ * 3. Command line syntax:
+ *    /usr/local/bin/rfcmd  /dev/ttyUSB0  IKEA 0 1 10 1"
+ *    Arg 1: device
+ *    Arg 2: Protocoll
+ *    Arg 3: System code
+ *    Arg 4: Device code
+ *    Arg 5: Level (0=off, 1 = 10%, 2=20%,...9=90%, 10=100%)
+ *    Arg 6: DimStyle (0=instant change, 1=gradually change)
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Modifications to rfcmd.c ver 2.1.0 done by Tord Andersson
+ *  Introduced semaphore protection to avoid problems with simultaneous port 
+ *  access from several processes (typically cron jobs). Note! Need rt lib. 
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Modifications from rfcmd.c ver 2.1.0 done by Leo
+ *  Added support for RISINGSUN
+ * Note:
+ * 1. Command line syntax:
+ *    /usr/local/bin/rfcmd  /dev/ttyUSB0  RISINGSUN 4 1 0" 
+ *    Arg 1: device
+ *    Arg 2: protocol
+ *    Arg 3: code 
+ *    Arg 4: device number
+ *    Arg 5: Level (0=off, 1 = on)
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Modifications from rfcmd.c ver 2.1.0 based on marvelous work by Snakehand
+ * See http://www.telldus.com/forum/viewtopic.php?t=97&start=63
+ *  Added support for EVERFLOURISH
+ * Note:
+ * 1. Command line syntax:
+ *    /usr/local/bin/rfcmd  /dev/ttyUSB0  EVERFLOURISH 1 15
+ *    Arg 1: device
+ *    Arg 2: protocol
+ *    Arg 3: device number (0..65535)
+ *    Arg 4: Level (0=off, 15=on, 10=learn)
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Modifications from rfcmd ver 2.1.1 done by Johan Ström
+ *  Default disabled semaphores for FreeBSD.
+ *  Added status readback in ftdi.c, instead of wasting time in sleep.
+ *
+ * FreeBSD does not have support in the GENERIC kernel semaphore.
+ * To enable usage of them, you'll have have the following option in your
+ * kernel configuration:
+ *
+ *   options P1003_1B_SEMAPHORES
+ *
+ * However, on FreeBSD only libftdi seems to be working (at least on my system),
+ * since the device is not identified as a ucom device. And as we're accessing it
+ * via libftdi, libftdi makes sure simultaneous access is impossible.
+ ******************************************************************************/
+
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef NO_SEMAPHORES
+#include 
+#endif
+
+#define PROG_NAME "rfcmd"
+#define PROG_VERSION "2.1.1"
+/* #define RFCMD_DEBUG */ 
+
+/* Local function declarations */
+int createNexaString(const char * pHouseStr, const char * pChannelStr,
+                     const char * pOn_offStr, char * pTxStr, int waveman);
+int createSartanoString(const char * pChannelStr, const char * pOn_offStr,
+                        char * pTxStr);
+int createIkeaString(const char * pSystemStr, const char * pChannelStr,
+                     const char * pLevelStr, const char *pDimStyle,
+                     char * pStrReturn);
+int createRisingSunString(const char * pCodeStr, const char* pUnitStr, const char * pOn_offStr,
+                        char * pTxStr);
+int createEverFlourishString(const char* pUnitStr, const char * pLevelStr,
+                        char * pTxStr);
+void printUsage(void);
+void printVersion(void);
+
+#ifdef LIBFTDI
+int usbWriteFtdi(char *cmdstr);
+#endif
+
+int main( int argc, char **argv )
+{
+	struct termios tio;
+	int fd = -1;
+#ifndef NO_SEMAPHORES
+	sem_t * portMutex;
+	char SEM_NAME[]= "RFCMD_SEM"; /* Semaphore for multiple access ctrl */
+#endif
+
+
+	char txStr[100];
+
+	if( (argc == 6) && (strcmp(*(argv+2), "NEXA") == 0)) {
+		if (createNexaString(*(argv+3), *(argv+4), *(argv+5), txStr, 0) == 0) {
+			printUsage();
+			exit(1);
+		}
+		/* else - a send cmd string was created */
+	} else if( (argc == 6) && (strcmp(*(argv+2), "WAVEMAN") == 0)) {
+		if (createNexaString(*(argv+3),*(argv+4), *(argv+5), txStr, 1) == 0) {
+			printUsage();
+			exit(1);
+		}
+	} else if( (argc == 5) && (strcmp(*(argv+2), "SARTANO") == 0)) {
+		if (createSartanoString(*(argv+3), *(argv+4), txStr) == 0) {
+			printUsage();
+			exit(1);
+		}
+		/* else - a send cmd string was created */
+	} else if ( (argc == 7) && (strcmp(*(argv+2),"IKEA")==0) ) {
+		//                    System,   Channel,    Level,    DimStyle, TXString
+		if ( createIkeaString(*(argv+3), *(argv+4), *(argv+5), *(argv+6),txStr) == 0 ) {
+			printUsage();
+			exit(1);
+		}
+		/* else - a send cmd string was created */
+	} else if ( (argc == 6) && (strcmp(*(argv+2),"RISINGSUN")==0) ) {
+	//                    Code,   Unit,    Power
+		if ( createRisingSunString(*(argv+3), *(argv+4), *(argv+5), txStr) == 0 ) {
+			printUsage();
+			exit(1);
+			}
+		/* else - a send cmd string was created */
+	} else if ( (argc == 5) && (strcmp(*(argv+2),"EVERFLOURISH")==0) ) {
+	//                      Unit,          Level
+		if ( createEverFlourishString(*(argv+3), *(argv+4), txStr) == 0 ) {
+			printUsage();
+			exit(1);
+		}
+		/* else - a send cmd string was created */
+	} else if ( (argc >= 2) && (strcmp(*(argv+1),"--version")==0) ) {
+		printVersion();
+		exit(1);
+	} else { /* protocol or parameters not recognized */
+		printUsage();
+		exit(1);
+	}
+
+#ifdef RFCMD_DEBUG
+	printf("txStr: %s\n", txStr);
+
+#endif
+
+	if(strlen(txStr) > 0) {
+#ifndef NO_SEMAPHORES
+		/* create the semaphore - will reuse an existing one if it exists */
+		portMutex = sem_open(SEM_NAME,O_CREAT,0644,1);
+		if( portMutex == SEM_FAILED) {
+			fprintf(stderr,  "%s - Error creating port semaphore\n", PROG_NAME);
+			perror("Semaphore open error");
+			sem_unlink(SEM_NAME);
+			exit(1);
+		}
+
+		/* lock semaphore to protect port from multiple access */
+		if(sem_wait(portMutex) != 0) {
+			fprintf(stderr,  "%s - Error aquiring port semaphore\n", PROG_NAME);
+			sem_unlink(SEM_NAME);
+			sem_close(portMutex);
+			exit(1); 
+		}
+#endif
+
+
+		if (strcmp(*(argv+1), "LIBUSB") != 0) {
+			if( 0 > ( fd = open( *(argv+1), O_RDWR ) ) ) {
+#ifdef __FreeBSD__
+				fprintf(stderr,  "%s - Error opening %s; You're on a FreeBSD system, you should probably use LIBUSB.\n", PROG_NAME, *(argv+1));
+#else
+				fprintf(stderr,  "%s - Error opening %s\n", PROG_NAME, *(argv+1));
+#endif
+#ifndef NO_SEMAPHORES
+				if(sem_post(portMutex) != 0) {
+					fprintf(stderr,  "%s - Error releasing port semaphore\n", PROG_NAME);
+				}
+				sem_unlink(SEM_NAME);
+				sem_close(portMutex);
+#endif
+				exit(1);
+			}
+
+			/* adjust serial port parameters */
+			bzero(&tio, sizeof(tio)); /* clear struct for new port settings */
+			tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */
+			tio.c_iflag = IGNPAR;
+			tio.c_oflag = 0;
+			tio.c_ispeed = 4800;
+			tio.c_ospeed = 4800;
+			tcflush(fd, TCIFLUSH);
+			tcsetattr(fd,TCSANOW,&tio);
+
+			write(fd, txStr, strlen(txStr));
+
+			sleep(1); /* one second sleep to avoid		device 'choking' */
+			close(fd); /* Modified : Close fd to make a clean exit */
+		} else {
+#ifdef LIBFTDI
+			usbWriteFtdi( txStr );
+#else
+			fprintf(stderr,  "%s - Support for libftdi is not compiled in, please recompile rfcmd with support for libftdi\n", PROG_NAME);
+#endif
+		}
+#ifndef NO_SEMAPHORES
+		/* Unlock semaphore */
+		if (sem_post(portMutex) != 0) {
+			fprintf(stderr,  "%s - Error releasing port semaphore\n", PROG_NAME);
+			sem_unlink(SEM_NAME);
+			sem_close(portMutex);
+			exit(1);
+		} else {
+			sem_unlink(SEM_NAME);
+			sem_close(portMutex);	
+		}
+#endif
+	}
+  exit(0);
+}
+
+
+int createNexaString(const char * pHouseStr, const char * pChannelStr,
+                     const char * pOn_offStr, char * pTxStr, int waveman)
+{
+	* pTxStr = '\0'; /* Make sure tx string is empty */
+	int houseCode;
+	int channelCode;
+	int on_offCode;
+	int txCode = 0;
+	const int unknownCode =  0x6;
+	int bit;
+	int bitmask = 0x0001;
+
+	houseCode = (int)((* pHouseStr) - 65);	/* House 'A'..'P' */
+	channelCode = atoi(pChannelStr) - 1;	/* Channel 1..16 */
+	on_offCode =  atoi(pOn_offStr);	        /* ON/OFF 0..1 */
+
+#ifdef RFCMD_DEBUG
+	printf("House: %d, channel: %d, on_off: %d\n", houseCode, channelCode, on_offCode);
+#endif
+
+	/* check converted parameters for validity */
+	if((houseCode < 0) || (houseCode > 15) ||      // House 'A'..'P'
+	   (channelCode < 0) || (channelCode > 15) ||
+	   (on_offCode < 0) || (on_offCode > 1))
+	{
+
+	} else {
+		/* b0..b11 txCode where 'X' will be represented by 1 for simplicity.
+		   b0 will be sent first */
+		txCode = houseCode;
+		txCode |= (channelCode <<  4);
+		if (waveman && on_offCode == 0) {
+		} else {
+			txCode |= (unknownCode <<  8);
+			txCode |= (on_offCode  << 11);
+		}
+
+		/* convert to send cmd string */
+		strcat(pTxStr,"S");
+		for(bit=0;bit<12;bit++)
+		{
+			if((bitmask & txCode) == 0) {
+				/* bit timing might need further refinement */
+				strcat(pTxStr," ` `"); /* 320 us high, 960 us low,  320 us high, 960 us low */
+				/* strcat(pTxStr,"$k$k"); *//* 360 us high, 1070 us low,  360 us high, 1070 us low */
+			} else { /* add 'X' (floating bit) */
+				strcat(pTxStr," `` "); /* 320 us high, 960 us low, 960 us high,  320 us low */
+				/*strcat(pTxStr,"$kk$"); *//* 360 us high, 1070 us low, 1070 us high,  360 us low */
+			}
+			bitmask = bitmask<<1;
+		}
+		/* add stop/sync bit and command termination char '+'*/
+		strcat(pTxStr," }+");
+		/* strcat(pTxStr,"$}+"); */
+	}
+
+#ifdef RFCMD_DEBUG
+	printf("txCode: %04X\n", txCode);
+#endif
+
+	return strlen(pTxStr);
+}
+
+int createSartanoString(const char * pChannelStr, const char * pOn_offStr,
+                        char * pTxStr)
+{
+	* pTxStr = '\0'; /* Make sure tx string is empty */
+	int on_offCode;
+	int bit;
+
+	on_offCode =  atoi(pOn_offStr);	        /* ON/OFF 0..1 */
+
+#ifdef RFCMD_DEBUG
+	printf("Channel: %s, on_off: %d\n", pChannelStr, on_offCode);
+#endif
+
+	/* check converted parameters for validity */
+	if((strlen(pChannelStr) != 10) ||
+	   (on_offCode < 0) || (on_offCode > 1)) {
+	} else {
+		strcat(pTxStr,"S");
+		for(bit=0;bit<=9;bit++)
+		{
+			if(strncmp(pChannelStr+bit, "1", 1) == 0) { //If it is a "1"
+				strcat(pTxStr,"$k$k");
+			} else {
+				strcat(pTxStr,"$kk$");
+	    }
+		}
+		if (on_offCode >= 1)
+			strcat(pTxStr,"$k$k$kk$"); //the "turn on"-code
+		else
+			strcat(pTxStr,"$kk$$k$k"); //the "turn off"-code
+
+		/* add stop/sync bit and command termination char '+'*/
+		strcat(pTxStr,"$k+");
+	}
+
+	return strlen(pTxStr);
+}
+
+int createIkeaString( const char * pSystemStr, const char * pChannelStr, const char * pLevelStr, const char *pDimStyle, char * pStrReturn)
+{
+	*pStrReturn = '\0'; /* Make sure tx string is empty */
+
+	const char STARTCODE[] = "STTTTTTª";
+	const char TT[]  = "TT";
+	const char A[]   = "ª";
+	int systemCode   = atoi(pSystemStr) - 1;   /* System 1..16 */
+	int channelCode  = atoi(pChannelStr);  /* Channel 1..10 */
+	int Level        = atoi(pLevelStr);     /* off,10,20,..,90,on */
+	int DimStyle     = atoi(pDimStyle);
+	int intCode      = 0;
+	int checksum1    = 0;
+	int checksum2    = 0;
+	int intFade ;
+	int i ;
+	int rawChannelCode = 0;
+
+	/* check converted parameters for validity */
+	if ( (channelCode <= 0) || (channelCode > 10) ||
+	     (systemCode < 0) || (systemCode > 15) ||
+	     (Level < 0) || (Level > 10) ||
+	     (DimStyle < 0) || (DimStyle > 1))
+	{
+		return 0;
+	}
+
+	if (channelCode == 10) {
+		channelCode = 0;
+	}
+	rawChannelCode = (1<<(9-channelCode));
+
+	strcat(pStrReturn, STARTCODE ) ; //Startcode, always like this;
+	intCode = (systemCode << 10) | rawChannelCode;
+
+	for ( i = 13; i >= 0; --i) {
+		if ((intCode>>i) & 1) {
+			strcat(pStrReturn, TT );
+			if (i % 2 == 0) {
+				checksum2++;
+			} else {
+				checksum1++;
+			}
+		} else {
+			strcat(pStrReturn,A);
+		}
+	}
+
+	if (checksum1 %2 == 0) {
+		strcat(pStrReturn, TT );
+	} else {
+		strcat(pStrReturn, A) ; //1st checksum
+	}
+
+	if (checksum2 %2 == 0) {
+		strcat(pStrReturn, TT );
+	} else {
+		strcat(pStrReturn, A ) ; //2nd checksum
+	}
+
+	if (DimStyle == 1) {
+		intFade = 11 << 4; //Smooth
+	} else {
+		intFade = 1 << 4; //Instant
+	}
+
+	switch ( Level )
+	{
+		case 0 :
+			intCode = (10 | intFade) ; //Concat level and fade
+			break;
+		case 1 :
+			intCode = (1 | intFade) ; //Concat level and fade
+			break;
+		case 2 :
+			intCode = (2 | intFade) ; //Concat level and fade
+			break;
+		case 3 :
+			intCode = (3 | intFade) ; //Concat level and fade
+			break;
+		case 4 :
+			intCode = (4 | intFade) ; //Concat level and fade
+			break;
+		case 5 :
+			intCode = (5 | intFade) ; //Concat level and fade
+			break;
+		case 6 :
+			intCode = (6 | intFade) ; //Concat level and fade
+			break;
+		case 7 :
+			intCode = (7 | intFade) ; //Concat level and fade
+			break;
+		case 8 :
+			intCode = (8 | intFade) ; //Concat level and fade
+			break;
+		case 9 :
+			intCode = (9 | intFade) ; //Concat level and fade
+			break;
+		case 10 :
+		default :
+			intCode = (0 | intFade) ; //Concat level and fade
+			break;
+	}
+
+	checksum1 = 0;
+	checksum2 = 0;
+
+	for (i = 0; i < 6; ++i) {
+		if ((intCode>>i) & 1) {
+			strcat(pStrReturn, TT);
+
+			if (i % 2 == 0) {
+				checksum1++;
+			} else {
+				checksum2++;
+			}
+		} else {
+			strcat(pStrReturn, A );
+		}
+	}
+
+	if (checksum1 %2 == 0) {
+		strcat(pStrReturn, TT);
+	} else {
+		strcat(pStrReturn, A ) ; //2nd checksum
+	}
+
+	if (checksum2 %2 == 0) {
+		strcat(pStrReturn, TT );
+	} else {
+		strcat(pStrReturn, A ) ; //2nd checksum
+	}
+
+	strcat(pStrReturn, "+");
+
+	return strlen(pStrReturn);
+}
+
+int createRisingSunString(const char * pCodeStr, const char * pUnitStr, const char * pOn_offStr,
+                        char * pTxStr)
+{
+	* pTxStr = '\0'; /* Make sure tx string is empty */
+	int on_offCode;
+	int unit;
+	int code;
+	int i;
+
+	on_offCode =  atoi(pOn_offStr);	        /* ON/OFF 0..1 */
+	code = atoi (pCodeStr);
+	unit = atoi (pUnitStr);
+
+#ifdef RFCMD_DEBUG
+	printf("Code: %s, unit: %s, on_off: %d\n", pCodeStr, pUnitStr, on_offCode);
+#endif
+
+	/* check converted parameters for validity */
+	if((code < 1) || (code > 4) ||
+	   (unit < 1) || (unit > 4) ||
+	   (on_offCode < 0) || (on_offCode > 1)) {
+	} else {
+		strcat(pTxStr,"S.e");
+		for (i = 1; i <= 4; ++i) {
+			if (i == code) {
+				strcat (pTxStr, ".e.e");
+			} else {
+				strcat (pTxStr, "e..e");
+			}
+		}
+		for (i = 1; i <= 4; ++i) {
+			if (i == unit) {
+				strcat (pTxStr, ".e.e");
+			} else {
+				strcat (pTxStr, "e..e");
+			}
+		}
+
+		if (on_offCode >= 1) {
+			strcat(pTxStr,"e..ee..ee..ee..e+"); //the "turn on"-code
+		} else {
+			strcat(pTxStr,"e..ee..ee..e.e.e+"); //the "turn off"-code
+		}
+	}
+
+	return strlen(pTxStr);
+}
+
+unsigned int everflourish_find_code(unsigned int x) {
+	unsigned int bits[16] = { 0xf ,0xa ,0x7 ,0xe,
+	                          0xf ,0xd ,0x9 ,0x1,
+	                          0x1 ,0x2 ,0x4 ,0x8,
+	                          0x3 ,0x6 ,0xc ,0xb };
+	unsigned int bit = 1;
+	unsigned int res = 0x5;
+	int i;
+	unsigned int lo,hi;
+
+	if ((x&0x3)==3) {
+		lo = x & 0x00ff;
+		hi = x & 0xff00;
+		lo += 4;
+		if (lo>0x100) lo = 0x12;
+		x = lo | hi;
+	}
+
+	for(i=0;i<16;i++) {
+		if (x&bit) {
+			res = res ^ bits[i];
+		}
+		bit = bit << 1;
+	}
+
+	return res;
+}
+
+
+int createEverFlourishString(const char * pUnitStr, const char * pLevelStr,
+                        char * pTxStr)
+{
+	int len = 0;
+	int level;
+	int unit;
+	unsigned int check;
+	int i;
+
+	unit = atoi(pUnitStr);
+	level = atoi(pLevelStr);                /* ON=15, OFF=0, LEARN=10 */
+	check = everflourish_find_code(unit);
+
+#ifdef RFCMD_DEBUG
+   printf("unit: %d, level: %d\n", unit, level);
+#endif
+
+	/* check converted parameters for validity */
+	if((unit < 0) || (unit > 0xffff) ||
+	  (level < 0) || (level > 15)) {
+	} else {
+		const char ssss = 85;
+		const char sssl = 84; // 0
+		const char slss = 69; // 1
+
+		const char bits[2] = {sssl,slss};
+		int i;
+
+		char preamble[] = {'R', 5, 'T', 114,60,1,1,105,ssss,ssss};
+		memcpy(pTxStr, preamble, sizeof(preamble));
+		len += sizeof(preamble);
+
+		for(i=15;i>=0;i--) pTxStr[len++]=bits[(unit>>i)&0x01];
+		for(i=3;i>=0;i--) pTxStr[len++]=bits[(check>>i)&0x01];
+		for(i=3;i>=0;i--) pTxStr[len++]=bits[(level>>i)&0x01];
+
+		pTxStr[len++] = ssss;
+		pTxStr[len++] = '+';
+	}
+
+	pTxStr[len] = '\0';
+	return strlen(pTxStr);
+}
+
+void printUsage(void)
+{
+	printf("Usage: rfcmd DEVICE PROTOCOL [PROTOCOL_ARGUMENTS] \n");
+	printf("\n");
+#ifdef LIBFTDI
+	printf("\t DEVICE: /dev/ttyUSB[0..n] | LIBUSB\n" );
+#else
+	printf("\t DEVICE: /dev/ttyUSB[0..n]\n" );
+#endif
+	printf("\t PROTOCOLS: NEXA, SARTANO, WAVEMAN, IKEA, RISINGSUN, EVERFLOURISH\n" );
+	printf("\n");
+	printf("\t PROTOCOL ARGUMENTS - NEXA, WAVEMAN:\n");
+	printf("\t\tHOUSE_CODE: A..P\n\t\tCHANNEL: 1..16\n\t\tOFF_ON: 0..1\n" );
+	printf("\n");
+	printf("\t PROTOCOL ARGUMENTS - SARTANO:\n");
+	printf("\t\tCHANNEL: 0000000000..1111111111\n\t\tOFF_ON: 0..1\n" );
+	printf("\n");
+	printf("\t PROTOCOL ARGUMENTS - IKEA:\n");
+	printf("\t\tSYSTEM: 1..16\n\t\tDEVICE: 1..10\n");
+	printf("\t\tDIM_LEVEL: 0..10\n\t\tDIM_STYLE: 0..1\n" );
+	printf("\n");
+	printf("\t PROTOCOL ARGUMENTS - RISINGSUN:\n");
+	printf("\t\tCODE: 1..4\n\t\tDEVICE: 1..4\n");
+	printf("\t\tOFF_ON: 0..1\n" );
+	printf("\n");
+	printf("\t PROTOCOL ARGUMENTS - EVERFLOURISH:\n");
+	printf("\t\tDEVICE: 0..65535\n");
+	printf("\t\tLEVEL: 0=off, 10=learn, 15=on\n" );
+	printf("\n");
+	printf("Report bugs to \n");
+}
+
+void printVersion(void) {
+	printf("%s v%s\n", PROG_NAME, PROG_VERSION);
+	printf("\n");
+	printf("Copyright (C) Tord Andersson 2007\n");
+	printf("\n");
+	printf("Written by:\n");
+	printf("Tord Andersson, Micke Prag, Gudmund Berggren, Tapani Rintala\n");
+	printf("and Johan Ström\n");
+}
+
diff --git a/systray/src/SysTray_sv.ts b/systray/src/SysTray_sv.ts
deleted file mode 100644
index 5767f648..00000000
--- a/systray/src/SysTray_sv.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-    Icon
-    
-        
-        TellStick
-        TellStick
-    
-    
-        
-        &On
-        &PÃ¥
-    
-    
-        
-        O&ff
-        &Av
-    
-    
-        
-        &Configure devices
-        &Konfigurera enheter
-    
-    
-        
-        &Quit
-        &Avsluta
-    
-    
-        
-        Error
-        Fel
-    
-    
-        
-        An error occurred while trying to transmit
-        Ett fel uppstod vid försök att sända
-    
-
-
diff --git a/systray/src/icon.cpp b/systray/src/icon.cpp
deleted file mode 100644
index ae25de6a..00000000
--- a/systray/src/icon.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-//
-// C++ Implementation: icon
-//
-// Description:
-//
-//
-// Author: Micke Prag , (C) 2007
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-#include "icon.h"
-#include 
-#include 
-#include 
-#include 
-#include "telldus-core.h"
-
-Icon::Icon()
- : QObject()
-{
-	this->setMenu();
- 	connect( &i, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(activated(QSystemTrayIcon::ActivationReason)));
-	i.setIcon( QIcon(":/images/lamp-on.png") );
-	i.setToolTip( tr("TellStick") );
-	i.show();
-}
-
-
-Icon::~Icon()
-{
-}
-
-
-/**
- * @fn Icon::activated( QSystemTrayIcon::ActivationReason reason )
- */
-void Icon::activated( QSystemTrayIcon::ActivationReason reason )
-{
-	if (reason == QSystemTrayIcon::DoubleClick) {
-		if (hasTelldusSetup()) {
-			configure();
-		}
-	}
-}
-
-/**
- * @fn Icon::bell()
- */
-void Icon::bell()
-{
-	QAction *action = (QAction *) sender();
-	int retval = tdBell( action->data().toInt() );
-	if (retval != TELLSTICK_SUCCESS) {
-		char *errorString = tdGetErrorString( retval );
-		i.showMessage( tr("Error"), tr("An error occurred while trying to transmit!\n\n%1").arg(errorString), QSystemTrayIcon::Critical );
-		free( errorString );
-	}
-}
-
-/**
- * @fn Icon::dim()
- */
-void Icon::dim()
-{
-	QAction *action = (QAction *) sender();
-	int intId = action->data().toString().section(":", 0, 0).toInt();
-	int intLevel = action->data().toString().section(":", 1, 1).toInt();
-	//i.showMessage( "", QString::number(intId));
-	int retval = tdDim( intId, intLevel );
-	if (retval != TELLSTICK_SUCCESS) {
-		char *errorString = tdGetErrorString( retval );
-		i.showMessage( tr("Error"), tr("An error occurred while trying to transmit!\n\n%1").arg(errorString), QSystemTrayIcon::Critical );
-		free( errorString );
-	}
-}
-
-/**
- * @fn Icon::on()
- */
-void Icon::on()
-{
-	QAction *action = (QAction *) sender();
-	int retval = tdTurnOn( action->data().toInt() );
-	if (retval != TELLSTICK_SUCCESS) {
-		char *errorString = tdGetErrorString( retval );
-		i.showMessage( tr("Error"), tr("An error occurred while trying to transmit!\n\n%1").arg(errorString), QSystemTrayIcon::Critical );
-		free( errorString );
-	}
-}
-
-/**
- * @fn Icon::off()
- */
-void Icon::off()
-{
-	QAction *action = (QAction *) sender();
-	int retval = tdTurnOff( action->data().toInt() );
-	if (retval != TELLSTICK_SUCCESS) {
-		char *errorString = tdGetErrorString( retval );
-		i.showMessage( tr("Error"), tr("An error occurred while trying to transmit!\n\n%1").arg(errorString), QSystemTrayIcon::Critical );
-		free( errorString );
-	}
-}
-
-
-/**
- * @fn Icon::configure()
- */
-void Icon::configure()
-{
-	QProcess *process = new QProcess(this);
-	connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(setMenu()));
-	process->setWorkingDirectory(QCoreApplication::applicationDirPath());
-	process->start("TelldusSetup.exe");
-}
-
-
-/**
- * @fn Icon::setMenu()
- */
-void Icon::setMenu()
-{
-	menu.clear();
-
-	int intNum = tdGetNumberOfDevices();
-	int index = 0;
-	while (index < intNum) {
-		addDevice(index, &menu);
-		index++;
-	}
-
-	menu.addSeparator();
-
-	if (hasTelldusSetup()) {
-		QAction *configure = menu.addAction(tr("&Configure devices"));
-		connect(configure, SIGNAL(triggered()), this, SLOT(configure()));
-		configure->setIcon( QIcon(":/images/preferences-system.png") );
-	}
-
-	QAction *quit = menu.addAction(tr("&Quit"));
-	quit->setIcon( QIcon(":/images/system-log-out.png") );
-	connect(quit, SIGNAL(triggered()), qApp, SLOT(quit()));
-
-	i.setContextMenu(&menu);
-
-}
-
-void Icon::addDevice( int index, QMenu *menu ) {
-	int intId = tdGetDeviceId(index);
-	QMenu *m = menu->addMenu( tdGetName(intId) );
-
-	int methods = tdMethods(intId);
-	if (methods & TELLSTICK_TURNON) {
-		QAction *on = m->addAction(tr("&On"));
-		on->setIcon(QIcon(":/images/lamp-on.png"));
-		on->setData( intId );
-		connect( on, SIGNAL(triggered()), this, SLOT(on()));
-	}
-
-	if (methods & TELLSTICK_DIM) {
-		QAction *dim = m->addAction(tr("90%"));
-		dim->setData( QString("%1:230").arg(intId) );
-		connect( dim, SIGNAL(triggered()), this, SLOT(dim()));
-		
-		dim = m->addAction(tr("80%"));
-		dim->setData( QString("%1:204").arg(intId) );
-		connect( dim, SIGNAL(triggered()), this, SLOT(dim()));
-
-		dim = m->addAction(tr("70%"));
-		dim->setData( QString("%1:179").arg(intId) );
-		connect( dim, SIGNAL(triggered()), this, SLOT(dim()));
-
-		dim = m->addAction(tr("60%"));
-		dim->setData( QString("%1:153").arg(intId) );
-		connect( dim, SIGNAL(triggered()), this, SLOT(dim()));
-
-		dim = m->addAction(tr("50%"));
-		dim->setData( QString("%1:128").arg(intId) );
-		connect( dim, SIGNAL(triggered()), this, SLOT(dim()));
-
-		dim = m->addAction(tr("40%"));
-		dim->setData( QString("%1:102").arg(intId) );
-		connect( dim, SIGNAL(triggered()), this, SLOT(dim()));
-
-		dim = m->addAction(tr("30%"));
-		dim->setData( QString("%1:77").arg(intId) );
-		connect( dim, SIGNAL(triggered()), this, SLOT(dim()));
-
-		dim = m->addAction(tr("20%"));
-		dim->setData( QString("%1:51").arg(intId) );
-		connect( dim, SIGNAL(triggered()), this, SLOT(dim()));
-
-		dim = m->addAction(tr("10%"));
-		dim->setData( QString("%1:25").arg(intId) );
-		connect( dim, SIGNAL(triggered()), this, SLOT(dim()));
-	}
-
-	if (methods & TELLSTICK_TURNON) {
-		QAction *off = m->addAction(tr("O&ff"));
-		off->setData( intId );
-		off->setIcon(QIcon(":/images/lamp-off.png"));
-		connect( off, SIGNAL(triggered()), this, SLOT(off()));
-	}
-	
-	if (methods & TELLSTICK_BELL) {
-		QAction *bell = m->addAction(tr("&Bell"));
-		bell->setData( intId );
-		bell->setIcon(QIcon(":/images/bell.png"));
-		connect( bell, SIGNAL(triggered()), this, SLOT(bell()));
-	}
-}
-
-bool Icon::hasTelldusSetup() {
-	return QFile::exists("TelldusSetup.exe");
-}
diff --git a/systray/src/icon.h b/systray/src/icon.h
deleted file mode 100644
index 68243342..00000000
--- a/systray/src/icon.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// C++ Interface: icon
-//
-// Description:
-//
-//
-// Author: Micke Prag , (C) 2007
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-#ifndef ICON_H
-#define ICON_H
-
-#include 
-#include 
-
-/**
-	@author Micke Prag 
-*/
-class Icon : public QObject
-{
-	Q_OBJECT
-public:
-	Icon();
-
-	~Icon();
-
-protected:
-	QSystemTrayIcon i;
-	QMenu menu;
-
-protected slots:
-	void activated( QSystemTrayIcon::ActivationReason reason );
-	void setMenu();
-	
-private slots:
-	void bell();
-	void dim();
-	void on();
-	void off();
-	
-public slots:
-	void configure();
-
-private:
-	void addDevice( int index, QMenu *menu );
-	static bool hasTelldusSetup();
-};
-
-#endif
diff --git a/systray/src/images/bell.png b/systray/src/images/bell.png
deleted file mode 100644
index 78765980..00000000
Binary files a/systray/src/images/bell.png and /dev/null differ
diff --git a/systray/src/images/lamp-off.png b/systray/src/images/lamp-off.png
deleted file mode 100644
index 007a1778..00000000
Binary files a/systray/src/images/lamp-off.png and /dev/null differ
diff --git a/systray/src/images/lamp-on.png b/systray/src/images/lamp-on.png
deleted file mode 100644
index 5bc874dd..00000000
Binary files a/systray/src/images/lamp-on.png and /dev/null differ
diff --git a/systray/src/images/preferences-system.png b/systray/src/images/preferences-system.png
deleted file mode 100644
index 6e52db7c..00000000
Binary files a/systray/src/images/preferences-system.png and /dev/null differ
diff --git a/systray/src/images/system-log-out.png b/systray/src/images/system-log-out.png
deleted file mode 100644
index fddbc2bc..00000000
Binary files a/systray/src/images/system-log-out.png and /dev/null differ
diff --git a/systray/src/images/systray.icns b/systray/src/images/systray.icns
deleted file mode 100644
index 7cfe1d77..00000000
Binary files a/systray/src/images/systray.icns and /dev/null differ
diff --git a/systray/src/images/systray.ico b/systray/src/images/systray.ico
deleted file mode 100644
index 9aeccbdc..00000000
Binary files a/systray/src/images/systray.ico and /dev/null differ
diff --git a/systray/src/main.cpp b/systray/src/main.cpp
deleted file mode 100644
index 295fc7c2..00000000
--- a/systray/src/main.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2006 by Micke Prag   *
- *   micke.prag@telldus.se   *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
- ***************************************************************************/
-
-
-#include 
-#include 
-#include 
-#include "icon.h"
-
-int main(int argc, char *argv[])
-{
-  QApplication a( argc, argv );
-
-  QCoreApplication::setOrganizationName("Telldus");
-  QCoreApplication::setOrganizationDomain("telldus.se");
-  QCoreApplication::setApplicationName("SysTray");
-
-  Q_INIT_RESOURCE(resource);
-  
-  QTranslator qtTranslator;
-	qtTranslator.load("qt_" + QLocale::system().name());
-	a.installTranslator(&qtTranslator);
-
-	QTranslator myappTranslator;
-	myappTranslator.load("SysTray_" + QLocale::system().name());
-	a.installTranslator(&myappTranslator);
-
-	Icon icon;
-  return a.exec();
-}
diff --git a/systray/src/resource.qrc b/systray/src/resource.qrc
deleted file mode 100644
index 325beebe..00000000
--- a/systray/src/resource.qrc
+++ /dev/null
@@ -1,9 +0,0 @@
-
-	
-		images/bell.png
-		images/lamp-on.png
-		images/lamp-off.png
-		images/preferences-system.png
-		images/system-log-out.png
-	
-
diff --git a/systray/src/src.pro b/systray/src/src.pro
deleted file mode 100644
index 2bfbc4cf..00000000
--- a/systray/src/src.pro
+++ /dev/null
@@ -1,23 +0,0 @@
-TEMPLATE = app
-
-SOURCES += main.cpp \
-icon.cpp
-
-!macx:LIBS += -ltelldus-core -L../bin
-macx{
-    LIBS += -framework telldus-core
-    ICON = images/systray.icns
-}
-win32{
-    TARGET = ../../bin/SysTray
-    CONFIG += release
-}
-unix{
-    TARGET = ../bin/systray
-    CONFIG += debug
-}
-HEADERS += icon.h
-#menu.h
-RESOURCES += resource.qrc
-RC_FILE = systray.rc
-TRANSLATIONS = SysTray_sv.ts
diff --git a/systray/src/systray.rc b/systray/src/systray.rc
deleted file mode 100644
index 3d90079c..00000000
--- a/systray/src/systray.rc
+++ /dev/null
@@ -1 +0,0 @@
-IDI_ICON1 ICON DISCARDABLE "images/systray.ico"
diff --git a/systray/systray.pro b/systray/systray.pro
deleted file mode 100644
index b2d719f0..00000000
--- a/systray/systray.pro
+++ /dev/null
@@ -1,4 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS = src
-CONFIG += warn_on
-
diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp
index d167a72d..2447a43e 100644
--- a/telldus-core/client/CallbackDispatcher.cpp
+++ b/telldus-core/client/CallbackDispatcher.cpp
@@ -8,6 +8,7 @@
  */
 
 #include "CallbackDispatcher.h"
+#include "common.h"
 
 using namespace TelldusCore;
 
@@ -28,7 +29,9 @@ bool TDDeviceEventDispatcher::done() const {
 }
 
 void TDDeviceEventDispatcher::run() {
+	char *str = wrapStdString(strData);
 	d->event(deviceId, method, strData.c_str(), d->id, d->context);
+
 	doneRunning = true;
 }
 
diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp
index c93bf37a..94845688 100644
--- a/telldus-core/client/Client.cpp
+++ b/telldus-core/client/Client.cpp
@@ -114,6 +114,9 @@ bool Client::getBoolFromService(const Message &msg) {
 
 int Client::getIntegerFromService(const Message &msg) {
 	std::wstring response = sendToService(msg);
+	if (response.compare(L"") == 0) {
+		return TELLSTICK_ERROR_COMMUNICATING_SERVICE;
+	}
 	return Message::takeInt(&response);
 }
 
@@ -181,7 +184,8 @@ void Client::run(){
 			}
 		}
 
-		std::wstring clientMessage = d->eventSocket.read(5000);	//testing 5 second timeout
+		std::wstring clientMessage = d->eventSocket.read(1000);	//testing 5 second timeout
+
 		while(clientMessage != L""){
 			//a message arrived
 			std::wstring type = Message::takeString(&clientMessage);
@@ -282,16 +286,46 @@ void Client::cleanupCallbacks() {
 }
 
 std::wstring Client::sendToService(const Message &msg) {
-	Socket s;
-	s.connect(L"TelldusClient");
-	if (!s.isConnected()) { //Connection failed
-		TelldusCore::Message msg;
-		msg.addArgument(TELLSTICK_ERROR_CONNECTING_SERVICE);
-		return msg;
+	
+	int tries = 0;
+	std::wstring readData;
+	while(tries < 20){
+		tries++;
+		if(tries == 20){
+			TelldusCore::Message msg;
+			msg.addArgument(TELLSTICK_ERROR_CONNECTING_SERVICE);
+			return msg;
+		}
+		Socket s;
+		s.connect(L"TelldusClient");
+		if (!s.isConnected()) { //Connection failed
+			printf("Connection failed\n\r");
+			msleep(500);
+			continue; //retry
+		}
+		s.write(msg.data());
+		if (!s.isConnected()) { //Connection failed sometime during operation... (better check here, instead of 5 seconds timeout later)
+			printf("Connection failed after write\n\r");
+			msleep(500);
+			continue; //retry
+		}
+		readData = s.read(8000);  //TODO changed to 10000 from 5000, how much does this do...?
+		if(readData == L""){
+			printf("Readdata nothing\n\r");
+			msleep(500);
+			continue; //TODO can we be really sure it SHOULD be anything?
+			//TODO perhaps break here instead?
+		}
+		
+		if (!s.isConnected()) { //Connection failed sometime during operation...
+			printf("Connection failed in the end\n\r");
+			msleep(500);
+			continue; //retry
+		}
+		break;
 	}
-	s.write(msg.data());
 
-	return s.read(5000);
+	return readData;
 }
 
 void Client::stopThread(){
diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp
index d859701a..88fa6a8d 100644
--- a/telldus-core/client/telldus-core.cpp
+++ b/telldus-core/client/telldus-core.cpp
@@ -57,6 +57,9 @@ using namespace TelldusCore;
  * @def TELLSTICK_SUCCESS
  * Error code. Returned when the command succeeded.
  *
+ * @def TELLSTICK_ERROR_BROKEN_PIPE
+ * Error code. Pipe broken during communication.
+ *
  * @def TELLSTICK_ERROR_NOT_FOUND
  * Error code. Returned if a TellStick was not found on the system.
  *
@@ -82,6 +85,13 @@ using namespace TelldusCore;
  * Error code. The client library received a response from the service
  * it did not understand.
  *
+ * @def TELLSTICK_ERROR_SYNTAX
+ * Error code. Input/command could not be parsed or didn't follow
+ * input rules.
+ *
+ * @def TELLSTICK_ERROR_COMMUNICATING_SERVICE
+ * Error code. Timeout waiting for response from the Telldus Service.
+ *
  * @def TELLSTICK_ERROR_UNKNOWN
  * Error code. An unkown error has occurred.
  */
@@ -479,10 +489,16 @@ int WINAPI tdMethods(int id, int methodsSupported){
  * @sa TELLSTICK_ERROR_PERMISSION_DENIED
  * @sa TELLSTICK_ERROR_DEVICE_NOT_FOUND
  * @sa TELLSTICK_ERROR_METHOD_NOT_SUPPORTED
+ * @sa TELLSTICK_ERROR_COMMUNICATION
+ * @sa TELLSTICK_ERROR_CONNECTING_SERVICE
+ * @sa TELLSTICK_ERROR_UNKNOWN_RESPONSE
+ * @sa TELLSTICK_ERROR_SYNTAX
+ * @sa TELLSTICK_ERROR_BROKEN_PIPE
+ * @sa TELLSTICK_ERROR_COMMUNICATING_SERVICE
  * @sa TELLSTICK_ERROR_UNKNOWN
  */
 char * WINAPI tdGetErrorString(int intErrorNo) {
-	const int numResponses = 8;
+	const int numResponses = 10;
 	const char *responses[numResponses] = {
 		"Success",
 		"TellStick not found",
@@ -491,7 +507,10 @@ char * WINAPI tdGetErrorString(int intErrorNo) {
 		"The method you tried to use is not supported by the device",
 		"An error occurred while communicating with TellStick",
 		"Could not connect to the Telldus Service",
-		"Received an unknown response"
+		"Received an unknown response",
+		"Syntax error",
+		"Broken pipe"
+		"An error occured while communicating with the Telldus Service"
 	};
 	std::string strReturn;
 	intErrorNo = abs(intErrorNo); //We don't use negative values here.
@@ -511,8 +530,12 @@ char * WINAPI tdGetErrorString(int intErrorNo) {
  * @returns TELLSTICK_SUCCESS on success or one of the errorcodes on failure
  */
 int WINAPI tdSendRawCommand(const char *command, int reserved) {
+	std::wstring wcommand;
+	for(int i = 0; i < strlen(command);++i) {
+		wcommand.append(1, (unsigned char)command[i]);
+	}
 	Message msg(L"tdSendRawCommand");
-	msg.addArgument(command);
+	msg.addArgument(wcommand);
 	msg.addArgument(reserved);
 	return Client::getIntegerFromService(msg);
 }
@@ -534,11 +557,36 @@ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial
 	Client::getWStringFromService(msg);
 }
 
+/**
+ * Use this function to iterate over all sensors. Iterate until
+ * TELLSTICK_SUCCESS is not returned
+ * @param protocol A byref string where the protocol of the sensor will be placed
+ * @param protocolLen The length of the \c protocol parameter
+ * @param model A byref string where the model of the sensor will be placed
+ * @param modelLen The length of the \c model parameter
+ * @param id A byref int where the id of the sensor will be placed
+ * @param dataTypes A byref int with flags for the supported sensor values
+ * @returns TELLSTICK_SUCCESS if there is more sensors to be fetched
+ */
 int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes) {
 	Client *client = Client::getInstance();
 	return client->getSensor(protocol, protocolLen, model, modelLen, id, dataTypes);
 }
 
+/**
+ * Get one of the supported sensor values from a sensor. Make sure it support
+ * the value type first by calling tdSensor(). The triplet \c protocol,
+ * \c model, and \c id together identifies a sensor.
+ * @param protocol The protocol for the sensor
+ * @param model The model for the sensor
+ * @param id The id of the sensor
+ * @param dataType One of the datatype to retrieve
+ * @param value A byref string where the value will be places
+ * @param len The length of the \c value parameter
+ * @param timestamp A byref int where the timestamp of the value will be placed
+ * @returns TELLSTICK_SUCCESS if the value could be fetched or one of the
+ * errorcodes on failure
+ */
 int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp) {
 	Message msg(L"tdSensorValue");
 	msg.addArgument(protocol);
@@ -562,4 +610,4 @@ int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int da
 }
 
 
-/*\@}*/
+/* @} */
diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h
index 1f25e0f3..87eb6132 100644
--- a/telldus-core/client/telldus-core.h
+++ b/telldus-core/client/telldus-core.h
@@ -115,6 +115,9 @@ extern "C" {
 #define TELLSTICK_ERROR_COMMUNICATION -5
 #define TELLSTICK_ERROR_CONNECTING_SERVICE -6
 #define TELLSTICK_ERROR_UNKNOWN_RESPONSE -7
+#define TELLSTICK_ERROR_SYNTAX -8
+#define TELLSTICK_ERROR_BROKEN_PIPE -9
+#define TELLSTICK_ERROR_COMMUNICATING_SERVICE -10
 #define TELLSTICK_ERROR_UNKNOWN -99
 
 //Device typedef
diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp
index 56504d9e..f2820021 100644
--- a/telldus-core/common/Message.cpp
+++ b/telldus-core/common/Message.cpp
@@ -23,21 +23,70 @@ Message::~Message(void) {
 }
 
 void Message::addArgument(const std::wstring &value) {
-	std::wstringstream st;
-	st << (int)value.size();
-	this->append(st.str());
+	//std::wstringstream st;
+	//st << (int)value.size();
+	this->append(TelldusCore::intToWstring(value.size())); //st.str());
 	this->append(L":");
 	this->append(value);
 }
 
 void Message::addArgument(int value) {
-	std::wstringstream st;
-	st << (int)value;
+	//std::wstringstream st;
+	//st << (int)value;
 	this->append(L"i");
-	this->append(st.str());
+	this->append(TelldusCore::intToWstring(value)); // st.str());
 	this->append(L"s");
 }
 
+/*
+void Message::addSpecialArgument(const std::wstring &value){
+	int i = 0;
+	while(i<1000000){
+		i++;
+
+		char numstr[21]; // enough to hold all numbers up to 64-bits
+		//sprintf(numstr, "%d", value.size());
+		//this->append(TelldusCore::charToWstring(numstr)); //.str());
+
+		itoa(value.size(), numstr, 10);
+		std::string test(numstr);
+		std::wstring temp(test.length(), L' ');
+		std::copy(test.begin(), test.end(), temp.begin());
+
+		this->append(temp);
+		this->append(L":");
+		this->append(value);
+
+		/*
+		std::wstringstream st;
+		st << (int)value.size();
+		this->append(st.str());
+		this->append(L":");
+		this->append(value);
+		
+	}
+}
+
+void Message::addSpecialArgument(int value){
+	int i = 0;
+	while(i<1000000){
+		i++;
+		/*
+		//std::wstringstream st;
+		//st << (int)value;
+		this->append(L"i");
+		//this->append(st.str());
+		this->append(L"s");
+		
+	}
+}
+*/
+/*
+void Message::addSpecialArgument(const char *value){
+	this->addSpecialArgument(TelldusCore::charToWstring(value));
+}
+*/
+
 void Message::addArgument(const char *value) {
 	this->addArgument(TelldusCore::charToWstring(value));
 }
diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h
index cf63251d..4b13123b 100644
--- a/telldus-core/common/Message.h
+++ b/telldus-core/common/Message.h
@@ -11,6 +11,9 @@ namespace TelldusCore {
 		~Message(void);
 
 		void addArgument(const std::wstring &);
+		//void addSpecialArgument(const std::wstring &);
+		//void addSpecialArgument(int);
+		//void addSpecialArgument(const char *);
 		void addArgument(int);
 		void addArgument(const char *);
 				
diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp
index 35045c20..0a2a2639 100644
--- a/telldus-core/common/Socket_unix.cpp
+++ b/telldus-core/common/Socket_unix.cpp
@@ -78,9 +78,9 @@ std::wstring Socket::read() {
 std::wstring Socket::read(int timeout) {
 	struct timeval tv;
 	char inbuf[BUFSIZE];
-	memset(inbuf, '\0', sizeof(inbuf));
 
 	FD_SET(d->socket, &d->infds);
+	std::string msg;
 	while(isConnected()) {
 		tv.tv_sec = floor(timeout / 1000.0);
 		tv.tv_usec = timeout % 1000;
@@ -93,21 +93,28 @@ std::wstring Socket::read(int timeout) {
 			continue;
 		}
 
-		int received = recv(d->socket, inbuf, BUFSIZE - 1, 0);
-		if (received <= 0) {
+		int received = BUFSIZE;
+		while(received >= (BUFSIZE - 1)){
+			memset(inbuf, '\0', sizeof(inbuf));
+			received = recv(d->socket, inbuf, BUFSIZE - 1, 0);
+			if(received > 0){
+				msg.append(std::string(inbuf));
+			}
+		}
+		if (received < 0) {
 			TelldusCore::MutexLocker locker(&d->mutex);
 			d->connected = false;
 		}
 		break;
 	}
 
-	std::string msg(inbuf);
 	return TelldusCore::charToWstring(msg.c_str());
 }
 
 void Socket::stopReadWait(){
 	TelldusCore::MutexLocker locker(&d->mutex);
 	d->connected = false;
+	//TODO somehow signal the socket here?
 }
 
 void Socket::write(const std::wstring &msg) {
diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp
index f78b274d..5fe760e4 100644
--- a/telldus-core/common/Socket_win.cpp
+++ b/telldus-core/common/Socket_win.cpp
@@ -37,6 +37,7 @@ Socket::~Socket(void){
 	SetEvent(d->readEvent);	//signal for break
 	if (d->hPipe != INVALID_HANDLE_VALUE) {
 		CloseHandle(d->hPipe);
+		d->hPipe = 0;
 	}
 	delete d;
 }
@@ -89,39 +90,52 @@ std::wstring Socket::read(int timeout){
 	
 	memset(&oOverlap, 0, sizeof(OVERLAPPED));
 
-	d->readEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
+	d->readEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 	oOverlap.hEvent = d->readEvent;
 	BOOL fSuccess = false;
+	std::wstring returnString;
+	bool moreData = true;
 
-	memset(&buf, 0, BUFSIZE);
+	while(moreData){
+		moreData = false;
+		memset(&buf, 0, sizeof(buf));
 
-	ReadFile( d->hPipe, &buf, sizeof(wchar_t)*BUFSIZE, &cbBytesRead, &oOverlap);
-
-	result = WaitForSingleObject(oOverlap.hEvent, timeout);
-	
-	if(!d->running){
-		CancelIo(d->hPipe);
-		CloseHandle(d->readEvent);
-		return L"";
-	}
-
-	if (result == WAIT_TIMEOUT) {
-		CancelIo(d->hPipe);
-		CloseHandle(d->readEvent);
-		return L"";
-	}
-	fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, false);
-	if (!fSuccess) {
-		DWORD err = GetLastError();
-		if (err == ERROR_BROKEN_PIPE) {
-			d->connected = false;
+		ReadFile( d->hPipe, &buf, sizeof(buf)-sizeof(wchar_t), &cbBytesRead, &oOverlap);
+		
+		result = WaitForSingleObject(oOverlap.hEvent, timeout);
+		
+		if(!d->running){
+			CancelIo(d->hPipe);
+			WaitForSingleObject(oOverlap.hEvent, INFINITE);
+			d->readEvent = 0;
+			CloseHandle(oOverlap.hEvent);
+			return L"";
 		}
-		buf[0] = 0;
-	}
 
-	CancelIo(d->hPipe);
-	CloseHandle(d->readEvent);
-	return buf;
+		if (result == WAIT_TIMEOUT) {
+			CancelIo(d->hPipe);
+			// Cancel, we still need to cleanup
+		}
+		fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, true);
+	
+		if (!fSuccess) {
+			DWORD err = GetLastError();
+
+			if(err == ERROR_MORE_DATA){
+				moreData = true;
+			}
+			else{
+				buf[0] = 0;
+			}
+			if (err == ERROR_BROKEN_PIPE) {
+				d->connected = false;
+			}
+		}
+		returnString.append(buf);
+	}
+	d->readEvent = 0;
+	CloseHandle(oOverlap.hEvent);
+	return returnString;
 }
 
 void Socket::write(const std::wstring &msg){
@@ -129,26 +143,33 @@ void Socket::write(const std::wstring &msg){
 	OVERLAPPED oOverlap;
 	DWORD bytesWritten = 0;
 	int result;
-	BOOL fSuccess;
+	BOOL fSuccess = false;
 
 	memset(&oOverlap, 0, sizeof(OVERLAPPED));
 
-	HANDLE writeEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
+	HANDLE writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 	oOverlap.hEvent = writeEvent;
 	
-	WriteFile(d->hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap);
-
-	result = WaitForSingleObject(writeEvent, 500);
-	if (result == WAIT_TIMEOUT) {
-		CancelIo(d->hPipe);
-		CloseHandle(writeEvent);
-		d->connected = false;
-		return;
+	BOOL writeSuccess = WriteFile(d->hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap);
+	result = GetLastError();
+	if (writeSuccess || result == ERROR_IO_PENDING) {
+		result = WaitForSingleObject(writeEvent, 500);
+		if (result == WAIT_TIMEOUT) {
+			CancelIo(d->hPipe);
+			WaitForSingleObject(oOverlap.hEvent, INFINITE);
+			CloseHandle(writeEvent);
+			CloseHandle(d->hPipe);
+			d->hPipe = 0;
+			d->connected = false;
+			return;
+		}
+		fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE);
 	}
-	fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE);
+
 	CloseHandle(writeEvent);
 	if (!fSuccess) {
-		CancelIo(d->hPipe);
+		CloseHandle(d->hPipe);
+		d->hPipe = 0;
 		d->connected = false;
 		return;	
 	}
diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp
index 83c1384f..fe0b7ca1 100644
--- a/telldus-core/common/Strings.cpp
+++ b/telldus-core/common/Strings.cpp
@@ -4,6 +4,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef _WINDOWS
 #include 
@@ -91,17 +92,58 @@ bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) {
 }
 
 std::wstring TelldusCore::intToWstring(int value) {
+#ifdef _WINDOWS
+	//no stream used
+//TODO! Make effective and safe...
+	wchar_t numstr[21]; // enough to hold all numbers up to 64-bits
+	_itow_s(value, numstr, sizeof(numstr), 10);
+	std::wstring newstring(numstr);
+	return newstring;
+	//return TelldusCore::charToWstring(stdstring.c_str());
+	//std::wstring temp = TelldusCore::charToWstring(stdstring.c_str());
+	//std::wstring temp(stdstring.length(), L' ');
+	//std::copy(stdstring.begin(), stdstring.end(), temp.begin());
+	//return temp;
+#else
 	std::wstringstream st;
 	st << value;
 	return st.str();
+#endif
 }
 
 std::string TelldusCore::intToString(int value) {
+//Not sure if this is neecssary (for ordinary stringstream that is)
+#ifdef _WINDOWS
+	char numstr[21]; // enough to hold all numbers up to 64-bits
+	_itoa_s(value, numstr, sizeof(numstr), 10);
+	std::string stdstring(numstr);
+	return stdstring;
+#else
 	std::stringstream st;
 	st << value;
 	return st.str();
+#endif
 }
 
+/*
+std::wstring TelldusCore::intToWStringSafe(int value){
+	#ifdef _WINDOWS
+		//no stream used
+	//TODO! Make effective and safe...
+		char numstr[21]; // enough to hold all numbers up to 64-bits
+		itoa(value, numstr, 10);
+		std::string stdstring(numstr);
+		return TelldusCore::charToWstring(stdstring.c_str());
+		//std::wstring temp = TelldusCore::charToWstring(stdstring.c_str());
+		//std::wstring temp(stdstring.length(), L' ');
+		//std::copy(stdstring.begin(), stdstring.end(), temp.begin());
+		//return temp;
+	#else
+		return TelldusCore::intToWString(value);
+	#endif
+}
+*/
+
 int TelldusCore::wideToInteger(const std::wstring &input){
 	std::wstringstream inputstream;
 	inputstream << input;
@@ -158,3 +200,48 @@ std::string TelldusCore::wideToString(const std::wstring &input) {
 	return retval;
 #endif
 }
+
+std::string TelldusCore::formatf(const char *format, ...) {
+	va_list ap;
+	va_start(ap, format);
+	std::string retval = sformatf(format, ap);
+	va_end(ap);
+	return retval;
+}
+
+std::string TelldusCore::sformatf(const char *format, va_list ap) {
+	//This code is based on code from the Linux man-pages project (man vsprintf)
+	int n;
+	int size = 100;     /* Guess we need no more than 100 bytes. */
+	char *p, *np;
+
+	if ((p = (char*)malloc(size)) == NULL) {
+		return "";
+	}
+
+	while (1) {
+		/* Try to print in the allocated space. */
+		n = vsnprintf(p, size, format, ap);
+
+		/* If that worked, return the string. */
+		if (n > -1 && n < size) {
+			std::string retval(p);
+			free(p);
+			return retval;
+		}
+
+		/* Else try again with more space. */
+
+		if (n > -1) {   /* glibc 2.1 */
+			size = n+1; /* precisely what is needed */
+		} else {        /* glibc 2.0 */
+			size *= 2;  /* twice the old size */
+		}
+		if ((np = (char *)realloc (p, size)) == NULL) {
+			free(p);
+			return "";
+		} else {
+			p = np;
+		}
+	}
+}
diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h
index aca16060..ad898424 100644
--- a/telldus-core/common/Strings.h
+++ b/telldus-core/common/Strings.h
@@ -2,6 +2,7 @@
 #define STRING_H
 
 #include 
+#include 
 
 namespace TelldusCore {
 	std::wstring charToWstring(const char *value);
@@ -10,10 +11,14 @@ namespace TelldusCore {
 
 	bool comparei(std::wstring stringA, std::wstring stringB);
 	std::wstring intToWstring(int value);
+	//std::wstring intToWStringSafe(int value);
 	std::string intToString(int value);
 	std::string wideToString(const std::wstring &input);
 
 	int wideToInteger(const std::wstring &input);
+
+	std::string formatf(const char *format, ...);
+	std::string sformatf(const char *format, va_list ap);
 }
 
 #endif //STRING_H
diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt
index a3e724b2..4943544f 100644
--- a/telldus-core/service/CMakeLists.txt
+++ b/telldus-core/service/CMakeLists.txt
@@ -19,10 +19,12 @@ SET( telldus-service_SRCS
 	Device.cpp
 	DeviceManager.cpp
 	Event.cpp
+	Log.cpp
 	Sensor.cpp
 	Settings.cpp
 	TelldusMain.cpp
 	TellStick.cpp
+	Timer.cpp
 	EventUpdateManager.cpp
 )
 SET( telldus-service_protocol_SRCS
@@ -34,6 +36,8 @@ SET( telldus-service_protocol_SRCS
 	ProtocolComen.cpp
 	ProtocolEverflourish.h
 	ProtocolEverflourish.cpp
+	ProtocolFineoffset.h
+	ProtocolFineoffset.cpp
 	ProtocolFuhaote.h
 	ProtocolFuhaote.cpp
 	ProtocolGroup.h
@@ -42,8 +46,12 @@ SET( telldus-service_protocol_SRCS
 	ProtocolHasta.cpp
 	ProtocolIkea.h
 	ProtocolIkea.cpp
+	ProtocolMandolyn.h
+	ProtocolMandolyn.cpp
 	ProtocolNexa.h
 	ProtocolNexa.cpp
+	ProtocolOregon.h
+	ProtocolOregon.cpp
 	ProtocolRisingSun.h
 	ProtocolRisingSun.cpp
 	ProtocolSartano.h
@@ -72,11 +80,13 @@ SET( telldus-service_HDRS
 	DeviceManager.h
 	Event.h
 	EventHandler.h
+	EventUpdateManager.h
+	Log.h
 	Sensor.h
 	Settings.h
 	TelldusMain.h
 	TellStick.h
-	EventUpdateManager.h
+	Timer.h
 )
 FIND_PACKAGE(Threads REQUIRED)
 LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
@@ -129,15 +139,27 @@ ELSEIF (WIN32) #### Windows ####
 		main_win.cpp
 		SettingsWinRegistry.cpp
 		TelldusWinService_win.cpp
+		Messages.mc
+		${CMAKE_CURRENT_BINARY_DIR}/Messages.rc
+		${CMAKE_CURRENT_BINARY_DIR}/Messages.h
 	)
 	LIST(APPEND telldus-service_HDRS
 		TelldusWinService_win.h
 	)
+	ADD_CUSTOM_COMMAND(
+		OUTPUT Messages.rc Messages.h
+		COMMAND mc.exe -u -r ${CMAKE_CURRENT_BINARY_DIR} -h ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc
+		DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc
+		DEPENDS Messages.rc
+		COMMENT "Compiling Messages Resource"
+	)
+	INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} )
 
 ELSE (APPLE) #### Linux ####
 	SET(DEFAULT_FTDI_ENGINE "libftdi")
 	FIND_LIBRARY(CONFUSE_LIBRARY confuse)
 	ADD_DEFINITIONS( -D_CONFUSE )
+	ADD_DEFINITIONS( -D_LINUX )
 
 	SET( telldus-service_TARGET	telldusd )
 	LIST(APPEND telldus-service_SRCS
diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp
index 7f84da27..d51144ab 100644
--- a/telldus-core/service/ClientCommunicationHandler.cpp
+++ b/telldus-core/service/ClientCommunicationHandler.cpp
@@ -76,6 +76,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage,
 	if (function == L"tdTurnOn") {
 		int deviceId = TelldusCore::Message::takeInt(&msg);
 		(*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, 0);
+
 	} else if (function == L"tdTurnOff") {
 		int deviceId = TelldusCore::Message::takeInt(&msg);
 		(*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNOFF, 0);
@@ -206,11 +207,6 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage,
 		std::wstring command = TelldusCore::Message::takeString(&msg);
 		int reserved = TelldusCore::Message::takeInt(&msg);
 		(*intReturn) = d->deviceManager->sendRawCommand(command, reserved);
-		EventUpdateData *eventData = new EventUpdateData();
-		eventData->messageType = L"TDRawDeviceEvent";
-		eventData->controllerId = -1;
-		eventData->eventValue = command;
-		d->deviceUpdateEvent->signal(eventData);
 
 	} else if (function == L"tdConnectTellStickController") {
 		int vid = TelldusCore::Message::takeInt(&msg);
diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp
index 992e1a87..f88bac48 100644
--- a/telldus-core/service/ConnectionListener_win.cpp
+++ b/telldus-core/service/ConnectionListener_win.cpp
@@ -91,46 +91,57 @@ void ConnectionListener::run() {
 
 	d->hEvent = CreateEvent(NULL, true, false, NULL);
 	oOverlap.hEvent = d->hEvent;
+	bool recreate = true;
 	
 	while (1) {
-		hPipe = CreateNamedPipe( 
-			(const wchar_t *)d->pipename.c_str(),             // pipe name 
-			PIPE_ACCESS_DUPLEX |      // read/write access 
-			FILE_FLAG_OVERLAPPED,	  //Overlapped mode
-			PIPE_TYPE_MESSAGE |       // message type pipe 
-			PIPE_READMODE_MESSAGE |   // message-read mode 
-			PIPE_WAIT,                // blocking mode 
-			PIPE_UNLIMITED_INSTANCES, // max. instances  
-			BUFSIZE,                  // output buffer size 
-			BUFSIZE,                  // input buffer size 
-			0,                        // client time-out 
-			&d->sa);                    // default security attribute 
+		BOOL alreadyConnected = false;
+		if (recreate) {
+			hPipe = CreateNamedPipe(
+				(const wchar_t *)d->pipename.c_str(),             // pipe name
+				PIPE_ACCESS_DUPLEX |      // read/write access
+				FILE_FLAG_OVERLAPPED,	  //Overlapped mode
+				PIPE_TYPE_MESSAGE |       // message type pipe
+				PIPE_READMODE_MESSAGE |   // message-read mode
+				PIPE_WAIT,                // blocking mode
+				PIPE_UNLIMITED_INSTANCES, // max. instances
+				BUFSIZE,                  // output buffer size
+				BUFSIZE,                  // input buffer size
+				0,                        // client time-out
+				&d->sa);                    // default security attribute
 
-		if (hPipe == INVALID_HANDLE_VALUE) {
-			//TelldusCore::logMessage("Could not create named pipe"); 
-			return;
+			if (hPipe == INVALID_HANDLE_VALUE) {
+				return;
+			}
+
+			ConnectNamedPipe(hPipe, &oOverlap);
+			alreadyConnected = GetLastError() == ERROR_PIPE_CONNECTED;
+			recreate = false;
 		}
+		if(!alreadyConnected){
+			DWORD result = WaitForSingleObject(oOverlap.hEvent, 1000);
+			if (!d->running) {
+				CancelIo(hPipe);
+				WaitForSingleObject(oOverlap.hEvent, INFINITE);
+				break;
+			}
+			
+			if(result == WAIT_TIMEOUT){
+				//CloseHandle(hPipe);
+				continue;
+			}
+			BOOL connected = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false);
 
-		ConnectNamedPipe(hPipe, &oOverlap);
-
-		DWORD result = WaitForSingleObject(oOverlap.hEvent, 1000);
-
-		if (!d->running) {
-			break;
-		}
-		if(result == WAIT_TIMEOUT){
-			CloseHandle(hPipe);
-			continue;
-		}
-		BOOL connected = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false);
-
-		if (!connected) {
-			CloseHandle(hPipe);
-			return;
+			if (!connected) {
+				CloseHandle(hPipe);
+				return;
+			}
 		}
 		ConnectionListenerEventData *data = new ConnectionListenerEventData();
+		ResetEvent(oOverlap.hEvent);
 		data->socket = new TelldusCore::Socket(hPipe);
 		d->waitEvent->signal(data);
+
+		recreate = true;
 	}
 
 	CloseHandle(d->hEvent);
diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h
index a1b92e74..42c47a04 100644
--- a/telldus-core/service/Controller.h
+++ b/telldus-core/service/Controller.h
@@ -16,6 +16,7 @@ public:
 
 	virtual int firmwareVersion() = 0;
 	virtual int send( const std::string &message ) = 0;
+	virtual int reset() = 0;
 
 protected:
 	Controller(int id, Event *event);
diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp
index 6081a421..6865e450 100644
--- a/telldus-core/service/ControllerManager.cpp
+++ b/telldus-core/service/ControllerManager.cpp
@@ -2,6 +2,8 @@
 #include "Controller.h"
 #include "Mutex.h"
 #include "TellStick.h"
+#include "Log.h"
+#include "../client/telldus-core.h"
 
 #include 
 #include 
@@ -119,3 +121,47 @@ void ControllerManager::loadControllers() {
 		d->controllers[d->lastControllerId] = controller;
 	}
 }
+
+void ControllerManager::queryControllerStatus(){
+
+	std::list tellStickControllers;
+
+	{
+		TelldusCore::MutexLocker locker(&d->mutex);
+		for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
+			TellStick *tellstick = reinterpret_cast(it->second);
+			if (tellstick) {
+				tellStickControllers.push_back(tellstick);
+			}
+		}
+	}
+
+	bool reloadControllers = false;
+	std::string noop = "N+";
+	for(std::list::iterator it = tellStickControllers.begin(); it != tellStickControllers.end(); ++it) {
+		int success = (*it)->send(noop);
+		if(success == TELLSTICK_ERROR_BROKEN_PIPE){
+			Log::warning("TellStick query: Error in communication with TellStick, resetting USB");
+			resetController(*it);
+		}
+		if(success == TELLSTICK_ERROR_BROKEN_PIPE || success == TELLSTICK_ERROR_NOT_FOUND){
+			reloadControllers = true;
+		}
+	}
+
+	if(!tellStickControllers.size() || reloadControllers){
+		//no tellstick at all found, or controller was reset
+		Log::debug("TellStick query: Rescanning USB ports");  //only log as debug, since this will happen all the time if no TellStick is connected
+		loadControllers();
+	}
+}
+
+int ControllerManager::resetController(Controller *controller) {
+	TellStick *tellstick = reinterpret_cast(controller);
+	if (!tellstick) {
+		return true; //not tellstick, nothing to reset at the moment, just return true
+	}
+	int success = tellstick->reset();
+	deviceInsertedOrRemoved(tellstick->vid(), tellstick->pid(), tellstick->serial(), false); //remove from list and delete
+	return success;
+}
diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h
index 199f7610..bab3525c 100644
--- a/telldus-core/service/ControllerManager.h
+++ b/telldus-core/service/ControllerManager.h
@@ -14,9 +14,9 @@ public:
 	void deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted);
 
 	Controller *getBestControllerById(int id);
-
-protected:
 	void loadControllers();
+	void queryControllerStatus();
+	int resetController(Controller *controller);
 
 private:
 	class PrivateData;
diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp
index 7a17eb12..3930108a 100644
--- a/telldus-core/service/DeviceManager.cpp
+++ b/telldus-core/service/DeviceManager.cpp
@@ -5,7 +5,7 @@
 #include "Settings.h"
 #include "Strings.h"
 #include "Message.h"
-#include "common.h"
+#include "Log.h"
 
 #include 
 #include 
@@ -432,9 +432,31 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){
 	}
 	else{
 		Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId());
+		if(!controller){
+			Log::warning("Trying to execute action, but no controller found. Rescanning USB ports");
+			//no controller found, scan for one, and retry once
+			d->controllerManager->loadControllers();
+			controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId());
+		}
+
 		if(controller){
 			retval = device->doAction(action, data, controller);
+			if(retval == TELLSTICK_ERROR_BROKEN_PIPE){
+				Log::warning("Error in communication with TellStick when executing action. Resetting USB");
+				d->controllerManager->resetController(controller);
+			}
+			if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND){
+				Log::warning("Rescanning USB ports");
+				d->controllerManager->loadControllers();
+				controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId());
+				if(!controller){
+					Log::error("No contoller (TellStick) found, even after reset. Giving up.");
+					return TELLSTICK_ERROR_NOT_FOUND;
+				}
+				retval = device->doAction(action, data, controller); //retry one more time
+			}
 		} else {
+			Log::error("No contoller (TellStick) found after one retry. Giving up.");
 			return TELLSTICK_ERROR_NOT_FOUND;
 		}
 	}
@@ -479,7 +501,7 @@ int DeviceManager::doGroupAction(const std::wstring devices, const int action, c
 					deviceReturnValue = doAction(deviceId, action, data);
 				}
 				else if(childType == TELLSTICK_TYPE_SCENE){
-					deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); //TODO make scenes (and test) infinite loops-safe
+					deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); //TODO make scenes infinite loops-safe
 				}
 				else{
 					//group (in group)
@@ -719,10 +741,29 @@ void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int da
 int DeviceManager::sendRawCommand(const std::wstring &command, int reserved){
 
 	Controller *controller = d->controllerManager->getBestControllerById(-1);
-	if(controller){
-		return controller->send(TelldusCore::wideToString(command));
+
+	if(!controller){
+		//no controller found, scan for one, and retry once
+		d->controllerManager->loadControllers();
+		controller = d->controllerManager->getBestControllerById(-1);
 	}
-	else{
+
+	int retval = TELLSTICK_ERROR_UNKNOWN;
+	if(controller){
+		retval = controller->send(TelldusCore::wideToString(command));
+		if(retval == TELLSTICK_ERROR_BROKEN_PIPE){
+			d->controllerManager->resetController(controller);
+		}
+		if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND){
+			d->controllerManager->loadControllers();
+			controller = d->controllerManager->getBestControllerById(-1);
+			if(!controller){
+				return TELLSTICK_ERROR_NOT_FOUND;
+			}
+			retval = controller->send(TelldusCore::wideToString(command));  //retry one more time
+		}
+		return retval;
+	} else {
 		return TELLSTICK_ERROR_NOT_FOUND;
 	}
 }
diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp
index 730b5b40..f44fe8c7 100644
--- a/telldus-core/service/EventHandler_win.cpp
+++ b/telldus-core/service/EventHandler_win.cpp
@@ -51,15 +51,17 @@ void EventHandler::signal(Event *) {
 }
 
 bool EventHandler::waitForAny() {
-	int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, INFINITE);
-
-	TelldusCore::MutexLocker locker(&d->mutex);
-	if (result == WAIT_TIMEOUT) {
-		return false;
+	
+	while(1){
+		int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, 1000);
+		if (result == WAIT_TIMEOUT) {
+			continue;
+		}
+		TelldusCore::MutexLocker locker(&d->mutex);
+		int eventIndex = result - WAIT_OBJECT_0;
+		if (eventIndex >= d->eventCount) {
+			return false;
+		}
+		return true;
 	}
-	int eventIndex = result - WAIT_OBJECT_0;
-	if (eventIndex >= d->eventCount) {
-		return false;
-	}
-	return true;
 }
diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp
index b1175ff6..5594e12a 100644
--- a/telldus-core/service/EventUpdateManager.cpp
+++ b/telldus-core/service/EventUpdateManager.cpp
@@ -73,10 +73,10 @@ void EventUpdateManager::run(){
 
 void EventUpdateManager::sendMessageToClients(EventUpdateData *data){
 
+	int connected = 0;
 	for(SocketList::iterator it = d->clients.begin(); it != d->clients.end();){
-
 		if((*it)->isConnected()){
-
+			connected++;
 			TelldusCore::Message msg;
 
 			if(data->messageType == L"TDDeviceEvent"){
diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp
new file mode 100644
index 00000000..f555378a
--- /dev/null
+++ b/telldus-core/service/Log.cpp
@@ -0,0 +1,180 @@
+#include "Log.h"
+#include 
+
+#if defined(_LINUX)
+#include 
+#elif defined(_WINDOWS)
+#include 
+#include "Strings.h"
+#include "Messages.h"
+#endif
+
+class Log::PrivateData {
+public:
+	PrivateData() : logOutput(Log::System), debug(false) {}
+
+	Log::LogOutput logOutput;
+	bool debug;
+
+	static Log *instance;
+#ifdef _WINDOWS
+	HANDLE eventSource;
+#endif
+};
+
+Log *Log::PrivateData::instance = 0;
+
+Log::Log()
+	:d(new PrivateData)
+{
+#if defined(_LINUX)
+	setlogmask(LOG_UPTO(LOG_INFO));
+	openlog("telldusd", LOG_CONS, LOG_USER);
+#elif defined(_MACOSX)
+	d->logOutput = Log::StdOut;
+#elif defined(_WINDOWS)
+	//Add ourselves to the registy
+	HKEY hRegKey = NULL;
+	DWORD dwError = 0;
+	TCHAR filePath[MAX_PATH];
+
+	std::wstring path(L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\TelldusService");
+	dwError = RegCreateKey( HKEY_LOCAL_MACHINE, path.c_str(), &hRegKey );
+
+	GetModuleFileName( NULL, filePath, MAX_PATH );
+	dwError = RegSetValueEx( hRegKey, L"EventMessageFile", 0,
+                           REG_EXPAND_SZ, (PBYTE) filePath,
+                           (DWORD)(wcslen(filePath) + 1) * sizeof TCHAR );
+
+	DWORD dwTypes = LOG_DEBUG | LOG_NOTICE | LOG_WARNING | LOG_ERR;
+    dwError = RegSetValueEx( hRegKey, L"TypesSupported",
+              0, REG_DWORD, (LPBYTE) &dwTypes, sizeof dwTypes );
+
+	RegCloseKey(hRegKey);
+
+	d->eventSource = RegisterEventSource(NULL, L"TelldusService");
+#endif
+}
+
+Log::~Log() {
+#if defined(_LINUX)
+	closelog();
+#elif defined(_WINDOWS)
+	if (d->eventSource != NULL) {
+		DeregisterEventSource(d->eventSource);
+	}
+#endif
+	delete d;
+}
+
+void Log::destroy() {
+	if (PrivateData::instance == 0) {
+		return;
+	}
+	delete PrivateData::instance;
+	PrivateData::instance = 0;
+}
+
+void Log::debug(const char *fmt, ...) {
+	Log *log = Log::instance();
+	va_list ap;
+	va_start(ap, fmt);
+	log->message(Debug, fmt, ap);
+	va_end(ap);
+}
+
+void Log::notice(const char *fmt, ...) {
+	Log *log = Log::instance();
+	va_list ap;
+	va_start(ap, fmt);
+	log->message(Notice, fmt, ap);
+	va_end(ap);
+}
+
+void Log::warning(const char *fmt, ...) {
+	Log *log = Log::instance();
+	va_list ap;
+	va_start(ap, fmt);
+	log->message(Warning, fmt, ap);
+	va_end(ap);
+}
+
+void Log::error(const char *fmt, ...) {
+	Log *log = Log::instance();
+	va_list ap;
+	va_start(ap, fmt);
+	log->message(Error, fmt, ap);
+	va_end(ap);
+}
+
+void Log::setDebug() {
+	Log *log = Log::instance();
+	log->d->debug = true;
+}
+
+void Log::setLogOutput(LogOutput logOutput) {
+#ifdef _MACOSX
+	//Always stdout
+	return;
+#endif
+	Log *log = Log::instance();
+	log->d->logOutput = logOutput;
+}
+
+void Log::message(Log::LogLevel logLevel, const char *format, va_list ap) const {
+	if (logLevel == Debug && d->debug == false) {
+		return;
+	}
+	if (d->logOutput == StdOut) {
+		FILE *stream = stdout;
+		if (logLevel == Warning || logLevel == Error) {
+			stream = stderr;
+		}
+		vfprintf(stream, format, ap);
+		fprintf(stream, "\n");
+		fflush(stream);
+	} else {
+#if defined(_LINUX)
+		switch (logLevel) {
+			case Debug:
+				vsyslog(LOG_DEBUG, format, ap);
+				break;
+			case Notice:
+				vsyslog(LOG_NOTICE, format, ap);
+				break;
+			case Warning:
+				vsyslog(LOG_WARNING, format, ap);
+				break;
+			case Error:
+				vsyslog(LOG_ERR, format, ap);
+				break;
+		}
+#elif defined(_WINDOWS)
+		LPWSTR pInsertStrings[2] = {NULL, NULL};
+		std::wstring str = TelldusCore::charToWstring(TelldusCore::sformatf(format, ap).c_str());
+		pInsertStrings[0] = (LPWSTR)str.c_str();
+
+		switch (logLevel) {
+			case Debug:
+				ReportEvent(d->eventSource, EVENTLOG_SUCCESS, NULL, LOG_DEBUG, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL);
+				break;
+			case Notice:
+				ReportEvent(d->eventSource, EVENTLOG_INFORMATION_TYPE, NULL, LOG_NOTICE, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL);
+				break;
+			case Warning:
+				ReportEvent(d->eventSource, EVENTLOG_WARNING_TYPE, NULL, LOG_WARNING, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL);
+				break;
+			case Error:
+				ReportEvent(d->eventSource, EVENTLOG_ERROR_TYPE, NULL, LOG_ERR, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL);
+				break;
+		}
+#endif
+	}
+}
+
+Log *Log::instance() {
+	if (PrivateData::instance == 0) {
+		PrivateData::instance = new Log();
+	}
+	return PrivateData::instance;
+}
diff --git a/telldus-core/service/Log.h b/telldus-core/service/Log.h
new file mode 100644
index 00000000..a2f547c0
--- /dev/null
+++ b/telldus-core/service/Log.h
@@ -0,0 +1,33 @@
+#ifndef LOG_H
+#define LOG_H
+
+#include 
+
+class Log {
+public:
+	enum LogLevel { Debug, Notice, Warning, Error };
+	enum LogOutput { StdOut, System };
+	virtual ~Log();
+
+	static void destroy();
+
+	static void debug(const char *fmt, ...);
+	static void notice(const char *fmt, ...);
+	static void warning(const char *fmt, ...);
+	static void error(const char *fmt, ...);
+
+	static void setDebug();
+	static void setLogOutput(LogOutput logOutput);
+
+protected:
+	Log();
+	void message(LogLevel logLevel, const char *format, va_list ap) const;
+	static Log *instance();
+
+private:
+	class PrivateData;
+	PrivateData *d;
+};
+
+
+#endif //LOG_H
diff --git a/telldus-core/service/Messages.mc b/telldus-core/service/Messages.mc
new file mode 100644
index 00000000..b7f81b41
Binary files /dev/null and b/telldus-core/service/Messages.mc differ
diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp
index ebcfebb3..0a2be23c 100644
--- a/telldus-core/service/Protocol.cpp
+++ b/telldus-core/service/Protocol.cpp
@@ -5,11 +5,14 @@
 #include "ProtocolBrateck.h"
 #include "ProtocolComen.h"
 #include "ProtocolEverflourish.h"
+#include "ProtocolFineoffset.h"
 #include "ProtocolFuhaote.h"
 #include "ProtocolGroup.h"
 #include "ProtocolHasta.h"
 #include "ProtocolIkea.h"
+#include "ProtocolMandolyn.h"
 #include "ProtocolNexa.h"
+#include "ProtocolOregon.h"
 #include "ProtocolRisingSun.h"
 #include "ProtocolSartano.h"
 #include "ProtocolScene.h"
@@ -195,10 +198,10 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr
 
 	} else if (TelldusCore::comparei(protocolName, L"yidong")) {
 		parameters.push_back("unit");
-	
+
 	} else if (TelldusCore::comparei(protocolName, L"group")) {
 		parameters.push_back("devices");
-	
+
 	}  else if (TelldusCore::comparei(protocolName, L"scene")) {
 		parameters.push_back("devices");
 	}
@@ -209,7 +212,7 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr
 std::list Protocol::decodeData(const std::string &fullData) {
 	std::list retval;
 	std::string decoded = "";
-	
+
 	ControllerMessage dataMsg(fullData);
 	if( TelldusCore::comparei(dataMsg.protocol(), L"arctech") ) {
 		decoded = ProtocolNexa::decodeData(dataMsg);
@@ -231,12 +234,30 @@ std::list Protocol::decodeData(const std::string &fullData) {
 			retval.push_back(decoded);
 		}
 	}
+	else if(TelldusCore::comparei(dataMsg.protocol(), L"fineoffset") ) {
+		decoded = ProtocolFineoffset::decodeData(dataMsg);
+		if (decoded != "") {
+			retval.push_back(decoded);
+		}
+	}
+	else if(TelldusCore::comparei(dataMsg.protocol(), L"mandolyn") ) {
+		decoded = ProtocolMandolyn::decodeData(dataMsg);
+		if (decoded != "") {
+			retval.push_back(decoded);
+		}
+	}
+	else if(TelldusCore::comparei(dataMsg.protocol(), L"oregon") ) {
+		decoded = ProtocolOregon::decodeData(dataMsg);
+		if (decoded != "") {
+			retval.push_back(decoded);
+		}
+	}
 	else if(TelldusCore::comparei(dataMsg.protocol(), L"x10") ) {
 		decoded = ProtocolX10::decodeData(dataMsg);
 		if (decoded != "") {
 			retval.push_back(decoded);
 		}
 	}
-	
+
 	return retval;
 }
diff --git a/telldus-core/service/ProtocolFineoffset.cpp b/telldus-core/service/ProtocolFineoffset.cpp
new file mode 100644
index 00000000..31d150a0
--- /dev/null
+++ b/telldus-core/service/ProtocolFineoffset.cpp
@@ -0,0 +1,50 @@
+#include "ProtocolFineoffset.h"
+#include 
+#include 
+#include 
+#ifdef _MSC_VER
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+#else
+#include 
+#endif
+
+std::string ProtocolFineoffset::decodeData(ControllerMessage &dataMsg)
+{
+	std::string data = dataMsg.getParameter("data");
+	if (data.length() < 8) {
+		return "";
+	}
+
+	uint8_t checksum = strtol(data.substr(data.length()-2).c_str(), NULL, 16);
+	data = data.substr(0, data.length()-2);
+
+	uint8_t humidity = strtol(data.substr(data.length()-2).c_str(), NULL, 16);
+	data = data.substr(0, data.length()-2);
+
+	uint16_t value = strtol(data.substr(data.length()-3).c_str(), NULL, 16);
+	double temperature = (value & 0x7FF)/10.0;
+
+	value >>= 11;
+	if (value & 1) {
+		temperature = -temperature;
+	}
+	data = data.substr(0, data.length()-3);
+
+	uint16_t id = strtol(data.c_str(), NULL, 16) & 0xFF;
+
+	std::stringstream retString;
+	retString << "class:sensor;protocol:fineoffset;id:" << id << ";model:";
+
+	if (humidity <= 100) {
+		retString << "temperaturehumidity;humidity:" << (int)humidity << ";";
+	} else if (humidity == 0xFF) {
+		retString << "temperature;";
+	} else {
+		return "";
+	}
+
+	retString << "temp:" << std::fixed << std::setprecision(1) << temperature << ";";
+
+	return retString.str();
+}
diff --git a/telldus-core/service/ProtocolFineoffset.h b/telldus-core/service/ProtocolFineoffset.h
new file mode 100644
index 00000000..fbae92c0
--- /dev/null
+++ b/telldus-core/service/ProtocolFineoffset.h
@@ -0,0 +1,13 @@
+#ifndef PROTOCOLFINEOFFSET_H
+#define PROTOCOLFINEOFFSET_H
+
+#include "ControllerMessage.h"
+#include "Protocol.h"
+
+class ProtocolFineoffset : public Protocol
+{
+public:
+	static std::string decodeData(ControllerMessage &dataMsg);
+};
+
+#endif //PROTOCOLFINEOFFSET_H
diff --git a/telldus-core/service/ProtocolMandolyn.cpp b/telldus-core/service/ProtocolMandolyn.cpp
new file mode 100644
index 00000000..420d6bdb
--- /dev/null
+++ b/telldus-core/service/ProtocolMandolyn.cpp
@@ -0,0 +1,44 @@
+#include "ProtocolMandolyn.h"
+#include 
+#include 
+#include 
+
+#ifdef _MSC_VER
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int32 uint32_t;
+#else
+#include 
+#endif
+
+std::string ProtocolMandolyn::decodeData(ControllerMessage &dataMsg)
+{
+	std::string data = dataMsg.getParameter("data");
+	uint32_t value = strtol(data.c_str(), NULL, 16);
+
+	bool parity = value & 0x1;
+	value >>= 1;
+
+	double temp = (value & 0x7FFF) - 6400;
+	temp = temp/128.0;
+	value >>= 15;
+
+	uint8_t humidity = (value & 0x7F);
+	value >>= 7;
+
+	bool battOk = value & 0x1;
+	value >>= 3;
+
+	uint8_t channel = (value & 0x3)+1;
+	value >>= 2;
+
+	uint8_t house = value & 0xF;
+
+	std::stringstream retString;
+	retString << "class:sensor;protocol:mandolyn;id:"
+		<< house*10+channel
+		<< ";model:temperaturehumidity;"
+		<< "temp:" << std::fixed << std::setprecision(1) << temp
+		<< ";humidity:" << (int)humidity << ";";
+
+	return retString.str();
+}
diff --git a/telldus-core/service/ProtocolMandolyn.h b/telldus-core/service/ProtocolMandolyn.h
new file mode 100644
index 00000000..a3ff0700
--- /dev/null
+++ b/telldus-core/service/ProtocolMandolyn.h
@@ -0,0 +1,13 @@
+#ifndef PROTOCOLMANDOLYN_H
+#define PROTOCOLMANDOLYN_H
+
+#include "ControllerMessage.h"
+#include "Protocol.h"
+
+class ProtocolMandolyn : public Protocol
+{
+public:
+	static std::string decodeData(ControllerMessage &dataMsg);
+};
+
+#endif //PROTOCOLMANDOLYN_H
diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp
index 2b29ced5..993f3ff2 100644
--- a/telldus-core/service/ProtocolNexa.cpp
+++ b/telldus-core/service/ProtocolNexa.cpp
@@ -3,7 +3,6 @@
 #include 
 #include "TellStick.h"
 #include "Strings.h"
-#include "common.h"
 
 int ProtocolNexa::lastArctecCodeSwitchWasTurnOff=0;  //TODO, always removing first turnon now, make more flexible (waveman too)
 
diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp
new file mode 100644
index 00000000..704ebeeb
--- /dev/null
+++ b/telldus-core/service/ProtocolOregon.cpp
@@ -0,0 +1,120 @@
+#include "ProtocolOregon.h"
+#include 
+#include 
+#include 
+#ifdef _MSC_VER
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int64 uint64_t;
+#else
+#include 
+#endif
+
+std::string ProtocolOregon::decodeData(ControllerMessage &dataMsg)
+{
+	std::string data = dataMsg.getParameter("data");
+
+	std::wstring model = dataMsg.model();
+	if (model.compare(L"0xEA4C") == 0) {
+		return decodeEA4C(data);
+	} else if (model.compare(L"0x1A2D") == 0) {
+		return decode1A2D(data);
+	}
+
+	return "";
+}
+
+std::string ProtocolOregon::decodeEA4C(const std::string &data) {
+	uint64_t value = strtol(data.c_str(), NULL, 16);
+
+	uint8_t checksum = 0xE + 0xA + 0x4 + 0xC;
+	checksum -= (value & 0xF) * 0x10;
+	checksum -= 0xA;
+	value >>= 8;
+
+	uint8_t checksumw = (value >> 4) & 0xF;
+	bool neg = value & (1 << 3);
+	checksum += (value & 0xF);
+	value >>= 8;
+
+	uint8_t temp2 = value & 0xF;
+	uint8_t temp1 = (value >> 4) & 0xF;
+	checksum += temp2 + temp1;
+	value >>= 8;
+
+	uint8_t temp3 = (value >> 4) & 0xF;
+	checksum += (value & 0xF) + temp3;
+	value >>= 8;
+
+	checksum += ((value >> 4) & 0xF) + (value & 0xF);
+	uint8_t address = value & 0xFF;
+	value >>= 8;
+
+	checksum += ((value >> 4) & 0xF) + (value & 0xF);
+	uint8_t channel = (value >> 4) & 0x7;
+
+	if (checksum != checksumw) {
+		return "";
+	}
+
+	double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0;
+	if (neg) {
+		temperature = -temperature;
+	}
+
+	std::stringstream retString;
+	retString << "class:sensor;protocol:oregon;model:EA4C;id:" << (int)address
+		<< ";temp:" << std::fixed << std::setprecision(1) << temperature << ";";
+
+	return retString.str();
+}
+
+std::string ProtocolOregon::decode1A2D(const std::string &data) {
+	uint64_t value = strtol(data.c_str(), NULL, 16);
+	uint8_t checksum2 = value & 0xFF;
+	value >>= 8;
+	uint8_t checksum1 = value & 0xFF;
+	value >>= 8;
+
+	uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
+	uint8_t hum1 = value & 0xF;
+	value >>= 8;
+
+	checksum += ((value >> 4) & 0xF) + (value & 0xF);
+	uint8_t neg = value & (1 << 3);
+	uint8_t hum2 = (value >> 4) & 0xF;
+	value >>= 8;
+
+	checksum += ((value >> 4) & 0xF) + (value & 0xF);
+	uint8_t temp2 = value & 0xF;
+	uint8_t temp1 = (value >> 4) & 0xF;
+	value >>= 8;
+
+	checksum += ((value >> 4) & 0xF) + (value & 0xF);
+	uint8_t temp3 = (value >> 4) & 0xF;
+	value >>= 8;
+
+	checksum += ((value >> 4) & 0xF) + (value & 0xF);
+	uint8_t address = value & 0xFF;
+	value >>= 8;
+
+	checksum += ((value >> 4) & 0xF) + (value & 0xF);
+	uint8_t channel = (value >> 4) & 0x7;
+
+	checksum += 0x1 + 0xA + 0x2 + 0xD - 0xA;
+
+	//TODO: Find out how checksum2 works
+	if (checksum != checksum1) {
+		return "";
+	}
+
+	double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0;
+	if (neg) {
+		temperature = -temperature;
+	}
+
+	std::stringstream retString;
+	retString << "class:sensor;protocol:oregon;model:1A2D;id:" << (int)address
+		<< ";temp:" << std::fixed << std::setprecision(1) << temperature << ";";
+
+	return retString.str();
+}
diff --git a/telldus-core/service/ProtocolOregon.h b/telldus-core/service/ProtocolOregon.h
new file mode 100644
index 00000000..8d8c3c8f
--- /dev/null
+++ b/telldus-core/service/ProtocolOregon.h
@@ -0,0 +1,17 @@
+#ifndef PROTOCOLOREGON_H
+#define PROTOCOLOREGON_H
+
+#include "ControllerMessage.h"
+#include "Protocol.h"
+
+class ProtocolOregon : public Protocol
+{
+public:
+	static std::string decodeData(ControllerMessage &dataMsg);
+
+protected:
+	static std::string decodeEA4C(const std::string &data);
+	static std::string decode1A2D(const std::string &data);
+};
+
+#endif //PROTOCOLOREGON_H
diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp
index af7e005f..9c0c7084 100644
--- a/telldus-core/service/SettingsConfuse.cpp
+++ b/telldus-core/service/SettingsConfuse.cpp
@@ -375,6 +375,7 @@ bool readConfig(cfg_t **cfg) {
 		CFG_STR(const_cast("user"), const_cast("nobody"), CFGF_NONE),
 		CFG_STR(const_cast("group"), const_cast("plugdev"), CFGF_NONE),
 		CFG_STR(const_cast("deviceNode"), const_cast("/dev/tellstick"), CFGF_NONE),
+		CFG_STR(const_cast("ignoreControllerConfirmation"), const_cast("false"), CFGF_NONE),
 		CFG_SEC(const_cast("device"), device_opts, CFGF_MULTI),
 		CFG_END()
 	};
diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp
index 939f6152..5ee83b2c 100644
--- a/telldus-core/service/SettingsWinRegistry.cpp
+++ b/telldus-core/service/SettingsWinRegistry.cpp
@@ -1,10 +1,12 @@
 #include "Settings.h"
+#include "Strings.h"
 #include 
 #include  
 #include 
 #include 
 #include 
 #include 
+#include "common.h"
 
 #include "../client/telldus-core.h"
 
@@ -93,9 +95,8 @@ int Settings::addDevice() {
 	DWORD dwDisp;
 	intDeviceId = getNextDeviceId();
 
-	std::wostringstream ssRegPath; 
-	ssRegPath << d->strRegPathDevice << intDeviceId;
-	std::wstring strCompleteRegPath = ssRegPath.str();
+	std::wstring strCompleteRegPath = d->strRegPathDevice;
+	strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId));
 		
 	if (RegCreateKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp)) {
 		//fail
@@ -122,7 +123,7 @@ int Settings::getNextDeviceId() const {
 		DWORD dwLength;
 		DWORD nResult(0);
 
-		long lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, reinterpret_cast(&nResult), &dwLength); //(LPBYTE)Buff, &dwLength);
+		long lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, reinterpret_cast(&nResult), &dwLength);
 
 		if(lngStatus == ERROR_SUCCESS){
 			intReturn = nResult + 1;
@@ -143,9 +144,8 @@ int Settings::getNextDeviceId() const {
 int Settings::removeDevice(int intDeviceId) {
 	TelldusCore::MutexLocker locker(&mutex);
 	
-	std::wostringstream ssRegPath; 
-	ssRegPath << d->strRegPathDevice << intDeviceId;
-	std::wstring strCompleteRegPath = ssRegPath.str();
+	std::wstring strCompleteRegPath = d->strRegPathDevice;
+	strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId));
 
 	long lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str());
 
@@ -157,13 +157,39 @@ int Settings::removeDevice(int intDeviceId) {
 	return TELLSTICK_ERROR_UNKNOWN;
 }
 
+std::wstring Settings::getSetting(const std::wstring &strName) const{
+	std::wstring strReturn;
+	HKEY hk;
+
+	std::wstring strCompleteRegPath = d->strRegPath;
+	long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk);
+			
+	if(lnExists == ERROR_SUCCESS){
+		wchar_t* Buff = new wchar_t[intMaxRegValueLength];
+		DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength;
+		long lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength);
+
+		if(lngStatus == ERROR_MORE_DATA){
+			//The buffer is to small, recreate it
+			delete Buff;
+			Buff = new wchar_t[dwLength];
+			lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength);
+		}
+		if (lngStatus == ERROR_SUCCESS) {
+			strReturn = Buff;
+		}
+		delete Buff;
+	}
+	RegCloseKey(hk);
+	return strReturn;
+}
+
 std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const {
 	std::wstring strReturn;
 	HKEY hk;
 
-	std::wostringstream ssRegPath; 
-	ssRegPath << d->strRegPathDevice << intDeviceId;
-	std::wstring strCompleteRegPath = ssRegPath.str();
+	std::wstring strCompleteRegPath = d->strRegPathDevice;
+	strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId));
 	long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk);
 			
 	if(lnExists == ERROR_SUCCESS){
@@ -191,9 +217,9 @@ int Settings::setStringSetting(int intDeviceId, const std::wstring &name, const
 	HKEY hk;
 	int ret = TELLSTICK_SUCCESS;
 		
-	std::wostringstream ssRegPath; 
-	ssRegPath << d->strRegPathDevice << intDeviceId;
-	std::wstring strCompleteRegPath = ssRegPath.str();
+	std::wstring bla = TelldusCore::intToWstring(intDeviceId);
+	std::wstring strCompleteRegPath = d->strRegPathDevice;
+	strCompleteRegPath.append(bla);
 	long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk);
 				
 	if (lnExists == ERROR_SUCCESS){
@@ -223,9 +249,8 @@ int Settings::setIntSetting(int intDeviceId, const std::wstring &name, int value
 	int intReturn = TELLSTICK_ERROR_UNKNOWN;
 	HKEY hk;
 
-	std::wostringstream ssRegPath; 
-	ssRegPath << d->strRegPathDevice << intDeviceId;
-	std::wstring strCompleteRegPath = ssRegPath.str();
+	std::wstring strCompleteRegPath =  d->strRegPathDevice;
+	strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId));
 	long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk);
 	if (lnExists == ERROR_SUCCESS) {
 		DWORD dwVal = value;
diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h
index 3824b1d8..db73faab 100644
--- a/telldus-core/service/TellStick.h
+++ b/telldus-core/service/TellStick.h
@@ -29,8 +29,12 @@ public:
 
 	virtual int firmwareVersion();
 	virtual int pid() const;
+	virtual int vid() const;
+	virtual std::string serial() const;
+
 	bool isOpen() const;
 	bool isSameAsDescriptor(const TellStickDescriptor &d) const;
+	virtual int reset();
 	virtual int send( const std::string &message );
 	bool stillConnected() const;
 
diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp
index 8769cd30..05ac6c10 100644
--- a/telldus-core/service/TellStick_ftd2xx.cpp
+++ b/telldus-core/service/TellStick_ftd2xx.cpp
@@ -10,8 +10,11 @@
 //
 //
 #include "TellStick.h"
+#include "common.h"
 #include "Mutex.h"
+#include "Settings.h"
 #include "Strings.h"
+#include "Log.h"
 #include "../client/telldus-core.h"
 #include 
 #include 
@@ -20,7 +23,7 @@
 
 class TellStick::PrivateData {
 public:
-	bool open, running;
+	bool open, running, ignoreControllerConfirmation;
 	int vid, pid, fwVersion;
 	std::string serial, message;
 	FT_HANDLE ftHandle;
@@ -53,6 +56,8 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
 	d->pid = td.pid;
 	d->fwVersion = 0;
 	d->serial = td.serial;
+	Settings set;
+	d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation")==L"true";
 
 	char *tempSerial = new char[td.serial.size()+1];
 #ifdef _WINDOWS
@@ -61,6 +66,7 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
 	strcpy(tempSerial, td.serial.c_str());
 	FT_SetVIDPID(td.vid, td.pid);
 #endif
+	Log::notice("Connecting to TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str());
 	FT_STATUS ftStatus = FT_OpenEx(tempSerial, FT_OPEN_BY_SERIAL_NUMBER, &d->ftHandle);
 	delete tempSerial;
 	if (ftStatus == FT_OK) {
@@ -76,10 +82,13 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
 			setBaud(4800);
 		}
 		this->start();
+	} else {
+		Log::warning("Failed to open TellStick");
 	}
 }
 
 TellStick::~TellStick() {
+	Log::warning("Disconnected TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str());
 	if (d->running) {
 		TelldusCore::MutexLocker locker(&d->mutex);
 		d->running = false;
@@ -108,6 +117,14 @@ int TellStick::pid() const {
 	return d->pid;
 }
 
+int TellStick::vid() const {
+	return d->vid;
+}
+
+std::string TellStick::serial() const {
+	return d->serial;
+}
+
 bool TellStick::isOpen() const {
 	return d->open;
 }
@@ -144,6 +161,18 @@ void TellStick::processData( const std::string &data ) {
 	}
 }
 
+int TellStick::reset(){
+#ifndef _WINDOWS
+	return TELLSTICK_SUCCESS; //nothing to be done on other platforms
+#else
+	int success = FT_CyclePort( d->ftHandle );
+	if(success == FT_OK){
+		return TELLSTICK_SUCCESS;
+	}
+	return TELLSTICK_ERROR_UNKNOWN;
+#endif
+}
+
 void TellStick::run() {
 	d->running = true;
 	DWORD dwBytesInQueue = 0;
@@ -186,8 +215,7 @@ int TellStick::send( const std::string &strMessage ) {
 	if (!d->open) {
 		return TELLSTICK_ERROR_NOT_FOUND;
 	}
-	bool c = true;
-
+	
 	//This lock does two things
 	// 1 Prevents two calls from different threads to this function
 	// 2 Prevents our running thread from receiving the data we are interested in here
@@ -205,26 +233,39 @@ int TellStick::send( const std::string &strMessage ) {
 	FT_STATUS ftStatus;
 	ftStatus = FT_Write(d->ftHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten);
 	free(tempMessage);
+	
+	if(ftStatus != FT_OK){
+		Log::debug("Broken pipe on send");
+		return TELLSTICK_ERROR_BROKEN_PIPE;
+	}
+
+	if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))){
+		//these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly
+		return TELLSTICK_SUCCESS;
+	}
+	if(d->ignoreControllerConfirmation){
+		//wait for TellStick to finish its air-sending
+		msleep(1000);
+		return TELLSTICK_SUCCESS;
+	}
 
-	while(c) {
+	while(1) {
 		ftStatus = FT_Read(d->ftHandle,&in,1,&bytesRead);
 		if (ftStatus == FT_OK) {
 			if (bytesRead == 1) {
 				if (in == '\n') {
-					break;
+					return TELLSTICK_SUCCESS;
+				} else {
+					continue;
 				}
 			} else { //Timeout
-				c = false;
+				return TELLSTICK_ERROR_COMMUNICATION;
 			}
 		} else { //Error
-			c = false;
+			Log::debug("Broken pipe on read");
+			return TELLSTICK_ERROR_BROKEN_PIPE;
 		}
 	}
-
-	if (!c) {
-		return TELLSTICK_ERROR_COMMUNICATION;
-	}
-	return TELLSTICK_SUCCESS;
 }
 
 bool TellStick::stillConnected() const {
diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp
index c5e6c3ae..56b2a5a5 100644
--- a/telldus-core/service/TellStick_libftdi.cpp
+++ b/telldus-core/service/TellStick_libftdi.cpp
@@ -18,6 +18,8 @@
 #include 
 #include "Thread.h"
 #include "Mutex.h"
+#include "Log.h"
+#include "Settings.h"
 #include "Strings.h"
 #include "common.h"
 
@@ -31,7 +33,7 @@ typedef int DWORD;
 
 class TellStick::PrivateData {
 public:
-	bool open;
+	bool open, ignoreControllerConfirmation;
 	int vid, pid, fwVersion;
 	std::string serial, message;
 	ftdi_context ftHandle;
@@ -51,9 +53,13 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
 	d->serial = td.serial;
 	d->running = false;
 
+	Settings set;
+	d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation")==L"true";
+
 	ftdi_init(&d->ftHandle);
 	ftdi_set_interface(&d->ftHandle, INTERFACE_ANY);
 
+	Log::notice("Connecting to TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str());
 	int ret = ftdi_usb_open_desc(&d->ftHandle, td.vid, td.pid, NULL, td.serial.c_str());
 	if (ret < 0) {
 		ftdi_deinit(&d->ftHandle);
@@ -62,6 +68,7 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
 	d->open = true;
 	ftdi_usb_reset( &d->ftHandle );
 	ftdi_disable_bitbang( &d->ftHandle );
+	ftdi_set_latency_timer(&d->ftHandle, 16);
 
 	if (d->open) {
 
@@ -71,10 +78,13 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
 			this->setBaud(4800);
 		}
 		this->start();
+	} else {
+		Log::warning("Failed to open TellStick");
 	}
 }
 
 TellStick::~TellStick() {
+	Log::warning("Disconnected TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str());
 	if (d->running) {
 		stop();
 	}
@@ -94,6 +104,14 @@ int TellStick::pid() const {
 	return d->pid;
 }
 
+int TellStick::vid() const {
+	return d->vid;
+}
+
+std::string TellStick::serial() const {
+	return d->serial;
+}
+
 bool TellStick::isOpen() const {
 	return d->open;
 }
@@ -130,6 +148,14 @@ void TellStick::processData( const std::string &data ) {
 	}
 }
 
+int TellStick::reset(){
+	int success = ftdi_usb_reset( &d->ftHandle );
+	if(success < 0){
+		return TELLSTICK_ERROR_UNKNOWN; //-1 = FTDI reset failed, -2 = USB device unavailable
+	}
+	return TELLSTICK_SUCCESS;
+}
+
 void TellStick::run() {
 	int dwBytesRead = 0;
 	unsigned char buf[1024];     // = 0;
@@ -186,33 +212,44 @@ int TellStick::send( const std::string &strMessage ) {
 	if(ret < 0) {
 		c = false;
 	} else if(ret != strMessage.length()) {
-		fprintf(stderr, "weird send length? retval %i instead of %d\n",
-		ret, (int)strMessage.length());
+		Log::debug("Weird send length? retval %i instead of %d\n", ret, (int)strMessage.length());
 	}
 
 	delete[] tempMessage;
 
-	int retrycnt = 200;
+	if(!c){
+		Log::debug("Broken pipe on send");
+		return TELLSTICK_ERROR_BROKEN_PIPE;
+	}
+
+	if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))){
+		//these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly
+		return TELLSTICK_SUCCESS;
+	}
+
+	if(d->ignoreControllerConfirmation){
+		//allow TellStick to finish its air-sending
+		msleep(1000);
+		return TELLSTICK_SUCCESS;
+	}
+
+	int retrycnt = 250;
 	unsigned char in;
-	while(c && --retrycnt) {
+	while(--retrycnt) {
 		ret = ftdi_read_data( &d->ftHandle, &in, 1);
 		if (ret > 0) {
 			if (in == '\n') {
-				break;
+				return TELLSTICK_SUCCESS;
 			}
 		} else if(ret == 0) { // No data available
 			usleep(100);
 		} else { //Error
-			c = false;
+			Log::debug("Broken pipe on read");
+			return TELLSTICK_ERROR_BROKEN_PIPE;
 		}
 	}
-	if (!retrycnt) {
-		c = false;
-	}
-	if (!c) {
-		return TELLSTICK_ERROR_COMMUNICATION;
-	}
-	return TELLSTICK_SUCCESS;
+
+	return TELLSTICK_ERROR_COMMUNICATION;
 }
 
 void TellStick::setBaud(int baud) {
diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp
index 7a24561d..32202c0b 100644
--- a/telldus-core/service/TelldusMain.cpp
+++ b/telldus-core/service/TelldusMain.cpp
@@ -6,6 +6,8 @@
 #include "ControllerManager.h"
 #include "ControllerListener.h"
 #include "EventUpdateManager.h"
+#include "Timer.h"
+#include "Log.h"
 
 #include 
 #include 
@@ -39,6 +41,10 @@ void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) {
 void TelldusMain::start(void) {
 	EventRef clientEvent = d->eventHandler.addEvent();
 	EventRef dataEvent = d->eventHandler.addEvent();
+	EventRef janitor = d->eventHandler.addEvent(); //Used for regular cleanups
+	Timer supervisor(janitor); //Tells the janitor to go back to work
+	supervisor.setInterval(60); //Once every minute
+	supervisor.start();
 
 	ControllerManager controllerManager(dataEvent.get());
 	EventUpdateManager eventUpdateManager;
@@ -101,7 +107,16 @@ void TelldusMain::start(void) {
 				}
 			}
 		}
+		if (janitor->isSignaled()) {
+			//Clear all of them if there is more than one
+			while(janitor->isSignaled()) {
+				janitor->popSignal();
+			}
+			controllerManager.queryControllerStatus();
+		}
 	}
+
+	supervisor.stop();
 }
 
 void TelldusMain::stop(void){
diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp
index a7c48322..6a415120 100644
--- a/telldus-core/service/TelldusWinService_win.cpp
+++ b/telldus-core/service/TelldusWinService_win.cpp
@@ -1,5 +1,6 @@
 #include "TelldusWinService_win.h"
 #include "TelldusMain.h"
+#include "Log.h"
 
 #include 
 #include 
@@ -111,6 +112,13 @@ DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD
 void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) {
 	TelldusWinService instance;
 
+	//Enable debug if we hade this supplied
+	for(unsigned int i = 1; i < argc; ++i) {
+		if (wcscmp(argv[i], L"--debug") == 0) {
+			Log::setDebug();
+		}
+	}
+
 	// initialise service status
 	instance.serviceStatus.dwServiceType = SERVICE_WIN32;
 	instance.serviceStatus.dwCurrentState = SERVICE_STOPPED;
@@ -140,8 +148,13 @@ void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) {
 		devInterface.dbcc_classguid = GUID_DEVINTERFACE_USBRAW;
 		HDEVNOTIFY deviceNotificationHandle = RegisterDeviceNotificationW(instance.serviceStatusHandle, &devInterface, DEVICE_NOTIFY_SERVICE_HANDLE);
 
+		Log::notice("TelldusService started");
+
 		//Start our main-loop
 		instance.tm->start();
+
+		Log::notice("TelldusService stopping");
+		Log::destroy();
 		
 		// service was stopped
 		instance.serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
diff --git a/telldus-core/service/Timer.cpp b/telldus-core/service/Timer.cpp
new file mode 100644
index 00000000..f552a414
--- /dev/null
+++ b/telldus-core/service/Timer.cpp
@@ -0,0 +1,114 @@
+#include "Timer.h"
+#include "Mutex.h"
+#ifdef _WINDOWS
+#else
+#include 
+#include 
+#endif
+
+class Timer::PrivateData {
+public:
+	PrivateData() : interval(0), running(false) {}
+	EventRef event;
+	int interval;
+	bool running;
+#ifdef _WINDOWS
+	HANDLE cond;
+	TelldusCore::Mutex mutex;
+#else
+	pthread_mutex_t waitMutex;
+	pthread_cond_t cond;
+#endif
+};
+
+Timer::Timer(EventRef event)
+	:TelldusCore::Thread(), d(new PrivateData)
+{
+	d->event = event;
+#ifdef _WINDOWS
+	d->cond = CreateEventW(NULL, false, false, NULL);
+#else
+	pthread_cond_init(&d->cond, NULL);
+	pthread_mutex_init(&d->waitMutex, NULL);
+#endif
+}
+
+Timer::~Timer() {
+	this->stop();
+	this->wait();
+
+#ifdef _WINDOWS
+#else
+	pthread_mutex_destroy(&d->waitMutex);
+	pthread_cond_destroy(&d->cond);
+	delete d;
+#endif
+}
+
+void Timer::setInterval(int sec) {
+	d->interval = sec;
+}
+
+void Timer::stop() {
+#ifdef _WINDOWS
+	TelldusCore::MutexLocker(&d->mutex);
+	d->running = false;
+	SetEvent(d->cond);
+#else
+	//Signal event
+	pthread_mutex_lock(&d->waitMutex);
+	if (d->running) {
+		d->running = false;
+		pthread_cond_signal(&d->cond);
+	}
+	pthread_mutex_unlock(&d->waitMutex);
+#endif
+}
+
+void Timer::run() {
+#ifdef _WINDOWS
+	int interval = 0;
+	{
+		TelldusCore::MutexLocker(&d->mutex);
+		d->running = true;
+		interval = d->interval*1000;
+	}
+	while(1) {
+		DWORD retval = WaitForSingleObject(d->cond, interval);
+		if (retval == WAIT_TIMEOUT) {
+			d->event->signal();
+		}
+		TelldusCore::MutexLocker(&d->mutex);
+		if (!d->running) {
+			break;
+		}
+	}
+#else
+	struct timespec ts;
+	struct timeval tp;
+
+	pthread_mutex_lock(&d->waitMutex);
+	d->running = true;
+	pthread_mutex_unlock(&d->waitMutex);
+
+	while(1) {
+		int rc =  gettimeofday(&tp, NULL);
+
+		ts.tv_sec  = tp.tv_sec;
+		ts.tv_nsec = tp.tv_usec * 1000;
+		ts.tv_sec += d->interval;
+
+		pthread_mutex_lock( &d->waitMutex );
+		if (d->running) {
+			rc = pthread_cond_timedwait(&d->cond, &d->waitMutex, &ts);
+		} else {
+			pthread_mutex_unlock( &d->waitMutex );
+			break;
+		}
+		pthread_mutex_unlock( &d->waitMutex );
+		if (rc == ETIMEDOUT) {
+			d->event->signal();
+		}
+	}
+#endif
+}
diff --git a/telldus-core/service/Timer.h b/telldus-core/service/Timer.h
new file mode 100644
index 00000000..7e8c082a
--- /dev/null
+++ b/telldus-core/service/Timer.h
@@ -0,0 +1,24 @@
+#ifndef TIMER_H
+#define TIMER_H
+
+#include "Event.h"
+#include "Thread.h"
+
+class Timer : public TelldusCore::Thread {
+public:
+	Timer(EventRef event);
+	virtual ~Timer();
+
+	void setInterval(int sec);
+	void stop();
+
+protected:
+	void run();
+
+private:
+	class PrivateData;
+	PrivateData *d;
+};
+
+
+#endif //TIMER_H
diff --git a/telldus-core/service/main_mac.cpp b/telldus-core/service/main_mac.cpp
index 4527225e..f87b718a 100644
--- a/telldus-core/service/main_mac.cpp
+++ b/telldus-core/service/main_mac.cpp
@@ -1,16 +1,16 @@
 #include "TelldusMain.h"
+#include "Log.h"
 #include 
-#include 
 
 TelldusMain tm;
 
 void shutdownHandler(int onSignal) {
-	printf("Shutting down\n");
+	Log::notice("Shutting down");
 	tm.stop();
 }
 
 void sigpipeHandler(int onSignal) {
-	printf("SIGPIPE received\n");
+	Log::notice("SIGPIPE received");
 }
 
 int main(int argc, char **argv) {
@@ -19,7 +19,10 @@ int main(int argc, char **argv) {
 	signal(SIGINT, shutdownHandler);
 	signal(SIGPIPE, sigpipeHandler);
 
+	Log::notice("telldusd started");
 	tm.start();
-	printf("telldusd stopped gracefully\n");
+	Log::notice("telldusd stopped gracefully");
+
+	Log::destroy();
 	return 0;
 }
diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp
index 7bfc36c5..b68d13b7 100644
--- a/telldus-core/service/main_unix.cpp
+++ b/telldus-core/service/main_unix.cpp
@@ -4,7 +4,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -12,6 +11,7 @@
 
 #include "Settings.h"
 #include "Strings.h"
+#include "Log.h"
 
 #define DAEMON_NAME "telldusd"
 #define PID_FILE "/var/run/" DAEMON_NAME ".pid"
@@ -21,19 +21,19 @@ TelldusMain tm;
 void signalHandler(int sig) {
 	switch(sig) {
 		case SIGHUP:
-			syslog(LOG_WARNING, "Received SIGHUP signal.");
+			Log::warning("Received SIGHUP signal.");
 			break;
 		case SIGTERM:
 		case SIGINT:
-			syslog(LOG_WARNING, "Received SIGTERM or SIGINT signal.");
-			syslog(LOG_WARNING, "Shutting down");
+			Log::warning("Received SIGTERM or SIGINT signal.");
+			Log::warning("Shutting down");
 			tm.stop();
 			break;
 		case SIGPIPE:
-			syslog(LOG_WARNING, "Received SIGPIPE signal.");
+			Log::warning("Received SIGPIPE signal.");
 			break;
 		default:
-			syslog(LOG_WARNING, "Unhandled signal (%d) %s", sig, strsignal(sig));
+			Log::warning("Unhandled signal (%d) %s", sig, strsignal(sig));
 			break;
 	}
 }
@@ -46,17 +46,19 @@ int main(int argc, char **argv) {
 	for (int i = 1; i < argc; ++i) {
 		if (strcmp(argv[i], "--nodaemon") == 0) {
 			deamonize = false;
-		}
-		if (strcmp(argv[i], "--help") == 0) {
+			Log::setLogOutput(Log::StdOut);
+		} else if (strcmp(argv[i], "--help") == 0) {
 			printf("Telldus TellStick background service\n\nStart with --nodaemon to not run as daemon\n\n");
 			printf("Report bugs to \n");
 			exit(EXIT_SUCCESS);
-		}
-		if (strcmp(argv[i], "--version") == 0) {
+		} else if (strcmp(argv[i], "--version") == 0) {
 			printf("telldusd " VERSION "\n\n");
 			printf("Copyright (C) 2011 Telldus Technologies AB\n\n");
 			printf("Written by Micke Prag \n");
 			exit(EXIT_SUCCESS);
+		} else {
+			printf("Unknown option %s\n", argv[i]);
+			exit(EXIT_FAILURE);
 		}
 	}
 
@@ -76,17 +78,14 @@ int main(int argc, char **argv) {
 				fprintf(fd,"%d\n",pid);
 				fclose(fd);
 			} else {
-				syslog(LOG_ERR, "Could not open pid file %s: %s", PID_FILE, strerror(errno));
+				Log::error("Could not open pid file %s: %s", PID_FILE, strerror(errno));
 				exit(EXIT_FAILURE);
 			}
 			exit(EXIT_SUCCESS);
 		}
 	}
 
-	setlogmask(LOG_UPTO(LOG_INFO));
-	openlog(DAEMON_NAME, LOG_CONS, LOG_USER);
-
-	syslog(LOG_NOTICE, "%s daemon starting up", DAEMON_NAME);
+	Log::notice("%s daemon starting up", DAEMON_NAME);
 
 	if (deamonize) {
 		/* Change the file mode mask */
@@ -115,14 +114,14 @@ int main(int argc, char **argv) {
 		if (grp) {
 			setgid(grp->gr_gid);
 		} else {
-			syslog(LOG_WARNING, "Group %s could not be found", group.c_str());
+			Log::warning("Group %s could not be found", group.c_str());
 			exit(EXIT_FAILURE);
 		}
 		struct passwd *pw = getpwnam(user.c_str());
 		if (pw) {
 			setuid( pw->pw_uid );
 		} else {
-			syslog(LOG_WARNING, "User %s could not be found", user.c_str());
+			Log::warning("User %s could not be found", user.c_str());
 			exit(EXIT_FAILURE);
 		}
 	}
@@ -139,6 +138,6 @@ int main(int argc, char **argv) {
 
 	tm.start();
 
-	syslog(LOG_NOTICE, "%s daemon exited", DAEMON_NAME);
+	Log::notice("%s daemon exited", DAEMON_NAME);
 	exit(EXIT_SUCCESS);
 }
diff --git a/telldus-core/service/tellstick.conf b/telldus-core/service/tellstick.conf
index 1a1bfe81..fed9c66f 100644
--- a/telldus-core/service/tellstick.conf
+++ b/telldus-core/service/tellstick.conf
@@ -1,5 +1,6 @@
 user = "nobody"
 group = "plugdev"
+ignoreControllerConfirmation = "false"
 device {
   id = 1
   name = "Example device"
diff --git a/telldus-core/tdadmin/05-tellstick.rules b/telldus-core/tdadmin/05-tellstick.rules
index 078ff757..7a6ae615 100644
--- a/telldus-core/tdadmin/05-tellstick.rules
+++ b/telldus-core/tdadmin/05-tellstick.rules
@@ -1,3 +1,3 @@
-ID_VENDOR_ID=="1781", SUBSYSTEM=="usb", ACTION=="add", MODE="664", GROUP="plugdev" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh"
-ID_VENDOR_ID=="1781", SUBSYSTEM=="usb", ACTION=="remove" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh"
+ATTRS{idVendor}=="1781", SUBSYSTEM=="usb", ACTION=="add", MODE="664", GROUP="plugdev" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh"
+ENV{ID_VENDOR_ID}=="1781", SUBSYSTEM=="usb", ACTION=="remove" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh"
 
diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp
index fe9f369e..8304d443 100644
--- a/telldus-core/tdtool/main.cpp
+++ b/telldus-core/tdtool/main.cpp
@@ -2,6 +2,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "../client/telldus-core.h"
 
 const int SUPPORTED_METHODS =
@@ -21,7 +22,7 @@ void print_usage( char *name ) {
 	printf("                      [ --raw input ]\n");
 	printf("\n");
 	printf("       --list (-l short option)\n");
-	printf("             List currently configured devices.\n");
+	printf("             List currently configured devices and all discovered sensors.\n");
 	printf("\n");
 	printf("       --help (-h short option)\n");
 	printf("             Shows this screen.\n");
@@ -77,6 +78,7 @@ void print_version() {
 }
 
 void print_device( int index ) {
+	tdInit();
 	int intId = tdGetDeviceId(index);
 	char *name = tdGetName(intId);
 	printf("%i\t%s\t", intId, name);
@@ -101,13 +103,14 @@ void print_device( int index ) {
 	printf("\n");
 }
 
-void list_devices() {
+int list_devices() {
+	tdInit();
 	int intNum = tdGetNumberOfDevices();
 	if (intNum < 0) {
 		char *errorString = tdGetErrorString(intNum);
 		fprintf(stderr, "Error fetching devices: %s\n", errorString);
 		tdReleaseString(errorString);
-		return;
+		return intNum;
 	}
 	printf("Number of devices: %i\n", intNum);
 	int i = 0;
@@ -115,9 +118,51 @@ void list_devices() {
 		print_device( i );
 		i++;
 	}
+
+	int DATA_LENGTH = 20;
+	char protocol[DATA_LENGTH], model[DATA_LENGTH];
+	int sensorId = 0, dataTypes = 0;
+
+	int sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes);
+	if(sensorStatus == 0){
+		printf("\nSENSORS:\n%-20s\t%-20s\t%-5s\t%-5s\t%-8s\t%-20s\n", "PROTOCOL", "MODEL", "ID", "TEMP", "HUMIDITY", "LAST UPDATED");
+	}
+	while(sensorStatus == 0){
+		sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes);
+
+		char tempvalue[DATA_LENGTH];
+		tempvalue[0] = 0;
+		char humidityvalue[DATA_LENGTH];
+		humidityvalue[0] = 0;
+		char timeBuf[80];
+		time_t timestamp = 0;
+
+		if (dataTypes & TELLSTICK_TEMPERATURE) {
+			tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, tempvalue, DATA_LENGTH, (int *)×tamp);
+			strcat(tempvalue, "°");
+			strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp));
+		}
+
+		if (dataTypes & TELLSTICK_HUMIDITY) {
+			tdSensorValue(protocol, model, sensorId, TELLSTICK_HUMIDITY, humidityvalue, DATA_LENGTH, (int *)×tamp);
+			strcat(humidityvalue, "%");
+			strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp));
+		}
+		printf("%-20s\t%-20s\t%-5i\t%-5s\t%-8s\t%-20s\n", protocol, model, sensorId, tempvalue, humidityvalue, timeBuf);
+
+		printf("\n");
+	}
+	if(sensorStatus != TELLSTICK_ERROR_DEVICE_NOT_FOUND){
+		char *errorString = tdGetErrorString(sensorStatus);
+		fprintf(stderr, "Error fetching sensors: %s\n", errorString);
+		tdReleaseString(errorString);
+		return sensorStatus;
+	}
+	return TELLSTICK_SUCCESS;
 }
 
 int find_device( char *device ) {
+	tdInit();
 	int deviceId = atoi(device);
 	if (deviceId == 0) { //Try to find the id from the name
 		int intNum = tdGetNumberOfDevices();
@@ -137,11 +182,12 @@ int find_device( char *device ) {
 	return deviceId;
 }
 
-void switch_device( bool turnOn, char *device ) {
+int switch_device( bool turnOn, char *device ) {
+	tdInit();
 	int deviceId = find_device( device );
 	if (deviceId == 0) {
 		printf("Device '%s', not found!\n", device);
-		return;
+		return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
 	}
 
 	char *name = tdGetName( deviceId );
@@ -158,17 +204,19 @@ void switch_device( bool turnOn, char *device ) {
 	
 	printf(" - %s\n", errorString);
 	tdReleaseString(errorString);
+	return retval;
 }
 
-void dim_device( char *device, int level ) {
+int dim_device( char *device, int level ) {
+	tdInit();
 	int deviceId = find_device( device );
 	if (deviceId == 0) {
 		printf("Device '%s', not found!\n", device);
-		return;
+		return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
 	}
 	if (level < 0 || level > 255) {
 		printf("Level %i out of range!\n", level);
-		return;
+		return TELLSTICK_ERROR_SYNTAX;
 	}
 
 	char *name = tdGetName( deviceId );
@@ -177,13 +225,15 @@ void dim_device( char *device, int level ) {
 	printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, errorString);
 	tdReleaseString(name);
 	tdReleaseString(errorString);
+	return retval;
 }
 
-void bell_device( char *device ) {
+int bell_device( char *device ) {
+	tdInit();
 	int deviceId = find_device( device );
 	if (deviceId == 0) {
 		printf("Device '%s', not found!\n", device);
-		return;
+		return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
 	}
 
 	char *name = tdGetName( deviceId );
@@ -192,13 +242,15 @@ void bell_device( char *device ) {
 	printf("Sending bell to: %i %s - %s\n", deviceId, name, errorString);
 	tdReleaseString(name);
 	tdReleaseString(errorString);
+	return retval;
 }
 
-void learn_device( char *device ) {
+int learn_device( char *device ) {
+	tdInit();
 	int deviceId = find_device( device );
 	if (deviceId == 0) {
 		printf("Device '%s', not found!\n", device);
-		return;
+		return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
 	}
 
 	char *name = tdGetName( deviceId );
@@ -207,9 +259,11 @@ void learn_device( char *device ) {
 	printf("Learning device: %i %s - %s\n", deviceId, name, errorString);
 	tdReleaseString(name);
 	tdReleaseString(errorString);
+	return retval;
 }
 
-void send_raw_command( char *command ) {
+int send_raw_command( char *command ) {
+	tdInit();
 	const int MAX_LENGTH = 100;
 	char msg[MAX_LENGTH];
 	
@@ -221,7 +275,7 @@ void send_raw_command( char *command ) {
 		fd = fopen(command, "r");
 		if (fd == NULL) {
 			printf("Error opening file %s\n", command);
-			return;
+			return TELLSTICK_ERROR_UNKNOWN;
 		}
 		fgets(msg, MAX_LENGTH, fd);
 	}
@@ -230,6 +284,7 @@ void send_raw_command( char *command ) {
 	char *errorString = tdGetErrorString(retval);
 	printf("Sending raw command: %s\n", errorString);
 	tdReleaseString(errorString);
+	return retval;
 }
 
 int main(int argc, char **argv)
@@ -253,48 +308,56 @@ int main(int argc, char **argv)
 
 	if (argc < 2) {
 		print_usage( argv[0] );
-		return -1;
+		return -TELLSTICK_ERROR_SYNTAX;
 	}
 
-	while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 )
+	int returnSuccess = 0;
+	while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ){
+		int success = 0;
 		switch (optch) {
 			case 'b' :
-				bell_device( &optarg[0] );
+				success = bell_device( &optarg[0] );
 				break;
 			case 'd' :
 				if (level >= 0) {
-					dim_device( &optarg[0], level );
+					success = dim_device( &optarg[0], level );
+					break;
 				}
+				printf("Dim level missing or incorrect value.\n");
+				success = TELLSTICK_ERROR_SYNTAX;
 				break;
 			case 'f' :
-				switch_device(false, &optarg[0]);
+				success = switch_device(false, &optarg[0]);
 				break;
 			case 'h' :
 				print_usage( argv[0] );
-				break;
+				success = TELLSTICK_SUCCESS;
 			case 'i' :
 				print_version( );
-				break;
+				success = TELLSTICK_SUCCESS;
 			case 'l' :
-				list_devices();
+				success = list_devices();
 				break;
 			case 'n' :
-				switch_device(true, &optarg[0]);
+				success = switch_device(true, &optarg[0]);
 				break;
 			case 'e' :
-				learn_device(&optarg[0]);
+				success = learn_device(&optarg[0]);
 				break;
 			case 'r' :
-				send_raw_command(&optarg[0]);
+				success = send_raw_command(&optarg[0]);
 				break;
 			case 'v' :
 				level = atoi( &optarg[0] );
 				break;
 			default :
 				print_usage( argv[0] );
-				return -1;
+				success = TELLSTICK_ERROR_SYNTAX;
 		}
-
+		if(success != TELLSTICK_SUCCESS){
+			returnSuccess = success;  //return last error message
+		}
+	}
 	tdClose(); //Cleaning up
-	return 0;
+	return -returnSuccess;
 }
diff --git a/telldus-gui/Plugins/Live/LiveMessageToken.cpp b/telldus-gui/Plugins/Live/LiveMessageToken.cpp
index 03b204ce..9c64f6d0 100644
--- a/telldus-gui/Plugins/Live/LiveMessageToken.cpp
+++ b/telldus-gui/Plugins/Live/LiveMessageToken.cpp
@@ -11,6 +11,11 @@ LiveMessageToken::LiveMessageToken(const QString &value) {
 	stringVal = value;
 }
 
+LiveMessageToken::LiveMessageToken(int value) {
+	valueType = Int;
+	intVal = value;
+}
+
 QByteArray LiveMessageToken::toByteArray() const {
 	if (valueType == Int) {
 		return QString("i%1s").arg(intVal, 0, 16).toUtf8();
@@ -122,7 +127,7 @@ void LiveMessageTokenScriptWrapper::add(LiveMessageTokenScriptWrapper *t) {
 	p_token.listVal << t->p_token;
 }
 
-int LiveMessageTokenScriptWrapper::getInt(const QString &key, int defaultValue) {
+int LiveMessageTokenScriptWrapper::getInt(const QString &key, int defaultValue) const {
 	if (p_token.valueType != LiveMessageToken::Dictionary) {
 		return defaultValue;
 	}
@@ -132,6 +137,16 @@ int LiveMessageTokenScriptWrapper::getInt(const QString &key, int defaultValue)
 	return p_token.dictVal[key].intVal;
 }
 
+QString LiveMessageTokenScriptWrapper::getString(const QString &key, const QString &defaultValue) const {
+	if (p_token.valueType != LiveMessageToken::Dictionary) {
+		return defaultValue;
+	}
+	if (!p_token.dictVal.contains(key)) {
+		return defaultValue;
+	}
+	return p_token.dictVal[key].stringVal;
+}
+
 int LiveMessageTokenScriptWrapper::intVal() const {
 	return p_token.intVal;
 }
diff --git a/telldus-gui/Plugins/Live/LiveMessageToken.h b/telldus-gui/Plugins/Live/LiveMessageToken.h
index 48699457..a94f476d 100644
--- a/telldus-gui/Plugins/Live/LiveMessageToken.h
+++ b/telldus-gui/Plugins/Live/LiveMessageToken.h
@@ -12,6 +12,7 @@ public:
 
 	LiveMessageToken();
 	LiveMessageToken(const QString &value);
+	LiveMessageToken(int value);
 	QByteArray toByteArray() const;
 	static LiveMessageToken parseToken(const QByteArray &string, int* start);
 
@@ -34,13 +35,14 @@ public:
 public slots:
 	void add(LiveMessageTokenScriptWrapper *token);
 
-	int getInt(const QString &key, int defaultValue = 0);
+	int getInt(const QString &key, int defaultValue = 0) const;
+	QString getString(const QString &key, const QString &defaultValue = "") const;
 
 	int intVal() const;
 
 	void set(const QString &key, int value);
 	void set(const QString &key, const QString &value);
-	
+
 private:
 	LiveMessageToken p_token;
 };
diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp
index 4d853d97..27b73280 100644
--- a/telldus-gui/Plugins/Live/LiveObject.cpp
+++ b/telldus-gui/Plugins/Live/LiveObject.cpp
@@ -13,7 +13,7 @@ public:
 	class Server;
 
 	QSslSocket *socket;
-	QTimer timer;
+	QTimer pingTimer, pongTimer;
 	bool registered;
 	QUrl registerUrl;
 	QString uuid, hashMethod;
@@ -46,8 +46,11 @@ LiveObject::LiveObject( QScriptEngine *engine, QObject * parent )
 	connect(d->socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(stateChanged(QAbstractSocket::SocketState)));
 	connect(d->socket, SIGNAL(sslErrors(const QList &)), this, SLOT(sslErrors(const QList &)));
 
-	d->timer.setInterval(60000); //Once a minute
-	connect(&d->timer, SIGNAL(timeout()), this, SLOT(pingServer()));
+	d->pingTimer.setInterval(120000); //Two minutes
+	d->pongTimer.setInterval(360000); //Six minutes
+	d->pongTimer.setSingleShot(true);
+	connect(&d->pingTimer, SIGNAL(timeout()), this, SLOT(pingServer()));
+	connect(&d->pongTimer, SIGNAL(timeout()), this, SLOT(pongTimeout()));
 
 	d->manager = new QNetworkAccessManager(this);
 	connect(d->manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(serverAssignReply(QNetworkReply*)));
@@ -102,6 +105,8 @@ void LiveObject::readyRead() {
 		//qDebug() << "HASH mismatch!" << msg->name();
 		return;
 	}
+	d->pongTimer.stop();
+	d->pongTimer.start();
 
 	if (msg->name() == "") {
 		return;
@@ -122,6 +127,14 @@ void LiveObject::readyRead() {
 		s.setValue("Live/UUID", d->uuid);
 		emit notRegistered();
 		emit errorChanged("Not registered");
+	} else if (msg->name() == "command") {
+		if (msg->arg(0).valueType == LiveMessageToken::Dictionary && msg->arg(0).dictVal.contains("ACK")) {
+			int ack = msg->arg(0).dictVal["ACK"].intVal;
+			LiveMessage msg("ACK");
+			msg.append(ack);
+			this->sendMessage(msg);
+		}
+		emit messageReceived(msg.data());
 	} else {
 		emit messageReceived(msg.data());
 	}
@@ -132,7 +145,7 @@ void LiveObject::refreshServerList() {
 	emit statusChanged("Discover servers");
 	d->serverList.clear();
 	QUrl url(TELLDUS_LIVE_URI);
-	QPair version("protocolVersion", "1");
+	QPair version("protocolVersion", "2");
 	QList > query;
 	query.append(version);
 	url.setQueryItems(query);
@@ -156,6 +169,8 @@ void LiveObject::sendMessage(const LiveMessage &message) {
 
 	d->socket->write(msg.toByteArray());
 	d->socket->flush();
+	d->pingTimer.stop();
+	d->pingTimer.start();
 }
 
 void LiveObject::sendMessage(LiveMessage *message) {
@@ -170,7 +185,8 @@ void LiveObject::p_connected() {
 	QSettings settings;
 	d->uuid = settings.value("Live/UUID", "").toString();
 
-	d->timer.start(); //For pings
+	d->pingTimer.start(); //For pings
+	d->pongTimer.start(); //For pongs
 	LiveMessage msg("Register");
 
 	LiveMessageToken token;
@@ -188,7 +204,12 @@ void LiveObject::p_connected() {
 }
 
 void LiveObject::p_disconnected() {
-	d->timer.stop();
+	d->pingTimer.stop();
+	d->pongTimer.stop();
+	if (d->registered) {
+		//Clear the registered status
+		emit errorChanged("Disconnected from server");
+	}
 	d->registered = false;
 }
 
@@ -198,11 +219,12 @@ void LiveObject::error( QAbstractSocket::SocketError socketError ) {
 
 void LiveObject::stateChanged( QAbstractSocket::SocketState socketState ) {
 	if (socketState == QAbstractSocket::UnconnectedState) {
-		int timeout = rand() % 20 + 10; //Random timeout from 10-30s to avoid flooding the servers
+		int timeout = rand() % 40 + 10; //Random timeout from 10-50s to avoid flooding the servers
 		QTimer::singleShot(timeout*1000, this, SLOT(connectToServer()));
 		emit statusChanged("Reconnecting in " + QString::number(timeout) + " seconds...");
 	} else if (socketState == QAbstractSocket::ConnectingState) {
 		emit statusChanged("Connecting...");
+		emit errorChanged("");
 	}
 }
 
@@ -228,8 +250,10 @@ void LiveObject::sslErrors( const QList & errors ) {
 void LiveObject::serverAssignReply( QNetworkReply *r ) {
 	r->deleteLater();
 	if (r->error() != QNetworkReply::NoError) {
+		int timeout = rand() % 300 + 60; //Random timeout from 60s-6min to avoid flooding the servers
 		emit errorChanged(r->errorString());
-		emit statusChanged("Error retrieving server list");
+		emit statusChanged("Retrying in " + QString::number(timeout) + " seconds...");
+		QTimer::singleShot(timeout * 1000, this, SLOT(connectToServer()));
 		return;
 	}
 	QXmlStreamReader xml(r);
@@ -253,7 +277,7 @@ void LiveObject::serverAssignReply( QNetworkReply *r ) {
 		d->serverRefreshTime = QDateTime::currentDateTime();
 		QTimer::singleShot(0, this, SLOT(connectToServer()));
 	} else {
-		int timeout = rand() % 20 + 10; //Random timeout from 10-30s to avoid flooding the servers
+		int timeout = rand() % 300 + 60; //Random timeout from 60-6min to avoid flooding the servers
 		emit errorChanged("No servers found");
 		emit statusChanged("Retrying in " + QString::number(timeout) + " seconds...");
 		QTimer::singleShot(timeout * 1000, this, SLOT(connectToServer()));
@@ -270,7 +294,7 @@ QByteArray LiveObject::signatureForMessage( const QByteArray &message ) {
 LiveMessageToken LiveObject::generateVersionToken() {
 	LiveMessageToken token;
 	token.valueType = LiveMessageToken::Dictionary;
-	token.dictVal["protocol"] = LiveMessageToken("1");
+	token.dictVal["protocol"] = LiveMessageToken(2);
 	token.dictVal["version"] = LiveMessageToken(TELLDUS_CENTER_VERSION);
 #if defined(Q_WS_WIN)
 	token.dictVal["os"] = LiveMessageToken("windows");
@@ -314,3 +338,7 @@ LiveMessageToken LiveObject::generateVersionToken() {
 #endif
 	return token;
 }
+
+void LiveObject::pongTimeout() {
+	this->disconnect();
+}
diff --git a/telldus-gui/Plugins/Live/LiveObject.h b/telldus-gui/Plugins/Live/LiveObject.h
index a0b93089..efa8959f 100644
--- a/telldus-gui/Plugins/Live/LiveObject.h
+++ b/telldus-gui/Plugins/Live/LiveObject.h
@@ -39,6 +39,7 @@ private slots:
 	void p_connected();
 	void p_disconnected();
 	void readyRead();
+	void pongTimeout();
 	void error( QAbstractSocket::SocketError socketError );
 	void stateChanged( QAbstractSocket::SocketState socketState );
 	void sslErrors( const QList & errors );
diff --git a/telldus-gui/Plugins/Live/__init__.js b/telldus-gui/Plugins/Live/__init__.js
index 64a851ea..1fbb20f0 100644
--- a/telldus-gui/Plugins/Live/__init__.js
+++ b/telldus-gui/Plugins/Live/__init__.js
@@ -19,6 +19,8 @@ com.telldus.live = function() {
 		socket.connectToServer();
 		com.telldus.core.deviceEvent.connect(deviceEvent);
 		com.telldus.core.deviceChange.connect(sendDevicesReport);
+		configUI.findChild('registrationLink').clicked.connect(socket.activate);
+		configUI.findChild('registrationLink').visible = false;
 	}
 
 	function notRegistered() {
@@ -28,6 +30,7 @@ com.telldus.live = function() {
 			menuId = com.telldus.systray.addMenuItem( qsTr("Activate Telldus Live!") );
 			com.telldus.systray.menuItem(menuId).triggered.connect(socket.activate);
 		}
+		registrationLinkVisible(true);
 	}
 
 	function deviceEvent(deviceId, method, data) {
@@ -42,16 +45,28 @@ com.telldus.live = function() {
 	}
 
 	function messageReceived(msg) {
-		if (msg.name() == "turnon") {
-			com.telldus.core.turnOn( msg.argument(0).intVal() );
-		} else if (msg.name() == "turnoff") {
-			com.telldus.core.turnOff( msg.argument(0).intVal() );
-		} else if (msg.name() == "dim") {
-			com.telldus.core.dim( msg.argument(0).intVal(), msg.argument(1).intVal() );
-		} else if (msg.name() == "bell") {
-			com.telldus.core.bell( msg.argument(0).intVal() );
+		if (msg.name() == "command") {
+			handleCommand(msg.argument(0));
+		}
+	}
+
+	function handleCommand(msg) {
+		var action = msg.getString('action');
+		if (action == "turnon") {
+			com.telldus.core.turnOn( msg.getInt('id') );
+		} else if (action == "turnoff") {
+			com.telldus.core.turnOff( msg.getInt('id') );
+		} else if (action == "dim") {
+			com.telldus.core.dim( msg.getInt('id'), msg.getInt('value') );
+		} else if (action == "bell") {
+			com.telldus.core.bell( msg.getInt('id') );
+		} else if (action == "up") {
+			com.telldus.core.up( msg.getInt('id') );
+		} else if (action == "down") {
+			com.telldus.core.down( msg.getInt('id') );
+		} else if (action == "stop") {
+			com.telldus.core.stop( msg.getInt('id') );
 		}
-		print("Received: " + msg.name());
 	}
 
 	function registered(msg) {
@@ -61,11 +76,25 @@ com.telldus.live = function() {
 			menuId = 0;
 			separatorId = 0;
 		}
-		supportedMethods = msg.getInt('supportedMethods');
+		//Mask to lowest common denominator
+		supportedMethods =
+			com.telldus.core.TELLSTICK_TURNON |
+			com.telldus.core.TELLSTICK_TURNOFF |
+			com.telldus.core.TELLSTICK_DIM |
+			com.telldus.core.TELLSTICK_BELL |
+			com.telldus.core.TELLSTICK_UP |
+			com.telldus.core.TELLSTICK_DOWN |
+			com.telldus.core.TELLSTICK_STOP;
+		supportedMethods = supportedMethods & msg.getInt('supportedMethods');
 		isRegistered = true;
+		registrationLinkVisible(false);
 		sendDevicesReport();
 	}
 
+	function registrationLinkVisible(visibleParam){
+		configUI.findChild('registrationLink').visible = visibleParam;
+	}
+
 	function sendDevicesReport() {
 		if (!isRegistered) {
 			return;
diff --git a/telldus-gui/Plugins/Live/configuration.ui b/telldus-gui/Plugins/Live/configuration.ui
index 608ffc5a..07b51802 100644
--- a/telldus-gui/Plugins/Live/configuration.ui
+++ b/telldus-gui/Plugins/Live/configuration.ui
@@ -7,38 +7,120 @@
     0
     0
     323
-    263
+    251
    
   
+  
+   
+    0
+    0
+   
+  
   
    Form
   
-  
-   
-    
-     
-      Status:
-     
-    
-   
-   
-    
-     
-      unknown
-     
-    
-   
-   
-    
-     
-      
-     
-     
-      true
-     
-    
-   
-  
+  
+   
+    
+     0
+     0
+     331
+     251
+    
+   
+   
+    
+     
+      
+       
+        
+         Status:
+        
+       
+      
+      
+       
+        
+         unknown
+        
+        
+         true
+        
+       
+      
+      
+       
+        
+         
+        
+        
+         true
+        
+       
+      
+      
+       
+        
+         Activate Telldus Live!
+        
+       
+      
+      
+       
+        
+         Qt::Vertical
+        
+        
+         
+          20
+          40
+         
+        
+       
+      
+      
+       
+        
+         Qt::Vertical
+        
+        
+         
+          20
+          40
+         
+        
+       
+      
+      
+       
+        
+         Qt::Vertical
+        
+        
+         
+          20
+          40
+         
+        
+       
+      
+     
+    
+    
+     
+      
+       Qt::Horizontal
+      
+      
+       
+        40
+        20
+       
+      
+     
+    
+   
+  
  
  
  
diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt
index 7aa29d22..8ec1b15b 100644
--- a/telldus-gui/TelldusCenter/CMakeLists.txt
+++ b/telldus-gui/TelldusCenter/CMakeLists.txt
@@ -64,10 +64,7 @@ ADD_DEFINITIONS( -DVERSION=${DISPLAYED_VERSION} )
 
 SET( telldus-center_TARGET	TelldusCenter )
 
-IF (APPLE) #### Mac OS X ####
-	LIST(APPEND telldus-center_LIBRARIES
-		/usr/lib/libQtUiTools.a
-	)
+IF (APPLE) #### Mac OS X ####
 	INCLUDE_DIRECTORIES(
 		/usr/include/QtUiTools
 	)
diff --git a/telldus-gui/TelldusGui/devicesetting.cpp b/telldus-gui/TelldusGui/devicesetting.cpp
index d83ab775..faae0571 100644
--- a/telldus-gui/TelldusGui/devicesetting.cpp
+++ b/telldus-gui/TelldusGui/devicesetting.cpp
@@ -21,3 +21,17 @@ DeviceSetting::DeviceSetting(Device *device, QWidget *parent)
 DeviceSetting::~DeviceSetting()
 {
 }
+
+void DeviceSetting::addProtocolMatch( const QString &protocol, const QString &model ){
+	QString protocolmodel; //concat to one string
+	protocolmodel.append(protocol).append(model);
+	acceptedProtocolModel << protocolmodel;
+}
+
+void DeviceSetting::setProtocolValue( const QString &name, const QString &value, const QString &protocol, const QString &model ){
+	QString protocolmodel; //concat to one string
+	protocolmodel.append(protocol).append(model);
+	if(acceptedProtocolModel.contains(protocolmodel)){  //protocol not set yet, or equal
+		this->setValue(name, value);
+	}
+}
diff --git a/telldus-gui/TelldusGui/devicesetting.h b/telldus-gui/TelldusGui/devicesetting.h
index 55ff50db..4dc6f91f 100644
--- a/telldus-gui/TelldusGui/devicesetting.h
+++ b/telldus-gui/TelldusGui/devicesetting.h
@@ -29,10 +29,18 @@ public:
 
 public slots:
 	virtual void saveParameters() = 0;
+	void addProtocolMatch( const QString &protocol, const QString &model );
+
+private slots:
+	void setProtocolValue( const QString &name, const QString &value, const QString &protocol, const QString &model );
 	virtual void setValue( const QString &name, const QString &value ) = 0;
 
 protected:
 	Device *p_device;
+
+private:
+	QList acceptedProtocolModel;
+
 };
 
 #endif
diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp
index 66afa766..4a211e95 100644
--- a/telldus-gui/TelldusGui/editdevicedialog.cpp
+++ b/telldus-gui/TelldusGui/editdevicedialog.cpp
@@ -173,10 +173,30 @@ EditDeviceDialog::EditDeviceDialog(Device *device, QWidget *parent, Qt::WFlags f
 	((DeviceSettingArctechSelflearning *)d->deviceSettings[9])->setUnitMinMax(1,15);
 
 	foreach( DeviceSetting *s, d->deviceSettings ) {
-		connect(d->filteredModel, SIGNAL(setParameter(const QString&, const QString&)), s, SLOT(setValue(const QString&, const QString&)));
+		connect(d->filteredModel, SIGNAL(setParameter(const QString&, const QString&, const QString&, const QString&)), s, SLOT(setProtocolValue(const QString&, const QString&, const QString&, const QString&)));
 		d->settingsLayout->addWidget( s );
 	}
 
+	for (int i=0; imodel->rowCount(QModelIndex()); ++i){
+		QModelIndex index = d->model->index(i, 0, QModelIndex());
+		VendorDeviceTreeItem *typeitem = d->model->item(index);
+
+		for(int j=0; jchildCount(); ++j){
+			VendorDeviceTreeItem *branditem = typeitem->child(j); //d->model->item(index);
+
+			for(int k=0; kchildCount(); ++k){
+				VendorDeviceTreeItem *deviceitem = branditem->child(k); //d->model->item(index);
+
+				int widget = deviceitem->widget();
+				QString strModel = deviceitem->deviceModel().section(':', 0, 0);
+				if (strModel.startsWith("selflearning-")) {
+					strModel = "selflearning";
+				}
+				d->deviceSettings[widget]->addProtocolMatch(deviceitem->deviceProtocol(), strModel);
+			}
+		}
+	}
+
 	expandNodes(deviceView);
 	QModelIndex index = d->filteredModel->mapFromSource(d->model->index( device ));
 	if (index.isValid()) {
diff --git a/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp b/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp
index 0e20ec6c..d6faa626 100644
--- a/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp
+++ b/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp
@@ -54,7 +54,7 @@ void FilteredDeviceProxyModel::addFilter( const QString &filter ) {
 			return; //don't scan sensors here 
 		}
 		else {
-			emit setParameter(name, value);
+			emit setParameter(name, value, protocol, model);
 		}
 	}
 	//Make sure we don't add a duplicate
diff --git a/telldus-gui/TelldusGui/filtereddeviceproxymodel.h b/telldus-gui/TelldusGui/filtereddeviceproxymodel.h
index df91cc9b..5029f49d 100644
--- a/telldus-gui/TelldusGui/filtereddeviceproxymodel.h
+++ b/telldus-gui/TelldusGui/filtereddeviceproxymodel.h
@@ -17,7 +17,7 @@ public:
 	void addFilter( const QString & );
 
 signals:
-	void setParameter(const QString &name, const QString &value);
+	void setParameter(const QString &name, const QString &value, const QString &protocol,  const QString &model);
 
 protected:
 	virtual bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const;