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) {
+ ?>
+
';
+ 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